Skip to content

Commit c74c863

Browse files
committed
Major rewrite
* Add support from configuration files with build settings * Add build-time dependency tracking (version change implies a rebuild of dependants) * Add the ability to keep multiple builds side by side for different architectures * Better error handling
1 parent 0c0d2ea commit c74c863

13 files changed

+311
-158
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/build_dir/
22
/dl/
33
/staging_dir/
4-
/toolchain/
54
/state_dir/
65
/bin/
6+
/output/
7+
/.config

Makefile

+71-20
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,84 @@
1-
.PHONY: all clean toolchain packages
1+
# Shell test: must support pipefail
2+
_ := $(shell set -o pipefail)
3+
ifneq "$(.SHELLSTATUS)" "0"
4+
$(error Your shell $(SHELL) does not support pipefail)
5+
endif
26

3-
export
7+
.PHONY: all toolchain packages config \
8+
nuke clean-all clean-build clean-config clean-arch
49

5-
top_dir := $(PWD)
6-
toolchain_dir = $(top_dir)/toolchain
7-
staging_dir := $(top_dir)/staging_dir
8-
build_dir := $(top_dir)/build_dir
9-
state_dir := $(top_dir)/state_dir
10-
dl_dir := $(top_dir)/dl
11-
bin_dir := $(top_dir)/bin
10+
export top_dir := $(PWD)
11+
export config_file := $(top_dir)/.config
1212

13+
goals_needing_config := all toolchain packages clean-config clean-arch
14+
15+
ifeq "$(filter config,$(MAKECMDGOALS))" ""
16+
# Not configuring
17+
# Empty == all
18+
ifeq "$(MAKECMDGOALS)" ""
19+
MAKECMDGOALS := all
20+
endif
21+
ifneq "$(filter $(goals_needing_config),$(MAKECMDGOALS))" ""
22+
include .config
23+
endif
24+
else
25+
# Configuring, we need a configuration name. Use the default
26+
# if none is provided. No other goals can go together with
27+
# config.
28+
export arch := $(or $(ARCH),armv7-eabihf)
29+
export prefix := $(or $(PREFIX),/system/opt/openssh)
30+
ifneq "$(filter-out config,$(MAKECMDGOALS))" ""
31+
$(error The config target must be used on its own)
32+
endif
33+
endif
34+
35+
export dl_root := $(top_dir)/dl
36+
export output_dir := $(top_dir)/output
37+
export config_dir := $(output_dir)/$(arch)
38+
export staging_dir := $(config_dir)/staging_dir
39+
export build_dir := $(config_dir)/build_dir
40+
export toolchain_dir := $(build_dir)/__toolchain__/$(__toolchain__/VERSION)
41+
export state_dir := $(config_dir)/state_dir
42+
export bin_dir := $(config_dir)/bin
43+
export dl_dir := $(dl_root)/$(arch)
44+
export dl_dir_noarch := $(dl_root)/noarch
45+
46+
# Build all packages and then copy the configuration
47+
# used for the build.
1348
all: packages
49+
cp $(config_file) $(bin_dir)/config
1450

1551
packages: toolchain
52+
# Always clean the staging area before a build, so that
53+
# it is not necessary to track what i salready present
54+
# there in case of a config change. Packages will be
55+
# reinstalled at each run, but not rebuilt.
56+
rm -rf '$(staging_dir)'
1657
'$(MAKE)' -f package.mk
1758

1859
toolchain:
1960
'$(MAKE)' -f toolchain.mk
2061

21-
clean:
22-
'$(MAKE)' -f package.mk clean
23-
'$(MAKE)' -f toolchain.mk clean
62+
config: $(config_file)
63+
64+
$(config_file)::
65+
printf 'export %s := %s\n' 'arch' '$(arch)' > '$(config_file)'
66+
printf 'export %s := %s\n' 'prefix' '$(prefix)' >> '$(config_file)'
67+
'$(MAKE)' -f toolchain.mk config
68+
'$(MAKE)' -f package.mk config
69+
70+
nuke: clean-all
71+
rm -f '$(config_file)'
72+
73+
clean-all: clean-build
74+
rm -rf '$(dl_root)'
75+
76+
clean-build:
77+
rm -rf '$(output_dir)'
2478

25-
dirclean:
26-
'$(MAKE)' -f package.mk dirclean
27-
'$(MAKE)' -f toolchain.mk dirclean
79+
clean-config:
80+
rm -rf '$(config_dir)'
2881

