From 5ccec1f7248dfa3dda91b003c6fb4bbfad01da0f Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Fri, 10 May 2024 10:31:47 +0800 Subject: [PATCH] Add support for BRIEFCASE_DEBUG. --- cookiecutter.json | 1 + .../src/bootstrap/main.c | 53 ++++++++++++------- 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/cookiecutter.json b/cookiecutter.json index c47e6c8..7c171ca 100644 --- a/cookiecutter.json +++ b/cookiecutter.json @@ -8,6 +8,7 @@ "bundle_identifier": "{{ cookiecutter.bundle }}.{{ cookiecutter.app_name|replace('_', '-') }}", "url": "https://example.com", "description": "Short description of app", + "console_app": false, "flatpak_runtime": "org.freedesktop.Platform", "flatpak_runtime_version": "21.08", "flatpak_sdk": "org.freedesktop.Sdk", diff --git a/{{ cookiecutter.format }}/src/bootstrap/main.c b/{{ cookiecutter.format }}/src/bootstrap/main.c index 2767f4e..48aa5a7 100644 --- a/{{ cookiecutter.format }}/src/bootstrap/main.c +++ b/{{ cookiecutter.format }}/src/bootstrap/main.c @@ -6,6 +6,11 @@ #include #include +// A global indicator of the debug level +char *debug_mode; + +void debug_log(const char *format, ...); + int main(int argc, char *argv[]) { int ret = 0; PyStatus status; @@ -25,6 +30,9 @@ int main(int argc, char *argv[]) { PyObject *exc_traceback; PyObject *systemExit_code; + // Set the global debug state based on the runtime environment + debug_mode = getenv("BRIEFCASE_DEBUG"); + // Generate an isolated Python configuration. PyPreConfig_InitIsolatedConfig(&preconfig); PyConfig_InitIsolatedConfig(&config); @@ -41,7 +49,7 @@ int main(int argc, char *argv[]) { // Isolated apps need to set the full PYTHONPATH manually. config.module_search_paths_set = 1; - printf("Pre-initializing Python runtime...\n"); + debug_log("Pre-initializing Python runtime...\n"); status = Py_PreInitialize(&preconfig); if (PyStatus_Exception(status)) { // crash_dialog("Unable to pre-initialize Python interpreter: %s", status.err_msg, nil]); @@ -51,7 +59,7 @@ int main(int argc, char *argv[]) { // Set the home for the Python interpreter python_home = "/app"; - printf("PYTHONHOME: %s\n", python_home); + debug_log("PYTHONHOME: %s\n", python_home); wtmp_str = Py_DecodeLocale(python_home, NULL); status = PyConfig_SetString(&config, &config.home, wtmp_str); if (PyStatus_Exception(status)) { @@ -62,6 +70,7 @@ int main(int argc, char *argv[]) { PyMem_RawFree(wtmp_str); // Set the executable to match the known path of the app binary in the flatpak. + debug_log("config.executable: /app/bin/{{ cookiecutter.app_name }}\n"); status = PyConfig_SetBytesString(&config, &config.executable, "/app/bin/{{ cookiecutter.app_name }}"); if (PyStatus_Exception(status)) { // crash_dialog("Unable to set executable name: %s", status.err_msg); @@ -77,6 +86,7 @@ int main(int argc, char *argv[]) { if (app_module_name == NULL) { app_module_name = "{{ cookiecutter.module_name }}"; } + debug_log("config.run_module: %s\n", app_module_name); status = PyConfig_SetBytesString(&config, &config.run_module, app_module_name); if (PyStatus_Exception(status)) { // crash_dialog("Unable to set app module name: %s", status.err_msg); @@ -93,10 +103,10 @@ int main(int argc, char *argv[]) { } // Set the full module path. This includes the stdlib, site-packages, and app code. - printf("PYTHONPATH:\n"); + debug_log("PYTHONPATH:\n"); // // The .zip form of the stdlib path = "/app/lib/python{{ ''.join(cookiecutter.python_version.split('.')[:2]) }}.zip"; - printf("- %s\n", path); + debug_log("- %s\n", path); wtmp_str = Py_DecodeLocale(path, NULL); status = PyWideStringList_Append(&config.module_search_paths, wtmp_str); if (PyStatus_Exception(status)) { @@ -108,7 +118,7 @@ int main(int argc, char *argv[]) { // The unpacked form of the stdlib path = "/app/lib/python{{ '.'.join(cookiecutter.python_version.split('.')[:2]) }}"; - printf("- %s\n", path); + debug_log("- %s\n", path); wtmp_str = Py_DecodeLocale(path, NULL); status = PyWideStringList_Append(&config.module_search_paths, wtmp_str); if (PyStatus_Exception(status)) { @@ -120,7 +130,7 @@ int main(int argc, char *argv[]) { // Add the stdlib binary modules path path = "/app/lib/python{{ '.'.join(cookiecutter.python_version.split('.')[:2]) }}/lib-dynload"; - printf("- %s\n", path); + debug_log("- %s\n", path); wtmp_str = Py_DecodeLocale(path, NULL); status = PyWideStringList_Append(&config.module_search_paths, wtmp_str); if (PyStatus_Exception(status)) { @@ -132,7 +142,7 @@ int main(int argc, char *argv[]) { // Add the app_packages path path = "/app/briefcase/app_packages"; - printf("- %s\n", path); + debug_log("- %s\n", path); wtmp_str = Py_DecodeLocale(path, NULL); status = PyWideStringList_Append(&config.module_search_paths, wtmp_str); if (PyStatus_Exception(status)) { @@ -144,7 +154,7 @@ int main(int argc, char *argv[]) { // Add the app path path = "/app/briefcase/app"; - printf("- %s\n", path); + debug_log("- %s\n", path); wtmp_str = Py_DecodeLocale(path, NULL); status = PyWideStringList_Append(&config.module_search_paths, wtmp_str); if (PyStatus_Exception(status)) { @@ -154,7 +164,7 @@ int main(int argc, char *argv[]) { } PyMem_RawFree(wtmp_str); - printf("Configure argc/argv...\n"); + debug_log("Configure argc/argv...\n"); status = PyConfig_SetBytesArgv(&config, argc, argv); if (PyStatus_Exception(status)) { // crash_dialog("Unable to configured argc/argv: %s", status.err_msg); @@ -162,7 +172,7 @@ int main(int argc, char *argv[]) { Py_ExitStatusException(status); } - printf("Initializing Python runtime...\n"); + debug_log("Initializing Python runtime...\n"); status = Py_InitializeFromConfig(&config); if (PyStatus_Exception(status)) { // crash_dialog("Unable to initialize Python interpreter: %s", status.err_msg); @@ -177,7 +187,7 @@ int main(int argc, char *argv[]) { // pymain_run_module() method); we need to re-implement it // because we need to be able to inspect the error state of // the interpreter, not just the return code of the module. - printf("Running app module: %s\n", app_module_name); + debug_log("Running app module: %s\n", app_module_name); module = PyImport_ImportModule("runpy"); if (module == NULL) { // crash_dialog(@"Could not import runpy module"); @@ -204,7 +214,7 @@ int main(int argc, char *argv[]) { // Print a separator to differentiate Python startup logs from app logs, // then flush stdout/stderr to ensure all startup logs have been output. - printf("---------------------------------------------------------------------------\n"); + debug_log("---------------------------------------------------------------------------\n"); fflush(stdout); fflush(stderr); @@ -224,7 +234,7 @@ int main(int argc, char *argv[]) { if (PyErr_GivenExceptionMatches(exc_value, PyExc_SystemExit)) { systemExit_code = PyObject_GetAttrString(exc_value, "code"); if (systemExit_code == NULL) { - printf("Could not determine exit code\n"); + debug_log("Could not determine exit code\n"); ret = -10; } else { @@ -232,10 +242,8 @@ int main(int argc, char *argv[]) { } } else { ret = -6; - } - - if (ret != 0) { - printf("Application quit abnormally (Exit code %d)!\n", ret); + printf("---------------------------------------------------------------------------\n"); + printf("Application quit abnormally!\n"); // Restore the error state of the interpreter. PyErr_Restore(exc_type, exc_value, exc_traceback); @@ -243,8 +251,6 @@ int main(int argc, char *argv[]) { // Print exception to stderr. // In case of SystemExit, this will call exit() PyErr_Print(); - - exit(ret); } } @@ -252,3 +258,12 @@ int main(int argc, char *argv[]) { return ret; } + +void debug_log(const char *format, ...) { + if (debug_mode) { + va_list args; + va_start(args, format); + vprintf(format, args); + va_end(args); + } +}