CMAKE - setting compile flags for libraries
Asked Answered
S

1

5

I have a CMakeLists.txt script to compile my libraries. The problem is I cannot set the compile flags for the libraries.

I've tried

SET(CMAKE_CXX_FLAGS "/W3 /nologo /EHsc")
SET(CMAKE_CXX_FLAGS_DEBUG "/MTd /Od /Ob0 /Zi /RTC1 /DDEBUG /D_DEBUG")
SET(CMAKE_CXX_FLAGS_RELEASE "/MT /O2 /Ob2 /DNDEBUG")
SET(CMAKE_C_FLAGS "/W3 /nologo /EHsc")
SET(CMAKE_C_FLAGS_DEBUG "/MTd /Od /Ob0 /Zi /RTC1 /DDEBUG /D_DEBUG")
SET(CMAKE_C_FLAGS_RELEASE "/MT /O2 /Ob2 /DNDEBUG")
SET(CMAKE_EXE_LINKER_FLAGS "/W3 /nologo /EHsc")
SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "/MTd /Od /Ob0 /Zi /RTC1 /DDEBUG /D_DEBUG")
SET(CMAKE_EXE_LINKER_FLAGS_RELEASE "/MT /O2 /Ob2 /DNDEBUG")
SET(CMAKE_MODULE_LINKER_FLAGS "/W3 /nologo /EHsc")
SET(CMAKE_MODULE_LINKER_FLAGS_DEBUG "/MTd /Od /Ob0 /Zi /RTC1 /DDEBUG /D_DEBUG")
SET(CMAKE_MODULE_LINKER_FLAGS_RELEASE "/MT /O2 /Ob2 /DNDEBUG")
SET(CMAKE_SHARED_LINKER_FLAGS "/W3 /nologo /EHsc")
SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "/MTd /Od /Ob0 /Zi /RTC1 /DDEBUG /D_DEBUG")
SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "/MT /O2 /Ob2 /DNDEBUG")
SET(CMAKE_STATIC_LINKER_FLAGS "/W3 /nologo /EHsc")
SET(CMAKE_STATIC_LINKER_FLAGS_DEBUG "/MTd /Od /Ob0 /Zi /RTC1 /DDEBUG /D_DEBUG")
SET(CMAKE_STATIC_LINKER_FLAGS_RELEASE "/MT /O2 /Ob2 /DNDEBUG")

None of those have effect...

The only way I can change flags for a library is like this.

SET_TARGET_PROPERTIES(MyLib PROPERTIES COMPILE_FLAGS "/W3 /nologo /EHsc")

and this will change the flags for both Debug and Release

How in the world can I set the Release and Debug flags separately for a library using CMake?

Snowfield answered 24/7, 2015 at 23:7 Comment(0)
W
14

Those are globally cached variables you are trying overwrite in your first approach.

Changing those compiler/linker options locally you need config-specific target properties or generator expressions. So taking your second approach and How can I set specific compiler flags for a specific target in a specific build configuration using CMake? I would get:

target_compile_options(
    MyLib PRIVATE 
    /W3 /nologo /EHsc
    "$<$<CONFIG:Debug>:/MTd;/Od;/Ob0;/Zi;/RTC1;/DDEBUG;/D_DEBUG>"
    "$<$<CONFIG:Release>:/MT;/O2;/Ob2;/DNDEBUG>"
)

or for CMake versions <= 2.8.12 (see also policy CMP0043):

set_target_properties(
    MyLib PROPERTIES 
        COMPILE_FLAGS 
            "/W4 /nologo /EHsc"
        COMPILE_FLAGS_DEBUG
            "/MTd /Od /Ob0 /Zi /RTC1"
        COMPILE_FLAGS_RELEASE
            "/MT /O2 /Ob2"
        COMPILE_DEFINITIONS_DEBUG
            "DEBUG;_DEBUG"
        COMPILE_DEFINITIONS_RELEASE
            "NDEBUG"
)

I personally like the "OLD" way of doing it better, because it replaces the default options in Visual Studio's project properties. Whatever is passed via target_compile_options() will end up in Configuration Properties / C/C++ / Command Line / Additional Options.

Some background information why your first approach didn't work:

CMake's generator takes whatever is set for CMAKE_<LANG>_FLAGS at the end of any CMakeLists.txt file and applies it to all library and executable targets in the same CMakeLists.txt file as the default compiler options when generating the build environment.

If you set the linker variables for you main CMakeLists.txt targets in subdirectories CMakeLists.txt it won't help (wrong scope). If I take your above code into the main CMakeLists.txt it does work and I get the following warnings (because you used compiler options for the linker):

1>LINK : warning LNK4044: unrecognized option '/W3'; ignored
1>LINK : warning LNK4044: unrecognized option '/EHsc'; ignored
1>LINK : warning LNK4044: unrecognized option '/MTd'; ignored
1>LINK : warning LNK4044: unrecognized option '/Od'; ignored
1>LINK : warning LNK4044: unrecognized option '/Ob0'; ignored
1>LINK : warning LNK4044: unrecognized option '/Zi'; ignored
1>LINK : warning LNK4044: unrecognized option '/RTC1'; ignored
1>LINK : warning LNK4044: unrecognized option '/DDEBUG'; ignored
1>LINK : warning LNK4044: unrecognized option '/D_DEBUG'; ignored

I'm now hiding the cached variables of the same name set by CMake during the compiler detection. For more details see:

Wendolynwendt answered 25/7, 2015 at 8:25 Comment(2)
Very nice answer, thanks for the references. I believe target_compile_options with generators are supported in 2.8.12.Pomiferous
I had to remove the quotation marks from the generator example to get this working with GCC 9.2.Bolme

© 2022 - 2024 — McMap. All rights reserved.