mailing list of musl libc
 help / color / mirror / code / Atom feed
* Support for out-of-tree build
@ 2015-11-06 23:40 Petr Hosek
  2015-11-07 13:05 ` Szabolcs Nagy
  0 siblings, 1 reply; 56+ messages in thread
From: Petr Hosek @ 2015-11-06 23:40 UTC (permalink / raw)
  To: musl


[-- Attachment #1.1: Type: text/plain, Size: 404 bytes --]

I'm porting musl to (Portable) Native Client. One of the requirements we
have is out-tree-build; I've found an older patch from Szabolcs Nagy so
I've decided to rebase it on top of master, clean and finish it. It seems
to be working fine with the current master with all different
configurations. I'd be happy to make any changes necessary to have it
landed, please let me know if you have any comments.

[-- Attachment #1.2: Type: text/html, Size: 472 bytes --]

[-- Attachment #2: suport-out-of-tree-build.patch --]
[-- Type: text/x-patch, Size: 9317 bytes --]

From 916b69c7757ae23f37e1112ad00cb50573c0244e Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek@chromium.org>
Date: Thu, 5 Nov 2015 14:51:50 -0800
Subject: [PATCH] suport out-of-tree build

this change add support for building musl outside of the source
tree. the implementation is similar to autotools where running
configure in a different folder 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. based on patch by Szabolcs Nagy.
---
 Makefile  | 56 ++++++++++++++++++++++++++++++++++++--------------------
 configure | 25 ++++++++++++++++++++++---
 2 files changed, 58 insertions(+), 23 deletions(-)

diff --git a/Makefile b/Makefile
index 2b21015..c63d588 100644
--- a/Makefile
+++ b/Makefile
@@ -8,6 +8,7 @@
 # Do not make changes here.
 #
 
+srcdir = .
 exec_prefix = /usr/local
 bindir = $(exec_prefix)/bin
 
@@ -16,8 +17,8 @@ includedir = $(prefix)/include
 libdir = $(prefix)/lib
 syslibdir = /lib
 
-SRCS = $(sort $(wildcard src/*/*.c arch/$(ARCH)/src/*.c))
-OBJS = $(SRCS:.c=.o)
+SRCS = $(sort $(wildcard $(srcdir)/src/*/*.c $(srcdir)/arch/$(ARCH)/src/*.c))
+OBJS = $(SRCS:$(srcdir)/%.c=%.o)
 LOBJS = $(OBJS:.o=.lo)
 GENH = include/bits/alltypes.h
 GENH_INT = src/internal/version.h
@@ -32,7 +33,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) -I./src/internal -I$(srcdir)/src/internal -I./include -I$(srcdir)/include
 CFLAGS_ALL += $(CPPFLAGS) $(CFLAGS_AUTO) $(CFLAGS)
 CFLAGS_ALL_STATIC = $(CFLAGS_ALL)
 CFLAGS_ALL_SHARED = $(CFLAGS_ALL) -fPIC -DSHARED
@@ -41,10 +42,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) $(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)
@@ -64,6 +66,20 @@ LDSO_PATHNAME = $(syslibdir)/ld-musl-$(ARCH)$(SUBARCH).so.1
 
 all: $(ALL_LIBS) $(ALL_TOOLS)
 
+ifneq ($(srcdir),.)
+VPATH = $(srcdir)
+$(ALL_TOOLS): tools/.dirstamp
+$(ALL_LIBS): lib/.dirstamp
+$(CRT_LIBS:lib/%=crt/%): crt/.dirstamp
+$(OBJS) $(LOBJS): $(patsubst %/,%/.dirstamp,$(sort $(dir $(OBJS))))
+$(GENH): arch/$(ARCH)/bits/.dirstamp
+include/bits: include/.dirstamp
+src/internal/version.h: src/internal/.dirstamp
+%/.dirstamp:
+	mkdir -p $*
+	touch $@
+endif
+
 install: install-libs install-headers install-tools
 
 clean:
@@ -82,26 +98,24 @@ include/bits:
 	@test "$(ARCH)" || { echo "Please set ARCH in config.mak before running make." ; exit 1 ; }
 	ln -sf ../arch/$(ARCH)/bits $@
 
-include/bits/alltypes.h.in: include/bits
+include/bits/alltypes.h: $(srcdir)/arch/$(ARCH)/bits/alltypes.h.in $(srcdir)/include/alltypes.h.in $(srcdir)/tools/mkalltypes.sed include/bits
+	sed -f $(srcdir)/tools/mkalltypes.sed $(srcdir)/arch/$(ARCH)/bits/alltypes.h.in $(srcdir)/include/alltypes.h.in > $@
 
-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 > $@
-
-src/internal/version.h: $(wildcard VERSION .git)
-	printf '#define VERSION "%s"\n' "$$(sh tools/version.sh)" > $@
+src/internal/version.h: $(wildcard $(srcdir)/VERSION $(srcdir)/.git)
+	printf '#define VERSION "%s"\n' "$$(cd $(srcdir); sh tools/version.sh)" > $@
 
 src/internal/version.lo: src/internal/version.h
 
 crt/rcrt1.o src/ldso/dlstart.lo src/ldso/dynlink.lo: src/internal/dynlink.h arch/$(ARCH)/reloc.h
 
-crt/crt1.o crt/Scrt1.o crt/rcrt1.o src/ldso/dlstart.lo: $(wildcard arch/$(ARCH)/crt_arch.h)
+crt/crt1.o crt/scrt1.o crt/rcrt1.o src/ldso/dlstart.lo: $(wildcard $(srcdir)/arch/$(ARCH)/crt_arch.h)
 
 crt/rcrt1.o: src/ldso/dlstart.c
 
 crt/Scrt1.o crt/rcrt1.o: CFLAGS_ALL += -fPIC
 
-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=%.o) $(OPTIMIZE_SRCS:$(srcdir)/%.c=%.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)
@@ -119,14 +133,14 @@ $(CRT_LIBS:lib/%=crt/%): CFLAGS_ALL += -DCRT
 # 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)
+$(dir $(patsubst $(srcdir)/%/,%,$(dir $(1))))$(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
@@ -202,9 +216,11 @@ install-headers: $(ALL_INCLUDES:include/%=$(DESTDIR)$(includedir)/%)
 install-tools: $(ALL_TOOLS:tools/%=$(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,%,$@)
+
+.SECONDARY:
 
 .PHONY: all clean install install-libs install-headers install-tools
diff --git a/configure b/configure
index dece1d0..b2d0c8d 100755
--- 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,11 +184,23 @@ 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 musl 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=.
+ln -sf $srcdir/Makefile .
+
+#
 # Get a temp filename we can use
 #
 i=0
@@ -293,6 +310,7 @@ microblaze*) ARCH=microblaze ;;
 or1k*) ARCH=or1k ;;
 powerpc*) ARCH=powerpc ;;
 sh[1-9bel-]*|sh|superh*) ARCH=sh ;;
+le32*) ARCH=le32 ;;
 unknown) fail "$0: unable to detect target arch; try $0 --target=..." ;;
 *) fail "$0: unknown or unsupported target \"$target\"" ;;
 esac
@@ -321,7 +339,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
@@ -620,7 +638,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
@@ -643,6 +661,7 @@ cat << EOF
 ARCH = $ARCH
 SUBARCH = $SUBARCH
 ASMSUBARCH = $ASMSUBARCH
+srcdir = $srcdir
 prefix = $prefix
 exec_prefix = $exec_prefix
 bindir = $bindir
-- 
2.6.0.rc2.230.g3dd15c0


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-06 23:40 Support for out-of-tree build Petr Hosek
@ 2015-11-07 13:05 ` Szabolcs Nagy
  2015-11-08  0:43   ` Rich Felker
  0 siblings, 1 reply; 56+ messages in thread
From: Szabolcs Nagy @ 2015-11-07 13:05 UTC (permalink / raw)
  To: musl

* Petr Hosek <phosek@chromium.org> [2015-11-06 23:40:48 +0000]:
> I'm porting musl to (Portable) Native Client. One of the requirements we
> have is out-tree-build; I've found an older patch from Szabolcs Nagy so

yes, this is on the roadmap for a while now
there were various iterations of this

one limitation of the VPATH approach is that
mixing in-tree and out-tree builds breaks:
if build targets are found in the source dir
after a previous in-tree build then those are
not rebuilt out-tree.

so at least there should be some check in the
Makefile (e.g. if config.mak exists in-tree
during an out-tree build)

the other approach is to change the problematic

%.o: $(ARCH)/%.s

rules, because

<dir>/%.o: $(srcdir)/<dir>/$(ARCH)/%.s

cannot be expressed in make.
(e.g. the dirs under src/ could be explicitly
listed and then just adding $(srcdir)/ to all
rules would make it work and in-/out-tree could
be mixed.)

> I've decided to rebase it on top of master, clean and finish it. It seems
> to be working fine with the current master with all different
> configurations. I'd be happy to make any changes necessary to have it
> landed, please let me know if you have any comments.

> From 916b69c7757ae23f37e1112ad00cb50573c0244e Mon Sep 17 00:00:00 2001
> From: Petr Hosek <phosek@chromium.org>
> Date: Thu, 5 Nov 2015 14:51:50 -0800
> Subject: [PATCH] suport out-of-tree build
> 
> this change add support for building musl outside of the source
> tree. the implementation is similar to autotools where running
> configure in a different folder 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. based on patch by Szabolcs Nagy.
> ---
>  Makefile  | 56 ++++++++++++++++++++++++++++++++++++--------------------
>  configure | 25 ++++++++++++++++++++++---
>  2 files changed, 58 insertions(+), 23 deletions(-)
> 
> diff --git a/Makefile b/Makefile
> index 2b21015..c63d588 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -8,6 +8,7 @@
>  # Do not make changes here.
>  #
>  
> +srcdir = .
>  exec_prefix = /usr/local
>  bindir = $(exec_prefix)/bin
>  
> @@ -16,8 +17,8 @@ includedir = $(prefix)/include
>  libdir = $(prefix)/lib
>  syslibdir = /lib
>  
> -SRCS = $(sort $(wildcard src/*/*.c arch/$(ARCH)/src/*.c))
> -OBJS = $(SRCS:.c=.o)
> +SRCS = $(sort $(wildcard $(srcdir)/src/*/*.c $(srcdir)/arch/$(ARCH)/src/*.c))
> +OBJS = $(SRCS:$(srcdir)/%.c=%.o)
>  LOBJS = $(OBJS:.o=.lo)
>  GENH = include/bits/alltypes.h
>  GENH_INT = src/internal/version.h
> @@ -32,7 +33,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) -I./src/internal -I$(srcdir)/src/internal -I./include -I$(srcdir)/include
>  CFLAGS_ALL += $(CPPFLAGS) $(CFLAGS_AUTO) $(CFLAGS)
>  CFLAGS_ALL_STATIC = $(CFLAGS_ALL)
>  CFLAGS_ALL_SHARED = $(CFLAGS_ALL) -fPIC -DSHARED
> @@ -41,10 +42,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) $(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)
> @@ -64,6 +66,20 @@ LDSO_PATHNAME = $(syslibdir)/ld-musl-$(ARCH)$(SUBARCH).so.1
>  
>  all: $(ALL_LIBS) $(ALL_TOOLS)
>  
> +ifneq ($(srcdir),.)
> +VPATH = $(srcdir)
> +$(ALL_TOOLS): tools/.dirstamp
> +$(ALL_LIBS): lib/.dirstamp
> +$(CRT_LIBS:lib/%=crt/%): crt/.dirstamp
> +$(OBJS) $(LOBJS): $(patsubst %/,%/.dirstamp,$(sort $(dir $(OBJS))))
> +$(GENH): arch/$(ARCH)/bits/.dirstamp
> +include/bits: include/.dirstamp
> +src/internal/version.h: src/internal/.dirstamp
> +%/.dirstamp:
> +	mkdir -p $*
> +	touch $@
> +endif
> +

i guess this works without the ifneq, just
litters the source dir with .dirstamps in
case of an in-tree build.

>  install: install-libs install-headers install-tools
>  
>  clean:
> @@ -82,26 +98,24 @@ include/bits:
>  	@test "$(ARCH)" || { echo "Please set ARCH in config.mak before running make." ; exit 1 ; }
>  	ln -sf ../arch/$(ARCH)/bits $@
>  
> -include/bits/alltypes.h.in: include/bits
> +include/bits/alltypes.h: $(srcdir)/arch/$(ARCH)/bits/alltypes.h.in $(srcdir)/include/alltypes.h.in $(srcdir)/tools/mkalltypes.sed include/bits
> +	sed -f $(srcdir)/tools/mkalltypes.sed $(srcdir)/arch/$(ARCH)/bits/alltypes.h.in $(srcdir)/include/alltypes.h.in > $@
>  
> -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 > $@
> -
> -src/internal/version.h: $(wildcard VERSION .git)
> -	printf '#define VERSION "%s"\n' "$$(sh tools/version.sh)" > $@
> +src/internal/version.h: $(wildcard $(srcdir)/VERSION $(srcdir)/.git)
> +	printf '#define VERSION "%s"\n' "$$(cd $(srcdir); sh tools/version.sh)" > $@
>  
>  src/internal/version.lo: src/internal/version.h
>  
>  crt/rcrt1.o src/ldso/dlstart.lo src/ldso/dynlink.lo: src/internal/dynlink.h arch/$(ARCH)/reloc.h
>  
> -crt/crt1.o crt/Scrt1.o crt/rcrt1.o src/ldso/dlstart.lo: $(wildcard arch/$(ARCH)/crt_arch.h)
> +crt/crt1.o crt/scrt1.o crt/rcrt1.o src/ldso/dlstart.lo: $(wildcard $(srcdir)/arch/$(ARCH)/crt_arch.h)
>  
>  crt/rcrt1.o: src/ldso/dlstart.c
>  
>  crt/Scrt1.o crt/rcrt1.o: CFLAGS_ALL += -fPIC
>  
> -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=%.o) $(OPTIMIZE_SRCS:$(srcdir)/%.c=%.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)
> @@ -119,14 +133,14 @@ $(CRT_LIBS:lib/%=crt/%): CFLAGS_ALL += -DCRT
>  # 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)
> +$(dir $(patsubst $(srcdir)/%/,%,$(dir $(1))))$(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
> @@ -202,9 +216,11 @@ install-headers: $(ALL_INCLUDES:include/%=$(DESTDIR)$(includedir)/%)
>  install-tools: $(ALL_TOOLS:tools/%=$(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,%,$@)
> +
> +.SECONDARY:
>  

what does .SECONDARY do?

>  .PHONY: all clean install install-libs install-headers install-tools
> diff --git a/configure b/configure
> index dece1d0..b2d0c8d 100755
> --- 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,11 +184,23 @@ 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 musl 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=.
> +ln -sf $srcdir/Makefile .
> +
> +#
>  # Get a temp filename we can use
>  #
>  i=0
> @@ -293,6 +310,7 @@ microblaze*) ARCH=microblaze ;;
>  or1k*) ARCH=or1k ;;
>  powerpc*) ARCH=powerpc ;;
>  sh[1-9bel-]*|sh|superh*) ARCH=sh ;;
> +le32*) ARCH=le32 ;;

is le32 something native client related?

>  unknown) fail "$0: unable to detect target arch; try $0 --target=..." ;;
>  *) fail "$0: unknown or unsupported target \"$target\"" ;;
>  esac
> @@ -321,7 +339,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
> @@ -620,7 +638,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
> @@ -643,6 +661,7 @@ cat << EOF
>  ARCH = $ARCH
>  SUBARCH = $SUBARCH
>  ASMSUBARCH = $ASMSUBARCH
> +srcdir = $srcdir
>  prefix = $prefix
>  exec_prefix = $exec_prefix
>  bindir = $bindir
> -- 
> 2.6.0.rc2.230.g3dd15c0
> 



^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-07 13:05 ` Szabolcs Nagy
@ 2015-11-08  0:43   ` Rich Felker
  2015-11-08  2:16     ` Szabolcs Nagy
  0 siblings, 1 reply; 56+ messages in thread
From: Rich Felker @ 2015-11-08  0:43 UTC (permalink / raw)
  To: musl

On Sat, Nov 07, 2015 at 02:05:37PM +0100, Szabolcs Nagy wrote:
> * Petr Hosek <phosek@chromium.org> [2015-11-06 23:40:48 +0000]:
> > I'm porting musl to (Portable) Native Client. One of the requirements we
> > have is out-tree-build; I've found an older patch from Szabolcs Nagy so
> 
> yes, this is on the roadmap for a while now
> there were various iterations of this

Great to see more interest in this right when I wanted to make it
happen. :)

> one limitation of the VPATH approach is that
> mixing in-tree and out-tree builds breaks:
> if build targets are found in the source dir
> after a previous in-tree build then those are
> not rebuilt out-tree.
> 
> so at least there should be some check in the
> Makefile (e.g. if config.mak exists in-tree
> during an out-tree build)

Yes, I think this could be reliably detected.

I would not even be opposed to getting rid of "true in-tree" builds,
i.e. always putting output in a subdirectory of the top-level musl dir
if the build is configured for in-tree, if that's practical. Thoughts?

> the other approach is to change the problematic
> 
> %.o: $(ARCH)/%.s
> 
> rules, because
> 
> <dir>/%.o: $(srcdir)/<dir>/$(ARCH)/%.s
> 
> cannot be expressed in make.
> (e.g. the dirs under src/ could be explicitly
> listed and then just adding $(srcdir)/ to all
> rules would make it work and in-/out-tree could
> be mixed.)

I would very strongly prefer to avoid anything that involves adding
additional rules beyond O(1). Rule-per-file or rule-per-dir is
undesirable. There are ways it could be avoided at the actual makefile
level by using fancy GNU make features for expanding at make time, but
this generally yields very bad performance (see the current *.sub
stuff we have, which I want to remove, and which was a major
performance hit when it was added) and reduces ease of human
comprehension of the makefile.

> > +ifneq ($(srcdir),.)
> > +VPATH = $(srcdir)
> > +$(ALL_TOOLS): tools/.dirstamp
> > +$(ALL_LIBS): lib/.dirstamp
> > +$(CRT_LIBS:lib/%=crt/%): crt/.dirstamp
> > +$(OBJS) $(LOBJS): $(patsubst %/,%/.dirstamp,$(sort $(dir $(OBJS))))
> > +$(GENH): arch/$(ARCH)/bits/.dirstamp
> > +include/bits: include/.dirstamp
> > +src/internal/version.h: src/internal/.dirstamp
> > +%/.dirstamp:
> > +	mkdir -p $*
> > +	touch $@
> > +endif
> > +
> 
> i guess this works without the ifneq, just
> litters the source dir with .dirstamps in
> case of an in-tree build.

What is the motive for having these .dirstamps at all?

> > +.SECONDARY:
> >  
> 
> what does .SECONDARY do?

It's buggy and can't be used. See commit
d18cf76d73df8f9cc751d4b4ba5a635c70c0c645.

> > diff --git a/configure b/configure
> > index dece1d0..b2d0c8d 100755
> > --- 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]
> > +

Does this match standard configure behavior?

> > +# Get the musl 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=.
> > +ln -sf $srcdir/Makefile .

Is it possible to get a relative path for the srcdir rather than an
absolute one here? I really don't like configurations that are not
relocatable in the filesystem.

> >  # Get a temp filename we can use
> >  #
> >  i=0
> > @@ -293,6 +310,7 @@ microblaze*) ARCH=microblaze ;;
> >  or1k*) ARCH=or1k ;;
> >  powerpc*) ARCH=powerpc ;;
> >  sh[1-9bel-]*|sh|superh*) ARCH=sh ;;
> > +le32*) ARCH=le32 ;;
> 
> is le32 something native client related?

I'm pretty sure it is.

Rich


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-08  0:43   ` Rich Felker
@ 2015-11-08  2:16     ` Szabolcs Nagy
  2015-11-08  2:29       ` Rich Felker
  0 siblings, 1 reply; 56+ messages in thread
From: Szabolcs Nagy @ 2015-11-08  2:16 UTC (permalink / raw)
  To: musl

* Rich Felker <dalias@libc.org> [2015-11-07 19:43:23 -0500]:
> On Sat, Nov 07, 2015 at 02:05:37PM +0100, Szabolcs Nagy wrote:
> > * Petr Hosek <phosek@chromium.org> [2015-11-06 23:40:48 +0000]:
> > > +ifneq ($(srcdir),.)
> > > +VPATH = $(srcdir)
> > > +$(ALL_TOOLS): tools/.dirstamp
> > > +$(ALL_LIBS): lib/.dirstamp
> > > +$(CRT_LIBS:lib/%=crt/%): crt/.dirstamp
> > > +$(OBJS) $(LOBJS): $(patsubst %/,%/.dirstamp,$(sort $(dir $(OBJS))))
> > > +$(GENH): arch/$(ARCH)/bits/.dirstamp
> > > +include/bits: include/.dirstamp
> > > +src/internal/version.h: src/internal/.dirstamp
> > > +%/.dirstamp:
> > > +	mkdir -p $*
> > > +	touch $@
> > > +endif
> > > +
> > 
> > i guess this works without the ifneq, just
> > litters the source dir with .dirstamps in
> > case of an in-tree build.
> 
> What is the motive for having these .dirstamps at all?
> 

have to create the directories out-of-tree

but directories cannot be properr make dependencies
because make works with file mtime

..and directory mtime changes whenever something
happens in the directory, triggering a rebuild
all the time

> > > +Configuration:
> > > +  --srcdir=DIR            source directory [detected]
> > > +
> 
> Does this match standard configure behavior?
> 

i think so, official configure help is:

http://git.savannah.gnu.org/gitweb/?p=autoconf.git;a=blob;f=lib/autoconf/general.m4;h=a7f143960de44182a0139f9ab302fd652aaebc32;hb=HEAD#l1033

> > > +# Get the musl 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=.
> > > +ln -sf $srcdir/Makefile .
> 
> Is it possible to get a relative path for the srcdir rather than an
> absolute one here? I really don't like configurations that are not
> relocatable in the filesystem.

srcdir is whatever the user used for configure,
the abs path is only used to make sure we are
out-of-tree.

so building with ../musl/configure the srcdir is
../musl, i guess it ends up in the debug info,
to avoid that more complex setup is necessary
i think


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-08  2:16     ` Szabolcs Nagy
@ 2015-11-08  2:29       ` Rich Felker
  2015-11-11 22:02         ` Petr Hosek
  0 siblings, 1 reply; 56+ messages in thread
From: Rich Felker @ 2015-11-08  2:29 UTC (permalink / raw)
  To: musl

On Sun, Nov 08, 2015 at 03:16:30AM +0100, Szabolcs Nagy wrote:
> * Rich Felker <dalias@libc.org> [2015-11-07 19:43:23 -0500]:
> > On Sat, Nov 07, 2015 at 02:05:37PM +0100, Szabolcs Nagy wrote:
> > > * Petr Hosek <phosek@chromium.org> [2015-11-06 23:40:48 +0000]:
> > > > +ifneq ($(srcdir),.)
> > > > +VPATH = $(srcdir)
> > > > +$(ALL_TOOLS): tools/.dirstamp
> > > > +$(ALL_LIBS): lib/.dirstamp
> > > > +$(CRT_LIBS:lib/%=crt/%): crt/.dirstamp
> > > > +$(OBJS) $(LOBJS): $(patsubst %/,%/.dirstamp,$(sort $(dir $(OBJS))))
> > > > +$(GENH): arch/$(ARCH)/bits/.dirstamp
> > > > +include/bits: include/.dirstamp
> > > > +src/internal/version.h: src/internal/.dirstamp
> > > > +%/.dirstamp:
> > > > +	mkdir -p $*
> > > > +	touch $@
> > > > +endif
> > > > +
> > > 
> > > i guess this works without the ifneq, just
> > > litters the source dir with .dirstamps in
> > > case of an in-tree build.
> > 
> > What is the motive for having these .dirstamps at all?
> > 
> 
> have to create the directories out-of-tree
> 
> but directories cannot be properr make dependencies
> because make works with file mtime
> 
> ...and directory mtime changes whenever something
> happens in the directory, triggering a rebuild
> all the time

Use | before the dependency to add an order-only dependency (ignores
time as long as the target exists).

> > > > +Configuration:
> > > > +  --srcdir=DIR            source directory [detected]
> > > > +
> > 
> > Does this match standard configure behavior?
> > 
> 
> i think so, official configure help is:
> 
> http://git.savannah.gnu.org/gitweb/?p=autoconf.git;a=blob;f=lib/autoconf/general.m4;h=a7f143960de44182a0139f9ab302fd652aaebc32;hb=HEAD#l1033

Actually the source I'm using for the "API" (or maybe this is a "UI"?)
is the GNU Coding Standard. Not a document I like by any means, but it
does have a good implementation-agnostic spec for how configure should
work.

> > > > +# Get the musl 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=.
> > > > +ln -sf $srcdir/Makefile .
> > 
> > Is it possible to get a relative path for the srcdir rather than an
> > absolute one here? I really don't like configurations that are not
> > relocatable in the filesystem.
> 
> srcdir is whatever the user used for configure,
> the abs path is only used to make sure we are
> out-of-tree.
> 
> so building with ../musl/configure the srcdir is
> .../musl, i guess it ends up in the debug info,
> to avoid that more complex setup is necessary
> i think

Ah, I see. That's probably fine unless there's some better way
matching inodes that would be portable.

