在CMake中添加一个从模板构建链接器脚本文件的步骤?

wbrvyc0a  于 2022-11-11  发布在  其他
关注(0)|答案(1)|浏览(172)

基本上,在执行链接之前,我希望将GCC链接器脚本模板文件转换为最终的链接器脚本,如Can I use Preprocessor Directives in .ld file中所讨论的那样-并且我希望由Cmake执行该步骤。
我猜我的问题类似于add_custom_command is not generating a target中的讨论;但是我仍然不知道如何解决这个问题。下面是一个最小的例子,我使用一个空的.ld链接器脚本模板文件来伪造;首先,让我们使用bash创建文件:

mkdir /tmp/cmake_test && cd /tmp/cmake_test

touch my_linkerscript_template.ld

cat > main.c <<'EOF'

# include <stdio.h>

const char greeting[] = "hello world";

int main() {
    printf("%s!\n", greeting);
    return 0;
}
EOF

cat > CMakeLists.txt <<'EOF'
cmake_minimum_required(VERSION 3.13)
SET(CMAKE_INCLUDE_CURRENT_DIR ON)

project(foobar C)
message("PROJECT_NAME is '${PROJECT_NAME}'")

add_executable(${PROJECT_NAME} 
               main.c
              )

add_compile_options(-Wall
                   )

target_link_options(${PROJECT_NAME} PRIVATE
                    "LINKER:--script=${CMAKE_SOURCE_DIR}/my_linkerscript.ld"
                   )
add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/my_linkerscript.ld
                   DEPENDS ${CMAKE_SOURCE_DIR}/my_linkerscript_template.ld
                   COMMAND bash ARGS -c "gcc -E -x c -CC -I/usr/include my_linkerscript_template.ld | grep -v '^#' > my_linkerscript.ld"
                   WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
                   COMMENT "build my_linkerscript_template.ld into my_linkerscript.ld (${CMAKE_CURRENT_SOURCE_DIR})"
                   VERBATIM
                   )
set_target_properties(${PROJECT_NAME} PROPERTIES LINK_DEPENDS "${CMAKE_SOURCE_DIR}/my_linkerscript.ld")
EOF

注意,上面没有创建my_linkerscript.ld;因为我打算把my_linkerscript_template.ld放到git中,然后根据需要生成最终的my_linkerscript.ld
如果在这种情况下,我这样做:

mkdir /tmp/cmake_test/build && cd /tmp/cmake_test/build
cmake ../ -DCMAKE_BUILD_TYPE=Debug
make

我得到:

$ make
make[2]:***No rule to make target 'D:/msys64/tmp/cmake_test/my_linkerscript.ld', needed by 'foobar.exe'.  Stop.
make[1]:***[CMakeFiles/Makefile2:83: CMakeFiles/foobar.dir/all] Error 2
make:***[Makefile:91: all] Error 2

$ grep -r linkerscript .
./CMakeFiles/foobar.dir/build.make:foobar.exe: D:/msys64/tmp/cmake_test/my_linkerscript.ld
./CMakeFiles/foobar.dir/build.make:     /D/msys64/mingw64/bin/cc.exe -g -Wl,--script=D:/msys64/tmp/cmake_test/my_linkerscript.ld -Wl,--whole-archive CMakeFiles/foobar.dir/objects.a -Wl,--no-whole-archive -o foobar.exe -Wl,--out-implib,libfoobar.dll.a -Wl,--major-image-version,0,--minor-image-version,0  -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32

因此,我得到了对my_linkerscript.ld的依赖关系;并且它确实被添加到了链接器选项中--但是add_custom_command没有生成任何构建步骤。
如何生成正确的依赖项,以便在需要my_linkerscript.ld进行链接但它不存在时,运行命令(在上面的add_custom_command中给出),从模板生成此文件?

fkaflof6

fkaflof61#

add_custom_command的输出需要由某个目标“使用”,否则自定义命令无效。
属性LINK_DEPENDS不提供消费者,因此您需要自己创建消费者目标:


# ... in addition to your code

# Create a consumer target for the linker script.

# So previous `add_custom_command` will have an effect.

add_custom_target(my_linkerscript
  DEPENDS ${CMAKE_SOURCE_DIR}/my_linkerscript.ld)

# Make executable to depend on that target.

# So, the check whether to relink the executable will be performed

# after possible rebuilding the linker script.

add_dependencies(${PROJECT_NAME} my_linkerscript)

相关问题