CMake: 'AUTOMOC' feature skips sources of executable targets? - c++

There is a medium-sized project with a top level CMakeLists.txt which defines some common stuff and invokes the configuration of all artifacts (subprojects) in the project like this:
add_subdirectory(components/A)
add_subdirectory(components/B)
add_subdirectory(components/C)
add_subdirectory(components/E)
Artifacts are static/shared libraries or executables (which somehow depend on each other). In this example, there is only one executable: E. Everything configures and builds perfectly fine when plain old qt4_wrap_cpp is used to process MOC.
When switching to the (relatively) new AUTOMOC feature by adding the following to the top CMakeLists.txt:
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
all the sources of static/shared libraries are AUTOMOC'ed just fine. However, the sources of executable target (E in this example) are never AUTOMOC'ed.
I've tried both MSYS Makefiles and Ninja generators, and both simply do not create the target for AUTOMOC'ing, but only for executable's sources (for static/shared library targets AUTOMOC'ing target is added).
Has anyone experienced that already?
What could be the cause?
Does that smell like a bug?
Update
I found the cause, the discussion is on CMake mailing list.

To summarize, the problem was that E didn't include Qt module neither explicitly:
find_package(Qt4 ...)
nor implicitly:
find_package(MyPrecious ...)
where MyPrecious could be some 3rd party module which includes Qt by itself.
As a result, non-cached variables like QT_VERSION_* are not present in the scope of E subproject, and for that reason AUTOMOC feature cannot function properly. Nasty pitfall I'd say. For more details refer to CMake mailing list.

Related

Setting up 3rd party libraries environment for CMake on Windows 10

I'm having problems with the "proper" way of installation third-party libraries for use with CMake projects (C++). For most of the time I haven't been bothering myself with this stuff and just hardcoding library paths in my CMakeLists.txt, but I really want to start using this properly.
I ultimately want to have something where I can just type, for example, find_package(SDL2 REQUIRED) in a project and the library is there, found, and works perfectly.
What I have right now is I have a folder C:\CMakeLibs where I --install all 3rd party libraries, so for example there is C:\CMakeLibs\SDL2 and in it, there are folders like cmake, include, lib, etc. Then I include the folder C:\CMakeLibs\SDL2 in CMAKE_PREFIX_PATH in system environment variables, so that CMake can find the SDL2Config.cmake file and there's no need for any FindSDL2.cmake. This way I can just type following code and it straight works, and is also probably the most portable for open-source projects.
find_package(SDL2 REQUIRED)
add_executable(app main.cpp)
target_link_libraries(app PRIVATE SDL2::SDL2main SDL2::SDL2-static)
My only concern here is that I have to manually add any new libraries to CMAKE_PREFIX_PATH. I'd like just have only C:\CMakeLibs as my CMAKE_PREFIX_PATH and everything working fine. I could technically --install the libraries directly to C:\CMakeLibs but I fear of any possible incompatibilities when having all the different files in one shared folders, it doesn't feel like the best solutions.
I know this question might be one of those "without the best answers/based on opinion". I've been looking for solutions on internet for long time already, ever since I started using CMake, so I decided to just write this post here. I hope I described my problem clearly, English isn't my native language.

Linking against built static libraries rather than using add_subdirectory?

Given a project with "app" and "lib" sibling directories, where "app" builds an executable depending on the (static) library built by "lib". What I'd like is a situation where the normal build process builds only the library, but if I build "app" it builds both "lib" and "app".
What I'm currently doing now is that in app, I include lib with add_subdirectory, but for whatever reason this is pulling in all of lib's indirect dependencies into the link line through a mechanism I'm not aware of. What I'd like is to have my app just build libmylib.a and libmylib.pc, then app could just calculate its own link line from libmylib.pc (or specify it manually), but I'm not sure how that's done.
Here's a minimum working example I've got set up now:
lib/CMakeLists.txt
cmake_minimum_required(VERSION 3.8.0)
project(mylib CXX)
find_package(PkgConfig REQUIRED)
pkg_check_modules("mylib" "libssl")
find_package(Boost REQUIRED)
set(LIBDIR "${PROJECT_SOURCE_DIR}")
set(HEADERS "${LIBDIR}/map_printer.hpp")
set(SOURCES "${LIBDIR}/map_printer.cpp")
add_library("mylib" "${SOURCES}")
target_include_directories("mylib" PUBLIC "${LIBDIR}"
"${Boost_INCLUDE_DIR}"
"${mylib_INCLUDE_DIRS}")
target_link_libraries("mylib" "${Boost_LIBRARIES}" "${mylib_LIBRARIES}")
install(TARGETS "mylib" ARCHIVE DESTINATION "lib")
install(FILES ${HEADERS} DESTINATION "include")
app/CMakeLists.txt
cmake_minimum_required(VERSION 3.8.0)
project(mylib CXX)
set(APPDIR "${PROJECT_SOURCE_DIR}")
set(LIBDIR "${APPDIR}/../lib")
set(SOURCES "${APPDIR}/main.cpp")
add_subdirectory("${LIBDIR}" "build")
list(APPEND LIBS "mylib")
add_executable("myapp" "${SOURCES}")
target_include_directories("myapp" PUBLIC "${LIBDIR}")
target_link_libraries("myapp" "${LIBS}")
install(TARGETS "myapp" DESTINATION "bin")
To get a working example, here are some source files that pull in libssl in the lib (but this function is not used in the app) - I put them in gists because they are only included for completeness and I didn't want to clutter up the question text:
lib/map_printer.cpp
lib/map_printer.hpp
app/main.cpp
The problem is that when I cmake app and then do make VERBOSE=1, the linker command generated is:
/usr/lib/hardening-wrapper/bin/c++ CMakeFiles/myapp.dir/main.cpp.o -o myapp build/libmylib.a -lssl
But I have not specified -lssl anywhere in app. Normally this would be fine, but in my real app, -lssl and several other unnecessary symbols are being included as .so files because of indirect dependencies. When I remove them from the linker command manually, the task builds and runs just fine. Ideally I'd be pulling in the built .a with its .pc file (not generated in this example) and if excess dependencies are necessarily being pulled in, I could tweak the link line manually, but with this method, the linker flags (and possibly other things) are leaking out of the lib scope in some way I don't understand.
Linking is all about resolving symbols so that the final target (standalone executable or shared object) has everything it needs to be launched. Things are simple when you depend only on a single library or upon a collection of libraries that in turn depend on nothing else. This is less likely to be the case for any program of moderate or larger size. The underlying issue is how to deal with transitive dependencies, e.g. the dependencies of the things directly used by your program.
CMake understands all of this and is designed to make it simple for you to consume libraries without understanding the entire dependency graph. If you look at the documentation for target_link_libraries, you'll see the PRIVATE, PUBLIC, and INTERFACE keywords described. This allows you to describe the private requirements of the library (compile definitions, compile arguments, dependent libraries, etc.) that it needs when you build the library. The public part allows you to specify things that both the library and its dependents (consumers) need. The interface part lets you specify things that the dependents need, but not the library itself. The commands target_compile_definitions and target_include_directories operate similarly.
The upshot of all of this is that with a properly declared dependency in CMake, the client of that dependency just adds it to its list of dependencies in its own target_link_libraries command and it naturally picks up all compile definitions, include directories and transitory link dependencies necessary for successful compilation and linking.
A CppCon 2017 presentation Modern CMake for modular design goes over this in more detail.

Convert from Xcode to CMake

