From 28ea03473785eddce544704306a239407a8f79bb Mon Sep 17 00:00:00 2001
From: Brad King <brad.king@kitware.com>
Date: Mon, 28 Jan 2008 13:05:58 -0500
Subject: ENH: Support exporting/importing of Framework targets.

  - Imported frameworks have the FRAMEWORK property set
  - Added cmTarget::IsFrameworkOnApple method to simplify checks
  - Also remove separate IMPORTED_ENABLE_EXPORTS property and just use ENABLE_EXPORTS since, like FRAMEWORK, it just represents the target type.
  - Document FRAMEWORK keyword in INSTALL command.
  - Updated IMPORTED_LOCATION property documentation for Frameworks
---
 Source/cmComputeLinkInformation.cxx         |  6 ++--
 Source/cmExportFileGenerator.cxx            | 13 +++++++-
 Source/cmExportInstallFileGenerator.cxx     | 13 ++++++--
 Source/cmGlobalGenerator.cxx                |  3 +-
 Source/cmGlobalXCodeGenerator.cxx           |  9 ++----
 Source/cmInstallCommand.cxx                 |  6 ++--
 Source/cmInstallCommand.h                   | 11 ++++---
 Source/cmInstallTargetGenerator.cxx         |  3 +-
 Source/cmMakefileLibraryTargetGenerator.cxx | 11 +++----
 Source/cmTarget.cxx                         | 48 ++++++++++-------------------
 Source/cmTarget.h                           |  4 +++
 11 files changed, 62 insertions(+), 65 deletions(-)

diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index 4d0d93a..b614de8 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -337,9 +337,8 @@ void cmComputeLinkInformation::AddItem(std::string const& item,
       // Pass the full path to the target file.
       std::string lib = tgt->GetFullPath(config, implib);
       this->Depends.push_back(lib);
-#ifdef __APPLE__
-      if(tgt->GetType() == cmTarget::SHARED_LIBRARY &&
-         tgt->GetPropertyAsBool("FRAMEWORK"))
+
+      if(tgt->IsFrameworkOnApple())
         {
         // Frameworks on OS X need only the framework directory to
         // link.
@@ -347,7 +346,6 @@ void cmComputeLinkInformation::AddItem(std::string const& item,
         this->AddFrameworkItem(fw);
         }
       else
-#endif
         {
         this->AddTargetItem(lib, tgt);
         this->AddLibraryRuntimeInfo(lib, tgt);
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index ec4bc33..2c916e5 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -237,10 +237,21 @@ cmExportFileGenerator
     default:  // should never happen
       break;
     }
+
+  // Mark the imported executable if it has exports.
   if(target->IsExecutableWithExports())
     {
     os << "SET_PROPERTY(TARGET " << targetName
-       << " PROPERTY IMPORTED_ENABLE_EXPORTS 1)\n";
+       << " PROPERTY ENABLE_EXPORTS 1)\n";
+    }
+
+  // Mark the imported framework.  This is done even on non-Apple
+  // platforms for reference and consistency purposes.
+  if(target->GetType() == cmTarget::SHARED_LIBRARY &&
+     target->GetPropertyAsBool("FRAMEWORK"))
+    {
+    os << "SET_PROPERTY(TARGET " << targetName
+       << " PROPERTY FRAMEWORK 1)\n";
     }
   os << "\n";
 }
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index 8266a96..f378106 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -158,8 +158,9 @@ cmExportInstallFileGenerator
                                     te->LibraryGenerator, properties);
     this->SetImportLocationProperty(config, suffix,
                                     te->RuntimeGenerator, properties);
+    this->SetImportLocationProperty(config, suffix,
+                                    te->FrameworkGenerator, properties);
 
-    // TODO: Frameworks?
     // TODO: Bundles?
 
     // If any file location was set for the target add it to the
@@ -223,7 +224,15 @@ cmExportInstallFileGenerator
   value += "/";
 
   // Append the installed file name.
