Refactor build system

The client was built with Meson, the server with Gradle, and were run by
a Makefile.

Add a Meson script for the server (which delegates to Gradle), and a
parent script to build and install both the client and the server to the
system, typically with:

    meson --buildtype release build
    cd build
    ninja
    sudo ninja install

In addition, use a separate Makefile to build a "portable" version of
the application (where the client expects the server to be in the
current directory). Typically:

    make release-portable
    cd dist/scrcpy
    ./scrcpy

This is especially useful for Windows builds, which are not "installed".
This commit is contained in:
Romain Vimont 2018-02-13 11:55:12 +01:00
parent 396df8a9d8
commit ff94462d8a
9 changed files with 109 additions and 42 deletions

View file

@ -1,9 +1,22 @@
.PHONY: default release clean build build-app build-server run dist dist-zip sums test
# This makefile provides recipes to build a "portable" version of scrcpy.
#
# Here, "portable" means that the client and server binaries are expected to be
# anywhere, but in the same directory, instead of well-defined separate
# locations (e.g. /usr/bin/scrcpy and /usr/share/scrcpy/scrcpy-server.jar).
#
# In particular, this implies to change the location from where the client push
# the server to the device.
#
# "make release-portable" builds a zip containing the client and the server.
#
# This is a simple Makefile because Meson is not flexible enough to execute some
# arbitrary commands.
.PHONY: default clean release-portable dist-portable dist-portable-zip sums test check
GRADLE ?= ./gradlew
APP_BUILD_DIR := app-build
APP_BUILD_DEBUG_DIR := app-build-debug
PORTABLE_BUILD_DIR := build-portable
DIST := dist
TARGET_DIR := scrcpy
@ -11,47 +24,28 @@ VERSION := $(shell git describe --tags --always)
TARGET := $(TARGET_DIR)-$(VERSION).zip
default:
@echo 'You must specify a target. Try: make release'
release: clean dist-zip sums
@echo 'You must specify a target. Try: make release-portable'
clean:
$(GRADLE) clean
rm -rf "$(APP_BUILD_DIR)" "$(APP_BUILD_DEBUG_DIR)" "$(DIST)"
rm -rf "$(PORTABLE_BUILD_DIR)" "$(DIST)"
build-app-debug:
[ -d "$(APP_BUILD_DEBUG_DIR)" ] || ( mkdir "$(APP_BUILD_DEBUG_DIR)" && \
meson app "$(APP_BUILD_DEBUG_DIR)" --buildtype debug )
ninja -C "$(APP_BUILD_DEBUG_DIR)"
build-portable:
[ -d "$(PORTABLE_BUILD_DIR)" ] || ( mkdir "$(PORTABLE_BUILD_DIR)" && \
meson "$(PORTABLE_BUILD_DIR)" \
--buildtype release --strip -Db_lto=true \
-Dapp:override_server_jar=scrcpy-server.jar )
ninja -C "$(PORTABLE_BUILD_DIR)"
build-server-debug:
$(GRADLE) assembleDebug
release-portable: clean dist-portable-zip sums
@echo "Release created in $(DIST)/."
build-debug: build-app-debug build-server-debug
run-debug:
SCRCPY_SERVER_JAR=server/build/outputs/apk/debug/server-debug.apk $(APP_BUILD_DEBUG_DIR)/scrcpy $(ARGS)
build-app:
[ -d "$(APP_BUILD_DIR)" ] || ( mkdir "$(APP_BUILD_DIR)" && \
meson app "$(APP_BUILD_DIR)" --buildtype release -Db_lto )
ninja -C "$(APP_BUILD_DIR)"
build-server:
$(GRADLE) assembleRelease
build: build-app build-server
run:
SCRCPY_SERVER_JAR=server/build/outputs/apk/release/server-release-unsigned.apk $(APP_BUILD_DIR)/scrcpy $(ARGS)
dist: build
dist-portable: build-portable
mkdir -p "$(DIST)/$(TARGET_DIR)"
# no need to sign the APK, we dont "install" it, this is in fact a simple jar
cp server/build/outputs/apk/release/server-release-unsigned.apk "$(DIST)/$(TARGET_DIR)/scrcpy-server.jar"
cp $(APP_BUILD_DIR)/scrcpy "$(DIST)/$(TARGET_DIR)/"
cp "$(PORTABLE_BUILD_DIR)"/server/scrcpy-server.jar "$(DIST)/$(TARGET_DIR)/"
cp "$(PORTABLE_BUILD_DIR)"/app/scrcpy "$(DIST)/$(TARGET_DIR)/"
dist-zip: dist
dist-portable-zip: dist-portable
cd "$(DIST)"; \
zip -r "$(TARGET)" "$(TARGET_DIR)"
@ -59,6 +53,10 @@ sums:
cd "$(DIST)"; \
sha256sum *.zip > SHA256SUM.txt
test:
test: build-portable
$(GRADLE) test
ninja -C "$(APP_BUILD_DIR)" test
ninja -C "$(PORTABLE_BUILD_DIR)" test
check: build-portable
$(GRADLE) check
ninja -C "$(PORTABLE_BUILD_DIR)" test

