浏览代码

Add the JOIN generator expression.

This generator expression joins a list with a separator. The separator
may contain arbitrary content, such as commas, which is ordinarily a
delimiter in the generator expression syntax.
Stephen Kelly 12 年之前
父节点
当前提交
a7ba4520c7

+ 2 - 0
Source/cmDocumentGeneratorExpressions.h

@@ -28,6 +28,8 @@
   "strings which contain a ',' for example.\n"                          \
   "  $<SEMICOLON>              = A literal ';'. Used to prevent "       \
   "list expansion on an argument with ';'.\n"                           \
+  "  $<JOIN:list,...>          = joins the list with the content of "   \
+  "\"...\"\n"                                                           \
   "  $<TARGET_NAME:...>        = Marks ... as being the name of a "     \
   "target.  This is required if exporting targets to multiple "         \
   "dependent export sets.  The '...' must be a literal name of a "      \

+ 30 - 0
Source/cmGeneratorExpressionEvaluator.cxx

@@ -307,6 +307,34 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
 } configurationTestNode;
 
 
+static const struct JoinNode : public cmGeneratorExpressionNode
+{
+  JoinNode() {}
+
+  virtual int NumExpectedParameters() const { return 2; }
+
+  virtual bool AcceptsArbitraryContentParameter() const { return true; }
+
+  std::string Evaluate(const std::vector<std::string> &parameters,
+                       cmGeneratorExpressionContext *,
+                       const GeneratorExpressionContent *,
+                       cmGeneratorExpressionDAGChecker *) const
+  {
+    std::string result;
+
+    std::vector<std::string> list;
+    cmSystemTools::ExpandListArgument(parameters.front(), list);
+    std::string sep;
+    for(std::vector<std::string>::const_iterator li = list.begin();
+      li != list.end(); ++li)
+      {
+      result += sep + *li;
+      sep = parameters[1];
+      }
+    return result;
+  }
+} joinNode;
+
 //----------------------------------------------------------------------------
 static const char* targetPropertyTransitiveWhitelist[] = {
     "INTERFACE_INCLUDE_DIRECTORIES"
@@ -973,6 +1001,8 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
     return &installInterfaceNode;
   else if (identifier == "INSTALL_PREFIX")
     return &installPrefixNode;
+  else if (identifier == "JOIN")
+    return &joinNode;
   return 0;
 
 }

+ 17 - 3
Tests/CompileDefinitions/compiletest.cpp

@@ -20,10 +20,16 @@ static const char very_fun_string[] = CMAKE_IS_REALLY;
 #endif
 
 enum {
-  StringLiteralTest1 = sizeof(CMakeStaticAssert<sizeof(CMAKE_IS_) == sizeof("Fun")>)
+  StringLiteralTest1 = sizeof(CMakeStaticAssert<sizeof(CMAKE_IS_) == sizeof("Fun")>),
 #ifndef NO_SPACES_IN_DEFINE_VALUES
-  ,
-  StringLiteralTest2 = sizeof(CMakeStaticAssert<sizeof(CMAKE_IS_REALLY) == sizeof("Very Fun")>)
+  StringLiteralTest2 = sizeof(CMakeStaticAssert<sizeof(CMAKE_IS_REALLY) == sizeof("Very Fun")>),
+#endif
+#ifdef TEST_GENERATOR_EXPRESSIONS
+  StringLiteralTest3 = sizeof(CMakeStaticAssert<sizeof(LETTER_LIST1) == sizeof("A,B,C,D")>),
+  StringLiteralTest4 = sizeof(CMakeStaticAssert<sizeof(LETTER_LIST2) == sizeof("A,,B,,C,,D")>),
+  StringLiteralTest5 = sizeof(CMakeStaticAssert<sizeof(LETTER_LIST3) == sizeof("A,-B,-C,-D")>),
+  StringLiteralTest6 = sizeof(CMakeStaticAssert<sizeof(LETTER_LIST4) == sizeof("A-,-B-,-C-,-D")>),
+  StringLiteralTest7 = sizeof(CMakeStaticAssert<sizeof(LETTER_LIST5) == sizeof("A-,B-,C-,D")>)
 #endif
 };
 
@@ -42,6 +48,14 @@ enum {
 #error Expected define expanded from list
 #endif
 
+#ifndef PREFIX_DEF1
+#error Expect PREFIX_DEF1
+#endif
+
+#ifndef PREFIX_DEF2
+#error Expect PREFIX_DEF2
+#endif
+
 // TEST_GENERATOR_EXPRESSIONS
 #endif
 

+ 6 - 0
Tests/CompileDefinitions/target_prop/CMakeLists.txt

@@ -13,6 +13,12 @@ set_property(TARGET target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS
     "$<1:CMAKE_IS_DECLARATIVE>"
     "$<0:GE_NOT_DEFINED>"
     "$<1:ARGUMENT;LIST>"
+    PREFIX_$<JOIN:DEF1;DEF2,;PREFIX_>
+    LETTER_LIST1=\"$<JOIN:A;B;C;D,,>\"
+    LETTER_LIST2=\"$<JOIN:A;B;C;D,,,>\"
+    LETTER_LIST3=\"$<JOIN:A;B;C;D,,->\"
+    LETTER_LIST4=\"$<JOIN:A;B;C;D,-,->\"
+    LETTER_LIST5=\"$<JOIN:A;B;C;D,-,>\"
 )
 
 set_property(TARGET target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS

+ 5 - 0
Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt

@@ -123,3 +123,8 @@ target_link_libraries(lib5 libbad libgood)
 target_include_directories(lib5
   BEFORE PRIVATE $<TARGET_PROPERTY:libgood,INTERFACE_INCLUDE_DIRECTORIES>
 )
+
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/prefix_foo/prefix_bar/prefix_bat")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/prefix_foo/prefix_bar/prefix_bat/prefix_foo_bar_bat.h" "// prefix_foo_bar_bat.h\n")
+
+target_include_directories(TargetIncludeDirectories PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/prefix_$<JOIN:foo;bar;bat,/prefix_>")

+ 1 - 0
Tests/IncludeDirectories/TargetIncludeDirectories/main.cpp

@@ -10,6 +10,7 @@
 #include "arguments.h"
 #include "list.h"
 #include "target.h"
+#include "prefix_foo_bar_bat.h"
 
 int main(int, char**)
 {