Access target's properties during link operation for platform specific post-processing steps
Hello,
Here is the description of the problem I tried to solve with !1346 (closed).
In short, I would like to be able to access a target's processing during the link operations.
On some platforms, for example, the final binary that can be run is not the direct output of the linker operation, but instead requires additional post-processing.
Let's take as an illustration an embedded platform where the compiler outputs an ELF, but which executable format has a custom header, with a per-application title, concatenated for example with the code and data sections.
I have found two ways of addressing this, but neither is ideal.
-
First, the platform can define the
CMAKE_<lang>_LINK_EXECUTABLE
variable with the additional steps as multiple commands like this for example:set(CMAKE_${lang}_LINK_EXECUTABLE "<CMAKE_CXX_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" "\"${CMAKE_COMMAND}\" -D \"TARGET=<TARGET>\" -D \"TARGET_TITLE=Sample Title\" -P \"${CMAKE_CURRENT_LIST_DIR}/${CMAKE_SYSTEM_NAME}-MakeBinary.cmake\"" )
This works fine as long as all the required data is avalable in the limited number of variables supported by cmRulePlaceholderExpander. This does not support generator expressions, so target's properties are not accessible, and thus it would not be possible to change the
TARGET_TITLE
parameter value using a target property (with a default value set globally in the platform). -
Another solution I recently came up with (which is slightly better) is to abuse the
add_executable
/_add_executable
functions, which although being not documented allow a platform to hook the creation of every single executable by redefiningadd_executable
and call_add_executable
.It's then possible to add
POST_BUILD
custom commands to every executable, accessing target's properties using generator expressions, like this:function(add_executable TARGET) _add_executable(${TARGET} ${ARGN}) add_custom_command(TARGET ${TARGET} POST_BUILD COMMAND "${CMAKE_COMMAND}" -D "TARGET=$<TARGET_FILE:${TARGET}>" -D "TARGET_TITLE=$<TARGET_PROPERTY:${TARGET},TITLE>" -P "${CMAKE_CURRENT_LIST_DIR}/${CMAKE_SYSTEM_NAME}-MakeBinary.cmake" ) endfunction()
Another advantage for this approach is that it is also possible to add additional file dependencies to the link step by systematically creating an empty static library as a custom target linked with the executable target, with
DEPENDS
parameter.
So, approach 1. requires modifications in cmRulePlaceholderExpander
to be
able to access a target's property, and approach 2. (which I believe is
more powerful) relies on an unofficial hook of add_executable
(and add_library
could be done as well I believe).
Any thoughts?