Browse Source

export: Add support for INTERFACE_LIBRARY targets

Stephen Kelly 13 years ago
parent
commit
435c912848

+ 10 - 0
Source/cmAddLibraryCommand.cxx

@@ -220,6 +220,16 @@ bool cmAddLibraryCommand
         );
       return true;
       }
+    if(type == cmTarget::INTERFACE_LIBRARY)
+      {
+      if (!cmGeneratorExpression::IsValidTargetName(libName))
+        {
+        cmOStringStream e;
+        e << "Invalid name for IMPORTED INTERFACE library target: " << libName;
+        this->SetError(e.str().c_str());
+        return false;
+        }
+      }
 
     // Make sure the target does not already exist.
     if(this->Makefile->FindTargetToUse(libName.c_str()))

+ 1 - 0
Source/cmCoreTryCompile.cxx

@@ -99,6 +99,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
           {
           case cmTarget::SHARED_LIBRARY:
           case cmTarget::STATIC_LIBRARY:
+          case cmTarget::INTERFACE_LIBRARY:
           case cmTarget::UNKNOWN_LIBRARY:
             break;
           case cmTarget::EXECUTABLE:

+ 17 - 7
Source/cmExportBuildFileGenerator.cxx

@@ -47,6 +47,10 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
         }
       return false;
       }
+    if (te->GetType() == cmTarget::INTERFACE_LIBRARY)
+      {
+      this->GenerateRequiredCMakeVersion(os, "2.8.12.20131007"); // 2.8.13
+      }
     }
 
   this->GenerateExpectedTargetsCode(os, expectedTargets);
@@ -118,16 +122,22 @@ cmExportBuildFileGenerator
     // Collect import properties for this target.
     cmTarget* target = *tei;
     ImportPropertyMap properties;
-    this->SetImportLocationProperty(config, suffix, target, properties);
+
+    if (target->GetType() != cmTarget::INTERFACE_LIBRARY)
+      {
+      this->SetImportLocationProperty(config, suffix, target, properties);
+      }
     if(!properties.empty())
       {
       // Get the rest of the target details.
-      this->SetImportDetailProperties(config, suffix,
-                                      target, properties, missingTargets);
-      this->SetImportLinkInterface(config, suffix,
-                                   cmGeneratorExpression::BuildInterface,
-                                   target, properties, missingTargets);
-
+      if (target->GetType() != cmTarget::INTERFACE_LIBRARY)
+        {
+        this->SetImportDetailProperties(config, suffix,
+                                        target, properties, missingTargets);
+        this->SetImportLinkInterface(config, suffix,
+                                    cmGeneratorExpression::BuildInterface,
+                                    target, properties, missingTargets);
+        }
 
       // TOOD: PUBLIC_HEADER_LOCATION
       // This should wait until the build feature propagation stuff

+ 2 - 1
Source/cmExportCommand.cxx

@@ -130,7 +130,8 @@ bool cmExportCommand
       if((target->GetType() == cmTarget::EXECUTABLE) ||
          (target->GetType() == cmTarget::STATIC_LIBRARY) ||
          (target->GetType() == cmTarget::SHARED_LIBRARY) ||
-         (target->GetType() == cmTarget::MODULE_LIBRARY))
+         (target->GetType() == cmTarget::MODULE_LIBRARY) ||
+         (target->GetType() == cmTarget::INTERFACE_LIBRARY))
         {
         targets.push_back(target);
         }

+ 11 - 5
Source/cmExportFileGenerator.cxx

@@ -378,11 +378,14 @@ void getCompatibleInterfaceProperties(cmTarget *target,
 
   if (!info)
     {
-    cmMakefile* mf = target->GetMakefile();
-    cmOStringStream e;
-    e << "Exporting the target \"" << target->GetName() << "\" is not "
-         "allowed since its linker language cannot be determined";
-    mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+    if (target->GetType() != cmTarget::INTERFACE_LIBRARY)
+      {
+      cmMakefile* mf = target->GetMakefile();
+      cmOStringStream e;
+      e << "Exporting the target \"" << target->GetName() << "\" is not "
+          "allowed since its linker language cannot be determined";
+      mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+      }
     return;
     }
 
@@ -887,6 +890,9 @@ cmExportFileGenerator
     case cmTarget::UNKNOWN_LIBRARY:
       os << "add_library(" << targetName << " UNKNOWN IMPORTED)\n";
       break;
+    case cmTarget::INTERFACE_LIBRARY:
+      os << "add_library(" << targetName << " INTERFACE IMPORTED)\n";
+      break;
     default:  // should never happen
       break;
     }

+ 2 - 1
Source/cmTarget.cxx

@@ -6164,7 +6164,8 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
   const char* loc = 0;
   const char* imp = 0;
   std::string suffix;
-  if (!this->GetMappedConfig(desired_config, &loc, &imp, suffix))
+  if (this->GetType() != INTERFACE_LIBRARY &&
+      !this->GetMappedConfig(desired_config, &loc, &imp, suffix))
     {
     return;
     }

+ 2 - 0
Tests/ExportImport/Export/CMakeLists.txt

@@ -426,3 +426,5 @@ export(TARGETS testExe2 testLib4 testLib5 testLib6 testExe3 testExe2lib
   NAMESPACE bld_
   APPEND FILE ExportBuildTree.cmake
   )
+
+add_subdirectory(Interface)

+ 29 - 0
Tests/ExportImport/Export/Interface/CMakeLists.txt

@@ -0,0 +1,29 @@
+
+add_library(headeronly INTERFACE)
+set_property(TARGET headeronly PROPERTY INTERFACE_INCLUDE_DIRECTORIES
+  "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/headeronly>"
+  "$<INSTALL_INTERFACE:${CMAKE_INSTALL_PREFIX}/include/headeronly>"
+)
+set_property(TARGET headeronly PROPERTY INTERFACE_COMPILE_DEFINITIONS "HEADERONLY_DEFINE")
+
+include(GenerateExportHeader)
+add_library(sharedlib SHARED sharedlib.cpp)
+generate_export_header(sharedlib)
+set_property(TARGET sharedlib PROPERTY INCLUDE_DIRECTORIES
+  "${CMAKE_CURRENT_SOURCE_DIR}/sharedlib"
+  "${CMAKE_CURRENT_BINARY_DIR}"
+)
+set_property(TARGET sharedlib PROPERTY INTERFACE_INCLUDE_DIRECTORIES
+  "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/sharedlib;${CMAKE_CURRENT_BINARY_DIR}>"
+  "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include/sharedlib>"
+)
+
+set_property(TARGET sharedlib PROPERTY INTERFACE_COMPILE_DEFINITIONS "SHAREDLIB_DEFINE")
+
+add_library(sharediface INTERFACE)
+target_link_libraries(sharediface INTERFACE sharedlib)
+
+export(TARGETS sharediface sharedlib headeronly
+  NAMESPACE bld_
+  FILE ../ExportInterfaceBuildTree.cmake
+)

+ 7 - 0
Tests/ExportImport/Export/Interface/headeronly/headeronly.h

@@ -0,0 +1,7 @@
+
+enum { one };
+
+struct HeaderOnly
+{
+  int foo() const { return 0; }
+};

+ 7 - 0
Tests/ExportImport/Export/Interface/sharedlib.cpp

@@ -0,0 +1,7 @@
+
+#include "sharedlib.h"
+
+int SharedLibObject::foo() const
+{
+  return 0;
+}

+ 7 - 0
Tests/ExportImport/Export/Interface/sharedlib/sharedlib.h

@@ -0,0 +1,7 @@
+
+#include "sharedlib_export.h"
+
+struct SHAREDLIB_EXPORT SharedLibObject
+{
+  int foo() const;
+};

+ 3 - 0
Tests/ExportImport/Import/CMakeLists.txt