I have a C++ project that I initially developed using Xcode on my Mac and I would like to set up the very same project using CMake. The project makes use of some external libraries, including eigen and boost. Xcode has a rather long list of Build Settings, including paths to external libraries, specification of the compiler version, additional linker flags, compiler optimization level, etc... and I am wondering where all of this information goes in the CMakeLists.txt file. I've searched extensively for help on this but have found precious little. I am new to CMake and have never written make files before. If there were a utility that could convert my Xcode project into a CMake project, that would be ideal. But I would be very glad to know of a tutorial on this, or to have some specific guidance. Any help on this would be greatly appreciated.
Conversion Strategy
I am pretty sure that the easiest and fastest way to move to CMake is a mixture of looking at comparable projects that link the same dependencies, and maybe copying a few relative file paths to your source files from XCode.
A well-written CMakeLists.txt that uses Eigen and Boost can be very small (and platform-independent).
One reason for this is CMake has a very different way to use dependencies.
For well-known libraries such as Boost, CMake includes scripts to include headers and link libraries.
Minimal CMakeLists.txt
A minimal example may look like this:
find_package(Eigen3 REQUIRED)
find_package(Boost REQUIRED COMPONENTS system)
add_executable(
app
src/main.cpp
)
target_include_directories(
app
${Eigen3_INCLUDE_DIRS}
${Boost_INCLUDE_DIR}
)
target_link_libraries(
app
${Boost_LIBRARIES}
)
Example Projects
For Eigen, there is no such pre-installed script that can be called by find_package.
Here are two real-world example projects that link Eigen and Boost: https://github.com/ompl/ompl/blob/master/CMakeLists.txt
https://github.com/roboticslibrary/rl
Here is an example for a find script for Eigen.
As a piece of advice, some CMake projects are out there are convoluted and use old syntax, newer project files tend to use small letters in commands.
If it happens that directly target linking libraries doesn't work, you'll have to write your own Find*.cmake files by yourself.
Here's a spec of what you should cover to make it (this is just one approach):
Imagine you have a library XYZ:
Your file
FindXYZ.cmake should have as a result a set of variables to use:
XYZ_LIBRARIES
XYZ_INCLUDE_DIR
For example:
set(XYZ_LIBRARIES ${SOME_PATH_TO_LIBRARY1} ${SOME_PATH_TO_LIBRARY2})
find_path(XYZ_INCLUDE_DIR NAMES xyz/xyz.h HINTS ${PLACE_WHERE_INCLUDE_SHOULD_BE}
PATH_SUFFIXES include
)
From your main cmake maybe you 'use' it:
find_package(XYZ REQUIRED)
# Now we use both _INCLUDE_DIR and _LIBRARIES
include_directories(SYSTEM "${XYZ_INCLUDE_DIR}")
# TARGET_NAME is the current target, the 'client' of XYZ
# append XYZ to our list of libraries to link
target_link_libraries(${TARGET_NAME} ${XYZ_LIBRARIES})
I'm surely missing details but that's the general idea. Here are some cmake scripts that I know work in a big project:
Example with OpenSSL
Find:
https://github.com/highfidelity/hifi/blob/Android/cmake/modules/FindOpenSSL.cmake
Client (in this case is a library that indeed needs OpenSSL):
https://github.com/highfidelity/hifi/blob/Android/domain-server/CMakeLists.txt

Can CMake find_package be "common dependency version aware"?

