How to omit debug info for a single source file? - cmake

I'm writing a test for a tool that parses debug info, and I would like to omit debug info for a single compilation unit (source file) in my debug target. Is there any way to accomplish this with cmake?
Obviously, I could just hardcode the compiler flags, but I'd like to keep my build portable across different OSes and toolchains (say gnu and msvc).
Changing CMAKE_BUILD_TYPE on the fly doesn't seem to work.

To do this you have to modify the default flags because with multi-configuration generators you can't force a specific build type. This is a just a quick example to show how to remove the debug flag from the defaults and then add it back in. You can then update this example to use a variable to collect all the source files and some if statements to check which compiler is being used to test for either -g or /Zi.
cmake_minimum_required(VERSION 3.12)
project(sample)
message( "\${CMAKE_CXX_FLAGS_RELEASE} = ${CMAKE_CXX_FLAGS_RELEASE}")
message( "\${CMAKE_CXX_FLAGS_DEBUG} = ${CMAKE_CXX_FLAGS_DEBUG}")
string(REPLACE "-g" "" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
string(REPLACE "/Zi" "" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
string(REPLACE "-g" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO})
string(REPLACE "/Zi" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO})
message( "\${CMAKE_CXX_FLAGS_DEBUG} = ${CMAKE_CXX_FLAGS_DEBUG}")
message( "\${CMAKE_CXX_FLAGS_RELWITHDEBINFO} = ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
set_source_files_properties(file1.cpp PROPERTIES COMPILE_FLAGS "/Zi")
add_executable( sample file1.cpp file2.cpp )

You can access the default compile flags that cmake uses per configuration (see this answer). You can also set the COMPILE_FLAGS property on any source file. Thus, after you have created a target, it should be as simple as querying the default compile options for your language, and applying the appropriate defaults using set_source_files_properties.
For example, here's a CMakeLists.txt for an extremely simple project:
cmake_minimum_required(VERSION 3.6.1)
project(MyProj)
set_source_files_properties(file1.cpp PROPERTIES COMPILE_FLAGS ${CMAKE_CXX_FLAGS_RELEASE})
get_source_file_property(FILE1_FLAGS file1.cpp COMPILE_FLAGS)
get_source_file_property(FILE2_FLAGS file2.cpp COMPILE_FLAGS)
message( "\${FILE1_FLAGS} = ${FILE1_FLAGS}")
message( "\${FILE2_FLAGS} = ${FILE2_FLAGS}")
add_executable( MyExe file1.cpp file2.cpp )
Which outputs (for MSVC):
${FILE1_FLAGS} = /MD /O2 /Ob2 /DNDEBUG
${FILE2_FLAGS} = NOTFOUND
If you inspect the generated MyExe.vcxproj, you'll see that defaults are used to compile file2.cpp, whereas for file1.cpp, all the configurations use release settings:
<ClCompile Include="C:\temp\cmake\file1.cpp">
<InlineFunctionExpansion Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AnySuitable</InlineFunctionExpansion>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">MaxSpeed</Optimization>
<RuntimeLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">MultiThreadedDLL</RuntimeLibrary>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<InlineFunctionExpansion Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AnySuitable</InlineFunctionExpansion>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MaxSpeed</Optimization>
<RuntimeLibrary Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MultiThreadedDLL</RuntimeLibrary>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<InlineFunctionExpansion Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">AnySuitable</InlineFunctionExpansion>
<Optimization Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">MaxSpeed</Optimization>
<RuntimeLibrary Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">MultiThreadedDLL</RuntimeLibrary>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<InlineFunctionExpansion Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">AnySuitable</InlineFunctionExpansion>
<Optimization Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">MaxSpeed</Optimization>
<RuntimeLibrary Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">MultiThreadedDLL</RuntimeLibrary>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<ClCompile Include="C:\temp\cmake\file2.cpp" />
I haven't tried this on other generators, but it should work identically.

Related

CMake protobuf external to application code

Basically, I want to have my structure like such:
MainRepo
+---app1
+---app2
+---common
+---some_lib1
+---some_lib2
+---protobuf
+---comms.proto
+---cs
+---Comms.pb.cs
+---cpp
+---comms.pb.cc
+---comms.pb.h
I want to be able to check out the repo and have a script that runs protoc for all the different languages for the apps that are in the repo. This is a mono repo containing an app for two different arm machines and an x64. I essentially are running protoc and it generates all the source files for c, js, cs, cpp, etc and puts them under protobuf in their own folders.
I want to have app1, for example, go find the c++ header and source and use them to build the app. At the moment, the example I have been hacking, uses cmake to generate the .cc and .h which makes it inconvenient for me as intellisense complains since those files dont exist when I'm writing.
Anyway, I've been hacking away at cmake all day. I always end up with cmake having a forward declaration error and cant compile my .cc and .h
PROJECT(test)
CMAKE_MINIMUM_REQUIRED (VERSION 2.6)
SET(CMAKE_CXX_FLAGS "-g -Wall -Werror -std=c++11")
ADD_EXECUTABLE(main main.cpp)
TARGET_LINK_LIBRARIES(main proto ${PROTOBUF_LIBRARY})
find_package(Protobuf REQUIRED)
set(PROTOBUF_IMPORT_DIRS "../proto")
set (msgs ${PROTOBUF_IMPORT_DIRS}/communications.proto)
PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${msgs})
add_library(proto SHARED ${PROTO_SRCS})
target_link_libraries(proto ${PROTOBUF_LIBRARY})
Wondering if there are any suggestions. I dont want to have my protobuf stuff outside of my common folder and I also dont need protoc to generate those files either as I do that another way (although I could change that way). I just want to ensure that the language specific files are still available to view and not just generated during cmake and I cant view them.
My 2 cents,
Here this is what I did for google/or-tools
ref: https://github.com/google/or-tools
Protobuf Integration
I'm using Fetchcontent() (CMake >= 3.18 to have SOURCE_SUBDIR option IIRC), but I also need to patch it (e.g. to have CMP0077)
you can find the protobuf patch here: https://github.com/google/or-tools/blob/stable/patches/protobuf-v3.12.2.patch
cmake/dependencies/CMakeLists.txt
include(FetchContent)
set(BUILD_SHARED_LIBS OFF)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(BUILD_TESTING OFF)
message(CHECK_START "Fetching Protobuf")
list(APPEND CMAKE_MESSAGE_INDENT " ")
set(protobuf_BUILD_TESTS OFF)
set(protobuf_BUILD_EXPORT OFF)
set(protobuf_MSVC_STATIC_RUNTIME OFF)
# FetchContent_Declare(SOURCE_SUBDIR) was introduced in 3.18
FetchContent_Declare(
protobuf
GIT_REPOSITORY "https://github.com/protocolbuffers/protobuf.git"
GIT_TAG "v3.12.2"
PATCH_COMMAND git apply "${CMAKE_CURRENT_LIST_DIR}/../../patches/protobuf-v3.12.2.patch"
SOURCE_SUBDIR cmake)
FetchContent_MakeAvailable(protobuf)
list(POP_BACK CMAKE_MESSAGE_INDENT)
message(CHECK_PASS "fetched")
ref: https://github.com/google/or-tools/blob/a0a56698ba8fd07b7f84aee4fc45d891a8cd9828/cmake/dependencies/CMakeLists.txt#L142-L168
note: for cmake < 3.18, I use ExternalProject + execute_process()
see: https://github.com/google/or-tools/blob/a0a56698ba8fd07b7f84aee4fc45d891a8cd9828/cmake/utils.cmake#L66-L137
Generate Protobuf files
Since we have integrated Protobuf, now we have access to protobuf::protoc.
To build proto file, simply adapt
# Get Protobuf include dirs
get_target_property(protobuf_dirs protobuf::libprotobuf INTERFACE_INCLUDE_DIRECTORIES)
foreach(dir IN LISTS protobuf_dirs)
if ("${dir}" MATCHES "BUILD_INTERFACE")
message(STATUS "Adding proto path: ${dir}")
list(APPEND PROTO_DIRS "--proto_path=${dir}")
endif()
endforeach()
# Generate Protobuf cpp sources
set(PROTO_HDRS)
set(PROTO_SRCS)
file(GLOB_RECURSE proto_files RELATIVE ${PROJECT_SOURCE_DIR}
"common/protobuf/*.proto"
)
foreach(PROTO_FILE IN LISTS proto_files)
#message(STATUS "protoc proto(cc): ${PROTO_FILE}")
get_filename_component(PROTO_DIR ${PROTO_FILE} DIRECTORY)
get_filename_component(PROTO_NAME ${PROTO_FILE} NAME_WE)
set(PROTO_HDR ${PROJECT_BINARY_DIR}/${PROTO_DIR}/${PROTO_NAME}.pb.h)
set(PROTO_SRC ${PROJECT_BINARY_DIR}/${PROTO_DIR}/${PROTO_NAME}.pb.cc)
#message(STATUS "protoc hdr: ${PROTO_HDR}")
#message(STATUS "protoc src: ${PROTO_SRC}")
add_custom_command(
OUTPUT ${PROTO_SRC} ${PROTO_HDR}
COMMAND protobuf::protoc
"--proto_path=${PROJECT_SOURCE_DIR}"
${PROTO_DIRS}
"--cpp_out=${PROJECT_BINARY_DIR}"
${PROTO_FILE}
DEPENDS ${PROTO_FILE} protobuf::protoc
COMMENT "Generate C++ protocol buffer for ${PROTO_FILE}"
VERBATIM)
list(APPEND PROTO_HDRS ${PROTO_HDR})
list(APPEND PROTO_SRCS ${PROTO_SRC})
endforeach()
ref: https://github.com/google/or-tools/blob/a0a56698ba8fd07b7f84aee4fc45d891a8cd9828/cmake/cpp.cmake#L234-L279
After you can use PROTO_HDR and PROTO_SRC e.g. add them to your target sources etc...
note: for .Net you can take a look at
https://github.com/google/or-tools/blob/a0a56698ba8fd07b7f84aee4fc45d891a8cd9828/cmake/dotnet.cmake#L30-L60
All in all, just adapt to your need, e.g. generate in source tree than binary dir etc. and you should be able to do whatever you want...

