Get rid of the various different launchers

Now there is only one launcher. Which means it can be used to start
kitty with profiling and ASAN in the natural way. The recommended
way to run kitty from source is now:

./kitty/launcher/kitty

The launcher also automatically re-execs to resolve symlinks on macOS.
This commit is contained in:
Kovid Goyal
2019-06-24 17:00:34 +05:30
parent af3504e05c
commit 9135387cfa
10 changed files with 190 additions and 243 deletions

View File

@@ -20,9 +20,16 @@
#endif
#include <Python.h>
#include <wchar.h>
#include <sys/stat.h>
#define MIN(x, y) ((x) < (y)) ? (x) : (y)
#define MAX_ARGC 1024
#ifndef KITTY_LIB_PATH
#define KITTY_LIB_PATH "../.."
#endif
#ifndef KITTY_LIB_DIR_NAME
#define KITTY_LIB_DIR_NAME "lib"
#endif
static inline bool
safe_realpath(const char* src, char *buf, size_t buf_sz) {
@@ -33,17 +40,15 @@ safe_realpath(const char* src, char *buf, size_t buf_sz) {
return true;
}
#if defined(FOR_BUNDLE) || defined(__APPLE__)
static inline void
set_bundle_exe_dir(const wchar_t *exe_dir) {
wchar_t buf[PATH_MAX+1] = {0};
swprintf(buf, PATH_MAX, L"bundle_exe_dir=%ls", exe_dir);
PySys_AddXOption(buf);
}
#endif
#ifdef FOR_BUNDLE
static int run_embedded(const char* exe_dir_, int argc, wchar_t **argv) {
static int run_embedded(const char* exe_dir_, const char *libpath, int argc, wchar_t **argv) {
int num;
Py_NoSiteFlag = 1;
Py_FrozenFlag = 1;
@@ -61,7 +66,7 @@ static int run_embedded(const char* exe_dir_, int argc, wchar_t **argv) {
#ifdef __APPLE__
const char *python_relpath = "../Resources/Python/lib";
#else
const char *python_relpath = "../lib";
const char *python_relpath = "../" KITTY_LIB_DIR_NAME;
#endif
num = swprintf(stdlib, PATH_MAX, L"%ls/%s/python%s:%ls/%s/python%s/lib-dynload:%ls/%s/python%s/site-packages",
exe_dir, python_relpath, PYVER,
@@ -70,17 +75,12 @@ static int run_embedded(const char* exe_dir_, int argc, wchar_t **argv) {
);
if (num < 0 || num >= PATH_MAX) { fprintf(stderr, "Failed to create path to python stdlib\n"); return 1; }
Py_SetPath(stdlib);
#ifdef __APPLE__
num = swprintf(stdlib, PATH_MAX, L"%ls/../Frameworks/kitty", exe_dir);
#else
num = swprintf(stdlib, PATH_MAX, L"%ls/../lib/kitty", exe_dir);
#endif
PyMem_RawFree(exe_dir);
if (num < 0 || num >= PATH_MAX) { fprintf(stderr, "Failed to create path to kitty lib\n"); return 1; }
Py_Initialize();
PySys_SetArgvEx(argc - 1, argv + 1, 0);
PySys_SetObject("frozen", Py_True);
PyObject *kitty = PyUnicode_FromWideChar(stdlib, -1);
PyObject *kitty = PyUnicode_FromString(libpath);
if (kitty == NULL) { fprintf(stderr, "Failed to allocate python kitty lib object\n"); goto end; }
PyObject *runpy = PyImport_ImportModule("runpy");
if (runpy == NULL) { PyErr_Print(); fprintf(stderr, "Unable to import runpy\n"); Py_CLEAR(kitty); goto end; }
@@ -94,27 +94,34 @@ end:
if (Py_FinalizeEx() < 0) ret = 120;
return ret;
}
#else
static int run_embedded(const char* exe_dir_, int argc, wchar_t **argv) {
(void)exe_dir_;
#ifdef __APPLE__
static int run_embedded(const char* exe_dir_, const char *libpath, int argc, wchar_t **argv) {
(void)libpath;
wchar_t *exe_dir = Py_DecodeLocale(exe_dir_, NULL);
if (exe_dir == NULL) { fprintf(stderr, "Fatal error: cannot decode exe_dir\n"); return 1; }
if (exe_dir == NULL) { fprintf(stderr, "Fatal error: cannot decode exe_dir: %s\n", exe_dir_); return 1; }
set_bundle_exe_dir(exe_dir);
#ifdef FROM_SOURCE
PySys_AddXOption(L"kitty_from_source=1");
#endif
PyMem_RawFree(exe_dir);
return Py_Main(argc, argv);
}
#endif
// read_exe_path() {{{
#ifdef __APPLE__
static inline bool
read_exe_path(char *exe, size_t buf_sz) {
read_exe_path(char *exe, size_t buf_sz, bool *is_symlink) {
(void)buf_sz;
*is_symlink = false;
uint32_t size = PATH_MAX;
char apple[PATH_MAX+1] = {0};
if (_NSGetExecutablePath(apple, &size) != 0) { fprintf(stderr, "Failed to get path to executable\n"); return false; }
struct stat buf;
if (lstat(apple, &buf) == 0) {
*is_symlink = S_ISLNK(buf.st_mode);
}
if (!safe_realpath(apple, exe, buf_sz)) { fprintf(stderr, "realpath() failed on the executable's path\n"); return false; }
return true;
}
@@ -123,7 +130,8 @@ read_exe_path(char *exe, size_t buf_sz) {
#include <sys/sysctl.h>
static inline bool
read_exe_path(char *exe, size_t buf_sz) {
read_exe_path(char *exe, size_t buf_sz, bool *is_symlink) {
*is_symlink = false;
int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
size_t length = buf_sz;
int error = sysctl(name, 4, exe, &length, NULL, 0);
@@ -136,7 +144,8 @@ read_exe_path(char *exe, size_t buf_sz) {
#elif defined(__NetBSD__)
static inline bool
read_exe_path(char *exe, size_t buf_sz) {
read_exe_path(char *exe, size_t buf_sz, bool *is_symlink) {
*is_symlink = false;
if (!safe_realpath("/proc/curproc/exe", exe, buf_sz)) { fprintf(stderr, "Failed to read /proc/curproc/exe\n"); return false; }
return true;
}
@@ -144,30 +153,28 @@ read_exe_path(char *exe, size_t buf_sz) {
#else
static inline bool
read_exe_path(char *exe, size_t buf_sz) {
read_exe_path(char *exe, size_t buf_sz, bool *is_symlink) {
*is_symlink = false;
if (!safe_realpath("/proc/self/exe", exe, buf_sz)) { fprintf(stderr, "Failed to read /proc/self/exe\n"); return false; }
return true;
}
#endif
#endif // }}}
int main(int argc, char *argv[]) {
char exe[PATH_MAX+1] = {0};
if (!read_exe_path(exe, sizeof(exe))) return 1;
bool is_symlink = false;
if (!read_exe_path(exe, sizeof(exe), &is_symlink)) return 1;
#ifdef __APPLE__
// Cocoa has issues with bundle executables launched via symlinks
if (is_symlink) execv(exe, argv);
#endif
char *exe_dir = dirname(exe);
int num, num_args, i, ret=0;
char lib[PATH_MAX+1] = {0};
char *final_argv[MAX_ARGC + 1] = {0};
wchar_t *argvw[MAX_ARGC + 1] = {0};
#ifdef WITH_PROFILER
num = snprintf(lib, PATH_MAX, "%s%s", exe_dir, "/");
#else
#ifdef FOR_LAUNCHER
num = snprintf(lib, PATH_MAX, "%s%s", exe_dir, "/../Frameworks/kitty");
#else
num = snprintf(lib, PATH_MAX, "%s%s%s%s", exe_dir, "/../", LIB_DIR_NAME, "/kitty");
#endif
#endif
num = snprintf(lib, PATH_MAX, "%s/%s", exe_dir, KITTY_LIB_PATH);
if (num < 0 || num >= PATH_MAX) { fprintf(stderr, "Failed to create path to kitty lib\n"); return 1; }
final_argv[0] = exe;
@@ -187,7 +194,7 @@ int main(int argc, char *argv[]) {
ret = 1; goto end;
}
}
ret = run_embedded(exe_dir, num_args, argvw);
ret = run_embedded(exe_dir, lib, num_args, argvw);
end:
for (i = 0; i < num_args; i++) { if(argvw[i]) PyMem_RawFree(argvw[i]); }
return ret;