Modern CMake - setup libraries targets inside project - cmake

My project structure presents as follows:
── src
├── app
│ ├── first_app
│ │ ├── include
│ │ └── src
│ │ └── CMakeLists.txt
│ ├── second_app
│ │ └── ...
├── lib
│ ├── first_lib
│ | ├── include
│ | └── src
│ | └── CMakeLists.txt
│ ├── second_lib
│ | ├── include
│ | └── src
│ | └── CMakeLists.txt
├── CMakeLists.txt
first_app uses both first_lib and second_lib. I would like to force CMake to find all dependencies (libraries and include headers) using
target_link_libraries(first_app first_lib::first_lib second_lib::second_lib).
I would like to ask two questions:
What command should be used to export first_lib::first_lib in ./src/lib/first_lib/CMakeLists.txt?
How to make first_lib::first_lib visible in ./src/app/first_app/CMakeLists.txt?

Supposing you create your lib using add_library(first_lib ...)
1) I would use:
include(GNUInstallDirs)
install(TARGETS first_lib
EXPORT FirstLibTargets
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/first_lib
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
src: https://github.com/Mizux/cmake-cpp/blob/master/Foo/CMakeLists.txt#L24
then you can install the export file using:
install(EXPORT FirstLibTargets
NAMESPACE first_lib::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/FirstLib
COMPONENT Devel)
src: https://github.com/Mizux/cmake-cpp/blob/master/CMakeLists.txt
note: I don't know if you can install target alias (i.e. install(TARGETS first_lib::first_lib) and/or have an export file with differents namespace (i.e. first_lib:: second_lib::)
2) simply use in first_lib/CMakeLists.txt:
add_library(first_lib::first_lib ALIAS first_lib) just after your add_library.
so first_app could always use first_lib::first-lib to retrieve this target dependencies what ever if you use a Meta CMake (i.e. add_subdirectory()) or find_package().
e.g. https://github.com/Mizux/cmake-cpp/blob/master/Foo/CMakeLists.txt

Related

Can I make a CMake target dependent upon a target in another CMake project?

I have two separate projects, but one of them must now incorporate aspects of the other, including the generation of some code, which done by a Python script which is called by CMake.
Here is my project structure:
repo/
├── project_top/
│ ├── stuff_and_things.cpp
│ └── CMakeLists.txt
│
└── submods/
└── project_bottom/
├── CMakeLists.txt
└── tools/
├── build_scripts
│ └── cmake_bits.cmake
└── generator
└── gen_code.py
In repo/submods/project_bottom/tools/build_scripts/cmake_bits.cmake there is a macro set_up_additional_targets(), which includes a custom target which runs repo/submods/project_bottom/tools/generator/gen_code.py in that directory. This is based on project_bottom being its own project.
add_custom_target(gen_code
COMMAND echo "Generating code"
COMMAND python3 gen_code.py args
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tools/generator
)
Now, I need to make a new target in project_top dependent upon the gen_code target in project_bottom. How do I do this? The gen_code target needs to be run as part of the project_top build, but within the context of project_bottom, because for that target, ${CMAKE_CURRENT_SOURCE_DIR} needs to be repo/submods/project_bottom, not repo/project_top.

Cmake add include_dirs to a target, then link target to a executable

How do I set the include dirs of a target, then include that target in my executable the current project folder looks like this:
├── CMakeLists.txt
├── libs
│ ├── CMakeLists.txt
│ └── libs.h
├── src
│ ├── CMakeLists.txt
│ └── main.cpp
└── tests
└── tests.cpp
So I would like to puts the .h files of the libs on the libs folder and make that a target which I can link to, I currently have something like this:
CMakeLists.txt:
cmake_minimum_required(VERSION 3.20.0)
project("Project")
add_subdirectory(libs)
add_subdirectory(src)
src/CMakeLists.txt:
add_executable(main main.cpp)
target_link_libraries(main libs)
libs/CMakeLists.txt:
add_custom_target(libs PUBLIC)
target_include_directories(libs ${CMAKE_CURRENT_SOURCE_DIR})

Library linking not working when CMake single build

