Skip to content

Commit

Permalink
Add cross-compilation scripts for Windows
Browse files Browse the repository at this point in the history
Build the Windows binary from mingw on Linux, using the official
prebuilt binaries for ffmpeg, SDL2 and adb.

MSYS2 and all its packaged dll are not necessary anymore.
  • Loading branch information
rom1v committed May 28, 2018
1 parent 7d68316 commit 106b87a
Show file tree
Hide file tree
Showing 8 changed files with 296 additions and 71 deletions.
65 changes: 0 additions & 65 deletions Makefile

This file was deleted.

106 changes: 106 additions & 0 deletions Makefile.CrossWindows
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# This makefile provides recipes to build a "portable" version of scrcpy for
# Windows.
#
# 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.

.PHONY: default clean \
build-server \
prepare-deps-win32 prepare-deps-win64 \
build-win32 build-win64 \
dist-win32 dist-win64 \
zip-win32 zip-win64 \
sums release

GRADLE ?= ./gradlew

SERVER_BUILD_DIR := build-server
WIN32_BUILD_DIR := build-win32
WIN64_BUILD_DIR := build-win64

DIST := dist
WIN32_TARGET_DIR := scrcpy-win32
WIN64_TARGET_DIR := scrcpy-win64

VERSION := $(shell git describe --tags --always)
WIN32_TARGET := $(WIN32_TARGET_DIR)-$(VERSION).zip
WIN64_TARGET := $(WIN64_TARGET_DIR)-$(VERSION).zip

release: clean zip-win32 zip-win64 sums
@echo "Release created in $(DIST)/."

clean:
$(GRADLE) clean
rm -rf "$(SERVER_BUILD_DIR)" "$(WIN32_BUILD_DIR)" "$(WIN64_BUILD_DIR)" "$(DIST)"

build-server:
[ -d "$(SERVER_BUILD_DIR)" ] || ( mkdir "$(SERVER_BUILD_DIR)" && \
meson "$(SERVER_BUILD_DIR)" \
--buildtype release -Dbuild_app=false )
ninja -C "$(SERVER_BUILD_DIR)"

prepare-deps-win32:
-$(MAKE) -C prebuilt-deps prepare-win32

build-win32: prepare-deps-win32
[ -d "$(WIN32_BUILD_DIR)" ] || ( mkdir "$(WIN32_BUILD_DIR)" && \
meson "$(WIN32_BUILD_DIR)" \
--cross-file cross_win32.txt \
--buildtype release --strip -Db_lto=true \
-Dbuild_server=false \
-Doverride_server_path=scrcpy-server.jar )
ninja -C "$(WIN32_BUILD_DIR)"

prepare-deps-win64:
-$(MAKE) -C prebuilt-deps prepare-win64

build-win64: prepare-deps-win64
[ -d "$(WIN64_BUILD_DIR)" ] || ( mkdir "$(WIN64_BUILD_DIR)" && \
meson "$(WIN64_BUILD_DIR)" \
--cross-file cross_win64.txt \
--buildtype release --strip -Db_lto=true \
-Dbuild_server=false \
-Doverride_server_path=scrcpy-server.jar )
ninja -C "$(WIN64_BUILD_DIR)"

dist-win32: build-server build-win32
mkdir -p "$(DIST)/$(WIN32_TARGET_DIR)"
cp "$(SERVER_BUILD_DIR)"/server/scrcpy-server.jar "$(DIST)/$(WIN32_TARGET_DIR)/"
cp "$(WIN32_BUILD_DIR)"/app/scrcpy.exe "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.0-win32-shared/bin/avutil-56.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.0-win32-shared/bin/avcodec-58.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.0-win32-shared/bin/avformat-58.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.0-win32-shared/bin/swresample-3.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/platform-tools/adb.exe "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/platform-tools/AdbWinApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/platform-tools/AdbWinUsbApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/SDL2-2.0.8/i686-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN32_TARGET_DIR)/"

dist-win64: build-server build-win64
mkdir -p "$(DIST)/$(WIN64_TARGET_DIR)"
cp "$(SERVER_BUILD_DIR)"/server/scrcpy-server.jar "$(DIST)/$(WIN64_TARGET_DIR)/"
cp "$(WIN64_BUILD_DIR)"/app/scrcpy.exe "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.0-win64-shared/bin/avutil-56.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.0-win64-shared/bin/avcodec-58.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.0-win64-shared/bin/avformat-58.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.0-win64-shared/bin/swresample-3.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/platform-tools/adb.exe "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/platform-tools/AdbWinApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/platform-tools/AdbWinUsbApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/SDL2-2.0.8/x86_64-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN64_TARGET_DIR)/"