@@ -19,3 +19,6 @@ add_executable(imp_testTransExe1b imp_testTransExe1.c)
 target_link_libraries(imp_testTransExe1b imp_lib1b)
 
 add_subdirectory(try_compile)
+
+# Test package INTERFACE controls
+add_subdirectory(Interface)

+ 42 - 0
Tests/ExportImport/Import/Interface/CMakeLists.txt

@@ -0,0 +1,42 @@
+
+# Import targets from the exported build tree.
+include(${Import_BINARY_DIR}/../Export/ExportInterfaceBuildTree.cmake)
+
+add_library(define_iface INTERFACE)
+set_property(TARGET define_iface PROPERTY
+  INTERFACE_COMPILE_DEFINITIONS DEFINE_IFACE_DEFINE)
+
+add_executable(headeronlytest_bld headeronlytest.cpp)
+target_link_libraries(headeronlytest_bld bld_headeronly)
+
+set_property(TARGET bld_sharediface APPEND PROPERTY INTERFACE_LINK_LIBRARIES define_iface)
+
+add_executable(interfacetest_bld interfacetest.cpp)
+target_link_libraries(interfacetest_bld bld_sharediface)
+
+include(CheckCXXSourceCompiles)
+
+macro(do_try_compile prefix)
+
+  set(CMAKE_REQUIRED_LIBRARIES ${prefix}headeronly)
+  check_cxx_source_compiles(
+    "
+  #include \"headeronly.h\"
+
+  #ifndef HEADERONLY_DEFINE
+  #error Expected HEADERONLY_DEFINE
+  #endif
+
+  int main(int,char**)
+  {
+    HeaderOnly ho;
+    return ho.foo();
+  }
+  " ${prefix}IFACE_TRY_COMPILE)
+
+  if(NOT ${prefix}IFACE_TRY_COMPILE)
+    message(SEND_ERROR "${prefix} try_compile with IMPORTED INTERFACE target failed!\n\n${OUTPUT}")
+  endif()
+endmacro()
+
+do_try_compile(bld_)

+ 17 - 0
Tests/ExportImport/Import/Interface/headeronlytest.cpp

@@ -0,0 +1,17 @@
+
+#include "headeronly.h"
+
+#ifndef HEADERONLY_DEFINE
+#error Expected HEADERONLY_DEFINE
+#endif
+
+#ifdef SHAREDLIB_DEFINE
+#error Unexpected SHAREDLIB_DEFINE
+#endif
+
+
+int main(int,char**)
+{
+  HeaderOnly ho;
+  return ho.foo();
+}

+ 20 - 0
Tests/ExportImport/Import/Interface/interfacetest.cpp

@@ -0,0 +1,20 @@
+
+#include "sharedlib.h"
+
+#ifndef SHAREDLIB_DEFINE
+#error Expected SHAREDLIB_DEFINE
+#endif
+
+#ifdef HEADERONLY_DEFINE
+#error Unexpected HEADERONLY_DEFINE
+#endif
+
+#ifndef DEFINE_IFACE_DEFINE
+#error Expected DEFINE_IFACE_DEFINE
+#endif
+
+int main(int,char**)
+{
+  SharedLibObject slo;
+  return slo.foo();
+}

+ 6 - 0
Tests/RunCMake/interface_library/invalid_name-stderr.txt

@@ -7,3 +7,9 @@ CMake Error at invalid_name.cmake:4 \(add_library\):
   add_library Invalid name for INTERFACE library target: iface::target
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)
++
+CMake Error at invalid_name.cmake:6 \(add_library\):
+  add_library Invalid name for IMPORTED INTERFACE library target:
+  if\$target_imported
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 2 - 0
Tests/RunCMake/interface_library/invalid_name.cmake

@@ -2,3 +2,5 @@
 add_library(if$ace INTERFACE)
 
 add_library(iface::target INTERFACE)
+
+add_library(if$target_imported INTERFACE IMPORTED)