Browse Source

GenEx: add POSTFIX option to $<TARGET_FILE_BASE_NAME>

Fixes: #27189
Marc Chevrier 1 month ago
parent
commit
0b055a8893
18 changed files with 259 additions and 40 deletions
  1. 67 15
      Help/manual/cmake-generator-expressions.7.rst
  2. 10 0
      Help/release/dev/GenEx-TARGET_FILE_BASE_NAME-POSTFIX.rst
  3. 74 25
      Source/cmGeneratorExpressionNode.cxx
  4. 4 0
      Tests/RunCMake/GenEx-TARGET_FILE/RunCMakeTest.cmake
  5. 14 0
      Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME-imported-target.cmake
  6. 1 0
      Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME-non-valid-POSTFIX-result.txt
  7. 8 0
      Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME-non-valid-POSTFIX-stderr.txt
  8. 10 0
      Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME-non-valid-POSTFIX.cmake
  9. 1 0
      Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME-too-many-args-result.txt
  10. 8 0
      Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME-too-many-args-stderr.txt
  11. 10 0
      Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME-too-many-args.cmake
  12. 14 0
      Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME.cmake
  13. 1 0
      Tests/RunCMake/GenEx-TARGET_FILE/TARGET_LINKER_FILE_BASE_NAME-non-valid-POSTFIX-result.txt
  14. 8 0
      Tests/RunCMake/GenEx-TARGET_FILE/TARGET_LINKER_FILE_BASE_NAME-non-valid-POSTFIX-stderr.txt
  15. 10 0
      Tests/RunCMake/GenEx-TARGET_FILE/TARGET_LINKER_FILE_BASE_NAME-non-valid-POSTFIX.cmake
  16. 1 0
      Tests/RunCMake/GenEx-TARGET_FILE/TARGET_LINKER_FILE_BASE_NAME-too-many-args-result.txt
  17. 8 0
      Tests/RunCMake/GenEx-TARGET_FILE/TARGET_LINKER_FILE_BASE_NAME-too-many-args-stderr.txt
  18. 10 0
      Tests/RunCMake/GenEx-TARGET_FILE/TARGET_LINKER_FILE_BASE_NAME-too-many-args.cmake

+ 67 - 15
Help/manual/cmake-generator-expressions.7.rst

@@ -2235,13 +2235,23 @@ In the following, the phrase "the ``tgt`` filename" means the name of the
   expression is evaluated on, unless the expression is being used in
   :command:`add_custom_command` or :command:`add_custom_target`.
 
-.. genex:: $<TARGET_FILE_BASE_NAME:tgt>
+.. genex:: $<TARGET_FILE_BASE_NAME:tgt[,POSTFIX:(INCLUDE|EXCLUDE)]>
 
   .. versionadded:: 3.15
 
+  .. versionadded:: 4.2
+    The option ``POSTFIX``, which can be used to control the inclusion or not
+    of the :prop_tgt:`<CONFIG>_POSTFIX` target property value as part of the
+    base name. The default is ``POSTFIX:INCLUDE``.
+
   Base name of ``tgt``, i.e. ``$<TARGET_FILE_NAME:tgt>`` without prefix and
-  suffix.
-  For example, if the ``tgt`` filename is ``libbase.so``, the base name is ``base``.
+  suffix and, optionally, postfix.
+  For example, if the ``tgt`` filename is ``libbase_postfix.so``, the base name
+  is:
+
+    * ``base_postfix`` for ``$<TARGET_FILE_BASE_NAME:tgt>`` or
+      ``$<TARGET_FILE_BASE_NAME:tgt,POSTFIX:INCLUDE>``.
+    * ``base`` for ``$<TARGET_FILE_BASE_NAME:tgt,POSTFIX:EXCLUDE>``.
 
   See also the :prop_tgt:`OUTPUT_NAME`, :prop_tgt:`ARCHIVE_OUTPUT_NAME`,
   :prop_tgt:`LIBRARY_OUTPUT_NAME` and :prop_tgt:`RUNTIME_OUTPUT_NAME`
@@ -2303,13 +2313,23 @@ In the following, the phrase "the ``tgt`` filename" means the name of the
   This expands to an empty string when there is no import file associated
   with the target.
 
-.. genex:: $<TARGET_IMPORT_FILE_BASE_NAME:tgt>
+.. genex:: $<TARGET_IMPORT_FILE_BASE_NAME:tgt[,POSTFIX:(INCLUDE|EXCLUDE)]>
 
   .. versionadded:: 3.27
 
