-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathbuild.jl
207 lines (171 loc) · 6.44 KB
/
build.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
using CBindingGen
using Libdl
using MPI
import Pkg.TOML
using Pkg.Artifacts
import P4est_jll
# setup configuration using ideas from MPI.jl
const config_toml = joinpath(first(DEPOT_PATH), "prefs", "P4est.toml")
mkpath(dirname(config_toml))
if !isfile(config_toml)
touch(config_toml)
end
config = TOML.parsefile(config_toml)
# P4est.toml has the following keys:
# p4est_generate_bindings = "" (default) | if non-empty, re-generate bindings during build stage
# p4est_path = "" (default) | path to p4est containing subdirectories lib and include
# p4est_library = "" (default) | library name/path
# p4est_include = "" (default) | include name/path
# p4est_uses_mpi = "" (default) | "yes" indicates that we need the MPI headers
# mpi_path = "" (default) | path to MPI containing subdirectories lib and include
# mpi_include = "" (default) | include name/path
# Step 1: Check environment variables and update preferences accordingly
if haskey(ENV, "JULIA_P4EST_GENERATE_BINDINGS")
config["p4est_generate_bindings"] = ENV["JULIA_P4EST_GENERATE_BINDINGS"]
else
config["p4est_generate_bindings"] = ""
end
if haskey(ENV, "JULIA_P4EST_PATH")
config["p4est_path"] = ENV["JULIA_P4EST_PATH"]
else
config["p4est_path"] = ""
end
if haskey(ENV, "JULIA_P4EST_LIBRARY")
config["p4est_library"] = ENV["JULIA_P4EST_LIBRARY"]
else
config["p4est_library"] = ""
end
if haskey(ENV, "JULIA_P4EST_INCLUDE")
config["p4est_include"] = ENV["JULIA_P4EST_INCLUDE"]
else
config["p4est_include"] = ""
end
if haskey(ENV, "JULIA_P4EST_USES_MPI")
config["p4est_uses_mpi"] = ENV["JULIA_P4EST_USES_MPI"]
else
config["p4est_uses_mpi"] = ""
end
if haskey(ENV, "JULIA_P4EST_MPI_PATH")
config["mpi_path"] = ENV["JULIA_P4EST_MPI_PATH"]
else
config["mpi_path"] = ""
end
if haskey(ENV, "JULIA_P4EST_MPI_INCLUDE")
config["mpi_include"] = ENV["JULIA_P4EST_MPI_INCLUDE"]
else
config["mpi_include"] = ""
end
open(config_toml, "w") do io
TOML.print(io, config)
end
if isempty(config["p4est_generate_bindings"])
println("Use pre-generated bindings for p4est")
const bindings_filename = joinpath(@__DIR__, "libp4est.jl")
const pre_generated_bindings_filename = joinpath(artifact"libp4est", "libp4est.jl")
cp(pre_generated_bindings_filename, bindings_filename, force=true)
else
# Step 2: Choose p4est library according to the settings
p4est_library = ""
if !isempty(config["p4est_library"])
p4est_library = config["p4est_library"]
println("Use custom p4est library $p4est_library")
elseif !isempty(config["p4est_path"])
p4est_library = joinpath(config["p4est_path"], "lib", "libp4est." * Libdl.dlext)
if isfile(p4est_library)
println("Use custom p4est library $p4est_library")
else
p4est_library = ""
end
end
if isempty(p4est_library)
p4est_library = P4est_jll.libp4est_path
println("Use p4est library provided by P4est_jll")
end
# Step 3a: Choose the p4est include path according to the settings
include_directories = String[]
p4est_include = ""
if !isempty(config["p4est_include"])
p4est_include = config["p4est_include"]
println("Use custom p4est include path $p4est_include")
elseif !isempty(config["p4est_path"])
p4est_include = joinpath(config["p4est_path"], "include")
if isdir(p4est_include)
println("Use custom p4est include path $p4est_include")
else
p4est_include = ""
end
end
if isempty(p4est_include)
p4est_include = joinpath(dirname(dirname(P4est_jll.libp4est_path)), "include")
println("Use p4est include path provided by P4est_jll")
end
push!(include_directories, p4est_include)
# Step 3b: Choose the MPI include path according to the settings
if config["p4est_uses_mpi"] == "yes"
mpi_include = ""
if !isempty(config["mpi_include"])
mpi_include = config["mpi_include"]
println("Use custom MPI include path $mpi_include")
elseif !isempty(config["mpi_path"])
mpi_include = joinpath(config["mpi_path"], "include")
if isdir(mpi_include)
println("Use custom MPI include path $mpi_include")
else
mpi_include = ""
end
end
if isempty(mpi_include)
mpi_include = joinpath(dirname(dirname(normpath(dlpath(MPI.libmpi)))), "include")
println("Use MPI include path based on path to `MPI.jl`'s `libmpi`")
end
if !isfile(joinpath(mpi_include, "mpi.h"))
error("could not find `mpi.h` in ", mpi_include)
end
push!(include_directories, mpi_include)
end
# Step 4: Generate binding using the include path according to the settings
# Manually set header files to consider
hdrs = ["p4est.h", "p4est_extended.h",
"p6est.h", "p6est_extended.h",
"p8est.h", "p8est_extended.h"]
# Build list of arguments for Clang
include_args = String[]
@show include_directories
for dir in include_directories
append!(include_args, ("-I", dir))
end
# Workaround for MacOS: The some headers required by p4est (such as `math.h`) are only available via
# Xcode
if Sys.isapple()
# These two paths *should* - on any reasonably current MacOS system - contain the relevant headers
const xcode_include_path_cli = "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/"
const xcode_include_path_gui = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/"
if !isdir(xcode_include_path_cli) && !isdir(xcode_include_path_gui)
error("MacOS SDK include paths ('$xcode_include_path_cli' or '$xcode_include_path_gui') do not exist. Have you installed Xcode?")
end
append!(include_args, ("-idirafter", xcode_include_path_cli, "-idirafter", xcode_include_path_gui))
end
# Convert symbols in header
cvts = convert_headers(hdrs, args=include_args) do cursor
header = CodeLocation(cursor).file
name = string(cursor)
# only wrap the libp4est and libsc headers
dirname, filename = splitdir(header)
if !(filename in hdrs ||
startswith(filename, "p4est_") ||
startswith(filename, "p6est_") ||
startswith(filename, "p8est_") ||
startswith(filename, "sc_") ||
filename == "sc.h" )
return false
end
# Ignore macro hacks
startswith(name, "sc_extern_c_hack_") && return false
return true
end
# Write generated C bindings to file
const bindings_filename = joinpath(@__DIR__, "libp4est.jl")
open(bindings_filename, "w+") do io
generate(io, p4est_library => cvts)
end
end