How to get include directories from a target for use in add_custom_target?

I'm modeling dependencies with target_link_libraries, as is done in this blog post.
target_link_libraries(Foo
LibraryA
LibraryB
)
This is working great, but for various reasons I need to use add_custom_target to preprocess to a file through a custom command. The problem is, this custom target depends on the includes of LibraryA and LibraryB. I was really hoping to do the following like how target_link_libraries works (see the LibraryA and LibraryB bit):
add_custom_target(Bar ALL
COMMAND ${CMAKE_C_COMPILER} thing.cpp LibraryA LibraryB /P
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/Path/Here
COMMENT "Preprocessing to a file"
VERBATIM
)
However, this doesn't work. LibraryA and LibraryB are put in as they appear. Even if it did work, I imagine I would get more than the includes, since I think the targets include the library as well. Maybe this is not a good approach.
So, what can I do here? How can I extract the include directories from each target, for use in the custom command? I found if I find_package(Foo REQUIRED) I get access to Foo_DIR, but that points to the build directory and not the source directory where the includes are.
You can extract the include directories from each target using get_target_property(). A target's INCLUDE_DIRECTORIES property contains the include directories for that target. Since you have two targets, LibraryA and LibraryB, we have to call it twice. Then, we can concatenate the list of include directories together using foreach(). If you are using these as include directories in a compiler command (such as MSVC), you can append the /I compiler option to each directory in the loop also:
# Get the include directories for the target.
get_target_property(LIBA_INCLUDES LibraryA INCLUDE_DIRECTORIES)
get_target_property(LIBB_INCLUDES LibraryB INCLUDE_DIRECTORIES)
# Construct the compiler string for the include directories.
foreach(dir ${LIBA_INCLUDES} ${LIBB_INCLUDES})
string(APPEND INCLUDE_COMPILER_STRING "/I${dir} ")
endforeach()
Then, you can call the custom target command using the constructed INCLUDE_COMPILER_STRING variable:
add_custom_target(Bar ALL
COMMAND ${CMAKE_C_COMPILER} thing.cpp ${INCLUDE_COMPILER_STRING} /P
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/Path/Here
COMMENT "Preprocessing to a file"
VERBATIM
)
If you wanted something more concise, you could use the generator expression example here, which gets the targets' include directories and expands them inline, within your custom target command. Something like this could work also:
add_custom_target(Bar ALL
COMMAND ${CMAKE_C_COMPILER} thing.cpp
"/I$<JOIN:$<TARGET_PROPERTY:LibraryA,INCLUDE_DIRECTORIES>,;/I>"
"/I$<JOIN:$<TARGET_PROPERTY:LibraryB,INCLUDE_DIRECTORIES>,;/I>"
/P
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/Path/Here
COMMENT "Preprocessing to a file"
VERBATIM
COMMAND_EXPAND_LISTS
)
As the comment, the current accepted answer does not handle transitive dependencies. And this question has been confusing me all day, so I'll sort it out now.
I'm in build the LibraryLinkUtilities here. This is my CMakeLists.txt used in project:
cmake_minimum_required(VERSION 3.15.0)
project ("CMakeProject1")
set(LLU_ROOT "D:/test/LibraryLinkUtilities/install")
set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "" FORCE)
find_package(LLU NO_MODULE PATH_SUFFIXES LLU)
add_library(${PROJECT_NAME} SHARED ${PROJECT_NAME}.cpp)
target_link_libraries(${PROJECT_NAME} PRIVATE LLU::LLU)
When I open the .sln with Visual Studio, It work well, I mean I can build it in any build type. But I find the include directories is empty in Configuation. This make me crazy, because I want to know the project have include which directory exactly. Then I use the function print_target_properties fixed here to print all properties about imported target:
function(print_target_properties target)
if(NOT TARGET ${target})
message(STATUS "There is no target named '${target}'")
return()
endif()
foreach(property ${CMAKE_PROPERTY_LIST})
string(REPLACE "<CONFIG>" "DEBUG" property ${property})
get_property(was_set TARGET ${target} PROPERTY ${property} SET)
if(was_set)
get_target_property(value ${target} ${property})
message("${target} ${property} = ${value}")
endif()
endforeach()
endfunction()
print_target_properties(LLU::LLU)
Note the red line place, the LLU::LLU dependent with WSTP::WSTP and WolframLibrary::WolframLibrary. So I use this code to print all include directories:
include(CMakePrintHelpers)
get_target_property(LLUDEPENDS LLU::LLU INTERFACE_LINK_LIBRARIES)
cmake_print_properties(TARGETS LLU::LLU ${LLUDEPENDS} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES)