+  .. versionadded:: 4.2
+    The option ``POSTFIX``, which can be used to control the inclusion or not
+    of the :prop_tgt:`<CONFIG>_POSTFIX` target property value as part of the
+    base name. The default is ``POSTFIX:INCLUDE``.
+
   Base name of the linker import file of the target ``tgt`` without prefix or
-  suffix. For example, if the target file name is ``libbase.tbd``, the base
-  name is ``base``.
+  suffix and, optionally, postfix.
+  For example, if the target file name is ``libbase_postfix.tbd``, the base
+  name is:
+
+    * ``base_postfix`` for ``$<TARGET_IMPORT_FILE_BASE_NAME:tgt>`` or
+      ``$<TARGET_IMPORT_FILE_BASE_NAME:tgt,POSTFIX:INCLUDE>``.
+    * ``base`` for ``$<TARGET_IMPORT_FILE_BASE_NAME:tgt,POSTFIX:EXCLUDE>``.
 
   See also the :prop_tgt:`OUTPUT_NAME` and :prop_tgt:`ARCHIVE_OUTPUT_NAME`
   target properties, their configuration-specific variants
@@ -2379,13 +2399,23 @@ In the following, the phrase "the ``tgt`` filename" means the name of the
   :genex:`$<TARGET_LINKER_IMPORT_FILE>` generator expressions, depending on the
   characteristics of the target and the platform.
 
-.. genex:: $<TARGET_LINKER_FILE_BASE_NAME:tgt>
+.. genex:: $<TARGET_LINKER_FILE_BASE_NAME:tgt[,POSTFIX:(INCLUDE|EXCLUDE)]>
 
   .. versionadded:: 3.15
 
+  .. versionadded:: 4.2
+    The option ``POSTFIX``, which can be used to control the inclusion or not
+    of the :prop_tgt:`<CONFIG>_POSTFIX` target property value as part of the
+    base name. The default is ``POSTFIX:INCLUDE``.
+
   Base name of file used to link the target ``tgt``, i.e.
-  :genex:`$<TARGET_LINKER_FILE_NAME:tgt>` without prefix and suffix. For
-  example, if target file name is ``libbase.a``, the base name is ``base``.
+  :genex:`$<TARGET_LINKER_FILE_NAME:tgt>` without prefix and suffix, and,
+  optionally, postfix.
+  For example, if target file name is ``libbase_postfix.a``, the base name is:
+
+    * ``base_postfix`` for ``$<TARGET_LINKER_FILE_BASE_NAME:tgt>`` or
+      ``$<TARGET_LINKER_FILE_BASE_NAME:tgt,POSTFIX:INCLUDE>``.
+    * ``base`` for ``$<TARGET_LINKER_FILE_BASE_NAME:tgt,POSTFIX:EXCLUDE>``.
 
   See also the :prop_tgt:`OUTPUT_NAME`, :prop_tgt:`ARCHIVE_OUTPUT_NAME`,
   and :prop_tgt:`LIBRARY_OUTPUT_NAME` target properties, their
@@ -2447,13 +2477,24 @@ In the following, the phrase "the ``tgt`` filename" means the name of the
   ``tgt`` represents (``.a``, ``.so``, ``.dylib``). So, on DLL platforms, it
   will be an empty string.
 
-.. genex:: $<TARGET_LINKER_LIBRARY_FILE_BASE_NAME:tgt>
+.. genex:: $<TARGET_LINKER_LIBRARY_FILE_BASE_NAME:tgt[,POSTFIX:(INCLUDE|EXCLUDE)]>
 
   .. versionadded:: 3.27
 
+  .. versionadded:: 4.2
+    The option ``POSTFIX``, which can be used to control the inclusion or not
+    of the :prop_tgt:`<CONFIG>_POSTFIX` target property value as part of the
+    base name. The default is ``POSTFIX:INCLUDE``.
+
   Base name of library file used to link the target ``tgt``, i.e.
-  :genex:`$<TARGET_LINKER_LIBRARY_FILE_NAME:tgt>` without prefix and suffix.
-  For example, if target file name is ``libbase.a``, the base name is ``base``.
+  :genex:`$<TARGET_LINKER_LIBRARY_FILE_NAME:tgt>` without prefix and
+  suffix,and, optionally, postfix.
+  For example, if target file name is ``libbase_postfix.a``, the base name is:
+
+    * ``base_postfix`` for ``$<TARGET_LINKER_LIBRARY_FILE_BASE_NAME:tgt>`` or
+      ``$<TARGET_LINKER_LIBRARY_FILE_BASE_NAME:tgt,POSTFIX:INCLUDE>``.
+    * ``base`` for
+      ``$<TARGET_LINKER_LIBRARY_FILE_BASE_NAME:tgt,POSTFIX:EXCLUDE>``.
 
   See also the :prop_tgt:`OUTPUT_NAME`, :prop_tgt:`ARCHIVE_OUTPUT_NAME`,
   and :prop_tgt:`LIBRARY_OUTPUT_NAME` target properties, their
