Created
February 14, 2019 18:03
-
-
Save egslava/7333c2aa1cbda9cb0a965ee41512056d to your computer and use it in GitHub Desktop.
CMake: add_custom_command OUTPUT support for generator expressions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function (add_custom_sources) | |
set(options VERBATIM) | |
set(oneValueArgs TARGET OUTPUT) | |
set(multiValueArgs DEPENDS COMMAND) | |
# Problem | |
# ------- | |
# CMake doesn't support generator expressions for OUTPUT directories. | |
# Thus, it's not gonna work: | |
# add_custom_command( | |
# OUTPUT "$<TARGET_FILE_DIR:Main>/gen/file1" | |
# DEPENDS file1 | |
# COMMAND blah | |
# ) | |
# target_sources(Main "$<TARGET_FILE_DIR:Arena>/gen/file1") | |
# | |
# So there will be problems with Debug/Release configurations | |
# in MS VS and Qt and Qt Creator and need to work it around. | |
# | |
# The section below contains the code with exactly the same logic. | |
# | |
# Using | |
# ----- | |
# add_custom_sources( | |
# TARGET Main | |
# OUTPUT "$<TARGET_FILE_DIR:Main>/gen/file1" | |
# DEPENDS file1 | |
# COMMAND blah | |
# ) | |
# TARGET - is the target where your generated source code/image/3d-model/anything should be added as a dependency. | |
# | |
# How it works | |
# ------------ | |
# 1. Replacing generator expressions to something unique. | |
# I map such name "$<TARGET_FILE_DIR:Arena>/gen/file1" | |
# to somewhat like: "genexpr/TARGET_FILE_DIR_Arena/gen/file1.shadow" | |
# 2. make all the subdirectories to SHADOW and the original file | |
# 3. add_custom_command on shadow file. I add TOUCH command to | |
# create/update shadow file as well | |
# 4. target_sources(SHADOW_FILE) | |
# 1. Parsing args | |
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) | |
if ( ${ARG_VERBATIM} ) | |
set(ARG_VERBATIM VERBATIM) | |
else() | |
unset(ARG_VERBATIM) | |
endif() | |
# 2. Getting SHADOW name | |
string(REGEX REPLACE "\\$<(.+)>" "\\1" _no_genex_file ${ARG_OUTPUT} ) | |
string(REPLACE ":" "_" _no_genex_file ${_no_genex_file} ) | |
set(_no_genex_file "${_no_genex_file}.shadow") | |
set(_no_genex_file "${CMAKE_BINARY_DIR}/genex/${_no_genex_file}") | |
# 3. Making all the dirs | |
get_filename_component(_no_genex_dir ${_no_genex_file} DIRECTORY) # _from_root = "~/my/arena-shooter/client/res" | |
get_filename_component(_output_dir ${ARG_OUTPUT} DIRECTORY) | |
# 4. Running the command and TOUCHing SHADOW-file | |
add_custom_command( | |
OUTPUT ${_no_genex_file} | |
DEPENDS ${ARG_DEPENDS} | |
COMMAND ${CMAKE_COMMAND} -E make_directory ${_output_dir} | |
COMMAND ${CMAKE_COMMAND} -E make_directory ${_no_genex_dir} | |
COMMAND ${CMAKE_COMMAND} -E touch ${_no_genex_file} | |
COMMAND ${ARG_COMMAND} | |
${ARG_VERBATIM} | |
) | |
# 5. Adding the dependency, so both files (the original and the shadow) | |
# will be updated when the source file is changed | |
target_sources(Arena PUBLIC ${_no_genex_file}) | |
endfunction() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment