CMake/Assembler

From KitwarePublic
Jump to: navigation, search

Introduction

Since version 2.6.0 CMake has basic support for using assembler source files in CMake projects. Assembler is different from other languages in that it actually is no single language, but there are many different assembler languages. CMake supports a generic "ASM" language and specialized "ASM_XXX" languages for assembler "dialects".

Currently supported:

  • ASM-ATT (since 2.6.0)
  • ASM_MASM (since 2.6.3)

We would be happy about patches which add support for nasm, yasm, tasm, etc.

Using the CMake Assembler Support

If you have a project which contains assembler files, you still probably don't want to use them in all cases, e.g. on all architectures. You have to add CMake code which tests for the respective architectures and enables the support for the associated assembler accordingly. You should also check whether the assembler has been found by testing MAKE_ASM-ATT_COMPILER_WORKS. This variable doesn't really show whether the assembler actually works, but only whether it has been found. There is no generic test whether an assembler works since each architecture would require its own assembler source file.

It is also possible to support multiple different assemblers in one project.

set(mySrcs foo.c bar.c)

set(can_use_assembler FALSE)

# test wether it is a x86 machine and as/gas is available
if("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "i.86")
   enable_language(ASM-ATT)
   if(CMAKE_ASM-ATT_COMPILER_WORKS)
      set(can_use_assembler TRUE)
      set(mySrcs ${mySrcs} codec_i86.s)
   endif(CMAKE_ASM-ATT_COMPILER_WORKS)
endif("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "i.86")

# no assembler found
if(not can_use_assembler)
   set(mySrcs ${mySrcs} codec_generic.c)
endif(not can_use_assembler)

add_executable(player ${mySrcs})

Supported Assembler Dialects

Generic ASM

This serves as base for the different assembler dialects.

  • Supported assembler names: defaults to as, gas, may have toolchain specific prefix. This can be overriden by setting CMAKE_ASM_COMPILER before enabling the ASM language.
  • Supported source files extensions: defaults to .s, .S, .asm. This can be overriden by setting CMAKE_ASM_SOURCE_FILE_EXTENSIONS before enabling the ASM language.
  • The variables which define the commands for compiling and linking files, CMAKE_ASM_COMPILE_OBJECT, CMAKE_ASM_CREATE_(STATIC_LIBRARY|SHARED_LIBRARY|SHARED_MODULE), CMAKE_ASM_LINK_EXECUTABLE, default to gas behaviour. They can be overridden by setting them before enabling the ASM language.
  • Involved files: CMakeASMInformation.cmake, CMakeDetermineASMCompiler.cmake, CMakeTestASMCompiler.cmake

ASM-ATT

This can be used for assembler files in AT&T assembler syntax. This includes the GNU assembler gas.

  • Supported assembler names: as, gas, may have toolchain specific prefix
  • Supported source files extensions: .s, .asm
  • .S files, i.e. assembler files which require preprocessing, are not supported
  • Involved files: CMakeASM-ATTInformation.cmake, CMakeDetermineASM-ATTCompiler.cmake, CMakeTestASM-ATTCompiler.cmake

ASM_MASM

This is support for the Microsoft assembler.

  • Supported assembler names: ml, ml64
  • Supported source files extensions: .asm
  • Involved files: CMakeASM_MASMInformation.cmake, CMakeDetermineASM_MASMCompiler.cmake, CMakeTestASM_MASMCompiler.cmake

How to add support for other assembler "dialects"

Adding support for another assembler dialect is easy. It consists of just a few steps:

  1. Find an appropriate suffix for the assembler dialect, e.g. "_FOO". This will be appended to "ASM" for the language name, thus with the suffix listed, the assembler dialect is "ASM_FOO". Use an underscore as first character of the suffix.
  2. Create the needed files: CMakeASM_FOOInformation.cmake, CMakeDetermineASM_FOOCompiler.cmake and CMakeTestASM_FOOCompiler.cmake. The easiest way to create these is by copying the ASM-ATT files (CMakeASM-ATTInformation.cmake, CMakeDetermineASM-ATTCompiler.cmake, and CMakeTestASM-ATTCompiler.cmake) to the new names.
  3. Edit CMakeASM_FOOInformation.cmake. This file sets all the assembler specific variables, like filename suffixes, compile rules, etc. First thing to do here is to set ASM_DIALECT to "_FOO", then include the generic CMakeASMInformation.cmake. Reset ASM_DIALECT after that again. If necessary you can override the assembler specific variables by setting them before including the generic file.
  4. Edit CMakeDetermineASM_FOOCompiler.cmake. The purpose of this file is to find the assembler executable. Basically you do here the same as for the Information-file. Set ASM_DIALECT to "_FOO", then set CMAKE_ASM_FOO_COMPILER to the names of the foo assembler, e.g. fooasm, then include the generic file CMakeDetermineASM_Compiler.cmake and reset ASM_DIALECT afterwards.
  5. Edit CMakeTestASM_FOOCompiler.cmake. This file is responsible for testing whether the assembler works. As previously noted, this is not really possible. Instead it just tests whether the assembler has been found, i.e. whether CMAKE_ASM_FOO_COMPILER variable has been set. First set ASM_DIALECT, then include the generic file CMakeTestASM_Compiler.cmake, then reset ASM_DIALECT.

Use the ASM-ATT files as example for how to do it.

Limitations

There may be problems with dependency scanning for assembler files. Let us know if this is the case for you.

NASM

NASM is not supported 'out of the box' (as of this writing in 2009).

There has been a patch submitted by P. Collingbourne to the Kitware bug site at http://public.kitware.com/Bug/bug_view_page.php?bug_id=10069&history=1

Just before I found that patch I wrote up this little description below, which is similar to Collingbourne's patch, but he adds support for Mac and 64-bit (maybe some should edit this wiki page to make it more like his patch....).

It works like this.. you add 3 files to your Cmake Modules directory, then you call enable_language() in your CMakeLists.txt, like this:

. . .
enable_language(ASM-NASM)
add_executable(main foo.c bar.c special.nasm)
. . .

This will run the C compiler on the .c files, but nasm on the .nasm files, and link everything together at the end.

This was tested on cmake version 2.6-p2, nasm 2.05.01, and ubuntu linux 9.04

Files to create

The files you create are in your Cmake Modules directory. On Ubuntu Linux 9.04 this is in /usr/share/cmake-2.6/Modules

CMakeASM-NASMInformation.cmake

SET(ASM_DIALECT "-NASM")
SET(CMAKE_ASM${ASM_DIALECT}_SOURCE_FILE_EXTENSIONS nasm;nas;asm)

# -f elf needed for linux. nasm -hf lists many formats, and default is 'bin'
# which doesnt work. See also the post by P. Punnoor to the CMake mailing-
# -list at http://www.cmake.org/pipermail/cmake/2005-November/007478.html
IF(UNIX)
    SET(CMAKE_ASM-NASM_COMPILER_ARG1 "-f elf")
ELSE(UNIX)
    SET(CMAKE_ASM-NASM_COMPILER_ARG1 "-f win32")
ENDIF(UNIX)

# This section exists to override the one in CMakeASMInformation.cmake 
# (the default Information file). This removes the <FLAGS>
# thing so that your C compiler flags that have been set via 
# set_target_properties don't get passed to nasm and confuse it. 
IF(NOT CMAKE_ASM${ASM_DIALECT}_COMPILE_OBJECT)
  SET(CMAKE_ASM${ASM_DIALECT}_COMPILE_OBJECT "<CMAKE_ASM${ASM_DIALECT}_COMPILER> -o <OBJECT> <SOURCE>")
ENDIF(NOT CMAKE_ASM${ASM_DIALECT}_COMPILE_OBJECT)

INCLUDE(CMakeASMInformation)
SET(ASM_DIALECT)

CMakeTestASM-NASMCompiler.cmake

# determine the compiler to use for NASM

SET(ASM_DIALECT "-NASM")
SET(CMAKE_ASM${ASM_DIALECT}_COMPILER_INIT ${_CMAKE_TOOLCHAIN_PREFIX}nasm)
INCLUDE(CMakeDetermineASMCompiler)
SET(ASM_DIALECT)

CMakeDetermineASM-NASMCompiler.cmake

# This file is used by EnableLanguage in cmGlobalGenerator to
# determine that that selected ASM-NASM compiler can actually compile
# and link the most basic of programs.   If not, a fatal error
# is set and cmake stops processing commands and will not generate
# any makefiles or projects.
SET(ASM_DIALECT "-NASM")
INCLUDE(CMakeTestASMCompiler)
SET(ASM_DIALECT)