mirror of
https://github.com/uutils/coreutils
synced 2024-12-13 23:02:38 +00:00
d54ee9689d
In the normal case, one does, e.g., make TEST="cat" test This means that the value of EXES in the Makefile contains all possible targets, which means many prerequisites that aren't required get built. With this change, when the `test` target is in effect (and, in particular, *only* the test target), then the value of EXES is ignored when calculating dependencies. Otherwise, the values of EXES and TESTS are both considered.
377 lines
9.5 KiB
Makefile
377 lines
9.5 KiB
Makefile
# Config options
|
|
ENABLE_LTO ?= n
|
|
ENABLE_STRIP ?= n
|
|
|
|
# Binaries
|
|
RUSTC ?= rustc
|
|
CARGO ?= cargo
|
|
CC ?= gcc
|
|
RM := rm
|
|
|
|
# Install directories
|
|
PREFIX ?= /usr/local
|
|
BINDIR ?= /bin
|
|
LIBDIR ?= /lib
|
|
|
|
# This won't support any directory with spaces in its name, but you can just
|
|
# make a symlink without spaces that points to the directory.
|
|
BASEDIR ?= $(shell pwd)
|
|
SRCDIR := $(BASEDIR)/src
|
|
BUILDDIR := $(BASEDIR)/build
|
|
TESTDIR := $(BASEDIR)/test
|
|
TEMPDIR := $(BASEDIR)/tmp
|
|
|
|
# Flags
|
|
RUSTCFLAGS := -O
|
|
RMFLAGS :=
|
|
|
|
RUSTCLIBFLAGS := $(RUSTCFLAGS) -L $(BUILDDIR)/
|
|
RUSTCTESTFLAGS := $(RUSTCFLAGS)
|
|
|
|
# Handle config setup
|
|
ifeq ($(ENABLE_LTO),y)
|
|
RUSTCBINFLAGS := $(RUSTCLIBFLAGS) -Z lto
|
|
else
|
|
RUSTCBINFLAGS := $(RUSTCLIBFLAGS)
|
|
endif
|
|
|
|
ifneq ($(ENABLE_STRIP),y)
|
|
ENABLE_STRIP :=
|
|
endif
|
|
|
|
# Possible programs
|
|
PROGS := \
|
|
base64 \
|
|
basename \
|
|
cat \
|
|
chmod \
|
|
cksum \
|
|
comm \
|
|
cp \
|
|
cut \
|
|
dirname \
|
|
echo \
|
|
env \
|
|
du \
|
|
expand \
|
|
factor \
|
|
false \
|
|
fmt \
|
|
fold \
|
|
link \
|
|
hashsum \
|
|
mkdir \
|
|
mv \
|
|
nl \
|
|
nproc \
|
|
od \
|
|
paste \
|
|
printenv \
|
|
pwd \
|
|
readlink \
|
|
realpath \
|
|
relpath \
|
|
rm \
|
|
rmdir \
|
|
sleep \
|
|
split \
|
|
seq \
|
|
shuf \
|
|
sort \
|
|
sum \
|
|
sync \
|
|
tac \
|
|
tee \
|
|
test \
|
|
touch \
|
|
tr \
|
|
true \
|
|
truncate \
|
|
tsort \
|
|
unexpand \
|
|
unlink \
|
|
uniq \
|
|
wc \
|
|
yes \
|
|
head \
|
|
tail \
|
|
whoami
|
|
|
|
UNIX_PROGS := \
|
|
chroot \
|
|
groups \
|
|
hostid \
|
|
hostname \
|
|
id \
|
|
kill \
|
|
logname \
|
|
mkfifo \
|
|
nice \
|
|
nohup \
|
|
stdbuf \
|
|
timeout \
|
|
tty \
|
|
uname \
|
|
uptime \
|
|
users
|
|
|
|
ifneq ($(OS),Windows_NT)
|
|
PROGS := $(PROGS) $(UNIX_PROGS)
|
|
endif
|
|
|
|
ALIASES := \
|
|
hashsum:md5sum \
|
|
hashsum:sha1sum \
|
|
hashsum:sha224sum \
|
|
hashsum:sha256sum \
|
|
hashsum:sha384sum \
|
|
hashsum:sha512sum
|
|
|
|
BUILD ?= $(PROGS)
|
|
|
|
# Output names
|
|
EXES := \
|
|
$(sort $(filter $(BUILD),$(filter-out $(DONT_BUILD),$(PROGS))))
|
|
|
|
CRATE_RLIBS :=
|
|
|
|
INSTALL ?= $(EXES)
|
|
|
|
INSTALLEES := \
|
|
$(filter $(INSTALL),$(filter-out $(DONT_INSTALL),$(EXES) uutils))
|
|
|
|
# Shared library extension
|
|
SYSTEM := $(shell uname)
|
|
DYLIB_EXT :=
|
|
ifeq ($(SYSTEM),Linux)
|
|
DYLIB_EXT := so
|
|
endif
|
|
ifeq ($(SYSTEM),Darwin)
|
|
DYLIB_EXT := dylib
|
|
endif
|
|
|
|
# Libaries to install
|
|
LIBS :=
|
|
ifneq (,$(findstring stdbuf, $(INSTALLEES)))
|
|
LIBS += libstdbuf.$(DYLIB_EXT)
|
|
endif
|
|
|
|
# Programs with usable tests
|
|
TEST_PROGS := \
|
|
cat \
|
|
cp \
|
|
mkdir \
|
|
mv \
|
|
nl \
|
|
seq \
|
|
sort \
|
|
test \
|
|
tr \
|
|
truncate \
|
|
unexpand
|
|
|
|
TEST ?= $(TEST_PROGS)
|
|
|
|
TESTS := \
|
|
$(filter $(TEST),$(filter-out $(DONT_TEST),$(filter $(BUILD),$(filter-out $(DONT_BUILD),$(TEST_PROGS)))))
|
|
|
|
# figure out what dependencies we need based on which programs we're building
|
|
define DEP_INCLUDE
|
|
-include $(SRCDIR)/$(1)/deps.mk
|
|
endef
|
|
# we always depend on libc because common/util does
|
|
DEPLIBS := libc
|
|
DEPPLUGS :=
|
|
# now, add in deps in src/utilname/deps.mk
|
|
# if we're testing, only consider the TESTS variable,
|
|
# otherwise consider the EXES variable
|
|
ifeq ($(MAKECMDGOALS),test)
|
|
$(foreach build,$(TESTS),$(eval $(call DEP_INCLUDE,$(build))))
|
|
else
|
|
$(foreach build,$(sort $(TESTS) $(EXES)),$(eval $(call DEP_INCLUDE,$(build))))
|
|
endif
|
|
# uniqify deps
|
|
DEPLIBS := $(sort $(DEPLIBS))
|
|
DEPPLUGS := $(sort $(DEPPLUGS))
|
|
# build --extern commandline for rustc
|
|
DEP_EXTERN := $(foreach lib,$(subst -,_,$(DEPLIBS)),--extern $(lib)=$(BUILDDIR)/lib$(lib).rlib)
|
|
DEP_EXTERN += $(foreach plug,$(subst -,_,$(DEPPLUGS)),--extern $(plug)=$(BUILDDIR)/lib$(plug).$(DYLIB_EXT))
|
|
|
|
# Setup for building crates
|
|
define BUILD_SETUP
|
|
X := $(shell $(RUSTC) --print file-names --crate-type rlib $(SRCDIR)/$(1)/$(1).rs)
|
|
$(1)_RLIB := $$(X)
|
|
CRATE_RLIBS += $$(X)
|
|
endef
|
|
$(foreach crate,$(EXES),$(eval $(call BUILD_SETUP,$(crate))))
|
|
|
|
# Utils stuff
|
|
EXES_PATHS := $(addprefix $(BUILDDIR)/,$(EXES))
|
|
RLIB_PATHS := $(addprefix $(BUILDDIR)/,$(CRATE_RLIBS))
|
|
command = sh -c '$(1)'
|
|
RESERVED_EXTERNS := --extern uufalse=$(BUILDDIR)/libfalse.rlib --extern uutrue=$(BUILDDIR)/libtrue.rlib --extern uutest=$(BUILDDIR)/libtest.rlib
|
|
|
|
# Main exe build rule
|
|
define EXE_BUILD
|
|
$(BUILDDIR)/gen/$(1).rs: $(BUILDDIR)/mkmain
|
|
$(BUILDDIR)/mkmain $(1) $$@
|
|
|
|
$(BUILDDIR)/$(1): $(BUILDDIR)/gen/$(1).rs $(BUILDDIR)/$($(1)_RLIB) | $(BUILDDIR) deps
|
|
$(RUSTC) $(RUSTCBINFLAGS) $(RESERVED_EXTERNS) -o $$@ $$<
|
|
$(if $(ENABLE_STRIP),strip $$@,)
|
|
endef
|
|
|
|
# GRRR rust-crypto makes a crate called "crypto".
|
|
# This should NOT be allowed by crates.io. GRRRR.
|
|
define DEP_BUILD
|
|
DEP_$(1):
|
|
ifeq ($(1),crypto)
|
|
cd $(BASEDIR)/deps && $(CARGO) build --package rust-crypto --release
|
|
else
|
|
cd $(BASEDIR)/deps && $(CARGO) build --package $(1) --release
|
|
endif
|
|
endef
|
|
|
|
define CRATE_BUILD
|
|
-include $(BUILDDIR)/$(1).d
|
|
|
|
$(BUILDDIR)/$($(1)_RLIB): $(SRCDIR)/$(1)/$(1).rs | $(BUILDDIR) deps
|
|
$(RUSTC) $(RUSTCLIBFLAGS) $(DEP_EXTERN) --crate-type rlib --emit link,dep-info $$< --out-dir $(BUILDDIR)
|
|
endef
|
|
|
|
# Aliases build rule
|
|
ALIAS_SOURCE = $(firstword $(subst :, ,$(1)))
|
|
ALIAS_TARGET = $(word 2,$(subst :, ,$(1)))
|
|
define MAKE_ALIAS
|
|
|
|
ifneq ($(ALIAS_TARGET,$(1)),)
|
|
all: $(BUILDDIR)/$(call ALIAS_TARGET,$(1))
|
|
$(BUILDDIR)/$(call ALIAS_TARGET,$(1)): $(BUILDDIR)/$(call ALIAS_SOURCE,$(1))
|
|
$(call command,install $$@ $$<)
|
|
endif
|
|
|
|
endef
|
|
|
|
# Test exe built rules
|
|
define TEST_BUILD
|
|
test_$(1): $(BUILDDIR)/$(1) $(TEMPDIR)/$(1)/$(1)_test
|
|
$(call command,cp $(BUILDDIR)/$(1) $(TEMPDIR)/$(1) && cd $(TEMPDIR)/$(1) && $(TEMPDIR)/$(1)/$(1)_test)
|
|
|
|
$(TEMPDIR)/$(1)/$(1)_test: $(TESTDIR)/$(1).rs | $(TEMPDIR)/$(1)
|
|
$(call command,$(RUSTC) $(RUSTCTESTFLAGS) $(DEP_EXTERN) --test -o $$@ $$<)
|
|
|
|
$(TEMPDIR)/$(1): | $(TEMPDIR)
|
|
$(call command,cp -r $(TESTDIR)/fixtures/$(1) $$@ || mkdir $$@)
|
|
endef
|
|
|
|
# Main rules
|
|
all: $(EXES_PATHS) $(BUILDDIR)/uutils
|
|
|
|
# Creating necessary rules for each targets
|
|
$(foreach crate,$(EXES),$(eval $(call CRATE_BUILD,$(crate))))
|
|
$(foreach exe,$(EXES),$(eval $(call EXE_BUILD,$(exe))))
|
|
$(foreach alias,$(ALIASES),$(eval $(call MAKE_ALIAS,$(alias))))
|
|
$(foreach test,$(TESTS),$(eval $(call TEST_BUILD,$(test))))
|
|
$(foreach dep,$(sort $(DEPLIBS) $(DEPPLUGS)),$(eval $(call DEP_BUILD,$(dep))))
|
|
|
|
-include $(BUILDDIR)/uutils.d
|
|
$(BUILDDIR)/uutils: $(SRCDIR)/uutils/uutils.rs $(BUILDDIR)/mkuutils $(RLIB_PATHS)
|
|
$(BUILDDIR)/mkuutils $(BUILDDIR)/gen/uutils.rs $(EXES)
|
|
$(RUSTC) $(RUSTCBINFLAGS) $(RESERVED_EXTERNS) --emit link,dep-info $(BUILDDIR)/gen/uutils.rs --out-dir $(BUILDDIR)
|
|
$(if $(ENABLE_STRIP),strip $@)
|
|
|
|
# Library for stdbuf
|
|
$(BUILDDIR)/libstdbuf.$(DYLIB_EXT): $(SRCDIR)/stdbuf/libstdbuf.rs $(SRCDIR)/stdbuf/libstdbuf.c $(SRCDIR)/stdbuf/libstdbuf.h | $(BUILDDIR)
|
|
cd $(SRCDIR)/stdbuf && \
|
|
$(RUSTC) libstdbuf.rs && \
|
|
$(CC) -c -Wall -Werror -fpic libstdbuf.c -L. -llibstdbuf.a && \
|
|
$(CC) -shared -o libstdbuf.$(DYLIB_EXT) -Wl,--whole-archive liblibstdbuf.a -Wl,--no-whole-archive libstdbuf.o -lpthread && \
|
|
mv *.$(DYLIB_EXT) $(BUILDDIR) && $(RM) *.o && $(RM) *.a
|
|
|
|
$(BUILDDIR)/stdbuf: $(BUILDDIR)/libstdbuf.$(DYLIB_EXT)
|
|
|
|
deps: $(BUILDDIR) $(SRCDIR)/cksum/crc_table.rs $(addprefix DEP_,$(DEPLIBS) $(DEPPLUGS))
|
|
$(foreach lib,$(subst -,_,$(DEPLIBS)),$(shell cp $(BASEDIR)/deps/target/release/deps/lib$(lib)-*.rlib $(BUILDDIR)/lib$(lib).rlib))
|
|
$(foreach plug,$(subst -,_,$(DEPPLUGS)),$(shell cp $(BASEDIR)/deps/target/release/deps/lib$(plug)-*.$(DYLIB_EXT) $(BUILDDIR)/lib$(plug).$(DYLIB_EXT)))
|
|
|
|
$(BUILDDIR)/mkmain: mkmain.rs | $(BUILDDIR)
|
|
$(RUSTC) $(RUSTCFLAGS) $< -o $@
|
|
|
|
$(BUILDDIR)/mkuutils: mkuutils.rs | $(BUILDDIR)
|
|
$(RUSTC) $(RUSTCFLAGS) $< -o $@
|
|
|
|
$(SRCDIR)/cksum/crc_table.rs: $(SRCDIR)/cksum/gen_table.rs
|
|
cd $(SRCDIR)/cksum && $(RUSTC) $(RUSTCBINFLAGS) gen_table.rs && ./gen_table && $(RM) gen_table
|
|
|
|
crates:
|
|
echo $(EXES)
|
|
|
|
test: $(TEMPDIR) $(addprefix test_,$(TESTS))
|
|
$(RM) -rf $(TEMPDIR)
|
|
|
|
clean:
|
|
$(RM) -rf $(BUILDDIR) $(TEMPDIR)
|
|
|
|
distclean: clean
|
|
cd $(BASEDIR)/deps && $(CARGO) clean
|
|
|
|
$(BUILDDIR):
|
|
mkdir -p $(BUILDDIR)/gen
|
|
|
|
$(TEMPDIR):
|
|
$(RM) -rf $(TEMPDIR)
|
|
mkdir $(TEMPDIR)
|
|
|
|
install: $(addprefix $(BUILDDIR)/,$(INSTALLEES))
|
|
mkdir -p $(DESTDIR)$(PREFIX)$(BINDIR)
|
|
for prog in $(INSTALLEES); do \
|
|
install $(BUILDDIR)/$$prog $(DESTDIR)$(PREFIX)$(BINDIR)/$(PROG_PREFIX)$$prog; \
|
|
done
|
|
mkdir -p $(DESTDIR)$(PREFIX)$(LIBDIR)
|
|
for lib in $(LIBS); do \
|
|
install $(BUILDDIR)/$$lib $(DESTDIR)$(PREFIX)$(LIBDIR)/$$lib; \
|
|
done
|
|
|
|
# TODO: figure out if there is way for prefixes to work with the symlinks
|
|
install-multicall: $(BUILDDIR)/uutils
|
|
mkdir -p $(DESTDIR)$(PREFIX)$(BINDIR)
|
|
install $(BUILDDIR)/uutils $(DESTDIR)$(PREFIX)$(BINDIR)/$(PROG_PREFIX)uutils
|
|
cd $(DESTDIR)$(PREFIX)$(BINDIR)
|
|
for prog in $(INSTALLEES); do \
|
|
ln -s $(PROG_PREFIX)uutils $$prog; \
|
|
done
|
|
mkdir -p $(DESTDIR)$(PREFIX)$(LIBDIR)
|
|
for lib in $(LIBS); do \
|
|
install $(BUILDDIR)/$$lib $(DESTDIR)$(PREFIX)$(LIBDIR)/$$lib; \
|
|
done
|
|
|
|
uninstall:
|
|
rm -f $(addprefix $(DESTDIR)$(PREFIX)$(BINDIR)/$(PROG_PREFIX),$(PROGS))
|
|
rm -f $(addprefix $(DESTDIR)$(PREFIX)$(LIBDIR)/,$(LIBS))
|
|
|
|
uninstall-multicall:
|
|
rm -f $(addprefix $(DESTDIR)$(PREFIX)$(BINDIR)/,$(PROGS) $(PROG_PREFIX)uutils)
|
|
rm -f $(addprefix $(DESTDIR)$(PREFIX)$(LIBDIR)/,$(LIBS))
|
|
|
|
# Test under the busybox testsuite
|
|
$(BUILDDIR)/busybox: $(BUILDDIR)/uutils
|
|
rm -f $(BUILDDIR)/busybox
|
|
ln -s $(BUILDDIR)/uutils $(BUILDDIR)/busybox
|
|
|
|
# This is a busybox-specific config file their test suite wants to parse.
|
|
$(BUILDDIR)/.config: $(BASEDIR)/.busybox-config $(BUILDDIR)/uutils
|
|
cp $< $@
|
|
|
|
ifeq ($(BUSYBOX_SRC),)
|
|
busytest:
|
|
@echo
|
|
@echo "To run \`busytest\` set BUSYBOX_SRC to the directory of the compiled busybox source code."
|
|
@echo "Optionally set RUNTEST_ARGS to arguments to pass to the busybox \`runtest\` program."
|
|
@echo
|
|
@false
|
|
else
|
|
busytest: $(BUILDDIR)/busybox $(BUILDDIR)/.config
|
|
(cd $(BUSYBOX_SRC)/testsuite && bindir=$(BUILDDIR) ./runtest $(RUNTEST_ARGS))
|
|
endif
|
|
|
|
.PHONY: $(TEMPDIR) all deps test distclean clean busytest install uninstall
|