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 ...)
This commit is contained in:
Stephen Kelly 2013-06-04 10:30:24 +02:00
parent 00c3840cc8
commit a984f3257e
8 changed files with 202 additions and 1 deletions

View File

@ -0,0 +1,28 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2013 Stephen Kelly <steveire@gmail.com>
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;
}

View File

@ -0,0 +1,72 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2013 Stephen Kelly <steveire@gmail.com>
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

View File

@ -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);

View File

@ -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.",

View File

@ -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&);

View File

@ -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)

View File

@ -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()

View File

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