32 options = |
32 options = |
33 List("--host=x86_64-w64-mingw32", "CPPFLAGS=-I/mingw64/include", "--disable-windows-gui"), |
33 List("--host=x86_64-w64-mingw32", "CPPFLAGS=-I/mingw64/include", "--disable-windows-gui"), |
34 setup = MinGW.environment_export, |
34 setup = MinGW.environment_export, |
35 libs = Set("libgcc_s_seh", "libgmp", "libstdc++", "libwinpthread"))) |
35 libs = Set("libgcc_s_seh", "libgmp", "libstdc++", "libwinpthread"))) |
36 |
36 |
|
37 def bash( |
|
38 cwd: Path, |
|
39 platform: Isabelle_Platform, |
|
40 mingw: MinGW, |
|
41 script: String, |
|
42 redirect: Boolean = false, |
|
43 progress: Progress = new Progress |
|
44 ): Process_Result = { |
|
45 val script1 = |
|
46 if (platform.is_arm && platform.is_macos) { |
|
47 "arch -arch arm64 bash -c " + Bash.string(script) |
|
48 } |
|
49 else mingw.bash_script(script) |
|
50 progress.bash(script1, cwd = cwd, redirect = redirect, echo = progress.verbose) |
|
51 } |
|
52 |
37 def polyml_platform(arch_64: Boolean): String = { |
53 def polyml_platform(arch_64: Boolean): String = { |
38 val platform = Isabelle_Platform.self |
54 val platform = Isabelle_Platform.self |
39 (if (arch_64) platform.arch_64 else platform.arch_64_32) + "-" + platform.os_name |
55 (if (arch_64) platform.arch_64 else platform.arch_64_32) + "-" + platform.os_name |
40 } |
56 } |
41 |
57 |
42 def make_polyml( |
58 def make_polyml( |
43 root: Path, |
59 root: Path, |
|
60 gmp_root: Option[Path] = None, |
44 sha1_root: Option[Path] = None, |
61 sha1_root: Option[Path] = None, |
45 target_dir: Path = Path.current, |
62 target_dir: Path = Path.current, |
46 arch_64: Boolean = false, |
63 arch_64: Boolean = false, |
47 options: List[String] = Nil, |
64 options: List[String] = Nil, |
48 mingw: MinGW = MinGW.none, |
65 mingw: MinGW = MinGW.none, |
60 error("Bad OS platform: " + quote(platform.os_name))) |
77 error("Bad OS platform: " + quote(platform.os_name))) |
61 |
78 |
62 if (platform.is_linux) Isabelle_System.require_command("patchelf") |
79 if (platform.is_linux) Isabelle_System.require_command("patchelf") |
63 |
80 |
64 |
81 |
65 /* bash */ |
82 /* configure and make */ |
66 |
83 |
67 def bash( |
84 val configure_options = { |
68 cwd: Path, script: String, |
85 val options1 = if (gmp_root.nonEmpty) List("--with-gmp") else List("--without-gmp") |
69 redirect: Boolean = false, |
86 |
70 echo: Boolean = false |
87 val options2 = |
71 ): Process_Result = { |
88 for (opt <- info.options) yield { |
72 val script1 = |
89 if (opt.startsWith("CFLAGS=") && gmp_root.nonEmpty) { |
73 if (platform.is_arm && platform.is_macos) { |
90 val root0 = gmp_root.get.absolute |
74 "arch -arch arm64 bash -c " + Bash.string(script) |
91 val root1 = mingw.standard_path(root0) |
|
92 require(root0.implode == File.bash_path(root0), "Bad directory name " + root0) |
|
93 opt + " " + "-I" + root1 + "/include -L" + root1 + "/lib" |
|
94 } |
|
95 else opt |
75 } |
96 } |
76 else mingw.bash_script(script) |
97 |
77 progress.bash(script1, cwd = cwd, redirect = redirect, echo = echo) |
98 val options3 = if (arch_64) Nil else List("--enable-compact32bit") |
|
99 |
|
100 List("--disable-shared", "--enable-intinf-as-int") ::: |
|
101 options1 ::: options2 ::: options ::: options3 |
78 } |
102 } |
79 |
103 |
80 |
104 bash(root, platform, mingw, |
81 /* configure and make */ |
|
82 |
|
83 val configure_options = |
|
84 List("--disable-shared", "--enable-intinf-as-int", "--with-gmp") ::: |
|
85 info.options ::: options ::: (if (arch_64) Nil else List("--enable-compact32bit")) |
|
86 |
|
87 bash(root, |
|
88 info.setup + "\n" + |
105 info.setup + "\n" + |
89 """ |
106 """ |
90 [ -f Makefile ] && make distclean |
107 [ -f Makefile ] && make distclean |
91 { |
108 { |
92 ./configure --prefix="$PWD/target" """ + Bash.strings(configure_options) + """ |
109 ./configure --prefix="$PWD/target" """ + Bash.strings(configure_options) + """ |
93 rm -rf target |
110 rm -rf target |
94 make && make install |
111 make && make install |
95 } || { echo "Build failed" >&2; exit 2; } |
112 } || { echo "Build failed" >&2; exit 2; } |
96 """, redirect = true, echo = true).check |
113 """, redirect = true, progress = progress).check |
97 |
114 |
98 |
115 |
99 /* sha1 library */ |
116 /* sha1 library */ |
100 |
117 |
101 val sha1_files = |
118 val sha1_files = |
102 if (sha1_root.isDefined) { |
119 if (sha1_root.isDefined) { |
103 val dir1 = sha1_root.get |
120 val dir1 = sha1_root.get |
104 bash(dir1, "./build " + sha1_platform, redirect = true, echo = true).check |
121 bash(dir1, platform, mingw, "./build " + sha1_platform, redirect = true, |
|
122 progress = progress).check |
105 |
123 |
106 val dir2 = dir1 + Path.explode(sha1_platform) |
124 val dir2 = dir1 + Path.explode(sha1_platform) |
107 File.read_dir(dir2).map(entry => dir2 + Path.basic(entry)) |
125 File.read_dir(dir2).map(entry => dir2 + Path.basic(entry)) |
108 } |
126 } |
109 else Nil |
127 else Nil |
179 |
199 |
180 def build_polyml( |
200 def build_polyml( |
181 options: List[String] = Nil, |
201 options: List[String] = Nil, |
182 mingw: MinGW = MinGW.none, |
202 mingw: MinGW = MinGW.none, |
183 component_name: String = "", |
203 component_name: String = "", |
|
204 gmp_url: String = "", |
184 polyml_url: String = default_polyml_url, |
205 polyml_url: String = default_polyml_url, |
185 polyml_version: String = default_polyml_version, |
206 polyml_version: String = default_polyml_version, |
186 polyml_name: String = default_polyml_name, |
207 polyml_name: String = default_polyml_name, |
187 sha1_url: String = default_sha1_url, |
208 sha1_url: String = default_sha1_url, |
188 sha1_version: String = default_sha1_version, |
209 sha1_version: String = default_sha1_version, |
189 target_dir: Path = Path.current, |
210 target_dir: Path = Path.current, |
190 progress: Progress = new Progress |
211 progress: Progress = new Progress |
191 ): Unit = { |
212 ): Unit = { |
|
213 val platform = Isabelle_Platform.self |
|
214 |
|
215 |
192 /* component */ |
216 /* component */ |
193 |
217 |
194 val component_name1 = if (component_name.isEmpty) "polyml-" + polyml_version else component_name |
218 val component_name1 = if (component_name.isEmpty) "polyml-" + polyml_version else component_name |
195 val component_dir = |
219 val component_dir = |
196 Components.Directory(target_dir + Path.basic(component_name1)).create(progress = progress) |
220 Components.Directory(target_dir + Path.basic(component_name1)).create(progress = progress) |
197 |
221 |
198 |
222 |
199 /* download and build */ |
223 /* download and build */ |
200 |
224 |
201 Isabelle_System.with_tmp_dir("download") { download_dir => |
225 Isabelle_System.with_tmp_dir("download") { download_dir => |
|
226 /* GMP library */ |
|
227 |
|
228 val gmp_root: Option[Path] = |
|
229 if (gmp_url.isEmpty) None |
|
230 else { |
|
231 val gmp_dir = Isabelle_System.make_directory(download_dir + Path.basic("gmp")) |
|
232 |
|
233 val archive_name = |
|
234 Url.get_base_name(gmp_url).getOrElse(error("No base name in " + quote(gmp_url))) |
|
235 val archive = download_dir + Path.basic(archive_name) |
|
236 Isabelle_System.download_file(gmp_url, archive, progress = progress) |
|
237 Isabelle_System.extract(archive, gmp_dir, strip = true) |
|
238 |
|
239 val platform_arch = if (platform.is_arm) "aarch64" else "x86_64" |
|
240 val platform_os = |
|
241 if (platform.is_linux) "unknown-linux-gnu" |
|
242 else if (platform.is_windows) "w64-mingw32" |
|
243 else if (platform.is_macos) """apple-darwin"$(uname -r)"""" |
|
244 else error("Bad platform " + platform) |
|
245 |
|
246 progress.echo("Building GMP library ...") |
|
247 bash(gmp_dir, platform, mingw, progress = progress, |
|
248 script = Library.make_lines( |
|
249 "set -e", |
|
250 "./configure --enable-cxx --build=" + platform_arch + "-" + platform_os + |
|
251 """ --prefix="$PWD/target"""", |
|
252 "make", |
|
253 "make check", |
|
254 "make install" |
|
255 )).check |
|
256 |
|
257 Some(gmp_dir + Path.explode("target")) |
|
258 } |
|
259 |
|
260 |
|
261 /* Poly/ML */ |
|
262 |
202 val List(polyml_download, sha1_download) = |
263 val List(polyml_download, sha1_download) = |
203 for { |
264 for { |
204 (url, version, target) <- |
265 (url, version, target) <- |
205 List((polyml_url, polyml_version, "src"), (sha1_url, sha1_version, "sha1")) |
266 List((polyml_url, polyml_version, "src"), (sha1_url, sha1_version, "sha1")) |
206 } yield { |
267 } yield { |
288 component_polyml", which can be used in the polyml component directory as |
350 component_polyml", which can be used in the polyml component directory as |
289 follows: |
351 follows: |
290 |
352 |
291 * Linux and macOS |
353 * Linux and macOS |
292 |
354 |
293 $ isabelle component_polyml |
355 $ isabelle component_polyml -G: |
294 |
356 |
295 * Windows (Cygwin shell) |
357 * Windows (Cygwin shell) |
296 |
358 |
297 $ isabelle component_polyml -M /cygdrive/c/msys64 |
359 $ isabelle component_polyml -G: -M /cygdrive/c/msys64 |
298 |
|
299 |
|
300 Building libgmp on macOS |
|
301 ======================== |
|
302 |
|
303 The build_polyml invocations above implicitly use the GNU Multiple Precision |
|
304 Arithmetic Library (libgmp), but that is not available on macOS by default. |
|
305 Appending "--without-gmp" to the command-line omits this library. Building |
|
306 libgmp properly from sources works as follows (library headers and binaries |
|
307 will be placed in /usr/local). |
|
308 |
|
309 * Download: |
|
310 |
|
311 $ curl https://gmplib.org/download/gmp/gmp-6.3.0.tar.bz2 | tar xjf - |
|
312 $ cd gmp-6.3.0 |
|
313 |
|
314 * build: |
|
315 |
|
316 $ make distclean |
|
317 |
|
318 #Intel |
|
319 $ ./configure --enable-cxx --build=core2-apple-darwin"$(uname -r)" |
|
320 |
|
321 #ARM |
|
322 $ ./configure --enable-cxx --build=aarch64-apple-darwin"$(uname -r)" |
|
323 |
|
324 $ make && make check |
|
325 $ sudo make install |
|
326 |
360 |
327 |
361 |
328 Makarius |
362 Makarius |
329 """ + Date.Format.date(Date.now()) + "\n") |
363 """ + Date.Format.date(Date.now()) + "\n") |
330 } |
364 } |
334 /** Isabelle tool wrappers **/ |
368 /** Isabelle tool wrappers **/ |
335 |
369 |
336 val isabelle_tool1 = |
370 val isabelle_tool1 = |
337 Isabelle_Tool("make_polyml", "make Poly/ML from existing sources", Scala_Project.here, |
371 Isabelle_Tool("make_polyml", "make Poly/ML from existing sources", Scala_Project.here, |
338 { args => |
372 { args => |
|
373 var gmp_root: Option[Path] = None |
339 var mingw = MinGW.none |
374 var mingw = MinGW.none |
340 var arch_64 = false |
375 var arch_64 = false |
341 var sha1_root: Option[Path] = None |
376 var sha1_root: Option[Path] = None |
342 |
377 |
343 val getopts = Getopts(""" |
378 val getopts = Getopts(""" |
344 Usage: isabelle make_polyml [OPTIONS] ROOT [CONFIGURE_OPTIONS] |
379 Usage: isabelle make_polyml [OPTIONS] ROOT [CONFIGURE_OPTIONS] |
345 |
380 |
346 Options are: |
381 Options are: |
|
382 -G DIR GMP library root |
347 -M DIR msys/mingw root specification for Windows |
383 -M DIR msys/mingw root specification for Windows |
348 -m ARCH processor architecture (32 or 64, default: """ + |
384 -m ARCH processor architecture (32 or 64, default: """ + |
349 (if (arch_64) "64" else "32") + """) |
385 (if (arch_64) "64" else "32") + """) |
350 -s DIR sha1 sources, see https://isabelle.sketis.net/repos/sha1 |
386 -s DIR sha1 sources, see https://isabelle.sketis.net/repos/sha1 |
351 |
387 |
352 Make Poly/ML in the ROOT directory of its sources, with additional |
388 Make Poly/ML in the ROOT directory of its sources, with additional |
353 CONFIGURE_OPTIONS (e.g. --without-gmp). |
389 CONFIGURE_OPTIONS. |
354 """, |
390 """, |
|
391 "G:" -> (arg => gmp_root = Some(Path.explode(arg))), |
355 "M:" -> (arg => mingw = MinGW(Path.explode(arg))), |
392 "M:" -> (arg => mingw = MinGW(Path.explode(arg))), |
356 "m:" -> |
393 "m:" -> |
357 { |
394 { |
358 case "32" => arch_64 = false |
395 case "32" => arch_64 = false |
359 case "64" => arch_64 = true |
396 case "64" => arch_64 = true |
365 val (root, options) = |
402 val (root, options) = |
366 more_args match { |
403 more_args match { |
367 case root :: options => (Path.explode(root), options) |
404 case root :: options => (Path.explode(root), options) |
368 case Nil => getopts.usage() |
405 case Nil => getopts.usage() |
369 } |
406 } |
370 make_polyml(root, sha1_root = sha1_root, progress = new Console_Progress, |
407 make_polyml(root, gmp_root = gmp_root, sha1_root = sha1_root, |
371 arch_64 = arch_64, options = options, mingw = mingw) |
408 progress = new Console_Progress, arch_64 = arch_64, options = options, mingw = mingw) |
372 }) |
409 }) |
373 |
410 |
374 val isabelle_tool2 = |
411 val isabelle_tool2 = |
375 Isabelle_Tool("component_polyml", "build Poly/ML component from official repository", |
412 Isabelle_Tool("component_polyml", "build Poly/ML component from official repository", |
376 Scala_Project.here, |
413 Scala_Project.here, |
377 { args => |
414 { args => |
378 var target_dir = Path.current |
415 var target_dir = Path.current |
|
416 var gmp_url = "" |
379 var mingw = MinGW.none |
417 var mingw = MinGW.none |
380 var component_name = "" |
418 var component_name = "" |
381 var sha1_url = default_sha1_url |
419 var sha1_url = default_sha1_url |
382 var sha1_version = default_sha1_version |
420 var sha1_version = default_sha1_version |
383 var polyml_url = default_polyml_url |
421 var polyml_url = default_polyml_url |
384 var polyml_version = default_polyml_version |
422 var polyml_version = default_polyml_version |
385 var polyml_name = default_polyml_name |
423 var polyml_name = default_polyml_name |
386 var verbose = false |
424 var verbose = false |
387 |
425 |
388 val getopts = Getopts(""" |
426 val getopts = Getopts(""" |
389 Usage: isabelle component_polyml [OPTIONS] [CONFIGURE_OPTIONS] |
427 Usage: isabelle component_polyml [OPTIONS] [CONFIGURE_OPTIONS] |
390 |
428 |
391 Options are: |
429 Options are: |
392 -D DIR target directory (default ".") |
430 -D DIR target directory (default ".") |
|
431 -G URL build GMP library from source: explicit URL or ":" for |
|
432 """ + standard_gmp_url + """ |
393 -M DIR msys/mingw root specification for Windows |
433 -M DIR msys/mingw root specification for Windows |
394 -N NAME component name (default: derived from Poly/ML version) |
434 -N NAME component name (default: derived from Poly/ML version) |
395 -S URL SHA1 repository archive area |
435 -S URL SHA1 repository archive area |
396 (default: """ + quote(default_sha1_url) + """) |
436 (default: """ + quote(default_sha1_url) + """) |
397 -T VERSION SHA1 version (default: """ + quote(default_sha1_version) + """) |
437 -T VERSION SHA1 version (default: """ + quote(default_sha1_version) + """) |
400 -V VERSION Poly/ML version (default: """ + quote(default_polyml_version) + """) |
440 -V VERSION Poly/ML version (default: """ + quote(default_polyml_version) + """) |
401 -W NAME Poly/ML name (default: """ + quote(default_polyml_name) + """) |
441 -W NAME Poly/ML name (default: """ + quote(default_polyml_name) + """) |
402 -v verbose |
442 -v verbose |
403 |
443 |
404 Download and build Poly/ML component from source repositories, with additional |
444 Download and build Poly/ML component from source repositories, with additional |
405 CONFIGURE_OPTIONS (e.g. --without-gmp). |
445 CONFIGURE_OPTIONS. |
406 """, |
446 """, |
407 "D:" -> (arg => target_dir = Path.explode(arg)), |
447 "D:" -> (arg => target_dir = Path.explode(arg)), |
|
448 "G:" -> (arg => gmp_url = if (arg == ":") standard_gmp_url else arg), |
408 "M:" -> (arg => mingw = MinGW(Path.explode(arg))), |
449 "M:" -> (arg => mingw = MinGW(Path.explode(arg))), |
409 "N:" -> (arg => component_name = arg), |
450 "N:" -> (arg => component_name = arg), |
410 "S:" -> (arg => sha1_url = arg), |
451 "S:" -> (arg => sha1_url = arg), |
411 "T:" -> (arg => sha1_version = arg), |
452 "T:" -> (arg => sha1_version = arg), |
412 "U:" -> (arg => polyml_url = arg), |
453 "U:" -> (arg => polyml_url = arg), |
417 val options = getopts(args) |
458 val options = getopts(args) |
418 |
459 |
419 val progress = new Console_Progress(verbose = verbose) |
460 val progress = new Console_Progress(verbose = verbose) |
420 |
461 |
421 build_polyml(options = options, mingw = mingw, component_name = component_name, |
462 build_polyml(options = options, mingw = mingw, component_name = component_name, |
422 polyml_url = polyml_url, polyml_version = polyml_version, polyml_name = polyml_name, |
463 gmp_url = gmp_url, polyml_url = polyml_url, polyml_version = polyml_version, |
423 sha1_url = sha1_url, sha1_version = sha1_version, target_dir = target_dir, |
464 polyml_name = polyml_name, sha1_url = sha1_url, sha1_version = sha1_version, |
424 progress = progress) |
465 target_dir = target_dir, progress = progress) |
425 }) |
466 }) |
426 } |
467 } |