From 78b3f4aa9b43b6009ad08d4fb5ce5c9085e2ee6e Mon Sep 17 00:00:00 2001 From: Hamza REMMAL Date: Mon, 8 Jul 2024 15:22:57 +0200 Subject: [PATCH 1/2] Use pathing jars in cli commands --- dist/bin/common | 20 ++------------------ dist/bin/common.bat | 2 +- dist/bin/scalac.bat | 31 ++----------------------------- dist/bin/scaladoc | 11 ++--------- dist/bin/scaladoc.bat | 27 +-------------------------- project/Build.scala | 2 +- project/RepublishPlugin.scala | 14 +++++++++++--- 7 files changed, 20 insertions(+), 87 deletions(-) diff --git a/dist/bin/common b/dist/bin/common index 63e598d70d7e..2de8bdf9f99a 100644 --- a/dist/bin/common +++ b/dist/bin/common @@ -6,25 +6,9 @@ source "$PROG_HOME/bin/common-shared" # * The code below is for Dotty # *-------------------------------------------------*/ -load_classpath () { - command="$1" - psep_pattern="$2" - __CLASS_PATH="" - while IFS= read -r line || [ -n "$line" ]; do - # jna-5 only appropriate for some combinations - if ! [[ ( -n ${conemu-} || -n ${msys-}) && "$line" == "*jna-5*" ]]; then - if [ -n "$__CLASS_PATH" ]; then - __CLASS_PATH+="$psep_pattern" - fi - __CLASS_PATH+="$PROG_HOME/maven2/$line" - fi - done < "$PROG_HOME/etc/$command.classpath" - echo "$__CLASS_PATH" -} - compilerJavaClasspathArgs () { - toolchain="$(load_classpath "scala" "$PSEP")" - toolchain_extra="$(load_classpath "with_compiler" "$PSEP")" + toolchain="$PROG_HOME/lib/scala.jar" + toolchain_extra="$PROG_HOME/lib/with_compiler.jar" if [ -n "$toolchain_extra" ]; then toolchain+="$PSEP$toolchain_extra" diff --git a/dist/bin/common.bat b/dist/bin/common.bat index f9c35e432b36..510771d43b6e 100644 --- a/dist/bin/common.bat +++ b/dist/bin/common.bat @@ -38,6 +38,6 @@ if not defined _PROG_HOME ( set _EXITCODE=1 goto :eof ) -set "_ETC_DIR=%_PROG_HOME%\etc" +set "_LIB_DIR=%_PROG_HOME%\lib" set _PSEP=; diff --git a/dist/bin/scalac.bat b/dist/bin/scalac.bat index dbcbaf11b8e2..7ad368582127 100644 --- a/dist/bin/scalac.bat +++ b/dist/bin/scalac.bat @@ -88,17 +88,8 @@ goto :eof @rem output parameter: _JVM_CP_ARGS :compilerJavaClasspathArgs - -set "CP_FILE=%_ETC_DIR%\scala.classpath" -call :loadClasspathFromFile %CP_FILE% -set "__TOOLCHAIN=%_CLASS_PATH_RESULT%" - -set "CP_FILE=%_ETC_DIR%\with_compiler.classpath" -call :loadClasspathFromFile %CP_FILE% - -if defined _CLASS_PATH_RESULT ( - set "__TOOLCHAIN=%__TOOLCHAIN%%_PSEP%%_CLASS_PATH_RESULT%" -) +set "__TOOLCHAIN=%_LIB_DIR%\scala.jar" +set "__TOOLCHAIN=%__TOOLCHAIN%%_PSEP%%_LIB_DIR%\with_compiler.jar%" if defined _SCALA_CPATH ( set "_JVM_CP_ARGS=%__TOOLCHAIN%%_SCALA_CPATH%" @@ -107,24 +98,6 @@ if defined _SCALA_CPATH ( ) goto :eof -@REM concatentate every line in "%_ARG_FILE%" with _PSEP -@REM arg 1 - file to read -:loadClasspathFromFile -set _ARG_FILE=%1 -set _CLASS_PATH_RESULT= -if exist "%_ARG_FILE%" ( - for /f "usebackq delims=" %%i in ("%_ARG_FILE%") do ( - set "_LIB=%_PROG_HOME%\maven2\%%i" - set "_LIB=!_LIB:/=\!" - if not defined _CLASS_PATH_RESULT ( - set "_CLASS_PATH_RESULT=!_LIB!" - ) else ( - set "_CLASS_PATH_RESULT=!_CLASS_PATH_RESULT!%_PSEP%!_LIB!" - ) - ) -) -goto :eof - @rem ######################################################################### @rem ## Cleanups diff --git a/dist/bin/scaladoc b/dist/bin/scaladoc index 15bc0813f93a..f4ef37af00ee 100755 --- a/dist/bin/scaladoc +++ b/dist/bin/scaladoc @@ -36,6 +36,7 @@ CompilerMain=dotty.tools.dotc.Main DecompilerMain=dotty.tools.dotc.decompiler.Main ReplMain=dotty.tools.repl.Main ScriptingMain=dotty.tools.scripting.Main +JVM_CP_ARGS="$PROG_HOME/lib/scaladoc.jar" PROG_NAME=$CompilerMain @@ -52,12 +53,6 @@ addScrip() { script_args+=("'$1'") } -classpathArgs () { - CLASS_PATH="$(load_classpath "scaladoc" "$PSEP")" - - jvm_cp_args="-classpath \"$CLASS_PATH\"" -} - #for A in "$@" ; do echo "A[$A]" ; done ; exit 2 while [[ $# -gt 0 ]]; do @@ -79,12 +74,10 @@ case "$1" in esac done -classpathArgs - eval "\"$JAVACMD\"" \ ${JAVA_OPTS:-$default_java_opts} \ "${java_args[@]}" \ - "${jvm_cp_args-}" \ + -classpath "${JVM_CP_ARGS}" \ -Dscala.usejavacp=true \ "dotty.tools.scaladoc.Main" \ "${scala_args[@]}" \ diff --git a/dist/bin/scaladoc.bat b/dist/bin/scaladoc.bat index 16433a83f501..fe4055633e02 100644 --- a/dist/bin/scaladoc.bat +++ b/dist/bin/scaladoc.bat @@ -21,8 +21,6 @@ call :args %* @rem ######################################################################### @rem ## Main -call :classpathArgs - if defined JAVA_OPTS ( set _JAVA_OPTS=%JAVA_OPTS% ) else ( set _JAVA_OPTS=%_DEFAULT_JAVA_OPTS% ) @@ -31,7 +29,7 @@ if defined JAVA_OPTS ( set _JAVA_OPTS=%JAVA_OPTS% set "_JAVACMD=!_JAVACMD:%%=%%%%!" call "%_JAVACMD%" %_JAVA_OPTS% %_JAVA_DEBUG% %_JAVA_ARGS% ^ --classpath "%_CLASS_PATH%" ^ +-classpath "%_LIB_DIR%\scaladoc.jar" ^ -Dscala.usejavacp=true ^ dotty.tools.scaladoc.Main %_SCALA_ARGS% %_RESIDUAL_ARGS% if not %ERRORLEVEL%==0 ( @@ -103,29 +101,6 @@ goto :eof set _RESIDUAL_ARGS=%_RESIDUAL_ARGS% %~1 goto :eof -@rem output parameter: _CLASS_PATH -:classpathArgs -set "_ETC_DIR=%_PROG_HOME%\etc" -@rem keep list in sync with bash script `bin\scaladoc` ! -call :loadClasspathFromFile -goto :eof - -@REM concatentate every line in "%_ETC_DIR%\scaladoc.classpath" with _PSEP -:loadClasspathFromFile -set _CLASS_PATH= -if exist "%_ETC_DIR%\scaladoc.classpath" ( - for /f "usebackq delims=" %%i in ("%_ETC_DIR%\scaladoc.classpath") do ( - set "_LIB=%_PROG_HOME%\maven2\%%i" - set "_LIB=!_LIB:/=\!" - if not defined _CLASS_PATH ( - set "_CLASS_PATH=!_LIB!" - ) else ( - set "_CLASS_PATH=!_CLASS_PATH!%_PSEP%!_LIB!" - ) - ) -) -goto :eof - @rem ######################################################################### @rem ## Cleanups diff --git a/project/Build.scala b/project/Build.scala index 28146989e40c..54b4a6bf7801 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -2134,7 +2134,7 @@ object Build { republishRepo := target.value / "republish", packResourceDir += (republishRepo.value / "bin" -> "bin"), packResourceDir += (republishRepo.value / "maven2" -> "maven2"), - packResourceDir += (republishRepo.value / "etc" -> "etc"), + packResourceDir += (republishRepo.value / "lib" -> "lib"), republishCommandLibs += ("scala" -> List("scala3-interfaces", "scala3-compiler", "scala3-library", "tasty-core")), republishCommandLibs += diff --git a/project/RepublishPlugin.scala b/project/RepublishPlugin.scala index e4bf40545a6b..8b95c6423e68 100644 --- a/project/RepublishPlugin.scala +++ b/project/RepublishPlugin.scala @@ -213,16 +213,24 @@ object RepublishPlugin extends AutoPlugin { val classpaths = coursierFetch(coursierJar, log, csrCacheDir, localRepo, resolvedLocal.map(_.id.toString)) if (commandLibs.nonEmpty) { - IO.createDirectory(republishDir / "etc") + IO.createDirectory(republishDir / "lib") for ((command, libs) <- commandLibs) { val (negated, actual) = libs.partition(_.startsWith("^!")) val subtractions = negated.map(_.stripPrefix("^!")) def compose(libs: List[String]): List[String] = libs.map(fuzzyFind(classpaths, _)).reduceOption(_ ++ _).map(_.distinct).getOrElse(Nil) - + + // Compute the classpath entries val entries = compose(actual).diff(compose(subtractions)) - IO.write(republishDir / "etc" / s"$command.classpath", entries.mkString("\n")) + // Generate the MANIFEST for the pathing jar + val manifest = new java.util.jar.Manifest(); + manifest.getMainAttributes().put(java.util.jar.Attributes.Name.MANIFEST_VERSION, "1.0"); + manifest.getMainAttributes().put(java.util.jar.Attributes.Name.CLASS_PATH, entries.map(e => s"../maven2/$e").mkString(" ")) + // Write the pathing jar to the Disk + val file = republishDir / "lib" / s"$command.jar" + val jar = new java.util.jar.JarOutputStream(new java.io.FileOutputStream(file), manifest) + jar.close() } } From e93430ff5a079b6493e30a4cef3e7b69338502ce Mon Sep 17 00:00:00 2001 From: Hamza REMMAL Date: Mon, 8 Jul 2024 19:18:51 +0200 Subject: [PATCH 2/2] Add support for Class-Path entries in Manifest --- .../dotc/classpath/ClassPathFactory.scala | 21 +++++++++++++++++-- compiler/src/dotty/tools/io/ClassPath.scala | 13 ++++++++---- dist/bin/scalac | 1 + dist/bin/scalac.bat | 2 +- dist/bin/scaladoc | 1 + dist/bin/scaladoc.bat | 1 + project/RepublishPlugin.scala | 2 +- 7 files changed, 33 insertions(+), 8 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/classpath/ClassPathFactory.scala b/compiler/src/dotty/tools/dotc/classpath/ClassPathFactory.scala index 0b66f339bf53..080f8d4e63d2 100644 --- a/compiler/src/dotty/tools/dotc/classpath/ClassPathFactory.scala +++ b/compiler/src/dotty/tools/dotc/classpath/ClassPathFactory.scala @@ -7,6 +7,7 @@ import dotty.tools.io.{AbstractFile, VirtualDirectory} import FileUtils.* import dotty.tools.io.ClassPath import dotty.tools.dotc.core.Contexts.* +import java.nio.file.Files /** * Provides factory methods for classpath. When creating classpath instances for a given path, @@ -52,14 +53,30 @@ class ClassPathFactory { // Internal protected def classesInPathImpl(path: String, expand: Boolean)(using Context): List[ClassPath] = - for { + val files = for { file <- expandPath(path, expand) dir <- { def asImage = if (file.endsWith(".jimage")) Some(AbstractFile.getFile(file)) else None Option(AbstractFile.getDirectory(file)).orElse(asImage) } } - yield newClassPath(dir) + yield dir + + val expanded = + if scala.util.Properties.propOrFalse("scala.expandjavacp") then + for + file <- files + a <- ClassPath.expandManifestPath(file.absolutePath) + path = java.nio.file.Paths.get(a.toURI()).nn + if Files.exists(path) + yield + newClassPath(AbstractFile.getFile(path)) + else + Seq.empty + + files.map(newClassPath) ++ expanded + + end classesInPathImpl private def createSourcePath(file: AbstractFile)(using Context): ClassPath = if (file.isJarOrZip) diff --git a/compiler/src/dotty/tools/io/ClassPath.scala b/compiler/src/dotty/tools/io/ClassPath.scala index f77bc1efca91..01a3f2cc1870 100644 --- a/compiler/src/dotty/tools/io/ClassPath.scala +++ b/compiler/src/dotty/tools/io/ClassPath.scala @@ -152,13 +152,18 @@ object ClassPath { val baseDir = file.parent new Jar(file).classPathElements map (elem => - specToURL(elem) getOrElse (baseDir / elem).toURL + specToURL(elem, baseDir) getOrElse (baseDir / elem).toURL ) } - def specToURL(spec: String): Option[URL] = - try Some(new URI(spec).toURL) - catch case _: MalformedURLException | _: URISyntaxException => None + def specToURL(spec: String, basedir: Directory): Option[URL] = + try + val uri = new URI(spec) + if uri.isAbsolute() then Some(uri.toURL()) + else + Some(basedir.resolve(Path(spec)).toURL) + catch + case _: MalformedURLException | _: URISyntaxException => None def manifests: List[java.net.URL] = { import scala.jdk.CollectionConverters.EnumerationHasAsScala diff --git a/dist/bin/scalac b/dist/bin/scalac index d9bd21ca425b..a527d9767749 100755 --- a/dist/bin/scalac +++ b/dist/bin/scalac @@ -86,6 +86,7 @@ eval "\"$JAVACMD\"" \ ${JAVA_OPTS:-$default_java_opts} \ "${java_args[@]}" \ "-classpath \"$jvm_cp_args\"" \ + "-Dscala.expandjavacp=true" \ "-Dscala.usejavacp=true" \ "-Dscala.home=\"$PROG_HOME\"" \ "dotty.tools.MainGenericCompiler" \ diff --git a/dist/bin/scalac.bat b/dist/bin/scalac.bat index 7ad368582127..e2898bdc2890 100644 --- a/dist/bin/scalac.bat +++ b/dist/bin/scalac.bat @@ -24,7 +24,7 @@ call :compilerJavaClasspathArgs @rem we need to escape % in the java command path, for some reason this doesnt work in common.bat set "_JAVACMD=!_JAVACMD:%%=%%%%!" -call "%_JAVACMD%" %_JAVA_ARGS% -classpath "%_JVM_CP_ARGS%" "-Dscala.usejavacp=true" "-Dscala.home=%_PROG_HOME%" dotty.tools.MainGenericCompiler %_SCALA_ARGS% +call "%_JAVACMD%" %_JAVA_ARGS% -classpath "%_JVM_CP_ARGS%" "-Dscala.usejavacp=true" "-Dscala.expandjavacp=true" "-Dscala.home=%_PROG_HOME%" dotty.tools.MainGenericCompiler %_SCALA_ARGS% if not %ERRORLEVEL%==0 ( set _EXITCODE=1 goto end diff --git a/dist/bin/scaladoc b/dist/bin/scaladoc index f4ef37af00ee..0af5a2b55acb 100755 --- a/dist/bin/scaladoc +++ b/dist/bin/scaladoc @@ -78,6 +78,7 @@ eval "\"$JAVACMD\"" \ ${JAVA_OPTS:-$default_java_opts} \ "${java_args[@]}" \ -classpath "${JVM_CP_ARGS}" \ + -Dscala.expandjavacp=true \ -Dscala.usejavacp=true \ "dotty.tools.scaladoc.Main" \ "${scala_args[@]}" \ diff --git a/dist/bin/scaladoc.bat b/dist/bin/scaladoc.bat index fe4055633e02..b9e4820b006d 100644 --- a/dist/bin/scaladoc.bat +++ b/dist/bin/scaladoc.bat @@ -30,6 +30,7 @@ set "_JAVACMD=!_JAVACMD:%%=%%%%!" call "%_JAVACMD%" %_JAVA_OPTS% %_JAVA_DEBUG% %_JAVA_ARGS% ^ -classpath "%_LIB_DIR%\scaladoc.jar" ^ +-Dscala.expandjavacp=true ^ -Dscala.usejavacp=true ^ dotty.tools.scaladoc.Main %_SCALA_ARGS% %_RESIDUAL_ARGS% if not %ERRORLEVEL%==0 ( diff --git a/project/RepublishPlugin.scala b/project/RepublishPlugin.scala index 8b95c6423e68..5611af798b33 100644 --- a/project/RepublishPlugin.scala +++ b/project/RepublishPlugin.scala @@ -220,7 +220,7 @@ object RepublishPlugin extends AutoPlugin { def compose(libs: List[String]): List[String] = libs.map(fuzzyFind(classpaths, _)).reduceOption(_ ++ _).map(_.distinct).getOrElse(Nil) - + // Compute the classpath entries val entries = compose(actual).diff(compose(subtractions)) // Generate the MANIFEST for the pathing jar