zip-win32: dist-win32
cd "$(DIST)"; \
zip -r "$(WIN32_TARGET)" "$(WIN32_TARGET_DIR)"

zip-win64: dist-win64
cd "$(DIST)"; \
zip -r "$(WIN64_TARGET)" "$(WIN64_TARGET_DIR)"

sums:
cd "$(DIST)"; \
sha256sum *.zip > SHA256SUM.txt
54 changes: 48 additions & 6 deletions app/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,54 @@ src = [
'src/tinyxpm.c',
]

dependencies = [
dependency('libavformat'),
dependency('libavcodec'),
dependency('libavutil'),
dependency('sdl2'),
]
if not meson.is_cross_build()

# native build
dependencies = [
dependency('libavformat'),
dependency('libavcodec'),
dependency('libavutil'),
dependency('sdl2'),
]

else

# cross-compile mingw32 build (from Linux to Windows)
cc = meson.get_compiler('c')

prebuilt_sdl2 = meson.get_cross_property('prebuilt_sdl2')
sdl2_bin_dir = meson.current_source_dir() + '/../prebuilt-deps/' + prebuilt_sdl2 + '/bin'
sdl2_lib_dir = meson.current_source_dir() + '/../prebuilt-deps/' + prebuilt_sdl2 + '/lib'
sdl2_include_dir = '../prebuilt-deps/' + prebuilt_sdl2 + '/include'

sdl2 = declare_dependency(
dependencies: [
cc.find_library('SDL2', dirs: sdl2_bin_dir),
cc.find_library('SDL2main', dirs: sdl2_lib_dir),
],
include_directories: include_directories(sdl2_include_dir)
)

prebuilt_ffmpeg_shared = meson.get_cross_property('prebuilt_ffmpeg_shared')
prebuilt_ffmpeg_dev = meson.get_cross_property('prebuilt_ffmpeg_dev')
ffmpeg_bin_dir = meson.current_source_dir() + '/../prebuilt-deps/' + prebuilt_ffmpeg_shared + '/bin'
ffmpeg_include_dir = '../prebuilt-deps/' + prebuilt_ffmpeg_dev + '/include'
ffmpeg = declare_dependency(
dependencies: [
cc.find_library('avcodec-58', dirs: ffmpeg_bin_dir),
cc.find_library('avformat-58', dirs: ffmpeg_bin_dir),
cc.find_library('avutil-56', dirs: ffmpeg_bin_dir),
],
include_directories: include_directories(ffmpeg_include_dir)
)

dependencies = [
ffmpeg,
sdl2,
cc.find_library('mingw32')
]

endif

cc = meson.get_compiler('c')

Expand Down
20 changes: 20 additions & 0 deletions cross_win32.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# apt install mingw-w64 mingw-w64-tools

[binaries]
name = 'mingw'
c = '/usr/bin/i686-w64-mingw32-gcc'
cpp = '/usr/bin/i686-w64-mingw32-g++'
ar = '/usr/bin/i686-w64-mingw32-ar'
strip = '/usr/bin/i686-w64-mingw32-strip'
pkgconfig = '/usr/bin/i686-w64-mingw32-pkg-config'

[host_machine]
system = 'windows'
cpu_family = 'x86'
cpu = 'i686'
endian = 'little'

[properties]
prebuilt_ffmpeg_shared = 'ffmpeg-4.0-win32-shared'
prebuilt_ffmpeg_dev = 'ffmpeg-4.0-win32-dev'
prebuilt_sdl2 = 'SDL2-2.0.8/i686-w64-mingw32'
20 changes: 20 additions & 0 deletions cross_win64.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# apt install mingw-w64 mingw-w64-tools

[binaries]
name = 'mingw'
c = '/usr/bin/x86_64-w64-mingw32-gcc'
cpp = '/usr/bin/x86_64-w64-mingw32-g++'
ar = '/usr/bin/x86_64-w64-mingw32-ar'
strip = '/usr/bin/x86_64-w64-mingw32-strip'
pkgconfig = '/usr/bin/x86_64-w64-mingw32-pkg-config'

