Expected a rant, got a life-pro-tip. Enough for a good happy new year.
That said, we can abuse the same trick for any languages that treats `//` as comment.
List of some practical(?) languages: C/C++, Java, JavaScript, Rust, Swift, Kotlin, ObjC, D, F#, GLSL/HLSL, Groovy
Personally, among those languages, GLSL sounds most interesting. A single-GLSL graphics demo is always inspiring. (Something like https://www.shadertoy.com/ )
Also, let’s not forget that we can do something similar using block comment(`/* … */`). An example in C:
For Swift there’s even a project[1] that allows running scripts that have external dependencies (posting the fork because the upstream is mostly dead).
I think it’s uv’s equivalent, but for Swift.
(Also Swift specifically supports an actual shebang for Swift scripts.)
For C/++ just use "#!". When TCC first came out, we used this exact technique for "C scripting". It requires a dirty SO methodology (you can't really control linking well).
For larger projects (the exe), the shebang points to a C build file, which when compiled, knows the root path; that C build script then looks for a manifest, builds, links, and fork()s. A good a/m timestamp library with direct ccache support can spin up as fast as a script even on big projects.
Again, this is all a bad idea bc it's hard to control your environment.
I guess we were doing all this in the mid 2000s? When did TCC come out?
That said, we can abuse the same trick for any languages that treats `//` as comment.
List of some practical(?) languages: C/C++, Java, JavaScript, Rust, Swift, Kotlin, ObjC, D, F#, GLSL/HLSL, Groovy
Personally, among those languages, GLSL sounds most interesting. A single-GLSL graphics demo is always inspiring. (Something like https://www.shadertoy.com/ )
Also, let’s not forget that we can do something similar using block comment(`/* … */`). An example in C:
/*/../usr/bin/env gcc "$0" "$@"; ./a.out; rm -vf a.out; exit; */
#include <stdio.h>
int main() { printf("Hello World!\n"); return 0; }