@@ -2517,13 +2558,24 @@ In the following, the phrase "the ``tgt`` filename" means the name of the
   (``.lib``, ``.tbd``). So, when no import file is involved in the link step,
   an empty string is returned.
 
-.. genex:: $<TARGET_LINKER_IMPORT_FILE_BASE_NAME:tgt>
+.. genex:: $<TARGET_LINKER_IMPORT_FILE_BASE_NAME:tgt[,POSTFIX:(INCLUDE|EXCLUDE)]>
 
   .. versionadded:: 3.27
 
+  .. versionadded:: 4.2
+    The option ``POSTFIX``, which can be used to control the inclusion or not
+    of the :prop_tgt:`<CONFIG>_POSTFIX` target property value as part of the
+    base name. The default is ``POSTFIX:INCLUDE``.
+
   Base name of the import file used to link the target ``tgt``, i.e.
-  :genex:`$<TARGET_LINKER_IMPORT_FILE_NAME:tgt>` without prefix and suffix.
-  For example, if target file name is ``libbase.tbd``, the base name is ``base``.
+  :genex:`$<TARGET_LINKER_IMPORT_FILE_NAME:tgt>` without prefix and suffix,
+  and, optionally, postfix.
+  For example, if target file name is ``libbase_postfix.tbd``, the base name is
+
+    * ``base_postfix`` for ``$<TARGET_LINKER_IMPORT_FILE_BASE_NAME:tgt>`` or
+      ``$<TARGET_LINKER_IMPORT_FILE_BASE_NAME:tgt,POSTFIX:INCLUDE>``.
+    * ``base`` for
+      ``$<TARGET_LINKER_IMPORT_FILE_BASE_NAME:tgt,POSTFIX:EXCLUDE>``.
 
   See also the :prop_tgt:`OUTPUT_NAME` and :prop_tgt:`ARCHIVE_OUTPUT_NAME`,
   target properties, their configuration-specific variants

+ 10 - 0
Help/release/dev/GenEx-TARGET_FILE_BASE_NAME-POSTFIX.rst

@@ -0,0 +1,10 @@
+GenEx-TARGET_FILE_BASE_NAME-POSTFIX
+-----------------------------------
+
+* The :genex:`TARGET_FILE_BASE_NAME`, :genex:`TARGET_IMPORT_FILE_BASE_NAME`,
+  :genex:`TARGET_LINKER_FILE_BASE_NAME`,
+  :genex:`TARGET_LINKER_LIBRARY_FILE_BASE_NAME`,
+  and :genex:`TARGET_LINKER_IMPORT_FILE_BASE_NAME`
+  generator expressions gained the option ``POSTFIX`` to control the inclusion
+  or not of the :prop_tgt:`<CONFIG>_POSTFIX` target property as part of the
+  base name of the target.

+ 74 - 25
Source/cmGeneratorExpressionNode.cxx

@@ -4164,12 +4164,19 @@ static TargetFilesystemArtifact<ArtifactBundleContentDirTag,
 //
 // To retrieve base name for various artifacts
 //
+enum class Postfix
+{
+  Exclude,
+  Include
+};
+
 template <typename ArtifactT>
 struct TargetOutputNameArtifactResultGetter
 {
   static std::string Get(cmGeneratorTarget* target,
                          cm::GenEx::Evaluation* eval,
-                         GeneratorExpressionContent const* content);
+                         GeneratorExpressionContent const* content,
+                         Postfix postfix);
 };
 
 template <>
@@ -4177,11 +4184,14 @@ struct TargetOutputNameArtifactResultGetter<ArtifactNameTag>
 {
   static std::string Get(cmGeneratorTarget* target,
                          cm::GenEx::Evaluation* eval,
-                         GeneratorExpressionContent const* /*unused*/)
+                         GeneratorExpressionContent const* /*unused*/,
+                         Postfix postfix)
   {
-    return target->GetOutputName(eval->Context.Config,
-                                 cmStateEnums::RuntimeBinaryArtifact) +
-      target->GetFilePostfix(eval->Context.Config);
+    auto output = target->GetOutputName(eval->Context.Config,
+                                        cmStateEnums::RuntimeBinaryArtifact);
+    return postfix == Postfix::Include
+      ? cmStrCat(output, target->GetFilePostfix(eval->Context.Config))
+      : output;
   }
 };
 
