From 47302038c1021f0b6b0d9977f5bccaa795045805 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Thu, 18 Sep 2014 13:59:40 -0400 Subject: CPack/DragNDrop: Use source file extension for background image Instead of blindly copying the `CPACK_DMG_BACKGROUND_IMAGE` file to `background.png`, we instead use the same file extension as the source image. This is needed for proper support of multi resolution `tif` backgrounds. --- Source/CPack/cmCPackDragNDropGenerator.cxx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx index 208a64c..3d1e4ea 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.cxx +++ b/Source/CPack/cmCPackDragNDropGenerator.cxx @@ -399,13 +399,17 @@ 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 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" << extension; if(!this->CopyFile(package_background_source, package_background_destination)) -- cgit v0.12 From 9c1dfbfd600819a751d4c5058fd939650ee6d6b4 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Thu, 18 Sep 2014 13:59:57 -0400 Subject: CPack/DragNDrop: Place the background image file in a hidden folder By using a hidden folder we avoid the need to mark the file as hidden from finder, and it makes it easier for future work to refer to the background image file. --- Source/CPack/cmCPackDragNDropGenerator.cxx | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx index 3d1e4ea..eff302c 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.cxx +++ b/Source/CPack/cmCPackDragNDropGenerator.cxx @@ -400,6 +400,7 @@ 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 = @@ -409,7 +410,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, std::ostringstream package_background_destination; package_background_destination << staging.str() - << "/background" << extension; + << "/.background/background" << extension; if(!this->CopyFile(package_background_source, package_background_destination)) @@ -421,21 +422,6 @@ 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 << "\""; - - if(!this->RunCommand(temp_background_hiding_command)) - { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Error setting attributes on disk volume background image." - << std::endl); - - return 0; - } } // Create a temporary read-write disk image ... -- cgit v0.12 From 167a465565cda9bb33d2e919509c23a761ea45e9 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Fri, 26 Sep 2014 14:38:38 -0400 Subject: CPack/DragNDrop: Optionally run an AppleScript when making a package While the DragNDropGenerator supports custom DS_Store and backgrounds, it is still very hard to automatically setup nice looking packages. The primary issue is that the DS_Store embeds the name of the volume in the path to backgrounds, which means that if a package embeds the version in its volume name a new DS_Store must generated for each release. Instead one now can use applescript to setup the DS_Store. This change also ensures that temporary RW image has enough space for these changes, creating 1 MB dummy padding file, that is later removed from the image. Co-Author: Adam Strzelecki --- Source/CPack/cmCPackDragNDropGenerator.cxx | 110 ++++++++++++++++++++++++++--- Source/CPack/cmCPackDragNDropGenerator.h | 1 + 2 files changed, 100 insertions(+), 11 deletions(-) diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx index eff302c..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) @@ -424,6 +450,25 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, } } + bool remount_image = !cpack_package_icon.empty() || + !cpack_dmg_ds_store_setup_script.empty(); + + // 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 creating dummy padding file." + << std::endl); + + return 0; + } + } + // Create a temporary read-write disk image ... std::string temp_image = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); temp_image += "/temp.dmg"; @@ -447,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"); @@ -469,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; @@ -498,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 -- cgit v0.12 From c4b9ee1878c62a272d38ae057e0a76409be54e8f Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Thu, 18 Dec 2014 14:56:37 -0500 Subject: CPack/DragNDrop: Update documentation to include new variables Document the new behavior of `CPACK_DMG_BACKGROUND_IMAGE` and the purpose of `CPACK_DMG_DS_STORE_SETUP_SCRIPT`. --- Help/release/dev/better-looking-mac-packages.rst | 8 ++++++++ Modules/CPackDMG.cmake | 20 +++++++++++++++----- 2 files changed, 23 insertions(+), 5 deletions(-) create mode 100644 Help/release/dev/better-looking-mac-packages.rst 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., 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 # -- cgit v0.12 From 4bca9401269878d2f3b0465377f0fb8bce87c734 Mon Sep 17 00:00:00 2001 From: Adam Strzelecki Date: Mon, 29 Sep 2014 08:42:49 -0400 Subject: Improve appearance of CMake .dmg package on OS X Configure our use of the CPack DragNDrop generator to specify a custom background image and script. --- CMakeCPackOptions.cmake.in | 7 +++++++ Packaging/CMakeDMGBackground.tif | Bin 0 -> 95690 bytes Packaging/CMakeDMGSetup.scpt | 42 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+) create mode 100644 Packaging/CMakeDMGBackground.tif create mode 100644 Packaging/CMakeDMGSetup.scpt 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/Packaging/CMakeDMGBackground.tif b/Packaging/CMakeDMGBackground.tif new file mode 100644 index 0000000..91c4b13 Binary files /dev/null and b/Packaging/CMakeDMGBackground.tif 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 -- cgit v0.12