CMake 自定义目标不构建
CMake custom target doesn't build
我正在使用以下方法构建两个目标:
add_library(tgt1 SHARED a.cpp)
add_library(tgt2 SHARED b.cpp)
两者都构建完成后,我需要 运行 一个 post 依赖于两个目标的构建步骤。我尝试了以下的许多组合但没有成功:
add_custom_target(final_tgt DEPENDS tgt1 tgt2)
add_custom_command(TARGET final_tgt POST_BUILD COMMAND <command> ARGS <args>)
最终目标根本不会构建,即使其 build.make 包含自定义命令。
尝试将 ALL 用于自定义目标,但是在缺少第一个目标时尝试先构建它。
而且我不能使用 add_library 或 add_executable 作为最终目标,因为它们需要指定源文件。
正确的做法是什么?
===================================
编辑:下面是一个最小的可验证源代码。
它试图做的是在两种架构中编译代码(针对 Mac),并作为 post-build 使用 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")
而a.cpp的内容是:
int main(){}
add_custom_command
有两种形式:产生新的输出和作用于单一目标。 Docs
您调用的命令是做什么的?它是否以任何方式产生结果(新文件等)?如果是这样,请像这样使用 add_custom_command
:
add_custom_command(
OUTPUT <output-file>
DEPENDS tgt1 tgt2
COMMAND <command>
ARGS <args>
COMMENT "Running <command> on targets tgt1 and tgt2."
)
使用 add_custom_command
的第二个变体,它没有 OUTPUT
参数,因为它将 <target>
更改为 POST_BUILD
(或预构建,预link) 步骤,需要一个目标。那么,tgt1
和 tgt2
中的哪一个被你的 <command>
修改了?
让我们假设 tgt1
在 POST_BUILD 步骤中被修改并且 tgt2 未被修改。那么你可以这样做:
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.
--
在问题中给出更多细节后进行编辑:
工作示例
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
(确保可执行!)
#!/bin/bash
# Hardcoded for q50198141
# Args: In1 In2 Out
md5sum >
以下示例对我有用。
两个相互独立的目标。一个自定义目标取决于两者。
add_library(Big SHARED ${SOURCES_BIG})
add_library(Foo SHARED ${SOURCES_FOO})
add_custom_target(pack ALL
COMMAND ${CMAKE_COMMAND} -E md5sum ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}Big${CMAKE_SHARED_LIBRARY_SUFFIX}
COMMAND ${CMAKE_COMMAND} -E md5sum ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}Foo${CMAKE_SHARED_LIBRARY_SUFFIX}
DEPENDS Big Foo
COMMENT Build target pack
)
注意:计算代码的哈希只是为了显示目标是否在更改时重建。
我正在使用以下方法构建两个目标:
add_library(tgt1 SHARED a.cpp)
add_library(tgt2 SHARED b.cpp)
两者都构建完成后,我需要 运行 一个 post 依赖于两个目标的构建步骤。我尝试了以下的许多组合但没有成功:
add_custom_target(final_tgt DEPENDS tgt1 tgt2)
add_custom_command(TARGET final_tgt POST_BUILD COMMAND <command> ARGS <args>)
最终目标根本不会构建,即使其 build.make 包含自定义命令。
尝试将 ALL 用于自定义目标,但是在缺少第一个目标时尝试先构建它。
而且我不能使用 add_library 或 add_executable 作为最终目标,因为它们需要指定源文件。
正确的做法是什么?
===================================
编辑:下面是一个最小的可验证源代码。 它试图做的是在两种架构中编译代码(针对 Mac),并作为 post-build 使用 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")
而a.cpp的内容是:
int main(){}
add_custom_command
有两种形式:产生新的输出和作用于单一目标。 Docs
您调用的命令是做什么的?它是否以任何方式产生结果(新文件等)?如果是这样,请像这样使用 add_custom_command
:
add_custom_command(
OUTPUT <output-file>
DEPENDS tgt1 tgt2
COMMAND <command>
ARGS <args>
COMMENT "Running <command> on targets tgt1 and tgt2."
)
使用 add_custom_command
的第二个变体,它没有 OUTPUT
参数,因为它将 <target>
更改为 POST_BUILD
(或预构建,预link) 步骤,需要一个目标。那么,tgt1
和 tgt2
中的哪一个被你的 <command>
修改了?
让我们假设 tgt1
在 POST_BUILD 步骤中被修改并且 tgt2 未被修改。那么你可以这样做:
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.
-- 在问题中给出更多细节后进行编辑:
工作示例
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
(确保可执行!)
#!/bin/bash
# Hardcoded for q50198141
# Args: In1 In2 Out
md5sum >
以下示例对我有用。
两个相互独立的目标。一个自定义目标取决于两者。
add_library(Big SHARED ${SOURCES_BIG})
add_library(Foo SHARED ${SOURCES_FOO})
add_custom_target(pack ALL
COMMAND ${CMAKE_COMMAND} -E md5sum ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}Big${CMAKE_SHARED_LIBRARY_SUFFIX}
COMMAND ${CMAKE_COMMAND} -E md5sum ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}Foo${CMAKE_SHARED_LIBRARY_SUFFIX}
DEPENDS Big Foo
COMMENT Build target pack
)
注意:计算代码的哈希只是为了显示目标是否在更改时重建。