6

Elsewhere the question has been asked, "How do I turn off optimizations on one file?" The answer is usually something like this:

cmake_minimum_required( VERSION 3.8 )

project( Hello )

add_executable( hello hello.c foo.c bar.c )

set( CMAKE_C_FLAGS_RELEASE "" )
set( CMAKE_CXX_FLAGS_RELEASE "" )

set_source_files_properties( hello.c 
                PROPERTIES
                COMPILE_FLAGS -O0 )

This works unless you invoke cmake like this:

cmake -GNinja -DCMAKE_BUILD_TYPE=Release ../hello

And you get this in your build.ninja

FLAGS = -O3 -DNDEBUG   -O0

Checking the documentation on COMPILE_FLAGS

Additional flags to be added when compiling this source file.

This makes sense, it is added to the list of COMPILE_FLAGS, it does not override existing compiler flags.

So, within CMake how can you override the optimisation level on a single file and being able to compile the rest of the project in Release? Otherwise you can force the compile to CMAKE_BUILD_TYPE="" which is the default behavior, but that somewhat defeats a selling point of Cmake.

1 Answer 1

3

You can't overwrite compiler options with the makefile CMake generators on source file level. Options are always appended (see my answer at Is Cmake set variable recursive? for the complete formula).

This is - as far as I know - only supported with the Visual Studio solution/project generators. These generators have flag tables to identify flags that are in the same group/that does overwrite a previous defined flag.

So yours is more like a feature request to also add compiler option tables to CMake's makefile generators.


Alternatives

I just wanted to add some crazy CMake magic I came up with as a workaround. Add the following to your main CMakeLists.txt after the project() command:

if (CMAKE_BUILD_TYPE)
    define_property(
        SOURCE
        PROPERTY COMPILE_FLAGS 
        INHERITED 
        BRIEF_DOCS "brief-doc"
        FULL_DOCS  "full-doc"
    )
    string(TOUPPER ${CMAKE_BUILD_TYPE} _build_type)
    set_directory_properties(PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS_${_build_type}}")
    set(CMAKE_CXX_FLAGS_${_build_type} "")
endif()    

This example moves the CMAKE_CXX_FLAGS_<build type> content into an new COMPILE_FLAGS directory property that is then linked to COMPILE_FLAGS source file property via define_property(... INHERITED ...).

Now the build type specific flags are only defined in COMPILE_FLAGS for each source file and you can overwrite/change them e.g. with the code snippet from your example:

set_source_files_properties( 
    hello.c 
    PROPERTIES
    COMPILE_FLAGS -O0 
)

References

4
  • I've just forced CMake to Debug, hammered the options and then manually roll through the files and add flags. Negates a lot of the advantage of CMake... Commented Dec 21, 2017 at 17:22
  • 1
    @CameronLowellPalmer The question would be why you need to remove the leading -O3 option from the compiler's command line since: "If you use multiple -O options, with or without level numbers, the last such option is the one that is effective.".
    – Florian
    Commented Dec 21, 2017 at 21:00
  • It assumes gcc or gcc compatibility, which may apply to clang as well, but is is most certainly not something you can count on. For a large complex cross-platform project I think you need to handle this such that the flags are exactly what you desire. In a project I'm familiar with incorrect compilation would seriously harm functionality. It's a pity you can't override a single file. Commented Dec 21, 2017 at 21:11
  • @CameronLowellPalmer I added some CMake code that does accomplish what you have been asking for. But maybe better to raise an issue at the CMake project to get "overwriting compiler flags on source level" implemented as a feature in future revisions.
    – Florian
    Commented Dec 21, 2017 at 22:00

Not the answer you're looking for? Browse other questions tagged or ask your own question.