View file

@ -42,6 +42,22 @@ conf.set('BUILD_DEBUG', get_option('buildtype') == 'debug')
# (conf.set_quoted() is not available on old versions of meson)
conf.set('SCRCPY_VERSION', '"0.1"')
# the prefix used during configuration (meson --prefix=PREFIX)
conf.set('PREFIX', '"' + get_option('prefix') + '"')
# the path of the server, which will be appended to the prefix
# ignored if OVERRIDE_SERVER_JAR if defined
# must be consistent with the install_dir in server/meson.build
conf.set('PREFIXED_SERVER_JAR', '"/share/scrcpy/scrcpy-server.jar"')
# the path of the server to be used "as is"
# this is useful for building a "portable" version (with the server in the same
# directory as the client)
override_server_jar = get_option('override_server_jar')
if override_server_jar != ''
conf.set('OVERRIDE_SERVER_JAR', '"' + override_server_jar + '"')
endif
# the default client TCP port for the "adb reverse" tunnel
# overridden by option --port
conf.set('DEFAULT_LOCAL_PORT', '27183')
@ -61,7 +77,7 @@ conf.set('SKIP_FRAMES', true)
configure_file(configuration: conf, input: 'src/config.h.in', output: 'config.h')
executable('scrcpy', src, dependencies: dependencies)
executable('scrcpy', src, dependencies: dependencies, install: true)
### TESTS

1
app/meson_options.txt Normal file
View file

@ -0,0 +1 @@
option('override_server_jar', type: 'string')

View file

@ -1,5 +1,8 @@
#mesondefine BUILD_DEBUG
#mesondefine SCRCPY_VERSION
#mesondefine PREFIX
#mesondefine PREFIXED_SERVER_JAR
#mesondefine OVERRIDE_SERVER_JAR
#mesondefine DEFAULT_LOCAL_PORT
#mesondefine DEFAULT_MAX_SIZE
#mesondefine DEFAULT_BIT_RATE

View file

@ -4,17 +4,28 @@
#include <errno.h>
#include <stdint.h>
#include "config.h"
#include "log.h"
#include "netutil.h"
#define SOCKET_NAME "scrcpy"
static SDL_bool push_server(const char *serial) {
#ifdef OVERRIDE_SERVER_JAR
# define DEFAULT_SERVER_JAR OVERRIDE_SERVER_JAR
#else
# define DEFAULT_SERVER_JAR PREFIX PREFIXED_SERVER_JAR
#endif
static const char *get_server_path(void) {
const char *server_path = getenv("SCRCPY_SERVER_JAR");
if (!server_path) {
server_path = "scrcpy-server.jar";
server_path = DEFAULT_SERVER_JAR;
}
process_t process = adb_push(serial, server_path, "/data/local/tmp/scrcpy-server.jar");
return server_path;
}
static SDL_bool push_server(const char *serial) {
process_t process = adb_push(serial, get_server_path(), "/data/local/tmp/scrcpy-server.jar");
return process_check_success(process, "adb push");
}

6
meson.build Normal file
View file

@ -0,0 +1,6 @@
project('scrcpy', 'c', subproject_dir: '.')
subproject('app')
subproject('server')
run_target('run', command: ['scripts/run-scrcpy.sh'])

2
scripts/run-scrcpy.sh Executable file
View file

@ -0,0 +1,2 @@
#!/bin/bash
SCRCPY_SERVER_JAR="$MESON_BUILD_ROOT/server/scrcpy-server.jar" "$MESON_BUILD_ROOT/app/scrcpy"

11
server/meson.build Normal file
View file

@ -0,0 +1,11 @@
project('scrcpy-server', 'c') # not really c, but meson expects something
# does not track dependencies, so meson does not guarantees that server is up to date
# call "touch server" or "ninja -t clean server/scrcpy-server.jar" before to rebuild
custom_target('scrcpy-server',
build_always: false, # do not enable, otherwise "sudo ninja install" will execute gradle!
input: '.',
output: 'scrcpy-server.jar',
command: [find_program('./scripts/build-wrapper.sh'), '@INPUT@', '@OUTPUT@', get_option('buildtype')],
install: true,
install_dir: 'share/scrcpy')

19
server/scripts/build-wrapper.sh Executable file
View file

@ -0,0 +1,19 @@
#!/bin/bash
# Wrapper script to invoke gradle from meson
set -e
PROJECT_ROOT="$1"
OUTPUT="$2"
BUILDTYPE="$3"
# gradlew is in the parent of the server directory
GRADLE=${GRADLE:-$PROJECT_ROOT/../gradlew}
if [[ "$BUILDTYPE" == debug ]]
then
"$GRADLE" -p "$PROJECT_ROOT" assembleDebug
cp "$PROJECT_ROOT/build/outputs/apk/debug/server-debug.apk" "$OUTPUT"
else
"$GRADLE" -p "$PROJECT_ROOT" assembleRelease
cp "$PROJECT_ROOT/build/outputs/apk/release/server-release-unsigned.apk" "$OUTPUT"
fi