aboutsummaryrefslogtreecommitdiff
path: root/Makefile
diff options
context:
space:
mode:
authorEuAndreh <eu@euandre.org>2024-01-02 17:28:59 -0300
committerEuAndreh <eu@euandre.org>2024-01-05 05:43:22 -0300
commit2e96fc06f325110af8c7177c0c60694eed5fd245 (patch)
treeba4e2ae8c50136cbf2f00a0edc8f31c90901bb64 /Makefile
parentsrc/internal/version.h: Check-in file with fixed value for compilation (diff)
downloadgrovel-2e96fc06f325110af8c7177c0c60694eed5fd245.tar.gz
grovel-2e96fc06f325110af8c7177c0c60694eed5fd245.tar.xz
Fix the build system.
The improvements are: - use most of the default "Makefile" for standard packaging; - also use the default ".gitignore" with for the derived assets; - don't impose so many $CFLAGS on the user. GCC still needs to be given the `-ffreestanding` flag explicitly for us to get a good binary; - stop using ad-hoc tools/* scripts, and avoid the code-generation anti-pattern overall on the build. Some of the generated files were checked-in, and some were removed; - remove empty files; - use POSIX make(1) over gmake; - add fuzz targets; - partial "install" and "uninstall" targets; - complete "clean" target. The shortcomings are: - only working on x86_64. More platforms coming soon; - code is still messy: way too many warnings, GNU/BSD specific extensions, inline assembly, and all kinds of unportable code; - still only works with GCC and GCC-like compilers, and completly fails with tcc(1) and cproc(1); - the `deps.mk` file is being maintained manually. As I work on the source files I'll finish automating its generation with `mkdeps.sh`; - still seems to be coupled with Linux; - still is missing tests setup; - still uses `#include <$NAME.h>` instead of the correct `#include "$NAME.h"` form. The generated libgrovel.a did match the previous lib/libc.a 100%.
Diffstat (limited to 'Makefile')
-rw-r--r--Makefile396
1 files changed, 162 insertions, 234 deletions
diff --git a/Makefile b/Makefile
index 5bf31622..7a788f02 100644
--- a/Makefile
+++ b/Makefile
@@ -1,284 +1,212 @@
-#
-# Makefile for musl (requires GNU make)
-#
-# This is how simple every makefile should be...
-# No, I take that back - actually most should be less than half this size.
-#
-# Use config.mak to override any of the following variables.
-# Do not make changes here.
-#
+.POSIX:
+DATE = 1970-01-01
+VERSION = 0.1.0
+NAME = grovel
+NAME_UC = $(NAME)
+MAILING_LIST = public-inbox
+LANGUAGES =
+## Installation prefix. Defaults to "/usr".
+PREFIX = /usr
+BINDIR = $(PREFIX)/bin
+LIBDIR = $(PREFIX)/lib
+INCLUDEDIR = $(PREFIX)/include
+SRCDIR = $(PREFIX)/src/$(NAME)
+SHAREDIR = $(PREFIX)/share
+LOCALEDIR = $(SHAREDIR)/locale
+MANDIR = $(SHAREDIR)/man
+EXEC = ./
+## Where to store the installation. Empty by default.
+DESTDIR =
+LDLIBS =
-srcdir = .
-exec_prefix = /usr/local
-bindir = $(exec_prefix)/bin
-prefix = /usr/local/musl
-includedir = $(prefix)/include
-libdir = $(prefix)/lib
-syslibdir = /lib
-MALLOC_DIR = mallocng
-SRC_DIRS = $(addprefix $(srcdir)/,src/* src/malloc/$(MALLOC_DIR) crt ldso $(COMPAT_SRC_DIRS))
-BASE_GLOBS = $(addsuffix /*.c,$(SRC_DIRS))
-ARCH_GLOBS = $(addsuffix /$(ARCH)/*.[csS],$(SRC_DIRS))
-BASE_SRCS = $(sort $(wildcard $(BASE_GLOBS)))
-ARCH_SRCS = $(sort $(wildcard $(ARCH_GLOBS)))
-BASE_OBJS = $(patsubst $(srcdir)/%,%.o,$(basename $(BASE_SRCS)))
-ARCH_OBJS = $(patsubst $(srcdir)/%,%.o,$(basename $(ARCH_SRCS)))
-REPLACED_OBJS = $(sort $(subst /$(ARCH)/,/,$(ARCH_OBJS)))
-ALL_OBJS = $(addprefix obj/, $(filter-out $(REPLACED_OBJS), $(sort $(BASE_OBJS) $(ARCH_OBJS))))
+.SUFFIXES:
+.SUFFIXES: .in .c .o .to .xa .bin .msg .cat
+.SUFFIXES: .s
-LIBC_OBJS = $(filter obj/src/%,$(ALL_OBJS)) $(filter obj/compat/%,$(ALL_OBJS))
-LDSO_OBJS = $(filter obj/ldso/%,$(ALL_OBJS:%.o=%.lo))
-CRT_OBJS = $(filter obj/crt/%,$(ALL_OBJS))
+.in:
+ sed \
+ -e 's:@VERSION@:$(VERSION):g' \
+ -e 's:@DATE@:$(DATE):g' \
+ -e 's:@NAME@:$(NAME):g' \
+ < $< > $@
+ if [ -x $< ]; then chmod +x $@; fi
-AOBJS = $(LIBC_OBJS)
-LOBJS = $(LIBC_OBJS:.o=.lo)
-GENH = obj/include/bits/alltypes.h obj/include/bits/syscall.h
-GENH_INT = obj/src/internal/version.h
-IMPH = $(addprefix $(srcdir)/, src/internal/stdio_impl.h src/internal/pthread_impl.h src/internal/locale_impl.h src/internal/libc.h)
+.s.o:
+ $(CC) $(CFLAGS) -o $@ -c $<
-LDFLAGS =
-LDFLAGS_AUTO =
-LIBCC = -lgcc
-CPPFLAGS =
-CFLAGS =
-CFLAGS_AUTO = -Os -pipe
-CFLAGS_C99FSE = -std=c99 -ffreestanding -nostdinc
+.c.o:
+ $(CC) $(CFLAGS) -o $@ -c $<
-CFLAGS_ALL = $(CFLAGS_C99FSE)
-CFLAGS_ALL += -D_XOPEN_SOURCE=700 -I$(srcdir)/arch/$(ARCH) -I$(srcdir)/arch/generic -Iobj/src/internal -I$(srcdir)/src/include -I$(srcdir)/src/internal -Iobj/include -I$(srcdir)/include
-CFLAGS_ALL += $(CPPFLAGS) $(CFLAGS_AUTO) $(CFLAGS)
+.c.to:
+ $(CC) $(CFLAGS) -DTEST -o $@ -c $<
-LDFLAGS_ALL = $(LDFLAGS_AUTO) $(LDFLAGS)
+.xa.bin:
+ $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS)
-AR = $(CROSS_COMPILE)ar
-RANLIB = $(CROSS_COMPILE)ranlib
-INSTALL = $(srcdir)/tools/install.sh
-ARCH_INCLUDES = $(wildcard $(srcdir)/arch/$(ARCH)/bits/*.h)
-GENERIC_INCLUDES = $(wildcard $(srcdir)/arch/generic/bits/*.h)
-INCLUDES = $(wildcard $(srcdir)/include/*.h $(srcdir)/include/*/*.h)
-ALL_INCLUDES = $(sort $(INCLUDES:$(srcdir)/%=%) $(GENH:obj/%=%) $(ARCH_INCLUDES:$(srcdir)/arch/$(ARCH)/%=include/%) $(GENERIC_INCLUDES:$(srcdir)/arch/generic/%=include/%))
-
-EMPTY_LIB_NAMES = m rt pthread crypt util xnet resolv dl
-EMPTY_LIBS = $(EMPTY_LIB_NAMES:%=lib/lib%.a)
-CRT_LIBS = $(addprefix lib/,$(notdir $(CRT_OBJS)))
-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 = obj/musl-gcc
-
-WRAPCC_GCC = gcc
-WRAPCC_CLANG = clang
-
-LDSO_PATHNAME = $(syslibdir)/ld-musl-$(ARCH)$(SUBARCH).so.1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-# This version of config.mak was generated by:
-# ./configure --enable-debug --disable-shared
-# Any changes made here will be lost if configure is re-run
-AR = $(CROSS_COMPILE)ar
-RANLIB = $(CROSS_COMPILE)ranlib
-ARCH = x86_64
-SUBARCH =
-ASMSUBARCH =
-srcdir = .
-prefix = /usr/local/musl
-exec_prefix = $(prefix)
-bindir = $(exec_prefix)/bin
-libdir = $(prefix)/lib
-includedir = $(prefix)/include
-syslibdir = /lib
-CC = gcc
-CFLAGS =
-CFLAGS_AUTO = -g -O2 -fno-align-jumps -fno-align-functions -fno-align-loops -fno-align-labels -fira-region=one -fira-hoist-pressure -freorder-blocks-algorithm=simple -fno-prefetch-loop-arrays -fno-tree-ch -pipe -fno-unwind-tables -fno-asynchronous-unwind-tables -ffunction-sections -fdata-sections -Wno-pointer-to-int-cast -Werror=implicit-function-declaration -Werror=implicit-int -Werror=pointer-sign -Werror=pointer-arith -Werror=int-conversion -Werror=incompatible-pointer-types -Werror=discarded-qualifiers -Werror=discarded-array-qualifiers -Waddress -Warray-bounds -Wchar-subscripts -Wduplicate-decl-specifier -Winit-self -Wreturn-type -Wsequence-point -Wstrict-aliasing -Wunused-function -Wunused-label -Wunused-variable
-CFLAGS_C99FSE = -std=c99 -nostdinc -ffreestanding -fexcess-precision=standard -frounding-math -fno-strict-aliasing -Wa,--noexecstack
-CFLAGS_MEMOPS = -fno-tree-loop-distribute-patterns
-CFLAGS_NOSSP = -fno-stack-protector
-CPPFLAGS =
-LDFLAGS =
-LDFLAGS_AUTO = -Wl,--sort-section,alignment -Wl,--sort-common -Wl,--gc-sections -Wl,--hash-style=both -Wl,--no-undefined -Wl,--exclude-libs=ALL
-CROSS_COMPILE =
-LIBCC = -lgcc -lgcc_eh
-OPTIMIZE_GLOBS = internal/*.c malloc/*.c string/*.c
-ALL_TOOLS = obj/musl-gcc
-TOOL_LIBS = lib/musl-gcc.specs
-ADD_CFI = yes
-MALLOC_DIR = mallocng
-SHARED_LIBS =
-WRAPCC_GCC = $(CC)
-
-
--include $(srcdir)/arch/$(ARCH)/arch.mak
-
-ifeq ($(ARCH),)
all:
- @echo "Please set ARCH in config.mak before running make."
- @exit 1
-
-else
-
-all: $(ALL_LIBS) $(ALL_TOOLS)
-
-OBJ_DIRS = $(sort $(patsubst %/,%,$(dir $(ALL_LIBS) $(ALL_TOOLS) $(ALL_OBJS) $(GENH) $(GENH_INT))) obj/include)
-
-$(ALL_LIBS) $(ALL_TOOLS) $(ALL_OBJS) $(ALL_OBJS:%.o=%.lo) $(GENH) $(GENH_INT): | $(OBJ_DIRS)
-
-$(OBJ_DIRS):
- mkdir -p $@
-
-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 > $@
-
-obj/include/bits/syscall.h: $(srcdir)/arch/$(ARCH)/bits/syscall.h.in
- cp $< $@
- sed -n -e s/__NR_/SYS_/p < $< >> $@
+include deps.mk
-obj/src/internal/version.h: $(wildcard $(srcdir)/VERSION $(srcdir)/.git)
- printf '#define VERSION "%s"\n' "$$(cd $(srcdir); sh tools/version.sh)" > $@
+manpages = $(manpages.in:.in=)
+catalogs.cat = $(catalogs.msg:.msg=.cat)
-obj/src/internal/version.o obj/src/internal/version.lo: obj/src/internal/version.h
+sources.o = $(sources.c:.c=.o) $(sources.s:.s=.o)
+sources.to = $(sources.c:.c=.to)
+sources.xa = $(sources.c:.c=.xa)
+# sources.bin = $(sources.c:.c=.bin) # FIXME
+fuzz.o = $(fuzz.c:.c=.o)
+fuzz.xa = $(fuzz.c:.c=.xa)
+fuzz.bin = $(fuzz.c:.c=.bin)
-obj/crt/rcrt1.o obj/ldso/dlstart.lo obj/ldso/dynlink.lo: $(srcdir)/src/internal/dynlink.h $(srcdir)/arch/$(ARCH)/reloc.h
+sources = \
+ $(sources.c) \
+ $(sources.c:.c=.h) \
+ src/config.h.in \
+ src/config.h \
+ src/main.c \
+ src/$(NAME).h \
+ $(catalogs.msg) \
-obj/crt/crt1.o obj/crt/scrt1.o obj/crt/rcrt1.o obj/ldso/dlstart.lo: $(srcdir)/arch/$(ARCH)/crt_arch.h
+empty-libs.a = \
+ libm.a \
+ librt.a \
+ libpthread.a \
+ libcrypt.a \
+ libutil.a \
+ libxnet.a \
+ libresolv.a \
+ libdl.a \
-obj/crt/rcrt1.o: $(srcdir)/ldso/dlstart.c
-obj/crt/Scrt1.o obj/crt/rcrt1.o: CFLAGS_ALL += -fPIC
+derived-assets = \
+ lib$(NAME).a \
+ $(empty-libs.a) \
+ libc.a \
+ src/config.h \
+ $(manpages) \
+ $(catalogs.cat) \
+ $(sources.o) \
+ $(sources.to) \
+ $(sources.xa) \
+ $(sources.bin) \
+ src/main.o \
+ src/main.xa \
+ src/main.bin \
-OPTIMIZE_SRCS = $(wildcard $(OPTIMIZE_GLOBS:%=$(srcdir)/src/%))
-$(OPTIMIZE_SRCS:$(srcdir)/%.c=obj/%.o) $(OPTIMIZE_SRCS:$(srcdir)/%.c=obj/%.lo): CFLAGS += -O3
+side-assets = \
+ $(fuzz.o) \
+ $(fuzz.xa) \
+ $(fuzz.bin) \
-MEMOPS_OBJS = $(filter %/memcpy.o %/memmove.o %/memcmp.o %/memset.o, $(LIBC_OBJS))
-$(MEMOPS_OBJS) $(MEMOPS_OBJS:%.o=%.lo): CFLAGS_ALL += $(CFLAGS_MEMOPS)
-NOSSP_OBJS = $(CRT_OBJS) $(LDSO_OBJS) $(filter \
- %/__libc_start_main.o %/__init_tls.o %/__stack_chk_fail.o \
- %/__set_thread_area.o %/memset.o %/memcpy.o \
- , $(LIBC_OBJS))
-$(NOSSP_OBJS) $(NOSSP_OBJS:%.o=%.lo): CFLAGS_ALL += $(CFLAGS_NOSSP)
-$(CRT_OBJS): CFLAGS_ALL += -DCRT
+## Default target. Builds all artifacts required for testing
+## and installation.
+all: $(derived-assets)
-$(LOBJS) $(LDSO_OBJS): CFLAGS_ALL += -fPIC
-CC_CMD = $(CC) $(CFLAGS_ALL) -c -o $@ $<
+lib$(NAME).a: $(libc.c:.c=.o) $(libc.s:.s=.o)
+src/main.xa: $(sources.o) src/main.o
+$(fuzz.bin): lib$(NAME).a
+$(manpages) src/config.h: Makefile deps.mk
+$(sources.o) $(sources.to): Makefile deps.mk src/config.h
-# Choose invocation of assembler to be used
-ifeq ($(ADD_CFI),yes)
- AS_CMD = LC_ALL=C awk -f $(srcdir)/tools/add-cfi.common.awk -f $(srcdir)/tools/add-cfi.$(ARCH).awk $< | $(CC) $(CFLAGS_ALL) -x assembler -c -o $@ -
-else
- AS_CMD = $(CC_CMD)
-endif
-obj/%.o: $(srcdir)/%.s
- $(AS_CMD)
+lib$(NAME).a $(sources.xa) src/main.xa $(fuzz.xa) $(empty-libs.a):
+ $(AR) $(ARFLAGS) $@ $?
-obj/%.o: $(srcdir)/%.S
- $(CC_CMD)
+src/$(NAME).en.cat: src/i18n.bin
+ env DUMP_TRANSLATABLE_STRINGS=1 $(EXEC)src/i18n.bin > $*.msg.new
+ cmp -s $*.msg.new $*.msg || mv $*.msg.new $*.msg
+ rm -f $*.msg.new
+ gencat $@ $*.msg
+ touch $@
-obj/%.o: $(srcdir)/%.c $(GENH) $(IMPH)
- $(CC_CMD)
+libc.a: lib$(NAME).a
+ ln -fs lib$(NAME).a $@
-obj/%.lo: $(srcdir)/%.s
- $(AS_CMD)
-obj/%.lo: $(srcdir)/%.S
- $(CC_CMD)
-obj/%.lo: $(srcdir)/%.c $(GENH) $(IMPH)
- $(CC_CMD)
+src/catalog.bin-check: src/$(NAME).en.cat
-lib/libc.so: $(LOBJS) $(LDSO_OBJS)
- $(CC) $(CFLAGS_ALL) $(LDFLAGS_ALL) -nostdlib -shared \
- -Wl,-e,_dlstart -o $@ $(LOBJS) $(LDSO_OBJS) $(LIBCC)
-lib/libc.a: $(AOBJS)
- rm -f $@
- $(AR) rc $@ $(AOBJS)
- $(RANLIB) $@
+.SUFFIXES: .bin-check
+# sources.bin-check = $(sources.c:.c=.bin-check)
+$(sources.bin-check):
+ $(EXEC)$*.bin
-$(EMPTY_LIBS):
- rm -f $@
- $(AR) rc $@
+check-unit: $(sources.bin-check)
-lib/%.o: obj/crt/$(ARCH)/%.o
- cp $< $@
-lib/%.o: obj/crt/%.o
- cp $< $@
+## Run all tests. Each test suite is isolated, so that a parallel
+## build can run tests at the same time. The required artifacts
+## are created if missing.
+check: check-unit
-lib/musl-gcc.specs: $(srcdir)/tools/musl-gcc.specs.sh
- sh $< "$(includedir)" "$(libdir)" "$(LDSO_PATHNAME)" > $@
-obj/musl-gcc:
- printf '#!/bin/sh\nexec "$${REALGCC:-$(WRAPCC_GCC)}" "$$@" -specs "%s/musl-gcc.specs"\n' "$(libdir)" > $@
- chmod +x $@
-obj/%-clang: $(srcdir)/tools/%-clang.in
- 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 $@
+fuzz.bin-check = $(fuzz.c:.c=.bin-check)
+$(fuzz.bin-check):
+ $(EXEC)$*.bin tests/fuzz/corpus/ $(FUZZFLAGS)
-$(DESTDIR)$(bindir)/%: obj/%
- $(INSTALL) -D $< $@
+## Run fuzzing targets indefinitely.
+fuzz: $(fuzz.bin-check)
-$(DESTDIR)$(libdir)/%.so: lib/%.so
- $(INSTALL) -D -m 755 $< $@
-$(DESTDIR)$(libdir)/%: lib/%
- $(INSTALL) -D -m 644 $< $@
-$(DESTDIR)$(includedir)/bits/%: $(srcdir)/arch/$(ARCH)/bits/%
- $(INSTALL) -D -m 644 $< $@
-
-$(DESTDIR)$(includedir)/bits/%: $(srcdir)/arch/generic/bits/%
- $(INSTALL) -D -m 644 $< $@
-
-$(DESTDIR)$(includedir)/bits/%: obj/include/bits/%
- $(INSTALL) -D -m 644 $< $@
-
-$(DESTDIR)$(includedir)/%: $(srcdir)/include/%
- $(INSTALL) -D -m 644 $< $@
-
-$(DESTDIR)$(LDSO_PATHNAME): $(DESTDIR)$(libdir)/libc.so
- $(INSTALL) -D -l $(libdir)/libc.so $@ || true
-
-install-libs: $(ALL_LIBS:lib/%=$(DESTDIR)$(libdir)/%) $(if $(SHARED_LIBS),$(DESTDIR)$(LDSO_PATHNAME),)
-
-install-headers: $(ALL_INCLUDES:include/%=$(DESTDIR)$(includedir)/%)
-
-install-tools: $(ALL_TOOLS:obj/%=$(DESTDIR)$(bindir)/%)
+## Remove *all* derived artifacts produced during the build.
+## A dedicated test asserts that this is always true.
+clean:
+ rm -rf $(derived-assets) $(side-assets)
-install: install-libs install-headers install-tools
-musl-git-%.tar.gz: .git
- git --git-dir=$(srcdir)/.git archive --format=tar.gz --prefix=$(patsubst %.tar.gz,%,$@)/ -o $@ $(patsubst musl-git-%.tar.gz,%,$@)
+## Installs into $(DESTDIR)$(PREFIX). Its dependency target
+## ensures that all installable artifacts are crafted beforehand.
+install: all
+ mkdir -p \
+ '$(DESTDIR)$(BINDIR)' \
+ '$(DESTDIR)$(LIBDIR)' \
+ '$(DESTDIR)$(INCLUDEDIR)'
+ cp src/main.bin '$(DESTDIR)$(BINDIR)'/$(NAME)
+ # FIXME headers in '$(DESTDIR)$(INCLUDEDIR)'
+ cp -P lib$(NAME).a $(empty-libs.a) libc.a '$(DESTDIR)$(LIBDIR)'
+ for f in $(FIXME_sources); do \
+ dir='$(DESTDIR)$(SRCDIR)'/"`dirname "$${f#src/}"`"; \
+ mkdir -p "$$dir"; \
+ cp -P "$$f" "$$dir"; \
+ done
+ for l in $(LANGUAGES); do \
+ dir='$(DESTDIR)$(LOCALEDIR)'/"$$l"/LC_MESSAGES; \
+ mkdir -p "$$dir"; \
+ cp src/$(NAME)."$$l".cat "$$dir"/$(NAME).cat; \
+ done
+ sh tools/manpages.sh -ip '$(DESTDIR)$(MANDIR)' $(manpages)
-musl-%.tar.gz: .git
- git --git-dir=$(srcdir)/.git archive --format=tar.gz --prefix=$(patsubst %.tar.gz,%,$@)/ -o $@ v$(patsubst musl-%.tar.gz,%,$@)
+## Uninstalls from $(DESTDIR)$(PREFIX). This is a perfect mirror
+## of the "install" target, and removes *all* that was installed.
+## A dedicated test asserts that this is always true.
+uninstall:
+ rm -rf \
+ '$(DESTDIR)$(BINDIR)'/$(NAME) \
+ '$(DESTDIR)$(LIBDIR)'/lib$(NAME).a \
+ '$(DESTDIR)$(INCLUDEDIR)'/$(NAME).h \
+ '$(DESTDIR)$(SRCDIR)'
+ for l in $(empty-libs.a) libc.a; do \
+ rm -f '$(DESTDIR)$(LIBDIR)'/"$$l"; \
+ done
+ for l in $(LANGUAGES); do \
+ rm -f '$(DESTDIR)$(LOCALEDIR)'/"$$l"/LC_MESSAGES/$(NAME).cat; \
+ done
+ sh tools/manpages.sh -up '$(DESTDIR)$(MANDIR)' $(manpages)
-endif
-clean:
- rm -rf obj lib
+MAKEFILE = Makefile
+## Show this help.
+help:
+ cat $(MAKEFILE) | sh tools/makehelp.sh
-distclean: clean
- rm -f config.mak
-.PHONY: all clean install install-libs install-headers install-tools
+ALWAYS: