emacs all in one
TOC TOC
Introduction
It's a note on how to compile and use spacemacs/doom and custom emacs profile on one computer in the same time.
And the offline emcs package is used in PortableLinuxTools. For providing a portable toolset for some adhoc linux development and maintainance.
build emacs
building emacs should be in fact very easy. Here is some shell history on resovling dependencies on ubuntu:
sudo apt install \
libxpm-dev \
libgif-dev \
libjpeg-dev \
libpng-dev \
libtiff-dev \
libx11-dev \
libncurses5-dev \
automake \
autoconf \
texinfo \
libgtk2.0-dev
sudo add-apt-repository ppa:ubuntu-toolchain-r/ppa
sudo apt install gcc-10 \
g++-10 \
libgccjit0 \
libgccjit-10-dev \
libjansson4 \
libjansson-dev
# this for gcc-9, ubuntu 1604 has no prebuilt gcc-10
# sudo apt install gcc-9 \
# g++-9 \
# libgccjit0 \
# libgccjit-9-dev \
# libjansson4 \
# libjansson-dev
sudo apt install libgnutls-dev
then clone the code from gnu.org. It's ok to clone from other mirrors too:
git clone git://git.sv.gnu.org/emacs.git
# or clone from github mirror
# https://github.com/emacs-mirror/emacs
# git@github.com:emacs-mirror/emacs.git
checkout the target branch (here it's the native-comp branch), and read the instruction in repos and do build it:
git checkout feature/native-comp
# export CC=/usr/bin/gcc-10 CXX=/usr/bin/gcc-10
export CC=/usr/bin/gcc-9 CXX=/usr/bin/gcc-9
./autogen.sh
./configure \
--prefix=$(realpath ../emacs-native-comp-build) \
--with-nativecomp \
--with-json CFLAGS="-O3 -mtune=native -march=native -fomit-frame-pointer"
make -j4 NATIVE_FULL_AOT=1
make install
or build a version of emacs 27.1 and remove some features not needed in terminal mode:
git checkout emacs-27.1
./autogen.sh
# here we remove all elc files and do make clean
# for sometimes we switching branch to make different target
./configure --prefix=$(realpath ../emacs-build-27.1) \
--with-json CFLAGS="-O3 -mtune=native -march=native -fomit-frame-pointer" \
--with-x-toolkit=no --with-xpm=no --with-jpeg=no \
--with-png=no --with-gif=no --with-tiff=no
make -j 4
make install
we remove most gui related features for avoiding dependencies on many unnecessary lib**.so libraries. BUt still we do not do --with-x=no
check emacsnativecomp too, there are some commands about building in it
run emacs
this part mostly is copied from
copy dependencies
we copy all necessary to relative path ~/emacs-build-27.1/lib
:
for i in $(ldd ../bin/emacs-27.1|rg '=> /' | awk '{print $3}')
do
cp $i .
done
and according to the file excludelist in project
# wget https://raw.githubusercontent.com/AppImage/pkg2appimage/master/excludelist
for i in $(grep -P ^lib.+so excludelist|awk '{print $1}')
do
rm -rf $i
done
but still we lack some so files, we add it back again:
libxcb.so.1
libX11.so.6
libfontconfig.so.1
libfreetype.so.6
libharfbuzz.so.0
all files we copied are:
libgraphite2.so.3
libjansson.so.4
libtasn1.so.6
libXdmcp.so.6
libXrandr.so.2
libffi.so.6
libharfbuzz.so.0
liblzma.so.5
libtinfo.so.5
libXext.so.6
libXrender.so.1
libfontconfig.so.1
libhogweed.so.4
libnettle.so.6
libX11.so.6
libXfixes.so.3
libfreetype.so.6
libicudata.so.55
libpcre.so.3
libX11-xcb.so.1
libXft.so.2
libgmodule-2.0.so.0
libicuuc.so.55
libpng12.so.0
libXau.so.6
libXinerama.so.1
libgnutls.so.30
libidn.so.11
libselinux.so.1
libxcb.so.1
libxml2.so.2
run built emacs
just setup all the related enviroment:
EMACS_PREFIX=$(realpath ~/emacs-build-27.1) \
LD_LIBRARY_PATH=$EMACS_PREFIX/lib/:$LD_LIBRARY_PATH \
PATH=$EMACS_PREFIX/bin:$PATH \
EMACSPATH=$EMACS_PREFIX/share/emacs/27.1 \
EMACSDATA=$EMACSPATH/etc \
EMACSDOC=$EMACSPATH/etc \
EMACSLOADPATH=$EMACSPATH/site-lisp:$EMACSPATH/lisp:$EMACSPATH/lisp/emacs-lisp \
emacs
The EMACS_PREFIX
is for our convinients to define other enviroments. LD_LIBRARY_PATH
is used to specified so for the target executable. For more detail plz ref to rpath.
EMACSPATH
EMACSDATA
EMACSLOADPATH
EMACSDOC
are all enviroment variables related to emacs. TODO currently we still not well understand and document this part.
chemacs, spacemacs and doom
This part is mostly about how to setup multiple version of emacs profile and using it in an offline enviroment. We use chemacs2 to switch different emacs profile (originally we use chemacs). Most part about chemacs2 is just following the tutorial.
the profile (file .emacs-profiles.el
) setup is:
(
("spacemacs" . ((user-emacs-directory . "~/csh_spacemacs_install")
(env . (("SPACEMACSDIR" . "~/.spacemacs.d")))))
("spacemacs-old" . ((user-emacs-directory . "~/spacemacs_old/.emacs.d")
(env . (("SPACEMACSDIR" . "~/spacemacs_old/.spacemacs.d")))))
;;
;; ("new-config" . ((user-emacs-directory . "~/spacemacs/develop")
;; (env . (("SPACEMACSDIR" . "~/my-spacemacs-config")))))
("default" . ((user-emacs-directory . "~/.emacs.d")))
("doom" . ((user-emacs-directory . "~/doom-emacs-27")
(env . (("DOOMDIR" . "~/.doom.d")))))
("myp1". ((user-emacs-directory . "~/.myp1")))
("enc". ((user-emacs-directory . "~/.enc.d")))
)
For emacs build files and .emacs.d .spacemacs.d and other files just tar them into a tar.gz file from an ubuntu enviroment (an enviroment that we installed chemacs2 and spacemacs and doom normally). Beware that we need to tar all directories removing its soft links and owner/group. Aka the package should use tar with a dereference option -h
, like: tar -zcvh -f targetfile.tar.gz blablabla
if got an error like: https://superuser.com/questions/169195/tar-exiting-with-failure-status-due-to-previous-errors try remove -v
to get a concrete reason or package without .git
:
tar -zcvh -f emacs-all-in-one.tar.gz --exclude .git .emacs.d csh_spacemacs_install .spacemacs.d doom-emacs-27 .doom.d .enc.d emacs-build-27.1 .emacs-profiles.el spacemacs_old
and for removing user/group, we use --owner=0 --group=0
for detail:
--exclude .git --owner=0 --group=0
package without git got an error in doom:
Loading /home/powerop/doom-emacs-27/.local/cache/recentf...done
Doom loaded 152 packages across 28 modules in 1.362s
Loading loadup.el (source)...done
Cannot determine Magit’s version (error "/home/powerop/doom-emacs-27/.local/straight/repos/magit/lisp/magit.el" repo static elpa dirname hash)
Reading /home/powerop/doom-emacs-27/.local/etc/scratch/__default.el
evil-motion-range: Beginning of buffer
but seems does not matter
and finaly, we just package the tar.gz
file to the PortableLinuxTools, a tool set for adhoc linux enviroment.
fix doom installation for offline usage
tldr, we need do doom build
and doom sync
again. And beware that do remove soft links in tar.gz file. It contains lots of soft links.
and another problem is that we failed at some point like:
Debugger entered--Lisp error: (wrong-type-argument stringp (require . china-util))
string-match("\\(\\`\\|/\\)imenu\\(\\.elc\\|\\.el\\|\\.so\\)?\\(\\.gz\\)?\\'" (require . china-util))
load-history-filename-element("\\(\\`\\|/\\)imenu\\(\\.elc\\|\\.el\\|\\.so\\)?\\(\\.gz\\)?\\'")
eval-after-load("imenu" #f(compiled-function () #<bytecode 0x156f3dd>))
require(org-compat)
byte-code("\302\303!\210\302\304!\210\302\305!\210\302\306!\210\10\307=\204:\0\3101)\0\311\312\11!\313P\314\315\211\211%0\2029\0\210\316\317!\210\320\321!\210..." [this-command load-fi$
#<subr autoload-do-load>((autoload "org" "Outline-based notes management and organizer, alia..." t nil) org-mode nil)
apply(#<subr autoload-do-load> ((autoload "org" "Outline-based notes management and organizer, alia..." t nil) org-mode))
autoload-do-load((autoload "org" "Outline-based notes management and organizer, alia..." t nil) org-mode)
command-execute(org-mode record)
counsel-M-x-action("org-mode")
ivy-call()
ivy-read("M-x " ("toggle-debug-on-error" "org-mode" "cd" "5x5" "amx" "arp" "dbx" "dig" "erc" "ert" "eww" "ftp" "gdb" "irc" "jdb" "man" "mpc" "pdb" "pwd" "rsh" "sdb" "xdb" "calc" "diff"$
counsel-M-x()
funcall-interactively(counsel-M-x)
call-interactively(counsel-M-x nil nil)
command-execute(counsel-M-x)
we did https://www.reddit.com/r/emacs/comments/bezim2/issue_with_withevalafterload_and_emacs_27/ and https://www.google.com/search?q=load-history-filename-element+emacs but it doesnt help.
but we did it with method mentioned in at https://emacs.stackexchange.com/q/5552/
put the code:
(defun load-history-filename-element (file-regexp)
"Get the first elt of `load-history' whose car matches FILE-REGEXP.
Return nil if there isn't one."
(let* ((loads load-history)
(load-elt (and loads (car loads))))
(save-match-data
(while (and loads
(or (null (car load-elt))
(not (and (stringp (car load-elt)) ; new condition
(string-match file-regexp (car load-elt))))))
(setq loads (cdr loads)
load-elt (and loads (car loads)))))
load-elt))
put in a very early point, it's working now. It should be something related to load-history
. But we haven't figure it too much now.