1. 8
    1. 4
      1. 2

        This article discusses a way to use a C++ static initializer in a dynamically generated C++ source file to inject build information into a structure.

        IMO, there are better ways. Some of the ways I’ve toyed with in the past include:

        • Defines on the compiler command line (something like BUILD_INFO := $(shell git rev-parse ...) followed by gcc '-DBUILD_INFO="$(BUILD_INFO)"' ... in a Makefile
        • The same, but generating a simple buildinfo.h header file which #defines various macros with information
        • “incbin” solutions:
          • C++ has std::embed now
          • C23 has #embed
          • bin2obj-type solutions convert an arbitrary binary file to an .o file (objcopy can also do this): objcopy -I binary -O elf32-i686 -B i386 file.bin file.o
          • xxd can convert an arbitrary binary file to a C initializer list, if that’s not an option
          • In GAS assembly, there is the .incbin directive which is useful. You can actually use this from GNU C (ipxe does this):
            extern uint8_t _my_symbol_start[];
            extern uint8_t _my_symbol_end[];
            asm(
              ".section \".rodata\", \"a\", @progbits\n"
              "_my_symbol_start:\n"
              ".incbin \"path\"\n"
              "_my_symbol_end:\n"
              ".previous\n"
            );
            
        • Windows only: Using Windows resource files. There is actually a section intended for version information strings.
        • There is probably something you can do with linker scripts, if you really want to.
        • I imagine there are tools which could add a section to an ELF file after the fact, which might be reasonably practical. This isn’t too far off from the GNU build ID section, etc.
        1. 4

          It’s also worth noting that all of this completely breaks reproducible builds if it’s actually embedding the build time. Most of the time, you want to do this the other way around: have a build environment that, from a given toolchain version and commit hash, is guaranteed to generate an identical binary. Then separately publish a signed attestation that the hash of the binary corresponds to a particular source revision and toolchain.

          1. 2

            Agreed: embedding the build time is a bad idea.

            Most of the time I tend to generate a Git commit hash and/or tag name, with a “+” appended if the tree appears dirty.

            1. 1

              Agreed. In the past, I’ve found it useful to embed the (hash and) timestamp of the git commit from which you’re building. The commit timestamp, like the build timestamp, gives you an idea of how old the binary is - and does allow reproducibility.

            2. 1

              I too spent most of this article thinking “neat but why not -D?”