Rich


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-08  2:29       ` Rich Felker
@ 2015-11-11 22:02         ` Petr Hosek
  2015-11-11 23:08           ` Rich Felker
  0 siblings, 1 reply; 56+ messages in thread
From: Petr Hosek @ 2015-11-11 22:02 UTC (permalink / raw)
  To: musl


[-- Attachment #1.1: Type: text/plain, Size: 346 bytes --]

Attached is an update version which doesn't use VPATH and supports both
in-tree and out-of-tree builds.

One way to improve this even further would be to completely avoid the
mkasmdep and instead include the architecture specific object files into
the list of objects directly (filtering out the generic versions). Would
that be a preferred way?

[-- Attachment #1.2: Type: text/html, Size: 396 bytes --]

[-- Attachment #2: suport-out-of-tree-build.patch --]
[-- Type: text/x-patch, Size: 11982 bytes --]

From 1336bc5c1eddc43214559712f85702efba8aa864 Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek@chromium.org>
Date: Thu, 5 Nov 2015 14:51:50 -0800
Subject: [PATCH] suport out-of-tree build

this change add support for building musl outside of the source
tree. the implementation is similar to autotools where running
configure in a different folder 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. based on patch by Szabolcs Nagy.
---
 Makefile  | 93 +++++++++++++++++++++++++++++++++++++++++----------------------
 configure | 24 ++++++++++++++---
 2 files changed, 82 insertions(+), 35 deletions(-)

diff --git a/Makefile b/Makefile
index 2b21015..a022411 100644
--- 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,24 @@ includedir = $(prefix)/include
 libdir = $(prefix)/lib
 syslibdir = /lib
 
-SRCS = $(sort $(wildcard src/*/*.c arch/$(ARCH)/src/*.c))
-OBJS = $(SRCS:.c=.o)
+SRCS = $(sort $(wildcard $(srcdir)/src/*/*.c $(srcdir)/arch/$(ARCH)/src/*.c))
+OBJS = $(SRCS:$(srcdir)/%.c=%.o)
 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
+IMPH = $(addprefix $(srcdir)/, src/internal/stdio_impl.h src/internal/pthread_impl.h src/internal/libc.h)
+
+SRCS_SUB = $(wildcard $(srcdir)/src/*/$(ARCH)$(ASMSUBARCH)/*.sub)
+OBJS_SUB = $(foreach s,$(SRCS_SUB),$(dir $(patsubst $(srcdir)/%/,%,$(dir $(s))))$(notdir $(s:.sub=.o)))
+LOBJS_SUB = $(OBJS_SUB:.o=.lo)
+
+SRCS_S = $(wildcard $(srcdir)/src/*/$(ARCH)*/*.s)
+OBJS_S = $(foreach s,$(SRCS_S),$(dir $(patsubst $(srcdir)/%/,%,$(dir $(s))))$(notdir $(s:.s=.o)))
+LOBJS_S = $(OBJS_S:.o=.lo)
+
+OBJS_C = $(filter-out $(OBJS_S) $(OBJS_SUB), $(OBJS))
+LOBJS_C = $(OBJS_C:.o=.lo)
+OBJS_C += crt/crt1.o crt/Scrt1.o crt/rcrt1.o crt/crti.o crt/crtn.o
 
 LDFLAGS =
 LDFLAGS_AUTO =
@@ -32,7 +45,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) $(sort -I./src/internal -I$(srcdir)/src/internal) $(sort -I./include -I$(srcdir)/include)
 CFLAGS_ALL += $(CPPFLAGS) $(CFLAGS_AUTO) $(CFLAGS)
 CFLAGS_ALL_STATIC = $(CFLAGS_ALL)
 CFLAGS_ALL_SHARED = $(CFLAGS_ALL) -fPIC -DSHARED
@@ -41,10 +54,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) $(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)
@@ -55,6 +69,8 @@ TOOL_LIBS = lib/musl-gcc.specs
 ALL_LIBS = $(CRT_LIBS) $(STATIC_LIBS) $(SHARED_LIBS) $(EMPTY_LIBS) $(TOOL_LIBS)
 ALL_TOOLS = tools/musl-gcc
 
+SRC_DIRS = $(sort $(dir $(OBJS) $(ALL_LIBS) $(ALL_TOOLS)) arch/$(ARCH)/bits/ crt/ include/ src/internal/)
+
 WRAPCC_GCC = gcc
 WRAPCC_CLANG = clang
 
@@ -64,6 +80,17 @@ LDSO_PATHNAME = $(syslibdir)/ld-musl-$(ARCH)$(SUBARCH).so.1
 
 all: $(ALL_LIBS) $(ALL_TOOLS)
 
+$(ALL_LIBS): | lib/
+$(ALL_TOOLS): | tools/
+$(CRT_LIBS:lib/%=crt/%): | crt/
+$(OBJS) $(LOBJS): | $(sort $(dir $(OBJS)))
+$(GENH): | arch/$(ARCH)/bits/
+$(GENH_INT): | src/internal/
+include/bits: | include
+
+$(SRC_DIRS):
+	mkdir -p $@
+
 install: install-libs install-headers install-tools
 
 clean:
@@ -82,26 +109,24 @@ include/bits:
 	@test "$(ARCH)" || { echo "Please set ARCH in config.mak before running make." ; exit 1 ; }
 	ln -sf ../arch/$(ARCH)/bits $@
 
-include/bits/alltypes.h.in: include/bits
-
-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 > $@
+include/bits/alltypes.h: $(srcdir)/arch/$(ARCH)/bits/alltypes.h.in $(srcdir)/include/alltypes.h.in $(srcdir)/tools/mkalltypes.sed include/bits
+	sed -f $(srcdir)/tools/mkalltypes.sed $(srcdir)/arch/$(ARCH)/bits/alltypes.h.in $(srcdir)/include/alltypes.h.in > $@
 
-src/internal/version.h: $(wildcard VERSION .git)
-	printf '#define VERSION "%s"\n' "$$(sh tools/version.sh)" > $@
+src/internal/version.h: $(wildcard $(srcdir)/VERSION $(srcdir)/.git)
+	printf '#define VERSION "%s"\n' "$$(cd $(srcdir); sh tools/version.sh)" > $@
 
 src/internal/version.lo: src/internal/version.h
 
-crt/rcrt1.o src/ldso/dlstart.lo src/ldso/dynlink.lo: src/internal/dynlink.h arch/$(ARCH)/reloc.h
+crt/rcrt1.o src/ldso/dlstart.lo src/ldso/dynlink.lo: $(srcdir)/src/internal/dynlink.h $(srcdir)/arch/$(ARCH)/reloc.h
 
-crt/crt1.o crt/Scrt1.o crt/rcrt1.o src/ldso/dlstart.lo: $(wildcard arch/$(ARCH)/crt_arch.h)
+crt/crt1.o crt/scrt1.o crt/rcrt1.o src/ldso/dlstart.lo: $(wildcard $(srcdir)/arch/$(ARCH)/crt_arch.h)
 
-crt/rcrt1.o: src/ldso/dlstart.c
+crt/rcrt1.o: $(srcdir)/src/ldso/dlstart.c
 
 crt/Scrt1.o crt/rcrt1.o: CFLAGS_ALL += -fPIC
 
-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=%.o) $(OPTIMIZE_SRCS:$(srcdir)/%.c=%.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)
@@ -119,34 +144,35 @@ $(CRT_LIBS:lib/%=crt/%): CFLAGS_ALL += -DCRT
 # 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)
+$(dir $(patsubst $(srcdir)/%/,%,$(dir $(1))))$(notdir $(1:.s=.o)): $(1)
+$(dir $(patsubst $(srcdir)/%/,%,$(dir $(1))))$(notdir $(1:.s=.lo)): $(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
+$(OBJS_SUB): %.o:
 	$(CC) $(CFLAGS_ALL_STATIC) -c -o $@ $(dir $<)$(shell cat $<)
 
-%.o: $(ARCH)/%.s
+$(OBJS_S): %.o:
 	$(AS_CMD) $(CFLAGS_ALL_STATIC)
 
-%.o: %.c $(GENH) $(IMPH)
+$(OBJS_C): %.o: $(srcdir)/%.c $(GENH) $(IMPH)
 	$(CC) $(CFLAGS_ALL_STATIC) -c -o $@ $<
 
-%.lo: $(ARCH)$(ASMSUBARCH)/%.sub
+$(LOBJS_SUB): %.lo:
 	$(CC) $(CFLAGS_ALL_SHARED) -c -o $@ $(dir $<)$(shell cat $<)
 
-%.lo: $(ARCH)/%.s
+$(LOBJS_S): %.lo:
 	$(AS_CMD) $(CFLAGS_ALL_SHARED)
 
-%.lo: %.c $(GENH) $(IMPH)
+$(LOBJS_C): %.lo: $(srcdir)/%.c $(GENH) $(IMPH)
 	$(CC) $(CFLAGS_ALL_SHARED) -c -o $@ $<
 
 lib/libc.so: $(LOBJS)
@@ -166,14 +192,14 @@ $(EMPTY_LIBS):
 lib/%.o: crt/%.o
 	cp $< $@
 
-lib/musl-gcc.specs: tools/musl-gcc.specs.sh config.mak
+lib/musl-gcc.specs: $(srcdir)/tools/musl-gcc.specs.sh config.mak
 	sh $< "$(includedir)" "$(libdir)" "$(LDSO_PATHNAME)" > $@
 
 tools/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
+tools/%-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 $@
 
@@ -186,10 +212,13 @@ $(DESTDIR)$(libdir)/%.so: lib/%.so
 $(DESTDIR)$(libdir)/%: lib/%
 	$(INSTALL) -D -m 644 $< $@
 
+$(DESTDIR)$(includedir)/bits/%: $(srcdir)/arch/$(ARCH)/bits/%
+	$(INSTALL) -D -m 644 $< $@
+
 $(DESTDIR)$(includedir)/bits/%: arch/$(ARCH)/bits/%
 	$(INSTALL) -D -m 644 $< $@
 
-$(DESTDIR)$(includedir)/%: include/%
+$(DESTDIR)$(includedir)/%: $(srcdir)/include/%
 	$(INSTALL) -D -m 644 $< $@
 
 $(DESTDIR)$(LDSO_PATHNAME): $(DESTDIR)$(libdir)/libc.so
@@ -202,9 +231,9 @@ install-headers: $(ALL_INCLUDES:include/%=$(DESTDIR)$(includedir)/%)
 install-tools: $(ALL_TOOLS:tools/%=$(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
diff --git a/configure b/configure
index dece1d0..60eb94f 100755
--- 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,11 +184,23 @@ 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 musl 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=.
+ln -sf $srcdir/Makefile .
+
+#
 # Get a temp filename we can use
 #
 i=0
@@ -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
@@ -620,7 +637,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
@@ -643,6 +660,7 @@ cat << EOF
 ARCH = $ARCH
 SUBARCH = $SUBARCH
 ASMSUBARCH = $ASMSUBARCH
+srcdir = $srcdir
 prefix = $prefix
 exec_prefix = $exec_prefix
 bindir = $bindir
-- 
2.6.0.rc2.230.g3dd15c0


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-11 22:02         ` Petr Hosek
@ 2015-11-11 23:08           ` Rich Felker
  2015-11-12  0:01             ` Rich Felker
  2015-11-12  0:28             ` Petr Hosek
  0 siblings, 2 replies; 56+ messages in thread
From: Rich Felker @ 2015-11-11 23:08 UTC (permalink / raw)
  To: musl

On Wed, Nov 11, 2015 at 10:02:50PM +0000, Petr Hosek wrote:
> Attached is an update version which doesn't use VPATH and supports both
> in-tree and out-of-tree builds.

Is there a reason you prefer not to use VPATH?

> One way to improve this even further would be to completely avoid the
> mkasmdep and instead include the architecture specific object files into
> the list of objects directly (filtering out the generic versions). Would
> that be a preferred way?

My intent is to remove the *.sub system entirely. The current idea is
to replace it with make fragments in the arch dirs that add the
implicit rules for whatever subarch dirs should be searched.

> From 1336bc5c1eddc43214559712f85702efba8aa864 Mon Sep 17 00:00:00 2001
> From: Petr Hosek <phosek@chromium.org>
> Date: Thu, 5 Nov 2015 14:51:50 -0800
> Subject: [PATCH] suport out-of-tree build
> 
> this change add support for building musl outside of the source
> tree. the implementation is similar to autotools where running
> configure in a different folder 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. based on patch by Szabolcs Nagy.

Some quick comments here, and then more inline below:

Assuming this all works, it looks to me like you've done a remarkable
job of preserving existing behavior while making out-of-tree work.
What I'd really like to do, though, is figure out what parts of the
current build system are "unclean" for out-of-tree and improve them so
that we can simplify the build system at the same time (or at least
keep the complexity around the same level). For instance eliminating
all generated files from directories that contain non-generated files
would probably be good idea. I'm not asking you to do things like that
right away, more for input on what changes would actually be good for
achieving this so we can discuss them.

> ---
>  Makefile  | 93 +++++++++++++++++++++++++++++++++++++++++----------------------
>  configure | 24 ++++++++++++++---
>  2 files changed, 82 insertions(+), 35 deletions(-)
> 
> diff --git a/Makefile b/Makefile
> index 2b21015..a022411 100644
> --- 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,24 @@ includedir = $(prefix)/include
>  libdir = $(prefix)/lib
>  syslibdir = /lib
>  
> -SRCS = $(sort $(wildcard src/*/*.c arch/$(ARCH)/src/*.c))
> -OBJS = $(SRCS:.c=.o)
> +SRCS = $(sort $(wildcard $(srcdir)/src/*/*.c $(srcdir)/arch/$(ARCH)/src/*.c))
> +OBJS = $(SRCS:$(srcdir)/%.c=%.o)
>  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
> +IMPH = $(addprefix $(srcdir)/, src/internal/stdio_impl.h src/internal/pthread_impl.h src/internal/libc.h)
> +
> +SRCS_SUB = $(wildcard $(srcdir)/src/*/$(ARCH)$(ASMSUBARCH)/*.sub)
> +OBJS_SUB = $(foreach s,$(SRCS_SUB),$(dir $(patsubst $(srcdir)/%/,%,$(dir $(s))))$(notdir $(s:.sub=.o)))
> +LOBJS_SUB = $(OBJS_SUB:.o=.lo)
> +
> +SRCS_S = $(wildcard $(srcdir)/src/*/$(ARCH)*/*.s)
> +OBJS_S = $(foreach s,$(SRCS_S),$(dir $(patsubst $(srcdir)/%/,%,$(dir $(s))))$(notdir $(s:.s=.o)))
> +LOBJS_S = $(OBJS_S:.o=.lo)
> +
> +OBJS_C = $(filter-out $(OBJS_S) $(OBJS_SUB), $(OBJS))
> +LOBJS_C = $(OBJS_C:.o=.lo)
> +OBJS_C += crt/crt1.o crt/Scrt1.o crt/rcrt1.o crt/crti.o crt/crtn.o
>  
>  LDFLAGS =
>  LDFLAGS_AUTO =
> @@ -32,7 +45,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) $(sort -I./src/internal -I$(srcdir)/src/internal) $(sort -I./include -I$(srcdir)/include)

I'm confused about why you are applying $(sort...) to include paths.
It seems like the resulting order may differ depending on $(srcdir).
Maybe this doesn't matter, but I'd rather not rely on that.

> +SRC_DIRS = $(sort $(dir $(OBJS) $(ALL_LIBS) $(ALL_TOOLS)) arch/$(ARCH)/bits/ crt/ include/ src/internal/)
> +
>  WRAPCC_GCC = gcc
>  WRAPCC_CLANG = clang
>  
> @@ -64,6 +80,17 @@ LDSO_PATHNAME = $(syslibdir)/ld-musl-$(ARCH)$(SUBARCH).so.1
>  
>  all: $(ALL_LIBS) $(ALL_TOOLS)
>  
> +$(ALL_LIBS): | lib/
> +$(ALL_TOOLS): | tools/
> +$(CRT_LIBS:lib/%=crt/%): | crt/
> +$(OBJS) $(LOBJS): | $(sort $(dir $(OBJS)))
> +$(GENH): | arch/$(ARCH)/bits/
> +$(GENH_INT): | src/internal/
> +include/bits: | include
> +
> +$(SRC_DIRS):
> +	mkdir -p $@

This all looks nice.

> @@ -82,26 +109,24 @@ include/bits:
>  	@test "$(ARCH)" || { echo "Please set ARCH in config.mak before running make." ; exit 1 ; }
>  	ln -sf ../arch/$(ARCH)/bits $@
>  
> -include/bits/alltypes.h.in: include/bits
> -
> -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 > $@
> +include/bits/alltypes.h: $(srcdir)/arch/$(ARCH)/bits/alltypes.h.in $(srcdir)/include/alltypes.h.in $(srcdir)/tools/mkalltypes.sed include/bits
> +	sed -f $(srcdir)/tools/mkalltypes.sed $(srcdir)/arch/$(ARCH)/bits/alltypes.h.in $(srcdir)/include/alltypes.h.in > $@
>  
> -src/internal/version.h: $(wildcard VERSION .git)
> -	printf '#define VERSION "%s"\n' "$$(sh tools/version.sh)" > $@
> +src/internal/version.h: $(wildcard $(srcdir)/VERSION $(srcdir)/.git)
> +	printf '#define VERSION "%s"\n' "$$(cd $(srcdir); sh tools/version.sh)" > $@
>  
>  src/internal/version.lo: src/internal/version.h
>  
> -crt/rcrt1.o src/ldso/dlstart.lo src/ldso/dynlink.lo: src/internal/dynlink.h arch/$(ARCH)/reloc.h
> +crt/rcrt1.o src/ldso/dlstart.lo src/ldso/dynlink.lo: $(srcdir)/src/internal/dynlink.h $(srcdir)/arch/$(ARCH)/reloc.h
>  
> -crt/crt1.o crt/Scrt1.o crt/rcrt1.o src/ldso/dlstart.lo: $(wildcard arch/$(ARCH)/crt_arch.h)
> +crt/crt1.o crt/scrt1.o crt/rcrt1.o src/ldso/dlstart.lo: $(wildcard $(srcdir)/arch/$(ARCH)/crt_arch.h)

Just a note: this $(wildcard...) is obsolete. crt_arch.h is now mandatory.

>  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)
> @@ -119,34 +144,35 @@ $(CRT_LIBS:lib/%=crt/%): CFLAGS_ALL += -DCRT
>  # 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)
> +$(dir $(patsubst $(srcdir)/%/,%,$(dir $(1))))$(notdir $(1:.s=.o)): $(1)
> +$(dir $(patsubst $(srcdir)/%/,%,$(dir $(1))))$(notdir $(1:.s=.lo)): $(1)
>  endef
> -$(foreach s,$(wildcard src/*/$(ARCH)*/*.s),$(eval $(call mkasmdep,$(s))))
> +$(foreach s,$(wildcard $(srcdir)/src/*/$(ARCH)*/*.s),$(eval $(call mkasmdep,$(s))))

Was this missing the dep rules for .lo files?

> -%.o: $(ARCH)$(ASMSUBARCH)/%.sub
> +$(OBJS_SUB): %.o:
>  	$(CC) $(CFLAGS_ALL_STATIC) -c -o $@ $(dir $<)$(shell cat $<)
>  
> -%.o: $(ARCH)/%.s
> +$(OBJS_S): %.o:
>  	$(AS_CMD) $(CFLAGS_ALL_STATIC)
>  
> -%.o: %.c $(GENH) $(IMPH)
> +$(OBJS_C): %.o: $(srcdir)/%.c $(GENH) $(IMPH)
>  	$(CC) $(CFLAGS_ALL_STATIC) -c -o $@ $<
>  
> -%.lo: $(ARCH)$(ASMSUBARCH)/%.sub
> +$(LOBJS_SUB): %.lo:
>  	$(CC) $(CFLAGS_ALL_SHARED) -c -o $@ $(dir $<)$(shell cat $<)
>  
> -%.lo: $(ARCH)/%.s
> +$(LOBJS_S): %.lo:
>  	$(AS_CMD) $(CFLAGS_ALL_SHARED)
>  
> -%.lo: %.c $(GENH) $(IMPH)
> +$(LOBJS_C): %.lo: $(srcdir)/%.c $(GENH) $(IMPH)
>  	$(CC) $(CFLAGS_ALL_SHARED) -c -o $@ $<

I don't understand these rules with two :'s. I assume it's some trick
I don't yet know. But in the case of the %.s ones, the new rules have
no %.s in them... this looks wrong, no?

Rich


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-11 23:08           ` Rich Felker
@ 2015-11-12  0:01             ` Rich Felker
  2015-11-12  0:28             ` Petr Hosek
  1 sibling, 0 replies; 56+ messages in thread
From: Rich Felker @ 2015-11-12  0:01 UTC (permalink / raw)
  To: musl

On Wed, Nov 11, 2015 at 06:08:48PM -0500, Rich Felker wrote:
> > -%.o: $(ARCH)$(ASMSUBARCH)/%.sub
> > +$(OBJS_SUB): %.o:
> >  	$(CC) $(CFLAGS_ALL_STATIC) -c -o $@ $(dir $<)$(shell cat $<)
> >  
> > -%.o: $(ARCH)/%.s
> > +$(OBJS_S): %.o:
> >  	$(AS_CMD) $(CFLAGS_ALL_STATIC)
> >  
> > -%.o: %.c $(GENH) $(IMPH)
> > +$(OBJS_C): %.o: $(srcdir)/%.c $(GENH) $(IMPH)
> >  	$(CC) $(CFLAGS_ALL_STATIC) -c -o $@ $<
> >  
> > -%.lo: $(ARCH)$(ASMSUBARCH)/%.sub
> > +$(LOBJS_SUB): %.lo:
> >  	$(CC) $(CFLAGS_ALL_SHARED) -c -o $@ $(dir $<)$(shell cat $<)
> >  
> > -%.lo: $(ARCH)/%.s
> > +$(LOBJS_S): %.lo:
> >  	$(AS_CMD) $(CFLAGS_ALL_SHARED)
> >  
> > -%.lo: %.c $(GENH) $(IMPH)
> > +$(LOBJS_C): %.lo: $(srcdir)/%.c $(GENH) $(IMPH)
> >  	$(CC) $(CFLAGS_ALL_SHARED) -c -o $@ $<
> 
> I don't understand these rules with two :'s. I assume it's some trick
> I don't yet know. But in the case of the %.s ones, the new rules have
> no %.s in them... this looks wrong, no?

I found the documentation here:

https://www.gnu.org/software/make/manual/html_node/Static-Pattern.html

I also checked that the feature has been around at least back to GNU
Make 3.81.

Anyway, it looks potentially very nice/useful, but with the above
apparent-error, I'm not sure how you express the rules we need. Note
that we do need to do something new about the .sub files, so I'm not
opposed to making some structural changes to the source tree to go
along with build system overhaul. I'd just like to keep the layout
reasonable and the semantics fully represented by source tree layout
rather than by makefile logic.

Rich


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-11 23:08           ` Rich Felker
  2015-11-12  0:01             ` Rich Felker
@ 2015-11-12  0:28             ` Petr Hosek
  2015-11-12 14:50               ` Szabolcs Nagy
  1 sibling, 1 reply; 56+ messages in thread
From: Petr Hosek @ 2015-11-12  0:28 UTC (permalink / raw)
  To: musl

