>
> It should not be an error for 'codesign' to not be available
> in the PATH.  The user may have set CPACK_COMMAND_CODESIGN
> to some other location.  The error should only occur if no
> value for CPACK_COMMAND_CODESIGN is available when the tool
> is actually needed for signing.
>

I attached another patch that will fix the broken tests. It will check for
defined CPACK_APPLE_CERT_APP before it will search for 'codesign'.

Well, the FindProgram line for codesign looks like the line for Rez,
hdiutil, SetFile and so on. I don't know cmake sources enough... but
shouldn't it be the same here?


André
From 5f2e6a0b2d6253515a5696b283976414dc72eb85 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Klitzing?= <aklitz...@gmail.com>
Date: Mon, 29 Sep 2014 12:05:59 +0200
Subject: [PATCH] CPack: Add support for code signing of bundles on MacOS

---
 Modules/CPackDMG.cmake                     |  24 +++++++
 Source/CPack/cmCPackBundleGenerator.cxx    |  18 ++++-
 Source/CPack/cmCPackBundleGenerator.h      |   1 +
 Source/CPack/cmCPackDragNDropGenerator.cxx | 107 +++++++++++++++++++++++++++++
 Source/CPack/cmCPackDragNDropGenerator.h   |   1 +
 5 files changed, 150 insertions(+), 1 deletion(-)

diff --git a/Modules/CPackDMG.cmake b/Modules/CPackDMG.cmake
index b7a6ba5..fb9fe39 100644
--- a/Modules/CPackDMG.cmake
+++ b/Modules/CPackDMG.cmake
@@ -36,6 +36,23 @@
 #  background image is set. The background image is applied after applying the
 #  custom .DS_Store file.
 #
+#
+#
+# .. variable:: CPACK_APPLE_CERT_APP
+#  The name of your Apple supplied code signing certificate for the application.
+#  The name usually takes the form "Developer ID Application: [Name]" or
+#  "3rd Party Mac Developer Application: [Name]". If this variable is not set
+#  the application will not be signed.
+#
+# .. variable:: CPACK_APPLE_ENTITLEMENTS
+#  The name of the plist file that contains your apple entitlements for sandboxing
+#  your application. This file is required for submission to the Mac App Store.
+#
+# .. variable:: CPACK_APPLE_CODESIGN_FILES
+#  A list of additional files that you wish to be signed. You do not need to
+#  list the main application folder, or the main executable. You should
+#  list any frameworks and plugins that are included in your app bundle.
+#
 # .. variable:: CPACK_COMMAND_HDIUTIL
 #
 #  Path to the hdiutil(1) command used to operate on disk image files on Mac
@@ -54,6 +71,13 @@
 #  Path to the Rez(1) command used to compile resources on Mac OS X. This
 #  variable can be used to override the automatically detected command (or
 #  specify its location if the auto-detection fails to find it.)
+#
+# .. variable:: CPACK_COMMAND_CODESIGN
+#  Path to the codesign(1) command used to sign applications with an
+#  Apple cert. This variable can be used to override the automatically
+#  detected command (or specify its location if the auto-detection fails
+#  to find it.)
+#
 
 #=============================================================================
 # Copyright 2006-2012 Kitware, Inc.
diff --git a/Source/CPack/cmCPackBundleGenerator.cxx b/Source/CPack/cmCPackBundleGenerator.cxx
index 6c994f1..c5f7139 100644
--- a/Source/CPack/cmCPackBundleGenerator.cxx
+++ b/Source/CPack/cmCPackBundleGenerator.cxx
@@ -53,7 +53,7 @@ const char* cmCPackBundleGenerator::GetPackagingInstallPrefix()
 }
 
 //----------------------------------------------------------------------
-int cmCPackBundleGenerator::PackageFiles()
+int cmCPackBundleGenerator::ConstructAppBundle()
 {
 
   // Get required arguments ...
@@ -165,6 +165,22 @@ int cmCPackBundleGenerator::PackageFiles()
     cmSystemTools::SetPermissions(command_target.str().c_str(), 0777);
     }
 
+  return 1;
+}
+
+//----------------------------------------------------------------------
+int cmCPackBundleGenerator::PackageFiles()
+{
+  if(!this->ConstructAppBundle())
+    {
+    return 0;
+    }
+
+  if(!this->SignPackage(toplevel))
+    {
+    return 0;
+    }
+
   return this->CreateDMG(toplevel, packageFileNames[0]);
 }
 
diff --git a/Source/CPack/cmCPackBundleGenerator.h b/Source/CPack/cmCPackBundleGenerator.h
index ed0187d..fa9f2fa 100644
--- a/Source/CPack/cmCPackBundleGenerator.h
+++ b/Source/CPack/cmCPackBundleGenerator.h
@@ -31,6 +31,7 @@ public:
 protected:
   virtual int InitializeInternal();
   virtual const char* GetPackagingInstallPrefix();
+  int ConstructAppBundle();
   int PackageFiles();
   bool SupportsComponentInstallation() const;
 
diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx
index 9f0a77e..4e7e9ca 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.cxx
+++ b/Source/CPack/cmCPackDragNDropGenerator.cxx
@@ -103,6 +103,21 @@ int cmCPackDragNDropGenerator::InitializeInternal()
     }
   this->SetOptionIfNotSet("CPACK_COMMAND_REZ", rez_path.c_str());
 
