如何使用 Cmake 通过 NASM 构建二进制文件

问题描述 投票:0回答:2

我正在学习 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
来链接,有没有更好的方法来做到这一点?

是否有类似于

target_object_format
的东西我可以用来指定对象格式而不是全局设置它?

有没有办法让 cmake 识别新的扩展名,而不是专门告诉它每个文件是 ASM_NASM?

assembly cmake nasm
2个回答
12
投票

更新:2024 年 3 月 13 日

五年后,我发布了一个 CMake 补丁,修复了大部分问题

因此,在 CMake 版本 >= 3.30 中,答案的唯一相关部分是通过

CMAKE_ASM_NASM_SOURCE_FILE_EXTENSIONS
更改源文件扩展名,您可能应该通过
-D
而不是通过
set()
命令来完成此操作。

链接器和对象格式现在应该“正常工作”。


原答案

查看源代码,ASM 构建仅由这组记录不完善的环境变量控制。

Michael 正确地指出,默认情况下,

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仅识别

.asm
.nasm
。如果我们想扩展它,我们可以通过使用关联的环境变量来实现:

set(CMAKE_ASM_NASM_SOURCE_FILE_EXTENSIONS ${CMAKE_ASM_NASM_SOURCE_FILE_EXTENSIONS} s S)

最后是对象格式,不幸的是,这也是由环境变量控制,因此我们可以使用以下方法全局更改它:

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 之前,每次通过

ASM_NASM
enable_language()
启用
project()
时,都会覆盖
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 支持似乎还不成熟。它显然比 Make 或 Automake 更好,但不能像您希望的那样顺利地支持“现代”cmake 的习惯用法。


1
投票

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})

这样您只需列出所有文件一次。

© www.soinside.com 2019 - 2024. All rights reserved.