1 module mage.msbuild.sln; 2 3 import mage; 4 import mage.msbuild : VSInfo; 5 import mage.msbuild.cpp; 6 7 8 void generateFile(ref in VSInfo info, MSBuildProject[] projects, in Path slnPath) 9 { 10 auto _ = log.Block(`Generate .sln File "%s"`, slnPath); 11 log.trace("The original list of projects: %s", projects.map!(a => a.name)); 12 13 // Prioritize those that have the "isStartup" flag set. 14 projects.partition!( a => a.isStartup ); 15 16 log.trace("The sorted list of projects: %s", projects.map!(a => a.name)); 17 18 // Collect all possible configurations. 19 string[string] cfgs; 20 foreach(proj; projects) 21 { 22 foreach(cfg; proj.configs) 23 { 24 auto cfgString = "%s|%s".format(cfg.name, cfg.architecture); 25 cfgs[cfgString] = cfgString; 26 } 27 } 28 29 import mage.util.stream; 30 if(!slnPath.parent.exists) { 31 slnPath.parent.mkdir(); 32 } 33 auto stream = FileStream(slnPath); 34 stream.indentString = "\t"; 35 36 auto __ = log.Block("Writing .sln File."); 37 38 // Header 39 stream.writeln(`Microsoft Visual Studio Solution File, Format Version %s0`.format(info.toolsVersion)); 40 stream.writeln(`# Visual Studio %s`.format(info.year)); 41 42 foreach(proj; projects) 43 { 44 auto typeID = "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}"; 45 auto projGuidString = "{%s}".format(proj.guid).toUpper(); 46 auto _projBlock = log.forcedBlock("Processing project %s %s", proj.name, projGuidString); 47 auto projFilePath = Path(proj.name) ~ "%s.vcxproj".format(proj.name); 48 stream.writeln(`Project("%s") = "%s", "%s", "%s"`.format(typeID, proj.name, projFilePath, projGuidString)); 49 stream.indent(); 50 scope(exit) { 51 stream.dedent(); 52 stream.writeln("EndProject"); 53 } 54 55 { 56 stream.writeln(`ProjectSection(ProjectDependencies) = postProject`); 57 stream.indent(); 58 scope(exit) { 59 stream.dedent(); 60 stream.writeln("EndProjectSection"); 61 } 62 auto allDeps = proj.target.properties["dependencies"]; 63 auto nonExternalDeps = allDeps.get!(Target[]).filter!(a => !a.isExternal); 64 auto vcxprojPropertyName = "%s_vcxproj".format(info.genName); 65 auto projDeps = nonExternalDeps.map!(a => a.properties[vcxprojPropertyName].get!(MSBuildProject*)); 66 log.info("Deps: %s", projDeps.map!(a => "%s {%s}".format(a.name, a.guid.toString().toUpper()))); 67 foreach(ref projDep; projDeps) 68 { 69 auto guidString = "{%s}".format(projDep.guid).toUpper(); 70 log.info("Writing project dep: %s", guidString); 71 stream.writeln("%s = %s".format(guidString, guidString)); 72 } 73 } 74 } 75 76 // Global 77 { 78 stream.writeln("Global"); 79 stream.indent(); 80 scope(exit) { 81 stream.dedent(); 82 stream.writeln("EndGlobal"); 83 } 84 85 { 86 stream.writeln("GlobalSection(SolutionConfigurationPlatforms) = preSolution"); 87 stream.indent(); 88 scope(exit) { 89 stream.dedent(); 90 stream.writeln("EndGlobalSection"); 91 } 92 foreach(cfg, _; cfgs) { 93 stream.writeln("%s = %s".format(cfg, cfg)); 94 } 95 } 96 97 { 98 stream.writeln("GlobalSection(ProjectConfigurationPlatforms) = postSolution"); 99 stream.indent(); 100 scope(exit) { 101 stream.dedent(); 102 stream.writeln("EndGlobalSection"); 103 } 104 // TODO 105 //stream.writeln("# TODO"); 106 foreach(proj; projects) { 107 auto guidString = "{%s}".format(proj.guid).toUpper(); 108 foreach(cfg; proj.configs) { 109 auto cfgString = "%s|%s".format(cfg.name, cfg.architecture); 110 stream.writeln("%s.%s.ActiveCfg = %s".format(guidString, cfgString, cfgString)); 111 stream.writeln("%s.%s.Build.0 = %s".format(guidString, cfgString, cfgString)); 112 } 113 } 114 } 115 { 116 stream.writeln("GlobalSection(ExtensibilityGlobals) = postSolution"); 117 stream.indent(); 118 scope(exit) { 119 stream.dedent(); 120 stream.writeln("EndGlobalSection"); 121 } 122 } 123 { 124 stream.writeln("GlobalSection(ExtensibilityAddIns) = postSolution"); 125 stream.indent(); 126 scope(exit) { 127 stream.dedent(); 128 stream.writeln("EndGlobalSection"); 129 } 130 } 131 } // Global 132 }