@@ -4190,12 +4200,15 @@ struct TargetOutputNameArtifactResultGetter<ArtifactImportTag>
 {
   static std::string Get(cmGeneratorTarget* target,
                          cm::GenEx::Evaluation* eval,
-                         GeneratorExpressionContent const* /*unused*/)
+                         GeneratorExpressionContent const* /*unused*/,
+                         Postfix postfix)
   {
     if (target->HasImportLibrary(eval->Context.Config)) {
-      return target->GetOutputName(eval->Context.Config,
-                                   cmStateEnums::ImportLibraryArtifact) +
-        target->GetFilePostfix(eval->Context.Config);
+      auto output = target->GetOutputName(eval->Context.Config,
+                                          cmStateEnums::ImportLibraryArtifact);
+      return postfix == Postfix::Include
+        ? cmStrCat(output, target->GetFilePostfix(eval->Context.Config))
+        : output;
     }
     return std::string{};
   }
@@ -4206,7 +4219,8 @@ struct TargetOutputNameArtifactResultGetter<ArtifactLinkerTag>
 {
   static std::string Get(cmGeneratorTarget* target,
                          cm::GenEx::Evaluation* eval,
-                         GeneratorExpressionContent const* content)
+                         GeneratorExpressionContent const* content,
+                         Postfix postfix)
   {
     // The library file used to link to the target (.so, .lib, .a) or import
     // file (.lin,  .tbd).
@@ -4220,8 +4234,10 @@ struct TargetOutputNameArtifactResultGetter<ArtifactLinkerTag>
       target->HasImportLibrary(eval->Context.Config)
       ? cmStateEnums::ImportLibraryArtifact
       : cmStateEnums::RuntimeBinaryArtifact;
-    return target->GetOutputName(eval->Context.Config, artifact) +
-      target->GetFilePostfix(eval->Context.Config);
+    auto output = target->GetOutputName(eval->Context.Config, artifact);
+    return postfix == Postfix::Include
+      ? cmStrCat(output, target->GetFilePostfix(eval->Context.Config))
+      : output;
   }
 };
 
@@ -4230,7 +4246,8 @@ struct TargetOutputNameArtifactResultGetter<ArtifactLinkerLibraryTag>
 {
   static std::string Get(cmGeneratorTarget* target,
                          cm::GenEx::Evaluation* eval,
-                         GeneratorExpressionContent const* content)
+                         GeneratorExpressionContent const* content,
+                         Postfix postfix)
   {
     // The library file used to link to the target (.so, .lib, .a).
     if (!target->IsLinkable() ||
@@ -4243,9 +4260,11 @@ struct TargetOutputNameArtifactResultGetter<ArtifactLinkerLibraryTag>
 
     if (!target->IsDLLPlatform() ||
         target->GetType() == cmStateEnums::STATIC_LIBRARY) {
-      return target->GetOutputName(eval->Context.Config,
-                                   cmStateEnums::ImportLibraryArtifact) +
-        target->GetFilePostfix(eval->Context.Config);
+      auto output = target->GetOutputName(eval->Context.Config,
+                                          cmStateEnums::ImportLibraryArtifact);
+      return postfix == Postfix::Include
+        ? cmStrCat(output, target->GetFilePostfix(eval->Context.Config))
+        : output;
     }
     return std::string{};
   }
@@ -4256,7 +4275,8 @@ struct TargetOutputNameArtifactResultGetter<ArtifactLinkerImportTag>
 {
   static std::string Get(cmGeneratorTarget* target,
                          cm::GenEx::Evaluation* eval,
-                         GeneratorExpressionContent const* content)
+                         GeneratorExpressionContent const* content,
+                         Postfix postfix)
   {
     // The import file used to link to the target (.lib, .tbd).
     if (!target->IsLinkable()) {
@@ -4267,9 +4287,11 @@ struct TargetOutputNameArtifactResultGetter<ArtifactLinkerImportTag>
     }
 
     if (target->HasImportLibrary(eval->Context.Config)) {
-      return target->GetOutputName(eval->Context.Config,
-                                   cmStateEnums::ImportLibraryArtifact) +
-        target->GetFilePostfix(eval->Context.Config);
+      auto output = target->GetOutputName(eval->Context.Config,
+                                          cmStateEnums::ImportLibraryArtifact);
+      return postfix == Postfix::Include
+        ? cmStrCat(output, target->GetFilePostfix(eval->Context.Config))
+        : output;
     }
     return std::string{};
   }
@@ -4280,7 +4302,8 @@ struct TargetOutputNameArtifactResultGetter<ArtifactPdbTag>
 {
   static std::string Get(cmGeneratorTarget* target,
                          cm::GenEx::Evaluation* eval,
-                         GeneratorExpressionContent const* content)
+                         GeneratorExpressionContent const* content,
+                         Postfix /* unused */)
   {
     if (target->IsImported()) {
       ::reportError(
@@ -4320,21 +4343,40 @@ struct TargetFileBaseNameArtifact : public TargetArtifactBase
 {
   TargetFileBaseNameArtifact() {} // NOLINT(modernize-use-equals-default)
 
-  int NumExpectedParameters() const override { return 1; }
+  int NumExpectedParameters() const override { return OneOrMoreParameters; }
 
   std::string Evaluate(
     std::vector<std::string> const& parameters, cm::GenEx::Evaluation* eval,
     GeneratorExpressionContent const* content,
     cmGeneratorExpressionDAGChecker* dagChecker) const override
   {
+    if (parameters.size() > 2) {
+      ::reportError(eval, content->GetOriginalExpression(),
+                    "Unexpected parameters, require one or two parameters.");
+      return std::string{};
+    }
+
     cmGeneratorTarget* target =
       this->GetTarget(parameters, eval, content, dagChecker);
     if (!target) {
       return std::string();
     }
 
+    Postfix postfix = Postfix::Include;
+    if (parameters.size() == 2) {
+      if (parameters[1] == "POSTFIX:INCLUDE") {
+        postfix = Postfix::Include;
+      } else if (parameters[1] == "POSTFIX:EXCLUDE") {
+        postfix = Postfix::Exclude;
+      } else {
+        ::reportError(eval, content->GetOriginalExpression(),
+                      "Wrong second parameter: \"POSTFIX:INCLUDE\" or "
+                      "\"POSTFIX:EXCLUDE\" is expected");
+      }
+    }
+
     std::string result = TargetOutputNameArtifactResultGetter<ArtifactT>::Get(
-      target, eval, content);
+      target, eval, content, postfix);
     if (eval->HadError) {
       return std::string();
     }
@@ -4342,6 +4384,14 @@ struct TargetFileBaseNameArtifact : public TargetArtifactBase
   }
 };
 
+struct TargetPdbFileBaseNameArtifact
+  : public TargetFileBaseNameArtifact<ArtifactPdbTag>
+{
+  TargetPdbFileBaseNameArtifact() {} // NOLINT(modernize-use-equals-default)
+
+  int NumExpectedParameters() const override { return 1; }
+};
+
 static TargetFileBaseNameArtifact<ArtifactNameTag> const
   targetFileBaseNameNode;
 static TargetFileBaseNameArtifact<ArtifactImportTag> const
@@ -4352,8 +4402,7 @@ static TargetFileBaseNameArtifact<ArtifactLinkerLibraryTag> const
   targetLinkerLibraryFileBaseNameNode;
 static TargetFileBaseNameArtifact<ArtifactLinkerImportTag> const
   targetLinkerImportFileBaseNameNode;
-static TargetFileBaseNameArtifact<ArtifactPdbTag> const
-  targetPdbFileBaseNameNode;
+static TargetPdbFileBaseNameArtifact const targetPdbFileBaseNameNode;
 
 class ArtifactFilePrefixTag;
 class ArtifactImportFilePrefixTag;

+ 4 - 0
Tests/RunCMake/GenEx-TARGET_FILE/RunCMakeTest.cmake

@@ -17,8 +17,12 @@ run_cmake(TARGET_FILE_SUFFIX-non-valid-target)
 run_cmake(TARGET_LINKER_FILE_SUFFIX-non-valid-target)
 run_cmake_with_options(TARGET_FILE_BASE_NAME -DCMAKE_BUILD_TYPE:STRING=Debug)
 run_cmake_with_options(TARGET_FILE_BASE_NAME-imported-target -DCMAKE_BUILD_TYPE:STRING=Debug)
+run_cmake(TARGET_FILE_BASE_NAME-too-many-args)
+run_cmake(TARGET_LINKER_FILE_BASE_NAME-too-many-args)
 run_cmake(TARGET_FILE_BASE_NAME-non-valid-target)
 run_cmake(TARGET_LINKER_FILE_BASE_NAME-non-valid-target)
+run_cmake(TARGET_FILE_BASE_NAME-non-valid-POSTFIX)
+run_cmake(TARGET_LINKER_FILE_BASE_NAME-non-valid-POSTFIX)
 if(CMAKE_HOST_SYSTEM_NAME STREQUAL "AIX")
   run_cmake(TARGET_SONAME_FILE-AIX)
   run_cmake(TARGET_SONAME_IMPORT_FILE-AIX)

+ 14 - 0
Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME-imported-target.cmake

@@ -92,10 +92,24 @@ set_property (TARGET static4 PROPERTY ${FIRST_CONFIG}_POSTFIX _postfix)
 string (APPEND GENERATE_CONTENT [[
 
 check_value ("TARGET_FILE_BASE_NAME executable all properties + postfix" "$<TARGET_FILE_BASE_NAME:exec4>" "exec4_runtime_postfix")
+check_value ("TARGET_FILE_BASE_NAME executable all properties + postfix" "$<TARGET_FILE_BASE_NAME:exec4,POSTFIX:INCLUDE>" "exec4_runtime_postfix")
+check_value ("TARGET_FILE_BASE_NAME executable all properties without postfix" "$<TARGET_FILE_BASE_NAME:exec4,POSTFIX:EXCLUDE>" "exec4_runtime")
+
 check_value ("TARGET_FILE_BASE_NAME shared all properties + postfix" "$<TARGET_FILE_BASE_NAME:shared4>" "$<IF:$<IN_LIST:$<PLATFORM_ID>,Windows$<SEMICOLON>CYGWIN$<SEMICOLON>MSYS>,shared4_runtime,shared4_library>_postfix")
+check_value ("TARGET_FILE_BASE_NAME shared all properties + postfix" "$<TARGET_FILE_BASE_NAME:shared4,POSTFIX:INCLUDE>" "$<IF:$<IN_LIST:$<PLATFORM_ID>,Windows$<SEMICOLON>CYGWIN$<SEMICOLON>MSYS>,shared4_runtime,shared4_library>_postfix")
+check_value ("TARGET_FILE_BASE_NAME shared all properties without postfix" "$<TARGET_FILE_BASE_NAME:shared4,POSTFIX:EXCLUDE>" "$<IF:$<IN_LIST:$<PLATFORM_ID>,Windows$<SEMICOLON>CYGWIN$<SEMICOLON>MSYS>,shared4_runtime,shared4_library>")
+
 check_value ("TARGET_LINKER_FILE_BASE_NAME shared linker all properties + postfix" "$<TARGET_LINKER_FILE_BASE_NAME:shared4>" "$<IF:$<IN_LIST:$<PLATFORM_ID>,Windows$<SEMICOLON>CYGWIN$<SEMICOLON>MSYS>,shared4_archive,shared4_library>_postfix")
+check_value ("TARGET_LINKER_FILE_BASE_NAME shared linker all properties + postfix" "$<TARGET_LINKER_FILE_BASE_NAME:shared4,POSTFIX:INCLUDE>" "$<IF:$<IN_LIST:$<PLATFORM_ID>,Windows$<SEMICOLON>CYGWIN$<SEMICOLON>MSYS>,shared4_archive,shared4_library>_postfix")
+check_value ("TARGET_LINKER_FILE_BASE_NAME shared linker all properties without postfix" "$<TARGET_LINKER_FILE_BASE_NAME:shared4,POSTFIX:EXCLUDE>" "$<IF:$<IN_LIST:$<PLATFORM_ID>,Windows$<SEMICOLON>CYGWIN$<SEMICOLON>MSYS>,shared4_archive,shared4_library>")
+
 check_value ("TARGET_FILE_BASE_NAME static all properties + postfix" "$<TARGET_FILE_BASE_NAME:static4>" "static4_archive_postfix")
+check_value ("TARGET_FILE_BASE_NAME static all properties + postfix" "$<TARGET_FILE_BASE_NAME:static4,POSTFIX:INCLUDE>" "static4_archive_postfix")
+check_value ("TARGET_FILE_BASE_NAME static all properties without postfix" "$<TARGET_FILE_BASE_NAME:static4,POSTFIX:EXCLUDE>" "static4_archive")
+
 check_value ("TARGET_LINKER_FILE_BASE_NAME static linker all properties + postfix" "$<TARGET_LINKER_FILE_BASE_NAME:static4>" "static4_archive_postfix")
+check_value ("TARGET_LINKER_FILE_BASE_NAME static linker all properties + postfix" "$<TARGET_LINKER_FILE_BASE_NAME:static4,POSTFIX:INCLUDE>" "static4_archive_postfix")
+check_value ("TARGET_LINKER_FILE_BASE_NAME static linker all properties without postfix" "$<TARGET_LINKER_FILE_BASE_NAME:static4,POSTFIX:EXCLUDE>" "static4_archive")
 ]])
 
 

+ 1 - 0
Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME-non-valid-POSTFIX-result.txt

@@ -0,0 +1 @@
+1

+ 8 - 0
Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME-non-valid-POSTFIX-stderr.txt

@@ -0,0 +1,8 @@
+CMake Error at TARGET_FILE_BASE_NAME-non-valid-POSTFIX.cmake:[0-9]+ \(file\):
+  Error evaluating generator expression:
+
+    \$<TARGET_FILE_BASE_NAME:shared1,FOO>
+
+  Wrong second parameter: "POSTFIX:INCLUDE" or "POSTFIX:EXCLUDE" is expected
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)

+ 10 - 0
Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME-non-valid-POSTFIX.cmake

@@ -0,0 +1,10 @@
+
+enable_language (C)
+
+
+add_library (shared1 SHARED empty.c)
+
+file(GENERATE
+  OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/test.txt"
+  CONTENT "[$<TARGET_FILE_BASE_NAME:shared1,FOO>]"
+)

+ 1 - 0
Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME-too-many-args-result.txt

@@ -0,0 +1 @@
+1

+ 8 - 0
Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME-too-many-args-stderr.txt

@@ -0,0 +1,8 @@
+CMake Error at TARGET_FILE_BASE_NAME-too-many-args.cmake:[0-9]+ \(file\):
+  Error evaluating generator expression:
+
+    \$<TARGET_FILE_BASE_NAME:shared1,POSTFIX:YES,foo>
+
+  Unexpected parameters, require one or two parameters.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)

+ 10 - 0
Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME-too-many-args.cmake

@@ -0,0 +1,10 @@
+
+enable_language (C)
+
+
+add_library (shared1 SHARED empty.c)
+
+file(GENERATE
+  OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/test.txt"
+  CONTENT "[$<TARGET_FILE_BASE_NAME:shared1,POSTFIX:YES,foo>]"
+)

+ 14 - 0
Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME.cmake

@@ -115,10 +115,24 @@ set_property (TARGET static4 PROPERTY ${FIRST_CONFIG}_POSTFIX _postfix)
 string (APPEND GENERATE_CONTENT [[
 
 check_value ("TARGET_FILE_BASE_NAME executable all properties + postfix" "$<TARGET_FILE_BASE_NAME:exec4>" "exec4_runtime_postfix")
+check_value ("TARGET_FILE_BASE_NAME executable all properties + postfix" "$<TARGET_FILE_BASE_NAME:exec4,POSTFIX:INCLUDE>" "exec4_runtime_postfix")
+check_value ("TARGET_FILE_BASE_NAME executable all properties without postfix" "$<TARGET_FILE_BASE_NAME:exec4,POSTFIX:EXCLUDE>" "exec4_runtime")
+
 check_value ("TARGET_FILE_BASE_NAME shared all properties + postfix" "$<TARGET_FILE_BASE_NAME:shared4>" "$<IF:$<IN_LIST:$<PLATFORM_ID>,Windows$<SEMICOLON>CYGWIN$<SEMICOLON>MSYS>,shared4_runtime,shared4_library>_postfix")
+check_value ("TARGET_FILE_BASE_NAME shared all properties + postfix" "$<TARGET_FILE_BASE_NAME:shared4,POSTFIX:INCLUDE>" "$<IF:$<IN_LIST:$<PLATFORM_ID>,Windows$<SEMICOLON>CYGWIN$<SEMICOLON>MSYS>,shared4_runtime,shared4_library>_postfix")
+check_value ("TARGET_FILE_BASE_NAME shared all properties without postfix" "$<TARGET_FILE_BASE_NAME:shared4,POSTFIX:EXCLUDE>" "$<IF:$<IN_LIST:$<PLATFORM_ID>,Windows$<SEMICOLON>CYGWIN$<SEMICOLON>MSYS>,shared4_runtime,shared4_library>")
+
 check_value ("TARGET_LINKER_FILE_BASE_NAME shared linker all properties + postfix" "$<TARGET_LINKER_FILE_BASE_NAME:shared4>" "$<IF:$<IN_LIST:$<PLATFORM_ID>,Windows$<SEMICOLON>CYGWIN$<SEMICOLON>MSYS>,shared4_archive,shared4_library>_postfix")
+check_value ("TARGET_LINKER_FILE_BASE_NAME shared linker all properties + postfix" "$<TARGET_LINKER_FILE_BASE_NAME:shared4,POSTFIX:INCLUDE>" "$<IF:$<IN_LIST:$<PLATFORM_ID>,Windows$<SEMICOLON>CYGWIN$<SEMICOLON>MSYS>,shared4_archive,shared4_library>_postfix")
+check_value ("TARGET_LINKER_FILE_BASE_NAME shared linker all properties without postfix" "$<TARGET_LINKER_FILE_BASE_NAME:shared4,POSTFIX:EXCLUDE>" "$<IF:$<IN_LIST:$<PLATFORM_ID>,Windows$<SEMICOLON>CYGWIN$<SEMICOLON>MSYS>,shared4_archive,shared4_library>")
+
 check_value ("TARGET_FILE_BASE_NAME static all properties + postfix" "$<TARGET_FILE_BASE_NAME:static4>" "static4_archive_postfix")
+check_value ("TARGET_FILE_BASE_NAME static all properties + postfix" "$<TARGET_FILE_BASE_NAME:static4,POSTFIX:INCLUDE>" "static4_archive_postfix")
+check_value ("TARGET_FILE_BASE_NAME static all properties without postfix" "$<TARGET_FILE_BASE_NAME:static4,POSTFIX:EXCLUDE>" "static4_archive")
+
 check_value ("TARGET_LINKER_FILE_BASE_NAME static linker all properties + postfix" "$<TARGET_LINKER_FILE_BASE_NAME:static4>" "static4_archive_postfix")
+check_value ("TARGET_LINKER_FILE_BASE_NAME static linker all properties + postfix" "$<TARGET_LINKER_FILE_BASE_NAME:static4,POSTFIX:INCLUDE>" "static4_archive_postfix")
+check_value ("TARGET_LINKER_FILE_BASE_NAME static linker all properties without postfix" "$<TARGET_LINKER_FILE_BASE_NAME:static4,POSTFIX:EXCLUDE>" "static4_archive")
 ]])
 if (CMAKE_C_LINKER_SUPPORTS_PDB)
   string (APPEND GENERATE_CONTENT [[

+ 1 - 0
Tests/RunCMake/GenEx-TARGET_FILE/TARGET_LINKER_FILE_BASE_NAME-non-valid-POSTFIX-result.txt

@@ -0,0 +1 @@
+1

+ 8 - 0
Tests/RunCMake/GenEx-TARGET_FILE/TARGET_LINKER_FILE_BASE_NAME-non-valid-POSTFIX-stderr.txt

@@ -0,0 +1,8 @@
+CMake Error at TARGET_LINKER_FILE_BASE_NAME-non-valid-POSTFIX.cmake:[0-9]+ \(file\):
+  Error evaluating generator expression:
+
+    \$<TARGET_LINKER_FILE_BASE_NAME:shared1,FOO>
+
+  Wrong second parameter: "POSTFIX:INCLUDE" or "POSTFIX:EXCLUDE" is expected
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)

+ 10 - 0
Tests/RunCMake/GenEx-TARGET_FILE/TARGET_LINKER_FILE_BASE_NAME-non-valid-POSTFIX.cmake

@@ -0,0 +1,10 @@
+
+enable_language (C)
+
+
+add_library (shared1 SHARED empty.c)
+
+file(GENERATE
+  OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/test.txt"
+  CONTENT "[$<TARGET_LINKER_FILE_BASE_NAME:shared1,FOO>]"
+)

+ 1 - 0
Tests/RunCMake/GenEx-TARGET_FILE/TARGET_LINKER_FILE_BASE_NAME-too-many-args-result.txt

@@ -0,0 +1 @@
+1

+ 8 - 0
Tests/RunCMake/GenEx-TARGET_FILE/TARGET_LINKER_FILE_BASE_NAME-too-many-args-stderr.txt

@@ -0,0 +1,8 @@
+CMake Error at TARGET_LINKER_FILE_BASE_NAME-too-many-args.cmake:[0-9]+ \(file\):
+  Error evaluating generator expression:
+
+    \$<TARGET_LINKER_FILE_BASE_NAME:shared1,POSTFIX:YES,foo>
+
+  Unexpected parameters, require one or two parameters.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)

+ 10 - 0
Tests/RunCMake/GenEx-TARGET_FILE/TARGET_LINKER_FILE_BASE_NAME-too-many-args.cmake

@@ -0,0 +1,10 @@
+
+enable_language (C)
+
+
+add_library (shared1 SHARED empty.c)
+
+file(GENERATE
+  OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/test.txt"
+  CONTENT "[$<TARGET_LINKER_FILE_BASE_NAME:shared1,POSTFIX:YES,foo>]"
+)