support out-of-tree build
authorPetr Hosek <phosek@chromium.org>
Wed, 18 Nov 2015 20:07:32 +0000 (12:07 -0800)
committerRich Felker <dalias@aerifal.cx>
Sun, 17 Jan 2016 21:34:43 +0000 (16:34 -0500)
this change adds support for building musl outside of the source
tree. the implementation is similar to autotools where running
configure in a different directory creates config.mak in the current
working directory and symlinks the makefile, which contains the
logic for creating all necessary directories and resolving paths
relative to the source directory.

to support both in-tree and out-of-tree builds with implicit make
rules, all object files are now placed into a separate directory.

.gitignore
Makefile
configure

index c5d5c4628d598954e667c75308db0bcb8e58e114..2cb88d4c699ddced66d0d84f166c45b223d76e24 100644 (file)
@@ -5,9 +5,6 @@
 *.so.1
 arch/*/bits/alltypes.h
 config.mak
-include/bits
-tools/musl-gcc
-tools/musl-clang
-tools/ld.musl-clang
 lib/musl-gcc.specs
 src/internal/version.h
+/obj/
index df20f94a5c7129c34e92acf57310497eeedff9d7..44b39b9527d5334f18f49e107c20983864356b45 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -8,6 +8,7 @@
 # Do not make changes here.
 #
 
+srcdir = .
 exec_prefix = /usr/local
 bindir = $(exec_prefix)/bin
 
@@ -16,12 +17,16 @@ includedir = $(prefix)/include
 libdir = $(prefix)/lib
 syslibdir = /lib
 
-SRCS = $(sort $(wildcard src/*/*.c arch/$(ARCH)/src/*.c))
-OBJS = $(SRCS:.c=.o)
+BASE_SRCS = $(sort $(wildcard $(srcdir)/src/*/*.c $(srcdir)/arch/$(ARCH)/src/*.c))
+BASE_OBJS = $(patsubst $(srcdir)/%.c,%.o,$(BASE_SRCS))
+ARCH_SRCS = $(wildcard $(srcdir)/src/*/$(ARCH)/*.s $(srcdir)/src/*/$(ARCH)$(ASMSUBARCH)/*.sub)
+ARCH_OBJS = $(patsubst $(srcdir)/%.sub,%.o,$(patsubst $(srcdir)/%.s,%.o,$(ARCH_SRCS)))
+REPLACED_OBJS = $(sort $(subst /$(ARCH)$(ASMSUBARCH)/,/,$(subst /$(ARCH)/,/,$(ARCH_OBJS))) $(subst /$(ARCH)$(ASMSUBARCH)/,/$(ARCH)/,$(subst /$(ARCH)/,/,$(ARCH_OBJS))))
+OBJS = $(addprefix obj/, $(filter-out $(REPLACED_OBJS), $(sort $(BASE_OBJS) $(ARCH_OBJS))))
 LOBJS = $(OBJS:.o=.lo)
-GENH = include/bits/alltypes.h
-GENH_INT = src/internal/version.h
-IMPH = src/internal/stdio_impl.h src/internal/pthread_impl.h src/internal/libc.h
+GENH = obj/include/bits/alltypes.h
+GENH_INT = obj/src/internal/version.h
+IMPH = $(addprefix $(srcdir)/, src/internal/stdio_impl.h src/internal/pthread_impl.h src/internal/libc.h)
 
 LDFLAGS =
 LDFLAGS_AUTO =
@@ -32,7 +37,7 @@ CFLAGS_AUTO = -Os -pipe
 CFLAGS_C99FSE = -std=c99 -ffreestanding -nostdinc 
 
 CFLAGS_ALL = $(CFLAGS_C99FSE)
-CFLAGS_ALL += -D_XOPEN_SOURCE=700 -I./arch/$(ARCH) -I./src/internal -I./include
+CFLAGS_ALL += -D_XOPEN_SOURCE=700 -I$(srcdir)/arch/$(ARCH) -Iobj/src/internal -I$(srcdir)/src/internal -Iobj/include -I$(srcdir)/include
 CFLAGS_ALL += $(CPPFLAGS) $(CFLAGS_AUTO) $(CFLAGS)
 CFLAGS_ALL_STATIC = $(CFLAGS_ALL)
 CFLAGS_ALL_SHARED = $(CFLAGS_ALL) -fPIC -DSHARED
@@ -41,10 +46,11 @@ LDFLAGS_ALL = $(LDFLAGS_AUTO) $(LDFLAGS)
 
 AR      = $(CROSS_COMPILE)ar
 RANLIB  = $(CROSS_COMPILE)ranlib
-INSTALL = ./tools/install.sh
+INSTALL = $(srcdir)/tools/install.sh
 
-ARCH_INCLUDES = $(wildcard arch/$(ARCH)/bits/*.h)
-ALL_INCLUDES = $(sort $(wildcard include/*.h include/*/*.h) $(GENH) $(ARCH_INCLUDES:arch/$(ARCH)/%=include/%))
+ARCH_INCLUDES = $(wildcard $(srcdir)/arch/$(ARCH)/bits/*.h)
+INCLUDES = $(wildcard $(srcdir)/include/*.h $(srcdir)/include/*/*.h)
+ALL_INCLUDES = $(sort $(INCLUDES:$(srcdir)/%=%) $(GENH:obj/%=%) $(ARCH_INCLUDES:$(srcdir)/arch/$(ARCH)/%=include/%))
 
 EMPTY_LIB_NAMES = m rt pthread crypt util xnet resolv dl
 EMPTY_LIBS = $(EMPTY_LIB_NAMES:%=lib/lib%.a)
