This page describes how scrcpy is built from source: the Meson-based build for the C client, the Gradle-based build for the Android server JAR, and how the two combine into deployable artifacts. For details on client source files and feature flags, see Client Build Configuration. For the server's Java build mechanics, see Server Build Process. For Windows cross-compilation, see Cross-Compilation for Windows. For third-party dependency scripts, see Dependencies. For the CI/CD release pipeline, see Release Pipeline.
scrcpy consists of two separately built components that are deployed together:
| Component | Language | Build Tool | Output |
|---|---|---|---|
| Client | C (C11) | Meson | scrcpy executable |
| Server | Java | Gradle or manual script | scrcpy-server JAR/DEX |
The client executable locates and pushes the server JAR to the Android device at runtime via ADB. The server binary is either built separately and referenced via a path, or compiled as part of the same Meson invocation.
Build System Diagram
Sources: meson.build1-19 meson_options.txt1-9
The file meson.build1-19 is the top-level entry point for the Meson build. It defines:
scrcpyc3.3.40.49c112b_ndebug=if-release)The root build file conditionally descends into the app/ and server/ subdirectories based on two boolean options:
meson setup build -Dcompile_app=true -Dcompile_server=true
All user-visible options are declared in meson_options.txt1-9:
| Option | Type | Default | Description |
|---|---|---|---|
compile_app | boolean | true | Build the C client |
compile_server | boolean | true | Build the Android server |
prebuilt_server | string | (empty) | Path to a prebuilt server JAR; skips server compilation |
portable | boolean | false | Look for scrcpy-server beside the executable instead of in datadir |
static | boolean | false | Link all dependencies statically |
server_debugger | boolean | false | Launch server with JDWP debugger and wait for attach |
v4l2 | boolean | true | Enable V4L2 sink (Linux only) |
usb | boolean | true | Enable HID/OTG via libusb (AOA) |
These options map directly to compile-time #define constants written into the generated config.h (see app/meson.build156-178).
The client is a standard C executable built from the source list in app/meson.build1-66
The build categorizes sources as follows:
| Category | Example Files |
|---|---|
| Core application | src/main.c, src/scrcpy.c, src/cli.c |
| ADB management | src/adb/adb.c, src/adb/adb_tunnel.c |
| Media pipeline | src/demuxer.c, src/decoder.c, src/audio_player.c |
| Input handling | src/input_manager.c, src/keyboard_sdk.c, src/mouse_sdk.c |
| HID subsystem | src/hid/hid_keyboard.c, src/uhid/keyboard_uhid.c |
| Utilities | src/util/net.c, src/util/thread.c, src/util/process.c |
| Platform (Unix) | src/sys/unix/file.c, src/sys/unix/process.c |
| Platform (Windows) | src/sys/win/file.c, src/sys/win/process.c |
| Optional (V4L2) | src/v4l2_sink.c |
| Optional (USB/AOA) | src/usb/scrcpy_otg.c, src/usb/aoa_hid.c, etc. |
app/meson.build74-91 handles platform branching:
src/sys/win/file.c, src/sys/win/process.c, and compiles scrcpy-windows.rc as a Windows resource (icon, manifest, version info). Sets _WIN32_WINNT and WINVER to 0x0600.src/sys/unix/file.c, src/sys/unix/process.c. Sets _DARWIN_C_SOURCE on macOS.v4l2_support is true only when v4l2=true AND host_machine.system() == 'linux'.usb_support follows the usb option unconditionally.| Library | Minimum Version | Purpose |
|---|---|---|
libavformat | >= 57.33 | Media container (recording) |
libavcodec | >= 57.37 | Video/audio decoding |
libavutil | — | FFmpeg utility functions |
libswresample | — | Audio resampling |
sdl2 | >= 2.0.5 | Window, rendering, events, audio |
libavdevice | — | V4L2 device output (optional) |
libusb-1.0 | — | USB/AOA HID (optional) |
mingw32 | — | Windows runtime (Windows only) |
ws2_32 | — | Winsock2 (Windows only) |
config.happ/meson.build68-179 generates config.h from a configuration_data() object. Key constants written into it:
| Constant | Source |
|---|---|
SCRCPY_VERSION | meson.project_version() |
PREFIX | --prefix option |
PORTABLE | -Dportable option |
SERVER_DEBUGGER | -Dserver_debugger option |
HAVE_V4L2 | v4l2 support flag |
HAVE_USB | usb support flag |
DEFAULT_LOCAL_PORT_RANGE_FIRST | 27183 |
DEFAULT_LOCAL_PORT_RANGE_LAST | 27199 |
HAVE_strdup, HAVE_asprintf, etc. | Runtime function probes via cc.has_function() |
HAVE_SOCK_CLOEXEC | Header symbol probe |
Sources: app/meson.build1-208 meson_options.txt1-9
The Android server JAR can be built in two ways.
server/build.gradle1-33 is a standard Android application build:
| Property | Value |
|---|---|
compileSdk | 36 |
minSdkVersion | 21 |
targetSdkVersion | 36 |
versionCode | 30304 |
versionName | 3.3.4 |
namespace | com.genymobile.scrcpy |
minifyEnabled | false (release) |
buildConfig | enabled |
aidl | enabled |
The server module is not a normal Android app (the manifest is intentionally empty: server/src/main/AndroidManifest.xml1-3). It is run via app_process on-device.
server/build_without_gradle.sh1-116 performs the same steps as Gradle, using only Android SDK command-line tools:
Key environment variables:
| Variable | Default | Purpose |
|---|---|---|
ANDROID_PLATFORM | 36 | Android API level for SDK tools |
ANDROID_BUILD_TOOLS | 36.0.0 | Build tools version |
ANDROID_HOME | (required) | Android SDK root |
BUILD_DIR | build_manual | Output directory |
The script compiles fake source stubs for hidden Android APIs alongside the real sources (server/build_without_gradle.sh56-58). For older API levels (< 31) it uses dx; for 31 and above it uses d8 (server/build_without_gradle.sh89-111).
app/meson.build214-281 defines unit tests compiled only in debug buildtype. Each test is a standalone executable linking only the specific source files it needs. Tests cover:
| Test Name | Tested Modules |
|---|---|
test_adb_parser | adb_parser.c, adb_device.c |
test_cli | cli.c, options.c, net.c |
test_control_msg_serialize | control_msg.c |
test_device_msg_deserialize | device_msg.c |
test_audiobuf | audiobuf.c |
test_strbuf | strbuf.c |
test_orientation | options.c |
test_vecdeque | memory.c |
test_binary | (standalone) |
test_str | str.c, strbuf.c |
test_vector | (standalone) |
All test executables are built with -DSDL_MAIN_HANDLED -DSC_TEST and linked against compat.c.
Sources: app/meson.build213-281
The client Meson build installs the following artifacts (app/meson.build189-208):
| Artifact | Destination |
|---|---|
scrcpy executable | bin/ |
scrcpy.1 man page | man/man1/ |
data/icon.png | share/icons/hicolor/256x256/apps/scrcpy.png |
data/zsh-completion/_scrcpy | share/zsh/site-functions/ |
data/bash-completion/scrcpy | share/bash-completion/completions/ |
data/scrcpy.desktop | share/applications/ (Linux only) |
data/scrcpy-console.desktop | share/applications/ (Linux only) |
The --prefix value is embedded in config.h as PREFIX so the client can compute the server JAR path at runtime, unless -Dportable=true is set (in which case the server is located beside the executable).
Refresh this wiki
This wiki was recently refreshed. Please wait 3 days to refresh again.