Wanna build GNU Emacs on macOS from source?

It’s really easy to build GNU Emacs on macOS from source. However it comes with some catches.

Basically you only need the Xcode Command Line Tools (CLT) installed and you are good to go. If you don’t have it already, simply run the following to install.

sudo xcode-select --install

Now you download the tarball from the official GNU site. After extracting, you want to configure and make it. Now you face the problem of dependent dynamic libraries like gnutls and jannson.

You realize that it’s easy to get them installed, provided you have Homebrew. You simply run

brew install gnutls
brew install jansson

respectively. That’s nice! Now you can build Emacs by issuing

./configure
make
make install

Perfect! This leaves you with a freshly built Emacs.app in the nextstep sub-directory. You probably want to stage it to your local Applications directory for further inspection and try.

cp -a nextstep/Emacs.app ~/Applications

Now comes the catch! Since the app depends on extra libraries which are not present on macOS systems by default, you cannot simply add your freshly built app to your friend to use, unless he/she has these extra libraries pre-installed on their system. This is bad. You want an app to simply work on any of those macOS systems, without the hustle installing dependent libraries first, right? What can we do?

Well, one solution can be to use a tool which puts all the dependent dynamic libraries inside the application bundle and fixes their dynamic-linking configuration to refer to them inside the bundle.

Is there such a tool? Well, neither Apple nor GNU offers such a command line tool to my knowledge. However there are several solutions floating around the internet. Some of them are written in C++, Ruby, Python and Shell. What’s common in them is that they invoke the commands, otool and install_name_tool from the CLT to get the job done. Also due to the nature of the dependency-tree, they do it recursively on all the dependent extra libraries.

Inspired by these, and my drive to learn about macOS bundles, dynamic libraries and tools, I created a command line tool in Shell which makes it super easy to process the Emacs.app after building it to make it truly standalone.

Tip: place the script bundle-dylibs in ~/bin and make sure that it’s executable and ~/bin is on the PATH!

curl -s -O https://raw.githubusercontent.com/imrehorvath/bundle-dylibs/main/bundle-dylibs
chmod +x bundle-dylibs

The final step is to invoke the tool, to do the magic. Simply run:

bundle-dylibs ~/Applications/Emacs.app

Of course, the tool can be applied to other application bundles as well. However it is highly recommended to apply it to a COPY of the app and not the original! Also keep in mind that there are no liabilities! Use it at your own risk!

Check the tool out on GitHub!

Wanna build GNU Emacs on macOS from source?

My Emacs Settings

“GNU Emacs is an extensible, customizable text editor—and more.” as they introduce it to the readers on the official site of GNU Emacs.

Actually it’s an old thing still in use today. But it’s no wonder so many people like it even now, since it’s flexible, configurable and extensible. It’s built around some powerful core ideas about buffers, editing and so, and provides a LISP dialect the Emacs Lisp to it’s users to extend and configure it’s features. It’s worth to mention, that the modern versions of GNU Emacs comes with a package system, and there are package repositories containing tons of useful packages to choose form.

Side note. The fact Emacs Lisp is a dynamically scoped language might surprise you, since almost all modern programming languages are statically scoped today. Before you would throw a rock on it, you would like to consider that there are cases when it can come in handy. Eg. You can make other parts of the code behave temporary different, without the need to pass arguments around all the way down in the call stack. The dynamic binding is the default in Emacs, but you may opt for lexical binding if needed on a per file basis.

;; -*- lexical-binding: t -*-

(defun make-adder (x)
  (lambda (y) (+ x y)))

To me it’s a versatile platform for doing many text related operations. Starting from source code editing, through project- and file management, to actually testing REST APIs interactively in a minimalist and easy to use style.

There are many awesome repositories on GitHub hosting Emacs settings and configuration for individuals. There were some attempts to provide a minimalistic, standard common ground with enhancements compared to the bare setup a freshly installed Emacs comes with, that fits everyone. Actually it’s a difficult task to do, since what fits all? Probably the most well known example is Technomancy’s Better Defaults for Emacs.

Based on these influencing examples by Technomancy, Magnars and Bodil, I assembled my minimalistic version that fits me well.

I find hosting my Emacs settings on GitHub to be a good idea, because when I move to a new machine, I only need to install Emacs and check out the repo and start Emacs up. And that’s all. All the packages I need are automatically downloaded and installed during the first start.

For my personal Emacs setup, I didn’t like the idea to depend on external, non-standard libraries to be able to install external and non-standard packages. One reason is that these libraries can be installed and updated through the package system and I didn’t like the git submodule binding for this.

Therefore I choose Bodil’s approach to use exclusively pure core Emacs Lisp code to perform this “bootstrapping”.

;; Install packages if not present
(dolist (pkg '(flx
	       flx-ido
	       flycheck
	       markdown-mode
	       paredit
	       projectile
	       restclient))
  (install-package-if-not-installed pkg))

I must also mention that on a Mac, it’s a bit tricky to setup properly to have the user environment settings from the shell right. But don’t worry. It’s not a big deal really. There is a package to the rescue.

;; Are we on a mac?
(defvar is-mac (equal system-type 'darwin)
  "Boolean indicating if we are on a mac")

;; Setup environment variables from the user's shell.
(when is-mac
  (install-package-if-not-installed 'exec-path-from-shell)
  (exec-path-from-shell-initialize))

I like the idea to have the customisation in a separate file. Therefore I put the following code in my init.el file.

;; Keep emacs Custom-settings in separate file
(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
(load custom-file)

Then it’s in a separate file, the custom.el.

(custom-set-variables
 ;; custom-set-variables was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(js-indent-level 2)
 '(projectile-find-dir-includes-top-level t)
 '(projectile-switch-project-action (quote projectile-find-dir))
 '(scheme-program-name "guile"))
(custom-set-faces
 ;; custom-set-faces was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 )

Are you considering using GNU Emacs?

Pros

  • Powerful and productive environment for text related tasks
  • No need to move your hand between the keyboard and the mouse all the time
  • Many packages for tons of tasks
  • You can modify, bend, and extend it to serve your needs best

Cons

  • Hard to learn all the funny keystrokes
  • It can be hard to learn LISP
  • Steep learning curve

GNU Emacs is an extensible text editor and can be customised to meet individual needs.

To see the the complete code to my Emacs settings, visit my GithHub repo!

My Emacs Settings