Skip to content

Commit

Permalink
Improve portable builds
Browse files Browse the repository at this point in the history
In portable builds, scrcpy-server.jar was supposed to be present in the
current directory, so in practice it worked only if scrcpy was launched
from its own directory.

Instead, find the absolute path of the executable and build a suitable
path to use scrcpy-server.jar from the same directory.
  • Loading branch information
rom1v committed Jun 11, 2019
1 parent 3b17ff7 commit 2755bfc
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 11 deletions.
4 changes: 2 additions & 2 deletions app/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ conf.set_quoted('SCRCPY_VERSION', meson.project_version())
# the prefix used during configuration (meson --prefix=PREFIX)
conf.set_quoted('PREFIX', get_option('prefix'))

# build a "portable" version (with scrcpy-server.jar accessible from the
# current directory)
# build a "portable" version (with scrcpy-server.jar accessible from the same
# directory as the executable)
conf.set('PORTABLE', get_option('portable'))

# the default client TCP port for the "adb reverse" tunnel
Expand Down
7 changes: 7 additions & 0 deletions app/src/command.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
// not needed here, but winsock2.h must never be included AFTER windows.h
# include <winsock2.h>
# include <windows.h>
# define PATH_SEPARATOR '\\'
# define PRIexitcode "lu"
// <https://stackoverflow.com/a/44383330/1987178>
# ifdef _WIN64
Expand All @@ -23,6 +24,7 @@
#else

# include <sys/types.h>
# define PATH_SEPARATOR '/'
# define PRIsizet "zu"
# define PRIexitcode "d"
# define PROCESS_NONE -1
Expand Down Expand Up @@ -76,4 +78,9 @@ adb_install(const char *serial, const char *local);
bool
process_check_success(process_t proc, const char *name);

// return the absolute path of the executable (the scrcpy binary)
// may be NULL on error; to be freed by SDL_free
char *
get_executable_path(void);

#endif
51 changes: 43 additions & 8 deletions app/src/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,67 @@

#include <errno.h>
#include <inttypes.h>
#include <libgen.h>
#include <stdio.h>
#include <SDL2/SDL_assert.h>
#include <SDL2/SDL_timer.h>

#include "config.h"
#include "command.h"
#include "log.h"
#include "net.h"

#define SOCKET_NAME "scrcpy"
#define SERVER_FILENAME "scrcpy-server.jar"

#ifdef PORTABLE
# define DEFAULT_SERVER_PATH SERVER_FILENAME
#else
# define DEFAULT_SERVER_PATH PREFIX "/share/scrcpy/" SERVER_FILENAME
#endif

#define DEFAULT_SERVER_PATH PREFIX "/share/scrcpy/" SERVER_FLENAME
#define DEVICE_SERVER_PATH "/data/local/tmp/" SERVER_FILENAME

static const char *
get_server_path(void) {
const char *server_path = getenv("SCRCPY_SERVER_PATH");
const char *server_path_env = getenv("SCRCPY_SERVER_PATH");
if (server_path_env) {
LOGD("Using SCRCPY_SERVER_PATH: %s", server_path_env);
// if the envvar is set, use it
return server_path_env;
}

#ifndef PORTABLE
LOGD("Using server: " DEFAULT_SERVER_PATH);
// the absolute path is hardcoded
return DEFAULT_SERVER_PATH;
#else
// use scrcpy-server.jar in the same directory as the executable
char *executable_path = get_executable_path();
if (!executable_path) {
LOGE("Cannot get executable path, "
"using " SERVER_FILENAME " from current directory");
// not found, use current directory
return SERVER_FILENAME;
}
char *dir = dirname(executable_path);
size_t dirlen = strlen(dir);

// sizeof(SERVER_FILENAME) gives statically the size including the null byte
size_t len = dirlen + 1 + sizeof(SERVER_FILENAME);
char *server_path = SDL_malloc(len);
if (!server_path) {
server_path = DEFAULT_SERVER_PATH;
LOGE("Cannot alloc server path string, "
"using " SERVER_FILENAME " from current directory");
SDL_free(executable_path);
return SERVER_FILENAME;
}

memcpy(server_path, dir, dirlen);
server_path[dirlen] = PATH_SEPARATOR;
memcpy(&server_path[dirlen + 1], SERVER_FILENAME, sizeof(SERVER_FILENAME));
// the final null byte has been copied with SERVER_FILENAME

SDL_free(executable_path);

LOGD("Using server (portable): %s", server_path);
return server_path;
#endif
}

static bool
Expand Down
26 changes: 26 additions & 0 deletions app/src/sys/unix/command.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
// for portability
#define _POSIX_SOURCE // for kill()
#define _BSD_SOURCE // for readlink()

// modern glibc will complain without this
#define _DEFAULT_SOURCE

#include "command.h"

#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/types.h>
Expand Down Expand Up @@ -98,3 +104,23 @@ cmd_simple_wait(pid_t pid, int *exit_code) {
}
return !code;
}

char *
get_executable_path(void) {
// <https://stackoverflow.com/a/1024937/1987178>
#ifdef __linux__
char buf[PATH_MAX + 1]; // +1 for the null byte
ssize_t len = readlink("/proc/self/exe", buf, PATH_MAX);
if (len == -1) {
perror("readlink");
return NULL;
}
buf[len] = '\0';
return SDL_strdup(buf);
#else
// in practice, we only need this feature for portable builds, only used on
// Windows, so we don't care implementing it for every platform
// (it's useful to have a working version on Linux for debugging though)
return NULL;
#endif
}
15 changes: 15 additions & 0 deletions app/src/sys/win/command.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,18 @@ cmd_simple_wait(HANDLE handle, DWORD *exit_code) {
}
return !code;
}

char *
get_executable_path(void) {
HMODULE hModule = GetModuleHandleW(NULL);
if (!hModule) {
return NULL;
}
WCHAR buf[MAX_PATH + 1]; // +1 for the null byte
int len = GetModuleFileNameW(hModule, buf, MAX_PATH);
if (!len) {
return NULL;
}
buf[len] = '\0';
return utf8_from_wide_char(buf);
}
2 changes: 1 addition & 1 deletion meson_options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ option('build_server', type: 'boolean', value: true, description: 'Build the ser
option('crossbuild_windows', type: 'boolean', value: false, description: 'Build for Windows from Linux')
option('windows_noconsole', type: 'boolean', value: false, description: 'Disable console on Windows (pass -mwindows flag)')
option('prebuilt_server', type: 'string', description: 'Path of the prebuilt server')
option('portable', type: 'boolean', description: 'Use scrcpy-server.jar from the current directory')
option('portable', type: 'boolean', description: 'Use scrcpy-server.jar from the same directory as the scrcpy executable')
option('skip_frames', type: 'boolean', value: true, description: 'Always display the most recent frame')
option('hidpi_support', type: 'boolean', value: true, description: 'Enable High DPI support')

0 comments on commit 2755bfc

Please sign in to comment.