From 24466f22c0c0e3235f0a21bd2a298c39df50e2f3 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 16 May 2013 15:20:16 +0200 Subject: [PATCH] Add target_compile_options command. This command populates the COMPILE_OPTIONS target property. --- Source/cmCommands.cxx | 2 + Source/cmTarget.cxx | 14 +++ Source/cmTarget.h | 2 + Source/cmTargetCompileOptionsCommand.cxx | 62 +++++++++++++ Source/cmTargetCompileOptionsCommand.h | 90 +++++++++++++++++++ .../target_compile_options/CMakeLists.txt | 35 ++++++++ .../target_compile_options/consumer.cpp | 18 ++++ .../target_compile_options/main.cpp | 18 ++++ Tests/CMakeLists.txt | 1 + 9 files changed, 242 insertions(+) create mode 100644 Source/cmTargetCompileOptionsCommand.cxx create mode 100644 Source/cmTargetCompileOptionsCommand.h create mode 100644 Tests/CMakeCommands/target_compile_options/CMakeLists.txt create mode 100644 Tests/CMakeCommands/target_compile_options/consumer.cpp create mode 100644 Tests/CMakeCommands/target_compile_options/main.cpp diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index 227b22678..75f2ae822 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -29,6 +29,7 @@ #include "cmSourceGroupCommand.cxx" #include "cmSubdirDependsCommand.cxx" #include "cmTargetCompileDefinitionsCommand.cxx" +#include "cmTargetCompileOptionsCommand.cxx" #include "cmTargetIncludeDirectoriesCommand.cxx" #include "cmTargetPropCommandBase.cxx" #include "cmUseMangledMesaCommand.cxx" @@ -71,6 +72,7 @@ void GetPredefinedCommands(std::list& commands.push_back(new cmSubdirDependsCommand); commands.push_back(new cmTargetIncludeDirectoriesCommand); commands.push_back(new cmTargetCompileDefinitionsCommand); + commands.push_back(new cmTargetCompileOptionsCommand); commands.push_back(new cmUseMangledMesaCommand); commands.push_back(new cmUtilitySourceCommand); commands.push_back(new cmVariableRequiresCommand); diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index ea5552efd..1f20be21c 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -2914,6 +2914,20 @@ void cmTarget::InsertInclude(const cmValueWithOrigin &entry, new cmTargetInternals::TargetPropertyEntry(ge.Parse(entry.Value))); } +//---------------------------------------------------------------------------- +void cmTarget::InsertCompileOption(const cmValueWithOrigin &entry, + bool before) +{ + cmGeneratorExpression ge(entry.Backtrace); + + std::vector::iterator position + = before ? this->Internal->CompileOptionsEntries.begin() + : this->Internal->CompileOptionsEntries.end(); + + this->Internal->CompileOptionsEntries.insert(position, + new cmTargetInternals::TargetPropertyEntry(ge.Parse(entry.Value))); +} + //---------------------------------------------------------------------------- static void processIncludeDirectories(cmTarget *tgt, const std::vector &entries, diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 7ec10dff1..b3d11318f 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -500,6 +500,8 @@ public: std::vector GetIncludeDirectories(const char *config); void InsertInclude(const cmValueWithOrigin &entry, bool before = false); + void InsertCompileOption(const cmValueWithOrigin &entry, + bool before = false); void AppendBuildInterfaceIncludes(); diff --git a/Source/cmTargetCompileOptionsCommand.cxx b/Source/cmTargetCompileOptionsCommand.cxx new file mode 100644 index 000000000..e80c8456b --- /dev/null +++ b/Source/cmTargetCompileOptionsCommand.cxx @@ -0,0 +1,62 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2013 Stephen Kelly + + 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 "cmTargetCompileOptionsCommand.h" + +bool cmTargetCompileOptionsCommand +::InitialPass(std::vector const& args, cmExecutionStatus &) +{ + return this->HandleArguments(args, "COMPILE_OPTIONS", PROCESS_BEFORE); +} + +void cmTargetCompileOptionsCommand +::HandleImportedTarget(const std::string &tgt) +{ + cmOStringStream e; + e << "Cannot specify compile options for imported target \"" + << tgt << "\"."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); +} + +void cmTargetCompileOptionsCommand +::HandleMissingTarget(const std::string &name) +{ + cmOStringStream e; + e << "Cannot specify compile options for target \"" << name << "\" " + "which is not built by this project."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); +} + +//---------------------------------------------------------------------------- +std::string cmTargetCompileOptionsCommand +::Join(const std::vector &content) +{ + std::string defs; + std::string sep; + for(std::vector::const_iterator it = content.begin(); + it != content.end(); ++it) + { + defs += sep + *it; + sep = ";"; + } + return defs; +} + +//---------------------------------------------------------------------------- +void cmTargetCompileOptionsCommand +::HandleDirectContent(cmTarget *tgt, const std::vector &content, + bool) +{ + cmListFileBacktrace lfbt; + this->Makefile->GetBacktrace(lfbt); + cmValueWithOrigin entry(this->Join(content), lfbt); + tgt->InsertCompileOption(entry); +} diff --git a/Source/cmTargetCompileOptionsCommand.h b/Source/cmTargetCompileOptionsCommand.h new file mode 100644 index 000000000..87fa1a720 --- /dev/null +++ b/Source/cmTargetCompileOptionsCommand.h @@ -0,0 +1,90 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2013 Stephen Kelly + + 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 cmTargetCompileOptionsCommand_h +#define cmTargetCompileOptionsCommand_h + +#include "cmTargetPropCommandBase.h" + +class cmTargetCompileOptionsCommand : public cmTargetPropCommandBase +{ +public: + /** + * This is a virtual constructor for the command. + */ + virtual cmCommand* Clone() + { + return new cmTargetCompileOptionsCommand; + } + + /** + * This is called when the command is first encountered in + * the CMakeLists.txt file. + */ + virtual bool InitialPass(std::vector const& args, + cmExecutionStatus &status); + + /** + * The name of the command as specified in CMakeList.txt. + */ + virtual const char* GetName() const { return "target_compile_options";} + + /** + * Succinct documentation. + */ + virtual const char* GetTerseDocumentation() const + { + return + "Add compile options to a target."; + } + + /** + * More documentation. + */ + virtual const char* GetFullDocumentation() const + { + return + " target_compile_options( [BEFORE] " + " [items1...]\n" + " [ [items2...] ...])\n" + "Specify compile options to use when compiling a given target. " + "The named must have been created by a command such as " + "add_executable or add_library and must not be an IMPORTED target. " + "If BEFORE is specified, the content will be prepended to the property " + "instead of being appended.\n" + "The INTERFACE, PUBLIC and PRIVATE keywords are required to specify " + "the scope of the following arguments. PRIVATE and PUBLIC items will " + "populate the COMPILE_OPTIONS property of . PUBLIC and " + "INTERFACE items will populate the INTERFACE_COMPILE_OPTIONS " + "property of . " + "The following arguments specify compile opitions. " + "Repeated calls for the same append items in the order called." + "\n" + "Arguments to target_compile_options may use \"generator " + "expressions\" with the syntax \"$<...>\". " + CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS + ; + } + + cmTypeMacro(cmTargetCompileOptionsCommand, cmTargetPropCommandBase); + +private: + virtual void HandleImportedTarget(const std::string &tgt); + virtual void HandleMissingTarget(const std::string &name); + + virtual void HandleDirectContent(cmTarget *tgt, + const std::vector &content, + bool prepend); + virtual std::string Join(const std::vector &content); +}; + +#endif diff --git a/Tests/CMakeCommands/target_compile_options/CMakeLists.txt b/Tests/CMakeCommands/target_compile_options/CMakeLists.txt new file mode 100644 index 000000000..06a48fb46 --- /dev/null +++ b/Tests/CMakeCommands/target_compile_options/CMakeLists.txt @@ -0,0 +1,35 @@ + +cmake_minimum_required(VERSION 2.8) + +project(target_compile_options) + +add_executable(target_compile_options + "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp" +) +target_compile_options(target_compile_options + PRIVATE $<$:-DMY_PRIVATE_DEFINE> + PUBLIC $<$:-DMY_PUBLIC_DEFINE> + INTERFACE $<$:-DMY_INTERFACE_DEFINE> +) + +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + target_compile_definitions(target_compile_options + PRIVATE + "DO_GNU_TESTS" + ) +endif() + +add_executable(consumer + "${CMAKE_CURRENT_SOURCE_DIR}/consumer.cpp" +) + +target_compile_options(consumer + PRIVATE $<$:$> +) + +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + target_compile_definitions(consumer + PRIVATE + "DO_GNU_TESTS" + ) +endif() diff --git a/Tests/CMakeCommands/target_compile_options/consumer.cpp b/Tests/CMakeCommands/target_compile_options/consumer.cpp new file mode 100644 index 000000000..12996065b --- /dev/null +++ b/Tests/CMakeCommands/target_compile_options/consumer.cpp @@ -0,0 +1,18 @@ + +#ifdef DO_GNU_TESTS + +# ifdef MY_PRIVATE_DEFINE +# error Unexpected MY_PRIVATE_DEFINE +# endif + +# ifndef MY_PUBLIC_DEFINE +# error Expected MY_PUBLIC_DEFINE +# endif + +# ifndef MY_INTERFACE_DEFINE +# error Expected MY_INTERFACE_DEFINE +# endif + +#endif + +int main() { return 0; } diff --git a/Tests/CMakeCommands/target_compile_options/main.cpp b/Tests/CMakeCommands/target_compile_options/main.cpp new file mode 100644 index 000000000..961c06dd7 --- /dev/null +++ b/Tests/CMakeCommands/target_compile_options/main.cpp @@ -0,0 +1,18 @@ + +#ifdef DO_GNU_TESTS + +# ifndef MY_PRIVATE_DEFINE +# error Expected MY_PRIVATE_DEFINE +# endif + +# ifndef MY_PUBLIC_DEFINE +# error Expected MY_PUBLIC_DEFINE +# endif + +# ifdef MY_INTERFACE_DEFINE +# error Unexpected MY_INTERFACE_DEFINE +# endif + +#endif + +int main() { return 0; } diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 3a28be200..e16fd011a 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1967,6 +1967,7 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/ ADD_TEST_MACRO(CMakeCommands.target_link_libraries target_link_libraries) ADD_TEST_MACRO(CMakeCommands.target_include_directories target_include_directories) ADD_TEST_MACRO(CMakeCommands.target_compile_definitions target_compile_definitions) + ADD_TEST_MACRO(CMakeCommands.target_compile_options target_compile_options) configure_file( "${CMake_SOURCE_DIR}/Tests/CTestTestCrash/test.cmake.in"