> The include_* macros are great for “packaging”. Being able to compile small assets directly into the binary and eschewing run time file loading is fantastic for a small game.

For C/C++/etc devs looking for something similar, BFD objcopy supports an "-I binary". It will emit an object file with _binary_objfile_start, _binary_objfile_end and _binary_objfile_size symbols.

But I have got to say that making it a language feature means that Rust is truly a batteries included language.

There is also an option to use assembler or inline asm. I found quite a nice utility that uses inline asm [0]. It's widely portable and I think that I will use it instead of my naive asm/shell combo that doesn't work with mingw asm.

The problem with objcopy outside of unconvenient usage and naming is that naive objcopy will result in your binary having executable stack [1]. You can change a symbol name, but that's also unconvenient.

Check resulting binary with:

  $ readelf -lW the_binary | grep GNU_STACK
    GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RWE  0x8
  $
Notice: RWE instead RW.

Also: https://wiki.gentoo.org/wiki/Hardened/GNU_stack_quickstart#H...

[0] https://github.com/graphitemaster/incbin

[1] https://news.ycombinator.com/item?id=10816322#10818085

EDIT:

My shell script - bin2o.sh:

  #!/bin/sh
  set -e
  
  filename="$1"
  name=$(echo "$1" | sed "s/[^A-Za-z0-9]/_/g")
  obj="$2"
  
  echo \
  "	.section .rodata
  	.global ${name}
  	.type ${name}, @object
  	.global ${name}_size
  ${name}:
  	.incbin \"${filename}\"
  1:
  ${name}_size:
  	.int 1b - ${name}
  	.section .note.GNU-stack,\"\",%progbits
  " | gcc -x assembler -c - -o "$obj"