-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMakefile
More file actions
285 lines (250 loc) · 11.2 KB
/
Copy pathMakefile
File metadata and controls
285 lines (250 loc) · 11.2 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
#
# All-in-one Makefile
#
MAKE=make
OUT=out
# Install locations.
EXT_DIR := /Library/Extensions
FS_DIR := /Library/Filesystems
SBIN_DIR := /usr/local/sbin
# Identifiers / runtime files.
BUNDLE_ID := com.beako.filesystems.ext2fs
ARM_FLAG := /var/db/ext2fs.enabled
KSYMS_FILE := /var/db/ext2fs.ksyms
VERSION := $(strip $(shell cat VERSION 2>/dev/null || echo 0.0.0))
# Installer artefacts.
PKG_ID := com.beako.filesystems.ext2fs.pkg
PKG_COMP := $(OUT)/ext2fs-component.pkg
PKG_OUT := $(OUT)/ext2fs-$(VERSION).pkg
DMG_OUT := $(OUT)/ext2fs-$(VERSION).dmg
# Detect native arch if ARCH not specified
NATIVE_ARCH := $(shell uname -m)
ifeq ($(NATIVE_ARCH),arm64)
DEFAULT_ARCH := arm64e
else
DEFAULT_ARCH := x86_64
endif
ARCH ?= $(DEFAULT_ARCH)
# Accept arm64 as alias for arm64e (kexts require arm64e ABI)
ifeq ($(ARCH),arm64)
override ARCH := arm64e
endif
# Per-arch settings
ifeq ($(ARCH),arm64e)
KEXT_ARCHFLAGS := -arch arm64e
KEXT_TRIPLE := arm64e-apple-macos12.0
FS_ARCHFLAGS := -arch arm64
FS_TRIPLE := arm64-apple-macos12.0
LIB_ARCHFLAGS := -arch arm64e
LIB_TRIPLE := arm64e-apple-macos12.0
else ifeq ($(ARCH),x86_64)
KEXT_ARCHFLAGS := -arch x86_64
KEXT_TRIPLE := x86_64-apple-macos10.15
FS_ARCHFLAGS := -arch x86_64
FS_TRIPLE := x86_64-apple-macos10.15
LIB_ARCHFLAGS := -arch x86_64
LIB_TRIPLE := x86_64-apple-macos10.15
else ifeq ($(ARCH),universal)
KEXT_ARCHFLAGS := -arch arm64e
KEXT_TRIPLE := arm64e-apple-macos12.0
FS_ARCHFLAGS := -arch arm64
FS_TRIPLE := arm64-apple-macos12.0
LIB_ARCHFLAGS := -arch arm64e
LIB_TRIPLE := arm64e-apple-macos12.0
else
$(error Unknown ARCH=$(ARCH). Use arm64e, x86_64, or universal)
endif
KEXT_FLAGS := ARCHFLAGS="$(KEXT_ARCHFLAGS)" TARGET_TRIPLE="$(KEXT_TRIPLE)"
FS_FLAGS := ARCHFLAGS="$(FS_ARCHFLAGS)" TARGET_TRIPLE="$(FS_TRIPLE)"
LIB_FLAGS := ARCHFLAGS="$(LIB_ARCHFLAGS)" TARGET_TRIPLE="$(LIB_TRIPLE)"
# The build wipes and repopulates $(OUT) in a fixed order; never parallelise it.
.NOTPARALLEL:
# ---------------------------------------------------------------------------
# Build -> $(OUT)
# ---------------------------------------------------------------------------
# Default: everything needed to install (kext, fs, tools, plists, GUI). Not tests.
all: clean kextfs tools pkg dmg
ifeq ($(ARCH),universal)
# kext + fs as fat (arm64e + x86_64) binaries.
kextfs:
rm -rf $(OUT)
mkdir $(OUT)
$(MAKE) -C lib ARCHFLAGS="-arch arm64e" TARGET_TRIPLE="arm64e-apple-macos12.0"
$(MAKE) debug -C kext ARCHFLAGS="-arch arm64e" TARGET_TRIPLE="arm64e-apple-macos12.0"
$(MAKE) debug -C fs ARCHFLAGS="-arch arm64" TARGET_TRIPLE="arm64-apple-macos12.0"
mv kext/ext2fs.kext kext/ext2fs.kext.dSYM fs/ext2fs.fs fs/ext2fs.fs.dSYM $(OUT)
mv $(OUT)/ext2fs.kext $(OUT)/ext2fs.kext.arm64e
mv $(OUT)/ext2fs.fs $(OUT)/ext2fs.fs.arm64
$(MAKE) -C kext clean
$(MAKE) -C fs clean
$(MAKE) -C lib all clean
$(MAKE) -C lib ARCHFLAGS="-arch x86_64" TARGET_TRIPLE="x86_64-apple-macos10.15"
$(MAKE) debug -C kext ARCHFLAGS="-arch x86_64" TARGET_TRIPLE="x86_64-apple-macos10.15"
$(MAKE) debug -C fs ARCHFLAGS="-arch x86_64" TARGET_TRIPLE="x86_64-apple-macos10.15"
rm -rf $(OUT)/ext2fs.kext.dSYM $(OUT)/ext2fs.fs.dSYM
mv kext/ext2fs.kext kext/ext2fs.kext.dSYM fs/ext2fs.fs fs/ext2fs.fs.dSYM $(OUT)
mv $(OUT)/ext2fs.kext $(OUT)/ext2fs.kext.x86_64
mv $(OUT)/ext2fs.fs $(OUT)/ext2fs.fs.x86_64
cp -r $(OUT)/ext2fs.kext.arm64e $(OUT)/ext2fs.kext
lipo -create $(OUT)/ext2fs.kext.arm64e/Contents/MacOS/ext2fs $(OUT)/ext2fs.kext.x86_64/Contents/MacOS/ext2fs -output $(OUT)/ext2fs.kext/Contents/MacOS/ext2fs
cp -r $(OUT)/ext2fs.fs.arm64 $(OUT)/ext2fs.fs
@# Every program in Contents/Resources has to be fattened, not just the
@# mount helper: newfs, fsck and the probe helper are separate binaries.
@for t in mount_ext2fs newfs_ext2fs fsck_ext2fs ext2fs.util; do \
echo " lipo $$t"; \
lipo -create $(OUT)/ext2fs.fs.arm64/Contents/Resources/$$t \
$(OUT)/ext2fs.fs.x86_64/Contents/Resources/$$t \
-output $(OUT)/ext2fs.fs/Contents/Resources/$$t || exit 1; \
done
codesign --force --timestamp=none --sign - $(OUT)/ext2fs.kext
codesign --force --timestamp=none --sign - $(OUT)/ext2fs.fs
rm -rf $(OUT)/ext2fs.kext.arm64e $(OUT)/ext2fs.kext.x86_64
rm -rf $(OUT)/ext2fs.fs.arm64 $(OUT)/ext2fs.fs.x86_64
else
# kext + fs for a single arch.
kextfs:
rm -rf $(OUT)
mkdir $(OUT)
$(MAKE) -C lib $(LIB_FLAGS)
$(MAKE) debug -C kext $(KEXT_FLAGS)
mv kext/ext2fs.kext kext/ext2fs.kext.dSYM $(OUT)
$(MAKE) debug -C fs $(FS_FLAGS)
mv fs/ext2fs.fs fs/ext2fs.fs.dSYM $(OUT)
endif
# Optional third-party tools (e2fsprogs and friends). The four programs the
# file system itself needs are built by fs/ and staged into the bundle there,
# because Contents/Resources is where diskarbitrationd resolves
# FSProbeExecutable / FSMountExecutable / FSFormatExecutable /
# FSRepairExecutable. Nothing in tools/ is ported yet, so this is a no-op.
tools:
$(MAKE) -C tools
# ---------------------------------------------------------------------------
# Distribution -> installer package and disk image
# ---------------------------------------------------------------------------
# Installer package. The payload is staged into a root that mirrors the
# destination layout, then pkgbuild wraps it and productbuild adds the panes.
#
# The /usr/local/sbin symlinks are not part of the payload: they are made by
# the postinstall script, which keeps one description of where they point
# rather than two that can disagree.
pkg: kextfs tools
@echo "==> Staging installer payload"
rm -rf $(OUT)/pkgroot $(OUT)/pkgres
install -d $(OUT)/pkgroot/Library/Extensions $(OUT)/pkgroot/Library/Filesystems
cp -R $(OUT)/ext2fs.kext $(OUT)/pkgroot/Library/Extensions/
cp -R $(OUT)/ext2fs.fs $(OUT)/pkgroot/Library/Filesystems/
@# codesign and pkgbuild reject Finder-info and similar xattrs.
xattr -cr $(OUT)/pkgroot
@echo "==> Building component package"
pkgbuild --root $(OUT)/pkgroot --identifier $(PKG_ID) --version $(VERSION) \
--scripts installer/scripts --ownership recommended \
--component-plist installer/ext2fs-component.plist \
--install-location / $(PKG_COMP)
@echo "==> Building product archive"
mkdir -p $(OUT)/pkgres
cp installer/resources/welcome.html installer/resources/conclusion.html $(OUT)/pkgres/
sed -e 's/__KEXTVERSION__/$(VERSION)/g' installer/distribution.xml.in > $(OUT)/distribution.xml
productbuild --distribution $(OUT)/distribution.xml --package-path $(OUT) \
--resources $(OUT)/pkgres $(PKG_OUT)
rm -rf $(PKG_COMP) $(OUT)/distribution.xml $(OUT)/pkgroot $(OUT)/pkgres
@echo "==> Built $(PKG_OUT)"
# Disk image wrapping the installer package, a README and the uninstaller.
dmg: pkg
@echo "==> Building disk image"
rm -f $(DMG_OUT)
rm -rf $(OUT)/dmg
mkdir -p $(OUT)/dmg
cp $(PKG_OUT) $(OUT)/dmg/
cp installer/resources/DMG-README.txt $(OUT)/dmg/README.txt
@# The .command is only a front-end; uninstall.sh must travel with it.
cp installer/uninstall.command "$(OUT)/dmg/Uninstall ext2fs.command"
cp installer/uninstall.sh $(OUT)/dmg/uninstall.sh
chmod +x "$(OUT)/dmg/Uninstall ext2fs.command" $(OUT)/dmg/uninstall.sh
hdiutil create -volname "ext2fs $(VERSION)" -srcfolder $(OUT)/dmg \
-ov -format UDZO $(DMG_OUT)
rm -rf $(OUT)/dmg
@echo "==> Built $(DMG_OUT)"
# Test programs (not part of the default build).
tests:
$(MAKE) -C tests
check: tests
@echo "==> ext2fs feature tests"
distcheck: dmg
@echo "==> Verifying distribution artefacts"
@pkgutil --check-signature "$(PKG_OUT)" >/dev/null 2>&1 || true
@pkgutil --payload-files "$(PKG_OUT)" >/dev/null 2>&1 || \
{ echo "FAIL: $(PKG_OUT) has no readable payload"; exit 1; }
@hdiutil imageinfo "$(DMG_OUT)" >/dev/null 2>&1 || \
{ echo "FAIL: $(DMG_OUT) is not a valid disk image"; exit 1; }
@echo " $(PKG_OUT)"
@echo " $(DMG_OUT)"
# Back-compat aliases.
debug: kextfs
release: TARGET=release
release: kextfs
# ---------------------------------------------------------------------------
# Install (run as root, AFTER `make`; copies only, never compiles)
# ---------------------------------------------------------------------------
install: preinstall install-kext install-fs install-tools install-man postinstall
# Tear down any previously installed/loaded build first. macOS caches third-party
# kexts in the Auxiliary Kernel Collection, so a stale staged copy otherwise
# shadows the freshly installed build and the new version is never detected.
preinstall:
@echo "==> Removing any previously installed ext2fs (unmount, unload, clear staging)"
-@mount | awk '/\(ext2fs[ ,]/ { print $$3 }' | while read -r mp; do \
echo " umount $$mp"; umount "$$mp" 2>/dev/null || true; done
-@kmutil unload -b $(BUNDLE_ID) 2>/dev/null || true
-@kmutil clear-staging 2>/dev/null || true
install-kext:
rm -rf $(EXT_DIR)/ext2fs.kext
cp -R $(OUT)/ext2fs.kext $(EXT_DIR)/ext2fs.kext
chown -R root:wheel $(EXT_DIR)/ext2fs.kext
chmod -R 755 $(EXT_DIR)/ext2fs.kext
install-fs:
rm -rf $(FS_DIR)/ext2fs.fs
cp -R $(OUT)/ext2fs.fs $(FS_DIR)/ext2fs.fs
chown -R root:wheel $(FS_DIR)/ext2fs.fs
chmod -R 755 $(FS_DIR)/ext2fs.fs
# The .fs bundle holds the only copy of newfs_ext2fs and fsck_ext2fs; what
# goes in $(SBIN_DIR) is a symlink to it, so the two can never drift apart.
# This is how the system's own file systems are arranged - /sbin/fsck_msdos
# and /sbin/newfs_msdos are symlinks into msdos.fs/Contents/Resources.
#
# mount_ext2fs is deliberately not linked: nothing calls it by hand, only
# diskarbitrationd through the bundle.
install-tools:
@install -d "$(SBIN_DIR)"
@for t in newfs_ext2fs fsck_ext2fs; do \
target="$(FS_DIR)/ext2fs.fs/Contents/Resources/$$t"; \
test -f "$$target" || { echo " missing $$target"; exit 1; }; \
echo " link $(SBIN_DIR)/$$t -> $$target"; \
/bin/ln -sfh "$$target" "$(SBIN_DIR)/$$t"; \
done
# Man pages go where the system's own do - /usr/local/share/man/man8, mirroring
# Apple's fsck_msdos.8 in /usr/share/man/man8 - and not inside the bundle:
# Apple's .fs bundles carry no man pages, and man(1) would not look there.
install-man:
$(MAKE) -C fs install-man
postinstall:
@echo "ext2fs: installed kext, fs."
# Uninstall. installer/uninstall.sh is the single description of what an
# uninstall removes; this target only escalates into it.
uninstall:
@test "$$(id -u)" -eq 0 || { echo "==> make uninstall must be run as root"; exit 1; }
@/bin/bash installer/uninstall.sh
# ---------------------------------------------------------------------------
# Clean (never needs sudo: the build never produces root-owned files)
# ---------------------------------------------------------------------------
# vendor/ is not recursed into: libutil and diskdev_cmds are Apple Xcode
# projects with no GNU makefile, and nothing links them any more. The tree uses
# vendor/libutil only as an include path, for mntopts.h.
clean:
rm -rf $(OUT)
$(MAKE) -C kext clean
$(MAKE) -C fs clean
$(MAKE) -C lib clean
$(MAKE) -C tests clean
$(MAKE) -C tools clean
.PHONY: all kextfs tools tests check distcheck debug release pkg dmg \
install preinstall install-kext install-fs install-tools install-man \
postinstall uninstall clean