Improve portable builds
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.
This commit is contained in:
parent
3b17ff7c86
commit
2755bfc255
6 changed files with 95 additions and 12 deletions
|
@ -93,8 +93,8 @@ conf.set_quoted('SCRCPY_VERSION', meson.project_version())
|
||||||
# the prefix used during configuration (meson --prefix=PREFIX)
|
# the prefix used during configuration (meson --prefix=PREFIX)
|
||||||
conf.set_quoted('PREFIX', get_option('prefix'))
|
conf.set_quoted('PREFIX', get_option('prefix'))
|
||||||
|
|
||||||
# build a "portable" version (with scrcpy-server.jar accessible from the
|
# build a "portable" version (with scrcpy-server.jar accessible from the same
|
||||||
# current directory)
|
# directory as the executable)
|
||||||
conf.set('PORTABLE', get_option('portable'))
|
conf.set('PORTABLE', get_option('portable'))
|
||||||
|
|
||||||
# the default client TCP port for the "adb reverse" tunnel
|
# the default client TCP port for the "adb reverse" tunnel
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
// not needed here, but winsock2.h must never be included AFTER windows.h
|
// not needed here, but winsock2.h must never be included AFTER windows.h
|
||||||
# include <winsock2.h>
|
# include <winsock2.h>
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
|
# define PATH_SEPARATOR '\\'
|
||||||
# define PRIexitcode "lu"
|
# define PRIexitcode "lu"
|
||||||
// <https://stackoverflow.com/a/44383330/1987178>
|
// <https://stackoverflow.com/a/44383330/1987178>
|
||||||
# ifdef _WIN64
|
# ifdef _WIN64
|
||||||
|
@ -23,6 +24,7 @@
|
||||||
#else
|
#else
|
||||||
|
|
||||||
# include <sys/types.h>
|
# include <sys/types.h>
|
||||||
|
# define PATH_SEPARATOR '/'
|
||||||
# define PRIsizet "zu"
|
# define PRIsizet "zu"
|
||||||
# define PRIexitcode "d"
|
# define PRIexitcode "d"
|
||||||
# define PROCESS_NONE -1
|
# define PROCESS_NONE -1
|
||||||
|
@ -76,4 +78,9 @@ adb_install(const char *serial, const char *local);
|
||||||
bool
|
bool
|
||||||
process_check_success(process_t proc, const char *name);
|
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
|
#endif
|
||||||
|
|
|
@ -2,32 +2,67 @@
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <libgen.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <SDL2/SDL_assert.h>
|
#include <SDL2/SDL_assert.h>
|
||||||
#include <SDL2/SDL_timer.h>
|
#include <SDL2/SDL_timer.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "command.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
|
||||||
#define SOCKET_NAME "scrcpy"
|
#define SOCKET_NAME "scrcpy"
|
||||||
#define SERVER_FILENAME "scrcpy-server.jar"
|
#define SERVER_FILENAME "scrcpy-server.jar"
|
||||||
|
|
||||||
#ifdef PORTABLE
|
#define DEFAULT_SERVER_PATH PREFIX "/share/scrcpy/" SERVER_FLENAME
|
||||||
# define DEFAULT_SERVER_PATH SERVER_FILENAME
|
|
||||||
#else
|
|
||||||
# define DEFAULT_SERVER_PATH PREFIX "/share/scrcpy/" SERVER_FILENAME
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define DEVICE_SERVER_PATH "/data/local/tmp/" SERVER_FILENAME
|
#define DEVICE_SERVER_PATH "/data/local/tmp/" SERVER_FILENAME
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
get_server_path(void) {
|
get_server_path(void) {
|
||||||
const char *server_path = getenv("SCRCPY_SERVER_PATH");
|
const char *server_path_env = getenv("SCRCPY_SERVER_PATH");
|
||||||
if (!server_path) {
|
if (server_path_env) {
|
||||||
server_path = DEFAULT_SERVER_PATH;
|
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) {
|
||||||
|
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;
|
return server_path;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
|
// for portability
|
||||||
#define _POSIX_SOURCE // for kill()
|
#define _POSIX_SOURCE // for kill()
|
||||||
|
#define _BSD_SOURCE // for readlink()
|
||||||
|
|
||||||
|
// modern glibc will complain without this
|
||||||
|
#define _DEFAULT_SOURCE
|
||||||
|
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
@ -98,3 +104,23 @@ cmd_simple_wait(pid_t pid, int *exit_code) {
|
||||||
}
|
}
|
||||||
return !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
|
||||||
|
}
|
||||||
|
|
|
@ -75,3 +75,18 @@ cmd_simple_wait(HANDLE handle, DWORD *exit_code) {
|
||||||
}
|
}
|
||||||
return !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);
|
||||||
|
}
|
||||||
|
|
|
@ -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('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('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('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('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')
|
option('hidpi_support', type: 'boolean', value: true, description: 'Enable High DPI support')
|
||||||
|
|
Loading…
Reference in a new issue