It seems the CMake include_directories will add not only the passed directory but also all its sub directories to the include list.
Is there a way to add only one directory (without its sub directories), i.e. some sort on include_directory command?
As indicated in the documentation, only the folders indicated int he command are added, not the subfolders. Of course, if you have a subfolder foo and someone does #include <foo/bar.h, then the file will be included.
Consider using target_include_directories as it is more flexible and better, as it targets one target, and if the target is reused, then dependent includes may also be carried to the dependent targets (depending on PUBLIC/PRIVATE/INTERFACE).
Related
How do I force CMake's function target_include_directories() to treat the value as an absolute path?
For example, I want this line of code:
target_include_directories(foobar PRIVATE "%FOOBAR_INCLUDE%")
to simply add %FOOBAR_INCLUDE% to the list of include directories.
However, what we actually get is c:\path\to\foobar\%FOOBAR_INCLUDE%.
I know that I could do
target_include_directories(foobar PRIVATE "$ENV{FOOBAR_INCLUDE}")
but that's not what I want. That would expand the value of the environment variable and insert the current setting of the FOOBAR_INCLUDE value.
We need for it to simply push the environment variable, and then during development the developers will change the value of FOOBAR_INCLUDE manually without having to re-run CMake each time.
It is not possible to add something that looks like a relative directory (i.e. "%FOOBAR_INCLUDE%") to the include directories this way. CMake will always try to manipulate these into absolute paths. This is more-or-less stated in the include_directories documentation:
Relative paths are interpreted as relative to the current source directory.
but applies to the target_include_directories() command as well.
Even if you try to circumvent this, and set the INCLUDE_DIRECTORIES property of the target manually:
set_target_properties(foobar PROPERTIES
INCLUDE_DIRECTORIES "%FOOBAR_INCLUDE%"
)
CMake will throw an error during the generation stage:
CMake Error in CMakeLists.txt:
Found relative path while evaluating include directories of "foobar":
"%FOOBAR_INCLUDE%"
You could compromise, providing a full path, but allowing the %FOOBAR_INCLUDE% variable to stay:
target_include_directories(foobar PRIVATE "C:/%FOOBAR_INCLUDE%")
but this ties you and your fellow developers to the C: drive.
I would recommend following the approach you suggested, using an environment variable:
target_include_directories(foobar PRIVATE "$ENV{FOOBAR_INCLUDE}")
or creating a FOOBAR_INCLUDE CMake cache variable that can be populated by each developer before they re-run CMake. If each developer's environment is different, CMake should be re-configured to match that environment.
You can trick CMake into accepting literal values through generator expressions
target_include_directories(foobar PRIVATE $<1:%FOOBAR_INCLUDE%>)
This, however, won't work as CMake will generate an error about the path not being absolute.
Luckily its an include directory, so therefore you can try to add the include flag manually:
target_compile_definitions(foobar PRIVATE -I%FOOBAR_INCLUDE%)
I am using cmake 2.8.12.
I am using multiple targets with the same definitions by calling add_definitions().
I want to find out how to remove those definitions for single target and replace them by some other definitions or by default definitions like I have not called add_definitions().
I found a solution there:
https://gitlab.kitware.com/cmake/cmake/issues/19796
This is a way to remove the NOMINMAX define:
get_target_property(defs someTarget COMPILE_DEFINITIONS)
list(FILTER defs EXCLUDE REGEX [[^NOMINMAX$]])
set_property(TARGET someTarget PROPERTY COMPILE_DEFINITIONS ${defs})
The better approach here is to add the definitions for single targets rather than globally.
To do so, you should use target_compile_definitions instead of add_definitions
For instance, instead of
add_definitions(-DSOMEMACRO)
add_executable(myExecutable main.cpp)
you would use
add_executable(myExecutable main.cpp)
target_compile_definitions(myExecutable PUBLIC -DSOMEMACRO)
This allows you for a fine-grain control of the definitions, and is usually the preferred way of setting them.
I would argue that adding definitions for every target is easier than removing definitions from some of the targets.
This is a very important thing to be able to do when building large projects and using other 3rd party (e.g. from Github) projects in your own, as they often screw up the compile definitions and end up creating build-breaking problems that require you to selectively remove a definition, without editing the original project itself.
I haven't found a modern, per target way to do this sadly.
However, remove_definitiions is an old way to do it. It works in the sloppy old style of applying to the current subdirectory and below. This causes leakages to your other targets in the same directory frustratingly enough. But sometimes that might be exactly what you want.
One ugly solution is to break out part of your CMakeLists.txt into a separate CMakeLists.txt for the offending targets, and place remove_definitions only in that secondary CMakelists.txt in a subdirectory that quarantines those targets.
Hopefully CMake will add a target_remove_definitions() function.
Here is an example of where I needed this and how I solved it:
# main_directory/CMakeLists.txt
# Add subdir of the offending targets
add_subdirectory(evil_dependencies)
....
# main_directory/evil_dependencies/CMakeLists.txt
# This is required or else, there are headers in the repo
# that #define NOMINMAX which then causes a warning:
# macro redefinition, and warnings as errors = stop the build.
if(MSVC)
remove_definitions(/DNOMINMAX)
endif()
add_subdirectory(some_evil_dependency1)
add_subdirectory(some_evil_dependency2)
For GCC style problems it will look more like remove_definitions(-DSOMEDEFINE). Note, for this old style call, the /D or -D are required, unfortunately. This sadly requires you to write a bunch of extra if-then branches to see if you're in MSVC et. al. or GCC/Clang.
EDIT: See Remi's answer below. It's probably? better than mine, and how I think I'd do it now, mainly. My answer is still useful potentially for some situations where you actually want to remove definitions from a bunch of children folders as well, but Remi's answer is likely to be more elegant most of the time, esp. because of the regex that can make it easier to scan for -D and /D options.
As this is an open issue for CMake, it will likely be fixed any time, obsoleting these answers for newer versions of CMake. That hasn't happened yet (as of 2020-07-16). https://gitlab.kitware.com/cmake/cmake/-/issues/19796
I need to create symbolic links to directory common_resources which contains textures, fonts, 3D models, shaders, and is located in my CMAKE_SOURCE_DIR. I have to put such a link into all of my compiled binary target's working directories (~50 directories).
I can probably do it one-by-one by adding this ADD_CUSTOM_TARGET to each subfolder
ADD_CUSTOM_TARGET( common_resources ALL COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_SOURCE_DIR}/common_resources ${CMAKE_CURRENT_BINARY_DIR}/common_resources )
but I do not want to do it because:
I don't want to to edit all those CMakeList.txt files and
I don't want to create so many custom targets for no reason. I use Code::Blocks IDE and I already have very long list of targets to select from, which makes it difficult to work with.
The answer is two-fold:
Write a function wrapping the custom command.
You have to automatically iterate over all sub-directories, see https://stackoverflow.com/a/7788165/2799037 how to do that. Call your function for every sub-directory.
Your second concern is probably a misconception. custom_command does not add a new target, that is only custom_target.
Why is it recommended to add sources to a list first, rather than directly to the executable?
PROJECT( helloworld )
SET( hello_SRCS hello.cpp )
ADD_EXECUTABLE( hello ${hello_SRCS} )
Why not just skip the SET line altogether?
I have seen this practice often enough to also think that it’s considered a good practice. For example, if you use the CLion IDE (which actually uses CMakeLists.txt as its project structure file), you’ll see that when you create a new project it creates a SOURCE_FILES variable by default.
One reason I can think of as to why this is a good practice is that if you want to build the same files into several targets. For example, you might want to have both static and shared binaries for your lib, so if you have a SOURCE_FILES var you just have to write something like:
add_library(myLibStatic STATIC ${SOURCE_FILES})
add_library(myLibShared SHARED ${SOURCE_FILES})
I am new to CMake build process. I have a list of sub directories and each sub directory requires a set of include_directories ( files from different libraries).
My question is: is it efficient to add the include_directory call right at the main CMakeList so that it is reference in all the sub directories (i.e. I wouldn't need to add in all the sub directories) or is it efficient to add it every sub directory.
Please let me know what are the pros and cons of such a process.
Note: I do understand that I can add the common include files in the main cmakelist file but, what if I were to add the project specific include directories in the main CMakefile? Are all the include_directories included in the created static libraries for each sub directory ?
Sometimes incude directories can have files with same names. This can lead to situation when compiler includes wrong file. Because of this the common practice is to set include dirs in subdirectories rather than in top CMakeLists.txt.
Except this, there's no difference at all.