aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJake Petroules <jake.petroules@qt.io>2017-04-27 03:47:31 -0700
committerJake Petroules <jake.petroules@qt.io>2017-06-12 16:24:44 +0000
commite675eda3d40bb0e17f10b410e1ccdbbd12d063c9 (patch)
treed1dadf89b6b1d58541bc92d0825ea59fbebbf4e6
parenta3bc51e1ea52d867ce6647a278225948982d7d48 (diff)
Add support for building macOS disk images
This allows users to build drag 'n' drop installers with custom backgrounds, volume icons, and icon layouts. Unlike other solutions, disk images with these features can be built without any reliance on AppleScript, Finder, or a graphical login session, making it (mostly) reproducible and CI-friendly. .DS_Store files and their contained alias and bookmark records (which control the mounted disk image's appearance in the Finder) are written on-demand based on qbs properties defined in the project file, as well as the Carbon LPic, TEXT, styl, and RTF resources used for embedding a license agreement prompt. Task-number: QBS-416 Change-Id: I95431e21becc3bea075a1468d5271a41c38bbd04 Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
-rw-r--r--doc/reference/items/convenience/androidapk.qdoc2
-rw-r--r--doc/reference/items/convenience/appleapplicationdiskimage.qdoc106
-rw-r--r--doc/reference/items/convenience/applediskimage.qdoc43
-rw-r--r--doc/reference/items/convenience/application.qdoc2
-rw-r--r--doc/reference/modules/dmg-module.qdoc342
-rw-r--r--examples/cocoa-application/CocoaApplication.qbs43
-rw-r--r--examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/Contents.json68
-rw-r--r--examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_128x128.pngbin0 -> 5256 bytes
-rw-r--r--examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_128x128@2x.pngbin0 -> 11304 bytes
-rw-r--r--examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_16x16.pngbin0 -> 487 bytes
-rw-r--r--examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_16x16@2x.pngbin0 -> 1374 bytes
-rw-r--r--examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_256x256.pngbin0 -> 11304 bytes
-rw-r--r--examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_256x256@2x.pngbin0 -> 26984 bytes
-rw-r--r--examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_32x32.pngbin0 -> 1374 bytes
-rw-r--r--examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_32x32@2x.pngbin0 -> 2423 bytes
-rw-r--r--examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_512x512.pngbin0 -> 26984 bytes
-rw-r--r--examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_512x512@2x.pngbin0 -> 63576 bytes
-rw-r--r--examples/cocoa-application/CocoaApplication/background.pngbin0 -> 86627 bytes
-rw-r--r--examples/cocoa-application/CocoaApplication/background@2x.pngbin0 -> 217596 bytes
-rw-r--r--examples/cocoa-application/CocoaApplication/dmg.iconset/icon_128x128.pngbin0 -> 5256 bytes
-rw-r--r--examples/cocoa-application/CocoaApplication/dmg.iconset/icon_128x128@2x.pngbin0 -> 11304 bytes
-rw-r--r--examples/cocoa-application/CocoaApplication/dmg.iconset/icon_16x16.pngbin0 -> 487 bytes
-rw-r--r--examples/cocoa-application/CocoaApplication/dmg.iconset/icon_16x16@2x.pngbin0 -> 1374 bytes
-rw-r--r--examples/cocoa-application/CocoaApplication/dmg.iconset/icon_256x256.pngbin0 -> 11304 bytes
-rw-r--r--examples/cocoa-application/CocoaApplication/dmg.iconset/icon_256x256@2x.pngbin0 -> 26984 bytes
-rw-r--r--examples/cocoa-application/CocoaApplication/dmg.iconset/icon_32x32.pngbin0 -> 1374 bytes
-rw-r--r--examples/cocoa-application/CocoaApplication/dmg.iconset/icon_32x32@2x.pngbin0 -> 2423 bytes
-rw-r--r--examples/cocoa-application/CocoaApplication/dmg.iconset/icon_512x512.pngbin0 -> 26984 bytes
-rw-r--r--examples/cocoa-application/CocoaApplication/dmg.iconset/icon_512x512@2x.pngbin0 -> 63576 bytes
-rw-r--r--examples/cocoa-application/CocoaApplication/en.lproj/LICENSE27
l---------examples/cocoa-application/CocoaApplication/en_US.lproj1
-rw-r--r--examples/cocoa-application/app.qbs83
-rw-r--r--examples/cocoa-application/dmg.qbs72
-rw-r--r--share/qbs/imports/qbs/base/AppleApplicationDiskImage.qbs110
-rw-r--r--share/qbs/imports/qbs/base/AppleDiskImage.qbs34
-rw-r--r--share/qbs/modules/dmg/DMGModule.qbs156
-rw-r--r--share/qbs/modules/dmg/dmg.js212
-rw-r--r--src/3rdparty/python/lib/python2.7/site-packages/mac_alias/bookmark.py7
-rw-r--r--tests/auto/blackbox/testdata-apple/apple-dmg/apple-dmg.qbs88
-rw-r--r--tests/auto/blackbox/testdata-apple/apple-dmg/de_DE.lproj/eula.txt6
-rw-r--r--tests/auto/blackbox/testdata-apple/apple-dmg/en_GB.lproj/eula.txt6
-rw-r--r--tests/auto/blackbox/testdata-apple/apple-dmg/en_US.lproj/eula.txt6
-rw-r--r--tests/auto/blackbox/testdata-apple/apple-dmg/fr_FR.lproj/eula.txt6
-rw-r--r--tests/auto/blackbox/testdata-apple/apple-dmg/hello.icnsbin0 -> 1393763 bytes
-rw-r--r--tests/auto/blackbox/testdata-apple/apple-dmg/hello.tifbin0 -> 866742 bytes
-rw-r--r--tests/auto/blackbox/testdata-apple/apple-dmg/ja_JP.lproj/eula.txt6
-rw-r--r--tests/auto/blackbox/testdata-apple/apple-dmg/ko_KR.lproj/eula.rtf49
-rw-r--r--tests/auto/blackbox/testdata-apple/apple-dmg/main.c1
-rw-r--r--tests/auto/blackbox/testdata-apple/apple-dmg/ru_RU.lproj/eula.txt6
-rw-r--r--tests/auto/blackbox/testdata-apple/apple-dmg/white.iconset/icon_16x16.pngbin0 -> 649 bytes
-rw-r--r--tests/auto/blackbox/testdata-apple/apple-dmg/white.iconset/icon_16x16@2x.pngbin0 -> 665 bytes
-rw-r--r--tests/auto/blackbox/testdata-apple/apple-dmg/zh_CN.lproj/eula.odtbin0 -> 2680 bytes
-rw-r--r--tests/auto/blackbox/testdata-apple/apple-dmg/zh_TW.lproj/eula.docxbin0 -> 12338 bytes
-rw-r--r--tests/auto/blackbox/tst_blackboxapple.cpp6
-rw-r--r--tests/auto/blackbox/tst_blackboxapple.h1
55 files changed, 1453 insertions, 36 deletions
diff --git a/doc/reference/items/convenience/androidapk.qdoc b/doc/reference/items/convenience/androidapk.qdoc
index 17496bbc3..c3cce0ea1 100644
--- a/doc/reference/items/convenience/androidapk.qdoc
+++ b/doc/reference/items/convenience/androidapk.qdoc
@@ -27,7 +27,7 @@
/*!
\contentspage list-of-convenience-items.html
\page androidapk-item.html
- \nextpage application-item.html
+ \nextpage applediskimage-item.html
\ingroup list-of-convenience-items
\ingroup list-of-items
diff --git a/doc/reference/items/convenience/appleapplicationdiskimage.qdoc b/doc/reference/items/convenience/appleapplicationdiskimage.qdoc
new file mode 100644
index 000000000..7612d60bf
--- /dev/null
+++ b/doc/reference/items/convenience/appleapplicationdiskimage.qdoc
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+/*!
+ \contentspage list-of-convenience-items.html
+ \page appleapplicationdiskimage-item.html
+ \previouspage applediskimage-item.html
+ \nextpage application-item.html
+ \ingroup list-of-convenience-items
+ \ingroup list-of-items
+
+ \title AppleApplicationDiskImage Item
+ \brief Represents a product that is an Apple application drag 'n' drop disk image installer.
+
+ An \c AppleApplicationDiskImage item is a convenience item that has a dependency on the
+ \l{Module dmg}{DMG module} and whose type is \c{["dmg.dmg"]}, and also has rules and properties
+ specific to building drag 'n' drop disk image installers with an application bundle and symbolic
+ link to the /Applications directory.
+
+ Any artifacts of product dependencies which are tagged \c{"installable"} will be copied into the
+ disk image, provided their file paths are relative to the path specified by the \c{sourceBase}
+ property (i.e. are located in that directory). Any artifacts tagged \c{"installable"} and which
+ are not relative to \c{sourceBase} will be ignored.
+
+ Here is what the project file could look like for a simple DMG installer:
+ \code
+ import qbs
+
+ AppleApplicationDiskImage {
+ Depends { name: "myapp" }
+ name: "My App"
+ dmg.volumeName: name
+ dmg.iconSize: 128
+ dmg.windowWidth: 640
+ dmg.windowHeight: 280
+ dmg.iconPositions: [
+ {"path": "Applications", "x": 128, "y": 128},
+ {"path": "My App.app", "x": 256, "y": 128}
+ ]
+ files: ["background.tiff", "volume-icon.icns"]
+ Group {
+ files: ["*.lproj/**"] // licenses
+ fileTags: ["dmg.license.input"]
+ }
+ }
+ \endcode
+
+ For plain disk images whose contents are not a single application bundle, consider the base
+ \l{AppleDiskImage Item}{AppleDiskImage} item instead.
+
+ \section1 AppleApplicationDiskImage Properties
+ The following properties are available in addition to the ones inherited from \c AppleDiskImage.
+
+ \table
+ \header
+ \li Property
+ \li Type
+ \li Since
+ \li Default
+ \li Description
+ \row
+ \li sourceBase
+ \li \c{string}
+ \li 1.9
+ \li /Applications
+ \li The base directory from which artifacts installed into the disk image will be copied.
+ This directory is always considered to be relative to \c{qbs.installRoot}.
+ For example, if the application Example.app exists at
+ \c{qbs.installRoot}/Applications/Example.app, and \c{sourceBase} is
+ \c{/Applications}, the application will be located at /Example.app
+ relative to the disk image root, and therefore its full path when the disk image is
+ mounted would be something like /Volumes/Example-1.0/Example.app.
+ \row
+ \li symlinks
+ \li \c{stringList}
+ \li 1.9
+ \li \c{["/Applications:Applications"]}
+ \li List of symlinks to create in the disk image. This is specified as a list of strings,
+ each string containing two file paths separated by a colon. The first path is the
+ symlink target, and the second path is the name of the symlink relative to the root of
+ the disk image.
+ \endtable
+*/
diff --git a/doc/reference/items/convenience/applediskimage.qdoc b/doc/reference/items/convenience/applediskimage.qdoc
new file mode 100644
index 000000000..ffd335212
--- /dev/null
+++ b/doc/reference/items/convenience/applediskimage.qdoc
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+/*!
+ \contentspage list-of-convenience-items.html
+ \page applediskimage-item.html
+ \previouspage androidapk-item.html
+ \nextpage appleapplicationdiskimage-item.html
+ \ingroup list-of-convenience-items
+ \ingroup list-of-items
+
+ \title AppleDiskImage Item
+ \brief Represents a product that is an Apple disk image.
+
+ An \c AppleDiskImage item is a convenience item that has a dependency on the
+ \l{Module dmg}{DMG module} and whose type is \c{["dmg.dmg"]}.
+
+ For single-application drag 'n' drop disk image installers, you'll probably want to use the
+ \l{AppleApplicationDiskImage Item}{AppleApplicationDiskImage} item instead.
+*/
diff --git a/doc/reference/items/convenience/application.qdoc b/doc/reference/items/convenience/application.qdoc
index 1a13724b1..d254e84ee 100644
--- a/doc/reference/items/convenience/application.qdoc
+++ b/doc/reference/items/convenience/application.qdoc
@@ -27,7 +27,7 @@
/*!
\contentspage list-of-convenience-items.html
\page application-item.html
- \previouspage androidapk-item.html
+ \previouspage appleapplicationdiskimage-item.html
\nextpage applicationextension-item.html
\ingroup list-of-convenience-items
\ingroup list-of-items
diff --git a/doc/reference/modules/dmg-module.qdoc b/doc/reference/modules/dmg-module.qdoc
new file mode 100644
index 000000000..6a11e6c4b
--- /dev/null
+++ b/doc/reference/modules/dmg-module.qdoc
@@ -0,0 +1,342 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \contentspage index.html
+ \page dmg-module.html
+ \ingroup list-of-modules
+
+ \title Module dmg
+ \since 1.9
+ \brief Provides support for building Apple Disk Images
+
+ The \c dmg module contains properties and rules for building Apple Disk Images, which are
+ typically used to distribute applications and installers on macOS.
+
+ This module is only available on Apple platforms.
+
+ \section1 General Properties
+
+ \table
+ \header
+ \li Property
+ \li Type
+ \li Since
+ \li Default
+ \li Description
+ \row
+ \li volumeName
+ \li \c{string}
+ \li 1.9
+ \li \c{product.targetName}
+ \li The name of the disk image which displayed in Finder when the DMG is mounted.
+ \row
+ \li badgeVolumeIcon
+ \li \c{bool}
+ \li 1.9
+ \li \c{false}
+ \li Whether to render the user-supplied icon (see the \c{"icns"} file tag documentation)
+ on top of the default volume icon instead of using it directly. This generally gives
+ the disk image icon a better and more consistent appearance.
+ \row
+ \li format
+ \li \c{string}
+ \li 1.9
+ \li \c{"UDBZ"}
+ \li The format to create the disk image in.
+ Allowed values include but are not limited to \c{"UDZO"}, \c{"UDBZ"} and \c{"ULFO"}.
+ \row
+ \li compressionLevel
+ \li \c{int}
+ \li 1.9
+ \li 9 in release mode, otherwise undefined
+ \li Sets the zlib, bzip2, or lzfse compression level for UDZO, UDBZ, or ULFO disk images.
+ \row
+ \li sourceBase
+ \li \c{string}
+ \li 1.9
+ \li \c{undefined}
+ \li Specifies the base directory of the files that are going to be embedded in the DMG
+ (see the \c{"dmg.input"} file tag documentation). The source base directory is omitted
+ from the target directory path of the DMG directory.
+ The default value of this property is the directory of the current file
+ to be embedded, relative to the product's source directory.
+ \endtable
+
+ \section1 Appearance Properties
+
+ Properties in this section are used to control the contents of the .DS_Store file and its
+ embedded Alias and Bookmark records, that will be generated by \QBS in order to control the
+ appearance of the disk image when mounted in Finder.
+
+ \table
+ \header
+ \li Property
+ \li Type
+ \li Since
+ \li Default
+ \li Description
+ \row
+ \li backgroundColor
+ \li \c{string}
+ \li 1.9
+ \li \c{undefined}
+ \li Specifies the background color of the disk image as seen when mounted in Finder.
+ Refer to the \l{https://dmgbuild.readthedocs.io/en/latest/settings.html#background}
+ {dmgbuild documentation}
+ for the full list of supported color names and formats.
+ To use an image for the background instead,
+ refer to the \c{"tiff"} file tag documentation.
+ \row
+ \li iconSize
+ \li \c{int}
+ \li 1.9
+ \li \c{128}
+ \li Specifies the width and height of the file icons as seen when the disk image is mounted
+ in Finder.
+ \row
+ \li windowX
+ \li \c{int}
+ \li 1.9
+ \li \c{100}
+ \li Specifies the X position of the Finder window that displays the disk image contents
+ when it is mounted.
+ \row
+ \li windowY
+ \li \c{int}
+ \li 1.9
+ \li \c{100}
+ \li Specifies the Y position of the Finder window that displays the disk image contents
+ when it is mounted.
+ \row
+ \li windowWidth
+ \li \c{int}
+ \li 1.9
+ \li \c{640}
+ \li Specifies the width of the Finder window that displays the disk image contents
+ when it is mounted.
+ \row
+ \li windowHeight
+ \li \c{int}
+ \li 1.9
+ \li \c{480}
+ \li Specifies the height of the Finder window that displays the disk image contents
+ when it is mounted. Note that the window height includes the height of the standard
+ macOS title bar (22 points).
+ \row
+ \li iconPositions
+ \li \c{list}
+ \li 1.9
+ \li \c{undefined}
+ List of objects containing \c{path}, \c{x}, and \c{y} properties, which correspond to
+ disk image-relative file paths and visual coordinates of file icons in the disk image
+ as seen when it is mounted in Finder. For example:
+ \code
+ dmg.iconPositions: [
+ {"path": "Applications", "x": 128, "y": 128},
+ {"path": "Foo Bar.app", "x": 256, "y": 128}
+ ]
+ \endcode
+ This property is useful for specifying the positions of files where you do not have
+ direct control over the corresponding \QBS artifact, or there is no corresponding \QBS
+ artifact (for example, "Foo Bar.app" is a directory, which has no equivalent artifact in
+ the build graph). For files to which you are directly applying the \c{dmg.input} file
+ tag, you should use the \c{dmg.iconX} and \c{dmg.iconY} properties instead.
+ \row
+ \li iconX
+ \li \c{int}
+ \li 1.9
+ \li \c{windowWidth / 2}
+ \li X position of the file icon in the Finder window that displayed the disk image contents
+ when it is mounted. This property is only useful with artifacts tagged \c{dmg.input} and
+ cannot be used at the product level to affect all files.
+ If you do not have access to the artifact corresponding to the file whose position you
+ want to set, use the \c{dmg.iconPositions} property instead.
+ \row
+ \li iconY
+ \li \c{int}
+ \li 1.9
+ \li \c{windowHeight / 2}
+ \li Y position of the file icon in the Finder window that displayed the disk image contents
+ when it is mounted. This property is only useful with artifacts tagged \c{dmg.input} and
+ cannot be used at the product level to affect all files.
+ If you do not have access to the artifact corresponding to the file whose position you
+ want to set, use the \c{dmg.iconPositions} property instead.
+ \endtable
+
+ \section1 License Properties
+
+ Properties in this section are used to control the content and appearance of the license prompt
+ displayed when a user attempts to mount the resulting disk image via Finder.
+
+ \table
+ \header
+ \li Property
+ \li Type
+ \li Since
+ \li Default
+ \li Description
+ \row
+ \li defaultLicenseLocale
+ \li \c{string}
+ \li 1.9
+ \li \c{"en_US"}
+ \li Locale of the default license to display when there is no license whose locale matches
+ the system locale.
+ \row
+ \li licenseLocale
+ \li \c{string}
+ \li 1.9
+ \li determined automatically
+ \li Locale of the license file. Defaults to a value guess from the file path, specifically
+ the base name of any .lproj directory found in the file's path. If the locale could not
+ be determined from the file path and this property is not set, an error will be emitted.
+ This property is only useful with artifacts tagged \c{dmg.license.input} and
+ cannot be used at the product level to affect all files.
+ \row
+ \li licenseLanguageName
+ \li \c{string}
+ \li 1.9
+ \li \c{"English"}
+ \li Name of the language associated with the license file, localized for that language.
+ This property is only useful with artifacts tagged \c{dmg.license.input} and
+ cannot be used at the product level to affect all files.
+ \row
+ \li licenseAgreeButtonText
+ \li \c{string}
+ \li 1.9
+ \li \c{"Agree"}
+ \li Text shown on the "Agree" button associated with the license file,
+ localized for that language.
+ This property is only useful with artifacts tagged \c{dmg.license.input} and
+ cannot be used at the product level to affect all files.
+ \row
+ \li licenseDisagreeButtonText
+ \li \c{string}
+ \li 1.9
+ \li \c{"Disagree"}
+ \li Text shown on the "Disagree" button associated with the license file,
+ localized for that language.
+ This property is only useful with artifacts tagged \c{dmg.license.input} and
+ cannot be used at the product level to affect all files.
+ \row
+ \li licensePrintButtonText
+ \li \c{string}
+ \li 1.9
+ \li \c{"Print"}
+ \li Text shown on the "Print" button associated with the license file,
+ localized for that language.
+ This property is only useful with artifacts tagged \c{dmg.license.input} and
+ cannot be used at the product level to affect all files.
+ \row
+ \li licenseSaveButtonText
+ \li \c{string}
+ \li 1.9
+ \li \c{"Save"}
+ \li Text shown on the "Save" button associated with the license file,
+ localized for that language.
+ This property is only useful with artifacts tagged \c{dmg.license.input} and
+ cannot be used at the product level to affect all files.
+ \row
+ \li licenseInstructionText
+ \li \c{string}
+ \li 1.9
+ \li \c{"If you agree with the terms of this license, press \"Agree\" to install the software. If you do not agree, press \"Disagree\"."}
+ \li Instruction text associated with the license file that will be shown on the license
+ dialog, localized for that language.
+ This property is only useful with artifacts tagged \c{dmg.license.input} and
+ cannot be used at the product level to affect all files.
+ \endtable
+
+ \section1 Advanced Properties
+
+ \table
+ \header
+ \li Property
+ \li Type
+ \li Since
+ \li Default
+ \li Description
+ \row
+ \li dmgSuffix
+ \li \c{string}
+ \li 1.9
+ \li \c{".dmg"}
+ \li File extension for disk images.
+ This should not normally need to be changed.
+ \row
+ \li hdiutilPath
+ \li \c{string}
+ \li 1.9
+ \li \c{"/usr/bin/hdiutil"}
+ \li Path to the hdiutil binary used to perform disk image related operations.
+ This should not normally need to be changed.
+ \row
+ \li textutilPath
+ \li \c{string}
+ \li 1.9
+ \li \c{"/usr/bin/textutil"}
+ \li Path to the textutil binary used to convert license agreement files to rich text format.
+ This should not normally need to be changed.
+ \endtable
+
+ \section1 Relevant File Tags
+
+ \table
+ \header
+ \li Tag
+ \li Auto-tagged File Names
+ \li Since
+ \li Description
+ \row
+ \li \c{"dmg.input"}
+ \li n/a
+ \li 1.9
+ \li If the product contains files with this tag, they will be copied into the disk image.
+ See the \c{sourceBase} property to learn how to control the destination directory and
+ hierarchy of copied files within the disk image.
+ \row
+ \li \c{"dmg.license.input"}
+ \li \c{*.txt}, \c{*.rtf}, \c{*.html}, \c{*.doc}, \c{*.docx}, \c{*.odt}, \c{*.xml},
+ \c{*.webarchive}
+ \li 1.9
+ \li If the product contains files with this tag, they will be converted into rich text and
+ used for the license prompt when mounting the DMG.
+ \row
+ \li \c{"icns"}
+ \li \c{*.icns}
+ \li 1.3
+ \li If the product contains a file with this tag, it will be added as the Apple Disk Image
+ volume icon, which will show up in the Finder as an overlay on the file icon.
+ \row
+ \li \c{"tiff"}
+ \li \c{*.tif}, \c{*.tiff}
+ \li 1.9
+ \li If the product contains a file with this tag, it will be used as the background image
+ of the directory as shown in Finder when the DMG file is mounted.
+ \endtable
+*/
diff --git a/examples/cocoa-application/CocoaApplication.qbs b/examples/cocoa-application/CocoaApplication.qbs
index 2c26904a8..d0d2affc6 100644
--- a/examples/cocoa-application/CocoaApplication.qbs
+++ b/examples/cocoa-application/CocoaApplication.qbs
@@ -36,39 +36,18 @@
**
****************************************************************************/
-import qbs 1.0
+import qbs
+import qbs.Utilities
-CppApplication {
- Depends { condition: product.condition; name: "ib" }
- condition: qbs.targetOS.contains("macos")
- name: "Cocoa Application"
+Project {
+ references: [
+ "app.qbs"
+ ]
- cpp.useObjcPrecompiledHeader: true
-
- cpp.frameworks: ["Cocoa"]
-
- Group {
- prefix: "CocoaApplication/"
- files: [
- "AppDelegate.h",
- "AppDelegate.m",
- "CocoaApplication-Info.plist",
- "main.m"
- ]
- }
-
- Group {
- name: "Supporting Files"
- prefix: "CocoaApplication/en.lproj/"
- files: [
- "Credits.rtf",
- "InfoPlist.strings",
- "MainMenu.xib"
- ]
- }
-
- Group {
- files: ["CocoaApplication/CocoaApplication-Prefix.pch"]
- fileTags: ["objc_pch_src"]
+ SubProject {
+ filePath: "dmg.qbs"
+ Properties {
+ condition: Utilities.versionCompare(qbs.version, "1.9") >= 0
+ }
}
}
diff --git a/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/Contents.json b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 000000000..7cd4f8e12
--- /dev/null
+++ b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,68 @@
+{
+ "images" : [
+ {
+ "size" : "16x16",
+ "idiom" : "mac",
+ "filename" : "icon_16x16.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "16x16",
+ "idiom" : "mac",
+ "filename" : "icon_16x16@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "32x32",
+ "idiom" : "mac",
+ "filename" : "icon_32x32.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "32x32",
+ "idiom" : "mac",
+ "filename" : "icon_32x32@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "128x128",
+ "idiom" : "mac",
+ "filename" : "icon_128x128.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "128x128",
+ "idiom" : "mac",
+ "filename" : "icon_128x128@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "256x256",
+ "idiom" : "mac",
+ "filename" : "icon_256x256.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "256x256",
+ "idiom" : "mac",
+ "filename" : "icon_256x256@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "512x512",
+ "idiom" : "mac",
+ "filename" : "icon_512x512.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "512x512",
+ "idiom" : "mac",
+ "filename" : "icon_512x512@2x.png",
+ "scale" : "2x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_128x128.png b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_128x128.png
new file mode 100644
index 000000000..6c556a835
--- /dev/null
+++ b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_128x128.png
Binary files differ
diff --git a/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_128x128@2x.png b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_128x128@2x.png
new file mode 100644
index 000000000..4442d3eb2
--- /dev/null
+++ b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_128x128@2x.png
Binary files differ
diff --git a/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_16x16.png b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_16x16.png
new file mode 100644
index 000000000..2adcdb5f4
--- /dev/null
+++ b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_16x16.png
Binary files differ
diff --git a/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_16x16@2x.png b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_16x16@2x.png
new file mode 100644
index 000000000..2a7030fd7
--- /dev/null
+++ b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_16x16@2x.png
Binary files differ
diff --git a/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_256x256.png b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_256x256.png
new file mode 100644
index 000000000..4442d3eb2
--- /dev/null
+++ b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_256x256.png
Binary files differ
diff --git a/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_256x256@2x.png b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_256x256@2x.png
new file mode 100644
index 000000000..069b5c050
--- /dev/null
+++ b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_256x256@2x.png
Binary files differ
diff --git a/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_32x32.png b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_32x32.png
new file mode 100644
index 000000000..2a7030fd7
--- /dev/null
+++ b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_32x32.png
Binary files differ
diff --git a/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_32x32@2x.png b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_32x32@2x.png
new file mode 100644
index 000000000..c5e458164
--- /dev/null
+++ b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_32x32@2x.png
Binary files differ
diff --git a/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_512x512.png b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_512x512.png
new file mode 100644
index 000000000..069b5c050
--- /dev/null
+++ b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_512x512.png
Binary files differ
diff --git a/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_512x512@2x.png b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_512x512@2x.png
new file mode 100644
index 000000000..0b810615e
--- /dev/null
+++ b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_512x512@2x.png
Binary files differ
diff --git a/examples/cocoa-application/CocoaApplication/background.png b/examples/cocoa-application/CocoaApplication/background.png
new file mode 100644
index 000000000..938dc0c04
--- /dev/null
+++ b/examples/cocoa-application/CocoaApplication/background.png
Binary files differ
diff --git a/examples/cocoa-application/CocoaApplication/background@2x.png b/examples/cocoa-application/CocoaApplication/background@2x.png
new file mode 100644
index 000000000..099e9d830
--- /dev/null
+++ b/examples/cocoa-application/CocoaApplication/background@2x.png
Binary files differ
diff --git a/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_128x128.png b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_128x128.png
new file mode 100644
index 000000000..6c556a835
--- /dev/null
+++ b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_128x128.png
Binary files differ
diff --git a/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_128x128@2x.png b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_128x128@2x.png
new file mode 100644
index 000000000..4442d3eb2
--- /dev/null
+++ b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_128x128@2x.png
Binary files differ
diff --git a/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_16x16.png b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_16x16.png
new file mode 100644
index 000000000..2adcdb5f4
--- /dev/null
+++ b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_16x16.png
Binary files differ
diff --git a/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_16x16@2x.png b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_16x16@2x.png
new file mode 100644
index 000000000..2a7030fd7
--- /dev/null
+++ b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_16x16@2x.png
Binary files differ
diff --git a/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_256x256.png b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_256x256.png
new file mode 100644
index 000000000..4442d3eb2
--- /dev/null
+++ b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_256x256.png
Binary files differ
diff --git a/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_256x256@2x.png b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_256x256@2x.png
new file mode 100644
index 000000000..069b5c050
--- /dev/null
+++ b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_256x256@2x.png
Binary files differ
diff --git a/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_32x32.png b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_32x32.png
new file mode 100644
index 000000000..2a7030fd7
--- /dev/null
+++ b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_32x32.png
Binary files differ
diff --git a/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_32x32@2x.png b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_32x32@2x.png
new file mode 100644
index 000000000..c5e458164
--- /dev/null
+++ b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_32x32@2x.png
Binary files differ
diff --git a/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_512x512.png b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_512x512.png
new file mode 100644
index 000000000..069b5c050
--- /dev/null
+++ b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_512x512.png
Binary files differ
diff --git a/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_512x512@2x.png b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_512x512@2x.png
new file mode 100644
index 000000000..0b810615e
--- /dev/null
+++ b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_512x512@2x.png
Binary files differ
diff --git a/examples/cocoa-application/CocoaApplication/en.lproj/LICENSE b/examples/cocoa-application/CocoaApplication/en.lproj/LICENSE
new file mode 100644
index 000000000..44650fe73
--- /dev/null
+++ b/examples/cocoa-application/CocoaApplication/en.lproj/LICENSE
@@ -0,0 +1,27 @@
+Copyright (C) 2017 The Qt Company Ltd.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names
+ of its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/examples/cocoa-application/CocoaApplication/en_US.lproj b/examples/cocoa-application/CocoaApplication/en_US.lproj
new file mode 120000
index 000000000..545e7ac76
--- /dev/null
+++ b/examples/cocoa-application/CocoaApplication/en_US.lproj
@@ -0,0 +1 @@
+en.lproj \ No newline at end of file
diff --git a/examples/cocoa-application/app.qbs b/examples/cocoa-application/app.qbs
new file mode 100644
index 000000000..366d49263
--- /dev/null
+++ b/examples/cocoa-application/app.qbs
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of the examples of Qbs.
+**
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names
+** of its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+****************************************************************************/
+
+import qbs
+
+CppApplication {
+ Depends { condition: product.condition; name: "ib" }
+ condition: qbs.targetOS.contains("macos")
+ name: "Cocoa Application"
+
+ cpp.useObjcPrecompiledHeader: true
+
+ cpp.frameworks: ["Cocoa"]
+
+ Group {
+ prefix: "CocoaApplication/"
+ files: [
+ "AppDelegate.h",
+ "AppDelegate.m",
+ "CocoaApplication-Info.plist",
+ "CocoaApplication.xcassets",
+ "main.m"
+ ]
+ }
+
+ Group {
+ name: "Supporting Files"
+ prefix: "CocoaApplication/en.lproj/"
+ files: [
+ "Credits.rtf",
+ "InfoPlist.strings",
+ "MainMenu.xib"
+ ]
+ }
+
+ Group {
+ files: ["CocoaApplication/CocoaApplication-Prefix.pch"]
+ fileTags: ["objc_pch_src"]
+ }
+
+ Group {
+ fileTagsFilter: ["bundle.content"]
+ qbs.install: true
+ qbs.installDir: "Applications"
+ qbs.installSourceBase: product.destinationDirectory
+ }
+
+ ib.appIconName: "AppIcon"
+}
diff --git a/examples/cocoa-application/dmg.qbs b/examples/cocoa-application/dmg.qbs
new file mode 100644
index 000000000..e8e0a923a
--- /dev/null
+++ b/examples/cocoa-application/dmg.qbs
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of the examples of Qbs.
+**
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names
+** of its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+****************************************************************************/
+
+import qbs
+
+AppleApplicationDiskImage {
+ condition: qbs.targetOS.contains("macos")
+ name: "Cocoa Application DMG"
+ targetName: "cocoa-application-" + version
+ version: "1.0"
+
+ Depends { name: "Cocoa Application" }
+ Depends { name: "ib" }
+
+ files: [
+ "CocoaApplication/dmg.iconset",
+ "CocoaApplication/en_US.lproj/LICENSE",
+ ]
+
+ // set to false to use a solid-color background (see dmg.backgroundColor below)
+ property bool useImageBackground: true
+ Group {
+ condition: useImageBackground
+ files: ["CocoaApplication/background*"]
+ }
+
+ dmg.backgroundColor: "#41cd52"
+ dmg.badgeVolumeIcon: true
+ dmg.iconPositions: [
+ {"x": 200, "y": 200, "path": "Cocoa Application.app"},
+ {"x": 400, "y": 200, "path": "Applications"}
+ ]
+ dmg.windowX: 420
+ dmg.windowY: 250
+ dmg.windowWidth: 600
+ dmg.windowHeight: 422 // this *includes* the macOS title bar height of 22
+ dmg.iconSize: 64
+}
diff --git a/share/qbs/imports/qbs/base/AppleApplicationDiskImage.qbs b/share/qbs/imports/qbs/base/AppleApplicationDiskImage.qbs
new file mode 100644
index 000000000..d1d4988c6
--- /dev/null
+++ b/share/qbs/imports/qbs/base/AppleApplicationDiskImage.qbs
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+import qbs.File
+import qbs.FileInfo
+import qbs.ModUtils
+
+AppleDiskImage {
+ property string sourceBase: "/Applications"
+ readonly property string absoluteSourceBase: FileInfo.joinPaths(qbs.installRoot, sourceBase)
+ property stringList symlinks: ["/Applications:Applications"]
+
+ readonly property string stageDirectory: FileInfo.joinPaths(destinationDirectory, "Volumes", dmg.volumeName)
+
+ Rule {
+ multiplex: true
+ inputs: ["qbs"]
+ outputFileTags: ["dmg.input", "dmg.input.symlink"]
+ outputArtifacts: Array.prototype.map.call(product.symlinks, function (symlink) {
+ var symlinkTarget = symlink.split(':')[0];
+ var symlinkName = symlink.split(':')[1] || symlinkTarget;
+ if (FileInfo.isAbsolutePath(symlinkName))
+ throw(symlink + " is an invalid symlink; the destination must be a relative path");
+ return {
+ filePath: FileInfo.joinPaths(product.stageDirectory, symlinkName),
+ fileTags: ["dmg.input", "dmg.input.symlink"],
+ dmg: { symlinkTarget: symlinkTarget, sourceBase: product.stageDirectory },
+ };
+ })
+ prepare: Array.prototype.map.call(outputs["dmg.input"], function (symlink) {
+ var cmd = new Command("ln", ["-sfn", symlink.dmg.symlinkTarget, symlink.filePath]);
+ cmd.workingDirectory = product.stageDirectory;
+ cmd.description = "symlinking " + symlink.fileName + " => " + symlink.dmg.symlinkTarget;
+ return cmd;
+ });
+ }
+
+ Rule {
+ multiplex: true
+ inputs: ["dmg.input.symlink"]
+ inputsFromDependencies: ["installable"]
+ outputFileTags: ["dmg.input"]
+ outputArtifacts: {
+ var absSourceBase = product.absoluteSourceBase;
+ var symlinkPaths = (inputs["dmg.input.symlink"] || []).map(function (s) { return s.filePath; });
+ return Array.prototype.map.call(inputs["installable"], function (a) {
+ var fp = ModUtils.artifactInstalledFilePath(a);
+ if (fp.startsWith(absSourceBase)) {
+ var outputFilePath = fp.replace(absSourceBase, product.stageDirectory);
+
+ // Check for symlink conflicts
+ for (var i in symlinkPaths) {
+ if (outputFilePath.startsWith(symlinkPaths[i]))
+ throw new Error("Cannot install '" + a.filePath
+ + "' to '" + outputFilePath + "' because it "
+ + "would conflict with the symlink at '"
+ + symlinkPaths[i] + "'");
+ }
+
+ return {
+ filePath: outputFilePath,
+ fileTags: ["dmg.input"],
+ dmg: { sourceBase: product.stageDirectory }
+ }
+ }
+ }).filter(function (a) { return !!a; });
+ }
+ prepare: {
+ var absSourceBase = product.absoluteSourceBase;
+ var cmds = [], dmgs = outputs["dmg.input"];
+ for (var i in dmgs) {
+ var a = dmgs[i];
+ var cmd = new JavaScriptCommand();
+ cmd.src = a.filePath.replace(product.stageDirectory, absSourceBase);
+ cmd.dst = a.filePath;
+ cmd.silent = true;
+ cmd.sourceCode = function () { File.copy(src, dst); };
+ cmds.push(cmd);
+ }
+ return cmds;
+ }
+ }
+}
diff --git a/share/qbs/imports/qbs/base/AppleDiskImage.qbs b/share/qbs/imports/qbs/base/AppleDiskImage.qbs
new file mode 100644
index 000000000..1467d822b
--- /dev/null
+++ b/share/qbs/imports/qbs/base/AppleDiskImage.qbs
@@ -0,0 +1,34 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+Product {
+ Depends { name: "dmg" }
+ type: ["dmg.dmg"]
+}
diff --git a/share/qbs/modules/dmg/DMGModule.qbs b/share/qbs/modules/dmg/DMGModule.qbs
new file mode 100644
index 000000000..b45f9d548
--- /dev/null
+++ b/share/qbs/modules/dmg/DMGModule.qbs
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+import qbs
+import qbs.DarwinTools
+import qbs.File
+import qbs.FileInfo
+import qbs.ModUtils
+import qbs.Process
+import qbs.TextFile
+import "dmg.js" as Dmg
+
+Module {
+ Depends { name: "xcode"; required: false }
+
+ condition: qbs.hostOS.contains("darwin") && qbs.targetOS.contains("darwin")
+
+ property string volumeName: product.targetName
+ PropertyOptions {
+ name: "volumeName"
+ description: "the name of the disk image (displayed in Finder when mounted)"
+ }
+
+ property bool badgeVolumeIcon: false
+ PropertyOptions {
+ name: "badgeVolumeIcon"
+ description: "whether to render the user-supplied icon on top of the " +
+ "default volume icon instead of using it directly"
+ }
+
+ property string format: "UDBZ"
+ PropertyOptions {
+ name: "format"
+ description: "the format to create the disk image in"
+ }
+
+ property int compressionLevel: qbs.buildVariant === "release" ? 9 : undefined
+ PropertyOptions {
+ name: "compressionLevel"
+ description: "sets the zlib or bzip2 compression level for UDZO and UDBZ disk images"
+ }
+
+ property string textutilPath: "/usr/bin/textutil"
+ property string hdiutilPath: "/usr/bin/hdiutil"
+ property string dmgSuffix: ".dmg"
+
+ property string sourceBase
+
+ readonly property string pythonPath: File.canonicalFilePath(FileInfo.joinPaths(path,
+ "..", "..",
+ "python"))
+ readonly property string libexecPath: File.canonicalFilePath(FileInfo.joinPaths(path,
+ "..", "..", "..", "..",
+ "libexec", "qbs"))
+
+ property string backgroundColor
+ property int iconSize: 128
+ property int windowX: 100
+ property int windowY: 100
+ property int windowWidth: 640
+ property int windowHeight: 480
+ property var iconPositions
+
+ property int iconX: windowWidth / 2
+ property int iconY: windowHeight / 2
+
+ property string defaultLicenseLocale
+ property string licenseLocale
+ property string licenseLanguageName
+ property string licenseAgreeButtonText
+ property string licenseDisagreeButtonText
+ property string licensePrintButtonText
+ property string licenseSaveButtonText
+ property string licenseInstructionText
+
+ FileTagger {
+ patterns: [
+ "*.txt", "*.rtf", "*.html", "*.doc", "*.docx", "*.odt", "*.xml", "*.webarchive",
+ "LICENSE"
+ ]
+ fileTags: ["dmg.license.input"]
+ }
+
+ FileTagger {
+ patterns: ["*.icns"]
+ fileTags: ["icns"]
+ }
+
+ FileTagger {
+ patterns: ["*.tif", "*.tiff"]
+ fileTags: ["tiff"]
+ }
+
+ Rule {
+ inputs: ["dmg.license.input"]
+
+ outputFileTags: ["dmg.license"]
+ outputArtifacts: ([{
+ filePath: FileInfo.joinPaths(product.destinationDirectory, "licenses",
+ FileInfo.relativePath(product.sourceDirectory,
+ input.filePath) + ".rtf"),
+ fileTags: ["dmg.license"],
+ dmg: {
+ licenseLocale: input.dmg.licenseLocale,
+ licenseLanguageName: input.dmg.licenseLanguageName,
+ licenseAgreeButtonText: input.dmg.licenseAgreeButtonText,
+ licenseDisagreeButtonText: input.dmg.licenseDisagreeButtonText,
+ licensePrintButtonText: input.dmg.licensePrintButtonText,
+ licenseSaveButtonText: input.dmg.licenseSaveButtonText,
+ licenseInstructionText: input.dmg.licenseInstructionText
+ }
+ }])
+
+ prepare: Dmg.prepareLicense.apply(Dmg, arguments)
+ }
+
+ Rule {
+ multiplex: true
+ inputs: ["qbs", "dmg.input", "dmg.license", "icns", "tiff"]
+
+ Artifact {
+ fileTags: ["dmg.dmg"]
+ filePath: FileInfo.joinPaths(product.destinationDirectory,
+ product.targetName + product.dmg.dmgSuffix)
+ }
+
+ prepare: Dmg.prepareDmg.apply(Dmg, arguments)
+ }
+}
diff --git a/share/qbs/modules/dmg/dmg.js b/share/qbs/modules/dmg/dmg.js
new file mode 100644
index 000000000..82b701434
--- /dev/null
+++ b/share/qbs/modules/dmg/dmg.js
@@ -0,0 +1,212 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+var DarwinTools = require("qbs.DarwinTools");
+var FileInfo = require("qbs.FileInfo");
+var TextFile = require("qbs.TextFile");
+var Utilities = require("qbs.Utilities");
+
+function localizationFromArtifact(input) {
+ var locale = input.dmg.licenseLocale || DarwinTools.localizationKey(input.filePath);
+ if (!locale)
+ throw("Could not determine localization for license file: " + input.filePath);
+ return locale;
+}
+
+function dmgbuildSettings(product, inputs) {
+ var backgroundImages = inputs["tiff"];
+ var backgroundImage;
+ if (backgroundImages) {
+ if (backgroundImages.length > 1)
+ throw new Error("only one background image may be specified");
+ backgroundImage = backgroundImages[0].filePath;
+ }
+
+ var volumeIcons = inputs["icns"];
+ var volumeIcon;
+ if (volumeIcons) {
+ if (volumeIcons.length > 1)
+ throw new Error("only one volume icon may be specified");
+ volumeIcon = volumeIcons[0].filePath;
+ }
+
+ var licenseFileObjects = Array.prototype.map.call(inputs["dmg.license"], function (a) {
+ return {
+ "dmg": {
+ "licenseLocale": localizationFromArtifact(a),
+ "licenseLanguageName": a.dmg.licenseLanguageName,
+ "licenseAgreeButtonText": a.dmg.licenseAgreeButtonText,
+ "licenseDisagreeButtonText": a.dmg.licenseDisagreeButtonText,
+ "licensePrintButtonText": a.dmg.licensePrintButtonText,
+ "licenseSaveButtonText": a.dmg.licenseSaveButtonText,
+ "licenseInstructionText": a.dmg.licenseInstructionText,
+ },
+ "filePath": a.filePath
+ };
+ });
+
+ function reduceLicensesForKey(licenseFileObjects, key) {
+ return licenseFileObjects.reduce(function (accumulator, currentValue) {
+ var locale = currentValue.dmg.licenseLocale;
+ if (accumulator[locale])
+ throw new Error("Multiple license files for localization '" + locale + "'");
+ switch (key) {
+ case "licenses":
+ accumulator[locale] = currentValue.filePath;
+ break;
+ case "buttons":
+ var texts = [
+ currentValue.dmg.licenseLanguageName,
+ currentValue.dmg.licenseAgreeButtonText,
+ currentValue.dmg.licenseDisagreeButtonText,
+ currentValue.dmg.licensePrintButtonText,
+ currentValue.dmg.licenseSaveButtonText,
+ currentValue.dmg.licenseInstructionText
+ ];
+ accumulator[locale] = texts.every(function (a) { return !!a; }) ? texts : undefined;
+ break;
+ }
+ return accumulator;
+ }, {});
+ }
+
+ var contentsArray = Array.prototype.map.call(inputs["dmg.input"], function (a) {
+ if (a.dmg.sourceBase && !a.filePath.startsWith(a.dmg.sourceBase)) {
+ throw new Error("Cannot install '" + a.filePath + "', " +
+ "because it doesn't start with the value of " +
+ "dmg.sourceBase '" + a.dmg.sourceBase + "'.");
+ }
+
+ var isSymlink = a.fileTags.contains("dmg.input.symlink");
+ return {
+ "x": a.dmg.iconX,
+ "y": a.dmg.iconY,
+ "type": isSymlink ? "link" : "file",
+ "path": isSymlink ? a.dmg.symlinkTarget : a.filePath,
+ "name": FileInfo.relativePath(a.dmg.sourceBase || FileInfo.path(a.filePath), a.filePath)
+ };
+ });
+
+ Array.prototype.forEach.call(product.dmg.iconPositions, function (obj) {
+ var existingIndex = -1;
+ Array.prototype.forEach.call(contentsArray, function (contentsItem, i) {
+ if (contentsItem["name"] === obj["path"])
+ existingIndex = i;
+ });
+
+ if (existingIndex >= 0) {
+ contentsArray[existingIndex]["x"] = obj["x"];
+ contentsArray[existingIndex]["y"] = obj["y"];
+ } else {
+ contentsArray.push({
+ "type": "position",
+ "name": obj["path"], // name => path is not a typo
+ "path": obj["path"],
+ "x": obj["x"],
+ "y": obj["y"]
+ });
+ }
+ });
+
+ return {
+ "title": product.dmg.volumeName,
+ "icon": !product.dmg.badgeVolumeIcon ? volumeIcon : undefined,
+ "badge-icon": product.dmg.badgeVolumeIcon ? volumeIcon : undefined,
+ "background": backgroundImage,
+ "background-color": product.dmg.backgroundColor,
+ "icon-size": product.dmg.iconSize,
+ "window": {
+ "position": {
+ "x": product.dmg.windowX,
+ "y": product.dmg.windowY
+ },
+ "size": {
+ "width": product.dmg.windowWidth,
+ "height": product.dmg.windowHeight
+ }
+ },
+ "format": product.dmg.format,
+ "compression-level": product.dmg.compressionLevel,
+ "license": {
+ "default-language": product.dmg.defaultLicenseLocale,
+ "licenses": reduceLicensesForKey(licenseFileObjects, "licenses"),
+ "buttons": reduceLicensesForKey(licenseFileObjects, "buttons")
+ },
+ "contents": contentsArray
+ };
+}
+
+function prepareLicense(project, product, inputs, outputs, input, output) {
+ var cmd = new Command(product.dmg.textutilPath, [
+ "-convert", "rtf",
+ "-strip",
+ "-font", "Arial",
+ "-output", output.filePath,
+ "--", input.filePath
+ ]);
+ cmd.description = "converting " + input.fileName;
+ return [cmd];
+}
+
+function prepareDmg(project, product, inputs, outputs, input, output) {
+ var i;
+ var cmd;
+ var cmds = [];
+
+ var settingsJsonFilePath = FileInfo.joinPaths(product.destinationDirectory,
+ "settings.json");
+ cmd = new JavaScriptCommand();
+ cmd.silent = true;
+ cmd.settingsJSON = dmgbuildSettings(product, inputs);
+ cmd.settingsJsonFilePath = settingsJsonFilePath;
+ cmd.sourceCode = function () {
+ var tf;
+ try {
+ tf = new TextFile(settingsJsonFilePath, TextFile.WriteOnly);
+ tf.writeLine(JSON.stringify(settingsJSON, undefined, 4));
+ } finally {
+ if (tf)
+ tf.close();
+ }
+ }
+ cmds.push(cmd);
+
+ // Create the actual DMG via dmgbuild
+ cmd = new Command(FileInfo.joinPaths(product.dmg.libexecPath, "dmgbuild"),
+ [product.dmg.volumeName,
+ output.filePath,
+ "--no-hidpi", // qbs handles this by itself
+ "--settings", settingsJsonFilePath]);
+ cmd.environment = ["PYTHONPATH=" + product.dmg.pythonPath];
+ cmd.description = "creating " + output.fileName;
+ cmds.push(cmd);
+
+ return cmds;
+}
diff --git a/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/bookmark.py b/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/bookmark.py
index 58a76a6e1..41b9acf35 100644
--- a/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/bookmark.py
+++ b/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/bookmark.py
@@ -144,7 +144,7 @@ kBookmarkFileCreationDate = 0x1040
# = 0x1055 # ?
# = 0x1056 # ?
# = 0x1101 # ?
-# = 0x1102 # ?
+# = 0x1102 # ?
kBookmarkTOCPath = 0x2000 # A list of (TOC id, ?) pairs
kBookmarkVolumePath = 0x2002
kBookmarkVolumeURL = 0x2005
@@ -299,6 +299,9 @@ class Bookmark (object):
def from_bytes(cls, data):
"""Create a :class:`Bookmark` given byte data."""
+ if isinstance(data, bytearray):
+ data = bytes(data)
+
if len(data) < 16:
raise ValueError('Not a bookmark file (too short)')
@@ -493,7 +496,7 @@ class Bookmark (object):
# binary search to find data
entries.sort()
- tocs.append((tid, b''.join([struct.pack('<III',k,o,0)
+ tocs.append((tid, b''.join([struct.pack(b'<III',k,o,0)
for k,o in entries])))
first_toc_offset = offset
diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/apple-dmg.qbs b/tests/auto/blackbox/testdata-apple/apple-dmg/apple-dmg.qbs
new file mode 100644
index 000000000..3bccebfd0
--- /dev/null
+++ b/tests/auto/blackbox/testdata-apple/apple-dmg/apple-dmg.qbs
@@ -0,0 +1,88 @@
+import qbs
+
+Project {
+ AppleApplicationDiskImage {
+ Depends { name: "myapp" }
+ Depends { name: "ib" }
+ dmg.volumeName: "My Great App"
+ dmg.iconSize: 128
+ dmg.windowWidth: 640
+ dmg.windowHeight: 280
+ files: [
+ "white.iconset",
+ ]
+ }
+
+ CppApplication {
+ name: "myapp"
+ targetName: "My Great App"
+ files: ["main.c"]
+
+ Group {
+ fileTagsFilter: ["bundle.content"]
+ qbs.install: true
+ qbs.installDir: "/Applications"
+ qbs.installSourceBase: product.buildDirectory
+ }
+ }
+
+ AppleDiskImage {
+ name: "hellodmg"
+ targetName: "hellodmg-1.0"
+ + (qbs.architecture ? "-" + qbs.architecture : "")
+
+ dmg.volumeName: "Hello DMG"
+
+ files: [
+ "hello.icns",
+ "hello.tif"
+ ]
+
+ Group {
+ files: ["en_US.lproj/eula.txt"]
+ fileTags: ["dmg.input", "dmg.license.input"]
+ dmg.iconX: 320
+ dmg.iconY: 240
+ dmg.licenseLocale: "en_US"
+ }
+
+ Group {
+ files: ["*.lproj/**"]
+ excludeFiles: ["en_US.lproj/eula.txt"]
+ }
+ }
+
+ AppleDiskImage {
+ name: "green"
+ dmg.backgroundColor: "green"
+ }
+
+ AppleDiskImage {
+ name: "german"
+ dmg.defaultLicenseLocale: "de_DE"
+
+ Group {
+ files: ["*.lproj/**"]
+ }
+ }
+
+ AppleDiskImage {
+ name: "custom-buttons"
+
+ Group {
+ files: ["ru_RU.lproj/eula.txt"]
+ dmg.licenseLocale: "sv_SE" // override auto-detected ru_RU with sv_SE
+ dmg.licenseLanguageName: "Swedish, not Russian"
+ dmg.licenseAgreeButtonText: "Of course"
+ dmg.licenseDisagreeButtonText: "Never!"
+ dmg.licensePrintButtonText: "Make Paper"
+ dmg.licenseSaveButtonText: "Make Bits"
+ dmg.licenseInstructionText: "Do please agree to the license!"
+ }
+
+ Group {
+ files: ["*.lproj/**"]
+ excludeFiles: ["ru_RU.lproj/eula.txt"]
+ }
+ }
+}
diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/de_DE.lproj/eula.txt b/tests/auto/blackbox/testdata-apple/apple-dmg/de_DE.lproj/eula.txt
new file mode 100644
index 000000000..7ca2bf84b
--- /dev/null
+++ b/tests/auto/blackbox/testdata-apple/apple-dmg/de_DE.lproj/eula.txt
@@ -0,0 +1,6 @@
+FIKTIVE UNTERNEHMEN
+SOFTWARE BEISPIEL VEREINBARUNG
+
+Sie stimmen zu, dass Sie nicht mit dieser App auf Atomwaffen zu machen.
+
+Sie bestätigen, dass Qbs das Beste ist.
diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/en_GB.lproj/eula.txt b/tests/auto/blackbox/testdata-apple/apple-dmg/en_GB.lproj/eula.txt
new file mode 100644
index 000000000..e2b7adbed
--- /dev/null
+++ b/tests/auto/blackbox/testdata-apple/apple-dmg/en_GB.lproj/eula.txt
@@ -0,0 +1,6 @@
+FICTIONAL CORPORATION
+SOFTWARE EXAMPLE AGREEMENT
+
+You agree that you will not use this app to make nuclear weapons.
+
+You agree that Qbs is the best.
diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/en_US.lproj/eula.txt b/tests/auto/blackbox/testdata-apple/apple-dmg/en_US.lproj/eula.txt
new file mode 100644
index 000000000..e2b7adbed
--- /dev/null
+++ b/tests/auto/blackbox/testdata-apple/apple-dmg/en_US.lproj/eula.txt
@@ -0,0 +1,6 @@
+FICTIONAL CORPORATION
+SOFTWARE EXAMPLE AGREEMENT
+
+You agree that you will not use this app to make nuclear weapons.
+
+You agree that Qbs is the best.
diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/fr_FR.lproj/eula.txt b/tests/auto/blackbox/testdata-apple/apple-dmg/fr_FR.lproj/eula.txt
new file mode 100644
index 000000000..48a9af57c
--- /dev/null
+++ b/tests/auto/blackbox/testdata-apple/apple-dmg/fr_FR.lproj/eula.txt
@@ -0,0 +1,6 @@
+SOCIÉTÉ FICTIONNEL
+EXEMPLE D'ACCORD DU LOGICIEL
+
+Vous vous engagez à ne pas utiliser cette application pour fabriquer des armes nucléaires.
+
+Vous acceptez que Qbs est le meilleur.
diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/hello.icns b/tests/auto/blackbox/testdata-apple/apple-dmg/hello.icns
new file mode 100644
index 000000000..b8ff0c53b
--- /dev/null
+++ b/tests/auto/blackbox/testdata-apple/apple-dmg/hello.icns
Binary files differ
diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/hello.tif b/tests/auto/blackbox/testdata-apple/apple-dmg/hello.tif
new file mode 100644
index 000000000..b58b4548d
--- /dev/null
+++ b/tests/auto/blackbox/testdata-apple/apple-dmg/hello.tif
Binary files differ
diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/ja_JP.lproj/eula.txt b/tests/auto/blackbox/testdata-apple/apple-dmg/ja_JP.lproj/eula.txt
new file mode 100644
index 000000000..e44c34bb3
--- /dev/null
+++ b/tests/auto/blackbox/testdata-apple/apple-dmg/ja_JP.lproj/eula.txt
@@ -0,0 +1,6 @@
+架空CORPORATION
+ソフトウェア例契約
+
+あなたは核兵器を作るために、このアプリを使用しないことに同意します。
+
+あなたは、QBSがベストであることに同意するものとします。
diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/ko_KR.lproj/eula.rtf b/tests/auto/blackbox/testdata-apple/apple-dmg/ko_KR.lproj/eula.rtf
new file mode 100644
index 000000000..5b7c49d56
--- /dev/null
+++ b/tests/auto/blackbox/testdata-apple/apple-dmg/ko_KR.lproj/eula.rtf
@@ -0,0 +1,49 @@
+{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset129 AppleSDGothicNeo-Regular;\f1\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\margl1440\margr1440\vieww10800\viewh8400\viewkind0
+\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural
+
+\f0\b\fs24 \cf0 \'c7\'e3\'b1\'b8
+\f1 CORPORATION\
+
+\f0 \'bc\'d2\'c7\'c1\'c6\'ae\'bf\'fe\'be\'ee
+\f1
+\f0 \'bf\'b9
+\f1
+\f0 \'b0\'e8\'be\'e0
+\f1\b0 \
+\
+
+\f0 \'b4\'e7\'bd\'c5\'c0\'ba
+\f1
+\f0 \'b4\'e7\'bd\'c5\'c0\'cc
+\f1
+\f0 \'c7\'d9\'b9\'ab\'b1\'e2\'b8\'a6
+\f1
+\f0 \'b8\'b8\'b5\'e9\'b1\'e2
+\f1
+\f0 \'c0\'a7\'c7\'d8\'c0\'cc
+\f1
+\f0 \'c0\'c0\'bf\'eb
+\f1
+\f0 \'c7\'c1\'b7\'ce\'b1\'d7\'b7\'a5\'c0\'bb
+\f1
+\f0 \'bb\'e7\'bf\'eb\'c7\'cf\'c1\'f6
+\f1
+\f0 \'be\'ca\'c0\'bb
+\f1
+\f0 \'b0\'cd\'bf\'a1
+\f1
+\f0 \'b5\'bf\'c0\'c7\'c7\'d5\'b4\'cf\'b4\'d9
+\f1 .\
+\
+
+\f0 \'b4\'e7\'bd\'c5\'c0\'ba
+\f1 QBS
+\f0 \'b0\'a1
+\f1
+\f0 \'c3\'d6\'b0\'ed\'b6\'f3\'b0\'ed
+\f1
+\f0 \'b5\'bf\'c0\'c7\'c7\'d5\'b4\'cf\'b4\'d9
+\f1 .} \ No newline at end of file
diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/main.c b/tests/auto/blackbox/testdata-apple/apple-dmg/main.c
new file mode 100644
index 000000000..76e819701
--- /dev/null
+++ b/tests/auto/blackbox/testdata-apple/apple-dmg/main.c
@@ -0,0 +1 @@
+int main() { return 0; }
diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/ru_RU.lproj/eula.txt b/tests/auto/blackbox/testdata-apple/apple-dmg/ru_RU.lproj/eula.txt
new file mode 100644
index 000000000..e2b7adbed
--- /dev/null
+++ b/tests/auto/blackbox/testdata-apple/apple-dmg/ru_RU.lproj/eula.txt
@@ -0,0 +1,6 @@
+FICTIONAL CORPORATION
+SOFTWARE EXAMPLE AGREEMENT
+
+You agree that you will not use this app to make nuclear weapons.
+
+You agree that Qbs is the best.
diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/white.iconset/icon_16x16.png b/tests/auto/blackbox/testdata-apple/apple-dmg/white.iconset/icon_16x16.png
new file mode 100644
index 000000000..60365798f
--- /dev/null
+++ b/tests/auto/blackbox/testdata-apple/apple-dmg/white.iconset/icon_16x16.png
Binary files differ
diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/white.iconset/icon_16x16@2x.png b/tests/auto/blackbox/testdata-apple/apple-dmg/white.iconset/icon_16x16@2x.png
new file mode 100644
index 000000000..20369000d
--- /dev/null
+++ b/tests/auto/blackbox/testdata-apple/apple-dmg/white.iconset/icon_16x16@2x.png
Binary files differ
diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/zh_CN.lproj/eula.odt b/tests/auto/blackbox/testdata-apple/apple-dmg/zh_CN.lproj/eula.odt
new file mode 100644
index 000000000..21345e536
--- /dev/null
+++ b/tests/auto/blackbox/testdata-apple/apple-dmg/zh_CN.lproj/eula.odt
Binary files differ
diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/zh_TW.lproj/eula.docx b/tests/auto/blackbox/testdata-apple/apple-dmg/zh_TW.lproj/eula.docx
new file mode 100644
index 000000000..9e48895ac
--- /dev/null
+++ b/tests/auto/blackbox/testdata-apple/apple-dmg/zh_TW.lproj/eula.docx
Binary files differ
diff --git a/tests/auto/blackbox/tst_blackboxapple.cpp b/tests/auto/blackbox/tst_blackboxapple.cpp
index f5bad1cbd..9d3364914 100644
--- a/tests/auto/blackbox/tst_blackboxapple.cpp
+++ b/tests/auto/blackbox/tst_blackboxapple.cpp
@@ -595,6 +595,12 @@ void TestBlackboxApple::deploymentTarget_data()
}
}
+void TestBlackboxApple::dmg()
+{
+ QDir::setCurrent(testDataDir + "/apple-dmg");
+ QCOMPARE(runQbs(), 0);
+}
+
void TestBlackboxApple::embedInfoPlist()
{
QDir::setCurrent(testDataDir + QLatin1String("/embedInfoPlist"));
diff --git a/tests/auto/blackbox/tst_blackboxapple.h b/tests/auto/blackbox/tst_blackboxapple.h
index ea56d915f..b9bb64104 100644
--- a/tests/auto/blackbox/tst_blackboxapple.h
+++ b/tests/auto/blackbox/tst_blackboxapple.h
@@ -57,6 +57,7 @@ private slots:
void bundleStructure_data();
void deploymentTarget();
void deploymentTarget_data();
+ void dmg();
void embedInfoPlist();
void frameworkStructure();
void iconset();