author | wenzelm |
Tue, 29 Jan 2019 22:47:45 +0100 | |
changeset 69754 | 8d548b8f63ca |
parent 69425 | 94f6ca69d983 |
child 71601 | 97ccf48c2f0c |
permissions | -rw-r--r-- |
64929 | 1 |
/* Title: Pure/Admin/build_jdk.scala |
2 |
Author: Makarius |
|
3 |
||
4 |
Build Isabelle jdk component from original platform installations. |
|
5 |
*/ |
|
6 |
||
7 |
package isabelle |
|
8 |
||
9 |
||
69186
573b7fbd96a8
updated to jdk-11+28 from https://adoptopenjdk.net -- with proper font rendering on Linux;
wenzelm
parents:
69128
diff
changeset
|
10 |
import java.io.{File => JFile} |
64933 | 11 |
import java.nio.file.Files |
64934 | 12 |
import java.nio.file.attribute.PosixFilePermission |
64933 | 13 |
|
64929 | 14 |
import scala.util.matching.Regex |
15 |
||
16 |
||
17 |
object Build_JDK |
|
18 |
{ |
|
19 |
/* version */ |
|
20 |
||
69128 | 21 |
def detect_version(s: String): String = |
64929 | 22 |
{ |
69754 | 23 |
val Version_Dir_Entry = """^jdk-([0-9.]+\+\d+)$""".r |
64929 | 24 |
s match { |
69128 | 25 |
case Version_Dir_Entry(version) => version |
64929 | 26 |
case _ => error("Cannot detect JDK version from " + quote(s)) |
27 |
} |
|
28 |
} |
|
29 |
||
30 |
||
31 |
/* platform */ |
|
32 |
||
69128 | 33 |
sealed case class JDK_Platform(name: String, home: String, exe: String, regex: Regex) |
64929 | 34 |
{ |
35 |
override def toString: String = name |
|
36 |
||
37 |
def detect(jdk_dir: Path): Boolean = |
|
38 |
{ |
|
39 |
val path = jdk_dir + Path.explode(exe) |
|
40 |
if (path.is_file) { |
|
41 |
val file_descr = Isabelle_System.bash("file -b " + File.bash_path(path)).check.out |
|
42 |
regex.pattern.matcher(file_descr).matches |
|
43 |
} |
|
44 |
else false |
|
45 |
} |
|
46 |
} |
|
47 |
val jdk_platforms = |
|
66906 | 48 |
List( |
69128 | 49 |
JDK_Platform("x86_64-linux", ".", "bin/java", """.*ELF 64-bit.*x86[-_]64.*""".r), |
50 |
JDK_Platform("x86_64-windows", ".", "bin/java.exe", """.*PE32\+ executable.*x86[-_]64.*""".r), |
|
51 |
JDK_Platform("x86_64-darwin", "Contents/Home", "Contents/Home/bin/java", |
|
52 |
""".*Mach-O 64-bit.*x86[-_]64.*""".r)) |
|
64929 | 53 |
|
54 |
||
55 |
/* README */ |
|
56 |
||
69128 | 57 |
def readme(version: String): String = |
58 |
"""This is OpenJDK """ + version + """ as required for Isabelle. |
|
64929 | 59 |
|
69186
573b7fbd96a8
updated to jdk-11+28 from https://adoptopenjdk.net -- with proper font rendering on Linux;
wenzelm
parents:
69128
diff
changeset
|
60 |
See https://adoptopenjdk.net for the original downloads, which are covered |
69128 | 61 |
the GPL2 (with various liberal exceptions, see legal/*). |
64929 | 62 |
|
63 |
Linux, Windows, Mac OS X all work uniformly, depending on certain |
|
64 |
platform-specific subdirectories. |
|
65 |
""" |
|
66 |
||
67 |
||
68 |
/* settings */ |
|
69 |
||
70 |
val settings = |
|
71 |
"""# -*- shell-script -*- :mode=shellscript: |
|
72 |
||
73 |
case "$ISABELLE_PLATFORM_FAMILY" in |
|
74 |
linux) |
|
66906 | 75 |
ISABELLE_JAVA_PLATFORM="$ISABELLE_PLATFORM64" |
64929 | 76 |
ISABELLE_JDK_HOME="$COMPONENT/$ISABELLE_JAVA_PLATFORM" |
77 |
;; |
|
78 |
windows) |
|
66906 | 79 |
ISABELLE_JAVA_PLATFORM="$ISABELLE_WINDOWS_PLATFORM64" |
64929 | 80 |
ISABELLE_JDK_HOME="$COMPONENT/$ISABELLE_JAVA_PLATFORM" |
81 |
;; |
|
82 |
macos) |
|
66906 | 83 |
ISABELLE_JAVA_PLATFORM="$ISABELLE_PLATFORM64" |
84 |
ISABELLE_JDK_HOME="$COMPONENT/$ISABELLE_JAVA_PLATFORM/Contents/Home" |
|
64929 | 85 |
;; |
86 |
esac |
|
87 |
""" |
|
88 |
||
89 |
||
90 |
/* extract archive */ |
|
91 |
||
69186
573b7fbd96a8
updated to jdk-11+28 from https://adoptopenjdk.net -- with proper font rendering on Linux;
wenzelm
parents:
69128
diff
changeset
|
92 |
private def suppress_name(name: String): Boolean = name.startsWith("._") |
573b7fbd96a8
updated to jdk-11+28 from https://adoptopenjdk.net -- with proper font rendering on Linux;
wenzelm
parents:
69128
diff
changeset
|
93 |
|
69128 | 94 |
def extract_archive(dir: Path, archive: Path): (String, JDK_Platform) = |
64929 | 95 |
{ |
96 |
try { |
|
97 |
val tmp_dir = dir + Path.explode("tmp") |
|
98 |
Isabelle_System.mkdirs(tmp_dir) |
|
69128 | 99 |
|
69367 | 100 |
if (archive.get_ext == "zip") { |
69128 | 101 |
Isabelle_System.bash( |
102 |
"unzip -x " + File.bash_path(archive.absolute), cwd = tmp_dir.file).check |
|
103 |
} |
|
104 |
else { |
|
69425 | 105 |
Isabelle_System.gnutar("-xzf " + File.bash_path(archive), dir = tmp_dir).check |
69128 | 106 |
} |
107 |
||
64929 | 108 |
val dir_entry = |
69186
573b7fbd96a8
updated to jdk-11+28 from https://adoptopenjdk.net -- with proper font rendering on Linux;
wenzelm
parents:
69128
diff
changeset
|
109 |
File.read_dir(tmp_dir).filterNot(suppress_name(_)) match { |
64929 | 110 |
case List(s) => s |
111 |
case _ => error("Archive contains multiple directories") |
|
112 |
} |
|
113 |
val version = detect_version(dir_entry) |
|
114 |
||
115 |
val jdk_dir = tmp_dir + Path.explode(dir_entry) |
|
116 |
val platform = |
|
117 |
jdk_platforms.find(_.detect(jdk_dir)) getOrElse error("Failed to detect JDK platform") |
|
118 |
||
119 |
val platform_dir = dir + Path.explode(platform.name) |
|
120 |
if (platform_dir.is_dir) error("Directory already exists: " + platform_dir) |
|
69128 | 121 |
|
69402
61f4c406d727
more direct File.link operation: avoid external process;
wenzelm
parents:
69395
diff
changeset
|
122 |
File.link(Path.current, jdk_dir + Path.explode(platform.home) + Path.explode("jre")) |
69128 | 123 |
|
64930 | 124 |
File.move(jdk_dir, platform_dir) |
64929 | 125 |
|
126 |
(version, platform) |
|
127 |
} |
|
128 |
catch { case ERROR(msg) => cat_error(msg, "The error(s) above occurred for " + archive) } |
|
129 |
} |
|
130 |
||
131 |
||
132 |
/* build jdk */ |
|
133 |
||
134 |
def build_jdk( |
|
135 |
archives: List[Path], |
|
136 |
progress: Progress = No_Progress, |
|
137 |
target_dir: Path = Path.current) |
|
138 |
{ |
|
139 |
if (Platform.is_windows) error("Cannot build jdk on Windows") |
|
140 |
||
141 |
Isabelle_System.with_tmp_dir("jdk")(dir => |
|
142 |
{ |
|
143 |
progress.echo("Extracting ...") |
|
144 |
val extracted = archives.map(extract_archive(dir, _)) |
|
145 |
||
146 |
val version = |
|
147 |
extracted.map(_._1).toSet.toList match { |
|
148 |
case List(version) => version |
|
149 |
case Nil => error("No archives") |
|
150 |
case versions => |
|
69128 | 151 |
error("Archives contain multiple JDK versions: " + commas_quote(versions)) |
64929 | 152 |
} |
153 |
||
154 |
val missing_platforms = |
|
155 |
jdk_platforms.filterNot(p1 => extracted.exists({ case (_, p2) => p1.name == p2.name })) |
|
156 |
if (missing_platforms.nonEmpty) |
|
157 |
error("Missing platforms: " + commas_quote(missing_platforms.map(_.name))) |
|
158 |
||
69128 | 159 |
val jdk_name = "jdk-" + version |
64929 | 160 |
val jdk_path = Path.explode(jdk_name) |
161 |
val component_dir = dir + jdk_path |
|
162 |
||
163 |
Isabelle_System.mkdirs(component_dir + Path.explode("etc")) |
|
69395
d1c4a1dee9e7
more explicit support for Isabelle system components;
wenzelm
parents:
69367
diff
changeset
|
164 |
File.write(Components.settings(component_dir), settings) |
64929 | 165 |
File.write(component_dir + Path.explode("README"), readme(version)) |
166 |
||
64930 | 167 |
for ((_, platform) <- extracted) |
168 |
File.move(dir + Path.explode(platform.name), component_dir) |
|
64929 | 169 |
|
64933 | 170 |
for (file <- File.find_files(component_dir.file, include_dirs = true)) { |
171 |
val path = file.toPath |
|
172 |
val perms = Files.getPosixFilePermissions(path) |
|
64934 | 173 |
perms.add(PosixFilePermission.OWNER_READ) |
174 |
perms.add(PosixFilePermission.GROUP_READ) |
|
175 |
perms.add(PosixFilePermission.OTHERS_READ) |
|
176 |
perms.add(PosixFilePermission.OWNER_WRITE) |
|
64933 | 177 |
if (file.isDirectory) { |
64934 | 178 |
perms.add(PosixFilePermission.OWNER_WRITE) |
179 |
perms.add(PosixFilePermission.OWNER_EXECUTE) |
|
180 |
perms.add(PosixFilePermission.GROUP_EXECUTE) |
|
181 |
perms.add(PosixFilePermission.OTHERS_EXECUTE) |
|
64933 | 182 |
} |
183 |
Files.setPosixFilePermissions(path, perms) |
|
184 |
} |
|
64931 | 185 |
|
186 |
File.find_files((component_dir + Path.explode("x86_64-darwin")).file, |
|
69186
573b7fbd96a8
updated to jdk-11+28 from https://adoptopenjdk.net -- with proper font rendering on Linux;
wenzelm
parents:
69128
diff
changeset
|
187 |
file => suppress_name(file.getName)).foreach(_.delete) |
64929 | 188 |
|
189 |
progress.echo("Sharing ...") |
|
64934 | 190 |
val main_dir :: other_dirs = |
191 |
jdk_platforms.map(platform => (component_dir + Path.explode(platform.name)).file.toPath) |
|
192 |
for { |
|
193 |
file1 <- File.find_files(main_dir.toFile).iterator |
|
194 |
path1 = file1.toPath |
|
195 |
dir2 <- other_dirs.iterator |
|
196 |
} { |
|
197 |
val path2 = dir2.resolve(main_dir.relativize(path1)) |
|
198 |
val file2 = path2.toFile |
|
65879
a43a079156a6
avoid mixture of symlinks and hardlinks, which causes problems with BSD tar on macOS Sierra;
wenzelm
parents:
65873
diff
changeset
|
199 |
if (!Files.isSymbolicLink(path2) && file2.isFile && File.eq_content(file1, file2)) { |
64934 | 200 |
file2.delete |
201 |
Files.createLink(path2, path1) |
|
202 |
} |
|
203 |
} |
|
64929 | 204 |
|
205 |
progress.echo("Archiving ...") |
|
69425 | 206 |
Isabelle_System.gnutar( |
207 |
"-czf " + File.bash_path(target_dir + jdk_path.ext("tar.gz")) + " " + jdk_name, |
|
208 |
dir = dir).check |
|
64929 | 209 |
}) |
210 |
} |
|
211 |
||
212 |
||
213 |
/* Isabelle tool wrapper */ |
|
214 |
||
215 |
val isabelle_tool = |
|
69128 | 216 |
Isabelle_Tool("build_jdk", "build Isabelle jdk component from original archives", |
64929 | 217 |
args => |
218 |
{ |
|
219 |
var target_dir = Path.current |
|
220 |
||
221 |
val getopts = Getopts(""" |
|
65873 | 222 |
Usage: isabelle build_jdk [OPTIONS] ARCHIVES... |
64929 | 223 |
|
224 |
Options are: |
|
225 |
-D DIR target directory (default ".") |
|
226 |
||
69128 | 227 |
Build jdk component from tar.gz archives, with original jdk archives |
66906 | 228 |
for x86_64 Linux, Windows, Mac OS X. |
64929 | 229 |
""", |
230 |
"D:" -> (arg => target_dir = Path.explode(arg))) |
|
231 |
||
232 |
val more_args = getopts(args) |
|
233 |
if (more_args.isEmpty) getopts.usage() |
|
234 |
||
235 |
val archives = more_args.map(Path.explode(_)) |
|
236 |
val progress = new Console_Progress() |
|
237 |
||
238 |
build_jdk(archives = archives, progress = progress, target_dir = target_dir) |
|
69277
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
wenzelm
parents:
69186
diff
changeset
|
239 |
}) |
64929 | 240 |
} |