Browse Source

Introduce add_compile_options command.

This command is similar to add_definitions, in that it affects
the compile options of all targets which follow it. The implementation
is similar to the implementation of the include_directories command,
in that it is based on populating a COMPILE_OPTIONS directory property
and using that to initialize the same property on targets.

Unlike the include_directories command however, the add_compile_options
command does not affect previously defined targets. That is, in
the following code, foo will not be compiled with -Wall, but bar
will be:

 add_library(foo ...)
 add_compile_options(-Wall)
 add_library(bar ...)
Stephen Kelly 12 years ago
parent
commit
a984f3257e

+ 28 - 0
Source/cmAddCompileOptionsCommand.cxx

@@ -0,0 +1,28 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2013 Stephen Kelly <[email protected]>
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+#include "cmAddCompileOptionsCommand.h"
+
+bool cmAddCompileOptionsCommand
+::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+{
+  if(args.size() < 1 )
+    {
+    return true;
+    }
+
+  for(std::vector<std::string>::const_iterator i = args.begin();
+      i != args.end(); ++i)
+    {
+    this->Makefile->AddCompileOption(i->c_str());
+    }
+  return true;
+}

+ 72 - 0
Source/cmAddCompileOptionsCommand.h

@@ -0,0 +1,72 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2013 Stephen Kelly <[email protected]>
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+#ifndef cmAddCompileOptionsCommand_h
+#define cmAddCompileOptionsCommand_h
+
+#include "cmCommand.h"
+#include "cmDocumentGeneratorExpressions.h"
+
+class cmAddCompileOptionsCommand : public cmCommand
+{
+public:
+  /**
+   * This is a virtual constructor for the command.
+   */
+  virtual cmCommand* Clone()
+    {
+    return new cmAddCompileOptionsCommand;
+    }
+
+  /**
+   * This is called when the command is first encountered in
+   * the CMakeLists.txt file.
+   */
+  virtual bool InitialPass(std::vector<std::string> const& args,
+                           cmExecutionStatus &status);
+
+  /**
+   * The name of the command as specified in CMakeList.txt.
+   */
+  virtual const char* GetName() const {return "add_compile_options";}
+
+  /**
+   * Succinct documentation.
+   */
+  virtual const char* GetTerseDocumentation() const
+    {
+    return "Adds options to the compilation of source files.";
+    }
+
+  /**
+   * More documentation.
+   */
+  virtual const char* GetFullDocumentation() const
+    {
+    return
+      "  add_compile_options(<option> ...)\n"
+      "Adds options to the compiler command line for sources in the "
+      "current directory and below.  This command can be used to add any "
+      "options, but alternative commands exist to add preprocessor "
+      "definitions or include directories.  "
+      "See documentation of the directory and target COMPILE_OPTIONS "
+      "properties for details.  "
+      "Arguments to add_compile_options may use \"generator "
+      "expressions\" with the syntax \"$<...>\".  "
+      CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
+      CM_DOCUMENT_LANGUAGE_GENERATOR_EXPRESSIONS
+      ;
+    }
+
+  cmTypeMacro(cmAddCompileOptionsCommand, cmCommand);
+};
+
+#endif

+ 2 - 0
Source/cmCommands.cxx

@@ -11,6 +11,7 @@
 ============================================================================*/
 #include "cmCommands.h"
 #if defined(CMAKE_BUILD_WITH_CMAKE)
+#include "cmAddCompileOptionsCommand.cxx"
 #include "cmAuxSourceDirectoryCommand.cxx"
 #include "cmBuildNameCommand.cxx"
 #include "cmElseIfCommand.cxx"
@@ -52,6 +53,7 @@ void GetPredefinedCommands(std::list<cmCommand*>&
   )
 {
 #if defined(CMAKE_BUILD_WITH_CMAKE)
+  commands.push_back(new cmAddCompileOptionsCommand);
   commands.push_back(new cmAuxSourceDirectoryCommand);
   commands.push_back(new cmBuildNameCommand);
   commands.push_back(new cmElseIfCommand);

+ 60 - 0
Source/cmMakefile.cxx

@@ -21,6 +21,7 @@
 #include "cmCacheManager.h"
 #include "cmFunctionBlocker.h"
 #include "cmListFileCache.h"
+#include "cmDocumentGeneratorExpressions.h"
 #include "cmCommandArgumentParserHelper.h"
 #include "cmDocumentCompileDefinitions.h"
 #include "cmGeneratorExpression.h"
@@ -1270,6 +1271,11 @@ void cmMakefile::RemoveDefineFlag(const char* flag,
     }
 }
 
+void cmMakefile::AddCompileOption(const char* option)
+{
+  this->AppendProperty("COMPILE_OPTIONS", option);
+}
+
 bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove)
 {
   // Create a regular expression to match valid definitions.
@@ -1493,6 +1499,12 @@ void cmMakefile::InitializeFromParent()
                                        parentIncludes.begin(),
                                        parentIncludes.end());
 
+  const std::vector<cmValueWithOrigin> parentOptions =
+                                        parent->GetCompileOptionsEntries();
+  this->CompileOptionsEntries.insert(this->CompileOptionsEntries.end(),
+                                     parentOptions.begin(),
+                                     parentOptions.end());
+
   this->SystemIncludeDirectories = parent->SystemIncludeDirectories;
 
   // define flags
@@ -3468,6 +3480,18 @@ void cmMakefile::SetProperty(const char* prop, const char* value)
                                         cmValueWithOrigin(value, lfbt));
     return;
     }