[host_machine]
system = 'windows'
cpu_family = 'x86'
cpu = 'x86_64'
endian = 'little'

[properties]
prebuilt_ffmpeg_shared = 'ffmpeg-4.0-win64-shared'
prebuilt_ffmpeg_dev = 'ffmpeg-4.0-win64-dev'
prebuilt_sdl2 = 'SDL2-2.0.8/x86_64-w64-mingw32'
4 changes: 4 additions & 0 deletions prebuilt-deps/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*
!/.gitignore
!/Makefile
!/prepare-dep
40 changes: 40 additions & 0 deletions prebuilt-deps/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
.PHONY: prepare-win32 prepare-win64 \
prepare-ffmpeg-shared-win32 \
prepare-ffmpeg-dev-win32 \
prepare-ffmpeg-shared-win64 \
prepare-ffmpeg-dev-win64 \
prepare-sdl2 \
prepare-adb

prepare-win32: prepare-sdl2 prepare-ffmpeg-shared-win32 prepare-ffmpeg-dev-win32 prepare-adb
prepare-win64: prepare-sdl2 prepare-ffmpeg-shared-win64 prepare-ffmpeg-dev-win64 prepare-adb

prepare-ffmpeg-shared-win32:
@./prepare-dep https://ffmpeg.zeranoe.com/builds/win32/shared/ffmpeg-4.0-win32-shared.zip \
530c92df0ca14c35901b4b681847d62da3c50a0cc9b7ced37b04968f6b5c243d \
ffmpeg-4.0-win32-shared

prepare-ffmpeg-dev-win32:
@./prepare-dep https://ffmpeg.zeranoe.com/builds/win32/dev/ffmpeg-4.0-win32-dev.zip \
e2f5200b5e73c4d0abb9b89c4ffc0438f92a0aadc54c81cf57e18c81a9f11c6b \
ffmpeg-4.0-win32-dev

prepare-ffmpeg-shared-win64:
@./prepare-dep https://ffmpeg.zeranoe.com/builds/win64/shared/ffmpeg-4.0-win64-shared.zip \
8fe2d344463dbefc2db4239a4203a55ed0324faceaae57276a40c4fabda84c37 \
ffmpeg-4.0-win64-shared

prepare-ffmpeg-dev-win64:
@./prepare-dep https://ffmpeg.zeranoe.com/builds/win64/dev/ffmpeg-4.0-win64-dev.zip \
facced738eabfc53fa92834dea8b24426f64db61298688fed480145945be07fa \
ffmpeg-4.0-win64-dev

prepare-sdl2:
@./prepare-dep https://libsdl.org/release/SDL2-devel-2.0.8-mingw.tar.gz \
ffff7305d634aff5e1df5b7bb935435c3a02c8b03ad94a1a2be9169a558a7961 \
SDL2-2.0.8

prepare-adb:
@./prepare-dep https://dl.google.com/android/repository/platform-tools_r27.0.1-windows.zip \
880662adfb0d6911ff250b9e13930ae1a4110fc36d5866afd4f8f56d935f7939 \
platform-tools
58 changes: 58 additions & 0 deletions prebuilt-deps/prepare-dep
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/bin/bash
set -e
url="$1"
sum="$2"
dir="$3"

checksum() {
local file="$1"
local sum="$2"
echo "$file: verifying checksum..."
echo "$sum $file" | sha256sum -c
}

get_file() {
local url="$1"
local file="$2"
local sum="$3"
if [[ -f "$file" ]]
then
echo "$file: found"
else
echo "$file: not found, downloading..."
wget "$url" -O "$file"
fi
checksum "$file" "$sum"
}

extract() {
local file="$1"
echo "Extracting $file..."
if [[ "$file" == *.zip ]]
then
unzip -q "$file"
elif [[ "$file" == *.tar.gz ]]
then
tar xf "$file"
else
echo "Unsupported file: $file"
return 1
fi
}

get_dep() {
local url="$1"
local sum="$2"
local dir="$3"
local file="${url##*/}"
if [[ -d "$dir" ]]
then
echo "$dir: found"
else
echo "$dir: not found"
get_file "$url" "$file" "$sum"
extract "$file"
fi
}

get_dep "$1" "$2" "$3"

0 comments on commit 106b87a

Please sign in to comment.