@@ -1193,6 +1193,54 @@ function glob_pattern_lib(lib)
11931193 error (" unknown os" )
11941194end
11951195
1196+ # Take `path` to a libstdc++ library and return aliases for shared library symlinks:
1197+ # - Unix:
1198+ # `path/to/libstdc++.so.6.0.30` will yield aliases
1199+ # `libstdc++.so.6.0.30`, `libstdc++.so.6`, `libstdc++.so`
1200+ # - Apple:
1201+ # `path/to/libstdc++.6.0.30.dylib` will yield aliases
1202+ # `libstdc++.6.0.30.dylib`, `libstdc++.6.dylib`, `libstdc++.dylib`
1203+ # - Windows:
1204+ # `path/to/libstdc++-6.0.30.dll` will yield aliases
1205+ # `libstdc++-6.0.30.dll`, `libstdc++-6.dll`, `libstdc++.dll`
1206+ # If the major version cannot be inferred from the filename, return only full name and the
1207+ # alias without any version information.
1208+ function get_libstdcxx_aliases (path)
1209+ # Extract library name and version from path
1210+ os = if Sys. iswindows ()
1211+ " windows"
1212+ elseif Sys. isapple ()
1213+ " macos"
1214+ elseif Sys. isunix ()
1215+ " unix"
1216+ else
1217+ error (" unable to determine aliases; system is not Windows, macOS, or UNIX" )
1218+ end
1219+ libname, version = Base. BinaryPlatforms. parse_dl_name_version (path, os)
1220+
1221+ # Always add full filename and base library name to list of aliases
1222+ ext = Libdl. dlext
1223+ aliases = String[basename (path), " $libname .$ext " ]
1224+
1225+ # If version exists, also add alias for major version
1226+ if ! isnothing (version)
1227+ major = version. major
1228+ if Sys. iswindows ()
1229+ # libname-major.dll
1230+ push! (aliases, " $libname -$major .$ext " )
1231+ elseif Sys. isapple ()
1232+ # libname.major.dylib
1233+ push! (aliases, " $libname .$major .$ext " )
1234+ else
1235+ # libname.so.major
1236+ push! (aliases, " $libname .$ext .$major " )
1237+ end
1238+ end
1239+
1240+ # Return unique list in case, e.g., filename is identical to base library name
1241+ return unique (aliases)
1242+ end
1243+
11961244# TODO : Detangle printing from business logic
11971245function bundle_julia_libraries (dest_dir, stdlibs)
11981246 app_lib_dir = joinpath (dest_dir, Sys. isunix () ? " lib" : " bin" )
@@ -1210,11 +1258,22 @@ function bundle_julia_libraries(dest_dir, stdlibs)
12101258 tot_libsize = 0
12111259 printstyled (" PackageCompiler: bundled libraries:\n " )
12121260
1213- # Reqiored libraries
1261+ # Bundle the libstdc++ that is actually loaded by Julia
1262+ # xref: https://discourse.julialang.org/t/precedence-of-local-and-julia-shipped-shared-libraries/104258?u=sloede
1263+ libstdcxx = filter (contains (" libstdc++" ), Libdl. dllist ())
1264+ # Load libstdc++ if not yet loaded to figure out which one Julia would load
1265+ if isempty (libstdcxx)
1266+ Libdl. dlopen (" libstdc++" )
1267+ libstdcxx = filter (contains (" libstdc++" ), Libdl. dllist ())
1268+ end
1269+ # Resolve symbolic links
1270+ libstdcxx = map (realpath ∘ abspath, libstdcxx)
1271+
1272+ # Required libraries
12141273 println (" ├── Base:" )
12151274 os = Sys. islinux () ? " linux" : Sys. isapple () ? " mac" : " windows"
12161275 for lib in required_libraries[os]
1217- matches = glob (glob_pattern_lib (lib), libjulia_dir)
1276+ matches = (lib == " libstdc++ " ) ? libstdcxx : glob (glob_pattern_lib (lib), libjulia_dir)
12181277 for match in matches
12191278 dest = joinpath (app_libjulia_dir, basename (match))
12201279 isfile (dest) && continue
@@ -1228,6 +1287,16 @@ function bundle_julia_libraries(dest_dir, stdlibs)
12281287 end
12291288 end
12301289
1290+ # For libstdc++, add additional symlinks since above only the library itself was copied
1291+ libstdcxx_path = first (libstdcxx)
1292+ for alias in get_libstdcxx_aliases (libstdcxx_path)
1293+ link = joinpath (app_libjulia_dir, alias)
1294+ if isfile (link) || islink (link)
1295+ continue
1296+ end
1297+ symlink (basename (libstdcxx_path), link)
1298+ end
1299+
12311300 major, minor, patch = VERSION . major, VERSION . minor, VERSION . patch
12321301 r = if Sys. isapple ()
12331302 Regex (" ^libjulia(\\ .$major (\\ .$minor (\\ .$patch )?)?)?\\ .dylib\$ " )
0 commit comments