[syslinux:firmware] Add per-firmware object directory support

syslinux-bot for Matt Fleming matt.fleming at intel.com
Fri Nov 9 09:06:30 PST 2012


Commit-ID:  1408e6ca7b3854d94aaa39612b4bb6fdf9111dc7
Gitweb:     http://www.syslinux.org/commit/1408e6ca7b3854d94aaa39612b4bb6fdf9111dc7
Author:     Matt Fleming <matt.fleming at intel.com>
AuthorDate: Tue, 25 Sep 2012 14:45:18 +0100
Committer:  Matt Fleming <matt.fleming at intel.com>
CommitDate: Tue, 16 Oct 2012 11:38:01 +0100

Add per-firmware object directory support

Now that we have multiple firmware backends it no longer makes sense
to write object files to the same directory as their source. A better
solution is to write the object files to a per-firmware directory
under a top-level object directory.

The top-level object directory can be specified on the command-line
with the O= variable, e.g. make O=/tmp/obj. If no top-level object
directory is specified an 'obj' directory is created in the top-level
of the Syslinux source repository.

All the existing make targets continue to work as before, however now
they apply to all firmware backends, e.g. 'make installer' will build
the BIOS, 32-bit EFI and 64-bit EFI installers and place them under
$(OBJ)/bios, $(OBJ)/efi32 and $(OBJ)/efi64 respectively.

Note unlike every other bit of Syslinux, the gpxe objects are still
kept in the src directory, e.g. gpxe/src, since gpxe is only required
by the BIOS backend.

It is possible to specify a make target for a specific firmware or
list of firmware with the following syntax,

    make [firmware[,firmware]] [target[,target]]

To clean the object directory for just the BIOS firmware type,

      'make bios clean'

To build both the 32-bit and 64-bit EFI installers type,

     'make efi32 efi64 installer'

Since the Syslinux make infrastructure is now more complex a new file
doc/building.txt has been created to explain how to build Syslinux.

The top-level Makefile now exports some make variables for use in
module Makefiles,

    - topdir - the top-level source directory of the Syslinux
      repository, e.g. /usr/src/syslinux

    - objdir - the top-level object directory for the firmware
      backend currently being built, e.g. /obj/syslinux/bios

    - SRC - the source directory in the Syslinux repository for the
      module currently being built,
      e.g. /usr/src/syslinux/com32/libupload

    - OBJ - the object directory for the module currently being
      built, e.g. /obj/syslinux/bios/com32/libupload

Since we're rewriting the Makefile infrastructure anyway it seemed
like a good idea to add parallel support. By writing subdirectories as
prequisites for make targets the objects in those subdirectories can
be built in parallel.

Signed-off-by: Matt Fleming <matt.fleming at intel.com>

---
 Makefile                       |  255 ++++++++++++++++++++++++++++++++++------
 codepage/Makefile              |    8 +-
 com32/Makefile                 |   21 +++-
 com32/chain/Makefile           |    4 +-
 com32/cmenu/Makefile           |   29 +++--
 com32/elflink/ldlinux/Makefile |   13 +-
 com32/gfxboot/Makefile         |    7 +-
 com32/gpllib/Makefile          |   16 ++-
 com32/hdt/Makefile             |   14 +-
 com32/lib/Makefile             |   16 ++-
 com32/lib/syslinux/version.c   |    2 +-
 com32/libupload/Makefile       |   10 +-
 com32/libutil/Makefile         |    3 +-
 com32/lua/src/Makefile         |    3 +-
 com32/mboot/Makefile           |    5 +-
 com32/menu/Makefile            |   15 +--
 com32/modules/Makefile         |   10 +-
 com32/rosh/Makefile            |    6 +-
 com32/rosh/rosh.c              |    2 +-
 com32/samples/Makefile         |   13 +-
 com32/sysdump/Makefile         |   11 +-
 com32/tools/Makefile           |    4 +-
 core/Makefile                  |   66 ++++++----
 diag/Makefile                  |    5 +-
 diag/geodsp/Makefile           |    9 +-
 diag/mbr/Makefile              |    3 +-
 doc/building.txt               |   40 ++++++
 dos/Makefile                   |   14 +-
 dosutil/Makefile               |    8 +-
 efi/Makefile                   |   33 +++---
 extlinux/Makefile              |    6 +-
 extlinux/main.c                |    2 +-
 gpxe/Makefile                  |   17 ++--
 libinstaller/Makefile          |   22 ++--
 libinstaller/syslxopt.c        |    2 +-
 linux/Makefile                 |    6 +-
 lzo/Makefile                   |   12 +-
 mbr/Makefile                   |   14 ++-
 memdisk/Makefile               |   13 +-
 memdisk/setup.c                |    2 +-
 memdump/Makefile               |    7 +-
 mk/efi.mk                      |    2 +-
 mk/elf.mk                      |   13 +-
 mk/lib.mk                      |   22 ++--
 modules/Makefile               |    4 +-
 mtools/Makefile                |    8 +-
 sample/Makefile                |    3 +-
 utils/Makefile                 |   22 ++--
 win32/Makefile                 |   13 +-
 win64/Makefile                 |   13 +-
 50 files changed, 552 insertions(+), 296 deletions(-)

diff --git a/Makefile b/Makefile
index e029428..15d0a98 100644
--- a/Makefile
+++ b/Makefile
@@ -14,8 +14,89 @@
 #
 # Main Makefile for SYSLINUX
 #
-topdir = .
+
+#
+# topdir is only set when we are doing a recursive make. Do a bunch of
+# initialisation if it's unset since this is the first invocation.
+#
+ifeq ($(topdir),)
+
+topdir = $(CURDIR)
+
+#
+# Because we need to build modules multiple times, e.g. for BIOS,
+# efi32, efi64, we output all object and executable files to a
+# separate object directory for each firmware.
+#
+# The output directory can be customised by setting the O=/obj/path/
+# variable when invoking make. If no value is specified the default
+# directory is 'obj'.
+#
+ifeq ("$(origin O)", "command line")
+	OBJDIR := $(O)
+else
+	OBJDIR = $(CURDIR)/obj
+	foo := $(shell mkdir -p $(OBJDIR) && /bin/true)
+endif
+
+# If the output directory does not exist we bail because that is the
+# least surprising thing to do.
+cd-output := $(shell cd $(OBJDIR) && /bin/pwd)
+$(if $(cd-output),, \
+	$(error output directory "$(OBJDIR)" does not exist))
+
+#
+# These environment variables are exported to every invocation of
+# make,
+#
+# 'topdir' - the top-level directory containing the Syslinux source
+# 'objdir' - the top-level directory of output files
+# 'MAKEDIR' - contains Makefile fragments
+#
+# There are also a handful of variables that are passed to each
+# sub-make,
+#
+# SRC - source tree location of the module being compiled
+# OBJ - output tree location of the module being compiled
+#
+# A couple of rules for writing Makefiles,
+#
+# - Do not use relative paths, use the above variables
+# - You can write $(SRC) a lot less if you add it to VPATH
+#
+
 MAKEDIR = $(topdir)/mk
+export MAKEDIR topdir
+
+ifeq ($(MAKECMDGOALS),)
+	MAKECMDGOALS += all
+endif
+
+#
+# The 'bios', 'efi32' and 'efi64' are dummy targets. Their only
+# purpose is to instruct us which output directories need
+# creating. Which means that we always need a *real* target, such as
+# 'all', appended to the make goals.
+#
+firmware = bios efi32 efi64
+real-target := $(filter-out $(firmware), $(MAKECMDGOALS))
+real-firmware := $(filter $(firmware), $(MAKECMDGOALS))
+
+ifeq ($(real-target),)
+	real-target = all
+endif
+
+ifeq ($(real-firmware),)
+	real-firmware = $(firmware)
+endif
+
+.PHONY: $(MAKECMDGOALS)
+$(MAKECMDGOALS):
+	$(MAKE) -C $(OBJDIR) -f $(CURDIR)/Makefile SRC="$(topdir)" \
+		OBJ=$(OBJDIR) objdir=$(OBJDIR) $(MAKECMDGOALS)
+
+else # ifeq ($(topdir),)
+
 include $(MAKEDIR)/syslinux.mk
 -include $(topdir)/version.mk
 