+  if (propname == "COMPILE_OPTIONS")
+    {
+    this->CompileOptionsEntries.clear();
+      if (!value)
+        {
+        return;
+        }
+    cmListFileBacktrace lfbt;
+    this->GetBacktrace(lfbt);
+    this->CompileOptionsEntries.push_back(cmValueWithOrigin(value, lfbt));
+    return;
+    }
 
   if ( propname == "INCLUDE_REGULAR_EXPRESSION" )
     {
@@ -3507,6 +3531,14 @@ void cmMakefile::AppendProperty(const char* prop, const char* value,
                                         cmValueWithOrigin(value, lfbt));
     return;
     }
+  if (propname == "COMPILE_OPTIONS")
+    {
+    cmListFileBacktrace lfbt;
+    this->GetBacktrace(lfbt);
+    this->CompileOptionsEntries.push_back(
+                                        cmValueWithOrigin(value, lfbt));
+    return;
+    }
   if ( propname == "LINK_DIRECTORIES" )
     {
     std::vector<std::string> varArgsExpanded;
@@ -3632,6 +3664,20 @@ const char *cmMakefile::GetProperty(const char* prop,
       }
     return output.c_str();
     }
+  else if (!strcmp("COMPILE_OPTIONS",prop))
+    {
+    std::string sep;
+    for (std::vector<cmValueWithOrigin>::const_iterator
+        it = this->CompileOptionsEntries.begin(),
+        end = this->CompileOptionsEntries.end();
+        it != end; ++it)
+      {
+      output += sep;
+      output += it->Value;
+      sep = ";";
+      }
+    return output.c_str();
+    }
 
   bool chain = false;
   const char *retVal =
@@ -4002,6 +4048,20 @@ void cmMakefile::DefineProperties(cmake *cm)
      "the include paths for the compiler. "
      "See also the include_directories command.");
 
+  cm->DefineProperty
+    ("COMPILE_OPTIONS", cmProperty::DIRECTORY,
+     "List of options to pass to the compiler.",
+     "This property specifies the list of directories given "
+     "so far for this property.  "
+     "This property exists on directories and targets.  "
+     "\n"
+     "The target property values are used by the generators to set "
+     "the options for the compiler.\n"
+     "Contents of COMPILE_OPTIONS may use \"generator expressions\" with "
+     "the syntax \"$<...>\".  "
+     CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
+     CM_DOCUMENT_LANGUAGE_GENERATOR_EXPRESSIONS);
+
   cm->DefineProperty
     ("LINK_DIRECTORIES", cmProperty::DIRECTORY,
      "List of linker search directories.",

+ 6 - 0
Source/cmMakefile.h

@@ -206,6 +206,7 @@ public:
    */
   void AddDefineFlag(const char* definition);
   void RemoveDefineFlag(const char* definition);
+  void AddCompileOption(const char* option);
 
   /** Create a new imported target with the name and type given.  */
   cmTarget* AddImportedTarget(const char* name, cmTarget::TargetType type,
@@ -866,6 +867,10 @@ public:
   {
     return this->IncludeDirectoriesEntries;
   }
+  std::vector<cmValueWithOrigin> GetCompileOptionsEntries() const
+  {
+    return this->CompileOptionsEntries;
+  }
 
   bool IsGeneratingBuildSystem(){ return this->GeneratingBuildSystem; }
   void SetGeneratingBuildSystem(){ this->GeneratingBuildSystem = true; }
@@ -919,6 +924,7 @@ protected:
   std::string DefineFlags;
 
   std::vector<cmValueWithOrigin> IncludeDirectoriesEntries;
+  std::vector<cmValueWithOrigin> CompileOptionsEntries;
 
   // Track the value of the computed DEFINITIONS property.
   void AddDefineFlag(const char*, std::string&);

+ 9 - 1
Source/cmTarget.cxx

@@ -297,7 +297,7 @@ void cmTarget::DefineProperties(cmake *cm)
      "List of options to pass to the compiler.",
      "This property specifies the list of options specified "
      "so far for this property.  "
-     "This property exists on targets only.  "
+     "This property exists on directories and targets.  "
      "\n"
      "The target property values are used by the generators to set "
      "the options for the compiler.\n"
@@ -1611,6 +1611,14 @@ void cmTarget::SetMakefile(cmMakefile* mf)
     {
     this->InsertInclude(*it);
     }
+  const std::vector<cmValueWithOrigin> parentOptions =
+                              this->Makefile->GetCompileOptionsEntries();
+
+  for (std::vector<cmValueWithOrigin>::const_iterator it
+              = parentOptions.begin(); it != parentOptions.end(); ++it)
+    {
+    this->InsertCompileOption(*it);
+    }
 
   if(this->TargetTypeValue == cmTarget::SHARED_LIBRARY
       || this->TargetTypeValue == cmTarget::MODULE_LIBRARY)

+ 14 - 0
Tests/CMakeCommands/add_compile_options/CMakeLists.txt

@@ -0,0 +1,14 @@
+cmake_minimum_required(VERSION 2.8)
+
+project(add_compile_options)
+
+add_compile_options(-DTEST_OPTION)
+
+add_executable(add_compile_options main.cpp)
+
+if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
+  target_compile_definitions(add_compile_options
+    PRIVATE
+      "DO_GNU_TESTS"
+  )
+endif()

+ 11 - 0
Tests/CMakeCommands/add_compile_options/main.cpp

@@ -0,0 +1,11 @@
+
+#ifdef DO_GNU_TESTS
+#  ifndef TEST_OPTION
+#  error Expected TEST_OPTION
+#  endif
+#endif
+
+int main(void)
+{
+  return 0;
+}