107

How do I programmatically determine which OS Emacs is running under in ELisp?

I would like to run different code in .emacs depending on the OS.

Bleeding Fingers
  • 6,993
  • 7
  • 46
  • 74
ljs
  • 37,275
  • 36
  • 106
  • 124
  • 1
    From GNU Emacs Lisp reference manual http://www.gnu.org/software/emacs/manual/html_node/elisp/System-Environment.html – WisdomFusion Aug 10 '12 at 14:06

8 Answers8

111

The system-type variable:

system-type is a variable defined in `C source code'.
Its value is darwin

Documentation:
Value is symbol indicating type of operating system you are using.
Special values:
  `gnu'         compiled for a GNU Hurd system.
  `gnu/linux'   compiled for a GNU/Linux system.
  `darwin'      compiled for Darwin (GNU-Darwin, Mac OS X, ...).
  `ms-dos'      compiled as an MS-DOS application.
  `windows-nt'  compiled as a native W32 application.
  `cygwin'      compiled using the Cygwin library.
Anything else indicates some sort of Unix system.
scottfrazer
  • 17,079
  • 4
  • 51
  • 49
97

For folks newer to elisp, a sample usage:

(if (eq system-type 'darwin)
  ; something for OS X if true
  ; optional something if not
)

Or, if we don't care for the else-form and have multiple then-forms,

(when (eq system-type 'darwin)
  ; do this
  ; and this ...
)
scribe
  • 673
  • 2
  • 6
  • 17
Endrju
  • 971
  • 6
  • 2
  • 2
    OK, I burned myself several times with weird branch blocks in Elisp (if- and else-part separated by a newline, `progn` necessary for blocks), so a recommendation to everyone not familiar with the quirks - check [this answer](http://stackoverflow.com/a/912397/544059) out. – metakermit Oct 08 '13 at 14:14
  • 3
    @kermit666 actually `progn` isn't needed if you don't have an else case. What I mean by that is that you can just use `when` instead of `if`, which is equivalent to `(if ... (progn ...) '())` – Electric Coffee Aug 11 '15 at 12:13
  • 1
    Upvoted because I was trying to use "=" and it wasn't working. – Philip Daniels Dec 23 '15 at 11:58
  • 3
    @metakermit you can use `cond` like so: `(case system-type ((gnu/linux) "notify-send") ((darwin) "growlnotify -a Emacs.app -m"))` – ealfonso Jan 11 '17 at 23:48
  • I meant `case`, not `cond`. `case` works since `system-type` is a symbol like `'gnu/linux` or `darwin`, not a string – ealfonso Jun 19 '18 at 05:54
  • I read somewhere that in emacs `eq` is not same with `equal`, and `equal` works better in general comparing stuffs. – SdSaati Aug 01 '21 at 23:15
  • @SdSaati In this case, `eq` works as intended. How could it "work better" here? – Rudolf Adamkovič Feb 11 '22 at 08:27
  • 1
    Note to the OP: With a single branch, one can use `when`. – Rudolf Adamkovič Feb 11 '22 at 08:27
27

I created a simple macro to easily run code depending on the system-type:

(defmacro with-system (type &rest body)
  "Evaluate BODY if `system-type' equals TYPE."
  (declare (indent defun))
  `(when (eq system-type ',type)
     ,@body))

(with-system gnu/linux
  (message "Free as in Beer")
  (message "Free as in Freedom!"))
Gerstmann
  • 5,368
  • 6
  • 37
  • 57
11

In a .emacs, there is not only the system-type, but also the window-system variable. This is useful when you want to choose between some x only option, or a terminal, or macos setting.

Eric
  • 3,959
  • 17
  • 15
7

Now there is also Linux Subsystem for Windows (bash under Windows 10) where system-type is gnu/linux. To detect this system type use:

(if
    (string-match "Microsoft"
         (with-temp-buffer (shell-command "uname -r" t)
                           (goto-char (point-max))
                           (delete-char -1)
                           (buffer-string)))
    (message "Running under Linux subsystem for Windows")
    (message "Not running under Linux subsystem for Windows")
  )
Konrad Eisele
  • 3,088
  • 20
  • 35
2

This is mostly already answered, but for those interested, I just tested this on FreeBSD and there the reported value was "berkeley-unix".

0

There's also (in versions 24-26 at least) system-configuration, if you want to adjust for differences in build system. However, the documentation of this variable does not describe the possible vales that it may contain like the documentation of the system-type variable does.

JCB
  • 13
  • 6
Jürgen A. Erhard
  • 4,908
  • 2
  • 23
  • 25
0

The easiest way to do this is to do a pattern match on the system-type variable, like this:

(pcase system-type
  ;; GNU/Linux or WSL
  (gnu/linux
   (message "This is GNU/Linux"))

  ;; macOS
  (darwin
   (message "This is macOS"))

  ;; Windows
  (windows-nt
   (message "This is Windows")) 

  ;; BSDs
  (berkeley-unix
    (message "This is a BSD"))

  ;; Other operating system
  (_
   (message "Unknown operating system")))

For more information, and additional types of operating systems, see the full documentation on system-type in https://www.gnu.org/software/emacs/manual/html_node/elisp/System-Environment.html

(An easy way to test the above code is to paste it in your *scratch* buffer and press C-j after the outermost parenthesis)

Debajit
  • 46,327
  • 33
  • 91
  • 100