How to generate raw binary (*.bin) with CMake

Viewed 134

Is there any simple and canonical way within CMake to compile C and/or C++ code into a raw binary (*.bin)?

What I would like is something equivalent to:

# Imaginary syntax
add_binary(something ${source_files})

to produce a something.bin while still having "something" act as a proper CMake target. Ideally I want this to still interoperate with the normal built-in mechanisms like target_include_directories/target_compile_options, and other C and C++-specific properties.

Effectively, I want CMake to produce something equivalent to;

i686-elf-gcc -T <linker script(s)...> -o <raw_binary>.bin -ffreestanding -nostdlib <object(s)...> -lgcc

I can probably achieve something similar by leveraging OBJECT libraries in a function with a custom target that executes ${CMAKE_CXX_COMPILER} against $<TARGET_OBJECTS:${target}>:

# Untested
function(add_binary target)
  add_library("${target}.objects" OBJECT ${ARGN})

  set(output_name "{target}.bin")
  set(linker_flags
    "$<TARGET_PROPERTY:${target}.objects,LINK_OPTIONS>"
  )
  set(link_libraries
    "$<TARGET_PROPERTY:${target}.objects,LINK_LIBRARIES>"
  )

  add_custom_target("${target}"
    COMMAND "${CMAKE_LINKER}" "${linker_flags}" -o "${output_name}" $<TARGET_OBJECTS:${target}.objects> -lgcc "${linker_libraries}"
    DEPENDS "${target}.objects"
    BYPRODUCT "${output_name}"
  )
endfunction()

However custom targets aren't able to reuse the standard built-in mechanisms that I would otherwise like to use. This will force me to define such properties on the object library "${target}.object" instead of the canonical target "${target}" (which may work, but is not desired if it's possible to avoid).

To emphasize:

  • add_library(... SHARED ...) does not work because this produces a shared library with -fPIC
  • add_library(... STATIC ...) does not work because it produces an archive of objects (need raw binary image, not an archive)
  • add_executable(...) does not work because it expects the symbol main to be defined. This also seems to implicitly pass -lstdc++ which is not available in my environment.
  • add_library(... OBJECT ...) may work as an intermediate step (?)

At this point I'm mostly out of ideas, and feel as though I may be stuck with the hack approach. Any suggestions are welcome. I'd love to know how this is normally handled, because i feel like there must be a simpler way.


Tagging this and as well for visibility, since this applies to both languages.

0 Answers
Related