Browse Source

ENH: Support exporting/importing of AppBundle targets.

  - Imported bundles have the MACOSX_BUNDLE property set
  - Added cmTarget::IsAppBundleOnApple method to simplify checks
  - Document BUNDLE keyword in INSTALL command
  - Updated IMPORTED_LOCATION property documentation for bundles
  - Updated ExportImport test to test bundles
Brad King 18 years ago
parent
commit
e3b1bdb058

+ 5 - 0
Source/cmExportBuildFileGenerator.cxx

@@ -84,6 +84,11 @@ cmExportBuildFileGenerator
   std::string prop = "IMPORTED_LOCATION";
   prop += suffix;
   std::string value = target->GetFullPath(config, false);
+  if(target->IsAppBundleOnApple())
+    {
+    value += ".app/Contents/MacOS/";
+    value += target->GetFullName(config, false);
+    }
   properties[prop] = value;
   }
 

+ 9 - 4
Source/cmExportFileGenerator.cxx

@@ -282,14 +282,19 @@ cmExportFileGenerator
        << " 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"))
+  // Mark the imported library if it is a framework.
+  if(target->IsFrameworkOnApple())
     {
     os << "SET_PROPERTY(TARGET " << targetName
        << " PROPERTY FRAMEWORK 1)\n";
     }
+
+  // Mark the imported executable if it is an application bundle.
+  if(target->IsAppBundleOnApple())
+    {
+    os << "SET_PROPERTY(TARGET " << targetName
+       << " PROPERTY MACOSX_BUNDLE 1)\n";
+    }
   os << "\n";
 }
 

+ 8 - 3
Source/cmExportInstallFileGenerator.cxx

@@ -160,8 +160,8 @@ cmExportInstallFileGenerator
                                     te->RuntimeGenerator, properties);
     this->SetImportLocationProperty(config, suffix,
                                     te->FrameworkGenerator, properties);
-
-    // TODO: Bundles?
+    this->SetImportLocationProperty(config, suffix,
+                                    te->BundleGenerator, properties);
 
     // If any file location was set for the target add it to the
     // import file.
@@ -227,12 +227,17 @@ cmExportInstallFileGenerator
   std::string fname = itgen->GetInstallFilename(config);
   value += fname;
 
-  // Fix name for frameworks.
+  // Fix name for frameworks and bundles.
   if(itgen->GetTarget()->IsFrameworkOnApple())
     {
     value += ".framework/";
     value += fname;
     }
+  else if(itgen->GetTarget()->IsAppBundleOnApple())
+    {
+    value += ".app/Contents/MacOS/";
+    value += fname;
+    }
 
   // Store the property.
   properties[prop] = value;

+ 3 - 2
Source/cmInstallCommand.cxx

