1 /// Common code for Visual Studio generators. 2 module mage.gen.vsCommon; 3 4 import mage; 5 6 import mage.util.option; 7 import mage.util.reflection; 8 import mage.msbuild; 9 import mage.msbuild.cpp; 10 import vcxproj = mage.msbuild.vcxproj; 11 import sln = mage.msbuild.sln; 12 13 import std.format : format; 14 import std.conv : to; 15 import std.uuid; 16 17 18 class VSGeneratorBase : IGenerator 19 { 20 protected VSInfo info; 21 22 this() 23 { 24 info.supportedLanguages ~= "c"; 25 info.supportedLanguages ~= "cpp"; 26 } 27 28 override void generate(MagicContext context, Target[] targets) 29 { 30 MSBuildProject[] projects; 31 auto slnName = *G.first("name").enforce("Global property `name' must be set."); 32 auto _generateBlock = log.Block(`Generating for project "%s"`, slnName); 33 34 targetProcessing: 35 foreach(target; targets) 36 { 37 auto targetName = target.properties["name"].get!string(); 38 auto _ = log.Block(`Processing target "%s"`.format(targetName)); 39 40 auto targetEnv = Environment("%s_env".format(targetName), target.properties, G.env); 41 context.setActive(targetEnv); 42 scope(exit) context.popActive(); 43 44 auto targetType = targetEnv.first("type").get!string(); 45 log.trace(`Target type is "%s"`, targetType); 46 if(targetType == "none") { 47 log.trace(`Skipping target.`); 48 continue; 49 } 50 51 string lang; 52 { 53 auto varLang = targetEnv.first("language"); 54 if(!(*varLang).hasValue()) { 55 log.error("The `language' property has to be set either as a global property, or on a per-Target basis."); 56 assert(0); 57 } 58 lang = varLang.get!string(); 59 } 60 log.info(`Language "%s"`.format(lang)); 61 languageProcessing: 62 foreach(supportedLang; info.supportedLanguages) 63 { 64 if(lang != supportedLang) { 65 continue languageProcessing; 66 } 67 68 // Consolidate all "includePaths" in the target properties. 69 auto allIncludePaths = targetEnv.all("includePaths").map!(a => a.get!(Path[])).joiner(); 70 foreach(ref path; allIncludePaths) 71 { 72 if(!path.isAbsolute) { 73 auto mageFilePath = target["mageFilePath"].get!Path; 74 path = mageFilePath.parent ~ path; 75 } 76 } 77 log.info("Include paths: %(\n...| - %s%)", allIncludePaths); 78 target["includePaths"] = allIncludePaths.array(); 79 auto proj = createProject(context, this.info, target); 80 proj.toolsVersion = this.info.toolsVersion; 81 if(auto pValue = target.tryGet("toolsVersion")) { 82 proj.toolsVersion = pValue.get!string; 83 } 84 projects ~= proj; 85 target["%s_vcxproj".format(this.info.genName)] = &projects[$-1]; 86 continue targetProcessing; 87 } 88 89 assert(0, `Unsupported language: "%s"; Supported languages: [%-(%s, %)]`.format(lang, this.info.supportedLanguages)); 90 } 91 92 foreach(proj; projects) 93 { 94 auto filePath = Path(proj.name) ~ "%s.vcxproj".format(proj.name); 95 vcxproj.generateFile(proj, filePath); 96 } 97 98 // Generate .sln file 99 sln.generateFile(this.info, projects, Path("%s.sln".format(slnName))); 100 } 101 }