@@ -41,8 +122,7 @@ MODULES = memdisk/memdisk memdump/memdump.com modules/*.com \
 else
 # memdump is BIOS specific code exclude it for EFI
 # FIXME: Prune other BIOS-centric modules
-MODULES = memdisk/memdisk modules/*.com \
-	com32/menu/*.c32 com32/modules/*.c32 com32/mboot/*.c32 \
+MODULES = com32/menu/*.c32 com32/modules/*.c32 com32/mboot/*.c32 \
 	com32/hdt/*.c32 com32/rosh/*.c32 com32/gfxboot/*.c32 \
 	com32/sysdump/*.c32 com32/lua/src/*.c32 com32/chain/*.c32 \
 	com32/lib/*.c32 com32/libutil/*.c32 com32/gpllib/*.c32 \
@@ -66,15 +146,19 @@ BOBJECTS = $(BTARGET) \
 # Note: libinstaller is both a BSUBDIR and an ISUBDIR.  It contains
 # files that depend only on the B phase, but may have to be regenerated
 # for "make installer".
-ifndef EFI_BUILD
-BSUBDIRS = codepage com32 lzo core memdisk modules mbr memdump gpxe sample \
-	   diag libinstaller dos win32 win64 dosutil efi
+
+ifdef EFI_BUILD
+
+BSUBDIRS = codepage com32 lzo core modules mbr sample efi
+ISUBDIRS = efi utils
+
+INSTALLSUBDIRS = efi
+
 else
-# memdump is BIOS specific code exclude it for EFI
-# FIXME: Prune other BIOS-centric modules
-BSUBDIRS = codepage com32 lzo core memdisk modules mbr gpxe sample \
-	   diag libinstaller win32 win64 dosutil efi
-endif
+
+BSUBDIRS = codepage com32 lzo core memdisk sample diag mbr memdump dos \
+	   modules gpxe libinstaller win32 win64 dosutil
+
 ITARGET  =
 IOBJECTS = $(ITARGET) \
 	utils/gethostip utils/isohybrid utils/mkdiskimage \
@@ -104,33 +188,117 @@ EXTBOOTINSTALL = $(MODULES)
 NETINSTALLABLE = core/pxelinux.0 gpxe/gpxelinux.0 \
 		 $(MODULES)
 
-all:
-	$(MAKE) all-local
-	set -e ; for i in $(BSUBDIRS) $(ISUBDIRS) ; do $(MAKE) -C $$i $@ ; done
-	-ls -l $(BOBJECTS) $(IOBJECTS)
+endif # ifdef EFI_BUILD
 
-all-local: $(BTARGET) $(ITARGET)
+.PHONY: subdirs $(BSUBDIRS) $(ISUBDIRS)
+
+ifeq ($(HAVE_FIRMWARE),)
+
+firmware = bios efi32 efi64
+
+# If no firmware was specified the rest of MAKECMDGOALS applies to all
+# firmware.
+ifeq ($(filter $(firmware),$(MAKECMDGOALS)),)
+all strip tidy clean dist spotless install installer: bios efi32 efi64
+
+else
+
+# Don't do anything for the rest of MAKECMDGOALS at this level. It
+# will be handled for each of $(firmware).
+strip tidy clean dist spotless install installer:
+
+endif
+
+# Convert 'make bios strip' to 'make strip', etc for rest of the Makefiles.
+MAKECMDGOALS := $(filter-out $(firmware),$(MAKECMDGOALS))
+ifeq ($(MAKECMDGOALS),)
+	MAKECMDGOALS += all
+endif
+
+#
+# You'd think that we'd be able to use the 'define' directive to
+# abstract the code for invoking make(1) in the output directory, but
+# by using 'define' we lose the ability to build in parallel.
+#
+.PHONY: $(firmware)
+bios:
+	@mkdir -p $(OBJ)/bios
+	$(MAKE) -C $(OBJ)/bios -f $(SRC)/Makefile SRC="$(SRC)" \
+		objdir=$(OBJ)/bios OBJ=$(OBJ)/bios HAVE_FIRMWARE=1 \
+		ARCH=i386 $(MAKECMDGOALS)
+
+efi32:
+	@mkdir -p $(OBJ)/efi32
+	$(MAKE) -C $(OBJ)/efi32 -f $(SRC)/Makefile SRC="$(SRC)" \
+		objdir=$(OBJ)/efi32 OBJ=$(OBJ)/efi32 HAVE_FIRMWARE=1 \
+		ARCH=i386 BITS=32 EFI_BUILD=1 $(MAKECMDGOALS)
+
+efi64:
+	@mkdir -p $(OBJ)/efi64
+	$(MAKE) -C $(OBJ)/efi64 -f $(SRC)/Makefile SRC="$(SRC)" \
+		objdir=$(OBJ)/efi64 OBJ=$(OBJ)/efi64 HAVE_FIRMWARE=1 \
+		ARCH=x86_64 BITS=64 EFI_BUILD=1 $(MAKECMDGOALS)
+
+else # ifeq($(HAVE_FIRMWARE),)
+
+all: all-local subdirs
 
-installer:
-	$(MAKE) installer-local
-	set -e ; for i in $(ISUBDIRS); do $(MAKE) -C $$i all ; done
+all-local: $(BTARGET) $(ITARGET)
 	-ls -l $(BOBJECTS) $(IOBJECTS)
+subdirs: $(BSUBDIRS) $(ISUBDIRS)
+
+# Note the double-colon which avoids the make warning about redefining
+# a rule for libinstaller.
+$(BSUBDIRS):
+	@mkdir -p $@
+	$(MAKE) -C $@ SRC="$(SRC)/$@" OBJ="$(OBJ)/$@" \
+		-f $(SRC)/$@/Makefile $(MAKECMDGOALS)
+
+$(ISUBDIRS):
+	@mkdir -p $@
+	$(MAKE) -C $@ SRC="$(SRC)/$@" OBJ="$(OBJ)/$@" \
+		-f $(SRC)/$@/Makefile $(MAKECMDGOALS)
+
+$(ITARGET):
+	@mkdir -p $@
+	$(MAKE) -C $@ SRC="$(SRC)/$@" OBJ="$(OBJ)/$@" \
+		-f $(SRC)/$@/Makefile $(MAKECMDGOALS)
+
+$(BINFILES):
+	@mkdir -p $@
+	$(MAKE) -C $@ SRC="$(SRC)/$@" OBJ="$(OBJ)/$@" \
+		-f $(SRC)/$@/Makefile $(MAKECMDGOALS)
+
+#
+# List the dependencies to help out parallel builds.
+dos extlinux linux mtools win32 win64: libinstaller
+libinstaller: core
+utils: mbr
+core: com32
+efi: core
+
+installer: installer-local
+	set -e; for i in $(ISUBDIRS); \
+		do $(MAKE) -C $$i SRC="$(SRC)/$$i" OBJ="$(OBJ)/$$i" \
+		-f $(SRC)/$$i/Makefile all; done
+
 
 installer-local: $(ITARGET) $(BINFILES)
 
-strip:
-	$(MAKE) strip-local
-	set -e ; for i in $(ISUBDIRS); do $(MAKE) -C $$i strip ; done
+strip: strip-local
+	set -e; for i in $(ISUBDIRS); \
+		do $(MAKE) -C $$i SRC="$(SRC)/$$i" OBJ="$(OBJ)/$$i" \
+		-f $(SRC)/$$i/Makefile strip; done
 	-ls -l $(BOBJECTS) $(IOBJECTS)
 
 strip-local:
 
-version.gen: version version.pl
-	$(PERL) version.pl $< $@ '%define < @'
-version.h: version version.pl
-	$(PERL) version.pl $< $@ '#define < @'
-version.mk: version version.pl
-	$(PERL) version.pl $< $@ '< := @'
+version.gen: $(topdir)/version $(topdir)/version.pl
+	$(PERL) $(topdir)/version.pl $< $@ '%define < @'
+version.h: $(topdir)/version $(topdir)/version.pl
+	$(PERL) $(topdir)/version.pl $< $@ '#define < @'
+version.mk: $(topdir)/version $(topdir)/version.pl
+	$(PERL) $(topdir)/version.pl $< $@ '< := @'
 
 local-install: installer
 	mkdir -m 755 -p $(INSTALLROOT)$(BINDIR)
@@ -143,12 +311,24 @@ local-install: installer
 	mkdir -m 755 -p $(INSTALLROOT)$(DIAGDIR)
 	install -m 644 -c $(INSTALL_DIAG) $(INSTALLROOT)$(DIAGDIR)
 	mkdir -m 755 -p $(INSTALLROOT)$(MANDIR)/man1
-	install -m 644 -c man/*.1 $(INSTALLROOT)$(MANDIR)/man1
+	install -m 644 -c $(topdir)/man/*.1 $(INSTALLROOT)$(MANDIR)/man1
 	: mkdir -m 755 -p $(INSTALLROOT)$(MANDIR)/man8
 	: install -m 644 -c man/*.8 $(INSTALLROOT)$(MANDIR)/man8
 
+ifndef EFI_BUILD
 install: local-install
-	set -e ; for i in $(INSTALLSUBDIRS) ; do $(MAKE) -C $$i $@ ; done
+	set -e ; for i in $(INSTALLSUBDIRS) ; \
+		do $(MAKE) -C $$i SRC="$(SRC)/$$i" OBJ="$(OBJ)/$$i" \
+		-f $(SRC)/$$i/Makefile $@; done
+else
+install:
+	set -e ; for i in $(INSTALLSUBDIRS) ; \
+		do $(MAKE) -C $$i SRC="$(SRC)/$$i" OBJ="$(OBJ)/$$i" \
+		BITS="$(BITS)" -f $(SRC)/$$i/Makefile $@; done
+
+	mkdir -m 755 -p $(INSTALLROOT)$(AUXDIR)/efi$(BITS)
+	install -m 755 $(MODULES) $(INSTALLROOT)$(AUXDIR)/efi$(BITS)
+endif
 
 netinstall: installer
 	mkdir -p $(INSTALLROOT)$(TFTPBOOT)
@@ -165,33 +345,32 @@ local-tidy:
 	rm -f *.lsr *.lst *.map *.sec *.tmp
 	rm -f $(OBSOLETE)
 
-tidy: local-tidy
-	set -e ; for i in $(BESUBDIRS) $(IESUBDIRS) $(BSUBDIRS) $(ISUBDIRS) ; do $(MAKE) -C $$i $@ ; done
+tidy: local-tidy $(BESUBDIRS) $(IESUBDIRS) $(BSUBDIRS) $(ISUBDIRS)
 
 local-clean:
 	rm -f $(ITARGET)
 
-clean: local-tidy local-clean
-	set -e ; for i in $(BESUBDIRS) $(IESUBDIRS) $(BSUBDIRS) $(ISUBDIRS) ; do $(MAKE) -C $$i $@ ; done
+clean: local-tidy local-clean $(BESUBDIRS) $(IESUBDIRS) $(BSUBDIRS) $(ISUBDIRS)
 
 local-dist:
 	find . \( -name '*~' -o -name '#*' -o -name core \
 		-o -name '.*.d' -o -name .depend \) -type f -print0 \
 	| xargs -0rt rm -f
 
-dist: local-dist local-tidy
-	set -e ; for i in $(BESUBDIRS) $(IESUBDIRS) $(BSUBDIRS) $(ISUBDIRS) ; do $(MAKE) -C $$i $@ ; done
+dist: local-dist local-tidy $(BESUBDIRS) $(IESUBDIRS) $(BSUBDIRS) $(ISUBDIRS)
 
 local-spotless:
 	rm -f $(BTARGET) .depend *.so.*
 
-spotless: local-clean local-dist local-spotless
-	set -e ; for i in $(BESUBDIRS) $(IESUBDIRS) $(BSUBDIRS) $(ISUBDIRS) ; do $(MAKE) -C $$i $@ ; done
+spotless: local-clean local-dist local-spotless $(BESUBDIRS) $(IESUBDIRS) $(ISUBDIRS) $(BSUBDIRS)
 
 # Shortcut to build linux/syslinux using klibc
 klibc:
 	$(MAKE) clean
 	$(MAKE) CC=klcc ITARGET= ISUBDIRS='linux extlinux' BSUBDIRS=
+endif # ifeq ($(HAVE_FIRMWARE),)
 
 # Hook to add private Makefile targets for the maintainer.
 -include Makefile.private
+
+endif # ifeq ($(topdir),)
diff --git a/codepage/Makefile b/codepage/Makefile
index 2a6fd12..18a590f 100644
--- a/codepage/Makefile
+++ b/codepage/Makefile
@@ -1,6 +1,8 @@
+VPATH		= $(SRC)
 PERL		= perl
-CPSRC		= $(wildcard *.txt)
-GENFILES	= $(patsubst %.txt,%.cp,$(CPSRC))
+CPSRC		= $(wildcard $(SRC)/*.txt)
+CPOBJ		= $(notdir $(CPSRC))
+GENFILES	= $(patsubst %.txt,%.cp,$(CPOBJ))
 
 .SUFFIXES: .txt .cp
 
@@ -9,7 +11,7 @@ all: $(GENFILES)
 # This generates codepage files where the display and filesystem
 # codepages are both the same.
 %.cp: %.txt cptable.pl UnicodeData
-	$(PERL) cptable.pl UnicodeData $< $< $@
+	$(PERL) $(SRC)/cptable.pl $(SRC)/UnicodeData $< $< $@
 
 tidy:
 	rm -f *.cp *.bin
diff --git a/com32/Makefile b/com32/Makefile
index c4699cf..7ea1b01 100644
--- a/com32/Makefile
+++ b/com32/Makefile
@@ -1,5 +1,22 @@
 SUBDIRS = libupload tools lib elflink/ldlinux gpllib libutil modules mboot \
 	  menu samples elflink rosh cmenu hdt gfxboot sysdump lua/src chain
 
-all tidy dist clean spotless install:
-	set -e; for d in $(SUBDIRS); do $(MAKE) -C $$d $@; done
+.PHONY: subdirs $(SUBDIRS)
+subdirs: $(SUBDIRS)
+$(SUBDIRS):
+	@mkdir -p $(OBJ)/$@
+	$(MAKE) -C $(OBJ)/$@ SRC="$(SRC)"/$@ OBJ="$(OBJ)"/$@/ \
+		-f $(SRC)/$@/Makefile $(MAKECMDGOALS)
+
+all tidy dist clean spotless install: subdirs
+
+# Parallel dependencies
+chain lua/src mboot menu: libutil gpllib
+cmenu: lib libutil
+elflink/ldlinux: lib
+gfxboot: libutil
+hdt: lib libupload cmenu gpllib libutil
+modules: lib libutil gpllib
+rosh: lib libutil
+samples: libutil elflink/ldlinux
+sysdump: libupload gpllib
diff --git a/com32/chain/Makefile b/com32/chain/Makefile
index 9a298fa..3238550 100644
--- a/com32/chain/Makefile
+++ b/com32/chain/Makefile
@@ -11,9 +11,7 @@
 ##
 ## -----------------------------------------------------------------------
 
-
-topdir = ../..
-MAKEDIR = $(topdir)/mk
+VPATH = $(SRC)
 include $(MAKEDIR)/elf.mk
 
 OBJS = chain.o partiter.o utility.o options.o mangle.o
diff --git a/com32/cmenu/Makefile b/com32/cmenu/Makefile
index beb8dd2..80fff36 100644
--- a/com32/cmenu/Makefile
+++ b/com32/cmenu/Makefile
@@ -18,31 +18,34 @@
 NOGPL := 1
 
 LIBS  = libmenu/libmenu.c32 \
-        $(com32)/libutil/libutil_com.c32 \
-        $(com32)/lib/libcom32.c32
+        $(objdir)/com32/libutil/libutil_com.c32 \
+        $(objdir)/com32/lib/libcom32.c32
 
-topdir = ../..
-MAKEDIR = $(topdir)/mk
+VPATH = $(SRC)
 include $(MAKEDIR)/elf.mk
 
-CFLAGS	  += -I./libmenu
+CFLAGS	  += -I$(SRC)/libmenu
 
-LIBMENU = libmenu/syslnx.o libmenu/com32io.o libmenu/tui.o \
-	libmenu/menu.o libmenu/passwords.o libmenu/des.o libmenu/help.o \
-	$(com32)/libutil/libutil_com.c32 $(com32)/lib/libcom32.c32
+LIBMENU = $(objdir)/com32/libutil/libutil_com.c32 \
+	$(objdir)/com32/lib/libcom32.c32 \
+	libmenu/syslnx.o libmenu/com32io.o libmenu/tui.o \
+	libmenu/menu.o libmenu/passwords.o libmenu/des.o libmenu/help.o
 
-CMENUS = $(patsubst %.c,%.c32,$(wildcard *.c))
-IMENUS = $(patsubst %.menu,%.c32,$(wildcard *.menu))
+CMENUS = $(patsubst %.c,%.c32,$(wildcard $(SRC)/*.c))
+IMENUS = $(patsubst %.menu,%.c32,$(wildcard $(SRC)/*.menu))
 
-MENUS = $(LIBS) $(CMENUS) $(IMENUS)
+MENUS = $(LIBS) $(subst $(SRC)/,,$(CMENUS) $(IMENUS))
 
 .SUFFIXES: .S .c .o .elf .c32 .menu
 
 .PRECIOUS: %.c
 %.c: %.menu adv_menu.tpl
-	python menugen.py --input=$< --output=$@ --template=adv_menu.tpl
+	python $(SRC)/menugen.py --input=$< --output=$@ --template=$(SRC)/adv_menu.tpl
 
-all:	menus
+all:	makeoutputdirs menus
+
+makeoutputdirs:
+	@mkdir -p $(OBJ)/libmenu
 
 libmenu/libmenu.c32: $(LIBMENU)
 	$(LD) -shared $(LDFLAGS) -o $@ $^
diff --git a/com32/elflink/ldlinux/Makefile b/com32/elflink/ldlinux/Makefile
index dc48ca9..58fc9c9 100644
--- a/com32/elflink/ldlinux/Makefile
+++ b/com32/elflink/ldlinux/Makefile
@@ -10,18 +10,19 @@
 ##
 ## -----------------------------------------------------------------------
 
-topdir = ../../..
-MAKEDIR = $(topdir)/mk
+VPATH = $(SRC)
 include $(MAKEDIR)/elf.mk
 
 CFLAGS += -I$(topdir)/core/elflink -I$(topdir)/core/include
-LIBS = --whole-archive $(com32)/lib/libcom32min.a
+LIBS = --whole-archive $(objdir)/com32/lib/libcom32min.a
+
+OBJS = ldlinux.o cli.o readconfig.o refstr.o colors.o getadv.o adv.o \
+	execute.o chainboot.o kernel.o get_key.o advwrite.o setadv.o \
+	eprintf.o loadhigh.o
 
 all: ldlinux.c32 ldlinux_lnx.a
 
-ldlinux.c32 : ldlinux.o cli.o readconfig.o refstr.o colors.o getadv.o \
-		adv.o execute.o chainboot.o kernel.o get_key.o \
-		advwrite.o setadv.o eprintf.o loadhigh.o
+ldlinux.c32 : $(OBJS)
 	$(LD) $(LDFLAGS) -o $@ $^ $(LIBS)
 
 LNXLIBOBJS = get_key.lo
diff --git a/com32/gfxboot/Makefile b/com32/gfxboot/Makefile
index a2420c4..98d6a03 100644
--- a/com32/gfxboot/Makefile
+++ b/com32/gfxboot/Makefile
@@ -11,15 +11,16 @@
 ##
 ## -----------------------------------------------------------------------
 
-topdir = ../..
-MAKEDIR = $(topdir)/mk
+VPATH = $(SRC)
 include $(MAKEDIR)/elf.mk
 
 MODULES	  = gfxboot.c32
 
 all: $(MODULES)
 
-gfxboot.c32 : gfxboot.o realmode_callback.o $(LIBS) $(C_LIBS)
+OBJS = gfxboot.o realmode_callback.o
+
+gfxboot.c32 : $(OBJS) $(LIBS) $(C_LIBS)
 	$(LD) $(LDFLAGS) -o $@ $^
 
 realmode_callback.o: realmode_callback.asm
diff --git a/com32/gpllib/Makefile b/com32/gpllib/Makefile
index 4f41ca8..3e2bd03 100644
--- a/com32/gpllib/Makefile
+++ b/com32/gpllib/Makefile
@@ -3,14 +3,12 @@
 #
 
 # Include configuration rules
-topdir = ../..
-MAKEDIR = $(topdir)/mk
 include $(MAKEDIR)/lib.mk
 
-REQFLAGS += -I../gplinclude -I../gplinclude/zzjson
+REQFLAGS += -I$(SRC)/../gplinclude -I$(SRC)/../gplinclude/zzjson
 
-GPLDIRS := . disk dmi vpd acpi zzjson
-LIBOBJS := $(foreach dir,$(GPLDIRS),$(patsubst %.c,%.o,$(wildcard $(dir)/*.c)))
+GPLDIRS := $(SRC) $(addprefix $(SRC)/,disk dmi vpd acpi zzjson)
+LIBOBJS := $(subst $(SRC)/,,$(foreach dir,$(GPLDIRS),$(patsubst %.c,%.o,$(wildcard $(dir)/*.c))))
 
 BINDIR   = /usr/bin
 LIBDIR   = /usr/lib
@@ -19,7 +17,11 @@ AUXDIR   = $(DATADIR)/syslinux
 INCDIR   = /usr/include
 COM32DIR = $(AUXDIR)/com32
 
-all: libcom32gpl.c32
+all: makeoutputdirs libcom32gpl.c32
+
+makeoutputdirs:
+	@mkdir -p $(foreach b, \
+		$(addprefix $(OBJ),$(sort $(dir $(LIBOBJS)))),$(b))
 
 libcom32gpl.c32 : $(LIBOBJS)
 	$(LD) -shared $(LDFLAGS) -o $@ $^
@@ -38,6 +40,6 @@ install: all
 	mkdir -m 755 -p $(INSTALLROOT)$(COM32DIR)
 	install -m 644 libcom32gpl.c32 $(INSTALLROOT)$(COM32DIR)
 	mkdir -p $(INSTALLROOT)$(COM32DIR)/include/
-	cp -r ../gplinclude $(INSTALLROOT)$(COM32DIR)/include/
+	cp -r $(SRC)/../gplinclude $(INSTALLROOT)$(COM32DIR)/include/
 
 -include .*.d */.*.d */*/.*.d
diff --git a/com32/hdt/Makefile b/com32/hdt/Makefile
index ff0fa2e..386c747 100644
--- a/com32/hdt/Makefile
+++ b/com32/hdt/Makefile
@@ -15,20 +15,20 @@
 ## Hardware Detection Tool
 ##
 
-topdir = ../..
-MAKEDIR = $(topdir)/mk
+VPATH = $(SRC)
 include $(MAKEDIR)/elf.mk
 
-LIBS      = ../libupload/libcom32upload.a
-C_LIBS    += $(com32)/cmenu/libmenu/libmenu.c32 \
-	     $(com32)/libutil/libutil_com.c32 \
-	     $(com32)/lib/libcom32.c32 $(com32)/gpllib/libcom32gpl.c32
+LIBS      = $(objdir)/com32/libupload/libcom32upload.a
+C_LIBS    += $(objdir)/com32/cmenu/libmenu/libmenu.c32 \
+	     $(objdir)/com32/libutil/libutil_com.c32 \
+	     $(objdir)/com32/lib/libcom32.c32 \
+	     $(objdir)/com32/gpllib/libcom32gpl.c32
 CFLAGS    += -I$(com32)/cmenu/libmenu -I$(com32)
 
 MODULES	  = hdt.c32
 TESTFILES =
 
-OBJS	  = $(patsubst %.c,%.o,$(wildcard *.c))
+OBJS	  = $(subst $(SRC)/,,$(patsubst %.c,%.o,$(wildcard $(SRC)/*.c)))
 VERSION   = $(shell $(SED) -n 's/\#define VERSION \"\(.*\)\"/\1/p' hdt.h)
 CODENAME  = $(shell $(SED) -n 's/\#define CODENAME \"\(.*\)\"/\1/p' hdt.h)
 NODASH_VERSION = $(shell echo $(VERSION) | $(SED) -e 's/-/_/g' | $(SED) -e 's/\./_/g')
diff --git a/com32/lib/Makefile b/com32/lib/Makefile
index 705feb3..eb0d612 100644
--- a/com32/lib/Makefile
+++ b/com32/lib/Makefile
@@ -4,8 +4,7 @@
 
 # Include configuration rules
 NOGPL := 1
-topdir = ../../
-MAKEDIR = $(topdir)/mk
+VPATH = $(SRC)
 include $(MAKEDIR)/lib.mk
 
 ## OPTIONAL OBJECTS, AVAILABLE AS DYNAMIC LINKED MODULES
@@ -77,8 +76,7 @@ DYNLIBOBJS = \
 	$(DYNENTRY_OBJS)
 
 
-LIBOBJS = \
-	$(DYNLIBOBJS)
+LIBOBJS = $(DYNLIBOBJS)
 
 BINDIR   = /usr/bin
 LIBDIR   = /usr/lib
@@ -87,7 +85,11 @@ AUXDIR   = $(DATADIR)/syslinux
 INCDIR   = /usr/include
 COM32DIR = $(AUXDIR)/com32
 
-all: libcom32.c32 libcom32min.a libcom32core.a
+all: makeoutputdirs libcom32.c32 libcom32min.a libcom32core.a
+
+makeoutputdirs:
+	@mkdir -p $(foreach b, \
+		$(addprefix $(OBJ)/,$(sort $(dir $(LIBOBJS) $(MINLIBOBJS) $(CORELIBOBJS)))),$(b))
 
 libcom32.c32 : $(LIBOBJS)
 	rm -f $@
@@ -114,9 +116,9 @@ spotless: clean
 
 install: all
 	mkdir -m 755 -p $(INSTALLROOT)$(COM32DIR)
-	install -m 644 com32.ld $(INSTALLROOT)$(COM32DIR)
+	install -m 644 $(SRC)/com32.ld $(INSTALLROOT)$(COM32DIR)
 	-rm -rf $(INSTALLROOT)$(COM32DIR)/include
-	cp -r ../include $(INSTALLROOT)$(COM32DIR)
+	cp -r $(SRC)/../include $(INSTALLROOT)$(COM32DIR)
 
 # These files are performance critical, and doesn't compile well with -Os
 #FIXME: determine if drawtxt.c is really EFI-dependent
diff --git a/com32/lib/syslinux/version.c b/com32/lib/syslinux/version.c
index 1cd2efd..6f0554d 100644
--- a/com32/lib/syslinux/version.c
+++ b/com32/lib/syslinux/version.c
@@ -28,7 +28,7 @@
 #include <syslinux/config.h>
 #include <klibc/compiler.h>
 #include <core.h>
-#include <../../../version.h>
+#include <version.h>
 
 struct syslinux_version __syslinux_version;
 
diff --git a/com32/libupload/Makefile b/com32/libupload/Makefile
index 8305335..f9440c5 100644
--- a/com32/libupload/Makefile
+++ b/com32/libupload/Makefile
@@ -1,12 +1,10 @@
 # Include configuration rules
-topdir = ../..
-MAKEDIR = $(topdir)/mk
+VPATH = $(SRC)
 include $(MAKEDIR)/com32.mk
 
-REQFLAGS += -I./
+REQFLAGS += -I$(SRC)
 
-SUBDIRS := . 
-LIBOBJS := $(foreach dir,$(SUBDIRS),$(patsubst %.c,%.o,$(wildcard $(dir)/*.c)))
+LIBOBJS := $(notdir $(patsubst %.c,%.o,$(wildcard $(SRC)/*.c)))
 
 BINDIR   = /usr/bin
 LIBDIR   = /usr/lib
@@ -34,6 +32,6 @@ install: all
 	mkdir -m 755 -p $(INSTALLROOT)$(COM32DIR)
 	install -m 644 libcom32upload.a $(INSTALLROOT)$(COM32DIR)
 	mkdir -p $(INSTALLROOT)$(COM32DIR)/include/
-	cp -r *.h $(INSTALLROOT)$(COM32DIR)/include/
+	cp -r $(SRC)/*.h $(INSTALLROOT)$(COM32DIR)/include/
 
 -include .*.d */.*.d */*/.*.d
diff --git a/com32/libutil/Makefile b/com32/libutil/Makefile
index 93c0c11..535b4ab 100644
--- a/com32/libutil/Makefile
+++ b/com32/libutil/Makefile
@@ -29,8 +29,7 @@
 ## Utility companion library for the COM32 library
 ##
 
-topdir = ../..
-MAKEDIR = $(topdir)/mk
+VPATH = $(SRC)
 include $(MAKEDIR)/elf.mk
 
 LIBOBJS	   = ansiline.o ansiraw.o keyname.o \
diff --git a/com32/lua/src/Makefile b/com32/lua/src/Makefile
index 01d1f81..70a7e80 100644
--- a/com32/lua/src/Makefile
+++ b/com32/lua/src/Makefile
@@ -15,8 +15,7 @@
 ## Lua Makefile
 ##
 
-topdir = ../../..
-MAKEDIR = $(topdir)/mk
+VPATH = $(SRC)
 include $(MAKEDIR)/elf.mk
 
 LNXLIBS	   = 
diff --git a/com32/mboot/Makefile b/com32/mboot/Makefile
index 02e9f49..a3f61ba 100644
--- a/com32/mboot/Makefile
+++ b/com32/mboot/Makefile
@@ -15,11 +15,10 @@
 ## Multiboot module
 ##
 
-topdir = ../..
-MAKEDIR = $(topdir)/mk
+VPATH = $(SRC)
 include $(MAKEDIR)/elf.mk
 
-LNXLIBS	   = ../libutil/libutil_lnx.a
+LNXLIBS	   = $(objdir)/com32/libutil/libutil_lnx.a
 
 MODULES	  = mboot.c32
 TESTFILES =
diff --git a/com32/menu/Makefile b/com32/menu/Makefile
index 2096b4c..9f7a0e4 100644
--- a/com32/menu/Makefile
+++ b/com32/menu/Makefile
@@ -14,26 +14,19 @@
 ## Simple menu system
 ##
 
-topdir = ../..
-MAKEDIR = $(topdir)/mk
+VPATH = $(SRC)
 include $(MAKEDIR)/elf.mk
 
-LNXLIBS	   = ../libutil/libutil_lnx.a
+LNXLIBS	   = $(objdir)/com32/libutil/libutil_lnx.a
 
 MODULES	  = menu.c32 vesamenu.c32
 TESTFILES =
 
-COMMONOBJS = menumain.o readconfig.o passwd.o drain.o printmsg.o colors.o \
-	background.o refstr.o
+COMMONOBJS = menumain.o readconfig.o passwd.o drain.o \
+		printmsg.o colors.o background.o refstr.o
 
 all: $(MODULES) $(TESTFILES)
 
-menu.c32 : menu.o $(COMMONOBJS) $(C_LIBS)
-	$(LD) $(LDFLAGS) -o $@ $^
-
-vesamenu.c32 : vesamenu.o $(COMMONOBJS) $(C_LIBS)
-	$(LD) $(LDFLAGS) -o $@ $^
-
 vesamenu.c32: vesamenu.o $(COMMONOBJS) $(C_LIBS)
 	$(LD) $(LDFLAGS) -o $@ $^
 
diff --git a/com32/modules/Makefile b/com32/modules/Makefile
index 8f5b769..392c720 100644
--- a/com32/modules/Makefile
+++ b/com32/modules/Makefile
@@ -15,11 +15,11 @@
 ## COM32 standard modules
 ##
 
-LIBS = $(com32)/gpllib/libcom32gpl.c32 $(com32)/lib/libcom32.c32 \
-	$(com32)/libutil/libutil_com.c32
+LIBS = $(objdir)/com32/gpllib/libcom32gpl.c32 \
+	$(objdir)/com32/lib/libcom32.c32 \
+	$(objdir)/com32/libutil/libutil_com.c32
 
-topdir = ../..
-MAKEDIR = $(topdir)/mk
+VPATH = $(SRC)
 include $(MAKEDIR)/elf.mk
 
 MODULES	  = config.c32 ethersel.c32 dmitest.c32 cpuidtest.c32 \
@@ -37,7 +37,7 @@ all: $(MODULES) $(TESTFILES)
 dmitest.o: dmitest.c
 	$(CC) $(CFLAGS) $(GPLINCLUDE) -c -o $@ $<
 
-dmitest.c32 :  dmi_utils.o dmitest.o $(GPLLIB) $(LIBS) $(C_LIBS)
+dmitest.c32 : dmi_utils.o dmitest.o $(GPLLIB) $(LIBS) $(C_LIBS)
 	$(LD) $(LDFLAGS) -o $@ $^
 
 tidy dist:
diff --git a/com32/rosh/Makefile b/com32/rosh/Makefile
index 309dde4..a4c0bc2 100644
--- a/com32/rosh/Makefile
+++ b/com32/rosh/Makefile
@@ -16,10 +16,10 @@
 ## ROSH Read Only Shell
 ##
 
-LIBS = $(com32)/libutil/libutil_com.c32 $(com32)/lib/libcom32.c32
+LIBS = $(objdir)/com32/libutil/libutil_com.c32 \
+	$(objdir)/com32/lib/libcom32.c32
 
-topdir = ../..
-MAKEDIR = $(topdir)/mk
+VPATH = $(SRC)
 include $(MAKEDIR)/rosh.mk
 
 # from com32/sysdump/Makefile
diff --git a/com32/rosh/rosh.c b/com32/rosh/rosh.c
index 68dad3f..8198a2b 100644
--- a/com32/rosh/rosh.c
+++ b/com32/rosh/rosh.c
@@ -37,7 +37,7 @@
  * debugging enabled; Comment to remove.
  */
 #include "rosh.h"
