Kaynağa Gözat

ENH: add custom commands, still failing a bunch of tests

Bill Hoffman 20 yıl önce
ebeveyn
işleme
f508fc9839
2 değiştirilmiş dosya ile 238 ekleme ve 3 silme
  1. 226 3
      Source/cmGlobalXCodeGenerator.cxx
  2. 12 0
      Source/cmGlobalXCodeGenerator.h

+ 226 - 3
Source/cmGlobalXCodeGenerator.cxx

@@ -340,15 +340,238 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
     frameworkBuildPhase->AddAttribute("files", buildFiles);
     frameworkBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", 
                                       this->CreateString("0"));
-
     cmXCodeObject* buildPhases = 
       this->CreateObject(cmXCodeObject::OBJECT_LIST);
+    this->CreateCustomCommands(buildPhases, sourceBuildPhase,
+                               headerBuildPhase, frameworkBuildPhase,
+                               cmtarget);
+    targets.push_back(this->CreateXCodeTarget(l->second, buildPhases));
+    }
+}
+
+void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject* buildPhases,
+                                                  cmXCodeObject*
+                                                  sourceBuildPhase,
+                                                  cmXCodeObject*
+                                                  headerBuildPhase,
+                                                  cmXCodeObject*
+                                                  frameworkBuildPhase,
+                                                  cmTarget& cmtarget)
+{
+  std::vector<cmCustomCommand> const & prebuild 
+    = cmtarget.GetPreBuildCommands();
+  std::vector<cmCustomCommand> const & prelink 
+    = cmtarget.GetPreLinkCommands();
+  std::vector<cmCustomCommand> const & postbuild 
+    = cmtarget.GetPostBuildCommands();
+  cmtarget.TraceVSDependencies(cmtarget.GetName(), m_CurrentMakefile);
+  std::vector<cmSourceFile*> &classes = cmtarget.GetSourceFiles();
+  // add all the sources
+  std::vector<cmCustomCommand> commands;
+  for(std::vector<cmSourceFile*>::iterator i = classes.begin(); 
+      i != classes.end(); ++i)
+    {
+    if((*i)->GetCustomCommand())
+      {
+      commands.push_back(*(*i)->GetCustomCommand());
+      }
+    }
+  
+  // create prebuild phase
+  cmXCodeObject* cmakeRulesBuildPhase = 0;
+  if(commands.size())
+    {
+    cmakeRulesBuildPhase = 
+      this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase);
+    cmakeRulesBuildPhase->AddAttribute("buildActionMask",
+                                this->CreateString("2147483647"));
+    cmXCodeObject* buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
+    cmakeRulesBuildPhase->AddAttribute("files", buildFiles);
+    cmakeRulesBuildPhase->AddAttribute("name", 
+                                this->CreateString("CMake Rules"));
+    cmakeRulesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", 
+                                this->CreateString("0"));
+    cmakeRulesBuildPhase->AddAttribute("shellPath",
+                                       this->CreateString("/bin/sh"));
+    this->AddCommandsToBuildPhase(cmakeRulesBuildPhase, cmtarget, commands,
+      "cmakeRulesCommands");
+    }
+  // create prebuild phase
+  cmXCodeObject* preBuildPhase = 0;
+  if(prebuild.size())
+    {
+    preBuildPhase = 
+      this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase);
+    preBuildPhase->AddAttribute("buildActionMask",
+                                this->CreateString("2147483647"));
+    cmXCodeObject* buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
+    preBuildPhase->AddAttribute("files", buildFiles);
+    preBuildPhase->AddAttribute("name", 
+                                this->CreateString("CMake PreBuild Rules"));
+    preBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", 
+                                this->CreateString("0"));
+    preBuildPhase->AddAttribute("shellPath", this->CreateString("/bin/sh"));
+    this->AddCommandsToBuildPhase(preBuildPhase, cmtarget, prebuild,
+      "preBuildCommands");
+    }
+  // create prebuild phase
+  cmXCodeObject* preLinkPhase = 0;
+  if(prelink.size())
+    {
+    preLinkPhase = 
+      this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase);
+    preLinkPhase->AddAttribute("buildActionMask",
+                               this->CreateString("2147483647"));
+    cmXCodeObject* buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
+    preLinkPhase->AddAttribute("files", buildFiles);
+    preLinkPhase->AddAttribute("name", 
+                               this->CreateString("CMake PreLink Rules"));
+    preLinkPhase->AddAttribute("runOnlyForDeploymentPostprocessing", 
+                               this->CreateString("0"));
+    preLinkPhase->AddAttribute("shellPath", this->CreateString("/bin/sh"));
+    this->AddCommandsToBuildPhase(preLinkPhase, cmtarget, prelink,
+                                  "preLinkCommands");
+    }
+  // create prebuild phase
+  cmXCodeObject* postBuildPhase = 0;
+  if(postbuild.size())
+    {
+    postBuildPhase = 
+      this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase);
+    postBuildPhase->AddAttribute("buildActionMask",
+                                 this->CreateString("2147483647"));
+    cmXCodeObject* buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
+    postBuildPhase->AddAttribute("files", buildFiles);
+    postBuildPhase->AddAttribute("name", 
+                                 this->CreateString("CMake PostBuild Rules"));
+    postBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", 
+                                 this->CreateString("0"));
+    postBuildPhase->AddAttribute("shellPath", this->CreateString("/bin/sh"));
+    this->AddCommandsToBuildPhase(postBuildPhase, cmtarget, postbuild,
+                                  "postBuildCommands");
+    }
+  // the order here is the order they will be built in
+  if(preBuildPhase)
+    {
+    buildPhases->AddObject(preBuildPhase);
+    }
+  if(cmakeRulesBuildPhase)
+    {
+    buildPhases->AddObject(cmakeRulesBuildPhase);
+    }
+  if(sourceBuildPhase)
+    {
     buildPhases->AddObject(sourceBuildPhase);
+    }
+  if(headerBuildPhase)
+    {
     buildPhases->AddObject(headerBuildPhase);
+    }
+  if(preLinkPhase)
+    {
+    buildPhases->AddObject(preLinkPhase);
+    }
+  if(frameworkBuildPhase)
+    {
     buildPhases->AddObject(frameworkBuildPhase);
-    targets.push_back(this->CreateXCodeTarget(l->second, buildPhases));
+    }
+  if(postBuildPhase)
+    {
+    buildPhases->AddObject(postBuildPhase);
+    }
+}
+
+void 
+cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
+                                                cmTarget& target,
+                                                std::vector<cmCustomCommand> 
+                                                const & commands,
+                                                const char* name)
+{
+  std::string makefile = m_CurrentMakefile->GetCurrentOutputDirectory();
+  cmSystemTools::MakeDirectory(makefile.c_str());
+  makefile += "/";
+  makefile += target.GetName();
+  makefile += "_";
+  makefile += name;
+  makefile += ".make";
+  cmGeneratedFileStream makefileStream(makefile.c_str());
+  if(!makefileStream)
+    {
+    return;
+    }
+  makefileStream << "# Generated by CMake, DO NOT EDIT\n";
+  makefileStream << "# Custom rules for " << target.GetName() << "\n";
+  
+  // have all depend on all outputs
+  makefileStream << "all: ";
+  for(std::vector<cmCustomCommand>::const_iterator i = commands.begin();
+      i != commands.end(); ++i)
+    {
+    cmCustomCommand const& cc = *i; 
+    if(cc.GetCommand().size())
+      {
+      if(cc.GetOutput().size())
+        {
+        makefileStream << "\\\n\t" << m_CurrentLocalGenerator
+          ->ConvertToRelativeOutputPath(cc.GetOutput().c_str());
+        }
+      else
+        {
+        makefileStream << "\\\n\t" << target.GetName();
+        }
+      }
+    }
+  makefileStream << "\n\n";
+  
+  for(std::vector<cmCustomCommand>::const_iterator i = commands.begin();
+      i != commands.end(); ++i)
+    {
+    cmCustomCommand const& cc = *i; 
+    if(cc.GetCommand().size())
+      {
+      
+      makefileStream << "\n#" << "Custom command rule: " << 
+        cc.GetComment() << "\n";
+      if(cc.GetOutput().size())
+        {
+        makefileStream << m_CurrentLocalGenerator
+          ->ConvertToRelativeOutputPath(cc.GetOutput().c_str()) << ": ";
+        }
+      else
+        {
+        // if no outputs then use the target name as this must
+        // be a utility target
+        makefileStream << target.GetName() << ": ";
+        }
+      for(std::vector<std::string>::const_iterator d = cc.GetDepends().begin();
+          d != cc.GetDepends().end(); ++d)
+        {
+        if(!this->FindTarget(d->c_str()))
+          {
+          makefileStream << "\\\n" << *d;
+          }
+        else
+          {
+          // if the depend is a target then make 
+          // the target with the source that is a custom command
+          // depend on the that target via a AddUtility call
+          target.AddUtility(d->c_str());
+          }
+        }
+      makefileStream << "\n";
+      makefileStream << "\t" << cc.GetCommand() << " " 
+                     << cc.GetArguments() << "\n";
+      }
     }
   
+  std::string dir = cmSystemTools::ConvertToOutputPath(
+    m_CurrentMakefile->GetCurrentOutputDirectory());
+  std::string makecmd = "make -C ";
+  makecmd += dir;
+  makecmd += " -f ";
+  makecmd += makefile;
+  buildphase->AddAttribute("shellScript", this->CreateString(makecmd.c_str()));
 }
 
 
@@ -566,7 +789,7 @@ cmGlobalXCodeGenerator::CreateUtilityTarget(cmTarget& cmtarget)
 
   cmXCodeObject* buildPhases = 
     this->CreateObject(cmXCodeObject::OBJECT_LIST);
-  buildPhases->AddObject(shellBuildPhase);
+  this->CreateCustomCommands(buildPhases, 0, 0, 0, cmtarget);
   target->AddAttribute("buildPhases", buildPhases);
   cmXCodeObject* buildSettings =
     this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);

+ 12 - 0
Source/cmGlobalXCodeGenerator.h

@@ -19,6 +19,7 @@
 
 #include "cmGlobalGenerator.h"
 #include "cmXCodeObject.h"
+#include "cmCustomCommand.h"
 class cmTarget;
 class cmSourceFile;
 
@@ -66,6 +67,17 @@ public:
   virtual void Generate();
 
 private:
+  void CreateCustomCommands(cmXCodeObject* buildPhases,
+                            cmXCodeObject* sourceBuildPhase,
+                            cmXCodeObject* headerBuildPhase,
+                            cmXCodeObject* frameworkBuildPhase,
+                            cmTarget& cmtarget);
+  
+  void AddCommandsToBuildPhase(cmXCodeObject* buildphase,
+                               cmTarget& target,
+                               std::vector<cmCustomCommand> 
+                               const & commands,
+                               const char* commandFileName);
   cmXCodeObject* FindXCodeTarget(cmTarget*);
   // create cmXCodeObject from these functions so that memory can be managed
   // correctly.  All objects created are stored in m_XCodeObjects.