Bläddra i källkod

Merge topic 'pdb-genex'

f86850ef Genex: Implement generator expressions for target PDB files.
028ad318 Genex: Simplify filesytem artifact code
Brad King 11 år sedan
förälder
incheckning
9f575a26fd

+ 11 - 0
Help/manual/cmake-generator-expressions.7.rst

@@ -148,6 +148,17 @@ than 4.2.0.
   Name of file with soname (.so.3).
 ``$<TARGET_SONAME_FILE_DIR:tgt>``
   Directory of with soname (.so.3).
+``$<TARGET_PDB_FILE:tgt>``
+  Full path to the linker generated program database file (.pdb)
+  where ``tgt`` is the name of a target.
+
+  See also the :prop_tgt:`PDB_NAME` and :prop_tgt:`PDB_OUTPUT_DIRECTORY`
+  target properties and their configuration specific variants
+  :prop_tgt:`PDB_NAME_<CONFIG>` and :prop_tgt:`PDB_OUTPUT_DIRECTORY_<CONFIG>`.
+``$<TARGET_PDB_FILE_NAME:tgt>``
+  Name of the linker generated program database file (.pdb).
+``$<TARGET_PDB_FILE_DIR:tgt>``
+  Directory of the linker generated program database file (.pdb).
 ``$<TARGET_PROPERTY:tgt,prop>``
   Value of the property ``prop`` on the target ``tgt``.
 

+ 1 - 0
Modules/Platform/Windows-MSVC.cmake

@@ -258,4 +258,5 @@ macro(__windows_compiler_msvc lang)
   set(CMAKE_${lang}_FLAGS_RELEASE_INIT "/MD /O2 /Ob2 /D NDEBUG")
   set(CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT "/MD /Zi /O2 /Ob1 /D NDEBUG")
   set(CMAKE_${lang}_FLAGS_MINSIZEREL_INIT "/MD /O1 /Ob1 /D NDEBUG")
+  set(CMAKE_${lang}_LINKER_SUPPORTS_PDB ON)
 endmacro()

+ 91 - 34
Source/cmGeneratorExpressionEvaluator.cxx

@@ -1523,7 +1523,17 @@ static const struct InstallPrefixNode : public cmGeneratorExpressionNode
 } installPrefixNode;
 
 //----------------------------------------------------------------------------