-#include "../../version.h"
+#include "version.h"
 
 #define APP_LONGNAME	"Read-Only Shell"
 #define APP_NAME	"rosh"
diff --git a/com32/samples/Makefile b/com32/samples/Makefile
index c7abadd..ca04f64 100644
--- a/com32/samples/Makefile
+++ b/com32/samples/Makefile
@@ -14,17 +14,16 @@
 ## samples for syslinux users
 ##
 
-LIBS = $(com32)/libutil/libutil_com.c32
+LIBS = $(objdir)/com32/libutil/libutil_com.c32
 
-topdir = ../..
-MAKEDIR = $(topdir)/mk
+VPATH = $(SRC)
 include $(MAKEDIR)/elf.mk
 
 all:	hello.c32 resolv.c32 serialinfo.c32 \
-	localboot.c32 \
-	fancyhello.c32 fancyhello.lnx \
-	keytest.c32 keytest.lnx \
-	advdump.c32 entrydump.c32
+		localboot.c32 \
+		fancyhello.c32 fancyhello.lnx \
+		keytest.c32 keytest.lnx \
+		advdump.c32 entrydump.c32
 
 tidy dist:
 	rm -f *.o *.lo *.a *.lst *.elf .*.d *.tmp
diff --git a/com32/sysdump/Makefile b/com32/sysdump/Makefile
index 8763b3c..dca5d71 100644
--- a/com32/sysdump/Makefile
+++ b/com32/sysdump/Makefile
@@ -15,21 +15,20 @@
 ## Simple menu system
 ##
 
