How do I make Emacs recognize bash environment variables for compilation? - emacs

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?

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.

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

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

Related

In powershell, how can I define all env vars for the next command similar to python's Popen abilities?

In powershell, how can I...
explicitly define all the env vars for the next command?
I don't want any system env vars if possible,
After this command runs I dont want anything we have done to affect further processes in the shell.
As an example, in python we have the equivalent ability in Popen to pass a dictionary of the full environment to the subprocess, and I'm hoping there might be something similar in Powershell.
I think this link explains what you need: Windows user environment variable vs. system environment variable
[Environment]::GetEnvironmentVariable("TEMP", "Machine")

Eshell can't find script on eshell path

My goal
I'm trying to add "/opt/bin" to the list of paths eshell uses to find scripts. So far I've tried to do this in three ways
Attempts so far
1) (setenv "PATH" (concat "/opt/bin:" (getenv "PATH")))
2) (eshell/addpath "/opt/bin:")
3) (add-to-list 'exec-path "/opt/bin")
The first attempt does add "/opt/bin" to eshell's path (it shows up as the first instance of "/opt/bin:" in the output of calling "which lein" below)
The second attempt also adds "/opt/bin" to eshell's path (it shows up as the second instance of "/opt/bin:" in the output of calling "which lein" below)
I actually have had "/opt/bin" added to my exec-path for a while. I believe I did this so that /opt/bin would be on my path when running the term command to start a shell, this seems to work fine but doesn't help eshell find commands there.
Failing attempts and temporary workaround
You can see in the eshell output below that even though a command, lein, is available on the path eshell recognizes eshell doesn't find the command. However if I create a symbolic link from a directory that is in eshells default path to a script in /opt/bin eshell is then able to find it.
Eshell output
~ $ which lein
which: no lein in (/opt/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/usr/local/sbin:/usr/sbin:/sbin:/opt/bin:)
~ $ l /opt/bin/ | grep lein
-rwxr-xr-x 1 kevin kevin 12538 2019-01-17 07:32 lein
~ $ sudo ln -s /opt/bin/lein /usr/local/bin/lein
[sudo] password for kevin:
~ $
~ $ which lein
/usr/local/bin/lein
I would prefer not to have to create symbolic links in /usr/local/bin/ just so that eshell can find scripts in my /opt/bin. Note even after restarting emacs it finds the symbolic link not the script in /opt/bin. This is occurring in a GUI instance of emacs-25 on linux mint debian (v9.3) edition.
Question:
How do I get eshell to actually check eshell path instead of the some default list of directories? Should I be updating a different path variable?
Looking at the source of eshell/addpath, it uses setq on eshell-path-env, which is a buffer local var. This means that if you use eshell/addpath, it has to be executed in the context of each eshell buffer. The best way to do this is to use a mode hook.
(defun jpk/eshell-mode-hook ()
(eshell/addpath "/opt/bin"))
(add-hook 'eshell-mode-hook #'jpk/eshell-mode-hook)
I'm not super familiar with Eshell, so I'm not going to say this is the best way, but it should work. eshell-path-env is set from (getenv "PATH") initially, so it's weird that setting PATH env var doesn't work (unless you're doing that after loading eshell).
One way:
Assuming you are running emacs in a terminal emulator or tty; then you can just add /opt/bin to your $PATH. Eshell uses your $PATH to find external commands. Not sure how it works for GTK version.

How to specify make program in emacs?

Vim has makeprg variable. This variable takes program name which will be executed if :make is entered. Is there something similar in emacs?
Thanks.
The variable compile-command specifies the compiler program, which you can customize as needed. Here's the manual page for M-x compile and family.
I'm not aware of a make command in Emacs, but there is compile:
Compile the program including the current buffer. Default: run `make'.
Runs COMMAND, a shell command, in a separate process asynchronously
with output going to the buffer `*compilation*'.
The command that gets run by compile is defined by the variable compile-command, which can be set like this:
(setq compile-command "some command")
compile-command's default value is "make -k ".

SLIME on Windows 7

I'm trying to get set up with SLIME on a Windows 7 box, but running M-x slime gives me the error
Spawning child process: invalid argument
I have inferior-lisp-program set to "C:\\Program Files\\ccl\\wx86cl.exe" (which is factually correct, and running (comint-run inferior-lisp-program) gives me a working CCL prompt), and the slime directory added to my 'load-path.
What am I doing wrong?
EDIT: Tried loading up the same environment through the Windows edition of lispbox, and it runs SLIME fine. I'd prefer not to use that one because it packages an older Emacs, CCL and SLIME than I want.
The message you received means that there's a high chance that there was a syntax problem with the command given to shell. This would be caused by having characters in the file name, which can be interpreted as doing something special. So, it looks like Emacs was trying to call C:\\Program "program" with an argument Files\\ccl\\wx86cl.exe.
There are several ways to address the error:
There has to be an escaping function, something like:
(shell-quote-argument "C:\\Program Files\\ccl\\wx86cl.exe")
But since you cannot affect how the file name is passed to the function which creates the process, this isn't going to work.
You can move the program you want to call to a directory with "safe" name.
You can move the executable to be on the system path (%PATH% variable in Windows) - through changing environment variables and appending the directory with the executable to it.
One more option is to add the directory with the executable to exec-path variable in Emacs. This variable holds a list of all directories looked up for programs to run, if you just call a program by name, rather then by full path. This also (at least for me) makes my .emacs file easier to port between different systems.

Commands from .bashrc not available in Emacs

I have some aliases and functions defined in ~/.bashrc.
I start emacs from a terminal window using emacs -nw
When I execute M-x shell-command, the aliases and functions from ~/.bashrc are not available, but give a "command not found".
I've googled quite a bit but all the posts I come across say, if I understand them correctly, that ~/.bashrc is the place where this should work (rather than ~/.profile or ~/.bash_profile).
What am I missing?
Aliases are available only in interactive shell - a snapshot from bash man page:
Aliases are not expanded when the
shell is not interactive, unless the
expand_aliases shell option is set
using shopt
(see the description of shopt under SHELL BUILTIN COMMANDS below).
If you start Emacs from an interactive shell (in which .bashrc, etc. have executed), then the commands from your .bashrc should be available for both shell-command and shell, at least that's how it works for me.
But yeah as the other answer says, there is not real way to get a .bashrc environment in emacs. There are some documentation about a .emacs_bash file, but that never worked for me.
Okay misread your question here. If you are looking for functions and aliases instead of commands by changing paths in .bashrc, the non-interactiveness is the problem. I guess you can change the default argument to shell-command (take a look at explicit-bash-args) to make bash interactive, but that probably has unintended consequences.
The accepted answer correctly states that "aliases are available only in interactive shell".
This means that in order to load (rightly located indeed) aliases from ~/.bashrc, an interactive shell would have to be launched with Emacs's M-x shell-command (M-!).
To achieve this, add -i (interactive) switch to the M-x shell-command with:
(setq shell-command-switch "-ic")
Side Note, not Emacs related:
On some operating systems users would need to add the line source ~/.bashrc to ~/.bash_profile (or similar), since ~/.bashrc is not always auto-read by a system.