Makefile,Dockerfile,README.md: improve build dependency setup and documentation (#114)

- Teach Makefile to install an Android SDK and the components we need
- Make Dockerfile delegate to Makefile for Android SDK setup
- Detect Android Studio and other known SDK paths, and use them if found.
- Update documentation to more consistently point to Android Studio & make.
- Add a task that checks for the SDK components and produces a useful error.
- Build an APK by default.
- Allow TOOLCHAINDIR to be passed in, and strip the first go/ component
  so that it is the path a user would expect.

Updates #cleanup
pull/119/head
James Tucker 10 months ago committed by GitHub
parent 5ca195b109
commit 926613ddae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

4
.gitignore vendored

@ -10,6 +10,10 @@ android/libs
# Output files from the Makefile:
tailscale-debug.apk
tailscale-release.aab
tailscale-fdroid.apk
# Signing key
tailscale.jks
# android sdk dir
./android-sdk

@ -12,26 +12,14 @@ RUN apt-get -y --no-install-recommends install ca-certificates libc6-dev git
RUN apt-get -y install make
RUN mkdir -p BUILD
RUN mkdir -p build
ENV HOME /build
# Get android sdk, ndk, and rest of the stuff needed to build the android app.
WORKDIR $HOME
# Make android sdk location, the later make step will populate it.
RUN mkdir android-sdk
ENV ANDROID_HOME $HOME/android-sdk
WORKDIR $ANDROID_HOME
RUN curl -O https://dl.google.com/android/repository/commandlinetools-linux-9477386_latest.zip
RUN echo 'bd1aa17c7ef10066949c88dc6c9c8d536be27f992a1f3b5a584f9bd2ba5646a0 commandlinetools-linux-9477386_latest.zip' | sha256sum -c
RUN mkdir cmdline-tools && unzip -d cmdline-tools/latest commandlinetools-linux-9477386_latest.zip && mv cmdline-tools/latest/cmdline-tools/* cmdline-tools/latest/
RUN echo y | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --update
RUN echo y | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager 'platforms;android-31'
RUN echo y | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager 'extras;android;m2repository'
RUN echo y | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager 'ndk;23.1.7779620'
RUN echo y | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager 'platform-tools'
RUN echo y | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager 'build-tools;33.0.2'
ENV ANDROID_SDK_ROOT $ANDROID_HOME
ENV PATH $PATH:$HOME/bin:$ANDROID_HOME/platform-tools
ENV ANDROID_SDK_ROOT /build/android-sdk
# We need some version of Go new enough to support the "embed" package
# to run "go run tailscale.com/cmd/printdep" to figure out which Tailscale Go
@ -43,6 +31,11 @@ RUN mkdir -p $HOME/tailscale-android
RUN git config --global --add safe.directory $HOME/tailscale-android
WORKDIR $HOME/tailscale-android
# Preload Android SDK
COPY Makefile Makefile
# Get android sdk, ndk, and rest of the stuff needed to build the android app.
RUN make androidsdk
# Preload Gradle
COPY android/gradlew android/gradlew
COPY android/gradle android/gradle

@ -21,15 +21,55 @@ TAILSCALE_COMMIT=$(shell echo $(TAILSCALE_VERSION) | cut -d - -f 2 | cut -d t -f
# Extract the version code from build.gradle.
VERSIONCODE=$(lastword $(shell grep versionCode android/build.gradle))
VERSIONCODE_PLUSONE=$(shell expr $(VERSIONCODE) + 1)
ifeq ($(shell uname),Linux)
ANDROID_TOOLS_URL="https://dl.google.com/android/repository/commandlinetools-linux-9477386_latest.zip"
ANDROID_TOOLS_SUM="bd1aa17c7ef10066949c88dc6c9c8d536be27f992a1f3b5a584f9bd2ba5646a0 commandlinetools-linux-9477386_latest.zip"
else
ANDROID_TOOLS_URL="https://dl.google.com/android/repository/commandlinetools-mac-9477386_latest.zip"
ANDROID_TOOLS_SUM="2072ffce4f54cdc0e6d2074d2f381e7e579b7d63e915c220b96a7db95b2900ee commandlinetools-mac-9477386_latest.zip"
endif
ANDROID_SDK_PACKAGES='platforms;android-31' 'extras;android;m2repository' 'ndk;23.1.7779620' 'platform-tools' 'build-tools;33.0.2'
# Attempt to find an ANDROID_SDK_ROOT / ANDROID_HOME based either from
# preexisting environment or common locations.
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)
# If ANDROID_SDK_ROOT is still unset, set it to a default location by platform.
ifeq ($(ANDROID_SDK_ROOT),)
ifeq ($(shell uname),Linux)
export ANDROID_SDK_ROOT=$(HOME)/Android/Sdk
else ifeq ($(shell uname),Darwin)
export ANDROID_SDK_ROOT=$(HOME)/Library/Android/sdk
else ifneq ($(WINDIR),))
export ANDROID_SDK_ROOT=$(HOME)/AppData/Local/Android/sdk
else
export ANDROID_SDK_ROOT=$(PWD)/android-sdk
endif
endif
export ANDROID_HOME ?= $(ANDROID_SDK_ROOT)
# Attempt to find Android Studio for Linux configuration, which does not have a
# predetermined location.
ANDROID_STUDIO_ROOT ?= $(shell find ~/android-studio /usr/local/android-studio /opt/android-studio /Applications/Android\ Studio.app $(PROGRAMFILES)/Android/Android\ Studio -type d -maxdepth 1 2>/dev/null | head -n 1)
# Set JAVA_HOME to the Android Studio bundled JDK.
export JAVA_HOME ?= $(shell find $(ANDROID_STUDIO_ROOT)/jre $(ANDROID_STUDIO_ROOT)/jbr $(ANDROID_STUDIO_ROOT)/Contents/jre/Contents/Home -maxdepth 1 -type d 2>/dev/null | head -n 1)
TOOLCHAINREV=$(shell go run tailscale.com/cmd/printdep --go)
TOOLCHAINDIR=${HOME}/.cache/tailscale-android-go-$(TOOLCHAINREV)
TOOLCHAINSUM=$(shell $(TOOLCHAINDIR)/go/bin/go version >/dev/null && echo "okay" || echo "bad")
TOOLCHAINWANT=okay
export PATH := $(TOOLCHAINDIR)/go/bin:$(PATH)
# Go toolchain path, by default pulled from Tailscale prebuilts pinned to the
# version in tailscale.com/cmd/printdep.
TOOLCHAINDIR ?= ${HOME}/.cache/tailscale-android-go-$(shell go run tailscale.com/cmd/printdep --go)
export PATH := $(TOOLCHAINDIR)/bin:$(JAVA_HOME)/bin:$(ANDROID_HOME)/cmdline-tools/latest/bin:$(ANDROID_HOME)/platform-tools:$(PATH)
export GOROOT := # Unset
all: $(APK)
all: $(DEBUG_APK) tailscale-fdroid.apk
env:
@echo PATH=$(PATH)
@echo ANDROID_SDK_ROOT=$(ANDROID_SDK_ROOT)
@echo ANDROID_HOME=$(ANDROID_HOME)
@echo JAVA_HOME=$(JAVA_HOME)
@echo TOOLCHAINDIR=$(TOOLCHAINDIR)
tag_release:
sed -i'.bak' 's/versionCode $(VERSIONCODE)/versionCode $(VERSIONCODE_PLUSONE)/' android/build.gradle && rm android/build.gradle.bak
@ -41,41 +81,75 @@ bumposs: toolchain
GOPROXY=direct go get tailscale.com@main
go mod tidy -compat=1.20
toolchain:
ifneq ($(TOOLCHAINWANT),$(TOOLCHAINSUM))
@echo want: $(TOOLCHAINWANT)
@echo got: $(TOOLCHAINSUM)
$(TOOLCHAINDIR)/bin/go:
@if ! echo $(TOOLCHAINDIR) | grep -q 'tailscale-android-go'; then \
echo "ERROR: TOOLCHAINDIR=$(TOOLCHAINDIR) is missing bin/go and does not appear to be a tailscale managed path"; \
exit 1; \
fi
rm -rf ${HOME}/.cache/tailscale-android-go-*
mkdir -p $(TOOLCHAINDIR)
curl --silent -L $(shell go run tailscale.com/cmd/printdep --go-url) | tar -C $(TOOLCHAINDIR) -zx
endif
$(DEBUG_APK): toolchain
curl --silent -L $(shell go run tailscale.com/cmd/printdep --go-url) | tar --strip-components=1 -C $(TOOLCHAINDIR) -zx
# Get the commandline tools package, this provides (among other things) the sdkmanager binary.
$(ANDROID_HOME)/cmdline-tools/latest/bin/sdkmanager:
mkdir -p $(ANDROID_HOME)/tmp
mkdir -p $(ANDROID_HOME)/cmdline-tools
(cd $(ANDROID_HOME)/tmp && \
curl --silent -O -L $(ANDROID_TOOLS_URL) && \
echo $(ANDROID_TOOLS_SUM) | sha256sum -c && \
unzip $(shell basename $(ANDROID_TOOLS_URL)))
mv $(ANDROID_HOME)/tmp/cmdline-tools $(ANDROID_HOME)/cmdline-tools/latest
rm -rf $(ANDROID_HOME)/tmp
# Install the set of Android SDK packages we need.
androidsdk: $(ANDROID_HOME)/cmdline-tools/latest/bin/sdkmanager
yes | $(ANDROID_HOME)/cmdline-tools/latest/bin/sdkmanager --licenses > /dev/null
$(ANDROID_HOME)/cmdline-tools/latest/bin/sdkmanager --update
$(ANDROID_HOME)/cmdline-tools/latest/bin/sdkmanager $(ANDROID_SDK_PACKAGES)
# Normally in make you would simply take a dependency on the task that provides
# the binaries, however users may have a decision to make as to whether they
# want to install an SDK or use the one from an Android Studio installation.
checkandroidsdk:
@$(ANDROID_HOME)/cmdline-tools/latest/bin/sdkmanager --list_installed | grep -q 'ndk' || (\
echo -e "\n\tERROR: Android SDK not installed.\n\
\tANDROID_HOME=$(ANDROID_HOME)\n\
\tANDROID_SDK_ROOT=$(ANDROID_SDK_ROOT)\n\n\
See README.md for instructions on how to install the prerequisites.\n"; exit 1)
androidpath:
@echo "export ANDROID_HOME=$(ANDROID_HOME)"
@echo "export ANDROID_SDK_ROOT=$(ANDROID_SDK_ROOT)"
@echo 'export PATH=$(ANDROID_HOME)/cmdline-tools/latest/bin:$(ANDROID_HOME)/platform-tools:$$PATH'
toolchain: $(TOOLCHAINDIR)/bin/go
android/libs:
mkdir -p android/libs
go run gioui.org/cmd/gogio -buildmode archive -target android -appid $(APPID) -tags novulkan,tailscale_go -o $(AAR) github.com/tailscale/tailscale-android/cmd/tailscale
$(AAR): toolchain checkandroidsdk android/libs
go run gioui.org/cmd/gogio \
-ldflags "-X tailscale.com/version.longStamp=$(VERSIONNAME) -X tailscale.com/version.shortStamp=$(VERSIONNAME_SHORT) -X tailscale.com/version.gitCommitStamp=$(TAILSCALE_COMMIT) -X tailscale.com/version.extraGitCommitStamp=$(OUR_VERSION)" \
-buildmode archive -target android -appid $(APPID) -tags novulkan,tailscale_go -o $@ github.com/tailscale/tailscale-android/cmd/tailscale
# tailscale-debug.apk builds a debuggable APK with the Google Play SDK.
$(DEBUG_APK): $(AAR)
(cd android && ./gradlew test assemblePlayDebug)
mv android/build/outputs/apk/play/debug/android-play-debug.apk $@
rundebug: $(DEBUG_APK)
adb install -r $(DEBUG_APK)
apk: $(DEBUG_APK)
run: install
adb shell am start -n com.tailscale.ipn/com.tailscale.ipn.IPNActivity
# tailscale-fdroid.apk builds a non-Google Play SDK, without the Google bits.
# This is effectively what the F-Droid build definition produces.
# This is useful for testing on e.g. Amazon Fire Stick devices.
tailscale-fdroid.apk: toolchain
mkdir -p android/libs
go run gioui.org/cmd/gogio -buildmode archive -target android -appid $(APPID) -tags novulkan,tailscale_go -o $(AAR) github.com/tailscale/tailscale-android/cmd/tailscale
tailscale-fdroid.apk: $(AAR)
(cd android && ./gradlew test assembleFdroidDebug)
mv android/build/outputs/apk/fdroid/debug/android-fdroid-debug.apk $@
# This target is also used by the F-Droid builder.
release_aar: toolchain
release_aar:
mkdir -p android/libs
go run gioui.org/cmd/gogio -ldflags "-X tailscale.com/version.longStamp=$(VERSIONNAME) -X tailscale.com/version.shortStamp=$(VERSIONNAME_SHORT) -X tailscale.com/version.gitCommitStamp=$(TAILSCALE_COMMIT) -X tailscale.com/version.extraGitCommitStamp=$(OUR_VERSION)" -buildmode archive -target android -appid $(APPID) -tags novulkan,tailscale_go -o $(AAR) github.com/tailscale/tailscale-android/cmd/tailscale
$(RELEASE_AAB): release_aar
$(RELEASE_AAB): $(AAR)
(cd android && ./gradlew test bundlePlayRelease)
mv ./android/build/outputs/bundle/playRelease/android-play-release.aab $@
@ -90,6 +164,7 @@ dockershell:
docker run -v $(CURDIR):/build/tailscale-android -it --rm tailscale-android
clean:
rm -rf android/build $(RELEASE_AAB) $(DEBUG_APK) $(AAR)
-rm -rf android/build $(DEBUG_APK) $(RELEASE_AAB) $(AAR) tailscale-fdroid.apk
-pkill -f gradle
.PHONY: all clean install $(DEBUG_APK) $(RELEASE_AAB) release_aar release bump_version dockershell
.PHONY: all clean install android/lib $(DEBUG_APK) $(RELEASE_AAB) $(AAR) release bump_version dockershell

@ -17,33 +17,63 @@ This repository contains the open source Tailscale Android client.
alt="Get it on Google Play"
height="80">](https://play.google.com/store/apps/details?id=com.tailscale.ipn)
## Building
[Go](https://golang.org), the [Android
SDK](https://developer.android.com/studio/releases/platform-tools),
the [Android NDK](https://developer.android.com/ndk) are required.
## Preparing a build environment
There are several options for setting up a build environment. The Android Studio
path is the most useful path for longer term development.
In all cases you will need:
- Go runtime
- Android SDK
- Android SDK components (`make androidsdk` will install them)
### Android Studio
1. Install a Go runtime (https://go.dev/dl/).
2. Install Android Studio (https://developer.android.com/studio).
3. Start Android Studio, from the Welcome screen select "More Actions" and "SDK Manager".
4. In the SDK manager, select the "SDK Tools" tab and install the "Android SDK Command-line Tools (latest)".
3. Run `make androidsdk` to install the necessary SDK components.
If you would prefer to avoid Android Studio, you can also install an Android
SDK. The makefile detects common paths, so `sudo apt install android-sdk` is
sufficient on Debian / Ubuntu systems. To use an Android SDK installed in a
non-standard location, set the `ANDROID_SDK_ROOT` environment variable to the
path to the SDK.
If you installed Android Studio the tools may not be in your path. To get the
correct tool path, run `make androidpath` and export the provided path in your
shell.
### Docker
If you wish to avoid installing software on your host system, a Docker based development strategy is available, you can build and start a shell with:
```sh
$ make tailscale-debug.apk
$ adb install -r tailscale-debug.apk
make dockershell
```
The `dockershell` target builds a container with the necessary
dependencies and runs a shell inside it.
### Nix
If you have Nix 2.4 or later installed, a Nix development environment can
be set up with:
```sh
$ make dockershell
# make tailscale-debug.apk
alias nix='nix --extra-experimental-features "nix-command flakes"'
nix develop
```
If you have Nix 2.4 or later installed, a Nix development environment can
be set up with
## Building
```sh
$ alias nix='nix --extra-experimental-features "nix-command flakes"'
$ nix develop
make apk
make install
```
## Building a release
Use `make tag_release` to bump the Android version code, update the version
name, and tag the current commit.
@ -52,6 +82,7 @@ release candidate builds (currently Go 1.14) in module mode. It might
work in earlier Go versions or in GOPATH mode, but we're making no
effort to keep those working.
## Google Sign-In
Google Sign-In support relies on configuring a [Google API Console
@ -97,20 +128,6 @@ adb shell am start -n com.tailscale.ipn/com.tailscale.ipn.IPNActivity
adb shell pm uninstall com.tailscale.ipn
```
## Building on macOS
To build from the CLI on macOS:
1. Install Android Studio (when asked which SDKs to install, choose 31 or the current value of targetSdkVersion in `build.gradle`)
2. In Android Studio's home screen: "More Actions" > "SDK Manager", install NDK.
3. You can now close Android Studio, unless you want it to create virtual devices
("More Actions" > "Virtual Device Manager").
4. Then, from CLI:
5. `export JAVA_HOME='/Applications/Android Studio.app/Contents/jbr/Contents/Home'`
6. `export ANDROID_SDK_ROOT=$HOME/Library/Android/sdk`
7. `export PATH=$ANDROID_SDK_ROOT/platform-tools:$PATH` (to allow `adb` and the like to work)
8. `make tailscale-fdroid.apk`, etc
## Bugs
Please file any issues about this code or the hosted service on

Loading…
Cancel
Save