-topdir = ../..
-MAKEDIR = $(topdir)/mk
+VPATH = $(SRC)
 include $(MAKEDIR)/elf.mk
 -include $(topdir)/version.mk
 
-LIBS	   = ../libupload/libcom32upload.a
-LNXLIBS	   = ../libutil/libutil_lnx.a
+LIBS	   = $(objdir)/com32/libupload/libcom32upload.a
+LNXLIBS	   = $(objdir)/com32/libutil/libutil_lnx.a
 
 CFLAGS += -I$(com32) -I$(topdir)
 
 MODULES	  = sysdump.c32
 TESTFILES =
 
-SRCS = $(wildcard *.c)
-OBJS = $(patsubst %.c,%.o,$(SRCS))
+SRCS = $(wildcard $(SRC)/*.c)
+OBJS = $(subst $(SRC)/,,$(patsubst %.c,%.o,$(SRCS)))
 
 # The DATE is set on the make command line when building binaries for
 # official release.  Otherwise, substitute a hex string that is pretty much
diff --git a/com32/tools/Makefile b/com32/tools/Makefile
index 0161baf..9c0ea70 100644
--- a/com32/tools/Makefile
+++ b/com32/tools/Makefile
@@ -10,12 +10,12 @@
 ##
 ## -----------------------------------------------------------------------
 
-MAKEDIR = ../../mk
+VPATH = $(SRC)
 include $(MAKEDIR)/build.mk
 
 BINS    = relocs
 
-INCLUDES += -I./include
+INCLUDES += -I$(SRC)/include
 
 all : $(BINS)
 
diff --git a/core/Makefile b/core/Makefile
index 1f68da6..0276f31 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -15,17 +15,22 @@
 # Makefile for the SYSLINUX core
 #
 
+VPATH = $(SRC)
+
 # No builtin rules
 MAKEFLAGS += -r
 MAKE      += -r
 
-topdir = ..
-MAKEDIR = $(topdir)/mk
+ifdef EFI_BUILD
+include $(MAKEDIR)/lib.mk
+include $(MAKEDIR)/efi.mk
+else
 include $(MAKEDIR)/embedded.mk
--include $(topdir)/version.mk
+-include $(objdir)/version.mk
+endif
 
 OPTFLAGS =
-INCLUDES = -I./include -I$(com32)/include -I$(com32)/include/sys -I$(com32)/lib
+INCLUDES = -I$(SRC)/include -I$(com32)/include -I$(com32)/include/sys -I$(com32)/lib
 
 # This is very similar to cp437; technically it's for Norway and Denmark,
 # but it's unlikely the characters that are different will be used in
@@ -38,29 +43,29 @@ BTARGET  = kwdhash.gen \
 	   isolinux.bin isolinux-debug.bin pxelinux.0
 
 # All primary source files for the main syslinux files
-NASMSRC	 := $(wildcard *.asm)
-NASMHDR  := $(wildcard *.inc)
-CSRC	 := $(wildcard *.c */*.c */*/*.c)
-SSRC	 := $(wildcard *.S */*.S */*/*.S)
-CHDR	 := $(wildcard *.h */*.h */*/*.h)
+NASMSRC	 := $(wildcard $(SRC)/*.asm)
+NASMHDR  := $(wildcard $(SRC)/*.inc)
+CSRC	 := $(wildcard $(SRC)/*.c $(SRC)/*/*.c $(SRC)/*/*/*.c)
+SSRC	 := $(wildcard $(SRC)/*.S $(SRC)/*/*.S $(SRC)/*/*/*.S)
+CHDR	 := $(wildcard $(SRC)/*.h $(SRC)/*/*.h $(SRC)/*/*/*.h)
 OTHERSRC := keywords
 ALLSRC    = $(NASMSRC) $(NASMHDR) $(CSRC) $(SSRC) $(CHDR) $(OTHERSRC)
 
-COBJ	 := $(patsubst %.c,%.o,$(CSRC))
-SOBJ	 := $(patsubst %.S,%.o,$(SSRC))
+COBJ	 := $(subst $(SRC)/,,$(patsubst %.c,%.o,$(CSRC)))
+SOBJ	 := $(subst $(SRC)/,,$(patsubst %.S,%.o,$(SSRC)))
 
 # Don't include derivative-specific objects
-COBJS	 = $(filter-out rawcon.o plaincon.o pxelinux-c.o ldlinux-c.o isolinux-c.o,$(COBJ))
+COBJS	 = $(filter-out %rawcon.o %plaincon.o %pxelinux-c.o %ldlinux-c.o %isolinux-c.o,$(COBJ))
 
 LIB	 = libcom32.a
