Search code examples
cmakepost-build

CMake custom target doesn't build


I'm building two targets using:

add_library(tgt1 SHARED a.cpp)
add_library(tgt2 SHARED b.cpp)

After both are built, I need to run a post build step that depends on both targets. I tried many combinations of the following but with no success:

add_custom_target(final_tgt DEPENDS tgt1 tgt2)
add_custom_command(TARGET final_tgt POST_BUILD COMMAND <command> ARGS <args>)

The final target would simply not build, even though its build.make contains the custom command.

Tried to use ALL for the custom target, however make attempts to build it first while missing the first targets.

And I can't use an add_library or add_executable for the final target, since they require specifying source files.

What is the correct way to do it?

===================================

Edit: below is a minimal verifiable source code. What it attempts to do is to compile code (for Mac) in two architectures and as a post-build to create a universal binary using lipo:

cmake_minimum_required(VERSION 2.8)
set(icpc_req_path "/usr/local/bin/icpc-16.0.146")

set(CMAKE_CXX_COMPILER "${icpc_req_path}")

project("CMakeTest")
set(SOURCE_FILES a.cpp)

set (TARGET_NAME "TGT")
set(TARGETS "")
set(ARCHITECTURES i386 x86_64)

foreach(ar ${ARCHITECTURES})
    set(CMAKE_CXX_FLAGS_RELEASE "")
    set(CMAKE_CXX_FLAGS_DEBUG "")
    set(CMAKE_CXX_FLAGS "")

    add_library(TGT_${ar} SHARED ${SOURCE_FILES})
    set_target_properties(${TARGET_NAME}_${ar}
        PROPERTIES COMPILE_FLAGS "-arch ${ar} -xSSE3")
    set_target_properties(${TARGET_NAME}_${ar}
        PROPERTIES LINK_FLAGS "-arch ${ar}")
    set(TARGETS "${TARGETS};lib${TARGET_NAME}_${ar}.dylib")
endforeach(ar)

message("Targets: ${TARGETS}")
add_custom_target(${TARGET_NAME} DEPENDS ${TARGETS})
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
     COMMAND "lipo"
     ARGS "-create" ${TARGETS} "-output" "${TARGET_NAME}.dylib")

And the contents of a.cpp is:

int main(){}

Solution

  • add_custom_command comes in two flavors: Producing new output, and acting on single targets. Docs

    What is the command that you are calling doing? Is it in any way producing results (new files, etc)? If so, use add_custom_command like this:

    add_custom_command(
      OUTPUT <output-file>
      DEPENDS tgt1 tgt2
      COMMAND <command>
      ARGS <args>
      COMMENT "Running  <command> on targets tgt1 and tgt2."
    )
    

    Using the second variant of add_custom_command which does not have an OUTPUT argument, because it changes a <target> as POST_BUILD (or pre-build, pre-link) step, needs a single target. So, which one of tgt1 and tgt2 gets modified by your <command>?

    Let's assume that tgt1 gets modified in the POST_BUILD step and tgt2 is untouched. Then you can do it like this:

    add_library(tgt2 SHARED b.cpp)
    
    add_library(tgt1 SHARED a.cpp)
    add_custom_command(
      TARGET tgt1 POST_BUILD
      COMMAND <command>
      ARGS <args>
    )
    add_dependencies(tgt1 tgt2) # tgt1 depends on tgt2 because
    # POST_BUILD-step is just the final step to build 'tgt1'
    # NOTE: It is incorrect to modify 'tgt2' as POST_BUILD step for tgt1.
    #       So this example expects no changes to tgt2 in add_custom_command.
    

    -- EDIT after more details given in question:

    Working example

    CMakeLists.txt

    # I don't have 'icpc' and could not find it easily available for macOS.
    # Instead, let's create a file "TGT" where contents are the two hashes of the two
    # libraries, like done in 'Th.Thielemann's answer.
    cmake_minimum_required(VERSION 3.10)
    project(q50198141)
    
    add_library(Big SHARED library1.cpp)
    add_library(Foo SHARED library2.cpp)
    
    add_custom_command(OUTPUT combined
        COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/combine.sh
        ARGS $<TARGET_FILE:Big> $<TARGET_FILE:Foo> combined
        DEPENDS Big Foo combine.sh
        COMMENT Build output 'combined'
    )
    add_custom_target(run_combined ALL DEPENDS combined)
    

    combined.sh (Make sure to be excecutable!)

    #!/bin/bash
    
    # Hardcoded for q50198141    
    # Args: In1 In2 Out
    md5sum $1 $2 > $3