Let’s see how things are organized in the Git repository. We will focus on the master branch.
This is not very interesting. It’s a lot of stuff that makes Emacs compile and run on many platforms and architectures.
Emacs --like a lot of GNU projects– use the GNU autotools.
I recommand reading the INSTALL.REPO if you want to build the git ‘master’ branch. Basically, if you have all dependancies to build the default Emacs, run:
$ make # does the needed autogen, configure, make with default settings $ ./src/emacs -Q # run it!
I recommend using -jPROC flag for make where PROC is the number of CPU core you have in order to speed up the compilation.
The core of Emacs is written in C.
Let’s look at src/lisp.h for fundamental definitions.
A Lisp object (Lisp_Object) is basically a number (an integer). This number is split in 2 parts in terms of bits:
The value is either a memory address or an integer i.e. the fixnum Lisp type. The tag indicates the type of the value.
On my 64bit build of Emacs, a Lisp object is stored on a 64bits signed integer which is called (typedef’ed to) EMACS_INT.
Everytime an object is allocated its address is aligned to 8 bytes. That way the 3 least significant bits are always 0 and thus can be used for the tag. The allocation code is in src/alloc.c.
The tag is 3 bit long and thus can have 8 different values. The value uses the remaining bits. Integers use another 1 bit of the 3 tag bits.
This technique makes integer handling fast but has the downside of limiting the available range of integers. This is problematic on 32bit systems where the point in a buffer can’t go past a 2^28 (256MB).
See enum Lisp_Type in lisp.h:243. It’s the value of each tag.
enum Lisp_Misc_Type)Two objects are equal (with EQ(a, b)) if both their Lisp_Object values are equal.
There are several macros defined to extract the relevant data from a Lisp_Object.
XTYPE(x) returns the tag (enum Lisp_Type)XINT(x) returns the EMACS_INT valueXUINT(x) returns the EMACS_UINT valueXCONS(x) returns a struct Lisp_Cons*XVECTOR(x) returns a struct Lisp_Vector*XSTRING(x) returns a struct Lisp_String*XSYMBOL(x) returns a struct Lisp_Symbol*XFLOAT(x) returns a struct Lisp_Float*XMISC(x) returns a union Lisp_Misc*XMARKER(x) returns a struct Lisp_Marker*XOVERLAY(x) returns a struct Lisp_Overlay*XSAVE_VALUE(x) returns a struct Lisp_Save_Value*XPROCESS(x) returns a struct Lisp_Process*XWINDOW(x) returns a struct window*XTERMINAL(x) returns a struct terminal*XSUBR(x) returns a struct Lisp_Subr*XBUFFER(x) returns a struct buffer*XCHAR_TABLE(x) returns a struct Lisp_Char_Table*XSUB_CHAR_TABLE(x) returns a struct Lisp_Sub_Char_Table*XBOOL_VECTOR(x) returns a struct Lisp_Bool_Vector*There’s a bunch of type predicates macros:
INTEGERP(x) checks for float or intNILP(x)SYMBOLP(x)STRINGP(x)CONSP(x)FLOATP(x)VECTORP(x)PROCESSP(x)WINDOWP(x)TERMINALP(x)SUBRP(x)BUFFERP(x)FRAMEP(x)MISCP(x)VECTORLIKEP(x)OVERLAYP(x)MARKERP(x)SAVE_VALUEP(x)IMAGEP(x)There is a DEFUN macro in lisp.h:1987. Have a look at the manual, it’s pretty well written. Writing Emacs Primitives
Lisp_Object tail; for (tail = list; CONSP (tail); tail = XCDR (tail)) { List_Object e = XCAR (tail); /* current element */ /* ... */ }
If you know how to write basic shell scripts you’re good to go. This is a crash course in autoconf for Emacs. Have a look at autoconf doc for more.
Open configure.ac, it’s a big shell script template that is processed by autoconf to generate the actual configure.sh script.
Look for OPTION_DEFAULT_ON or OPTION_DEFAULT_OFF depending on if you want your option to be turn on or off by default.
The syntax is OPTION_DEFAULT_ON([thing],[description]) where:
thing is the thing you want to turn on or off (--with-thing, --without-thing)description is a description of the thing.This macro will define a with_thing shell variable available in the rest of the script. Its value will be either “yes” or “no”.
The convention is later in the script:
$with_thing is yesHAVE_THING variable to yes. If you can’t enable it, set it to no.echo close the the end of the script. Look for “Does Emacs use” in configure.ac.If you need to export something to make it available in the C sources (as a define macro written in src/config.h), use:
AC_DEFINE(YOUR_MACRO, value, [Purpose of the macro])
This will define YOUR_MACRO to the verbatim value. In case you want to export the content of a shell variable (expand it), simply putting $value will not work, you have to use:
AC_DEFINE_UNQUOTED(YOUR_MACRO, "$your_variable", [ description ])
If you need to export a shell variable to src/Makefile.in (the file that is processed by autoconf to generate the actual Makefile) you need to use
AC_SUBST(YOUR_SHELL_VAR)
This will replace any occurence of @YOUR_SHELL_VAR@ in files processed by autoconf with the content of the shell var. If you look at src/Makefile.in for example, you can see:
LIBZ = @LIBZ@
This define a Makefile variable to the value of the shell variable defined earlier in configure.ac.
# first define the configure option OPTION_DEFAULT_ON([thing],[description]) # ... # Thing support HAVE_THING=no ## declare here other variable you need ## like additional build flags, etc. ## ## the convention is to use ## - THING_OBJ for additional object files (use AC_SUBST to export!) ## - LIBTHING for additional librares to add to the linker flags (use AC_SUBST to export!) if test "${with_thing}" != "no"; then # do your check to see if you can actually enable it HAVE_THING=yes # (lets assume you can) # define fi if test "${HAVE_MODULES}" = yes; then # now you *have* to enable Thing! # AC_SUBST, AC_DEFINE, etc usually go here AC_DEFINE(HAVE_THING, 1, [Define to 1 if Thing enabled]) fi # ... # add a "summary line" printed at the end of configuration echo " Does Emacs has Thing? ${HAVE_THING}"