Skip to content

Commit

Permalink
Fixup Qt 4 frameworks during hdiutil-codesign for compatibility with …
Browse files Browse the repository at this point in the history
…GateKeeper in OS X 10.9.5 / 10.10

GateKeeper in OS X 10.9.5 / 10.10 has stricter checks which
reject the Qt 4 framework bundles.

This commit adds logic to hdiutil-codesign to remove files from the root
of the Qt 4 framework bundles which should not be present and add
/Versions/4/Resources/Info.plist files and a /Resources symlink.

MD-20425
QTBUG-23268
  • Loading branch information
Robert Knight committed Sep 1, 2014
1 parent 07048b4 commit 4f92019
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 23 deletions.
10 changes: 0 additions & 10 deletions README

This file was deleted.

30 changes: 30 additions & 0 deletions README.md
@@ -0,0 +1,30 @@
OS X Bundle Utilities
=====================

This repository contains a set of utility scripts
related to packaging Qt applications under OS X.

### update-mac-bundle-lib-names.rb

update-mac-bundle-lib-names.rb is a script to replace
references to libraries in binaries in a Mac OS X bundle to refer
to copies of the libraries in the bundle instead of system-wide locations.

It was originally written for use with a Qt application to ensure that the application
in the bundle used the copies of the Qt libraries instead of copies installed to
system-wide locations.

See update-mac-bundle-lib-names.rb for more details and usage.

### hdiutil-codesign.rb

hdiutil-codesign.rb is a wrapper around the hdiutil command which
CPack uses to generate .dmg disk images for Mac applications.

In CPack's config file, set CPACK_COMMAND_HDIUTIL to point to this
wrapper script instead of hdiutil.

When CPack invokes this script with the path of a directory to
compress into a .dmg image, the wrapper script will first codesign
the contents of the app bundle in the directory and then
invoke the real hdiutil tool to create the .dmg image.
84 changes: 71 additions & 13 deletions hdiutil-codesign.rb
@@ -1,5 +1,8 @@
#!/usr/bin/env ruby

require 'fileutils'
require 'find'

# This is a wrapper script around 'hdiutil' which can be used to ensure
# that a Mac OS bundle's contents are code-signed before the .dmg is created using 'hdiutil create'
#
Expand All @@ -24,26 +27,81 @@
exit 1
end

# Fix up Qt framework bundles to conform to the bundle structure described
# at https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/FrameworkAnatomy.html
#
# See also: https://bugreports.qt-project.org/browse/QTBUG-23268
def fixup_framework_bundle(framework_path)
# ensure the Resources directory exists under Versions/Current
# and that it contains an Info.plist file.
#
# When the Qt 4 framework bundles are built, the Info.plist file
# is incorrectly placed in Contents/Info.plist, so move it if necessary
content_plist = "#{framework_path}/Contents/Info.plist"
resource_dir = "#{framework_path}/Resources"
resource_plist = "#{resource_dir}/Info.plist"

FileUtils.mkpath "#{framework_path}/Versions/Current/Resources"
FileUtils.ln_sf 'Versions/Current/Resources', "#{framework_path}/Resources"

if File.exist?(content_plist) && !File.exist?(resource_plist)
FileUtils.cp content_plist, resource_plist
end

# Remove anything from the root of the bundle which is not a symlink
# or the 'Versions' directory - see link above to Apple's documentation
# on the structure of framework bundles
Dir.foreach(framework_path) do |entry|
next if entry == '.' || entry == '..'

file_info = File.lstat("#{framework_path}/#{entry}")

if entry != 'Versions' && file_info.ftype != 'link'
$stderr.puts "Removing unexpected entry from framework bundle root #{framework_path}/#{entry}"
FileUtils.rm_rf "#{framework_path}/#{entry}"
end
end
end

def codesign_bundle(src_dir)
puts "Signing bundle #{src_dir}"

# Attempt to unlock the keychain using the 'security' tool so that 'codesign' does
# not prompt for user interaction
if !system("security unlock-keychain -p '#{ENV[CODESIGN_KEYCHAIN_PASS_VAR]}' #{ENV[CODESIGN_KEYCHAIN_VAR]}")
$stderr.puts "Error signing bundle - Unlocking keychain failed"
exit 1
end

# Work around an issue where the Qt framework bundles are not correctly
# structured under Qt 4.
#
# - There should only be one real top-level folder, 'Versions' with
# a symlink for the main lib: 'QtModule -> Versions/Current/QtModule' and
# the Resources folder 'Resources -> Versions/Current/Resourcs'
#
# - There must be an Info.plist file in the Resources/ folder
#
# See http://stackoverflow.com/a/18149893/434243
#
Find.find(src_dir).select { |path| path.end_with?('.framework') }.each do |framework_path|
fixup_framework_bundle framework_path
end

if !system('codesign', '--deep', '--force', '--sign', CODESIGN_IDENTITY, src_dir)
$stderr.puts "Error signing bundle"
exit 1
end
end

# Check if this is the initial command to create the .DMG image and if so,
# codesign the bundle's contents first
if ARGV[0] == "create"
ARGV.each_with_index do |arg,index|
if arg == "-srcfolder"
# Attempt to unlock the keychain using the 'security' tool so that 'codesign' does
# not prompt for user interaction
if !system("security unlock-keychain -p '#{ENV[CODESIGN_KEYCHAIN_PASS_VAR]}' #{ENV[CODESIGN_KEYCHAIN_VAR]}")
$stderr.puts "Error signing bundle - Unlocking keychain failed"
exit 1
end

src_dir = ARGV[index+1] + '/' + BUNDLE_NAME
if !system("codesign -f -s '#{CODESIGN_IDENTITY}' \"#{src_dir}\"")
$stderr.puts "Error signing bundle"
exit 1
end
codesign_bundle ARGV[index+1] + '/' + BUNDLE_NAME
end
end

end

# Invoke the real hdiutil utility
Expand Down

0 comments on commit 4f92019

Please sign in to comment.