|
| 1 | +# This file serves as a way to provide access to libraries that Base needs |
| 2 | +# that are usually included as artifacts. We can't use Artifacts this early |
| 3 | +# becuase we haven't bootstrapped far enough, so this file contains "Base" |
| 4 | +# JLLs that are manually adapted to load things from hardcoded paths so that |
| 5 | +# we can bootstrap, but once GMP_jll, MPFR_jll, etc... are loaded, we replace |
| 6 | +# the definitions here with the `LazyLibrary` objects defined there, as they |
| 7 | +# may be overloaded by Preferences and refer to a different library than we |
| 8 | +# would have used during bootstrap. |
| 9 | +module JLLAdapters |
| 10 | + |
| 11 | +# We're early enough that we don't have access to `Sys.iswindows()`, etc... |
| 12 | +const UNAME = ccall(:jl_get_UNAME, Any, ())::Symbol |
| 13 | +const early_pathsep = (UNAME === :Windows || UNAME === :NT) ? "\\" : "/" |
| 14 | + |
| 15 | +function early_joinpath(pieces...) |
| 16 | + result = pieces[1] |
| 17 | + for piece in pieces[2:end] |
| 18 | + result = string(result, early_pathsep, piece) |
| 19 | + end |
| 20 | + return result |
| 21 | +end |
| 22 | + |
| 23 | +""" |
| 24 | + LazyLibraryPath |
| 25 | +
|
| 26 | +Helper type for lazily constructed library paths for use with `LazyLibrary`. |
| 27 | +Arguments are passed to `joinpath()`. Arguments must be able to have |
| 28 | +`string()` called on them. |
| 29 | +
|
| 30 | +``` |
| 31 | +libfoo = LazyLibrary(LazyLibraryPath(prefix, "lib/libfoo.so.1.2.3")) |
| 32 | +``` |
| 33 | +""" |
| 34 | +struct LazyLibraryPath |
| 35 | + pieces::Vector |
| 36 | + LazyLibraryPath(pieces::Vector) = new(pieces) |
| 37 | +end |
| 38 | +LazyLibraryPath(args...) = LazyLibraryPath(collect(args)) |
| 39 | +Base.string(llp::LazyLibraryPath) = early_joinpath([string(p) for p in llp.pieces]...) |
| 40 | +Base.cconvert(::Type{Cstring}, llp::LazyLibraryPath) = Base.cconvert(Cstring, string(llp)) |
| 41 | +# Define `print` so that we can wrap this in a `LazyString` |
| 42 | +Base.print(io::IO, llp::LazyLibraryPath) = print(io, string(llp)) |
| 43 | + |
| 44 | +# Helper to get `Sys.BINDIR` at runtime |
| 45 | +struct SysBindirGetter; end |
| 46 | +Base.string(::SysBindirGetter) = string(ccall(:jl_get_julia_bindir, Any, ())::String, early_pathsep, "..") |
| 47 | + |
| 48 | +""" |
| 49 | + BundledLazyLibraryPath |
| 50 | +
|
| 51 | +Helper type for lazily constructed library paths that are stored within the |
| 52 | +bundled Julia distribution, primarily for use by Base modules. |
| 53 | +
|
| 54 | +``` |
| 55 | +libfoo = LazyLibrary(BundledLazyLibraryPath("lib/libfoo.so.1.2.3")) |
| 56 | +``` |
| 57 | +""" |
| 58 | +BundledLazyLibraryPath(subpath) = LazyLibraryPath(SysBindirGetter(), subpath) |
| 59 | + |
| 60 | +# PCRE |
| 61 | +if (UNAME === :Windows || UNAME === :NT) |
| 62 | + const libpcre2_8_name = "bin/libpcre2-8-0.dll" |
| 63 | +elseif (UNAME === :Apple || UNAME === :Darwin) |
| 64 | + const libpcre2_8_name = "lib/libpcre2-8.0.dylib" |
| 65 | +else |
| 66 | + const libpcre2_8_name = "lib/libpcre2-8.so.0" |
| 67 | +end |
| 68 | + |
| 69 | +const libpcre2_8 = Ref{Any}(BundledLazyLibraryPath(libpcre2_8_name)) |
| 70 | +function get_libpcre2_8() |
| 71 | + if isa(libpcre2_8[], LazyLibraryPath) |
| 72 | + return string(libpcre2_8[]) |
| 73 | + end |
| 74 | + return libpcre2_8[] |
| 75 | +end |
| 76 | + |
| 77 | +# GMP |
| 78 | +if (UNAME === :Windows || UNAME === :NT) |
| 79 | + const libgmp_name = "bin/libgmp-10.dll" |
| 80 | +elseif (UNAME === :Apple || UNAME === :Darwin) |
| 81 | + const libgmp_name = "lib/libgmp.10.dylib" |
| 82 | +else |
| 83 | + const libgmp_name = "lib/libgmp.so.10" |
| 84 | +end |
| 85 | +const libgmp = Ref{Any}(BundledLazyLibraryPath(libgmp_name)) |
| 86 | +function get_libgmp() |
| 87 | + if isa(libgmp[], LazyLibraryPath) |
| 88 | + return string(libgmp[]) |
| 89 | + end |
| 90 | + return libgmp[] |
| 91 | +end |
| 92 | + |
| 93 | + |
| 94 | +# MPFR |
| 95 | +if (UNAME === :Windows || UNAME === :NT) |
| 96 | + const libmpfr_name = "bin/libmpfr-6.dll" |
| 97 | +elseif (UNAME === :Apple || UNAME === :Darwin) |
| 98 | + const libmpfr_name = "lib/libmpfr.6.dylib" |
| 99 | +else |
| 100 | + const libmpfr_name = "lib/libmpfr.so.6" |
| 101 | +end |
| 102 | +const libmpfr = Ref{Any}(BundledLazyLibraryPath(libmpfr_name)) |
| 103 | +function get_libmpfr() |
| 104 | + # Work around early bootstrap problems where we need to load `libgmp` |
| 105 | + # when `libmpfr` is loaded. This only works if we're far enough along |
| 106 | + # in bootstrap to be able to call `dlopen()`! Later, `libmpfr[]` |
| 107 | + # is going to return a `LazyLibrary` that will have a dependency on |
| 108 | + # `libgmp[]`. |
| 109 | + if isa(libmpfr[], LazyLibraryPath) |
| 110 | + Base.Libc.Libdl.dlopen(get_libgmp()) |
| 111 | + return string(libmpfr[]) |
| 112 | + end |
| 113 | + return libmpfr[] |
| 114 | +end |
| 115 | + |
| 116 | + |
| 117 | +end # module JLLAdapters |
0 commit comments