3

I have a C++ project and I want to use CMake in the project. My project has multiple directories and sub-directories.

I have a top-level CMakeLists.txt which builds the whole project. I also have CMakeLists.txt in the sub-directories. I wanted to set the compiler flags but here is what I am confused about. Are the effects of the compiler flags in CMake apply only to the corresponding directory or will it apply to the whole project?

For example, my project (let's call it MyProject) has a CMakeLists.txt associated. The project has two subdirectories A and B. Each with its own CMakeLists.txt. In the A/CMakelist.txt, I have set the compiler flag as below:

set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y -Wno-narrowing") 

The B/CMakeLists.txt is as below:

set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y") 

What I do not understand is that whether the compiler will use the flag -Wno-narrowing for the cpp files in subdirectory B also (in general will it apply to the whole project)?

Is the scope of setting a compiler flag (in general any variable) in CMakeList.txt are applicable only to the corresponding directory or it will be applied globally throughout the project?

1 Answer 1

4

CMake's set command works on function and directory scope. That is, if you set a variable like you did, outside of a CMake function, the effect will be visible in that directory and all of its subdirectories.

Whenever you define a new target (through calling add_executable or add_library), the value of the CMAKE_CXX_FLAG variable at that point will be used to determine the initial value of the target properties for the compile flags.

So the -Wno-narrowing option should not be able to leak over from one subdirectory to a sibling subdirectory.

A quick note on modern CMake style: Prefer using the compile features functionalities over setting the -std option directly. The former will be portable and work on all toolchains and compiler versions. For instance, to require C++14 globally for all targets in the project, simply set(CMAKE_CXX_STANDARD 14) in the top-level CMakelists. Similarly, consider using the target_compile_options command for setting options that only apply to certain targets of your project. Using that command is usually less error-prone than fiddling with the global variable everywhere. For manual toolchain-specific flags like -Wno-narrowing, consider wrapping them in a generator expression to make sure they will only be used on toolchains that supports the flag.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for the detailed answer. Just reiterating to make sure I understood correctly. The value set for CMAKE_CXX_FLAGS at the top level Cmakelist will be available to A/Cmakelist.txt. I can add or even remove flags from it but the effect will be only local to A. When it comes to B/Cmakelist.txt, the CMAKE_CXX_FLAGS setting for top-level Cmakelist.txt where target was added would come to picture(NOT the final CMAKE_CXX_FLAGS value at A).
Hi, One more follow up question regarding the CMAKE_CXX_STANDARD . Is it possible (and also is it good practice) to set the C++ version in the top level Cmakelist as 'set(CMAKE_CXX_STANDARD 14)' However, in a subdirectory Cmakelist set it as 'set(CMAKE_CXX_STANDARD 98)'
@AnkurBose No. In that case you should rather not set the variable at all and use the target_compile_features command to specify the version for each target seperately. Setting variables in CMake works best if you can do it in one place. If you scatter different values throughout the project, it becomes hard to maintain quickly. The per-target approach is preferable in that case.
Thanks for the suggesstion
Hmm, it doesn't seem to be exactly at that point to me. If I do add_library(...) before string(REPLACE "/EHsc" "/EHs-c-" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") in the same file, I seem to get the flag replaced in my build.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.