@@ -33,55 +33,56 @@ object MsvcEnvironment {
3333 case Some (vcvars) =>
3434 logger.debug(s " Using vcvars script $vcvars" )
3535
36- val msvcEnv = captureVcvarsEnv(vcvars, workingDir)
37- val clDir = os.Path (msvcEnv(" VCTOOLSINSTALLDIR" )) / " bin" / " Hostx64" / " x64"
38- logger.debug(s " clDir[ $clDir] " )
39- if (! os.exists(clDir)) {
40- logger.message(s " cl.exe directory missing: $clDir" )
41- - 1
36+ val (debugEcho : Seq [String ], msvcEnv : Map [String , String ]) =
37+ captureVcvarsEnv(vcvars, workingDir)
38+ debugEcho.foreach { dbg =>
39+ logger.message(s " $dbg" )
4240 }
43- else {
44- val msvcEnv : Map [String , String ] = captureVcvarsEnv(vcvars, workingDir)
45- val clExe : os.Path = clDir / " cl.exe"
46- if ! os.exists(clExe) then
47- logger.message(s " warning: file not found: $clExe" )
48-
49- val msvcEntries : Seq [String ] = {
50- val entries = msvcEnv.getOrElse(" PATH" , " " ).split(" ;" ).toSeq
51- if entries.headOption == Some (clDir.toString) then entries
52- else clDir.toString +: entries
53- }
41+ val msvcEntries : Seq [String ] = msvcEnv.getOrElse(" PATH" , " " ).split(" ;" ).toSeq
42+
43+ // show aliased drive map
44+ val substMap : Map [Char , String ] = aliasedDriveLetters
45+ substMap.foreach((k, v) => logger.message(s " substMap $k: -> $v" ))
5446
55- // show aliased drive map
56- val substMap : Map [Char , String ] = aliasedDriveLetters
57- substMap.foreach((k, v) => logger.message(s " substMap $k: -> $v" ))
47+ val finalPath = msvcEntries.mkString(" ;" )
48+ val finalEnv =
49+ msvcEnv +
50+ (" PATH" -> finalPath) +
51+ (" GRAALVM_ARGUMENT_VECTOR_PROGRAM_NAME" -> " native-image" )
5852
59- val finalPath = msvcEntries.mkString(" ;" )
60- val finalEnv =
61- msvcEnv +
62- (" PATH" -> finalPath) +
63- (" GRAALVM_ARGUMENT_VECTOR_PROGRAM_NAME" -> " native-image" )
53+ logger.message(s " msvc PATH entries: " )
54+ msvcEntries.foreach { entry =>
55+ logger.message(s " $entry; " )
56+ }
6457
65- logger.message(s " msvc PATH entries: " )
66- msvcEntries.foreach { entry =>
67- logger.message(s " $entry; " )
58+ // Replace native-image.cmd with native-image.exe, if applicable
59+ val updatedCommand : Seq [String ] =
60+ command.headOption match {
61+ case Some (cmd) if cmd.toLowerCase.endsWith(" native-image.cmd" ) =>
62+ val cmdPath = os.Path (cmd, os.pwd)
63+ val graalHome = cmdPath / os.up / os.up
64+ resolveNativeImage(graalHome) match {
65+ case Some (exe) =>
66+ exe.toString +: command.tail
67+ case None =>
68+ command // fall back to the .cmd wrapper
69+ }
70+ case _ =>
71+ command
6872 }
6973
70- logger.message(s " native-image w/args: $command" )
74+ logger.message(s " native-image w/args: $command" )
7175
72- // request extra info in case of exceptions
73- val altCommand = insertAfterCp(command, " -H:+ReportExceptionStackTraces" )
74- val result =
75- os.proc(altCommand)
76- .call(
77- cwd = workingDir,
78- env = finalEnv,
79- stdout = os.Inherit ,
80- stderr = os.Inherit
81- )
76+ val result =
77+ os.proc(updatedCommand)
78+ .call(
79+ cwd = workingDir,
80+ env = finalEnv,
81+ stdout = os.Inherit ,
82+ stderr = os.Inherit
83+ )
8284
83- result.exitCode
84- }
85+ result.exitCode
8586 }
8687 }
8788
@@ -177,19 +178,24 @@ object MsvcEnvironment {
177178 // =========================
178179 // Capture MSVC environment
179180 // =========================
180- private def captureVcvarsEnv (vcvars : os.Path , workingDir : os.Path ): Map [String , String ] = {
181+ private def captureVcvarsEnv (
182+ vcvars : os.Path ,
183+ workingDir : os.Path
184+ ): (Seq [String ], Map [String , String ]) = {
185+
181186 val vcvarsCmd = vcvars.toIO.getAbsolutePath
182187
183- val cmd = Seq (
188+ val sentinel = " ::sentinel"
189+ val cmd = Seq (
184190 cmdExe,
185191 " /c" ,
186- s """ ( call \ " $vcvarsCmd\") & & set"""
192+ s """ set "VSCMD_DEBUG=1" & call " $vcvarsCmd" & echo $sentinel & set"""
187193 )
188194
189195 val out = new StringBuilder
190196
191197 val res = os.proc(cmd).call(
192- cwd = workingDir, // run vcvars from the working directory
198+ cwd = workingDir,
193199 env = sys.env,
194200 stdout = os.ProcessOutput .Readlines (line => out.append(line).append(" \n " )),
195201 stderr = os.Inherit ,
@@ -198,17 +204,40 @@ object MsvcEnvironment {
198204
199205 if res.exitCode != 0 then
200206 System .err.println(s " vcvars call failed with exit code ${res.exitCode}" )
201- Map .empty
207+ ( Seq .empty, Map .empty)
202208 else
203- out.result().linesIterator
204- .map(_.trim)
205- .filter(_.contains(" =" ))
206- .flatMap {
207- _.split(" =" , 2 ) match
208- case Array (k, v) => Some (k.toUpperCase(Locale .ROOT ) -> v)
209- case _ => None
210- }
211- .toMap
209+ val lines = out.result().linesIterator.map(_.trim).filter(_.nonEmpty).toVector
210+
211+ // Split at sentinel
212+ val (debugLines, afterSentinel) = lines.span(_ != sentinel)
213+
214+ // Drop the sentinel itself
215+ val envLines = afterSentinel.drop(1 )
216+
217+ // Parse KEY=VALUE lines
218+ val envMap =
219+ envLines
220+ .flatMap { line =>
221+ if line.contains(" =" ) then
222+ line.split(" =" , 2 ) match
223+ case Array (k, v) =>
224+ Some (k.toUpperCase(Locale .ROOT ) -> v)
225+ case _ =>
226+ None
227+ else None
228+ }
229+ .toMap
230+
231+ (debugLines, envMap)
232+ }
233+
234+ private def resolveNativeImage (graalHome : os.Path ): Option [os.Path ] = {
235+ val candidates = Seq (
236+ graalHome / " lib" / " svm" / " bin" / " native-image.exe" ,
237+ graalHome / " bin" / " native-image.exe" ,
238+ graalHome / " native-image.exe"
239+ )
240+ candidates.find(os.exists)
212241 }
213242
214243 private def vcvarsOpt : Option [os.Path ] = {
0 commit comments