Skip to content

Commit b33bde5

Browse files
authored
[Products] Print nothing as dlopen flags for libraries not to dlopen (#90)
Also improve docstrings of products, they were greatly out-of-date, and the most useful parts (the docstrings attached to the inner constructors) were basically inaccessible.
1 parent e74d9d6 commit b33bde5

File tree

2 files changed

+71
-35
lines changed

2 files changed

+71
-35
lines changed

src/Products.jl

Lines changed: 67 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,49 @@ that refers to `"/lib/libnettle.so"`, the "directory" would be "/lib", and the
7373
"libname" would be "libnettle". Note that a `LibraryProduct` can support
7474
multiple libnames, as some software projects change the libname based on the
7575
build configuration.
76+
77+
---
78+
79+
LibraryProduct(libname, varname::Symbol; dir_paths=String[],
80+
dont_dlopen=false,
81+
dlopen_flags=Symbol[])
82+
83+
Declares a `LibraryProduct` that points to a library located within the prefix.
84+
`libname` specifies the basename of the library, `varname` is the name of the
85+
variable in the JLL package that can be used to call into the library. By
86+
default, the library is searched in the `libdir`, but you can add other
87+
directories within the prefix to the `dir_paths` keyword argument. You can
88+
specify the flags to pass to `dlopen` as a vector of `Symbols` with the
89+
`dlopen_flags` keyword argument. If the library should not be dlopen'ed
90+
automatically by the JLL package, set `dont_dlopen=true`.
91+
92+
For example, if the `libname` is `libnettle`, this would be satisfied by the
93+
following paths:
94+
95+
* `lib/libnettle.so` or `lib/libnettle.so.6` on Linux and FreeBSD;
96+
* `lib/libnettle.6.dylib` on macOS;
97+
* `lib/libnettle-6.dll` on Windows.
98+
99+
Libraries matching the search pattern are rejected if they are not
100+
`dlopen()`'able.
101+
102+
If you are unsure what value to use for `libname`, you can use
103+
`Base.BinaryPlatforms.parse_dl_name_version`:
104+
105+
```
106+
julia> using Base.BinaryPlatforms
107+
108+
julia> parse_dl_name_version("sfml-audio-2.dll", "windows")[1]
109+
"sfml-audio"
110+
```
111+
112+
If the library would have different basenames on different operating systems
113+
(e.g., `libz.so` on Linux and FreeBSD, `libz.dylib` on macOS, and `zlib.dll` on
114+
Windows), `libname` can be also a vector of `String`s with the different
115+
alternatives:
116+
```
117+
LibraryProduct(["libz", "zlib"], :libz)
118+
```
76119
"""
77120
struct LibraryProduct <: Product
78121
libnames::Vector{String}
@@ -81,22 +124,6 @@ struct LibraryProduct <: Product
81124
dont_dlopen::Bool
82125
dlopen_flags::Vector{Symbol}
83126

84-
"""
85-
LibraryProduct(libnames, varname::Symbol)
86-
87-
Declares a [`LibraryProduct`](@ref) that points to a library located within
88-
the `libdir` of the given `Prefix`, with a name containing `libname`. As an
89-
example, given that `libdir(prefix)` is equal to `usr/lib`, and `libname` is
90-
equal to `libnettle`, this would be satisfied by the following paths:
91-
92-
usr/lib/libnettle.so
93-
usr/lib/libnettle.so.6
94-
usr/lib/libnettle.6.dylib
95-
usr/lib/libnettle-6.dll
96-
97-
Libraries matching the search pattern are rejected if they are not
98-
`dlopen()`'able.
99-
"""
100127
LibraryProduct(libname::AbstractString, varname, args...; kwargs...) = LibraryProduct([libname], varname, args...; kwargs...)
101128
LibraryProduct(libnames::Vector{<:AbstractString}, varname::Symbol, dir_path::AbstractString, args...; kwargs...) = LibraryProduct(libnames, varname, [dir_path], args...; kwargs...)
102129
function LibraryProduct(libnames::Vector{<:AbstractString}, varname::Symbol,
@@ -124,7 +151,9 @@ struct LibraryProduct <: Product
124151
end
125152

126153
function dlopen_flags_str(p::LibraryProduct)
127-
if length(p.dlopen_flags) > 0
154+
if p.dont_dlopen
155+
return "nothing"
156+
elseif length(p.dlopen_flags) > 0
128157
return join(p.dlopen_flags, " | ")
129158
else
130159
# This is the default if no flags are specified
@@ -233,20 +262,21 @@ This implies that for cross-platform builds where a library is provided as a Fra
233262
on macOS and as a normal library on other platforms, two calls to BinaryBuilder's `build_tarballs`
234263
are needed: one with the `LibraryProduct` and all non-macOS platforms, and one with the `FrameworkProduct`
235264
and the `MacOS` platforms.
265+
266+
---
267+
268+
FrameworkProduct(fwnames, varname::Symbol)
269+
270+
Declares a macOS `FrameworkProduct` that points to a framework located within
271+
the prefix, with a name containing `fwname` appended with `.framework`. As an
272+
example, given that `fwname` is equal to `QtCore`, this would be satisfied by
273+
the following path:
274+
275+
lib/QtCore.framework
236276
"""
237277
struct FrameworkProduct <: Product
238278
libraryproduct::LibraryProduct
239279

240-
"""
241-
FrameworkProduct(fwnames, varname::Symbol)
242-
243-
Declares a macOS [`FrameworkProduct`](@ref) that points to a framework located within
244-
the `libdir` of the given `Prefix`, with a name containing `fwname` appended with `.framework`. As an
245-
example, given that `libdir(prefix)` is equal to `usr/lib`, and `fwname` is
246-
equal to `QtCore`, this would be satisfied by the following paths:
247-
248-
usr/lib/QtCore.framework
249-
"""
250280
FrameworkProduct(fwname::AbstractString, varname, args...; kwargs...) = FrameworkProduct([fwname], varname, args...; kwargs...)
251281
function FrameworkProduct(fwnames::Vector{<:AbstractString}, varname::Symbol,
252282
dir_paths::Vector{<:AbstractString}=String[];
@@ -306,18 +336,22 @@ On all platforms, an ExecutableProduct checks for existence of the file. On
306336
non-Windows platforms, it will check for the executable bit being set. On
307337
Windows platforms, it will check that the file ends with ".exe", (adding it on
308338
automatically, if it is not already present).
339+
340+
---
341+
342+
ExecutableProduct(binname, varname::Symbol, dir_path="bin")
343+
344+
Declares an `ExecutableProduct` that points to an executable located within the
345+
prefix. `binname` specifies the basename of the executable, `varname` is the
346+
name of the variable in the JLL package that can be used to call into the
347+
library. By default, the library is searched in the `bindir`, but you can
348+
specify a different directory within the prefix with the `dir_path` argument.
309349
"""
310350
struct ExecutableProduct <: Product
311351
binnames::Vector{String}
312352
variable_name::Symbol
313353
dir_path::Union{String, Nothing}
314354

315-
"""
316-
ExecutableProduct(binnames::Vector{String}, varname::Symbol)
317-
318-
Declares an `ExecutableProduct` that points to an executable located within
319-
the `bindir` of the given `Prefix`, named one of the given `binname`s.
320-
"""
321355
function ExecutableProduct(binnames::Vector{String}, varname::Symbol, dir_path::Union{AbstractString, Nothing}=nothing)
322356
if isdefined(Base, varname)
323357
error("`$(varname)` is already defined in Base")

test/products.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ using Test
22
using Base.BinaryPlatforms
33
import Libdl
44
using BinaryBuilderBase
5-
using BinaryBuilderBase: template
5+
using BinaryBuilderBase: template, dlopen_flags_str
66

77
# The platform we're running on
88
const platform = HostPlatform()
@@ -190,8 +190,10 @@ end
190190
fp = FrameworkProduct("libfoo2", :libfoo2; dlopen_flags=[:RTLD_GLOBAL, :RTLD_NOLOAD])
191191
@test fp.libraryproduct.dlopen_flags == [:RTLD_GLOBAL, :RTLD_NOLOAD]
192192
for p in (lp, fp)
193-
flag_str = BinaryBuilderBase.dlopen_flags_str(p)
193+
flag_str = dlopen_flags_str(p)
194194
@test flag_str == "RTLD_GLOBAL | RTLD_NOLOAD"
195195
@test Libdl.eval(Meta.parse(flag_str)) == (Libdl.RTLD_NOLOAD | Libdl.RTLD_GLOBAL)
196196
end
197+
lp = LibraryProduct("libfoo2", :libfoo2; dont_dlopen=true)
198+
@test dlopen_flags_str(lp) == "nothing"
197199
end

0 commit comments

Comments
 (0)