Explorar el Código

Adding NET project generator

Josh Engebretson hace 10 años
padre
commit
953fa33db7

+ 26 - 0
Script/AtomicNET/AtomicNETProjects.json

@@ -0,0 +1,26 @@
+{
+  "solution" : {
+    "name" : "AtomicNET",
+    "outputPath" : "$ATOMIC_ROOT$/Artifacts/AtomicNET/Build/"
+  },
+  "projects" : [
+    {
+      "name": "AtomicNETEngine",
+      "projectGuid": "9821AC3B-E926-4FBB-90EC-BC4EBCD43FBC",
+      "outputType" : "Library",
+      "rootNamespace" : "AtomicEngine",
+      "assemblyName" : "AtomicNETEngine",
+      "assemblyOutputPath" : "$ATOMIC_ROOT$/Artifacts/AtomicNET/",
+      "references" : [
+        "System.Console", "System.Runtime" , "System.IO",  "System.IO.FileSystem",
+        "System.Linq", "System.Linq.Expressions" 
+      ],
+      "sources" : [
+        "$ATOMIC_ROOT$/Script/AtomicNET/AtomicNET/AtomicNETEngine/",
+        "$ATOMIC_ROOT$/Build/Source/Generated/$SCRIPT_PLATFORM$/CSharp/Packages/Atomic/Managed/",
+        "$ATOMIC_ROOT$/Build/Source/Generated/$SCRIPT_PLATFORM$/CSharp/Packages/AtomicNET/Managed/",
+        "$ATOMIC_ROOT$/Build/Source/Generated/$SCRIPT_PLATFORM$/CSharp/Packages/AtomicPlayer/Managed/"
+      ]
+    }
+  ]
+}

+ 5 - 1
Source/ToolCore/Command/CommandParser.cpp

@@ -14,6 +14,7 @@
 #include "PlayCmd.h"
 #include "EditCmd.h"
 #include "BindCmd.h"
+#include "NETProjectGenCmd.h"
 
 namespace ToolCore
 {
@@ -66,6 +67,10 @@ Command* CommandParser::Parse(const Vector<String>& arguments)
             {
                 cmd = new BindCmd(context_);
             }
+            else if (argument == "net-projectgen")
+            {
+                cmd = new NETProjectGenCmd(context_);
+            }
 
         }
 
@@ -74,7 +79,6 @@ Command* CommandParser::Parse(const Vector<String>& arguments)
             if (cmd->Parse(arguments, i, errorMsg_))
                 return cmd;
 
-            cmd->ReleaseRef();
             break;
         }
 

+ 73 - 0
Source/ToolCore/Command/NETProjectGenCmd.cpp

@@ -0,0 +1,73 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// LICENSE: Atomic Game Engine Editor and Tools EULA
+// Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
+// license information: https://github.com/AtomicGameEngine/AtomicGameEngine
+//
+
+#include <Atomic/Core/Context.h>
+#include <Atomic/Core/StringUtils.h>
+#include <Atomic/IO/Log.h>
+#include <Atomic/IO/File.h>
+
+#include "../ToolSystem.h"
+#include "../ToolEnvironment.h"
+#include "../NETTools/NETProjectGen.h"
+
+#include "NETProjectGenCmd.h"
+
+namespace ToolCore
+{
+
+NETProjectGenCmd::NETProjectGenCmd(Context* context) : Command(context)
+{
+
+}
+
+NETProjectGenCmd::~NETProjectGenCmd()
+{
+
+}
+
+bool NETProjectGenCmd::Parse(const Vector<String>& arguments, unsigned startIndex, String& errorMsg)
+{
+    String argument = arguments[startIndex].ToLower();
+
+    projectFile_ = startIndex + 1 < arguments.Size() ? arguments[startIndex + 1] : String::EMPTY;
+    scriptPlatform_ = startIndex + 2 < arguments.Size() ? arguments[startIndex + 2] : String::EMPTY;
+
+    if (argument != "net-projectgen")
+    {
+        errorMsg = "Unable to parse bind command";
+        return false;
+    }
+
+    if (!projectFile_.Length())
+    {
+        errorMsg = "Unable to parse net-projectgen command";
+        return false;
+    }
+
+
+    if (!scriptPlatform_.Length())
+    {
+        errorMsg = "Unable to parse net-projectgen command";
+        return false;
+    }
+
+    return true;
+}
+
+void NETProjectGenCmd::Run()
+{
+    SharedPtr<NETProjectGen> gen(new NETProjectGen(context_));
+    gen->SetScriptPlatform(scriptPlatform_);
+
+    gen->LoadProject(projectFile_);
+
+    gen->Generate();
+
+    Finished();
+}
+
+}

+ 39 - 0
Source/ToolCore/Command/NETProjectGenCmd.h

@@ -0,0 +1,39 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// LICENSE: Atomic Game Engine Editor and Tools EULA
+// Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
+// license information: https://github.com/AtomicGameEngine/AtomicGameEngine
+//
+
+#pragma once
+
+#include "Command.h"
+
+using namespace Atomic;
+
+namespace ToolCore
+{
+
+class NETProjectGenCmd: public Command
+{
+    OBJECT(NETProjectGenCmd);
+
+public:
+
+    NETProjectGenCmd(Context* context);
+    virtual ~NETProjectGenCmd();
+
+    bool Parse(const Vector<String>& arguments, unsigned startIndex, String& errorMsg);
+
+    void Run();
+
+    bool RequiresProjectLoad() { return false; }
+
+private:
+
+    String scriptPlatform_;
+    String projectFile_;
+
+};
+
+}

+ 390 - 0
Source/ToolCore/NETTools/NETProjectGen.cpp

@@ -0,0 +1,390 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// LICENSE: Atomic Game Engine Editor and Tools EULA
+// Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
+// license information: https://github.com/AtomicGameEngine/AtomicGameEngine
+//
+
+#include <Atomic/IO/Log.h>
+#include <Atomic/IO/File.h>
+#include <Atomic/IO/FileSystem.h>
+
+#include "../ToolEnvironment.h"
+#include "NETProjectGen.h"
+
+namespace ToolCore
+{
+
+NETProjectBase::NETProjectBase(Context* context, NETProjectGen* projectGen):
+    Object(context), xmlFile_(new XMLFile(context)), projectGen_(projectGen)
+{
+
+}
+
+NETProjectBase::~NETProjectBase()
+{
+
+}
+
+void NETProjectBase::ReplacePathStrings(String& path)
+{
+    ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
+
+    const String& atomicRoot = tenv->GetRootSourceDir();
+    const String& scriptPlatform = projectGen_->GetScriptPlatform();
+
+    path.Replace("$ATOMIC_ROOT$", atomicRoot, false);
+    path.Replace("$SCRIPT_PLATFORM$", scriptPlatform, false);
+}
+
+NETCSProject::NETCSProject(Context* context, NETProjectGen* projectGen) : NETProjectBase(context, projectGen)
+{
+
+}
+
+NETCSProject::~NETCSProject()
+{
+
+}
+
+void NETCSProject::CreateCompileItemGroup(XMLElement &projectRoot)
+{
+    FileSystem* fs = GetSubsystem<FileSystem>();
+
+    XMLElement igroup = projectRoot.CreateChild("ItemGroup");
+
+    for (unsigned i = 0; i < sourceFolders_.Size(); i++)
+    {
+        const String& sourceFolder = sourceFolders_[i];
+
+        Vector<String> result;
+        fs->ScanDir(result, sourceFolder, "*.cs", SCAN_FILES, true);
+
+        for (unsigned j = 0; j < result.Size(); j++)
+        {
+            igroup.CreateChild("Compile").SetAttribute("Include", sourceFolder + result[j]);
+
+        }
+
+    }
+
+}
+
+void NETCSProject::CreateReferencesItemGroup(XMLElement &projectRoot)
+{
+    ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
+    FileSystem* fs = GetSubsystem<FileSystem>();
+
+    const String& coreCLRAbsPath = tenv->GetNETCoreCLRAbsPath();
+
+    XMLElement igroup = projectRoot.CreateChild("ItemGroup");
+
+    XMLElement mscorlibref = igroup.CreateChild("Reference");
+    mscorlibref.SetAttribute("Include", "mscorlib");
+    mscorlibref.CreateChild("HintPath").SetValue(coreCLRAbsPath + "mscorlib.dll");
+    mscorlibref.CreateChild("Private").SetValue("False");
+
+    for (unsigned i = 0; i < references_.Size(); i++)
+    {
+        String ref = references_[i];
+        String refpath = ref + ".dll";
+
+        // we explicitly add mscorlib
+        if (ref == "mscorlib")
+            continue;
+
+        XMLElement xref = igroup.CreateChild("Reference");
+        xref.SetAttribute("Include", ref);
+
+        // if we're a coreclr assembly, qualify it
+        if (fs->FileExists(coreCLRAbsPath + refpath))
+        {
+            refpath = coreCLRAbsPath + refpath;
+        }
+
+        xref.CreateChild("HintPath").SetValue(refpath);
+        xref.CreateChild("Private").SetValue("False");
+
+    }
+}
+
+void NETCSProject::CreateReleasePropertyGroup(XMLElement &projectRoot)
+{
+    XMLElement pgroup = projectRoot.CreateChild("PropertyGroup");
+    pgroup.SetAttribute("Condition", " '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ");
+
+    pgroup.CreateChild("DebugType").SetValue("full");
+    pgroup.CreateChild("Optimize").SetValue("true");
+    pgroup.CreateChild("OutputPath").SetValue(assemblyOutputPath_);
+    pgroup.CreateChild("ErrorReport").SetValue("prompt");
+    pgroup.CreateChild("WarningLevel").SetValue("4");
+    pgroup.CreateChild("ConsolePause").SetValue("false");
+    pgroup.CreateChild("AllowUnsafeBlocks").SetValue("true");
+    pgroup.CreateChild("NoStdLib").SetValue("true");
+}
+
+void NETCSProject::CreateDebugPropertyGroup(XMLElement &projectRoot)
+{
+    XMLElement pgroup = projectRoot.CreateChild("PropertyGroup");
+    pgroup.SetAttribute("Condition", " '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ");
+
+    pgroup.CreateChild("DebugSymbols").SetValue("true");
+    pgroup.CreateChild("DebugType").SetValue("full");
+    pgroup.CreateChild("Optimize").SetValue("false");
+    pgroup.CreateChild("OutputPath").SetValue(assemblyOutputPath_);
+    pgroup.CreateChild("DefineConstants").SetValue("DEBUG;");
+    pgroup.CreateChild("ErrorReport").SetValue("prompt");
+    pgroup.CreateChild("WarningLevel").SetValue("4");
+    pgroup.CreateChild("ConsolePause").SetValue("false");
+    pgroup.CreateChild("AllowUnsafeBlocks").SetValue("true");
+    pgroup.CreateChild("NoStdLib").SetValue("true");
+}
+
+void NETCSProject::CreateMainPropertyGroup(XMLElement& projectRoot)
+{
+    XMLElement pgroup = projectRoot.CreateChild("PropertyGroup");
+
+    // Configuration
+    XMLElement config = pgroup.CreateChild("Configuration");
+    config.SetAttribute("Condition", " '$(Configuration)' == '' ");
+    config.SetValue("Debug");
+
+    // Platform
+    XMLElement platform = pgroup.CreateChild("Platform");
+    platform.SetAttribute("Condition", " '$(Platform)' == '' ");
+    platform.SetValue("AnyCPU");
+
+    // ProjectGuid
+    XMLElement guid = pgroup.CreateChild("ProjectGuid");
+    guid.SetValue(projectGuid_);
+
+    // OutputType
+    XMLElement outputType = pgroup.CreateChild("OutputType");
+    outputType.SetValue(outputType_);
+
+    // RootNamespace
+    XMLElement rootNamespace = pgroup.CreateChild("RootNamespace");
+    rootNamespace.SetValue(rootNamespace_);
+
+    // AssemblyName
+    XMLElement assemblyName = pgroup.CreateChild("AssemblyName");
+    assemblyName.SetValue(assemblyName_);
+
+    // TargetFrameworkVersion
+    XMLElement targetFrameWork = pgroup.CreateChild("TargetFrameworkVersion");
+    targetFrameWork.SetValue("4.5");
+
+}
+
+bool NETCSProject::Generate()
+{
+    XMLElement project = xmlFile_->CreateRoot("Project");
+
+    project.SetAttribute("DefaultTargets", "Build");
+    project.SetAttribute("ToolsVersion", "4.0");
+    project.SetAttribute("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
+
+    CreateMainPropertyGroup(project);
+    CreateDebugPropertyGroup(project);
+    CreateReleasePropertyGroup(project);
+    CreateReferencesItemGroup(project);
+    CreateCompileItemGroup(project);
+
+    project.CreateChild("Import").SetAttribute("Project", "$(MSBuildBinPath)\\Microsoft.CSharp.targets");
+
+    String projectSource = xmlFile_->ToString();
+
+    NETSolution* solution = projectGen_->GetSolution();
+
+    String projectPath = solution->GetOutputPath() + name_ + ".csproj";
+
+    SharedPtr<File> output(new File(context_, projectPath, FILE_WRITE));
+    output->Write(projectSource.CString(), projectSource.Length());
+
+    return true;
+}
+
+bool NETCSProject::Load(const JSONValue& root)
+{
+
+    name_ = root["name"].GetString();
+    projectGuid_ = root["projectGuid"].GetString();
+    outputType_ = root["outputType"].GetString();
+    rootNamespace_ = root["rootNamespace"].GetString();
+    assemblyName_ = root["assemblyName"].GetString();
+    assemblyOutputPath_ = root["assemblyOutputPath"].GetString();
+    ReplacePathStrings(assemblyOutputPath_);
+
+    const JSONArray& references = root["references"].GetArray();
+
+    for (unsigned i = 0; i < references.Size(); i++)
+    {
+        String reference = references[i].GetString();
+        ReplacePathStrings(reference);
+        references_.Push(reference);
+    }
+
+    const JSONArray& sources = root["sources"].GetArray();
+
+    for (unsigned i = 0; i < sources.Size(); i++)
+    {
+        String source = sources[i].GetString();
+        ReplacePathStrings(source);
+        sourceFolders_.Push(AddTrailingSlash(source));
+    }
+
+    return true;
+}
+
+NETSolution::NETSolution(Context* context, NETProjectGen* projectGen) : NETProjectBase(context, projectGen)
+{
+
+}
+
+NETSolution::~NETSolution()
+{
+
+}
+
+bool NETSolution::Generate()
+{
+
+    String slnPath = outputPath_ + name_ + ".sln";
+
+    GenerateXamarinStudio(slnPath);
+
+    return true;
+}
+
+void NETSolution::GenerateXamarinStudio(const String &slnPath)
+{
+
+    String source = "Microsoft Visual Studio Solution File, Format Version 12.00\n";
+    source += "# Visual Studio 2012\n";
+
+    const Vector<SharedPtr<NETCSProject>>& projects = projectGen_->GetCSProjects();
+    for (unsigned i = 0; i < projects.Size(); i++)
+    {
+        NETCSProject* p = projects.At(i);
+
+        source += ToString("Project(\"{%s}\") = \"%s\", \"%s.csproj\", \"{%s}\"\n",
+                           p->GetProjectGUID().CString(), p->GetName().CString(), p->GetName().CString(),
+                           p->GetProjectGUID().CString());
+
+        source += "EndProject\n";
+    }
+
+    source += "Global\n";
+    source += "    GlobalSection(SolutionConfigurationPlatforms) = preSolution\n";
+    source += "        Debug|Any CPU = Debug|Any CPU\n";
+    source += "        Release|Any CPU = Release|Any CPU\n";
+    source += "    EndGlobalSection\n";
+    source += "    GlobalSection(ProjectConfigurationPlatforms) = postSolution\n";
+
+    for (unsigned i = 0; i < projects.Size(); i++)
+    {
+        NETCSProject* p = projects.At(i);
+
+        source += ToString("        {%s}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n",  p->GetProjectGUID().CString());
+        source += ToString("        {%s}.Debug|Any CPU.Build.0 = Debug|Any CPU\n",  p->GetProjectGUID().CString());
+        source += ToString("        {%s}.Release|Any CPU.ActiveCfg = Release|Any CPU\n",  p->GetProjectGUID().CString());
+        source += ToString("        {%s}.Release|Any CPU.Build.0 = Release|Any CPU\n",  p->GetProjectGUID().CString());
+    }
+
+    source += "    EndGlobalSection\n";
+
+    source += "EndGlobal\n";
+
+    SharedPtr<File> output(new File(context_, slnPath, FILE_WRITE));
+    output->Write(source.CString(), source.Length());
+    output->Close();
+}
+
+bool NETSolution::Load(const JSONValue& root)
+{
+    FileSystem* fs = GetSubsystem<FileSystem>();
+
+    name_ = root["name"].GetString();
+
+    outputPath_ = AddTrailingSlash(root["outputPath"].GetString());
+    ReplacePathStrings(outputPath_);
+
+    // TODO: use poco mkdirs
+    if (!fs->DirExists(outputPath_))
+        fs->CreateDir(outputPath_);
+
+    return true;
+}
+
+NETProjectGen::NETProjectGen(Context* context) : Object(context)
+{
+
+}
+
+NETProjectGen::~NETProjectGen()
+{
+
+}
+
+bool NETProjectGen::Generate()
+{
+    solution_->Generate();
+
+    for (unsigned i = 0; i < projects_.Size(); i++)
+    {
+        if (!projects_[i]->Generate())
+            return false;
+    }
+    return true;
+}
+
+bool NETProjectGen::LoadProject(const JSONValue &root)
+{
+
+    solution_ = new NETSolution(context_, this);
+
+    solution_->Load(root["solution"]);
+
+    const JSONValue& jprojects = root["projects"];
+
+    if (!jprojects.IsArray() || ! jprojects.Size())
+        return false;
+
+    for (unsigned i = 0; i < jprojects.Size(); i++)
+    {
+        const JSONValue& jproject = jprojects[i];
+
+        if (!jproject.IsObject())
+            return false;
+
+        SharedPtr<NETCSProject> csProject(new NETCSProject(context_, this));
+
+        if (!csProject->Load(jproject))
+            return false;
+
+        projects_.Push(csProject);
+
+    }
+
+    return true;
+}
+
+bool NETProjectGen::LoadProject(const String& projectPath)
+{
+    SharedPtr<File> file(new File(context_));
+
+    if (!file->Open(projectPath))
+        return false;
+
+    String json;
+    file->ReadText(json);
+
+    JSONValue jvalue;
+
+    if (!JSONFile::ParseJSON(json, jvalue))
+        return false;
+
+    return LoadProject(jvalue);
+}
+
+}

+ 131 - 0
Source/ToolCore/NETTools/NETProjectGen.h

@@ -0,0 +1,131 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// LICENSE: Atomic Game Engine Editor and Tools EULA
+// Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
+// license information: https://github.com/AtomicGameEngine/AtomicGameEngine
+//
+
+#pragma once
+
+#include <Atomic/Core/Object.h>
+
+#include <Atomic/Resource/XMLFile.h>
+#include <Atomic/Resource/JSONFile.h>
+
+using namespace Atomic;
+
+namespace ToolCore
+{
+
+class NETProjectGen;
+
+class NETProjectBase : public Object
+{
+    OBJECT(NETProjectBase);
+
+public:
+
+    NETProjectBase(Context* context, NETProjectGen* projectGen);
+    virtual ~NETProjectBase();
+
+    void ReplacePathStrings(String& path);
+
+protected:
+
+    SharedPtr<XMLFile> xmlFile_;
+    WeakPtr<NETProjectGen> projectGen_;
+
+};
+
+class NETCSProject : public NETProjectBase
+{
+    OBJECT(NETCSProject);
+
+public:
+
+    NETCSProject(Context* context, NETProjectGen* projectGen);
+    virtual ~NETCSProject();
+
+    bool Load(const JSONValue& root);
+
+    const String& GetName() { return name_; }
+    const String& GetProjectGUID() { return projectGuid_; }
+
+    bool Generate();
+
+private:
+
+    void CreateCompileItemGroup(XMLElement &projectRoot);
+    void CreateReferencesItemGroup(XMLElement &projectRoot);
+    void CreateMainPropertyGroup(XMLElement &projectRoot);
+    void CreateDebugPropertyGroup(XMLElement &projectRoot);
+    void CreateReleasePropertyGroup(XMLElement &projectRoot);
+
+    String name_;
+    String projectGuid_;
+    String outputType_;
+    String rootNamespace_;
+    String assemblyName_;
+    String assemblyOutputPath_;
+
+    XMLElement xmlRoot_;
+
+    Vector<String> references_;
+    Vector<String> sourceFolders_;
+};
+
+class NETSolution : public NETProjectBase
+{
+    OBJECT(NETSolution);
+
+public:
+
+    NETSolution(Context* context, NETProjectGen* projectGen);
+    virtual ~NETSolution();
+
+    bool Load(const JSONValue& root);
+
+    bool Generate();
+
+    const String& GetOutputPath() { return outputPath_; }
+
+private:
+
+    void GenerateXamarinStudio(const String& slnPath);
+
+    String name_;
+    String outputPath_;
+
+};
+
+class NETProjectGen : public Object
+{
+    OBJECT(NETProjectGen);
+
+public:
+
+    NETProjectGen(Context* context);
+    virtual ~NETProjectGen();
+
+    const String& GetScriptPlatform() { return scriptPlatform_; }
+
+    NETSolution* GetSolution() { return solution_; }
+    const Vector<SharedPtr<NETCSProject>>& GetCSProjects() { return projects_; }
+
+    void SetScriptPlatform(const String& platform) { scriptPlatform_ = platform; }
+
+    bool Generate();
+
+    bool LoadProject(const JSONValue& root);
+    bool LoadProject(const String& projectPath);
+
+private:
+
+    String scriptPlatform_;
+
+    SharedPtr<NETSolution> solution_;
+    Vector<SharedPtr<NETCSProject>> projects_;
+
+};
+
+}