Repository navigation
Expand file tree
/
Copy pathMakefile
More file actions
287 lines (259 loc) · 11 KB
/
Copy pathMakefile
File metadata and controls
287 lines (259 loc) · 11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
# Droidspaces v7 - Build system
# Copyright (C) 2026 ravindu644 <droidcasts@protonmail.com>
# SPDX-License-Identifier: GPL-3.0-or-later
BINARY_NAME = droidspaces
SRC_DIR = src
OUT_DIR = output
# Default compiler. Do not allow recursive builds to accidentally get empty CC.
CC ?= cc
# DS_VERSION in droidspaces.h is the one place the version lives; `make bump` rewrites it
VERSION := $(shell grep "DS_VERSION" $(SRC_DIR)/include/droidspaces.h | awk '{print $$3}' | tr -d '"')
NPROC := $(shell nproc 2>/dev/null || sysctl -n hw.logicalcpu 2>/dev/null || echo 4)
# V=1 shows full commands, V=0 (default) shows kernel-style short logs
V ?= 0
ifeq ($(V),1)
Q =
msg_cc =
msg_ld =
else
Q = @
msg_cc = @printf " CC %s\n" $<
msg_ld = @printf " LD %s\n" $@
endif
# Every source listed by hand: a stray .c in the tree must not get linked in
SRCS = $(SRC_DIR)/main.c \
$(SRC_DIR)/core/log.c \
$(SRC_DIR)/core/string.c \
$(SRC_DIR)/core/fs.c \
$(SRC_DIR)/core/paths.c \
$(SRC_DIR)/core/proc.c \
$(SRC_DIR)/core/exec.c \
$(SRC_DIR)/core/fdpass.c \
$(SRC_DIR)/core/frame.c \
$(SRC_DIR)/core/json.c \
$(SRC_DIR)/core/platform.c \
$(SRC_DIR)/security/peer_auth.c \
$(SRC_DIR)/security/selinux.c \
$(SRC_DIR)/config/config.c \
$(SRC_DIR)/config/parse.c \
$(SRC_DIR)/config/load.c \
$(SRC_DIR)/config/save.c \
$(SRC_DIR)/security/jail.c \
$(SRC_DIR)/security/caps.c \
$(SRC_DIR)/security/seccomp.c \
$(SRC_DIR)/security/seccomp_shims.c \
$(SRC_DIR)/rootfs/mount.c \
$(SRC_DIR)/rootfs/image.c \
$(SRC_DIR)/rootfs/volatile.c \
$(SRC_DIR)/rootfs/binds.c \
$(SRC_DIR)/dev/dev.c \
$(SRC_DIR)/dev/devpts.c \
$(SRC_DIR)/cgroup/discover.c \
$(SRC_DIR)/cgroup/mount.c \
$(SRC_DIR)/cgroup/v1.c \
$(SRC_DIR)/cgroup/lifecycle.c \
$(SRC_DIR)/cgroup/limits.c \
$(SRC_DIR)/cgroup/stats.c \
$(SRC_DIR)/virt/mem.c \
$(SRC_DIR)/virt/cpu.c \
$(SRC_DIR)/virt/affinity.c \
$(SRC_DIR)/virt/vproc.c \
$(SRC_DIR)/hw/gpu.c \
$(SRC_DIR)/hw/hardware.c \
$(SRC_DIR)/tty/pty.c \
$(SRC_DIR)/tty/proxy.c \
$(SRC_DIR)/tty/console.c \
$(SRC_DIR)/net/nl/core.c \
$(SRC_DIR)/net/nl/probe.c \
$(SRC_DIR)/net/nl/link.c \
$(SRC_DIR)/net/nl/addr.c \
$(SRC_DIR)/net/nl/linkdump.c \
$(SRC_DIR)/net/nl/route_query.c \
$(SRC_DIR)/net/nl/rule.c \
$(SRC_DIR)/net/ipt/core.c \
$(SRC_DIR)/net/ipt/match.c \
$(SRC_DIR)/net/ipt/insert.c \
$(SRC_DIR)/net/ipt/remove.c \
$(SRC_DIR)/net/ipt/rules.c \
$(SRC_DIR)/net/ipt/portfwd.c \
$(SRC_DIR)/net/dhcp/proto.c \
$(SRC_DIR)/net/dhcp/server.c \
$(SRC_DIR)/net/dhcp/ra.c \
$(SRC_DIR)/net/naming.c \
$(SRC_DIR)/net/netns.c \
$(SRC_DIR)/net/dns.c \
$(SRC_DIR)/net/static_ip.c \
$(SRC_DIR)/net/nat/veth.c \
$(SRC_DIR)/net/nat/filter.c \
$(SRC_DIR)/net/route/policy.c \
$(SRC_DIR)/net/route/uplink.c \
$(SRC_DIR)/net/route/monitor.c \
$(SRC_DIR)/net/gateway/wire.c \
$(SRC_DIR)/net/gateway/lifecycle.c \
$(SRC_DIR)/net/macvlan.c \
$(SRC_DIR)/net/guest.c \
$(SRC_DIR)/net/cleanup.c \
$(SRC_DIR)/android/firmware.c \
$(SRC_DIR)/android/spawn.c \
$(SRC_DIR)/android/socket.c \
$(SRC_DIR)/container/inspect.c \
$(SRC_DIR)/container/registry.c \
$(SRC_DIR)/container/recovery.c \
$(SRC_DIR)/container/lock.c \
$(SRC_DIR)/container/command.c \
$(SRC_DIR)/container/cleanup.c \
$(SRC_DIR)/container/start.c \
$(SRC_DIR)/container/stop.c \
$(SRC_DIR)/container/exec.c \
$(SRC_DIR)/container/info.c \
$(SRC_DIR)/container/restart.c \
$(SRC_DIR)/android/helpers.c \
$(SRC_DIR)/status/collect.c \
$(SRC_DIR)/status/show.c \
$(SRC_DIR)/cli/options.c \
$(SRC_DIR)/cli/usage.c \
$(SRC_DIR)/android/android.c \
$(SRC_DIR)/boot/init.c \
$(SRC_DIR)/boot/env.c \
$(SRC_DIR)/monitor/console.c \
$(SRC_DIR)/monitor/monitor.c \
$(SRC_DIR)/cli/docs.c \
$(SRC_DIR)/daemon/protocol.c \
$(SRC_DIR)/daemon/session.c \
$(SRC_DIR)/daemon/server.c \
$(SRC_DIR)/daemon/client.c \
$(SRC_DIR)/cli/check.c \
$(SRC_DIR)/android/x11.c \
$(SRC_DIR)/android/virgl.c \
$(SRC_DIR)/android/pulseaudio.c \
$(SRC_DIR)/android/anland/anland.c \
$(SRC_DIR)/android/anland/display_daemon.c
# Hardened warning set, all warnings are errors
CFLAGS = -Wall -Wextra -Wpedantic -Werror -O2 -flto=auto -std=gnu99 -I$(SRC_DIR)/include -no-pie -pthread
CFLAGS += -Wformat=2 -Wformat-security -Wformat-overflow=2 -Wformat-truncation=2
CFLAGS += -Wnull-dereference -Wcast-qual -Wlogical-op -Wshadow -Wdouble-promotion -Wundef
CFLAGS += -Wduplicated-cond -Wduplicated-branches -Wimplicit-fallthrough=3
CFLAGS += -fstack-protector-strong
# A header edit rebuilds every object that includes it
CFLAGS += -MMD -MP
# LTO raises some warnings only at link time, and they are failures there too
LDFLAGS = -static -no-pie -flto=auto -pthread -Werror
ifeq ($(NO_STRIP),)
LDFLAGS += -s
endif
LIBS = -lutil
ARCH := $(shell $(CC) -dumpmachine 2>/dev/null | cut -d'-' -f1 | \
sed 's/i.86/x86/; s/armv7l/armhf/; s/^arm.*/armhf/; s/unknown/x86_64/' || echo "x86_64")
# Objects and the binary live per arch so the cross builds do not collide
OBJ_DIR = $(OUT_DIR)/.obj/$(ARCH)
OBJS = $(SRCS:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
-include $(OBJS:.o=.d)
# The link target is a real file, so an unchanged arch is a no-op
BINARY = $(OUT_DIR)/$(BINARY_NAME)-$(ARCH)
find-cc = $(shell \
if [ -n "$(MUSL_CROSS)" ] && [ -f "$(MUSL_CROSS)/$(1)-gcc" ]; then \
echo "$(MUSL_CROSS)/$(1)-gcc"; \
elif [ -f "$(HOME)/toolchains/$(1)-cross/bin/$(1)-gcc" ]; then \
echo "$(HOME)/toolchains/$(1)-cross/bin/$(1)-gcc"; \
elif command -v $(1)-gcc >/dev/null 2>&1; then \
echo "$(1)-gcc"; \
fi)
.PHONY: all help clean native x86_64 aarch64 armhf x86 riscv64 all-build all-tarball debug-hardened format bump test
all: help
help:
@echo "Droidspaces v$(VERSION) Build System"
@echo ""
@echo "Build (static, musl):"
@echo " make native - Build for this machine's architecture"
@echo " make x86_64 - Build for 64-bit x86"
@echo " make aarch64 - Build for 64-bit ARM"
@echo " make armhf - Build for 32-bit ARM (hard-float)"
@echo " make x86 - Build for 32-bit x86"
@echo " make riscv64 - Build for 64-bit RISC-V"
@echo ""
@echo "Advanced targets:"
@echo " make all-build - Build for all supported architectures"
@echo " make all-tarball - Build all and create unified distribution"
@echo ""
@echo "Options:"
@echo " V=1 - Show full compiler commands"
@echo " MUSL_CROSS=dir - Directory holding <triplet>-gcc"
@echo " NO_STRIP=1 - Keep symbols"
@echo ""
@echo "Other:"
@echo " make bump NEW=x.y.z - Set the version (droidspaces.h)"
@echo " make clean - Remove build artifacts"
@echo " make debug-hardened - Build with ASan/UBSan/LSan to find bugs"
@echo " make format - Run clang-format on all .c/.h/.cpp files"
@echo " make test - Drive the installed binary through the running daemon (tests/, no sudo)"
# Black-box tests against the installed binary. They need a running daemon and a
# user in the droidspaces group, so install the build first:
# sudo cp output/droidspaces /usr/bin/droidspaces && sudo systemctl restart droidspaces
test:
python3 -m unittest discover -s tests -v
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
$(msg_cc)
$(Q)mkdir -p $(dir $@)
$(Q)$(CC) $(CFLAGS) -c $< -o $@
$(BINARY): $(OBJS)
$(msg_ld)
$(Q)$(CC) $(OBJS) -o $@ $(LDFLAGS) $(LIBS)
@echo "[+] Built: $@"
# output/droidspaces is always the arch asked for last, built or not, for the
# device-test instructions
native:
@if [ -n "$(NATIVE_CC)" ]; then $(MAKE) --no-print-directory -j$(NPROC) $(BINARY) CC="$(NATIVE_CC)" && cp -f $(BINARY) $(OUT_DIR)/$(BINARY_NAME); \
else echo "Error: no musl toolchain for $(ARCH) ($(triplet_$(ARCH))-gcc). Run scripts/install-musl.sh $(ARCH) or set MUSL_CROSS"; exit 1; fi
triplet_x86_64 = x86_64-linux-musl
triplet_aarch64 = aarch64-linux-musl
triplet_x86 = i686-linux-musl
triplet_armhf = arm-linux-musleabihf
triplet_riscv64 = riscv64-linux-musl
# A musl CC is used as is, anything else means the host arch's cross toolchain
NATIVE_CC := $(if $(findstring musl,$(shell $(CC) -dumpmachine 2>/dev/null)),$(CC),$(call find-cc,$(triplet_$(ARCH))))
# The sub-make re-derives ARCH, OBJ_DIR and BINARY from the cross compiler
x86_64 aarch64 x86 armhf riscv64:
@CROSS_CC="$(call find-cc,$(triplet_$@))"; \
if [ -n "$$CROSS_CC" ]; then $(MAKE) --no-print-directory -j$(NPROC) $(OUT_DIR)/$(BINARY_NAME)-$@ CC=$$CROSS_CC && cp -f $(OUT_DIR)/$(BINARY_NAME)-$@ $(OUT_DIR)/$(BINARY_NAME); \
else echo "Error: $(triplet_$@)-gcc not found. Run scripts/install-musl.sh $@ or set MUSL_CROSS"; exit 1; fi
debug-hardened:
@echo "[*] Building hardened debug binary..."
@mkdir -p $(OUT_DIR)
$(Q)$(CC) $(SRCS) -o $(OUT_DIR)/$(BINARY_NAME)-hardened \
-I$(SRC_DIR)/include -I$(SRC_DIR) -g3 -O1 -pthread -lutil \
-fsanitize=address -fsanitize=undefined -fsanitize=leak \
-fstack-protector-strong -D_FORTIFY_SOURCE=2 \
-Wall -Wextra -Wno-unused-parameter
@echo "[+] Hardened binary built: $(OUT_DIR)/$(BINARY_NAME)-hardened"
@echo "[!] Note: Run this on a standard Linux host (not static/musl) for best results."
# Stops at the first arch that fails; an unchanged arch costs nothing
all-build:
@for a in x86_64 aarch64 armhf x86 riscv64; do \
$(MAKE) --no-print-directory $$a || exit 1; \
done
@echo "[+] All architectures built successfully in $(OUT_DIR)/"
all-tarball: all-build
@COMMIT_HASH=$$(git rev-parse --short HEAD 2>/dev/null || date +%Y-%m-%d); \
TARBALL="$(BINARY_NAME)-v$(VERSION)-$$COMMIT_HASH.tar.gz"; \
ROOT_DIR="$(BINARY_NAME)-v$(VERSION)"; \
TEMP_DIR="/tmp/droidspaces-tarball-$$$$"; \
mkdir -p $$TEMP_DIR/$$ROOT_DIR; \
for arch in x86_64 aarch64 armhf x86 riscv64; do \
mkdir -p $$TEMP_DIR/$$ROOT_DIR/$$arch; \
cp $(OUT_DIR)/$(BINARY_NAME)-$$arch $$TEMP_DIR/$$ROOT_DIR/$$arch/$(BINARY_NAME); \
done; \
echo "[*] Creating unified distribution: $$TARBALL..."; \
tar -czf $$TARBALL -C $$TEMP_DIR $$ROOT_DIR; \
rm -rf $$TEMP_DIR; \
echo "[+] Created: $$TARBALL ($$(du -h $$TARBALL | cut -f1))"
bump:
@echo "$(NEW)" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$$' || { echo "Usage: make bump NEW=x.y.z"; exit 1; }
@sed -i 's/define DS_VERSION ".*"/define DS_VERSION "$(NEW)"/' $(SRC_DIR)/include/droidspaces.h
@echo "[+] Version $(VERSION) -> $(NEW). Commit it, then tag v$(NEW) to release."
format:
@command -v clang-format >/dev/null 2>&1 || { echo "Error: clang-format not found"; exit 1; }
@find $(SRC_DIR) -name '*.c' -o -name '*.h' -o -name '*.cpp' | xargs clang-format -i
@echo "[+] Formatted all source files"
clean:
@rm -rf $(OUT_DIR) $(BINARY_NAME)-*.tar.gz
@echo "[+] Cleaned build artifacts"