From 6d400e4f205db5e010248f1ecf26f90474fd4880 Mon Sep 17 00:00:00 2001 From: Cody Tapscott <84105208+topolarity@users.noreply.github.com> Date: Thu, 29 Jun 2023 12:23:36 -0400 Subject: [PATCH] Makefile: Add support for symbol versioning (ON by default) (#49012) This enables symbol versioning by default, with the version string `JL_LIBJULIA_1.10` (the version suffix is the SOMAJOR in general). This will configure the linker to assign the specified version string to all Julia-exported symbols. As part of this change, the SOMAJOR has also been changed to be MAJOR.MINOR instead of just MAJOR. This is required to allow multiple minor releases of libjulia to live side-by-side in the same process. `SYMBOL_VERSION_SUFFIX` is provided to allow appending an additional unique "salt" to SOMAJOR, which can be helpful for creating template binaries that will be "version-stamped" after distribution. Correctly compute `LLVM_SHLIB_SYMBOL_VERSION` using `llvm-config`, so USE_SYSTEM_LLVM should continue to work. --- .gitignore | 1 + Make.inc | 24 +++++++++++++----------- cli/Makefile | 16 ++++++++++++---- cli/julia.expmap.in | 1 + deps/llvm-ver.make | 1 + src/Makefile | 20 ++++++++++++++------ src/{julia.expmap => julia.expmap.in} | 11 +++++++---- 7 files changed, 49 insertions(+), 25 deletions(-) create mode 100644 cli/julia.expmap.in rename src/{julia.expmap => julia.expmap.in} (92%) diff --git a/.gitignore b/.gitignore index 0368b7d19efa0..f0072fec9c91e 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ /source-dist.tmp /source-dist.tmp1 +*.expmap *.exe *.dll *.dwo diff --git a/Make.inc b/Make.inc index bc8f5b94f259b..96064cb7eac15 100644 --- a/Make.inc +++ b/Make.inc @@ -188,15 +188,17 @@ JULIA_MINOR_VERSION := $(shell echo $(JULIA_VERSION) | cut -d'-' -f 1 | cut -d'. JULIA_PATCH_VERSION := $(shell echo $(JULIA_VERSION) | cut -d'-' -f 1 | cut -d'+' -f 1 | cut -d'.' -f 3) # libjulia's SONAME will follow the format libjulia.so.$(SOMAJOR). Before v1.0.0, -# SOMAJOR will be a two-decimal value, e.g. libjulia.so.0.5, whereas at and beyond -# v1.0.0, SOMAJOR will be simply the major version number, e.g. libjulia.so.1 +# somajor was a two-decimal value (e.g. libjulia.so.0.5). During v1.0.x - v1.9.x, +# somajor was simply the major version number (e.g. libjulia.so.1). Starting in +# v1.10.0, somajor is major.minor again (e.g. libjulia.so.1.10) # The file itself will ultimately symlink to libjulia.so.$(SOMAJOR).$(SOMINOR) -ifeq ($(JULIA_MAJOR_VERSION),0) SOMAJOR := $(JULIA_MAJOR_VERSION).$(JULIA_MINOR_VERSION) SOMINOR := $(JULIA_PATCH_VERSION) -else -SOMAJOR := $(JULIA_MAJOR_VERSION) -SOMINOR := $(JULIA_MINOR_VERSION) + +# This suffix affects libjulia's SONAME and the symbol version associated with +# all of its exported symbols. +ifdef SYMBOL_VERSION_SUFFIX +SOMAJOR := $(SOMAJOR)_$(SYMBOL_VERSION_SUFFIX) endif ifneq ($(NO_GIT), 1) @@ -488,7 +490,7 @@ endif JCFLAGS_COMMON := -std=gnu11 -pipe $(fPIC) -fno-strict-aliasing -D_FILE_OFFSET_BITS=64 JCFLAGS_CLANG := $(JCFLAGS_COMMON) -JCFLAGS_GCC := $(JCFLAGS_COMMON) +JCFLAGS_GCC := $(JCFLAGS_COMMON) -fno-gnu-unique # AArch64 needs this flag to generate the .eh_frame used by libunwind JCPPFLAGS_COMMON := -fasynchronous-unwind-tables @@ -497,7 +499,7 @@ JCPPFLAGS_GCC := $(JCPPFLAGS_COMMON) JCXXFLAGS_COMMON := -pipe $(fPIC) -fno-rtti -std=c++14 JCXXFLAGS_CLANG := $(JCXXFLAGS_COMMON) -pedantic -JCXXFLAGS_GCC := $(JCXXFLAGS_COMMON) +JCXXFLAGS_GCC := $(JCXXFLAGS_COMMON) -fno-gnu-unique DEBUGFLAGS_COMMON := -O0 -DJL_DEBUG_BUILD -fstack-protector DEBUGFLAGS_CLANG := $(DEBUGFLAGS_COMMON) -g @@ -1317,7 +1319,7 @@ ifeq (supported, $(shell echo $(IFUNC_DETECT_SRC) | $(CC) -Werror -x c - -S -o / JCPPFLAGS += -DJULIA_HAS_IFUNC_SUPPORT=1 endif JLDFLAGS += -Wl,-Bdynamic -OSLIBS += -Wl,--version-script=$(JULIAHOME)/src/julia.expmap +OSLIBS += -Wl,--version-script=$(BUILDROOT)/src/julia.expmap ifneq ($(SANITIZE),1) JLDFLAGS += -Wl,-no-undefined endif @@ -1342,7 +1344,7 @@ OSLIBS += -lelf -lkvm -lrt -lpthread -latomic # See #21788 OSLIBS += -lgcc_s -OSLIBS += -Wl,--export-dynamic -Wl,--version-script=$(JULIAHOME)/src/julia.expmap \ +OSLIBS += -Wl,--export-dynamic -Wl,--version-script=$(BUILDROOT)/src/julia.expmap \ $(NO_WHOLE_ARCHIVE) endif @@ -1357,7 +1359,7 @@ endif ifeq ($(OS), WINNT) HAVE_SSP := 1 -OSLIBS += -Wl,--export-all-symbols -Wl,--version-script=$(JULIAHOME)/src/julia.expmap \ +OSLIBS += -Wl,--export-all-symbols -Wl,--version-script=$(BUILDROOT)/src/julia.expmap \ $(NO_WHOLE_ARCHIVE) -lpsapi -lkernel32 -lws2_32 -liphlpapi -lwinmm -ldbghelp -luserenv -lsecur32 -latomic JLDFLAGS += -Wl,--stack,8388608 ifeq ($(ARCH),i686) diff --git a/cli/Makefile b/cli/Makefile index c2e2bcd568a07..b6a2b48ebf044 100644 --- a/cli/Makefile +++ b/cli/Makefile @@ -104,14 +104,18 @@ julia-debug: $(build_bindir)/julia-debug$(EXE) libjulia-release: $(build_shlibdir)/libjulia.$(SHLIB_EXT) libjulia-debug: $(build_shlibdir)/libjulia-debug.$(SHLIB_EXT) +ifneq (,$(filter $(OS), Linux FreeBSD)) +VERSIONSCRIPT := -Wl,--version-script=$(BUILDDIR)/julia.expmap +endif + ifeq ($(OS),WINNT) # On Windows we need to strip out exported functions from the generated import library. STRIP_EXPORTED_FUNCS := $(shell $(CPP_STDOUT) -I$(JULIAHOME)/src $(SRCDIR)/list_strip_symbols.h) endif -$(build_shlibdir)/libjulia.$(JL_MAJOR_MINOR_SHLIB_EXT): $(LIB_OBJS) $(SRCDIR)/list_strip_symbols.h | $(build_shlibdir) $(build_libdir) +$(build_shlibdir)/libjulia.$(JL_MAJOR_MINOR_SHLIB_EXT): $(LIB_OBJS) $(SRCDIR)/list_strip_symbols.h $(BUILDDIR)/julia.expmap | $(build_shlibdir) $(build_libdir) @$(call PRINT_LINK, $(CC) $(call IMPLIB_FLAGS,$@.tmp) $(LOADER_CFLAGS) -shared $(SHIPFLAGS) $(LIB_OBJS) -o $@ \ - $(JLIBLDFLAGS) $(LOADER_LDFLAGS) $(call SONAME_FLAGS,libjulia.$(JL_MAJOR_SHLIB_EXT))) + $(JLIBLDFLAGS) $(LOADER_LDFLAGS) $(VERSIONSCRIPT) $(call SONAME_FLAGS,libjulia.$(JL_MAJOR_SHLIB_EXT))) @$(INSTALL_NAME_CMD)libjulia.$(JL_MAJOR_SHLIB_EXT) $@ @$(DSYMUTIL) $@ ifeq ($(OS), WINNT) @@ -120,9 +124,9 @@ ifeq ($(OS), WINNT) @$(call PRINT_ANALYZE, $(OBJCOPY) $(build_libdir)/$(notdir $@).tmp.a $(STRIP_EXPORTED_FUNCS) $(build_libdir)/$(notdir $@).a && rm $(build_libdir)/$(notdir $@).tmp.a) endif -$(build_shlibdir)/libjulia-debug.$(JL_MAJOR_MINOR_SHLIB_EXT): $(LIB_DOBJS) $(SRCDIR)/list_strip_symbols.h | $(build_shlibdir) $(build_libdir) +$(build_shlibdir)/libjulia-debug.$(JL_MAJOR_MINOR_SHLIB_EXT): $(LIB_DOBJS) $(SRCDIR)/list_strip_symbols.h $(BUILDDIR)/julia.expmap | $(build_shlibdir) $(build_libdir) @$(call PRINT_LINK, $(CC) $(call IMPLIB_FLAGS,$@.tmp) $(LOADER_CFLAGS) -shared $(DEBUGFLAGS) $(LIB_DOBJS) -o $@ \ - $(JLIBLDFLAGS) $(LOADER_LDFLAGS) $(call SONAME_FLAGS,libjulia-debug.$(JL_MAJOR_SHLIB_EXT))) + $(JLIBLDFLAGS) $(LOADER_LDFLAGS) $(VERSIONSCRIPT) $(call SONAME_FLAGS,libjulia-debug.$(JL_MAJOR_SHLIB_EXT))) @$(INSTALL_NAME_CMD)libjulia-debug.$(JL_MAJOR_SHLIB_EXT) $@ @$(DSYMUTIL) $@ ifeq ($(OS), WINNT) @@ -144,8 +148,12 @@ $(build_bindir)/julia$(EXE): $(EXE_OBJS) $(build_shlibdir)/libjulia.$(SHLIB_EXT) $(build_bindir)/julia-debug$(EXE): $(EXE_DOBJS) $(build_shlibdir)/libjulia-debug.$(SHLIB_EXT) | $(build_bindir) @$(call PRINT_LINK, $(CC) $(LOADER_CFLAGS) $(DEBUGFLAGS) $(EXE_DOBJS) -o $@ $(LOADER_LDFLAGS) $(RPATH) -ljulia-debug) +$(BUILDDIR)/julia.expmap: $(SRCDIR)/julia.expmap.in + sed <'$<' >'$@' -e 's/@JULIA_SHLIB_SYMBOL_VERSION@/JL_LIBJULIA_$(SOMAJOR)/' + clean: | $(CLEAN_TARGETS) rm -f $(BUILDDIR)/*.o $(BUILDDIR)/*.dbg.obj rm -f $(build_bindir)/julia* + rm -f $(BUILDDIR)/julia.expmap .PHONY: clean release debug julia-release julia-debug diff --git a/cli/julia.expmap.in b/cli/julia.expmap.in new file mode 100644 index 0000000000000..b6fa72e9aca03 --- /dev/null +++ b/cli/julia.expmap.in @@ -0,0 +1 @@ +@JULIA_SHLIB_SYMBOL_VERSION@ { global: *; }; diff --git a/deps/llvm-ver.make b/deps/llvm-ver.make index 3c498be6c2363..3777d5b37915a 100644 --- a/deps/llvm-ver.make +++ b/deps/llvm-ver.make @@ -17,3 +17,4 @@ LLVM_SHARED_LIB_VER_SUFFIX := $(LLVM_VER_MAJ)jl # e.g.: "libLLVM-14jl" LLVM_SHARED_LIB_NAME := libLLVM-$(LLVM_SHARED_LIB_VER_SUFFIX) LLVM_SHARED_LINK_FLAG := -lLLVM-$(LLVM_SHARED_LIB_VER_SUFFIX) +LLVM_SHLIB_SYMBOL_VERSION := JL_LLVM_$(LLVM_VER_MAJ).$(LLVM_VER_MIN) diff --git a/src/Makefile b/src/Makefile index 6a7c2fee844a1..9e34dfda1c4ed 100644 --- a/src/Makefile +++ b/src/Makefile @@ -119,6 +119,9 @@ ifeq ($(JULIACODEGEN),LLVM) ifneq ($(USE_SYSTEM_LLVM),0) # USE_SYSTEM_LLVM != 0 CG_LLVMLINK += $(LLVM_LDFLAGS) $(shell $(LLVM_CONFIG_HOST) --libs --system-libs) +LLVM_SHLIB_SYMBOL_VERSION := $(shell nm -D --with-symbol-versions $(shell $(LLVM_CONFIG_HOST) --libfiles --link-shared | awk '{print $1; exit}') | \ + grep _ZN4llvm3Any6TypeId | head -n 1 | sed -e 's/.*@//') + # HACK: llvm-config doesn't correctly point to shared libs on all platforms # https://github.com/JuliaLang/julia/issues/29981 else @@ -344,10 +347,10 @@ $(FLISP_EXECUTABLE_release): $(BUILDDIR)/flisp/libflisp.a $(FLISP_EXECUTABLE_debug): $(BUILDDIR)/flisp/libflisp-debug.a $(MAKE) -C $(BUILDDIR)/flisp $(subst $(abspath $(BUILDDIR)/flisp)/,,$(abspath $(FLISP_EXECUTABLE_debug))) -$(BUILDDIR)/flisp/libflisp.a: $(addprefix $(SRCDIR)/flisp/,*.h *.c) $(BUILDDIR)/support/libsupport.a +$(BUILDDIR)/flisp/libflisp.a: $(addprefix $(SRCDIR)/flisp/,*.h *.c) $(BUILDDIR)/support/libsupport.a $(BUILDDIR)/julia.expmap $(MAKE) -C $(SRCDIR)/flisp BUILDDIR='$(abspath $(BUILDDIR)/flisp)' -$(BUILDDIR)/flisp/libflisp-debug.a: $(addprefix $(SRCDIR)/,flisp/*.h flisp/*.c) $(BUILDDIR)/support/libsupport-debug.a +$(BUILDDIR)/flisp/libflisp-debug.a: $(addprefix $(SRCDIR)/,flisp/*.h flisp/*.c) $(BUILDDIR)/support/libsupport-debug.a $(BUILDDIR)/julia.expmap $(MAKE) -C $(SRCDIR)/flisp debug BUILDDIR='$(abspath $(BUILDDIR)/flisp)' $(BUILDDIR)/julia_version.h: $(JULIAHOME)/VERSION @@ -365,13 +368,17 @@ $(BUILDDIR)/julia_version.h: $(JULIAHOME)/VERSION CXXLD = $(CXX) -shared -$(build_shlibdir)/libjulia-internal.$(JL_MAJOR_MINOR_SHLIB_EXT): $(SRCDIR)/julia.expmap $(OBJS) $(BUILDDIR)/flisp/libflisp.a $(BUILDDIR)/support/libsupport.a $(LIBUV) +$(BUILDDIR)/julia.expmap: $(SRCDIR)/julia.expmap.in + sed <'$<' >'$@' -e "s/@JULIA_SHLIB_SYMBOL_VERSION@/JL_LIBJULIA_$(SOMAJOR)/" \ + -e "s/@LLVM_SHLIB_SYMBOL_VERSION@/$(LLVM_SHLIB_SYMBOL_VERSION)/" + +$(build_shlibdir)/libjulia-internal.$(JL_MAJOR_MINOR_SHLIB_EXT): $(BUILDDIR)/julia.expmap $(OBJS) $(BUILDDIR)/flisp/libflisp.a $(BUILDDIR)/support/libsupport.a $(LIBUV) @$(call PRINT_LINK, $(CXXLD) $(call IMPLIB_FLAGS,$@) $(JCXXFLAGS) $(JL_CXXFLAGS) $(CXXLDFLAGS) $(SHIPFLAGS) $(OBJS) $(RPATH_LIB) -o $@ \ $(JLDFLAGS) $(JLIBLDFLAGS) $(RT_RELEASE_LIBS) $(call SONAME_FLAGS,libjulia-internal.$(JL_MAJOR_SHLIB_EXT))) @$(INSTALL_NAME_CMD)libjulia-internal.$(SHLIB_EXT) $@ $(DSYMUTIL) $@ -$(build_shlibdir)/libjulia-internal-debug.$(JL_MAJOR_MINOR_SHLIB_EXT): $(SRCDIR)/julia.expmap $(DOBJS) $(BUILDDIR)/flisp/libflisp-debug.a $(BUILDDIR)/support/libsupport-debug.a $(LIBUV) +$(build_shlibdir)/libjulia-internal-debug.$(JL_MAJOR_MINOR_SHLIB_EXT): $(BUILDDIR)/julia.expmap $(DOBJS) $(BUILDDIR)/flisp/libflisp-debug.a $(BUILDDIR)/support/libsupport-debug.a $(LIBUV) @$(call PRINT_LINK, $(CXXLD) $(call IMPLIB_FLAGS,$@) $(JCXXFLAGS) $(JL_CXXFLAGS) $(CXXLDFLAGS) $(DEBUGFLAGS) $(DOBJS) $(RPATH_LIB) -o $@ \ $(JLDFLAGS) $(JLIBLDFLAGS) $(RT_DEBUG_LIBS) $(call SONAME_FLAGS,libjulia-internal-debug.$(JL_MAJOR_SHLIB_EXT))) @$(INSTALL_NAME_CMD)libjulia-internal-debug.$(SHLIB_EXT) $@ @@ -393,13 +400,13 @@ libjulia-internal-release: $(build_shlibdir)/libjulia-internal.$(JL_MAJOR_MINOR_ libjulia-internal-debug: $(build_shlibdir)/libjulia-internal-debug.$(JL_MAJOR_MINOR_SHLIB_EXT) libjulia-internal-debug libjulia-internal-release: $(PUBLIC_HEADER_TARGETS) -$(build_shlibdir)/libjulia-codegen.$(JL_MAJOR_MINOR_SHLIB_EXT): $(SRCDIR)/julia.expmap $(CODEGEN_OBJS) $(BUILDDIR)/support/libsupport.a $(build_shlibdir)/libjulia-internal.$(JL_MAJOR_MINOR_SHLIB_EXT) +$(build_shlibdir)/libjulia-codegen.$(JL_MAJOR_MINOR_SHLIB_EXT): $(BUILDDIR)/julia.expmap $(CODEGEN_OBJS) $(BUILDDIR)/support/libsupport.a $(build_shlibdir)/libjulia-internal.$(JL_MAJOR_MINOR_SHLIB_EXT) @$(call PRINT_LINK, $(CXXLD) $(call IMPLIB_FLAGS,$@) $(JCXXFLAGS) $(JL_CXXFLAGS) $(CXXLDFLAGS) $(SHIPFLAGS) $(CODEGEN_OBJS) $(RPATH_LIB) -o $@ \ $(JLDFLAGS) $(JLIBLDFLAGS) $(CG_RELEASE_LIBS) $(call SONAME_FLAGS,libjulia-codegen.$(JL_MAJOR_SHLIB_EXT))) @$(INSTALL_NAME_CMD)libjulia-codegen.$(SHLIB_EXT) $@ $(DSYMUTIL) $@ -$(build_shlibdir)/libjulia-codegen-debug.$(JL_MAJOR_MINOR_SHLIB_EXT): $(SRCDIR)/julia.expmap $(CODEGEN_DOBJS) $(BUILDDIR)/support/libsupport-debug.a $(build_shlibdir)/libjulia-internal-debug.$(JL_MAJOR_MINOR_SHLIB_EXT) +$(build_shlibdir)/libjulia-codegen-debug.$(JL_MAJOR_MINOR_SHLIB_EXT): $(BUILDDIR)/julia.expmap $(CODEGEN_DOBJS) $(BUILDDIR)/support/libsupport-debug.a $(build_shlibdir)/libjulia-internal-debug.$(JL_MAJOR_MINOR_SHLIB_EXT) @$(call PRINT_LINK, $(CXXLD) $(call IMPLIB_FLAGS,$@) $(JCXXFLAGS) $(JL_CXXFLAGS) $(CXXLDFLAGS) $(DEBUGFLAGS) $(CODEGEN_DOBJS) $(RPATH_LIB) -o $@ \ $(JLDFLAGS) $(JLIBLDFLAGS) $(CG_DEBUG_LIBS) $(call SONAME_FLAGS,libjulia-codegen-debug.$(JL_MAJOR_SHLIB_EXT))) @$(INSTALL_NAME_CMD)libjulia-codegen-debug.$(SHLIB_EXT) $@ @@ -429,6 +436,7 @@ clean: -rm -fr $(build_shlibdir)/libjulia-internal* $(build_shlibdir)/libjulia-codegen* $(build_shlibdir)/libccalltest* $(build_shlibdir)/libllvmcalltest* -rm -f $(BUILDDIR)/julia_flisp.boot $(BUILDDIR)/julia_flisp.boot.inc $(BUILDDIR)/jl_internal_funcs.inc -rm -f $(BUILDDIR)/*.dbg.obj $(BUILDDIR)/*.o $(BUILDDIR)/*.dwo $(BUILDDIR)/*.$(SHLIB_EXT) $(BUILDDIR)/*.a $(BUILDDIR)/*.h.gen + -rm -f $(BUILDDIR)/julia.expmap -rm -f $(BUILDDIR)/julia_version.h clean-flisp: diff --git a/src/julia.expmap b/src/julia.expmap.in similarity index 92% rename from src/julia.expmap rename to src/julia.expmap.in index ee35997827221..484c83a4b16b2 100644 --- a/src/julia.expmap +++ b/src/julia.expmap.in @@ -1,4 +1,4 @@ -{ +@JULIA_SHLIB_SYMBOL_VERSION@ { global: pthread*; __stack_chk_guard; @@ -35,9 +35,6 @@ JLJIT*; llvmGetPassPluginInfo; - /* Make visible so that linker will merge duplicate definitions across DSO boundaries */ - _ZN4llvm3Any6TypeId*; - /* freebsd */ environ; __progname; @@ -45,3 +42,9 @@ local: *; }; + +@LLVM_SHLIB_SYMBOL_VERSION@ { + global: + /* Make visible so that linker will merge duplicate definitions across DSO boundaries */ + _ZN4llvm3Any6TypeId*; +};