The Problem:
I'm in the process of redoing the make system in our legacy project, changing from its present arcane version to CMake. At the moment, I've got CMake treating the whole thing as one large CMake project, but our code base is so large that it's breaking most of the IDEs we throw at it.
We'd like to break it apart, and CMake's find_package "module mode" seems to be ideal for breaking it into "feature-sized" chunks. The prime candidate is a large chunk of the code that only needs to be maintained rarely, and even then its usually by another team. That would allow us to maintain the code, but not continuously recompile it when updating different code.
That said, this chunk of code uses Boost's shared pointer in the API, and while different versions of shared pointer probably will work together, I'd rather not take the chance. So, ideally, the package will be aware of what version of "boost" the system is using, what version of boost was used when the module was compiled, and be able to recompile -- or, at the very least, throw an error or warning in CMake -- if the two don't match.
So ... how does one go about ensuring that versions of common dependencies match in CMake find_package modules? The only thing I can think of is testing the appropriate VERSION variable, but that seems ... bulky. Is there something I'm missing?
Additional Information:
We're using CMake 3.5.1, but we can upgrade to 3.5.2 if that would make a difference. This project is actually a Software Product Line (q.v.), so we are planning to use more modern SPL Software Engineering techniques at some point in the future (yet another reason to choose CMake). The codebase is currently in Redhat Linux, but ideally the technique(s) would be cross-platform.
You may use config mode of the find_package for allow you modules to expose some internal properties to their user (root project).
If each your module provides library target, you may expose that target with property containing Boost version attached and list this property in a special COMPATIBLE_INTERFACE_STRING property.
Your root project will include modules via find_package() calls and will read these properties. When it will try to link libraries, provided by such modules, version compatibility will be automatically performed by CMake:
modA/CMakeLists.txt:
...
find_package(Boost)
add_library(modA_lib ...)
... # Link modA_lib with Boost
# Install modA_lib target and exports it for use in other project.
install(TARGETS modA_lib EXPORT modA_lib)
# Configured -config file is shown below
configure(modA-config.cmake.in modA-config.cmake)
install(EXPORT modA_lib
DESTINATION share/cmake/modA)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/modA-config.cmake
DESTINATION share/cmake/modA)
modA/modA-config.cmake.in:
include(#CMAKE_INSTALL_PREFIX#/share/cmake/modA/modA_lib.cmake) # Include file described library target
# Expose linked version of Boost via target's property.
set_property(TARGET modA_lib PROPERTY INTERFACE_BOOST_VERSION #Boost_VERSION#)
# Mark this property as compatibility requirement
set_property(TARGET modA_lib PROPERTY APPEND COMPATIBLE_INTERFACE_STRING BOOST_VERSION)
(modB is implemented in similar manner)
root/CMakeLists.txt:
find_package(modA) # This imports target modA_lib
find_package(modB) # This imports target modB_lib
add_executable(root_exe <...>)
# Boost version check will be performed here
target_link_libraries(root_exe modA_lib modB_lib)
Additionally, an executable created in the root project may request specific Boost version via setting appropriate property:
add_executable(root_exe <...>)
set_property(TARGET root_exe PROPERTY BOOST_VERSION <...>)
In this case it will be prohibited (by CMake) for its dependencies to use Boost library with other versions.
More info and usage examples see in CMake build system description.

How to easily include headers from library dependency in cmake circa v2.8.8

I'm experimenting with CMake a bit for a C++ repository, but I'm running into some trouble trying to make it easy to build applications against libraries in the same source tree without a lot of extra CMake code.
The layout of the source tree is basically the following:
ROOT
libs/
lib1/
lib2/
lib3/
apps/
app1/
app2/
app3/
The libraries are independent of one another, and the applications may link against one or more of the libraries.
Currently I have a root CMakeLists.txt that lists out each application and library as a subdirectory so that if the library is changed and the application is rebuilt, so is the library. This works fine and CMake links it in without me having to specify where the library lives, but I don't see a way to do something similar for include directories.
Is there a common way to handle this? I'd prefer not to have each application's CMakeLists.txt have to manually list out the path to the libraries it needs.
If you are not afraid of making more headers available than you actually need for each application, you could list all lib directories in an INCLUDE_DIRECTORIES statement e.g. in the CMakeListst.txt adding all application sublists. But there is no such concept of managing "belonging" include folders per target built-in.
This question is pretty old. It was asked on 2012-07-18. I'm adding an answer here to attempt to explain some history. Warning: I may have gotten it wrong or misunderstood the history.
At that time, the latest non-release-candidate relase was CMake v2.8.8 (released on 2012-04-18). The INCLUDE_DIRECTORIES target property already existed in v2.8.8, but there was no corresponding INTERFACE_INCLUDE_DIRECTORIES target property yet. Its target_link_libraries documentation didn't say anything about a target automatically adding the include directories of the targets it depended upon.
About ten months after this question was asked (2012-07-18), CMake v.2.8.11 was released. It added the target_include_directories command signature with the INTERFACE|PUBLIC|PRIVATE argument, and added the INTERFACE_INCLUDE_DIRECTORIES target property.
So you can create a target B, specify public/interface include directories for it, and then make a target A depend on it via target_linK_libraries, and then A will automatically add/use the include directories of B. That can be made transitive by making the link public/interface, or non-transitive by making the link private.
You can find Kitware's list of software releases here, and a list of the documentation revisions here.