Przeglądaj źródła

Merge topic 'INTERFACE_LIBRARY-build-targets'

b04f3b9 Create make rules for INTERFACE_LIBRARY targets.
dba4962 Makefile: Always create clean target command
Brad King 12 lat temu
rodzic
commit
bf02e75079

+ 9 - 1
Source/cmComputeTargetDepends.cxx

@@ -208,7 +208,15 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
   std::set<cmStdString> emitted;
   {
   std::vector<std::string> tlibs;
-  depender->GetDirectLinkLibraries(0, tlibs, depender);
+  if (depender->GetType() == cmTarget::INTERFACE_LIBRARY)
+    {
+    // For INTERFACE_LIBRARY depend on the interface instead.
+    depender->GetInterfaceLinkLibraries(0, tlibs, depender);
+    }
+  else
+    {
+    depender->GetDirectLinkLibraries(0, tlibs, depender);
+    }
   // A target should not depend on itself.
   emitted.insert(depender->GetName());
   for(std::vector<std::string>::const_iterator lib = tlibs.begin();

+ 55 - 37
Source/cmGlobalUnixMakefileGenerator3.cxx

@@ -435,6 +435,7 @@ cmGlobalUnixMakefileGenerator3
        (l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
        (l->second.GetType() == cmTarget::MODULE_LIBRARY) ||
        (l->second.GetType() == cmTarget::OBJECT_LIBRARY) ||
+       (l->second.GetType() == cmTarget::INTERFACE_LIBRARY) ||
        (l->second.GetType() == cmTarget::UTILITY))
       {
       // Add this to the list of depends rules in this directory.
@@ -612,6 +613,7 @@ cmGlobalUnixMakefileGenerator3
           (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
           (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
           (t->second.GetType() == cmTarget::OBJECT_LIBRARY) ||
+          (t->second.GetType() == cmTarget::INTERFACE_LIBRARY) ||
           (t->second.GetType() == cmTarget::UTILITY)))
         {
         // Add a rule to build the target by name.
@@ -633,6 +635,10 @@ cmGlobalUnixMakefileGenerator3
                           t->second.GetName(), depends, commands,
                           true);
 
+        if (t->second.GetType() == cmTarget::INTERFACE_LIBRARY)
+          {
+          continue;
+          }
         // Add a fast rule to build the target
         std::string localName = lg->GetRelativeTargetDirectory(t->second);
         std::string makefileName;
@@ -699,6 +705,7 @@ cmGlobalUnixMakefileGenerator3
         || (t->second.GetType() == cmTarget::SHARED_LIBRARY)
         || (t->second.GetType() == cmTarget::MODULE_LIBRARY)
         || (t->second.GetType() == cmTarget::OBJECT_LIBRARY)
+        || (t->second.GetType() == cmTarget::INTERFACE_LIBRARY)
         || (t->second.GetType() == cmTarget::UTILITY)))
       {
       std::string makefileName;
@@ -715,53 +722,64 @@ cmGlobalUnixMakefileGenerator3
         << localName << "\n\n";
 
       commands.clear();
-      makeTargetName = localName;
-      makeTargetName += "/depend";
-      commands.push_back(lg->GetRecursiveMakeCall
-                         (makefileName.c_str(),makeTargetName.c_str()));
 
-      // add requires if we need it for this generator
-      if (needRequiresStep)
+      if(t->second.GetType() != cmTarget::INTERFACE_LIBRARY)
         {
         makeTargetName = localName;
-        makeTargetName += "/requires";
+        makeTargetName += "/depend";
         commands.push_back(lg->GetRecursiveMakeCall
-                           (makefileName.c_str(),makeTargetName.c_str()));
-        }
-      makeTargetName = localName;
-      makeTargetName += "/build";
-      commands.push_back(lg->GetRecursiveMakeCall
                           (makefileName.c_str(),makeTargetName.c_str()));
 
-      // Write the rule.
-      localName += "/all";
-      depends.clear();
+        // add requires if we need it for this generator
+        if (needRequiresStep)
+          {
+          makeTargetName = localName;
+          makeTargetName += "/requires";
+          commands.push_back(lg->GetRecursiveMakeCall
+                            (makefileName.c_str(),makeTargetName.c_str()));
+          }
+        makeTargetName = localName;
+        makeTargetName += "/build";
+        commands.push_back(lg->GetRecursiveMakeCall
+                            (makefileName.c_str(),makeTargetName.c_str()));
 
-      std::string progressDir =
-        lg->GetMakefile()->GetHomeOutputDirectory();
-      progressDir += cmake::GetCMakeFilesDirectory();
-        {
-        cmOStringStream progCmd;
-        progCmd << "$(CMAKE_COMMAND) -E cmake_progress_report ";
-        // all target counts
-        progCmd << lg->Convert(progressDir.c_str(),
-                                cmLocalGenerator::FULL,
-                                cmLocalGenerator::SHELL);
-        progCmd << " ";
-        std::vector<unsigned long>& progFiles =
-          this->ProgressMap[&t->second].Marks;
-        for (std::vector<unsigned long>::iterator i = progFiles.begin();
-              i != progFiles.end(); ++i)
+        // Write the rule.
+        localName += "/all";
+        depends.clear();
+
+        std::string progressDir =
+          lg->GetMakefile()->GetHomeOutputDirectory();
+        progressDir += cmake::GetCMakeFilesDirectory();
           {
-          progCmd << " " << *i;
+          cmOStringStream progCmd;
+          progCmd << "$(CMAKE_COMMAND) -E cmake_progress_report ";
+          // all target counts
+          progCmd << lg->Convert(progressDir.c_str(),
+                                  cmLocalGenerator::FULL,
+                                  cmLocalGenerator::SHELL);
+          progCmd << " ";
+          std::vector<unsigned long>& progFiles =
+            this->ProgressMap[&t->second].Marks;
+          for (std::vector<unsigned long>::iterator i = progFiles.begin();
+                i != progFiles.end(); ++i)
+            {
+            progCmd << " " << *i;
+            }
+          commands.push_back(progCmd.str());
           }
-        commands.push_back(progCmd.str());
+        progressDir = "Built target ";
+        progressDir += t->first;
+        lg->AppendEcho(commands,progressDir.c_str());
+        }
+      else
+        {
+        depends.clear();
         }
-      progressDir = "Built target ";
-      progressDir += t->first;
-      lg->AppendEcho(commands,progressDir.c_str());
-
       this->AppendGlobalTargetDepends(depends,t->second);
+      if(depends.empty() && this->EmptyRuleHackDepends != "")
+        {
+        depends.push_back(this->EmptyRuleHackDepends);
+        }
       lg->WriteMakeRule(ruleFileStream, "All Build rule for target.",
                         localName.c_str(), depends, commands, true);
 
@@ -777,7 +795,7 @@ cmGlobalUnixMakefileGenerator3
 
       // Write the rule.
       commands.clear();
-      progressDir = lg->GetMakefile()->GetHomeOutputDirectory();
+      std::string progressDir = lg->GetMakefile()->GetHomeOutputDirectory();
       progressDir += cmake::GetCMakeFilesDirectory();
 
       {

+ 38 - 37
Source/cmLocalUnixMakefileGenerator3.cxx

@@ -381,6 +381,7 @@ void cmLocalUnixMakefileGenerator3
        (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
        (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
        (t->second.GetType() == cmTarget::OBJECT_LIBRARY) ||
+       (t->second.GetType() == cmTarget::INTERFACE_LIBRARY) ||
        (t->second.GetType() == cmTarget::UTILITY))
       {
       emitted.insert(t->second.GetName());
@@ -1158,27 +1159,25 @@ cmLocalUnixMakefileGenerator3
                      const std::vector<std::string>& files,
                      cmTarget& target, const char* filename)
 {
+  std::string cleanfile = this->Makefile->GetCurrentOutputDirectory();
+  cleanfile += "/";
+  cleanfile += this->GetTargetDirectory(target);
+  cleanfile += "/cmake_clean";
+  if(filename)
+    {
+    cleanfile += "_";
+    cleanfile += filename;
+    }
+  cleanfile += ".cmake";
+  std::string cleanfilePath = this->Convert(cleanfile.c_str(), FULL);
+  std::ofstream fout(cleanfilePath.c_str());
+  if(!fout)
+    {
+    cmSystemTools::Error("Could not create ", cleanfilePath.c_str());
+    }
   if(!files.empty())
     {
-    std::string cleanfile = this->Makefile->GetCurrentOutputDirectory();
-    cleanfile += "/";
-    cleanfile += this->GetTargetDirectory(target);
-    cleanfile += "/cmake_clean";
-    if(filename)
-      {
-      cleanfile += "_";
-      cleanfile += filename;
-      }
-    cleanfile += ".cmake";
-    std::string cleanfilePath = this->Convert(cleanfile.c_str(), FULL);
-    std::ofstream fout(cleanfilePath.c_str());
-    if(!fout)
-      {
-      cmSystemTools::Error("Could not create ", cleanfilePath.c_str());
-      }
     fout << "file(REMOVE_RECURSE\n";
-    std::string remove = "$(CMAKE_COMMAND) -P ";
-    remove += this->Convert(cleanfile.c_str(), START_OUTPUT, SHELL);
     for(std::vector<std::string>::const_iterator f = files.begin();
         f != files.end(); ++f)
       {
@@ -1186,27 +1185,29 @@ cmLocalUnixMakefileGenerator3
       fout << "  " << this->EscapeForCMake(fc.c_str()) << "\n";
       }
     fout << ")\n";
-    commands.push_back(remove);
-
-    // For the main clean rule add per-language cleaning.
-    if(!filename)
+    }
+  std::string remove = "$(CMAKE_COMMAND) -P ";
+  remove += this->Convert(cleanfile.c_str(), START_OUTPUT, SHELL);
+  commands.push_back(remove);
+
+  // For the main clean rule add per-language cleaning.
+  if(!filename)
+    {
+    // Get the set of source languages in the target.
+    std::set<cmStdString> languages;
+    target.GetLanguages(languages);
+    fout << "\n"
+         << "# Per-language clean rules from dependency scanning.\n"
+         << "foreach(lang";
+    for(std::set<cmStdString>::const_iterator l = languages.begin();
+        l != languages.end(); ++l)
       {
-      // Get the set of source languages in the target.
-      std::set<cmStdString> languages;
-      target.GetLanguages(languages);
-      fout << "\n"
-           << "# Per-language clean rules from dependency scanning.\n"
-           << "foreach(lang";
-      for(std::set<cmStdString>::const_iterator l = languages.begin();
-          l != languages.end(); ++l)
-        {
-        fout << " " << *l;
-        }
-      fout << ")\n"
-           << "  include(" << this->GetTargetDirectory(target)
-           << "/cmake_clean_${lang}.cmake OPTIONAL)\n"
-           << "endforeach()\n";
+      fout << " " << *l;
       }
+    fout << ")\n"
+         << "  include(" << this->GetTargetDirectory(target)
+         << "/cmake_clean_${lang}.cmake OPTIONAL)\n"
+         << "endforeach()\n";
     }
 }
 

+ 3 - 0
Source/cmMakefileLibraryTargetGenerator.cxx

@@ -82,6 +82,9 @@ void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
     case cmTarget::OBJECT_LIBRARY:
       this->WriteObjectLibraryRules();
       break;
+    case cmTarget::INTERFACE_LIBRARY:
+      // Nothing to do.
+      break;
     default:
       // If language is not known, this is an error.
       cmSystemTools::Error("Unknown Library Type");

+ 1 - 0
Source/cmMakefileTargetGenerator.cxx

@@ -75,6 +75,7 @@ cmMakefileTargetGenerator::New(cmTarget *tgt)
     case cmTarget::SHARED_LIBRARY:
     case cmTarget::MODULE_LIBRARY:
     case cmTarget::OBJECT_LIBRARY:
+    case cmTarget::INTERFACE_LIBRARY:
       result = new cmMakefileLibraryTargetGenerator(tgt);
       break;
     case cmTarget::UTILITY:

+ 23 - 0
Source/cmTarget.cxx

@@ -1111,6 +1111,29 @@ void cmTarget::GetDirectLinkLibraries(const char *config,
     }
 }
 
+//----------------------------------------------------------------------------
+void cmTarget::GetInterfaceLinkLibraries(const char *config,
+                            std::vector<std::string> &libs, cmTarget *head)
+{
+  const char *prop = this->GetProperty("INTERFACE_LINK_LIBRARIES");
+  if (prop)
+    {
+    cmListFileBacktrace lfbt;
+    cmGeneratorExpression ge(lfbt);
+    const cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
+
+    cmGeneratorExpressionDAGChecker dagChecker(lfbt,
+                                        this->GetName(),
+                                        "INTERFACE_LINK_LIBRARIES", 0, 0);
+    cmSystemTools::ExpandListArgument(cge->Evaluate(this->Makefile,
+                                        config,
+                                        false,
+                                        head,
+                                        &dagChecker),
+                                      libs);
+    }
+}
+
 //----------------------------------------------------------------------------
 std::string cmTarget::GetDebugGeneratorExpressions(const std::string &value,
                                   cmTarget::LinkLibraryType llt)

+ 3 - 0
Source/cmTarget.h

@@ -177,6 +177,9 @@ public:
   void GetDirectLinkLibraries(const char *config,
                               std::vector<std::string> &,
                               cmTarget *head);
+  void GetInterfaceLinkLibraries(const char *config,
+                              std::vector<std::string> &,
+                              cmTarget *head);
 
   /** Compute the link type to use for the given configuration.  */
   LinkLibraryType ComputeLinkType(const char* config);

+ 17 - 0
Tests/CMakeLists.txt

@@ -261,6 +261,23 @@ if(BUILD_TESTING)
       PASS_REGULAR_EXPRESSION "(file is not of required architecture|does not match cputype|not the architecture being linked)")
   endif()
 
+  if(CMAKE_TEST_GENERATOR MATCHES Make)
+    set(InterfaceBuildTargets_libname testlib)
+    if (CMAKE_TEST_GENERATOR MATCHES "Borland|Watcom")
+      set(InterfaceBuildTargets_libname testlib.lib)
+    endif()
+    add_test(InterfaceBuildTargets ${CMAKE_CTEST_COMMAND}
+      --build-and-test
+      "${CMake_SOURCE_DIR}/Tests/InterfaceBuildTargets"
+      "${CMake_BINARY_DIR}/Tests/InterfaceBuildTargets"
+      --build-two-config
+      ${build_generator_args}
+      --build-project InterfaceBuildTargets
+      --test-command ${CMAKE_CMAKE_COMMAND} -E touch_nocreate ${InterfaceBuildTargets_libname}
+      )
+    list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/InterfaceBuildTargets")
+  endif()
+
   list(APPEND TEST_BUILD_DIRS ${CMake_TEST_INSTALL_PREFIX})
 
   if(NOT QT4_FOUND)

+ 13 - 0
Tests/InterfaceBuildTargets/CMakeLists.txt

@@ -0,0 +1,13 @@
+project(InterfaceBuildTargets)
+
+add_library(testlib EXCLUDE_FROM_ALL testlib.cxx)
+set_property(TARGET testlib PROPERTY PREFIX "")
+if(CMAKE_GENERATOR MATCHES "Borland|Watcom")
+  # These librarians add the .lib suffix anyway.
+  set_property(TARGET testlib PROPERTY SUFFIX ".lib")
+else()
+  set_property(TARGET testlib PROPERTY SUFFIX "")
+endif()
+
+add_library(iface INTERFACE)
+target_link_libraries(iface INTERFACE testlib)

+ 5 - 0
Tests/InterfaceBuildTargets/main.cxx

@@ -0,0 +1,5 @@
+
+int main(int, char**)
+{
+  return 0;
+}

+ 5 - 0
Tests/InterfaceBuildTargets/testlib.cxx

@@ -0,0 +1,5 @@
+
+void testlib(void)
+{
+
+}