You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When a forking JavacCompiler receives an argument it translates all canonical platform path separators to /. This behaviour is invisible on most contemporary JVM capable platforms but it trivially manifests on Windows where the canonical path separator is \.
The practical effect of this behaviour is that Maven cannot pass multiline arguments to a forked javac on Windows. Multiline arguments rely on \ to escape line breaks, and javac does accept these on Windows, but JavacCompiler corrupts such arguments by erroneously POSIX-path'ifying them.
Besides the unfortunate translation just described, JavacCompiler additionally fails to replicate that same translation when merely reporting the command line. The practical effect of that behaviour is that mvn -X will report multiline compiler arguments verbatim, then actually pass another set of arguments to javac.
This translation behaviour was introduced in commit d3fee7f ([PLX-314] When forking javac, receive "The input line is too long" error from Windows, 2007-01-11), first released in plexus-compiler-1.5.3, and has existed since. There is no apparent motivation for the translation part of that change.
It is evident that JavacCompiler's path separator handling is defective but it is not obvious what the defect is.
Arguably the path separator translation may now be considered canonical and therefore unchangeable. Hypothetically, a configuration may have passed path arguments on some non-/ path separator platform using native path separators and since come to rely on the hidden translation for compilation on / path separator platforms. Such a configuration would break on / path separator platforms were the translation to be removed. I would personally argue that a translation such as this should never be automatically performed and that the functionality is in every sense an undesirable bug, however, I can understand erring on the side of caution here. If simply removing the translation is unacceptable, as a compromise, JavacCompiler might learn to preserve any \ immediately followed by /[\r\n]+/, i.e. a line break escape.
The relevant implementations are
JavacCompiler::createCommandLine
JavacCompiler::createFileWithArguments
The behaviour can be trivially reproduced with any forking maven-compiler-plugin on Windows. For example, the POM
For comparison, InProcessCompiler supports multiline arguments in Linux and Windows whether or not the line break is escaped, i.e. the following is accepted:
javac does not support the unescaped form; arguably, JavacCompiler might reasonably learn to perform a translation from unescaped to escaped.
The text was updated successfully, but these errors were encountered:
commonquail
changed the title
JavacCompiler breaks multiline arguments on Windows
Forking JavacCompiler breaks multiline arguments on Windows
Jan 24, 2024
When a forking
JavacCompiler
receives an argument it translates all canonical platform path separators to/
. This behaviour is invisible on most contemporary JVM capable platforms but it trivially manifests on Windows where the canonical path separator is\
.The practical effect of this behaviour is that Maven cannot pass multiline arguments to a forked
javac
on Windows. Multiline arguments rely on\
to escape line breaks, andjavac
does accept these on Windows, butJavacCompiler
corrupts such arguments by erroneously POSIX-path'ifying them.Besides the unfortunate translation just described,
JavacCompiler
additionally fails to replicate that same translation when merely reporting the command line. The practical effect of that behaviour is thatmvn -X
will report multiline compiler arguments verbatim, then actually pass another set of arguments tojavac
.This translation behaviour was introduced in commit d3fee7f ([PLX-314] When forking javac, receive "The input line is too long" error from Windows, 2007-01-11), first released in
plexus-compiler-1.5.3
, and has existed since. There is no apparent motivation for the translation part of that change.It is evident that
JavacCompiler
's path separator handling is defective but it is not obvious what the defect is.Arguably the path separator translation may now be considered canonical and therefore unchangeable. Hypothetically, a configuration may have passed path arguments on some non-
/
path separator platform using native path separators and since come to rely on the hidden translation for compilation on/
path separator platforms. Such a configuration would break on/
path separator platforms were the translation to be removed. I would personally argue that a translation such as this should never be automatically performed and that the functionality is in every sense an undesirable bug, however, I can understand erring on the side of caution here. If simply removing the translation is unacceptable, as a compromise,JavacCompiler
might learn to preserve any\
immediately followed by/[\r\n]+/
, i.e. a line break escape.The relevant implementations are
JavacCompiler::createCommandLine
JavacCompiler::createFileWithArguments
The behaviour can be trivially reproduced with any forking
maven-compiler-plugin
on Windows. For example, the POMgenerates a
target/javac.bat
that containswhose execution fails with
where it should fail with
For an authentic example see google/error-prone#4256.
For comparison,
InProcessCompiler
supports multiline arguments in Linux and Windows whether or not the line break is escaped, i.e. the following is accepted:javac
does not support the unescaped form; arguably,JavacCompiler
might reasonably learn to perform a translation from unescaped to escaped.The text was updated successfully, but these errors were encountered: