|  | 
|  | 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