# Makefile for uClibc
#
# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
#
# Licensed under the LGPL v2.1, see the file COPYING.libXXX in this tarball.

# Static libraries (lib/XXXXX.a files to build)
#TODO: libintl - when is it built?
liblist := \
    libc \
    libcrypt \
    libm \
    libnsl \
    libresolv \
    librt \
    libutil \

# Shared libraries (lib/XXXXX-N.N.N.so files to build)
liblist_so := \
    ld-uClibc \
    libuClibc \
    libcrypt \
    libdl \
    libm \
    libnsl \
    libresolv \
    librt \
    libutil \

ifeq ($(UCLIBC_HAS_THREADS),y)
liblist += libpthread
liblist_so += libpthread
endif

# Target(s) to always remake
always := uclibc

# Subdirs to descend into
subdir-y := $(liblist)
subdir-$(HAVE_SHARED) += ldso


.PHONY: uclibc
# Always build these
uclibc: \
    $(foreach l,$(liblist),lib/$(l).a) \
    lib/crt1.o lib/crti.o lib/crtn.o
	@true

# Recurse must happen _after_ headers are generated etc
$(subdir-y): \
    scripts/basic/fixdep \
    include/bits/uClibc_config.h \
    arch_stamp .config

# Some of libpthread's object files are linked in libc[_so].s
# FIXME. But for now, ensure ordering
ifeq ($(UCLIBC_HAS_THREADS),y)
libc: libpthread
endif

arch_stamp include/bits/uClibc_config.h: .config
	@echo '  GEN     $@'
	$(Q)$(srctree)/scripts/generate_h.sh

scripts/basic/fixdep: $(srctree)/scripts/basic/fixdep.c
	$(Q)$(MAKE) $(klibc)=scripts/basic

.config:
	@echo '  CP      $@'
	$(Q)cp $(srctree)/extra/Configs/defconfigs/$(ARCH) .config

ifneq ($(PTDIR),)
# "| libpthread" is an "order dependency" - it instructs make
# to build libpthread before this target, but does not force rebuilding
# if only libpthread has changed (which is always true: libpthread
# is a phony target)
lib/libc.a: libc/klib.list | libpthread
	@echo '  AR      $@'
	$(Q)rm -f $@; mkdir -p $(dir $@)
	$(Q)$(AR) cr $@ $(CAT_KLIB_LIST) $(PTDIR)/libc_pthread_init.o
else
lib/libc.a: libc/klib.list
	@echo '  AR      $@'
	$(Q)rm -f $@; mkdir -p $(dir $@)
	$(Q)$(AR) cr $@ $(CAT_KLIB_LIST)
endif

# The rest has the same command line, use template rule
lib/%.a: %/klib.list
	@echo '  AR      $@'
	$(Q)rm -f $@; mkdir -p $(dir $@)
	$(Q)$(AR) cr $@ $(CAT_KLIB_LIST)

# Not exactly correct: they don't require lib/libc.a.
# We just use the fact that building lib/libc.a descends into libc/
# and results in these files being built in libc/sysdeps/linux/$(ARCH).
lib/crt1.o lib/crti.o lib/crtn.o lib/Scrt1.o: lib/libc.a include/bits/uClibc_config.h
	@echo '  CP      $@'
	$(Q)rm -f $@; mkdir -p $(dir $@)
	$(Q)cp libc/sysdeps/linux/$(ARCH)/$(notdir $@) $@



# These rules are added only for shared library build

# HAVE_SHARED is from .config
ifeq ($(HAVE_SHARED),y)

LIBGCC_FILENAME := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
OUTPUT_FORMAT = $(CC) $(CFLAGS) -Wl,--verbose 2>&1 | sed -n 's/^OUTPUT_FORMAT("\([^"]*\)",.*/OUTPUT_FORMAT ( \1 )/p'


# If shared lib is being built, also build these targets
uclibc: \
    lib/Scrt1.o \
    lib/libdl.a \
    $(foreach l,$(liblist_so),lib/$(l)-$(VERSION).so)

# lib/Scrt1.o is built only in HAVE_SHARED=y case, but
# it shares the rule for lib/crtX.o - see above

lib/uclibc_nonshared.a: | libc
	@echo '  AR      $@'
	$(Q)rm -f $@; mkdir -p $(dir $@)
# NB: we need PIC objects here (.os, not .o), we link uclibc_nonshared.a
# into libc-N.N.N.so even if DOPIC!=y.
ifeq ($(UCLIBC_HAS_SSP),y)
	$(Q)$(AR) cr $@ libc/stdlib/atexit.os libc/sysdeps/linux/common/ssp-local.os
else
	$(Q)$(AR) cr $@ libc/stdlib/atexit.os
endif

lib/libdl.a: | ldso
	@echo '  AR      $@'
	$(Q)rm -f $@; mkdir -p $(dir $@)
	$(Q)$(AR) cr $@ ldso/libdl/libdl.$(OEXT) ldso/ldso/$(ARCH)/resolve.$(OEXT)

# Dynamic loader.
# lib/$(UCLIBC_LDSO) (typically ld-uClibc.so.0) will point to it.
lib/ld-uClibc-$(VERSION).so: ldso/ldso/ld-uClibc_so.a
	$(Q)rm -f $@; mkdir -p $(dir $@)
	$(Q)$(CC) \
		-o $@ \
		$(LDFLAGS) \
		-nostdlib \
		-Wl,-soname=$(UCLIBC_LDSO) \
		-Wl,-e,_start -Wl,-z,now -Wl,-Bsymbolic -Wl,--export-dynamic \
		-Wl,--sort-common -Wl,--discard-locals -Wl,--discard-all -Wl,--no-undefined \
		-Wl,--whole-archive ldso/ldso/ld-uClibc_so.a -Wl,--no-whole-archive \
		$(LIBGCC_FILENAME)
	$(Q)ln -sf $(notdir $@) lib/$(UCLIBC_LDSO)
	$(Q)ln -sf $(notdir $@) lib/ld-uClibc.so


# Stub pointing to dynamic loader's name and location
# SHARED_LIB_LOADER_PREFIX is from .config
lib/interp.os:
	@echo '  GEN     $@'
	$(Q)rm -f $@; mkdir -p $(dir $@)
	$(Q)echo '/* Force shared libraries to know about the correct library loader */' >lib/interp.c
	$(Q)echo '#include <features.h>' >>lib/interp.c
	$(Q)echo 'const char __dl_ldso__[] __attribute__ ((section (".interp"))) =' >>lib/interp.c
	$(Q)echo '"$(subst ",,$(SHARED_LIB_LOADER_PREFIX))/$(UCLIBC_LDSO)";' >>lib/interp.c
	$(Q)$(CC) $(CFLAGS) $(CFLAGS_os) -c lib/interp.c -o lib/interp.os
	$(Q)$(STRIP) $(STRIPFLAGS) lib/interp.os


# libc proper
lib/libuClibc-$(VERSION).so: libc/libc_so.a lib/interp.os lib/$(UCLIBC_LDSO) lib/uclibc_nonshared.a
	@echo '  LINK    $@'
	$(Q)rm -f $@; mkdir -p $(dir $@)
	$(Q)$(CC) \
		-o $@ \
		$(LDFLAGS) \
		-nostdlib \
		-Wl,-soname=libc.so.$(MAJOR_VERSION) \
		-Wl,-init,__uClibc_init \
		-Wl,--whole-archive libc/libc_so.a -Wl,--no-whole-archive \
		lib/interp.os lib/$(UCLIBC_LDSO) lib/uclibc_nonshared.a \
		$(LIBGCC_FILENAME)
	$(Q)ln -sf $(notdir $@) lib/libc.so.$(MAJOR_VERSION)
# do not make lib/libc.so symlink, we'll create a linker script instead (see below)

lib/libc.so:
	@echo '  GEN     $@'
	$(Q)rm -f $@; mkdir -p $(dir $@)
	$(Q)cp extra/scripts/format.lds $@
	$(Q)echo '$(shell $(OUTPUT_FORMAT))' >>$@
ifeq ($(COMPAT_ATEXIT),y)
	$(Q)echo "GROUP ( uclibc_nonshared.a libc.so.$(MAJOR_VERSION) AS_NEEDED ( $(UCLIBC_LDSO) ) )" >>$@
else
	$(Q)echo "GROUP ( libc.so.$(MAJOR_VERSION) uclibc_nonshared.a AS_NEEDED ( $(UCLIBC_LDSO) ) )" >>$@
endif


# The rest of dynamic libs