-  value += itgen->GetInstallFilename(config);
+  std::string fname = itgen->GetInstallFilename(config);
+  value += fname;
+
+  // Fix name for frameworks.
+  if(itgen->GetTarget()->IsFrameworkOnApple())
+    {
+    value += ".framework/";
+    value += fname;
+    }
 
   // Store the property.
   properties[prop] = value;
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 6c1af53..dfa6e05 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -1359,8 +1359,7 @@ bool cmGlobalGenerator::NameResolvesToFramework(const std::string& libname)
 
   if(cmTarget* tgt = this->FindTarget(0, libname.c_str()))
     {
-    if(tgt->GetType() == cmTarget::SHARED_LIBRARY &&
-       tgt->GetPropertyAsBool("FRAMEWORK"))
+    if(tgt->IsFrameworkOnApple())
        {
        return true;
        }
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 19394f2..f1a2b71 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -498,8 +498,7 @@ cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg,
   // Is this a "private" or "public" framework header file?
   // Set the ATTRIBUTES attribute appropriately...
   //
-  if(cmtarget.GetType() == cmTarget::SHARED_LIBRARY &&
-     cmtarget.GetPropertyAsBool("FRAMEWORK"))
+  if(cmtarget.IsFrameworkOnApple())
     {
     if(tsFlags.PrivateHeader)
       {
@@ -710,8 +709,7 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
       }
 
     // some build phases only apply to bundles and/or frameworks
-    bool isFrameworkTarget = cmtarget.GetType() == cmTarget::SHARED_LIBRARY &&
-      cmtarget.GetPropertyAsBool("FRAMEWORK");
+    bool isFrameworkTarget = cmtarget.IsFrameworkOnApple();
     bool isBundleTarget = cmtarget.GetPropertyAsBool("MACOSX_BUNDLE");
 
     cmXCodeObject* buildFiles = 0;
@@ -1359,8 +1357,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
      target.GetType() == cmTarget::EXECUTABLE)
     {
     std::string pndir = target.GetDirectory();
-    if (target.GetType() == cmTarget::SHARED_LIBRARY &&
-        target.GetPropertyAsBool("FRAMEWORK"))
+    if(target.IsFrameworkOnApple())
       {
       pndir += "/..";
       pndir = cmSystemTools::CollapseFullPath(pndir.c_str());
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index 6c742b9..863f138 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -376,7 +376,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
           // This is a non-DLL platform.
           // If it is marked with FRAMEWORK property use the FRAMEWORK set of
           // INSTALL properties. Otherwise, use the LIBRARY properties.
-          if(target.GetPropertyAsBool("FRAMEWORK"))
+          if(target.IsFrameworkOnApple())
             {
             // Use the FRAMEWORK properties.
             if (!frameworkArgs.GetDestination().empty())
@@ -512,9 +512,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
   //
   bool createInstallGeneratorsForTargetFileSets = true;
 
-  if(cmTarget::SHARED_LIBRARY == target.GetType() &&
-    target.GetPropertyAsBool("FRAMEWORK") &&
-    this->Makefile->IsOn("APPLE"))
+  if(target.IsFrameworkOnApple())
     {
     createInstallGeneratorsForTargetFileSets = false;
     }
diff --git a/Source/cmInstallCommand.h b/Source/cmInstallCommand.h
index 0f5eb16..ed3a3a2 100644
--- a/Source/cmInstallCommand.h
+++ b/Source/cmInstallCommand.h
@@ -99,7 +99,7 @@ public:
       "\n"
       "The TARGETS signature:\n"
       "  install(TARGETS targets... [EXPORT <export-name>]\n"
-      "          [[ARCHIVE|LIBRARY|RUNTIME]\n"
+      "          [[ARCHIVE|LIBRARY|RUNTIME|FRAMEWORK]\n"
       "           [DESTINATION <dir>]\n"
       "           [PERMISSIONS permissions...]\n"
       "           [CONFIGURATIONS [Debug|Release|...]]\n"
@@ -107,19 +107,20 @@ public:
       "           [OPTIONAL]\n"
       "          ] [...])\n"
       "The TARGETS form specifies rules for installing targets from a "
-      "project.  There are three kinds of target files that may be "
-      "installed: archive, library, and runtime.  "
+      "project.  There are four kinds of target files that may be "
+      "installed: archive, library, runtime, and framework.  "
 
       "Executables are always treated as runtime targets. "
       "Static libraries are always treated as archive targets. "
       "Module libraries are always treated as library targets. "
       "For non-DLL platforms shared libraries are treated as library "
-      "targets. "
+      "targets, except that those marked with the FRAMEWORK property "
+      "are treated as framework targets on OS X.  "
       "For DLL platforms the DLL part of a shared library is treated as "
       "a runtime target and the corresponding import library is treated as "
       "an archive target. "
       "All Windows-based systems including Cygwin are DLL platforms. "
-      "The ARCHIVE, LIBRARY, and RUNTIME "
+      "The ARCHIVE, LIBRARY, RUNTIME, and FRAMEWORK "
       "arguments change the type of target to which the subsequent "
       "properties "
       "apply.  If none is given the installation properties apply to "
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index 8a56329..ae16288 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -222,8 +222,7 @@ cmInstallTargetGenerator
       // An import library looks like a static library.
       type = cmTarget::STATIC_LIBRARY;
       }
-    else if(this->Target->GetMakefile()->IsOn("APPLE") &&
-            this->Target->GetPropertyAsBool("FRAMEWORK"))
+    else if(this->Target->IsFrameworkOnApple())
       {
       // Compute the build tree location of the framework directory
       std::string from1 = fromDirConfig;
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index 40bbdf2..9ab4649 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -111,13 +111,11 @@ void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules()
 //----------------------------------------------------------------------------
 void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink)
 {
-#ifdef __APPLE__
-  if (this->Target->GetPropertyAsBool("FRAMEWORK"))
+  if(this->Target->IsFrameworkOnApple())
     {
     this->WriteFrameworkRules(relink);
     return;
     }
-#endif
   const char* linkLanguage =
     this->Target->GetLinkerLanguage(this->GlobalGenerator);
   std::string linkRuleVar = "CMAKE_";
@@ -479,14 +477,13 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
       outpathImp += "/";
       }
     }
-#if defined(__APPLE__)
+
   // If we're creating a framework, place the output into a framework directory
-  if (this->Target->GetType() == cmTarget::SHARED_LIBRARY &&
-      this->Target->GetPropertyAsBool("FRAMEWORK"))
+  if(this->Target->IsFrameworkOnApple())
     {
     this->CreateFramework(targetName, outpath);
     }
-#endif
+
   std::string targetFullPath = outpath + targetName;
   std::string targetFullPathPDB = outpath + targetNamePDB;
   std::string targetFullPathSO = outpath + targetNameSO;
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 0fb6f7b..39b8a4e 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -125,7 +125,7 @@ void cmTarget::DefineProperties(cmake *cm)
   cm->DefineProperty
     ("FRAMEWORK", cmProperty::TARGET,
      "This target is a framework on the Mac.",
-     "Is set to true then if this target is a shared library, it will "
+     "If a shared library target has this property set to true it will "
      "be built as a framework when built on the mac. It will have the "
      "directory structure required for a framework and will be suitable "
      "to be used with the -framework option");
@@ -172,14 +172,6 @@ void cmTarget::DefineProperties(cmake *cm)
      "Ignored for non-imported targets.");
 
   cm->DefineProperty
-    ("IMPORTED_ENABLE_EXPORTS", cmProperty::TARGET,
-     "Enable linking to an IMPORTED executable target.",
-     "Indicates that an IMPORTED executable target exports symbols for "
-     "use by plugin modules.  "
-     "This is the imported target equivalent of the ENABLE_EXPORTS "
-     "property.");
-
-  cm->DefineProperty
     ("IMPORTED_IMPLIB", cmProperty::TARGET,
      "Full path to the import library for an IMPORTED target.",
      "Specifies the location of the \".lib\" part of a windows DLL.  "
@@ -217,6 +209,8 @@ void cmTarget::DefineProperties(cmake *cm)
      "library or module.  "
      "For shared libraries on non-DLL platforms this is the location of "
      "the shared library.  "
+     "For frameworks on OS X this is the location of the library file "
+     "symlink just inside the framework folder.  "
      "For DLLs this is the location of the \".dll\" part of the library.  "
      "Ignored for non-imported targets.");
 
@@ -599,20 +593,16 @@ void cmTarget::SetMakefile(cmMakefile* mf)
 //----------------------------------------------------------------------------
 bool cmTarget::IsExecutableWithExports()
 {
-  if(this->GetType() == cmTarget::EXECUTABLE)
-    {
-    if(this->IsImported())
-      {
-      // The "IMPORTED_" namespace is used for properties exported
-      // from the project providing imported targets.
-      return this->GetPropertyAsBool("IMPORTED_ENABLE_EXPORTS");
-      }
-    else
-      {
-      return this->GetPropertyAsBool("ENABLE_EXPORTS");
-      }
-    }
-  return false;
+  return (this->GetType() == cmTarget::EXECUTABLE &&
+          this->GetPropertyAsBool("ENABLE_EXPORTS"));
+}
+
+//----------------------------------------------------------------------------
+bool cmTarget::IsFrameworkOnApple()
+{
+  return (this->GetType() == cmTarget::SHARED_LIBRARY &&
+          this->Makefile->IsOn("APPLE") &&
+          this->GetPropertyAsBool("FRAMEWORK"));
 }
 
 //----------------------------------------------------------------------------
@@ -2090,15 +2080,13 @@ void cmTarget::GetFullNameInternal(TargetType type,
     {
     targetSuffix = this->Makefile->GetSafeDefinition(suffixVar);
     }
-#if defined(__APPLE__)
+
   // frameworks do not have a prefix or a suffix
-  if (this->GetType() == cmTarget::SHARED_LIBRARY &&
-      this->GetPropertyAsBool("FRAMEWORK"))
+  if(this->IsFrameworkOnApple())
     {
     targetPrefix = 0;
     targetSuffix = 0;
     }
-#endif
 
   // Begin the final name with the prefix.
   outPrefix = targetPrefix?targetPrefix:"";
@@ -2715,16 +2703,12 @@ const char* cmTarget::GetAndCreateOutputDir(bool implib, bool create)
       cmSystemTools::CollapseFullPath
       (out.c_str(), this->Makefile->GetStartOutputDirectory());
 
-#if defined(__APPLE__)
-    // frameworks do not have a prefix or a suffix
-    if (this->GetType() == cmTarget::SHARED_LIBRARY &&
-        this->GetPropertyAsBool("FRAMEWORK"))
+    if(this->IsFrameworkOnApple())
       {
       out += "/";
       out += this->GetFullName(0, implib);
       out += ".framework";
       }
-#endif
 
     // Optionally make sure the output path exists on disk.
     if(create)
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index b983629..45359bb 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -320,6 +320,10 @@ public:
       enabled.  */
   bool IsExecutableWithExports();
 
+  /** Return whether this target is a shared library Framework on
+      Apple.  */
+  bool IsFrameworkOnApple();
+
 private:
   /**
    * A list of direct dependencies. Use in conjunction with DependencyMap.
-- 
cgit v0.12