Mac OS X Global Environment Variables

Having just spent way too long (couple hours) figuring out how to set environment variables on Mac OS X 10.5 in such a way that they were accessible from a bundled Java application (specifically, M2_HOME in IntelliJ so that the Maven integration would work 100%), I'm writing this up so that 1) I don't have to remember it later, and 2) to possibly save other folks the hassle.

For the impatient, the solution is

1) edit /etc/launchd.conf to contain a line like this:

setenv M2_HOME /opt/maven/2.0.9

2) reboot

Your environment variable will now be accessible in every possible context (that I could find) in which you can run your application. There are other ways to do this, but none of them worked for me. If you're interested in the details, read on.

The first thing I tried was creating a ~/.MacOSX/environment.plist as described in Apple's technical documentation. And to be honest, that *almost* works. Unfortunately it does not work for applications launched via Spotlight in 10.5 (which is how I launch pretty much everything, having gotten hooked on that way of launching things using Butler) - apps launched via Spotlight do not get the environment you define in the .plist. For me, this was a deal breaker, so I kept looking.

Also in Apple's technical documentation is a method for setting application-specific environment variables using the LSEnvironment key in the app's info.plist. This completely failed to do anything useful, perhaps because the app in question was a Java app.

I then went on to try to create a "prelude" script. Surprisingly, this didn't work either. In fact, it seemed the script never even got executed. I was able to change the CFBundleExecutable key to a completely nonsensical value and the app still launched. This method may actually work, I suspect there is some .plist caching going on in 10.5, and so you may need to reboot after making this change. I didn't, because frankly at that point my patience had run out.

By now, I had confirmed that my environment variable worked fine if I set it in .bash_profile and launched it from a shell. So clearly what I had was an issue with the parent process not being what I think it was (in the case of the environment.plist, the issue is that the environment.plist applies to the WindowServer, and Spotlight - aka "mds" in Activity Monitor - is not a child of WindowServer). This led me to wondering if there was a way to set environment variables in launchd, which is the parent of all processes (it is pid=1, equivalent to init on other *ix systems), which led me to this launchd article, from which I finally arrived at the solution posted above. Well, almost - per the man pages, I tried setting the variable in ~/.launchd.conf first, but best I can tell, that file never gets processed, so I set it in /etc/launchd.conf.

So there you have it. Setting an environment variable, which is so trivial in other OSes as to be taken for granted, can be painfully hard in Mac OS X.