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-fPICadd_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 symbolmainto 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 c++ and c as well for visibility, since this applies to both languages.