author | wenzelm |
Fri, 12 Sep 2025 17:07:21 +0200 | |
changeset 83138 | c66d77fb729e |
parent 83012 | fb5310760fce |
permissions | -rw-r--r-- |
78415
a4dee214dfcf
clarified file location: to be used by regular Isabelle/Scala tools;
wenzelm
parents:
78158
diff
changeset
|
1 |
/* Title: Pure/System/other_isabelle.scala |
64188 | 2 |
Author: Makarius |
3 |
||
77082 | 4 |
Manage other Isabelle distributions: support historic versions starting from |
5 |
tag "build_history_base". |
|
64188 | 6 |
*/ |
7 |
||
8 |
package isabelle |
|
9 |
||
10 |
||
75393 | 11 |
object Other_Isabelle { |
77050 | 12 |
def apply( |
77093 | 13 |
root: Path, |
77050 | 14 |
isabelle_identifier: String = "", |
77093 | 15 |
ssh: SSH.System = SSH.Local, |
77050 | 16 |
progress: Progress = new Progress |
17 |
): Other_Isabelle = { |
|
77093 | 18 |
val (isabelle_home, url_prefix) = |
19 |
ssh match { |
|
20 |
case session: SSH.Session => (ssh.absolute_path(root), session.rsync_prefix) |
|
21 |
case _ => |
|
22 |
if (proper_string(System.getenv("ISABELLE_SETTINGS_PRESENT")).isDefined) { |
|
82725 | 23 |
error( |
24 |
"Cannot manage other Isabelle distribution: ISABELLE_SETTINGS_PRESENT " + |
|
25 |
"-- consider using SSH") |
|
77093 | 26 |
} |
27 |
(root.canonical, "") |
|
28 |
} |
|
29 |
val isabelle_home_url = url_prefix + isabelle_home.implode |
|
30 |
new Other_Isabelle(isabelle_home, isabelle_identifier, isabelle_home_url, ssh, progress) |
|
77050 | 31 |
} |
67045 | 32 |
} |
33 |
||
77041 | 34 |
final class Other_Isabelle private( |
67045 | 35 |
val isabelle_home: Path, |
36 |
val isabelle_identifier: String, |
|
77093 | 37 |
isabelle_home_url: String, |
80023 | 38 |
val ssh: SSH.System, |
39 |
val progress: Progress |
|
82718
e1a8753eaad7
clarified signature: more modular, avoid adhoc mixins;
wenzelm
parents:
82716
diff
changeset
|
40 |
) { |
80021
ba06861e91f9
proper services for Setup_Tool --- avoid hardwired stuff;
wenzelm
parents:
79681
diff
changeset
|
41 |
other_isabelle => |
ba06861e91f9
proper services for Setup_Tool --- avoid hardwired stuff;
wenzelm
parents:
79681
diff
changeset
|
42 |
|
77093 | 43 |
override def toString: String = isabelle_home_url |
82725 | 44 |
def error_context: String = "\nThe error(s) above occurred for other Isabelle " + toString |
67046 | 45 |
|
64188 | 46 |
|
47 |
/* static system */ |
|
48 |
||
80231 | 49 |
def bash_context(script: String, cwd: Path = isabelle_home): String = |
80227
af6b60c75d7d
clarified context for (remote) bash scripts: export variables are optional, support cwd;
wenzelm
parents:
80223
diff
changeset
|
50 |
Bash.context(script, |
af6b60c75d7d
clarified context for (remote) bash scripts: export variables are optional, support cwd;
wenzelm
parents:
80223
diff
changeset
|
51 |
user_home = ssh.user_home, |
af6b60c75d7d
clarified context for (remote) bash scripts: export variables are optional, support cwd;
wenzelm
parents:
80223
diff
changeset
|
52 |
isabelle_identifier = isabelle_identifier, |
80231 | 53 |
cwd = cwd) |
80227
af6b60c75d7d
clarified context for (remote) bash scripts: export variables are optional, support cwd;
wenzelm
parents:
80223
diff
changeset
|
54 |
|
65930 | 55 |
def bash( |
77042 | 56 |
script: String, |
80231 | 57 |
cwd: Path = isabelle_home, |
82712
2f22014a3a49
more robust: inspect true ML environment instead of reconstructing it externally;
wenzelm
parents:
82711
diff
changeset
|
58 |
input: String = "", |
77042 | 59 |
redirect: Boolean = false, |
60 |
echo: Boolean = false, |
|
61 |
strict: Boolean = true |
|
62 |
): Process_Result = { |
|
80232 | 63 |
ssh.bash(bash_context(script, cwd = cwd), |
77093 | 64 |
progress_stdout = progress.echo_if(echo, _), |
65 |
progress_stderr = progress.echo_if(echo, _), |
|
82712
2f22014a3a49
more robust: inspect true ML environment instead of reconstructing it externally;
wenzelm
parents:
82711
diff
changeset
|
66 |
input = input, |
77093 | 67 |
redirect = redirect, |
68 |
settings = false, |
|
69 |
strict = strict) |
|
77042 | 70 |
} |
64188 | 71 |
|
69166 | 72 |
def getenv(name: String): String = |
80232 | 73 |
ssh.execute(bash_context("bin/isabelle getenv -b " + Bash.string(name)), |
74 |
settings = false).check.out |
|
69166 | 75 |
|
82711 | 76 |
def getenv_strict(name: String): String = |
77 |
proper_string(getenv(name)) getOrElse |
|
82725 | 78 |
error("Undefined Isabelle environment variable: " + quote(name) + error_context) |
82711 | 79 |
|
77080
7e11e96a922d
more formal Other_Isabelle.settings, with derived expand_path / bash_path;
wenzelm
parents:
77078
diff
changeset
|
80 |
val settings: Isabelle_System.Settings = (name: String) => getenv(name) |
7e11e96a922d
more formal Other_Isabelle.settings, with derived expand_path / bash_path;
wenzelm
parents:
77078
diff
changeset
|
81 |
|
7e11e96a922d
more formal Other_Isabelle.settings, with derived expand_path / bash_path;
wenzelm
parents:
77078
diff
changeset
|
82 |
def expand_path(path: Path): Path = path.expand_env(settings) |
7e11e96a922d
more formal Other_Isabelle.settings, with derived expand_path / bash_path;
wenzelm
parents:
77078
diff
changeset
|
83 |
def bash_path(path: Path): String = Bash.string(expand_path(path).implode) |
64188 | 84 |
|
82716 | 85 |
val isabelle_home_user: Path = expand_path(Path.explode("$ISABELLE_HOME_USER")) |
86 |
||
87 |
def host_db: Path = isabelle_home_user + Path.explode("host.db") |
|
88 |
||
89 |
def etc: Path = isabelle_home_user + Path.explode("etc") |
|
90 |
def etc_settings: Path = etc + Path.explode("settings") |
|
91 |
def etc_preferences: Path = etc + Path.explode("preferences") |
|
92 |
||
83012
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
93 |
def cleanup(): Unit = |
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
94 |
ssh.delete(host_db, etc_settings, etc_preferences, etc, isabelle_home_user) |
64188 | 95 |
|
73625
f8f065e20837
misc tuning and clarification: more explicit types Release_Context, Release_Archive;
wenzelm
parents:
73522
diff
changeset
|
96 |
|
69388 | 97 |
/* components */ |
98 |
||
99 |
def init_components( |
|
77128
f40c36ab154d
clarified names to emphasize suble differences in meaning;
wenzelm
parents:
77124
diff
changeset
|
100 |
components_base: String = Components.dynamic_components_base, |
77055 | 101 |
catalogs: List[String] = Components.default_catalogs, |
75393 | 102 |
components: List[String] = Nil |
103 |
): List[String] = { |
|
77088
6e2c6ccc5dc0
clarified defaults: imitate "isabelle components -I" without further parameters;
wenzelm
parents:
77087
diff
changeset
|
104 |
val admin = Components.admin(Path.ISABELLE_HOME).implode |
73240
3e963d68d394
more robust ISABELLE_COMPONENT_REPOSITORY: use current value of managing process to avoid its fluctuation in ancient history;
wenzelm
parents:
72375
diff
changeset
|
105 |
|
77090 | 106 |
catalogs.map(name => |
107 |
"init_components " + quote(components_base) + " " + quote(admin + "/" + name)) ::: |
|
108 |
components.map(name => |
|
109 |
"init_component " + quote(components_base) + "/" + name) |
|
69388 | 110 |
} |
111 |
||
77097
023273cf2651
clean components more accurately: purge other platforms or archives;
wenzelm
parents:
77095
diff
changeset
|
112 |
def resolve_components( |
023273cf2651
clean components more accurately: purge other platforms or archives;
wenzelm
parents:
77095
diff
changeset
|
113 |
echo: Boolean = false, |
78610 | 114 |
clean_platforms: Option[List[Platform.Family]] = None, |
77124
be90af1e3254
proper use of current ISABELLE_COMPONENT_REPOSITORY from the managing Isabelle system (amending 3e963d68d394);
wenzelm
parents:
77123
diff
changeset
|
115 |
clean_archives: Boolean = false, |
77128
f40c36ab154d
clarified names to emphasize suble differences in meaning;
wenzelm
parents:
77124
diff
changeset
|
116 |
component_repository: String = Components.static_component_repository |
77097
023273cf2651
clean components more accurately: purge other platforms or archives;
wenzelm
parents:
77095
diff
changeset
|
117 |
): Unit = { |
77093 | 118 |
val missing = Path.split(getenv("ISABELLE_COMPONENTS_MISSING")) |
119 |
for (path <- missing) { |
|
77097
023273cf2651
clean components more accurately: purge other platforms or archives;
wenzelm
parents:
77095
diff
changeset
|
120 |
Components.resolve(path.dir, path.file_name, |
023273cf2651
clean components more accurately: purge other platforms or archives;
wenzelm
parents:
77095
diff
changeset
|
121 |
clean_platforms = clean_platforms, |
023273cf2651
clean components more accurately: purge other platforms or archives;
wenzelm
parents:
77095
diff
changeset
|
122 |
clean_archives = clean_archives, |
77124
be90af1e3254
proper use of current ISABELLE_COMPONENT_REPOSITORY from the managing Isabelle system (amending 3e963d68d394);
wenzelm
parents:
77123
diff
changeset
|
123 |
component_repository = component_repository, |
77097
023273cf2651
clean components more accurately: purge other platforms or archives;
wenzelm
parents:
77095
diff
changeset
|
124 |
ssh = ssh, |
77093 | 125 |
progress = if (echo) progress else new Progress) |
126 |
} |
|
127 |
} |
|
128 |
||
77094 | 129 |
def scala_build(fresh: Boolean = false, echo: Boolean = false): Unit = { |
130 |
if (fresh) ssh.rm_tree(isabelle_home + Path.explode("lib/classes")) |
|
131 |
||
132 |
val dummy_stty = Path.explode("~~/lib/dummy_stty/stty") |
|
133 |
val dummy_stty_remote = expand_path(dummy_stty) |
|
134 |
if (!ssh.is_file(dummy_stty_remote)) { |
|
135 |
ssh.make_directory(dummy_stty_remote.dir) |
|
136 |
ssh.write_file(dummy_stty_remote, dummy_stty) |
|
78158 | 137 |
ssh.set_executable(dummy_stty_remote) |
77094 | 138 |
} |
139 |
try { |
|
140 |
bash( |
|
141 |
"export PATH=\"" + bash_path(dummy_stty_remote.dir) + ":$PATH\"\n" + |
|
142 |
"export CLASSPATH=" + Bash.string(getenv("ISABELLE_CLASSPATH")) + "\n" + |
|
143 |
"bin/isabelle jedit -b", echo = echo).check |
|
144 |
} |
|
82725 | 145 |
catch { |
146 |
case ERROR(msg) => |
|
147 |
error("Failed to build Isabelle/Scala/Java modules:\n" + msg + error_context) |
|
148 |
} |
|
77094 | 149 |
} |
150 |
||
69388 | 151 |
|
69168
68816d1c73a7
eliminated "isabelle makedist" -- prefer Scala over bash/perl scripting;
wenzelm
parents:
69166
diff
changeset
|
152 |
/* settings */ |
68816d1c73a7
eliminated "isabelle makedist" -- prefer Scala over bash/perl scripting;
wenzelm
parents:
69166
diff
changeset
|
153 |
|
68816d1c73a7
eliminated "isabelle makedist" -- prefer Scala over bash/perl scripting;
wenzelm
parents:
69166
diff
changeset
|
154 |
def clean_settings(): Boolean = |
77093 | 155 |
if (!ssh.is_file(etc_settings)) true |
156 |
else if (ssh.read(etc_settings).startsWith("# generated by Isabelle")) { |
|
157 |
ssh.delete(etc_settings) |
|
77042 | 158 |
true |
69168
68816d1c73a7
eliminated "isabelle makedist" -- prefer Scala over bash/perl scripting;
wenzelm
parents:
69166
diff
changeset
|
159 |
} |
68816d1c73a7
eliminated "isabelle makedist" -- prefer Scala over bash/perl scripting;
wenzelm
parents:
69166
diff
changeset
|
160 |
else false |
64188 | 161 |
|
75393 | 162 |
def init_settings(settings: List[String]): Unit = { |
77078 | 163 |
if (clean_settings()) { |
77093 | 164 |
ssh.make_directory(etc_settings.dir) |
165 |
ssh.write(etc_settings, |
|
77078 | 166 |
"# generated by Isabelle " + Date.now() + "\n" + |
167 |
"#-*- shell-script -*- :mode=shellscript:\n" + |
|
168 |
settings.mkString("\n", "\n", "\n")) |
|
77042 | 169 |
} |
82725 | 170 |
else error("Cannot proceed with existing user settings file: " + etc_settings + error_context) |
64188 | 171 |
} |
69168
68816d1c73a7
eliminated "isabelle makedist" -- prefer Scala over bash/perl scripting;
wenzelm
parents:
69166
diff
changeset
|
172 |
|
79681
df1059ea8846
propagate property "isabelle.debug", notably for Java/Scala exception trace;
wenzelm
parents:
79633
diff
changeset
|
173 |
def debug_settings(): List[String] = { |
df1059ea8846
propagate property "isabelle.debug", notably for Java/Scala exception trace;
wenzelm
parents:
79633
diff
changeset
|
174 |
val debug = System.getProperty("isabelle.debug", "") == "true" |
df1059ea8846
propagate property "isabelle.debug", notably for Java/Scala exception trace;
wenzelm
parents:
79633
diff
changeset
|
175 |
if (debug) { |
df1059ea8846
propagate property "isabelle.debug", notably for Java/Scala exception trace;
wenzelm
parents:
79633
diff
changeset
|
176 |
List("ISABELLE_JAVA_SYSTEM_OPTIONS=\"$ISABELLE_JAVA_SYSTEM_OPTIONS -Disabelle.debug=true\"") |
df1059ea8846
propagate property "isabelle.debug", notably for Java/Scala exception trace;
wenzelm
parents:
79633
diff
changeset
|
177 |
} |
df1059ea8846
propagate property "isabelle.debug", notably for Java/Scala exception trace;
wenzelm
parents:
79633
diff
changeset
|
178 |
else Nil |
df1059ea8846
propagate property "isabelle.debug", notably for Java/Scala exception trace;
wenzelm
parents:
79633
diff
changeset
|
179 |
} |
df1059ea8846
propagate property "isabelle.debug", notably for Java/Scala exception trace;
wenzelm
parents:
79633
diff
changeset
|
180 |
|
69168
68816d1c73a7
eliminated "isabelle makedist" -- prefer Scala over bash/perl scripting;
wenzelm
parents:
69166
diff
changeset
|
181 |
|
77123 | 182 |
/* init */ |
183 |
||
77095 | 184 |
def init( |
185 |
other_settings: List[String] = init_components(), |
|
186 |
fresh: Boolean = false, |
|
77097
023273cf2651
clean components more accurately: purge other platforms or archives;
wenzelm
parents:
77095
diff
changeset
|
187 |
echo: Boolean = false, |
78610 | 188 |
clean_platforms: Option[List[Platform.Family]] = None, |
77124
be90af1e3254
proper use of current ISABELLE_COMPONENT_REPOSITORY from the managing Isabelle system (amending 3e963d68d394);
wenzelm
parents:
77123
diff
changeset
|
189 |
clean_archives: Boolean = false, |
77128
f40c36ab154d
clarified names to emphasize suble differences in meaning;
wenzelm
parents:
77124
diff
changeset
|
190 |
component_repository: String = Components.static_component_repository |
77095 | 191 |
): Unit = { |
192 |
init_settings(other_settings) |
|
77097
023273cf2651
clean components more accurately: purge other platforms or archives;
wenzelm
parents:
77095
diff
changeset
|
193 |
resolve_components( |
023273cf2651
clean components more accurately: purge other platforms or archives;
wenzelm
parents:
77095
diff
changeset
|
194 |
echo = echo, |
023273cf2651
clean components more accurately: purge other platforms or archives;
wenzelm
parents:
77095
diff
changeset
|
195 |
clean_platforms = clean_platforms, |
77124
be90af1e3254
proper use of current ISABELLE_COMPONENT_REPOSITORY from the managing Isabelle system (amending 3e963d68d394);
wenzelm
parents:
77123
diff
changeset
|
196 |
clean_archives = clean_archives, |
be90af1e3254
proper use of current ISABELLE_COMPONENT_REPOSITORY from the managing Isabelle system (amending 3e963d68d394);
wenzelm
parents:
77123
diff
changeset
|
197 |
component_repository = component_repository) |
77095 | 198 |
scala_build(fresh = fresh, echo = echo) |
80021
ba06861e91f9
proper services for Setup_Tool --- avoid hardwired stuff;
wenzelm
parents:
79681
diff
changeset
|
199 |
Setup_Tool.init(other_isabelle) |
77095 | 200 |
} |
201 |
||
202 |
||
83012
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
203 |
/* ML system settings */ |
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
204 |
|
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
205 |
val ml_settings: ML_Settings = |
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
206 |
new ML_Settings { |
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
207 |
override def polyml_home: Path = |
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
208 |
getenv("POLYML_HOME") match { |
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
209 |
case "" => |
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
210 |
try { expand_path(Path.variable("ML_HOME")).dir } |
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
211 |
catch { case ERROR(msg) => error("Bad ML_HOME: " + msg + error_context) } |
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
212 |
case s => Path.explode(s) |
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
213 |
} |
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
214 |
|
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
215 |
override def ml_system: String = getenv_strict("ML_SYSTEM") |
69168
68816d1c73a7
eliminated "isabelle makedist" -- prefer Scala over bash/perl scripting;
wenzelm
parents:
69166
diff
changeset
|
216 |
|
83012
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
217 |
override def ml_platform: String = |
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
218 |
if (ssh.is_file(isabelle_home + Path.explode("lib/Tools/console"))) { |
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
219 |
val Pattern = """.*val ML_PLATFORM = "(.*)".*""".r |
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
220 |
val input = """val ML_PLATFORM = Option.getOpt (OS.Process.getEnv "ML_PLATFORM", "")""" |
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
221 |
val result = bash("bin/isabelle console -r", input = input) |
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
222 |
result.out match { |
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
223 |
case Pattern(a) if result.ok && a.nonEmpty => a |
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
224 |
case _ => |
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
225 |
error("Cannot get ML_PLATFORM from other Isabelle: " + isabelle_home + |
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
226 |
if_proper(result.err, "\n" + result.err) + error_context) |
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
227 |
} |
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
228 |
} |
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
229 |
else getenv_strict("ML_PLATFORM") |
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
230 |
|
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
231 |
override def ml_options: String = |
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
232 |
proper_string(getenv("ML_OPTIONS")) getOrElse |
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
233 |
getenv(if (ml_platform_is_64_32) "ML_OPTIONS32" else "ML_OPTIONS64") |
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
234 |
} |
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
235 |
|
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
236 |
def user_output_dir: Path = |
fb5310760fce
tuned source structure: ml_settings operations implicitly assume init;
wenzelm
parents:
82728
diff
changeset
|
237 |
isabelle_home_user + Path.basic("heaps") + Path.basic(ml_settings.ml_identifier) |
64188 | 238 |
} |