Skip to content

Instantly share code, notes, and snippets.

@zb3
Last active March 17, 2018 14:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zb3/74125fb1af82c2474e2e4a8e4704cb96 to your computer and use it in GitHub Desktop.
Save zb3/74125fb1af82c2474e2e4a8e4704cb96 to your computer and use it in GitHub Desktop.
#/*
TARGET=selfcompiled
CODE=$(cat <<'FILE_CONTENTS_DELIM'
//*/
// CODE STARTS HERE
#include <stdio.h>
int main()
{
printf("works\n");
}
// CODE ENDS HERE
/*
FILE_CONTENTS_DELIM
)"*"/
rm $TARGET 2>/dev/null
echo "$CODE" | gcc -x c -o $TARGET -
./$TARGET $@
#*/
#define FILE_CONTENTS_DELIM_283 /*
F=selfcompiled
rm $F 2>/dev/null
gcc -x c -o $F - <<'FILE_CONTENTS_DELIM_283'
//*/
// CODE STARTS HERE
#include <stdio.h>
int main()
{
printf("works\n");
}
// CODE ENDS HERE
FILE_CONTENTS_DELIM_283
#/*
./$F $@
#*/

Selfcompile

Name is misleading, but still. The goal of this is to be able to compile and run a C file in one line, with the C source file containing all instructions needed to compile itself when interpreted as a shell script.

So these cases need to be supported:

curl URL | bash
wget URL; source SCRIPT ARGS...
wget URL; chmod +x SCRIPT; ./SCRIPT ARGS...

For development purposes, this also needs to be a valid C file, so this must work too:

gcc source.c -o program

Current version

Always creates a binary file with specified name. Can overwrite itself when executed as file.

Relies on quoted heredocs and uses gcc which compiles code from stdin. Of course, the code may not contain the delimiter.

Tested on bash and ash shells and gcc 7.2.1. I'm not sure if traliling # characters are allowed or it's just gcc. We need them though.

@zb3
Copy link
Author

zb3 commented Mar 17, 2018

Previous version couldn't overwrite itself when executed as a target file, because after new contents were written, bash couldn't read further instructions. Now we use a .tmp file and overwrite ourselves when gcc is executed, but since && is used, bash should buffer these instructions. That means now it won't overwrite itself when executed as target file with .tmp suffix, but that's acceptable for now.

@zb3
Copy link
Author

zb3 commented Mar 17, 2018

Ok, I'm an idiot. We can simply remove ourselves - this doesn't remove the contents on disk - bash can continue. Good. Second thing is that gcc can compile from STDIN - we can use that thx to the define hack. Also there's no point in implementing return handling if that's what happens by default.

That rm $F line might be unnecessary, since ld first calls unlink and then creates a new file, but this is not guaranteed since it depends on a specific linker implementation.

And finally, I don't like the new header, so here goes selfcompile-alt.c.
Jeez, that's enough...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment