NETProjectGen.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. //
  2. // Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
  3. // LICENSE: Atomic Game Engine Editor and Tools EULA
  4. // Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
  5. // license information: https://github.com/AtomicGameEngine/AtomicGameEngine
  6. //
  7. #include <Atomic/IO/Log.h>
  8. #include <Atomic/IO/File.h>
  9. #include <Atomic/IO/FileSystem.h>
  10. #include "../ToolEnvironment.h"
  11. #include "NETProjectGen.h"
  12. namespace ToolCore
  13. {
  14. NETProjectBase::NETProjectBase(Context* context, NETProjectGen* projectGen):
  15. Object(context), xmlFile_(new XMLFile(context)), projectGen_(projectGen)
  16. {
  17. }
  18. NETProjectBase::~NETProjectBase()
  19. {
  20. }
  21. void NETProjectBase::ReplacePathStrings(String& path)
  22. {
  23. ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
  24. const String& atomicRoot = tenv->GetRootSourceDir();
  25. const String& scriptPlatform = projectGen_->GetScriptPlatform();
  26. path.Replace("$ATOMIC_ROOT$", atomicRoot, false);
  27. path.Replace("$SCRIPT_PLATFORM$", scriptPlatform, false);
  28. }
  29. NETCSProject::NETCSProject(Context* context, NETProjectGen* projectGen) : NETProjectBase(context, projectGen)
  30. {
  31. }
  32. NETCSProject::~NETCSProject()
  33. {
  34. }
  35. void NETCSProject::CreateCompileItemGroup(XMLElement &projectRoot)
  36. {
  37. FileSystem* fs = GetSubsystem<FileSystem>();
  38. XMLElement igroup = projectRoot.CreateChild("ItemGroup");
  39. for (unsigned i = 0; i < sourceFolders_.Size(); i++)
  40. {
  41. const String& sourceFolder = sourceFolders_[i];
  42. Vector<String> result;
  43. fs->ScanDir(result, sourceFolder, "*.cs", SCAN_FILES, true);
  44. for (unsigned j = 0; j < result.Size(); j++)
  45. {
  46. igroup.CreateChild("Compile").SetAttribute("Include", sourceFolder + result[j]);
  47. }
  48. }
  49. }
  50. void NETCSProject::CreateReferencesItemGroup(XMLElement &projectRoot)
  51. {
  52. ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
  53. FileSystem* fs = GetSubsystem<FileSystem>();
  54. const String& coreCLRAbsPath = tenv->GetNETCoreCLRAbsPath();
  55. XMLElement igroup = projectRoot.CreateChild("ItemGroup");
  56. XMLElement mscorlibref = igroup.CreateChild("Reference");
  57. mscorlibref.SetAttribute("Include", "mscorlib");
  58. mscorlibref.CreateChild("HintPath").SetValue(coreCLRAbsPath + "mscorlib.dll");
  59. mscorlibref.CreateChild("Private").SetValue("False");
  60. for (unsigned i = 0; i < references_.Size(); i++)
  61. {
  62. String ref = references_[i];
  63. String refpath = ref + ".dll";
  64. // we explicitly add mscorlib
  65. if (ref == "mscorlib")
  66. continue;
  67. XMLElement xref = igroup.CreateChild("Reference");
  68. xref.SetAttribute("Include", ref);
  69. // if we're a coreclr assembly, qualify it
  70. if (fs->FileExists(coreCLRAbsPath + refpath))
  71. {
  72. refpath = coreCLRAbsPath + refpath;
  73. }
  74. xref.CreateChild("HintPath").SetValue(refpath);
  75. xref.CreateChild("Private").SetValue("False");
  76. }
  77. }
  78. void NETCSProject::GetAssemblySearchPaths(String& paths)
  79. {
  80. paths.Clear();
  81. ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
  82. const String& coreCLRAbsPath = tenv->GetNETCoreCLRAbsPath();
  83. Vector<String> searchPaths;
  84. searchPaths.Push(coreCLRAbsPath);
  85. if (assemblySearchPaths_.Length())
  86. searchPaths.Push(assemblySearchPaths_);
  87. paths.Join(searchPaths, ";");
  88. }
  89. void NETCSProject::CreateReleasePropertyGroup(XMLElement &projectRoot)
  90. {
  91. XMLElement pgroup = projectRoot.CreateChild("PropertyGroup");
  92. pgroup.SetAttribute("Condition", " '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ");
  93. pgroup.CreateChild("DebugType").SetValue("full");
  94. pgroup.CreateChild("Optimize").SetValue("true");
  95. pgroup.CreateChild("OutputPath").SetValue(assemblyOutputPath_);
  96. pgroup.CreateChild("ErrorReport").SetValue("prompt");
  97. pgroup.CreateChild("WarningLevel").SetValue("4");
  98. pgroup.CreateChild("ConsolePause").SetValue("false");
  99. pgroup.CreateChild("AllowUnsafeBlocks").SetValue("true");
  100. pgroup.CreateChild("NoStdLib").SetValue("true");
  101. pgroup.CreateChild("NoConfig").SetValue("true");
  102. pgroup.CreateChild("NoCompilerStandardLib").SetValue("true");
  103. String assemblySearchPaths;
  104. GetAssemblySearchPaths(assemblySearchPaths);
  105. pgroup.CreateChild("AssemblySearchPaths").SetValue(assemblySearchPaths);
  106. }
  107. void NETCSProject::CreateDebugPropertyGroup(XMLElement &projectRoot)
  108. {
  109. XMLElement pgroup = projectRoot.CreateChild("PropertyGroup");
  110. pgroup.SetAttribute("Condition", " '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ");
  111. pgroup.CreateChild("DebugSymbols").SetValue("true");
  112. pgroup.CreateChild("DebugType").SetValue("full");
  113. pgroup.CreateChild("Optimize").SetValue("false");
  114. pgroup.CreateChild("OutputPath").SetValue(assemblyOutputPath_);
  115. pgroup.CreateChild("DefineConstants").SetValue("DEBUG;");
  116. pgroup.CreateChild("ErrorReport").SetValue("prompt");
  117. pgroup.CreateChild("WarningLevel").SetValue("4");
  118. pgroup.CreateChild("ConsolePause").SetValue("false");
  119. pgroup.CreateChild("AllowUnsafeBlocks").SetValue("true");
  120. pgroup.CreateChild("NoStdLib").SetValue("true");
  121. pgroup.CreateChild("NoConfig").SetValue("true");
  122. pgroup.CreateChild("NoCompilerStandardLib").SetValue("true");
  123. String assemblySearchPaths;
  124. GetAssemblySearchPaths(assemblySearchPaths);
  125. pgroup.CreateChild("AssemblySearchPaths").SetValue(assemblySearchPaths);
  126. }
  127. void NETCSProject::CreateMainPropertyGroup(XMLElement& projectRoot)
  128. {
  129. XMLElement pgroup = projectRoot.CreateChild("PropertyGroup");
  130. // Configuration
  131. XMLElement config = pgroup.CreateChild("Configuration");
  132. config.SetAttribute("Condition", " '$(Configuration)' == '' ");
  133. config.SetValue("Debug");
  134. // Platform
  135. XMLElement platform = pgroup.CreateChild("Platform");
  136. platform.SetAttribute("Condition", " '$(Platform)' == '' ");
  137. platform.SetValue("AnyCPU");
  138. // ProjectGuid
  139. XMLElement guid = pgroup.CreateChild("ProjectGuid");
  140. guid.SetValue(projectGuid_);
  141. // OutputType
  142. XMLElement outputType = pgroup.CreateChild("OutputType");
  143. outputType.SetValue(outputType_);
  144. // RootNamespace
  145. XMLElement rootNamespace = pgroup.CreateChild("RootNamespace");
  146. rootNamespace.SetValue(rootNamespace_);
  147. // AssemblyName
  148. XMLElement assemblyName = pgroup.CreateChild("AssemblyName");
  149. assemblyName.SetValue(assemblyName_);
  150. // TargetFrameworkVersion
  151. XMLElement targetFrameWork = pgroup.CreateChild("TargetFrameworkVersion");
  152. targetFrameWork.SetValue("4.5");
  153. }
  154. bool NETCSProject::Generate()
  155. {
  156. XMLElement project = xmlFile_->CreateRoot("Project");
  157. project.SetAttribute("DefaultTargets", "Build");
  158. project.SetAttribute("ToolsVersion", "4.0");
  159. project.SetAttribute("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
  160. CreateMainPropertyGroup(project);
  161. CreateDebugPropertyGroup(project);
  162. CreateReleasePropertyGroup(project);
  163. CreateReferencesItemGroup(project);
  164. CreateCompileItemGroup(project);
  165. project.CreateChild("Import").SetAttribute("Project", "$(MSBuildBinPath)\\Microsoft.CSharp.targets");
  166. // on msbuild this seems to stop referencing of framework assemblies
  167. project.CreateChild("Target").SetAttribute("Name", "GetReferenceAssemblyPaths");
  168. project.CreateChild("Target").SetAttribute("Name", "GetFrameworkPaths");
  169. String projectSource = xmlFile_->ToString();
  170. NETSolution* solution = projectGen_->GetSolution();
  171. String projectPath = solution->GetOutputPath() + name_ + ".csproj";
  172. SharedPtr<File> output(new File(context_, projectPath, FILE_WRITE));
  173. output->Write(projectSource.CString(), projectSource.Length());
  174. return true;
  175. }
  176. bool NETCSProject::Load(const JSONValue& root)
  177. {
  178. name_ = root["name"].GetString();
  179. projectGuid_ = root["projectGuid"].GetString();
  180. outputType_ = root["outputType"].GetString();
  181. rootNamespace_ = root["rootNamespace"].GetString();
  182. assemblyName_ = root["assemblyName"].GetString();
  183. assemblyOutputPath_ = root["assemblyOutputPath"].GetString();
  184. ReplacePathStrings(assemblyOutputPath_);
  185. assemblySearchPaths_ = root["assemblyOutputPath"].GetString();
  186. ReplacePathStrings(assemblySearchPaths_);
  187. const JSONArray& references = root["references"].GetArray();
  188. for (unsigned i = 0; i < references.Size(); i++)
  189. {
  190. String reference = references[i].GetString();
  191. ReplacePathStrings(reference);
  192. references_.Push(reference);
  193. }
  194. // msvc doesn't like including these
  195. if (projectGen_->GetMonoBuild())
  196. {
  197. references_.Push("System.Console");
  198. references_.Push("System.IO");
  199. references_.Push("System.IO.FileSystem");
  200. }
  201. const JSONArray& sources = root["sources"].GetArray();
  202. for (unsigned i = 0; i < sources.Size(); i++)
  203. {
  204. String source = sources[i].GetString();
  205. ReplacePathStrings(source);
  206. sourceFolders_.Push(AddTrailingSlash(source));
  207. }
  208. return true;
  209. }
  210. NETSolution::NETSolution(Context* context, NETProjectGen* projectGen) : NETProjectBase(context, projectGen)
  211. {
  212. }
  213. NETSolution::~NETSolution()
  214. {
  215. }
  216. bool NETSolution::Generate()
  217. {
  218. String slnPath = outputPath_ + name_ + ".sln";
  219. GenerateXamarinStudio(slnPath);
  220. return true;
  221. }
  222. void NETSolution::GenerateXamarinStudio(const String &slnPath)
  223. {
  224. String source = "Microsoft Visual Studio Solution File, Format Version 12.00\n";
  225. source += "# Visual Studio 2012\n";
  226. const Vector<SharedPtr<NETCSProject>>& projects = projectGen_->GetCSProjects();
  227. for (unsigned i = 0; i < projects.Size(); i++)
  228. {
  229. NETCSProject* p = projects.At(i);
  230. source += ToString("Project(\"{%s}\") = \"%s\", \"%s.csproj\", \"{%s}\"\n",
  231. p->GetProjectGUID().CString(), p->GetName().CString(), p->GetName().CString(),
  232. p->GetProjectGUID().CString());
  233. source += "EndProject\n";
  234. }
  235. source += "Global\n";
  236. source += " GlobalSection(SolutionConfigurationPlatforms) = preSolution\n";
  237. source += " Debug|Any CPU = Debug|Any CPU\n";
  238. source += " Release|Any CPU = Release|Any CPU\n";
  239. source += " EndGlobalSection\n";
  240. source += " GlobalSection(ProjectConfigurationPlatforms) = postSolution\n";
  241. for (unsigned i = 0; i < projects.Size(); i++)
  242. {
  243. NETCSProject* p = projects.At(i);
  244. source += ToString(" {%s}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n", p->GetProjectGUID().CString());
  245. source += ToString(" {%s}.Debug|Any CPU.Build.0 = Debug|Any CPU\n", p->GetProjectGUID().CString());
  246. source += ToString(" {%s}.Release|Any CPU.ActiveCfg = Release|Any CPU\n", p->GetProjectGUID().CString());
  247. source += ToString(" {%s}.Release|Any CPU.Build.0 = Release|Any CPU\n", p->GetProjectGUID().CString());
  248. }
  249. source += " EndGlobalSection\n";
  250. source += "EndGlobal\n";
  251. SharedPtr<File> output(new File(context_, slnPath, FILE_WRITE));
  252. output->Write(source.CString(), source.Length());
  253. output->Close();
  254. }
  255. bool NETSolution::Load(const JSONValue& root)
  256. {
  257. FileSystem* fs = GetSubsystem<FileSystem>();
  258. name_ = root["name"].GetString();
  259. outputPath_ = AddTrailingSlash(root["outputPath"].GetString());
  260. ReplacePathStrings(outputPath_);
  261. // TODO: use poco mkdirs
  262. if (!fs->DirExists(outputPath_))
  263. fs->CreateDir(outputPath_);
  264. return true;
  265. }
  266. NETProjectGen::NETProjectGen(Context* context) : Object(context),
  267. monoBuild_(false)
  268. {
  269. #ifndef ATOMIC_PLATFORM_WINDOWS
  270. monoBuild_ = true;
  271. #endif
  272. }
  273. NETProjectGen::~NETProjectGen()
  274. {
  275. }
  276. bool NETProjectGen::Generate()
  277. {
  278. solution_->Generate();
  279. for (unsigned i = 0; i < projects_.Size(); i++)
  280. {
  281. if (!projects_[i]->Generate())
  282. return false;
  283. }
  284. return true;
  285. }
  286. bool NETProjectGen::LoadProject(const JSONValue &root)
  287. {
  288. solution_ = new NETSolution(context_, this);
  289. solution_->Load(root["solution"]);
  290. const JSONValue& jprojects = root["projects"];
  291. if (!jprojects.IsArray() || ! jprojects.Size())
  292. return false;
  293. for (unsigned i = 0; i < jprojects.Size(); i++)
  294. {
  295. const JSONValue& jproject = jprojects[i];
  296. if (!jproject.IsObject())
  297. return false;
  298. SharedPtr<NETCSProject> csProject(new NETCSProject(context_, this));
  299. if (!csProject->Load(jproject))
  300. return false;
  301. projects_.Push(csProject);
  302. }
  303. return true;
  304. }
  305. bool NETProjectGen::LoadProject(const String& projectPath)
  306. {
  307. SharedPtr<File> file(new File(context_));
  308. if (!file->Open(projectPath))
  309. return false;
  310. String json;
  311. file->ReadText(json);
  312. JSONValue jvalue;
  313. if (!JSONFile::ParseJSON(json, jvalue))
  314. return false;
  315. return LoadProject(jvalue);
  316. }
  317. }