#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-pl...
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 $@ ?
OTOH we're trying to write self-compiling executable C scripts, so the safety, correctness and good sense ships sailed a while back.
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().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.
#if 0
cc -static -pipe -xc "$0"||exit 100
exec ./a.out
#endif
int puts(const char *);
int unlink(const char *);
int main(int argc,char *argv[]){
puts("it works");
unlink(argv[0]);
return 0;
} /*bin/true ; exec tcc -run "$0" "$@" # */What is the benefit of registering an extension via binfmt_misc?
Isn't that already legitimized by configure scripts, compiler command lines and Make files?
"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