Hi, I’m starting to use CMake and I was wondering if I can mix a raw binary with linking using CMake.
This is useful for firmware development and it is used by UEFI tools (EDK2) using scripts.
Do we have a custom command that can do the trick as well?
Do you want it passed to the linker or embedded as a binary blob? I don’t think there’s an easy way for the former (adding it as a source file may work though; CMake might need to detect it as a certain LANGUAGE or something to put it through the $<TARGET_OBJECTS> codepath).
If the second, there are a number around. VTK has its own module to do this. But I don’t think CMake has any (VTK’s is probably a decent starting point though).
Hi Ben, thank you for the prompt reply. I was looking for an option to do what EDK2 does.
It uses rules for the build framework to include the raw binary (the reset vector).
[Rule.Common.SEC.RESET_VECTOR]
FILE RAW = $(NAMED_GUID) {
RAW BIN Align = 16 |.bin
}
Basically it would have the elf content for the compiled ASM and C code and then in the end, top of the file, the raw binary with the jump to the startup code.
Thank you!
I don’t know of any way to do that off-hand. You’ll likely need a linker script or set of flags to do it. target_link_options (new in CMake 3.13) would be the best way to add them, but target_link_libraries can likely be abused for older versions.
Hi Fernando! This is a very common challenge in firmware development, especially when migrating complex builds like UEFI or custom bootloaders to CMake. Ben is completely right about needing to lean on the linker for this. I have run into this exact scenario when needing to place a reset vector at a precise memory boundary.
The most robust way embedded engineers handle this in CMake is by converting the raw binary into an object file prior to the linking stage. You can automate this process by using add_custom_command to invoke objcopy. You can configure objcopy to take your raw binary file as input and output a standard ELF object file. Once it is converted, you simply add that new object file to your CMake target sources. The linker will then merge it just like any regular C or assembly file.
If your goal is strictly to append or prepend a raw binary block to your compiled output, you can take a different route. You can use add_custom_command with the POST_BUILD hook on your main target. This allows you to run a lightweight script or copy command to stitch your compiled binary and the raw reset vector together right after the build finishes.
Finally, relying on a custom linker script passed through target_link_options is definitely the way to go if you need strict control over the exact memory section where that raw binary data will reside.
Hopefully, this gives you a few solid options to get your EDK2 build working cleanly!