+  if(this->GetOption("CPACK_APPLE_CERT_APP"))
+    {
+    const std::string codesign_path = cmSystemTools::FindProgram("codesign",
+       std::vector<std::string>(), false);
+
+    if(codesign_path.empty())
+      {
+      cmCPackLogger(cmCPackLog::LOG_ERROR,
+        "Cannot locate codesign command"
+        << std::endl);
+      return 0;
+      }
+    this->SetOptionIfNotSet("CPACK_COMMAND_CODESIGN", codesign_path.c_str());
+    }
+
   return this->Superclass::InitializeInternal();
 }
 
@@ -216,6 +231,98 @@ bool cmCPackDragNDropGenerator::RunCommand(cmOStringStream& command,
   return true;
 }
 
+int cmCPackDragNDropGenerator::SignPackage(const std::string& src_dir)
+{
+  const std::string cpack_apple_cert_app =
+    this->GetOption("CPACK_APPLE_CERT_APP")
+    ? this->GetOption("CPACK_APPLE_CERT_APP") : "";
+
+  // codesign the application.
+  if(!cpack_apple_cert_app.empty())
+    {
+    std::string bundle_path;
+    bundle_path = src_dir + "/";
+    bundle_path += this->GetOption("CPACK_BUNDLE_NAME");
+    bundle_path += ".app";
+
+    // A list of additional files to sign, ie. frameworks and plugins.
+    const std::string sign_files =
+      this->GetOption("CPACK_APPLE_CODESIGN_FILES")
+      ? this->GetOption("CPACK_APPLE_CODESIGN_FILES") : "";
+
+    std::vector<std::string> relFiles;
+    cmSystemTools::ExpandListArgument(sign_files, relFiles);
+
+    // sign the files supplied by the user, ie. frameworks.
+    for(std::vector<std::string>::iterator it = relFiles.begin();
+      it != relFiles.end(); ++it)
+      {
+      cmOStringStream temp_sign_file_cmd;
+      temp_sign_file_cmd << this->GetOption("CPACK_COMMAND_CODESIGN");
+      temp_sign_file_cmd << " --deep -f -s \"" << cpack_apple_cert_app;
+      temp_sign_file_cmd << "\" -i ";
+      temp_sign_file_cmd << this->GetOption("CPACK_APPLE_BUNDLE_ID");
+      temp_sign_file_cmd << " \"";
+      temp_sign_file_cmd << bundle_path;
+      temp_sign_file_cmd << it->c_str() << "\"";
+
+      if(!this->RunCommand(temp_sign_file_cmd))
+        {
+        cmCPackLogger(cmCPackLog::LOG_ERROR,
+          "Error signing file:"
+          << bundle_path << it->c_str() << std::endl);
+
+        return 0;
+        }
+      }
+
+    // sign main binary
+    cmOStringStream temp_sign_binary_cmd;
+    temp_sign_binary_cmd << this->GetOption("CPACK_COMMAND_CODESIGN");
+    temp_sign_binary_cmd << " --deep -f -s \"" << cpack_apple_cert_app;
+    temp_sign_binary_cmd << "\" \"" << bundle_path << "\"";
+
+    if(!this->RunCommand(temp_sign_binary_cmd))
+      {
+      cmCPackLogger(cmCPackLog::LOG_ERROR,
+        "Error signing the application binary."
+        << std::endl);
+
+      return 0;
+      }
+
+    // sign app bundle
+    cmOStringStream temp_codesign_cmd;
+    temp_codesign_cmd << this->GetOption("CPACK_COMMAND_CODESIGN");
+    temp_codesign_cmd << " --deep -f -s \"" << cpack_apple_cert_app << "\"";
+    if(this->GetOption("CPACK_APPLE_ENTITLEMENTS"))
+      {
+      temp_codesign_cmd << " --entitlements ";
+      temp_codesign_cmd << this->GetOption("CPACK_APPLE_ENTITLEMENTS");
+      }
+    temp_codesign_cmd << " \"" << bundle_path << "\"";
+
+    if(!this->RunCommand(temp_codesign_cmd))
+      {
+      cmCPackLogger(cmCPackLog::LOG_ERROR,
+        "Error signing the application package."
+        << std::endl);
+
+      return 0;
+      }
+
+    cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+      "- Application has been codesigned"
+      << std::endl);
+    cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+       (this->GetOption("CPACK_APPLE_ENTITLEMENTS")
+         ? "with entitlement sandboxing" : "without entitlement sandboxing")
+       << std::endl);
+  }
+
+  return 1;
+}
+
 //----------------------------------------------------------------------
 int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
                                          const std::string& output_file)
diff --git a/Source/CPack/cmCPackDragNDropGenerator.h b/Source/CPack/cmCPackDragNDropGenerator.h
index 808c618..b852422 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.h
+++ b/Source/CPack/cmCPackDragNDropGenerator.h
@@ -39,6 +39,7 @@ protected:
   std::string
   GetComponentInstallDirNameSuffix(const std::string& componentName);
 
+  int SignPackage(const std::string& src_dir);
   int CreateDMG(const std::string& src_dir, const std::string& output_file);
 
   std::string InstallPrefix;
-- 
2.1.1

-- 

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: 
http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more 
information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at 
http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake-developers

Reply via email to