【发布时间】:2019-06-17 23:49:19
【问题描述】:
我正在使用 CMake 通过ExternalProject_Add 编译一个外部项目。项目编译完美,但我需要根据项目构建的二进制文件创建 其他 目标。
基本上,外部二进制文件是我要创建的目标的依赖项。
这意味着我无法为不存在的文件创建目标(还),因此 CMake 会抱怨。由于这个确切原因,我无法创建一组文件 (file(GLOB files $external_build/bin)) 或使用任何其他 CMake 规则,因为它们是在配置时进行评估的。
有没有办法在编译后评估 CMake 规则?
用例
我正在使用 LLVM,并且我已经修改了 llc,将自定义通行证集成到其中。我需要在现实世界的项目中测试我修改后的llc 可执行文件,例如,这是我直接从源代码树编译 GNU 的 binutils 的方法:
set(BINUTILS_URL "https://ftp.gnu.org/gnu/binutils/binutils-2.32.tar.xz")
set(BINUTILS_SHA256 "0ab6c55dd86a92ed561972ba15b9b70a8b9f75557f896446c82e8b36e473ee04")
set(BINUTILS_PREFIX ${CMAKE_BINARY_DIR}/binutils)
set(BINUTILS_BINARY_DIR ${BINUTILS_PREFIX}/bin)
find_program(MAKE_BIN NAMES gmake nmake make)
ExternalProject_Add(binutils
URL ${BINUTILS_URL}
URL_HASH SHA256=${BINUTILS_SHA256}
BUILD_IN_SOURCE On
GIT_PROGRESS On
CONFIGURE_COMMAND ${WLLVM_CONFIGURE_FLAGS} ./configure --prefix ${BINUTILS_PREFIX}
BUILD_COMMAND ${WLLVM_COMPILE_FLAGS} ${MAKE_BIN} -j${JOBS}
)
ExternalProject_Add_Step(binutils
extract-bitcode
COMMENT "Extracting binutils' bitcode..."
DEPENDEES install
WORKING_DIRECTORY ${BINUTILS_BINARY_DIR}
COMMAND ${EXTRACT_BC_EXE} ${BINUTILS_BINARY_DIR}
)
为了测试llc,我需要处理LLVM 的位码,所以我使用wllvm 来编译LLVM 的位码并将其直接嵌入到binutils 的已编译二进制文件中。
从现在开始,我需要二进制文件列表(设置输出二进制目录后非常简单)通过add_executable 创建 CMake 目标。
我已经使用add_custom_command() 用我的自定义工具链编译.c 文件:这种情况不会有什么不同,但这次我没有可用的位码文件(与.c 文件相反),因为它们是由extract-bitcode 步骤。
编辑:
我遵循了 cmets 中的建议,并提出了这个CMakeLists.txt。我已经手动插入了构建的二进制文件列表,我想用自动化的东西替换它,然后我添加了指令以从ExternalProject_Add 的步骤之一生成的.bc 文件中创建新的可执行文件。
不幸的是,CMake 抱怨循环依赖。我想我必须找到一种方法让 CMake 了解 .bc 文件。
这是我的CMakeLists.txt:
set(BINUTILS_URL "https://ftp.gnu.org/gnu/binutils/binutils-2.32.tar.xz")
set(BINUTILS_SHA256 "0ab6c55dd86a92ed561972ba15b9b70a8b9f75557f896446c82e8b36e473ee04")
set(BINUTILS_PREFIX ${CMAKE_BINARY_DIR}/binutils)
set(BINUTILS_BINARY_DIR ${BINUTILS_PREFIX}/bin)
set(BINUTILS_BINARY_NAMES
addr2line
ar
as
c++filt
elfedit
gprof
ld
ld.bfd
nm
objcopy
objdump
ranlib
readelf
size
strings
strip
)
find_program(MAKE_BIN NAMES gmake nmake make)
# This step will compile GNU's binutils
ExternalProject_Add(binutils
URL ${BINUTILS_URL}
URL_HASH SHA256=${BINUTILS_SHA256}
BUILD_IN_SOURCE On
GIT_PROGRESS On
CONFIGURE_COMMAND ${WLLVM_CONFIGURE_FLAGS} ./configure --prefix ${BINUTILS_PREFIX}
BUILD_COMMAND ${WLLVM_COMPILE_FLAGS} ${MAKE_BIN} -j${JOBS}
)
# This step will create the ${binutil-exec}.bc files needed in the next step
ExternalProject_Add_Step(binutils
extract-bitcode
COMMENT "Extracting binutils' bitcode..."
DEPENDEES install
WORKING_DIRECTORY ${BINUTILS_BINARY_DIR}
COMMAND ${EXTRACT_BC_EXE} ${BINUTILS_BINARY_DIR}
)
# use llc on the ${binutils-exec}.bc files
foreach (exec_name ${BINUTILS_BINARY_NAMES})
set(llc_exec_name "${exec_name}-llc")
add_dependencies(binutils ${llc_exec_name})
add_executable(${llc_exec_name} ${llc_exec_name}.s)
target_link_libraries(${llc_exec_name} c)
add_custom_command(
OUTPUT
${llc_exec_name}.s
DEPENDS
binutils llc
COMMAND
$<TARGET_FILE:llc>
ARGS
${BINUTILS_BINARY_DIR}/${llc_exec_name}.bc -o ${llc_exec_name}.s
)
endforeach ()
这是运行cmake时的CMake错误:
CMake Error: The inter-target dependency graph contains the following strongly connected component (cycle):
"objcopy-llc" of type EXECUTABLE
depends on "binutils" (strong)
"elfedit-llc" of type EXECUTABLE
depends on "binutils" (strong)
"addr2line-llc" of type EXECUTABLE
depends on "binutils" (strong)
"strip-llc" of type EXECUTABLE
depends on "binutils" (strong)
"nm-llc" of type EXECUTABLE
depends on "binutils" (strong)
"as-llc" of type EXECUTABLE
depends on "binutils" (strong)
"c++filt-llc" of type EXECUTABLE
depends on "binutils" (strong)
"binutils" of type UTILITY
depends on "objcopy-llc" (strong)
depends on "elfedit-llc" (strong)
depends on "addr2line-llc" (strong)
depends on "strip-llc" (strong)
depends on "nm-llc" (strong)
depends on "as-llc" (strong)
depends on "c++filt-llc" (strong)
depends on "ar-llc" (strong)
depends on "ld.bfd-llc" (strong)
depends on "objdump-llc" (strong)
depends on "ld-llc" (strong)
depends on "gprof-llc" (strong)
depends on "readelf-llc" (strong)
depends on "size-llc" (strong)
depends on "ranlib-llc" (strong)
depends on "strings-llc" (strong)
"ar-llc" of type EXECUTABLE
depends on "binutils" (strong)
"ld.bfd-llc" of type EXECUTABLE
depends on "binutils" (strong)
"objdump-llc" of type EXECUTABLE
depends on "binutils" (strong)
"ld-llc" of type EXECUTABLE
depends on "binutils" (strong)
"gprof-llc" of type EXECUTABLE
depends on "binutils" (strong)
"readelf-llc" of type EXECUTABLE
depends on "binutils" (strong)
"size-llc" of type EXECUTABLE
depends on "binutils" (strong)
"ranlib-llc" of type EXECUTABLE
depends on "binutils" (strong)
"strings-llc" of type EXECUTABLE
depends on "binutils" (strong)
At least one of these targets is not a STATIC_LIBRARY. Cyclic dependencies are allowed only among static libraries.
【问题讨论】:
-
你不知道要构建哪些二进制文件吗?
-
您能否在此处提供有关您的用例的更多背景信息?如果 cmake 以您希望的方式工作,您会使用什么流程?
-
您可以将
ExternalProject_Add创建的目标添加为依赖项。不过,这不会注入包含或链接路径,这可能需要更多的工作。 -
@VTT:是的,我已经考虑过了。我正在尝试自动获取二进制文件列表,因为这是一个我会为几个外部项目重复的过程,我希望它尽可能地即插即用。如果存在,我会优先考虑自动方法。
-
@MilesBudnek:我没想到,谢谢。这应该可以解决我的部分问题。