diff --git a/linux-launcher.c b/linux-launcher.c index 1e9daf3c8..69c994d7f 100644 --- a/linux-launcher.c +++ b/linux-launcher.c @@ -17,33 +17,51 @@ #else #include #endif +#include #define MIN(x, y) ((x) < (y)) ? (x) : (y) #define MAX_ARGC 1024 int main(int argc, char *argv[]) { - char exe[PATH_MAX+1] = {0}; - char lib[PATH_MAX+1] = {0}; - char *final_argv[MAX_ARGC + 1] = {0}; + int num, num_args, i, ret=0; + char exe[PATH_MAX+1] = {0}; + char lib[PATH_MAX+1] = {0}; + char *final_argv[MAX_ARGC + 1] = {0}; + wchar_t *argvw[MAX_ARGC + 1] = {0}; + #ifdef __APPLE__ - 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 1; } - if (realpath(apple, exe) == NULL) { fprintf(stderr, "realpath() failed on the executable's path\n"); return 1; } + 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 1; } + if (realpath(apple, exe) == NULL) { fprintf(stderr, "realpath() failed on the executable's path\n"); return 1; } #else - if (realpath("/proc/self/exe", exe) == NULL) { fprintf(stderr, "Failed to read /proc/self/exe\n"); return 1; } + if (realpath("/proc/self/exe", exe) == NULL) { fprintf(stderr, "Failed to read /proc/self/exe\n"); return 1; } #endif - char *exe_dir = dirname(exe); - int num = snprintf(lib, PATH_MAX, "%s%s", exe_dir, "/../lib/kitty"); - if (num < 0 || num >= PATH_MAX) { fprintf(stderr, "Failed to create path to /../lib/kitty\n"); return 1; } - final_argv[0] = "python3"; - final_argv[1] = lib; - for (int i = 1; i < argc && i + 1 <= MAX_ARGC; i++) { - final_argv[i+1] = argv[i]; - } - execvp(final_argv[0], final_argv); - fprintf(stderr, "Failed to run %s: %s\n", final_argv[0], strerror(errno)); - return 0; + + char *exe_dir = dirname(exe); + +#ifdef FOR_BUNDLE + num = snprintf(lib, PATH_MAX, "%s%s", exe_dir, "/../Frameworks/kitty"); +#else + num = snprintf(lib, PATH_MAX, "%s%s", exe_dir, "/../lib/kitty"); +#endif + + if (num < 0 || num >= PATH_MAX) { fprintf(stderr, "Failed to create path to /../lib/kitty\n"); return 1; } + final_argv[0] = exe; + final_argv[1] = lib; + for (i = 1, num_args=2; i < argc && i + 1 <= MAX_ARGC; i++) { + final_argv[i+1] = argv[i]; + num_args++; + } + for (i = 0; i < num_args; i++) { + argvw[i] = Py_DecodeLocale(final_argv[i], NULL); + if (argvw[i] == NULL) { + fprintf(stderr, "Fatal error: cannot decode argv[%d]\n", i); + goto end; + } + } + ret = Py_Main(num_args, argvw); +end: + for (i = 0; i < num_args; i++) { if(argvw[i]) PyMem_RawFree(argvw[i]); } + return ret; } - - diff --git a/setup.py b/setup.py index c000bfd2e..4d332c0e8 100755 --- a/setup.py +++ b/setup.py @@ -176,7 +176,7 @@ def compile_c_extension(module, incremental, sources, headers): def option_parser(): p = argparse.ArgumentParser() - p.add_argument('action', nargs='?', default='build', choices='build test linux-package'.split(), help='Action to perform (default is build)') + p.add_argument('action', nargs='?', default='build', choices='build test linux-package osx-bundle'.split(), help='Action to perform (default is build)') p.add_argument('--debug', default=False, action='store_true', help='Build extension modules with debugging symbols') p.add_argument('--asan', default=False, action='store_true', @@ -214,7 +214,7 @@ def safe_makedirs(path): pass -def package(args): # {{{ +def package(args, for_bundle=False): # {{{ ddir = args.prefix libdir = os.path.join(ddir, 'lib', 'kitty') if os.path.exists(libdir): @@ -239,8 +239,13 @@ def package(args): # {{{ os.chmod(path, 0o755 if f.endswith('.so') else 0o644) launcher_dir = os.path.join(ddir, 'bin') safe_makedirs(launcher_dir) - run_tool([cc, '-O3', 'linux-launcher.c', '-o', os.path.join(launcher_dir, 'kitty')]) - if not isosx: + cflags = '-O3'.split() + if for_bundle: + cflags.append('-DFOR_BUNDLE') + pylib = get_python_flags(cflags) + cmd = [cc] + cflags + ['linux-launcher.c', '-o', os.path.join(launcher_dir, 'kitty')] + pylib + run_tool(cmd) + if not isosx: # {{{ linux desktop gunk icdir = os.path.join(ddir, 'share', 'icons', 'hicolor', '256x256') safe_makedirs(icdir) shutil.copy2('logo/kitty.png', icdir) @@ -259,6 +264,16 @@ Exec=kitty Icon=kitty Categories=System; ''') + # }}} + + if for_bundle: # OS X bundle gunk {{{ + os.chdir(ddir) + os.mkdir('Contents') + os.chdir('Contents') + os.rename('../share', 'Resources') + os.rename('../bin', 'MacOS') + os.rename('../lib', 'Frameworks') + # }}} # }}} @@ -275,6 +290,9 @@ def main(): elif args.action == 'linux-package': build(args) package(args) + elif args.action == 'osx-bundle': + build(args) + package(args, for_bundle=True) if __name__ == '__main__':