diff --git a/doc/src/manual/embedding.md b/doc/src/manual/embedding.md index 64104771cd9cd..7fb40ba5bd649 100644 --- a/doc/src/manual/embedding.md +++ b/doc/src/manual/embedding.md @@ -54,7 +54,7 @@ linking against `libjulia`. The first thing that must be done before calling any other Julia C function is to initialize Julia. This is done by calling `jl_init`, which tries to automatically determine Julia's install location. If you need to specify a custom location, or specify which system -image to load, use `jl_init_with_image` instead. +image to load, use `jl_init_with_image_file` or `jl_init_with_image_handle` instead. The second statement in the test program evaluates a Julia statement using a call to `jl_eval_string`. diff --git a/src/init.c b/src/init.c index cf432a6bd6047..5a8a3eaf5ccf2 100644 --- a/src/init.c +++ b/src/init.c @@ -533,169 +533,6 @@ int jl_isabspath(const char *in) JL_NOTSAFEPOINT return 0; // relative path } -static char *absrealpath(const char *in, int nprefix) -{ // compute an absolute realpath location, so that chdir doesn't change the file reference - // ignores (copies directly over) nprefix characters at the start of abspath -#ifndef _OS_WINDOWS_ - char *out = realpath(in + nprefix, NULL); - if (out) { - if (nprefix > 0) { - size_t sz = strlen(out) + 1; - char *cpy = (char*)malloc_s(sz + nprefix); - memcpy(cpy, in, nprefix); - memcpy(cpy + nprefix, out, sz); - free(out); - out = cpy; - } - } - else { - size_t sz = strlen(in + nprefix) + 1; - if (in[nprefix] == PATHSEPSTRING[0]) { - out = (char*)malloc_s(sz + nprefix); - memcpy(out, in, sz + nprefix); - } - else { - size_t path_size = JL_PATH_MAX; - char *path = (char*)malloc_s(JL_PATH_MAX); - if (uv_cwd(path, &path_size)) { - jl_error("fatal error: unexpected error while retrieving current working directory"); - } - out = (char*)malloc_s(path_size + 1 + sz + nprefix); - memcpy(out, in, nprefix); - memcpy(out + nprefix, path, path_size); - out[nprefix + path_size] = PATHSEPSTRING[0]; - memcpy(out + nprefix + path_size + 1, in + nprefix, sz); - free(path); - } - } -#else - // GetFullPathName intentionally errors if given an empty string so manually insert `.` to invoke cwd - char *in2 = (char*)malloc_s(JL_PATH_MAX); - if (strlen(in) - nprefix == 0) { - memcpy(in2, in, nprefix); - in2[nprefix] = '.'; - in2[nprefix+1] = '\0'; - in = in2; - } - DWORD n = GetFullPathName(in + nprefix, 0, NULL, NULL); - if (n <= 0) { - jl_error("fatal error: jl_options.image_file path too long or GetFullPathName failed"); - } - char *out = (char*)malloc_s(n + nprefix); - DWORD m = GetFullPathName(in + nprefix, n, out + nprefix, NULL); - if (n != m + 1) { - jl_error("fatal error: jl_options.image_file path too long or GetFullPathName failed"); - } - memcpy(out, in, nprefix); - free(in2); -#endif - return out; -} - -// create an absolute-path copy of the input path format string -// formed as `joinpath(replace(pwd(), "%" => "%%"), in)` -// unless `in` starts with `%` -static const char *absformat(const char *in) -{ - if (in[0] == '%' || jl_isabspath(in)) - return in; - // get an escaped copy of cwd - size_t path_size = JL_PATH_MAX; - char path[JL_PATH_MAX]; - if (uv_cwd(path, &path_size)) { - jl_error("fatal error: unexpected error while retrieving current working directory"); - } - size_t sz = strlen(in) + 1; - size_t i, fmt_size = 0; - for (i = 0; i < path_size; i++) - fmt_size += (path[i] == '%' ? 2 : 1); - char *out = (char*)malloc_s(fmt_size + 1 + sz); - fmt_size = 0; - for (i = 0; i < path_size; i++) { // copy-replace pwd portion - char c = path[i]; - out[fmt_size++] = c; - if (c == '%') - out[fmt_size++] = '%'; - } - out[fmt_size++] = PATHSEPSTRING[0]; // path sep - memcpy(out + fmt_size, in, sz); // copy over format, including nul - return out; -} - -static void jl_resolve_sysimg_location(JL_IMAGE_SEARCH rel) -{ - // this function resolves the paths in jl_options to absolute file locations as needed - // and it replaces the pointers to `julia_bindir`, `julia_bin`, `image_file`, and output file paths - // it may fail, print an error, and exit(1) if any of these paths are longer than JL_PATH_MAX - // - // note: if you care about lost memory, you should call the appropriate `free()` function - // on the original pointer for each `char*` you've inserted into `jl_options`, after - // calling `julia_init()` - char *free_path = (char*)malloc_s(JL_PATH_MAX); - size_t path_size = JL_PATH_MAX; - if (uv_exepath(free_path, &path_size)) { - jl_error("fatal error: unexpected error while retrieving exepath"); - } - if (path_size >= JL_PATH_MAX) { - jl_error("fatal error: jl_options.julia_bin path too long"); - } - jl_options.julia_bin = (char*)malloc_s(path_size + 1); - memcpy((char*)jl_options.julia_bin, free_path, path_size); - ((char*)jl_options.julia_bin)[path_size] = '\0'; - if (!jl_options.julia_bindir) { - jl_options.julia_bindir = getenv("JULIA_BINDIR"); - if (!jl_options.julia_bindir) { - jl_options.julia_bindir = dirname(free_path); - } - } - if (jl_options.julia_bindir) - jl_options.julia_bindir = absrealpath(jl_options.julia_bindir, 0); - free(free_path); - free_path = NULL; - if (jl_options.image_file) { - if (rel == JL_IMAGE_JULIA_HOME && !jl_isabspath(jl_options.image_file)) { - // build time path, relative to JULIA_BINDIR - free_path = (char*)malloc_s(JL_PATH_MAX); - int n = snprintf(free_path, JL_PATH_MAX, "%s" PATHSEPSTRING "%s", - jl_options.julia_bindir, jl_options.image_file); - if (n >= JL_PATH_MAX || n < 0) { - jl_error("fatal error: jl_options.image_file path too long"); - } - jl_options.image_file = free_path; - } - if (jl_options.image_file) - jl_options.image_file = absrealpath(jl_options.image_file, 0); - if (free_path) { - free(free_path); - free_path = NULL; - } - } - if (jl_options.outputo) - jl_options.outputo = absrealpath(jl_options.outputo, 0); - if (jl_options.outputji) - jl_options.outputji = absrealpath(jl_options.outputji, 0); - if (jl_options.outputbc) - jl_options.outputbc = absrealpath(jl_options.outputbc, 0); - if (jl_options.outputasm) - jl_options.outputasm = absrealpath(jl_options.outputasm, 0); - if (jl_options.machine_file) - jl_options.machine_file = absrealpath(jl_options.machine_file, 0); - if (jl_options.output_code_coverage) - jl_options.output_code_coverage = absformat(jl_options.output_code_coverage); - if (jl_options.tracked_path) - jl_options.tracked_path = absrealpath(jl_options.tracked_path, 0); - - const char **cmdp = jl_options.cmds; - if (cmdp) { - for (; *cmdp; cmdp++) { - const char *cmd = *cmdp; - if (cmd[0] == 'L') { - *cmdp = absrealpath(cmd, 1); - } - } - } -} - JL_DLLEXPORT int jl_is_file_tracked(jl_sym_t *path) { const char* path_ = jl_symbol_name(path); @@ -721,8 +558,85 @@ static void restore_fp_env(void) jl_error("Failed to configure floating point environment"); } } +static NOINLINE void _finish_jl_init_(jl_image_buf_t sysimage, jl_ptls_t ptls, jl_task_t *ct) +{ + JL_TIMING(JULIA_INIT, JULIA_INIT); + + if (sysimage.kind == JL_IMAGE_KIND_SO) + jl_gc_notify_image_load(sysimage.data, sysimage.size); + + if (jl_options.cpu_target == NULL) + jl_options.cpu_target = "native"; + + // Parse image, perform relocations, and init JIT targets, etc. + jl_image_t parsed_image = jl_init_processor_sysimg(sysimage, jl_options.cpu_target); + + jl_init_codegen(); + jl_init_common_symbols(); + + if (sysimage.kind != JL_IMAGE_KIND_NONE) { + // Load the .ji or .so sysimage + jl_restore_system_image(&parsed_image, sysimage); + } else { + // No sysimage provided, init a minimal environment + jl_init_types(); + jl_global_roots_list = (jl_genericmemory_t*)jl_an_empty_memory_any; + jl_global_roots_keyset = (jl_genericmemory_t*)jl_an_empty_memory_any; + } + + jl_init_flisp(); + jl_init_serializer(); + + if (sysimage.kind == JL_IMAGE_KIND_NONE) { + jl_top_module = jl_core_module; + jl_init_intrinsic_functions(); + jl_init_primitives(); + jl_init_main_module(); + jl_load(jl_core_module, "boot.jl"); + jl_current_task->world_age = jl_atomic_load_acquire(&jl_world_counter); + post_boot_hooks(); + } + + if (jl_base_module == NULL) { + // nthreads > 1 requires code in Base + jl_atomic_store_relaxed(&jl_n_threads, 1); + jl_n_markthreads = 0; + jl_n_sweepthreads = 0; + jl_n_gcthreads = 0; + jl_n_threads_per_pool[JL_THREADPOOL_ID_INTERACTIVE] = 0; + jl_n_threads_per_pool[JL_THREADPOOL_ID_DEFAULT] = 1; + } else { + jl_current_task->world_age = jl_atomic_load_acquire(&jl_world_counter); + post_image_load_hooks(); + } + jl_start_threads(); + jl_start_gc_threads(); + uv_barrier_wait(&thread_init_done); + + jl_gc_enable(1); + + if ((sysimage.kind != JL_IMAGE_KIND_NONE) && + (!jl_generating_output() || jl_options.incremental) && jl_module_init_order) { + jl_array_t *init_order = jl_module_init_order; + JL_GC_PUSH1(&init_order); + jl_module_init_order = NULL; + int i, l = jl_array_nrows(init_order); + for (i = 0; i < l; i++) { + jl_value_t *mod = jl_array_ptr_ref(init_order, i); + jl_module_run_initializer((jl_module_t*)mod); + } + JL_GC_POP(); + } + + if (jl_options.trim) { + jl_entrypoint_mis = (arraylist_t *)malloc_s(sizeof(arraylist_t)); + arraylist_new(jl_entrypoint_mis, 0); + } + + if (jl_options.handle_signals == JL_OPTIONS_HANDLE_SIGNALS_ON) + jl_install_sigint_handler(); +} -static NOINLINE void _finish_julia_init(JL_IMAGE_SEARCH rel, jl_ptls_t ptls, jl_task_t *ct); JL_DLLEXPORT int jl_default_debug_info_kind; JL_DLLEXPORT jl_cgparams_t jl_default_cgparams = { @@ -750,12 +664,12 @@ static void init_global_mutexes(void) { JL_MUTEX_INIT(&profile_show_peek_cond_lock, "profile_show_peek_cond_lock"); } -JL_DLLEXPORT void julia_init(JL_IMAGE_SEARCH rel) +JL_DLLEXPORT void jl_init_(jl_image_buf_t sysimage) { // initialize many things, in no particular order // but generally running from simple platform things to optional // configuration features - jl_init_timing(); + // Make sure we finalize the tls callback before starting any threads. (void)jl_get_pgcstack(); @@ -860,96 +774,7 @@ JL_DLLEXPORT void julia_init(JL_IMAGE_SEARCH rel) jl_task_t *ct = jl_init_root_task(ptls, stack_lo, stack_hi); #pragma GCC diagnostic pop JL_GC_PROMISE_ROOTED(ct); - _finish_julia_init(rel, ptls, ct); -} - -static NOINLINE void _finish_julia_init(JL_IMAGE_SEARCH rel, jl_ptls_t ptls, jl_task_t *ct) -{ - JL_TIMING(JULIA_INIT, JULIA_INIT); - jl_resolve_sysimg_location(rel); - - // loads sysimg if available, and conditionally sets jl_options.cpu_target - jl_image_buf_t sysimage = { JL_IMAGE_KIND_NONE }; - if (rel == JL_IMAGE_IN_MEMORY) { - sysimage = jl_set_sysimg_so(jl_exe_handle); - jl_options.image_file = jl_options.julia_bin; - } - else if (jl_options.image_file) - sysimage = jl_preload_sysimg(jl_options.image_file); - - if (sysimage.kind == JL_IMAGE_KIND_SO) - jl_gc_notify_image_load(sysimage.data, sysimage.size); - - if (jl_options.cpu_target == NULL) - jl_options.cpu_target = "native"; - - // Parse image, perform relocations, and init JIT targets, etc. - jl_image_t parsed_image = jl_init_processor_sysimg(sysimage, jl_options.cpu_target); - - jl_init_codegen(); - jl_init_common_symbols(); - - if (sysimage.kind != JL_IMAGE_KIND_NONE) { - // Load the .ji or .so sysimage - jl_restore_system_image(&parsed_image, sysimage); - } else { - // No sysimage provided, init a minimal environment - jl_init_types(); - jl_global_roots_list = (jl_genericmemory_t*)jl_an_empty_memory_any; - jl_global_roots_keyset = (jl_genericmemory_t*)jl_an_empty_memory_any; - } - - jl_init_flisp(); - jl_init_serializer(); - - if (sysimage.kind == JL_IMAGE_KIND_NONE) { - jl_top_module = jl_core_module; - jl_init_intrinsic_functions(); - jl_init_primitives(); - jl_init_main_module(); - jl_load(jl_core_module, "boot.jl"); - jl_current_task->world_age = jl_atomic_load_acquire(&jl_world_counter); - post_boot_hooks(); - } - - if (jl_base_module == NULL) { - // nthreads > 1 requires code in Base - jl_atomic_store_relaxed(&jl_n_threads, 1); - jl_n_markthreads = 0; - jl_n_sweepthreads = 0; - jl_n_gcthreads = 0; - jl_n_threads_per_pool[JL_THREADPOOL_ID_INTERACTIVE] = 0; - jl_n_threads_per_pool[JL_THREADPOOL_ID_DEFAULT] = 1; - } else { - jl_current_task->world_age = jl_atomic_load_acquire(&jl_world_counter); - post_image_load_hooks(); - } - jl_start_threads(); - jl_start_gc_threads(); - uv_barrier_wait(&thread_init_done); - - jl_gc_enable(1); - - if ((sysimage.kind != JL_IMAGE_KIND_NONE) && - (!jl_generating_output() || jl_options.incremental) && jl_module_init_order) { - jl_array_t *init_order = jl_module_init_order; - JL_GC_PUSH1(&init_order); - jl_module_init_order = NULL; - int i, l = jl_array_nrows(init_order); - for (i = 0; i < l; i++) { - jl_value_t *mod = jl_array_ptr_ref(init_order, i); - jl_module_run_initializer((jl_module_t*)mod); - } - JL_GC_POP(); - } - - if (jl_options.trim) { - jl_entrypoint_mis = (arraylist_t *)malloc_s(sizeof(arraylist_t)); - arraylist_new(jl_entrypoint_mis, 0); - } - - if (jl_options.handle_signals == JL_OPTIONS_HANDLE_SIGNALS_ON) - jl_install_sigint_handler(); + _finish_jl_init_(sysimage, ptls, ct); } #ifdef __cplusplus diff --git a/src/jl_exported_funcs.inc b/src/jl_exported_funcs.inc index 64dcb2278d240..cdf280c97db6d 100644 --- a/src/jl_exported_funcs.inc +++ b/src/jl_exported_funcs.inc @@ -235,9 +235,11 @@ XX(jl_hrtime) \ XX(jl_idtable_rehash) \ XX(jl_init) \ + XX(jl_init_) \ XX(jl_init_options) \ XX(jl_init_restored_module) \ - XX(jl_init_with_image) \ + XX(jl_init_with_image_file) \ + XX(jl_init_with_image_handle) \ XX(jl_install_sigint_handler) \ XX(jl_instantiate_type_in_env) \ XX(jl_instantiate_unionall) \ diff --git a/src/jlapi.c b/src/jlapi.c index 6ef0dd17befed..47d5b84fa5606 100644 --- a/src/jlapi.c +++ b/src/jlapi.c @@ -26,11 +26,13 @@ extern "C" { #include #endif +static void jl_resolve_sysimg_location(JL_IMAGE_SEARCH rel, const char* julia_bindir); + /** * @brief Check if Julia is already initialized. * - * Determine if Julia has been previously initialized - * via `jl_init` or `jl_init_with_image`. + * Determine if Julia has been previously initialized via `jl_init` or + * `jl_init_with_image_file` or `jl_init_with_image_handle`. * * @return Returns 1 if Julia is initialized, 0 otherwise. */ @@ -68,6 +70,20 @@ JL_DLLEXPORT void jl_set_ARGS(int argc, char **argv) } } +JL_DLLEXPORT void jl_init_with_image_handle(void *handle) { + if (jl_is_initialized()) + return; + + const char *image_path = jl_pathname_for_handle(handle); + jl_options.image_file = image_path; + + jl_resolve_sysimg_location(JL_IMAGE_JULIA_HOME, NULL); + jl_image_buf_t sysimage = jl_set_sysimg_so(handle); + + jl_init_(sysimage); + + jl_exception_clear(); +} /** * @brief Initialize Julia with a specified system image file. * @@ -82,28 +98,21 @@ JL_DLLEXPORT void jl_set_ARGS(int argc, char **argv) * @param image_path The path of a system image file (*.so). Interpreted as relative to julia_bindir * or the default Julia home directory if not an absolute path. */ -JL_DLLEXPORT void jl_init_with_image(const char *julia_bindir, - const char *image_path) +JL_DLLEXPORT void jl_init_with_image_file(const char *julia_bindir, + const char *image_path) { if (jl_is_initialized()) return; - libsupport_init(); - if (julia_bindir) { - jl_options.julia_bindir = julia_bindir; - } else { -#ifdef _OS_WINDOWS_ - jl_options.julia_bindir = strdup(jl_get_libdir()); -#else - int written = asprintf((char**)&jl_options.julia_bindir, "%s" PATHSEPSTRING ".." PATHSEPSTRING "%s", jl_get_libdir(), "bin"); - if (written < 0) - abort(); // unexpected: memory allocation failed -#endif - } if (image_path != NULL) jl_options.image_file = image_path; else jl_options.image_file = jl_get_default_sysimg_path(); - julia_init(JL_IMAGE_JULIA_HOME); + + jl_resolve_sysimg_location(JL_IMAGE_JULIA_HOME, julia_bindir); + jl_image_buf_t sysimage = jl_preload_sysimg(jl_options.image_file); + + jl_init_(sysimage); + jl_exception_clear(); } @@ -115,7 +124,7 @@ JL_DLLEXPORT void jl_init_with_image(const char *julia_bindir, */ JL_DLLEXPORT void jl_init(void) { - jl_init_with_image(NULL, jl_get_default_sysimg_path()); + jl_init_with_image_file(NULL, jl_get_default_sysimg_path()); } static void _jl_exception_clear(jl_task_t *ct) JL_NOTSAFEPOINT @@ -1101,7 +1110,14 @@ JL_DLLEXPORT int jl_repl_entrypoint(int argc, char *argv[]) jl_error("Failed to self-execute"); } - julia_init(jl_options.image_file_specified ? JL_IMAGE_CWD : JL_IMAGE_JULIA_HOME); + JL_IMAGE_SEARCH rel = jl_options.image_file_specified ? JL_IMAGE_CWD : JL_IMAGE_JULIA_HOME; + jl_resolve_sysimg_location(rel, NULL); + jl_image_buf_t sysimage = { JL_IMAGE_KIND_NONE }; + if (jl_options.image_file) + sysimage = jl_preload_sysimg(jl_options.image_file); + + jl_init_(sysimage); + if (lisp_prompt) { jl_current_task->world_age = jl_get_world_counter(); jl_lisp_prompt(); @@ -1112,6 +1128,180 @@ JL_DLLEXPORT int jl_repl_entrypoint(int argc, char *argv[]) return ret; } +// create an absolute-path copy of the input path format string +// formed as `joinpath(replace(pwd(), "%" => "%%"), in)` +// unless `in` starts with `%` +static const char *absformat(const char *in) +{ + if (in[0] == '%' || jl_isabspath(in)) + return in; + // get an escaped copy of cwd + size_t path_size = JL_PATH_MAX; + char path[JL_PATH_MAX]; + if (uv_cwd(path, &path_size)) { + jl_error("fatal error: unexpected error while retrieving current working directory"); + } + size_t sz = strlen(in) + 1; + size_t i, fmt_size = 0; + for (i = 0; i < path_size; i++) + fmt_size += (path[i] == '%' ? 2 : 1); + char *out = (char*)malloc_s(fmt_size + 1 + sz); + fmt_size = 0; + for (i = 0; i < path_size; i++) { // copy-replace pwd portion + char c = path[i]; + out[fmt_size++] = c; + if (c == '%') + out[fmt_size++] = '%'; + } + out[fmt_size++] = PATHSEPSTRING[0]; // path sep + memcpy(out + fmt_size, in, sz); // copy over format, including nul + return out; +} + +static char *absrealpath(const char *in, int nprefix) +{ // compute an absolute realpath location, so that chdir doesn't change the file reference + // ignores (copies directly over) nprefix characters at the start of abspath +#ifndef _OS_WINDOWS_ + char *out = realpath(in + nprefix, NULL); + if (out) { + if (nprefix > 0) { + size_t sz = strlen(out) + 1; + char *cpy = (char*)malloc_s(sz + nprefix); + memcpy(cpy, in, nprefix); + memcpy(cpy + nprefix, out, sz); + free(out); + out = cpy; + } + } + else { + size_t sz = strlen(in + nprefix) + 1; + if (in[nprefix] == PATHSEPSTRING[0]) { + out = (char*)malloc_s(sz + nprefix); + memcpy(out, in, sz + nprefix); + } + else { + size_t path_size = JL_PATH_MAX; + char *path = (char*)malloc_s(JL_PATH_MAX); + if (uv_cwd(path, &path_size)) { + jl_error("fatal error: unexpected error while retrieving current working directory"); + } + out = (char*)malloc_s(path_size + 1 + sz + nprefix); + memcpy(out, in, nprefix); + memcpy(out + nprefix, path, path_size); + out[nprefix + path_size] = PATHSEPSTRING[0]; + memcpy(out + nprefix + path_size + 1, in + nprefix, sz); + free(path); + } + } +#else + // GetFullPathName intentionally errors if given an empty string so manually insert `.` to invoke cwd + char *in2 = (char*)malloc_s(JL_PATH_MAX); + if (strlen(in) - nprefix == 0) { + memcpy(in2, in, nprefix); + in2[nprefix] = '.'; + in2[nprefix+1] = '\0'; + in = in2; + } + DWORD n = GetFullPathName(in + nprefix, 0, NULL, NULL); + if (n <= 0) { + jl_error("fatal error: jl_options.image_file path too long or GetFullPathName failed"); + } + char *out = (char*)malloc_s(n + nprefix); + DWORD m = GetFullPathName(in + nprefix, n, out + nprefix, NULL); + if (n != m + 1) { + jl_error("fatal error: jl_options.image_file path too long or GetFullPathName failed"); + } + memcpy(out, in, nprefix); + free(in2); +#endif + return out; +} + +static void jl_resolve_sysimg_location(JL_IMAGE_SEARCH rel, const char* julia_bindir) +{ + libsupport_init(); + jl_init_timing(); + + // this function resolves the paths in jl_options to absolute file locations as needed + // and it replaces the pointers to `julia_bindir`, `julia_bin`, `image_file`, and output file paths + // it may fail, print an error, and exit(1) if any of these paths are longer than JL_PATH_MAX + // + // note: if you care about lost memory, you should call the appropriate `free()` function + // on the original pointer for each `char*` you've inserted into `jl_options`, after + // calling `jl_init_()` + char *free_path = (char*)malloc_s(JL_PATH_MAX); + size_t path_size = JL_PATH_MAX; + if (uv_exepath(free_path, &path_size)) { + jl_error("fatal error: unexpected error while retrieving exepath"); + } + if (path_size >= JL_PATH_MAX) { + jl_error("fatal error: jl_options.julia_bin path too long"); + } + jl_options.julia_bin = (char*)malloc_s(path_size + 1); + memcpy((char*)jl_options.julia_bin, free_path, path_size); + ((char*)jl_options.julia_bin)[path_size] = '\0'; + if (julia_bindir == NULL) { + jl_options.julia_bindir = getenv("JULIA_BINDIR"); + if (!jl_options.julia_bindir) { +#ifdef _OS_WINDOWS_ + jl_options.julia_bindir = strdup(jl_get_libdir()); +#else + int written = asprintf((char**)&jl_options.julia_bindir, "%s" PATHSEPSTRING ".." PATHSEPSTRING "%s", jl_get_libdir(), "bin"); + if (written < 0) + abort(); // unexpected: memory allocation failed +#endif + } + } else { + jl_options.julia_bindir = julia_bindir; + } + if (jl_options.julia_bindir) + jl_options.julia_bindir = absrealpath(jl_options.julia_bindir, 0); + free(free_path); + free_path = NULL; + if (jl_options.image_file) { + if (rel == JL_IMAGE_JULIA_HOME && !jl_isabspath(jl_options.image_file)) { + // build time path, relative to JULIA_BINDIR + free_path = (char*)malloc_s(JL_PATH_MAX); + int n = snprintf(free_path, JL_PATH_MAX, "%s" PATHSEPSTRING "%s", + jl_options.julia_bindir, jl_options.image_file); + if (n >= JL_PATH_MAX || n < 0) { + jl_error("fatal error: jl_options.image_file path too long"); + } + jl_options.image_file = free_path; + } + if (jl_options.image_file) + jl_options.image_file = absrealpath(jl_options.image_file, 0); + if (free_path) { + free(free_path); + free_path = NULL; + } + } + if (jl_options.outputo) + jl_options.outputo = absrealpath(jl_options.outputo, 0); + if (jl_options.outputji) + jl_options.outputji = absrealpath(jl_options.outputji, 0); + if (jl_options.outputbc) + jl_options.outputbc = absrealpath(jl_options.outputbc, 0); + if (jl_options.outputasm) + jl_options.outputasm = absrealpath(jl_options.outputasm, 0); + if (jl_options.machine_file) + jl_options.machine_file = absrealpath(jl_options.machine_file, 0); + if (jl_options.output_code_coverage) + jl_options.output_code_coverage = absformat(jl_options.output_code_coverage); + if (jl_options.tracked_path) + jl_options.tracked_path = absrealpath(jl_options.tracked_path, 0); + + const char **cmdp = jl_options.cmds; + if (cmdp) { + for (; *cmdp; cmdp++) { + const char *cmd = *cmdp; + if (cmd[0] == 'L') { + *cmdp = absrealpath(cmd, 1); + } + } + } +} + #ifdef __cplusplus } #endif diff --git a/src/julia.h b/src/julia.h index faad02c0aa50c..7f7362b9d4a9a 100644 --- a/src/julia.h +++ b/src/julia.h @@ -2223,10 +2223,10 @@ struct _jl_image_t; typedef struct _jl_image_t jl_image_t; JL_DLLIMPORT const char *jl_get_libdir(void); -JL_DLLEXPORT void julia_init(JL_IMAGE_SEARCH rel); JL_DLLEXPORT void jl_init(void); -JL_DLLEXPORT void jl_init_with_image(const char *julia_bindir, - const char *image_path); +JL_DLLEXPORT void jl_init_with_image_file(const char *julia_bindir, + const char *image_path); +JL_DLLEXPORT void jl_init_with_image_handle(void *handle); JL_DLLEXPORT const char *jl_get_default_sysimg_path(void); JL_DLLEXPORT int jl_is_initialized(void); JL_DLLEXPORT void jl_atexit_hook(int status); diff --git a/src/julia_internal.h b/src/julia_internal.h index b588f84d05319..573ccb3306bd0 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -196,6 +196,7 @@ void JL_UV_LOCK(void); extern _Atomic(unsigned) _threadedregion; extern _Atomic(uint16_t) io_loop_tid; +JL_DLLEXPORT void jl_init_(jl_image_buf_t sysimage); JL_DLLEXPORT void jl_enter_threaded_region(void); JL_DLLEXPORT void jl_exit_threaded_region(void); int jl_running_under_rr(int recheck) JL_NOTSAFEPOINT; diff --git a/src/threading.c b/src/threading.c index f01db388f4cc3..4256115214fc2 100644 --- a/src/threading.c +++ b/src/threading.c @@ -461,9 +461,7 @@ JL_DLLEXPORT jl_gcframe_t **jl_autoinit_and_adopt_thread(void) " (this should not happen, please file a bug report)\n"); exit(1); } - const char *image_path = jl_pathname_for_handle(handle); - jl_enter_threaded_region(); // This should maybe be behind a lock, but it's harmless if done twice - jl_init_with_image(NULL, image_path); + jl_init_with_image_handle(handle); return &jl_get_current_task()->gcstack; } diff --git a/test/trimming/init.c b/test/trimming/init.c index ea1b02f8e5c8f..889d71d47d540 100644 --- a/test/trimming/init.c +++ b/test/trimming/init.c @@ -1,9 +1,11 @@ +#define _GNU_SOURCE +#include #include __attribute__((constructor)) void static_init(void) { if (jl_is_initialized()) return; - julia_init(JL_IMAGE_IN_MEMORY); + jl_init_with_image_handle((void *)RTLD_DEFAULT); jl_exception_clear(); }