# Operating on Target after it's built to modify based on input file

**URL:** https://discourse.cmake.org/t/operating-on-target-after-its-built-to-modify-based-on-input-file/13575
**Category:** Code
**Created:** [February 13, 2025, 10:07pm UTC](https://discourse.cmake.org/t/operating-on-target-after-its-built-to-modify-based-on-input-file/13575 "2025-02-13T22:07:12Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![jcurl](https://discourse.cmake.org/user_avatar/discourse.cmake.org/jcurl/32/4992_2.png) [@jcurl](https://discourse.cmake.org/u/jcurl)
#### Post date: [February 13, 2025, 10:07pm UTC](https://discourse.cmake.org/t/operating-on-target-after-its-built-to-modify-based-on-input-file/13575/1 "2025-02-13T22:07:12Z")

</div>

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.

```auto
function(target_use_msg TARGET USEFILE)
    if(QNXNTO)
        set(QNX_USEMSG_EXECUTABLE usemsg)
        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)

            add_custom_target(
                ${TARGET}_use
                DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${USEFILE}"
            )
            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
            )
            add_dependencies(${TARGET} ${TARGET}_use)
        endif()
    endif()
endfunction()

```

This is just one variation. I hoped I could create some kind of dependencies. But that code is not helping. Just the same is using:

```auto
            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}>"
            )

```

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.

---

<div class="post-metadata">

### Author: ![LegalizeAdulthood](https://discourse.cmake.org/user_avatar/discourse.cmake.org/legalizeadulthood/32/5282_2.png) [@LegalizeAdulthood](https://discourse.cmake.org/u/LegalizeAdulthood)
#### Post date: [February 14, 2025, 5:22pm UTC](https://discourse.cmake.org/t/operating-on-target-after-its-built-to-modify-based-on-input-file/13575/2 "2025-02-14T17:22:53Z")

</div>

> [@jcurl](#):
>
> Bulding works. Modify the input file ${USEFILE} and it’s not recognised.

Is `${USEFILE}` added as a source to the target that contains the custom command?

You’re not using [`MAIN_DEPENDENCY` or `DEPENDS` keywords](https://cmake.org/cmake/help/latest/command/add_custom_command.html) to tell CMake that the custom command depends on the input file.

---

<div class="post-metadata">

### Author: ![jcurl](https://discourse.cmake.org/user_avatar/discourse.cmake.org/jcurl/32/4992_2.png) [@jcurl](https://discourse.cmake.org/u/jcurl)
#### Post date: [February 14, 2025, 7:14pm UTC](https://discourse.cmake.org/t/operating-on-target-after-its-built-to-modify-based-on-input-file/13575/3 "2025-02-14T19:14:49Z")

</div>

The QNX usemsg takes an input file and literally copies it into the target verbatim as an ELF section.

I had tried initially to add the ${USEFILE} to the sources via the add\_executable without success.

---

<div class="post-metadata">

### Author: ![jcurl](https://discourse.cmake.org/user_avatar/discourse.cmake.org/jcurl/32/4992_2.png) [@jcurl](https://discourse.cmake.org/u/jcurl)
#### Post date: [February 14, 2025, 10:06pm UTC](https://discourse.cmake.org/t/operating-on-target-after-its-built-to-modify-based-on-input-file/13575/4 "2025-02-14T22:06:03Z")

</div>

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).

```auto
        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()

```

I’d appreciate if there are better ideas.

---

<div class="post-metadata">

### Author: ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)
#### Post date: [February 15, 2025, 5:48am UTC](https://discourse.cmake.org/t/operating-on-target-after-its-built-to-modify-based-on-input-file/13575/5 "2025-02-15T05:48:33Z")

</div>

You may use a checksum check to trigger the build again if needed:

```cmake

add_library(ObjLib OBJECT ${CMAKE_BINARY_DIR}/gtest-tidy-mwe.cpp)

# NOTE: OBJECT_DEPENDS does not help? CK
# TODO: set_property(TARGET ObjLib PROPERTY OBJECT_DEPENDS ${CMAKE_BINARY_DIR}/verify/gtest-tidy-mwe.md5)

add_executable(gtest-tidy-mwe $<TARGET_OBJECTS:ObjLib>)

target_link_libraries(gtest-tidy-mwe PRIVATE GTest::gtest_main)

# enable clang-tidy for my target only!
target_enable_clang_tidy(gtest-tidy-mwe)

enable_testing()
add_test(NAME gtest-tidy-mwe COMMAND gtest-tidy-mwe)
install(TARGETS gtest-tidy-mwe)

# Additional command which will run after the above from a different directory
add_custom_command(
    TARGET gtest-tidy-mwe
    POST_BUILD
    COMMAND md5sum $<TARGET_OBJECTS:ObjLib> $<TARGET_FILE:gtest-tidy-mwe> > gtest-tidy-mwe.md5
    BYPRODUCTS ${CMAKE_BINARY_DIR}/verify/gtest-tidy-mwe.md5
    WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/verify
)

# Additional target the depends on BYPRODUCT above ...
add_custom_target(
    check
    COMMAND md5sum -c gtest-tidy-mwe.md5 || touch $<TARGET_OBJECTS:ObjLib>
    DEPENDS gtest-tidy-mwe
    WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/verify
)

```