-template<bool linker, bool soname>
+class ArtifactNameTag;
+class ArtifactLinkerTag;
+class ArtifactSonameTag;
+class ArtifactPdbTag;
+
+class ArtifactPathTag;
+class ArtifactDirTag;
+class ArtifactNameTag;
+
+//----------------------------------------------------------------------------
+template<typename ArtifactT>
 struct TargetFilesystemArtifactResultCreator
 {
   static std::string Create(cmTarget* target,
@@ -1533,7 +1543,7 @@ struct TargetFilesystemArtifactResultCreator
 
 //----------------------------------------------------------------------------
 template<>
-struct TargetFilesystemArtifactResultCreator<false, true>
+struct TargetFilesystemArtifactResultCreator<ArtifactSonameTag>
 {
   static std::string Create(cmTarget* target,
                             cmGeneratorExpressionContext *context,
@@ -1563,7 +1573,45 @@ struct TargetFilesystemArtifactResultCreator<false, true>
 
 //----------------------------------------------------------------------------
 template<>
-struct TargetFilesystemArtifactResultCreator<true, false>
+struct TargetFilesystemArtifactResultCreator<ArtifactPdbTag>
+{
+  static std::string Create(cmTarget* target,
+                            cmGeneratorExpressionContext *context,
+                            const GeneratorExpressionContent *content)
+  {
+    std::string language = target->GetLinkerLanguage(context->Config);
+
+    std::string pdbSupportVar = "CMAKE_" + language + "_LINKER_SUPPORTS_PDB";
+
+    if(!context->Makefile->IsOn(pdbSupportVar))
+      {
+      ::reportError(context, content->GetOriginalExpression(),
+                    "TARGET_PDB_FILE is not supported by the target linker.");
+      return std::string();
+      }
+
+    cmTarget::TargetType targetType = target->GetType();
+
+    if(targetType != cmTarget::SHARED_LIBRARY &&
+       targetType != cmTarget::MODULE_LIBRARY &&
+       targetType != cmTarget::EXECUTABLE)
+      {
+      ::reportError(context, content->GetOriginalExpression(),
+                    "TARGET_PDB_FILE is allowed only for "
+                    "targets with linker created artifacts.");
+      return std::string();
+      }
+
+    std::string result = target->GetPDBDirectory(context->Config);
+    result += "/";
+    result += target->GetPDBName(context->Config);
+    return result;
+  }
+};
+
+//----------------------------------------------------------------------------
+template<>
+struct TargetFilesystemArtifactResultCreator<ArtifactLinkerTag>
 {
   static std::string Create(cmTarget* target,
                             cmGeneratorExpressionContext *context,
@@ -1584,7 +1632,7 @@ struct TargetFilesystemArtifactResultCreator<true, false>
 
 //----------------------------------------------------------------------------
 template<>
-struct TargetFilesystemArtifactResultCreator<false, false>
+struct TargetFilesystemArtifactResultCreator<ArtifactNameTag>
 {
   static std::string Create(cmTarget* target,
                             cmGeneratorExpressionContext *context,
@@ -1596,7 +1644,7 @@ struct TargetFilesystemArtifactResultCreator<false, false>
 
 
 //----------------------------------------------------------------------------
-template<bool dirQual, bool nameQual>
+template<typename ArtifactT>
 struct TargetFilesystemArtifactResultGetter
 {
   static std::string Get(const std::string &result);
@@ -1604,7 +1652,7 @@ struct TargetFilesystemArtifactResultGetter
 
 //----------------------------------------------------------------------------
 template<>
-struct TargetFilesystemArtifactResultGetter<false, true>
+struct TargetFilesystemArtifactResultGetter<ArtifactNameTag>
 {
   static std::string Get(const std::string &result)
   { return cmSystemTools::GetFilenameName(result); }
@@ -1612,7 +1660,7 @@ struct TargetFilesystemArtifactResultGetter<false, true>
 
 //----------------------------------------------------------------------------
 template<>
-struct TargetFilesystemArtifactResultGetter<true, false>
+struct TargetFilesystemArtifactResultGetter<ArtifactDirTag>
 {
   static std::string Get(const std::string &result)
   { return cmSystemTools::GetFilenamePath(result); }
@@ -1620,14 +1668,14 @@ struct TargetFilesystemArtifactResultGetter<true, false>
 
 //----------------------------------------------------------------------------
 template<>
-struct TargetFilesystemArtifactResultGetter<false, false>
+struct TargetFilesystemArtifactResultGetter<ArtifactPathTag>
 {
   static std::string Get(const std::string &result)
   { return result; }
 };
 
 //----------------------------------------------------------------------------
-template<bool linker, bool soname, bool dirQual, bool nameQual>
+template<typename ArtifactT, typename ComponentT>
 struct TargetFilesystemArtifact : public cmGeneratorExpressionNode
 {
   TargetFilesystemArtifact() {}
@@ -1675,7 +1723,7 @@ struct TargetFilesystemArtifact : public cmGeneratorExpressionNode
     context->AllTargets.insert(target);
 
     std::string result =
-                TargetFilesystemArtifactResultCreator<linker, soname>::Create(
+                TargetFilesystemArtifactResultCreator<ArtifactT>::Create(
                           target,
                           context,
                           content);
@@ -1684,29 +1732,35 @@ struct TargetFilesystemArtifact : public cmGeneratorExpressionNode
       return std::string();
       }
     return
-        TargetFilesystemArtifactResultGetter<dirQual, nameQual>::Get(result);
+        TargetFilesystemArtifactResultGetter<ComponentT>::Get(result);
   }
 };
 
+//----------------------------------------------------------------------------
+template<typename ArtifactT>
+struct TargetFilesystemArtifactNodeGroup
+{
+  TargetFilesystemArtifactNodeGroup()
+    {
+    }
+
+  TargetFilesystemArtifact<ArtifactT, ArtifactPathTag> File;
+  TargetFilesystemArtifact<ArtifactT, ArtifactNameTag> FileName;
+  TargetFilesystemArtifact<ArtifactT, ArtifactDirTag> FileDir;
+};
+
 //----------------------------------------------------------------------------
 static const
-TargetFilesystemArtifact<false, false, false, false> targetFileNode;
-static const
-TargetFilesystemArtifact<true, false, false, false> targetLinkerFileNode;
-static const
-TargetFilesystemArtifact<false, true, false, false> targetSoNameFileNode;
-static const
-TargetFilesystemArtifact<false, false, false, true> targetFileNameNode;
-static const
-TargetFilesystemArtifact<true, false, false, true> targetLinkerFileNameNode;
-static const
-TargetFilesystemArtifact<false, true, false, true> targetSoNameFileNameNode;
+TargetFilesystemArtifactNodeGroup<ArtifactNameTag> targetNodeGroup;
+
 static const
-TargetFilesystemArtifact<false, false, true, false> targetFileDirNode;
+TargetFilesystemArtifactNodeGroup<ArtifactLinkerTag> targetLinkerNodeGroup;
+
 static const
-TargetFilesystemArtifact<true, false, true, false> targetLinkerFileDirNode;
+TargetFilesystemArtifactNodeGroup<ArtifactSonameTag> targetSoNameNodeGroup;
+
 static const
-TargetFilesystemArtifact<false, true, true, false> targetSoNameFileDirNode;
+TargetFilesystemArtifactNodeGroup<ArtifactPdbTag> targetPdbNodeGroup;
 
 //----------------------------------------------------------------------------
 static const
@@ -1732,15 +1786,18 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
     nodeMap["COMPILE_FEATURES"] = &compileFeaturesNode;
     nodeMap["CONFIGURATION"] = &configurationNode;
     nodeMap["CONFIG"] = &configurationTestNode;
-    nodeMap["TARGET_FILE"] = &targetFileNode;
-    nodeMap["TARGET_LINKER_FILE"] = &targetLinkerFileNode;
-    nodeMap["TARGET_SONAME_FILE"] = &targetSoNameFileNode;
-    nodeMap["TARGET_FILE_NAME"] = &targetFileNameNode;
-    nodeMap["TARGET_LINKER_FILE_NAME"] = &targetLinkerFileNameNode;
-    nodeMap["TARGET_SONAME_FILE_NAME"] = &targetSoNameFileNameNode;
-    nodeMap["TARGET_FILE_DIR"] = &targetFileDirNode;
-    nodeMap["TARGET_LINKER_FILE_DIR"] = &targetLinkerFileDirNode;
-    nodeMap["TARGET_SONAME_FILE_DIR"] = &targetSoNameFileDirNode;
+    nodeMap["TARGET_FILE"] = &targetNodeGroup.File;
+    nodeMap["TARGET_LINKER_FILE"] = &targetLinkerNodeGroup.File;
+    nodeMap["TARGET_SONAME_FILE"] = &targetSoNameNodeGroup.File;
+    nodeMap["TARGET_PDB_FILE"] = &targetPdbNodeGroup.File;
+    nodeMap["TARGET_FILE_NAME"] = &targetNodeGroup.FileName;
+    nodeMap["TARGET_LINKER_FILE_NAME"] = &targetLinkerNodeGroup.FileName;
+    nodeMap["TARGET_SONAME_FILE_NAME"] = &targetSoNameNodeGroup.FileName;
+    nodeMap["TARGET_PDB_FILE_NAME"] = &targetPdbNodeGroup.FileName;
+    nodeMap["TARGET_FILE_DIR"] = &targetNodeGroup.FileDir;
+    nodeMap["TARGET_LINKER_FILE_DIR"] = &targetLinkerNodeGroup.FileDir;
+    nodeMap["TARGET_SONAME_FILE_DIR"] = &targetSoNameNodeGroup.FileDir;
+    nodeMap["TARGET_PDB_FILE_DIR"] = &targetPdbNodeGroup.FileDir;
     nodeMap["STREQUAL"] = &strEqualNode;
     nodeMap["EQUAL"] = &equalNode;
     nodeMap["LOWER_CASE"] = &lowerCaseNode;

+ 6 - 0
Tests/RunCMake/CMakeLists.txt

@@ -21,6 +21,12 @@ if(XCODE_VERSION AND "${XCODE_VERSION}" VERSION_LESS 2)
   set(File_Generate_ARGS -DXCODE_BELOW_2=1)
 endif()
 
+# Test MSVC for older host CMake versions, and test
+# WIN32/CMAKE_C_COMPILER_ID to fix check on Intel for Windows.
+if(MSVC OR (WIN32 AND CMAKE_C_COMPILER_ID MATCHES "MSVC|Intel"))
+  set(GeneratorExpression_ARGS -DLINKER_SUPPORTS_PDB=1)
+endif()
+
 add_RunCMake_test(CMP0019)
 add_RunCMake_test(CMP0022)
 add_RunCMake_test(CMP0026)

+ 1 - 0
Tests/RunCMake/GeneratorExpression/NonValidCompiler-TARGET_PDB_FILE-result.txt

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

+ 8 - 0
Tests/RunCMake/GeneratorExpression/NonValidCompiler-TARGET_PDB_FILE-stderr.txt

@@ -0,0 +1,8 @@
+CMake Error at NonValidCompiler-TARGET_PDB_FILE.cmake:6 \(file\):
+  Error evaluating generator expression:
+
+    \$<TARGET_PDB_FILE:empty>
+
+  TARGET_PDB_FILE is not supported by the target linker.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 9 - 0
Tests/RunCMake/GeneratorExpression/NonValidCompiler-TARGET_PDB_FILE.cmake

@@ -0,0 +1,9 @@
+
+enable_language(C)
+
+add_library(empty STATIC empty.c)
+
+file(GENERATE
+  OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/test.txt"
+  CONTENT "[$<TARGET_PDB_FILE:empty>]"
+)

+ 1 - 0
Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_PDB_FILE-result.txt

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

+ 8 - 0
Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_PDB_FILE-stderr.txt

@@ -0,0 +1,8 @@
+CMake Error at NonValidTarget-TARGET_PDB_FILE.cmake:6 \(file\):
+  Error evaluating generator expression:
+
+    \$<TARGET_PDB_FILE:empty>
+
+  TARGET_PDB_FILE is allowed only for targets with linker created artifacts.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 9 - 0
Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_PDB_FILE.cmake

@@ -0,0 +1,9 @@
+
+enable_language(C)
+
+add_library(empty STATIC empty.c)
+
+file(GENERATE
+  OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/test.txt"
+  CONTENT "[$<TARGET_PDB_FILE:empty>]"
+)

+ 7 - 0
Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake

@@ -16,3 +16,10 @@ run_cmake(NonValidTarget-C_COMPILER_VERSION)
 run_cmake(NonValidTarget-CXX_COMPILER_VERSION)
 run_cmake(NonValidTarget-TARGET_PROPERTY)
 run_cmake(NonValidTarget-TARGET_POLICY)
+
+if(LINKER_SUPPORTS_PDB)
+  run_cmake(NonValidTarget-TARGET_PDB_FILE)
+  run_cmake(ValidTarget-TARGET_PDB_FILE)
+else()
+  run_cmake(NonValidCompiler-TARGET_PDB_FILE)
+endif()

+ 17 - 0
Tests/RunCMake/GeneratorExpression/ValidTarget-TARGET_PDB_FILE-check.cmake

@@ -0,0 +1,17 @@
+file(STRINGS ${RunCMake_TEST_BINARY_DIR}/test.txt TEST_TXT)
+
+list(GET TEST_TXT 0 PDB_PATH)
+list(GET TEST_TXT 1 PDB_NAME)
+list(GET TEST_TXT 2 PDB_DIR)
+
+if(NOT PDB_PATH MATCHES "empty\\.pdb")
+  message(FATAL_ERROR "unexpected PDB_PATH [${PDB_PATH}]")
+endif()
+
+if(NOT PDB_NAME STREQUAL "empty.pdb")
+  message(FATAL_ERROR "unexpected PDB_NAME [${PDB_NAME}]")
+endif()
+
+if(PDB_DIR MATCHES "empty\\.pdb")
+  message(FATAL_ERROR "unexpected PDB_DIR [${PDB_DIR}]")
+endif()

+ 1 - 0
Tests/RunCMake/GeneratorExpression/ValidTarget-TARGET_PDB_FILE-stderr.txt

@@ -0,0 +1 @@
+^$

+ 19 - 0
Tests/RunCMake/GeneratorExpression/ValidTarget-TARGET_PDB_FILE.cmake

@@ -0,0 +1,19 @@
+
+enable_language(C)
+
+add_library(empty SHARED empty.c)
+
+if(CMAKE_CONFIGURATION_TYPES)
+  list(GET CMAKE_CONFIGURATION_TYPES 0 FIRST_CONFIG)
+  set(GENERATE_CONDITION CONDITION $<CONFIG:${FIRST_CONFIG}>)
+endif()
+
+file(GENERATE
+  OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/test.txt"
+  CONTENT
+[[$<TARGET_PDB_FILE:empty>
+$<TARGET_PDB_FILE_NAME:empty>
+$<TARGET_PDB_FILE_DIR:empty>
+]]
+  ${GENERATE_CONDITION}
+)