@@ -229,6 +229,7 @@ struct GlobalSettings
229229 bool prettyPrint;
230230 bool printCallees;
231231 bool verboseCallees;
232+ bool verbose;
232233 bool printTotalTime;
233234 bool timeTrace;
234235
@@ -244,6 +245,7 @@ struct GlobalSettings
244245
245246 // settings parser
246247 void setTarget (string option, string target) {
248+
247249 foreach (component; target.asLowerCase.text.splitter(' -' )) {
248250 auto aliasIndex = countUntil(targetAliases[].map! (a => a.from), component);
249251 if (aliasIndex >= 0 ) {
@@ -310,6 +312,7 @@ void printOptions() {
310312 stderr.writeln(" --print-commands Print commands that are being run" );
311313 stderr.writeln(" --pretty Enable pretty printing of the commands" );
312314 stderr.writeln(" --print-callees Print output of callee programs" );
315+ stderr.writeln(" --verbose Verbose printing of a build process" );
313316 stderr.writeln(" --verbose-callees Passes verbose flag to called programs" );
314317 stderr.writeln(" --print-total-time Print time of all run commands" );
315318 stderr.writeln(" --fuzzer Enable fuzzing" );
@@ -362,6 +365,7 @@ GlobalSettings parseSettings(string[] args, const(Config)[] configs) {
362365 " pretty" , " " , &settings.prettyPrint,
363366 " print-callees" , " " , &settings.printCallees,
364367 " verbose-callees" , " " , &settings.verboseCallees,
368+ " verbose" , " " , &settings.verbose,
365369 " print-total-time" , " " , &settings.printTotalTime,
366370 " no-deps" , " " , &settings.nodeps,
367371 " fuzzer" , " " , &settings.fuzzer,
@@ -455,6 +459,7 @@ struct CompileParams {
455459struct Job {
456460 CompileParams params;
457461 string [] args;
462+ string [string ] envVars;
458463 string workDir;
459464 // When executable is produced it will be a first artifact
460465 string [] artifacts;
@@ -467,6 +472,95 @@ struct Job {
467472 bool printOutput;
468473}
469474
475+ bool isSomeWindowsTarget (in GlobalSettings gs) {
476+ if (gs.targetOs != TargetOs.windows) return false ;
477+ if (gs.targetArch == TargetArch.arm64) return true ;
478+ if (gs.targetArch == TargetArch.x64) return true ;
479+ return false ;
480+ }
481+
482+ bool addWindowsLibs (in GlobalSettings gs, ref string [string ] envVars) {
483+ import std.file ;
484+ import std.path : baseName;
485+
486+ if (hostOs != TargetOs.windows) return true ;
487+ if (! isSomeWindowsTarget(gs)) return true ;
488+ // Only needed when cross-compiling
489+ if (! gs.isCrossCompiling) return true ;
490+
491+ import std.process : execute, Config;
492+ auto result = execute([" vswhere" , " -latest" , " -property" , " resolvedInstallationPath" ], null , Config.none, size_t .max);
493+
494+ if (result.status != 0 ) {
495+ stderr.writeln(" vswhere exited with " , result.status);
496+ stderr.writeln(" Cannot find Windows SDK and Visual Studio" );
497+ return false ;
498+ }
499+
500+ // LDC will skip environment setup if it detects VSINSTALLDIR and VSCMD_ARG_TGT_ARCH
501+ auto vsPath = result.output.strip;
502+ envVars[" VSINSTALLDIR" ] = vsPath;
503+ envVars[" VSCMD_ARG_TGT_ARCH" ] = archName[gs.targetArch];
504+
505+ auto sdkPath = ` C:\Program Files (x86)\Windows Kits\10\Lib` ;
506+ if (! exists(sdkPath)) {
507+ stderr.writefln(" Cannot find Windows SDK at %s" , sdkPath);
508+ return false ;
509+ }
510+
511+ string maxSdkPath;
512+ foreach (DirEntry e; dirEntries(sdkPath, SpanMode.shallow)) {
513+ if (gs.verbose) stderr.writefln(" - SDK %s" , e.name);
514+ // Filter out Windows Driver Kit (wdf)
515+ if (! e.name.baseName.startsWith(" 10." )) continue ;
516+ if (maxSdkPath is null || e.name > maxSdkPath) {
517+ maxSdkPath = e.name;
518+ }
519+ }
520+ if (maxSdkPath is null ) {
521+ stderr.writefln(" Cannot find SDK at %s" , sdkPath);
522+ return false ;
523+ }
524+
525+ auto vsToolsPath = buildPath(vsPath, ` VC\Tools\MSVC` );
526+ string maxVSPath;
527+ foreach (DirEntry e; dirEntries(vsToolsPath, SpanMode.shallow)) {
528+ if (gs.verbose) stderr.writefln(" - VS %s" , e.name);
529+ if (maxVSPath is null || e.name > maxVSPath) {
530+ maxVSPath = e.name;
531+ }
532+ }
533+ if (maxVSPath is null ) {
534+ stderr.writefln(" Cannot find Visual Studio at %s" , vsToolsPath);
535+ return false ;
536+ }
537+
538+ auto umLibsPath = buildPath(maxSdkPath, " um" , archName[gs.targetArch]);
539+ auto ucrtLibsPath = buildPath(maxSdkPath, " ucrt" , archName[gs.targetArch]);
540+ auto vsLibsPath = buildPath(maxVSPath, " lib" , archName[gs.targetArch]);
541+
542+ auto umTestPath = buildPath(umLibsPath, " kernel32.lib" );
543+ auto ucrtTestPath = buildPath(ucrtLibsPath, " libucrt.lib" );
544+ auto vsTestPath = buildPath(vsLibsPath, " libcmt.lib" );
545+
546+ if (! exists(umTestPath)) {
547+ stderr.writefln(" Cannot find kernel32.lib in %s" , umLibsPath);
548+ return false ;
549+ }
550+ if (! exists(ucrtTestPath)) {
551+ stderr.writefln(" Cannot find libucrt.lib in %s" , ucrtLibsPath);
552+ return false ;
553+ }
554+ if (! exists(vsTestPath)) {
555+ stderr.writefln(" Cannot find libcmt.lib in %s" , vsLibsPath);
556+ return false ;
557+ }
558+
559+ import std.array : join;
560+ envVars[" LIB" ] = join([umLibsPath, ucrtLibsPath, vsLibsPath], " ;" );
561+ return true ;
562+ }
563+
470564Job makeCompileJob (in GlobalSettings gs, in CompileParams params) {
471565 import std.path : buildPath;
472566
@@ -499,7 +593,12 @@ Job makeCompileJob(in GlobalSettings gs, in CompileParams params) {
499593 extraArtifacts ~= params.makeArtifactPath(osObjExt[gs.targetOs]);
500594
501595 Flags flags = selectFlags(gs, params);
502- string [] flagsStrings = flagsToStrings(gs, cast (size_t )flags, params);
596+
597+ string [string ] envVars;
598+ string [] flagsStrings;
599+ string [] linkerFlags;
600+ addWindowsLibs(gs, envVars);
601+ flagsToStrings(gs, cast (size_t )flags, params, flagsStrings);
503602
504603 flagsStrings ~= gs.makeTargetTripleFlag;
505604
@@ -532,6 +631,7 @@ Job makeCompileJob(in GlobalSettings gs, in CompileParams params) {
532631 artifacts : artifacts,
533632 extraArtifacts : extraArtifacts,
534633 printOutput : gs.printCallees,
634+ envVars : envVars,
535635 };
536636 return job;
537637}
@@ -619,10 +719,16 @@ JobResult runJob(in GlobalSettings gs, in Job job) {
619719 }
620720
621721 void printCommand () {
622- if (gs.prettyPrint)
722+ if (gs.prettyPrint) {
623723 stderr.writefln(" > %-(%s\n | %)" , job.args);
624- else
625- stderr.writefln(" > %-(%s %)" , job.args);
724+ foreach (key, val; job.envVars)
725+ stderr.writefln(" | $%s = %s" , key, val);
726+ } else {
727+ stderr.writef(" > %-(%s %)" , job.args);
728+ foreach (key, val; job.envVars)
729+ stderr.writef(" $%s=%s" , key, val);
730+ stderr.writeln;
731+ }
626732 }
627733
628734 if (gs.printCommands) printCommand;
@@ -632,7 +738,7 @@ JobResult runJob(in GlobalSettings gs, in Job job) {
632738 MonoTime startTime = currTime;
633739 import std.process : execute, Config;
634740 try {
635- auto result = execute(job.args, null , Config.none, size_t .max, job.workDir);
741+ auto result = execute(job.args, job.envVars , Config.none, size_t .max, job.workDir);
636742 MonoTime endTime = currTime;
637743
638744 void printCalleeOutput () {
@@ -800,10 +906,14 @@ Flags selectFlags(in GlobalSettings g, in CompileParams params)
800906 return flags;
801907}
802908
803- string [] flagsToStrings (in GlobalSettings gs, in size_t bits, in CompileParams params) {
909+ void flagsToStrings (
910+ in GlobalSettings gs,
911+ in size_t bits,
912+ in CompileParams params,
913+ ref string [] flags)
914+ {
804915 import core.bitop : bsf;
805916
806- string [] flags;
807917 string [] versions;
808918 string [] linkerFlags;
809919
@@ -1030,8 +1140,6 @@ string[] flagsToStrings(in GlobalSettings gs, in size_t bits, in CompileParams p
10301140 if (params.compiler == Compiler.dmd) flags ~= text(" -version=" , ver);
10311141 if (params.compiler == Compiler.ldc) flags ~= text(" -d-version=" , ver);
10321142 }
1033-
1034- return flags;
10351143}
10361144
10371145enum TargetType : ubyte {
0 commit comments