CPack: Add support for code signing of bundles on MacOS

This commit is contained in:
André Klitzing 2014-10-28 19:15:55 +01:00 committed by Clinton Stimpson
parent fddb3ca443
commit bd3fbf36b4
3 changed files with 152 additions and 1 deletions

View File

@ -33,6 +33,31 @@
# Path to a startup script. This is a path to an executable or script that
# will be run whenever an end-user double-clicks the generated bundle in the
# OSX Finder. Optional.
#
# .. variable:: CPACK_BUNDLE_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_BUNDLE_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_BUNDLE_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_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-2009 Kitware, Inc.

View File

@ -39,6 +39,21 @@ int cmCPackBundleGenerator::InitializeInternal()
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();
}
@ -53,7 +68,7 @@ const char* cmCPackBundleGenerator::GetPackagingInstallPrefix()
}
//----------------------------------------------------------------------
int cmCPackBundleGenerator::PackageFiles()
int cmCPackBundleGenerator::ConstructBundle()
{
// Get required arguments ...
@ -165,6 +180,22 @@ int cmCPackBundleGenerator::PackageFiles()
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]);
}
@ -172,3 +203,96 @@ 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 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_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)
{
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_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))
{
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_BUNDLE_APPLE_ENTITLEMENTS")
? "with entitlement sandboxing" : "without entitlement sandboxing")
<< std::endl);
}
return 1;
}

View File

@ -31,6 +31,8 @@ public:
protected:
virtual int InitializeInternal();
virtual const char* GetPackagingInstallPrefix();
int ConstructBundle();
int SignBundle(const std::string& src_dir);
int PackageFiles();
bool SupportsComponentInstallation() const;