瀏覽代碼

support out-of-tree build

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.
Petr Hosek 9 年之前
父節點
當前提交
2f853dd6b9
共有 3 個文件被更改,包括 101 次插入60 次删除
  1. 1 4
      .gitignore
  2. 75 51
      Makefile
  3. 25 5
      configure

+ 1 - 4
.gitignore

@@ -5,9 +5,6 @@
 *.so.1
 *.so.1
 arch/*/bits/alltypes.h
 arch/*/bits/alltypes.h
 config.mak
 config.mak
-include/bits
-tools/musl-gcc
-tools/musl-clang
-tools/ld.musl-clang
 lib/musl-gcc.specs
 lib/musl-gcc.specs
 src/internal/version.h
 src/internal/version.h
+/obj/

+ 75 - 51
Makefile

@@ -8,6 +8,7 @@
 # Do not make changes here.
 # Do not make changes here.
 #
 #
 
 
+srcdir = .
 exec_prefix = /usr/local
 exec_prefix = /usr/local
 bindir = $(exec_prefix)/bin
 bindir = $(exec_prefix)/bin
 
 
@@ -16,12 +17,16 @@ includedir = $(prefix)/include
 libdir = $(prefix)/lib
 libdir = $(prefix)/lib
 syslibdir = /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)
 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 =
 LDFLAGS_AUTO =
 LDFLAGS_AUTO =
@@ -32,7 +37,7 @@ CFLAGS_AUTO = -Os -pipe
 CFLAGS_C99FSE = -std=c99 -ffreestanding -nostdinc 
 CFLAGS_C99FSE = -std=c99 -ffreestanding -nostdinc 
 
 
 CFLAGS_ALL = $(CFLAGS_C99FSE)
 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 += $(CPPFLAGS) $(CFLAGS_AUTO) $(CFLAGS)
 CFLAGS_ALL_STATIC = $(CFLAGS_ALL)
 CFLAGS_ALL_STATIC = $(CFLAGS_ALL)
 CFLAGS_ALL_SHARED = $(CFLAGS_ALL) -fPIC -DSHARED
 CFLAGS_ALL_SHARED = $(CFLAGS_ALL) -fPIC -DSHARED
@@ -41,10 +46,11 @@ LDFLAGS_ALL = $(LDFLAGS_AUTO) $(LDFLAGS)
 
 
 AR      = $(CROSS_COMPILE)ar
 AR      = $(CROSS_COMPILE)ar
 RANLIB  = $(CROSS_COMPILE)ranlib
 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_LIB_NAMES = m rt pthread crypt util xnet resolv dl
 EMPTY_LIBS = $(EMPTY_LIB_NAMES:%=lib/lib%.a)
 EMPTY_LIBS = $(EMPTY_LIB_NAMES:%=lib/lib%.a)
@@ -53,7 +59,7 @@ STATIC_LIBS = lib/libc.a
 SHARED_LIBS = lib/libc.so
 SHARED_LIBS = lib/libc.so
 TOOL_LIBS = lib/musl-gcc.specs
 TOOL_LIBS = lib/musl-gcc.specs
 ALL_LIBS = $(CRT_LIBS) $(STATIC_LIBS) $(SHARED_LIBS) $(EMPTY_LIBS) $(TOOL_LIBS)
 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_GCC = gcc
 WRAPCC_CLANG = clang
 WRAPCC_CLANG = clang
@@ -62,91 +68,100 @@ LDSO_PATHNAME = $(syslibdir)/ld-musl-$(ARCH)$(SUBARCH).so.1
 
 
 -include config.mak
 -include config.mak
 
 
+ifeq ($(ARCH),)
+$(error Please set ARCH in config.mak before running make.)
+endif
+
 all: $(ALL_LIBS) $(ALL_TOOLS)
 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
 install: install-libs install-headers install-tools
 
 
 clean:
 clean:
