Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20151120040955.GV3818@brightrain.aerifal.cx>
Date: Thu, 19 Nov 2015 23:09:55 -0500
From: Rich Felker <dalias@...c.org>
To: musl@...ts.openwall.com
Subject: Re: Support for out-of-tree build

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

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.