如何使用Cmake与NASM生成二进制文件

时间:2019-06-03 00:49:22

标签: assembly cmake 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进行链接,并且有更好的方法吗?

是否可以使用target_object_format中的某些内容来指定对象格式,而不用进行全局设置?

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

2 个答案:

答案 0 :(得分:1)

从源头上看,ASM版本仅由this set of poorly documented environment variables控制。

Michael correctly pointed out(默认情况下,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之前,每次通过ASM_NASMenable_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 :(得分:0)

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

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