@@ -53,7 +59,7 @@ STATIC_LIBS = lib/libc.a
 SHARED_LIBS = lib/libc.so
 TOOL_LIBS = lib/musl-gcc.specs
 ALL_LIBS = $(CRT_LIBS) $(STATIC_LIBS) $(SHARED_LIBS) $(EMPTY_LIBS) $(TOOL_LIBS)
-ALL_TOOLS = tools/musl-gcc
+ALL_TOOLS = obj/musl-gcc
 
 WRAPCC_GCC = gcc
 WRAPCC_CLANG = clang
@@ -62,91 +68,100 @@ LDSO_PATHNAME = $(syslibdir)/ld-musl-$(ARCH)$(SUBARCH).so.1
 
 -include config.mak
 
+ifeq ($(ARCH),)
+$(error Please set ARCH in config.mak before running make.)
+endif
+
 all: $(ALL_LIBS) $(ALL_TOOLS)
 
+OBJ_DIRS = $(sort $(patsubst %/,%,$(dir $(ALL_LIBS) $(ALL_TOOLS) $(OBJS) $(GENH) $(GENH_INT))) $(addprefix obj/, crt crt/$(ARCH) include))
+
+$(ALL_LIBS) $(ALL_TOOLS) $(CRT_LIBS:lib/%=obj/crt/%) $(OBJS) $(LOBJS) $(GENH) $(GENH_INT): | $(OBJ_DIRS)
+
+$(OBJ_DIRS):
+       mkdir -p $@
+
 install: install-libs install-headers install-tools
 
 clean:
