2013-03-14

I really, really suck at shell scripting. I don’t do it quite often, hopefully, but I’d like to write scripts in a more modern language. Of course, in the real world, I’m going to use Python or Ruby or anything that’s less insane than shell.

However, the language I’m most comfortable with is Objective-C. Here’s a hack (don’t do this at home) to make your .m files directly runnable. 1

The idea is to play with shell and C comments so that the file is both a valid shell script and an Objective-C program. The shell script calls clang to compile itself, and then runs the output executable.

/*/../bin/ls > /dev/null
COMPILED=${0%.*}
clang $0 -o $COMPILED -framework Foundation;
$COMPILED; rm $COMPILED; exit;
*/
 
 
#import <Foundation/Foundation.h>
  
int main(int argc, char *argv[])
{
    autoreleasepool
    {
        NSLog(@"Hello %@",NSProcessInfo.processInfo.environment[@"USER"]);
    }
    return 0;
}

The first 5 lines are the shell script, inside of /* */ comments. The first line is essentially a noop: we only need a valid shell command that starts with “/*”. The script proceeds to compile itself ($0) into a file with the same name, but without the extension, runs it, and deletes it. Finally, it has to exit before the end of the C comment. Voilà!

Obviously, this as serious drawbacks:

  • it’s a clever hack, and you shouldn’t use clever hacks. Noone else will understand what you’re doing; don’t be “clever”.
  • Objective-C, Foundation, Cocoa and the various frameworks are not meant to be used like that : it’s going to break anytime the compiler introduces some change, or when an API becomes deprecated… Anything could happen.

As I said, in the real world, I’ll use a proper scripting language. However, with LLVM, it should be possible to build an interpreter/JIT compiler for Objective-C. It might be fun.

Here’s a gist of it. If you’re really curious, I used a more complex version of it a while ago for a program that compiled and ran itself several times, in various configurations.

As usual, comments are welcome, on twitter and by email.

  1. I certainly didn’t come up with this idea. I can’t seem to find a source right now, but this hack has been around for decades.