-LIBS	 = $(LIB) --whole-archive $(com32)/lib/libcom32core.a
+LIBS	 = $(LIB) --whole-archive $(objdir)/com32/lib/libcom32core.a
 LIBDEP   = $(filter-out -% %start%,$(LIBS))
 LIBOBJS  = $(COBJS) $(SOBJ)
 
 NASMDEBUG = -g -F dwarf
 NASMOPT  += $(NASMDEBUG)
 
-PREPCORE = ../lzo/prepcore
+PREPCORE = $(OBJ)/../lzo/prepcore
 
 CFLAGS += -D__SYSLINUX_CORE__
 
@@ -68,10 +73,10 @@ CFLAGS += -D__SYSLINUX_CORE__
 # official release.  Otherwise, substitute a hex string that is pretty much
 # guaranteed to be unique to be unique from build to build.
 ifndef HEXDATE
-HEXDATE := $(shell $(PERL) ../now.pl $(SRCS))
+HEXDATE := $(shell $(PERL) $(SRC)/../now.pl $(SRCS))
 endif
 ifndef DATE
-DATE    := $(shell sh ../gen-id.sh $(VERSION) $(HEXDATE))
+DATE    := $(shell sh $(SRC)/../gen-id.sh $(VERSION) $(HEXDATE))
 endif
 
 # Set up the NASM and LD options for the architecture
@@ -87,10 +92,17 @@ ifeq ($(ARCH),x86_64)
 	LD_PIE = 
 endif
 
-all: $(BTARGET) clean
+ifdef EFI_BUILD
+all: makeoutputdirs $(filter-out %bios.o,$(COBJS)) codepage.o
+else
+all: makeoutputdirs $(BTARGET)
+endif
+
+makeoutputdirs:
+	@mkdir -p $(sort $(dir $(COBJ) $(SOBJ)))
 
 kwdhash.gen: keywords genhash.pl
-	$(PERL) genhash.pl < keywords > kwdhash.gen
+	$(PERL) $(SRC)/genhash.pl < $(SRC)/keywords > $(OBJ)/kwdhash.gen
 
 .PRECIOUS: %.elf
 
@@ -98,25 +110,27 @@ kwdhash.gen: keywords genhash.pl
 	$(OBJCOPY) -O binary -S $< $(@:.bin=.raw)
 
 # GNU make 3.82 gets confused by the first form
-.PRECIOUS: %.raw
+.PRECIOUS: $(OBJ)/%.raw
 
 %.bin: %.raw $(PREPCORE)
 	$(PREPCORE) $< $@
 
-%.o: %.asm kwdhash.gen ../version.gen
+%.o: %.asm kwdhash.gen $(OBJ)/../version.gen
 	$(NASM) -f $(NASM_ELF) $(NASMOPT) -DDATE_STR="'$(DATE)'" \
 		-DHEXDATE="$(HEXDATE)" \
 		-D$(ARCH) \
-		-l $(@:.o=.lsr) -o $@ -MP -MD .$@.d $<
+		-I$(SRC)/ \
+		-l $(@:.o=.lsr) -o $@ -MP -MD $(dir $@).$(notdir $@).d $<
 
 AUXLIBS = libisolinux.a libisolinux-debug.a libldlinux.a libpxelinux.a
+LDSCRIPT = $(SRC)/$(ARCH)/syslinux.ld
 
-%.elf: %.o $(LIBDEP) $(ARCH)/syslinux.ld $(AUXLIBS)
-	$(LD) $(LDFLAGS) -Bsymbolic $(LD_PIE) -E --hash-style=gnu -T $(ARCH)/syslinux.ld -M -o $@ $< \
-		--start-group $(LIBS) lib$(patsubst %.elf,%.a,$@) --end-group \
+%.elf: %.o $(LIBDEP) $(LDSCRIPT) $(AUXLIBS)
+	$(LD) $(LDFLAGS) -Bsymbolic $(LD_PIE) -E --hash-style=gnu -T $(LDSCRIPT) -M -o $@ $< \
+		--start-group $(LIBS) $(subst $(*F).elf,lib$(*F).a,$@) --end-group \
 		> $(@:.elf=.map)
 	$(OBJDUMP) -h $@ > $(@:.elf=.sec)
-	$(PERL) lstadjust.pl $(@:.elf=.lsr) $(@:.elf=.sec) $(@:.elf=.lst)
+	$(PERL) $(SRC)/lstadjust.pl $(@:.elf=.lsr) $(@:.elf=.sec) $(@:.elf=.lst)
 
 libisolinux.a: rawcon.o isolinux-c.o
 	rm -f $@
@@ -150,7 +164,7 @@ ldlinux.bss: ldlinux.bin
 ldlinux.sys: ldlinux.bin
 	dd if=$< of=$@ bs=512 skip=2
 
-codepage.cp: ../codepage/$(CODEPAGE).cp
+codepage.cp: $(OBJ)/../codepage/$(CODEPAGE).cp
 	cp -f $< $@
 
 codepage.o: codepage.S codepage.cp
diff --git a/diag/Makefile b/diag/Makefile
index 969acbb..e335375 100644
--- a/diag/Makefile
+++ b/diag/Makefile
@@ -1,4 +1,7 @@
 SUBDIRS = mbr geodsp
 
 all tidy dist clean spotless install:
-	set -e; for d in $(SUBDIRS); do $(MAKE) -C $$d $@; done
+	@mkdir -p $(addprefix $(OBJ)/,$(SUBDIRS))
+	set -e; for d in $(SUBDIRS); \
+		do $(MAKE) -C $(OBJ)/$$d -f $(SRC)/$$d/Makefile \
+		SRC="$(SRC)"/$$d OBJ="$(OBJ)"/$$d $@; done
diff --git a/diag/geodsp/Makefile b/diag/geodsp/Makefile
index 5516085..1217c9c 100644
--- a/diag/geodsp/Makefile
+++ b/diag/geodsp/Makefile
@@ -18,15 +18,14 @@
 # Makefile for the SYSLINUX geometry display for diagnostics
 #
 
-topdir = ../..
-MAKEDIR = $(topdir)/mk
 include $(MAKEDIR)/embedded.mk
 coredir = $(topdir)/core
+VPATH = $(SRC)
 
 BTARGET = geodsp1s.bin geodspms.bin \
 	geodsp1s.img.xz geodspms.img.xz
 
-NASMOPT = -i $(coredir)/ -Ox -f bin
+NASMOPT = -i $(coredir)/ -i $(SRC)/ -Ox -f bin
 NASMOPT += -w+orphan-labels
 CFLAGS = -g -O
 
@@ -34,10 +33,10 @@ all: $(BTARGET)
 
 # Higher compression levels result in larger files
 %.img.xz: %.bin mk-lba-img.pl
-	$(PERL) mk-lba-img $< | $(XZ) -0 > $@ || ( rm -f $@ ; false )
+	$(PERL) $(SRC)/mk-lba-img $< | $(XZ) -0 > $@ || ( rm -f $@ ; false )
 
 %.img.gz: %.bin mk-lba-img.pl
-	$(PERL) mk-lba-img $< | $(GZIPPROG) -9 > $@ || ( rm -f $@ ; false )
+	$(PERL) $(SRC)/mk-lba-img $< | $(GZIPPROG) -9 > $@ || ( rm -f $@ ; false )
 
 # in case someone really wants these without needing a decompressor
 %.img: %.bin mk-lba-img.pl
diff --git a/diag/mbr/Makefile b/diag/mbr/Makefile
index f858205..5b7153c 100644
--- a/diag/mbr/Makefile
+++ b/diag/mbr/Makefile
@@ -15,10 +15,9 @@
 # Makefile for MBR
 #
 
-topdir = ../..
 mbrdir = $(topdir)/mbr
-MAKEDIR = $(topdir)/mk
 include $(MAKEDIR)/embedded.mk
+VPATH = $(SRC)
 
 all:	handoff.bin
 
diff --git a/doc/building.txt b/doc/building.txt
new file mode 100644
index 0000000..d0f5068
--- /dev/null
+++ b/doc/building.txt
@@ -0,0 +1,40 @@
+			Building Syslinux
+
+From Syslinux 6.0 onwards there is support for three different
+firmware backends, BIOS, 32-bit EFI and 64-bit EFI. To allow users the
+flexibility to build only the firmware they need the Syslinux make
+infrastructure has become more complex.
+
+The Syslinux make infrastructure understands the following syntax,
+
+	make [firmware[,firwmware]] [target[,target]]
+
+If no firmware is specified then any targets will be applied to all
+three firmware backends. If no target is specified then the 'all'
+target is implicitly built.
+
+For example, to build the installers for BIOS, 32-bit EFI and 64-bit
+EFI type,
+
+	make installer
+
+TO build the BIOS and 64-bit EFI installers type,
+
+	make bios efi64 installer
+
+To delete all object files and build the installer for 32-bit EFI
+type,
+
+	make efi32 spotless installer
+
+
+      ++++ THE OBJECT DIRECTORY ++++
+
+A custom top-level object directory can be specified on the make
+command-line by using the O= variable, e.g.
+
+	make O=/tmp/syslinux-obj efi32
+
+will build the 32-bit object files under /tmp/syslinux-obj/efi32. If
+no object directory is specified then object files will be written to
+an 'obj' directory in the top-level of the Syslinux source.
diff --git a/dos/Makefile b/dos/Makefile
index f942008..1371205 100644
--- a/dos/Makefile
+++ b/dos/Makefile
@@ -14,17 +14,17 @@
 ## MS-DOS FAT installer
 ##
 
-topdir = ..
-MAKEDIR = $(topdir)/mk
 include $(MAKEDIR)/embedded.mk
 
 CFLAGS	+= -D__MSDOS__
 # CFLAGS  += -DDEBUG
 
-LDFLAGS	 = -T dosexe.ld
+LDFLAGS	 = -T $(SRC)/dosexe.ld
 OPTFLAGS = -g
 INCLUDES = -include code16.h -nostdinc -iwithprefix include \
-	   -I. -I.. -I../libfat -I ../libinstaller -I ../libinstaller/getopt
+	   -I$(SRC) -I$(SRC)/.. -I$(SRC)/../libfat \
+	   -I $(SRC)/../libinstaller -I $(SRC)/../libinstaller/getopt \
+	   -I$(objdir)
 
 SRCS     = syslinux.c \
 	   ../libinstaller/fs.c \
@@ -34,14 +34,14 @@ SRCS     = syslinux.c \
 	   ../libinstaller/getopt/getopt_long.c \
 	   ../libinstaller/bootsect_bin.c \
 	   ../libinstaller/mbr_bin.c \
-           $(wildcard ../libfat/*.c)
+           $(wildcard $(SRC)/../libfat/*.c)
 OBJS	 = header.o crt0.o ldlinux.o \
 	   $(patsubst %.c,%.o,$(notdir $(SRCS)))
 LIBOBJS	 = int2526.o conio.o memcpy.o memset.o memmove.o skipatou.o atou.o \
 	   malloc.o free.o getopt_long.o getsetsl.o strchr.o strtoul.o \
 	   strntoumax.o argv.o printf.o __divdi3.o __udivmoddi4.o
 
-VPATH = .:../libfat:../libinstaller:../libinstaller/getopt
+VPATH = $(SRC):$(SRC)/../libfat:$(SRC)/../libinstaller:$(SRC)/../libinstaller/getopt:$(OBJ)/../libinstaller
 
 TARGETS = syslinux.com
 
@@ -74,6 +74,6 @@ syslinux.com: syslinux.elf
 %.com: %.asm
 	$(NASM) $(NASMOPT) -f bin -o $@ -MP -MD .$@.d -l $*.lst $<
 
-ldlinux.o: ldlinux.S ../core/ldlinux.sys
+ldlinux.o: ldlinux.S $(OBJ)/../core/ldlinux.sys
 
 -include .*.d *.tmp
diff --git a/dosutil/Makefile b/dosutil/Makefile
index 6bce624..9dc88d1 100644
--- a/dosutil/Makefile
+++ b/dosutil/Makefile
@@ -1,8 +1,7 @@
 #
 # OpenWatcom compile and link utility
 #
-topdir = ..
-MAKEDIR = $(topdir)/mk
+VPATH = $(SRC)
 include $(MAKEDIR)/syslinux.mk
 
 WCL	= wcl
@@ -15,6 +14,8 @@ NASMOPT = -Ox
 
 WCTARGETS = mdiskchk.com
 NSTARGETS = eltorito.sys copybs.com
+WCOBJS    = $(addprefix $(SRC)/,$(WCTARGETS))
+NSOBJS    = $(addprefix $(OBJ)/,$(NSTARGETS))
 TARGETS   = $(WCTARGETS) $(NSTARGETS)
 
 %.obj: %.c
@@ -58,4 +59,5 @@ installer: all
 
 install: installer
 	mkdir -m 755 -p $(INSTALLROOT)$(AUXDIR)/dosutil
-	install -m 644 $(TARGETS) $(INSTALLROOT)$(AUXDIR)/dosutil
+	install -m 644 $(WCOBJS) $(INSTALLROOT)$(AUXDIR)/dosutil
+	install -m 644 $(NSOBJS) $(INSTALLROOT)$(AUXDIR)/dosutil
diff --git a/efi/Makefile b/efi/Makefile
index 19c1a4d..1cb9361 100644
--- a/efi/Makefile
+++ b/efi/Makefile
@@ -10,26 +10,23 @@
 ##
 ## -----------------------------------------------------------------------
 
-topdir = ..
-MAKEDIR = $(topdir)/mk
+VPATH = $(SRC)
 include $(MAKEDIR)/lib.mk
 include $(MAKEDIR)/efi.mk
 
 CORE_CSRC := $(wildcard $(core)/*.c $(core)/*/*.c $(core)/*/*/*.c)
