summaryrefslogtreecommitdiff
path: root/build-aux
diff options
context:
space:
mode:
authorAlex Deymo <deymo@chromium.org>2014-06-05 19:50:32 -0700
committerPádraig Brady <P@draigBrady.com>2014-07-13 14:23:09 +0100
commit71e2ea773414b2316bbe6b803b9a52c38d3752e8 (patch)
treea535f4cf2c4b8580be95b3c53bf061239aa31e4b /build-aux
parent9c128c0e4943421a73fb0cde4b06a2baa751fdeb (diff)
downloadcoreutils-71e2ea773414b2316bbe6b803b9a52c38d3752e8.tar.gz
build: support building all tools in a single binary
Add the --enable-single-binary option to the configure file. When enabled, this option builds a single binary file containing the selected tools. Which tool gets executed depends on the value of argv[0] which can be set implicitly through symlinks to the single program. This setup reduces significantly the size of a complete coreutils install, since code from lib/libcoreutils.a is not duplicated in every one of the more than 100 binaries. Runtime overhead is increased due to more dynamic libraries being loaded, and extra initialization being performed for all utils. Also initially a larger binary is loaded from storage, though this is usually alleviated due to caching and lazy mmaping of unused blocks, and in fact the single binary should have better caching characteristics. Comparing the size of the individual versus single binary on x86_64: $ cd src $ size coreutils $ size -t $(../build-aux/gen-lists-of-programs.sh --list-progs | grep -Ev '(coreutils|libstdbuf)') | tail -n1 text data bss dec hex filename 1097416 5388 88432 1191236 122d44 src/coreutils 4901010 124964 163768 5189742 4f306e (TOTALS) Storage requirements are reduced similarly: $ cd src $ du -h coreutils $ du -ch $(../build-aux/gen-lists-of-programs.sh --list-progs | grep -Ev '(coreutils|libstdbuf)') | tail -n1 1.2M coreutils 5.3M total When installing, the makefile will create either symlinks or shebangs based on the --enable-single-binary setting, for each configured tool. In this way, all the tools are still callable individually, but they are all implemented by the same "coreutils" binary installed on the same directory. * .gitignore: Add new generated files. * Makefile.am: New rules to generate build-aux/gen-single-binary.sh and install symlinks. * NEWS: Mention the new feature. * README: Add "coreutils" to the list of utils. * bootstrap.conf: Regenerate src/single-binary.mk * build-aux/gen-lists-of-programs.sh: New --list-progs option. * build-aux/gen-single-binary.sh: Regenerate * configure.ac: New --enable-single-binary option and other variables. Disallow --enable-single-binary=symlinks with --program-prefix et. al. * man/coreutils.x: Manpage hook. * man/local.mk: Add manpage hook and fix dependencies. * src/coreutils.c: Multicall implementation. * src/local.mk: New rules for the single binary option. * tests/local.mk: Add $single_binary_progs to support require_built_() from init.cfg * tests/misc/env.sh: Avoid the use of symlink to echo. * tests/misc/help-version.sh: Add exception for coreutils. * tests/install/basic-1.sh: Really avoid using ginstall strip functionality if there is an issue with the independent strip command. * src/kill.c: Changes to call exit() in main. * src/readlink.c: Likewise. * src/shuf.c: Likewise. * src/timeout.c: Likewise. * src/truncate.c: Likewise.
Diffstat (limited to 'build-aux')
-rwxr-xr-xbuild-aux/gen-lists-of-programs.sh7
-rwxr-xr-xbuild-aux/gen-single-binary.sh110
2 files changed, 117 insertions, 0 deletions
diff --git a/build-aux/gen-lists-of-programs.sh b/build-aux/gen-lists-of-programs.sh
index bf63ee30a..c95e59815 100755
--- a/build-aux/gen-lists-of-programs.sh
+++ b/build-aux/gen-lists-of-programs.sh
@@ -17,6 +17,7 @@ set -e
# use "--enable-install-program=A,B" when invoking configure.
disabled_by_default_progs='
arch
+ coreutils
hostname
'
@@ -178,6 +179,12 @@ END
echo default__progs += $progsdir/$p
done
;;
+ 1,--list-progs)
+ for p in $disabled_by_default_progs $build_if_possible_progs \
+ $normal_progs; do
+ echo $p
+ done
+ ;;
*)
echo "$0: invalid usage" >&2; exit 2
;;
diff --git a/build-aux/gen-single-binary.sh b/build-aux/gen-single-binary.sh
new file mode 100755
index 000000000..463570656
--- /dev/null
+++ b/build-aux/gen-single-binary.sh
@@ -0,0 +1,110 @@
+#!/bin/sh
+
+# Generate the list of rules for the single-binary option based on all the other
+# binaries found in src/local.mk.
+#
+# We need to duplicate the specific rules to build each program into a new
+# static library target. We can't reuse the existing target since we need to
+# create a .a file instead of linking the program. We can't do this at
+# ./configure since the file names need to be available when automake runs
+# to let it generate all the required rules in Makefile.in. The configure
+# step will select which ones will be used to build, but they need to be
+# generated beforehand.
+#
+# Instead of maintaining a duplicated list of rules, we generate the
+# single-binary required rules based on the normal configuration found on
+# src/local.mk with this script.
+
+if test "x$1" = "x"; then
+ echo "Usage: $0 path/to/src/local.mk" >&2
+ exit 1
+fi
+
+set -e
+
+LOCAL_MK=$1
+GEN_LISTS_OF_PROGRAMS="`dirname "$0"`/gen-lists-of-programs.sh"
+
+ALL_PROGRAMS=$($GEN_LISTS_OF_PROGRAMS --list-progs \
+ | grep -v -F -e coreutils -e libstdbuf.so \
+ | tr '[' '_')
+
+# Compute default SOURCES. automake will assume the source file for the
+# src_${cmd} target to be src/${cmd}.c, but we will add rules to generate
+# the lib src_libsinglebin_${cmd}_a which won't match the autogenerated source
+# file. This loop will initialize the default source file and will be reset
+# later if needed.
+for cmd in $ALL_PROGRAMS; do
+ eval "src_${cmd}_SOURCES=src/${cmd}.c"
+done
+
+# Load actual values from src/local.mk. This will read all the variables from
+# the local.mk matching the src_${cmd}_... case.
+while read l; do
+ if echo "$l" | grep -E '^src_\w+ +\+?=' > /dev/null; then
+ var=$(echo $l | cut -f 1 -d ' ')
+ value=$(echo $l | cut -f 2- -d =)
+ if [ "$value" != " \$(LDADD)" ]; then
+ oldvalue=""
+ if echo $l | grep -F '+=' >/dev/null; then
+ eval "oldvalue=\${$var}"
+ fi
+ eval "$var='$oldvalue "${value//\'/\'\"\'\"\'}"'"
+ fi
+ fi
+done < $LOCAL_MK
+
+me=`echo "$0" | sed 's,.*/,,'`
+echo "## Automatically generated by $me. DO NOT EDIT BY HAND!"
+
+# Override the sources for dir and vdir. We use a smaller version of dir and
+# vdir that relies on the ls main.
+src_dir_SOURCES="src/coreutils-dir.c"
+src_dir_LDADD+=" src/libsinglebin_ls.a"
+echo src_libsinglebin_dir_a_DEPENDENCIES = src/libsinglebin_ls.a
+src_vdir_SOURCES="src/coreutils-vdir.c"
+src_vdir_LDADD+=" src/libsinglebin_ls.a"
+echo src_libsinglebin_vdir_a_DEPENDENCIES = src/libsinglebin_ls.a
+
+# Override the sources for arch likewise, using the main from uname.
+src_arch_SOURCES="src/coreutils-arch.c"
+src_arch_LDADD+=" src/libsinglebin_uname.a"
+echo src_libsinglebin_arch_a_DEPENDENCIES = src/libsinglebin_uname.a
+
+for cmd in $ALL_PROGRAMS; do
+ echo "# Command $cmd"
+ echo noinst_LIBRARIES += src/libsinglebin_${cmd}.a
+ base="src_libsinglebin_${cmd}_a"
+ # SOURCES
+ var=src_${cmd}_SOURCES
+ eval "value=\$$var"
+ echo "${base}_SOURCES = $value"
+
+ # LDADD
+ var=src_${cmd}_LDADD
+ eval "value=\$$var"
+ if [ "x$value" != "x" ]; then
+ echo "${base}_ldadd = $value"
+ fi
+
+ # CFLAGS
+ # Hack any other program defining a main() replacing its main by
+ # _single_binary_main_$PROGRAM_NAME.
+ echo "${base}_CFLAGS = \"-Dmain=_single_binary_main_${cmd}(int, char**) " \
+ "ATTRIBUTE_NORETURN; int _single_binary_main_${cmd}\" " \
+ "-Dusage=_usage_${cmd} \$(src_coreutils_CFLAGS)"
+ var=src_${cmd}_CFLAGS
+ eval "value=\$$var"
+ if [ "x$value" != "x" ]; then
+ echo "${base}_CFLAGS += $value"
+ fi
+
+ # CPPFLAGS
+ var=src_${cmd}_CPPFLAGS
+ eval "value=\$$var"
+ if [ "x$value" != "x" ]; then
+ echo "${base}_CPPFLAGS = $value"
+ fi
+done
+
+exit 0