Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use pathing jars in cli commands #21121

Merged
merged 2 commits into from
Jul 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions compiler/src/dotty/tools/dotc/classpath/ClassPathFactory.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -52,14 +53,30 @@ class ClassPathFactory {

// Internal
protected def classesInPathImpl(path: String, expand: Boolean)(using Context): List[ClassPath] =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if I had one comment for cleanup - there should probably be a third argument i.e. expandManifest: Boolean and this would only be true specifically when calling classesInExpandedPath(javaUserClassPath) in PathResolvers

Copy link
Member

@bishabosha bishabosha Jul 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

which then isolates the expansion specifically to the java.class.path property - but this should not be an issue in practice

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and then finally move the logic to expandPath?

Copy link
Member

@bishabosha bishabosha Jul 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all not blockers - could be in follow up PR

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)
Expand Down
13 changes: 9 additions & 4 deletions compiler/src/dotty/tools/io/ClassPath.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
20 changes: 2 additions & 18 deletions dist/bin/common
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion dist/bin/common.bat
Original file line number Diff line number Diff line change
Expand Up @@ -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=;
1 change: 1 addition & 0 deletions dist/bin/scalac
Original file line number Diff line number Diff line change
Expand Up @@ -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" \
Expand Down
33 changes: 3 additions & 30 deletions dist/bin/scalac.bat
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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%"
Expand All @@ -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

Expand Down
12 changes: 3 additions & 9 deletions dist/bin/scaladoc
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
Expand All @@ -79,12 +74,11 @@ case "$1" in
esac
done

classpathArgs

eval "\"$JAVACMD\"" \
${JAVA_OPTS:-$default_java_opts} \
"${java_args[@]}" \
"${jvm_cp_args-}" \
-classpath "${JVM_CP_ARGS}" \
-Dscala.expandjavacp=true \
-Dscala.usejavacp=true \
"dotty.tools.scaladoc.Main" \
"${scala_args[@]}" \
Expand Down
28 changes: 2 additions & 26 deletions dist/bin/scaladoc.bat
Original file line number Diff line number Diff line change
Expand Up @@ -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%
)
Expand All @@ -31,7 +29,8 @@ 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.expandjavacp=true ^
-Dscala.usejavacp=true ^
dotty.tools.scaladoc.Main %_SCALA_ARGS% %_RESIDUAL_ARGS%
if not %ERRORLEVEL%==0 (
Expand Down Expand Up @@ -103,29 +102,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

Expand Down
2 changes: 1 addition & 1 deletion project/Build.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 +=
Expand Down
12 changes: 10 additions & 2 deletions project/RepublishPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
}

Expand Down
Loading