Преглед на файлове

ENH: add file specific compile flags

Bill Hoffman преди 24 години
родител
ревизия
076aafe79a

+ 2 - 0
Source/cmCommands.cxx

@@ -65,6 +65,7 @@
 #include "cmSetCommand.cxx"
 #include "cmSiteNameCommand.cxx"
 #include "cmSourceFilesCommand.cxx"
+#include "cmSourceFilesFlagsCommand.cxx"
 #include "cmSourceFilesRemoveCommand.cxx"
 #include "cmSourceGroupCommand.cxx"
 #include "cmSubdirCommand.cxx"
@@ -130,6 +131,7 @@ void GetPredefinedCommands(std::list<cmCommand*>& commands)
   commands.push_back(new cmSetCommand);
   commands.push_back(new cmSiteNameCommand);
   commands.push_back(new cmSourceFilesCommand);
+  commands.push_back(new cmSourceFilesFlagsCommand);
   commands.push_back(new cmSourceFilesRemoveCommand);
   commands.push_back(new cmSourceGroupCommand);
   commands.push_back(new cmSubdirCommand);

+ 35 - 9
Source/cmDSPWriter.cxx

@@ -210,7 +210,7 @@ void cmDSPWriter::WriteDSPFile(std::ostream& fout,
     std::string source = i->GetFullPath();
     cmSourceGroup& sourceGroup = m_Makefile->FindSourceGroup(source.c_str(),
                                                              sourceGroups);
-    sourceGroup.AddSource(source.c_str());
+    sourceGroup.AddSource(source.c_str(), &(*i));
     }
   
   // add any custom rules to the source groups
@@ -262,8 +262,12 @@ void cmDSPWriter::WriteDSPFile(std::ostream& fout,
           buildRules.begin(); cc != buildRules.end(); ++ cc)
       {
       std::string source = cc->first;
-      const cmSourceGroup::Commands& commands = cc->second;
-
+      const cmSourceGroup::Commands& commands = cc->second.m_Commands;
+      const char* compileFlags = 0;
+      if(cc->second.m_SourceFile)
+        {
+        compileFlags = cc->second.m_SourceFile->GetCompileFlags();
+        }
       if (source != libName || target.GetType() == cmTarget::UTILITY)
         {
         fout << "# Begin Source File\n\n";
@@ -280,7 +284,24 @@ void cmDSPWriter::WriteDSPFile(std::ostream& fout,
                                                   source.c_str());
           this->WriteCustomRule(fout, source.c_str(), totalCommandStr.c_str(), 
                                 totalCommand.m_Depends, 
-                                totalCommand.m_Outputs);
+                                totalCommand.m_Outputs, compileFlags);
+          }
+        else if(compileFlags)
+          {
+          for(std::vector<std::string>::iterator i
+                = m_Configurations.begin(); i != m_Configurations.end(); ++i)
+            { 
+            if (i == m_Configurations.begin())
+              {
+              fout << "!IF  \"$(CFG)\" == " << i->c_str() << std::endl;
+              }
+            else 
+              {
+              fout << "!ELSEIF  \"$(CFG)\" == " << i->c_str() << std::endl;
+              }
+            fout << "\n# ADD CPP " << compileFlags << "\n\n";
+            } 
+          fout << "!ENDIF\n\n";
           }
         fout << "# End Source File\n";
         }
