4 ms·
Binfmtc – binfmt_misc C scripting interface
- zx2c4 1y agoSimilar project of mine from a long while ago: https://git.zx2c4.com/cscript/about/ https://git.zx2c4.com/cscript/about/
- Surac 1y agoSo lovely
- elitepleb 1y agosimilar to http://www.iq0.com/duffgram/com.html http://www.iq0.com/duffgram/com.html
- JSR_FDED 1y agoC is still my first love. You can hold the whole language in your head, and it’s fast. Yes there are footguns but it’s a libertarian programming language - you’re responsible for what you build. No hand holding.
- throwaway984393 1y ago[dead]
- ykonstant 1y agoI like that too, but the problem is that C doesn't keep its end of the deal. No hand holding, but make what you are doing transparent. It used to be the case back in the 80s, but not anymore. Not with our optimizing compilers and oodles of UB and spec subtleties and implicit actions.
- radiospiel 1y agoAmazing; when I tried something similar I used a "#!" line pointing to a C compiler + runner of sorts (https://github.com/radiospiel/jit https://github.com/radiospiel/jit). https://git.zx2c4.com/cscript/about/ https://git.zx2c4.com/cscript/about/ is also following that approach. What is the benefit of registering an extension via binfmt_misc?
- lmz 1y agoIt's still valid C source code? Is the #! sequence valid C?
- enriquto 1y agowas surprised that "sudo apt install binfmtc" works out of the box on my box (linux mint) and i can do the magic just as described here
- rwmj 1y agoYou can already do this without using binfmt ... #if 0 gcc "$0" -o "$@".out && exec ./"$@".out #endif #include <stdio.h> int main () { printf ("hello, world\n"); return 0; } Usage: $ chmod +x print.c $ ./print.c hello, world (Could be better to use a temporary file though.) There's a similar cute trick for compiled OCaml scripts that we use with nbdkit: https://libguestfs.org/nbdkit-cc-plugin.3.html#Using-this-plugin-with-OCaml https://libguestfs.org/nbdkit-cc-plugin.3.html#Using-this-pl...
- mananaysiempre 1y agoCompiler errors won’t cause as many funny consequences with gcc "$0" -o "$@".out && exec ./"$@".out || exit $? # I'd use ${0%.c} not $@ Love this trick too, but the difference, as far as I understand, is that it only works with a Bourne(-compatible) shell, whereas shebangs or binfmt_misc also work with exec().
- AlotOfReading 1y agoYou can also #embed the compiler binary, and execve it to much the same effect as binfmtc. I explored that trick for an IOCC entry that was never submitted because it ended up far too readable.
- ckastner 1y agoOh this is neat. Took me a bit. The shell treats the first line as a comment. It executes the second line, which eventually exec's the binary so the rest of the file do not matter to the shell. And the compiler treats the first line as a preprocessor directive, so it ignores the second line. I initially misread/mistook the first line for a shebang.
- teo_zero 1y agoThe use of $@ doesn't look right to me. In the trivial case exposed here where there are no additional arguments to pass to the .c program, the shell executes gcc "print.c" -o .out && exec ./.out and it works "by chance". In a more complex scenario where print.c expects some parameters, it won't work. For example, ./print.c a b c will result in the shell trying to invoke gcc "print.c" -o "a" "b" "c".out && exec ./"a" "b" "c".out which makes no sense. Are you sure you didn't intend $0 instead of $@ ?
- monocasa 1y agoThere's also tcc, which has a shebang compatible extension to allow it to be used by scripts.
- kazinator 1y agoThis is doable entirely without a Linux-specific binfmt-misc hack. https://rosettacode.org/wiki/Multiline_shebang#C https://rosettacode.org/wiki/Multiline_shebang#C
- enriquto 1y agoThis is a neat hack, but the whole file is not a valid C program.
- kazinator 1y agoYou mean it consists of a C program, plus non-C cruft to get it running? Isn't that already legitimized by configure scripts, compiler command lines and Make files?
- enriquto 1y agoof course it is legitimized. I just meant that the selling point of binfmtc is that the same .c file can either be compiled by any C compiler, or executed directly.
- kazinator 1y agoWe could perhaps split it into a two-file system where a "foo.sh" containing certain boilerplate will execute a "foo.c" that doesn't require any special conventions at all. "foo.sh" could be identical for any .c file, and so we could symbolically link them all to a common file. Of course, neither that file nor symlinks to it require a .sh suffix. The contents might look like this: #!/bin/sh c_file=${0%.sh}.c x_file=${0%.sh}.bin # If cached executable file is missing, or out of date w.r.t. # the source file, compile it: if [ "$c_file" -nt "$x_file" ]; then cc $CFLAGS "$c_file" -o "$x_file" fi # Run cached executable file $x_file
- codr7 1y agoI did a simple hack for doing the same thing from inside a C program for my book: https://github.com/codr7/hacktical-c/tree/main/dynamic https://github.com/codr7/hacktical-c/tree/main/dynamic
- rurban 1y ago(2006)