I would like to include a .cpp-file in two different targets (becoming two VS projects after running CMake). I would like to set different COMPILE_FLAGS for these projects.
However, when I do
SET_TARGET_PROPERTIES(myfile.cpp PROPERTIES COMPILE_FLAGS "flags1")
ADD_EXECUTABLE(project1 myfile.cpp)
SET_TARGET_PROPERTIES(myfile.cpp PROPERTIES COMPILE_FLAGS "flags2")
ADD_EXECUTABLE(project2 myfile.cpp)
the "flags2" applies for both projects, so it seems like the properties are overwritten in line 3 and not considered in line 2. Is this true or am I missing something? Is there a way to solve this?
Thank you!
Apply the set_target_properties
command to the projects and not to the source files:
add_executable(project1 myfile.cpp)
set_target_properties(project1 PROPERTIES COMPILE_FLAGS "flags1")
add_executable(project2 myfile.cpp)
set_target_properties(project2 PROPERTIES COMPILE_FLAGS "flags2")
The flags set on the target will apply to all sources within the target.
If you adhere to a one target per subdirectory philosophy, you could do the following using add_definitions
to add your compile flags.
# in ./CMakeLists.txt
add_subdirectory(project1)
add_subdirectory(project2)
# in ./project1/CMakeLists.txt:
add_definitions("flags1")
add_executable(project1 ../myfile.cpp)
# in ./project2/CMakeLists.txt:
add_definitions("flags2")
add_executable(project2 ../myfile.cpp)
add_definitions
applies to all files compiled in this subdirectory and those under it. You can apply flags to specific files using the following:
set_source_files_properties(myfile.cpp PROPERTIES COMPILE_FLAGS "flags")
I was having the same issue (how to specify per-target precompiled header dependencies on the same source file). Luckily, the effect of set_source_files_properties is only the current directory (CMAKE_CURRENT_SOURCE_DIR). I was able to use that to come up with the following:
In source directory:
CMakeLists.txt:
add_subdirectory(lib_varient_1)
add_subdirectory(lib_varient_2)
LibSources.cmake:
set(SOURCES
"${CMAKE_CURRENT_LIST_DIR}/Source1.cpp"
"${CMAKE_CURRENT_LIST_DIR}/Source2.cpp"
...)
set_source_files_properties(${SOURCES} PROPERTIES
COMPILE_FLAGS "/Yu\"stdafx.h\""
"/Fp\"${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch\"")
set_source_files_properties(${SOURCES} PROPERTIES
OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch")
set_source_files_properties(${CMAKE_CURRENT_LIST_DIR}/stdafx.cpp
PROPERTIES COMPILE_FLAGS "/Yc\"stdafx.h\""
"/Fp\"${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch\"")
set_source_files_properties(${CMAKE_CURRENT_LIST_DIR}/stdafx.cpp
PROPERTIES OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch")
add_library(lib_varient_${VARIENT} ${SOURCES} stdafx.cpp)
In lib_varient_1
CMakeLists.txt:
set(VARIENT 1)
include(../LibSources)
In lib_varient_2
CMakeLists.txt:
set(VARIENT 2)
include(../LibSources)
This works because set_source_files_properties only has an effect on the current CMakeLists.txt file. The included file will have different values for ${VARIENT} and ${CMAKE_CURRENT_BINARY_DIR} since it is included from two different CMakeLists.txt files. You can also set various compilation flags, preprocessor definitions or include paths in each of the varient's CMakeLists.txt files prior to including the LibSources.cmake file.
I solve this problem as follows. In CMakeLists.txt:
set_target_properties (test1 PROPERTIES COMPILE_DEFINITIONS "TARGET_ID=1")
set_target_properties (test2 PROPERTIES COMPILE_DEFINITIONS "TARGET_ID=9")
set_source_files_properties (source1.cpp PROPERTIES COMPILE_DEFINITIONS "FILE_ID=7")
set_source_files_properties (source2.cpp PROPERTIES COMPILE_DEFINITIONS "FILE_ID=4")
In some header file:
#if TARGET_ID==1 && FILE_ID==7
#define SPECIAL_VALUE 17
#elif TARGET_ID==1 && FILE_ID==4
#define SPECIAL_VALUE 14
#elif TARGET_ID==9 && FILE_ID==7
#define SPECIAL_VALUE 97
#elif TARGET_ID==9 && FILE_ID==4
#define SPECIAL_VALUE 94
#endif
Further, include above-mentioned header in both source1.cpp and source2.cpp and compile
I think, CMake has no more acceptable solution