20

I'm trying to compile u-boot via Emacs' compilation mode, and it looks like Emacs doesn't know how to find bash environment variables. Even though I set them, and can compile via Emacs shell emulation, compilation mode still tries to compile as if they aren't there.

What do I need to do to make it more environment conscious?

EpsilonVector
  • 3,973
  • 7
  • 38
  • 62

3 Answers3

33

You can try adding something like to your .emacs:

(let ((path (shell-command-to-string ". ~/.bashrc; echo -n $PATH")))
  (setenv "PATH" path)
  (setq exec-path 
        (append
         (split-string-and-unquote path ":")
         exec-path)))

Depending on whether you've set the env variables in .bash_profile or .bashrc you might need to slightly adjust this snippet. The example is for the PATH variable, which is a bit more special (since you have to set exec-path in Emacs as well), but can be extended to work for arbitrary variables - you could have a list of variables that have to be read from .bashrc and set into Emacs.

I'm not sure whether you're using OS X or GNU/Linux. Starting Emacs from the GUI's menu-bar in Linux will typically result in an Emacs that does not have the same PATH as one launched from the command line. This problem dates back to the first xdm Xsession scripts, and while they are fairly easy to fix (basically use an Xsessionwrapper script that does exec $SHELL -c Xsession so the shell gets run before running the user's Xsession), nobody has bother to do so in a very long time (and I doubt that anyone will). As far as I know the problem is present even into moder xdm descendants such as kdm and gdm.

On OS X the handling of the env variables is another problem entirely and to get your ENV variables you typically have to run Emacs from the command line like this /Applications/Emacs.app/Contents/MacOS/Emacs or play with ~/.MacOSX/environment.plist. The code snippet I've provided should cover you in both cases though.

Update

Recently this process was made easier by the exec-path-from-shell extension. It sets the emacs $PATH in more or less the same manner, but using an extension is generally preferable to hacking the solution yourself.

Bozhidar Batsov
  • 55,802
  • 13
  • 100
  • 117
  • This resolve my issue with Flymake not using the correct Perl from perlbrew. Unlike perlbrew-mini.el – titanofold Apr 20 '13 at 01:28
  • 1
    _exec-path-from-shell_ is great and resolved my issue with _ensime_ which couldn't start and throw `wrong type argument stringp nil` error. – kikulikov Jul 21 '14 at 20:17
  • Why do you use split-string-and-unquote instead of split-string? – Clément May 14 '17 at 18:30
  • Although the answer is clear on this, for anyone skimming quickly, the first two lines in this answer were what I was searching for: (let ((MYVAR (shell-command-to-string ". ~/.bashrc; echo -n $MYVAR"))) (setenv "MYVAR" MYVAR)) – Jesse W. Collins Mar 16 '19 at 22:22
  • this solved my problem. Thanks – Rajanboy Mar 14 '22 at 01:24
7

This is where the environment variables of the process that started emacs are:

— Command: getenv var

This function returns the value of the environment variable var, as a string. var should be a string. If var is undefined in the environment, getenv returns nil. It returns ‘""’ if var is set but null. Within Emacs, a list of environment variables and their values is kept in the variable process-environment.

      (getenv "USER")
           ⇒ "lewis"

— Variable: process-environment

This variable is a list of strings, each describing one environment variable. The functions getenv and setenv work by means of this variable.

      process-environment
      ⇒ ("PATH=/usr/local/bin:/usr/bin:/bin"
          "USER=lewis"
          "TERM=xterm"
          "SHELL=/bin/bash"
          "HOME=/home/lewis"
          ...)

You seem to be assuming that emacs was started from a bash session. However, often processes under X are started from an sh session, which would not read the environment variables you had set in your ~/.bashrc script. One simple way to circumvent this is to change your ~/.xinitrc file to use bash instead of sh (it could be as simple as adding #!/bin/bash at the top of the file).

Source: gnu.org

dmvianna
  • 15,088
  • 18
  • 77
  • 106
3

It doesn't strictly answer your question, but you can always pass environment variables on the make command-line. For example : M-xcompileRETmake -k CXXFLAGS='-Wall'RET

François Févotte
  • 19,520
  • 4
  • 51
  • 74