@@ -299,10 +320,12 @@ void cmDSPWriter::WriteDSPFile(std::ostream& fout,
 
 
 void cmDSPWriter::WriteCustomRule(std::ostream& fout,
-                                    const char* source,
-                                    const char* command,
-                                    const std::set<std::string>& depends,
-                                    const std::set<std::string>& outputs)
+                                  const char* source,
+                                  const char* command,
+                                  const std::set<std::string>& depends,
+                                  const std::set<std::string>& outputs,
+                                  const char* flags
+                                  )
 {
   std::vector<std::string>::iterator i;
   for(i = m_Configurations.begin(); i != m_Configurations.end(); ++i)
@@ -315,7 +338,10 @@ void cmDSPWriter::WriteCustomRule(std::ostream& fout,
       {
       fout << "!ELSEIF  \"$(CFG)\" == " << i->c_str() << std::endl;
       }
-    
+    if(flags)
+      {
+      fout << "\n# ADD CPP " << flags << "\n\n";
+      }
     // Write out the dependencies for the rule.
     fout << "USERDEP__HACK=";
     for(std::set<std::string>::const_iterator d = depends.begin();

+ 2 - 1
Source/cmDSPWriter.h

@@ -79,7 +79,8 @@ private:
                        const char* source,
                        const char* command,
                        const std::set<std::string>& depends,
-                       const std::set<std::string>& outputs);
+                       const std::set<std::string>& outputs,
+                       const char* flags);
 
   std::string CreateTargetRules(const cmTarget &target, 
                                 const char *libName);

+ 68 - 13
Source/cmMSDotNETGenerator.cxx

@@ -769,6 +769,11 @@ void cmMSDotNETGenerator::WriteConfiguration(std::ostream& fout,
          << "\t\t\t\tInlineFunctionExpansion=\"1\"\n"
          << "\t\t\t\tPreprocessorDefinitions=\"WIN32,NDEBUG,_WINDOWS";
     }
+  if(target.GetType() == cmTarget::SHARED_LIBRARY
+     || target.GetType() == cmTarget::MODULE_LIBRARY)
+    {
+    fout << "," << libName << "_EXPORTS";
+    }
   this->OutputDefineFlags(fout);
   fout << "\"\n";
   if(m_Makefile->IsOn("CMAKE_CXX_USE_RTTI"))
@@ -801,14 +806,41 @@ void cmMSDotNETGenerator::OutputBuildTool(std::ostream& fout,
     {
     case cmTarget::STATIC_LIBRARY:
     {
-      std::string libpath = m_LibraryOutputPath + "$(OutDir)/" + libName + ".lib";
+      std::string libpath = m_LibraryOutputPath + 
+        "$(OutDir)/" + libName + ".lib";
       fout << "\t\t\t<Tool\n"
            << "\t\t\t\tName=\"VCLibrarianTool\"\n"
-           << "\t\t\t\t\tOutputFile=\"" << this->ConvertToXMLOutputPath(libpath.c_str()) << ".\"/>\n";
+           << "\t\t\t\t\tOutputFile=\"" 
+           << this->ConvertToXMLOutputPath(libpath.c_str()) << ".\"/>\n";
       break;
     }
     case cmTarget::SHARED_LIBRARY:
     case cmTarget::MODULE_LIBRARY:
+      fout << "\t\t\t<Tool\n"
+           << "\t\t\t\tName=\"VCLinkerTool\"\n"
+           << "\t\t\t\tAdditionalOptions=\"/MACHINE:I386\"\n"
+           << "\t\t\t\tAdditionalDependencies=\" odbc32.lib odbccp32.lib ";
+      this->OutputLibraries(fout, configName, libName, target);
+      fout << "\"\n";
+      fout << "\t\t\t\tOutputFile=\"" 
+           << m_ExecutableOutputPath << configName << "/" 
+           << libName << ".dll\"\n";
+      fout << "\t\t\t\tLinkIncremental=\"1\"\n";
+      fout << "\t\t\t\tSuppressStartupBanner=\"TRUE\"\n";
+      fout << "\t\t\t\tAdditionalLibraryDirectories=\"";
+      this->OutputLibraryDirectories(fout, configName, libName, target);
+      fout << "\"\n";
+      fout << "\t\t\t\tProgramDatabaseFile=\"" << m_LibraryOutputPath 
+           << "$(OutDir)\\" << libName << ".pdb\"\n";
+      if(strcmp(configName, "Debug") == 0)
+        {
+        fout << "\t\t\t\tGenerateDebugInformation=\"TRUE\"\n";
+        }
+      fout << "\t\t\t\tStackReserveSize=\"" 
+           << m_Makefile->GetDefinition("CMAKE_CXX_STACK_SIZE") << "\"\n";
+      fout << "\t\t\t\tImportLibrary=\"" 
+           << m_ExecutableOutputPath << configName << "/" 
+           << libName << ".lib\"/>\n";
       break;
     case cmTarget::EXECUTABLE:
     case cmTarget::WIN32_EXECUTABLE:
@@ -843,9 +875,6 @@ void cmMSDotNETGenerator::OutputBuildTool(std::ostream& fout,
       fout << "\t\t\t\tStackReserveSize=\"" 
            << m_Makefile->GetDefinition("CMAKE_CXX_STACK_SIZE") << "\"/>\n";
       break;
-
-      fout << "\t\t\t\tSubSystem=\"2\"\n";
-
     case cmTarget::UTILITY:
       break;
     }
@@ -961,7 +990,7 @@ void cmMSDotNETGenerator::WriteVCProjFile(std::ostream& fout,
     std::string source = i->GetFullPath();
     cmSourceGroup& sourceGroup = m_Makefile->FindSourceGroup(source.c_str(),
                                                              sourceGroups);
-    sourceGroup.AddSource(source.c_str());
+    sourceGroup.AddSource(source.c_str(), &(*i));
     }
   
   // add any custom rules to the source groups
@@ -1017,8 +1046,12 @@ void cmMSDotNETGenerator::WriteVCProjFile(std::ostream& fout,
           buildRules.begin(); cc != buildRules.end(); ++ cc)
       {
       std::string source = cc->first;
-      const cmSourceGroup::Commands& commands = cc->second;
-
+      const cmSourceGroup::Commands& commands = cc->second.m_Commands;
+      const char* compileFlags = 0;
+      if(cc->second.m_SourceFile)
+        {
+        compileFlags = cc->second.m_SourceFile->GetCompileFlags();
+        }
       if (source != libName || target.GetType() == cmTarget::UTILITY)
         {
         fout << "\t\t\t<File\n";
@@ -1034,7 +1067,21 @@ void cmMSDotNETGenerator::WriteVCProjFile(std::ostream& fout,
                                                   source.c_str());
           this->WriteCustomRule(fout, source.c_str(), totalCommandStr.c_str(), 
                                 totalCommand.m_Depends, 
-                                totalCommand.m_Outputs);
+                                totalCommand.m_Outputs, compileFlags);
+          }
+        else if(compileFlags)
+          {
+          for(std::vector<std::string>::iterator i
+                = m_Configurations.begin(); i != m_Configurations.end(); ++i)
+            {
+            fout << "\t\t\t\t<FileConfiguration\n"
+                 << "\t\t\t\t\tName=\""  << *i << "|Win32\">\n"
+                 << "\t\t\t\t\t<Tool\n"
+                 << "\t\t\t\t\tName=\"VCCLCompilerTool\"\n"
+                 << "\t\t\t\t\tAdditionalOptions=\""
+                 << compileFlags << "\"/>\n"
+                 << "\t\t\t\t</FileConfiguration>\n";
+            }
           }
         fout << "\t\t\t</File>\n";
         }
@@ -1054,10 +1101,11 @@ void cmMSDotNETGenerator::WriteVCProjFile(std::ostream& fout,
 
 
 void cmMSDotNETGenerator::WriteCustomRule(std::ostream& fout,
-                                    const char* source,
-                                    const char* command,
-                                    const std::set<std::string>& depends,
-                                    const std::set<std::string>& outputs)
+                                          const char* source,
+                                          const char* command,
+                                          const std::set<std::string>& depends,
+                                          const std::set<std::string>& outputs,
+                                          const char* compileFlags)
 {
   std::string cmd = command;
   cmSystemTools::ReplaceString(cmd, "\"", "&quot;");
@@ -1066,6 +1114,13 @@ void cmMSDotNETGenerator::WriteCustomRule(std::ostream& fout,
     {
     fout << "\t\t\t\t<FileConfiguration\n";
     fout << "\t\t\t\t\tName=\"" << *i << "|Win32\">\n";
+    if(compileFlags)
+      {
+      fout << "\t\t\t\t\t<Tool\n"
+           << "\t\t\t\t\tName=\"VCCLCompilerTool\"\n"
+           << "\t\t\t\t\tAdditionalOptions=\""
+           << compileFlags << "\"/>\n";
+      }
     fout << "\t\t\t\t\t<Tool\n"
          << "\t\t\t\t\tName=\"VCCustomBuildTool\"\n"
          << "\t\t\t\t\tCommandLine=\"" << cmd << "\n\"\n"

+ 2 - 1
Source/cmMSDotNETGenerator.h

@@ -110,7 +110,8 @@ private:
                        const char* source,
                        const char* command,
                        const std::set<std::string>& depends,
-                       const std::set<std::string>& outputs);
+                       const std::set<std::string>& outputs,
+                       const char* extraFlags);
 
   void OutputTargetRules(std::ostream& fout,
                          const cmTarget &target, 

+ 4 - 0
Source/cmSourceFile.h

@@ -107,10 +107,14 @@ public:
   const std::vector<std::string> &GetDepends() const {return m_Depends;}
   std::vector<std::string> &GetDepends() {return m_Depends;}
 
+  ///! Set/Get per file compiler flags
+  void SetCompileFlags(const char* f)  { m_CompileFlags = f;}
+  const char* GetCompileFlags() const { return m_CompileFlags.size() ? m_CompileFlags.c_str(): 0; }
 private:
   bool m_AbstractClass;
   bool m_WrapExclude;
   bool m_HeaderFileOnly;
+  std::string m_CompileFlags;
   std::string m_FullPath;
   std::string m_SourceName;
   std::string m_SourceExtension;

+ 49 - 0
Source/cmSourceFilesFlagsCommand.cxx

@@ -0,0 +1,49 @@
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  Copyright (c) 2002 Insight Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even 
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#include "cmSourceFilesFlagsCommand.h"
+
+// cmSourceFilesFlagsCommand
+bool cmSourceFilesFlagsCommand::InitialPass(std::vector<std::string> const& 
+                                             args)
+{
+  if(args.size() < 2 )
+    {
+    this->SetError("called with incorrect number of arguments");
+    return false;
+    }
+  cmMakefile::SourceMap &Classes = m_Makefile->GetSources();
+  std::vector<std::string>::const_iterator j = args.begin();
+  std::string flags = *j;
+  ++j;
+  for(;j != args.end(); ++j)
+    {   
+    for(cmMakefile::SourceMap::iterator l = Classes.begin(); 
+        l != Classes.end(); l++)
+      {
+      for(std::vector<cmSourceFile>::iterator i = l->second.begin(); 
+          i != l->second.end(); i++)
+        {
+        if(i->GetSourceName() == (*j))
+          {
+          i->SetCompileFlags(flags.c_str());
+          }
+        }
+      }
+    }
+  return true;
+}
+

+ 64 - 0
Source/cmSourceFilesFlagsCommand.h

@@ -0,0 +1,64 @@
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  Copyright (c) 2002 Insight Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even 
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef cmSourceFilesFlagsCommand_h
+#define cmSourceFilesFlagsCommand_h
+
+#include "cmStandardIncludes.h"
+#include "cmCommand.h"
+
+class cmSourceFilesFlagsCommand : public cmCommand
+{
+public:
+  virtual cmCommand* Clone() 
+    {
+      return new cmSourceFilesFlagsCommand;
+    }
+
+  /**
+   * This is called when the command is first encountered in
+   * the input file.
+   */
+  virtual bool InitialPass(std::vector<std::string> const& args);
+
+  /**
+   * The name of the command as specified in CMakeList.txt.
+   */
+  virtual const char* GetName() { return "SOURCE_FILES_FLAGS";}
+
+  /**
+   * Succinct documentation.
+   */
+  virtual const char* GetTerseDocumentation() 
+    {
+    return "Set compile flags for a specific list of files.";
+    }
+  
+  /**
+   * Longer documentation.
+   */
+  virtual const char* GetFullDocumentation()
+    {
+      return
+        "SOURCE_FILES_FLAGS(flags file1 file2 ..)";
+    }
+  
+  cmTypeMacro(cmSourceFilesFlagsCommand, cmCommand);
+};
+
+
+
+#endif

+ 9 - 6
Source/cmSourceGroup.cxx

@@ -50,13 +50,15 @@ bool cmSourceGroup::Matches(const char* name)
 /**
  * Add a source to the group that the compiler will know how to build.
  */
-void cmSourceGroup::AddSource(const char* name)
+void cmSourceGroup::AddSource(const char* name, const cmSourceFile* sf)
 {
   BuildRules::iterator s = m_BuildRules.find(name);
   if(s == m_BuildRules.end())
     {
+    SourceAndCommands sc;
+    sc.m_SourceFile = sf;
     // The source was not found.  Add it with no commands.
-    m_BuildRules[name];
+    m_BuildRules[name] = sc;
     return;
     }
 }
@@ -75,7 +77,8 @@ void cmSourceGroup::AddCustomCommand(const cmCustomCommand &cmd)
   if(s == m_BuildRules.end())
     {
     // The source was not found.  Add it with this command.
-    CommandFiles& cmdFiles = m_BuildRules[cmd.GetSourceName()][commandAndArgs];
+    CommandFiles& cmdFiles = 
+      m_BuildRules[cmd.GetSourceName()].m_Commands[commandAndArgs];
     cmdFiles.m_Command = cmd.GetCommand();
     cmdFiles.m_Arguments = cmd.GetArguments();
     cmdFiles.m_Depends.insert(cmd.GetDepends().begin(),cmd.GetDepends().end());
@@ -84,7 +87,7 @@ void cmSourceGroup::AddCustomCommand(const cmCustomCommand &cmd)
     }
   
   // The source already exists.  See if the command exists.
-  Commands& commands = s->second;
+  Commands& commands = s->second.m_Commands;
   Commands::iterator c = commands.find(commandAndArgs);
   if(c == commands.end())
     {
@@ -113,8 +116,8 @@ void cmSourceGroup::Print() const
       i != m_BuildRules.end(); ++i)
     {
     std::cout << "BuildRule: " << i->first.c_str() << "\n";
-    for(Commands::const_iterator j = i->second.begin();
-        j != i->second.end(); ++j)
+    for(Commands::const_iterator j = i->second.m_Commands.begin();
+        j != i->second.m_Commands.end(); ++j)
       {
       std::cout << "FullCommand: " << j->first.c_str() << "\n";
       std::cout << "Command: " << j->second.m_Command.c_str() << "\n";

+ 9 - 3
Source/cmSourceGroup.h

@@ -20,7 +20,7 @@
 #include "cmStandardIncludes.h"
 #include "cmRegularExpression.h"
 #include "cmCustomCommand.h"
-
+class cmSourceFile;
 
 /** \class cmSourceGroup
  * \brief Hold a group of sources as specified by a SOURCE_GROUP command.
@@ -54,15 +54,21 @@ public:
    */
   typedef std::map<cmStdString, CommandFiles> Commands;
 
+  struct SourceAndCommands
+  {
+    SourceAndCommands(): m_SourceFile(0) {}
+    const cmSourceFile* m_SourceFile;
+    Commands m_Commands;
+  };
   /**
    * Map from source to command map.
    */
-  typedef std::map<cmStdString, Commands>  BuildRules;
+  typedef std::map<cmStdString, SourceAndCommands>  BuildRules;
 
   bool Matches(const char* name);
   void SetGroupRegex(const char* regex)
     { m_GroupRegex.compile(regex); }
-  void AddSource(const char* name);
+  void AddSource(const char* name, const cmSourceFile*);
   void AddCustomCommand(const cmCustomCommand &cmd);
   const char* GetName() const
     { return m_Name.c_str(); }

+ 6 - 1
Source/cmUnixMakefileGenerator.cxx

@@ -1360,7 +1360,7 @@ void cmUnixMakefileGenerator::OutputCustomRules(std::ostream& fout)
           buildRules.begin(); cc != buildRules.end(); ++ cc)
       {
       std::string source = cc->first;
-      const cmSourceGroup::Commands& commands = cc->second;
+      const cmSourceGroup::Commands& commands = cc->second.m_Commands;
       // Loop through every command generating code from the current source.
       for(cmSourceGroup::Commands::const_iterator c = commands.begin();
           c != commands.end(); ++c)
@@ -1918,6 +1918,11 @@ void cmUnixMakefileGenerator::OutputSourceObjectBuildRules(std::ostream& fout)
         // Only output a rule for each .o once.
         if(rules.find(shortNameWithExt) == rules.end())
           {
+          if(source->GetCompileFlags())
+            {
+            exportsDef += source->GetCompileFlags();
+            exportsDef += " ";
+            }
           this->OutputBuildObjectFromSource(fout,
                                             shortName.c_str(),
                                             *source,