[-- Attachment #1: Type: text/plain, Size: 9380 bytes --]

On Wed, Nov 11, 2015 at 3:09 PM Rich Felker <dalias@libc.org> wrote:

> On Wed, Nov 11, 2015 at 10:02:50PM +0000, Petr Hosek wrote:
> > Attached is an update version which doesn't use VPATH and supports both
> > in-tree and out-of-tree builds.
>
> Is there a reason you prefer not to use VPATH?
>

This was to allow combining in tree and out-of-tree builds as mentioned buy
Szabolcs. It's not something I really need, but if there are others who
need this functionality I'll do my best to support that scenario.


> > One way to improve this even further would be to completely avoid the
> > mkasmdep and instead include the architecture specific object files into
> > the list of objects directly (filtering out the generic versions). Would
> > that be a preferred way?
>
> My intent is to remove the *.sub system entirely. The current idea is
> to replace it with make fragments in the arch dirs that add the
> implicit rules for whatever subarch dirs should be searched.
>
> > From 1336bc5c1eddc43214559712f85702efba8aa864 Mon Sep 17 00:00:00 2001
> > From: Petr Hosek <phosek@chromium.org>
> > Date: Thu, 5 Nov 2015 14:51:50 -0800
> > Subject: [PATCH] suport out-of-tree build
> >
> > this change add support for building musl outside of the source
> > tree. the implementation is similar to autotools where running
> > configure in a different folder 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. based on patch by Szabolcs Nagy.
>
> Some quick comments here, and then more inline below:
>
> Assuming this all works, it looks to me like you've done a remarkable
> job of preserving existing behavior while making out-of-tree work.
> What I'd really like to do, though, is figure out what parts of the
> current build system are "unclean" for out-of-tree and improve them so
> that we can simplify the build system at the same time (or at least
> keep the complexity around the same level). For instance eliminating
> all generated files from directories that contain non-generated files
> would probably be good idea. I'm not asking you to do things like that
> right away, more for input on what changes would actually be good for
> achieving this so we can discuss them.
>

Right now the biggest headache for me is really the *.sub system. If that
gets replaced, it should be possible to avoid some the "hacks" I had to use
around the static rules.


> > ---
> >  Makefile  | 93
> +++++++++++++++++++++++++++++++++++++++++----------------------
> >  configure | 24 ++++++++++++++---
> >  2 files changed, 82 insertions(+), 35 deletions(-)
> >
> > diff --git a/Makefile b/Makefile
> > index 2b21015..a022411 100644
> > --- 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,24 @@ includedir = $(prefix)/include
> >  libdir = $(prefix)/lib
> >  syslibdir = /lib
> >
> > -SRCS = $(sort $(wildcard src/*/*.c arch/$(ARCH)/src/*.c))
> > -OBJS = $(SRCS:.c=.o)
> > +SRCS = $(sort $(wildcard $(srcdir)/src/*/*.c
> $(srcdir)/arch/$(ARCH)/src/*.c))
> > +OBJS = $(SRCS:$(srcdir)/%.c=%.o)
> >  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
> > +IMPH = $(addprefix $(srcdir)/, src/internal/stdio_impl.h
> src/internal/pthread_impl.h src/internal/libc.h)
> > +
> > +SRCS_SUB = $(wildcard $(srcdir)/src/*/$(ARCH)$(ASMSUBARCH)/*.sub)
> > +OBJS_SUB = $(foreach s,$(SRCS_SUB),$(dir $(patsubst
> $(srcdir)/%/,%,$(dir $(s))))$(notdir $(s:.sub=.o)))
> > +LOBJS_SUB = $(OBJS_SUB:.o=.lo)
> > +
> > +SRCS_S = $(wildcard $(srcdir)/src/*/$(ARCH)*/*.s)
> > +OBJS_S = $(foreach s,$(SRCS_S),$(dir $(patsubst $(srcdir)/%/,%,$(dir
> $(s))))$(notdir $(s:.s=.o)))
> > +LOBJS_S = $(OBJS_S:.o=.lo)
> > +
> > +OBJS_C = $(filter-out $(OBJS_S) $(OBJS_SUB), $(OBJS))
> > +LOBJS_C = $(OBJS_C:.o=.lo)
> > +OBJS_C += crt/crt1.o crt/Scrt1.o crt/rcrt1.o crt/crti.o crt/crtn.o
> >
> >  LDFLAGS =
> >  LDFLAGS_AUTO =
> > @@ -32,7 +45,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) $(sort
> -I./src/internal -I$(srcdir)/src/internal) $(sort -I./include
> -I$(srcdir)/include)
>
> I'm confused about why you are applying $(sort...) to include paths.
> It seems like the resulting order may differ depending on $(srcdir).
> Maybe this doesn't matter, but I'd rather not rely on that.
>

sort here is not for sorting but for removing duplicates; in case you're
doing an in tree build, $(srcdir) will be . in which case each include path
will be listed twice, sort removes those duplicates.


> > +SRC_DIRS = $(sort $(dir $(OBJS) $(ALL_LIBS) $(ALL_TOOLS))
> arch/$(ARCH)/bits/ crt/ include/ src/internal/)
> > +
> >  WRAPCC_GCC = gcc
> >  WRAPCC_CLANG = clang
> >
> > @@ -64,6 +80,17 @@ LDSO_PATHNAME =
> $(syslibdir)/ld-musl-$(ARCH)$(SUBARCH).so.1
> >
> >  all: $(ALL_LIBS) $(ALL_TOOLS)
> >
> > +$(ALL_LIBS): | lib/
> > +$(ALL_TOOLS): | tools/
> > +$(CRT_LIBS:lib/%=crt/%): | crt/
> > +$(OBJS) $(LOBJS): | $(sort $(dir $(OBJS)))
> > +$(GENH): | arch/$(ARCH)/bits/
> > +$(GENH_INT): | src/internal/
> > +include/bits: | include
> > +
> > +$(SRC_DIRS):
> > +     mkdir -p $@
>
> This all looks nice.
>
> > @@ -82,26 +109,24 @@ include/bits:
> >       @test "$(ARCH)" || { echo "Please set ARCH in config.mak before
> running make." ; exit 1 ; }
> >       ln -sf ../arch/$(ARCH)/bits $@
> >
> > -include/bits/alltypes.h.in: include/bits
> > -
> > -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 > $@
> > +include/bits/alltypes.h: $(srcdir)/arch/$(ARCH)/bits/alltypes.h.in
> $(srcdir)/include/alltypes.h.in $(srcdir)/tools/mkalltypes.sed
> include/bits
> > +     sed -f $(srcdir)/tools/mkalltypes.sed $(srcdir)/arch/$(ARCH)/bits/
> alltypes.h.in $(srcdir)/include/alltypes.h.in > $@
> >
> > -src/internal/version.h: $(wildcard VERSION .git)
> > -     printf '#define VERSION "%s"\n' "$$(sh tools/version.sh)" > $@
> > +src/internal/version.h: $(wildcard $(srcdir)/VERSION $(srcdir)/.git)
> > +     printf '#define VERSION "%s"\n' "$$(cd $(srcdir); sh
> tools/version.sh)" > $@
> >
> >  src/internal/version.lo: src/internal/version.h
> >
> > -crt/rcrt1.o src/ldso/dlstart.lo src/ldso/dynlink.lo:
> src/internal/dynlink.h arch/$(ARCH)/reloc.h
> > +crt/rcrt1.o src/ldso/dlstart.lo src/ldso/dynlink.lo:
> $(srcdir)/src/internal/dynlink.h $(srcdir)/arch/$(ARCH)/reloc.h
> >
> > -crt/crt1.o crt/Scrt1.o crt/rcrt1.o src/ldso/dlstart.lo: $(wildcard
> arch/$(ARCH)/crt_arch.h)
> > +crt/crt1.o crt/scrt1.o crt/rcrt1.o src/ldso/dlstart.lo: $(wildcard
> $(srcdir)/arch/$(ARCH)/crt_arch.h)
>
> Just a note: this $(wildcard...) is obsolete. crt_arch.h is now mandatory.
>

I'll fix that.


> >  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)
> > @@ -119,34 +144,35 @@ $(CRT_LIBS:lib/%=crt/%): CFLAGS_ALL += -DCRT
> >  # 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)
> > +$(dir $(patsubst $(srcdir)/%/,%,$(dir $(1))))$(notdir $(1:.s=.o)): $(1)
> > +$(dir $(patsubst $(srcdir)/%/,%,$(dir $(1))))$(notdir $(1:.s=.lo)): $(1)
> >  endef
> > -$(foreach s,$(wildcard src/*/$(ARCH)*/*.s),$(eval $(call
> mkasmdep,$(s))))
> > +$(foreach s,$(wildcard $(srcdir)/src/*/$(ARCH)*/*.s),$(eval $(call
> mkasmdep,$(s))))
>
> Was this missing the dep rules for .lo files?
>

I'm not sure how this worked before, I was getting build errors without the
explicit dep rule for .lo files.


> > -%.o: $(ARCH)$(ASMSUBARCH)/%.sub
> > +$(OBJS_SUB): %.o:
> >       $(CC) $(CFLAGS_ALL_STATIC) -c -o $@ $(dir $<)$(shell cat $<)
> >
> > -%.o: $(ARCH)/%.s
> > +$(OBJS_S): %.o:
> >       $(AS_CMD) $(CFLAGS_ALL_STATIC)
> >
> > -%.o: %.c $(GENH) $(IMPH)
> > +$(OBJS_C): %.o: $(srcdir)/%.c $(GENH) $(IMPH)
> >       $(CC) $(CFLAGS_ALL_STATIC) -c -o $@ $<
> >
> > -%.lo: $(ARCH)$(ASMSUBARCH)/%.sub
> > +$(LOBJS_SUB): %.lo:
> >       $(CC) $(CFLAGS_ALL_SHARED) -c -o $@ $(dir $<)$(shell cat $<)
> >
> > -%.lo: $(ARCH)/%.s
> > +$(LOBJS_S): %.lo:
> >       $(AS_CMD) $(CFLAGS_ALL_SHARED)
> >
> > -%.lo: %.c $(GENH) $(IMPH)
> > +$(LOBJS_C): %.lo: $(srcdir)/%.c $(GENH) $(IMPH)
> >       $(CC) $(CFLAGS_ALL_SHARED) -c -o $@ $<
>
> I don't understand these rules with two :'s. I assume it's some trick
> I don't yet know. But in the case of the %.s ones, the new rules have
> no %.s in them... this looks wrong, no?
>

This is bit of hack which uses the static rules. I think we might be able
to get rid of those if we remove the *.sub system as mentioned earlier, but
this is the only way I got it to work without having a per file rule in the
current setup.

[-- Attachment #2: Type: text/html, Size: 12246 bytes --]

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-12  0:28             ` Petr Hosek
@ 2015-11-12 14:50               ` Szabolcs Nagy
  2015-11-12 20:17                 ` Petr Hosek
  0 siblings, 1 reply; 56+ messages in thread
From: Szabolcs Nagy @ 2015-11-12 14:50 UTC (permalink / raw)
  To: musl

* Petr Hosek <phosek@chromium.org> [2015-11-12 00:28:44 +0000]:
> On Wed, Nov 11, 2015 at 3:09 PM Rich Felker <dalias@libc.org> wrote:
> > On Wed, Nov 11, 2015 at 10:02:50PM +0000, Petr Hosek wrote:
> > >  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)
> > > @@ -119,34 +144,35 @@ $(CRT_LIBS:lib/%=crt/%): CFLAGS_ALL += -DCRT
> > >  # 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)
> > > +$(dir $(patsubst $(srcdir)/%/,%,$(dir $(1))))$(notdir $(1:.s=.o)): $(1)
> > > +$(dir $(patsubst $(srcdir)/%/,%,$(dir $(1))))$(notdir $(1:.s=.lo)): $(1)
> > >  endef
> > > -$(foreach s,$(wildcard src/*/$(ARCH)*/*.s),$(eval $(call
> > mkasmdep,$(s))))
> > > +$(foreach s,$(wildcard $(srcdir)/src/*/$(ARCH)*/*.s),$(eval $(call
> > mkasmdep,$(s))))
> >
> > Was this missing the dep rules for .lo files?
> >
> 
> I'm not sure how this worked before, I was getting build errors without the
> explicit dep rule for .lo files.
> 
> 
> > > -%.o: $(ARCH)$(ASMSUBARCH)/%.sub
> > > +$(OBJS_SUB): %.o:
> > >       $(CC) $(CFLAGS_ALL_STATIC) -c -o $@ $(dir $<)$(shell cat $<)
> > >
> > > -%.o: $(ARCH)/%.s
> > > +$(OBJS_S): %.o:
> > >       $(AS_CMD) $(CFLAGS_ALL_STATIC)
> > >
> > > -%.o: %.c $(GENH) $(IMPH)
> > > +$(OBJS_C): %.o: $(srcdir)/%.c $(GENH) $(IMPH)
> > >       $(CC) $(CFLAGS_ALL_STATIC) -c -o $@ $<
> > >
> > > -%.lo: $(ARCH)$(ASMSUBARCH)/%.sub
> > > +$(LOBJS_SUB): %.lo:
> > >       $(CC) $(CFLAGS_ALL_SHARED) -c -o $@ $(dir $<)$(shell cat $<)
> > >
> > > -%.lo: $(ARCH)/%.s
> > > +$(LOBJS_S): %.lo:
> > >       $(AS_CMD) $(CFLAGS_ALL_SHARED)
> > >
> > > -%.lo: %.c $(GENH) $(IMPH)
> > > +$(LOBJS_C): %.lo: $(srcdir)/%.c $(GENH) $(IMPH)
> > >       $(CC) $(CFLAGS_ALL_SHARED) -c -o $@ $<
> >
> > I don't understand these rules with two :'s. I assume it's some trick
> > I don't yet know. But in the case of the %.s ones, the new rules have
> > no %.s in them... this looks wrong, no?
> >
> 
> This is bit of hack which uses the static rules. I think we might be able
> to get rid of those if we remove the *.sub system as mentioned earlier, but
> this is the only way I got it to work without having a per file rule in the
> current setup.

i'm fine with VPATH + a make time check that in/out is not mixed

this second approach is ok if there is some solution for the
%.o: %.s rules (i guess AS_CMD only works without %.s because
mkasmdeps adds the deps).

the .sub approach is not flexible and i don't see an easy way to
encode all configury bits in the directory tree
(e.g. if we ever want to allow musl to be compiled for sse4,
avx, or other more finegrained arch extensions.. maybe .S
with #ifdefs for subarch is more flexible)


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-12 14:50               ` Szabolcs Nagy
@ 2015-11-12 20:17                 ` Petr Hosek
  2015-11-12 20:30                   ` Rich Felker
  0 siblings, 1 reply; 56+ messages in thread
From: Petr Hosek @ 2015-11-12 20:17 UTC (permalink / raw)
  To: musl

[-- Attachment #1: Type: text/plain, Size: 3449 bytes --]

There is one other issue with the VPATH solution which I just realized
while trying to make changes to the original patch: the order-only
dependencies don't work with VPATH because the directories already exist
the source directory, so we'd need to use the solution with .dirstamps.

On Thu, Nov 12, 2015 at 6:50 AM Szabolcs Nagy <nsz@port70.net> wrote:

> * Petr Hosek <phosek@chromium.org> [2015-11-12 00:28:44 +0000]:
> > On Wed, Nov 11, 2015 at 3:09 PM Rich Felker <dalias@libc.org> wrote:
> > > On Wed, Nov 11, 2015 at 10:02:50PM +0000, Petr Hosek wrote:
> > > >  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)
> > > > @@ -119,34 +144,35 @@ $(CRT_LIBS:lib/%=crt/%): CFLAGS_ALL += -DCRT
> > > >  # 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)
> > > > +$(dir $(patsubst $(srcdir)/%/,%,$(dir $(1))))$(notdir $(1:.s=.o)):
> $(1)
> > > > +$(dir $(patsubst $(srcdir)/%/,%,$(dir $(1))))$(notdir $(1:.s=.lo)):
> $(1)
> > > >  endef
> > > > -$(foreach s,$(wildcard src/*/$(ARCH)*/*.s),$(eval $(call
> > > mkasmdep,$(s))))
> > > > +$(foreach s,$(wildcard $(srcdir)/src/*/$(ARCH)*/*.s),$(eval $(call
> > > mkasmdep,$(s))))
> > >
> > > Was this missing the dep rules for .lo files?
> > >
> >
> > I'm not sure how this worked before, I was getting build errors without
> the
> > explicit dep rule for .lo files.
> >
> >
> > > > -%.o: $(ARCH)$(ASMSUBARCH)/%.sub
> > > > +$(OBJS_SUB): %.o:
> > > >       $(CC) $(CFLAGS_ALL_STATIC) -c -o $@ $(dir $<)$(shell cat $<)
> > > >
> > > > -%.o: $(ARCH)/%.s
> > > > +$(OBJS_S): %.o:
> > > >       $(AS_CMD) $(CFLAGS_ALL_STATIC)
> > > >
> > > > -%.o: %.c $(GENH) $(IMPH)
> > > > +$(OBJS_C): %.o: $(srcdir)/%.c $(GENH) $(IMPH)
> > > >       $(CC) $(CFLAGS_ALL_STATIC) -c -o $@ $<
> > > >
> > > > -%.lo: $(ARCH)$(ASMSUBARCH)/%.sub
> > > > +$(LOBJS_SUB): %.lo:
> > > >       $(CC) $(CFLAGS_ALL_SHARED) -c -o $@ $(dir $<)$(shell cat $<)
> > > >
> > > > -%.lo: $(ARCH)/%.s
> > > > +$(LOBJS_S): %.lo:
> > > >       $(AS_CMD) $(CFLAGS_ALL_SHARED)
> > > >
> > > > -%.lo: %.c $(GENH) $(IMPH)
> > > > +$(LOBJS_C): %.lo: $(srcdir)/%.c $(GENH) $(IMPH)
> > > >       $(CC) $(CFLAGS_ALL_SHARED) -c -o $@ $<
> > >
> > > I don't understand these rules with two :'s. I assume it's some trick
> > > I don't yet know. But in the case of the %.s ones, the new rules have
> > > no %.s in them... this looks wrong, no?
> > >
> >
> > This is bit of hack which uses the static rules. I think we might be able
> > to get rid of those if we remove the *.sub system as mentioned earlier,
> but
> > this is the only way I got it to work without having a per file rule in
> the
> > current setup.
>
> i'm fine with VPATH + a make time check that in/out is not mixed
>
> this second approach is ok if there is some solution for the
> %.o: %.s rules (i guess AS_CMD only works without %.s because
> mkasmdeps adds the deps).
>
> the .sub approach is not flexible and i don't see an easy way to
> encode all configury bits in the directory tree
> (e.g. if we ever want to allow musl to be compiled for sse4,
> avx, or other more finegrained arch extensions.. maybe .S
> with #ifdefs for subarch is more flexible)
>

[-- Attachment #2: Type: text/html, Size: 4537 bytes --]

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-12 20:17                 ` Petr Hosek
@ 2015-11-12 20:30                   ` Rich Felker
  2015-11-12 21:10                     ` Szabolcs Nagy
  0 siblings, 1 reply; 56+ messages in thread
From: Rich Felker @ 2015-11-12 20:30 UTC (permalink / raw)
  To: musl

On Thu, Nov 12, 2015 at 08:17:05PM +0000, Petr Hosek wrote:
> There is one other issue with the VPATH solution which I just realized
> while trying to make changes to the original patch: the order-only
> dependencies don't work with VPATH because the directories already exist
> the source directory, so we'd need to use the solution with .dirstamps.

Alternatively, configure could be responsible for making the skeleton
tree at the same time it puts a Makefile in the build dir. I don't
know if I like this approach but it's achievable with a simple find
command.

I'm still uncertain which approach (VPATH or non-VPATH) we should
take, so I'm trying to reason through the consequences of both.

Rich


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-12 20:30                   ` Rich Felker
@ 2015-11-12 21:10                     ` Szabolcs Nagy
  2015-11-12 21:52                       ` Rich Felker
  0 siblings, 1 reply; 56+ messages in thread
From: Szabolcs Nagy @ 2015-11-12 21:10 UTC (permalink / raw)
  To: musl

* Rich Felker <dalias@libc.org> [2015-11-12 15:30:48 -0500]:
> On Thu, Nov 12, 2015 at 08:17:05PM +0000, Petr Hosek wrote:
> > There is one other issue with the VPATH solution which I just realized
> > while trying to make changes to the original patch: the order-only
> > dependencies don't work with VPATH because the directories already exist
> > the source directory, so we'd need to use the solution with .dirstamps.
> 
> Alternatively, configure could be responsible for making the skeleton
> tree at the same time it puts a Makefile in the build dir. I don't
> know if I like this approach but it's achievable with a simple find
> command.
> 

that only works if no new source directories are added after configure.

> I'm still uncertain which approach (VPATH or non-VPATH) we should
> take, so I'm trying to reason through the consequences of both.
> 

depends on if we change the src/dir/arch layout and sub handling.

if we dont change anything then i think vpath with dirstamps is
the cleanest solution.

it might be worth looking at how well make handles generated rules
with foreach (instead of %.o patterns), then we can use whatever
directory layout and precedence rules.



^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-12 21:10                     ` Szabolcs Nagy
@ 2015-11-12 21:52                       ` Rich Felker
  2015-11-12 22:35                         ` Petr Hosek
  0 siblings, 1 reply; 56+ messages in thread
From: Rich Felker @ 2015-11-12 21:52 UTC (permalink / raw)
  To: musl

On Thu, Nov 12, 2015 at 10:10:24PM +0100, Szabolcs Nagy wrote:
> * Rich Felker <dalias@libc.org> [2015-11-12 15:30:48 -0500]:
> > On Thu, Nov 12, 2015 at 08:17:05PM +0000, Petr Hosek wrote:
> > > There is one other issue with the VPATH solution which I just realized
> > > while trying to make changes to the original patch: the order-only
> > > dependencies don't work with VPATH because the directories already exist
> > > the source directory, so we'd need to use the solution with .dirstamps.
> > 
> > Alternatively, configure could be responsible for making the skeleton
> > tree at the same time it puts a Makefile in the build dir. I don't
> > know if I like this approach but it's achievable with a simple find
> > command.
> > 
> 
> that only works if no new source directories are added after configure.

Yes. For active development where you don't want to re-run configure
all the time that could be a pain. I was thinking more just for
automated builds.

> > I'm still uncertain which approach (VPATH or non-VPATH) we should
> > take, so I'm trying to reason through the consequences of both.
> > 
> 
> depends on if we change the src/dir/arch layout and sub handling.
> 
> if we dont change anything then i think vpath with dirstamps is
> the cleanest solution.

I don't like it a lot, but it's not horrible, and it does solve the
problem with supporting new dirs.

> it might be worth looking at how well make handles generated rules
> with foreach (instead of %.o patterns), then we can use whatever
> directory layout and precedence rules.

I think this is very slow. The stuff I added for .sub files was a big
performance regression.

What if we put the *.o files for arch asm in the arch dirs rather than
in the main src dirs. Is there some clean way we could write a rule to
remove the base .o files from OBJS when the arch-specific .o files are
there?

Rich


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-12 21:52                       ` Rich Felker
@ 2015-11-12 22:35                         ` Petr Hosek
  2015-11-12 23:41                           ` Rich Felker
  0 siblings, 1 reply; 56+ messages in thread
From: Petr Hosek @ 2015-11-12 22:35 UTC (permalink / raw)
  To: musl

[-- Attachment #1: Type: text/plain, Size: 528 bytes --]

>
> What if we put the *.o files for arch asm in the arch dirs rather than
> in the main src dirs. Is there some clean way we could write a rule to
> remove the base .o files from OBJS when the arch-specific .o files are
> there?
>

That's what I had in mind and I've already implemented it, but I couldn't
get the *.sub files to work in that setup. However, if we replace them with
Makefile fragments as you suggested it might it might solve that problem.
Let me try that out and I'll let you know whether this is a way to go.

[-- Attachment #2: Type: text/html, Size: 743 bytes --]

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-12 22:35                         ` Petr Hosek
@ 2015-11-12 23:41                           ` Rich Felker
  2015-11-17  2:45                             ` Petr Hosek
  0 siblings, 1 reply; 56+ messages in thread
From: Rich Felker @ 2015-11-12 23:41 UTC (permalink / raw)
  To: musl

On Thu, Nov 12, 2015 at 10:35:07PM +0000, Petr Hosek wrote:
> >
> > What if we put the *.o files for arch asm in the arch dirs rather than
> > in the main src dirs. Is there some clean way we could write a rule to
> > remove the base .o files from OBJS when the arch-specific .o files are
> > there?
> 
> That's what I had in mind and I've already implemented it, but I couldn't
> get the *.sub files to work in that setup. However, if we replace them with
> Makefile fragments as you suggested it might it might solve that problem.
> Let me try that out and I'll let you know whether this is a way to go.

I don't see why the same wouldn't work for .sub files: their .o files
could be put in their own dirs. But I'd rather get rid of them still
and just have the arch provide an ordered list, for the specific
subarch, of arch and subarch .s or .c files that should replace the .c
files "above" them in the tree. Do you have good ideas for how to do
this?

Rich


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-12 23:41                           ` Rich Felker
@ 2015-11-17  2:45                             ` Petr Hosek
  2015-11-17  6:05                               ` Petr Hosek
  2015-11-17 21:00                               ` Rich Felker
  0 siblings, 2 replies; 56+ messages in thread
From: Petr Hosek @ 2015-11-17  2:45 UTC (permalink / raw)
  To: musl


[-- Attachment #1.1: Type: text/plain, Size: 1566 bytes --]

This is the final solution I've converged to. It's a bigger change than the
previous version, but the implementation is actually cleaner. In nutshell,
I've replaced all .sub files with .mk equivalent files which are included
from the Makefile. I'm then filtering out all C object files which have
assembly equivalent. This allowed me to simplify the build rules while we
still support both in-tree and out-of-tree builds. Please let me know what
you think, I'll be happy to iterate on this.

On Thu, Nov 12, 2015 at 3:41 PM Rich Felker <dalias@libc.org> wrote:

> On Thu, Nov 12, 2015 at 10:35:07PM +0000, Petr Hosek wrote:
> > >
> > > What if we put the *.o files for arch asm in the arch dirs rather than
> > > in the main src dirs. Is there some clean way we could write a rule to
> > > remove the base .o files from OBJS when the arch-specific .o files are
> > > there?
> >
> > That's what I had in mind and I've already implemented it, but I couldn't
> > get the *.sub files to work in that setup. However, if we replace them
> with
> > Makefile fragments as you suggested it might it might solve that problem.
> > Let me try that out and I'll let you know whether this is a way to go.
>
> I don't see why the same wouldn't work for .sub files: their .o files
> could be put in their own dirs. But I'd rather get rid of them still
> and just have the arch provide an ordered list, for the specific
> subarch, of arch and subarch .s or .c files that should replace the .c
> files "above" them in the tree. Do you have good ideas for how to do
> this?
>
> Rich
>

[-- Attachment #1.2: Type: text/html, Size: 1975 bytes --]

[-- Attachment #2: suport-out-of-tree-build.patch --]
[-- Type: text/x-patch, Size: 26594 bytes --]

From 8bf1353e1018a4f25c30e1ba44ec60ff7527cb8f Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek@chromium.org>
Date: Thu, 5 Nov 2015 14:51:50 -0800
Subject: [PATCH] suport out-of-tree build

this change add support for building musl outside of the source
tree. the implementation is similar to autotools where running
configure in a different folder 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. based on patch by Szabolcs Nagy.
---
 Makefile                          | 105 +++++++++++++++++++++-----------------
 configure                         |  24 +++++++--
 src/fenv/armebhf/fenv.mk          |   1 +
 src/fenv/armebhf/fenv.sub         |   1 -
 src/fenv/armhf/fenv.mk            |   1 +
 src/fenv/armhf/fenv.sub           |   1 -
 src/fenv/mips-sf/fenv.mk          |   1 +
 src/fenv/mips-sf/fenv.sub         |   1 -
 src/fenv/mipsel-sf/fenv.mk        |   1 +
 src/fenv/mipsel-sf/fenv.sub       |   1 -
 src/fenv/sh-nofpu/fenv.mk         |   1 +
 src/fenv/sh-nofpu/fenv.sub        |   1 -
 src/fenv/sheb-nofpu/fenv.mk       |   1 +
 src/fenv/sheb-nofpu/fenv.sub      |   1 -
 src/math/armebhf/fabs.mk          |   1 +
 src/math/armebhf/fabs.sub         |   1 -
 src/math/armebhf/fabsf.mk         |   1 +
 src/math/armebhf/fabsf.sub        |   1 -
 src/math/armebhf/sqrt.mk          |   1 +
 src/math/armebhf/sqrt.sub         |   1 -
 src/math/armebhf/sqrtf.mk         |   1 +
 src/math/armebhf/sqrtf.sub        |   1 -
 src/math/armhf/fabs.mk            |   1 +
 src/math/armhf/fabs.sub           |   1 -
 src/math/armhf/fabsf.mk           |   1 +
 src/math/armhf/fabsf.sub          |   1 -
 src/math/armhf/sqrt.mk            |   1 +
 src/math/armhf/sqrt.sub           |   1 -
 src/math/armhf/sqrtf.mk           |   1 +
 src/math/armhf/sqrtf.sub          |   1 -
 src/setjmp/mips-sf/longjmp.mk     |   1 +
 src/setjmp/mips-sf/longjmp.sub    |   1 -
 src/setjmp/mips-sf/setjmp.mk      |   1 +
 src/setjmp/mips-sf/setjmp.sub     |   1 -
 src/setjmp/mipsel-sf/longjmp.mk   |   1 +
 src/setjmp/mipsel-sf/longjmp.sub  |   1 -
 src/setjmp/mipsel-sf/setjmp.mk    |   1 +
 src/setjmp/mipsel-sf/setjmp.sub   |   1 -
 src/setjmp/sh-nofpu/longjmp.mk    |   1 +
 src/setjmp/sh-nofpu/longjmp.sub   |   1 -
 src/setjmp/sh-nofpu/setjmp.mk     |   1 +
 src/setjmp/sh-nofpu/setjmp.sub    |   1 -
 src/setjmp/sheb-nofpu/longjmp.mk  |   1 +
 src/setjmp/sheb-nofpu/longjmp.sub |   1 -
 src/setjmp/sheb-nofpu/setjmp.mk   |   1 +
 src/setjmp/sheb-nofpu/setjmp.sub  |   1 -
 src/string/armel/memcpy.mk        |   1 +
 src/string/armel/memcpy.sub       |   1 -
 src/string/armhf/memcpy.mk        |   1 +
 src/string/armhf/memcpy.sub       |   1 -
 50 files changed, 103 insertions(+), 74 deletions(-)
 create mode 100644 src/fenv/armebhf/fenv.mk
 delete mode 100644 src/fenv/armebhf/fenv.sub
 create mode 100644 src/fenv/armhf/fenv.mk
 delete mode 100644 src/fenv/armhf/fenv.sub
 create mode 100644 src/fenv/mips-sf/fenv.mk
 delete mode 100644 src/fenv/mips-sf/fenv.sub
 create mode 100644 src/fenv/mipsel-sf/fenv.mk
 delete mode 100644 src/fenv/mipsel-sf/fenv.sub
 create mode 100644 src/fenv/sh-nofpu/fenv.mk
 delete mode 100644 src/fenv/sh-nofpu/fenv.sub
 create mode 100644 src/fenv/sheb-nofpu/fenv.mk
 delete mode 100644 src/fenv/sheb-nofpu/fenv.sub
 create mode 100644 src/math/armebhf/fabs.mk
 delete mode 100644 src/math/armebhf/fabs.sub
 create mode 100644 src/math/armebhf/fabsf.mk
 delete mode 100644 src/math/armebhf/fabsf.sub
 create mode 100644 src/math/armebhf/sqrt.mk
 delete mode 100644 src/math/armebhf/sqrt.sub
 create mode 100644 src/math/armebhf/sqrtf.mk
 delete mode 100644 src/math/armebhf/sqrtf.sub
 create mode 100644 src/math/armhf/fabs.mk
 delete mode 100644 src/math/armhf/fabs.sub
 create mode 100644 src/math/armhf/fabsf.mk
 delete mode 100644 src/math/armhf/fabsf.sub
 create mode 100644 src/math/armhf/sqrt.mk
 delete mode 100644 src/math/armhf/sqrt.sub
 create mode 100644 src/math/armhf/sqrtf.mk
 delete mode 100644 src/math/armhf/sqrtf.sub
 create mode 100644 src/setjmp/mips-sf/longjmp.mk
 delete mode 100644 src/setjmp/mips-sf/longjmp.sub
 create mode 100644 src/setjmp/mips-sf/setjmp.mk
 delete mode 100644 src/setjmp/mips-sf/setjmp.sub
 create mode 100644 src/setjmp/mipsel-sf/longjmp.mk
 delete mode 100644 src/setjmp/mipsel-sf/longjmp.sub
 create mode 100644 src/setjmp/mipsel-sf/setjmp.mk
 delete mode 100644 src/setjmp/mipsel-sf/setjmp.sub
 create mode 100644 src/setjmp/sh-nofpu/longjmp.mk
 delete mode 100644 src/setjmp/sh-nofpu/longjmp.sub
 create mode 100644 src/setjmp/sh-nofpu/setjmp.mk
 delete mode 100644 src/setjmp/sh-nofpu/setjmp.sub
 create mode 100644 src/setjmp/sheb-nofpu/longjmp.mk
 delete mode 100644 src/setjmp/sheb-nofpu/longjmp.sub
 create mode 100644 src/setjmp/sheb-nofpu/setjmp.mk
 delete mode 100644 src/setjmp/sheb-nofpu/setjmp.sub
 create mode 100644 src/string/armel/memcpy.mk
 delete mode 100644 src/string/armel/memcpy.sub
 create mode 100644 src/string/armhf/memcpy.mk
 delete mode 100644 src/string/armhf/memcpy.sub

diff --git a/Makefile b/Makefile
index 2b21015..05cb650 100644
--- 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,19 @@ includedir = $(prefix)/include
 libdir = $(prefix)/lib
 syslibdir = /lib
 
-SRCS = $(sort $(wildcard src/*/*.c arch/$(ARCH)/src/*.c))
-OBJS = $(SRCS:.c=.o)
-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
+IMPH = $(addprefix $(srcdir)/, src/internal/stdio_impl.h src/internal/pthread_impl.h src/internal/libc.h)
+
+ASM_SRCS = $(wildcard $(srcdir)/src/*/$(ARCH)/*.s)
+ASM_OBJS = $(ASM_SRCS:$(srcdir)/%.s=%.o)
+ASM_LOBJS = $(ASM_OBJS:.o=.lo)
+
+SRCS = $(sort $(wildcard $(srcdir)/src/*/*.c $(srcdir)/arch/$(ARCH)/src/*.c))
+EXCLUDE_OBJS = $(foreach s,$(ASM_SRCS),$(dir $(patsubst $(srcdir)/%/,%,$(dir $(s))))$(notdir $(s:.s=.o)))
+EXCLUDE_LOBJS = $(EXCLUDE_OBJS:.o=.lo)
+OBJS = $(filter-out $(EXCLUDE_OBJS),$(SRCS:$(srcdir)/%.c=%.o)) crt/crt1.o crt/Scrt1.o crt/rcrt1.o crt/crti.o crt/crtn.o
+LOBJS = $(filter-out $(EXCLUDE_LOBJS),$(SRCS:$(srcdir)/%.c=%.lo))
 
 LDFLAGS =
 LDFLAGS_AUTO =
@@ -32,7 +40,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) $(sort -I./src/internal -I$(srcdir)/src/internal) $(sort -I./include -I$(srcdir)/include)
 CFLAGS_ALL += $(CPPFLAGS) $(CFLAGS_AUTO) $(CFLAGS)
 CFLAGS_ALL_STATIC = $(CFLAGS_ALL)
 CFLAGS_ALL_SHARED = $(CFLAGS_ALL) -fPIC -DSHARED
@@ -41,10 +49,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) $(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)
@@ -55,6 +64,8 @@ TOOL_LIBS = lib/musl-gcc.specs
 ALL_LIBS = $(CRT_LIBS) $(STATIC_LIBS) $(SHARED_LIBS) $(EMPTY_LIBS) $(TOOL_LIBS)
 ALL_TOOLS = tools/musl-gcc
 
+SRC_DIRS = $(sort $(dir $(ASM_OBJS) $(OBJS) $(ALL_LIBS) $(ALL_TOOLS)) arch/$(ARCH)/bits/ crt/ include/ src/internal/)
+
 WRAPCC_GCC = gcc
 WRAPCC_CLANG = clang
 
@@ -64,6 +75,19 @@ LDSO_PATHNAME = $(syslibdir)/ld-musl-$(ARCH)$(SUBARCH).so.1
 
 all: $(ALL_LIBS) $(ALL_TOOLS)
 
+-include $(srcdir)/src/*/$(ARCH)$(ASMSUBARCH)/*.mk
+
+$(ALL_LIBS): | lib/
+$(ALL_TOOLS): | tools/
+$(CRT_LIBS:lib/%=crt/%): | crt/
+$(ASM_OBJS) $(ASM_LOBJS) $(OBJS) $(LOBJS): | $(sort $(dir $(ASM_OBJS) $(OBJS)))
+$(GENH): | arch/$(ARCH)/bits/
+$(GENH_INT): | src/internal/
+include/bits: | include
+
+$(SRC_DIRS):
+	mkdir -p $@
+
 install: install-libs install-headers install-tools
 
 clean:
@@ -82,26 +106,24 @@ include/bits:
 	@test "$(ARCH)" || { echo "Please set ARCH in config.mak before running make." ; exit 1 ; }
 	ln -sf ../arch/$(ARCH)/bits $@
 
-include/bits/alltypes.h.in: include/bits
+include/bits/alltypes.h: $(srcdir)/arch/$(ARCH)/bits/alltypes.h.in $(srcdir)/include/alltypes.h.in $(srcdir)/tools/mkalltypes.sed include/bits
+	sed -f $(srcdir)/tools/mkalltypes.sed $(srcdir)/arch/$(ARCH)/bits/alltypes.h.in $(srcdir)/include/alltypes.h.in > $@
 
-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 > $@
-
-src/internal/version.h: $(wildcard VERSION .git)
-	printf '#define VERSION "%s"\n' "$$(sh tools/version.sh)" > $@
+src/internal/version.h: $(wildcard $(srcdir)/VERSION $(srcdir)/.git)
+	printf '#define VERSION "%s"\n' "$$(cd $(srcdir); sh tools/version.sh)" > $@
 
 src/internal/version.lo: src/internal/version.h
 
-crt/rcrt1.o src/ldso/dlstart.lo src/ldso/dynlink.lo: src/internal/dynlink.h arch/$(ARCH)/reloc.h
+crt/rcrt1.o src/ldso/dlstart.lo src/ldso/dynlink.lo: $(srcdir)/src/internal/dynlink.h $(srcdir)/arch/$(ARCH)/reloc.h
 
-crt/crt1.o crt/Scrt1.o crt/rcrt1.o src/ldso/dlstart.lo: $(wildcard arch/$(ARCH)/crt_arch.h)
+crt/crt1.o crt/scrt1.o crt/rcrt1.o src/ldso/dlstart.lo: $(srcdir)/arch/$(ARCH)/crt_arch.h
 
-crt/rcrt1.o: src/ldso/dlstart.c
+crt/rcrt1.o: $(srcdir)/src/ldso/dlstart.c
 
 crt/Scrt1.o crt/rcrt1.o: CFLAGS_ALL += -fPIC
 
-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=%.o) $(OPTIMIZE_SRCS:$(srcdir)/%.c=%.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)
@@ -115,48 +137,34 @@ $(NOSSP_SRCS:%.c=%.o) $(NOSSP_SRCS:%.c=%.lo): CFLAGS_ALL += $(CFLAGS_NOSSP)
 
 $(CRT_LIBS:lib/%=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)
-endef
-$(foreach s,$(wildcard 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 $<)
-
-%.o: $(ARCH)/%.s
+$(ASM_OBJS): %.o: $(srcdir)/%.s
 	$(AS_CMD) $(CFLAGS_ALL_STATIC)
 
-%.o: %.c $(GENH) $(IMPH)
+$(OBJS): %.o: $(srcdir)/%.c $(GENH) $(IMPH)
 	$(CC) $(CFLAGS_ALL_STATIC) -c -o $@ $<
 
-%.lo: $(ARCH)$(ASMSUBARCH)/%.sub
-	$(CC) $(CFLAGS_ALL_SHARED) -c -o $@ $(dir $<)$(shell cat $<)
-
-%.lo: $(ARCH)/%.s
+$(ASM_LOBJS): %.lo: $(srcdir)/%.s
 	$(AS_CMD) $(CFLAGS_ALL_SHARED)
 
-%.lo: %.c $(GENH) $(IMPH)
+$(LOBJS): %.lo: $(srcdir)/%.c $(GENH) $(IMPH)
 	$(CC) $(CFLAGS_ALL_SHARED) -c -o $@ $<
 
-lib/libc.so: $(LOBJS)
+lib/libc.so: $(LOBJS) $(ASM_LOBJS)
 	$(CC) $(CFLAGS_ALL_SHARED) $(LDFLAGS_ALL) -nostdlib -shared \
 	-Wl,-e,_dlstart -Wl,-Bsymbolic-functions \
-	-o $@ $(LOBJS) $(LIBCC)
+	-o $@ $(LOBJS) $(ASM_LOBJS) $(LIBCC)
 
-lib/libc.a: $(OBJS)
+lib/libc.a: $(OBJS) $(ASM_OBJS)
 	rm -f $@
-	$(AR) rc $@ $(OBJS)
+	$(AR) rc $@ $(OBJS) $(ASM_OBJS)
 	$(RANLIB) $@
 
 $(EMPTY_LIBS):
@@ -166,14 +174,14 @@ $(EMPTY_LIBS):
 lib/%.o: crt/%.o
 	cp $< $@
 
-lib/musl-gcc.specs: tools/musl-gcc.specs.sh config.mak
+lib/musl-gcc.specs: $(srcdir)/tools/musl-gcc.specs.sh config.mak
 	sh $< "$(includedir)" "$(libdir)" "$(LDSO_PATHNAME)" > $@
 
 tools/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
+tools/%-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 $@
 
@@ -186,10 +194,13 @@ $(DESTDIR)$(libdir)/%.so: lib/%.so
 $(DESTDIR)$(libdir)/%: lib/%
 	$(INSTALL) -D -m 644 $< $@
 
+$(DESTDIR)$(includedir)/bits/%: $(srcdir)/arch/$(ARCH)/bits/%
+	$(INSTALL) -D -m 644 $< $@
+
 $(DESTDIR)$(includedir)/bits/%: arch/$(ARCH)/bits/%
 	$(INSTALL) -D -m 644 $< $@
 
-$(DESTDIR)$(includedir)/%: include/%
+$(DESTDIR)$(includedir)/%: $(srcdir)/include/%
 	$(INSTALL) -D -m 644 $< $@
 
 $(DESTDIR)$(LDSO_PATHNAME): $(DESTDIR)$(libdir)/libc.so
@@ -202,9 +213,9 @@ install-headers: $(ALL_INCLUDES:include/%=$(DESTDIR)$(includedir)/%)
 install-tools: $(ALL_TOOLS:tools/%=$(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
diff --git a/configure b/configure
index dece1d0..60eb94f 100755
--- 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,11 +184,23 @@ 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 musl 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=.
+ln -sf $srcdir/Makefile .
+
+#
 # Get a temp filename we can use
 #
 i=0
@@ -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
@@ -620,7 +637,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
@@ -643,6 +660,7 @@ cat << EOF
 ARCH = $ARCH
 SUBARCH = $SUBARCH
 ASMSUBARCH = $ASMSUBARCH
+srcdir = $srcdir
 prefix = $prefix
 exec_prefix = $exec_prefix
 bindir = $bindir
diff --git a/src/fenv/armebhf/fenv.mk b/src/fenv/armebhf/fenv.mk
new file mode 100644
index 0000000..769320f
--- /dev/null
+++ b/src/fenv/armebhf/fenv.mk
@@ -0,0 +1 @@
+ASM_SRCS += $(srcdir)/src/fenv/armhf/fenv.s
diff --git a/src/fenv/armebhf/fenv.sub b/src/fenv/armebhf/fenv.sub
deleted file mode 100644
index 5281e40..0000000
--- a/src/fenv/armebhf/fenv.sub
+++ /dev/null
@@ -1 +0,0 @@
-../armhf/fenv.s
diff --git a/src/fenv/armhf/fenv.mk b/src/fenv/armhf/fenv.mk
new file mode 100644
index 0000000..769320f
--- /dev/null
+++ b/src/fenv/armhf/fenv.mk
@@ -0,0 +1 @@
+ASM_SRCS += $(srcdir)/src/fenv/armhf/fenv.s
diff --git a/src/fenv/armhf/fenv.sub b/src/fenv/armhf/fenv.sub
deleted file mode 100644
index ec559cd..0000000
--- a/src/fenv/armhf/fenv.sub
+++ /dev/null
@@ -1 +0,0 @@
-fenv.s
diff --git a/src/fenv/mips-sf/fenv.mk b/src/fenv/mips-sf/fenv.mk
new file mode 100644
index 0000000..96b54d2
--- /dev/null
+++ b/src/fenv/mips-sf/fenv.mk
@@ -0,0 +1 @@
+SRCS += $(srcdir)/src/fenv/fenv.c
diff --git a/src/fenv/mips-sf/fenv.sub b/src/fenv/mips-sf/fenv.sub
deleted file mode 100644
index 9cafca5..0000000
--- a/src/fenv/mips-sf/fenv.sub
+++ /dev/null
@@ -1 +0,0 @@
-../fenv.c
diff --git a/src/fenv/mipsel-sf/fenv.mk b/src/fenv/mipsel-sf/fenv.mk
new file mode 100644
index 0000000..96b54d2
--- /dev/null
+++ b/src/fenv/mipsel-sf/fenv.mk
@@ -0,0 +1 @@
+SRCS += $(srcdir)/src/fenv/fenv.c
diff --git a/src/fenv/mipsel-sf/fenv.sub b/src/fenv/mipsel-sf/fenv.sub
deleted file mode 100644
index 9cafca5..0000000
--- a/src/fenv/mipsel-sf/fenv.sub
+++ /dev/null
@@ -1 +0,0 @@
-../fenv.c
diff --git a/src/fenv/sh-nofpu/fenv.mk b/src/fenv/sh-nofpu/fenv.mk
new file mode 100644
index 0000000..96b54d2
--- /dev/null
+++ b/src/fenv/sh-nofpu/fenv.mk
@@ -0,0 +1 @@
+SRCS += $(srcdir)/src/fenv/fenv.c
diff --git a/src/fenv/sh-nofpu/fenv.sub b/src/fenv/sh-nofpu/fenv.sub
deleted file mode 100644
index 9cafca5..0000000
--- a/src/fenv/sh-nofpu/fenv.sub
+++ /dev/null
@@ -1 +0,0 @@
-../fenv.c
diff --git a/src/fenv/sheb-nofpu/fenv.mk b/src/fenv/sheb-nofpu/fenv.mk
new file mode 100644
index 0000000..96b54d2
--- /dev/null
+++ b/src/fenv/sheb-nofpu/fenv.mk
@@ -0,0 +1 @@
+SRCS += $(srcdir)/src/fenv/fenv.c
diff --git a/src/fenv/sheb-nofpu/fenv.sub b/src/fenv/sheb-nofpu/fenv.sub
deleted file mode 100644
index 9cafca5..0000000
--- a/src/fenv/sheb-nofpu/fenv.sub
+++ /dev/null
@@ -1 +0,0 @@
-../fenv.c
diff --git a/src/math/armebhf/fabs.mk b/src/math/armebhf/fabs.mk
new file mode 100644
index 0000000..836bbd6
--- /dev/null
+++ b/src/math/armebhf/fabs.mk
@@ -0,0 +1 @@
+ASM_SRCS += $(srcdir)/src/math/armhf/fabs.s
diff --git a/src/math/armebhf/fabs.sub b/src/math/armebhf/fabs.sub
deleted file mode 100644
index 10d9fb7..0000000
--- a/src/math/armebhf/fabs.sub
+++ /dev/null
@@ -1 +0,0 @@
-../armhf/fabs.s
diff --git a/src/math/armebhf/fabsf.mk b/src/math/armebhf/fabsf.mk
new file mode 100644
index 0000000..3640a9d
--- /dev/null
+++ b/src/math/armebhf/fabsf.mk
@@ -0,0 +1 @@
+ASM_SRCS += $(srcdir)/src/math/armhf/fabsf.s
diff --git a/src/math/armebhf/fabsf.sub b/src/math/armebhf/fabsf.sub
deleted file mode 100644
index 940b20b..0000000
--- a/src/math/armebhf/fabsf.sub
+++ /dev/null
@@ -1 +0,0 @@
-../armhf/fabsf.s
diff --git a/src/math/armebhf/sqrt.mk b/src/math/armebhf/sqrt.mk
new file mode 100644
index 0000000..58ae464
--- /dev/null
+++ b/src/math/armebhf/sqrt.mk
@@ -0,0 +1 @@
+ASM_SRCS += $(srcdir)/src/math/armhf/sqrt.s
diff --git a/src/math/armebhf/sqrt.sub b/src/math/armebhf/sqrt.sub
deleted file mode 100644
index de2be11..0000000
--- a/src/math/armebhf/sqrt.sub
+++ /dev/null
@@ -1 +0,0 @@
-../armhf/sqrt.s
diff --git a/src/math/armebhf/sqrtf.mk b/src/math/armebhf/sqrtf.mk
new file mode 100644
index 0000000..49d9ed3
--- /dev/null
+++ b/src/math/armebhf/sqrtf.mk
@@ -0,0 +1 @@
+ASM_SRCS += $(srcdir)/src/math/armhf/sqrtf.s
diff --git a/src/math/armebhf/sqrtf.sub b/src/math/armebhf/sqrtf.sub
deleted file mode 100644
index 150ab9c..0000000
--- a/src/math/armebhf/sqrtf.sub
+++ /dev/null
@@ -1 +0,0 @@
-../armhf/sqrtf.s
diff --git a/src/math/armhf/fabs.mk b/src/math/armhf/fabs.mk
new file mode 100644
index 0000000..836bbd6
--- /dev/null
+++ b/src/math/armhf/fabs.mk
@@ -0,0 +1 @@
+ASM_SRCS += $(srcdir)/src/math/armhf/fabs.s
diff --git a/src/math/armhf/fabs.sub b/src/math/armhf/fabs.sub
deleted file mode 100644
index 99e8740..0000000
--- a/src/math/armhf/fabs.sub
+++ /dev/null
@@ -1 +0,0 @@
-fabs.s
diff --git a/src/math/armhf/fabsf.mk b/src/math/armhf/fabsf.mk
new file mode 100644
index 0000000..3640a9d
--- /dev/null
+++ b/src/math/armhf/fabsf.mk
@@ -0,0 +1 @@
+ASM_SRCS += $(srcdir)/src/math/armhf/fabsf.s
diff --git a/src/math/armhf/fabsf.sub b/src/math/armhf/fabsf.sub
deleted file mode 100644
index c04638a..0000000
--- a/src/math/armhf/fabsf.sub
+++ /dev/null
@@ -1 +0,0 @@
-fabsf.s
diff --git a/src/math/armhf/sqrt.mk b/src/math/armhf/sqrt.mk
new file mode 100644
index 0000000..58ae464
--- /dev/null
+++ b/src/math/armhf/sqrt.mk
@@ -0,0 +1 @@
+ASM_SRCS += $(srcdir)/src/math/armhf/sqrt.s
diff --git a/src/math/armhf/sqrt.sub b/src/math/armhf/sqrt.sub
deleted file mode 100644
index 25de7cf..0000000
--- a/src/math/armhf/sqrt.sub
+++ /dev/null
@@ -1 +0,0 @@
-sqrt.s
diff --git a/src/math/armhf/sqrtf.mk b/src/math/armhf/sqrtf.mk
new file mode 100644
index 0000000..49d9ed3
--- /dev/null
+++ b/src/math/armhf/sqrtf.mk
@@ -0,0 +1 @@
+ASM_SRCS += $(srcdir)/src/math/armhf/sqrtf.s
diff --git a/src/math/armhf/sqrtf.sub b/src/math/armhf/sqrtf.sub
deleted file mode 100644
index 3bcbac8..0000000
--- a/src/math/armhf/sqrtf.sub
+++ /dev/null
@@ -1 +0,0 @@
-sqrtf.s
diff --git a/src/setjmp/mips-sf/longjmp.mk b/src/setjmp/mips-sf/longjmp.mk
new file mode 100644
index 0000000..fdc926f
--- /dev/null
+++ b/src/setjmp/mips-sf/longjmp.mk
@@ -0,0 +1 @@
+ASM_SRCS += $(srcdir)/src/setjmp/mips-sf/longjmp.s
diff --git a/src/setjmp/mips-sf/longjmp.sub b/src/setjmp/mips-sf/longjmp.sub
deleted file mode 100644
index e80331b..0000000
--- a/src/setjmp/mips-sf/longjmp.sub
+++ /dev/null
@@ -1 +0,0 @@
-longjmp.s
diff --git a/src/setjmp/mips-sf/setjmp.mk b/src/setjmp/mips-sf/setjmp.mk
new file mode 100644
index 0000000..2a1ad3b
--- /dev/null
+++ b/src/setjmp/mips-sf/setjmp.mk
@@ -0,0 +1 @@
+ASM_SRCS += $(srcdir)/src/setjmp/mips-sf/setjmp.s
diff --git a/src/setjmp/mips-sf/setjmp.sub b/src/setjmp/mips-sf/setjmp.sub
deleted file mode 100644
index b7ad221..0000000
--- a/src/setjmp/mips-sf/setjmp.sub
+++ /dev/null
@@ -1 +0,0 @@
-setjmp.s
diff --git a/src/setjmp/mipsel-sf/longjmp.mk b/src/setjmp/mipsel-sf/longjmp.mk
new file mode 100644
index 0000000..fdc926f
--- /dev/null
+++ b/src/setjmp/mipsel-sf/longjmp.mk
@@ -0,0 +1 @@
+ASM_SRCS += $(srcdir)/src/setjmp/mips-sf/longjmp.s
diff --git a/src/setjmp/mipsel-sf/longjmp.sub b/src/setjmp/mipsel-sf/longjmp.sub
deleted file mode 100644
index 6907202..0000000
--- a/src/setjmp/mipsel-sf/longjmp.sub
+++ /dev/null
@@ -1 +0,0 @@
-../mips-sf/longjmp.s
diff --git a/src/setjmp/mipsel-sf/setjmp.mk b/src/setjmp/mipsel-sf/setjmp.mk
new file mode 100644
index 0000000..2a1ad3b
--- /dev/null
+++ b/src/setjmp/mipsel-sf/setjmp.mk
@@ -0,0 +1 @@
+ASM_SRCS += $(srcdir)/src/setjmp/mips-sf/setjmp.s
diff --git a/src/setjmp/mipsel-sf/setjmp.sub b/src/setjmp/mipsel-sf/setjmp.sub
deleted file mode 100644
index 9917475..0000000
--- a/src/setjmp/mipsel-sf/setjmp.sub
+++ /dev/null
@@ -1 +0,0 @@
-../mips-sf/setjmp.s
diff --git a/src/setjmp/sh-nofpu/longjmp.mk b/src/setjmp/sh-nofpu/longjmp.mk
new file mode 100644
index 0000000..844c7e4
--- /dev/null
+++ b/src/setjmp/sh-nofpu/longjmp.mk
@@ -0,0 +1 @@
+ASM_SRCS += $(srcdir)/src/setjmp/sh-nofpu/longjmp.s
diff --git a/src/setjmp/sh-nofpu/longjmp.sub b/src/setjmp/sh-nofpu/longjmp.sub
deleted file mode 100644
index e80331b..0000000
--- a/src/setjmp/sh-nofpu/longjmp.sub
+++ /dev/null
@@ -1 +0,0 @@
-longjmp.s
diff --git a/src/setjmp/sh-nofpu/setjmp.mk b/src/setjmp/sh-nofpu/setjmp.mk
new file mode 100644
index 0000000..a97d797
--- /dev/null
+++ b/src/setjmp/sh-nofpu/setjmp.mk
@@ -0,0 +1 @@
+ASM_SRCS += $(srcdir)/src/setjmp/sh-nofpu/setjmp.s
diff --git a/src/setjmp/sh-nofpu/setjmp.sub b/src/setjmp/sh-nofpu/setjmp.sub
deleted file mode 100644
index b7ad221..0000000
--- a/src/setjmp/sh-nofpu/setjmp.sub
+++ /dev/null
@@ -1 +0,0 @@
-setjmp.s
diff --git a/src/setjmp/sheb-nofpu/longjmp.mk b/src/setjmp/sheb-nofpu/longjmp.mk
new file mode 100644
index 0000000..844c7e4
--- /dev/null
+++ b/src/setjmp/sheb-nofpu/longjmp.mk
@@ -0,0 +1 @@
+ASM_SRCS += $(srcdir)/src/setjmp/sh-nofpu/longjmp.s
diff --git a/src/setjmp/sheb-nofpu/longjmp.sub b/src/setjmp/sheb-nofpu/longjmp.sub
deleted file mode 100644
index 62fcd2b..0000000
--- a/src/setjmp/sheb-nofpu/longjmp.sub
+++ /dev/null
@@ -1 +0,0 @@
-../sh-nofpu/longjmp.s
diff --git a/src/setjmp/sheb-nofpu/setjmp.mk b/src/setjmp/sheb-nofpu/setjmp.mk
new file mode 100644
index 0000000..a97d797
--- /dev/null
+++ b/src/setjmp/sheb-nofpu/setjmp.mk
@@ -0,0 +1 @@
+ASM_SRCS += $(srcdir)/src/setjmp/sh-nofpu/setjmp.s
diff --git a/src/setjmp/sheb-nofpu/setjmp.sub b/src/setjmp/sheb-nofpu/setjmp.sub
deleted file mode 100644
index a5bb294..0000000
--- a/src/setjmp/sheb-nofpu/setjmp.sub
+++ /dev/null
@@ -1 +0,0 @@
-../sh-nofpu/setjmp.s
diff --git a/src/string/armel/memcpy.mk b/src/string/armel/memcpy.mk
new file mode 100644
index 0000000..ce03f62
--- /dev/null
+++ b/src/string/armel/memcpy.mk
@@ -0,0 +1 @@
+ASM_SRCS += $(srcdir)/src/string/armel/memcpy.s
diff --git a/src/string/armel/memcpy.sub b/src/string/armel/memcpy.sub
deleted file mode 100644
index 543f583..0000000
--- a/src/string/armel/memcpy.sub
+++ /dev/null
@@ -1 +0,0 @@
-memcpy.s
diff --git a/src/string/armhf/memcpy.mk b/src/string/armhf/memcpy.mk
new file mode 100644
index 0000000..ce03f62
--- /dev/null
+++ b/src/string/armhf/memcpy.mk
@@ -0,0 +1 @@
+ASM_SRCS += $(srcdir)/src/string/armel/memcpy.s
diff --git a/src/string/armhf/memcpy.sub b/src/string/armhf/memcpy.sub
deleted file mode 100644
index add0590..0000000
--- a/src/string/armhf/memcpy.sub
+++ /dev/null
@@ -1 +0,0 @@
-../armel/memcpy.s
-- 
2.6.0.rc2.230.g3dd15c0


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-17  2:45                             ` Petr Hosek
@ 2015-11-17  6:05                               ` Petr Hosek
  2015-11-17 19:51                                 ` Szabolcs Nagy
  2015-11-17 21:00                               ` Rich Felker
  1 sibling, 1 reply; 56+ messages in thread
From: Petr Hosek @ 2015-11-17  6:05 UTC (permalink / raw)
  To: musl


[-- Attachment #1.1: Type: text/plain, Size: 1773 bytes --]

One minor improvement, we obviously don't need more than one .mk file per
directory.

On Mon, Nov 16, 2015 at 6:45 PM Petr Hosek <phosek@chromium.org> wrote:

> This is the final solution I've converged to. It's a bigger change than
> the previous version, but the implementation is actually cleaner. In
> nutshell, I've replaced all .sub files with .mk equivalent files which are
> included from the Makefile. I'm then filtering out all C object files which
> have assembly equivalent. This allowed me to simplify the build rules while
> we still support both in-tree and out-of-tree builds. Please let me know
> what you think, I'll be happy to iterate on this.
>
> On Thu, Nov 12, 2015 at 3:41 PM Rich Felker <dalias@libc.org> wrote:
>
>> On Thu, Nov 12, 2015 at 10:35:07PM +0000, Petr Hosek wrote:
>> > >
>> > > What if we put the *.o files for arch asm in the arch dirs rather than
>> > > in the main src dirs. Is there some clean way we could write a rule to
>> > > remove the base .o files from OBJS when the arch-specific .o files are
>> > > there?
>> >
>> > That's what I had in mind and I've already implemented it, but I
>> couldn't
>> > get the *.sub files to work in that setup. However, if we replace them
>> with
>> > Makefile fragments as you suggested it might it might solve that
>> problem.
>> > Let me try that out and I'll let you know whether this is a way to go.
>>
>> I don't see why the same wouldn't work for .sub files: their .o files
>> could be put in their own dirs. But I'd rather get rid of them still
>> and just have the arch provide an ordered list, for the specific
>> subarch, of arch and subarch .s or .c files that should replace the .c
>> files "above" them in the tree. Do you have good ideas for how to do
>> this?
>>
>> Rich
>>
>

[-- Attachment #1.2: Type: text/html, Size: 2418 bytes --]

[-- Attachment #2: suport-out-of-tree-build.patch --]
[-- Type: text/x-patch, Size: 23862 bytes --]

From be9c05003e8882fc10f0621734160214cde79a7e Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek@chromium.org>
Date: Thu, 5 Nov 2015 14:51:50 -0800
Subject: [PATCH] suport out-of-tree build

this change add support for building musl outside of the source
tree. the implementation is similar to autotools where running
configure in a different folder 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. based on patch by Szabolcs Nagy.
---
 Makefile                          | 105 +++++++++++++++++++++-----------------
 configure                         |  24 +++++++--
 src/fenv/armebhf/fenv.mk          |   1 +
 src/fenv/armebhf/fenv.sub         |   1 -
 src/fenv/armhf/fenv.mk            |   1 +
 src/fenv/armhf/fenv.sub           |   1 -
 src/fenv/mips-sf/fenv.mk          |   1 +
 src/fenv/mips-sf/fenv.sub         |   1 -
 src/fenv/mipsel-sf/fenv.mk        |   1 +
 src/fenv/mipsel-sf/fenv.sub       |   1 -
 src/fenv/sh-nofpu/fenv.mk         |   1 +
 src/fenv/sh-nofpu/fenv.sub        |   1 -
 src/fenv/sheb-nofpu/fenv.mk       |   1 +
 src/fenv/sheb-nofpu/fenv.sub      |   1 -
 src/math/armebhf/fabs.sub         |   1 -
 src/math/armebhf/fabsf.sub        |   1 -
 src/math/armebhf/math.mk          |   4 ++
 src/math/armebhf/sqrt.sub         |   1 -
 src/math/armebhf/sqrtf.sub        |   1 -
 src/math/armhf/fabs.sub           |   1 -
 src/math/armhf/fabsf.sub          |   1 -
 src/math/armhf/math.mk            |   4 ++
 src/math/armhf/sqrt.sub           |   1 -
 src/math/armhf/sqrtf.sub          |   1 -
 src/setjmp/mips-sf/longjmp.sub    |   1 -
 src/setjmp/mips-sf/setjmp.mk      |   2 +
 src/setjmp/mips-sf/setjmp.sub     |   1 -
 src/setjmp/mipsel-sf/longjmp.sub  |   1 -
 src/setjmp/mipsel-sf/setjmp.mk    |   2 +
 src/setjmp/mipsel-sf/setjmp.sub   |   1 -
 src/setjmp/sh-nofpu/longjmp.sub   |   1 -
 src/setjmp/sh-nofpu/setjmp.mk     |   2 +
 src/setjmp/sh-nofpu/setjmp.sub    |   1 -
 src/setjmp/sheb-nofpu/longjmp.sub |   1 -
 src/setjmp/sheb-nofpu/setjmp.mk   |   2 +
 src/setjmp/sheb-nofpu/setjmp.sub  |   1 -
 src/string/armel/memcpy.mk        |   1 +
 src/string/armel/memcpy.sub       |   1 -
 src/string/armhf/memcpy.mk        |   1 +
 src/string/armhf/memcpy.sub       |   1 -
 40 files changed, 103 insertions(+), 74 deletions(-)
 create mode 100644 src/fenv/armebhf/fenv.mk
 delete mode 100644 src/fenv/armebhf/fenv.sub
 create mode 100644 src/fenv/armhf/fenv.mk
 delete mode 100644 src/fenv/armhf/fenv.sub
 create mode 100644 src/fenv/mips-sf/fenv.mk
 delete mode 100644 src/fenv/mips-sf/fenv.sub
 create mode 100644 src/fenv/mipsel-sf/fenv.mk
 delete mode 100644 src/fenv/mipsel-sf/fenv.sub
 create mode 100644 src/fenv/sh-nofpu/fenv.mk
 delete mode 100644 src/fenv/sh-nofpu/fenv.sub
 create mode 100644 src/fenv/sheb-nofpu/fenv.mk
 delete mode 100644 src/fenv/sheb-nofpu/fenv.sub
 delete mode 100644 src/math/armebhf/fabs.sub
 delete mode 100644 src/math/armebhf/fabsf.sub
 create mode 100644 src/math/armebhf/math.mk
 delete mode 100644 src/math/armebhf/sqrt.sub
 delete mode 100644 src/math/armebhf/sqrtf.sub
 delete mode 100644 src/math/armhf/fabs.sub
 delete mode 100644 src/math/armhf/fabsf.sub
 create mode 100644 src/math/armhf/math.mk
 delete mode 100644 src/math/armhf/sqrt.sub
 delete mode 100644 src/math/armhf/sqrtf.sub
 delete mode 100644 src/setjmp/mips-sf/longjmp.sub
 create mode 100644 src/setjmp/mips-sf/setjmp.mk
 delete mode 100644 src/setjmp/mips-sf/setjmp.sub
 delete mode 100644 src/setjmp/mipsel-sf/longjmp.sub
 create mode 100644 src/setjmp/mipsel-sf/setjmp.mk
 delete mode 100644 src/setjmp/mipsel-sf/setjmp.sub
 delete mode 100644 src/setjmp/sh-nofpu/longjmp.sub
 create mode 100644 src/setjmp/sh-nofpu/setjmp.mk
 delete mode 100644 src/setjmp/sh-nofpu/setjmp.sub
 delete mode 100644 src/setjmp/sheb-nofpu/longjmp.sub
 create mode 100644 src/setjmp/sheb-nofpu/setjmp.mk
 delete mode 100644 src/setjmp/sheb-nofpu/setjmp.sub
 create mode 100644 src/string/armel/memcpy.mk
 delete mode 100644 src/string/armel/memcpy.sub
 create mode 100644 src/string/armhf/memcpy.mk
 delete mode 100644 src/string/armhf/memcpy.sub

diff --git a/Makefile b/Makefile
index 2b21015..05cb650 100644
--- 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,19 @@ includedir = $(prefix)/include
 libdir = $(prefix)/lib
 syslibdir = /lib
 
-SRCS = $(sort $(wildcard src/*/*.c arch/$(ARCH)/src/*.c))
-OBJS = $(SRCS:.c=.o)
-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
+IMPH = $(addprefix $(srcdir)/, src/internal/stdio_impl.h src/internal/pthread_impl.h src/internal/libc.h)
+
+ASM_SRCS = $(wildcard $(srcdir)/src/*/$(ARCH)/*.s)
+ASM_OBJS = $(ASM_SRCS:$(srcdir)/%.s=%.o)
+ASM_LOBJS = $(ASM_OBJS:.o=.lo)
+
+SRCS = $(sort $(wildcard $(srcdir)/src/*/*.c $(srcdir)/arch/$(ARCH)/src/*.c))
+EXCLUDE_OBJS = $(foreach s,$(ASM_SRCS),$(dir $(patsubst $(srcdir)/%/,%,$(dir $(s))))$(notdir $(s:.s=.o)))
+EXCLUDE_LOBJS = $(EXCLUDE_OBJS:.o=.lo)
+OBJS = $(filter-out $(EXCLUDE_OBJS),$(SRCS:$(srcdir)/%.c=%.o)) crt/crt1.o crt/Scrt1.o crt/rcrt1.o crt/crti.o crt/crtn.o
+LOBJS = $(filter-out $(EXCLUDE_LOBJS),$(SRCS:$(srcdir)/%.c=%.lo))
 
 LDFLAGS =
 LDFLAGS_AUTO =
@@ -32,7 +40,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) $(sort -I./src/internal -I$(srcdir)/src/internal) $(sort -I./include -I$(srcdir)/include)
 CFLAGS_ALL += $(CPPFLAGS) $(CFLAGS_AUTO) $(CFLAGS)
 CFLAGS_ALL_STATIC = $(CFLAGS_ALL)
 CFLAGS_ALL_SHARED = $(CFLAGS_ALL) -fPIC -DSHARED
@@ -41,10 +49,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) $(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)
@@ -55,6 +64,8 @@ TOOL_LIBS = lib/musl-gcc.specs
 ALL_LIBS = $(CRT_LIBS) $(STATIC_LIBS) $(SHARED_LIBS) $(EMPTY_LIBS) $(TOOL_LIBS)
 ALL_TOOLS = tools/musl-gcc
 
+SRC_DIRS = $(sort $(dir $(ASM_OBJS) $(OBJS) $(ALL_LIBS) $(ALL_TOOLS)) arch/$(ARCH)/bits/ crt/ include/ src/internal/)
+
 WRAPCC_GCC = gcc
 WRAPCC_CLANG = clang
 
@@ -64,6 +75,19 @@ LDSO_PATHNAME = $(syslibdir)/ld-musl-$(ARCH)$(SUBARCH).so.1
 
 all: $(ALL_LIBS) $(ALL_TOOLS)
 
+-include $(srcdir)/src/*/$(ARCH)$(ASMSUBARCH)/*.mk
+
+$(ALL_LIBS): | lib/
+$(ALL_TOOLS): | tools/
+$(CRT_LIBS:lib/%=crt/%): | crt/
+$(ASM_OBJS) $(ASM_LOBJS) $(OBJS) $(LOBJS): | $(sort $(dir $(ASM_OBJS) $(OBJS)))
+$(GENH): | arch/$(ARCH)/bits/
+$(GENH_INT): | src/internal/
+include/bits: | include
+
+$(SRC_DIRS):
+	mkdir -p $@
+
 install: install-libs install-headers install-tools
 
 clean:
@@ -82,26 +106,24 @@ include/bits:
 	@test "$(ARCH)" || { echo "Please set ARCH in config.mak before running make." ; exit 1 ; }
 	ln -sf ../arch/$(ARCH)/bits $@
 
-include/bits/alltypes.h.in: include/bits
+include/bits/alltypes.h: $(srcdir)/arch/$(ARCH)/bits/alltypes.h.in $(srcdir)/include/alltypes.h.in $(srcdir)/tools/mkalltypes.sed include/bits
+	sed -f $(srcdir)/tools/mkalltypes.sed $(srcdir)/arch/$(ARCH)/bits/alltypes.h.in $(srcdir)/include/alltypes.h.in > $@
 
-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 > $@
-
-src/internal/version.h: $(wildcard VERSION .git)
-	printf '#define VERSION "%s"\n' "$$(sh tools/version.sh)" > $@
+src/internal/version.h: $(wildcard $(srcdir)/VERSION $(srcdir)/.git)
+	printf '#define VERSION "%s"\n' "$$(cd $(srcdir); sh tools/version.sh)" > $@
 
 src/internal/version.lo: src/internal/version.h
 
-crt/rcrt1.o src/ldso/dlstart.lo src/ldso/dynlink.lo: src/internal/dynlink.h arch/$(ARCH)/reloc.h
+crt/rcrt1.o src/ldso/dlstart.lo src/ldso/dynlink.lo: $(srcdir)/src/internal/dynlink.h $(srcdir)/arch/$(ARCH)/reloc.h
 
-crt/crt1.o crt/Scrt1.o crt/rcrt1.o src/ldso/dlstart.lo: $(wildcard arch/$(ARCH)/crt_arch.h)
+crt/crt1.o crt/scrt1.o crt/rcrt1.o src/ldso/dlstart.lo: $(srcdir)/arch/$(ARCH)/crt_arch.h
 
-crt/rcrt1.o: src/ldso/dlstart.c
+crt/rcrt1.o: $(srcdir)/src/ldso/dlstart.c
 
 crt/Scrt1.o crt/rcrt1.o: CFLAGS_ALL += -fPIC
 
-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=%.o) $(OPTIMIZE_SRCS:$(srcdir)/%.c=%.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)
@@ -115,48 +137,34 @@ $(NOSSP_SRCS:%.c=%.o) $(NOSSP_SRCS:%.c=%.lo): CFLAGS_ALL += $(CFLAGS_NOSSP)
 
 $(CRT_LIBS:lib/%=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)
-endef
-$(foreach s,$(wildcard 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 $<)
-
-%.o: $(ARCH)/%.s
+$(ASM_OBJS): %.o: $(srcdir)/%.s
 	$(AS_CMD) $(CFLAGS_ALL_STATIC)
 
-%.o: %.c $(GENH) $(IMPH)
+$(OBJS): %.o: $(srcdir)/%.c $(GENH) $(IMPH)
 	$(CC) $(CFLAGS_ALL_STATIC) -c -o $@ $<
 
-%.lo: $(ARCH)$(ASMSUBARCH)/%.sub
-	$(CC) $(CFLAGS_ALL_SHARED) -c -o $@ $(dir $<)$(shell cat $<)
-
-%.lo: $(ARCH)/%.s
+$(ASM_LOBJS): %.lo: $(srcdir)/%.s
 	$(AS_CMD) $(CFLAGS_ALL_SHARED)
 
-%.lo: %.c $(GENH) $(IMPH)
+$(LOBJS): %.lo: $(srcdir)/%.c $(GENH) $(IMPH)
 	$(CC) $(CFLAGS_ALL_SHARED) -c -o $@ $<
 
-lib/libc.so: $(LOBJS)
+lib/libc.so: $(LOBJS) $(ASM_LOBJS)
 	$(CC) $(CFLAGS_ALL_SHARED) $(LDFLAGS_ALL) -nostdlib -shared \
 	-Wl,-e,_dlstart -Wl,-Bsymbolic-functions \
-	-o $@ $(LOBJS) $(LIBCC)
+	-o $@ $(LOBJS) $(ASM_LOBJS) $(LIBCC)
 
-lib/libc.a: $(OBJS)
+lib/libc.a: $(OBJS) $(ASM_OBJS)
 	rm -f $@
-	$(AR) rc $@ $(OBJS)
+	$(AR) rc $@ $(OBJS) $(ASM_OBJS)
 	$(RANLIB) $@
 
 $(EMPTY_LIBS):
@@ -166,14 +174,14 @@ $(EMPTY_LIBS):
 lib/%.o: crt/%.o
 	cp $< $@
 
-lib/musl-gcc.specs: tools/musl-gcc.specs.sh config.mak
+lib/musl-gcc.specs: $(srcdir)/tools/musl-gcc.specs.sh config.mak
 	sh $< "$(includedir)" "$(libdir)" "$(LDSO_PATHNAME)" > $@
 
 tools/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
+tools/%-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 $@
 
@@ -186,10 +194,13 @@ $(DESTDIR)$(libdir)/%.so: lib/%.so
 $(DESTDIR)$(libdir)/%: lib/%
 	$(INSTALL) -D -m 644 $< $@
 
+$(DESTDIR)$(includedir)/bits/%: $(srcdir)/arch/$(ARCH)/bits/%
+	$(INSTALL) -D -m 644 $< $@
+
 $(DESTDIR)$(includedir)/bits/%: arch/$(ARCH)/bits/%
 	$(INSTALL) -D -m 644 $< $@
 
-$(DESTDIR)$(includedir)/%: include/%
+$(DESTDIR)$(includedir)/%: $(srcdir)/include/%
 	$(INSTALL) -D -m 644 $< $@
 
 $(DESTDIR)$(LDSO_PATHNAME): $(DESTDIR)$(libdir)/libc.so
@@ -202,9 +213,9 @@ install-headers: $(ALL_INCLUDES:include/%=$(DESTDIR)$(includedir)/%)
 install-tools: $(ALL_TOOLS:tools/%=$(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
diff --git a/configure b/configure
index dece1d0..60eb94f 100755
--- 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,11 +184,23 @@ 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 musl 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=.
+ln -sf $srcdir/Makefile .
+
+#
 # Get a temp filename we can use
 #
 i=0
@@ -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
@@ -620,7 +637,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
@@ -643,6 +660,7 @@ cat << EOF
 ARCH = $ARCH
 SUBARCH = $SUBARCH
 ASMSUBARCH = $ASMSUBARCH
+srcdir = $srcdir
 prefix = $prefix
 exec_prefix = $exec_prefix
 bindir = $bindir
diff --git a/src/fenv/armebhf/fenv.mk b/src/fenv/armebhf/fenv.mk
new file mode 100644
index 0000000..769320f
--- /dev/null
+++ b/src/fenv/armebhf/fenv.mk
@@ -0,0 +1 @@
+ASM_SRCS += $(srcdir)/src/fenv/armhf/fenv.s
diff --git a/src/fenv/armebhf/fenv.sub b/src/fenv/armebhf/fenv.sub
deleted file mode 100644
index 5281e40..0000000
--- a/src/fenv/armebhf/fenv.sub
+++ /dev/null
@@ -1 +0,0 @@
-../armhf/fenv.s
diff --git a/src/fenv/armhf/fenv.mk b/src/fenv/armhf/fenv.mk
new file mode 100644
index 0000000..769320f
--- /dev/null
+++ b/src/fenv/armhf/fenv.mk
@@ -0,0 +1 @@
+ASM_SRCS += $(srcdir)/src/fenv/armhf/fenv.s
diff --git a/src/fenv/armhf/fenv.sub b/src/fenv/armhf/fenv.sub
deleted file mode 100644
index ec559cd..0000000
--- a/src/fenv/armhf/fenv.sub
+++ /dev/null
@@ -1 +0,0 @@
-fenv.s
diff --git a/src/fenv/mips-sf/fenv.mk b/src/fenv/mips-sf/fenv.mk
new file mode 100644
index 0000000..96b54d2
--- /dev/null
+++ b/src/fenv/mips-sf/fenv.mk
@@ -0,0 +1 @@
+SRCS += $(srcdir)/src/fenv/fenv.c
diff --git a/src/fenv/mips-sf/fenv.sub b/src/fenv/mips-sf/fenv.sub
deleted file mode 100644
index 9cafca5..0000000
--- a/src/fenv/mips-sf/fenv.sub
+++ /dev/null
@@ -1 +0,0 @@
-../fenv.c
diff --git a/src/fenv/mipsel-sf/fenv.mk b/src/fenv/mipsel-sf/fenv.mk
new file mode 100644
index 0000000..96b54d2
--- /dev/null
+++ b/src/fenv/mipsel-sf/fenv.mk
@@ -0,0 +1 @@
+SRCS += $(srcdir)/src/fenv/fenv.c
diff --git a/src/fenv/mipsel-sf/fenv.sub b/src/fenv/mipsel-sf/fenv.sub
deleted file mode 100644
index 9cafca5..0000000
--- a/src/fenv/mipsel-sf/fenv.sub
+++ /dev/null
@@ -1 +0,0 @@
-../fenv.c
diff --git a/src/fenv/sh-nofpu/fenv.mk b/src/fenv/sh-nofpu/fenv.mk
new file mode 100644
index 0000000..96b54d2
--- /dev/null
+++ b/src/fenv/sh-nofpu/fenv.mk
@@ -0,0 +1 @@
+SRCS += $(srcdir)/src/fenv/fenv.c
diff --git a/src/fenv/sh-nofpu/fenv.sub b/src/fenv/sh-nofpu/fenv.sub
deleted file mode 100644
index 9cafca5..0000000
--- a/src/fenv/sh-nofpu/fenv.sub
+++ /dev/null
@@ -1 +0,0 @@
-../fenv.c
diff --git a/src/fenv/sheb-nofpu/fenv.mk b/src/fenv/sheb-nofpu/fenv.mk
new file mode 100644
index 0000000..96b54d2
--- /dev/null
+++ b/src/fenv/sheb-nofpu/fenv.mk
@@ -0,0 +1 @@
+SRCS += $(srcdir)/src/fenv/fenv.c
diff --git a/src/fenv/sheb-nofpu/fenv.sub b/src/fenv/sheb-nofpu/fenv.sub
deleted file mode 100644
index 9cafca5..0000000
--- a/src/fenv/sheb-nofpu/fenv.sub
+++ /dev/null
@@ -1 +0,0 @@
-../fenv.c
diff --git a/src/math/armebhf/fabs.sub b/src/math/armebhf/fabs.sub
deleted file mode 100644
index 10d9fb7..0000000
--- a/src/math/armebhf/fabs.sub
+++ /dev/null
@@ -1 +0,0 @@
-../armhf/fabs.s
diff --git a/src/math/armebhf/fabsf.sub b/src/math/armebhf/fabsf.sub
deleted file mode 100644
index 940b20b..0000000
--- a/src/math/armebhf/fabsf.sub
+++ /dev/null
@@ -1 +0,0 @@
-../armhf/fabsf.s
diff --git a/src/math/armebhf/math.mk b/src/math/armebhf/math.mk
new file mode 100644
index 0000000..3567ed3
--- /dev/null
+++ b/src/math/armebhf/math.mk
@@ -0,0 +1,4 @@
+ASM_SRCS += $(srcdir)/src/math/armhf/fabsf.s \
+	$(srcdir)/src/math/armhf/fabs.s \
+	$(srcdir)/src/math/armhf/sqrt.s \
+	$(srcdir)/src/math/armhf/sqrtf.s
diff --git a/src/math/armebhf/sqrt.sub b/src/math/armebhf/sqrt.sub
deleted file mode 100644
index de2be11..0000000
--- a/src/math/armebhf/sqrt.sub
+++ /dev/null
@@ -1 +0,0 @@
-../armhf/sqrt.s
diff --git a/src/math/armebhf/sqrtf.sub b/src/math/armebhf/sqrtf.sub
deleted file mode 100644
index 150ab9c..0000000
--- a/src/math/armebhf/sqrtf.sub
+++ /dev/null
@@ -1 +0,0 @@
-../armhf/sqrtf.s
diff --git a/src/math/armhf/fabs.sub b/src/math/armhf/fabs.sub
deleted file mode 100644
index 99e8740..0000000
--- a/src/math/armhf/fabs.sub
+++ /dev/null
@@ -1 +0,0 @@
-fabs.s
diff --git a/src/math/armhf/fabsf.sub b/src/math/armhf/fabsf.sub
deleted file mode 100644
index c04638a..0000000
--- a/src/math/armhf/fabsf.sub
+++ /dev/null
@@ -1 +0,0 @@
-fabsf.s
diff --git a/src/math/armhf/math.mk b/src/math/armhf/math.mk
new file mode 100644
index 0000000..3567ed3
--- /dev/null
+++ b/src/math/armhf/math.mk
@@ -0,0 +1,4 @@
+ASM_SRCS += $(srcdir)/src/math/armhf/fabsf.s \
+	$(srcdir)/src/math/armhf/fabs.s \
+	$(srcdir)/src/math/armhf/sqrt.s \
+	$(srcdir)/src/math/armhf/sqrtf.s
diff --git a/src/math/armhf/sqrt.sub b/src/math/armhf/sqrt.sub
deleted file mode 100644
index 25de7cf..0000000
--- a/src/math/armhf/sqrt.sub
+++ /dev/null
@@ -1 +0,0 @@
-sqrt.s
diff --git a/src/math/armhf/sqrtf.sub b/src/math/armhf/sqrtf.sub
deleted file mode 100644
index 3bcbac8..0000000
--- a/src/math/armhf/sqrtf.sub
+++ /dev/null
@@ -1 +0,0 @@
-sqrtf.s
diff --git a/src/setjmp/mips-sf/longjmp.sub b/src/setjmp/mips-sf/longjmp.sub
deleted file mode 100644
index e80331b..0000000
--- a/src/setjmp/mips-sf/longjmp.sub
+++ /dev/null
@@ -1 +0,0 @@
-longjmp.s
diff --git a/src/setjmp/mips-sf/setjmp.mk b/src/setjmp/mips-sf/setjmp.mk
new file mode 100644
index 0000000..dcb0d39
--- /dev/null
+++ b/src/setjmp/mips-sf/setjmp.mk
@@ -0,0 +1,2 @@
+ASM_SRCS += $(srcdir)/src/setjmp/mips-sf/longjmp.s \
+	$(srcdir)/src/setjmp/mips-sf/setjmp.s
diff --git a/src/setjmp/mips-sf/setjmp.sub b/src/setjmp/mips-sf/setjmp.sub
deleted file mode 100644
index b7ad221..0000000
--- a/src/setjmp/mips-sf/setjmp.sub
+++ /dev/null
@@ -1 +0,0 @@
-setjmp.s
diff --git a/src/setjmp/mipsel-sf/longjmp.sub b/src/setjmp/mipsel-sf/longjmp.sub
deleted file mode 100644
index 6907202..0000000
--- a/src/setjmp/mipsel-sf/longjmp.sub
+++ /dev/null
@@ -1 +0,0 @@
-../mips-sf/longjmp.s
diff --git a/src/setjmp/mipsel-sf/setjmp.mk b/src/setjmp/mipsel-sf/setjmp.mk
new file mode 100644
index 0000000..dcb0d39
--- /dev/null
+++ b/src/setjmp/mipsel-sf/setjmp.mk
@@ -0,0 +1,2 @@
+ASM_SRCS += $(srcdir)/src/setjmp/mips-sf/longjmp.s \
+	$(srcdir)/src/setjmp/mips-sf/setjmp.s
diff --git a/src/setjmp/mipsel-sf/setjmp.sub b/src/setjmp/mipsel-sf/setjmp.sub
deleted file mode 100644
index 9917475..0000000
--- a/src/setjmp/mipsel-sf/setjmp.sub
+++ /dev/null
@@ -1 +0,0 @@
-../mips-sf/setjmp.s
diff --git a/src/setjmp/sh-nofpu/longjmp.sub b/src/setjmp/sh-nofpu/longjmp.sub
deleted file mode 100644
index e80331b..0000000
--- a/src/setjmp/sh-nofpu/longjmp.sub
+++ /dev/null
@@ -1 +0,0 @@
-longjmp.s
diff --git a/src/setjmp/sh-nofpu/setjmp.mk b/src/setjmp/sh-nofpu/setjmp.mk
new file mode 100644
index 0000000..709ce41
--- /dev/null
+++ b/src/setjmp/sh-nofpu/setjmp.mk
@@ -0,0 +1,2 @@
+ASM_SRCS += $(srcdir)/src/setjmp/sh-nofpu/longjmp.s \
+	$(srcdir)/src/setjmp/sh-nofpu/setjmp.s
diff --git a/src/setjmp/sh-nofpu/setjmp.sub b/src/setjmp/sh-nofpu/setjmp.sub
deleted file mode 100644
index b7ad221..0000000
--- a/src/setjmp/sh-nofpu/setjmp.sub
+++ /dev/null
@@ -1 +0,0 @@
-setjmp.s
diff --git a/src/setjmp/sheb-nofpu/longjmp.sub b/src/setjmp/sheb-nofpu/longjmp.sub
deleted file mode 100644
index 62fcd2b..0000000
--- a/src/setjmp/sheb-nofpu/longjmp.sub
+++ /dev/null
@@ -1 +0,0 @@
-../sh-nofpu/longjmp.s
diff --git a/src/setjmp/sheb-nofpu/setjmp.mk b/src/setjmp/sheb-nofpu/setjmp.mk
new file mode 100644
index 0000000..709ce41
--- /dev/null
+++ b/src/setjmp/sheb-nofpu/setjmp.mk
@@ -0,0 +1,2 @@
+ASM_SRCS += $(srcdir)/src/setjmp/sh-nofpu/longjmp.s \
+	$(srcdir)/src/setjmp/sh-nofpu/setjmp.s
diff --git a/src/setjmp/sheb-nofpu/setjmp.sub b/src/setjmp/sheb-nofpu/setjmp.sub
deleted file mode 100644
index a5bb294..0000000
--- a/src/setjmp/sheb-nofpu/setjmp.sub
+++ /dev/null
@@ -1 +0,0 @@
-../sh-nofpu/setjmp.s
diff --git a/src/string/armel/memcpy.mk b/src/string/armel/memcpy.mk
new file mode 100644
index 0000000..ce03f62
--- /dev/null
+++ b/src/string/armel/memcpy.mk
@@ -0,0 +1 @@
+ASM_SRCS += $(srcdir)/src/string/armel/memcpy.s
diff --git a/src/string/armel/memcpy.sub b/src/string/armel/memcpy.sub
deleted file mode 100644
index 543f583..0000000
--- a/src/string/armel/memcpy.sub
+++ /dev/null
@@ -1 +0,0 @@
-memcpy.s
diff --git a/src/string/armhf/memcpy.mk b/src/string/armhf/memcpy.mk
new file mode 100644
index 0000000..ce03f62
--- /dev/null
+++ b/src/string/armhf/memcpy.mk
@@ -0,0 +1 @@
+ASM_SRCS += $(srcdir)/src/string/armel/memcpy.s
diff --git a/src/string/armhf/memcpy.sub b/src/string/armhf/memcpy.sub
deleted file mode 100644
index add0590..0000000
--- a/src/string/armhf/memcpy.sub
+++ /dev/null
@@ -1 +0,0 @@
-../armel/memcpy.s
-- 
2.6.0.rc2.230.g3dd15c0


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-17  6:05                               ` Petr Hosek
@ 2015-11-17 19:51                                 ` Szabolcs Nagy
  0 siblings, 0 replies; 56+ messages in thread
From: Szabolcs Nagy @ 2015-11-17 19:51 UTC (permalink / raw)
  To: musl

* Petr Hosek <phosek@chromium.org> [2015-11-17 06:05:21 +0000]:
> One minor improvement, we obviously don't need more than one .mk file per
> directory.
> 
> On Mon, Nov 16, 2015 at 6:45 PM Petr Hosek <phosek@chromium.org> wrote:
> > This is the final solution I've converged to. It's a bigger change than
> > the previous version, but the implementation is actually cleaner. In
> > nutshell, I've replaced all .sub files with .mk equivalent files which are
> > included from the Makefile. I'm then filtering out all C object files which
> > have assembly equivalent. This allowed me to simplify the build rules while
> > we still support both in-tree and out-of-tree builds. Please let me know
> > what you think, I'll be happy to iterate on this.
> >

> -SRCS = $(sort $(wildcard src/*/*.c arch/$(ARCH)/src/*.c))
> -OBJS = $(SRCS:.c=.o)
> -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
> +IMPH = $(addprefix $(srcdir)/, src/internal/stdio_impl.h src/internal/pthread_impl.h src/internal/libc.h)
> +
> +ASM_SRCS = $(wildcard $(srcdir)/src/*/$(ARCH)/*.s)
> +ASM_OBJS = $(ASM_SRCS:$(srcdir)/%.s=%.o)
> +ASM_LOBJS = $(ASM_OBJS:.o=.lo)
> +
> +SRCS = $(sort $(wildcard $(srcdir)/src/*/*.c $(srcdir)/arch/$(ARCH)/src/*.c))
> +EXCLUDE_OBJS = $(foreach s,$(ASM_SRCS),$(dir $(patsubst $(srcdir)/%/,%,$(dir $(s))))$(notdir $(s:.s=.o)))
> +EXCLUDE_LOBJS = $(EXCLUDE_OBJS:.o=.lo)
> +OBJS = $(filter-out $(EXCLUDE_OBJS),$(SRCS:$(srcdir)/%.c=%.o)) crt/crt1.o crt/Scrt1.o crt/rcrt1.o crt/crti.o crt/crtn.o
> +LOBJS = $(filter-out $(EXCLUDE_LOBJS),$(SRCS:$(srcdir)/%.c=%.lo))

i was afraid this might be O(nm), but it seems gnu make can
use a hash.

> +-include $(srcdir)/src/*/$(ARCH)$(ASMSUBARCH)/*.mk

a .mk change might not trigger the rebuild of the right files,
but that's true for the Makefile as well so that's ok.

note that the .mk is much more powerful than the .sub was
e.g. it can add a .s for which there is no corresponding .c

since you only use one .mk per dir, it can have a fixed name,
but including as *.mk is ok too.

> -%.o: $(ARCH)/%.s
> +$(ASM_OBJS): %.o: $(srcdir)/%.s
>  	$(AS_CMD) $(CFLAGS_ALL_STATIC)
>  
> -%.o: %.c $(GENH) $(IMPH)
> +$(OBJS): %.o: $(srcdir)/%.c $(GENH) $(IMPH)
>  	$(CC) $(CFLAGS_ALL_STATIC) -c -o $@ $<
>  

i assume $(ASM_OBJS): and $(OBJS): are no longer necessary.
(first rule only matches a .o under an $ARCH$SUBARCH dir)

> -lib/libc.so: $(LOBJS)
> +lib/libc.so: $(LOBJS) $(ASM_LOBJS)
>  	$(CC) $(CFLAGS_ALL_SHARED) $(LDFLAGS_ALL) -nostdlib -shared \
>  	-Wl,-e,_dlstart -Wl,-Bsymbolic-functions \
> -	-o $@ $(LOBJS) $(LIBCC)
> +	-o $@ $(LOBJS) $(ASM_LOBJS) $(LIBCC)
>  
> -lib/libc.a: $(OBJS)
> +lib/libc.a: $(OBJS) $(ASM_OBJS)
>  	rm -f $@
> -	$(AR) rc $@ $(OBJS)
> +	$(AR) rc $@ $(OBJS) $(ASM_OBJS)
>  	$(RANLIB) $@

this change can be avoided if OBJS contains ASM_OBJS.

otherwise i'm ok with this patch.


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-17  2:45                             ` Petr Hosek
  2015-11-17  6:05                               ` Petr Hosek
@ 2015-11-17 21:00                               ` Rich Felker
  2015-11-17 21:37                                 ` Petr Hosek
  1 sibling, 1 reply; 56+ messages in thread
From: Rich Felker @ 2015-11-17 21:00 UTC (permalink / raw)
  To: musl

On Tue, Nov 17, 2015 at 02:45:58AM +0000, Petr Hosek wrote:
> This is the final solution I've converged to. It's a bigger change than the
> previous version, but the implementation is actually cleaner. In nutshell,
> I've replaced all .sub files with .mk equivalent files which are included
> from the Makefile. I'm then filtering out all C object files which have
> assembly equivalent. This allowed me to simplify the build rules while we
> still support both in-tree and out-of-tree builds. Please let me know what
> you think, I'll be happy to iterate on this.

What I had in mind was something more like a single fragment for the
arch containing something like (example on sh with 3 subarch
dimensions, where full arch with subarch is sheb-nofpu-fdpic):

%.o: sheb/%.s
	$(AS_CMD)

%.o: sh-nofpu/%.s
	$(AS_CMD)

%.o: sh-fdpic/%.s
	$(AS_CMD)

Even better would be just an ordered list of subarch subdirs that the
top-level makefile can interpret:

SUBARCH_ASM_DIRS = sheb sh-nofpu sh-fdpic

Replacing *.sub with *.mk is not an improvement from my perspective;
rather, it's replacing N files which just contained one piece of data
(a filename) with N files each coupled with the makefile logic.

Rich


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-17 21:00                               ` Rich Felker
@ 2015-11-17 21:37                                 ` Petr Hosek
  2015-11-17 22:01                                   ` Rich Felker
  0 siblings, 1 reply; 56+ messages in thread
From: Petr Hosek @ 2015-11-17 21:37 UTC (permalink / raw)
  To: musl

[-- Attachment #1: Type: text/plain, Size: 1459 bytes --]

How would you express the fact that e.g. armhf subarch should use armel
implementation of memcpy.s?

On Tue, Nov 17, 2015 at 1:00 PM Rich Felker <dalias@libc.org> wrote:

> On Tue, Nov 17, 2015 at 02:45:58AM +0000, Petr Hosek wrote:
> > This is the final solution I've converged to. It's a bigger change than
> the
> > previous version, but the implementation is actually cleaner. In
> nutshell,
> > I've replaced all .sub files with .mk equivalent files which are included
> > from the Makefile. I'm then filtering out all C object files which have
> > assembly equivalent. This allowed me to simplify the build rules while we
> > still support both in-tree and out-of-tree builds. Please let me know
> what
> > you think, I'll be happy to iterate on this.
>
> What I had in mind was something more like a single fragment for the
> arch containing something like (example on sh with 3 subarch
> dimensions, where full arch with subarch is sheb-nofpu-fdpic):
>
> %.o: sheb/%.s
>         $(AS_CMD)
>
> %.o: sh-nofpu/%.s
>         $(AS_CMD)
>
> %.o: sh-fdpic/%.s
>         $(AS_CMD)
>
> Even better would be just an ordered list of subarch subdirs that the
> top-level makefile can interpret:
>
> SUBARCH_ASM_DIRS = sheb sh-nofpu sh-fdpic
>
> Replacing *.sub with *.mk is not an improvement from my perspective;
> rather, it's replacing N files which just contained one piece of data
> (a filename) with N files each coupled with the makefile logic.
>
> Rich
>

[-- Attachment #2: Type: text/html, Size: 1853 bytes --]

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-17 21:37                                 ` Petr Hosek
@ 2015-11-17 22:01                                   ` Rich Felker
  2015-11-17 22:15                                     ` Petr Hosek
  2015-11-17 23:06                                     ` Szabolcs Nagy
  0 siblings, 2 replies; 56+ messages in thread
From: Rich Felker @ 2015-11-17 22:01 UTC (permalink / raw)
  To: musl

On Tue, Nov 17, 2015 at 09:37:37PM +0000, Petr Hosek wrote:
> How would you express the fact that e.g. armhf subarch should use armel
> implementation of memcpy.s?

The point of the *.sub files is to define a mapping from a fully
specific subarch (with 'default'/'empty' replaced with an explicit
default; this is why configure sets ASMSUBARCH=el for plain arm) to
the actual file to use, which is almost always going ot be shared
between a number of subarchs when there's more than one 'dimension'
involved.

However there's no need for this mapping to be defined per-file. In
reality it's sufficient to have a fixed fallback sequence. In the rare
case where there were asm files that depended on endianness and
hard/soft float in the same file, the fallback order would look
something like (for le-hf):

	le-hf le-any any-hf any-any

But for our actual usage cases it suffices just to have:

	le hf any

However, at this point I'm strongly considering whether we should just
do away with the subarch dirs entirely and use preprocessed asm or C
with inline asm in their place. The one place this is mildly difficult
is when only some of the subarchs want the asm at all, and others want
the generic C. This is common for fenv.s and also applies to arm
memcpy.s where we lack a big-endian variant.

One possible solution would be to have (for example)
src/string/arm/memcpy.c that just does

#ifdef __ARMEB__
#include <../memcpy.c>
#endif

and then put memcpy.S in arch/arm/src/ with #ifndef __ARMEB__ around
the whole file.

That would fully eliminate the subarch mess from the build system and
leave us with a fixed fallback order for it to use:

$(ARCH)/%.S
$(ARCH)/%.s
$(ARCH)/%.c
%.S
%.s
%.c

Currently the unadorned %.S/%.s is not needed, but I would consider
adding it so we can put asm files in arch/$(ARCH)/src without needing
dummy .c files for them to pull in asm from arch/$(ARCH)/src/$(ARCH).

Would this make things simpler for the build system? I think so.

Rich


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-17 22:01                                   ` Rich Felker
@ 2015-11-17 22:15                                     ` Petr Hosek
  2015-11-17 22:58                                       ` Rich Felker
  2015-11-17 23:06                                     ` Szabolcs Nagy
  1 sibling, 1 reply; 56+ messages in thread
From: Petr Hosek @ 2015-11-17 22:15 UTC (permalink / raw)
  To: musl

[-- Attachment #1: Type: text/plain, Size: 2460 bytes --]

Absolutely, that's probably the simplest solution in the sense that it
avoids using additional .mk/.sub files or complicated build-time logic.

If that's the solution we all agree on, I'd be happy to implement this as a
separate patch and then rebase the out-of-tree build patch on top of that.

On Tue, Nov 17, 2015 at 2:01 PM Rich Felker <dalias@libc.org> wrote:

> On Tue, Nov 17, 2015 at 09:37:37PM +0000, Petr Hosek wrote:
> > How would you express the fact that e.g. armhf subarch should use armel
> > implementation of memcpy.s?
>
> The point of the *.sub files is to define a mapping from a fully
> specific subarch (with 'default'/'empty' replaced with an explicit
> default; this is why configure sets ASMSUBARCH=el for plain arm) to
> the actual file to use, which is almost always going ot be shared
> between a number of subarchs when there's more than one 'dimension'
> involved.
>
> However there's no need for this mapping to be defined per-file. In
> reality it's sufficient to have a fixed fallback sequence. In the rare
> case where there were asm files that depended on endianness and
> hard/soft float in the same file, the fallback order would look
> something like (for le-hf):
>
>         le-hf le-any any-hf any-any
>
> But for our actual usage cases it suffices just to have:
>
>         le hf any
>
> However, at this point I'm strongly considering whether we should just
> do away with the subarch dirs entirely and use preprocessed asm or C
> with inline asm in their place. The one place this is mildly difficult
> is when only some of the subarchs want the asm at all, and others want
> the generic C. This is common for fenv.s and also applies to arm
> memcpy.s where we lack a big-endian variant.
>
> One possible solution would be to have (for example)
> src/string/arm/memcpy.c that just does
>
> #ifdef __ARMEB__
> #include <../memcpy.c>
> #endif
>
> and then put memcpy.S in arch/arm/src/ with #ifndef __ARMEB__ around
> the whole file.
>
> That would fully eliminate the subarch mess from the build system and
> leave us with a fixed fallback order for it to use:
>
> $(ARCH)/%.S
> $(ARCH)/%.s
> $(ARCH)/%.c
> %.S
> %.s
> %.c
>
> Currently the unadorned %.S/%.s is not needed, but I would consider
> adding it so we can put asm files in arch/$(ARCH)/src without needing
> dummy .c files for them to pull in asm from arch/$(ARCH)/src/$(ARCH).
>
> Would this make things simpler for the build system? I think so.
>
> Rich
>

[-- Attachment #2: Type: text/html, Size: 2980 bytes --]

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-17 22:15                                     ` Petr Hosek
@ 2015-11-17 22:58                                       ` Rich Felker
  0 siblings, 0 replies; 56+ messages in thread
From: Rich Felker @ 2015-11-17 22:58 UTC (permalink / raw)
  To: musl

On Tue, Nov 17, 2015 at 10:15:29PM +0000, Petr Hosek wrote:
> Absolutely, that's probably the simplest solution in the sense that it
> avoids using additional .mk/.sub files or complicated build-time logic.
> 
> If that's the solution we all agree on, I'd be happy to implement this as a
> separate patch and then rebase the out-of-tree build patch on top of that.

The only concern I'm aware of for this is interaction of the CFI
generation scripts with preprocessed asm. They might need to be
updated to be able to handle it safely. At present x86[_64] has no
need for preprocessing anyway so it's not a pressing issue, but we
should probably think through the consequences and make sure we don't
get into another situation that's hard to get out of.

One idea that came up on irc was that we could shift to doing more of
the arch asm with inline asm in C rather than asm source files. This
would eliminate most of the need for CFI generation and would yield
better LTO results. There are a few files for which this can't be
done, however, and I'm not sure everyone likes the idea in principle,
though I haven't seen any strong technical reasons not to do it.

Rich


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-17 22:01                                   ` Rich Felker
  2015-11-17 22:15                                     ` Petr Hosek
@ 2015-11-17 23:06                                     ` Szabolcs Nagy
  2015-11-17 23:27                                       ` Rich Felker
  1 sibling, 1 reply; 56+ messages in thread
From: Szabolcs Nagy @ 2015-11-17 23:06 UTC (permalink / raw)
  To: musl

* Rich Felker <dalias@libc.org> [2015-11-17 17:01:41 -0500]:
> However, at this point I'm strongly considering whether we should just
> do away with the subarch dirs entirely and use preprocessed asm or C
> with inline asm in their place. The one place this is mildly difficult
...
> 
> Would this make things simpler for the build system? I think so.

ok, but that's a separate change then

i think the relevant decision for out-of-tree is
if we want to keep

%.o: $(ARCH)/%.s

which means VPATH is needed, or if it's ok to have
.o files under the $(ARCH) dir, so the rules are just

%.o: %.s

%.o: %.sub

(of course setting $(OBJS) is more tricky then)


i think we can then do out-of-tree independently from
the subarch changes.


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-17 23:06                                     ` Szabolcs Nagy
@ 2015-11-17 23:27                                       ` Rich Felker
  2015-11-17 23:43                                         ` Rich Felker
  0 siblings, 1 reply; 56+ messages in thread
From: Rich Felker @ 2015-11-17 23:27 UTC (permalink / raw)
  To: musl

On Wed, Nov 18, 2015 at 12:06:08AM +0100, Szabolcs Nagy wrote:
> * Rich Felker <dalias@libc.org> [2015-11-17 17:01:41 -0500]:
> > However, at this point I'm strongly considering whether we should just
> > do away with the subarch dirs entirely and use preprocessed asm or C
> > with inline asm in their place. The one place this is mildly difficult
> ....
> > 
> > Would this make things simpler for the build system? I think so.
> 
> ok, but that's a separate change then

Yes, but rather than introduce a lot of mess and complexity in the
build system then go trying to remove it, I'd rather first think
through what simple related changes could be made that would eliminate
the need to add that mess in the first place. This yields a cleaner,
easier-to-understand history and ensures that the prerequisite changes
actually happen first so we don't end up stuck with a mess because the
changes to make it go away get put off. :)

> i think the relevant decision for out-of-tree is
> if we want to keep
> 
> %.o: $(ARCH)/%.s
> 
> which means VPATH is needed, or if it's ok to have
> ..o files under the $(ARCH) dir, so the rules are just
> 
> %.o: %.s
> 
> %.o: %.sub
> 
> (of course setting $(OBJS) is more tricky then)

Assuming .o files in arch dirs are ok, does the following work
(non-VPATH)?

%.o: $(srcdir)/%.sub
	...
%.o: $(srcdir)/%.s
	...
%.o: $(srcdir)/%.c
	...

(with appropriate commands, of course). If so, I think I like it a
lot, because it factors the rules for file *types* separately from the
rules for which files to select (the "tricky" $(OBJS) setting). The
only big concern is whether this "tricky" setting is too costly in
runtime performance or complexity.

> i think we can then do out-of-tree independently from
> the subarch changes.

I don't see a good way to do this without introducing a fairly large
amount of mess we plan to immediately remove, unless we just go the
VPATH route and leave most of the *.sub stuff alone.

Rich


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-17 23:27                                       ` Rich Felker
@ 2015-11-17 23:43                                         ` Rich Felker
  2015-11-17 23:54                                           ` Petr Hosek
  0 siblings, 1 reply; 56+ messages in thread
From: Rich Felker @ 2015-11-17 23:43 UTC (permalink / raw)
  To: musl

On Tue, Nov 17, 2015 at 06:27:11PM -0500, Rich Felker wrote:
> Assuming .o files in arch dirs are ok, does the following work
> (non-VPATH)?
> 
> %.o: $(srcdir)/%.sub
> 	...
> %.o: $(srcdir)/%.s
> 	...
> %.o: $(srcdir)/%.c
> 	...
> 
> (with appropriate commands, of course). If so, I think I like it a
> lot, because it factors the rules for file *types* separately from the
> rules for which files to select (the "tricky" $(OBJS) setting). The
> only big concern is whether this "tricky" setting is too costly in
> runtime performance or complexity.

Here's my idea for the 'tricky' setting of OBJS and it actually looks
very simple and efficient:

ARCH_OBJS = $(wildcard ...)
BASE_OBJS = $(wildcard ...)
OBJS = $(ARCH_OBJS) $(filter-out $(ARCH_OBJS:/$(ARCH)/=/),$(BASE_OBJS))

If the above all works I think we have a pretty good path forward.

It does change where the .o files for arch-specific sources live (one
level deeper in the tree) and requires these dirs to be created in the
output tree, but I think this is actually an improvement since
removing an arch source file will result in the base-level .o file
being built (right now the stale .o file based on the arch asm sticks
around).

Presumably we can also just do:

LOBJS = $(OBJS:.o=.lo)

although it's my intent to remove LOBJS soon anyway and instead have
pic/non-pic objs (and only use pic ones by default). How to name them
will be a fun bikeshed...

Rich


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-17 23:43                                         ` Rich Felker
@ 2015-11-17 23:54                                           ` Petr Hosek
  2015-11-18  0:19                                             ` Szabolcs Nagy
  2015-11-18  0:19                                             ` Rich Felker
  0 siblings, 2 replies; 56+ messages in thread
From: Petr Hosek @ 2015-11-17 23:54 UTC (permalink / raw)
  To: musl

[-- Attachment #1: Type: text/plain, Size: 1688 bytes --]

This'll work if we remove the .sub files as discussed, with .sub files it
becomes more complicated.

On Tue, Nov 17, 2015 at 3:43 PM Rich Felker <dalias@libc.org> wrote:

> On Tue, Nov 17, 2015 at 06:27:11PM -0500, Rich Felker wrote:
> > Assuming .o files in arch dirs are ok, does the following work
> > (non-VPATH)?
> >
> > %.o: $(srcdir)/%.sub
> >       ...
> > %.o: $(srcdir)/%.s
> >       ...
> > %.o: $(srcdir)/%.c
> >       ...
> >
> > (with appropriate commands, of course). If so, I think I like it a
> > lot, because it factors the rules for file *types* separately from the
> > rules for which files to select (the "tricky" $(OBJS) setting). The
> > only big concern is whether this "tricky" setting is too costly in
> > runtime performance or complexity.
>
> Here's my idea for the 'tricky' setting of OBJS and it actually looks
> very simple and efficient:
>
> ARCH_OBJS = $(wildcard ...)
> BASE_OBJS = $(wildcard ...)
> OBJS = $(ARCH_OBJS) $(filter-out $(ARCH_OBJS:/$(ARCH)/=/),$(BASE_OBJS))
>
> If the above all works I think we have a pretty good path forward.
>
> It does change where the .o files for arch-specific sources live (one
> level deeper in the tree) and requires these dirs to be created in the
> output tree, but I think this is actually an improvement since
> removing an arch source file will result in the base-level .o file
> being built (right now the stale .o file based on the arch asm sticks
> around).
>
> Presumably we can also just do:
>
> LOBJS = $(OBJS:.o=.lo)
>
> although it's my intent to remove LOBJS soon anyway and instead have
> pic/non-pic objs (and only use pic ones by default). How to name them
> will be a fun bikeshed...
>
> Rich
>

[-- Attachment #2: Type: text/html, Size: 2154 bytes --]

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-17 23:54                                           ` Petr Hosek
@ 2015-11-18  0:19                                             ` Szabolcs Nagy
  2015-11-18  0:19                                             ` Rich Felker
  1 sibling, 0 replies; 56+ messages in thread
From: Szabolcs Nagy @ 2015-11-18  0:19 UTC (permalink / raw)
  To: musl

* Petr Hosek <phosek@chromium.org> [2015-11-17 23:54:23 +0000]:
> This'll work if we remove the .sub files as discussed, with .sub files it
> becomes more complicated.
> 

why is it more complicated?

%.o: %.sub
	...

rule should generate a .o in the directory where the .sub is
so OBJS should have a subarch/foo.o for a subarch/foo.sub

(you wont have a proper dependency between the .o and the .s
but that does not work now either.. only through ugly mkasmdep)


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-17 23:54                                           ` Petr Hosek
  2015-11-18  0:19                                             ` Szabolcs Nagy
@ 2015-11-18  0:19                                             ` Rich Felker
  2015-11-18 20:19                                               ` Petr Hosek
  1 sibling, 1 reply; 56+ messages in thread
From: Rich Felker @ 2015-11-18  0:19 UTC (permalink / raw)
  To: musl

On Tue, Nov 17, 2015 at 11:54:23PM +0000, Petr Hosek wrote:
> This'll work if we remove the .sub files as discussed, with .sub files it
> becomes more complicated.

Are you sure? I think the only complicated part for the *.sub files is
the automatic dependency generation to make sure the .o files get
rebuild when the potentially-pointed-to .s files change. Otherwise
they are just like .s files in how they're handled except that you use
`cat $<` in place of $<.

BTW could you refrain from top posting on the list? Even if you just
have a short reply that's in regards to the whole quoted message
rather than specific points to address inline, things get awkward to
follow in a hurry (just like now) when somebody else replies to you
but also wants to keep the quoted content you were replying to as
context (like below).

> On Tue, Nov 17, 2015 at 3:43 PM Rich Felker <dalias@libc.org> wrote:
> 
> > On Tue, Nov 17, 2015 at 06:27:11PM -0500, Rich Felker wrote:
> > > Assuming .o files in arch dirs are ok, does the following work
> > > (non-VPATH)?
> > >
> > > %.o: $(srcdir)/%.sub
> > >       ...
> > > %.o: $(srcdir)/%.s
> > >       ...
> > > %.o: $(srcdir)/%.c
> > >       ...
> > >
> > > (with appropriate commands, of course). If so, I think I like it a
> > > lot, because it factors the rules for file *types* separately from the
> > > rules for which files to select (the "tricky" $(OBJS) setting). The
> > > only big concern is whether this "tricky" setting is too costly in
> > > runtime performance or complexity.
> >
> > Here's my idea for the 'tricky' setting of OBJS and it actually looks
> > very simple and efficient:
> >
> > ARCH_OBJS = $(wildcard ...)
> > BASE_OBJS = $(wildcard ...)
> > OBJS = $(ARCH_OBJS) $(filter-out $(ARCH_OBJS:/$(ARCH)/=/),$(BASE_OBJS))

Discussion on irc, along with some basic testing, showed that this
does not work. The obvious solution with $(subst ...) also does not
work because it's plausible that $(srcdir) also contains the substring
/$(ARCH)/, in which case it would get messed up. However I did find a
form that seems to work reliably and that's not hideous:

$(patsubst %,$(srcdir)/%,$(subst /$(ARCH)/,/,$(patsubst $(srcdir)/%,%,$(ARCH_OBJS))))

That yields the list of object files to filter out, which can then be
passed into $(filter-out ...).

Rich


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-18  0:19                                             ` Rich Felker
@ 2015-11-18 20:19                                               ` Petr Hosek
  2015-11-18 21:44                                                 ` Rich Felker
  0 siblings, 1 reply; 56+ messages in thread
From: Petr Hosek @ 2015-11-18 20:19 UTC (permalink / raw)
  To: musl


[-- Attachment #1.1: Type: text/plain, Size: 1452 bytes --]

On Tue, Nov 17, 2015 at 4:20 PM Rich Felker <dalias@libc.org> wrote:

> BTW could you refrain from top posting on the list? Even if you just
> have a short reply that's in regards to the whole quoted message
> rather than specific points to address inline, things get awkward to
> follow in a hurry (just like now) when somebody else replies to you
> but also wants to keep the quoted content you were replying to as
> context (like below).
>

Yes, I'm sorry about that, that's the default configuration I use in my
mail client, but I'll avoid it on the list.


> Discussion on irc, along with some basic testing, showed that this
> does not work. The obvious solution with $(subst ...) also does not
> work because it's plausible that $(srcdir) also contains the substring
> /$(ARCH)/, in which case it would get messed up. However I did find a
> form that seems to work reliably and that's not hideous:
>
> $(patsubst %,$(srcdir)/%,$(subst /$(ARCH)/,/,$(patsubst
> $(srcdir)/%,%,$(ARCH_OBJS))))
>
> That yields the list of object files to filter out, which can then be
> passed into $(filter-out ...).
>

I've reworked the patch following our discussion on IRC by placing all
object files into a directory which enables the use of implicit rules. The
rest of the logic is similar to what you proposed as well as to my previous
patches: constructing the list of objects and then filtering out files for
which (sub)architecture versions are available.

[-- Attachment #1.2: Type: text/html, Size: 1929 bytes --]

[-- Attachment #2: support-out-of-tree-build.patch --]
[-- Type: text/x-patch, Size: 13623 bytes --]

From 06192153361a68ccb232fdbb0b491825f70ab792 Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek@chromium.org>
Date: Wed, 18 Nov 2015 12:07:32 -0800
Subject: [PATCH] support out-of-tree build

this change add support for building musl outside of the source
tree. the implementation is similar to autotools where running
configure in a different folder 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 |   1 +
 Makefile   | 124 ++++++++++++++++++++++++++++++++++---------------------------
 configure  |  24 ++++++++++--
 3 files changed, 92 insertions(+), 57 deletions(-)

diff --git a/.gitignore b/.gitignore
index c5d5c46..36dc5f9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@
 *.a
 *.so
 *.so.1
+obj
 arch/*/bits/alltypes.h
 config.mak
 include/bits
diff --git a/Makefile b/Makefile
index 2b21015..952cee9 100644
--- a/Makefile
+++ b/Makefile
@@ -8,6 +8,8 @@
 # Do not make changes here.
 #
 
+srcdir = .
+objdir = obj
 exec_prefix = /usr/local
 bindir = $(exec_prefix)/bin
 
@@ -16,12 +18,19 @@ 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 = $(BASE_SRCS:$(srcdir)/%.c=%.o)
+ARCH_SRCS = $(wildcard $(srcdir)/src/*/$(ARCH)/*.s)
+ARCH_OBJS = $(ARCH_SRCS:$(srcdir)/%.s=%.o)
+SUB_SRCS = $(wildcard $(srcdir)/src/*/$(ARCH)$(ASMSUBARCH)/*.sub)
+SUB_OBJS = $(SUB_SRCS:$(srcdir)/%.sub=%.o)
+EXCLUDE_ARCH_OBJS = $(patsubst $(srcdir)/%,%,$(subst /$(ARCH)/,/,$(patsubst $(srcdir)/%,%,$(ARCH_OBJS))))
+EXCLUDE_SUB_OBJS = $(patsubst $(srcdir)/%,%,$(subst /$(ARCH)$(ASMSUBARCH)/,/,$(patsubst $(srcdir)/%,%,$(SUB_OBJS))))
+OBJS = $(addprefix $(objdir)/, $(filter-out $(EXCLUDE_SUB_OBJS) $(EXCLUDE_ARCH_OBJS), $(BASE_OBJS)) $(ARCH_OBJS) $(SUB_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 = $(objdir)/include/bits/alltypes.h
+GENH_INT = $(objdir)/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 +41,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) $(sort -I$(objdir)/src/internal -I$(srcdir)/src/internal) $(sort -I$(objdir)/include -I$(srcdir)/include)
 CFLAGS_ALL += $(CPPFLAGS) $(CFLAGS_AUTO) $(CFLAGS)
 CFLAGS_ALL_STATIC = $(CFLAGS_ALL)
 CFLAGS_ALL_SHARED = $(CFLAGS_ALL) -fPIC -DSHARED
@@ -41,10 +50,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) $(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)
@@ -64,10 +74,23 @@ LDSO_PATHNAME = $(syslibdir)/ld-musl-$(ARCH)$(SUBARCH).so.1
 
 all: $(ALL_LIBS) $(ALL_TOOLS)
 
+$(ALL_LIBS): | lib/
+$(ALL_TOOLS): | tools/
+$(CRT_LIBS:lib/%=$(objdir)/crt/%): | $(objdir)/crt/
+$(OBJS) $(LOBJS): | $(sort $(dir $(OBJS)))
+$(GENH): | $(objdir)/arch/$(ARCH)/bits/
+$(GENH_INT): | $(objdir)/src/internal/
+$(objdir)/include/bits: | $(objdir)/include
+
+SRC_DIRS = $(sort $(dir $(ALL_LIBS) $(ALL_TOOLS) $(OBJS) $(GENH_INT)) $(addprefix $(objdir)/, arch/$(ARCH)/bits/ crt/ include/))
+
+$(SRC_DIRS):
+	mkdir -p $@
+
 install: install-libs install-headers install-tools
 
 clean:
-	rm -f crt/*.o
+	rm -f $(objdir)/crt/*.o
 	rm -f $(OBJS)
 	rm -f $(LOBJS)
 	rm -f $(ALL_LIBS) lib/*.[ao] lib/*.so
@@ -78,75 +101,65 @@ clean:
 distclean: clean
 	rm -f config.mak
 
-include/bits:
+$(objdir)/include/bits:
 	@test "$(ARCH)" || { echo "Please set ARCH in config.mak before running make." ; exit 1 ; }
 	ln -sf ../arch/$(ARCH)/bits $@
 
-include/bits/alltypes.h.in: include/bits
-
-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 > $@
+$(objdir)/include/bits/alltypes.h: $(srcdir)/arch/$(ARCH)/bits/alltypes.h.in $(srcdir)/include/alltypes.h.in $(srcdir)/tools/mkalltypes.sed $(objdir)/include/bits
+	sed -f $(srcdir)/tools/mkalltypes.sed $(srcdir)/arch/$(ARCH)/bits/alltypes.h.in $(srcdir)/include/alltypes.h.in > $@
 
-src/internal/version.h: $(wildcard VERSION .git)
-	printf '#define VERSION "%s"\n' "$$(sh tools/version.sh)" > $@
+$(objdir)/src/internal/version.h: $(wildcard $(srcdir)/VERSION $(srcdir)/.git)
+	printf '#define VERSION "%s"\n' "$$(cd $(srcdir); sh tools/version.sh)" > $@
 
-src/internal/version.lo: src/internal/version.h
+$(objdir)/src/internal/version.lo: $(objdir)/src/internal/version.h
 
-crt/rcrt1.o src/ldso/dlstart.lo src/ldso/dynlink.lo: src/internal/dynlink.h arch/$(ARCH)/reloc.h
+$(objdir)/crt/rcrt1.o $(objdir)/src/ldso/dlstart.lo $(objdir)/src/ldso/dynlink.lo: $(srcdir)/src/internal/dynlink.h $(srcdir)/arch/$(ARCH)/reloc.h
 
-crt/crt1.o crt/Scrt1.o crt/rcrt1.o src/ldso/dlstart.lo: $(wildcard arch/$(ARCH)/crt_arch.h)
+$(objdir)/crt/crt1.o $(objdir)/crt/scrt1.o $(objdir)/crt/rcrt1.o $(objdir)/src/ldso/dlstart.lo: $(srcdir)/arch/$(ARCH)/crt_arch.h
 
-crt/rcrt1.o: src/ldso/dlstart.c
+$(objdir)/crt/rcrt1.o: $(srcdir)/src/ldso/dlstart.c
 
-crt/Scrt1.o crt/rcrt1.o: CFLAGS_ALL += -fPIC
+$(objdir)/crt/Scrt1.o $(objdir)/crt/rcrt1.o: CFLAGS_ALL += -fPIC
 
-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=$(objdir)/%.o) $(OPTIMIZE_SRCS:$(srcdir)/%.c=$(objdir)/%.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=$(objdir)/%.o) $(MEMOPS_SRCS:%.c=$(objdir)/%.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)
-
-$(CRT_LIBS:lib/%=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)
-endef
-$(foreach s,$(wildcard src/*/$(ARCH)*/*.s),$(eval $(call mkasmdep,$(s))))
+	$(srcdir)/src/env/__libc_start_main.c $(srcdir)/src/env/__init_tls.c \
+	$(srcdir)/src/thread/__set_thread_area.c $(srcdir)/src/env/__stack_chk_fail.c \
+	$(srcdir)/src/string/memset.c $(srcdir)/src/string/memcpy.c \
+	$(srcdir)/src/ldso/dlstart.c $(srcdir)/src/ldso/dynlink.c
+$(NOSSP_SRCS:$(srcdir)/%.c=$(objdir)/%.o) $(NOSSP_SRCS:$(srcdir)/%.c=$(objdir)/%.lo): CFLAGS_ALL += $(CFLAGS_NOSSP)
+
+$(CRT_LIBS:lib/%=$(objdir)/crt/%): CFLAGS_ALL += -DCRT
 
 # 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
+$(objdir)/%.o: $(srcdir)/%.sub
 	$(CC) $(CFLAGS_ALL_STATIC) -c -o $@ $(dir $<)$(shell cat $<)
 
-%.o: $(ARCH)/%.s
+$(objdir)/%.o: $(srcdir)/%.s
 	$(AS_CMD) $(CFLAGS_ALL_STATIC)
 
-%.o: %.c $(GENH) $(IMPH)
+$(objdir)/%.o: $(srcdir)/%.c $(GENH) $(IMPH)
 	$(CC) $(CFLAGS_ALL_STATIC) -c -o $@ $<
 
-%.lo: $(ARCH)$(ASMSUBARCH)/%.sub
-	$(CC) $(CFLAGS_ALL_SHARED) -c -o $@ $(dir $<)$(shell cat $<)
+$(objdir)/%.lo: $(srcdir)/%.sub
+	 $(CC) $(CFLAGS_ALL_SHARED) -c -o $@ $(dir $<)$(shell cat $<)
 
-%.lo: $(ARCH)/%.s
+$(objdir)/%.lo: $(srcdir)/%.s
 	$(AS_CMD) $(CFLAGS_ALL_SHARED)
 
-%.lo: %.c $(GENH) $(IMPH)
+$(objdir)/%.lo: $(srcdir)/%.c $(GENH) $(IMPH)
 	$(CC) $(CFLAGS_ALL_SHARED) -c -o $@ $<
 
 lib/libc.so: $(LOBJS)
@@ -163,17 +176,17 @@ $(EMPTY_LIBS):
 	rm -f $@
 	$(AR) rc $@
 
-lib/%.o: crt/%.o
+lib/%.o: $(objdir)/crt/%.o
 	cp $< $@
 
-lib/musl-gcc.specs: tools/musl-gcc.specs.sh config.mak
+lib/musl-gcc.specs: $(srcdir)/tools/musl-gcc.specs.sh config.mak
 	sh $< "$(includedir)" "$(libdir)" "$(LDSO_PATHNAME)" > $@
 
 tools/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
+tools/%-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 $@
 
@@ -186,10 +199,13 @@ $(DESTDIR)$(libdir)/%.so: lib/%.so
 $(DESTDIR)$(libdir)/%: lib/%
 	$(INSTALL) -D -m 644 $< $@
 
+$(DESTDIR)$(includedir)/bits/%: $(srcdir)/arch/$(ARCH)/bits/%
+	$(INSTALL) -D -m 644 $< $@
+
 $(DESTDIR)$(includedir)/bits/%: arch/$(ARCH)/bits/%
 	$(INSTALL) -D -m 644 $< $@
 
-$(DESTDIR)$(includedir)/%: include/%
+$(DESTDIR)$(includedir)/%: $(srcdir)/include/%
 	$(INSTALL) -D -m 644 $< $@
 
 $(DESTDIR)$(LDSO_PATHNAME): $(DESTDIR)$(libdir)/libc.so
@@ -202,9 +218,9 @@ install-headers: $(ALL_INCLUDES:include/%=$(DESTDIR)$(includedir)/%)
 install-tools: $(ALL_TOOLS:tools/%=$(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
diff --git a/configure b/configure
index dece1d0..60eb94f 100755
--- 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,11 +184,23 @@ 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 musl 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=.
+ln -sf $srcdir/Makefile .
+
+#
 # Get a temp filename we can use
 #
 i=0
@@ -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
@@ -620,7 +637,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
@@ -643,6 +660,7 @@ cat << EOF
 ARCH = $ARCH
 SUBARCH = $SUBARCH
 ASMSUBARCH = $ASMSUBARCH
+srcdir = $srcdir
 prefix = $prefix
 exec_prefix = $exec_prefix
 bindir = $bindir
-- 
2.6.0.rc2.230.g3dd15c0


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-18 20:19                                               ` Petr Hosek
@ 2015-11-18 21:44                                                 ` Rich Felker
  2015-11-19  0:22                                                   ` Petr Hosek
  0 siblings, 1 reply; 56+ messages in thread
From: Rich Felker @ 2015-11-18 21:44 UTC (permalink / raw)
  To: musl

On Wed, Nov 18, 2015 at 08:19:28PM +0000, Petr Hosek wrote:
> > Discussion on irc, along with some basic testing, showed that this
> > does not work. The obvious solution with $(subst ...) also does not
> > work because it's plausible that $(srcdir) also contains the substring
> > /$(ARCH)/, in which case it would get messed up. However I did find a
> > form that seems to work reliably and that's not hideous:
> >
> > $(patsubst %,$(srcdir)/%,$(subst /$(ARCH)/,/,$(patsubst
> > $(srcdir)/%,%,$(ARCH_OBJS))))
> >
> > That yields the list of object files to filter out, which can then be
> > passed into $(filter-out ...).
> >
> 
> I've reworked the patch following our discussion on IRC by placing all
> object files into a directory which enables the use of implicit rules. The
> rest of the logic is similar to what you proposed as well as to my previous
> patches: constructing the list of objects and then filtering out files for
> which (sub)architecture versions are available.

I've tried to review it in detail this time, with comments inline
below.

> -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 = $(BASE_SRCS:$(srcdir)/%.c=%.o)
> +ARCH_SRCS = $(wildcard $(srcdir)/src/*/$(ARCH)/*.s)
> +ARCH_OBJS = $(ARCH_SRCS:$(srcdir)/%.s=%.o)
> +SUB_SRCS = $(wildcard $(srcdir)/src/*/$(ARCH)$(ASMSUBARCH)/*.sub)
> +SUB_OBJS = $(SUB_SRCS:$(srcdir)/%.sub=%.o)
> +EXCLUDE_ARCH_OBJS = $(patsubst $(srcdir)/%,%,$(subst /$(ARCH)/,/,$(patsubst $(srcdir)/%,%,$(ARCH_OBJS))))
> +EXCLUDE_SUB_OBJS = $(patsubst $(srcdir)/%,%,$(subst /$(ARCH)$(ASMSUBARCH)/,/,$(patsubst $(srcdir)/%,%,$(SUB_OBJS))))
> +OBJS = $(addprefix $(objdir)/, $(filter-out $(EXCLUDE_SUB_OBJS) $(EXCLUDE_ARCH_OBJS), $(BASE_OBJS)) $(ARCH_OBJS) $(SUB_OBJS))

Why not just put all the arch files (whether they come from .s or
.sub, or in the future .c or .S) together in ARCH_OBJS? I think this
can all be done with no intermediate *_SRCS vars (and probably even
without SRCS) with some explicit $(patsubst...) etc. Actually I'm a
bit surprised if things like this work:

	$(BASE_SRCS:$(srcdir)/%.c=%.o)

I had trouble with % in the middle of the pattern not doing what I
expected it to.

>  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) $(sort -I$(objdir)/src/internal -I$(srcdir)/src/internal) $(sort -I$(objdir)/include -I$(srcdir)/include)

What is the $(sort...) for now? Before I thought it was to remove
duplicates, but now they will not be duplicates unless you're trying
to support objdir=. -- is that your intent? I don't think it will
work based on our discussions yesterday.

>  clean:
> -	rm -f crt/*.o
> +	rm -f $(objdir)/crt/*.o
>  	rm -f $(OBJS)
>  	rm -f $(LOBJS)
>  	rm -f $(ALL_LIBS) lib/*.[ao] lib/*.so

This can probably just be rm -rf obj, but perhaps we should wait to
make that change. And seeing this, I'm mildly in favor of hard-coding
obj/ (everywhere) rather than using $(objdir)/ simply because the
latter is really dangerous if you override it on the command line with
an unwanted setting (like make clean objdir=/).

> -include/bits:
> +$(objdir)/include/bits:
>  	@test "$(ARCH)" || { echo "Please set ARCH in config.mak before running make." ; exit 1 ; }
>  	ln -sf ../arch/$(ARCH)/bits $@

I think this may be problematic -- for an in-tree build, you'll get a
bits symlink in the source include dir, and then out-of-tree builds
might use it. Include order might prevent that but it sounds fragile.
We should probably eliminate the bits symlink here.

> -include/bits/alltypes.h.in: include/bits
> -
> -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 > $@
> +$(objdir)/include/bits/alltypes.h: $(srcdir)/arch/$(ARCH)/bits/alltypes.h.in $(srcdir)/include/alltypes.h.in $(srcdir)/tools/mkalltypes.sed $(objdir)/include/bits
> +	sed -f $(srcdir)/tools/mkalltypes.sed $(srcdir)/arch/$(ARCH)/bits/alltypes.h.in $(srcdir)/include/alltypes.h.in > $@

So the generated alltypes.h goes in obj/include/bits? But the
installation rule does not seem to get it from there. It seems to only
look in arch/$(ARCH)/bits/%. I guess the above symlink causes them to
be the same, but I don't think there's actually a dependency in the
makefile to let make know that...

> -src/internal/version.h: $(wildcard VERSION .git)
> -	printf '#define VERSION "%s"\n' "$$(sh tools/version.sh)" > $@
> +$(objdir)/src/internal/version.h: $(wildcard $(srcdir)/VERSION $(srcdir)/.git)
> +	printf '#define VERSION "%s"\n' "$$(cd $(srcdir); sh tools/version.sh)" > $@
>  
> -src/internal/version.lo: src/internal/version.h
> +$(objdir)/src/internal/version.lo: $(objdir)/src/internal/version.h
>  
> -crt/rcrt1.o src/ldso/dlstart.lo src/ldso/dynlink.lo: src/internal/dynlink.h arch/$(ARCH)/reloc.h
> +$(objdir)/crt/rcrt1.o $(objdir)/src/ldso/dlstart.lo $(objdir)/src/ldso/dynlink.lo: $(srcdir)/src/internal/dynlink.h $(srcdir)/arch/$(ARCH)/reloc.h
>  
> -crt/crt1.o crt/Scrt1.o crt/rcrt1.o src/ldso/dlstart.lo: $(wildcard arch/$(ARCH)/crt_arch.h)
> +$(objdir)/crt/crt1.o $(objdir)/crt/scrt1.o $(objdir)/crt/rcrt1.o $(objdir)/src/ldso/dlstart.lo: $(srcdir)/arch/$(ARCH)/crt_arch.h
>  
> -crt/rcrt1.o: src/ldso/dlstart.c
> +$(objdir)/crt/rcrt1.o: $(srcdir)/src/ldso/dlstart.c
>  
> -crt/Scrt1.o crt/rcrt1.o: CFLAGS_ALL += -fPIC
> +$(objdir)/crt/Scrt1.o $(objdir)/crt/rcrt1.o: CFLAGS_ALL += -fPIC
>  
> -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=$(objdir)/%.o) $(OPTIMIZE_SRCS:$(srcdir)/%.c=$(objdir)/%.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=$(objdir)/%.o) $(MEMOPS_SRCS:%.c=$(objdir)/%.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)
> -
> -$(CRT_LIBS:lib/%=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)
> -endef
> -$(foreach s,$(wildcard src/*/$(ARCH)*/*.s),$(eval $(call mkasmdep,$(s))))

Simply removing this will break dependency-based regeneration of
object files that use .sub files when the underlying .s file changes.
Maybe we don't care since .sub files will be removed soon, but it
should be noted as a regression for the time being, or we should just
transform this for out-of-tree support.

> +	$(srcdir)/src/env/__libc_start_main.c $(srcdir)/src/env/__init_tls.c \
> +	$(srcdir)/src/thread/__set_thread_area.c $(srcdir)/src/env/__stack_chk_fail.c \
> +	$(srcdir)/src/string/memset.c $(srcdir)/src/string/memcpy.c \
> +	$(srcdir)/src/ldso/dlstart.c $(srcdir)/src/ldso/dynlink.c

It might make sense to use a function to apply a prefix to all of
these rather than repeating $(srcdir)/ over and over.

> +$(NOSSP_SRCS:$(srcdir)/%.c=$(objdir)/%.o) $(NOSSP_SRCS:$(srcdir)/%.c=$(objdir)/%.lo): CFLAGS_ALL += $(CFLAGS_NOSSP)

Actually I think we don't even want $(srcdir) there to begin with.
It's just removed immediately.

> +
> +$(CRT_LIBS:lib/%=$(objdir)/crt/%): CFLAGS_ALL += -DCRT

I'm not clear on whether crti.o/crtn.o end up in crt/ or crt/$(ARCH)/
but if it's the latter we need to handle this somehow.

> -%.lo: $(ARCH)$(ASMSUBARCH)/%.sub
> -	$(CC) $(CFLAGS_ALL_SHARED) -c -o $@ $(dir $<)$(shell cat $<)
> +$(objdir)/%.lo: $(srcdir)/%.sub
> +	 $(CC) $(CFLAGS_ALL_SHARED) -c -o $@ $(dir $<)$(shell cat $<)

Looks like you got a spurious space in there.

> -lib/%.o: crt/%.o
> +lib/%.o: $(objdir)/crt/%.o
>  	cp $< $@

This also depends on crti.o/crtn.o not being in an arch subdir.

> +$(DESTDIR)$(includedir)/bits/%: $(srcdir)/arch/$(ARCH)/bits/%
> +	$(INSTALL) -D -m 644 $< $@
> +
>  $(DESTDIR)$(includedir)/bits/%: arch/$(ARCH)/bits/%
>  	$(INSTALL) -D -m 644 $< $@

This is the rule I mentioned above that doesn't seem to have any way
for make to know how to generate arch/$(ARCH)/bits/alltypes.h unless
it already happened to be generated.

> +# Get the musl source dir for out-of-tree builds

I don't recall if I've followed this principle myself, but it probably
makes sense to avoid writing musl explicitly all over the configure
script in case someone goes and reuses parts of it for another
project.

> +#
> +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=.
> +ln -sf $srcdir/Makefile .

Doesn't this do ln -sf ./Makefile . when srcdir=.? That needs to be
suppressed, and the ln should probably not happen until the configure
script has "succeeded", at the same time config.mak is generated.

Rich


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-18 21:44                                                 ` Rich Felker
@ 2015-11-19  0:22                                                   ` Petr Hosek
  2015-11-20  4:09                                                     ` Rich Felker
                                                                       ` (3 more replies)
  0 siblings, 4 replies; 56+ messages in thread
From: Petr Hosek @ 2015-11-19  0:22 UTC (permalink / raw)
  To: musl


[-- Attachment #1.1: Type: text/plain, Size: 9945 bytes --]

On Wed, Nov 18, 2015 at 1:45 PM Rich Felker <dalias@libc.org> wrote:

> > -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 = $(BASE_SRCS:$(srcdir)/%.c=%.o)
> > +ARCH_SRCS = $(wildcard $(srcdir)/src/*/$(ARCH)/*.s)
> > +ARCH_OBJS = $(ARCH_SRCS:$(srcdir)/%.s=%.o)
> > +SUB_SRCS = $(wildcard $(srcdir)/src/*/$(ARCH)$(ASMSUBARCH)/*.sub)
> > +SUB_OBJS = $(SUB_SRCS:$(srcdir)/%.sub=%.o)
> > +EXCLUDE_ARCH_OBJS = $(patsubst $(srcdir)/%,%,$(subst
> /$(ARCH)/,/,$(patsubst $(srcdir)/%,%,$(ARCH_OBJS))))
> > +EXCLUDE_SUB_OBJS = $(patsubst $(srcdir)/%,%,$(subst
> /$(ARCH)$(ASMSUBARCH)/,/,$(patsubst $(srcdir)/%,%,$(SUB_OBJS))))
> > +OBJS = $(addprefix $(objdir)/, $(filter-out $(EXCLUDE_SUB_OBJS)
> $(EXCLUDE_ARCH_OBJS), $(BASE_OBJS)) $(ARCH_OBJS) $(SUB_OBJS))
>
> Why not just put all the arch files (whether they come from .s or
> .sub, or in the future .c or .S) together in ARCH_OBJS? I think this
> can all be done with no intermediate *_SRCS vars (and probably even
> without SRCS) with some explicit $(patsubst...) etc. Actually I'm a
> bit surprised if things like this work:
>
>         $(BASE_SRCS:$(srcdir)/%.c=%.o)
>
> I had trouble with % in the middle of the pattern not doing what I
> expected it to.
>

I have merged ARCH_* and SUB_* into ARCH_*.


> >  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) $(sort
> -I$(objdir)/src/internal -I$(srcdir)/src/internal) $(sort
> -I$(objdir)/include -I$(srcdir)/include)
>
> What is the $(sort...) for now? Before I thought it was to remove
> duplicates, but now they will not be duplicates unless you're trying
> to support objdir=. -- is that your intent? I don't think it will
> work based on our discussions yesterday.
>

Correct, this would only make sense if objdir=. but then the implicit rules
wouldn't work so we don't need to support that scenario.


> >  clean:
> > -     rm -f crt/*.o
> > +     rm -f $(objdir)/crt/*.o
> >       rm -f $(OBJS)
> >       rm -f $(LOBJS)
> >       rm -f $(ALL_LIBS) lib/*.[ao] lib/*.so
>
> This can probably just be rm -rf obj, but perhaps we should wait to
> make that change. And seeing this, I'm mildly in favor of hard-coding
> obj/ (everywhere) rather than using $(objdir)/ simply because the
> latter is really dangerous if you override it on the command line with
> an unwanted setting (like make clean objdir=/).
>

That's why I avoided using rm -rf $(objdir). I can imagine the use case for
setting $(objdir) to a different location, changing this to make it
hard-coded wouldn't be a problem if you prefer.


> > -include/bits:
> > +$(objdir)/include/bits:
> >       @test "$(ARCH)" || { echo "Please set ARCH in config.mak before
> running make." ; exit 1 ; }
> >       ln -sf ../arch/$(ARCH)/bits $@
>
> I think this may be problematic -- for an in-tree build, you'll get a
> bits symlink in the source include dir, and then out-of-tree builds
> might use it. Include order might prevent that but it sounds fragile.
> We should probably eliminate the bits symlink here.
>

I agree, if we're not going to support the objdir=. scenario, we can remove
the symlink. It'll also simplify some of the directory dependencies.


> > -include/bits/alltypes.h.in: include/bits
> > -
> > -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 > $@
> > +$(objdir)/include/bits/alltypes.h: $(srcdir)/arch/$(ARCH)/bits/
> alltypes.h.in $(srcdir)/include/alltypes.h.in
> $(srcdir)/tools/mkalltypes.sed $(objdir)/include/bits
> > +     sed -f $(srcdir)/tools/mkalltypes.sed $(srcdir)/arch/$(ARCH)/bits/
> alltypes.h.in $(srcdir)/include/alltypes.h.in > $@
>
> So the generated alltypes.h goes in obj/include/bits? But the
> installation rule does not seem to get it from there. It seems to only
> look in arch/$(ARCH)/bits/%. I guess the above symlink causes them to
> be the same, but I don't think there's actually a dependency in the
> makefile to let make know that...
>

That's fixed, well spotted.


> > -src/internal/version.h: $(wildcard VERSION .git)
> > -     printf '#define VERSION "%s"\n' "$$(sh tools/version.sh)" > $@
> > +$(objdir)/src/internal/version.h: $(wildcard $(srcdir)/VERSION
> $(srcdir)/.git)
> > +     printf '#define VERSION "%s"\n' "$$(cd $(srcdir); sh
> tools/version.sh)" > $@
> >
> > -src/internal/version.lo: src/internal/version.h
> > +$(objdir)/src/internal/version.lo: $(objdir)/src/internal/version.h
> >
> > -crt/rcrt1.o src/ldso/dlstart.lo src/ldso/dynlink.lo:
> src/internal/dynlink.h arch/$(ARCH)/reloc.h
> > +$(objdir)/crt/rcrt1.o $(objdir)/src/ldso/dlstart.lo
> $(objdir)/src/ldso/dynlink.lo: $(srcdir)/src/internal/dynlink.h
> $(srcdir)/arch/$(ARCH)/reloc.h
> >
> > -crt/crt1.o crt/Scrt1.o crt/rcrt1.o src/ldso/dlstart.lo: $(wildcard
> arch/$(ARCH)/crt_arch.h)
> > +$(objdir)/crt/crt1.o $(objdir)/crt/scrt1.o $(objdir)/crt/rcrt1.o
> $(objdir)/src/ldso/dlstart.lo: $(srcdir)/arch/$(ARCH)/crt_arch.h
> >
> > -crt/rcrt1.o: src/ldso/dlstart.c
> > +$(objdir)/crt/rcrt1.o: $(srcdir)/src/ldso/dlstart.c
> >
> > -crt/Scrt1.o crt/rcrt1.o: CFLAGS_ALL += -fPIC
> > +$(objdir)/crt/Scrt1.o $(objdir)/crt/rcrt1.o: CFLAGS_ALL += -fPIC
> >
> > -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=$(objdir)/%.o)
> $(OPTIMIZE_SRCS:$(srcdir)/%.c=$(objdir)/%.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=$(objdir)/%.o) $(MEMOPS_SRCS:%.c=$(objdir)/%.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)
> > -
> > -$(CRT_LIBS:lib/%=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)
> > -endef
> > -$(foreach s,$(wildcard src/*/$(ARCH)*/*.s),$(eval $(call
> mkasmdep,$(s))))
>
> Simply removing this will break dependency-based regeneration of
> object files that use .sub files when the underlying .s file changes.
> Maybe we don't care since .sub files will be removed soon, but it
> should be noted as a regression for the time being, or we should just
> transform this for out-of-tree support.
>

Reverted and update to work with the new setup.


> > +     $(srcdir)/src/env/__libc_start_main.c
> $(srcdir)/src/env/__init_tls.c \
> > +     $(srcdir)/src/thread/__set_thread_area.c
> $(srcdir)/src/env/__stack_chk_fail.c \
> > +     $(srcdir)/src/string/memset.c $(srcdir)/src/string/memcpy.c \
> > +     $(srcdir)/src/ldso/dlstart.c $(srcdir)/src/ldso/dynlink.c
>
> It might make sense to use a function to apply a prefix to all of
> these rather than repeating $(srcdir)/ over and over.
>
> > +$(NOSSP_SRCS:$(srcdir)/%.c=$(objdir)/%.o)
> $(NOSSP_SRCS:$(srcdir)/%.c=$(objdir)/%.lo): CFLAGS_ALL += $(CFLAGS_NOSSP)
>
> Actually I think we don't even want $(srcdir) there to begin with.
> It's just removed immediately.
>

Removed.


> > +
> > +$(CRT_LIBS:lib/%=$(objdir)/crt/%): CFLAGS_ALL += -DCRT
>
> I'm not clear on whether crti.o/crtn.o end up in crt/ or crt/$(ARCH)/
> but if it's the latter we need to handle this somehow.
>

These end up in crt/ even in the current upstream implementation.


> > -%.lo: $(ARCH)$(ASMSUBARCH)/%.sub
> > -     $(CC) $(CFLAGS_ALL_SHARED) -c -o $@ $(dir $<)$(shell cat $<)
> > +$(objdir)/%.lo: $(srcdir)/%.sub
> > +      $(CC) $(CFLAGS_ALL_SHARED) -c -o $@ $(dir $<)$(shell cat $<)
>
> Looks like you got a spurious space in there.
>

Removed.


> > -lib/%.o: crt/%.o
> > +lib/%.o: $(objdir)/crt/%.o
> >       cp $< $@
>
> This also depends on crti.o/crtn.o not being in an arch subdir.
>
> > +$(DESTDIR)$(includedir)/bits/%: $(srcdir)/arch/$(ARCH)/bits/%
> > +     $(INSTALL) -D -m 644 $< $@
> > +
> >  $(DESTDIR)$(includedir)/bits/%: arch/$(ARCH)/bits/%
> >       $(INSTALL) -D -m 644 $< $@
>
> This is the rule I mentioned above that doesn't seem to have any way
> for make to know how to generate arch/$(ARCH)/bits/alltypes.h unless
> it already happened to be generated.
>

Fixed.


> > +# Get the musl source dir for out-of-tree builds
>
> I don't recall if I've followed this principle myself, but it probably
> makes sense to avoid writing musl explicitly all over the configure
> script in case someone goes and reuses parts of it for another
> project.
>

Removed.


> > +#
> > +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=.
> > +ln -sf $srcdir/Makefile .
>
> Doesn't this do ln -sf ./Makefile . when srcdir=.? That needs to be
> suppressed, and the ln should probably not happen until the configure
> script has "succeeded", at the same time config.mak is generated.
>

Check added and moved to the bottom. of the configure script.

[-- Attachment #1.2: Type: text/html, Size: 13614 bytes --]

[-- Attachment #2: support-out-of-tree-build.patch --]
[-- Type: text/x-patch, Size: 13615 bytes --]

From a0e52a03744ddc72a4803efbb2cd904d1ff4012c Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek@chromium.org>
Date: Wed, 18 Nov 2015 12:07:32 -0800
Subject: [PATCH] support out-of-tree build

this change add support for building musl outside of the source
tree. the implementation is similar to autotools where running
configure in a different folder 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 |   1 +
 Makefile   | 109 +++++++++++++++++++++++++++++++++++--------------------------
 configure  |  25 ++++++++++++--
 3 files changed, 86 insertions(+), 49 deletions(-)

diff --git a/.gitignore b/.gitignore
index c5d5c46..36dc5f9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@
 *.a
 *.so
 *.so.1
+obj
 arch/*/bits/alltypes.h
 config.mak
 include/bits
diff --git a/Makefile b/Makefile
index df20f94..7c8954d 100644
--- a/Makefile
+++ b/Makefile
@@ -8,6 +8,8 @@
 # Do not make changes here.
 #
 
+srcdir = .
+objdir = obj
 exec_prefix = /usr/local
 bindir = $(exec_prefix)/bin
 
@@ -16,12 +18,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)))
+EXCLUDE_OBJS = $(patsubst $(srcdir)/%,%,$(subst /$(ARCH)$(ASMSUBARCH)/,/,$(subst /$(ARCH)/,/,$(patsubst $(srcdir)/%,%,$(ARCH_OBJS)))))
+OBJS = $(addprefix $(objdir)/, $(filter-out $(EXCLUDE_OBJS), $(BASE_OBJS)) $(ARCH_OBJS) $(SUB_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 = $(objdir)/include/bits/alltypes.h
+GENH_INT = $(objdir)/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 +38,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) -I$(objdir)/src/internal -I$(srcdir)/src/internal -I$(objdir)/include -I$(srcdir)/include
 CFLAGS_ALL += $(CPPFLAGS) $(CFLAGS_AUTO) $(CFLAGS)
 CFLAGS_ALL_STATIC = $(CFLAGS_ALL)
 CFLAGS_ALL_SHARED = $(CFLAGS_ALL) -fPIC -DSHARED
@@ -41,10 +47,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:$(objdir)/%=%) $(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)
@@ -64,10 +71,22 @@ LDSO_PATHNAME = $(syslibdir)/ld-musl-$(ARCH)$(SUBARCH).so.1
 
 all: $(ALL_LIBS) $(ALL_TOOLS)
 
+$(ALL_LIBS): | lib/
+$(ALL_TOOLS): | tools/
+$(CRT_LIBS:lib/%=$(objdir)/crt/%): | $(objdir)/crt/
+$(OBJS) $(LOBJS): | $(sort $(dir $(OBJS)))
+$(GENH): | $(objdir)/include/bits/
+$(GENH_INT): | $(objdir)/src/internal/
+
+SRC_DIRS = $(sort $(dir $(ALL_LIBS) $(ALL_TOOLS) $(OBJS) $(GENH) $(GENH_INT)) $(addprefix $(objdir)/, crt/ include/))
+
+$(SRC_DIRS):
+	mkdir -p $@
+
 install: install-libs install-headers install-tools
 
 clean:
-	rm -f crt/*.o
+	rm -f $(objdir)/crt/*.o
 	rm -f $(OBJS)
 	rm -f $(LOBJS)
 	rm -f $(ALL_LIBS) lib/*.[ao] lib/*.so
@@ -78,75 +97,70 @@ clean:
 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 $@
-
-include/bits/alltypes.h.in: include/bits
+$(objdir)/include/bits/alltypes.h: $(srcdir)/arch/$(ARCH)/bits/alltypes.h.in $(srcdir)/include/alltypes.h.in $(srcdir)/tools/mkalltypes.sed $(objdir)/include/bits
+	sed -f $(srcdir)/tools/mkalltypes.sed $(srcdir)/arch/$(ARCH)/bits/alltypes.h.in $(srcdir)/include/alltypes.h.in > $@
 
-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 > $@
+$(objdir)/src/internal/version.h: $(wildcard $(srcdir)/VERSION $(srcdir)/.git)
+	printf '#define VERSION "%s"\n' "$$(cd $(srcdir); sh tools/version.sh)" > $@
 
-src/internal/version.h: $(wildcard VERSION .git)
-	printf '#define VERSION "%s"\n' "$$(sh tools/version.sh)" > $@
+$(objdir)/src/internal/version.o $(objdir)/src/internal/version.lo: $(objdir)/src/internal/version.h
 
-src/internal/version.o src/internal/version.lo: src/internal/version.h
+$(objdir)/crt/rcrt1.o $(objdir)/src/ldso/dlstart.lo $(objdir)/src/ldso/dynlink.lo: $(srcdir)/src/internal/dynlink.h $(srcdir)/arch/$(ARCH)/reloc.h
 
-crt/rcrt1.o src/ldso/dlstart.lo src/ldso/dynlink.lo: src/internal/dynlink.h arch/$(ARCH)/reloc.h
+$(objdir)/crt/crt1.o $(objdir)/crt/scrt1.o $(objdir)/crt/rcrt1.o $(objdir)/src/ldso/dlstart.lo: $(srcdir)/arch/$(ARCH)/crt_arch.h
 
-crt/crt1.o crt/Scrt1.o crt/rcrt1.o src/ldso/dlstart.lo: $(wildcard arch/$(ARCH)/crt_arch.h)
+$(objdir)/crt/rcrt1.o: $(srcdir)/src/ldso/dlstart.c
 
-crt/rcrt1.o: src/ldso/dlstart.c
+$(objdir)/crt/Scrt1.o $(objdir)/crt/rcrt1.o: CFLAGS_ALL += -fPIC
 
-crt/Scrt1.o crt/rcrt1.o: CFLAGS_ALL += -fPIC
-
-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=$(objdir)/%.o) $(OPTIMIZE_SRCS:$(srcdir)/%.c=$(objdir)/%.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=$(objdir)/%.o) $(MEMOPS_SRCS:%.c=$(objdir)/%.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=$(objdir)/%.o) $(NOSSP_SRCS:%.c=$(objdir)/%.lo): CFLAGS_ALL += $(CFLAGS_NOSSP)
 
-$(CRT_LIBS:lib/%=crt/%): CFLAGS_ALL += -DCRT
+$(CRT_LIBS:lib/%=$(objdir)/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.
+#$(dir $(patsubst %/,%,$(dir $(1))))$(notdir $(1:.s=.o)): $(1)
 define mkasmdep
-$(dir $(patsubst %/,%,$(dir $(1))))$(notdir $(1:.s=.o)): $(1)
+$(patsubst $(srcdir)/%,$(objdir)/%,$(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
+$(objdir)/%.o: $(srcdir)/%.sub
 	$(CC) $(CFLAGS_ALL_STATIC) -c -o $@ $(dir $<)$(shell cat $<)
 
-%.o: $(ARCH)/%.s
+$(objdir)/%.o: $(srcdir)/%.s
 	$(AS_CMD) $(CFLAGS_ALL_STATIC)
 
-%.o: %.c $(GENH) $(IMPH)
+$(objdir)/%.o: $(srcdir)/%.c $(GENH) $(IMPH)
 	$(CC) $(CFLAGS_ALL_STATIC) -c -o $@ $<
 
-%.lo: $(ARCH)$(ASMSUBARCH)/%.sub
+$(objdir)/%.lo: $(srcdir)/%.sub
 	$(CC) $(CFLAGS_ALL_SHARED) -c -o $@ $(dir $<)$(shell cat $<)
 
-%.lo: $(ARCH)/%.s
+$(objdir)/%.lo: $(srcdir)/%.s
 	$(AS_CMD) $(CFLAGS_ALL_SHARED)
 
-%.lo: %.c $(GENH) $(IMPH)
+$(objdir)/%.lo: $(srcdir)/%.c $(GENH) $(IMPH)
 	$(CC) $(CFLAGS_ALL_SHARED) -c -o $@ $<
 
 lib/libc.so: $(LOBJS)
@@ -163,17 +177,17 @@ $(EMPTY_LIBS):
 	rm -f $@
 	$(AR) rc $@
 
-lib/%.o: crt/%.o
+lib/%.o: $(objdir)/crt/%.o
 	cp $< $@
 
-lib/musl-gcc.specs: tools/musl-gcc.specs.sh config.mak
+lib/musl-gcc.specs: $(srcdir)/tools/musl-gcc.specs.sh config.mak
 	sh $< "$(includedir)" "$(libdir)" "$(LDSO_PATHNAME)" > $@
 
 tools/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
+tools/%-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 $@
 
@@ -186,10 +200,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/%: $(objdir)/include/bits/%
 	$(INSTALL) -D -m 644 $< $@
 
-$(DESTDIR)$(includedir)/%: include/%
+$(DESTDIR)$(includedir)/%: $(srcdir)/include/%
 	$(INSTALL) -D -m 644 $< $@
 
 $(DESTDIR)$(LDSO_PATHNAME): $(DESTDIR)$(libdir)/libc.so
@@ -202,9 +219,9 @@ install-headers: $(ALL_INCLUDES:include/%=$(DESTDIR)$(includedir)/%)
 install-tools: $(ALL_TOOLS:tools/%=$(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
diff --git a/configure b/configure
index ee21771..0fac304 100755
--- 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,11 +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=.
+
+#
 # Get a temp filename we can use
 #
 i=0
@@ -321,7 +337,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 +641,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 +664,7 @@ cat << EOF
 ARCH = $ARCH
 SUBARCH = $SUBARCH
 ASMSUBARCH = $ASMSUBARCH
+srcdir = $srcdir
 prefix = $prefix
 exec_prefix = $exec_prefix
 bindir = $bindir
@@ -676,4 +693,6 @@ test "x$cc_family" = xgcc && echo 'WRAPCC_GCC = $(CC)'
 test "x$cc_family" = xclang && echo 'WRAPCC_CLANG = $(CC)'
 exec 1>&3 3>&-
 
+test -f Makefile || ln -sf $srcdir/Makefile .
+
 printf "done\n"
-- 
2.6.0.rc2.230.g3dd15c0


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-19  0:22                                                   ` Petr Hosek
@ 2015-11-20  4:09                                                     ` Rich Felker
  2015-11-20  5:02                                                       ` Rich Felker
                                                                         ` (2 more replies)
  2015-11-20 22:20                                                     ` Rich Felker
                                                                       ` (2 subsequent siblings)
  3 siblings, 3 replies; 56+ messages in thread
From: Rich Felker @ 2015-11-20  4:09 UTC (permalink / raw)
  To: musl

Thanks! Have you tested it? I get:

$ mkdir foo
$ cd foo
$ ../configure
$ make
make: *** No rule to make target `obj/include/bits', needed by `obj/include/bits/alltypes.h'.  Stop.

I think this means there's still some cruft using the old include/bits
symlink rather than the proper pathname. See below:

On Thu, Nov 19, 2015 at 12:22:09AM +0000, Petr Hosek wrote:
> > >  clean:
> > > -     rm -f crt/*.o
> > > +     rm -f $(objdir)/crt/*.o
> > >       rm -f $(OBJS)
> > >       rm -f $(LOBJS)
> > >       rm -f $(ALL_LIBS) lib/*.[ao] lib/*.so
> >
> > This can probably just be rm -rf obj, but perhaps we should wait to
> > make that change. And seeing this, I'm mildly in favor of hard-coding
> > obj/ (everywhere) rather than using $(objdir)/ simply because the
> > latter is really dangerous if you override it on the command line with
> > an unwanted setting (like make clean objdir=/).
> 
> That's why I avoided using rm -rf $(objdir). I can imagine the use case for
> setting $(objdir) to a different location, changing this to make it
> hard-coded wouldn't be a problem if you prefer.

Did you mean "can't imagine a use"? To me this looks roughly like a
"second level of out-of-tree support" that's probably not useful, and
could be error-prone e.g. if somebody tries to get clever and use
objdir=., or could be dangerous (objdir=). I think it's best just to
hard-code it.

> > > +
> > > +$(CRT_LIBS:lib/%=$(objdir)/crt/%): CFLAGS_ALL += -DCRT
> >
> > I'm not clear on whether crti.o/crtn.o end up in crt/ or crt/$(ARCH)/
> > but if it's the latter we need to handle this somehow.
> 
> These end up in crt/ even in the current upstream implementation.

I don't follow. In current upstream musl, crt*.o end up in crt/ and
then get copied from there to lib/. But if, after the out-of-tree
patch, some object files end up in crt/$(ARCH)/ instead of crt/, we
need to make sure they make it to lib/ correctly.

Now for comments on the new patch:

> +objdir = obj

Let's remove objdir entirely and just use obj/.

> -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)))
> +EXCLUDE_OBJS = $(patsubst $(srcdir)/%,%,$(subst /$(ARCH)$(ASMSUBARCH)/,/,$(subst /$(ARCH)/,/,$(patsubst $(srcdir)/%,%,$(ARCH_OBJS)))))
> +OBJS = $(addprefix $(objdir)/, $(filter-out $(EXCLUDE_OBJS), $(BASE_OBJS)) $(ARCH_OBJS) $(SUB_OBJS))

Not important at all, but REPLACED_OBJS might be a better name to
signify to people reading the makefile what this is about.

> -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:$(objdir)/%=%) $(ARCH_INCLUDES:$(srcdir)/arch/$(ARCH)/%=include/%))

This is confusing, but probably no worse than what was already there.

>  EMPTY_LIB_NAMES = m rt pthread crypt util xnet resolv dl
>  EMPTY_LIBS = $(EMPTY_LIB_NAMES:%=lib/lib%.a)
> @@ -64,10 +71,22 @@ LDSO_PATHNAME = $(syslibdir)/ld-musl-$(ARCH)$(SUBARCH).so.1
>  
>  all: $(ALL_LIBS) $(ALL_TOOLS)
>  
> +$(ALL_LIBS): | lib/
> +$(ALL_TOOLS): | tools/
> +$(CRT_LIBS:lib/%=$(objdir)/crt/%): | $(objdir)/crt/
> +$(OBJS) $(LOBJS): | $(sort $(dir $(OBJS)))
> +$(GENH): | $(objdir)/include/bits/
> +$(GENH_INT): | $(objdir)/src/internal/
> +
> +SRC_DIRS = $(sort $(dir $(ALL_LIBS) $(ALL_TOOLS) $(OBJS) $(GENH) $(GENH_INT)) $(addprefix $(objdir)/, crt/ include/))
> +
> +$(SRC_DIRS):
> +	mkdir -p $@
> +

It looks like you're missing mkdir rules for everything but $(SRC_DIRS).

> -include/bits:
> -	@test "$(ARCH)" || { echo "Please set ARCH in config.mak before running make." ; exit 1 ; }
> -	ln -sf ../arch/$(ARCH)/bits $@

Removing the bits symlink is ok, but we need to preserve the logic
that prevents trying to build without ARCH set. Perhaps something
like:

ifeq ($(ARCH),)
$(error Please run configure or set ARCH in config.mak before running make)
endif

just after the inclusion of config.mak.

>  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=$(objdir)/%.o) $(NOSSP_SRCS:%.c=$(objdir)/%.lo): CFLAGS_ALL += $(CFLAGS_NOSSP)

This looks much better.

> -$(CRT_LIBS:lib/%=crt/%): CFLAGS_ALL += -DCRT
> +$(CRT_LIBS:lib/%=$(objdir)/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.
> +#$(dir $(patsubst %/,%,$(dir $(1))))$(notdir $(1:.s=.o)): $(1)

I suppose this comment was meant to be removed?

> -%.o: $(ARCH)$(ASMSUBARCH)/%.sub
> +$(objdir)/%.o: $(srcdir)/%.sub
>  	$(CC) $(CFLAGS_ALL_STATIC) -c -o $@ $(dir $<)$(shell cat $<)

Not new in your patch, but I wonder if using $$(cat $<) would make
more sense than $(shell cat $<) -- does the latter risk getting
evaluated even when the rule isn't being run?

> -lib/%.o: crt/%.o
> +lib/%.o: $(objdir)/crt/%.o
>  	cp $< $@

I don't see how this gets arch versions of crti.o/crtn.o. I think you
must be producing the dummy ones from the empty .c files, which won't
work. Actually once this is all done the dummy .c files there can
probably be removed, or we could remove them right away to eliminate
the need for another filter-out here (but I don't think that's really
needed anyway since it's a small fixed set of files we can hard-code).

BTW that made me realize one semantic change in how the new build
system treats arch files: src/*/$(ARCH)/*.s (and .sub and whatever
other types we add) will get used now even if there's no .c file by
the same name in the parent directory. This actually looks to be
really nice -- we can eliminate dummy .c files that are empty and only
have them when the generic implementation works for some/most archs.
We can also move the arch/$(ARCH)/src/* files to appropriate
src/*/$(ARCH) locations based on what code they go with.

> +test -f Makefile || ln -sf $srcdir/Makefile .

Is there a reason you do it this way rather than checking for
srcdir=.? The reason I ask is that existence of a stray makefile
that's not a symlink to the musl makefile should probably be an error
here rather than silently ignored. But maybe there are more things to
consider..

Rich


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-20  4:09                                                     ` Rich Felker
@ 2015-11-20  5:02                                                       ` Rich Felker
  2015-11-20 10:51                                                       ` Szabolcs Nagy
  2015-11-30  1:25                                                       ` Petr Hosek
  2 siblings, 0 replies; 56+ messages in thread
From: Rich Felker @ 2015-11-20  5:02 UTC (permalink / raw)
  To: musl

On Thu, Nov 19, 2015 at 11:09:55PM -0500, Rich Felker wrote:
> On Thu, Nov 19, 2015 at 12:22:09AM +0000, Petr Hosek wrote:
> > > >  clean:
> > > > -     rm -f crt/*.o
> > > > +     rm -f $(objdir)/crt/*.o
> > > >       rm -f $(OBJS)
> > > >       rm -f $(LOBJS)
> > > >       rm -f $(ALL_LIBS) lib/*.[ao] lib/*.so
> > >
> > > This can probably just be rm -rf obj, but perhaps we should wait to
> > > make that change. And seeing this, I'm mildly in favor of hard-coding
> > > obj/ (everywhere) rather than using $(objdir)/ simply because the
> > > latter is really dangerous if you override it on the command line with
> > > an unwanted setting (like make clean objdir=/).
> > 
> > That's why I avoided using rm -rf $(objdir). I can imagine the use case for
> > setting $(objdir) to a different location, changing this to make it
> > hard-coded wouldn't be a problem if you prefer.
> 
> Did you mean "can't imagine a use"? To me this looks roughly like a
> "second level of out-of-tree support" that's probably not useful, and
> could be error-prone e.g. if somebody tries to get clever and use
> objdir=., or could be dangerous (objdir=). I think it's best just to
> hard-code it.
> 
> [...]
> 
> > +test -f Makefile || ln -sf $srcdir/Makefile .
> 
> Is there a reason you do it this way rather than checking for
> srcdir=.? The reason I ask is that existence of a stray makefile
> that's not a symlink to the musl makefile should probably be an error
> here rather than silently ignored. But maybe there are more things to
> consider..

Additional thought: can't we just ln -s $srcdir/src $srcdir/crt . in
configure and never have to bother with $(srcdir) in the makefiles?
That seems like another big benefit we can get out of putting all the
generated files in obj/ (and lib/).

Rich


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-20  4:09                                                     ` Rich Felker
  2015-11-20  5:02                                                       ` Rich Felker
@ 2015-11-20 10:51                                                       ` Szabolcs Nagy
  2015-11-30  1:25                                                       ` Petr Hosek
  2 siblings, 0 replies; 56+ messages in thread
From: Szabolcs Nagy @ 2015-11-20 10:51 UTC (permalink / raw)
  To: musl

* Rich Felker <dalias@libc.org> [2015-11-19 23:09:55 -0500]:
> Thanks! Have you tested it? I get:
> 
> $ mkdir foo
> $ cd foo
> $ ../configure
> $ make
> make: *** No rule to make target `obj/include/bits', needed by `obj/include/bits/alltypes.h'.  Stop.
> 

i cannot reproduce this, the patch works here with make 3.81


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-19  0:22                                                   ` Petr Hosek
  2015-11-20  4:09                                                     ` Rich Felker
@ 2015-11-20 22:20                                                     ` Rich Felker
  2015-11-30  1:29                                                       ` Petr Hosek
  2015-11-21  1:05                                                     ` Szabolcs Nagy
  2015-11-22 14:56                                                     ` Szabolcs Nagy
  3 siblings, 1 reply; 56+ messages in thread
From: Rich Felker @ 2015-11-20 22:20 UTC (permalink / raw)
  To: musl

On Thu, Nov 19, 2015 at 12:22:09AM +0000, Petr Hosek wrote:
> -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)))
> +EXCLUDE_OBJS = $(patsubst $(srcdir)/%,%,$(subst /$(ARCH)$(ASMSUBARCH)/,/,$(subst /$(ARCH)/,/,$(patsubst $(srcdir)/%,%,$(ARCH_OBJS)))))
> +OBJS = $(addprefix $(objdir)/, $(filter-out $(EXCLUDE_OBJS), $(BASE_OBJS)) $(ARCH_OBJS) $(SUB_OBJS))

I think this is failing to replicate the current behavior where a .sub
file in src/*/$(ARCH)$(ASMSUBARCH) replaces the .s file in
src/*/$(ARCH). In cases where both exist we'll end up with duplicate
symbol errors linking libc.so and both present (with the wrong one
likely getting used) in libc.a.

This problem will of course disappear when we get rid of .sub files,
but that doesn't help unless we remove .sub files first.

I suppose all that's needed for now is to add more EXCLUDE_OBJS using
the same input but with:

	$(subst /$(ARCH)$(ASMSUBARCH)/,/$(ARCH)/,...

instead of:

	$(subst /$(ARCH)$(ASMSUBARCH)/,/,...

Does this sound right?

Rich


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-19  0:22                                                   ` Petr Hosek
  2015-11-20  4:09                                                     ` Rich Felker
  2015-11-20 22:20                                                     ` Rich Felker
@ 2015-11-21  1:05                                                     ` Szabolcs Nagy
  2015-11-21  1:16                                                       ` Szabolcs Nagy
  2015-11-22 14:56                                                     ` Szabolcs Nagy
  3 siblings, 1 reply; 56+ messages in thread
From: Szabolcs Nagy @ 2015-11-21  1:05 UTC (permalink / raw)
  To: musl

* Petr Hosek <phosek@chromium.org> [2015-11-19 00:22:09 +0000]:
> +$(ALL_LIBS): | lib/
> +$(ALL_TOOLS): | tools/
> +$(CRT_LIBS:lib/%=$(objdir)/crt/%): | $(objdir)/crt/
> +$(OBJS) $(LOBJS): | $(sort $(dir $(OBJS)))
> +$(GENH): | $(objdir)/include/bits/
> +$(GENH_INT): | $(objdir)/src/internal/
> +
> +SRC_DIRS = $(sort $(dir $(ALL_LIBS) $(ALL_TOOLS) $(OBJS) $(GENH) $(GENH_INT)) $(addprefix $(objdir)/, crt/ include/))
> +
> +$(SRC_DIRS):
> +	mkdir -p $@
> +
...
> +$(objdir)/include/bits/alltypes.h: $(srcdir)/arch/$(ARCH)/bits/alltypes.h.in $(srcdir)/include/alltypes.h.in $(srcdir)/tools/mkalltypes.sed $(objdir)/include/bits

this needs a / at the end otherwise make 4.1 fails with

make: *** No rule to make target 'obj/include/bits', needed by 'obj/include/bits/alltypes.h'.  Stop.

> +	sed -f $(srcdir)/tools/mkalltypes.sed $(srcdir)/arch/$(ARCH)/bits/alltypes.h.in $(srcdir)/include/alltypes.h.in > $@
>  


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-21  1:05                                                     ` Szabolcs Nagy
@ 2015-11-21  1:16                                                       ` Szabolcs Nagy
  0 siblings, 0 replies; 56+ messages in thread
From: Szabolcs Nagy @ 2015-11-21  1:16 UTC (permalink / raw)
  To: musl

* Szabolcs Nagy <nsz@port70.net> [2015-11-21 02:05:33 +0100]:

> * Petr Hosek <phosek@chromium.org> [2015-11-19 00:22:09 +0000]:
> > +$(ALL_LIBS): | lib/
> > +$(ALL_TOOLS): | tools/
> > +$(CRT_LIBS:lib/%=$(objdir)/crt/%): | $(objdir)/crt/
> > +$(OBJS) $(LOBJS): | $(sort $(dir $(OBJS)))
> > +$(GENH): | $(objdir)/include/bits/
> > +$(GENH_INT): | $(objdir)/src/internal/
> > +
> > +SRC_DIRS = $(sort $(dir $(ALL_LIBS) $(ALL_TOOLS) $(OBJS) $(GENH) $(GENH_INT)) $(addprefix $(objdir)/, crt/ include/))
> > +
> > +$(SRC_DIRS):
> > +	mkdir -p $@
> > +
> ...
> > +$(objdir)/include/bits/alltypes.h: $(srcdir)/arch/$(ARCH)/bits/alltypes.h.in $(srcdir)/include/alltypes.h.in $(srcdir)/tools/mkalltypes.sed $(objdir)/include/bits
> 
> this needs a / at the end otherwise make 4.1 fails with
> 
> make: *** No rule to make target 'obj/include/bits', needed by 'obj/include/bits/alltypes.h'.  Stop.
> 

sorry,
the obj/include/bits dependency has to be removed here,
the order only dep does the right thing


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-19  0:22                                                   ` Petr Hosek
                                                                       ` (2 preceding siblings ...)
  2015-11-21  1:05                                                     ` Szabolcs Nagy
@ 2015-11-22 14:56                                                     ` Szabolcs Nagy
  2015-11-30  1:30                                                       ` Petr Hosek
  3 siblings, 1 reply; 56+ messages in thread
From: Szabolcs Nagy @ 2015-11-22 14:56 UTC (permalink / raw)
  To: musl

* Petr Hosek <phosek@chromium.org> [2015-11-19 00:22:09 +0000]:
>  
> +$(ALL_LIBS): | lib/
> +$(ALL_TOOLS): | tools/
> +$(CRT_LIBS:lib/%=$(objdir)/crt/%): | $(objdir)/crt/
> +$(OBJS) $(LOBJS): | $(sort $(dir $(OBJS)))
> +$(GENH): | $(objdir)/include/bits/
> +$(GENH_INT): | $(objdir)/src/internal/
> +

one more comment:
tools/ is now used for both sources and outputs,
i think it can be used for sources only by moving
the tools outputs under obj/ (so tools/ does not
need to be created out of tree, only obj/ and lib/)


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-20  4:09                                                     ` Rich Felker
  2015-11-20  5:02                                                       ` Rich Felker
  2015-11-20 10:51                                                       ` Szabolcs Nagy
@ 2015-11-30  1:25                                                       ` Petr Hosek
  2 siblings, 0 replies; 56+ messages in thread
From: Petr Hosek @ 2015-11-30  1:25 UTC (permalink / raw)
  To: musl


[-- Attachment #1.1: Type: text/plain, Size: 2907 bytes --]

I'm sorry about the delay, I've been away last week. I've incorporated all
your code review comments. However, I haven't replaced the use of Makefile
symlink with make -C $(srcdir) as discussed on IRC since it's not clear
whether that's the way we want to go.

On Thu, Nov 19, 2015 at 8:10 PM Rich Felker <dalias@libc.org> wrote:

> Let's remove objdir entirely and just use obj/.
>

Done.


> Not important at all, but REPLACED_OBJS might be a better name to
> signify to people reading the makefile what this is about.
>

Renamed.


> It looks like you're missing mkdir rules for everything but $(SRC_DIRS).
>

Those are the only directories which should be needed.


> Removing the bits symlink is ok, but we need to preserve the logic
> that prevents trying to build without ARCH set. Perhaps something
> like:
>
> ifeq ($(ARCH),)
> $(error Please run configure or set ARCH in config.mak before running make)
> endif
>
> just after the inclusion of config.mak.
>

Done.


> I suppose this comment was meant to be removed?
>

Yes, removed.


> Not new in your patch, but I wonder if using $$(cat $<) would make
> more sense than $(shell cat $<) -- does the latter risk getting
> evaluated even when the rule isn't being run?
>

That seem to work fine.


> > -lib/%.o: crt/%.o
> > +lib/%.o: $(objdir)/crt/%.o
> >       cp $< $@
>
> I don't see how this gets arch versions of crti.o/crtn.o. I think you
> must be producing the dummy ones from the empty .c files, which won't
> work. Actually once this is all done the dummy .c files there can
> probably be removed, or we could remove them right away to eliminate
> the need for another filter-out here (but I don't think that's really
> needed anyway since it's a small fixed set of files we can hard-code).
>

That was a mistake. I've added explicit rules for both crti.o and crtn.o.


> BTW that made me realize one semantic change in how the new build
> system treats arch files: src/*/$(ARCH)/*.s (and .sub and whatever
> other types we add) will get used now even if there's no .c file by
> the same name in the parent directory. This actually looks to be
> really nice -- we can eliminate dummy .c files that are empty and only
> have them when the generic implementation works for some/most archs.
> We can also move the arch/$(ARCH)/src/* files to appropriate
> src/*/$(ARCH) locations based on what code they go with.
>

True, do you want me to remove all these files in the same or a separate
patch?


> > +test -f Makefile || ln -sf $srcdir/Makefile .
>
> Is there a reason you do it this way rather than checking for
> srcdir=.? The reason I ask is that existence of a stray makefile
> that's not a symlink to the musl makefile should probably be an error
> here rather than silently ignored. But maybe there are more things to
> consider..
>

There is no particular reason, failing in case of existing Makefile sounds
like a better solution.

[-- Attachment #1.2: Type: text/html, Size: 5241 bytes --]

[-- Attachment #2: support-out-of-tree-build.patch --]
[-- Type: text/x-patch, Size: 13742 bytes --]

From bbd093ca25b244fef288c4a0c4ec2265fae1de45 Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek@chromium.org>
Date: Wed, 18 Nov 2015 12:07:32 -0800
Subject: [PATCH] support out-of-tree build

this change add support for building musl outside of the source
tree. the implementation is similar to autotools where running
configure in a different folder 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 |   1 +
 Makefile   | 121 ++++++++++++++++++++++++++++++++++++++-----------------------
 configure  |  25 +++++++++++--
 3 files changed, 98 insertions(+), 49 deletions(-)

diff --git a/.gitignore b/.gitignore
index c5d5c46..36dc5f9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@
 *.a
 *.so
 *.so.1
+obj
 arch/*/bits/alltypes.h
 config.mak
 include/bits
diff --git a/Makefile b/Makefile
index df20f94..bbf6794 100644
--- 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 = $(patsubst $(srcdir)/%,%,$(subst /$(ARCH)$(ASMSUBARCH)/,/,$(subst /$(ARCH)/,/,$(patsubst $(srcdir)/%,%,$(ARCH_OBJS)))))
+OBJS = $(addprefix obj/, $(filter-out $(REPLACED_OBJS), $(BASE_OBJS)) $(ARCH_OBJS) $(SUB_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)
@@ -62,12 +68,28 @@ 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)
 
+$(ALL_LIBS): | lib/
+$(ALL_TOOLS): | tools/
+$(CRT_LIBS:lib/%=obj/crt/%): | obj/crt/ obj/crt/$(ARCH)/
+$(OBJS) $(LOBJS): | $(sort $(dir $(OBJS)))
+$(GENH): | obj/include/bits/
+$(GENH_INT): | obj/src/internal/
+
+OBJ_DIRS = $(sort $(dir $(ALL_LIBS) $(ALL_TOOLS) $(OBJS) $(GENH) $(GENH_INT)) $(addprefix obj/, crt/ crt/$(ARCH) include/))
+
+$(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
@@ -78,75 +100,73 @@ clean:
 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,17 +183,23 @@ $(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
 	printf '#!/bin/sh\nexec "$${REALGCC:-$(WRAPCC_GCC)}" "$$@" -specs "%s/musl-gcc.specs"\n' "$(libdir)" > $@
 	chmod +x $@
 
-tools/%-clang: tools/%-clang.in config.mak
+tools/%-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 $@
 
@@ -186,10 +212,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
@@ -202,9 +231,9 @@ install-headers: $(ALL_INCLUDES:include/%=$(DESTDIR)$(includedir)/%)
 install-tools: $(ALL_TOOLS:tools/%=$(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
diff --git a/configure b/configure
index ee21771..0e48002 100755
--- 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,11 +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=.
+
+#
 # Get a temp filename we can use
 #
 i=0
@@ -321,7 +337,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 +641,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 +664,7 @@ cat << EOF
 ARCH = $ARCH
 SUBARCH = $SUBARCH
 ASMSUBARCH = $ASMSUBARCH
+srcdir = $srcdir
 prefix = $prefix
 exec_prefix = $exec_prefix
 bindir = $bindir
@@ -676,4 +693,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 -s $srcdir/Makefile .
+
 printf "done\n"
-- 
2.6.0.rc2.230.g3dd15c0


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-20 22:20                                                     ` Rich Felker
@ 2015-11-30  1:29                                                       ` Petr Hosek
  2015-11-30  1:35                                                         ` Rich Felker
  0 siblings, 1 reply; 56+ messages in thread
From: Petr Hosek @ 2015-11-30  1:29 UTC (permalink / raw)
  To: musl

[-- Attachment #1: Type: text/plain, Size: 1118 bytes --]

On Fri, Nov 20, 2015 at 2:21 PM Rich Felker <dalias@libc.org> wrote:

> I think this is failing to replicate the current behavior where a .sub
> file in src/*/$(ARCH)$(ASMSUBARCH) replaces the .s file in
> src/*/$(ARCH). In cases where both exist we'll end up with duplicate
> symbol errors linking libc.so and both present (with the wrong one
> likely getting used) in libc.a.
>

I tried various combinations of ARCH and SUBARCH and the behavior seems to
be the same as in current implementation. Do you have any examples?


> This problem will of course disappear when we get rid of .sub files,
> but that doesn't help unless we remove .sub files first.
>
> I suppose all that's needed for now is to add more EXCLUDE_OBJS using
> the same input but with:
>
>         $(subst /$(ARCH)$(ASMSUBARCH)/,/$(ARCH)/,...
>
> instead of:
>
>         $(subst /$(ARCH)$(ASMSUBARCH)/,/,...
>
> Does this sound right?
>

When I tried this change, I started getting duplicate symbol errors when
linking libc.so, but with the original it seems to be working fine (this
particular case was when ARCH=arm SUBARCH=hf ASMSUBARCH=ebhf).

[-- Attachment #2: Type: text/html, Size: 1600 bytes --]

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-22 14:56                                                     ` Szabolcs Nagy
@ 2015-11-30  1:30                                                       ` Petr Hosek
  2015-11-30 12:01                                                         ` Szabolcs Nagy
  0 siblings, 1 reply; 56+ messages in thread
From: Petr Hosek @ 2015-11-30  1:30 UTC (permalink / raw)
  To: musl

[-- Attachment #1: Type: text/plain, Size: 689 bytes --]

On Sun, Nov 22, 2015 at 6:56 AM Szabolcs Nagy <nsz@port70.net> wrote:

> * Petr Hosek <phosek@chromium.org> [2015-11-19 00:22:09 +0000]:
> >
> > +$(ALL_LIBS): | lib/
> > +$(ALL_TOOLS): | tools/
> > +$(CRT_LIBS:lib/%=$(objdir)/crt/%): | $(objdir)/crt/
> > +$(OBJS) $(LOBJS): | $(sort $(dir $(OBJS)))
> > +$(GENH): | $(objdir)/include/bits/
> > +$(GENH_INT): | $(objdir)/src/internal/
> > +
>
> one more comment:
> tools/ is now used for both sources and outputs,
> i think it can be used for sources only by moving
> the tools outputs under obj/ (so tools/ does not
> need to be created out of tree, only obj/ and lib/)
>

Do you mean moving the tools output directly to obj/ or obj/tools?

[-- Attachment #2: Type: text/html, Size: 1076 bytes --]

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-30  1:29                                                       ` Petr Hosek
@ 2015-11-30  1:35                                                         ` Rich Felker
  2015-11-30  2:49                                                           ` Petr Hosek
  0 siblings, 1 reply; 56+ messages in thread
From: Rich Felker @ 2015-11-30  1:35 UTC (permalink / raw)
  To: musl

On Mon, Nov 30, 2015 at 01:29:06AM +0000, Petr Hosek wrote:
> On Fri, Nov 20, 2015 at 2:21 PM Rich Felker <dalias@libc.org> wrote:
> 
> > I think this is failing to replicate the current behavior where a .sub
> > file in src/*/$(ARCH)$(ASMSUBARCH) replaces the .s file in
> > src/*/$(ARCH). In cases where both exist we'll end up with duplicate
> > symbol errors linking libc.so and both present (with the wrong one
> > likely getting used) in libc.a.
> >
> 
> I tried various combinations of ARCH and SUBARCH and the behavior seems to
> be the same as in current implementation. Do you have any examples?

With ARCH=sh and SUBARCH=-nofpu and ASMSUBARCH=-nofpu, it looks to
me like both src/setjmp/sh/setjmp.o and src/setjmp/sh-nofpu/setjmp.s
will get included, rather than the latter replacing the former.

> > This problem will of course disappear when we get rid of .sub files,
> > but that doesn't help unless we remove .sub files first.
> >
> > I suppose all that's needed for now is to add more EXCLUDE_OBJS using
> > the same input but with:
> >
> >         $(subst /$(ARCH)$(ASMSUBARCH)/,/$(ARCH)/,...
> >
> > instead of:
> >
> >         $(subst /$(ARCH)$(ASMSUBARCH)/,/,...
> >
> > Does this sound right?
> >
> 
> When I tried this change, I started getting duplicate symbol errors when
> linking libc.so, but with the original it seems to be working fine (this
> particular case was when ARCH=arm SUBARCH=hf ASMSUBARCH=ebhf).

I didn't mean to get rid of the existing subst, but to introduce a
second one, so that src/whatever/$(ARCH)@(ASMSUBARCH)/foo.o
excludes/replaces both src/whatever/$(ARCH)/foo.o and
src/whatever/foo.o.

Rich


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-30  1:35                                                         ` Rich Felker
@ 2015-11-30  2:49                                                           ` Petr Hosek
  2015-11-30 21:14                                                             ` Rich Felker
  0 siblings, 1 reply; 56+ messages in thread
From: Petr Hosek @ 2015-11-30  2:49 UTC (permalink / raw)
  To: musl


[-- Attachment #1.1: Type: text/plain, Size: 825 bytes --]

On Sun, Nov 29, 2015 at 5:36 PM Rich Felker <dalias@libc.org> wrote:

> With ARCH=sh and SUBARCH=-nofpu and ASMSUBARCH=-nofpu, it looks to
> me like both src/setjmp/sh/setjmp.o and src/setjmp/sh-nofpu/setjmp.s
> will get included, rather than the latter replacing the former.
>

Thanks, I managed to replicate that error.


> > When I tried this change, I started getting duplicate symbol errors when
> > linking libc.so, but with the original it seems to be working fine (this
> > particular case was when ARCH=arm SUBARCH=hf ASMSUBARCH=ebhf).
>
> I didn't mean to get rid of the existing subst, but to introduce a
> second one, so that src/whatever/$(ARCH)@(ASMSUBARCH)/foo.o
> excludes/replaces both src/whatever/$(ARCH)/foo.o and
> src/whatever/foo.o.
>

Got it, I've added the additional subst which solves the problem.

[-- Attachment #1.2: Type: text/html, Size: 1279 bytes --]

[-- Attachment #2: support-out-of-tree-build.patch --]
[-- Type: text/x-patch, Size: 13770 bytes --]

From f9817bb4fe1075c58764107151017d81b158db31 Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek@chromium.org>
Date: Wed, 18 Nov 2015 12:07:32 -0800
Subject: [PATCH] support out-of-tree build

this change add support for building musl outside of the source
tree. the implementation is similar to autotools where running
configure in a different folder 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 |   1 +
 Makefile   | 121 ++++++++++++++++++++++++++++++++++++++-----------------------
 configure  |  25 +++++++++++--
 3 files changed, 98 insertions(+), 49 deletions(-)

diff --git a/.gitignore b/.gitignore
index c5d5c46..36dc5f9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@
 *.a
 *.so
 *.so.1
+obj
 arch/*/bits/alltypes.h
 config.mak
 include/bits
diff --git a/Makefile b/Makefile
index df20f94..c5847b3 100644
--- 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)
@@ -62,12 +68,28 @@ 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)
 
+$(ALL_LIBS): | lib/
+$(ALL_TOOLS): | tools/
+$(CRT_LIBS:lib/%=obj/crt/%): | obj/crt/ obj/crt/$(ARCH)/
+$(OBJS) $(LOBJS): | $(sort $(dir $(OBJS)))
+$(GENH): | obj/include/bits/
+$(GENH_INT): | obj/src/internal/
+
+OBJ_DIRS = $(sort $(dir $(ALL_LIBS) $(ALL_TOOLS) $(OBJS) $(GENH) $(GENH_INT)) $(addprefix obj/, crt/ crt/$(ARCH) include/))
+
+$(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
@@ -78,75 +100,73 @@ clean:
 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,17 +183,23 @@ $(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
 	printf '#!/bin/sh\nexec "$${REALGCC:-$(WRAPCC_GCC)}" "$$@" -specs "%s/musl-gcc.specs"\n' "$(libdir)" > $@
 	chmod +x $@
 
-tools/%-clang: tools/%-clang.in config.mak
+tools/%-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 $@
 
@@ -186,10 +212,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
@@ -202,9 +231,9 @@ install-headers: $(ALL_INCLUDES:include/%=$(DESTDIR)$(includedir)/%)
 install-tools: $(ALL_TOOLS:tools/%=$(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
diff --git a/configure b/configure
index ee21771..0e48002 100755
--- 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,11 +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=.
+
+#
 # Get a temp filename we can use
 #
 i=0
@@ -321,7 +337,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 +641,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 +664,7 @@ cat << EOF
 ARCH = $ARCH
 SUBARCH = $SUBARCH
 ASMSUBARCH = $ASMSUBARCH
+srcdir = $srcdir
 prefix = $prefix
 exec_prefix = $exec_prefix
 bindir = $bindir
@@ -676,4 +693,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 -s $srcdir/Makefile .
+
 printf "done\n"
-- 
2.6.0.rc2.230.g3dd15c0


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-30  1:30                                                       ` Petr Hosek
@ 2015-11-30 12:01                                                         ` Szabolcs Nagy
  2015-11-30 22:22                                                           ` Rich Felker
  0 siblings, 1 reply; 56+ messages in thread
From: Szabolcs Nagy @ 2015-11-30 12:01 UTC (permalink / raw)
  To: musl

* Petr Hosek <phosek@chromium.org> [2015-11-30 01:30:30 +0000]:
> On Sun, Nov 22, 2015 at 6:56 AM Szabolcs Nagy <nsz@port70.net> wrote:
> 
> > * Petr Hosek <phosek@chromium.org> [2015-11-19 00:22:09 +0000]:
> > >
> > > +$(ALL_LIBS): | lib/
> > > +$(ALL_TOOLS): | tools/
> > > +$(CRT_LIBS:lib/%=$(objdir)/crt/%): | $(objdir)/crt/
> > > +$(OBJS) $(LOBJS): | $(sort $(dir $(OBJS)))
> > > +$(GENH): | $(objdir)/include/bits/
> > > +$(GENH_INT): | $(objdir)/src/internal/
> > > +
> >
> > one more comment:
> > tools/ is now used for both sources and outputs,
> > i think it can be used for sources only by moving
> > the tools outputs under obj/ (so tools/ does not
> > need to be created out of tree, only obj/ and lib/)
> >
> 
> Do you mean moving the tools output directly to obj/ or obj/tools?

i think obj/ is ok.

(i like flatter dir hierarchy if only a small number
of files are involved.)



^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-30  2:49                                                           ` Petr Hosek
@ 2015-11-30 21:14                                                             ` Rich Felker
  2015-11-30 22:14                                                               ` Rich Felker
  0 siblings, 1 reply; 56+ messages in thread
From: Rich Felker @ 2015-11-30 21:14 UTC (permalink / raw)
  To: musl

On Mon, Nov 30, 2015 at 02:49:47AM +0000, Petr Hosek wrote:
> On Sun, Nov 29, 2015 at 5:36 PM Rich Felker <dalias@libc.org> wrote:
> 
> > With ARCH=sh and SUBARCH=-nofpu and ASMSUBARCH=-nofpu, it looks to
> > me like both src/setjmp/sh/setjmp.o and src/setjmp/sh-nofpu/setjmp.s
> > will get included, rather than the latter replacing the former.
> >
> 
> Thanks, I managed to replicate that error.
> 
> 
> > > When I tried this change, I started getting duplicate symbol errors when
> > > linking libc.so, but with the original it seems to be working fine (this
> > > particular case was when ARCH=arm SUBARCH=hf ASMSUBARCH=ebhf).
> >
> > I didn't mean to get rid of the existing subst, but to introduce a
> > second one, so that src/whatever/$(ARCH)@(ASMSUBARCH)/foo.o
> > excludes/replaces both src/whatever/$(ARCH)/foo.o and
> > src/whatever/foo.o.
> >
> 
> Got it, I've added the additional subst which solves the problem.

I'm trying it again now, and I'm still getting an error trying to
build in a fresh out-of-tree dir:

make: *** No rule to make target `obj/crt/i386/', needed by `obj/crt/crt1.o'.  Stop.

Rich


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-30 21:14                                                             ` Rich Felker
@ 2015-11-30 22:14                                                               ` Rich Felker
  2015-12-01  2:14                                                                 ` Petr Hosek
  0 siblings, 1 reply; 56+ messages in thread
From: Rich Felker @ 2015-11-30 22:14 UTC (permalink / raw)
  To: musl

On Mon, Nov 30, 2015 at 04:14:32PM -0500, Rich Felker wrote:
> On Mon, Nov 30, 2015 at 02:49:47AM +0000, Petr Hosek wrote:
> > On Sun, Nov 29, 2015 at 5:36 PM Rich Felker <dalias@libc.org> wrote:
> > 
> > > With ARCH=sh and SUBARCH=-nofpu and ASMSUBARCH=-nofpu, it looks to
> > > me like both src/setjmp/sh/setjmp.o and src/setjmp/sh-nofpu/setjmp.s
> > > will get included, rather than the latter replacing the former.
> > >
> > 
> > Thanks, I managed to replicate that error.
> > 
> > 
> > > > When I tried this change, I started getting duplicate symbol errors when
> > > > linking libc.so, but with the original it seems to be working fine (this
> > > > particular case was when ARCH=arm SUBARCH=hf ASMSUBARCH=ebhf).
> > >
> > > I didn't mean to get rid of the existing subst, but to introduce a
> > > second one, so that src/whatever/$(ARCH)@(ASMSUBARCH)/foo.o
> > > excludes/replaces both src/whatever/$(ARCH)/foo.o and
> > > src/whatever/foo.o.
> > >
> > 
> > Got it, I've added the additional subst which solves the problem.
> 
> I'm trying it again now, and I'm still getting an error trying to
> build in a fresh out-of-tree dir:
> 
> make: *** No rule to make target `obj/crt/i386/', needed by `obj/crt/crt1.o'.  Stop.

Manually creating the directory makes the build succeed. I also get,
when re-running configure:

creating config.mak... ln: ./Makefile: File exists
done

Not an error, but confusing and not what I would expect.

Rich


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-30 12:01                                                         ` Szabolcs Nagy
@ 2015-11-30 22:22                                                           ` Rich Felker
  0 siblings, 0 replies; 56+ messages in thread
From: Rich Felker @ 2015-11-30 22:22 UTC (permalink / raw)
  To: musl

On Mon, Nov 30, 2015 at 01:01:57PM +0100, Szabolcs Nagy wrote:
> * Petr Hosek <phosek@chromium.org> [2015-11-30 01:30:30 +0000]:
> > On Sun, Nov 22, 2015 at 6:56 AM Szabolcs Nagy <nsz@port70.net> wrote:
> > 
> > > * Petr Hosek <phosek@chromium.org> [2015-11-19 00:22:09 +0000]:
> > > >
> > > > +$(ALL_LIBS): | lib/
> > > > +$(ALL_TOOLS): | tools/
> > > > +$(CRT_LIBS:lib/%=$(objdir)/crt/%): | $(objdir)/crt/
> > > > +$(OBJS) $(LOBJS): | $(sort $(dir $(OBJS)))
> > > > +$(GENH): | $(objdir)/include/bits/
> > > > +$(GENH_INT): | $(objdir)/src/internal/
> > > > +
> > >
> > > one more comment:
> > > tools/ is now used for both sources and outputs,
> > > i think it can be used for sources only by moving
> > > the tools outputs under obj/ (so tools/ does not
> > > need to be created out of tree, only obj/ and lib/)
> > >
> > 
> > Do you mean moving the tools output directly to obj/ or obj/tools?
> 
> i think obj/ is ok.
> 
> (i like flatter dir hierarchy if only a small number
> of files are involved.)

I'm not sure if it makes a difference, but conceptually right now obj
is intermediate files for build, and lib and tools contain the actual
files intended to be installed. The one exception to this is headers,
which are split between the $(srcdir)/include,
$(srcdir)/arch/$(ARCH)/bits, and obj/include/bits, making the latter
the one installed file from obj.

I don't think we have to resolve this at the same time as out-of-tree,
but I'd moderately prefer putting all the installable files under one
directory structured just like an install prefix, to make it easy to
use them in-place without installing. This worked historically with
the in-tree build thanks to the (very problematic, otherwise) bits
symlink.

Rich


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-11-30 22:14                                                               ` Rich Felker
@ 2015-12-01  2:14                                                                 ` Petr Hosek
  2015-12-09  0:39                                                                   ` Rich Felker
  0 siblings, 1 reply; 56+ messages in thread
From: Petr Hosek @ 2015-12-01  2:14 UTC (permalink / raw)
  To: musl


[-- Attachment #1.1: Type: text/plain, Size: 624 bytes --]

On Mon, Nov 30, 2015 at 2:14 PM Rich Felker <dalias@libc.org> wrote:

> > I'm trying it again now, and I'm still getting an error trying to
> > build in a fresh out-of-tree dir:
> >
> > make: *** No rule to make target `obj/crt/i386/', needed by
> `obj/crt/crt1.o'.  Stop.
>

I've removed the trailing slashes as discussed on IRC and this should work
now.


> Manually creating the directory makes the build succeed. I also get,
> when re-running configure:
>
> creating config.mak... ln: ./Makefile: File exists
> done
>
> Not an error, but confusing and not what I would expect.
>

I've added a check to configure script.

[-- Attachment #1.2: Type: text/html, Size: 1095 bytes --]

[-- Attachment #2: support-out-of-tree-build.patch --]
[-- Type: text/x-patch, Size: 14932 bytes --]

From 2378d148101102b9cdeda56255a0c5e865b957d5 Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek@chromium.org>
Date: Wed, 18 Nov 2015 12:07:32 -0800
Subject: [PATCH] support out-of-tree build

this change add support for building musl outside of the source
tree. the implementation is similar to autotools where running
configure in a different folder 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 |   5 +--
 Makefile   | 131 +++++++++++++++++++++++++++++++++++++------------------------
 configure  |  30 +++++++++++---
 3 files changed, 106 insertions(+), 60 deletions(-)

diff --git a/.gitignore b/.gitignore
index c5d5c46..2cb88d4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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/
diff --git a/Makefile b/Makefile
index df20f94..3a98b0b 100644
--- 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,105 @@ 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)
 
+$(ALL_LIBS): | lib
+$(ALL_TOOLS): | obj
+$(CRT_LIBS:lib/%=obj/crt/%): | obj/crt obj/crt/$(ARCH)
+$(OBJS) $(LOBJS): | $(sort $(dir $(OBJS)))
+$(GENH): | obj/include/bits
+$(GENH_INT): | obj/src/internal
+
+OBJ_DIRS = $(sort $(dir $(ALL_LIBS) $(ALL_TOOLS) $(OBJS) $(GENH) $(GENH_INT)) $(addprefix obj/, crt crt/$(ARCH) include))
+
+$(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 +183,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 +212,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 +228,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
diff --git a/configure b/configure
index ee21771..9666f1f 100755
--- 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,11 +184,23 @@ 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 -e Makefile && fail "$0: Makefile already exists in the working directory"
+
+#
 # Get a temp filename we can use
 #
 i=0
@@ -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"
-- 
2.6.0.rc2.230.g3dd15c0


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-12-01  2:14                                                                 ` Petr Hosek
@ 2015-12-09  0:39                                                                   ` Rich Felker
  2015-12-10  1:39                                                                     ` Petr Hosek
  0 siblings, 1 reply; 56+ messages in thread
From: Rich Felker @ 2015-12-09  0:39 UTC (permalink / raw)
  To: musl

Sorry it took me a while to get to this (and other pending musl
stuff). Here's my review:

On Tue, Dec 01, 2015 at 02:14:29AM +0000, Petr Hosek wrote:
> On Mon, Nov 30, 2015 at 2:14 PM Rich Felker <dalias@libc.org> wrote:
> 
> > > I'm trying it again now, and I'm still getting an error trying to
> > > build in a fresh out-of-tree dir:
> > >
> > > make: *** No rule to make target `obj/crt/i386/', needed by
> > `obj/crt/crt1.o'.  Stop.
> >
> 
> I've removed the trailing slashes as discussed on IRC and this should work
> now.

I get:

make: *** No rule to make target `obj/include/bits', needed by `obj/include/bits/alltypes.h'.  Stop.

I think this is because $(dir...) intentionally leaves the trailing
slash, so you have to remove it to get the desired behavior.

First I tried:

OBJ_DIRS = $(sort $(patsubst %/,%,$(dir $(ALL_LIBS) $(ALL_TOOLS) $(OBJS) $(GENH) $(GENH_INT))) $(addprefix obj/, crt crt/$(ARCH) include))

but this does not seem to be sufficient, because of:

$(OBJS) $(LOBJS): | $(sort $(dir $(OBJS)))

Adding patsubst there would work too, but I wonder if it even makes
sense to have fine-grained dir dependencies, rather than just making
all the targets in this section of the makefile depend on $(OBJ_DIRS).
Thoughts?

> > Manually creating the directory makes the build succeed. I also get,
> > when re-running configure:
> >
> > creating config.mak... ln: ./Makefile: File exists
> > done
> >
> > Not an error, but confusing and not what I would expect.
> >
> 
> I've added a check to configure script.

../configure: Makefile already exists in the working directory

This isn't what I would expect either. Normally you want to be able to
re-run configure with different options. There's probably a little bit
of subtlety here because we would like to avoid overwriting an actual
file (if somebody copied and edited a makefile here) but happily
replace a symlink.

Aside from these issues it seems to be okay/working for me. I'd
appreciate comments from anyone else who's tried it.

Rich


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-12-09  0:39                                                                   ` Rich Felker
@ 2015-12-10  1:39                                                                     ` Petr Hosek
  2015-12-10 12:47                                                                       ` Szabolcs Nagy
  2016-01-17 22:32                                                                       ` Rich Felker
  0 siblings, 2 replies; 56+ messages in thread
From: Petr Hosek @ 2015-12-10  1:39 UTC (permalink / raw)
  To: musl


[-- Attachment #1.1: Type: text/plain, Size: 1802 bytes --]

On Tue, Dec 8, 2015 at 4:39 PM Rich Felker <dalias@libc.org> wrote:

> I get:
>
> make: *** No rule to make target `obj/include/bits', needed by
> `obj/include/bits/alltypes.h'.  Stop.
>
> I think this is because $(dir...) intentionally leaves the trailing
> slash, so you have to remove it to get the desired behavior.
>

I'm not sure why I don't see the same behavior in my setting, but I used
make -p and you're correct, $(dir ...) leaves the trailing slashes.


> First I tried:
>
> OBJ_DIRS = $(sort $(patsubst %/,%,$(dir $(ALL_LIBS) $(ALL_TOOLS) $(OBJS)
> $(GENH) $(GENH_INT))) $(addprefix obj/, crt crt/$(ARCH) include))
>
> but this does not seem to be sufficient, because of:
>
> $(OBJS) $(LOBJS): | $(sort $(dir $(OBJS)))
>
> Adding patsubst there would work too, but I wonder if it even makes
> sense to have fine-grained dir dependencies, rather than just making
> all the targets in this section of the makefile depend on $(OBJ_DIRS).
> Thoughts?
>

I've used the approach you suggested yesterday over IRC which simplifies
the Makefile a bit.


> ../configure: Makefile already exists in the working directory
>
> This isn't what I would expect either. Normally you want to be able to
> re-run configure with different options. There's probably a little bit
> of subtlety here because we would like to avoid overwriting an actual
> file (if somebody copied and edited a makefile here) but happily
> replace a symlink.
>

I've expanded the check to cover both the existing file and symlink case.


> Aside from these issues it seems to be okay/working for me. I'd
> appreciate comments from anyone else who's tried it.
>

I've been using the previous version in my setup for about two weeks now
and haven't found any further issue but I'd like to hear from others if
they found any issues.

[-- Attachment #1.2: Type: text/html, Size: 2644 bytes --]

[-- Attachment #2: support-out-of-tree-build.patch --]
[-- Type: text/x-patch, Size: 14870 bytes --]

From d56b49b703ba9a86f099c49095686d6477309cdf Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek@chromium.org>
Date: Wed, 18 Nov 2015 12:07:32 -0800
Subject: [PATCH] support out-of-tree build

this change add support for building musl outside of the source
tree. the implementation is similar to autotools where running
configure in a different folder 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 |   5 +--
 Makefile   | 126 ++++++++++++++++++++++++++++++++++++-------------------------
 configure  |  30 ++++++++++++---
 3 files changed, 101 insertions(+), 60 deletions(-)

diff --git a/.gitignore b/.gitignore
index c5d5c46..2cb88d4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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/
diff --git a/Makefile b/Makefile
index df20f94..44b39b9 100644
--- 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
diff --git a/configure b/configure
index ee21771..fcfdc15 100755
--- 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,11 +184,23 @@ 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
 #
 i=0
@@ -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"
-- 
2.6.0.rc2.230.g3dd15c0


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-12-10  1:39                                                                     ` Petr Hosek
@ 2015-12-10 12:47                                                                       ` Szabolcs Nagy
  2016-01-17 22:32                                                                       ` Rich Felker
  1 sibling, 0 replies; 56+ messages in thread
From: Szabolcs Nagy @ 2015-12-10 12:47 UTC (permalink / raw)
  To: musl

* Petr Hosek <phosek@chromium.org> [2015-12-10 01:39:44 +0000]:
> On Tue, Dec 8, 2015 at 4:39 PM Rich Felker <dalias@libc.org> wrote:
> 
> > I get:
> >
> > make: *** No rule to make target `obj/include/bits', needed by
> > `obj/include/bits/alltypes.h'.  Stop.
> >
> > I think this is because $(dir...) intentionally leaves the trailing
> > slash, so you have to remove it to get the desired behavior.
> >
> 
> I'm not sure why I don't see the same behavior in my setting, but I used
> make -p and you're correct, $(dir ...) leaves the trailing slashes.
> 

because different versions of gnu make behave differently.

(you probably have an older version that ignores trailing / on targets)


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2015-12-10  1:39                                                                     ` Petr Hosek
  2015-12-10 12:47                                                                       ` Szabolcs Nagy
@ 2016-01-17 22:32                                                                       ` Rich Felker
  2016-01-17 23:41                                                                         ` Szabolcs Nagy
  1 sibling, 1 reply; 56+ messages in thread
From: Rich Felker @ 2016-01-17 22:32 UTC (permalink / raw)
  To: musl

On Thu, Dec 10, 2015 at 01:39:44AM +0000, Petr Hosek wrote:
> On Tue, Dec 8, 2015 at 4:39 PM Rich Felker <dalias@libc.org> wrote:
> 
> > I get:
> >
> > make: *** No rule to make target `obj/include/bits', needed by
> > `obj/include/bits/alltypes.h'.  Stop.
> >
> > I think this is because $(dir...) intentionally leaves the trailing
> > slash, so you have to remove it to get the desired behavior.
> >
> 
> I'm not sure why I don't see the same behavior in my setting, but I used
> make -p and you're correct, $(dir ...) leaves the trailing slashes.
> 
> 
> > First I tried:
> >
> > OBJ_DIRS = $(sort $(patsubst %/,%,$(dir $(ALL_LIBS) $(ALL_TOOLS) $(OBJS)
> > $(GENH) $(GENH_INT))) $(addprefix obj/, crt crt/$(ARCH) include))
> >
> > but this does not seem to be sufficient, because of:
> >
> > $(OBJS) $(LOBJS): | $(sort $(dir $(OBJS)))
> >
> > Adding patsubst there would work too, but I wonder if it even makes
> > sense to have fine-grained dir dependencies, rather than just making
> > all the targets in this section of the makefile depend on $(OBJ_DIRS).
> > Thoughts?
> >
> 
> I've used the approach you suggested yesterday over IRC which simplifies
> the Makefile a bit.
> 
> 
> > ../configure: Makefile already exists in the working directory
> >
> > This isn't what I would expect either. Normally you want to be able to
> > re-run configure with different options. There's probably a little bit
> > of subtlety here because we would like to avoid overwriting an actual
> > file (if somebody copied and edited a makefile here) but happily
> > replace a symlink.
> >
> 
> I've expanded the check to cover both the existing file and symlink case.
> 
> 
> > Aside from these issues it seems to be okay/working for me. I'd
> > appreciate comments from anyone else who's tried it.
> >
> 
> I've been using the previous version in my setup for about two weeks now
> and haven't found any further issue but I'd like to hear from others if
> they found any issues.

Hi again Petr!

Sorry it's taken so long to get around to actually committing this.
I've had a lot keeping me busy aside from musl, and was waiting both
to get some feedback from other users and to have a good chance to try
it out in real-world usage myself.

The good news is that everything looks fine. I've got my own
foreign-arch builds all converted over to build from my main source
tree, which is going to greatly reduce my frustration of having
in-progress cruft (that was later finished elsewhere) sitting around
in different cloned trees.

As such I've committed/pushed your patch. If anything else turns up
that should be fixed/improved that can be done later but I'm quite
happy with what we've got now. Thanks for all your work on it and your
patience with the process.

Rich


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2016-01-17 22:32                                                                       ` Rich Felker
@ 2016-01-17 23:41                                                                         ` Szabolcs Nagy
  2016-01-20  3:49                                                                           ` Rich Felker
  0 siblings, 1 reply; 56+ messages in thread
From: Szabolcs Nagy @ 2016-01-17 23:41 UTC (permalink / raw)
  To: musl

* Rich Felker <dalias@libc.org> [2016-01-17 17:32:48 -0500]:
> As such I've committed/pushed your patch. If anything else turns up
> that should be fixed/improved that can be done later but I'm quite
> happy with what we've got now. Thanks for all your work on it and your
> patience with the process.
> 

great, thanks

i hit one issue with my messed up source tree: it had
src/foo/bar.s asm files hanging around in non-arch dirs

previously those were not matched by the wildcard rules.
time to clean them up i guess..

(and those who have an existing in-tree build probably
want to run make clean before pulling this commit)


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Support for out-of-tree build
  2016-01-17 23:41                                                                         ` Szabolcs Nagy
@ 2016-01-20  3:49                                                                           ` Rich Felker
  0 siblings, 0 replies; 56+ messages in thread
From: Rich Felker @ 2016-01-20  3:49 UTC (permalink / raw)
  To: musl

On Mon, Jan 18, 2016 at 12:41:17AM +0100, Szabolcs Nagy wrote:
> * Rich Felker <dalias@libc.org> [2016-01-17 17:32:48 -0500]:
> > As such I've committed/pushed your patch. If anything else turns up
> > that should be fixed/improved that can be done later but I'm quite
> > happy with what we've got now. Thanks for all your work on it and your
> > patience with the process.
> > 
> 
> great, thanks
> 
> i hit one issue with my messed up source tree: it had
> src/foo/bar.s asm files hanging around in non-arch dirs
> 
> previously those were not matched by the wildcard rules.
> time to clean them up i guess..
> 
> (and those who have an existing in-tree build probably
> want to run make clean before pulling this commit)

Found one build regression for arm, fixed in commit
b6363bb70aad402be7c548a7ec053b124db076d9.

Another small annoyance we could try to fix: if you have a leftover
src/internal/version.h, the version doesn't get updated when you
rebuild.

I've also made a lot of additional cleanup today. The .sub files and
framework for them are all gone and makefile rules are simplified a
bit in the process. I'm soon going to try to get rid of arch/*/src/*
by putting them in appropriate places in the src/ tree instead, now
that .c files are usable in src/*/$(ARCH), but I may do the atomics
overhaul first since I don't want to bother moving around files I'm
about to remove or rewrite -- in particular, arch/arm/src/atomics.s
and arch/sh/src/atomic.c and related files.

Hopefully I can get through all that tomorrow. I'd like to have the
release out by the end of the month.

Rich


^ permalink raw reply	[flat|nested] 56+ messages in thread

end of thread, other threads:[~2016-01-20  3:49 UTC | newest]

Thread overview: 56+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-06 23:40 Support for out-of-tree build Petr Hosek
2015-11-07 13:05 ` Szabolcs Nagy
2015-11-08  0:43   ` Rich Felker
2015-11-08  2:16     ` Szabolcs Nagy
2015-11-08  2:29       ` Rich Felker
2015-11-11 22:02         ` Petr Hosek
2015-11-11 23:08           ` Rich Felker
2015-11-12  0:01             ` Rich Felker
2015-11-12  0:28             ` Petr Hosek
2015-11-12 14:50               ` Szabolcs Nagy
2015-11-12 20:17                 ` Petr Hosek
2015-11-12 20:30                   ` Rich Felker
2015-11-12 21:10                     ` Szabolcs Nagy
2015-11-12 21:52                       ` Rich Felker
2015-11-12 22:35                         ` Petr Hosek
2015-11-12 23:41                           ` Rich Felker
2015-11-17  2:45                             ` Petr Hosek
2015-11-17  6:05                               ` Petr Hosek
2015-11-17 19:51                                 ` Szabolcs Nagy
2015-11-17 21:00                               ` Rich Felker
2015-11-17 21:37                                 ` Petr Hosek
2015-11-17 22:01                                   ` Rich Felker
2015-11-17 22:15                                     ` Petr Hosek
2015-11-17 22:58                                       ` Rich Felker
2015-11-17 23:06                                     ` Szabolcs Nagy
2015-11-17 23:27                                       ` Rich Felker
2015-11-17 23:43                                         ` Rich Felker
2015-11-17 23:54                                           ` Petr Hosek
2015-11-18  0:19                                             ` Szabolcs Nagy
2015-11-18  0:19                                             ` Rich Felker
2015-11-18 20:19                                               ` Petr Hosek
2015-11-18 21:44                                                 ` Rich Felker
2015-11-19  0:22                                                   ` Petr Hosek
2015-11-20  4:09                                                     ` Rich Felker
2015-11-20  5:02                                                       ` Rich Felker
2015-11-20 10:51                                                       ` Szabolcs Nagy
2015-11-30  1:25                                                       ` Petr Hosek
2015-11-20 22:20                                                     ` Rich Felker
2015-11-30  1:29                                                       ` Petr Hosek
2015-11-30  1:35                                                         ` Rich Felker
2015-11-30  2:49                                                           ` Petr Hosek
2015-11-30 21:14                                                             ` Rich Felker
2015-11-30 22:14                                                               ` Rich Felker
2015-12-01  2:14                                                                 ` Petr Hosek
2015-12-09  0:39                                                                   ` Rich Felker
2015-12-10  1:39                                                                     ` Petr Hosek
2015-12-10 12:47                                                                       ` Szabolcs Nagy
2016-01-17 22:32                                                                       ` Rich Felker
2016-01-17 23:41                                                                         ` Szabolcs Nagy
2016-01-20  3:49                                                                           ` Rich Felker
2015-11-21  1:05                                                     ` Szabolcs Nagy
2015-11-21  1:16                                                       ` Szabolcs Nagy
2015-11-22 14:56                                                     ` Szabolcs Nagy
2015-11-30  1:30                                                       ` Petr Hosek
2015-11-30 12:01                                                         ` Szabolcs Nagy
2015-11-30 22:22                                                           ` Rich Felker

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).