summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2015-11-13 13:53:40 (GMT)
committerCMake Topic Stage <kwrobot@kitware.com>2015-11-13 13:53:40 (GMT)
commit9feb24e514f3c0f6b9a9705e17cf1917152df977 (patch)
tree8e9d592405399bc81d5ef33f25e1fd2c12cbe8a1
parentbbf1757dfa4804c0d8ac311e6645084982831a50 (diff)
parent4bca9401269878d2f3b0465377f0fb8bce87c734 (diff)
downloadCMake-9feb24e514f3c0f6b9a9705e17cf1917152df977.zip
CMake-9feb24e514f3c0f6b9a9705e17cf1917152df977.tar.gz
CMake-9feb24e514f3c0f6b9a9705e17cf1917152df977.tar.bz2
Merge topic 'better_looking_mac_package'
4bca9401 Improve appearance of CMake .dmg package on OS X c4b9ee18 CPack/DragNDrop: Update documentation to include new variables 167a4655 CPack/DragNDrop: Optionally run an AppleScript when making a package 9c1dfbfd CPack/DragNDrop: Place the background image file in a hidden folder 47302038 CPack/DragNDrop: Use source file extension for background image
-rw-r--r--CMakeCPackOptions.cmake.in7
-rw-r--r--Help/release/dev/better-looking-mac-packages.rst8
-rw-r--r--Modules/CPackDMG.cmake20
-rw-r--r--Packaging/CMakeDMGBackground.tifbin0 -> 95690 bytes
-rw-r--r--Packaging/CMakeDMGSetup.scpt42
-rw-r--r--Source/CPack/cmCPackDragNDropGenerator.cxx120
-rw-r--r--Source/CPack/cmCPackDragNDropGenerator.h1
7 files changed, 172 insertions, 26 deletions
diff --git a/CMakeCPackOptions.cmake.in b/CMakeCPackOptions.cmake.in
index b6013ef..ae00653 100644
--- a/CMakeCPackOptions.cmake.in
+++ b/CMakeCPackOptions.cmake.in
@@ -183,6 +183,13 @@ if("${CPACK_GENERATOR}" STREQUAL "PackageMaker")
endif()
endif()
+if("${CPACK_GENERATOR}" STREQUAL "DragNDrop")
+ set(CPACK_DMG_BACKGROUND_IMAGE
+ "@CMake_SOURCE_DIR@/Packaging/CMakeDMGBackground.tif")
+ set(CPACK_DMG_DS_STORE_SETUP_SCRIPT
+ "@CMake_SOURCE_DIR@/Packaging/CMakeDMGSetup.scpt")
+endif()
+
if("${CPACK_GENERATOR}" STREQUAL "WIX")
# Reset CPACK_PACKAGE_VERSION to deal with WiX restriction.
# But the file names still use the full CMake_VERSION value:
diff --git a/Help/release/dev/better-looking-mac-packages.rst b/Help/release/dev/better-looking-mac-packages.rst
new file mode 100644
index 0000000..ef1b8e8
--- /dev/null
+++ b/Help/release/dev/better-looking-mac-packages.rst
@@ -0,0 +1,8 @@
+better-looking-mac-packages
+---------------------------
+
+* The :module:`CPackDMG` module learned new variable to specify AppleScript
+ file run to customize appearance of ``DragNDrop`` installer folder,
+ including background image setting using supplied PNG or multi-resolution
+ TIFF file. See the :variable:`CPACK_DMG_DS_STORE_SETUP_SCRIPT` and
+ :variable:`CPACK_DMG_BACKGROUND_IMAGE` variables.
diff --git a/Modules/CPackDMG.cmake b/Modules/CPackDMG.cmake
index 37d7352..6b5af7e 100644
--- a/Modules/CPackDMG.cmake
+++ b/Modules/CPackDMG.cmake
@@ -26,15 +26,25 @@
# Path to a custom DS_Store file. This .DS_Store file e.g. can be used to
# specify the Finder window position/geometry and layout (such as hidden
# toolbars, placement of the icons etc.). This file has to be generated by
-# the Finder (either manually or through OSA-script) using a normal folder
+# the Finder (either manually or through AppleScript) using a normal folder
# from which the .DS_Store file can then be extracted.
#
+# .. variable:: CPACK_DMG_DS_STORE_SETUP_SCRIPT
+#
+# Path to a custom AppleScript file. This AppleScript is used to generate
+# a .DS_Store file which specifies the Finder window position/geometry and
+# layout (such as hidden toolbars, placement of the icons etc.).
+# By specifying a custom AppleScript there is no need to use
+# CPACK_DMG_DS_STORE, as the .DS_Store that is generated by the AppleScript
+# will be packaged.
+#
# .. variable:: CPACK_DMG_BACKGROUND_IMAGE
#
-# Path to a background image file. This file will be used as the background
-# for the Finder Window when the disk image is opened. By default no
-# background image is set. The background image is applied after applying the
-# custom .DS_Store file.
+# Path to an image file to be used as the background. This file will be
+# copied to .background/background.<ext>, where ext is the original image file
+# extension. The background image is installed into the image before
+# CPACK_DMG_DS_STORE_SETUP_SCRIPT is executed or CPACK_DMG_DS_STORE is
+# installed. By default no background image is set.
#
# .. variable:: CPACK_DMG_SLA_DIR
#
diff --git a/Packaging/CMakeDMGBackground.tif b/Packaging/CMakeDMGBackground.tif
new file mode 100644
index 0000000..91c4b13
--- /dev/null
+++ b/Packaging/CMakeDMGBackground.tif
Binary files differ
diff --git a/Packaging/CMakeDMGSetup.scpt b/Packaging/CMakeDMGSetup.scpt
new file mode 100644
index 0000000..c7ddcfb
--- /dev/null
+++ b/Packaging/CMakeDMGSetup.scpt
@@ -0,0 +1,42 @@
+on run argv
+ set image_name to item 1 of argv
+
+ tell application "Finder"
+ tell disk image_name
+
+ -- open the image the first time and save a DS_Store with just
+ -- background and icon setup
+ open
+ set current view of container window to icon view
+ set theViewOptions to the icon view options of container window
+ set background picture of theViewOptions to file ".background:background.tif"
+ set arrangement of theViewOptions to not arranged
+ set icon size of theViewOptions to 128
+ delay 1
+ close
+
+ -- next setup the position of the app and Applications symlink
+ -- plus hide all the window decoration
+ open
+ update without registering applications
+ tell container window
+ set sidebar width to 0
+ set statusbar visible to false
+ set toolbar visible to false
+ set the bounds to { 400, 100, 900, 465 }
+ set position of item "CMake.app" to { 133, 200 }
+ set position of item "Applications" to { 378, 200 }
+ end tell
+ update without registering applications
+ delay 1
+ close
+
+ -- one last open and close so you can see everything looks correct
+ open
+ delay 5
+ close
+
+ end tell
+ delay 1
+end tell
+end run
diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx
index 208a64c..7a93fc6 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.cxx
+++ b/Source/CPack/cmCPackDragNDropGenerator.cxx
@@ -271,6 +271,28 @@ bool cmCPackDragNDropGenerator::CopyFile(std::ostringstream& source,
}
//----------------------------------------------------------------------
+bool cmCPackDragNDropGenerator::CreateEmptyFile(std::ostringstream& target,
+ size_t size)
+{
+ cmsys::ofstream fout(target.str().c_str(),
+ std::ios::out | std::ios::binary);
+ if(!fout)
+ {
+ return false;
+ }
+ else
+ {
+ // Seek to desired size - 1 byte
+ fout.seekp(size - 1, std::ios_base::beg);
+ char byte = 0;
+ // Write one byte to ensure file grows
+ fout.write(&byte, 1);
+ }
+
+ return true;
+}
+
+//----------------------------------------------------------------------
bool cmCPackDragNDropGenerator::RunCommand(std::ostringstream& command,
std::string* output)
{
@@ -331,6 +353,10 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
this->GetOption("CPACK_DMG_LANGUAGES")
? this->GetOption("CPACK_DMG_LANGUAGES") : "";
+ const std::string cpack_dmg_ds_store_setup_script =
+ this->GetOption("CPACK_DMG_DS_STORE_SETUP_SCRIPT")
+ ? this->GetOption("CPACK_DMG_DS_STORE_SETUP_SCRIPT") : "";
+
// only put license on dmg if is user provided
if(!cpack_license_file.empty() &&
cpack_license_file.find("CPack.GenericLicense.txt") != std::string::npos)
@@ -399,13 +425,18 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
}
// Optionally add a custom background image ...
+ // Make sure the background file type is the same as the custom image
+ // and that the file is hidden so it doesn't show up.
if(!cpack_dmg_background_image.empty())
{
+ const std::string extension =
+ cmSystemTools::GetFilenameLastExtension(cpack_dmg_background_image);
std::ostringstream package_background_source;
package_background_source << cpack_dmg_background_image;
std::ostringstream package_background_destination;
- package_background_destination << staging.str() << "/background.png";
+ package_background_destination << staging.str()
+ << "/.background/background" << extension;
if(!this->CopyFile(package_background_source,
package_background_destination))
@@ -417,18 +448,22 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
return 0;
}
+ }
- std::ostringstream temp_background_hiding_command;
- temp_background_hiding_command << this->GetOption("CPACK_COMMAND_SETFILE");
- temp_background_hiding_command << " -a V \"";
- temp_background_hiding_command << package_background_destination.str();
- temp_background_hiding_command << "\"";
+ bool remount_image = !cpack_package_icon.empty() ||
+ !cpack_dmg_ds_store_setup_script.empty();
- if(!this->RunCommand(temp_background_hiding_command))
+ // Create 1 MB dummy padding file in staging area when we need to remount
+ // image, so we have enough space for storing changes ...
+ if(remount_image)
+ {
+ std::ostringstream dummy_padding;
+ dummy_padding << staging.str() << "/.dummy-padding-file";
+ if(!this->CreateEmptyFile(dummy_padding, 1048576))
{
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error setting attributes on disk volume background image."
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error creating dummy padding file."
+ << std::endl);
return 0;
}
@@ -457,10 +492,11 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
return 0;
}
- // Optionally set the custom icon flag for the image ...
- if(!cpack_package_icon.empty())
+ if(remount_image)
{
- std::ostringstream temp_mount;
+ // Store that we have a failure so that we always unmount the image
+ // before we exit.
+ bool had_error = false;
std::ostringstream attach_command;
attach_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
@@ -479,20 +515,57 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
cmsys::RegularExpression mountpoint_regex(".*(/Volumes/[^\n]+)\n.*");
mountpoint_regex.find(attach_output.c_str());
+ std::ostringstream temp_mount;
temp_mount << mountpoint_regex.match(1);
- std::ostringstream setfile_command;
- setfile_command << this->GetOption("CPACK_COMMAND_SETFILE");
- setfile_command << " -a C";
- setfile_command << " \"" << temp_mount.str() << "\"";
-
- if(!this->RunCommand(setfile_command))
+ // Remove dummy padding file so we have enough space on RW image ...
+ std::ostringstream dummy_padding;
+ dummy_padding << temp_mount.str() << "/.dummy-padding-file";
+ if(!cmSystemTools::RemoveFile(dummy_padding.str()))
{
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error assigning custom icon to temporary disk image."
+ "Error removing dummy padding file."
<< std::endl);
- return 0;
+ had_error = true;
+ }
+
+ // Optionally set the custom icon flag for the image ...
+ if(!had_error && !cpack_package_icon.empty())
+ {
+ std::ostringstream setfile_command;
+ setfile_command << this->GetOption("CPACK_COMMAND_SETFILE");
+ setfile_command << " -a C";
+ setfile_command << " \"" << temp_mount.str() << "\"";
+
+ if(!this->RunCommand(setfile_command))
+ {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error assigning custom icon to temporary disk image."
+ << std::endl);
+
+ had_error = true;
+ }
+ }
+
+ // Optionally we can execute a custom apple script to generate
+ // the .DS_Store for the volume folder ...
+ if(!had_error && !cpack_dmg_ds_store_setup_script.empty())
+ {
+ std::ostringstream setup_script_command;
+ setup_script_command << "osascript"
+ << " \"" << cpack_dmg_ds_store_setup_script << "\""
+ << " \"" << cpack_dmg_volume_name << "\"";
+ std::string error;
+ if(!this->RunCommand(setup_script_command, &error))
+ {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error executing custom script on disk image." << std::endl
+ << error
+ << std::endl);
+
+ had_error = true;
+ }
}
std::ostringstream detach_command;
@@ -508,6 +581,11 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
return 0;
}
+
+ if(had_error)
+ {
+ return 0;
+ }
}
if(!cpack_license_file.empty() || !slaDirectory.empty())
diff --git a/Source/CPack/cmCPackDragNDropGenerator.h b/Source/CPack/cmCPackDragNDropGenerator.h
index 12db469..53d38c4 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.h
+++ b/Source/CPack/cmCPackDragNDropGenerator.h
@@ -36,6 +36,7 @@ protected:
bool CopyFile(std::ostringstream& source, std::ostringstream& target);
+ bool CreateEmptyFile(std::ostringstream& target, size_t size);
bool RunCommand(std::ostringstream& command, std::string* output = 0);
std::string