1

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.

MuertoExcobito
  • 9,741
  • 2
  • 37
  • 78
user1411900
  • 384
  • 4
  • 14
  • `CMAKE_BUILD_TYPE` is only for single configuration generators. You could remove `-g` from the defaults (for the compiler assuming it is `-g` for every compiler that could be used) and then add it back in for every other source file via `COMPILE_FLAGS `. – fdk1342 Dec 20 '18 at 17:25

2 Answers2

0

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 )
fdk1342
  • 3,274
  • 1
  • 16
  • 17
-1

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.

MuertoExcobito
  • 9,741
  • 2
  • 37
  • 78
  • This seems to add flags, not replace them. Unfortunately, some flags don't have a "negative form", so once added, they cannot be turned off. – user1411900 Dec 20 '18 at 06:22
  • see the sample I added, and the explanation. – MuertoExcobito Dec 21 '18 at 20:42
  • This doesn't work. The example as is returns the error `cl : Command line error D8016: '/O2' and '/RTC1' command-line options are incompatible`. This happens because the release flags were simply added to the debug flags. `${CMAKE_CXX_FLAGS_RELEASE} = /MD /O2 /Ob2 /DNDEBUG` `${CMAKE_CXX_FLAGS_DEBUG} = /MDd /Zi /Ob0 /Od /RTC1` You can verify this by looking at the complete command line for that file. – fdk1342 Dec 21 '18 at 21:11