summaryrefslogtreecommitdiffstats
path: root/Source/CPack/cmCPackBundleGenerator.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/CPack/cmCPackBundleGenerator.cxx')
-rw-r--r--Source/CPack/cmCPackBundleGenerator.cxx292
1 files changed, 292 insertions, 0 deletions
diff --git a/Source/CPack/cmCPackBundleGenerator.cxx b/Source/CPack/cmCPackBundleGenerator.cxx
new file mode 100644
index 0000000..9276e3a
--- /dev/null
+++ b/Source/CPack/cmCPackBundleGenerator.cxx
@@ -0,0 +1,292 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+
+#include "cmCPackBundleGenerator.h"
+
+#include "cmCPackLog.h"
+#include "cmSystemTools.h"
+
+#include <cmsys/RegularExpression.hxx>
+
+cmCPackBundleGenerator::cmCPackBundleGenerator()
+{
+}
+
+cmCPackBundleGenerator::~cmCPackBundleGenerator()
+{
+}
+
+int cmCPackBundleGenerator::InitializeInternal()
+{
+ const char* name = this->GetOption("CPACK_BUNDLE_NAME");
+ if (0 == name) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "CPACK_BUNDLE_NAME must be set to use the Bundle generator."
+ << std::endl);
+
+ return 0;
+ }
+
+ if (this->GetOption("CPACK_BUNDLE_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();
+}
+
+const char* cmCPackBundleGenerator::GetPackagingInstallPrefix()
+{
+ this->InstallPrefix = "/";
+ this->InstallPrefix += this->GetOption("CPACK_BUNDLE_NAME");
+ this->InstallPrefix += ".app/Contents/Resources";
+
+ return this->InstallPrefix.c_str();
+}
+
+int cmCPackBundleGenerator::ConstructBundle()
+{
+
+ // Get required arguments ...
+ const std::string cpack_bundle_name = this->GetOption("CPACK_BUNDLE_NAME")
+ ? this->GetOption("CPACK_BUNDLE_NAME")
+ : "";
+ if (cpack_bundle_name.empty()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_BUNDLE_NAME must be set."
+ << std::endl);
+
+ return 0;
+ }
+
+ const std::string cpack_bundle_plist = this->GetOption("CPACK_BUNDLE_PLIST")
+ ? this->GetOption("CPACK_BUNDLE_PLIST")
+ : "";
+ if (cpack_bundle_plist.empty()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_BUNDLE_PLIST must be set."
+ << std::endl);
+
+ return 0;
+ }
+
+ const std::string cpack_bundle_icon = this->GetOption("CPACK_BUNDLE_ICON")
+ ? this->GetOption("CPACK_BUNDLE_ICON")
+ : "";
+ if (cpack_bundle_icon.empty()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_BUNDLE_ICON must be set."
+ << std::endl);
+
+ return 0;
+ }
+
+ // Get optional arguments ...
+ const std::string cpack_bundle_startup_command =
+ this->GetOption("CPACK_BUNDLE_STARTUP_COMMAND")
+ ? this->GetOption("CPACK_BUNDLE_STARTUP_COMMAND")
+ : "";
+
+ // The staging directory contains everything that will end-up inside the
+ // final disk image ...
+ std::ostringstream staging;
+ staging << toplevel;
+
+ std::ostringstream contents;
+ contents << staging.str() << "/" << cpack_bundle_name << ".app/"
+ << "Contents";
+
+ std::ostringstream application;
+ application << contents.str() << "/"
+ << "MacOS";
+
+ std::ostringstream resources;
+ resources << contents.str() << "/"
+ << "Resources";
+
+ // Install a required, user-provided bundle metadata file ...
+ std::ostringstream plist_source;
+ plist_source << cpack_bundle_plist;
+
+ std::ostringstream plist_target;
+ plist_target << contents.str() << "/"
+ << "Info.plist";
+
+ if (!this->CopyFile(plist_source, plist_target)) {
+ cmCPackLogger(
+ cmCPackLog::LOG_ERROR,
+ "Error copying plist. Check the value of CPACK_BUNDLE_PLIST."
+ << std::endl);
+
+ return 0;
+ }
+
+ // Install a user-provided bundle icon ...
+ std::ostringstream icon_source;
+ icon_source << cpack_bundle_icon;
+
+ std::ostringstream icon_target;
+ icon_target << resources.str() << "/" << cpack_bundle_name << ".icns";
+
+ if (!this->CopyFile(icon_source, icon_target)) {
+ cmCPackLogger(
+ cmCPackLog::LOG_ERROR,
+ "Error copying bundle icon. Check the value of CPACK_BUNDLE_ICON."
+ << std::endl);
+
+ return 0;
+ }
+
+ // Optionally a user-provided startup command (could be an
+ // executable or a script) ...
+ if (!cpack_bundle_startup_command.empty()) {
+ std::ostringstream command_source;
+ command_source << cpack_bundle_startup_command;
+
+ std::ostringstream command_target;
+ command_target << application.str() << "/" << cpack_bundle_name;
+
+ if (!this->CopyFile(command_source, command_target)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error copying startup command. "
+ " Check the value of CPACK_BUNDLE_STARTUP_COMMAND."
+ << std::endl);
+
+ return 0;
+ }
+
+ cmSystemTools::SetPermissions(command_target.str().c_str(), 0777);
+ }
+
+ return 1;
+}
+
+int cmCPackBundleGenerator::PackageFiles()
+{
+ if (!this->ConstructBundle()) {
+ return 0;
+ }
+
+ if (!this->SignBundle(toplevel)) {
+ return 0;
+ }
+
+ return this->CreateDMG(toplevel, packageFileNames[0]);
+}
+
+bool cmCPackBundleGenerator::SupportsComponentInstallation() const
+{
+ return false;
+}
+
+int cmCPackBundleGenerator::SignBundle(const std::string& src_dir)
+{
+ const std::string cpack_apple_cert_app =
+ this->GetOption("CPACK_BUNDLE_APPLE_CERT_APP")
+ ? this->GetOption("CPACK_BUNDLE_APPLE_CERT_APP")
+ : "";
+
+ // codesign the application.
+ if (!cpack_apple_cert_app.empty()) {
+ std::string output;
+ 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_parameter =
+ this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_PARAMETER")
+ ? this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_PARAMETER")
+ : "--deep -f";
+
+ const std::string sign_files =
+ this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_FILES")
+ ? this->GetOption("CPACK_BUNDLE_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) {
+ std::ostringstream temp_sign_file_cmd;
+ temp_sign_file_cmd << this->GetOption("CPACK_COMMAND_CODESIGN");
+ temp_sign_file_cmd << " " << sign_parameter << " -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 << "\"";
+
+ if (!this->RunCommand(temp_sign_file_cmd, &output)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error signing file:" << bundle_path << *it << std::endl
+ << output << std::endl);
+
+ return 0;
+ }
+ }
+
+ // sign main binary
+ std::ostringstream temp_sign_binary_cmd;
+ temp_sign_binary_cmd << this->GetOption("CPACK_COMMAND_CODESIGN");
+ temp_sign_binary_cmd << " " << sign_parameter << " -s \""
+ << cpack_apple_cert_app;
+ temp_sign_binary_cmd << "\" \"" << bundle_path << "\"";
+
+ if (!this->RunCommand(temp_sign_binary_cmd, &output)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error signing the application binary." << std::endl
+ << output
+ << std::endl);
+
+ return 0;
+ }
+
+ // sign app bundle
+ std::ostringstream temp_codesign_cmd;
+ temp_codesign_cmd << this->GetOption("CPACK_COMMAND_CODESIGN");
+ temp_codesign_cmd << " " << sign_parameter << " -s \""
+ << cpack_apple_cert_app << "\"";
+ if (this->GetOption("CPACK_BUNDLE_APPLE_ENTITLEMENTS")) {
+ temp_codesign_cmd << " --entitlements ";
+ temp_codesign_cmd << this->GetOption("CPACK_BUNDLE_APPLE_ENTITLEMENTS");
+ }
+ temp_codesign_cmd << " \"" << bundle_path << "\"";
+
+ if (!this->RunCommand(temp_codesign_cmd, &output)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error signing the application package." << std::endl
+ << output
+ << std::endl);
+
+ return 0;
+ }
+
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Application has been codesigned"
+ << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ (this->GetOption("CPACK_BUNDLE_APPLE_ENTITLEMENTS")
+ ? "with entitlement sandboxing"
+ : "without entitlement sandboxing")
+ << std::endl);
+ }
+
+ return 1;
+}