29-
# Delete the toolchain ands its downloads,
30-
# but keep downloaded packages
31-
switch-toolchain:
32-
'$(MAKE)' -f package.mk dirclean
33-
'$(MAKE)' -f toolchain.mk clean
82+
clean-arch:
83+
rm -rf '$(dl_dir)'
84+
rm -rf '$(config_dir)'

functions.mk

+4-1
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,7 @@ ifeq "$(__all__/VERSION)" "latest"
2525
determine_version = $(call determine_latest,$1)
2626
else
2727
determine_version = $(if $(subst undefined,,$(origin $1/VERSION)),$(call determine_helper,$1),$(eval $1/VERSION := $2))
28-
endif
28+
endif
29+
30+
# Wrapper for shell that checks the return value and bais of if there was an error
31+
shell_checked = $(shell $1)$(if $(filter-out 0,$(.SHELLSTATUS)),$(error Execution of $1 failed with $(.SHELLSTATUS)))

package-graph.mk

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
override packages := openssh
2+
3+
-include package/*/*.mk
4+
5+
.PHONY: all config
6+
.SHELLFLAGS = -e -c
7+
.ONESHELL:
8+
9+
#############################################
10+
# Dynamically declare dependencies between packages
11+
#############################################
12+
define declaredeps =
13+
$(eval .PHONY: $1)
14+
$(eval $1 : $(foreach dep,$($1/DEPENDS),$(dep)); +'$(MAKE)' -f package.mk package_name='$1')
15+
$(foreach dep,$($1/DEPENDS),$(call declareonce,$(dep)))
16+
endef
17+
18+
define declareonce =
19+
$(if $($1_done),,$(call declaredeps,$1) $(eval $1_done=1))
20+
endef
21+
22+
$(foreach pkg,$(packages),$(call declareonce,$(pkg)))
23+
24+
#############################################
25+
# Targets
26+
#############################################
27+
all: $(packages)
28+
29+
config:
30+
$(foreach \
31+
var,\
32+
$(filter %/VERSION,$(filter-out __all__/%,$(.VARIABLES))),\
33+
[ -z "$($(var))" ] && { echo "$(var) is empty" >&2; exit 1; };\
34+
printf 'export %s := %s\n' '$(var)' '$($(var))' >> '$(config_file)';\
35+
)

package-single.mk

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
include package/$(package_name)/*.mk
2+
3+
.SHELLFLAGS = -e -c
4+
.ONESHELL:
5+
6+
# Don't pass variable definitions like ARCH= down to
7+
# submakes, as they may interfere with the package build system
8+
MAKEOVERRIDES =
9+
10+
host_path := $(PATH)
11+
export PATH := $(toolchain_dir)/bin:$(PATH)
12+
export CPPFLAGS := -I$(staging_dir)/$(prefix)/include
13+
export CFLAGS := $(CPPFLAGS) -fPIC
14+
export LDFLAGS := -L$(staging_dir)/$(prefix)/lib
15+
16+
# Adjust paths
17+
dl_dir := $(dl_dir_noarch)/$(package_name)/$($(package_name)/VERSION)
18+
state_dir := $(state_dir)/$(package_name)/$($(package_name)/VERSION)
19+
build_dir := $(build_dir)/$(package_name)/$($(package_name)/VERSION)
20+
21+
#############################################
22+
# Macros for specific stages
23+
#############################################
24+
define downloadpkg =
25+
mkdir -p '$(dl_dir)'
26+
cd '$(dl_dir)'
27+
if [ -n '$($1/TARBALL)' ]; then
28+
curl -fL '$($1/TARBALL)' -o '$(dl_dir)/$(notdir $($1/TARBALL))'
29+
fi
30+
endef
31+
32+
define preparepkg =
33+
rm -rf '$(build_dir)/$1'
34+
mkdir -p '$(build_dir)/$1'
35+
cd '$(build_dir)/$1'
36+
if [ -n '$($1/TARBALL)' ]; then
37+
tar -xf '$(dl_dir)/$(notdir $($1/TARBALL))'
38+
fi
39+
$(call depfile,$1,prepare)
40+
endef
41+
42+
define buildpkg =
43+
$(call $1/build)
44+
$(call depfile,$1,build)
45+
endef
46+
47+
define installpkg =
48+
$(call $1/install)
49+
endef
50+
51+
define packagepkg =
52+
mkdir -p '$(bin_dir)'
53+
$(call $1/package)
54+
endef
55+
56+
# To detect if a version has been changed in the configuration, and thus we
57+
# need to reextract/rebuild that package and all its dependants, each package
58+
# has a dependency file that holds a digest of the concatenation of the
59+
# versions for all of its direct and transitive dependencies, plus the
60+
# toolchain.
61+
62+
# This macro calls a script that computes the digest and is careful to only
63+
# update the dependency file timestamp when it changes.
64+
dep_digest = '$(SHELL)' ./update_dep_digest.sh \
65+
'$(call dep_traversal,$(package_name))$(__toolchain__/VERSION)' \
66+
'$(call depends,$(package_name),depdigest)'
67+
68+
# DFS traversal of the dependency graph
69+
dep_traversal = $($1/VERSION):$(foreach dep,$($1/DEPENDS),$(call dep_traversal,$(dep)))
70+
71+
define declarestages =
72+
$(eval .PHONY : $1 package install )
73+
$(eval $1 : package )
74+
$(eval package : install ; $(call packagepkg,$1) )
75+
$(eval install : $(call depends,$1,build) ; $(call installpkg,$1) )
76+
$(eval $(call depends,$1,build) : $(call depends,$1,prepare) ; $(call buildpkg,$1) )
77+
$(eval $(call depends,$1,prepare) : $(dl_dir)/$(notdir $($1/TARBALL)); $(call preparepkg,$1) )
78+
$(eval $(dl_dir)/$(notdir $($1/TARBALL)): ; $(call downloadpkg,$1))
79+
80+
$(eval $(call depends,$1,prepare) : $(call depends,$1,depdigest) )
81+
$(eval $(call depends,$1,depdigest) :: ; $(dep_digest) )
82+
endef
83+
84+
$(call declarestages,$(package_name))

package.mk

+8-91
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,15 @@
11
include functions.mk
22

3+
# Adjust the toolchain dir in case the bin subfolder
4+
# sits under an extra subdirectory.
35
ifneq "$(shell [ -d '$(toolchain_dir)/bin' ] && echo 1)" "1"
46
toolchain_dir := $(wildcard $(toolchain_dir)/*)
57
endif
68

7-
host_triplet := $(subst -gcc,,$(firstword $(notdir $(wildcard $(toolchain_dir)/bin/*-gcc))))
9+
export host_triplet := $(subst -gcc,,$(firstword $(notdir $(wildcard $(toolchain_dir)/bin/*-gcc))))
810

9-
dl_dir := $(dl_dir)/package
10-
state_dir := $(state_dir)/package
11-
host_path := $(PATH)
12-
PREFIX ?= /system/opt/openssh
13-
prefix := $(PREFIX)
14-
export PATH := $(toolchain_dir)/bin:$(PATH)
15-
export CPPFLAGS := -I$(staging_dir)/$(prefix)/include -L. -fPIC
16-
export CFLAGS := -I$(staging_dir)/$(prefix)/include -L. -fPIC
17-
export LDFLAGS := -L$(staging_dir)/$(prefix)/lib
18-
19-
.PHONY: all
20-
-include package/*/*.mk
21-
22-
# If no package is specifies, build openssh
23-
PACKAGES ?= openssh
24-
25-
#############################################
26-
# Dynamically declare dependencies between packages
27-
#############################################
28-
define declaredeps =
29-
$(eval .PHONY: $1)
30-
$(eval $1: $(call depends,$1,package))
31-
$(eval $(call depends,$1,package) : $(call depends,$1,install) ; $(call packagepkg,$1) )
32-
$(eval $(call depends,$1,install) : $(call depends,$1,build) ; $(call installpkg,$1) )
33-
$(eval $(call depends,$1,build) : $(call depends,$1,prepare) ; $(call buildpkg,$1) )
34-
$(eval $(call depends,$1,prepare) : $(call depends,$1,download); $(call preparepkg,$1) )
35-
$(eval $(call depends,$1,download): ; $(call downloadpkg,$1))
36-
37-
$(eval $(call depends,$1,build) : $(foreach dep,$($1/DEPENDS),$(call depends,$(dep),install)))
38-
$(foreach dep,$($1/DEPENDS),$(call declareonce,$(dep)))
39-
endef
40-
41-
define declareonce =
42-
$(if $($1_done),,$(call declaredeps,$1) $(eval $1_done=1))
43-
endef
44-
45-
.SHELLFLAGS = -e -c
46-
.ONESHELL:
47-
48-
#############################################
49-
# Macros for specific stages
50-
#############################################
51-
define downloadpkg =
52-
mkdir -p '$(dl_dir)'
53-
cd '$(dl_dir)'
54-
if [ -n '$($1/TARBALL)' ]; then
55-
wget '$($1/TARBALL)' -O- > '$(dl_dir)/$(notdir $($1/TARBALL))'
56-
fi
57-
$(call depfile,$1,download)
58-
endef
59-
60-
define preparepkg =
61-
mkdir -p '$(build_dir)/$1'
62-
cd '$(build_dir)/$1'
63-
if [ -n '$($1/TARBALL)' ]; then
64-
tar -xf '$(dl_dir)/$(notdir $($1/TARBALL))'
65-
fi
66-
$(call depfile,$1,prepare)
67-
endef
68-
69-
define buildpkg =
70-
$(call $1/build)
71-
$(call depfile,$1,build)
72-
endef
73-
74-
define installpkg =
75-
$(call $1/install)
76-
$(call depfile,$1,install)
77-
endef
78-
79-
define packagepkg =
80-
mkdir -p '$(bin_dir)'
81-
$(call $1/package)
82-
$(call depfile,$1,package)
83-
endef
84-
85-
#############################################
86-
# Targets
87-
#############################################
88-
all: $(PACKAGES)
89-
90-
# Import dependencies between packages and package stages
91-
$(foreach pkg,$(PACKAGES),$(call declareonce,$(pkg)))
92-
93-
clean:
94-
rm -rf '$(dl_dir)' '$(state_dir)' '$(staging_dir)' '$(bin_dir)' '$(build_dir)'
95-
96-
dirclean:
97-
rm -rf '$(staging_dir)' '$(bin_dir)' '$(build_dir)'
98-
find '$(state_dir)' -type f -not -name '$(notdir $(call depends,*,download))' -delete
11+
ifneq "$(package_name)" ""
12+
include ./package-single.mk
13+
else
14+
include ./package-graph.mk
15+
endif