@@ -451,9 +451,9 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
         break;
       case cmTarget::EXECUTABLE:
         {
-        // Executables use the RUNTIME properties.
-        if(target.GetPropertyAsBool("MACOSX_BUNDLE"))
+        if(target.IsAppBundleOnApple())
           {
+          // Application bundles use the BUNDLE properties.
           if (!bundleArgs.GetDestination().empty())
             {
             bundleGenerator = CreateInstallTargetGenerator(target, bundleArgs, 
@@ -470,6 +470,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
           }
         else
           {
+          // Executables use the RUNTIME properties.
           if (!runtimeArgs.GetDestination().empty())
             {
             runtimeGenerator = CreateInstallTargetGenerator(target, 

+ 6 - 4
Source/cmInstallCommand.h

@@ -99,7 +99,7 @@ public:
       "\n"
       "The TARGETS signature:\n"
       "  install(TARGETS targets... [EXPORT <export-name>]\n"
-      "          [[ARCHIVE|LIBRARY|RUNTIME|FRAMEWORK]\n"
+      "          [[ARCHIVE|LIBRARY|RUNTIME|FRAMEWORK|BUNDLE]\n"
       "           [DESTINATION <dir>]\n"
       "           [PERMISSIONS permissions...]\n"
       "           [CONFIGURATIONS [Debug|Release|...]]\n"
@@ -107,10 +107,12 @@ public:
       "           [OPTIONAL]\n"
       "          ] [...])\n"
       "The TARGETS form specifies rules for installing targets from a "
-      "project.  There are four kinds of target files that may be "
-      "installed: archive, library, runtime, and framework.  "
+      "project.  There are five kinds of target files that may be "
+      "installed: archive, library, runtime, framework, and bundle.  "
 
-      "Executables are always treated as runtime targets. "
+      "Executables are treated as runtime targets, except that those "
+      "marked with the MACOSX_BUNDLE property are treated as bundle "
+      "targets on OS X. "
       "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 "

+ 1 - 2
Source/cmInstallTargetGenerator.cxx

@@ -176,8 +176,7 @@ cmInstallTargetGenerator
       from1 += targetName;
 
       // Handle OSX Bundles.
-      if(this->Target->GetMakefile()->IsOn("APPLE") &&
-         this->Target->GetPropertyAsBool("MACOSX_BUNDLE"))
+      if(this->Target->IsAppBundleOnApple())
         {
         // Compute the source locations of the bundle executable and
         // Info.plist file.

+ 10 - 0
Source/cmTarget.cxx

@@ -205,6 +205,8 @@ void cmTarget::DefineProperties(cmake *cm)
      "Full path to the main file on disk for an IMPORTED target.",
      "Specifies the location of an IMPORTED target file on disk.  "
      "For executables this is the location of the executable file.  "
+     "For bundles on OS X this is the location of the executable file "
+     "inside Contents/MacOS under the application bundle folder.  "
      "For static libraries and modules this is the location of the "
      "library or module.  "
      "For shared libraries on non-DLL platforms this is the location of "
@@ -605,6 +607,14 @@ bool cmTarget::IsFrameworkOnApple()
           this->GetPropertyAsBool("FRAMEWORK"));
 }
 
+//----------------------------------------------------------------------------
+bool cmTarget::IsAppBundleOnApple()
+{
+  return (this->GetType() == cmTarget::EXECUTABLE &&
+          this->Makefile->IsOn("APPLE") &&
+          this->GetPropertyAsBool("MACOSX_BUNDLE"));
+}
+
 //----------------------------------------------------------------------------
 class cmTargetTraceDependencies
 {

+ 3 - 0
Source/cmTarget.h

@@ -324,6 +324,9 @@ public:
       Apple.  */
   bool IsFrameworkOnApple();
 
+  /** Return whether this target is an executable Bundle on Apple.  */
+  bool IsAppBundleOnApple();
+
 private:
   /**
    * A list of direct dependencies. Use in conjunction with DependencyMap.

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

@@ -21,14 +21,18 @@ add_library(testLib3 SHARED testLib3.c)
 add_library(testLib4 SHARED testLib4.c)
 set_property(TARGET testLib4 PROPERTY FRAMEWORK 1)
 
+add_executable(testExe3 testExe3.c)
+set_property(TARGET testExe3 PROPERTY MACOSX_BUNDLE 1)
+
 # Install and export from install tree.
 install(
-  TARGETS testExe1 testLib1 testLib2 testExe2 testLib3 testLib4
+  TARGETS testExe1 testLib1 testLib2 testExe2 testLib3 testLib4 testExe3
   EXPORT exp
   RUNTIME DESTINATION bin
   LIBRARY DESTINATION lib
   ARCHIVE DESTINATION lib
   FRAMEWORK DESTINATION Frameworks
+  BUNDLE DESTINATION Applications
   )
 install(EXPORT exp NAMESPACE exp_ DESTINATION lib/exp)
 
@@ -37,7 +41,7 @@ export(TARGETS testExe1 testLib1 testLib2
   NAMESPACE bld_
   FILE ExportBuildTree.cmake
   )
-export(TARGETS testExe2 testLib3 testLib4
+export(TARGETS testExe2 testLib3 testLib4 testExe3
   NAMESPACE bld_
   APPEND FILE ExportBuildTree.cmake
   )

+ 24 - 0
Tests/ExportImport/Export/testExe3.c

@@ -0,0 +1,24 @@
+#include <stdio.h>
+
+int main(int argc, const char* argv[])
+{
+  if(argc < 2)
+    {
+    fprintf(stderr, "Must specify output file.\n");
+    return 1;
+    }
+  {
+  FILE* f = fopen(argv[1], "w");
+  if(f)
+    {
+    fprintf(f, "int generated_by_testExe3() { return 0; }\n");
+    fclose(f);
+    }
+  else
+    {
+    fprintf(stderr, "Error writing to %s\n", argv[1]);
+    return 1;
+    }
+  }
+  return 0;
+}

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

@@ -17,10 +17,16 @@ add_custom_command(
   COMMAND exp_testExe1 ${Import_BINARY_DIR}/exp_generated.c
   DEPENDS exp_testExe1
   )
+add_custom_command(
+  OUTPUT ${Import_BINARY_DIR}/exp_generated3.c
+  COMMAND exp_testExe3 ${Import_BINARY_DIR}/exp_generated3.c
+  DEPENDS exp_testExe3
+  )
 
 add_executable(imp_testExe1
   imp_testExe1.c
   ${Import_BINARY_DIR}/exp_generated.c
+  ${Import_BINARY_DIR}/exp_generated3.c
   )
 
 # Try linking to a library imported from the install tree.
@@ -36,10 +42,16 @@ add_custom_command(
   COMMAND bld_testExe1 ${Import_BINARY_DIR}/bld_generated.c
   DEPENDS bld_testExe1
   )
+add_custom_command(
+  OUTPUT ${Import_BINARY_DIR}/bld_generated3.c
+  COMMAND bld_testExe3 ${Import_BINARY_DIR}/bld_generated3.c
+  DEPENDS bld_testExe3
+  )
 
 add_executable(imp_testExe1b
   imp_testExe1.c
   ${Import_BINARY_DIR}/bld_generated.c
+  ${Import_BINARY_DIR}/bld_generated3.c
   )
 
 # Try linking to a library imported from the build tree.

+ 3 - 1
Tests/ExportImport/Import/imp_testExe1.c

@@ -1,9 +1,11 @@
 extern int generated_by_testExe1();
+extern int generated_by_testExe3();
 extern int testLib2();
 extern int testLib3();
 extern int testLib4();
 
 int main()
 {
-  return testLib2() + generated_by_testExe1() + testLib3() + testLib4();
+  return (testLib2() + generated_by_testExe1() + testLib3() + testLib4()
+          + generated_by_testExe3());
 }