After building my binary, I need to run a post processing script on the binary, which effectively copies an input into the ELF object.
Under QNX, this is the “usemsg” command. The input is the target and a text file, the output is also the target, which is now modified to include the contents of that text file in the ELF object itself.
I’m able to run via add_custom_command. However, if the input file is modified, I can’t figure out how to get the custom command to run again.
Bulding works. Modify the input file ${USEFILE} and it’s not recognised.
It doesn’t seem QNX specific, anything might want to postprocess a binary and modify it based on some input file (i.e. merge resources).
Any hints on how to get this work, or alternatives? I couldn’t find any general way either to specify a file (e.g. ending in “.use”) and then apply a general rule after everything is linked either. Honestly, not too sure where I should be looking.
I was able to do a real hack (that I’m certainly not proud of, but it works as intended with side effects of having to relink).
if(DEFINED QNX_USEMSG_EXECUTABLE)
set(_singleargs DESCRIPTION)
cmake_parse_arguments(PARSE_ARGV 2 arg "" "${_singleargs}" "")
site_name(HOSTNAME)
set(_USE_INFO_SOURCE "")
string(APPEND _USE_INFO_SOURCE "USER=$ENV{USER}\nHOST=${HOSTNAME}\nMYVERSION=x\n")
if(arg_DESCRIPTION)
string(APPEND _USE_INFO_SOURCE "DESCRIPTION=${arg_DESCRIPTION}")
endif()
file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${TARGET}_info.use" "${_USE_INFO_SOURCE}")
UNSET(_USE_INFO_SOURCE)
# This is very hacky.
#
# I need a way to run `usemsg` after building the target. But
# additionally to that, if the use message file is modified, I need
# a way to re-run the command.
#
# Because `add_custom_command(TARGET ... POST_BUILD)` ignores the
# DEPENDS command, and `add_executable(TARGET file.use)` is ignored
# because it's not a source file, modifying the `file.use` won't
# cause it to rebuild.
#
# So create an empty source file, add it as a dependency to the
# executable target. The empty source file is dependent on the
# `file.use` file. Thus when the use file is modified, the timestamp
# of the empty source file is updated. This causes the binary to be
# relinked (which unfortunately can add time to the build), but at
# least the POST_BUILD now is executed resulting in the use message
# being added.
if(CMAKE_C_COMPILER_LOADED)
set(_qnx_usemsg_file "${TARGET}.tmp.c")
elseif(CMAKE_CXX_COMPILER_LOADED)
set(_qnx_usemsg_file "${TARGET}.tmp.cpp")
else()
message(FATAL_ERROR "TARGET_USE_MSG needs either C or CXX language enabled")
endif()
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${_qnx_usemsg_file}"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${USEFILE}"
COMMAND ${CMAKE_COMMAND} -E touch "${CMAKE_CURRENT_BINARY_DIR}/${_qnx_usemsg_file}"
COMMENT ""
)
add_custom_command(
TARGET ${TARGET} POST_BUILD
COMMAND ${QNX_USEMSG_EXECUTABLE}
ARGS "$<TARGET_FILE:${TARGET}>" "${CMAKE_CURRENT_SOURCE_DIR}/${USEFILE}"
COMMAND ${QNX_USEMSG_EXECUTABLE}
ARGS -f "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${TARGET}_info.use" "$<TARGET_FILE:${TARGET}>"
VERBATIM
)
target_sources(${BINARY} PRIVATE ${_qnx_usemsg_file})
endif()