如何使用 Cmake 构建带有 NASM 的二进制文件
How to use Cmake to build binaries with NASM
我正在学习 x64,但我讨厌 make,所以我试图让 cmake 使用 NASM 构建二进制文件。
cmake 大致支持这一点,但文档很糟糕。这就是我现在所做的工作,将堆栈溢出的东西拼凑在一起,然后删除不会破坏构建的所有内容:
cmake_minimum_required(VERSION 3.14)
set(CMAKE_ASM_NASM_LINK_EXECUTABLE "ld <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
set(CMAKE_ASM_NASM_OBJECT_FORMAT elf64)
project(test_project ASM_NASM)
set_source_files_properties(test.s PROPERTIES LANGUAGE ASM_NASM)
add_executable(test test.s)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
target_compile_options(test PRIVATE -g -Fdwarf)
endif()
所以有几个问题,为什么我必须告诉cmake使用ld
到link,还有更好的方法吗?
是否有类似 target_object_format
的东西可以用来指定对象格式而不是全局设置?
有没有办法让 cmake 识别一个新的扩展而不是具体告诉它每个文件是 ASM_NASM?
CMake 默认尝试使用编译器(在本例中 nasm
)作为链接器。显然 nasm
对链接一无所知,因此您必须通过指定要用于 ASM_NASM
语言的链接器来覆盖该设置。
至于为源文件指定语言,您可以这样做:
set(SOURCE_FILES test.s foo.s bar.s) # etc for all source files
set_source_files_properties(${SOURCE_FILES) PROPERTIES LANGUAGE ASM_NASM)
add_executable(test ${SOURCE_FILES})
这样您只需列出所有文件一次。
查看源代码,ASM 构建仅由 this set of poorly documented environment variables 控制。
默认情况下,CMAKE_ASM_LINK_EXECUTABLE
定义为:
<CMAKE_ASM_NASM_COMPILER> <FLAGS> <CMAKE_ASM_NASM_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>
这感觉像是一个错误,因为 nasm
不进行链接并且没有记录您需要更改此环境变量。所以要使用 ld
我们需要设置:
set(CMAKE_ASM_NASM_LINK_EXECUTABLE "ld <CMAKE_ASM_NASM_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
接下来是源文件扩展名,默认为 cmake only recognizes .asm
and .nasm
。如果我们想扩展它,我们可以通过使用相关的环境变量来实现:
set(CMAKE_ASM_NASM_SOURCE_FILE_EXTENSIONS ${CMAKE_ASM_NASM_SOURCE_FILE_EXTENSIONS} s S)
最后是对象格式,不幸的是,这也是 controlled by an environment variable,因此我们可以使用以下方式全局更改它:
set(CMAKE_ASM_NASM_OBJECT_FORMAT elf64)
或者我们可以通过重新定义 CMAKE_ASM_NASM_COMPILE_OBJECT
并创建我们自己的 属性 来获得更细粒度的控制(我不明白为什么这不是由 cmake 自己完成的):
enable_language(ASM_NASM)
set(CMAKE_ASM_NASM_COMPILE_OBJECT "<CMAKE_ASM_NASM_COMPILER> <INCLUDES> <FLAGS> -o <OBJECT> <SOURCE>")
# Create a compile option that operates on ASM_NASM files
# If the target has a property NASM_OBJ_FORMAT, use it, otherwise
# use the environment variable CMAKE_ASM_NASM_OBJECT_FORMAT
add_compile_options(
"$<$<COMPILE_LANGUAGE:ASM_NASM>:-f $<IF:$<BOOL:$<TARGET_PROPERTY:NASM_OBJ_FORMAT>>, \
$<TARGET_PROPERTY:NASM_OBJ_FORMAT>, ${CMAKE_ASM_NASM_OBJECT_FORMAT}>>"
)
add_executable(test test.S)
set_target_properties(test PROPERTIES NASM_OBJ_FORMAT elf64)
在 cmake 3.15 之前,每次通过 enable_language()
或 project()
启用 ASM_NASM
时,您都会覆盖 CMAKE_ASM_NASM_COMPILE_OBJECT
。在版本 >3.15 中,不需要调用 enable_language()
并且可以在 project()
.
中正常启用语言
奖金,CMAKE_ASM_NASM_FLAGS_DEBUG
默认情况下为空,因此请随意将其设置为合理的值:
set(CMAKE_ASM_NASM_FLAGS_DEBUG "-g -Fdwarf")
老实说,cmake 中的 ASM 支持似乎 half-baked。它明显优于 Make 或 Automake,但不支持 "modern" cmake 的惯用语,如您所愿。
我正在学习 x64,但我讨厌 make,所以我试图让 cmake 使用 NASM 构建二进制文件。
cmake 大致支持这一点,但文档很糟糕。这就是我现在所做的工作,将堆栈溢出的东西拼凑在一起,然后删除不会破坏构建的所有内容:
cmake_minimum_required(VERSION 3.14)
set(CMAKE_ASM_NASM_LINK_EXECUTABLE "ld <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
set(CMAKE_ASM_NASM_OBJECT_FORMAT elf64)
project(test_project ASM_NASM)
set_source_files_properties(test.s PROPERTIES LANGUAGE ASM_NASM)
add_executable(test test.s)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
target_compile_options(test PRIVATE -g -Fdwarf)
endif()
所以有几个问题,为什么我必须告诉cmake使用ld
到link,还有更好的方法吗?
是否有类似 target_object_format
的东西可以用来指定对象格式而不是全局设置?
有没有办法让 cmake 识别一个新的扩展而不是具体告诉它每个文件是 ASM_NASM?
CMake 默认尝试使用编译器(在本例中 nasm
)作为链接器。显然 nasm
对链接一无所知,因此您必须通过指定要用于 ASM_NASM
语言的链接器来覆盖该设置。
至于为源文件指定语言,您可以这样做:
set(SOURCE_FILES test.s foo.s bar.s) # etc for all source files
set_source_files_properties(${SOURCE_FILES) PROPERTIES LANGUAGE ASM_NASM)
add_executable(test ${SOURCE_FILES})
这样您只需列出所有文件一次。
查看源代码,ASM 构建仅由 this set of poorly documented environment variables 控制。
CMAKE_ASM_LINK_EXECUTABLE
定义为:
<CMAKE_ASM_NASM_COMPILER> <FLAGS> <CMAKE_ASM_NASM_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>
这感觉像是一个错误,因为 nasm
不进行链接并且没有记录您需要更改此环境变量。所以要使用 ld
我们需要设置:
set(CMAKE_ASM_NASM_LINK_EXECUTABLE "ld <CMAKE_ASM_NASM_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
接下来是源文件扩展名,默认为 cmake only recognizes .asm
and .nasm
。如果我们想扩展它,我们可以通过使用相关的环境变量来实现:
set(CMAKE_ASM_NASM_SOURCE_FILE_EXTENSIONS ${CMAKE_ASM_NASM_SOURCE_FILE_EXTENSIONS} s S)
最后是对象格式,不幸的是,这也是 controlled by an environment variable,因此我们可以使用以下方式全局更改它:
set(CMAKE_ASM_NASM_OBJECT_FORMAT elf64)
或者我们可以通过重新定义 CMAKE_ASM_NASM_COMPILE_OBJECT
并创建我们自己的 属性 来获得更细粒度的控制(我不明白为什么这不是由 cmake 自己完成的):
enable_language(ASM_NASM)
set(CMAKE_ASM_NASM_COMPILE_OBJECT "<CMAKE_ASM_NASM_COMPILER> <INCLUDES> <FLAGS> -o <OBJECT> <SOURCE>")
# Create a compile option that operates on ASM_NASM files
# If the target has a property NASM_OBJ_FORMAT, use it, otherwise
# use the environment variable CMAKE_ASM_NASM_OBJECT_FORMAT
add_compile_options(
"$<$<COMPILE_LANGUAGE:ASM_NASM>:-f $<IF:$<BOOL:$<TARGET_PROPERTY:NASM_OBJ_FORMAT>>, \
$<TARGET_PROPERTY:NASM_OBJ_FORMAT>, ${CMAKE_ASM_NASM_OBJECT_FORMAT}>>"
)
add_executable(test test.S)
set_target_properties(test PROPERTIES NASM_OBJ_FORMAT elf64)
在 cmake 3.15 之前,每次通过 enable_language()
或 project()
启用 ASM_NASM
时,您都会覆盖 CMAKE_ASM_NASM_COMPILE_OBJECT
。在版本 >3.15 中,不需要调用 enable_language()
并且可以在 project()
.
奖金,CMAKE_ASM_NASM_FLAGS_DEBUG
默认情况下为空,因此请随意将其设置为合理的值:
set(CMAKE_ASM_NASM_FLAGS_DEBUG "-g -Fdwarf")
老实说,cmake 中的 ASM 支持似乎 half-baked。它明显优于 Make 或 Automake,但不支持 "modern" cmake 的惯用语,如您所愿。