### Difference between Emacs's “(setenv PATH ...)” and “(setq exec-path ...)”

perm url with update: http://xahlee.org/emacs/emacs_env_var_paths.html

# Difference between Emacs's “(setenv PATH ...)” and “(setq exec-path ...)”

Xah Lee, 2009-08-04

This page explains the mechanisms of setting environment variables in emacs, especially if you have problems in Windows emacs of getting aspell or other unix utils to run.

Spent some time to study the diff between (setenv "PATH" ...) vs (setq exec-path ...).

Their docs are here:

In summary:

“setenv” is for setting OS env vars within emacs environment. (That is, it doesn't change the OS's env var, it just changes the env var as seen within emacs.)

Unixes and Windows both have env vars. Env vars are global info available to processes (apps). A process is free to use the info in env var. Some env var are important as they contain system info such as Windows WINDIR that contains OS path, and PATH in both Windows and unixes that specify program paths. Many are config items such as HOME dir in unix and Windows, and “locale” in unixes. When a process launchs, it inherits (have access) to all the env vars where the process is launched.

Emacs uses the system's env var just like other apps, but more importantly, emacs functions as a shell due to its various interfaces to OS's shells.

When using a shell (e.g. bash, tcsh, scsh, cmd.exe, PowerShell), typically there's a init file to allow users to sets its own extra env vars when the shell starts. So, when emacs is used as a shell, it also has this ability, and this is done with emacs commands “setenv” and “getenv” used in emacs's init file “.emacs”. (setenv and getenv are actually wrappers that manipulate emacs's process-environment var.)

Emacs's “exec-path” var is actually the var emacs uses to locate external programs. Here's a quote: “Emacs initializes exec-path when it starts up, based on the value of the environment variable PATH.”.

So, the system's PATH env var and emacs exec-path needs not to be the same, and ideally their values probably shouldn't be identical if one is a control freak, since they serve different purposes.

The value for exec-path is important to emacs in locating programs, while the PATH system env var is more important in using emacs as a shell.

So, judging from all i know, getting aspell to work in emacs means exec-path should contain the path to aspell. Since emacs set exec-path to system's PATH env var when it starts, thus setting aspell path in OS's PATH env var should work too.

As of today (2009-08-04), my emacs has this setup:

```(when (string-equal system-type "windows-nt")
(progn
;; am using cygwin
(setenv "PATH"
(concat
"/usr/local/bin" ":"
"/usr/bin" ":"
"/bin" ":"
"/usr/X11R6/bin" ":"
"/cygdrive/c/Windows/Program Files (x86)/PHP/" ":"

"/cygdrive/c/Windows/system32" ":"
"/cygdrive/c/Windows" ":"
"/cygdrive/c/Windows/System32/Wbem" ":"
"/cygdrive/c/Windows/system32/WindowsPowerShell/v1.0"
)
)
(setq exec-path
'(
"C:/cygwin/bin/"
"C:/Program Files (x86)/Emacs/emacs/bin/"
"C:/Program Files (x86)/PHP/"
"C:/Windows/system32/"
"C:/Windows/"
"C:/Windows/System32/Wbem/"
"C:/Windows/system32/WindowsPowerShell/v1.0/"
)
)
)
)
```

This is still far from ideal.

For example, the path syntax used are different. Some uses “/” while others uses “\”, and some contains the drive name while others doesn't. Some with lower case drive letter, while other doesn't. Also, some uses cygwin's path mapping.

Note that you can't simply change them to use one consistent syntax without knowing the details. For exmaple, if you simply replace those “/cygdrive/c/” paths with “C:/”, cygwin bash in emacs will chock.

I still need to do some study on the various paths to have a some sort of more universal setup, so that i should be able to invoke cygwin or Windows commands in all of emacs interactive shells: shell, cmd-shell, powershell... as of now, am not sure that's even desirable... i guess i needs to understand more about how these shells relates to each other technically outside of emacs first...

The path separator issue of / vs \ and their automatic conversion in different shells has also been a pain... In cygwin bash, cmd.exe, PowerShell, they all let you type either forward slash or backward slash for path separators while you work in the shell, and the drive letter can be omitted too. However, when you write scripts or set paths, you can't arbitrarily use / or \ (even if properly quoted in string), the rule for the omission of drive letter is also complex. Further, cygwin has some rather esoteric mechanisms to map drives (e.g. in cygwin bash, “/cygdrive/c” maps to “C:\”) ...