@@ -841,20 +841,48 @@ function parse_dl_name_version(path::AbstractString, os::AbstractString)
841841 return parse_dl_name_version (string (path):: String , string (os):: String )
842842end
843843
844+ function get_csl_member (member:: Symbol )
845+ # If CompilerSupportLibraries_jll is an stdlib, we can just grab things from it
846+ csl_pkgids = filter (pkgid -> pkgid. name == " CompilerSupportLibraries_jll" , keys (Base. loaded_modules))
847+ if ! isempty (csl_pkgids)
848+ CSL_mod = Base. loaded_modules[first (csl_pkgids)]
849+
850+ # This can fail during bootstrap, so we skip in that case.
851+ if isdefined (CSL_mod, member)
852+ return getproperty (CSL_mod, member)
853+ end
854+ end
855+
856+ return nothing
857+ end
858+
844859"""
845860 detect_libgfortran_version()
846861
847862Inspects the current Julia process to determine the libgfortran version this Julia is
848- linked against (if any).
863+ linked against (if any). Returns `nothing` if no libgfortran version dependence is
864+ detected.
849865"""
850866function detect_libgfortran_version ()
851- libgfortran_paths = filter! (x -> occursin (" libgfortran" , x), Libdl. dllist ())
852- if isempty (libgfortran_paths)
867+ function get_libgfortran_path ()
868+ # If CompilerSupportLibraries_jll is an stdlib, we can just directly ask for
869+ # the path here, without checking `dllist()`:
870+ libgfortran_path = get_csl_member (:libgfortran_path )
871+ if libgfortran_path != = nothing
872+ return libgfortran_path:: String
873+ end
874+
875+ # Otherwise, look for it having already been loaded by something
876+ libgfortran_paths = filter! (x -> occursin (" libgfortran" , x), Libdl. dllist ())
877+ if ! isempty (libgfortran_paths)
878+ return first (libgfortran_paths):: String
879+ end
880+
853881 # One day, I hope to not be linking against libgfortran in base Julia
854882 return nothing
855883 end
856- libgfortran_path = first (libgfortran_paths)
857884
885+ libgfortran_path = get_libgfortran_path ()
858886 name, version = parse_dl_name_version (libgfortran_path, os ())
859887 if version === nothing
860888 # Even though we complain about this, we allow it to continue in the hopes that
@@ -878,24 +906,37 @@ it is linked against (if any). `max_minor_version` is the latest version in the
8789063.4 series of GLIBCXX where the search is performed.
879907"""
880908function detect_libstdcxx_version (max_minor_version:: Int = 30 )
881- libstdcxx_paths = filter! (x -> occursin (" libstdc++" , x), Libdl. dllist ())
882- if isempty (libstdcxx_paths)
883- # This can happen if we were built by clang, so we don't link against
884- # libstdc++ at all.
909+ function get_libstdcxx_handle ()
910+ # If CompilerSupportLibraries_jll is an stdlib, we can just directly open it
911+ libstdcxx = get_csl_member (:libstdcxx )
912+ if libstdcxx != = nothing
913+ return nothing
914+ end
915+
916+ # Otherwise, look for it having already been loaded by something
917+ libstdcxx_paths = filter! (x -> occursin (" libstdc++" , x), Libdl. dllist ())
918+ if ! isempty (libstdcxx_paths)
919+ return Libdl. dlopen (first (libstdcxx_paths), Libdl. RTLD_NOLOAD):: Ptr{Cvoid}
920+ end
921+
922+ # One day, I hope to not be linking against libgfortran in base Julia
885923 return nothing
886924 end
887925
888926 # Brute-force our way through GLIBCXX_* symbols to discover which version we're linked against
889- hdl = Libdl. dlopen (first (libstdcxx_paths)):: Ptr{Cvoid}
890- # Try all GLIBCXX versions down to GCC v4.8:
891- # https://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html
892- for minor_version in max_minor_version: - 1 : 18
893- if Libdl. dlsym (hdl, " GLIBCXX_3.4.$(minor_version) " ; throw_error= false ) != = nothing
894- Libdl. dlclose (hdl)
895- return VersionNumber (" 3.4.$(minor_version) " )
927+ libstdcxx = get_libstdcxx_handle ()
928+
929+ if libstdcxx != = nothing
930+ # Try all GLIBCXX versions down to GCC v4.8:
931+ # https://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html
932+ for minor_version in max_minor_version: - 1 : 18
933+ if Libdl. dlsym (libstdcxx, " GLIBCXX_3.4.$(minor_version) " ; throw_error= false ) != = nothing
934+ Libdl. dlclose (libstdcxx)
935+ return VersionNumber (" 3.4.$(minor_version) " )
936+ end
896937 end
897938 end
898- Libdl. dlclose (hdl )
939+ Libdl. dlclose (libstdcxx )
899940 return nothing
900941end
901942
0 commit comments