# libdl is a bit special
lib/libdl-$(VERSION).so: ldso/libdl/libdl_so.a lib/interp.os lib/libc.so lib/$(UCLIBC_LDSO) | ldso libc
	@echo '  LINK    $@'
	$(Q)rm -f $@; mkdir -p $(dir $@)
	$(Q)$(CC) \
		-o $@ \
		$(LDFLAGS) \
		-nostdlib \
		-Wl,-soname=$(patsubst lib/%-$(VERSION).so,%.so.$(MAJOR_VERSION),$@) \
		-Wl,-fini,dl_cleanup \
		-Wl,--whole-archive ldso/libdl/libdl_so.a -Wl,--no-whole-archive \
		lib/interp.os -Llib lib/libc.so \
		lib/$(UCLIBC_LDSO) \
		$(LIBGCC_FILENAME) 
	$(Q)ln -sf $(notdir $@) $(patsubst lib/%-$(VERSION).so,lib/%.so.$(MAJOR_VERSION),$@)
	$(Q)ln -sf $(notdir $@) $(patsubst lib/%-$(VERSION).so,lib/%.so,$@)

# libpthread is special too
ifeq ($(UCLIBC_HAS_THREADS),y)
PTHREAD_START_FILES :=
PTHREAD_END_FILES   :=
ifeq ($(UCLIBC_CTOR_DTOR),y)
PTHREAD_START_FILES := lib/crti.o $(dir $(LIBGCC_FILENAME))crtbeginS.o
PTHREAD_END_FILES   := $(dir $(LIBGCC_FILENAME))crtendS.o lib/crtn.o
endif
lib/libpthread-$(VERSION).so: lib/crti.o lib/interp.os lib/libc.so lib/$(UCLIBC_LDSO) lib/crtn.o | libpthread
	@echo '  LINK    $@'
	$(Q)rm -f $@; mkdir -p $(dir $@)
	$(Q)$(CC) \
		-o $@ \
		$(LDFLAGS) \
		-nostdlib \
		-Wl,-soname=$(patsubst lib/%-$(VERSION).so,%.so.$(MAJOR_VERSION),$@) \
		$(PTHREAD_START_FILES) \
		-Wl,--whole-archive $(PTDIR)/libpthread_so.a -Wl,--no-whole-archive \
		lib/interp.os -Llib lib/libc.so \
		lib/$(UCLIBC_LDSO) \
		$(LIBGCC_FILENAME) \
		$(PTHREAD_END_FILES)
	$(Q)ln -sf $(notdir $@) $(patsubst lib/%-$(VERSION).so,lib/%.so.$(MAJOR_VERSION),$@)
	$(Q)ln -sf $(notdir $@) $(patsubst lib/%-$(VERSION).so,lib/%.so,$@)
endif

# The rest has the same command line, use template rule
lib/lib%-$(VERSION).so: $(patsubst lib/%-$(VERSION).so,lib/%.a,$@) lib/interp.os lib/libc.so lib/$(UCLIBC_LDSO)
# adding this makes it rebuild spuriously (why?): | lib%
# we cheat and use lib/%.a dependency instead...
	@echo '  LINK    $@'
	$(Q)rm -f $@; mkdir -p $(dir $@)
ifeq ($(DOPIC),y)
	$(Q)$(CC) \
		-o $@ \
		$(LDFLAGS) \
		-nostdlib \
		-Wl,-soname=$(patsubst lib/%-$(VERSION).so,%.so.$(MAJOR_VERSION),$@) \
		-Wl,--whole-archive $(patsubst lib/lib%-$(VERSION).so,lib/lib%.a,$@) -Wl,--no-whole-archive \
		lib/interp.os -Llib lib/libc.so \
		$(LIBGCC_FILENAME)
else
	$(Q)$(CC) \
		-o $@ \
		$(LDFLAGS) \
		-nostdlib \
		-Wl,-soname=$(patsubst lib/%-$(VERSION).so,%.so.$(MAJOR_VERSION),$@) \
		-Wl,--whole-archive $(patsubst lib/lib%-$(VERSION).so,*/lib%_so.a,$@) -Wl,--no-whole-archive \
		lib/interp.os -Llib lib/libc.so \
		$(LIBGCC_FILENAME)
endif
	$(Q)ln -sf $(notdir $@) $(patsubst lib/%-$(VERSION).so,lib/%.so.$(MAJOR_VERSION),$@)
	$(Q)ln -sf $(notdir $@) $(patsubst lib/%-$(VERSION).so,lib/%.so,$@)

endif