package/openssh/openssh.mk

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
openssh/DEFAULT_VERSION := V_9_5_P1
1+
openssh/DEFAULT_VERSION := V_9_8_P1
22
define openssh/determine_latest
3-
$(eval override openssh/VERSION := $(shell
3+
$(eval override openssh/VERSION := $(call shell_checked,
44
. ./version.sh;
55
list_github_tags https://github.com/openssh/openssh-portable |
66
sort_versions | tail -n 1
@@ -11,8 +11,8 @@ $(call determine_version,openssh,$(openssh/DEFAULT_VERSION))
1111
openssh/TARBALL := https://github.com/openssh/openssh-portable/archive/refs/tags/$(openssh/VERSION).tar.gz
1212
openssh/DEPENDS := zlib openssl
1313

14-
openssh/dir := $(build_dir)/openssh/openssh-portable-$(openssh/VERSION)
15-
openssh/bin := $(bin_dir)/openssh-$(openssh/VERSION).tgz
14+
openssh/dir = $(build_dir)/openssh/openssh-portable-$(openssh/VERSION)
15+
openssh/bin = $(bin_dir)/openssh-$(openssh/VERSION).tgz
1616
openssh/binfiles := \
1717
sbin/sshd \
1818
$(addprefix bin/,ssh scp ssh-add ssh-agent ssh-keygen ssh-keyscan sftp) \
@@ -21,7 +21,7 @@ openssh/binfiles := \
2121
openssh/conffiles := etc/sshd_config
2222
openssh/emptydir := var/empty
2323

24-
define openssh/build :=
24+
define openssh/build =
2525
+cd $(openssh/dir)
2626
env PATH='$(host_path)' autoreconf -i
2727
./configure LDFLAGS="-static $(LDFLAGS)" LIBS="-lpthread" \
@@ -30,14 +30,14 @@ define openssh/build :=
3030
'$(MAKE)'
3131
endef
3232

33-
define openssh/install :=
33+
define openssh/install =
3434
+'$(MAKE)' -C '$(openssh/dir)' install-nokeys DESTDIR='$(staging_dir)'
3535
endef
3636

37-
define openssh/package :=
37+
define openssh/package =
3838
cd '$(staging_dir)/$(prefix)'
3939
echo $(openssh/binfiles) | xargs -n1 $(host_triplet)-strip -s
40-
tar -czf $(openssh/bin) --transform 's|^|$(shell echo '$(prefix)' | sed 's|^/*||')/|' \
40+
tar -czf $(openssh/bin) --transform 's|^|$(call shell_checked,echo '$(prefix)' | sed 's|^/*||')/|' \
4141
--owner=root:0 --group=root:0 \
4242
$(openssh/binfiles) $(openssh/conffiles) \
4343
$(openssh/emptydir)

0 commit comments

Comments
 (0)