Metric Panda Games

One pixel at a time.

Using NASM with CMake and Clang

Trying to integrate NASM with CMake for the build system of Rival Fortress has been tricky. The documentation on the official wiki is not up to date, and in fact, states that NASM is not supported by CMake 2.6 and below, but fortunately after a little bit of digging through CMake’s source I found that NASM is indeed supported since CMake version 2.8.

Using NASM with CMake

To enable support for .asm source files in your project you have to make sure you add the C language flag to your project declaration in your CMakeLists.txt file like so:

project(RivalFortress C CXX)

Rival Fortress is in C++, but the C specification is required otherwise the CMake variable CMAKE_C_SIZEOF_DATA_PTR will not be set. This variable is read by the NASM CMake module during initialization and used by CMake to detect processor architecture (32/64bit) and determines the -f flag that will be passed to NASM during compilation.

Next, in order to enable *.asm compilation, you must enable the ASM_NASM language like so:

enable_language(ASM_NASM)
if(CMAKE_ASM_NASM_COMPILER_LOADED)
  set(CAN_USE_ASSEMBLER TRUE)
  file(GLOB_RECURSE ENGINE_ASM_FILES "src/engine/*.asm")
  set(ENGINE_SOURCES ${ENGINE_SOURCES} ${ENGINE_ASM_FILES})
endif(CMAKE_ASM_NASM_COMPILER_LOADED)

This snippet of code attempts to load the ASM_NASM language compiler and checks if it has been loaded correctly. If load was successful, the CAN_USE_ASSEMBLER variable is set to TRUE and all *.asm files are globbed and added to the source files to be compiles.

Later in the CMakeLists.txt you can check if assembly is supported for the current build using the CAN_USE_ASSEMBLER variable and branch like so:

if(NOT CAN_USE_ASSEMBLER)
   set(ENGINE_SOURCES ${ENGINE_SOURCES} codec_generic.cpp)
endif(NOT CAN_USE_ASSEMBLER)

Now CMake will automatically call NASM during compilation to generate object files that will be linked with other object files generated by clang.