1 /* Title: Pure/Tools/scala_project.scala |
1 /* Title: Pure/Tools/scala_project.scala |
2 Author: Makarius |
2 Author: Makarius |
3 |
3 |
4 Manage Isabelle/Scala/Java project sources, with output to Maven for |
4 Manage Isabelle/Scala/Java project sources, with output to Gradle or |
5 IntelliJ IDEA. |
5 Maven for IntelliJ IDEA. |
6 */ |
6 */ |
7 |
7 |
8 package isabelle |
8 package isabelle |
9 |
9 |
10 |
10 |
11 object Scala_Project |
11 object Scala_Project |
12 { |
12 { |
13 /* Maven project */ |
13 /** build tools **/ |
14 |
14 |
15 def java_version: String = "15" |
15 def java_version: String = "15" |
16 def scala_version: String = scala.util.Properties.versionNumberString |
16 def scala_version: String = scala.util.Properties.versionNumberString |
17 |
17 |
18 def maven_project(jars: List[Path]): String = |
18 abstract class Build_Tool |
19 { |
19 { |
20 def dependency(jar: Path): String = |
20 def project_root: Path |
21 { |
21 def init_project(dir: Path, jars: List[Path]): Unit |
22 val name = jar.expand.drop_ext.base.implode |
22 |
23 val system_path = File.platform_path(jar.absolute) |
23 val java_src_dir: Path = Path.explode("src/main/java") |
|
24 val scala_src_dir: Path = Path.explode("src/main/scala") |
|
25 |
|
26 def detect_project(dir: Path): Boolean = |
|
27 (dir + project_root).is_file && |
|
28 (dir + scala_src_dir).is_dir |
|
29 |
|
30 def package_dir(source_file: Path): Path = |
|
31 { |
|
32 val is_java = source_file.is_java |
|
33 val dir = |
|
34 package_name(source_file) match { |
|
35 case Some(name) => |
|
36 if (is_java) Path.explode(space_explode('.', name).mkString("/")) |
|
37 else Path.basic(name) |
|
38 case None => error("Failed to guess package from " + source_file) |
|
39 } |
|
40 (if (is_java) java_src_dir else scala_src_dir) + dir |
|
41 } |
|
42 } |
|
43 |
|
44 def build_tools: List[Build_Tool] = List(Gradle, Maven) |
|
45 |
|
46 |
|
47 /* Gradle */ |
|
48 |
|
49 object Gradle extends Build_Tool |
|
50 { |
|
51 override def toString: String = "Gradle" |
|
52 |
|
53 val project_settings: Path = Path.explode("settings.gradle") |
|
54 override val project_root: Path = Path.explode("build.gradle") |
|
55 |
|
56 private def groovy_string(s: String): String = |
|
57 { |
|
58 s.map(c => |
|
59 c match { |
|
60 case '\t' | '\b' | '\n' | '\r' | '\f' | '\\' | '\'' | '"' => "\\" + c |
|
61 case _ => c.toString |
|
62 }).mkString("'", "", "'") |
|
63 } |
|
64 |
|
65 override def init_project(dir: Path, jars: List[Path]): Unit = |
|
66 { |
|
67 File.write(dir + project_settings, "rootProject.name = 'Isabelle'\n") |
|
68 File.write(dir + project_root, |
|
69 """plugins { |
|
70 id 'scala' |
|
71 } |
|
72 |
|
73 repositories { |
|
74 mavenCentral() |
|
75 } |
|
76 |
|
77 dependencies { |
|
78 implementation 'org.scala-lang:scala-library:""" + scala_version + """' |
|
79 compileOnly files( |
|
80 """ + jars.map(jar => groovy_string(File.platform_path(jar))).mkString("", ",\n ", ")") + |
|
81 """ |
|
82 } |
|
83 """) |
|
84 } |
|
85 } |
|
86 |
|
87 |
|
88 /* Maven */ |
|
89 |
|
90 object Maven extends Build_Tool |
|
91 { |
|
92 override def toString: String = "Maven" |
|
93 |
|
94 override val project_root: Path = Path.explode("pom.xml") |
|
95 |
|
96 override def init_project(dir: Path, jars: List[Path]): Unit = |
|
97 { |
|
98 def dependency(jar: Path): String = |
|
99 { |
|
100 val name = jar.expand.drop_ext.base.implode |
|
101 val system_path = File.platform_path(jar.absolute) |
24 """ <dependency> |
102 """ <dependency> |
25 <groupId>classpath</groupId> |
103 <groupId>classpath</groupId> |
26 <artifactId>""" + XML.text(name) + """</artifactId> |
104 <artifactId>""" + XML.text(name) + """</artifactId> |
27 <version>0</version> |
105 <version>0</version> |
28 <scope>system</scope> |
106 <scope>system</scope> |
29 <systemPath>""" + XML.text(system_path) + """</systemPath> |
107 <systemPath>""" + XML.text(system_path) + """</systemPath> |
30 </dependency>""" |
108 </dependency>""" |
31 } |
109 } |
32 |
110 |
33 """<?xml version="1.0" encoding="UTF-8"?> |
111 val project = """<?xml version="1.0" encoding="UTF-8"?> |
34 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
112 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
35 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
113 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
36 <modelVersion>4.0.0</modelVersion> |
114 <modelVersion>4.0.0</modelVersion> |
37 |
115 |
38 <groupId>isabelle</groupId> |
116 <groupId>isabelle</groupId> |
146 val lines = Library.trim_split_lines(File.read(source_file)) |
227 val lines = Library.trim_split_lines(File.read(source_file)) |
147 val Package = """\s*\bpackage\b\s*(?:object\b\s*)?((?:\w|\.)+)\b.*""".r |
228 val Package = """\s*\bpackage\b\s*(?:object\b\s*)?((?:\w|\.)+)\b.*""".r |
148 lines.collectFirst({ case Package(name) => name }) |
229 lines.collectFirst({ case Package(name) => name }) |
149 } |
230 } |
150 |
231 |
151 def the_package_dir(source_file: Path): Path = |
|
152 { |
|
153 package_name(source_file) match { |
|
154 case Some(name) => |
|
155 if (source_file.is_java) Path.explode(space_explode('.', name).mkString("/")) |
|
156 else Path.basic(name) |
|
157 case None => error("Failed to guess package from " + source_file) |
|
158 } |
|
159 } |
|
160 |
|
161 def scala_project( |
232 def scala_project( |
|
233 build_tool: Build_Tool, |
162 project_dir: Path = default_project_dir, |
234 project_dir: Path = default_project_dir, |
163 more_sources: List[Path] = Nil, |
235 more_sources: List[Path] = Nil, |
164 symlinks: Boolean = false, |
236 symlinks: Boolean = false, |
165 force: Boolean = false, |
237 force: Boolean = false, |
166 progress: Progress = new Progress): Unit = |
238 progress: Progress = new Progress): Unit = |
167 { |
239 { |
168 if (project_dir.file.exists) { |
240 if (project_dir.file.exists) { |
169 val detect = |
241 val detect = project_dir.is_dir && build_tools.exists(_.detect_project(project_dir)) |
170 project_dir.is_dir && |
|
171 (project_dir + Path.explode("pom.xml")).is_file && |
|
172 (project_dir + Path.explode("src/main/scala")).is_dir |
|
173 |
242 |
174 if (force && detect) { |
243 if (force && detect) { |
175 progress.echo("Purging existing project directory: " + project_dir.absolute) |
244 progress.echo("Purging existing project directory: " + project_dir.absolute) |
176 Isabelle_System.rm_tree(project_dir) |
245 Isabelle_System.rm_tree(project_dir) |
177 } |
246 } |
178 else error("Project directory already exists: " + project_dir.absolute) |
247 else error("Project directory already exists: " + project_dir.absolute) |
179 } |
248 } |
180 |
249 |
181 progress.echo("Creating project directory: " + project_dir.absolute) |
250 progress.echo("Creating " + build_tool + " project directory: " + project_dir.absolute) |
182 Isabelle_System.make_directory(project_dir) |
251 Isabelle_System.make_directory(project_dir) |
183 |
252 |
184 val java_src_dir = Isabelle_System.make_directory(Path.explode("src/main/java")) |
253 val java_src_dir = Isabelle_System.make_directory(project_dir + build_tool.java_src_dir) |
185 val scala_src_dir = Isabelle_System.make_directory(Path.explode("src/main/scala")) |
254 val scala_src_dir = Isabelle_System.make_directory(project_dir + build_tool.scala_src_dir) |
186 |
255 |
187 val (jars, sources) = isabelle_files |
256 val (jars, sources) = isabelle_files |
188 isabelle_scala_files |
257 isabelle_scala_files |
189 |
258 |
190 File.write(project_dir + Path.explode("pom.xml"), maven_project(jars)) |
259 build_tool.init_project(project_dir, jars) |
191 |
260 |
192 for (source <- sources ::: more_sources) { |
261 for (source <- sources ::: more_sources) { |
193 val dir = (if (source.is_java) java_src_dir else scala_src_dir) + the_package_dir(source) |
262 val dir = build_tool.package_dir(source) |
194 val target_dir = project_dir + dir |
263 val target_dir = project_dir + dir |
195 if (!target_dir.is_dir) { |
264 if (!target_dir.is_dir) { |
196 progress.echo(" Creating package directory: " + dir) |
265 progress.echo(" Creating package directory: " + dir) |
197 Isabelle_System.make_directory(target_dir) |
266 Isabelle_System.make_directory(target_dir) |
198 } |
267 } |
203 |
272 |
204 |
273 |
205 /* Isabelle tool wrapper */ |
274 /* Isabelle tool wrapper */ |
206 |
275 |
207 val isabelle_tool = |
276 val isabelle_tool = |
208 Isabelle_Tool("scala_project", "setup Maven project for Isabelle/Scala/jEdit", |
277 Isabelle_Tool("scala_project", "setup IDE project for Isabelle/Java/Scala sources", |
209 Scala_Project.here, args => |
278 Scala_Project.here, args => |
210 { |
279 { |
|
280 var build_tool: Option[Build_Tool] = None |
211 var project_dir = default_project_dir |
281 var project_dir = default_project_dir |
212 var symlinks = false |
282 var symlinks = false |
213 var force = false |
283 var force = false |
214 |
284 |
215 val getopts = Getopts(""" |
285 val getopts = Getopts(""" |
216 Usage: isabelle scala_project [OPTIONS] [MORE_SOURCES ...] |
286 Usage: isabelle scala_project [OPTIONS] [MORE_SOURCES ...] |
217 |
287 |
218 Options are: |
288 Options are: |
219 -D DIR project directory (default: """ + default_project_dir + """) |
289 -D DIR project directory (default: """ + default_project_dir + """) |
|
290 -G use Gradle as build tool |
220 -L make symlinks to original source files |
291 -L make symlinks to original source files |
|
292 -M use Maven as build tool |
221 -f force update of existing directory |
293 -f force update of existing directory |
222 |
294 |
223 Setup Maven project for Isabelle/Scala/jEdit --- to support common IDEs |
295 Setup project for Isabelle/Scala/jEdit --- to support common IDEs such |
224 such as IntelliJ IDEA. |
296 as IntelliJ IDEA. Either option -G or -M is mandatory to specify the |
|
297 build tool. |
225 """, |
298 """, |
226 "D:" -> (arg => project_dir = Path.explode(arg)), |
299 "D:" -> (arg => project_dir = Path.explode(arg)), |
|
300 "G" -> (_ => build_tool = Some(Gradle)), |
227 "L" -> (_ => symlinks = true), |
301 "L" -> (_ => symlinks = true), |
|
302 "M" -> (_ => build_tool = Some(Maven)), |
228 "f" -> (_ => force = true)) |
303 "f" -> (_ => force = true)) |
229 |
304 |
230 val more_args = getopts(args) |
305 val more_args = getopts(args) |
231 |
306 |
232 val more_sources = more_args.map(Path.explode) |
307 val more_sources = more_args.map(Path.explode) |
233 val progress = new Console_Progress |
308 val progress = new Console_Progress |
234 |
309 |
235 scala_project(project_dir = project_dir, more_sources = more_sources, |
310 if (build_tool.isEmpty) { |
|
311 error("Unspecified build tool: need to provide option -G or -M") |
|
312 } |
|
313 |
|
314 scala_project(build_tool.get, project_dir = project_dir, more_sources = more_sources, |
236 symlinks = symlinks, force = force, progress = progress) |
315 symlinks = symlinks, force = force, progress = progress) |
237 }) |
316 }) |
238 } |
317 } |