-CORE_COBJ := $(patsubst %.c,%.o,$(CORE_CSRC))
+CORE_COBJ := $(subst $(core),$(OBJ)/../core/,$(patsubst %.c,%.o,$(CORE_CSRC)))
 
 # Don't include console objects
-CORE_OBJS = $(filter-out $(core)/hello.o $(core)/rawcon.o \
-	$(core)/plaincon.o $(core)/strcasecmp.o $(core)/bios.o \
-	$(core)/fs/diskio_bios.o $(core)/ldlinux-c.o $(core)/isolinux-c.o \
-	$(core)/pxelinux-c.o,$(CORE_COBJ))
-LIB_OBJS = $(addprefix $(com32)/lib/,$(CORELIBOBJS))
+CORE_OBJS = $(filter-out %hello.o %rawcon.o %plaincon.o %strcasecmp.o %bios.o \
+	%diskio_bios.o %ldlinux-c.o %isolinux-c.o %pxelinux-c.o,$(CORE_COBJ))
 
-CSRC = $(wildcard *.c)
-OBJ = $(patsubst %.c,%.o,$(CSRC))
-OBJS = $(filter-out wrapper.o,$(OBJ))
+LIB_OBJS = $(addprefix $(objdir)/com32/lib/,$(CORELIBOBJS))
 
