I am using CMake for an embedded system. In a CMakeLists.txt
I define an object library add_library(sdk OBJECT)
and add include directories and sources to this target. There are some specialized headers and sources that has to be selected based on the hardware device. Therefore I have a function that has to be called that receives the target device as a parameter and sets the necessary sources and headers. Also a target property is set with the value of the provided parameter.
function(set_target_device)
set(oneValueArgs TARGET DEVICE)
cmake_parse_arguments(PARSE_ARGV 0 ARG "" "${oneValueArgs}" "")
# skipped checks for valid device
set_target_properties(sdk PROPERTIES target_device ${ARG_DEVICE})
# skipped adding of headers and sources
endfunction()
The library can be used by adding the subdirectory and link against it. But the function set_target_device
has to be called to get a useful build.
add_subdirectory(${CMAKE_SOURCE_DIR}/deps/sdk)
set_target_device(TARGET firmware DEVICE target_device_value)
target_link_libraries(${TARGET} sdk)
Without calling the function the build is still succeeding. So I want to reject the build or fail it if the property is not set.
One idea was to add a custom target as dependency that calls a function to check the property but only way I found to do this was calling cmake in script mode, so no target related commands are availabe. Another way might be to put the whole target definition in the function so the target is not available until the functions was called. But putting a whole CMakeLists.txt in a function feels wrong.
Is there any way to check for the property and reject or fail a target if the property is not set? Or any other way to solve this problem of enforcing a function call? Is it more convinient to expect a variable to be set before adding the subdirectory?
I am using CMake for an embedded system. In a CMakeLists.txt
I define an object library add_library(sdk OBJECT)
and add include directories and sources to this target. There are some specialized headers and sources that has to be selected based on the hardware device. Therefore I have a function that has to be called that receives the target device as a parameter and sets the necessary sources and headers. Also a target property is set with the value of the provided parameter.
function(set_target_device)
set(oneValueArgs TARGET DEVICE)
cmake_parse_arguments(PARSE_ARGV 0 ARG "" "${oneValueArgs}" "")
# skipped checks for valid device
set_target_properties(sdk PROPERTIES target_device ${ARG_DEVICE})
# skipped adding of headers and sources
endfunction()
The library can be used by adding the subdirectory and link against it. But the function set_target_device
has to be called to get a useful build.
add_subdirectory(${CMAKE_SOURCE_DIR}/deps/sdk)
set_target_device(TARGET firmware DEVICE target_device_value)
target_link_libraries(${TARGET} sdk)
Without calling the function the build is still succeeding. So I want to reject the build or fail it if the property is not set.
One idea was to add a custom target as dependency that calls a function to check the property but only way I found to do this was calling cmake in script mode, so no target related commands are availabe. Another way might be to put the whole target definition in the function so the target is not available until the functions was called. But putting a whole CMakeLists.txt in a function feels wrong.
Is there any way to check for the property and reject or fail a target if the property is not set? Or any other way to solve this problem of enforcing a function call? Is it more convinient to expect a variable to be set before adding the subdirectory?
Share Improve this question edited Mar 6 at 11:24 Tsyvarev 66.6k18 gold badges135 silver badges176 bronze badges asked Mar 6 at 10:20 DreyFaxDreyFax 4273 silver badges15 bronze badges 1 |1 Answer
Reset to default 1I believe this does what you're looking for given the name of the target is assigned to TARGET_NAME
:
# Get the `target_device` property and fail if it's not set
get_target_property(property_value ${TARGET_NAME} target_device)
if(NOT property_value)
message(FATAL_ERROR "target_device not set")
endif()
I tested with placing the following above the check:
set_target_properties(${TARGET_NAME} PROPERTIES target_device test)
add_subdirectory
) is actually the most simple way. – Tsyvarev Commented Mar 6 at 11:48