Skip to content

Commit

Permalink
Move libstdc++ path into LOADER_*_DEP_LIBS
Browse files Browse the repository at this point in the history
After adding `libstdc++` probing into the Julia loader [0], we
originally made the assumption that the `libstdc++` that is shipped with
`julia` would always be co-located with `libjulia.so` [1].  This is not
the case when building with `USE_SYSTEM_CSL=1`, however, where we
sequester system libraries in `usr/lib/julia`, even at build-time.

The path to `libstdc++.so` has already been getting altered when moving
from build-time to install time via `stringreplace` [2], but after
further thought, I decided that it would be better to just use the
pre-existing `LOADER_*_DEP_LIBS` mechanism to communicate to the loader
what the correct relative path to `libstdc++.so` is.  This also allows
the single `stringreplace` to update all of our "special" library paths.

[0] #46976
[1] https://github.com/JuliaLang/julia/pull/46976/files#diff-8c5c98f26f3f7aac8905a1074c5bec11a57e9b9c7c556791deac5a3b27cc096fR379
[2] https://github.com/JuliaLang/julia/blob/master/Makefile#L430
  • Loading branch information
staticfloat committed Jan 19, 2023
1 parent b540315 commit 0b21160
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 35 deletions.
21 changes: 17 additions & 4 deletions Make.inc
Original file line number Diff line number Diff line change
Expand Up @@ -1512,6 +1512,19 @@ LIBGCC_BUILD_DEPLIB := $(call dep_lib_path,$(build_libdir),$(build_shlibdir)/$(L
endif
LIBGCC_INSTALL_DEPLIB := $(call dep_lib_path,$(libdir),$(private_shlibdir)/$(LIBGCC_NAME))

# We only bother to define this on Linux, as that's the only platform that does libstdc++ probing
# On all other platforms, the LIBSTDCXX_*_DEPLIB variables will be empty.
ifeq ($(OS),Linux)
LIBSTDCXX_NAME := libstdc++.so.6
ifeq ($(USE_SYSTEM_CSL),1)
LIBSTDCXX_BUILD_DEPLIB := $(call dep_lib_path,$(build_libdir),$(build_private_shlibdir)/$(LIBSTDCXX_NAME))
else
LIBSTDCXX_BUILD_DEPLIB := $(call dep_lib_path,$(build_libdir),$(build_shlibdir)/$(LIBSTDCXX_NAME))
endif
LIBSTDCXX_INSTALL_DEPLIB := $(call dep_lib_path,$(libdir),$(private_shlibdir)/$(LIBSTDCXX_NAME))
endif


# USE_SYSTEM_LIBM and USE_SYSTEM_OPENLIBM causes it to get symlinked into build_private_shlibdir
ifeq ($(USE_SYSTEM_LIBM),1)
LIBM_BUILD_DEPLIB := $(call dep_lib_path,$(build_libdir),$(build_private_shlibdir)/$(LIBMNAME).$(SHLIB_EXT))
Expand All @@ -1534,10 +1547,10 @@ LIBM_INSTALL_DEPLIB := $(call dep_lib_path,$(libdir),$(private_shlibdir)/$(LIBMN
# That second point will no longer be true for most deps once they are placed within Artifacts directories.
# Note that we prefix `libjulia-codegen` and `libjulia-internal` with `@` to signify to the loader that it
# should not automatically dlopen() it in its loading loop.
LOADER_BUILD_DEP_LIBS = $(LIBGCC_BUILD_DEPLIB):$(LIBM_BUILD_DEPLIB):@$(LIBJULIAINTERNAL_BUILD_DEPLIB):@$(LIBJULIACODEGEN_BUILD_DEPLIB):
LOADER_DEBUG_BUILD_DEP_LIBS = $(LIBGCC_BUILD_DEPLIB):$(LIBM_BUILD_DEPLIB):@$(LIBJULIAINTERNAL_DEBUG_BUILD_DEPLIB):@$(LIBJULIACODEGEN_DEBUG_BUILD_DEPLIB):
LOADER_INSTALL_DEP_LIBS = $(LIBGCC_INSTALL_DEPLIB):$(LIBM_INSTALL_DEPLIB):@$(LIBJULIAINTERNAL_INSTALL_DEPLIB):@$(LIBJULIACODEGEN_INSTALL_DEPLIB):
LOADER_DEBUG_INSTALL_DEP_LIBS = $(LIBGCC_INSTALL_DEPLIB):$(LIBM_INSTALL_DEPLIB):@$(LIBJULIAINTERNAL_DEBUG_INSTALL_DEPLIB):@$(LIBJULIACODEGEN_DEBUG_INSTALL_DEPLIB):
LOADER_BUILD_DEP_LIBS = $(LIBGCC_BUILD_DEPLIB):$(LIBM_BUILD_DEPLIB):@$(LIBSTDCXX_BUILD_DEPLIB):@$(LIBJULIAINTERNAL_BUILD_DEPLIB):@$(LIBJULIACODEGEN_BUILD_DEPLIB):
LOADER_DEBUG_BUILD_DEP_LIBS = $(LIBGCC_BUILD_DEPLIB):$(LIBM_BUILD_DEPLIB):@$(LIBSTDCXX_BUILD_DEPLIB):@$(LIBJULIAINTERNAL_DEBUG_BUILD_DEPLIB):@$(LIBJULIACODEGEN_DEBUG_BUILD_DEPLIB):
LOADER_INSTALL_DEP_LIBS = $(LIBGCC_INSTALL_DEPLIB):$(LIBM_INSTALL_DEPLIB):@$(LIBSTDCXX_INSTALL_DEPLIB):@$(LIBJULIAINTERNAL_INSTALL_DEPLIB):@$(LIBJULIACODEGEN_INSTALL_DEPLIB):
LOADER_DEBUG_INSTALL_DEP_LIBS = $(LIBGCC_INSTALL_DEPLIB):$(LIBM_INSTALL_DEPLIB):@$(LIBSTDCXX_INSTALL_DEPLIB):@$(LIBJULIAINTERNAL_DEBUG_INSTALL_DEPLIB):@$(LIBJULIACODEGEN_DEBUG_INSTALL_DEPLIB):

# Colors for make
ifndef VERBOSE
Expand Down
6 changes: 0 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -412,12 +412,6 @@ ifeq ($(OS), Linux)
-$(PATCHELF) --set-rpath '$$ORIGIN' $(DESTDIR)$(private_shlibdir)/libLLVM.$(SHLIB_EXT)
endif

# Replace libstdc++ path, which is also moving from `lib` to `../lib/julia`.
ifeq ($(OS),Linux)
$(call stringreplace,$(DESTDIR)$(shlibdir)/libjulia.$(JL_MAJOR_MINOR_SHLIB_EXT),\*libstdc++\.so\.6$$,*$(call dep_lib_path,$(shlibdir),$(private_shlibdir)/libstdc++.so.6))
endif


ifneq ($(LOADER_BUILD_DEP_LIBS),$(LOADER_INSTALL_DEP_LIBS))
# Next, overwrite relative path to libjulia-internal in our loader if $$(LOADER_BUILD_DEP_LIBS) != $$(LOADER_INSTALL_DEP_LIBS)
ifeq ($(JULIA_BUILD_MODE),release)
Expand Down
72 changes: 47 additions & 25 deletions cli/loader_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,50 @@ __attribute__((constructor)) void jl_load_libjulia_internal(void) {

void *cxx_handle;

// We keep track of "special" libraries names (ones whose name is prefixed with `@`)
// which are libraries that we want to load in some special, custom way.
// The current list is:
// special_library_names = {
// libstdc++,
// libjulia-internal,
// libjulia-codegen,
// }
int special_idx = 0;
char * special_library_names[3] = {NULL};
while (1) {
// try to find next colon character; if we can't, break out
char * colon = strchr(curr_dep, ':');
if (colon == NULL)
break;

// If this library name starts with `@`, don't open it here (but mark it as special)
if (curr_dep[0] == '@') {
if (special_idx > sizeof(special_library_names)/sizeof(char *)) {
jl_loader_print_stderr("ERROR: Too many special library names specified, check LOADER_BUILD_DEP_LIBS and friends!\n");
exit(1);
}
special_library_names[special_idx] = curr_dep + 1;
special_idx += 1;

// Chop the string at the colon so it's a valid-ending-string
*colon = '\0';
}

// Skip to next dep
curr_dep = colon + 1;
}

// Assert that we have exactly the right number of special library names
if (special_idx != sizeof(special_library_names)/sizeof(char *)) {
jl_loader_print_stderr("ERROR: Too few special library names specified, check LOADER_BUILD_DEP_LIBS and friends!\n");
exit(1);
}

// Unpack our special library names. This is why ordering of library names matters.
char * bundled_libstdcxx_path = special_library_names[0];
libjulia_internal = load_library(special_library_names[1], lib_dir, 1);
void *libjulia_codegen = load_library(special_library_names[2], lib_dir, 0);

#if defined(_OS_LINUX_)
int do_probe = 1;
int done_probe = 0;
Expand All @@ -391,16 +435,10 @@ __attribute__((constructor)) void jl_load_libjulia_internal(void) {
}
}
if (!done_probe) {
const static char bundled_path[256] = "\0*libstdc++.so.6";
load_library(&bundled_path[2], lib_dir, 1);
load_library(bundled_libstdcxx_path, lib_dir, 1);
}
#endif

// We keep track of "special" libraries names (ones whose name is prefixed with `@`)
// which are libraries that we want to load in some special, custom way, such as
// `libjulia-internal` or `libjulia-codegen`.
int special_idx = 0;
char * special_library_names[2] = {NULL};
while (1) {
// try to find next colon character; if we can't, break out
char * colon = strchr(curr_dep, ':');
Expand All @@ -410,31 +448,15 @@ __attribute__((constructor)) void jl_load_libjulia_internal(void) {
// Chop the string at the colon so it's a valid-ending-string
*colon = '\0';

// If this library name starts with `@`, don't open it here (but mark it as special)
if (curr_dep[0] == '@') {
if (special_idx > sizeof(special_library_names)/sizeof(char *)) {
jl_loader_print_stderr("ERROR: Too many special library names specified, check LOADER_BUILD_DEP_LIBS and friends!\n");
exit(1);
}
special_library_names[special_idx] = curr_dep + 1;
special_idx += 1;
}
else {
// If this library name starts with `@`, don't open it here
if (curr_dep[0] != '@') {
load_library(curr_dep, lib_dir, 1);
}

// Skip ahead to next dependency
curr_dep = colon + 1;
}

if (special_idx != sizeof(special_library_names)/sizeof(char *)) {
jl_loader_print_stderr("ERROR: Too few special library names specified, check LOADER_BUILD_DEP_LIBS and friends!\n");
exit(1);
}

// Unpack our special library names. This is why ordering of library names matters.
libjulia_internal = load_library(special_library_names[0], lib_dir, 1);
void *libjulia_codegen = load_library(special_library_names[1], lib_dir, 0);
const char * const * codegen_func_names;
const char *codegen_liberr;
if (libjulia_codegen == NULL) {
Expand Down

0 comments on commit 0b21160

Please sign in to comment.