10
10
# with this name, it will be used.
11
11
#
12
12
# The convention here is tailscale-android-build-amd64-<date>
13
- DOCKER_IMAGE = tailscale-android-build-amd64-191124
13
+ DOCKER_IMAGE := tailscale-android-build-amd64-191124
14
14
export TS_USE_TOOLCHAIN =1
15
15
16
- DEBUG_APK =tailscale-debug.apk
17
- RELEASE_AAB =tailscale-release.aab
18
- RELEASE_TV_AAB =tailscale-tv-release.aab
19
- LIBTAILSCALE =android/libs/libtailscale.aar
20
- # Extract the version code from build.gradle.
16
+ # Auto-select an NDK from ANDROID_HOME (choose highest version available)
17
+ NDK_ROOT ?= $(shell ls -1d $(ANDROID_HOME ) /ndk/* 2>/dev/null | sort -V | tail -n 1)
18
+
19
+ HOST_OS := $(shell uname | tr A-Z a-z)
20
+ ifeq ($(HOST_OS ) ,linux)
21
+ STRIP_TOOL := $(NDK_ROOT ) /toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-objcopy
22
+ else ifeq ($(HOST_OS),darwin)
23
+ STRIP_TOOL := $(NDK_ROOT ) /toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objcopy
24
+ endif
25
+
26
+ $(info Using NDK_ROOT : $(NDK_ROOT ) )
27
+ $(info Using STRIP_TOOL : $(STRIP_TOOL ) )
28
+
29
+ DEBUG_APK := tailscale-debug.apk
30
+ RELEASE_AAB := tailscale-release.aab
31
+ RELEASE_TV_AAB := tailscale-tv-release.aab
32
+
33
+ # Define output filenames.
34
+ LIBTAILSCALE_AAR := android/libs/libtailscale.aar
35
+ UNSTRIPPED_AAR := android/libs/libtailscale_unstripped.aar
36
+ ARM64_SO_PATH := jni/arm64-v8a/libgojni.so
37
+
38
+ # Compute an absolute path for the unstripped AAR.
39
+ ABS_UNSTRIPPED_AAR := $(shell pwd) /$(UNSTRIPPED_AAR )
40
+
41
+ # Android SDK & Tools settings.
21
42
ifeq ($(shell uname) ,Linux)
22
- ANDROID_TOOLS_URL= "https://dl.google.com/android/repository/commandlinetools-linux-9477386_latest.zip"
23
- ANDROID_TOOLS_SUM= "bd1aa17c7ef10066949c88dc6c9c8d536be27f992a1f3b5a584f9bd2ba5646a0 commandlinetools-linux-9477386_latest.zip"
43
+ ANDROID_TOOLS_URL := "https://dl.google.com/android/repository/commandlinetools-linux-9477386_latest.zip"
44
+ ANDROID_TOOLS_SUM := "bd1aa17c7ef10066949c88dc6c9c8d536be27f992a1f3b5a584f9bd2ba5646a0 commandlinetools-linux-9477386_latest.zip"
24
45
else
25
- ANDROID_TOOLS_URL= "https://dl.google.com/android/repository/commandlinetools-mac-9477386_latest.zip"
26
- ANDROID_TOOLS_SUM= "2072ffce4f54cdc0e6d2074d2f381e7e579b7d63e915c220b96a7db95b2900ee commandlinetools-mac-9477386_latest.zip"
46
+ ANDROID_TOOLS_URL := "https://dl.google.com/android/repository/commandlinetools-mac-9477386_latest.zip"
47
+ ANDROID_TOOLS_SUM := "2072ffce4f54cdc0e6d2074d2f381e7e579b7d63e915c220b96a7db95b2900ee commandlinetools-mac-9477386_latest.zip"
27
48
endif
28
- ANDROID_SDK_PACKAGES = 'platforms;android-31' 'extras;android;m2repository' 'ndk;23.1.7779620' 'platform-tools' 'build-tools;33.0.2'
49
+ ANDROID_SDK_PACKAGES := 'platforms;android-31' 'extras;android;m2repository' 'ndk;23.1.7779620' 'platform-tools' 'build-tools;33.0.2'
29
50
30
51
# Attempt to find an ANDROID_SDK_ROOT / ANDROID_HOME based either from
31
52
# preexisting environment or common locations.
32
53
export ANDROID_SDK_ROOT ?= $(shell find $$ANDROID_SDK_ROOT $$ANDROID_HOME $$HOME/Library/Android/sdk $$HOME/Android/Sdk $$HOME/AppData/Local/Android/Sdk /usr/lib/android-sdk -maxdepth 1 -type d 2>/dev/null | head -n 1)
33
-
34
- # If ANDROID_SDK_ROOT is still unset, set it to a default location by platform.
35
54
ifeq ($(ANDROID_SDK_ROOT ) ,)
36
- ifeq ($(shell uname),Linux)
37
- export ANDROID_SDK_ROOT= $(HOME)/Android/Sdk
38
- else ifeq ($(shell uname),Darwin)
39
- export ANDROID_SDK_ROOT= $(HOME)/Library/Android/sdk
40
- else ifneq ($(WINDIR),) )
41
- export ANDROID_SDK_ROOT= $(HOME)/AppData/Local/Android/sdk
42
- else
43
- export ANDROID_SDK_ROOT= $(PWD)/android-sdk
44
- endif
55
+ ifeq ($(shell uname),Linux)
56
+ export ANDROID_SDK_ROOT := $(HOME ) /Android/Sdk
57
+ else ifeq ($(shell uname),Darwin)
58
+ export ANDROID_SDK_ROOT := $(HOME ) /Library/Android/sdk
59
+ else ifneq ($(WINDIR),)
60
+ export ANDROID_SDK_ROOT := $(HOME ) /AppData/Local/Android/sdk
61
+ else
62
+ export ANDROID_SDK_ROOT := $(PWD ) /android-sdk
63
+ endif
45
64
endif
46
65
export ANDROID_HOME ?= $(ANDROID_SDK_ROOT )
47
66
@@ -51,67 +70,71 @@ ANDROID_STUDIO_ROOT ?= $(shell find ~/android-studio /usr/local/android-studio /
51
70
52
71
# Set JAVA_HOME to the Android Studio bundled JDK.
53
72
export JAVA_HOME ?= $(shell find "$(ANDROID_STUDIO_ROOT ) /jbr" "$(ANDROID_STUDIO_ROOT ) /jre" "$(ANDROID_STUDIO_ROOT ) /Contents/jbr/Contents/Home" "$(ANDROID_STUDIO_ROOT ) /Contents/jre/Contents/Home" -maxdepth 1 -type d 2>/dev/null | head -n 1)
54
- # If JAVA_HOME is still unset, remove it, because SDK tools go into a CPU spin if it is set and empty.
55
73
ifeq ($(JAVA_HOME ) ,)
56
- unexport JAVA_HOME
74
+ unexport JAVA_HOME
57
75
else
58
- export PATH := $(JAVA_HOME)/bin:$(PATH)
76
+ export PATH := $(JAVA_HOME ) /bin:$(PATH )
59
77
endif
60
78
61
79
AVD_BASE_IMAGE := "system-images;android-33;google_apis;"
62
- export HOST_ARCH = $(shell uname -m)
80
+ export HOST_ARCH := $(shell uname -m)
63
81
ifeq ($(HOST_ARCH ) ,aarch64)
64
- AVD_IMAGE := "$(AVD_BASE_IMAGE)arm64-v8a"
82
+ AVD_IMAGE := "$(AVD_BASE_IMAGE ) arm64-v8a"
65
83
else ifeq ($(HOST_ARCH),arm64)
66
- AVD_IMAGE := "$(AVD_BASE_IMAGE)arm64-v8a"
84
+ AVD_IMAGE := "$(AVD_BASE_IMAGE ) arm64-v8a"
67
85
else
68
- AVD_IMAGE := "$(AVD_BASE_IMAGE)x86_64"
86
+ AVD_IMAGE := "$(AVD_BASE_IMAGE ) x86_64"
69
87
endif
70
88
AVD ?= tailscale-$(HOST_ARCH )
71
89
export AVD_IMAGE
72
90
export AVD
73
91
74
92
# Use our toolchain or the one that is specified, do not perform dynamic toolchain switching.
75
- GOTOOLCHAIN = local
93
+ GOTOOLCHAIN := local
76
94
export GOTOOLCHAIN
77
95
78
- # TOOLCHAINDIR is set by fdoid CI and used by tool/* scripts.
79
96
TOOLCHAINDIR ?=
80
97
export TOOLCHAINDIR
81
98
82
- GOBIN ? = $(PWD ) /android/build/go/bin
99
+ GOBIN : = $(PWD ) /android/build/go/bin
83
100
export GOBIN
84
101
85
102
export PATH := $(PWD ) /tool:$(GOBIN ) :$(ANDROID_HOME ) /cmdline-tools/latest/bin:$(ANDROID_HOME ) /platform-tools:$(PATH )
86
103
export GOROOT := # Unset
87
104
88
- #
89
- # Android Builds:
90
- #
105
+ # ------------------------------------------------------------------------------
106
+ # Android Build Targets
107
+ # ------------------------------------------------------------------------------
108
+
109
+
110
+ .PHONY : debug-unstripped
111
+ debug-unstripped : build-unstripped-aar
112
+ @echo " Listing contents of $( ABS_UNSTRIPPED_AAR) :"
113
+ unzip -l $(ABS_UNSTRIPPED_AAR )
91
114
92
115
.PHONY : apk
93
- apk : $(DEBUG_APK ) # # Build the debug APK
116
+ apk : $(DEBUG_APK )
94
117
95
118
.PHONY : tailscale-debug
96
- tailscale-debug : $(DEBUG_APK ) # # Build the debug APK
119
+ tailscale-debug : $(DEBUG_APK )
120
+
121
+ $(DEBUG_APK ) : libtailscale debug-symbols version gradle-dependencies build-unstripped-aar
122
+ (cd android && ./gradlew test assembleDebug)
123
+ install -C android/build/outputs/apk/debug/android-debug.apk $@
97
124
98
125
# Builds the release AAB and signs it (phone/tablet/chromeOS variant)
99
126
.PHONY : release
100
- release : jarsign-env $(RELEASE_AAB ) # # Build the release AAB
127
+ release : jarsign-env $(RELEASE_AAB )
101
128
@jarsigner -sigalg SHA256withRSA -digestalg SHA-256 -keystore $(JKS_PATH ) -storepass $(JKS_PASSWORD ) $(RELEASE_AAB ) tailscale
102
129
103
130
# Builds the release AAB and signs it (androidTV variant)
104
131
.PHONY : release-tv
105
- release-tv : jarsign-env $(RELEASE_TV_AAB ) # # Build the release AAB
132
+ release-tv : jarsign-env $(RELEASE_TV_AAB )
106
133
@jarsigner -sigalg SHA256withRSA -digestalg SHA-256 -keystore $(JKS_PATH ) -storepass $(JKS_PASSWORD ) $(RELEASE_TV_AAB ) tailscale
107
134
108
135
# gradle-dependencies groups together the android sources and libtailscale needed to assemble tests/debug/release builds.
109
136
.PHONY : gradle-dependencies
110
- gradle-dependencies : $(shell find android -type f -not -path "android/build/* " -not -path '* /.* ') $(LIBTAILSCALE ) tailscale.version
111
-
112
- $(DEBUG_APK ) : version gradle-dependencies
113
- (cd android && ./gradlew test assembleDebug)
114
- install -C android/build/outputs/apk/debug/android-debug.apk $@
137
+ gradle-dependencies : $(shell find android -type f -not -path "android/build/* " -not -path '* /.* ') $(LIBTAILSCALE_AAR ) tailscale.version
115
138
116
139
$(RELEASE_AAB ) : version gradle-dependencies
117
140
@echo " Building release AAB"
@@ -128,50 +151,93 @@ tailscale-test.apk: version gradle-dependencies
128
151
install -C ./android/build/outputs/apk/androidTest/applicationTest/android-applicationTest-androidTest.apk $@
129
152
130
153
tailscale.version : go.mod go.sum $(wildcard .git/HEAD)
131
- $(shell ./tool/go run tailscale.com/cmd/mkversion > tailscale.version)
154
+ @bash -c " ./tool/go run tailscale.com/cmd/mkversion > tailscale.version"
132
155
133
156
.PHONY : version
134
- version : tailscale.version # # print the current version information
135
- cat tailscale.version
157
+ version : tailscale.version
158
+ @ cat tailscale.version
136
159
137
- #
138
- # Go Builds:
139
- #
160
+ # ------------------------------------------------------------------------------
161
+ # Go Build Targets (Unstripped AAR, Debug Symbols, Stripped SO, Packaging)
162
+ # ------------------------------------------------------------------------------
140
163
141
164
android/libs :
142
165
mkdir -p android/libs
143
166
144
- $(GOBIN ) /gomobile : $(GOBIN ) /gobind go.mod go.sum
167
+ $(GOBIN ) :
168
+ mkdir -p $(GOBIN )
169
+
170
+ $(GOBIN ) /gomobile : $(GOBIN ) /gobind go.mod go.sum | $(GOBIN )
145
171
./tool/go install golang.org/x/mobile/cmd/gomobile
146
172
147
173
$(GOBIN ) /gobind : go.mod go.sum
148
174
./tool/go install golang.org/x/mobile/cmd/gobind
149
175
150
- $(LIBTAILSCALE ) : Makefile android/libs $(shell find libtailscale -name * .go) go.mod go.sum $(GOBIN ) /gomobile tailscale.version
176
+ .PHONY : build-unstripped-aar
177
+ build-unstripped-aar : tailscale.version $(GOBIN ) /gomobile
178
+ @echo " Running gomobile bind to generate unstripped AAR..."
179
+ @echo " Output file: $( ABS_UNSTRIPPED_AAR) "
180
+ mkdir -p $(dir $(ABS_UNSTRIPPED_AAR ) )
181
+ rm -f $(ABS_UNSTRIPPED_AAR )
151
182
$(GOBIN ) /gomobile bind -target android -androidapi 26 \
152
183
-tags " $$ (./build-tags.sh)" \
153
- -ldflags " -w $$ (./version-ldflags.sh)" \
154
- -o $@ ./libtailscale
184
+ -ldflags " $$ (./version-ldflags.sh)" \
185
+ -o $(ABS_UNSTRIPPED_AAR ) ./libtailscale || { echo " gomobile bind failed" ; exit 1; }
186
+ @if [ ! -f $( ABS_UNSTRIPPED_AAR) ]; then \
187
+ echo " Error: $( ABS_UNSTRIPPED_AAR) was not created" ; exit 1; \
188
+ fi
189
+ @echo " Generated unstripped AAR: $( ABS_UNSTRIPPED_AAR) "
190
+
191
+ $(UNSTRIPPED_AAR ) : build-unstripped-aar
192
+
193
+ libgojni.so.unstripped : $(UNSTRIPPED_AAR )
194
+ @echo " Extracting libgojni.so from unstripped AAR..."
195
+ @if unzip -p $(ABS_UNSTRIPPED_AAR ) jni/arm64-v8a/libgojni.so > libgojni.so.unstripped; then \
196
+ echo " Found arm64-v8a libgojni.so" ; \
197
+ elif unzip -p $(ABS_UNSTRIPPED_AAR ) jni/armeabi-v7a/libgojni.so > libgojni.so.unstripped; then \
198
+ echo " Found armeabi-v7a libgojni.so" ; \
199
+ else \
200
+ echo " Neither jni/arm64-v8a/libgojni.so nor jni/armeabi-v7a/libgojni.so was found." ; \
201
+ echo " Listing contents of $( ABS_UNSTRIPPED_AAR) :" ; \
202
+ unzip -l $(ABS_UNSTRIPPED_AAR ) ; exit 1; \
203
+ fi
204
+
205
+ libgojni.so.debug : libgojni.so.unstripped
206
+ @echo " Extracting debug symbols from libgojni.so..."
207
+ $(STRIP_TOOL ) --only-keep-debug libgojni.so.unstripped libgojni.so.debug
208
+
209
+ libgojni.so.stripped : libgojni.so.unstripped
210
+ @echo " Stripping debug symbols from libgojni.so..."
211
+ $(STRIP_TOOL ) --strip-debug libgojni.so.unstripped libgojni.so.stripped
212
+
213
+ $(LIBTAILSCALE_AAR ) : libgojni.so.stripped $(UNSTRIPPED_AAR )
214
+ @echo " Repackaging AAR with stripped libgojni.so..."
215
+ rm -rf temp_aar
216
+ mkdir temp_aar
217
+ unzip $(ABS_UNSTRIPPED_AAR ) -d temp_aar
218
+ cp libgojni.so.stripped temp_aar/$(ARM64_SO_PATH )
219
+ (cd temp_aar && zip -r ../$( LIBTAILSCALE_AAR) .)
220
+ rm -rf temp_aar
155
221
156
222
.PHONY : libtailscale
157
- libtailscale : $(LIBTAILSCALE ) # # Build the libtailscale AAR
223
+ libtailscale : $(LIBTAILSCALE_AAR ) # # Build the stripped libtailscale AAR
158
224
159
- #
160
- # Utility tasks:
161
- #
225
+ .PHONY : debug-symbols
226
+ debug-symbols : libgojni.so.debug
162
227
163
- .PHONY : all
164
- all : test $(DEBUG_APK ) # # Build and test everything
228
+ # ------------------------------------------------------------------------------
229
+ # Utility Targets
230
+ # ------------------------------------------------------------------------------
165
231
166
232
.PHONY : env
167
233
env :
168
- @echo PATH=$(PATH )
169
- @echo ANDROID_SDK_ROOT=$(ANDROID_SDK_ROOT )
170
- @echo ANDROID_HOME=$(ANDROID_HOME )
171
- @echo ANDROID_STUDIO_ROOT=$(ANDROID_STUDIO_ROOT )
172
- @echo JAVA_HOME=$(JAVA_HOME )
173
- @echo TOOLCHAINDIR=$(TOOLCHAINDIR )
174
- @echo AVD_IMAGE=" $( AVD_IMAGE) "
234
+ @echo " PATH=$( PATH) "
235
+ @echo " ANDROID_SDK_ROOT=$( ANDROID_SDK_ROOT) "
236
+ @echo " ANDROID_HOME=$( ANDROID_HOME) "
237
+ @echo " ANDROID_STUDIO_ROOT=$( ANDROID_STUDIO_ROOT) "
238
+ @echo " JAVA_HOME=$( JAVA_HOME) "
239
+ @echo " TOOLCHAINDIR=$( TOOLCHAINDIR) "
240
+ @echo " AVD_IMAGE=$( AVD_IMAGE) "
175
241
176
242
# Ensure that JKS_PATH and JKS_PASSWORD are set before we attempt a build
177
243
# that requires signing.
@@ -195,21 +261,20 @@ androidpath:
195
261
@echo ' export PATH=$(ANDROID_HOME)/cmdline-tools/latest/bin:$(ANDROID_HOME)/platform-tools:$$PATH'
196
262
197
263
.PHONY : tag_release
198
- tag_release : tailscale.version # # Tag the current commit with the current version
264
+ tag_release : debug-symbols tailscale.version # # Tag the current commit with the current version
199
265
source tailscale.version && git tag -a " $$ {VERSION_LONG}" -m " OSS and Version updated to $$ {VERSION_LONG}"
200
266
201
-
202
267
.PHONY : bumposs # # Bump to the latest oss and update the versions.
203
268
bumposs : update-oss tailscale.version
204
269
source tailscale.version && git commit -sm " android: bump OSS" -m " OSS and Version updated to $$ {VERSION_LONG}" go.toolchain.rev android/build.gradle go.mod go.sum
205
270
source tailscale.version && git tag -a " $$ {VERSION_LONG}" -m " OSS and Version updated to $$ {VERSION_LONG}"
206
271
207
- .PHONY : bump_version_code
208
- bump_version_code : # # Bump the version code in build.gradle
272
+ .PHONY : bump_version_code # # Bump the version code in build.gradle
273
+ bump_version_code :
209
274
sed -i' .bak' " s/versionCode .*/versionCode $$ (expr $$ (awk '/versionCode ([0-9]+)/{print $$ 2}' android/build.gradle) + 1)/" android/build.gradle && rm android/build.gradle.bak
210
275
211
- .PHONY : update-oss
212
- update-oss : # # Update the tailscale.com go module
276
+ .PHONY : update-oss # # Update the tailscale.com go module
277
+ update-oss :
213
278
GOPROXY=direct ./tool/go get tailscale.com@main
214
279
./tool/go mod tidy -compat=1.24
215
280
./tool/go run tailscale.com/cmd/printdep --go > go.toolchain.rev.new
@@ -247,7 +312,7 @@ checkandroidsdk: ## Check that Android SDK is installed
247
312
test : gradle-dependencies # # Run the Android tests
248
313
(cd android && ./gradlew test)
249
314
250
- .PHONY : emulator
315
+ .PHONY : emulator
251
316
emulator : # # Start an android emulator instance
252
317
@echo " Checking installed SDK packages..."
253
318
@if ! $(ANDROID_HOME ) /cmdline-tools/latest/bin/sdkmanager --list_installed | grep -q " $( AVD_IMAGE) " ; then \
@@ -262,15 +327,15 @@ emulator: ## Start an android emulator instance
262
327
@echo " Starting emulator..."
263
328
@$(ANDROID_HOME ) /emulator/emulator -avd " $( AVD) " -logcat-output /dev/stdout -netdelay none -netspeed full
264
329
265
- .PHONY : install
330
+ .PHONY : install
266
331
install : $(DEBUG_APK ) # # Install the debug APK on a connected device
267
332
adb install -r $<
268
333
269
334
.PHONY : run
270
335
run : install # # Run the debug APK on a connected device
271
336
adb shell am start -n com.tailscale.ipn/com.tailscale.ipn.MainActivity
272
337
273
- .PHONY : docker-build-image
338
+ .PHONY : docker-build-image
274
339
docker-build-image : # # Builds the docker image for the android build environment if it does not exist
275
340
@echo " Checking if docker image $( DOCKER_IMAGE) already exists..."
276
341
@if ! docker images $(DOCKER_IMAGE ) -q | grep -q . ; then \
@@ -279,29 +344,29 @@ docker-build-image: ## Builds the docker image for the android build environment
279
344
fi
280
345
281
346
.PHONY : docker-run-build
282
- docker-run-build : clean jarsign-env docker-build-image # # Runs the docker image for the android build environment and builds release
347
+ docker-run-build : clean jarsign-env docker-build-image # # Runs the docker image for the android build environment and builds release
283
348
@docker run --rm -v $(CURDIR ) :/build/tailscale-android --env JKS_PASSWORD=$(JKS_PASSWORD ) --env JKS_PATH=$(JKS_PATH ) $(DOCKER_IMAGE )
284
349
285
350
.PHONY : docker-remove-build-image
286
351
docker-remove-build-image : # # Removes the current docker build image
287
352
docker rmi --force $(DOCKER_IMAGE )
288
353
289
- .PHONY : docker-all # # Makes a fresh docker environment, builds docker and cleans up. For CI.
354
+ .PHONY : docker-all # # Makes a fresh docker environment, builds docker and cleans up. For CI.
290
355
docker-all : docker-build-image docker-run-build $(DOCKER_IMAGE )
291
356
292
357
.PHONY : docker-shell
293
358
docker-shell : # # Builds a docker image with the android build env and opens a shell
294
- docker build -f docker/DockerFile.amd64-shell -t tailscale-android-shell-amd64 .
359
+ docker build -f docker/DockerFile.amd64-shell -t tailscale-android-shell-amd64 .
295
360
docker run --rm -v $(CURDIR ) :/build/tailscale-android -it tailscale-android-shell-amd64
296
361
297
362
.PHONY : docker-remove-shell-image
298
363
docker-remove-shell-image : # # Removes all docker shell image
299
364
docker rmi --force tailscale-android-shell-amd64
300
365
301
366
.PHONY : clean
302
- clean : # # Remove build artifacts. Does not purge docker build envs. Use dockerRemoveEnv for that.
367
+ clean : # # Remove build artifacts. Does not purge docker build envs. Use dockerRemoveEnv for that.
303
368
@echo " Cleaning up old build artifacts"
304
- -rm -rf android/build $(DEBUG_APK ) $(RELEASE_AAB ) $(RELEASE_TV_AAB ) $(LIBTAILSCALE ) android/libs * .apk * .aab
369
+ -rm -rf android/build $(DEBUG_APK ) $(RELEASE_AAB ) $(RELEASE_TV_AAB ) $(LIBTAILSCALE_AAR ) android/libs * .apk * .aab
305
370
@echo " Cleaning cached toolchain"
306
371
-rm -rf $(HOME ) /.cache/tailscale-go{,.extracted}
307
372
-pkill -f gradle
0 commit comments