-	rm -f crt/*.o
+	rm -f obj/crt/*.o obj/crt/$(ARCH)/*.o
 	rm -f $(OBJS)
 	rm -f $(OBJS)
 	rm -f $(LOBJS)
 	rm -f $(LOBJS)
 	rm -f $(ALL_LIBS) lib/*.[ao] lib/*.so
 	rm -f $(ALL_LIBS) lib/*.[ao] lib/*.so
 	rm -f $(ALL_TOOLS)
 	rm -f $(ALL_TOOLS)
 	rm -f $(GENH) $(GENH_INT)
 	rm -f $(GENH) $(GENH_INT)
-	rm -f include/bits
+	rm -f obj/include/bits/alltypes.h
 
 
 distclean: clean
 distclean: clean
 	rm -f config.mak
 	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 = 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) \
 NOSSP_SRCS = $(wildcard crt/*.c) \
 	src/env/__libc_start_main.c src/env/__init_tls.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/thread/__set_thread_area.c src/env/__stack_chk_fail.c \
 	src/string/memset.c src/string/memcpy.c \
 	src/string/memset.c src/string/memcpy.c \
 	src/ldso/dlstart.c src/ldso/dynlink.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
 # This incantation ensures that changes to any subarch asm files will
 # force the corresponding object file to be rebuilt, even if the implicit
 # force the corresponding object file to be rebuilt, even if the implicit
 # rule below goes indirectly through a .sub file.
 # rule below goes indirectly through a .sub file.
 define mkasmdep
 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
 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
 # Choose invocation of assembler to be used
 # $(1) is input file, $(2) is output file, $(3) is assembler flags
 # $(1) is input file, $(2) is output file, $(3) is assembler flags
 ifeq ($(ADD_CFI),yes)
 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
 else
 	AS_CMD = $(CC) -c -o $@ $<
 	AS_CMD = $(CC) -c -o $@ $<
 endif
 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)
 	$(AS_CMD) $(CFLAGS_ALL_STATIC)
 
 
-%.o: %.c $(GENH) $(IMPH)
+obj/%.o: $(srcdir)/%.c $(GENH) $(IMPH)
 	$(CC) $(CFLAGS_ALL_STATIC) -c -o $@ $<
 	$(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)
 	$(AS_CMD) $(CFLAGS_ALL_SHARED)
 
 
-%.lo: %.c $(GENH) $(IMPH)
+obj/%.lo: $(srcdir)/%.c $(GENH) $(IMPH)
 	$(CC) $(CFLAGS_ALL_SHARED) -c -o $@ $<
 	$(CC) $(CFLAGS_ALL_SHARED) -c -o $@ $<
 
 
 lib/libc.so: $(LOBJS)
 lib/libc.so: $(LOBJS)
@@ -163,21 +178,27 @@ $(EMPTY_LIBS):
 	rm -f $@
 	rm -f $@
 	$(AR) rc $@
 	$(AR) rc $@
 
 
-lib/%.o: crt/%.o
+lib/%.o: obj/crt/%.o
 	cp $< $@
 	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)" > $@
 	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)" > $@
 	printf '#!/bin/sh\nexec "$${REALGCC:-$(WRAPCC_GCC)}" "$$@" -specs "%s/musl-gcc.specs"\n' "$(libdir)" > $@
 	chmod +x $@
 	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' $< > $@
 	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 $@
 	chmod +x $@
 
 
-$(DESTDIR)$(bindir)/%: tools/%
+$(DESTDIR)$(bindir)/%: obj/%
 	$(INSTALL) -D $< $@
 	$(INSTALL) -D $< $@
 
 
 $(DESTDIR)$(libdir)/%.so: lib/%.so
 $(DESTDIR)$(libdir)/%.so: lib/%.so
@@ -186,10 +207,13 @@ $(DESTDIR)$(libdir)/%.so: lib/%.so
 $(DESTDIR)$(libdir)/%: lib/%
 $(DESTDIR)$(libdir)/%: lib/%
 	$(INSTALL) -D -m 644 $< $@
 	$(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 $< $@
 	$(INSTALL) -D -m 644 $< $@
 
 
-$(DESTDIR)$(includedir)/%: include/%
+$(DESTDIR)$(includedir)/%: $(srcdir)/include/%
 	$(INSTALL) -D -m 644 $< $@
 	$(INSTALL) -D -m 644 $< $@
 
 
 $(DESTDIR)$(LDSO_PATHNAME): $(DESTDIR)$(libdir)/libc.so
 $(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-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
 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
 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
 .PHONY: all clean install install-libs install-headers install-tools

+ 25 - 5
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.
 Defaults for the options are specified in brackets.
 
 
+Configuration:
+  --srcdir=DIR            source directory [detected]
+
 Installation directories:
 Installation directories:
   --prefix=PREFIX         main installation prefix [/usr/local/musl]
   --prefix=PREFIX         main installation prefix [/usr/local/musl]
   --exec-prefix=EPREFIX   installation prefix for executable files [PREFIX]
   --exec-prefix=EPREFIX   installation prefix for executable files [PREFIX]
@@ -117,6 +120,7 @@ CFLAGS_TRY=
 LDFLAGS_AUTO=
 LDFLAGS_AUTO=
 LDFLAGS_TRY=
 LDFLAGS_TRY=
 OPTIMIZE_GLOBS=
 OPTIMIZE_GLOBS=
+srcdir=
 prefix=/usr/local/musl
 prefix=/usr/local/musl
 exec_prefix='$(prefix)'
 exec_prefix='$(prefix)'
 bindir='$(exec_prefix)/bin'
 bindir='$(exec_prefix)/bin'
@@ -139,6 +143,7 @@ clang_wrapper=no
 for arg ; do
 for arg ; do
 case "$arg" in
 case "$arg" in
 --help) usage ;;
 --help) usage ;;
+--srcdir=*) srcdir=${arg#*=} ;;
 --prefix=*) prefix=${arg#*=} ;;
 --prefix=*) prefix=${arg#*=} ;;
 --exec-prefix=*) exec_prefix=${arg#*=} ;;
 --exec-prefix=*) exec_prefix=${arg#*=} ;;
 --bindir=*) bindir=${arg#*=} ;;
 --bindir=*) bindir=${arg#*=} ;;
@@ -179,10 +184,22 @@ LIBCC=*) LIBCC=${arg#*=} ;;
 esac
 esac
 done
 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
 stripdir $i
 done
 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
 # Get a temp filename we can use
 #
 #
@@ -263,11 +280,11 @@ fi
 fi
 fi
 
 
 if test "$gcc_wrapper" = yes ; then
 if test "$gcc_wrapper" = yes ; then
-tools="$tools tools/musl-gcc"
+tools="$tools obj/musl-gcc"
 tool_libs="$tool_libs lib/musl-gcc.specs"
 tool_libs="$tool_libs lib/musl-gcc.specs"
 fi
 fi
 if test "$clang_wrapper" = yes ; then
 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
 fi
 
 
 #
 #
@@ -321,7 +338,7 @@ __attribute__((__may_alias__))
 #endif
 #endif
 x;
 x;
 EOF
 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
   -c -o /dev/null "$tmpc" >/dev/null 2>&1 ; then
 printf "no\n"
 printf "no\n"
 else
 else
@@ -625,7 +642,7 @@ echo '#include <float.h>' > "$tmpc"
 echo '#if LDBL_MANT_DIG == 53' >> "$tmpc"
 echo '#if LDBL_MANT_DIG == 53' >> "$tmpc"
 echo 'typedef char ldcheck[9-(int)sizeof(long double)];' >> "$tmpc"
 echo 'typedef char ldcheck[9-(int)sizeof(long double)];' >> "$tmpc"
 echo '#endif' >> "$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
   -c -o /dev/null "$tmpc" >/dev/null 2>&1 ; then
 printf "yes\n"
 printf "yes\n"
 else
 else
@@ -648,6 +665,7 @@ cat << EOF
 ARCH = $ARCH
 ARCH = $ARCH
 SUBARCH = $SUBARCH
 SUBARCH = $SUBARCH
 ASMSUBARCH = $ASMSUBARCH
 ASMSUBARCH = $ASMSUBARCH
+srcdir = $srcdir
 prefix = $prefix
 prefix = $prefix
 exec_prefix = $exec_prefix
 exec_prefix = $exec_prefix
 bindir = $bindir
 bindir = $bindir
@@ -676,4 +694,6 @@ test "x$cc_family" = xgcc && echo 'WRAPCC_GCC = $(CC)'
 test "x$cc_family" = xclang && echo 'WRAPCC_CLANG = $(CC)'
 test "x$cc_family" = xclang && echo 'WRAPCC_CLANG = $(CC)'
 exec 1>&3 3>&-
 exec 1>&3 3>&-
 
 
+test "$srcdir" = "." || ln -sf $srcdir/Makefile .
+
 printf "done\n"
 printf "done\n"