summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Help/manual/cmake-modules.7.rst1
-rw-r--r--Help/module/CPackProductBuild.rst1
-rw-r--r--Modules/CPack.cmake3
-rw-r--r--Modules/CPackProductBuild.cmake38
-rw-r--r--Source/CMakeLists.txt1
-rw-r--r--Source/CPack/cmCPackGeneratorFactory.cxx5
-rw-r--r--Source/CPack/cmCPackPKGGenerator.cxx1
-rw-r--r--Source/CPack/cmCPackPackageMakerGenerator.cxx2
-rw-r--r--Source/CPack/cmCPackProductBuildGenerator.cxx260
-rw-r--r--Source/CPack/cmCPackProductBuildGenerator.h60
-rw-r--r--Tests/CMakeLists.txt11
11 files changed, 382 insertions, 1 deletions
diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst
index 62910cf..f911662 100644
--- a/Help/manual/cmake-modules.7.rst
+++ b/Help/manual/cmake-modules.7.rst
@@ -60,6 +60,7 @@ All Modules
/module/CPackIFW
/module/CPackNSIS
/module/CPackPackageMaker
+ /module/CPackProductBuild
/module/CPackRPM
/module/CPack
/module/CPackWIX
diff --git a/Help/module/CPackProductBuild.rst b/Help/module/CPackProductBuild.rst
new file mode 100644
index 0000000..6081fe4
--- /dev/null
+++ b/Help/module/CPackProductBuild.rst
@@ -0,0 +1 @@
+.. cmake-module:: ../../Modules/CPackProductBuild.cmake
diff --git a/Modules/CPack.cmake b/Modules/CPack.cmake
index 77f854d..4d51a3e 100644
--- a/Modules/CPack.cmake
+++ b/Modules/CPack.cmake
@@ -455,6 +455,7 @@ if(NOT CPACK_GENERATOR)
option(CPACK_BINARY_DRAGNDROP "Enable to build OSX Drag And Drop package" OFF)
option(CPACK_BINARY_OSXX11 "Enable to build OSX X11 packages" OFF)
option(CPACK_BINARY_PACKAGEMAKER "Enable to build PackageMaker packages" OFF)
+ option(CPACK_BINARY_PRODUCTBUILD "Enable to build productbuild packages" OFF)
else()
option(CPACK_BINARY_TZ "Enable to build TZ packages" ON)
endif()
@@ -483,6 +484,7 @@ if(NOT CPACK_GENERATOR)
cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_NSIS NSIS)
cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_OSXX11 OSXX11)
cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_PACKAGEMAKER PackageMaker)
+ cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_PRODUCTBUILD productbuild)
cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_RPM RPM)
cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_STGZ STGZ)
cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_TBZ2 TBZ2)
@@ -531,6 +533,7 @@ mark_as_advanced(
CPACK_BINARY_NSIS
CPACK_BINARY_OSXX11
CPACK_BINARY_PACKAGEMAKER
+ CPACK_BINARY_PRODUCTBUILD
CPACK_BINARY_RPM
CPACK_BINARY_STGZ
CPACK_BINARY_TBZ2
diff --git a/Modules/CPackProductBuild.cmake b/Modules/CPackProductBuild.cmake
new file mode 100644
index 0000000..6545a3a
--- /dev/null
+++ b/Modules/CPackProductBuild.cmake
@@ -0,0 +1,38 @@
+#.rst:
+# CPackProductBuild
+# -----------------
+#
+# productbuild CPack generator (Mac OS X).
+#
+# Variables specific to CPack productbuild generator
+# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#
+# The following variable is specific to installers built on Mac
+# OS X using productbuild:
+#
+# .. variable:: CPACK_COMMAND_PRODUCTBUILD
+#
+# Path to the productbuild(1) command used to generate a product archive for
+# the OS X Installer or Mac App Store. 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_PKGBUILD
+#
+# Path to the pkgbuild(1) command used to generate an OS X component package
+# on 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.)
+#
+
+#=============================================================================
+# Copyright 2006-2012 Kitware, Inc.
+#
+# 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.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+# License text for the above reference.)
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index f85f143..7cf11ca 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -719,6 +719,7 @@ if(APPLE)
CPack/cmCPackOSXX11Generator.cxx
CPack/cmCPackPKGGenerator.cxx
CPack/cmCPackPackageMakerGenerator.cxx
+ CPack/cmCPackProductBuildGenerator.cxx
)
endif()
diff --git a/Source/CPack/cmCPackGeneratorFactory.cxx b/Source/CPack/cmCPackGeneratorFactory.cxx
index b17f52e..cf072bb 100644
--- a/Source/CPack/cmCPackGeneratorFactory.cxx
+++ b/Source/CPack/cmCPackGeneratorFactory.cxx
@@ -28,6 +28,7 @@
#include "cmCPackDragNDropGenerator.h"
#include "cmCPackOSXX11Generator.h"
#include "cmCPackPackageMakerGenerator.h"
+#include "cmCPackProductBuildGenerator.h"
#endif
#ifdef __CYGWIN__
@@ -122,6 +123,10 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory()
this->RegisterGenerator("OSXX11", "Mac OSX X11 bundle",
cmCPackOSXX11Generator::CreateGenerator);
}
+ if (cmCPackProductBuildGenerator::CanGenerate()) {
+ this->RegisterGenerator("productbuild", "Mac OSX pkg",
+ cmCPackProductBuildGenerator::CreateGenerator);
+ }
#endif
#if !defined(_WIN32) && !defined(__QNXNTO__) && !defined(__BEOS__) && \
!defined(__HAIKU__)
diff --git a/Source/CPack/cmCPackPKGGenerator.cxx b/Source/CPack/cmCPackPKGGenerator.cxx
index 8282714..ff0fa8c 100644
--- a/Source/CPack/cmCPackPKGGenerator.cxx
+++ b/Source/CPack/cmCPackPKGGenerator.cxx
@@ -41,7 +41,6 @@ int cmCPackPKGGenerator::InitializeInternal()
{
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"cmCPackPKGGenerator::Initialize()" << std::endl);
- this->SetOptionIfNotSet("CPACK_PACKAGING_INSTALL_PREFIX", "/usr");
return this->Superclass::InitializeInternal();
}
diff --git a/Source/CPack/cmCPackPackageMakerGenerator.cxx b/Source/CPack/cmCPackPackageMakerGenerator.cxx
index e50c2e6..5bb24c0 100644
--- a/Source/CPack/cmCPackPackageMakerGenerator.cxx
+++ b/Source/CPack/cmCPackPackageMakerGenerator.cxx
@@ -329,6 +329,8 @@ int cmCPackPackageMakerGenerator::PackageFiles()
int cmCPackPackageMakerGenerator::InitializeInternal()
{
+ this->SetOptionIfNotSet("CPACK_PACKAGING_INSTALL_PREFIX", "/usr");
+
// Starting with Xcode 4.3, PackageMaker is a separate app, and you
// can put it anywhere you want. So... use a variable for its location.
// People who put it in unexpected places can use the variable to tell
diff --git a/Source/CPack/cmCPackProductBuildGenerator.cxx b/Source/CPack/cmCPackProductBuildGenerator.cxx
new file mode 100644
index 0000000..c1f63cc
--- /dev/null
+++ b/Source/CPack/cmCPackProductBuildGenerator.cxx
@@ -0,0 +1,260 @@
+/*============================================================================
+ 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 "cmCPackProductBuildGenerator.h"
+
+#include "cmake.h"
+#include "cmGlobalGenerator.h"
+#include "cmLocalGenerator.h"
+#include "cmSystemTools.h"
+#include "cmMakefile.h"
+#include "cmGeneratedFileStream.h"
+#include "cmCPackComponentGroup.h"
+#include "cmCPackLog.h"
+
+#include <cmsys/SystemTools.hxx>
+#include <cmsys/Glob.hxx>
+
+cmCPackProductBuildGenerator::cmCPackProductBuildGenerator()
+{
+ this->componentPackageMethod = ONE_PACKAGE;
+}
+
+cmCPackProductBuildGenerator::~cmCPackProductBuildGenerator()
+{
+}
+
+int cmCPackProductBuildGenerator::PackageFiles()
+{
+ // TODO: Use toplevel
+ // It is used! Is this an obsolete comment?
+
+ std::string packageDirFileName
+ = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
+
+ // Create the directory where component packages will be built.
+ std::string basePackageDir = packageDirFileName;
+ basePackageDir += "/Contents/Packages";
+ if (!cmsys::SystemTools::MakeDirectory(basePackageDir.c_str()))
+ {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem creating component packages directory: "
+ << basePackageDir.c_str() << std::endl);
+ return 0;
+ }
+
+ if (!this->Components.empty())
+ {
+ std::map<std::string, cmCPackComponent>::iterator compIt;
+ for (compIt = this->Components.begin(); compIt != this->Components.end();
+ ++compIt)
+ {
+ std::string packageDir = toplevel;
+ packageDir += '/';
+ packageDir += compIt->first;
+ if (!this->GenerateComponentPackage(basePackageDir,
+ GetPackageName(compIt->second),
+ packageDir,
+ &compIt->second))
+ {
+ return 0;
+ }
+ }
+ }
+ else
+ {
+ if(!this->GenerateComponentPackage(basePackageDir,
+ this->GetOption("CPACK_PACKAGE_NAME"),
+ toplevel, NULL))
+ {
+ return 0;
+ }
+ }
+
+ // Copy or create all of the resource files we need.
+ std::string resDir = packageDirFileName + "/Contents";
+ if ( !this->CopyCreateResourceFile("License", resDir.c_str())
+ || !this->CopyCreateResourceFile("ReadMe", resDir.c_str())
+ || !this->CopyCreateResourceFile("Welcome", resDir.c_str()))
+ {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem copying the resource files"
+ << std::endl);
+ return 0;
+ }
+
+ // combine package(s) into a distribution
+ WriteDistributionFile(packageDirFileName.c_str());
+ std::ostringstream pkgCmd;
+
+ std::string version = this->GetOption("CPACK_PACKAGE_VERSION");
+ std::string productbuild = this->GetOption("CPACK_COMMAND_PRODUCTBUILD");
+
+ pkgCmd << productbuild
+ << " --distribution \"" << packageDirFileName
+ << "/Contents/distribution.dist\""
+ << " --package-path \"" << packageDirFileName << "/Contents/Packages" << "\""
+ << " --resources \"" << resDir << "\""
+ << " --version \"" << version << "\""
+ << " \"" << packageFileNames[0] << "\"";
+
+ // Run ProductBuild
+ return RunProductBuild(pkgCmd.str());
+}
+
+int cmCPackProductBuildGenerator::InitializeInternal()
+{
+ this->SetOptionIfNotSet("CPACK_PACKAGING_INSTALL_PREFIX", "/Applications");
+
+ std::vector<std::string> no_paths;
+ std::string program =
+ cmSystemTools::FindProgram("pkgbuild", no_paths, false);
+ if (program.empty()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find pkgbuild executable"
+ << std::endl);
+ return 0;
+ }
+ this->SetOptionIfNotSet("CPACK_COMMAND_PKGBUILD", program.c_str());
+
+
+ program = cmSystemTools::FindProgram("productbuild", no_paths, false);
+ if (program.empty()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find productbuild executable"
+ << std::endl);
+ return 0;
+ }
+ this->SetOptionIfNotSet("CPACK_COMMAND_PRODUCTBUILD", program.c_str());
+
+ return this->Superclass::InitializeInternal();
+}
+
+
+bool cmCPackProductBuildGenerator::RunProductBuild(
+ const std::string& command)
+{
+ std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
+ tmpFile += "/ProductBuildOutput.log";
+
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << command << std::endl);
+ std::string output, error_output;
+ int retVal = 1;
+ bool res = cmSystemTools::RunSingleCommand(command.c_str(),
+ &output, &error_output, &retVal, 0, this->GeneratorVerbose, 0);
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Done running command"
+ << std::endl);
+ if ( !res || retVal )
+ {
+ cmGeneratedFileStream ofs(tmpFile.c_str());
+ ofs << "# Run command: " << command << std::endl
+ << "# Output:" << std::endl
+ << output.c_str() << std::endl;
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem running command: " << command
+ << std::endl << "Please check " << tmpFile.c_str() << " for errors"
+ << std::endl);
+ return false;
+ }
+ return true;
+}
+
+bool cmCPackProductBuildGenerator::GenerateComponentPackage(
+ const std::string& packageFileDir,
+ const std::string& packageFileName,
+ const std::string& packageDir,
+ const cmCPackComponent* component)
+{
+ std::string packageFile = packageFileDir;
+ packageFile += '/';
+ packageFile += packageFileName;
+
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "- Building component package: " <<
+ packageFile << std::endl);
+
+ const char* comp_name = component ? component->Name.c_str() : NULL;
+
+ const char* preflight = this->GetComponentScript("PREFLIGHT", comp_name);
+ const char* postflight = this->GetComponentScript("POSTFLIGHT", comp_name);
+
+ std::string resDir = packageFileDir;
+ if(component)
+ {
+ resDir += "/";
+ resDir += component->Name;
+ }
+ std::string scriptDir = resDir + "/scripts";
+
+ if ( !cmsys::SystemTools::MakeDirectory(scriptDir.c_str()))
+ {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem creating installer directory: "
+ << scriptDir.c_str() << std::endl);
+ return 0;
+ }
+
+ // if preflight, postflight, or postupgrade are set
+ // then copy them into the script directory and make
+ // them executable
+ if(preflight)
+ {
+ this->CopyInstallScript(scriptDir.c_str(),
+ preflight,
+ "preinstall");
+ }
+ if(postflight)
+ {
+ this->CopyInstallScript(scriptDir.c_str(),
+ postflight,
+ "postinstall");
+ }
+
+
+ // The command that will be used to run ProductBuild
+ std::ostringstream pkgCmd;
+
+ std::string pkgId = "com.";
+ pkgId += this->GetOption("CPACK_PACKAGE_VENDOR");
+ pkgId += '.';
+ pkgId += this->GetOption("CPACK_PACKAGE_NAME");
+ if(component)
+ {
+ pkgId += '.';
+ pkgId += component->Name;
+ }
+
+ std::string version = this->GetOption("CPACK_PACKAGE_VERSION");
+ std::string pkgbuild = this->GetOption("CPACK_COMMAND_PKGBUILD");
+
+ pkgCmd << pkgbuild
+ << " --root \"" << packageDir << "\""
+ << " --identifier \"" << pkgId << "\""
+ << " --scripts \"" << scriptDir << "\""
+ << " --version \"" << version << "\""
+ << " --install-location \"/\""
+ << " \"" << packageFile << "\"";
+
+ // Run ProductBuild
+ return RunProductBuild(pkgCmd.str());
+}
+
+const char* cmCPackProductBuildGenerator::GetComponentScript(
+ const char* script,
+ const char* component_name)
+{
+ std::string scriptname = std::string("CPACK_") + script + "_";
+ if(component_name)
+ {
+ scriptname += cmSystemTools::UpperCase(component_name);
+ scriptname += "_";
+ }
+ scriptname += "SCRIPT";
+
+ return this->GetOption(scriptname);
+}
diff --git a/Source/CPack/cmCPackProductBuildGenerator.h b/Source/CPack/cmCPackProductBuildGenerator.h
new file mode 100644
index 0000000..0740f89
--- /dev/null
+++ b/Source/CPack/cmCPackProductBuildGenerator.h
@@ -0,0 +1,60 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2009 Kitware, Inc.
+
+ 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.
+============================================================================*/
+
+#ifndef cmCPackProductBuildGenerator_h
+#define cmCPackProductBuildGenerator_h
+
+
+#include "cmCPackPKGGenerator.h"
+
+class cmCPackComponent;
+
+/** \class cmCPackProductBuildGenerator
+ * \brief A generator for ProductBuild files
+ *
+ */
+class cmCPackProductBuildGenerator : public cmCPackPKGGenerator
+{
+public:
+ cmCPackTypeMacro(cmCPackProductBuildGenerator, cmCPackPKGGenerator);
+
+ /**
+ * Construct generator
+ */
+ cmCPackProductBuildGenerator();
+ virtual ~cmCPackProductBuildGenerator();
+
+protected:
+ virtual int InitializeInternal();
+ int PackageFiles();
+ virtual const char* GetOutputExtension() { return ".pkg"; }
+
+ // Run ProductBuild with the given command line, which will (if
+ // successful) produce the given package file. Returns true if
+ // ProductBuild succeeds, false otherwise.
+ bool RunProductBuild(const std::string& command);
+
+ // Generate a package in the file packageFile for the given
+ // component. All of the files within this component are stored in
+ // the directory packageDir. Returns true if successful, false
+ // otherwise.
+ bool GenerateComponentPackage(const std::string& packageFileDir,
+ const std::string& packageFileName,
+ const std::string& packageDir,
+ const cmCPackComponent* component);
+
+ const char* GetComponentScript(const char* script,
+ const char* script_component);
+
+};
+
+#endif
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 2db5ded..bffa4b7 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -951,6 +951,10 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
set(CPackComponents_BUILD_OPTIONS)
if(APPLE)
set(CPackComponents_BUILD_OPTIONS -DCPACK_BINARY_DRAGNDROP:BOOL=ON)
+ if(CMake_TEST_XCODE_VERSION VERSION_GREATER "4.6")
+ set(CPackComponents_BUILD_OPTIONS ${CPackComponents_BUILD_OPTIONS}
+ -DCPACK_BINARY_PRODUCTBUILD:BOOL=ON)
+ endif()
endif()
if(NSIS_MAKENSIS_EXECUTABLE)
set(CPackComponents_BUILD_OPTIONS ${CPackComponents_BUILD_OPTIONS}
@@ -995,6 +999,9 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
list(APPEND ACTIVE_CPACK_GENERATORS "ZIP")
if(APPLE)
list(APPEND ACTIVE_CPACK_GENERATORS "DragNDrop")
+ if(CMake_TEST_XCODE_VERSION VERSION_GREATER "4.6")
+ list(APPEND ACTIVE_CPACK_GENERATORS "productbuild")
+ endif()
endif()
# set up list of component packaging ways
@@ -1105,6 +1112,10 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
set(CPackComponents_BUILD_OPTIONS)
if(APPLE)
set(CPackComponents_BUILD_OPTIONS -DCPACK_BINARY_DRAGNDROP:BOOL=ON)
+ if(CMake_TEST_XCODE_VERSION VERSION_GREATER "4.6")
+ set(CPackComponents_BUILD_OPTIONS ${CPackComponents_BUILD_OPTIONS}
+ -DCPACK_BINARY_PRODUCTBUILD:BOOL=ON)
+ endif()
endif()
if(NOT NSIS_MAKENSIS_EXECUTABLE)
set(CPackComponents_BUILD_OPTIONS ${CPackComponents_BUILD_OPTIONS}