CMake per file optimizations

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.
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
Directory properties and subdirectories
CMake: How do I change properties on subdirectory project targets?

Should I cache CMAKE_BUILD_TYPE?

If you don't set the CMAKE_BUILD_TYPE, then, by default, it doesn't get cached. Should I cache it? e.g. should I have:
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" )
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Type of build (Debug, Release etc." FORCE)
endif()
or just:
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" )
endif()
Or does it not really matter?
Caching of CMAKE_BUILD_TYPE is usefull for cmake-gui: user of your project would able to change a build type in a nice manner.
There is a good template for setting default CMAKE_BUILD_TYPE from developers:
# Set a default build type if none was specified
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to 'Debug' as none was specified.")
set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE)
# Set the possible values of build type for cmake-gui
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release"
"MinSizeRel" "RelWithDebInfo")
endif()
CMAKE_BUILD_TYPE in CMake's Cache
The user would normally define CMAKE_BUILD_TYPE via the command line with cmake -D .... So this does generate a cached entry.
And even when you don't give a CMAKE_BUILD_TYPE for single configuration makefile generators, CMake will automatically create an empty cache entry (so the user can choose in e.g. cmake-gui):
//Choose the type of build, options are: None(CMAKE_CXX_FLAGS or
// CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.
CMAKE_BUILD_TYPE:STRING=
If no default for CMAKE_BUILD_TYPE is given by the CMake's Platform/Compiler definitions via CMAKE_BUILD_TYPE_INIT like for Windows-MSVC:
# default to Debug builds
set(CMAKE_BUILD_TYPE_INIT Debug)
Settings a Default for CMAKE_BUILD_TYPE
So yes, if you want to force a default that is visible in the GUI then set the cached variable (see #Tsyvarev answer).
I don't normally force the cached defaults, I just set a temporary value if none is given. This allows e.g. my project to be used as a sub-project.
But that's more a matter of your personal taste.
In my project's those default CMAKE_BUILD_TYPE checks look a little more complex, since I allow more use cases:
# Make RelWithDebInfo the default (it does e.g. add '-O2 -g -DNDEBUG' for GNU)
# If not in multi-configuration environments, no explicit build type
# is set by the user and if we are the root CMakeLists.txt file.
if (NOT CMAKE_CONFIGURATION_TYPES AND
NOT CMAKE_NO_BUILD_TYPE AND
NOT CMAKE_BUILD_TYPE AND
CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
set(CMAKE_BUILD_TYPE RelWithDebInfo)
endif()
if (CMAKE_BUILD_TYPE)
string(TOUPPER "_${CMAKE_BUILD_TYPE}" MY_PROJECT_BUILD_TYPE_EXT)
endif()
# Choose a configuration for our compiler tests
if (NOT CMAKE_CONFIGURATION_TYPES AND
NOT CMAKE_NO_BUILD_TYPE)
set(CMAKE_TRY_COMPILE_CONFIGURATION "${CMAKE_BUILD_TYPE}")
else()
set(CMAKE_TRY_COMPILE_CONFIGURATION RelWithDebInfo)
endif()
But probably I should update this code to take the new GENERATOR_IS_MULTI_CONFIG global property into account (instead of checking for CMAKE_NO_BUILD_TYPE).
References
"CMake and the Default Build Type" blog post by Marcus D. Hanwell
CMake Issue #16768: Add reliable way to detect multi-config generators

How to set compile flags for external INTERFACE_SOURCES in CMake?

I use an external package in cmake, that uses INTERFACE_SOURCES. This means when I link the imported library to my target, the interface source files are automatically added to my target. When I compile my target, those external files are compiled too.
This causes a problem for me, because the external files cause compile warnings. I want to remove the warnings by setting a lower warning level when compiling the external files. But I do not know how to do this.
This is what I got so far.
# reduce the warning level for some files over which we have no control.
macro( remove_warning_flags_for_some_external_files myTarget )
# blacklist of files that throw warnings
set( blackListedExternalFiles
static_qt_plugins.cpp
)
get_target_property( linkedLibraries ${myTarget} LINK_LIBRARIES )
foreach(library ${linkedLibraries})
get_property( sources TARGET ${library} PROPERTY INTERFACE_SOURCES )
foreach(source ${sources})
get_filename_component(shortName ${source} NAME)
if( ${shortName} IN_LIST blackListedExternalFiles)
# everything works until here
# does not work
get_source_file_property( flags1 ${source} COMPILE_FLAGS)
# does not work
get_property(flags2 SOURCE ${source} PROPERTY COMPILE_FLAGS)
# exchange flags in list, this I can do
# set flags to source file, do not know how to
endif()
endforeach()
endforeach()
endmacro()
This is what this should do
Go through all linked libraries and get the external INTERFACE_SOURCES source files.
Check for each external source file if it appears in the black-list. If so, change its compile flags to a lower level.
The problem I have is with getting and setting the compile flags for those INTERFACE_SOURCES. The get_source_file_property() and get_property() calls return nothing.
How can I get and set the flags for these files that seem to not belong to my target, but are compiled at the same time?
The get_source_file_property() and get_property() calls return nothing
COMPILE_FLAGS property of source file is not modified by "target" commands like target_compile_options. Final set of flags is a mix of global + target specific + source specific. As far as I understand there is no way to turn off "inheriting" of global or target flags.
As a workaround you can disable warning by adding -w option:
get_source_file_property(flags "${external_source}" COMPILE_FLAGS)
if(NOT flags)
set(flags "") # convert "NOTFOUND" to "" if needed
endif()
set_source_files_properties(
"${external_source}"
PROPERTIES
COMPILE_FLAGS "-w ${flags}"
)
Just for your information: How to set warning level in CMake?.
For the record: originally from issue #408.