-       rm -f crt/*.o
+       rm -f obj/crt/*.o obj/crt/$(ARCH)/*.o
        rm -f $(OBJS)
        rm -f $(LOBJS)
        rm -f $(ALL_LIBS) lib/*.[ao] lib/*.so
        rm -f $(ALL_TOOLS)
        rm -f $(GENH) $(GENH_INT)
-       rm -f include/bits
+       rm -f obj/include/bits/alltypes.h
 
 distclean: clean
        rm -f config.mak
 
-include/bits:
-       @test "$(ARCH)" || { echo "Please set ARCH in config.mak before running make." ; exit 1 ; }
-       ln -sf ../arch/$(ARCH)/bits $@
+obj/include/bits/alltypes.h: $(srcdir)/arch/$(ARCH)/bits/alltypes.h.in $(srcdir)/include/alltypes.h.in $(srcdir)/tools/mkalltypes.sed
+       sed -f $(srcdir)/tools/mkalltypes.sed $(srcdir)/arch/$(ARCH)/bits/alltypes.h.in $(srcdir)/include/alltypes.h.in > $@
 
-include/bits/alltypes.h.in: include/bits
+obj/src/internal/version.h: $(wildcard $(srcdir)/VERSION $(srcdir)/.git)
+       printf '#define VERSION "%s"\n' "$$(cd $(srcdir); sh tools/version.sh)" > $@
 
-include/bits/alltypes.h: include/bits/alltypes.h.in include/alltypes.h.in tools/mkalltypes.sed
-       sed -f tools/mkalltypes.sed include/bits/alltypes.h.in include/alltypes.h.in > $@
+obj/src/internal/version.o obj/src/internal/version.lo: obj/src/internal/version.h
 
-src/internal/version.h: $(wildcard VERSION .git)
-       printf '#define VERSION "%s"\n' "$$(sh tools/version.sh)" > $@
+obj/crt/rcrt1.o obj/src/ldso/dlstart.lo obj/src/ldso/dynlink.lo: $(srcdir)/src/internal/dynlink.h $(srcdir)/arch/$(ARCH)/reloc.h
 
-src/internal/version.o src/internal/version.lo: src/internal/version.h
+obj/crt/crt1.o obj/crt/scrt1.o obj/crt/rcrt1.o obj/src/ldso/dlstart.lo: $(srcdir)/arch/$(ARCH)/crt_arch.h
 
-crt/rcrt1.o src/ldso/dlstart.lo src/ldso/dynlink.lo: src/internal/dynlink.h arch/$(ARCH)/reloc.h
+obj/crt/rcrt1.o: $(srcdir)/src/ldso/dlstart.c
 
-crt/crt1.o crt/Scrt1.o crt/rcrt1.o src/ldso/dlstart.lo: $(wildcard arch/$(ARCH)/crt_arch.h)
+obj/crt/Scrt1.o obj/crt/rcrt1.o: CFLAGS_ALL += -fPIC
 
-crt/rcrt1.o: src/ldso/dlstart.c
+obj/crt/$(ARCH)/crti.o: $(srcdir)/crt/$(ARCH)/crti.s
 
-crt/Scrt1.o crt/rcrt1.o: CFLAGS_ALL += -fPIC
+obj/crt/$(ARCH)/crtn.o: $(srcdir)/crt/$(ARCH)/crtn.s
 
-OPTIMIZE_SRCS = $(wildcard $(OPTIMIZE_GLOBS:%=src/%))
-$(OPTIMIZE_SRCS:%.c=%.o) $(OPTIMIZE_SRCS:%.c=%.lo): CFLAGS += -O3
+OPTIMIZE_SRCS = $(wildcard $(OPTIMIZE_GLOBS:%=$(srcdir)/src/%))
+$(OPTIMIZE_SRCS:$(srcdir)/%.c=obj/%.o) $(OPTIMIZE_SRCS:$(srcdir)/%.c=obj/%.lo): CFLAGS += -O3
 
 MEMOPS_SRCS = src/string/memcpy.c src/string/memmove.c src/string/memcmp.c src/string/memset.c
-$(MEMOPS_SRCS:%.c=%.o) $(MEMOPS_SRCS:%.c=%.lo): CFLAGS_ALL += $(CFLAGS_MEMOPS)
+$(MEMOPS_SRCS:%.c=obj/%.o) $(MEMOPS_SRCS:%.c=obj/%.lo): CFLAGS_ALL += $(CFLAGS_MEMOPS)
 
 NOSSP_SRCS = $(wildcard crt/*.c) \
        src/env/__libc_start_main.c src/env/__init_tls.c \
        src/thread/__set_thread_area.c src/env/__stack_chk_fail.c \
        src/string/memset.c src/string/memcpy.c \
        src/ldso/dlstart.c src/ldso/dynlink.c
-$(NOSSP_SRCS:%.c=%.o) $(NOSSP_SRCS:%.c=%.lo): CFLAGS_ALL += $(CFLAGS_NOSSP)
+$(NOSSP_SRCS:%.c=obj/%.o) $(NOSSP_SRCS:%.c=obj/%.lo): CFLAGS_ALL += $(CFLAGS_NOSSP)
 
-$(CRT_LIBS:lib/%=crt/%): CFLAGS_ALL += -DCRT
+$(CRT_LIBS:lib/%=obj/crt/%): CFLAGS_ALL += -DCRT
 
 # This incantation ensures that changes to any subarch asm files will
 # force the corresponding object file to be rebuilt, even if the implicit
 # rule below goes indirectly through a .sub file.
 define mkasmdep
-$(dir $(patsubst %/,%,$(dir $(1))))$(notdir $(1:.s=.o)): $(1)
+$(patsubst $(srcdir)/%,obj/%,$(dir $(patsubst %/,%,$(dir $(1))))$(ARCH)$(ASMSUBARCH)/$(notdir $(1:.s=.o))): $(1)
 endef
-$(foreach s,$(wildcard src/*/$(ARCH)*/*.s),$(eval $(call mkasmdep,$(s))))
+$(foreach s,$(wildcard $(srcdir)/src/*/$(ARCH)*/*.s),$(eval $(call mkasmdep,$(s))))
 
 # Choose invocation of assembler to be used
 # $(1) is input file, $(2) is output file, $(3) is assembler flags
 ifeq ($(ADD_CFI),yes)
-       AS_CMD = LC_ALL=C awk -f tools/add-cfi.common.awk -f tools/add-cfi.$(ARCH).awk $< | $(CC) -x assembler -c -o $@ -
+       AS_CMD = LC_ALL=C awk -f $(srcdir)/tools/add-cfi.common.awk -f $(srcdir)/tools/add-cfi.$(ARCH).awk $< | $(CC) -x assembler -c -o $@ -
 else
        AS_CMD = $(CC) -c -o $@ $<
 endif
 
-%.o: $(ARCH)$(ASMSUBARCH)/%.sub
-       $(CC) $(CFLAGS_ALL_STATIC) -c -o $@ $(dir $<)$(shell cat $<)
+obj/%.o: $(srcdir)/%.sub
+       $(CC) $(CFLAGS_ALL_STATIC) -c -o $@ $(dir $<)$$(cat $<)
 
-%.o: $(ARCH)/%.s
+obj/%.o: $(srcdir)/%.s
        $(AS_CMD) $(CFLAGS_ALL_STATIC)
 
-%.o: %.c $(GENH) $(IMPH)
+obj/%.o: $(srcdir)/%.c $(GENH) $(IMPH)
        $(CC) $(CFLAGS_ALL_STATIC) -c -o $@ $<
 
-%.lo: $(ARCH)$(ASMSUBARCH)/%.sub
-       $(CC) $(CFLAGS_ALL_SHARED) -c -o $@ $(dir $<)$(shell cat $<)
+obj/%.lo: $(srcdir)/%.sub
+       $(CC) $(CFLAGS_ALL_SHARED) -c -o $@ $(dir $<)$$(cat $<)
 
-%.lo: $(ARCH)/%.s
+obj/%.lo: $(srcdir)/%.s
        $(AS_CMD) $(CFLAGS_ALL_SHARED)
 
-%.lo: %.c $(GENH) $(IMPH)
+obj/%.lo: $(srcdir)/%.c $(GENH) $(IMPH)
        $(CC) $(CFLAGS_ALL_SHARED) -c -o $@ $<
 
 lib/libc.so: $(LOBJS)
@@ -163,21 +178,27 @@ $(EMPTY_LIBS):
        rm -f $@
        $(AR) rc $@
 
-lib/%.o: crt/%.o
+lib/%.o: obj/crt/%.o
        cp $< $@
 
-lib/musl-gcc.specs: tools/musl-gcc.specs.sh config.mak
+lib/crti.o: obj/crt/$(ARCH)/crti.o
+       cp $< $@
+
+lib/crtn.o: obj/crt/$(ARCH)/crtn.o
+       cp $< $@
+
+lib/musl-gcc.specs: $(srcdir)/tools/musl-gcc.specs.sh config.mak
        sh $< "$(includedir)" "$(libdir)" "$(LDSO_PATHNAME)" > $@
 
-tools/musl-gcc: config.mak
+obj/musl-gcc: config.mak
        printf '#!/bin/sh\nexec "$${REALGCC:-$(WRAPCC_GCC)}" "$$@" -specs "%s/musl-gcc.specs"\n' "$(libdir)" > $@
        chmod +x $@
 
-tools/%-clang: tools/%-clang.in config.mak
+obj/%-clang: $(srcdir)/tools/%-clang.in config.mak
        sed -e 's!@CC@!$(WRAPCC_CLANG)!g' -e 's!@PREFIX@!$(prefix)!g' -e 's!@INCDIR@!$(includedir)!g' -e 's!@LIBDIR@!$(libdir)!g' -e 's!@LDSO@!$(LDSO_PATHNAME)!g' $< > $@
        chmod +x $@
 
-$(DESTDIR)$(bindir)/%: tools/%
+$(DESTDIR)$(bindir)/%: obj/%
        $(INSTALL) -D $< $@
 
 $(DESTDIR)$(libdir)/%.so: lib/%.so
@@ -186,10 +207,13 @@ $(DESTDIR)$(libdir)/%.so: lib/%.so
 $(DESTDIR)$(libdir)/%: lib/%
        $(INSTALL) -D -m 644 $< $@
 
-$(DESTDIR)$(includedir)/bits/%: arch/$(ARCH)/bits/%
+$(DESTDIR)$(includedir)/bits/%: $(srcdir)/arch/$(ARCH)/bits/%
+       $(INSTALL) -D -m 644 $< $@
+
+$(DESTDIR)$(includedir)/bits/%: obj/include/bits/%
        $(INSTALL) -D -m 644 $< $@
 
-$(DESTDIR)$(includedir)/%: include/%
+$(DESTDIR)$(includedir)/%: $(srcdir)/include/%
        $(INSTALL) -D -m 644 $< $@
 
 $(DESTDIR)$(LDSO_PATHNAME): $(DESTDIR)$(libdir)/libc.so
@@ -199,12 +223,12 @@ install-libs: $(ALL_LIBS:lib/%=$(DESTDIR)$(libdir)/%) $(if $(SHARED_LIBS),$(DEST
 
 install-headers: $(ALL_INCLUDES:include/%=$(DESTDIR)$(includedir)/%)
 
-install-tools: $(ALL_TOOLS:tools/%=$(DESTDIR)$(bindir)/%)
+install-tools: $(ALL_TOOLS:obj/%=$(DESTDIR)$(bindir)/%)
 
 musl-git-%.tar.gz: .git
-        git archive --format=tar.gz --prefix=$(patsubst %.tar.gz,%,$@)/ -o $@ $(patsubst musl-git-%.tar.gz,%,$@)
+        git --git-dir=$(srcdir)/.git archive --format=tar.gz --prefix=$(patsubst %.tar.gz,%,$@)/ -o $@ $(patsubst musl-git-%.tar.gz,%,$@)
 
 musl-%.tar.gz: .git
-        git archive --format=tar.gz --prefix=$(patsubst %.tar.gz,%,$@)/ -o $@ v$(patsubst musl-%.tar.gz,%,$@)
+        git --git-dir=$(srcdir)/.git archive --format=tar.gz --prefix=$(patsubst %.tar.gz,%,$@)/ -o $@ v$(patsubst musl-%.tar.gz,%,$@)
 
 .PHONY: all clean install install-libs install-headers install-tools
index ee217713568ea7d55c5699043efb221a6dc73b54..fcfdc1587559ce8e168ce8723b59348b46a3a739 100755 (executable)
--- a/configure
+++ b/configure
@@ -9,6 +9,9 @@ VAR=VALUE.  See below for descriptions of some of the useful variables.
 
 Defaults for the options are specified in brackets.
 
+Configuration:
+  --srcdir=DIR            source directory [detected]
+
 Installation directories:
   --prefix=PREFIX         main installation prefix [/usr/local/musl]
   --exec-prefix=EPREFIX   installation prefix for executable files [PREFIX]
@@ -117,6 +120,7 @@ CFLAGS_TRY=
 LDFLAGS_AUTO=
 LDFLAGS_TRY=
 OPTIMIZE_GLOBS=
+srcdir=
 prefix=/usr/local/musl
 exec_prefix='$(prefix)'
 bindir='$(exec_prefix)/bin'
@@ -139,6 +143,7 @@ clang_wrapper=no
 for arg ; do
 case "$arg" in
 --help) usage ;;
+--srcdir=*) srcdir=${arg#*=} ;;
 --prefix=*) prefix=${arg#*=} ;;
 --exec-prefix=*) exec_prefix=${arg#*=} ;;
 --bindir=*) bindir=${arg#*=} ;;
@@ -179,10 +184,22 @@ LIBCC=*) LIBCC=${arg#*=} ;;
 esac
 done
 
-for i in prefix exec_prefix bindir libdir includedir syslibdir ; do
+for i in srcdir prefix exec_prefix bindir libdir includedir syslibdir ; do
 stripdir $i
 done
 
+#
+# Get the source dir for out-of-tree builds
+#
+if test -z "$srcdir" ; then
+srcdir="${0%/configure}"
+stripdir srcdir
+fi
+abs_builddir="$(pwd)" || fail "$0: cannot determine working directory"
+abs_srcdir="$(cd $srcdir && pwd)" || fail "$0: invalid source directory $srcdir"
+test "$abs_srcdir" = "$abs_builddir" && srcdir=.
+test "$srcdir" != "." -a -f Makefile -a ! -h Makefile && fail "$0: Makefile already exists in the working directory"
+
 #
 # Get a temp filename we can use
 #
@@ -263,11 +280,11 @@ fi
 fi
 
 if test "$gcc_wrapper" = yes ; then
-tools="$tools tools/musl-gcc"
+tools="$tools obj/musl-gcc"
 tool_libs="$tool_libs lib/musl-gcc.specs"
 fi
 if test "$clang_wrapper" = yes ; then
-tools="$tools tools/musl-clang tools/ld.musl-clang"
+tools="$tools obj/musl-clang obj/ld.musl-clang"
 fi
 
 #
@@ -321,7 +338,7 @@ __attribute__((__may_alias__))
 #endif
 x;
 EOF
-if $CC $CFLAGS_C99FSE -I./arch/$ARCH -I./include $CPPFLAGS $CFLAGS \
+if $CC $CFLAGS_C99FSE -I$srcdir/arch/$ARCH -I$srcdir/include $CPPFLAGS $CFLAGS \
   -c -o /dev/null "$tmpc" >/dev/null 2>&1 ; then
 printf "no\n"
 else
@@ -625,7 +642,7 @@ echo '#include <float.h>' > "$tmpc"
 echo '#if LDBL_MANT_DIG == 53' >> "$tmpc"
 echo 'typedef char ldcheck[9-(int)sizeof(long double)];' >> "$tmpc"
 echo '#endif' >> "$tmpc"
-if $CC $CFLAGS_C99FSE -I./arch/$ARCH -I./include $CPPFLAGS $CFLAGS \
+if $CC $CFLAGS_C99FSE -I$srcdir/arch/$ARCH -I$srcdir/include $CPPFLAGS $CFLAGS \
   -c -o /dev/null "$tmpc" >/dev/null 2>&1 ; then
 printf "yes\n"
 else
@@ -648,6 +665,7 @@ cat << EOF
 ARCH = $ARCH
 SUBARCH = $SUBARCH
 ASMSUBARCH = $ASMSUBARCH
+srcdir = $srcdir
 prefix = $prefix
 exec_prefix = $exec_prefix
 bindir = $bindir
@@ -676,4 +694,6 @@ test "x$cc_family" = xgcc && echo 'WRAPCC_GCC = $(CC)'
 test "x$cc_family" = xclang && echo 'WRAPCC_CLANG = $(CC)'
 exec 1>&3 3>&-
 
+test "$srcdir" = "." || ln -sf $srcdir/Makefile .
+
 printf "done\n"