summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Kelly <steveire@gmail.com>2013-01-01 22:20:04 (GMT)
committerBrad King <brad.king@kitware.com>2013-01-10 14:46:57 (GMT)
commit8a37ebec784cefe4f04cb8897c23a014c3930052 (patch)
tree6a1fff33c9447c3fbb87f2496baf57fa208f4dec
parentc2cde7f1047b2f11e7d4a466000a20d8c42394be (diff)
downloadCMake-8a37ebec784cefe4f04cb8897c23a014c3930052.zip
CMake-8a37ebec784cefe4f04cb8897c23a014c3930052.tar.gz
CMake-8a37ebec784cefe4f04cb8897c23a014c3930052.tar.bz2
Add the target_include_directories command.
This is a convenience API to populate the corresponding properties.
-rw-r--r--Source/cmCommands.cxx3
-rw-r--r--Source/cmTargetIncludeDirectoriesCommand.cxx74
-rw-r--r--Source/cmTargetIncludeDirectoriesCommand.h95
-rw-r--r--Source/cmTargetPropCommandBase.cxx144
-rw-r--r--Source/cmTargetPropCommandBase.h57
-rw-r--r--Tests/CMakeCommands/target_include_directories/CMakeLists.txt50
-rw-r--r--Tests/CMakeCommands/target_include_directories/consumer.cpp27
-rw-r--r--Tests/CMakeCommands/target_include_directories/main.cpp22
-rw-r--r--Tests/CMakeLists.txt1
9 files changed, 473 insertions, 0 deletions
diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx
index 49ed967..6b315ea 100644
--- a/Source/cmCommands.cxx
+++ b/Source/cmCommands.cxx
@@ -28,6 +28,8 @@
#include "cmRemoveDefinitionsCommand.cxx"
#include "cmSourceGroupCommand.cxx"
#include "cmSubdirDependsCommand.cxx"
+#include "cmTargetIncludeDirectoriesCommand.cxx"
+#include "cmTargetPropCommandBase.cxx"
#include "cmUseMangledMesaCommand.cxx"
#include "cmUtilitySourceCommand.cxx"
#include "cmVariableRequiresCommand.cxx"
@@ -66,6 +68,7 @@ void GetPredefinedCommands(std::list<cmCommand*>&
commands.push_back(new cmRemoveDefinitionsCommand);
commands.push_back(new cmSourceGroupCommand);
commands.push_back(new cmSubdirDependsCommand);
+ commands.push_back(new cmTargetIncludeDirectoriesCommand);
commands.push_back(new cmUseMangledMesaCommand);
commands.push_back(new cmUtilitySourceCommand);
commands.push_back(new cmVariableRequiresCommand);
diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx
new file mode 100644
index 0000000..18e2cba
--- /dev/null
+++ b/Source/cmTargetIncludeDirectoriesCommand.cxx
@@ -0,0 +1,74 @@
+/*============================================================================
+ 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 "cmTargetIncludeDirectoriesCommand.h"
+
+#include "cmMakefileIncludeDirectoriesEntry.h"
+
+//----------------------------------------------------------------------------
+bool cmTargetIncludeDirectoriesCommand
+::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+{
+ return this->HandleArguments(args, "INCLUDE_DIRECTORIES", PROCESS_BEFORE);
+}
+
+//----------------------------------------------------------------------------
+void cmTargetIncludeDirectoriesCommand
+::HandleImportedTargetInvalidScope(const std::string &tgt,
+ const std::string &scope)
+{
+ cmOStringStream e;
+ e << "Cannot specify " << scope << " include directories for imported "
+ "target \"" << tgt << "\". Include directories can only be "
+ "specified for an imported target in the INTERFACE mode.";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+}
+
+//----------------------------------------------------------------------------
+void cmTargetIncludeDirectoriesCommand
+::HandleMissingTarget(const std::string &name)
+{
+ cmOStringStream e;
+ e << "Cannot specify include directories for target \"" << name << "\" "
+ "which is not built by this project.";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+}
+
+//----------------------------------------------------------------------------
+bool cmTargetIncludeDirectoriesCommand
+::HandleNonTargetArg(std::string &content,
+ const std::string &sep,
+ const std::string &entry,
+ const std::string &tgt)
+{
+ if (!cmSystemTools::FileIsFullPath(entry.c_str()))
+ {
+ cmOStringStream e;
+ e << "Cannot specify relative include directory \"" << entry << "\" for "
+ "target \"" << tgt << "\". Only absolute paths are permitted";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return false;
+ }
+
+ content += sep + entry;
+ return true;
+}
+
+//----------------------------------------------------------------------------
+void cmTargetIncludeDirectoriesCommand
+::HandleDirectContent(cmTarget *tgt, const std::string &content,
+ bool prepend)
+{
+ cmListFileBacktrace lfbt;
+ this->Makefile->GetBacktrace(lfbt);
+ cmMakefileIncludeDirectoriesEntry entry(content, lfbt);
+ tgt->InsertInclude(entry, prepend);
+}
diff --git a/Source/cmTargetIncludeDirectoriesCommand.h b/Source/cmTargetIncludeDirectoriesCommand.h
new file mode 100644
index 0000000..c1957d6
--- /dev/null
+++ b/Source/cmTargetIncludeDirectoriesCommand.h
@@ -0,0 +1,95 @@
+/*============================================================================
+ 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 cmTargetIncludeDirectoriesCommand_h
+#define cmTargetIncludeDirectoriesCommand_h
+
+#include "cmTargetPropCommandBase.h"
+
+//----------------------------------------------------------------------------
+class cmTargetIncludeDirectoriesCommand : public cmTargetPropCommandBase
+{
+public:
+ /**
+ * This is a virtual constructor for the command.
+ */
+ virtual cmCommand* Clone()
+ {
+ return new cmTargetIncludeDirectoriesCommand;
+ }
+
+ /**
+ * 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 "target_include_directories";}
+
+ /**
+ * Succinct documentation.
+ */
+ virtual const char* GetTerseDocumentation() const
+ {
+ return
+ "Add include directories to a target.";
+ }
+
+ /**
+ * More documentation.
+ */
+ virtual const char* GetFullDocumentation() const
+ {
+ return
+ " target_include_directories(<target> [BEFORE] "
+ "<INTERFACE|PUBLIC|PRIVATE> [items1...]\n"
+ " [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])\n"
+ "Specify include directories or targets to use when compiling a given "
+ "target. "
+ "The named <target> must have been created by a command such as "
+ "add_executable or add_library.\n"
+ "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 INCLUDE_DIRECTORIES property of <target>. PUBLIC and "
+ "INTERFACE items will populate the INTERFACE_INCLUDE_DIRECTORIES "
+ "property of <target>. "
+ "The non-scope arguments specify either include directories or targets "
+ "to use INTERFACE_INCLUDE_DIRECTORIES from. Any specified include "
+ "directories must be absolute paths, not relative paths. "
+ "Repeated calls for the same <target> append items in the order called."
+ "\n"
+ ;
+ }
+
+ cmTypeMacro(cmTargetIncludeDirectoriesCommand, cmCommand);
+
+private:
+ virtual void HandleImportedTargetInvalidScope(const std::string &tgt,
+ const std::string &scope);
+ virtual void HandleMissingTarget(const std::string &name);
+
+ virtual bool HandleNonTargetArg(std::string &content,
+ const std::string &sep,
+ const std::string &entry,
+ const std::string &tgt);
+
+ virtual void HandleDirectContent(cmTarget *tgt, const std::string &content,
+ bool prepend);
+};
+
+#endif
diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx
new file mode 100644
index 0000000..69aaf17
--- /dev/null
+++ b/Source/cmTargetPropCommandBase.cxx
@@ -0,0 +1,144 @@
+/*============================================================================
+ 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 "cmTargetPropCommandBase.h"
+
+#include "cmGlobalGenerator.h"
+
+//----------------------------------------------------------------------------
+bool cmTargetPropCommandBase
+::HandleArguments(std::vector<std::string> const& args, const char *prop,
+ ArgumentFlags flags)
+{
+ if(args.size() < 3)
+ {
+ this->SetError("called with incorrect number of arguments");
+ return false;
+ }
+
+ // Lookup the target for which libraries are specified.
+ this->Target =
+ this->Makefile->GetCMakeInstance()
+ ->GetGlobalGenerator()->FindTarget(0, args[0].c_str());
+ if(!this->Target)
+ {
+ this->Target = this->Makefile->FindTargetToUse(args[0].c_str());
+ }
+ if(!this->Target)
+ {
+ this->HandleMissingTarget(args[0]);
+ return false;
+ }
+
+ unsigned int argIndex = 1;
+
+ bool prepend = false;
+ if ((flags & PROCESS_BEFORE) && args[argIndex] == "BEFORE")
+ {
+ if (args.size() < 4)
+ {
+ this->SetError("called with incorrect number of arguments");
+ return false;
+ }
+ prepend = true;
+ ++argIndex;
+ }
+
+ this->Property = prop;
+
+ while (argIndex < args.size())
+ {
+ if (!this->ProcessContentArgs(args, argIndex, prepend))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+//----------------------------------------------------------------------------
+bool cmTargetPropCommandBase
+::ProcessContentArgs(std::vector<std::string> const& args,
+ unsigned int &argIndex, bool prepend)
+{
+ const std::string scope = args[argIndex];
+
+ if(scope != "PUBLIC"
+ && scope != "PRIVATE"
+ && scope != "INTERFACE" )
+ {
+ this->SetError("called with invalid arguments");
+ return false;
+ }
+
+ if(this->Target->IsImported() && scope != "INTERFACE")
+ {
+ this->HandleImportedTargetInvalidScope(args[0], scope);
+ return false;
+ }
+
+ ++argIndex;
+
+ std::string content;
+
+ std::string sep;
+ for(unsigned int i=argIndex; i < args.size(); ++i, ++argIndex)
+ {
+ if(args[i] == "PUBLIC"
+ || args[i] == "PRIVATE"
+ || args[i] == "INTERFACE" )
+ {
+ this->PopulateTargetProperies(scope, content, prepend);
+ return true;
+ }
+ if (this->Makefile->FindTargetToUse(args[i].c_str()))
+ {
+ content += sep + "$<TARGET_PROPERTY:" + args[i]
+ + ",INTERFACE_" + this->Property + ">";
+ }
+ else if (!this->HandleNonTargetArg(content, sep, args[i], args[0]))
+ {
+ return false;
+ }
+ sep = ";";
+ }
+ this->PopulateTargetProperies(scope, content, prepend);
+ return true;
+}
+
+//----------------------------------------------------------------------------
+void cmTargetPropCommandBase
+::PopulateTargetProperies(const std::string &scope,
+ const std::string &content, bool prepend)
+{
+ if (scope == "PRIVATE" || scope == "PUBLIC")
+ {
+ this->HandleDirectContent(this->Target, content, prepend);
+ }
+ if (scope == "INTERFACE" || scope == "PUBLIC")
+ {
+ if (prepend)
+ {
+ const std::string propName = std::string("INTERFACE_") + this->Property;
+ const char *propValue = this->Target->GetProperty(propName.c_str());
+ const std::string totalContent = content + (propValue
+ ? std::string(";") + propValue
+ : std::string());
+ this->Target->SetProperty(propName.c_str(), totalContent.c_str());
+ }
+ else
+ {
+ this->Target->AppendProperty(("INTERFACE_" + this->Property).c_str(),
+ content.c_str());
+ }
+ }
+}
diff --git a/Source/cmTargetPropCommandBase.h b/Source/cmTargetPropCommandBase.h
new file mode 100644
index 0000000..90e3bbb
--- /dev/null
+++ b/Source/cmTargetPropCommandBase.h
@@ -0,0 +1,57 @@
+/*============================================================================
+ 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 cmTargetPropCommandBase_h
+#define cmTargetPropCommandBase_h
+
+#include "cmCommand.h"
+
+class cmTarget;
+
+//----------------------------------------------------------------------------
+class cmTargetPropCommandBase : public cmCommand
+{
+public:
+
+ enum ArgumentFlags {
+ NO_FLAGS = 0,
+ PROCESS_BEFORE = 1
+ };
+
+ bool HandleArguments(std::vector<std::string> const& args,
+ const char *prop, ArgumentFlags flags = NO_FLAGS);
+
+private:
+ virtual void HandleImportedTargetInvalidScope(const std::string &tgt,
+ const std::string &scope) = 0;
+ virtual void HandleMissingTarget(const std::string &name) = 0;
+
+ virtual bool HandleNonTargetArg(std::string &content,
+ const std::string &sep,
+ const std::string &entry,
+ const std::string &tgt) = 0;
+
+ virtual void HandleDirectContent(cmTarget *tgt,
+ const std::string &content,
+ bool prepend) = 0;
+
+ bool ProcessContentArgs(std::vector<std::string> const& args,
+ unsigned int &argIndex, bool prepend);
+ void PopulateTargetProperies(const std::string &scope,
+ const std::string &content, bool prepend);
+
+private:
+ cmTarget *Target;
+ std::string Property;
+};
+
+#endif
diff --git a/Tests/CMakeCommands/target_include_directories/CMakeLists.txt b/Tests/CMakeCommands/target_include_directories/CMakeLists.txt
new file mode 100644
index 0000000..a0f2ee0
--- /dev/null
+++ b/Tests/CMakeCommands/target_include_directories/CMakeLists.txt
@@ -0,0 +1,50 @@
+cmake_minimum_required(VERSION 2.8)
+
+project(target_include_directories)
+
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/privateinclude")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/privateinclude/privateinclude.h" "#define PRIVATEINCLUDE_DEFINE\n")
+
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/publicinclude")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/publicinclude/publicinclude.h" "#define PUBLICINCLUDE_DEFINE\n")
+
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/interfaceinclude")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/interfaceinclude/interfaceinclude.h" "#define INTERFACEINCLUDE_DEFINE\n")
+
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/importedinterfaceinclude")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/importedinterfaceinclude/importedinterfaceinclude.h" "#define IMPORTEDINTERFACEINCLUDE_DEFINE\n")
+
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/poison")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/poison/common.h" "#error Should not be included\n")
+
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/cure")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cure/common.h" "#define CURE_DEFINE\n")
+
+add_executable(target_include_directories
+ "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp"
+)
+target_include_directories(target_include_directories
+ PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/privateinclude"
+ PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/publicinclude"
+ INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/interfaceinclude"
+)
+
+target_include_directories(target_include_directories
+ PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/poison"
+)
+target_include_directories(target_include_directories
+ BEFORE PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/cure"
+)
+
+add_library(importedlib UNKNOWN IMPORTED)
+target_include_directories(importedlib
+ INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/importedinterfaceinclude"
+)
+
+add_executable(consumer
+ "${CMAKE_CURRENT_SOURCE_DIR}/consumer.cpp"
+)
+
+target_include_directories(consumer
+ PRIVATE target_include_directories importedlib
+)
diff --git a/Tests/CMakeCommands/target_include_directories/consumer.cpp b/Tests/CMakeCommands/target_include_directories/consumer.cpp
new file mode 100644
index 0000000..6fd61d5
--- /dev/null
+++ b/Tests/CMakeCommands/target_include_directories/consumer.cpp
@@ -0,0 +1,27 @@
+
+#include "common.h"
+#include "publicinclude.h"
+#include "interfaceinclude.h"
+#include "importedinterfaceinclude.h"
+
+#ifdef PRIVATEINCLUDE_DEFINE
+#error Unexpected PRIVATEINCLUDE_DEFINE
+#endif
+
+#ifndef PUBLICINCLUDE_DEFINE
+#error Expected PUBLICINCLUDE_DEFINE
+#endif
+
+#ifndef INTERFACEINCLUDE_DEFINE
+#error Expected INTERFACEINCLUDE_DEFINE
+#endif
+
+#ifndef IMPORTEDINTERFACEINCLUDE_DEFINE
+#error Expected IMPORTEDINTERFACEINCLUDE_DEFINE
+#endif
+
+#ifndef CURE_DEFINE
+#error Expected CURE_DEFINE
+#endif
+
+int main() { return 0; }
diff --git a/Tests/CMakeCommands/target_include_directories/main.cpp b/Tests/CMakeCommands/target_include_directories/main.cpp
new file mode 100644
index 0000000..8434b97
--- /dev/null
+++ b/Tests/CMakeCommands/target_include_directories/main.cpp
@@ -0,0 +1,22 @@
+
+#include "common.h"
+#include "privateinclude.h"
+#include "publicinclude.h"
+
+#ifndef PRIVATEINCLUDE_DEFINE
+#error Expected PRIVATEINCLUDE_DEFINE
+#endif
+
+#ifndef PUBLICINCLUDE_DEFINE
+#error Expected PUBLICINCLUDE_DEFINE
+#endif
+
+#ifdef INTERFACEINCLUDE_DEFINE
+#error Unexpected INTERFACEINCLUDE_DEFINE
+#endif
+
+#ifndef CURE_DEFINE
+#error Expected CURE_DEFINE
+#endif
+
+int main() { return 0; }
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index ade6a01..2dced5f 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -1930,6 +1930,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)
configure_file(
"${CMake_SOURCE_DIR}/Tests/CTestTestCrash/test.cmake.in"