using CMake I want to build in each directory A, B, and C.
The project structure is as follows:
.
├── A
│   ├── CMakeLists.txt
│   └── src
│   └── a.cpp
├── B
│   ├── CMakeLists.txt
│   └── src
│   └── b.cpp
├── common
│   ├── CMakeLists.txt
│   ├── include
│   │   ├── common.h
│   └── src
│   └── common.cpp
└── C
├── CMakeLists.txt
└── src
└── c.cpp
Create a library in the Common directory and install the created library.
common/CmakeLists.txt :
set(COMMON_LIB_NAME CommonTemp)
set(SRC_CODE
${CMAKE_CURRENT_SOURCE_DIR}/include/common.h
${CMAKE_CURRENT_SOURCE_DIR}/src/common.cpp
)
add_library (${COMMON_LIB_NAME} SHARED ${SRC_CODE})
install(TARGETS ${COMMON_LIB_NAME} DESTINATION ~/tempDir/lib)
I want to link the generated library to directory A.
a.cpp requires common.h.
A/CMakeLists.txt:
ADD_EXECUTABLE(ServiceA src/a.cpp)
target_include_directories (
ServiceA PUBLIC
include
)
target_sources (
ServiceA PRIVATE
src/a.cpp
)
target_link_libraries(
ServiceA PUBLIC
${COMMON_LIB_NAME} #### Location considered to be a problem
)
install(TARGETS ServiceA DESTINATION ~/tempDir/bin/A)
An error message occurs saying that common.h cannot be included.
My guess is that the ${COMMON_LIB_NAME} variable is defined in CMakeLists.txt in another directory, so it is expected that it cannot be linked.
But even if I put CommonTemp , the value of the variable, it says that common.h cannot be found.
How can I link library links even if I build CMake individually in each directory?
In common/CmakeLists.txt.
You need to include the headers in target_include_directores.
target_include_directories(
${COMMON_LIB_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include
)
No need to mention it in add_library
In A/CMakeLists.txt. Include path is not correct.
target_include_directories(
ServiceA PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/<path to common>/include
)
For linking the library you have to mention the correct library path otherwise it will fail
target_link_libraries(
ServiceA PUBLIC
${COMMON_LIB_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/<path to tempDir>/lib
)

How can I have Wintersmith generate a static site with a blog in a subdirectory?

I'm looking into Wintersmith-ifying my site, which is currently hand-written. I have a couple pages: index.html, projects.html, gpg.html, etc. I want to have a blog/ subdirectory, so that the final site looks like this:
.
|- index.html
|- gpg.html
|- project.html
|- blog/
| |- look-a-new-wintersmith-blog.md
| |- monkeys-are-really-cool.md
Is this possible? I've searched and looked at the Wintersmith documentation (and even the featured Wintersmith-powered sites), and come up with nothing. It seems like the only way is to have two instances of Wintersmith or something, but it also seems like there must be a better way.
You should get the desired result with something like this:
├── config.json <- site configuration
├── contents
│ ├── index.html <- these will just be outputted as-is
│ ├── gpg.html
│ ├── project.html
│ ├── blog <– each article has its own directory
│ │ ├── index.json <- this is your blog index at /blog/index.html
│ │ ├── look-a-new-wintersmith-blog
│ │ │ └── index.md
│ │ └── monkeys-are-really-cool
│ │ └── index.md
│ ├── authors <- author metadata, check author.jade
│ │ └── the-wintersmith.json
│ ├── css
│ │ └── main.css
│ └── feed.json
├── plugins
│ └── paginator.coffee <- paginator plugin
├── templates
│ ├── archive.jade
│ ├── article.jade
│ ├── author.jade
│ ├── feed.jade
│ ├── index.jade
│ └── layout.jade
└── views
└── articles.coffee <- view that lists articles
index.json is just a renamed and moved archive.json to give a /blog/index.html URL instead. If you want the default Wintersmith index instead of an archive layout, edit the file to use the index.jade layout instead of archive.jade.
If you change your current HTML files to Markdown and put them in the same spot, then they'll be outputted as HTML as your blog posts would.
You might want to add some sort of navigation menu to your article layout, too.
Edit: To create a static page, create a Markdown file in contents similar to the following:
---
title: GPG
author: baker
date: 2014-03-23
template: article.jade
---
Content
If you named this file gpg.md, it should be accessible at http://localhost:8080/gpg.html. Because we used the article.jade template, it expects an author and a date field for completeness (it would work without, however it would still include "Written by" without an author), but you could make a custom template that doesn't use those fields.

Correct cmake setup to include headers

I have a project structured like this:
─root
├──src
│ ├──main.cpp
│ └──CMakeLists.txt[2]
├──build
├──out
├──inc
├──dep
│ ├──log
│ │ ├──include
│ │ │ └──log.h
│ │ ├──src
│ │ │ └──log.cpp
│ │ └──CMakeLists.txt[4]
│ └──CMakeLists.txt[3]
└──CMakeLists.txt[1]
Under dep I have a logging library, which is an external git repository with his own CMakeLists.txt file.
The main CMakeLists.txt (marked as [1]) is:
cmake_minimum_required(VERSION 2.6)
set(APP_ROOT ${PROJECT_SOURCE_DIR})
add_subdirectory(dep)
add_subdirectory(src)
The CMakeLists.txt (marked as [2]) for the current project code is:
add_executable(app main.cpp)
target_link_libraries(app log)
include_directories("${APP_ROOT}/inc")
The CMakeLists.txt (marked as [3]) for the dependencies is:
add_subdirectory(log)
What I'm trying to do is to have the contents of the dep/log/include folder copied inside a new folder called inc/log, so that in main.cpp I can write something like #include <log/log.h>, but I don't understand how. I would like to avoid editing the CMakeLists.txt of the logger project.
My solution: in /dep/CMakeLists.txt I added
file(MAKE_DIRECTORY "${APP_ROOT}/inc/log")
file(COPY "log/include/" DESTINATION "${APP_ROOT}/inc/log")