-OBJS += $(core)/codepage.o
+CSRC = $(wildcard $(SRC)/*.c)
+OBJS = $(subst $(SRC)/,,$(filter-out %wrapper.o, $(patsubst %.c,%.o,$(CSRC))))
+
+OBJS += $(objdir)/core/codepage.o
 
 # The targets to build in this directory
 BTARGET  = syslinux.efi
@@ -49,14 +46,20 @@ wrapper: wrapper.c
 #
 # Build the wrapper app and wrap our .so to produce a .efi
 syslinux.efi: syslinux.so wrapper
-	./wrapper syslinux.so $@
+	$(OBJ)/wrapper syslinux.so $@
 
 all: $(BTARGET)
 
-$(core)/codepage.o: ../codepage/cp865.cp
-	cp ../codepage/cp865.cp codepage.cp
+codepage.o: ../codepage/cp865.cp
+	cp $(objdir)/../codepage/cp865.cp codepage.cp
 	$(CC) $(SFLAGS) -c -o $@ $(core)/codepage.S
 
+installer: syslinux.efi
+
+install: all
+	mkdir -m 755 -p $(INSTALLROOT)$(AUXDIR)/efi$(BITS)
+	install -m 755 $(BTARGET) $(INSTALLROOT)$(AUXDIR)/efi$(BITS)
+
 tidy dist:
 	rm -f *.so *.o
 	find . \( -name \*.o -o -name \*.a -o -name .\*.d -o -name \*.tmp \) -print0 | \
diff --git a/extlinux/Makefile b/extlinux/Makefile
index 6cde574..b1a76a0 100644
--- a/extlinux/Makefile
+++ b/extlinux/Makefile
@@ -14,12 +14,10 @@
 ## Linux vfat, ntfs, ext2/ext3/ext4 and btrfs installer
 ##
 
-topdir = ..
-MAKEDIR = $(topdir)/mk
 include $(MAKEDIR)/syslinux.mk
 
 OPTFLAGS = -g -Os
-INCLUDES = -I. -I.. -I../libinstaller
+INCLUDES = -I$(SRC) -I$(objdir) -I$(SRC)/../libinstaller
 CFLAGS	 = $(GCCWARN) -Wno-sign-compare -D_FILE_OFFSET_BITS=64 \
 	   $(OPTFLAGS) $(INCLUDES)
 LDFLAGS	 = 
@@ -37,7 +35,7 @@ OBJS	 = $(patsubst %.c,%.o,$(notdir $(SRCS)))
 
 .SUFFIXES: .c .o .i .s .S
 
-VPATH = .:../libinstaller
+VPATH = $(SRC):$(SRC)/../libinstaller:$(OBJ)/../libinstaller
 
 all: installer
 
diff --git a/extlinux/main.c b/extlinux/main.c
index 73f3fbe..b72bee2 100644
--- a/extlinux/main.c
+++ b/extlinux/main.c
@@ -46,7 +46,7 @@
 #include "btrfs.h"
 #include "fat.h"
 #include "ntfs.h"
-#include "../version.h"
+#include "version.h"
 #include "syslxint.h"
 #include "syslxcom.h" /* common functions shared with extlinux and syslinux */
 #include "syslxfs.h"
diff --git a/gpxe/Makefile b/gpxe/Makefile
index fe754c6..d2f5e75 100644
--- a/gpxe/Makefile
+++ b/gpxe/Makefile
@@ -17,9 +17,10 @@
 # Very simple, really...
 #
 
+VPATH = $(SRC)
 TARGETS	= gpxelinux.0 gpxelinuxk.0
 
-PXEMAKE = $(MAKE) -C src NO_WERROR=1
+PXEMAKE = $(MAKE) -C $(SRC)/src NO_WERROR=1
 
 all: $(TARGETS)
 
@@ -28,7 +29,7 @@ tidy:
 clean: tidy
 
 dist:
-	$(MAKE) -C src veryclean > /dev/null 2>&1
+	$(MAKE) -C $(SRC)/src veryclean > /dev/null 2>&1
 
 #spotless: clean dist
 #Including 'dist' errors out for make ARCH=x86_64 spotless
@@ -42,14 +43,14 @@ installer:
 src/bin/blib.a:
 	$(PXEMAKE) bin/blib.a
 
-src/bin/undionly.kkpxe: src/bin/blib.a pxelinux.gpxe ../core/pxelinux.0
-	$(PXEMAKE) bin/undionly.kkpxe EMBEDDED_IMAGE=../pxelinux.gpxe,../../core/pxelinux.0
+src/bin/undionly.kkpxe: src/bin/blib.a pxelinux.gpxe $(objdir)/core/pxelinux.0
+	$(PXEMAKE) bin/undionly.kkpxe EMBEDDED_IMAGE=$(SRC)/pxelinux.gpxe,$(objdir)/core/pxelinux.0
 
 gpxelinux.0: src/bin/undionly.kkpxe
-	cp -f $< $@
+	cp -f $(SRC)/$< $@
 
-src/bin/undionly.kpxe: src/bin/blib.a pxelinuxk.gpxe ../core/pxelinux.0
-	$(PXEMAKE) bin/undionly.kpxe EMBEDDED_IMAGE=../pxelinuxk.gpxe,../../core/pxelinux.0
+src/bin/undionly.kpxe: src/bin/blib.a pxelinuxk.gpxe $(objdir)/core/pxelinux.0
+	$(PXEMAKE) bin/undionly.kpxe EMBEDDED_IMAGE=$(SRC)/pxelinuxk.gpxe,$(objdir)/core/pxelinux.0
 
 gpxelinuxk.0: src/bin/undionly.kpxe
-	cp -f $< $@
+	cp -f $(SRC)/$< $@
diff --git a/libinstaller/Makefile b/libinstaller/Makefile
index e67a468..30c3d3d 100644
--- a/libinstaller/Makefile
+++ b/libinstaller/Makefile
@@ -4,19 +4,23 @@ BINFILES = bootsect_bin.c ldlinux_bin.c \
 
 PERL	 = perl
 
-all: $(BINFILES)
+VPATH = $(SRC)
 
-bootsect_bin.c: ../core/ldlinux.bss bin2c.pl
-	$(PERL) bin2c.pl syslinux_bootsect < $< > $@
+all: installer
 
-ldlinux_bin.c: ../core/ldlinux.sys bin2c.pl
-	$(PERL) bin2c.pl syslinux_ldlinux 512 < $< > $@
+bootsect_bin.c: $(OBJ)/../core/ldlinux.bss bin2c.pl
+	$(PERL) $(SRC)/bin2c.pl syslinux_bootsect < $< > $@
 
-mbr_bin.c: ../mbr/mbr.bin bin2c.pl
-	$(PERL) bin2c.pl syslinux_mbr < $< > $@
+ldlinux_bin.c: $(OBJ)/../core/ldlinux.sys bin2c.pl
+	$(PERL) $(SRC)/bin2c.pl syslinux_ldlinux 512 < $< > $@
 
-gptmbr_bin.c: ../mbr/gptmbr.bin bin2c.pl
-	$(PERL) bin2c.pl syslinux_gptmbr < $< > $@
+mbr_bin.c: $(OBJ)/../mbr/mbr.bin bin2c.pl
+	$(PERL) $(SRC)/bin2c.pl syslinux_mbr < $< > $@
+
+gptmbr_bin.c: $(OBJ)/../mbr/gptmbr.bin bin2c.pl
+	$(PERL) $(SRC)/bin2c.pl syslinux_gptmbr < $< > $@
+
+installer: $(BINFILES)
 
 tidy:
 	rm -f $(BINFILES)
diff --git a/libinstaller/syslxopt.c b/libinstaller/syslxopt.c
index b739752..a73cd10 100644
--- a/libinstaller/syslxopt.c
+++ b/libinstaller/syslxopt.c
@@ -23,7 +23,7 @@
 #include <string.h>
 #include <getopt.h>
 #include <sysexits.h>
-#include "../version.h"
+#include "version.h"
 #include "syslxcom.h"
 #include "syslxfs.h"
 #include "syslxopt.h"
diff --git a/linux/Makefile b/linux/Makefile
index 08a3ed4..d63306a 100644
--- a/linux/Makefile
+++ b/linux/Makefile
@@ -14,12 +14,10 @@
 ## Linux FAT/NTFS installer
 ##
 
-topdir = ..
-MAKEDIR = $(topdir)/mk
 include $(MAKEDIR)/syslinux.mk
 
 OPTFLAGS = -g -Os
-INCLUDES = -I. -I.. -I../libinstaller
+INCLUDES = -I$(SRC) -I$(objdir) -I$(SRC)/../libinstaller
 CFLAGS	 = $(GCCWARN) -D_FILE_OFFSET_BITS=64 $(OPTFLAGS) $(INCLUDES)
 LDFLAGS	 = 
 
@@ -36,7 +34,7 @@ OBJS	 = $(patsubst %.c,%.o,$(notdir $(SRCS)))
 
 .SUFFIXES: .c .o .i .s .S
 
-VPATH = .:../libinstaller
+VPATH = $(SRC):$(SRC)/../libinstaller:$(OBJ)/../libinstaller
 
 all: installer
 
diff --git a/lzo/Makefile b/lzo/Makefile
index cf8f985..0c5d296 100644
--- a/lzo/Makefile
+++ b/lzo/Makefile
@@ -10,17 +10,19 @@
 ##
 ## -----------------------------------------------------------------------
 
-topdir = ..
-MAKEDIR = $(topdir)/mk
+VPATH = $(SRC)
 include $(MAKEDIR)/build.mk
 
-INCLUDES += -I./include
+INCLUDES += -I$(SRC)/include
 
-LIBOBJS = $(patsubst %.c,%.o,$(wildcard src/*.c))
+LIBOBJS = $(patsubst %.c,%.o,$(subst $(SRC)/,,$(wildcard $(SRC)/src/*.c)))
 LIB     = lzo.a
 BINS    = prepcore
 
-all : $(BINS)
+all : makeoutputdirs $(BINS)
+
+makeoutputdirs:
+	@mkdir -p $(OBJ)/src
 
 $(LIB) : $(LIBOBJS)
 	rm -f $@
diff --git a/mbr/Makefile b/mbr/Makefile
index 8b46452..be2bded 100644
--- a/mbr/Makefile
+++ b/mbr/Makefile
@@ -15,8 +15,8 @@
 # Makefile for MBR
 #
 
-topdir = ..
-MAKEDIR = $(topdir)/mk
+VPATH = $(SRC)
+
 include $(MAKEDIR)/embedded.mk
 
 all:	mbr.bin   altmbr.bin   gptmbr.bin   isohdpfx.bin   isohdppx.bin \
@@ -34,16 +34,18 @@ all:	mbr.bin   altmbr.bin   gptmbr.bin   isohdpfx.bin   isohdppx.bin \
 
 .PRECIOUS: %.elf
 #%.elf: %.o mbr.ld
-%.elf: %.o $(ARCH)/mbr.ld
-	$(LD) $(LDFLAGS) -T $(ARCH)/mbr.ld -e _start -o $@ $<
+%.elf: %.o $(SRC)/$(ARCH)/mbr.ld
+	$(LD) $(LDFLAGS) -T $(SRC)/$(ARCH)/mbr.ld -e _start -o $@ $<
 
-%.bin: %.elf checksize.pl
+%.bin: %.elf $(SRC)/checksize.pl
 	$(OBJCOPY) -O binary $< $@
-	$(PERL) checksize.pl $@
+	$(PERL) $(SRC)/checksize.pl $@
 	$(CHMOD) -x $@
 
 mbr_bin.c: mbr.bin
 
+install:
+
 tidy dist:
 	rm -f *.o *.elf *.lst .*.d
 
diff --git a/memdisk/Makefile b/memdisk/Makefile
index 3668997..4ae0855 100644
--- a/memdisk/Makefile
+++ b/memdisk/Makefile
@@ -11,29 +11,28 @@
 ##
 ## -----------------------------------------------------------------------
 
-topdir = ..
-MAKEDIR = $(topdir)/mk
 include $(MAKEDIR)/embedded.mk
 -include $(topdir)/version.mk
 
-INCLUDES = -I$(topdir)/com32/include
+INCLUDES = -I$(topdir)/com32/include -I$(objdir)
 CFLAGS  += -D__MEMDISK__ -DDATE='"$(DATE)"'
 LDFLAGS  = $(GCCOPT) -g
 NASM     = nasm
 NASMOPT  = -Ox
 NFLAGS   = -dDATE='"$(DATE)"'
-NINCLUDE =
+NINCLUDE = -I$(SRC)/
 
+VPATH = $(SRC)
 SRCS	 = $(wildcard *.asm *.c *.h)
 
 # The DATE is set on the make command line when building binaries for
 # official release.  Otherwise, substitute a hex string that is pretty much
 # guaranteed to be unique to be unique from build to build.
 ifndef HEXDATE
-HEXDATE := $(shell $(PERL) ../now.pl $(SRCS))
+HEXDATE := $(shell $(PERL) $(SRC)/../now.pl $(SRCS))
 endif
 ifndef DATE
-DATE    := $(shell sh ../gen-id.sh $(VERSION) $(HEXDATE))
+DATE    := $(shell sh $(SRC)/../gen-id.sh $(VERSION) $(HEXDATE))
 endif
 
 # Important: init.o16 must be first!!
@@ -92,7 +91,7 @@ memdisk32.elf: $(ARCH)/memdisk.ld $(OBJS32)
 	$(OBJCOPY) -O binary $< $@
 
 memdisk: memdisk16.bin memdisk32.bin postprocess.pl
-	$(PERL) postprocess.pl $@ memdisk16.bin memdisk32.bin
+	$(PERL) $(SRC)/postprocess.pl $@ memdisk16.bin memdisk32.bin
 
 e820test: e820test.c e820func.c msetup.c
 	$(CC) -m32 -g $(GCCWARN) -DTEST -o $@ $^
diff --git a/memdisk/setup.c b/memdisk/setup.c
index b6093b7..72c6785 100644
--- a/memdisk/setup.c
+++ b/memdisk/setup.c
@@ -22,7 +22,7 @@
 #include "conio.h"
 #include "version.h"
 #include "memdisk.h"
-#include "../version.h"
+#include <version.h>
 
 const char memdisk_version[] = "MEMDISK " VERSION_STR " " DATE;
 const char copyright[] =
diff --git a/memdump/Makefile b/memdump/Makefile
index 6a30431..e5c2796 100644
--- a/memdump/Makefile
+++ b/memdump/Makefile
@@ -14,13 +14,12 @@
 ## memory dump utility
 ##
 
-topdir = ..
-MAKEDIR = $(topdir)/mk
+VPATH = $(SRC)
 include $(MAKEDIR)/embedded.mk
 
 OPTFLAGS = 
-INCLUDES = -include code16.h -I.
-LDFLAGS	 = -T com16.ld
+INCLUDES = -include $(SRC)/code16.h -I$(SRC)
+LDFLAGS	 = -T $(SRC)/com16.ld
 
 SRCS     = main.c serial.c ymsend.c srecsend.c
 OBJS	 = crt0.o $(patsubst %.c,%.o,$(notdir $(SRCS)))
diff --git a/mk/efi.mk b/mk/efi.mk
index c3c4ca4..db70ec8 100644
--- a/mk/efi.mk
+++ b/mk/efi.mk
@@ -40,7 +40,7 @@ CFLAGS = -I$(EFIINC) -I$(EFIINC)/$(EFI_SUBARCH) \
 CRT0 := $(shell find $(LIBDIR) -name crt0-efi-$(EFI_SUBARCH).o 2>/dev/null | tail -n1)
 LDSCRIPT := $(shell find $(LIBDIR) -name elf_$(EFI_SUBARCH)_efi.lds 2>/dev/null | tail -n1)
 
-LDFLAGS = -T $(ARCH)/syslinux.ld -Bsymbolic -pie -nostdlib -znocombreloc \
+LDFLAGS = -T $(SRC)/$(ARCH)/syslinux.ld -Bsymbolic -pie -nostdlib -znocombreloc \
 		-L$(LIBDIR) --hash-style=gnu -m elf_$(ARCH) $(CRT0) -E
 
 SFLAGS     = $(GCCOPT) $(GCCWARN) $(SARCHOPT) \
diff --git a/mk/elf.mk b/mk/elf.mk
index 2999f5a..1cb3254 100644
--- a/mk/elf.mk
+++ b/mk/elf.mk
@@ -47,7 +47,7 @@ com32 = $(topdir)/com32
 core = $(topdir)/core
 
 ifneq ($(NOGPL),1)
-GPLLIB     = $(com32)/gpllib/libcom32gpl.c32
+GPLLIB     = $(objdir)/com32/gpllib/libcom32gpl.c32
 GPLINCLUDE = -I$(com32)/gplinclude
 else
 GPLLIB     =
@@ -58,7 +58,8 @@ CFLAGS     = $(GCCOPT) -W -Wall \
 	     -fomit-frame-pointer -D__COM32__ -DDYNAMIC_MODULE \
 	     -nostdinc -iwithprefix include \
 	     -I$(com32)/libutil/include -I$(com32)/include \
-		-I$(com32)/include/sys $(GPLINCLUDE) -I$(core)/include
+		-I$(com32)/include/sys $(GPLINCLUDE) -I$(core)/include \
+		-I$(objdir)
 SFLAGS     = $(GCCOPT) -D__COM32__ 
 LDFLAGS    = -m elf_$(ARCH) -shared --hash-style=gnu -T $(com32)/lib/$(ARCH)/elf.ld --as-needed
 LIBGCC    := $(shell $(CC) $(GCCOPT) --print-libgcc)
@@ -67,10 +68,10 @@ LNXCFLAGS  = -I$(com32)/libutil/include -W -Wall -O -g -D_GNU_SOURCE
 LNXSFLAGS  = -g
 LNXLDFLAGS = -g
 
-C_LIBS	   = $(com32)/libutil/libutil_com.c32 $(GPLLIB) \
-	     $(com32)/lib/libcom32.c32
-C_LNXLIBS  = $(com32)/libutil/libutil_lnx.a \
-	     $(com32)/elflink/ldlinux/ldlinux_lnx.a
+C_LIBS	   = $(objdir)/com32/libutil/libutil_com.c32 $(GPLLIB) \
+	     $(objdir)/com32/lib/libcom32.c32
+C_LNXLIBS  = $(objdir)/com32/libutil/libutil_lnx.a \
+	     $(objdir)/com32/elflink/ldlinux/ldlinux_lnx.a
 
 .SUFFIXES: .lss .c .o
 
diff --git a/mk/lib.mk b/mk/lib.mk
index d315e11..b37d0dc 100644
--- a/mk/lib.mk
+++ b/mk/lib.mk
@@ -29,7 +29,7 @@ GCCOPT += $(call gcc_ok,-falign-jumps=0,-malign-jumps=0)
 GCCOPT += $(call gcc_ok,-falign-labels=0,-malign-labels=0)
 GCCOPT += $(call gcc_ok,-falign-loops=0,-malign-loops=0)
 
-INCLUDE	= -I.
+INCLUDE	= -I$(SRC)
 STRIP	= strip --strip-all -R .comment -R .note
 
 # zlib and libpng configuration flags
@@ -44,9 +44,10 @@ LIBFLAGS = -DDYNAMIC_CRC_TABLE -DPNG_NO_CONSOLE_IO \
 # LIBFLAGS += -DPNG_NO_FLOATING_POINT_SUPPORTED
 
 REQFLAGS  = $(GCCOPT) -g -D__COM32__ \
-	    -nostdinc -iwithprefix include -I. -I./sys -I../include \
-	    -I../include/sys -I../../core/include -I$(com32)/lib/ \
-	    -I$(com32)/lib/sys/module
+	    -nostdinc -iwithprefix include -I. -I$(SRC)/sys \
+	    -I$(SRC)/../include -I$(com32)/include/sys \
+	    -I$(topdir)/core/include -I$(com32)/lib/ \
+	    -I$(com32)/lib/sys/module -I$(OBJ)/../..
 OPTFLAGS  = -Os -march=$(MARCH) -falign-functions=0 -falign-jumps=0 \
 	    -falign-labels=0 -ffast-math -fomit-frame-pointer
 WARNFLAGS = $(GCCWARN) -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Winline
@@ -64,6 +65,7 @@ REQFLAGS += $(EFIINC)
 endif
 CFLAGS  = $(OPTFLAGS) $(REQFLAGS) $(WARNFLAGS) $(LIBFLAGS)
 
+VPATH = $(SRC)
 LIBOTHER_OBJS = \
 	atoi.o atol.o atoll.o calloc.o creat.o		\
 	fgets.o fprintf.o fputc.o	\
@@ -181,13 +183,13 @@ LIBZLIB_OBJS = \
 	sys/zfile.o sys/zfopen.o
 
 MINLIBOBJS = \
-	syslinux/ipappend.o \
+	$(addprefix $(OBJ)/,syslinux/ipappend.o \
 	syslinux/dsinfo.o \
 	$(LIBOTHER_OBJS) \
 	$(LIBGCC_OBJS) \
 	$(LIBCONSOLE_OBJS) \
 	$(LIBLOAD_OBJS) \
-	$(LIBZLIB_OBJS)
+	$(LIBZLIB_OBJS))
 #	$(LIBVESA_OBJS)
 
 CORELIBOBJS = \
@@ -214,16 +216,16 @@ LDFLAGS	= -m elf_$(ARCH) --hash-style=gnu -T $(com32)/lib/$(ARCH)/elf.ld
 
 % : %.S
 
-.c.o:
+%.o: %.c
 	$(CC) $(MAKEDEPS) $(CFLAGS) -c -o $@ $<
 
 .c.i:
 	$(CC) $(MAKEDEPS) $(CFLAGS) -E -o $@ $<
 
-.c.s:
+%.s: %.c
 	$(CC) $(MAKEDEPS) $(CFLAGS) -S -o $@ $<
 
-.S.o:
+%.o: %.S
 	$(CC) $(MAKEDEPS) $(CFLAGS) -D__ASSEMBLY__ -c -o $@ $<
 
 .S.s:
@@ -235,7 +237,7 @@ LDFLAGS	= -m elf_$(ARCH) --hash-style=gnu -T $(com32)/lib/$(ARCH)/elf.ld
 .S.ls:
 	$(CC) $(MAKEDEPS) $(CFLAGS) $(SOFLAGS) -D__ASSEMBLY__ -E -o $@ $<
 
-.s.o:
+%(OBJ)/%.o: $(SRC)/%.s
 	$(CC) $(MAKEDEPS) $(CFLAGS) -x assembler -c -o $@ $<
 
 .ls.lo:
diff --git a/modules/Makefile b/modules/Makefile
index f878c70..e985af4 100644
--- a/modules/Makefile
+++ b/modules/Makefile
@@ -14,11 +14,11 @@
 ## Non-COM32 simple Syslinux modules
 ##
 
-topdir = ..
-MAKEDIR = $(topdir)/mk
+VPATH = $(SRC)
 include $(MAKEDIR)/embedded.mk
 
 INCLUDES   = -I$(com32)/include
+NASMOPT = -I$(SRC)/ -I$(SRC)/../core/
 
 BINS = pxechain.com poweroff.com int18.com ver.com
 
diff --git a/mtools/Makefile b/mtools/Makefile
index 78cea1e..3544388 100755
--- a/mtools/Makefile
+++ b/mtools/Makefile
@@ -1,9 +1,7 @@
-topdir = ..
-MAKEDIR = $(topdir)/mk
 include $(MAKEDIR)/syslinux.mk
 
 OPTFLAGS = -g -Os
-INCLUDES = -I. -I.. -I../libfat -I../libinstaller
+INCLUDES = -I$(SRC) -I$(objdir) -I$(SRC)/../libfat -I$(SRC)/../libinstaller
 CFLAGS	 = $(GCCWARN) -D_FILE_OFFSET_BITS=64 $(OPTFLAGS) $(INCLUDES)
 LDFLAGS	 = 
 
@@ -14,12 +12,12 @@ SRCS     = syslinux.c \
 	   ../libinstaller/setadv.c \
 	   ../libinstaller/bootsect_bin.c \
 	   ../libinstaller/ldlinux_bin.c \
-	   $(wildcard ../libfat/*.c)
+	   $(wildcard $(SRC)/../libfat/*.c)
 OBJS	 = $(patsubst %.c,%.o,$(notdir $(SRCS)))
 
 .SUFFIXES: .c .o .i .s .S
 
-VPATH = .:../libfat:../libinstaller
+VPATH = $(SRC):$(SRC)/../libfat:$(SRC)/../libinstaller:$(OBJ)/../libinstaller
 
 all: installer
 
diff --git a/sample/Makefile b/sample/Makefile
index 9e504d9..1515a06 100644
--- a/sample/Makefile
+++ b/sample/Makefile
@@ -14,9 +14,8 @@
 ## samples for syslinux users
 ##
 
-topdir = ..
-MAKEDIR = $(topdir)/mk
 include $(MAKEDIR)/embedded.mk
+VPATH = $(SRC)
 
 PPMTOLSS16 = $(topdir)/utils/ppmtolss16
 
diff --git a/utils/Makefile b/utils/Makefile
index be73993..dfe6259 100644
--- a/utils/Makefile
+++ b/utils/Makefile
@@ -14,23 +14,23 @@
 # SYSLINUX utilities
 #
 
-topdir = ..
-MAKEDIR = $(topdir)/mk
+VPATH = $(SRC)
 include $(MAKEDIR)/syslinux.mk
 
-CFLAGS   = $(GCCWARN) -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64
+CFLAGS   = $(GCCWARN) -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I$(SRC)
 LDFLAGS  = -O2
 
 C_TARGETS	 = isohybrid gethostip memdiskfind
 SCRIPT_TARGETS	 = mkdiskimage
 SCRIPT_TARGETS	+= isohybrid.pl  # about to be obsoleted
-ASIS		 = keytab-lilo lss16toppm md5pass ppmtolss16 sha1pass \
-		   syslinux2ansi pxelinux-options
+ASIS		 = $(addprefix $(SRC)/,keytab-lilo lss16toppm md5pass \
+		   ppmtolss16 sha1pass syslinux2ansi pxelinux-options)
 
 TARGETS = $(C_TARGETS) $(SCRIPT_TARGETS)
 
-ISOHDPFX = ../mbr/isohdpfx.bin ../mbr/isohdpfx_f.bin ../mbr/isohdpfx_c.bin \
-	   ../mbr/isohdppx.bin ../mbr/isohdppx_f.bin ../mbr/isohdppx_c.bin
+ISOHDPFX = $(addprefix $(OBJ)/,../mbr/isohdpfx.bin ../mbr/isohdpfx_f.bin \
+	   ../mbr/isohdpfx_c.bin \
+	   ../mbr/isohdppx.bin ../mbr/isohdppx_f.bin ../mbr/isohdppx_c.bin)
 
 all: $(TARGETS)
 
@@ -38,17 +38,17 @@ all: $(TARGETS)
 	$(CC) $(UMAKEDEPS) $(CFLAGS) -c -o $@ $<
 
 mkdiskimage: mkdiskimage.in ../mbr/mbr.bin bin2hex.pl
-	$(PERL) bin2hex.pl < ../mbr/mbr.bin | cat mkdiskimage.in - > $@
+	$(PERL) $(SRC)/bin2hex.pl < $(OBJ)/../mbr/mbr.bin | cat $(SRC)/mkdiskimage.in - > $@
 	chmod a+x $@
 
 # Works on anything with a Perl interpreter...
 isohybrid.pl: isohybrid.in $(ISOHDPFX) bin2hex.pl
-	cp -f isohybrid.in $@
-	for f in $(ISOHDPFX) ; do $(PERL) bin2hex.pl < $$f >> $@ ; done
+	cp -f $(SRC)/isohybrid.in $@
+	for f in $(ISOHDPFX) ; do $(PERL) $(SRC)/bin2hex.pl < $$f >> $@ ; done
 	chmod a+x $@
 
 isohdpfx.c: $(ISOHDPFX) isohdpfxarray.pl
-	$(PERL) isohdpfxarray.pl $(ISOHDPFX) > $@
+	$(PERL) $(SRC)/isohdpfxarray.pl $(ISOHDPFX) > $@
 
 isohybrid: isohybrid.o isohdpfx.o
 	$(CC) $(LDFLAGS) -o $@ $^ -luuid
diff --git a/win32/Makefile b/win32/Makefile
index f960998..943a966 100644
--- a/win32/Makefile
+++ b/win32/Makefile
@@ -29,21 +29,22 @@ else
 ifeq ($(findstring MINGW32,$(OSTYPE)),MINGW32)
 WINPREFIX  :=
 else
-WINPREFIX  := $(shell ./find-mingw32.sh gcc)
+WINPREFIX  := $(shell $(SRC)/find-mingw32.sh gcc)
 endif
 WINCFLAGS  := $(GCCWARN) -Wno-sign-compare -Os -fomit-frame-pointer \
 	      -D_FILE_OFFSET_BITS=64
 WINLDFLAGS := -Os -s
 endif
-WINCFLAGS += -I. -I../win -I.. -I../libfat -I../libinstaller \
-	     -I../libinstaller/getopt
+WINCFLAGS += -I$(SRC) -I$(SRC)/../win -I$(objdir) \
+	     -I$(SRC)/../libfat -I$(SRC)/../libinstaller \
+	     -I$(SRC)/../libinstaller/getopt
 
 WINCC      := $(WINPREFIX)gcc
 WINAR	   := $(WINPREFIX)ar
 WINRANLIB  := $(WINPREFIX)ranlib
 
 WINCC_IS_GOOD := $(shell $(WINCC) $(WINCFLAGS) $(WINLDFLAGS) \
-	-o hello.exe ../win/hello.c >/dev/null 2>&1 ; echo $$?)
+	-o hello.exe $(SRC)/../win/hello.c >/dev/null 2>&1 ; echo $$?)
 
 .SUFFIXES: .c .obj .lib .exe .i .s .S
 
@@ -57,12 +58,12 @@ LIBSRC   = ../libinstaller/fs.c \
 	   ../libinstaller/bootsect_bin.c \
 	   ../libinstaller/ldlinux_bin.c \
 	   ../libinstaller/mbr_bin.c \
-	   $(wildcard ../libfat/*.c)
+	   $(wildcard $(SRC)/../libfat/*.c)
 LIBOBJS  = $(patsubst %.c,%.obj,$(notdir $(LIBSRC)))
 
 LIB	 = syslinux.lib
 
-VPATH = .:../win:../libfat:../libinstaller:../libinstaller/getopt
+VPATH = $(SRC):$(SRC)/../win:$(SRC)/../libfat:$(SRC)/../libinstaller:$(SRC)/../libinstaller/getopt:$(OBJ)/../libinstaller
 
 TARGETS = syslinux.exe
 
diff --git a/win64/Makefile b/win64/Makefile
index fe60793..f28570a 100644
--- a/win64/Makefile
+++ b/win64/Makefile
@@ -20,20 +20,21 @@
 
 OSTYPE   = $(shell uname -msr)
 # Don't know how to do a native compile here...
-WINPREFIX  := $(shell ./find-mingw64.sh gcc)
+WINPREFIX  := $(shell $(SRC)/find-mingw64.sh gcc)
 WINCFLAGS  := $(GCCWARN) -Wno-sign-compare -Os -fomit-frame-pointer \
 	      -D_FILE_OFFSET_BITS=64
 WINLDFLAGS := -Os -s
 
-WINCFLAGS += -I. -I../win -I.. -I../libfat -I../libinstaller \
-	     -I../libinstaller/getopt
+WINCFLAGS += -I$(SRC) -I$(SRC)/../win -I$(objdir) \
+	     -I$(SRC)/../libfat -I$(SRC)/../libinstaller \
+	     -I$(SRC)/../libinstaller/getopt
 
 WINCC      := $(WINPREFIX)gcc
 WINAR	   := $(WINPREFIX)ar
 WINRANLIB  := $(WINPREFIX)ranlib
 
 WINCC_IS_GOOD := $(shell $(WINCC) $(WINCFLAGS) $(WINLDFLAGS) \
-	-o hello.exe ../win/hello.c >/dev/null 2>&1 ; echo $$?)
+	-o hello.exe $(SRC)/../win/hello.c >/dev/null 2>&1 ; echo $$?)
 
 .SUFFIXES: .c .obj .lib .exe .i .s .S
 
@@ -47,12 +48,12 @@ LIBSRC   = ../libinstaller/fs.c \
 	   ../libinstaller/bootsect_bin.c \
 	   ../libinstaller/ldlinux_bin.c \
 	   ../libinstaller/mbr_bin.c \
-	   $(wildcard ../libfat/*.c)
+	   $(wildcard $(SRC)/../libfat/*.c)
 LIBOBJS  = $(patsubst %.c,%.obj,$(notdir $(LIBSRC)))
 
 LIB	 = syslinux.lib
 
-VPATH = .:../win:../libfat:../libinstaller:../libinstaller/getopt
+VPATH = $(SRC):$(SRC)/../win:$(SRC)/../libfat:$(SRC)/../libinstaller:$(SRC)/../libinstaller/getopt:$(OBJ)/../libinstaller
 
 TARGETS = syslinux64.exe
 


More information about the Syslinux-commits mailing list