aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--dist/dist.qbs6
-rw-r--r--doc/reference/items/artifact.qdoc3
-rw-r--r--doc/reference/items/rule.qdoc4
-rw-r--r--doc/reference/jsextensions/jsextensions-general.qdoc14
-rw-r--r--doc/reference/modules/android-ndk-module.qdoc12
-rw-r--r--doc/reference/modules/bundle-module.qdoc47
-rw-r--r--doc/reference/modules/cpp-module.qdoc21
-rw-r--r--doc/reference/modules/xcode-module.qdoc52
-rw-r--r--share/qbs/imports/qbs/DarwinTools/darwin-tools.js85
-rw-r--r--share/qbs/imports/qbs/ModUtils/utils.js3
-rw-r--r--share/qbs/imports/qbs/PathTools/path-tools.js27
-rw-r--r--share/qbs/imports/qbs/Probes/NodeJsProbe.qbs2
-rw-r--r--share/qbs/imports/qbs/Probes/TypeScriptProbe.qbs5
-rw-r--r--share/qbs/imports/qbs/Probes/path-probe.js17
-rw-r--r--share/qbs/imports/qbs/base/ApplicationExtension.qbs12
-rw-r--r--share/qbs/modules/Android/ndk/ndk.qbs18
-rw-r--r--share/qbs/modules/bundle/BundleModule.qbs222
-rw-r--r--share/qbs/modules/bundle/MacOSX-Package-Types.xcspec462
-rw-r--r--share/qbs/modules/bundle/MacOSX-Product-Types.xcspec545
-rw-r--r--share/qbs/modules/bundle/bundle.js214
-rwxr-xr-xshare/qbs/modules/bundle/update-specs.sh10
-rw-r--r--share/qbs/modules/cli/mono.qbs2
-rwxr-xr-xshare/qbs/modules/cli/windows-dotnet.qbs2
-rw-r--r--share/qbs/modules/cpp/CppModule.qbs5
-rw-r--r--share/qbs/modules/cpp/DarwinGCC.qbs17
-rw-r--r--share/qbs/modules/cpp/GenericGCC.qbs94
-rw-r--r--share/qbs/modules/cpp/gcc.js69
-rw-r--r--share/qbs/modules/cpp/genericunix-gcc.qbs2
-rw-r--r--share/qbs/modules/cpp/msvc.js23
-rw-r--r--share/qbs/modules/ib/ib.js4
-rw-r--r--share/qbs/modules/java/utils.js3
-rw-r--r--share/qbs/modules/nodejs/NodeJS.qbs2
-rw-r--r--share/qbs/modules/typescript/TypeScriptModule.qbs62
-rw-r--r--share/qbs/modules/typescript/typescript.js18
-rw-r--r--share/qbs/modules/xcode/xcode.js21
-rw-r--r--share/qbs/modules/xcode/xcode.qbs22
-rw-r--r--src/app/qbs-setup-toolchains/probe.cpp13
-rw-r--r--src/app/qbs/commandlinefrontend.cpp4
-rw-r--r--src/lib/corelib/api/project.cpp47
-rw-r--r--src/lib/corelib/api/runenvironment.cpp53
-rw-r--r--src/lib/corelib/api/runenvironment.h18
-rw-r--r--src/lib/corelib/buildgraph/jscommandexecutor.cpp4
-rw-r--r--src/lib/corelib/buildgraph/qtmocscanner.cpp24
-rw-r--r--src/lib/corelib/buildgraph/qtmocscanner.h2
-rw-r--r--src/lib/corelib/buildgraph/rulenode.cpp2
-rw-r--r--src/lib/corelib/buildgraph/rulesapplicator.cpp40
-rw-r--r--src/lib/corelib/buildgraph/rulesapplicator.h4
-rw-r--r--src/lib/corelib/buildgraph/rulesevaluationcontext.cpp3
-rw-r--r--src/lib/corelib/buildgraph/transformer.cpp18
-rw-r--r--src/lib/corelib/corelib.pro2
-rw-r--r--src/lib/corelib/corelib.qbs13
-rw-r--r--src/lib/corelib/jsextensions/propertylist.mm25
-rw-r--r--src/lib/corelib/jsextensions/utilitiesextension.cpp77
-rw-r--r--src/lib/corelib/language/evaluatorscriptclass.cpp2
-rw-r--r--src/lib/corelib/language/language.cpp11
-rw-r--r--src/lib/corelib/language/language.h2
-rw-r--r--src/lib/corelib/language/moduleloader.cpp15
-rw-r--r--src/lib/corelib/language/projectresolver.cpp3
-rw-r--r--src/lib/corelib/language/scriptengine.cpp6
-rw-r--r--src/lib/corelib/language/scriptengine.h4
-rw-r--r--src/lib/corelib/language/testdata/throwing-probe.qbs12
-rw-r--r--src/lib/corelib/language/tst_language.cpp29
-rw-r--r--src/lib/corelib/language/tst_language.h2
-rw-r--r--src/lib/corelib/tools/applecodesignutils.cpp143
-rw-r--r--src/lib/corelib/tools/applecodesignutils.h47
-rw-r--r--src/lib/corelib/tools/codelocation.h3
-rw-r--r--src/lib/corelib/tools/error.cpp48
-rw-r--r--src/lib/corelib/tools/error.h7
-rw-r--r--src/lib/corelib/tools/persistence.cpp2
-rw-r--r--src/lib/corelib/tools/tools.pri6
-rw-r--r--src/lib/qtprofilesetup/qtmoduleinfo.cpp7
-rw-r--r--src/plugins/scanner/cpp/cppscanner.cpp5
-rw-r--r--tests/auto/api/testdata/error-in-setup-run-environment/error-in-setup-run-environment.qbs5
-rw-r--r--tests/auto/api/testdata/error-in-setup-run-environment/modules/mymodule/mymodule.qbs7
-rw-r--r--tests/auto/api/testdata/moc-hpp-included/object2.h13
-rw-r--r--tests/auto/api/testdata/moc-hpp-included/object2.mm16
-rw-r--r--tests/auto/api/testdata/moc-hpp-included/project.qbs6
-rw-r--r--tests/auto/api/testdata/simple-probe/project.qbs6
-rw-r--r--tests/auto/api/tst_api.cpp30
-rw-r--r--tests/auto/api/tst_api.h1
-rw-r--r--tests/auto/blackbox/testdata/bundle-structure/bundle-structure.qbs167
-rw-r--r--tests/auto/blackbox/testdata/bundle-structure/dummy.c1
-rw-r--r--tests/auto/blackbox/testdata/bundle-structure/dummy.h0
-rw-r--r--tests/auto/blackbox/testdata/bundle-structure/dummy_p.h0
-rw-r--r--tests/auto/blackbox/testdata/bundle-structure/resource.txt0
-rw-r--r--tests/auto/blackbox/testdata/change-in-imported-file/prepare.js2
-rw-r--r--tests/auto/blackbox/testdata/concurrent-executor/concurrent-executor.qbs2
-rw-r--r--tests/auto/blackbox/testdata/deploymentTarget/deployment.qbs9
-rw-r--r--tests/auto/blackbox/testdata/deploymentTarget/main.c1
-rw-r--r--tests/auto/blackbox/testdata/enableExceptions/empty.m1
-rw-r--r--tests/auto/blackbox/testdata/enableExceptions/empty.mm1
-rw-r--r--tests/auto/blackbox/testdata/enableExceptions/emptymain.cpp1
-rw-r--r--tests/auto/blackbox/testdata/enableExceptions/exceptions-objc.qbs6
-rw-r--r--tests/auto/blackbox/testdata/enableExceptions/exceptions-objcpp-cpp.qbs6
-rw-r--r--tests/auto/blackbox/testdata/enableExceptions/exceptions-objcpp.qbs7
-rw-r--r--tests/auto/blackbox/testdata/enableExceptions/exceptions.qbs7
-rw-r--r--tests/auto/blackbox/testdata/enableExceptions/main.cpp8
-rw-r--r--tests/auto/blackbox/testdata/enableExceptions/main.m5
-rw-r--r--tests/auto/blackbox/testdata/enableExceptions/none.qbs10
-rw-r--r--tests/auto/blackbox/testdata/enableRtti/main.cpp23
-rw-r--r--tests/auto/blackbox/testdata/enableRtti/rtti.qbs13
-rw-r--r--tests/auto/blackbox/testdata/error-info/helper.js9
-rw-r--r--tests/auto/blackbox/testdata/error-info/project.qbs71
-rw-r--r--tests/auto/blackbox/testdata/linkerscripts/linkerscripts.qbs2
-rw-r--r--tests/auto/blackbox/testdata/nodejs/hello.qbs1
-rw-r--r--tests/auto/blackbox/testdata/probe-in-exported-module/dependee.qbs15
-rw-r--r--tests/auto/blackbox/testdata/probe-in-exported-module/dependency.qbs8
-rw-r--r--tests/auto/blackbox/testdata/probe-in-exported-module/modules/depmodule/depmodule.qbs21
-rw-r--r--tests/auto/blackbox/testdata/probe-in-exported-module/modules/mymodule/mymodule.qbs27
-rw-r--r--tests/auto/blackbox/testdata/probe-in-exported-module/probe-in-exported-module.qbs5
-rw-r--r--tests/auto/blackbox/testdata/probe-in-exported-module/test.in0
-rw-r--r--tests/auto/blackbox/testdata/probe-in-exported-module/test2.in0
-rw-r--r--tests/auto/blackbox/testdata/probeProperties/bin/tool0
-rw-r--r--tests/auto/blackbox/testdata/probeProperties/main.c1
-rw-r--r--tests/auto/blackbox/testdata/probeProperties/probeProperties.qbs30
-rw-r--r--tests/auto/blackbox/testdata/referenceErrorInExport/main.c1
-rw-r--r--tests/auto/blackbox/testdata/referenceErrorInExport/project.qbs20
-rw-r--r--tests/auto/blackbox/testdata/separate-debug-info/project.qbs73
-rw-r--r--tests/auto/blackbox/testdata/trackExternalProductChanges/fileList.js2
-rw-r--r--tests/auto/blackbox/testdata/trackExternalProductChanges/project.qbs2
-rw-r--r--tests/auto/blackbox/testdata/typescript/typescript.qbs3
-rw-r--r--tests/auto/blackbox/testdata/versionscript/versionscript.qbs2
-rw-r--r--tests/auto/blackbox/tst_blackbox.cpp537
-rw-r--r--tests/auto/blackbox/tst_blackbox.h11
125 files changed, 3542 insertions, 487 deletions
diff --git a/.gitignore b/.gitignore
index 636212ee5..af37f8f0f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
+.qmake.cache
+.qmake.stash
.qbs
build
*.dll
@@ -10,6 +12,8 @@ build
*.pdb
*.pro.user*
*.qbs.user*
+*.xcodeproj/
+target_wrapper.sh
*~
*.o
*.lib
diff --git a/dist/dist.qbs b/dist/dist.qbs
index a43f5820e..3278cd2c3 100644
--- a/dist/dist.qbs
+++ b/dist/dist.qbs
@@ -49,7 +49,7 @@ Product {
cmd.binaryFilePaths = inputs.installable.filter(function (artifact) {
return artifact.fileTags.contains("application")
|| artifact.fileTags.contains("dynamiclibrary");
- }).map(ModUtils.artifactInstalledFilePath);
+ }).map(function(a) { return ModUtils.artifactInstalledFilePath(a); });
cmd.sourceCode = function () {
var out;
var process;
@@ -90,7 +90,9 @@ Product {
prepare: {
var cmd = new JavaScriptCommand();
cmd.silent = true;
- cmd.inputFilePaths = inputs.installable.map(ModUtils.artifactInstalledFilePath);
+ cmd.inputFilePaths = inputs.installable.map(function(a) {
+ return ModUtils.artifactInstalledFilePath(a);
+ });
cmd.outputFilePath = output.filePath;
cmd.installRoot = product.moduleProperty("qbs", "installRoot");
cmd.sourceCode = function() {
diff --git a/doc/reference/items/artifact.qdoc b/doc/reference/items/artifact.qdoc
index 4c5e6b3ef..e9a6330a7 100644
--- a/doc/reference/items/artifact.qdoc
+++ b/doc/reference/items/artifact.qdoc
@@ -37,7 +37,8 @@
\title Artifact Item
\brief Describes a file produced by a \c Rule or \c Transformer.
- An \c Artifact represents a single file produced by a \c Rule or \c Transformer.
+ An \c Artifact represents a single file produced by a \l{Rule Item}{Rule} or
+ \l{Transformer Item}{Transformer}.
For example, if a rule produces three files, it needs to contain three Artifact items.
diff --git a/doc/reference/items/rule.qdoc b/doc/reference/items/rule.qdoc
index 37be27954..e74b6fd3d 100644
--- a/doc/reference/items/rule.qdoc
+++ b/doc/reference/items/rule.qdoc
@@ -149,8 +149,8 @@
\code
outputArtifacts: [{filePath: "myfile.txt", fileTags: ["foo", "bar"]}]
\endcode
- For a description of the possible properties, see the documentation of the Artifact
- item.
+ For a description of the possible properties, see the documentation of the
+ \l{Artifact item}.
Output artifacts can be specified either by \c{Rule.outputArtifacts} or by \c{Artifact}
items. Use \c{Rule.outputArtifacts} if the set of outputs is not fixed but dependent on
the input's content. If no file tags are provided, \QBS will apply all
diff --git a/doc/reference/jsextensions/jsextensions-general.qdoc b/doc/reference/jsextensions/jsextensions-general.qdoc
index 1e63ce574..61c95231b 100644
--- a/doc/reference/jsextensions/jsextensions-general.qdoc
+++ b/doc/reference/jsextensions/jsextensions-general.qdoc
@@ -75,6 +75,20 @@
\endcode
Returns \c{true} if the array contains the element \c{e}. Returns \c{false} otherwise.
+ \section2 Array.containsAll
+ \code
+ Array.containsAll(other: any[]): boolean
+ \endcode
+ Returns \c{true} if the array contains every element in the \c{other} array.
+ Returns \c{false} otherwise.
+
+ \section2 Array.containsAny
+ \code
+ Array.containsAny(other: any[]): boolean
+ \endcode
+ Returns \c{true} if the array contains some element(s) in the \c{other} array.
+ Returns \c{false} otherwise.
+
\section2 Array.uniqueConcat
\code
Array.uniqueConcat(other: any[]): any[]
diff --git a/doc/reference/modules/android-ndk-module.qdoc b/doc/reference/modules/android-ndk-module.qdoc
index 0d9e10e52..dc95ec10a 100644
--- a/doc/reference/modules/android-ndk-module.qdoc
+++ b/doc/reference/modules/android-ndk-module.qdoc
@@ -97,18 +97,6 @@
\li undefined
\li Whether to use the hard floating point variant of the armeabi-v7a ABI.
\row
- \li enableExceptions
- \li bool
- \li 1.4
- \li \c{appStl !== "system"}
- \li Whether to enable exceptions in C++ code.
- \row
- \li enableRtti
- \li bool
- \li 1.4
- \li \c{appStl !== "system"}
- \li Whether to enable runtime type information in C++ code.
- \row
\li ndkDir
\li path
\li 1.4
diff --git a/doc/reference/modules/bundle-module.qdoc b/doc/reference/modules/bundle-module.qdoc
index daa444c3f..471d44a8b 100644
--- a/doc/reference/modules/bundle-module.qdoc
+++ b/doc/reference/modules/bundle-module.qdoc
@@ -69,12 +69,11 @@
whether it should actually be built as a bundle.
\row
\li isShallow
- \li \c{bool}
+ \li \c{bool} (read only)
\li 1.4
- \li \c{true} for iOS applications
+ \li \c{false} on OS X, otherwise \c{true}
\li Whether the bundle directory tree is "shallow", i.e. whether it lacks a Contents
- subdirectory. This is the default for iOS applications and should normally never be
- changed.
+ subdirectory. This is the default on all platforms other than OS X.
\row
\li identifierPrefix
\li \c{string}
@@ -112,6 +111,14 @@
This property should almost never need to be changed, though specifying an
alternative package type for custom bundles is allowed.
\row
+ \li generatePackageInfo
+ \li \c{bool}
+ \li 1.5
+ \li \c{true} for applications, otherwise \c{false}
+ \li Whether to generate a PkgInfo file for the bundle.
+ This property should almost never need to be changed, though enabling it when specifying
+ an alternative package type for custom bundles using \c{packageType} is allowed.
+ \row
\li signature
\li \c{string}
\li 1.4
@@ -207,10 +214,13 @@
\row
\li infoPlistPath
\li 1.4
- \li Path that the Info.plist file will be written to. If \c{embedInfoPlist} is \c{true},
- this will point to a file in a temporary directory.
+ \li Path that the Info.plist file will be written to.
\row
- \li infoPlistPath
+ \li infoStringsPath
+ \li 1.5
+ \li Path that the InfoPlist.strings file will be written to.
+ \row
+ \li pkgInfoPath
\li 1.4
\li Path that the PkgInfo file will be written to.
\row
@@ -222,6 +232,14 @@
\li 1.4
\li Path that the main executable file will be written to.
\row
+ \li contentsFolderPath
+ \li 1.4
+ \li Path of the bundle's Contents subdirectory.
+ \row
+ \li documentationFolderPath
+ \li 1.5
+ \li Path of the directory where documentation will be written.
+ \row
\li executableFolderPath
\li 1.4
\li Path of the directory where the main exectuable will be written.
@@ -236,6 +254,14 @@
\li 1.4
\li Path of the directory where internal frameworks will be copied.
\row
+ \li javaFolderPath
+ \li 1.5
+ \li Path of the directory where Java content will be written.
+ \row
+ \li localizedResourcesFolderPath
+ \li 1.5
+ \li Path of the directory where localized resource files will be copied.
+ \row
\li pluginsFolderPath
\li 1.4
\li Path of the directory where plugins will be copied.
@@ -265,8 +291,9 @@
\li Path of the directory where non-localized resource files will be copied.
This is the same as the base resources path.
\row
- \li contentsFolderPath
- \li 1.4
- \li Path of the bundle's Contents subdirectory.
+ \li versionsFolderPath
+ \li 1.5
+ \li Path of the bundle's Versions subdirectory.
+ This is only relevant for (non-shallow) framework bundles.
\endtable
*/
diff --git a/doc/reference/modules/cpp-module.qdoc b/doc/reference/modules/cpp-module.qdoc
index 49d681260..0980f3d9e 100644
--- a/doc/reference/modules/cpp-module.qdoc
+++ b/doc/reference/modules/cpp-module.qdoc
@@ -329,7 +329,26 @@
toolchain is used.
\note For MSVC the default value is \c{"dynamic"}.
\note At the moment this property is only functional for MSVC.
-
+ \row
+ \li enableExceptions
+ \li \c{bool}
+ \li 1.5
+ \li \c{undefined}
+ \li Whether to enable exceptions in C++ code.
+ \row
+ \li exceptionHandlingModel
+ \li \c{string}
+ \li 1.5
+ \li \c{"default"}
+ \li The exception handling model to use. For MSVC, this can be \c{"default"}, \c{"seh"} or
+ \c{"externc"}. For all other compilers, \c{"default"} indicates the default or only
+ exception handling model.
+ \row
+ \li enableRtti
+ \li \c{bool}
+ \li 1.5
+ \li \c{undefined}
+ \li Whether to enable runtime type information in C++ code.
\row
\li enableReproducibleBuilds
\li \c{bool}
diff --git a/doc/reference/modules/xcode-module.qdoc b/doc/reference/modules/xcode-module.qdoc
index 4e772a573..b3f05c335 100644
--- a/doc/reference/modules/xcode-module.qdoc
+++ b/doc/reference/modules/xcode-module.qdoc
@@ -59,12 +59,6 @@
directory of the Xcode installation at its default location in /Applications.
Corresponds to the \c DEVELOPER_DIR environment variable.
\row
- \li provisioningProfile
- \li string
- \li 1.5
- \li \c undefined
- \li Name or UUID of the provisioning profile to embed in the product.
- \row
\li sdk
\li string
\li 1.5
@@ -75,26 +69,6 @@
available for that platform will be used. The default is the latest SDK available in the
Xcode installation for the current platform.
\row
- \li signingIdentity
- \li string
- \li 1.5
- \li \c undefined
- \li Search string used to find the certificate to sign the product. This does not have to be
- a full certificate name like "Mac Developer: John Doe (XXXXXXXXXX)", and can instead be
- a partial string like "Mac Developer".
- The search string should generally be one of the following:
- \list
- \li 3rd Party Mac Developer Application
- \li 3rd Party Mac Developer Installer
- \li Developer ID Application
- \li Developer ID Installer
- \li iPhone Developer
- \li iPhone Distribution
- \li Mac Developer
- \endlist
- See \l{https://developer.apple.com/library/mac/documentation/IDEs/Conceptual/AppDistributionGuide/MaintainingCertificates/MaintainingCertificates.html#//apple_ref/doc/uid/TP40012582-CH31-SW41}{Maintaining Your Signing Identities and Certificates}
- for complete documentation on the existing certificate types.
- \row
\li targetDevices
\li stringList
\li 1.5
@@ -105,32 +79,6 @@
the current platform.
\endtable
- \section1 Advanced Properties
-
- \table
- \header
- \li Property
- \li Type
- \li Since
- \li Default
- \li Description
- \row
- \li provisioningProfilesPath
- \li path
- \li 1.5
- \li \c{"~/Library/MobileDevice/Provisioning Profiles"}
- \li Path to directory containing provisioning profiles installed on the system.
- \row
- \li signingTimestamp
- \li string
- \li 1.5
- \li \c{"none"}
- \li URL of the timestamp authority server to be contacted to authenticate code signing.
- \c{undefined} indicates that a system-specific default should be used, and the empty
- string indicates the default server provided by Apple. \c{"none"} explicitly disables
- the use of timestamp services and this should not usually need to be changed.
- \endtable
-
\section1 Read-only Properties
\table
diff --git a/share/qbs/imports/qbs/DarwinTools/darwin-tools.js b/share/qbs/imports/qbs/DarwinTools/darwin-tools.js
index 670ca8181..ad67dc16b 100644
--- a/share/qbs/imports/qbs/DarwinTools/darwin-tools.js
+++ b/share/qbs/imports/qbs/DarwinTools/darwin-tools.js
@@ -31,38 +31,45 @@
var FileInfo = loadExtension("qbs.FileInfo");
var Utilities = loadExtension("qbs.Utilities");
+var _deviceMap = {
+ "mac": undefined, // only devices have an ID
+ "iphone": 1,
+ "ipad": 2,
+ "tv": 3,
+ "watch": 4,
+ "car": 5
+};
+
+var _platformMap = {
+ "ios": "iPhone",
+ "osx": "MacOSX",
+ "tvos": "AppleTV",
+ "watchos": "Watch"
+};
+
+var _platformDeviceMap = {
+ "ios": ["iphone", "ipad"],
+ "osx": ["mac"],
+ "tvos": ["tv"],
+ "watchos": ["watch"]
+}
+
/**
* Returns the numeric identifier corresponding to an Apple device name
* (i.e. for use by TARGETED_DEVICE_FAMILY).
*/
function appleDeviceNumber(deviceName) {
- if (deviceName === "mac") {
- return undefined; // only iOS devices have an ID
- } else if (deviceName === "iphone") {
- return 1;
- } else if (deviceName === "ipad") {
- return 2;
- } else if (deviceName === "tv") {
- return 3;
- } else if (deviceName === "watch") {
- return 4;
- } else if (deviceName === "car") {
- return 5;
- }
+ return _deviceMap[deviceName];
}
/**
* Returns the list of target devices available for the given qbs target OS list.
*/
function targetDevices(targetOS) {
- if (targetOS.contains("osx"))
- return ["mac"];
- if (targetOS.contains("ios"))
- return ["iphone", "ipad"];
- if (targetOS.contains("tvos"))
- return ["tv"];
- if (targetOS.contains("watchos"))
- return ["watch"];
+ for (var key in _platformDeviceMap) {
+ if (targetOS.contains(key))
+ return _platformDeviceMap[key];
+ }
}
/**
@@ -77,22 +84,26 @@ function targetedDeviceFamily(deviceNames) {
/**
* Returns the most appropriate Apple platform name given a targetOS list.
*/
-function applePlatformName(targetOSList) {
- if (targetOSList.contains("ios-simulator"))
- return "iphonesimulator";
- else if (targetOSList.contains("ios"))
- return "iphoneos";
- else if (targetOSList.contains("osx"))
- return "macosx";
- else if (targetOSList.contains("tvos-simulator"))
- return "appletvsimulator";
- else if (targetOSList.contains("tvos"))
- return "appletvos";
- else if (targetOSList.contains("watchos-simulator"))
- return "watchsimulator";
- else if (targetOSList.contains("watchos"))
- return "watchos";
- throw("No Apple platform corresponds to target OS list: " + targetOSList);
+function applePlatformName(targetOSList, platformType) {
+ return applePlatformDirectoryName(targetOSList, platformType).toLowerCase();
+}
+
+/**
+ * Returns the most appropriate Apple platform directory name given a targetOS list and version.
+ */
+function applePlatformDirectoryName(targetOSList, platformType, version, throwOnError) {
+ var suffixMap = {
+ "device": "OS",
+ "simulator": "Simulator"
+ };
+
+ for (var key in _platformMap) {
+ if (targetOSList.contains(key))
+ return _platformMap[key] + (suffixMap[platformType] || "") + (version || "");
+ }
+
+ if (throwOnError || throwOnError === undefined)
+ throw("No Apple platform corresponds to target OS list: " + targetOSList);
}
/**
diff --git a/share/qbs/imports/qbs/ModUtils/utils.js b/share/qbs/imports/qbs/ModUtils/utils.js
index 262704da9..493316850 100644
--- a/share/qbs/imports/qbs/ModUtils/utils.js
+++ b/share/qbs/imports/qbs/ModUtils/utils.js
@@ -452,7 +452,8 @@ var BlackboxOutputArtifactTracker = (function () {
"/B", "/S", "/A:-D"], true);
else
proc.exec("find", [dir, "-type", "f"], true);
- return proc.readStdOut().trim().split(/\r?\n/).map(FileInfo.fromWindowsSeparators);
+ return proc.readStdOut().trim().split(/\r?\n/).map(
+ function(p) { return FileInfo.fromWindowsSeparators(p); });
}
finally {
if (proc)
diff --git a/share/qbs/imports/qbs/PathTools/path-tools.js b/share/qbs/imports/qbs/PathTools/path-tools.js
index 5333127d8..02de91b4a 100644
--- a/share/qbs/imports/qbs/PathTools/path-tools.js
+++ b/share/qbs/imports/qbs/PathTools/path-tools.js
@@ -126,22 +126,21 @@ function debugInfoIsBundle(product) {
function debugInfoFileName(product) {
var suffix = "";
- // For bundled dSYMs, the suffix appears on the bundle name, not the actual debug info file
+ // For dSYM bundles, the DWARF debug info file has no suffix
if (!product.moduleProperty("qbs", "targetOS").contains("darwin")
|| !debugInfoIsBundle(product))
suffix = product.moduleProperty("cpp", "debugInfoSuffix");
- if (product.moduleProperty("bundle", "isBundle")) {
- if (!debugInfoIsBundle(product))
- return product.moduleProperty("bundle", "bundleName") + suffix;
- } else if (product.type.contains("application"))
- return applicationFileName(product) + suffix;
- else if (product.type.contains("dynamiclibrary"))
- return dynamicLibraryFileName(product) + suffix;
- else if (product.type.contains("loadablemodule"))
- return loadableModuleFileName(product) + suffix;
- else if (product.type.contains("staticlibrary"))
- return staticLibraryFileName(product) + suffix;
+ if (!product.moduleProperty("bundle", "isBundle")) {
+ if (product.type.contains("application"))
+ return applicationFileName(product) + suffix;
+ else if (product.type.contains("dynamiclibrary"))
+ return dynamicLibraryFileName(product) + suffix;
+ else if (product.type.contains("loadablemodule"))
+ return loadableModuleFileName(product) + suffix;
+ else if (product.type.contains("staticlibrary"))
+ return staticLibraryFileName(product) + suffix;
+ }
return product.targetName + suffix;
}
@@ -149,7 +148,7 @@ function debugInfoFileName(product) {
function debugInfoBundlePath(product) {
if (!debugInfoIsBundle(product))
return undefined;
- var suffix = product.moduleProperty("cpp", "debugInfoSuffix");
+ var suffix = product.moduleProperty("cpp", "debugInfoBundleSuffix");
if (product.moduleProperty("qbs", "targetOS").contains("darwin")
&& product.moduleProperty("bundle", "isBundle"))
return product.moduleProperty("bundle", "bundleName") + suffix;
@@ -161,6 +160,8 @@ function debugInfoFilePath(product) {
if (product.moduleProperty("qbs", "targetOS").contains("darwin") && debugInfoIsBundle(product)) {
return FileInfo.joinPaths(debugInfoBundlePath(product), "Contents", "Resources", "DWARF",
name);
+ } else if (product.moduleProperty("bundle", "isBundle")) {
+ return FileInfo.joinPaths(product.moduleProperty("bundle", "executableFolderPath"), name);
}
return name;
diff --git a/share/qbs/imports/qbs/Probes/NodeJsProbe.qbs b/share/qbs/imports/qbs/Probes/NodeJsProbe.qbs
index ecaf91180..2f648d19e 100644
--- a/share/qbs/imports/qbs/Probes/NodeJsProbe.qbs
+++ b/share/qbs/imports/qbs/Probes/NodeJsProbe.qbs
@@ -33,7 +33,7 @@ import qbs.Environment
import qbs.FileInfo
BinaryProbe {
- names: ["nodejs", "node"]
+ names: ["node", "nodejs"]
platformPaths: {
var paths = base;
if (qbs.hostOS.contains("windows")) {
diff --git a/share/qbs/imports/qbs/Probes/TypeScriptProbe.qbs b/share/qbs/imports/qbs/Probes/TypeScriptProbe.qbs
index cc7782a73..b0b4ecf14 100644
--- a/share/qbs/imports/qbs/Probes/TypeScriptProbe.qbs
+++ b/share/qbs/imports/qbs/Probes/TypeScriptProbe.qbs
@@ -41,6 +41,7 @@ BinaryProbe {
pathPrefixes: [packageManagerBinPath]
// Inputs
+ property path interpreterPath
property path packageManagerBinPath
property path packageManagerRootPath
@@ -50,6 +51,8 @@ BinaryProbe {
configure: {
if (!condition)
return;
+ if (!interpreterPath)
+ throw '"interpreterPath" must be specified';
if (!packageManagerBinPath)
throw '"packageManagerBinPath" must be specified';
if (!packageManagerRootPath)
@@ -59,7 +62,7 @@ BinaryProbe {
pathSuffixes, platformPaths, environmentPaths,
platformEnvironmentPaths, qbs.pathListSeparator);
result.version = result.found
- ? TypeScript.findTscVersion(result.filePath, packageManagerBinPath)
+ ? TypeScript.findTscVersion(result.filePath, interpreterPath)
: undefined;
if (FileInfo.fromNativeSeparators(packageManagerBinPath) !== result.path ||
!File.exists(FileInfo.fromNativeSeparators(packageManagerRootPath, "typescript"))) {
diff --git a/share/qbs/imports/qbs/Probes/path-probe.js b/share/qbs/imports/qbs/Probes/path-probe.js
index 4f634876a..53e04fa39 100644
--- a/share/qbs/imports/qbs/Probes/path-probe.js
+++ b/share/qbs/imports/qbs/Probes/path-probe.js
@@ -39,7 +39,7 @@ function configure(names, nameSuffixes, nameFilter, pathPrefixes, pathSuffixes,
throw '"names" must be specified';
var _names = ModUtils.concatAll(names);
if (nameFilter)
- _names = _names.map(nameFilter);
+ _names = _names.map(function(n) { return nameFilter(n); });
_names = ModUtils.concatAll.apply(undefined, _names.map(function(name) {
return (nameSuffixes || [""]).map(function(suffix) { return name + suffix; });
}));
@@ -53,8 +53,8 @@ function configure(names, nameSuffixes, nameFilter, pathPrefixes, pathSuffixes,
_paths = _paths.concat(value.split(pathListSeparator));
}
var _suffixes = ModUtils.concatAll('', pathSuffixes);
- _paths = _paths.map(FileInfo.fromNativeSeparators);
- _suffixes = _suffixes.map(FileInfo.fromNativeSeparators);
+ _paths = _paths.map(function(p) { return FileInfo.fromNativeSeparators(p); });
+ _suffixes = _suffixes.map(function(p) { return FileInfo.fromNativeSeparators(p); });
for (i = 0; i < _names.length; ++i) {
for (var j = 0; j < _paths.length; ++j) {
for (var k = 0; k < _suffixes.length; ++k) {
@@ -63,8 +63,15 @@ function configure(names, nameSuffixes, nameFilter, pathPrefixes, pathSuffixes,
return {
found: true,
filePath: _filePath,
- fileName: FileInfo.fileName(_filePath),
- path: FileInfo.path(_filePath)
+
+ // Manually specify the path components that constitute _filePath rather
+ // than using the FileInfo.path and FileInfo.fileName functions because we
+ // want to break _filePath into its constituent parts based on the input
+ // originally given by the user. For example, the FileInfo functions would
+ // produce a different result if any of the items in the names property
+ // contained more than a single path component.
+ fileName: _names[i],
+ path: FileInfo.joinPaths(_paths[j], _suffixes[k]),
}
}
}
diff --git a/share/qbs/imports/qbs/base/ApplicationExtension.qbs b/share/qbs/imports/qbs/base/ApplicationExtension.qbs
index 656007567..0e534de38 100644
--- a/share/qbs/imports/qbs/base/ApplicationExtension.qbs
+++ b/share/qbs/imports/qbs/base/ApplicationExtension.qbs
@@ -31,10 +31,20 @@
import qbs
XPCService {
+ Depends { name: "xcode" }
+
type: base.concat(["applicationextension"])
cpp.entryPoint: "_NSExtensionMain"
- cpp.frameworks: base.concat(["/System/Library/PrivateFrameworks/PlugInKit.framework"])
+ cpp.frameworks: {
+ var frameworks = base.concat(["Foundation"]);
+ if (qbs.targetOS.contains("osx") && parseInt(xcode.sdkVersion.split(".")[1], 10) < 11 ||
+ qbs.targetOS.contains("ios") && parseInt(xcode.sdkVersion.split(".")[0], 10) < 9) {
+ frameworks = base.concat(["/System/Library/PrivateFrameworks/PlugInKit.framework"]);
+ }
+ return frameworks;
+ }
+
cpp.requireAppExtensionSafeApi: true
xpcServiceType: undefined
diff --git a/share/qbs/modules/Android/ndk/ndk.qbs b/share/qbs/modules/Android/ndk/ndk.qbs
index d9ea534d5..ea7d48352 100644
--- a/share/qbs/modules/Android/ndk/ndk.qbs
+++ b/share/qbs/modules/Android/ndk/ndk.qbs
@@ -77,8 +77,6 @@ Module {
return cpp.toolchainPrefix + toolchainVersionNumber;
}
- property bool enableExceptions: appStl !== "system"
- property bool enableRtti: appStl !== "system"
property bool hardFloat
property string ndkDir: ndkProbe.path
property string platform: "android-9"
@@ -206,23 +204,13 @@ Module {
qbs.optimization: cpp.targetAbi === "androideabi" ? "small" : base
+ cpp.enableExceptions: appStl !== "system"
+ cpp.enableRtti: appStl !== "system"
+
cpp.commonCompilerFlags: NdkUtils.commonCompilerFlags(qbs.buildVariant, abi, hardFloat, armMode)
cpp.linkerFlags: NdkUtils.commonLinkerFlags(abi, hardFloat)
- cpp.cxxFlags: {
- var flags = [];
- if (enableExceptions)
- flags.push("-fexceptions");
- else
- flags.push("-fno-exceptions");
- if (enableRtti)
- flags.push("-frtti");
- else
- flags.push("-fno-rtti");
- return flags;
- }
-
cpp.libraryPaths: {
var prefix = FileInfo.joinPaths(cpp.sysroot, "usr");
var paths = [];
diff --git a/share/qbs/modules/bundle/BundleModule.qbs b/share/qbs/modules/bundle/BundleModule.qbs
index 8ec0e8458..88fb6ecd6 100644
--- a/share/qbs/modules/bundle/BundleModule.qbs
+++ b/share/qbs/modules/bundle/BundleModule.qbs
@@ -31,43 +31,80 @@
import qbs
import qbs.BundleTools
import qbs.DarwinTools
+import qbs.Environment
import qbs.File
import qbs.FileInfo
import qbs.ModUtils
import qbs.PropertyList
import qbs.TextFile
import qbs.Utilities
+import "bundle.js" as Bundle
Module {
+ Depends { name: "xcode"; required: false; }
+
+ Probe {
+ id: bundleSettingsProbe
+ condition: qbs.targetOS.contains("darwin")
+
+ property string xcodeDeveloperPath: xcode.developerPath
+
+ // Note that we include several settings pointing to properties which reference the output
+ // of this probe (WRAPPER_NAME, WRAPPER_EXTENSION, etc.). This is to ensure that derived
+ // properties take into account the value of these settings if the user customized them.
+ property var additionalSettings: ({
+ "DEVELOPMENT_LANGUAGE": "English",
+ "EXECUTABLE_VARIANT_SUFFIX": "", // e.g. _debug, _profile
+ "FRAMEWORK_VERSION": frameworkVersion,
+ "GENERATE_PKGINFO_FILE": generatePackageInfo !== undefined
+ ? (generatePackageInfo ? "YES" : "NO")
+ : undefined,
+ "PRODUCT_NAME": product.targetName,
+ "LOCAL_APPS_DIR": Environment.getEnv("HOME") + "/Applications",
+ "LOCAL_LIBRARY_DIR": Environment.getEnv("HOME") + "/Library",
+ "TARGET_BUILD_DIR": product.buildDirectory,
+ "WRAPPER_NAME": bundleName,
+ "WRAPPER_EXTENSION": extension
+ })
+
+ // Outputs
+ property var xcodeSettings: ({})
+
+ configure: {
+ var specsPath = path;
+ var specsSeparator = "-";
+ if (xcodeDeveloperPath && _useXcodeBuildSpecs) {
+ specsPath = xcodeDeveloperPath
+ + "/Platforms/MacOSX.platform/Developer/Library/Xcode/Specifications";
+ specsSeparator = " ";
+ }
+
+ var reader = new Bundle.XcodeBuildSpecsReader(specsPath,
+ specsSeparator,
+ additionalSettings,
+ !qbs.targetOS.contains("osx"));
+ var settings = reader.expandedSettings(_productTypeIdentifier);
+ if (settings) {
+ xcodeSettings = settings;
+ found = true;
+ } else {
+ xcodeSettings = {};
+ found = false;
+ }
+ }
+ }
+
additionalProductTypes: ["bundle"]
- property bool isBundle: qbs.targetOS.contains("darwin")
- && (product.type.contains("application")
- || product.type.contains("dynamiclibrary")
- || product.type.contains("loadablemodule"))
- && !product.consoleApplication
- property bool isShallow: !qbs.targetOS.contains("osx") && product.type.contains("application")
+ property bool isBundle: !product.consoleApplication && qbs.targetOS.contains("darwin") &&
+ product.type.containsAny(["application", "dynamiclibrary", "loadablemodule"])
+
+ readonly property bool isShallow: bundleSettingsProbe.xcodeSettings["SHALLOW_BUNDLE"] === "YES"
property string identifierPrefix: "org.example"
property string identifier: [identifierPrefix, Utilities.rfc1034Identifier(product.targetName)].join(".")
- property string extension: {
- if (packageType === undefined) {
- return "";
- } else if (packageType === "APPL") {
- return "app";
- } else if (packageType === "XPC!") {
- if (product.type.contains("applicationextension"))
- return "appex";
- return "xpc";
- } else if (packageType === "FMWK") {
- return "framework";
- } else{
- return "bundle";
- }
-
- // Also: kext, prefPane, qlgenerator, saver, mdimporter, or a custom extension
- }
+ property string extension: bundleSettingsProbe.xcodeSettings["WRAPPER_EXTENSION"]
property string packageType: {
if (product.type.contains("inapppurchase"))
@@ -76,20 +113,27 @@ Module {
return "XPC!";
if (product.type.contains("application"))
return "APPL";
- if (product.type.contains("dynamiclibrary") || product.type.contains("staticlibrary"))
+ if (product.type.containsAny(["dynamiclibrary", "staticlibrary"]))
return "FMWK";
+ if (product.type.contains("kernelmodule"))
+ return "KEXT";
return "BNDL";
}
property string signature: "????" // legacy creator code in Mac OS Classic (CFBundleSignature), can be ignored
- property string bundleName: product.targetName + (extension ? ("." + extension) : "")
+ property string bundleName: bundleSettingsProbe.xcodeSettings["WRAPPER_NAME"]
property string frameworkVersion: {
- if (packageType === "FMWK") {
- var n = parseInt(product.version, 10);
- return isNaN(n) ? 'A' : String(n);
- }
+ var n = parseInt(product.version, 10);
+ return isNaN(n) ? bundleSettingsProbe.xcodeSettings["FRAMEWORK_VERSION"] : String(n);
+ }
+
+ property bool generatePackageInfo: {
+ // Make sure to return undefined as default to indicate "not set"
+ var genPkgInfo = bundleSettingsProbe.xcodeSettings["GENERATE_PKGINFO_FILE"];
+ if (genPkgInfo)
+ return genPkgInfo === "YES";
}
property pathList publicHeaders
@@ -110,46 +154,34 @@ Module {
"/Versions/A/Support", lsregisterName);
// all paths are relative to the directory containing the bundle
- readonly property string infoPlistPath: {
- var path;
- if (!isBundle)
- path = FileInfo.joinPaths(".tmp", product.name);
- else if (packageType === "FMWK")
- path = unlocalizedResourcesFolderPath;
- else if (product.type.contains("inapppurchase"))
- path = bundleName;
- else
- path = contentsFolderPath;
-
- return FileInfo.joinPaths(path, product.type.contains("inapppurchase") ? "ContentInfo.plist" : "Info.plist");
- }
-
- readonly property string pkgInfoPath: FileInfo.joinPaths(packageType === "FMWK" ? bundleName : contentsFolderPath, "PkgInfo")
- readonly property string versionPlistPath: FileInfo.joinPaths(packageType === "FMWK" ? unlocalizedResourcesFolderPath : contentsFolderPath, "version.plist")
-
- readonly property string executablePath: FileInfo.joinPaths(executableFolderPath, product.targetName)
-
- readonly property string executableFolderPath: (!isShallow && packageType !== "FMWK" && !isShallowContents) ? FileInfo.joinPaths(contentsFolderPath, "MacOS") : contentsFolderPath
- readonly property string executablesFolderPath: packageType === "FMWK" ? unlocalizedResourcesFolderPath : FileInfo.joinPaths(contentsFolderPath, !isShallowContents ? "Executables" : "")
- readonly property string frameworksFolderPath: FileInfo.joinPaths(contentsFolderPath, !isShallowContents ? "Frameworks" : "")
- readonly property string pluginsFolderPath: packageType === "FMWK" ? unlocalizedResourcesFolderPath : FileInfo.joinPaths(contentsFolderPath, !isShallowContents ? "PlugIns" : "")
- readonly property string privateHeadersFolderPath: FileInfo.joinPaths(contentsFolderPath, !isShallowContents ? "PrivateHeaders" : "")
- readonly property string publicHeadersFolderPath: FileInfo.joinPaths(contentsFolderPath, !isShallowContents ? "Headers" : "")
- readonly property string scriptsFolderPath: FileInfo.joinPaths(unlocalizedResourcesFolderPath, "Scripts")
- readonly property string sharedFrameworksFolderPath: FileInfo.joinPaths(contentsFolderPath, !isShallowContents ? "SharedFrameworks" : "")
- readonly property string sharedSupportFolderPath: packageType === "FMWK" ? unlocalizedResourcesFolderPath : FileInfo.joinPaths(contentsFolderPath, !isShallowContents ? "SharedSupport" : "")
- readonly property string unlocalizedResourcesFolderPath: isShallow ? contentsFolderPath : FileInfo.joinPaths(contentsFolderPath, !isShallowContents ? "Resources" : "")
-
- readonly property string contentsFolderPath: {
- if (packageType === "FMWK")
- return FileInfo.joinPaths(bundleName, "Versions", frameworkVersion);
- else if (!isShallow)
- return FileInfo.joinPaths(bundleName, "Contents");
- return bundleName;
- }
+ readonly property string infoPlistPath: bundleSettingsProbe.xcodeSettings["INFOPLIST_PATH"]
+ readonly property string infoStringsPath: bundleSettingsProbe.xcodeSettings["INFOSTRINGS_PATH"]
+ readonly property string pbdevelopmentPlistPath: bundleSettingsProbe.xcodeSettings["PBDEVELOPMENTPLIST_PATH"]
+ readonly property string pkgInfoPath: bundleSettingsProbe.xcodeSettings["PKGINFO_PATH"]
+ readonly property string versionPlistPath: bundleSettingsProbe.xcodeSettings["VERSIONPLIST_PATH"]
+
+ readonly property string executablePath: bundleSettingsProbe.xcodeSettings["EXECUTABLE_PATH"]
+
+ readonly property string contentsFolderPath: bundleSettingsProbe.xcodeSettings["CONTENTS_FOLDER_PATH"]
+ readonly property string documentationFolderPath: bundleSettingsProbe.xcodeSettings["DOCUMENTATION_FOLDER_PATH"]
+ readonly property string executableFolderPath: bundleSettingsProbe.xcodeSettings["EXECUTABLE_FOLDER_PATH"]
+ readonly property string executablesFolderPath: bundleSettingsProbe.xcodeSettings["EXECUTABLES_FOLDER_PATH"]
+ readonly property string frameworksFolderPath: bundleSettingsProbe.xcodeSettings["FRAMEWORKS_FOLDER_PATH"]
+ readonly property string javaFolderPath: bundleSettingsProbe.xcodeSettings["JAVA_FOLDER_PATH"]
+ readonly property string localizedResourcesFolderPath: bundleSettingsProbe.xcodeSettings["LOCALIZED_RESOURCES_FOLDER_PATH"]
+ readonly property string pluginsFolderPath: bundleSettingsProbe.xcodeSettings["PLUGINS_FOLDER_PATH"]
+ readonly property string privateHeadersFolderPath: bundleSettingsProbe.xcodeSettings["PRIVATE_HEADERS_FOLDER_PATH"]
+ readonly property string publicHeadersFolderPath: bundleSettingsProbe.xcodeSettings["PUBLIC_HEADERS_FOLDER_PATH"]
+ readonly property string scriptsFolderPath: bundleSettingsProbe.xcodeSettings["SCRIPTS_FOLDER_PATH"]
+ readonly property string sharedFrameworksFolderPath: bundleSettingsProbe.xcodeSettings["SHARED_FRAMEWORKS_FOLDER_PATH"]
+ readonly property string sharedSupportFolderPath: bundleSettingsProbe.xcodeSettings["SHARED_SUPPORT_FOLDER_PATH"]
+ readonly property string unlocalizedResourcesFolderPath: bundleSettingsProbe.xcodeSettings["UNLOCALIZED_RESOURCES_FOLDER_PATH"]
+ readonly property string versionsFolderPath: bundleSettingsProbe.xcodeSettings["VERSIONS_FOLDER_PATH"]
// private properties
- readonly property bool isShallowContents: product.type.contains("inapppurchase")
+ property string _productTypeIdentifier: Bundle.productTypeIdentifier(product.type)
+
+ property bool _useXcodeBuildSpecs: true // false to use ONLY the qbs build specs
readonly property var extraEnv: ({
"PRODUCT_BUNDLE_IDENTIFIER": identifier
@@ -182,6 +214,47 @@ Module {
};
}
+ validate: {
+ if (!qbs.targetOS.contains("darwin"))
+ return;
+ if (!bundleSettingsProbe.found) {
+ var error = "Bundle product type " + _productTypeIdentifier + " is not supported.";
+ if ((_productTypeIdentifier || "").startsWith("com.apple.product-type."))
+ error += " You may need to upgrade Xcode.";
+ throw error;
+ }
+
+ var validator = new ModUtils.PropertyValidator("bundle");
+ validator.setRequiredProperty("bundleName", bundleName);
+ validator.setRequiredProperty("infoPlistPath", infoPlistPath);
+ validator.setRequiredProperty("pbdevelopmentPlistPath", pbdevelopmentPlistPath);
+ validator.setRequiredProperty("pkgInfoPath", pkgInfoPath);
+ validator.setRequiredProperty("versionPlistPath", versionPlistPath);
+ validator.setRequiredProperty("executablePath", executablePath);
+ validator.setRequiredProperty("contentsFolderPath", contentsFolderPath);
+ validator.setRequiredProperty("documentationFolderPath", documentationFolderPath);
+ validator.setRequiredProperty("executableFolderPath", executableFolderPath);
+ validator.setRequiredProperty("executablesFolderPath", executablesFolderPath);
+ validator.setRequiredProperty("frameworksFolderPath", frameworksFolderPath);
+ validator.setRequiredProperty("javaFolderPath", javaFolderPath);
+ validator.setRequiredProperty("localizedResourcesFolderPath", localizedResourcesFolderPath);
+ validator.setRequiredProperty("pluginsFolderPath", pluginsFolderPath);
+ validator.setRequiredProperty("privateHeadersFolderPath", privateHeadersFolderPath);
+ validator.setRequiredProperty("publicHeadersFolderPath", publicHeadersFolderPath);
+ validator.setRequiredProperty("scriptsFolderPath", scriptsFolderPath);
+ validator.setRequiredProperty("sharedFrameworksFolderPath", sharedFrameworksFolderPath);
+ validator.setRequiredProperty("sharedSupportFolderPath", sharedSupportFolderPath);
+ validator.setRequiredProperty("unlocalizedResourcesFolderPath", unlocalizedResourcesFolderPath);
+
+ if (packageType === "FMWK") {
+ validator.setRequiredProperty("frameworkVersion", frameworkVersion);
+ validator.setRequiredProperty("versionsFolderPath", versionsFolderPath);
+ }
+
+ // extension and infoStringsPath might not be set
+ return validator.validate();
+ }
+
FileTagger {
fileTags: ["infoplist"]
patterns: ["Info.plist", "*-Info.plist"]
@@ -199,9 +272,13 @@ Module {
outputFileTags: ["aggregate_infoplist"]
outputArtifacts: {
var artifacts = [];
- if (ModUtils.moduleProperty(product, "isBundle") || ModUtils.moduleProperty(product, "embedInfoPlist")) {
+ var embed = ModUtils.moduleProperty(product, "embedInfoPlist");
+ if (ModUtils.moduleProperty(product, "isBundle") || embed) {
artifacts.push({
- filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "infoPlistPath")),
+ filePath: FileInfo.joinPaths(
+ product.destinationDirectory, embed
+ ? product.name + "-Info.plist"
+ : ModUtils.moduleProperty(product, "infoPlistPath")),
fileTags: ["aggregate_infoplist"]
});
}
@@ -378,7 +455,7 @@ Module {
outputFileTags: ["pkginfo"]
outputArtifacts: {
var artifacts = [];
- if (ModUtils.moduleProperty(product, "isBundle")) {
+ if (ModUtils.moduleProperty(product, "isBundle") && ModUtils.moduleProperty(product, "generatePackageInfo")) {
artifacts.push({
filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "pkgInfoPath")),
fileTags: ["pkginfo"]
@@ -443,7 +520,8 @@ Module {
}
var packageType = ModUtils.moduleProperty(product, "packageType");
- if (packageType === "FMWK") {
+ var isShallow = ModUtils.moduleProperty(product, "isShallow");
+ if (packageType === "FMWK" && !isShallow) {
var publicHeaders = ModUtils.moduleProperties(product, "publicHeaders");
if (publicHeaders && publicHeaders.length) {
artifacts.push({
@@ -471,7 +549,7 @@ Module {
});
artifacts.push({
- filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "bundleName"), "Versions", "Current"),
+ filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "versionsFolderPath"), "Current"),
fileTags: ["bundle.symlink.version"]
});
}
diff --git a/share/qbs/modules/bundle/MacOSX-Package-Types.xcspec b/share/qbs/modules/bundle/MacOSX-Package-Types.xcspec
new file mode 100644
index 000000000..b36353fc7
--- /dev/null
+++ b/share/qbs/modules/bundle/MacOSX-Package-Types.xcspec
@@ -0,0 +1,462 @@
+[
+ {
+ "DefaultBuildSettings" : {
+ "EXECUTABLE_PATH" : "$(EXECUTABLE_NAME)",
+ "EXECUTABLE_PREFIX" : "",
+ "EXECUTABLE_SUFFIX" : "",
+ "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)"
+ },
+ "Identifier" : "com.apple.package-type.mach-o-executable",
+ "Type" : "PackageType",
+ "Name" : "Mach-O Executable",
+ "Description" : "Mach-O executable",
+ "ProductReference" : {
+ "FileType" : "compiled.mach-o.executable",
+ "Name" : "$(EXECUTABLE_NAME)",
+ "IsLaunchable" : "YES"
+ }
+ },
+ {
+ "DefaultBuildSettings" : {
+ "EXECUTABLE_PATH" : "$(EXECUTABLE_NAME)",
+ "EXECUTABLE_PREFIX" : "",
+ "EXECUTABLE_SUFFIX" : "",
+ "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)"
+ },
+ "Identifier" : "com.apple.package-type.mach-o-objfile",
+ "Type" : "PackageType",
+ "Name" : "Mach-O Object File",
+ "Description" : "Mach-O Object File",
+ "ProductReference" : {
+ "FileType" : "compiled.mach-o.objfile",
+ "Name" : "$(EXECUTABLE_NAME)",
+ "IsLaunchable" : "NO"
+ }
+ },
+ {
+ "DefaultBuildSettings" : {
+ "EXECUTABLE_PATH" : "$(EXECUTABLE_NAME)",
+ "EXECUTABLE_PREFIX" : "",
+ "EXECUTABLE_SUFFIX" : "",
+ "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)"
+ },
+ "Identifier" : "com.apple.package-type.mach-o-dylib",
+ "Type" : "PackageType",
+ "Name" : "Mach-O Dynamic Library",
+ "Description" : "Mach-O dynamic library",
+ "ProductReference" : {
+ "FileType" : "compiled.mach-o.dylib",
+ "Name" : "$(EXECUTABLE_NAME)",
+ "IsLaunchable" : "NO"
+ }
+ },
+ {
+ "DefaultBuildSettings" : {
+ "EXECUTABLE_PATH" : "$(EXECUTABLE_NAME)",
+ "EXECUTABLE_PREFIX" : "lib",
+ "EXECUTABLE_SUFFIX" : ".a",
+ "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)"
+ },
+ "Identifier" : "com.apple.package-type.static-library",
+ "Type" : "PackageType",
+ "Name" : "Mach-O Static Library",
+ "Description" : "Mach-O static library",
+ "ProductReference" : {
+ "FileType" : "archive.ar",
+ "Name" : "$(EXECUTABLE_NAME)",
+ "IsLaunchable" : "NO"
+ }
+ },
+ {
+ "DefaultBuildSettings" : {
+ "EXECUTABLE_PATH" : "$(EXECUTABLE_NAME)",
+ "EXECUTABLE_PREFIX" : "",
+ "EXECUTABLE_SUFFIX" : ".dylib",
+ "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)"
+ },
+ "Identifier" : "com.apple.package-type.mach-o-bundle",
+ "Type" : "PackageType",
+ "Name" : "Mach-O Loadable",
+ "Description" : "Mach-O loadable",
+ "ProductReference" : {
+ "FileType" : "compiled.mach-o.bundle",
+ "Name" : "$(EXECUTABLE_NAME)",
+ "IsLaunchable" : "NO"
+ }
+ },
+ {
+ "DefaultBuildSettings" : {
+ "PUBLIC_HEADERS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/Headers",
+ "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)",
+ "EXECUTABLE_PREFIX" : "",
+ "PLUGINS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/PlugIns",
+ "DOCUMENTATION_FOLDER_PATH" : "$(LOCALIZED_RESOURCES_FOLDER_PATH)\/Documentation",
+ "EXECUTABLES_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/Executables",
+ "INFOSTRINGS_PATH" : "$(LOCALIZED_RESOURCES_FOLDER_PATH)\/InfoPlist.strings",
+ "INFOPLIST_PATH" : "$(CONTENTS_FOLDER_PATH)\/Info.plist",
+ "EXECUTABLE_SUFFIX" : "",
+ "VERSIONPLIST_PATH" : "$(CONTENTS_FOLDER_PATH)\/version.plist",
+ "SHARED_SUPPORT_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/SharedSupport",
+ "EXECUTABLE_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/MacOS",
+ "PBDEVELOPMENTPLIST_PATH" : "$(CONTENTS_FOLDER_PATH)\/pbdevelopment.plist",
+ "FRAMEWORKS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/Frameworks",
+ "LOCALIZED_RESOURCES_FOLDER_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)\/$(DEVELOPMENT_LANGUAGE).lproj",
+ "SCRIPTS_FOLDER_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)\/Scripts",
+ "WRAPPER_PREFIX" : "",
+ "PRIVATE_HEADERS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/PrivateHeaders",
+ "CONTENTS_FOLDER_PATH" : "$(WRAPPER_NAME)\/Contents",
+ "WRAPPER_NAME" : "$(WRAPPER_PREFIX)$(PRODUCT_NAME)$(WRAPPER_SUFFIX)",
+ "PKGINFO_PATH" : "$(CONTENTS_FOLDER_PATH)\/PkgInfo",
+ "EXECUTABLE_PATH" : "$(EXECUTABLE_FOLDER_PATH)\/$(EXECUTABLE_NAME)",
+ "UNLOCALIZED_RESOURCES_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/Resources",
+ "JAVA_FOLDER_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)\/Java",
+ "SHARED_FRAMEWORKS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/SharedFrameworks",
+ "WRAPPER_SUFFIX" : ".bundle"
+ },
+ "Identifier" : "com.apple.package-type.wrapper",
+ "Type" : "PackageType",
+ "Name" : "Wrapper",
+ "Description" : "Wrapper",
+ "ProductReference" : {
+ "FileType" : "wrapper.cfbundle",
+ "Name" : "$(WRAPPER_NAME)",
+ "IsLaunchable" : "NO"
+ }
+ },
+ {
+ "ProductReference" : {
+ "FileType" : "wrapper.cfbundle",
+ "Name" : "$(WRAPPER_NAME)",
+ "IsLaunchable" : "NO"
+ },
+ "DefaultBuildSettings" : {
+ "CONTENTS_FOLDER_PATH" : "$(WRAPPER_NAME)",
+ "UNLOCALIZED_RESOURCES_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)",
+ "SHALLOW_BUNDLE" : "YES",
+ "EXECUTABLE_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)"
+ },
+ "Type" : "PackageType",
+ "BasedOn" : "com.apple.package-type.wrapper",
+ "Name" : "Wrapper (Shallow)",
+ "Identifier" : "com.apple.package-type.wrapper.shallow",
+ "Description" : "Shallow Wrapper"
+ },
+ {
+ "ProductReference" : {
+ "FileType" : "wrapper.application",
+ "Name" : "$(WRAPPER_NAME)",
+ "IsLaunchable" : "YES"
+ },
+ "DefaultBuildSettings" : {
+ "GENERATE_PKGINFO_FILE" : "YES"
+ },
+ "Type" : "PackageType",
+ "BasedOn" : "com.apple.package-type.wrapper",
+ "Name" : "Application Wrapper",
+ "Identifier" : "com.apple.package-type.wrapper.application",
+ "Description" : "Application Wrapper"
+ },
+ {
+ "ProductReference" : {
+ "FileType" : "wrapper.application",
+ "Name" : "$(WRAPPER_NAME)",
+ "IsLaunchable" : "YES"
+ },
+ "DefaultBuildSettings" : {
+ "UNLOCALIZED_RESOURCES_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)",
+ "SHALLOW_BUNDLE" : "YES",
+ "GENERATE_PKGINFO_FILE" : "YES"
+ },
+ "Type" : "PackageType",
+ "BasedOn" : "com.apple.package-type.wrapper.shallow",
+ "Name" : "Application Wrapper (Shallow)",
+ "Identifier" : "com.apple.package-type.wrapper.application.shallow",
+ "Description" : "Shallow Application Wrapper"
+ },
+ {
+ "ProductReference" : {
+ "FileType" : "wrapper.cfbundle",
+ "Name" : "$(WRAPPER_NAME)",
+ "IsLaunchable" : "NO"
+ },
+ "DefaultBuildSettings" : {
+ "PRIVATE_HEADERS_FOLDER_PATH" : "$(KEXT_FRAMEWORK)\/Contents\/PrivateHeaders\/$(KEXT_FAMILY_NAME)",
+ "PUBLIC_HEADERS_FOLDER_PATH" : "$(KEXT_FRAMEWORK)\/Contents\/Headers\/$(KEXT_FAMILY_NAME)"
+ },
+ "Type" : "PackageType",
+ "BasedOn" : "com.apple.package-type.wrapper",
+ "Name" : "Kernel Extension Wrapper",
+ "Identifier" : "com.apple.package-type.wrapper.kernel-extension",
+ "Description" : "Kernel Extension Wrapper"
+ },
+ {
+ "ProductReference" : {
+ "FileType" : "wrapper.cfbundle",
+ "Name" : "$(WRAPPER_NAME)",
+ "IsLaunchable" : "NO"
+ },
+ "DefaultBuildSettings" : {
+ "PRIVATE_HEADERS_FOLDER_PATH" : "$(KEXT_FRAMEWORK)\/Contents\/PrivateHeaders\/$(KEXT_FAMILY_NAME)",
+ "PUBLIC_HEADERS_FOLDER_PATH" : "$(KEXT_FRAMEWORK)\/Contents\/Headers\/$(KEXT_FAMILY_NAME)",
+ "SHALLOW_BUNDLE" : "YES"
+ },
+ "Type" : "PackageType",
+ "BasedOn" : "com.apple.package-type.wrapper.shallow",
+ "Name" : "Kernel Extension Wrapper (Shallow)",
+ "Identifier" : "com.apple.package-type.wrapper.kernel-extension.shallow",
+ "Description" : "Shallow Kernel Extension Wrapper"
+ },
+ {
+ "DefaultBuildSettings" : {
+ "PUBLIC_HEADERS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/Headers",
+ "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)",
+ "EXECUTABLE_PREFIX" : "",
+ "PLUGINS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/PlugIns",
+ "DOCUMENTATION_FOLDER_PATH" : "$(LOCALIZED_RESOURCES_FOLDER_PATH)\/Documentation",
+ "EXECUTABLES_FOLDER_PATH" : "$(LOCALIZED_RESOURCES_FOLDER_PATH)",
+ "INFOPLIST_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)\/Info.plist",
+ "EXECUTABLE_SUFFIX" : "",
+ "INFOPLISTSTRINGS_PATH" : "$(LOCALIZED_RESOURCES_FOLDER_PATH)\/InfoPlist.strings",
+ "VERSIONPLIST_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)\/version.plist",
+ "SHARED_SUPPORT_FOLDER_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)",
+ "EXECUTABLE_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)",
+ "PBDEVELOPMENTPLIST_PATH" : "$(CONTENTS_FOLDER_PATH)\/pbdevelopment.plist",
+ "VERSIONS_FOLDER_PATH" : "$(WRAPPER_NAME)\/Versions",
+ "FRAMEWORKS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/Frameworks",
+ "CODESIGNING_FOLDER_PATH" : "$(TARGET_BUILD_DIR)\/$(CONTENTS_FOLDER_PATH)",
+ "LOCALIZED_RESOURCES_FOLDER_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)\/$(DEVELOPMENT_LANGUAGE).lproj",
+ "SCRIPTS_FOLDER_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)\/Scripts",
+ "WRAPPER_PREFIX" : "",
+ "PRIVATE_HEADERS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/PrivateHeaders",
+ "CURRENT_VERSION" : "Current",
+ "PKGINFO_PATH" : "$(WRAPPER_NAME)\/PkgInfo",
+ "WRAPPER_NAME" : "$(WRAPPER_PREFIX)$(PRODUCT_NAME)$(WRAPPER_SUFFIX)",
+ "CONTENTS_FOLDER_PATH" : "$(VERSIONS_FOLDER_PATH)\/$(FRAMEWORK_VERSION)",
+ "EXECUTABLE_PATH" : "$(EXECUTABLE_FOLDER_PATH)\/$(EXECUTABLE_NAME)",
+ "UNLOCALIZED_RESOURCES_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/Resources",
+ "JAVA_FOLDER_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)\/Java",
+ "SHARED_FRAMEWORKS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/SharedFrameworks",
+ "WRAPPER_SUFFIX" : ".framework"
+ },
+ "Identifier" : "com.apple.package-type.wrapper.framework",
+ "Type" : "PackageType",
+ "Name" : "Framework Wrapper",
+ "Description" : "Framework wrapper",
+ "ProductReference" : {
+ "FileType" : "wrapper.framework",
+ "Name" : "$(WRAPPER_NAME)",
+ "IsLaunchable" : "NO"
+ }
+ },
+ {
+ "ProductReference" : {
+ "FileType" : "wrapper.framework.static",
+ "Name" : "$(WRAPPER_NAME)",
+ "IsLaunchable" : "NO"
+ },
+ "DefaultBuildSettings" : {
+ "EXECUTABLE_SUFFIX" : "",
+ "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)",
+ "EXECUTABLE_PREFIX" : ""
+ },
+ "Type" : "PackageType",
+ "BasedOn" : "com.apple.package-type.wrapper.framework",
+ "Name" : "Mach-O Static Framework",
+ "Identifier" : "com.apple.package-type.wrapper.framework.static",
+ "Description" : "Mach-O static framework"
+ },
+ {
+ "ProductReference" : {
+ "FileType" : "wrapper.framework",
+ "Name" : "$(WRAPPER_NAME)",
+ "IsLaunchable" : "NO"
+ },
+ "DefaultBuildSettings" : {
+ "UNLOCALIZED_RESOURCES_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)",
+ "CONTENTS_FOLDER_PATH" : "$(WRAPPER_NAME)",
+ "SHALLOW_BUNDLE" : "YES",
+ "VERSIONS_FOLDER_PATH" : "$(WRAPPER_NAME)"
+ },
+ "Type" : "PackageType",
+ "BasedOn" : "com.apple.package-type.wrapper.framework",
+ "Name" : "Shallow Framework Wrapper",
+ "Identifier" : "com.apple.package-type.wrapper.framework.shallow",
+ "Description" : "Shallow framework wrapper"
+ },
+ {
+ "ProductReference" : {
+ "FileType" : "wrapper.cfbundle",
+ "Name" : "$(WRAPPER_NAME)",
+ "IsLaunchable" : "NO"
+ },
+ "DefaultBuildSettings" : {
+ "WRAPPER_SUFFIX" : "xctest"
+ },
+ "Type" : "PackageType",
+ "BasedOn" : "com.apple.package-type.wrapper",
+ "Name" : "Unit Test Bundle",
+ "Identifier" : "com.apple.package-type.bundle.unit-test",
+ "Description" : "Unit Test Bundle"
+ },
+ {
+ "ProductReference" : {
+ "FileType" : "wrapper.cfbundle",
+ "Name" : "$(WRAPPER_NAME)",
+ "IsLaunchable" : "NO"
+ },
+ "DefaultBuildSettings" : {
+ "WRAPPER_SUFFIX" : "octest"
+ },
+ "Type" : "PackageType",
+ "BasedOn" : "com.apple.package-type.wrapper",
+ "Name" : "OCUnit Test Bundle",
+ "Identifier" : "com.apple.package-type.bundle.ocunit-test",
+ "Description" : "OCUnit Test Bundle"
+ },
+ {
+ "ProductReference" : {
+ "FileType" : "folder",
+ "Name" : "$(WRAPPER_NAME)",
+ "IsLaunchable" : "NO"
+ },
+ "DefaultBuildSettings" : {
+ "EXECUTABLE_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)",
+ "JAVA_FOLDER_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)",
+ "INFOSTRINGS_PATH" : "$(LOCALIZED_RESOURCES_FOLDER_PATH)\/ContentInfo.strings",
+ "INFOPLIST_PATH" : "$(WRAPPER_NAME)\/ContentInfo.plist",
+ "WRAPPER_SUFFIX" : "",
+ "UNLOCALIZED_RESOURCES_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)",
+ "DOCUMENTATION_FOLDER_PATH" : "$(LOCALIZED_RESOURCES_FOLDER_PATH)",
+ "EXECUTABLES_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)",
+ "LOCALIZED_RESOURCES_FOLDER_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)\/$(DEVELOPMENT_LANGUAGE).lproj",
+ "PLUGINS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)",
+ "PUBLIC_HEADERS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)",
+ "SHARED_SUPPORT_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)",
+ "SHARED_FRAMEWORKS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)",
+ "PRIVATE_HEADERS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)",
+ "SCRIPTS_FOLDER_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)",
+ "FRAMEWORKS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)"
+ },
+ "Type" : "PackageType",
+ "BasedOn" : "com.apple.package-type.wrapper",
+ "Name" : "In-App Purchase Content",
+ "Identifier" : "com.apple.package-type.in-app-purchase-content",
+ "Description" : "In-App Purchase Content"
+ },
+ {
+ "ProductReference" : {
+ "FileType" : "wrapper.xpc-service",
+ "Name" : "$(WRAPPER_NAME)",
+ "IsLaunchable" : "NO"
+ },
+ "DefaultBuildSettings" : {
+ "WRAPPER_SUFFIX" : ".xpc"
+ },
+ "Type" : "PackageType",
+ "BasedOn" : "com.apple.package-type.wrapper",
+ "Name" : "XPC Service",
+ "Identifier" : "com.apple.package-type.xpc-service",
+ "Description" : "XPC Service"
+ },
+ {
+ "ProductReference" : {
+ "FileType" : "wrapper.app-extension",
+ "Name" : "$(WRAPPER_NAME)",
+ "IsLaunchable" : "NO"
+ },
+ "DefaultBuildSettings" : {
+ "WRAPPER_SUFFIX" : ".pluginkit"
+ },
+ "Type" : "PackageType",
+ "BasedOn" : "com.apple.package-type.xpc-service",
+ "Name" : "PlugInKit PlugIn",
+ "Identifier" : "com.apple.package-type.pluginkit-plugin",
+ "Description" : "PlugInKit PlugIn"
+ },
+ {
+ "ProductReference" : {
+ "FileType" : "wrapper.app-extension",
+ "Name" : "$(WRAPPER_NAME)",
+ "IsLaunchable" : "NO"
+ },
+ "DefaultBuildSettings" : {
+ "WRAPPER_SUFFIX" : ".appex"
+ },
+ "Type" : "PackageType",
+ "BasedOn" : "com.apple.package-type.pluginkit-plugin",
+ "Name" : "App Extension",
+ "Identifier" : "com.apple.package-type.app-extension",
+ "Description" : "App Extension"
+ },
+ {
+ "ProductReference" : {
+ "FileType" : "wrapper.spotlight-importer",
+ "Name" : "$(WRAPPER_NAME)",
+ "IsLaunchable" : "NO"
+ },
+ "DefaultBuildSettings" : {
+
+ },
+ "Type" : "PackageType",
+ "BasedOn" : "com.apple.package-type.wrapper",
+ "Name" : "Spotlight Importer",
+ "Identifier" : "com.apple.package-type.spotlight-importer",
+ "Description" : "Spotlight Importer"
+ },
+ {
+ "DefaultBuildSettings" : {
+ "EXECUTABLE_PATH" : "$(EXECUTABLE_NAME)",
+ "JAVA_MAKE_ZIPFILE" : "NO",
+ "JAVA_ARCHIVE_CLASSES" : "YES",
+ "EXECUTABLE_PREFIX" : "",
+ "EXECUTABLE_SUFFIX" : ".jar",
+ "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_SUFFIX)"
+ },
+ "Identifier" : "com.apple.package-type.jarfile",
+ "Type" : "PackageType",
+ "Name" : "Jar File",
+ "Description" : "Jar file",
+ "ProductReference" : {
+ "FileType" : "archive.jar",
+ "Name" : "$(EXECUTABLE_NAME)",
+ "IsLaunchable" : "NO"
+ }
+ },
+ {
+ "DefaultBuildSettings" : {
+ "EXECUTABLE_PATH" : "$(EXECUTABLE_NAME)",
+ "JAVA_MAKE_ZIPFILE" : "YES",
+ "JAVA_ARCHIVE_CLASSES" : "YES",
+ "EXECUTABLE_PREFIX" : "",
+ "EXECUTABLE_SUFFIX" : ".zip",
+ "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_SUFFIX)"
+ },
+ "Identifier" : "com.apple.package-type.zipfile",
+ "Type" : "PackageType",
+ "Name" : "Zip File",
+ "Description" : "Zip file",
+ "ProductReference" : {
+ "FileType" : "archive.zip",
+ "Name" : "$(EXECUTABLE_NAME)",
+ "IsLaunchable" : "NO"
+ }
+ },
+ {
+ "DefaultBuildSettings" : {
+ "EXECUTABLE_PATH" : "$(EXECUTABLE_NAME)",
+ "JAVA_ARCHIVE_CLASSES" : "NO",
+ "EXECUTABLE_PREFIX" : "",
+ "EXECUTABLE_SUFFIX" : "",
+ "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_SUFFIX)"
+ },
+ "Identifier" : "com.apple.package-type.javaclassfolder",
+ "Type" : "PackageType",
+ "Name" : "Class Folder",
+ "Description" : "Class folder",
+ "ProductReference" : {
+ "FileType" : "wrapper.java-classfolder",
+ "Name" : "$(EXECUTABLE_NAME)",
+ "IsLaunchable" : "NO"
+ }
+ }
+]
diff --git a/share/qbs/modules/bundle/MacOSX-Product-Types.xcspec b/share/qbs/modules/bundle/MacOSX-Product-Types.xcspec
new file mode 100644
index 000000000..f7766be24
--- /dev/null
+++ b/share/qbs/modules/bundle/MacOSX-Product-Types.xcspec
@@ -0,0 +1,545 @@
+[
+ {
+ "IconNamePrefix" : "TargetExecutable",
+ "DefaultBuildProperties" : {
+ "REZ_EXECUTABLE" : "YES",
+ "FULL_PRODUCT_NAME" : "$(EXECUTABLE_NAME)",
+ "LIBRARY_FLAG_NOSPACE" : "YES",
+ "INSTALL_PATH" : "\/usr\/local\/bin",
+ "GCC_INLINES_ARE_PRIVATE_EXTERN" : "YES",
+ "FRAMEWORK_FLAG_PREFIX" : "-framework",
+ "GCC_DYNAMIC_NO_PIC" : "NO",
+ "GCC_SYMBOLS_PRIVATE_EXTERN" : "YES",
+ "CODE_SIGNING_ALLOWED" : "YES",
+ "STRIP_STYLE" : "all",
+ "EXECUTABLE_PREFIX" : "",
+ "EXECUTABLE_SUFFIX" : "",
+ "LIBRARY_FLAG_PREFIX" : "-l"
+ },
+ "PackageTypes" : [
+ "com.apple.package-type.mach-o-executable"
+ ],
+ "Type" : "ProductType",
+ "DefaultTargetName" : "Command-line Tool",
+ "Name" : "Command-line Tool",
+ "Identifier" : "com.apple.product-type.tool",
+ "Description" : "Standalone command-line tool",
+ "Class" : "PBXToolProductType"
+ },
+ {
+ "IconNamePrefix" : "TargetExecutable",
+ "IsJava" : "YES",
+ "PackageTypes" : [
+ "com.apple.package-type.jarfile",
+ "com.apple.package-type.zipfile",
+ "com.apple.package-type.javaclassfolder"
+ ],
+ "Type" : "ProductType",
+ "DefaultTargetName" : "Java Command-line Tool",
+ "Name" : "Java Command-line Tool",
+ "Identifier" : "com.apple.product-type.tool.java",
+ "Description" : "Java Command-line tool",
+ "DefaultBuildProperties" : {
+ "REZ_EXECUTABLE" : "YES",
+ "INSTALL_PATH" : "\/usr\/local\/bin",
+ "FULL_PRODUCT_NAME" : "$(EXECUTABLE_NAME)"
+ }
+ },
+ {
+ "IconNamePrefix" : "TargetPlugin",
+ "DefaultBuildProperties" : {
+ "DEAD_CODE_STRIPPING" : "NO",
+ "REZ_EXECUTABLE" : "YES",
+ "LINK_WITH_STANDARD_LIBRARIES" : "NO",
+ "FULL_PRODUCT_NAME" : "$(EXECUTABLE_NAME)",
+ "LIBRARY_FLAG_NOSPACE" : "YES",
+ "FRAMEWORK_FLAG_PREFIX" : "-framework",
+ "INSTALL_PATH" : "$(HOME)\/Objects",
+ "SKIP_INSTALL" : "YES",
+ "GCC_INLINES_ARE_PRIVATE_EXTERN" : "YES",
+ "KEEP_PRIVATE_EXTERNS" : "YES",
+ "EXECUTABLE_EXTENSION" : "o",
+ "PUBLIC_HEADERS_FOLDER_PATH" : "\/usr\/local\/include",
+ "MACH_O_TYPE" : "mh_object",
+ "EXECUTABLE_SUFFIX" : ".$(EXECUTABLE_EXTENSION)",
+ "LIBRARY_FLAG_PREFIX" : "-l",
+ "PRIVATE_HEADERS_FOLDER_PATH" : "\/usr\/local\/include",
+ "STRIP_STYLE" : "debugging"
+ },
+ "PackageTypes" : [
+ "com.apple.package-type.mach-o-objfile"
+ ],
+ "Type" : "ProductType",
+ "DefaultTargetName" : "Object File",
+ "Name" : "Object File",
+ "Identifier" : "com.apple.product-type.objfile",
+ "Description" : "Object File",
+ "Class" : "XCStandaloneExecutableProductType"
+ },
+ {
+ "IconNamePrefix" : "TargetLibrary",
+ "DefaultBuildProperties" : {
+ "LIBRARY_FLAG_PREFIX" : "-l",
+ "STRIP_STYLE" : "debugging",
+ "REZ_EXECUTABLE" : "YES",
+ "FULL_PRODUCT_NAME" : "$(EXECUTABLE_NAME)",
+ "LD_DYLIB_INSTALL_NAME" : "$(DYLIB_INSTALL_NAME_BASE:standardizepath)\/$(EXECUTABLE_PATH)",
+ "DYLIB_COMPATIBILITY_VERSION" : "1",
+ "INSTALL_PATH" : "\/usr\/local\/lib",
+ "FRAMEWORK_FLAG_PREFIX" : "-framework",
+ "LIBRARY_FLAG_NOSPACE" : "YES",
+ "GCC_INLINES_ARE_PRIVATE_EXTERN" : "YES",
+ "CODE_SIGNING_ALLOWED" : "YES",
+ "EXECUTABLE_EXTENSION" : "dylib",
+ "PUBLIC_HEADERS_FOLDER_PATH" : "\/usr\/local\/include",
+ "DYLIB_INSTALL_NAME_BASE" : "$(INSTALL_PATH)",
+ "EXECUTABLE_SUFFIX" : ".$(EXECUTABLE_EXTENSION)",
+ "PRIVATE_HEADERS_FOLDER_PATH" : "\/usr\/local\/include",
+ "MACH_O_TYPE" : "mh_dylib",
+ "DYLIB_CURRENT_VERSION" : "1"
+ },
+ "PackageTypes" : [
+ "com.apple.package-type.mach-o-dylib"
+ ],
+ "Type" : "ProductType",
+ "DefaultTargetName" : "Dynamic Library",
+ "Name" : "Dynamic Library",
+ "Identifier" : "com.apple.product-type.library.dynamic",
+ "Description" : "Dynamic library",
+ "Class" : "PBXDynamicLibraryProductType"
+ },
+ {
+ "IconNamePrefix" : "TargetLibrary",
+ "DefaultBuildProperties" : {
+ "STRIP_STYLE" : "debugging",
+ "REZ_EXECUTABLE" : "YES",
+ "FULL_PRODUCT_NAME" : "$(EXECUTABLE_NAME)",
+ "LIBRARY_FLAG_NOSPACE" : "YES",
+ "FRAMEWORK_FLAG_PREFIX" : "-framework",
+ "INSTALL_PATH" : "\/usr\/local\/lib",
+ "SEPARATE_STRIP" : "YES",
+ "EXECUTABLE_EXTENSION" : "a",
+ "EXECUTABLE_PREFIX" : "lib",
+ "PUBLIC_HEADERS_FOLDER_PATH" : "\/usr\/local\/include",
+ "EXECUTABLE_SUFFIX" : ".$(EXECUTABLE_EXTENSION)",
+ "LIBRARY_FLAG_PREFIX" : "-l",
+ "PRIVATE_HEADERS_FOLDER_PATH" : "\/usr\/local\/include",
+ "MACH_O_TYPE" : "staticlib"
+ },
+ "AlwaysPerformSeparateStrip" : "YES",
+ "PackageTypes" : [
+ "com.apple.package-type.static-library"
+ ],
+ "Type" : "ProductType",
+ "DefaultTargetName" : "Static Library",
+ "Name" : "Static Library",
+ "Identifier" : "com.apple.product-type.library.static",
+ "Description" : "Static library",
+ "Class" : "PBXStaticLibraryProductType"
+ },
+ {
+ "IconNamePrefix" : "TargetPlugin",
+ "IsJava" : "YES",
+ "PackageTypes" : [
+ "com.apple.package-type.jarfile",
+ "com.apple.package-type.zipfile",
+ "com.apple.package-type.javaclassfolder"
+ ],
+ "Type" : "ProductType",
+ "DefaultTargetName" : "Java Library",
+ "Name" : "Java Library",
+ "Identifier" : "com.apple.product-type.library.java.archive",
+ "Description" : "Java library packaged as a Jar file, Zip file, or class folder",
+ "DefaultBuildProperties" : {
+ "INSTALL_PATH" : "\/usr\/local\/lib",
+ "FULL_PRODUCT_NAME" : "$(PRODUCT_NAME)"
+ }
+ },
+ {
+ "HasInfoPlistStrings" : "YES",
+ "Description" : "Generic bundle",
+ "HasInfoPlist" : "YES",
+ "Name" : "Bundle",
+ "Class" : "PBXBundleProductType",
+ "DefaultTargetName" : "Bundle",
+ "DefaultBuildProperties" : {
+ "LIBRARY_FLAG_NOSPACE" : "YES",
+ "WRAPPER_NAME" : "$(WRAPPER_PREFIX)$(PRODUCT_NAME)$(WRAPPER_SUFFIX)",
+ "FRAMEWORK_FLAG_PREFIX" : "-framework",
+ "GCC_INLINES_ARE_PRIVATE_EXTERN" : "YES",
+ "WRAPPER_SUFFIX" : ".$(WRAPPER_EXTENSION)",
+ "FULL_PRODUCT_NAME" : "$(WRAPPER_NAME)",
+ "WRAPPER_EXTENSION" : "bundle",
+ "CODE_SIGNING_ALLOWED" : "YES",
+ "WRAPPER_PREFIX" : "",
+ "STRIP_STYLE" : "non-global",
+ "MACH_O_TYPE" : "mh_bundle",
+ "LIBRARY_FLAG_PREFIX" : "-l"
+ },
+ "PackageTypes" : [
+ "com.apple.package-type.wrapper",
+ "com.apple.package-type.wrapper.shallow"
+ ],
+ "IsWrapper" : "YES",
+ "Type" : "ProductType",
+ "Identifier" : "com.apple.product-type.bundle",
+ "IconNamePrefix" : "TargetPlugin"
+ },
+ {
+ "PackageTypes" : [
+ "com.apple.package-type.wrapper.shallow"
+ ],
+ "Type" : "ProductType",
+ "BasedOn" : "com.apple.product-type.bundle",
+ "Name" : "Bundle (Shallow)",
+ "Identifier" : "com.apple.product-type.bundle.shallow",
+ "Description" : "Bundle (Shallow)",
+ "Class" : "PBXBundleProductType"
+ },
+ {
+ "Description" : "Application",
+ "Class" : "PBXApplicationProductType",
+ "Name" : "Application",
+ "RunpathSearchPathForEmbeddedFrameworks" : "@executable_path\/..\/Frameworks",
+ "CanEmbedAddressSanitizerLibraries" : "YES",
+ "ValidateEmbeddedBinaries" : "YES",
+ "DefaultTargetName" : "Application",
+ "DefaultBuildProperties" : {
+ "INSTALL_PATH" : "$(LOCAL_APPS_DIR)",
+ "WRAPPER_EXTENSION" : "app",
+ "GCC_DYNAMIC_NO_PIC" : "NO",
+ "STRIP_STYLE" : "all",
+ "CODE_SIGNING_ALLOWED" : "YES",
+ "GCC_INLINES_ARE_PRIVATE_EXTERN" : "YES",
+ "WRAPPER_SUFFIX" : ".$(WRAPPER_EXTENSION)",
+ "GCC_SYMBOLS_PRIVATE_EXTERN" : "YES",
+ "MACH_O_TYPE" : "mh_execute"
+ },
+ "BasedOn" : "com.apple.product-type.bundle",
+ "PackageTypes" : [
+ "com.apple.package-type.wrapper.application"
+ ],
+ "Type" : "ProductType",
+ "Identifier" : "com.apple.product-type.application",
+ "IconNamePrefix" : "TargetApp"
+ },
+ {
+ "PackageTypes" : [
+ "com.apple.package-type.wrapper.application.shallow"
+ ],
+ "Type" : "ProductType",
+ "BasedOn" : "com.apple.product-type.application",
+ "Name" : "Application (Shallow Bundle)",
+ "Identifier" : "com.apple.product-type.application.shallow",
+ "Description" : "Application (Shallow Bundle)",
+ "Class" : "PBXApplicationProductType"
+ },
+ {
+ "DefaultBuildProperties" : {
+ "PKGINFO_PATH" : "",
+ "INFOPLIST_PATH" : ""
+ },
+ "IsJava" : "YES",
+ "Type" : "ProductType",
+ "BasedOn" : "com.apple.product-type.application",
+ "Name" : "Java Application",
+ "Identifier" : "com.apple.product-type.application.java",
+ "Description" : "Java Application",
+ "DefaultTargetName" : "Java Application"
+ },
+ {
+ "IconNamePrefix" : "TargetFramework",
+ "DefaultTargetName" : "Framework",
+ "DefaultBuildProperties" : {
+ "WRAPPER_EXTENSION" : "framework",
+ "DYLIB_INSTALL_NAME_BASE" : "$(INSTALL_PATH)",
+ "STRIP_STYLE" : "debugging",
+ "FRAMEWORK_VERSION" : "A",
+ "CODE_SIGNING_ALLOWED" : "YES",
+ "LD_DYLIB_INSTALL_NAME" : "$(DYLIB_INSTALL_NAME_BASE:standardizepath)\/$(EXECUTABLE_PATH)",
+ "INSTALL_PATH" : "$(LOCAL_LIBRARY_DIR)\/Frameworks",
+ "WRAPPER_SUFFIX" : ".$(WRAPPER_EXTENSION)",
+ "MACH_O_TYPE" : "mh_dylib"
+ },
+ "PackageTypes" : [
+ "com.apple.package-type.wrapper.framework"
+ ],
+ "Type" : "ProductType",
+ "BasedOn" : "com.apple.product-type.bundle",
+ "Name" : "Framework",
+ "Identifier" : "com.apple.product-type.framework",
+ "Description" : "Framework",
+ "Class" : "PBXFrameworkProductType"
+ },
+ {
+ "PackageTypes" : [
+ "com.apple.package-type.wrapper.framework.shallow"
+ ],
+ "Type" : "ProductType",
+ "BasedOn" : "com.apple.product-type.framework",
+ "Name" : "Framework (Shallow Bundle)",
+ "Identifier" : "com.apple.product-type.framework.shallow",
+ "Description" : "Framework (Shallow Bundle)",
+ "Class" : "PBXFrameworkProductType"
+ },
+ {
+ "IconNamePrefix" : "TargetFramework",
+ "DefaultTargetName" : "Static Framework",
+ "DefaultBuildProperties" : {
+ "SEPARATE_STRIP" : "YES",
+ "WRAPPER_EXTENSION" : "framework",
+ "DYLIB_INSTALL_NAME_BASE" : "",
+ "CODE_SIGNING_ALLOWED" : "NO",
+ "FRAMEWORK_VERSION" : "A",
+ "LD_DYLIB_INSTALL_NAME" : "",
+ "GCC_INLINES_ARE_PRIVATE_EXTERN" : "NO",
+ "INSTALL_PATH" : "$(LOCAL_LIBRARY_DIR)\/Frameworks",
+ "WRAPPER_SUFFIX" : ".$(WRAPPER_EXTENSION)",
+ "MACH_O_TYPE" : "staticlib"
+ },
+ "AlwaysPerformSeparateStrip" : "YES",
+ "PackageTypes" : [
+ "com.apple.package-type.wrapper.framework.static"
+ ],
+ "Type" : "ProductType",
+ "BasedOn" : "com.apple.product-type.framework",
+ "Name" : "Static Framework",
+ "Identifier" : "com.apple.product-type.framework.static",
+ "Description" : "Static Framework",
+ "Class" : "XCStaticFrameworkProductType"
+ },
+ {
+ "DefaultTargetName" : "Kernel Extension",
+ "DefaultBuildProperties" : {
+ "GCC_ENABLE_BUILTIN_FUNCTIONS" : "NO",
+ "MODULE_START" : "0",
+ "PRIVATE_HEADERS_FOLDER_PATH" : "$(KEXT_FRAMEWORK)\/Contents\/PrivateHeaders\/$(KEXT_FAMILY_NAME)",
+ "WRAPPER_SUFFIX" : ".$(WRAPPER_EXTENSION)",
+ "MACH_O_TYPE" : "mh_execute",
+ "GCC_ENABLE_KERNEL_DEVELOPMENT" : "YES",
+ "MODULE_STOP" : "0",
+ "GCC_ENABLE_FLOATING_POINT_LIBRARY_CALLS" : "YES",
+ "GCC_PRODUCT_TYPE_PREPROCESSOR_DEFINITIONS" : "$(inherited) KERNEL KERNEL_PRIVATE DRIVER_PRIVATE APPLE NeXT",
+ "GCC_DISABLE_STATIC_FUNCTION_INLINING" : "YES",
+ "ENABLE_APPLE_KEXT_CODE_GENERATION" : "YES",
+ "CODE_SIGNING_ALLOWED" : "YES",
+ "GCC_FORCE_CPU_SUBTYPE_ALL" : "YES",
+ "WRAPPER_EXTENSION" : "kext",
+ "KERNEL_EXTENSION_HEADER_SEARCH_PATHS" : "$(KERNEL_FRAMEWORK)\/PrivateHeaders $(KERNEL_FRAMEWORK_HEADERS)",
+ "GCC_INLINES_ARE_PRIVATE_EXTERN" : "NO",
+ "KEXT_FRAMEWORK_NAME" : "Kernel",
+ "GCC_NO_COMMON_BLOCKS" : "YES",
+ "GCC_ENABLE_PASCAL_STRINGS" : "NO",
+ "PUBLIC_HEADERS_FOLDER_PATH" : "$(KEXT_FRAMEWORK)\/Contents\/Headers\/$(KEXT_FAMILY_NAME)",
+ "GCC_ENABLE_FUNCTION_INLINING" : "YES",
+ "KERNEL_FRAMEWORK_HEADERS" : "$(KERNEL_FRAMEWORK)\/Headers",
+ "KEXT_FAMILY_NAME" : "family",
+ "KEXT_FRAMEWORK" : "$(SYSTEM_LIBRARY_DIR)\/Frameworks\/$(KEXT_FRAMEWORK_NAME).framework",
+ "GCC_ENABLE_CPP_EXCEPTIONS" : "NO",
+ "GCC_ENABLE_CPP_RTTI" : "NO",
+ "MODULE_NAME" : "com.company.driver.modulename",
+ "GCC_USE_STANDARD_INCLUDE_SEARCHING" : "NO",
+ "KERNEL_FRAMEWORK" : "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)\/Frameworks\/Kernel.framework",
+ "MODULE_VERSION" : "1.0",
+ "INSTALL_PATH" : "$(DEFAULT_KEXT_INSTALL_PATH)",
+ "PRODUCT_TYPE_HEADER_SEARCH_PATHS" : "$(inherited) $(KERNEL_EXTENSION_HEADER_SEARCH_PATHS)",
+ "GCC_CHECK_RETURN_VALUE_OF_OPERATOR_NEW" : "YES",
+ "STRIP_STYLE" : "debugging"
+ },
+ "PackageTypes" : [
+ "com.apple.package-type.wrapper.kernel-extension",
+ "com.apple.package-type.wrapper.kernel-extension.shallow"
+ ],
+ "Type" : "ProductType",
+ "BasedOn" : "com.apple.product-type.bundle",
+ "Name" : "Kernel Extension",
+ "Identifier" : "com.apple.product-type.kernel-extension",
+ "Description" : "Kernel extension",
+ "Class" : "XCKernelExtensionProductType"
+ },
+ {
+ "DefaultBuildProperties" : {
+
+ },
+ "PackageTypes" : [
+ "com.apple.package-type.wrapper.kernel-extension.shallow"
+ ],
+ "Type" : "ProductType",
+ "BasedOn" : "com.apple.product-type.kernel-extension",
+ "Name" : "Kernel Extension (Shallow)",
+ "Identifier" : "com.apple.product-type.kernel-extension.shallow",
+ "Description" : "Kernel extension (shallow)",
+ "Class" : "XCKernelExtensionProductType"
+ },
+ {
+ "DefaultTargetName" : "IOKit Kernel Extension",
+ "DefaultBuildProperties" : {
+ "CODE_SIGNING_ALLOWED" : "YES"
+ },
+ "PackageTypes" : [
+ "com.apple.package-type.wrapper.kernel-extension",
+ "com.apple.package-type.wrapper.kernel-extension.shallow"
+ ],
+ "Type" : "ProductType",
+ "BasedOn" : "com.apple.product-type.kernel-extension",
+ "Name" : "IOKit Kernel Extension",
+ "Identifier" : "com.apple.product-type.kernel-extension.iokit",
+ "Description" : "IOKit Kernel extension",
+ "Class" : "XCKernelExtensionProductType"
+ },
+ {
+ "DefaultTargetName" : "IOKit Kernel Extension (Shallow)",
+ "DefaultBuildProperties" : {
+
+ },
+ "PackageTypes" : [
+ "com.apple.package-type.wrapper.kernel-extension.shallow"
+ ],
+ "Type" : "ProductType",
+ "BasedOn" : "com.apple.product-type.kernel-extension",
+ "Name" : "IOKit Kernel Extension (Shallow)",
+ "Identifier" : "com.apple.product-type.kernel-extension.iokit.shallow",
+ "Description" : "IOKit Kernel extension (Shallow)",
+ "Class" : "XCKernelExtensionProductType"
+ },
+ {
+ "DefaultBuildProperties" : {
+ "TEST_FRAMEWORK_SEARCH_PATHS" : [
+ "$(inherited)",
+ "$(PLATFORM_DIR)\/Developer\/Library\/Frameworks"
+ ],
+ "PRODUCT_SPECIFIC_LDFLAGS" : "-framework XCTest",
+ "WRAPPER_EXTENSION" : "xctest",
+ "PRODUCT_TYPE_FRAMEWORK_SEARCH_PATHS" : "$(TEST_FRAMEWORK_SEARCH_PATHS)"
+ },
+ "PackageTypes" : [
+ "com.apple.package-type.bundle.unit-test"
+ ],
+ "Type" : "ProductType",
+ "BasedOn" : "com.apple.product-type.bundle",
+ "Name" : "Unit Test Bundle",
+ "Identifier" : "com.apple.product-type.bundle.unit-test",
+ "Description" : "Unit Test Bundle",
+ "Class" : "PBXXCTestBundleProductType"
+ },
+ {
+ "DefaultBuildProperties" : {
+ "TEST_FRAMEWORK_SEARCH_PATHS" : [
+ "$(inherited)",
+ "$(PLATFORM_DIR)\/Developer\/Library\/Frameworks"
+ ],
+ "PRODUCT_SPECIFIC_LDFLAGS" : "-framework XCTest",
+ "WRAPPER_EXTENSION" : "xctest",
+ "USES_XCTRUNNER" : "YES",
+ "PRODUCT_TYPE_FRAMEWORK_SEARCH_PATHS" : "$(TEST_FRAMEWORK_SEARCH_PATHS)"
+ },
+ "PackageTypes" : [
+ "com.apple.package-type.bundle.unit-test"
+ ],
+ "Type" : "ProductType",
+ "BasedOn" : "com.apple.product-type.bundle.unit-test",
+ "Name" : "UI Testing Bundle",
+ "Identifier" : "com.apple.product-type.bundle.ui-testing",
+ "Description" : "UI Testing Bundle",
+ "Class" : "PBXXCTestBundleProductType"
+ },
+ {
+ "DefaultBuildProperties" : {
+ "WRAPPER_EXTENSION" : "octest"
+ },
+ "PackageTypes" : [
+ "com.apple.package-type.bundle.ocunit-test"
+ ],
+ "Type" : "ProductType",
+ "BasedOn" : "com.apple.product-type.bundle",
+ "Name" : "OCUnit Test Bundle",
+ "Identifier" : "com.apple.product-type.bundle.ocunit-test",
+ "Description" : "OCUnit Test Bundle",
+ "Class" : "PBXBundleProductType"
+ },
+ {
+ "HasInfoPlistStrings" : "NO",
+ "PackageTypes" : [
+ "com.apple.package-type.in-app-purchase-content"
+ ],
+ "HasInfoPlist" : "YES",
+ "IsWrapper" : "YES",
+ "Type" : "ProductType",
+ "DefaultBuildProperties" : {
+ "FULL_PRODUCT_NAME" : "$(WRAPPER_NAME)"
+ },
+ "Name" : "In-App Purchase Content",
+ "Identifier" : "com.apple.product-type.in-app-purchase-content",
+ "Description" : "In-App Purchase Content",
+ "Class" : "PBXBundleProductType"
+ },
+ {
+ "IconNamePrefix" : "XPCService",
+ "DefaultTargetName" : "XPC Service",
+ "CanEmbedAddressSanitizerLibraries" : "YES",
+ "DefaultBuildProperties" : {
+ "MACH_O_TYPE" : "mh_execute",
+ "WRAPPER_EXTENSION" : "xpc"
+ },
+ "PackageTypes" : [
+ "com.apple.package-type.xpc-service"
+ ],
+ "Type" : "ProductType",
+ "BasedOn" : "com.apple.product-type.bundle",
+ "Name" : "XPC Service",
+ "Identifier" : "com.apple.product-type.xpc-service",
+ "Description" : "XPC Service",
+ "Class" : "PBXBundleProductType"
+ },
+ {
+ "IconNamePrefix" : "XPCService",
+ "DefaultTargetName" : "PlugInKit PlugIn",
+ "DefaultBuildProperties" : {
+ "WRAPPER_EXTENSION" : "pluginkit",
+ "PRODUCT_SPECIFIC_LDFLAGS" : "$(SDKROOT)\/System\/Library\/PrivateFrameworks\/PlugInKit.framework\/PlugInKit"
+ },
+ "PackageTypes" : [
+ "com.apple.package-type.pluginkit-plugin"
+ ],
+ "Type" : "ProductType",
+ "BasedOn" : "com.apple.product-type.xpc-service",
+ "Name" : "PlugInKit PlugIn",
+ "Identifier" : "com.apple.product-type.pluginkit-plugin",
+ "Description" : "PlugInKit PlugIn",
+ "Class" : "PBXBundleProductType"
+ },
+ {
+ "IconNamePrefix" : "AppExtension",
+ "DefaultTargetName" : "App Extension",
+ "DefaultBuildProperties" : {
+ "APPLICATION_EXTENSION_API_ONLY" : "YES",
+ "PRODUCT_SPECIFIC_LDFLAGS" : "-e _NSExtensionMain",
+ "WRAPPER_EXTENSION" : "appex",
+ "CODE_SIGNING_ALLOWED" : "YES"
+ },
+ "PackageTypes" : [
+ "com.apple.package-type.app-extension"
+ ],
+ "Type" : "ProductType",
+ "BasedOn" : "com.apple.product-type.pluginkit-plugin",
+ "Name" : "App Extension",
+ "Identifier" : "com.apple.product-type.app-extension",
+ "Description" : "App Extension",
+ "Class" : "PBXBundleProductType"
+ },
+ {
+ "DefaultTargetName" : "Spotlight",
+ "DefaultBuildProperties" : {
+ "CODE_SIGNING_ALLOWED" : "YES"
+ },
+ "PackageTypes" : [
+ "com.apple.package-type.spotlight-importer"
+ ],
+ "Type" : "ProductType",
+ "BasedOn" : "com.apple.product-type.bundle",
+ "Name" : "Spotlight Importer",
+ "Identifier" : "com.apple.product-type.spotlight-importer",
+ "Description" : "Spotlight Importer",
+ "Class" : "PBXBundleProductType"
+ }
+]
diff --git a/share/qbs/modules/bundle/bundle.js b/share/qbs/modules/bundle/bundle.js
new file mode 100644
index 000000000..d6ab4b56a
--- /dev/null
+++ b/share/qbs/modules/bundle/bundle.js
@@ -0,0 +1,214 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of the Qt Build Suite.
+**
+** 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 = loadExtension("qbs.DarwinTools");
+var Process = loadExtension("qbs.Process");
+
+// HACK: Workaround until the PropertyList extension is supported cross-platform
+var PropertyList2 = (function () {
+ function PropertyList2() {
+ }
+ PropertyList2.prototype.readFromFile = function (filePath) {
+ var str;
+ var process = new Process();
+ try {
+ if (process.exec("plutil", ["-convert", "json", "-o", "-", filePath], false) === 0) {
+ str = process.readStdOut();
+ } else {
+ var tf = new TextFile(filePath);
+ try {
+ str = tf.readAll();
+ } finally {
+ tf.close();
+ }
+ }
+ } finally {
+ process.close();
+ }
+
+ if (str)
+ this.obj = JSON.parse(str);
+ };
+ PropertyList2.prototype.toObject = function () {
+ return this.obj;
+ };
+ PropertyList2.prototype.clear = function () {
+ };
+ return PropertyList2;
+}());
+
+// Order is significant due to productTypeIdentifier() search path
+var _productTypeIdentifiers = {
+ "inapppurchase": "com.apple.product-type.in-app-purchase-content",
+ "applicationextension": "com.apple.product-type.app-extension",
+ "xpcservice": "com.apple.product-type.xpc-service",
+ "application": "com.apple.product-type.application",
+ "dynamiclibrary": "com.apple.product-type.framework",
+ "loadablemodule": "com.apple.product-type.bundle",
+ "staticlibrary": "com.apple.product-type.framework.static",
+ "kernelmodule": "com.apple.product-type.kernel-extension"
+};
+
+function productTypeIdentifier(productType) {
+ for (var k in _productTypeIdentifiers) {
+ if (productType.contains(k))
+ return _productTypeIdentifiers[k];
+ }
+ return "com.apple.package-type.wrapper";
+}
+
+var XcodeBuildSpecsReader = (function () {
+ function XcodeBuildSpecsReader(specsPath, separator, additionalSettings, useShallowBundles) {
+ this._additionalSettings = additionalSettings;
+ this._useShallowBundles = useShallowBundles;
+ var i;
+ var plist = new PropertyList2();
+ var plist2 = new PropertyList2();
+ try {
+ plist.readFromFile(specsPath + ["/MacOSX", "Package", "Types.xcspec"].join(separator));
+ plist2.readFromFile(specsPath + ["/MacOSX", "Product", "Types.xcspec"].join(separator));
+ this._packageTypes = plist.toObject();
+ this._productTypes = plist2.toObject();
+ this._types = {};
+ for (i = 0; i < this._packageTypes.length; ++i)
+ this._types[this._packageTypes[i]["Identifier"]] = this._packageTypes[i];
+ for (i = 0; i < this._productTypes.length; ++i)
+ this._types[this._productTypes[i]["Identifier"]] = this._productTypes[i];
+ } finally {
+ plist.clear();
+ plist2.clear();
+ }
+ }
+ XcodeBuildSpecsReader.prototype.settings = function (typeIdentifier, recursive, skipPackageTypes) {
+ // Silently use shallow bundles when preferred since it seems to be some sort of automatic
+ // shadowing mechanism. For example, this matches Xcode behavior where static frameworks
+ // are shallow even though no such product specification exists, and also seems to match
+ // other behavior i.e. where productType in pbxproj files is never explicitly shallow.
+ if (this._useShallowBundles && this._types[typeIdentifier + ".shallow"] && !skipPackageTypes)
+ typeIdentifier += ".shallow";
+
+ var typesObject = this._types[typeIdentifier];
+ if (typesObject) {
+ var buildProperties = {};
+
+ if (recursive) {
+ // Get all the settings for the product's package type
+ if (!skipPackageTypes && typesObject["PackageTypes"]) {
+ for (var k = 0; k < typesObject["PackageTypes"].length; ++k) {
+ var props = this.settings(typesObject["PackageTypes"][k], recursive, true);
+ for (var y in props) {
+ if (props.hasOwnProperty(y))
+ buildProperties[y] = props[y];
+ }
+ break;
+ }
+ }
+
+ // Get all the settings for the product's inherited product type
+ if (typesObject["BasedOn"]) {
+ // We'll only do the auto shallow substitution for wrapper package types...
+ // this ensures that in-app purchase content bundles are non-shallow on both
+ // OS X and iOS, for example (which matches Xcode behavior)
+ var isWrapper = false;
+ if (typesObject["ProductReference"]) {
+ var fileType = typesObject["ProductReference"]["FileType"];
+ if (fileType)
+ isWrapper = fileType.startsWith("wrapper.");
+ }
+
+ // Prevent recursion loop if this spec's base plus .shallow would be the same
+ // as the current spec's identifier
+ var baseIdentifier = typesObject["BasedOn"];
+ if (this._useShallowBundles && isWrapper
+ && this._types[baseIdentifier + ".shallow"]
+ && typeIdentifier !== baseIdentifier + ".shallow")
+ baseIdentifier += ".shallow";
+
+ props = this.settings(baseIdentifier, recursive, true);
+ for (y in props) {
+ if (props.hasOwnProperty(y))
+ buildProperties[y] = props[y];
+ }
+ }
+ }
+
+
+ if (typesObject["Type"] === "PackageType") {
+ props = typesObject["DefaultBuildSettings"];
+ for (y in props) {
+ if (props.hasOwnProperty(y))
+ buildProperties[y] = props[y];
+ }
+ }
+
+ if (typesObject["Type"] === "ProductType") {
+ props = typesObject["DefaultBuildProperties"];
+ for (y in props) {
+ if (props.hasOwnProperty(y))
+ buildProperties[y] = props[y];
+ }
+ }
+
+ return buildProperties;
+ }
+ };
+ XcodeBuildSpecsReader.prototype.setting = function (typeIdentifier, settingName) {
+ var obj = this.settings(typeIdentifier, false);
+ if (obj) {
+ return obj[settingName];
+ }
+ };
+ XcodeBuildSpecsReader.prototype.expandedSettings = function (typeIdentifier) {
+ var obj = this.settings(typeIdentifier, true);
+ if (obj) {
+ for (var k in obj)
+ obj[k] = this.expandedSetting(typeIdentifier, k);
+ return obj;
+ }
+ };
+ XcodeBuildSpecsReader.prototype.expandedSetting = function (typeIdentifier, settingName) {
+ var obj = this.settings(typeIdentifier, true);
+ if (obj) {
+ for (var x in this._additionalSettings) {
+ var additionalSetting = this._additionalSettings[x];
+ if (additionalSetting !== undefined)
+ obj[x] = additionalSetting;
+ }
+ var setting = obj[settingName];
+ var original;
+ while (original !== setting) {
+ original = setting;
+ setting = DarwinTools.expandPlistEnvironmentVariables({ key: setting }, obj, true)["key"];
+ }
+ return setting;
+ }
+ };
+ return XcodeBuildSpecsReader;
+}());
diff --git a/share/qbs/modules/bundle/update-specs.sh b/share/qbs/modules/bundle/update-specs.sh
new file mode 100755
index 000000000..869fb011f
--- /dev/null
+++ b/share/qbs/modules/bundle/update-specs.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+# Update build specs from Xcode - this script should be run when new Xcode releases are made.
+specs_dir="$(xcrun --sdk macosx --show-sdk-platform-path)/Developer/Library/Xcode/Specifications"
+spec_files=("MacOSX Package Types.xcspec" "MacOSX Product Types.xcspec")
+for spec_file in "${spec_files[@]}" ; do
+ printf "%s\n" "$(plutil -convert json -r -o - "$specs_dir/$spec_file")" > "${spec_file// /-}"
+done
+xcode_version="$(/usr/libexec/PlistBuddy -c 'Print CFBundleShortVersionString' \
+ "$(xcode-select --print-path)/../Info.plist")"
+echo "Updated build specs from Xcode $xcode_version"
diff --git a/share/qbs/modules/cli/mono.qbs b/share/qbs/modules/cli/mono.qbs
index 9f19f3a0a..6ce1ea3e6 100644
--- a/share/qbs/modules/cli/mono.qbs
+++ b/share/qbs/modules/cli/mono.qbs
@@ -1,7 +1,7 @@
import qbs
CLIModule {
- condition: qbs.toolchain.contains("mono")
+ condition: qbs.toolchain && qbs.toolchain.contains("mono")
debugInfoSuffix: ".mdb"
csharpCompilerName: "mcs"
diff --git a/share/qbs/modules/cli/windows-dotnet.qbs b/share/qbs/modules/cli/windows-dotnet.qbs
index a51eb4c40..0ec457bdf 100755
--- a/share/qbs/modules/cli/windows-dotnet.qbs
+++ b/share/qbs/modules/cli/windows-dotnet.qbs
@@ -2,7 +2,7 @@ import qbs
import qbs.Utilities
CLIModule {
- condition: qbs.toolchain.contains("dotnet")
+ condition: qbs.toolchain && qbs.toolchain.contains("dotnet")
debugInfoSuffix: ".pdb"
csharpCompilerName: "csc"
diff --git a/share/qbs/modules/cpp/CppModule.qbs b/share/qbs/modules/cpp/CppModule.qbs
index df10fd1dc..18ae4df1d 100644
--- a/share/qbs/modules/cpp/CppModule.qbs
+++ b/share/qbs/modules/cpp/CppModule.qbs
@@ -168,6 +168,7 @@ Module {
property string loadableModuleSuffix
property string executableSuffix
property string debugInfoSuffix
+ property string debugInfoBundleSuffix
property bool createSymlinks: true
property stringList dynamicLibraries // list of names, will be linked with -lname
property stringList staticLibraries // list of static library files
@@ -271,6 +272,10 @@ Module {
description: "version of the C++ standard library to use"
}
+ property bool enableExceptions
+ property string exceptionHandlingModel: "default"
+ property bool enableRtti
+
// Platform properties. Those are intended to be set by the toolchain setup
// and are prepended to the corresponding user properties.
property stringList platformAssemblerFlags
diff --git a/share/qbs/modules/cpp/DarwinGCC.qbs b/share/qbs/modules/cpp/DarwinGCC.qbs
index 906da4bfe..a147de935 100644
--- a/share/qbs/modules/cpp/DarwinGCC.qbs
+++ b/share/qbs/modules/cpp/DarwinGCC.qbs
@@ -47,7 +47,8 @@ UnixGCC {
loadableModuleSuffix: ".bundle"
dynamicLibrarySuffix: ".dylib"
separateDebugInformation: true
- debugInfoSuffix: ".dSYM"
+ debugInfoBundleSuffix: ".dSYM"
+ debugInfoSuffix: ".dwarf"
toolchainInstallPath: xcode.present
? FileInfo.joinPaths(xcode.toolchainPath, "usr", "bin") : base
@@ -73,14 +74,16 @@ UnixGCC {
dict["LSMinimumSystemVersion"] = minimumOsxVersion;
}
- if (qbs.targetOS.contains("ios") || qbs.targetOS.contains("tvos")) {
+ if (qbs.targetOS.containsAny(["ios", "tvos"])) {
dict["LSRequiresIPhoneOS"] = true;
- if (qbs.targetOS.contains("ios") && !qbs.targetOS.contains("ios-simulator"))
- dict["UIRequiredDeviceCapabilities"] = ["armv7"];
+ if (xcode.platformType === "device") {
+ if (qbs.targetOS.contains("ios"))
+ dict["UIRequiredDeviceCapabilities"] = ["armv7"];
- if (qbs.targetOS.contains("tvos") && !qbs.targetOS.contains("tvos-simulator"))
- dict["UIRequiredDeviceCapabilities"] = ["arm64"];
+ if (qbs.targetOS.contains("tvos"))
+ dict["UIRequiredDeviceCapabilities"] = ["arm64"];
+ }
}
if (xcode.present) {
@@ -88,7 +91,7 @@ UnixGCC {
if (qbs.targetOS.contains("ios"))
dict["UIDeviceFamily"] = targetDevices;
- if (qbs.targetOS.contains("ios") || qbs.targetOS.contains("watchos")) {
+ if (qbs.targetOS.containsAny(["ios", "watchos"])) {
var orientations = [
"UIInterfaceOrientationPortrait",
"UIInterfaceOrientationPortraitUpsideDown",
diff --git a/share/qbs/modules/cpp/GenericGCC.qbs b/share/qbs/modules/cpp/GenericGCC.qbs
index 9ffe1505c..6f54fe924 100644
--- a/share/qbs/modules/cpp/GenericGCC.qbs
+++ b/share/qbs/modules/cpp/GenericGCC.qbs
@@ -107,8 +107,8 @@ CppModule {
assemblerPath: toolchainPathPrefix + assemblerName
compilerPath: toolchainPathPrefix + compilerName
linkerPath: toolchainPathPrefix + linkerName
- property path archiverPath: { return toolchainPathPrefix + archiverName }
- property path nmPath: { return toolchainPathPrefix + nmName }
+ property string archiverPath: toolchainPathPrefix + archiverName
+ property string nmPath: toolchainPathPrefix + nmName
property string objcopyPath: toolchainPathPrefix + objcopyName
property string stripPath: toolchainPathPrefix + stripName
property string dsymutilPath: toolchainPathPrefix + dsymutilName
@@ -122,10 +122,15 @@ CppModule {
if (product.version === undefined)
return undefined;
- if (typeof product.version !== "string"
- || !product.version.match(/^([0-9]+\.){0,3}[0-9]+$/))
+ if (!Gcc.isNumericProductVersion(product.version)) {
+ // Dynamic library version numbers like "A" or "B" are common on Apple platforms, so
+ // don't restrict the product version to a componentized version number here.
+ if (qbs.targetOS.contains("darwin"))
+ return product.version;
+
throw("product.version must be a string in the format x[.y[.z[.w]] "
- + "where each component is an integer");
+ + "where each component is an integer");
+ }
var maxVersionParts = 3;
var versionParts = product.version.split('.').slice(0, maxVersionParts);
@@ -137,6 +142,26 @@ CppModule {
return versionParts.join('.');
}
+ exceptionHandlingModel: {
+ if (qbs.toolchain.contains("mingw")) {
+ // https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html claims
+ // __USING_SJLJ_EXCEPTIONS__ is defined as 1 when using SJLJ exceptions, but there don't
+ // seem to be defines for the other models, so use the presence of the DLLs for now.
+ var prefix = toolchainInstallPath;
+ if (!qbs.hostOS.contains("windows"))
+ prefix = FileInfo.joinPaths(toolchainInstallPath, "..", "lib", "gcc",
+ toolchainPrefix,
+ [compilerVersionMajor, compilerVersionMinor].join("."));
+ var models = ["seh", "sjlj", "dw2"];
+ for (var i = 0; i < models.length; ++i) {
+ if (File.exists(FileInfo.joinPaths(prefix, "libgcc_s_" + models[i] + "-1.dll"))) {
+ return models[i];
+ }
+ }
+ }
+ return base;
+ }
+
validate: {
var validator = new ModUtils.PropertyValidator("cpp");
validator.setRequiredProperty("architecture", architecture,
@@ -175,7 +200,8 @@ CppModule {
var artifacts = [lib, libCopy];
if (ModUtils.moduleProperty(product, "shouldCreateSymlinks") && !product.moduleProperty("bundle", "isBundle")) {
- for (var i = 0; i < 3; ++i) {
+ var maxVersionParts = Gcc.isNumericProductVersion(product.version) ? 3 : 1;
+ for (var i = 0; i < maxVersionParts; ++i) {
var symlink = {
filePath: product.destinationDirectory + "/"
+ PathTools.dynamicLibraryFileName(product, undefined, i),
@@ -186,23 +212,7 @@ CppModule {
artifacts.push(symlink);
}
}
- if (ModUtils.moduleProperty(product, "separateDebugInformation")) {
- artifacts.push({
- filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.debugInfoFilePath(product)),
- fileTags: ["debuginfo"]
- });
- if (PathTools.debugInfoIsBundle(product)) {
- artifacts.push({
- filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.debugInfoBundlePath(product)),
- fileTags: ["debuginfo_bundle"]
- });
- artifacts.push({
- filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.debugInfoPlistFilePath(product)),
- fileTags: ["debuginfo_plist"]
- });
- }
- }
- return artifacts;
+ return artifacts.concat(Gcc.debugInfoArtifacts(product));
}
prepare: {
@@ -271,24 +281,7 @@ CppModule {
PathTools.loadableModuleFilePath(product)),
fileTags: ["loadablemodule"]
}
- var artifacts = [app];
- if (ModUtils.moduleProperty(product, "separateDebugInformation")) {
- artifacts.push({
- filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.debugInfoFilePath(product)),
- fileTags: ["debuginfo"]
- });
- if (PathTools.debugInfoIsBundle(product)) {
- artifacts.push({
- filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.debugInfoBundlePath(product)),
- fileTags: ["debuginfo_bundle"]
- });
- artifacts.push({
- filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.debugInfoPlistFilePath(product)),
- fileTags: ["debuginfo_plist"]
- });
- }
- }
- return artifacts;
+ return [app].concat(Gcc.debugInfoArtifacts(product));
}
prepare: {
@@ -316,24 +309,7 @@ CppModule {
PathTools.applicationFilePath(product)),
fileTags: ["application"]
}
- var artifacts = [app];
- if (ModUtils.moduleProperty(product, "separateDebugInformation")) {
- artifacts.push({
- filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.debugInfoFilePath(product)),
- fileTags: ["debuginfo"]
- });
- if (PathTools.debugInfoIsBundle(product)) {
- artifacts.push({
- filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.debugInfoBundlePath(product)),
- fileTags: ["debuginfo_bundle"]
- });
- artifacts.push({
- filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.debugInfoPlistFilePath(product)),
- fileTags: ["debuginfo_plist"]
- });
- }
- }
- return artifacts;
+ return [app].concat(Gcc.debugInfoArtifacts(product));
}
prepare: {
diff --git a/share/qbs/modules/cpp/gcc.js b/share/qbs/modules/cpp/gcc.js
index 0c65dc060..d7842c4e0 100644
--- a/share/qbs/modules/cpp/gcc.js
+++ b/share/qbs/modules/cpp/gcc.js
@@ -82,7 +82,7 @@ function linkerFlags(product, inputs, output) {
if (isDarwin) {
var internalVersion = product.moduleProperty("cpp", "internalVersion");
- if (internalVersion)
+ if (internalVersion && isNumericProductVersion(internalVersion))
args.push("-current_version", internalVersion);
args = args.concat(escapeLinkerFlags(product, [
@@ -98,7 +98,7 @@ function linkerFlags(product, inputs, output) {
if (output.fileTags.contains("loadablemodule"))
args.push(isDarwin ? "-bundle" : "-shared");
- if (output.fileTags.contains("dynamiclibrary") || output.fileTags.contains("loadablemodule")) {
+ if (output.fileTags.containsAny(["dynamiclibrary", "loadablemodule"])) {
if (isDarwin)
args = args.concat(escapeLinkerFlags(product, ["-headerpad_max_install_names"]));
else
@@ -420,6 +420,23 @@ function compilerFlags(product, input, output) {
args.push(useArc ? "-fobjc-arc" : "-fno-objc-arc");
}
+ var enableExceptions = ModUtils.moduleProperty(input, "enableExceptions");
+ if (enableExceptions !== undefined) {
+ if (tag === "cpp" || tag === "objcpp")
+ args.push(enableExceptions ? "-fexceptions" : "-fno-exceptions");
+
+ if (tag === "objc" || tag === "objcpp") {
+ args.push(enableExceptions ? "-fobjc-exceptions" : "-fno-objc-exceptions");
+ if (useArc !== undefined)
+ args.push(useArc ? "-fobjc-arc-exceptions" : "-fno-objc-arc-exceptions");
+ }
+ }
+
+ var enableRtti = ModUtils.moduleProperty(input, "enableRtti");
+ if (enableRtti !== undefined && (tag === "cpp" || tag === "objcpp")) {
+ args.push(enableRtti ? "-frtti" : "-fno-rtti");
+ }
+
var visibility = ModUtils.moduleProperty(input, 'visibility');
if (!product.type.contains('staticlibrary')
&& !product.moduleProperty("qbs", "toolchain").contains("mingw")) {
@@ -704,24 +721,25 @@ function prepareLinker(project, product, inputs, outputs, input, output) {
]));
cmd.description = "generating dSYM for " + product.name;
commands.push(cmd);
+
+ cmd = new Command(ModUtils.moduleProperty(product, "stripPath"),
+ ["-S", primaryOutput.filePath]);
+ cmd.silent = true;
+ commands.push(cmd);
} else {
- cmd = new Command(ModUtils.moduleProperty(product, "objcopyPath"), [
- "--only-keep-debug", primaryOutput.filePath,
- outputs.debuginfo[0].filePath
- ]);
+ var objcopy = ModUtils.moduleProperty(product, "objcopyPath");
+
+ cmd = new Command(objcopy, ["--only-keep-debug", primaryOutput.filePath,
+ outputs.debuginfo[0].filePath]);
cmd.silent = true;
commands.push(cmd);
- cmd = new Command(ModUtils.moduleProperty(product, "stripPath"), [
- "--strip-debug", primaryOutput.filePath
- ]);
+ cmd = new Command(objcopy, ["--strip-debug", primaryOutput.filePath]);
cmd.silent = true;
commands.push(cmd);
- cmd = new Command(ModUtils.moduleProperty(product, "objcopyPath"), [
- "--add-gnu-debuglink=" + outputs.debuginfo[0].filePath,
- primaryOutput.filePath
- ]);
+ cmd = new Command(objcopy, ["--add-gnu-debuglink=" + outputs.debuginfo[0].filePath,
+ primaryOutput.filePath]);
cmd.silent = true;
commands.push(cmd);
}
@@ -856,3 +874,28 @@ function concatLibsFromArtifacts(libs, artifacts)
deps.reverse();
return concatLibs(deps, libs);
}
+
+function debugInfoArtifacts(product) {
+ var artifacts = [];
+ if (product.moduleProperty("cpp", "separateDebugInformation")) {
+ artifacts.push({
+ filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.debugInfoFilePath(product)),
+ fileTags: ["debuginfo"]
+ });
+ if (PathTools.debugInfoIsBundle(product)) {
+ artifacts.push({
+ filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.debugInfoBundlePath(product)),
+ fileTags: ["debuginfo_bundle"]
+ });
+ artifacts.push({
+ filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.debugInfoPlistFilePath(product)),
+ fileTags: ["debuginfo_plist"]
+ });
+ }
+ }
+ return artifacts;
+}
+
+function isNumericProductVersion(version) {
+ return version && version.match(/^([0-9]+\.){0,3}[0-9]+$/);
+}
diff --git a/share/qbs/modules/cpp/genericunix-gcc.qbs b/share/qbs/modules/cpp/genericunix-gcc.qbs
index fa330abed..7c8869d63 100644
--- a/share/qbs/modules/cpp/genericunix-gcc.qbs
+++ b/share/qbs/modules/cpp/genericunix-gcc.qbs
@@ -31,6 +31,6 @@
import qbs 1.0
UnixGCC {
- condition: !qbs.targetOS.contains('darwin') && !qbs.targetOS.contains('linux') &&
+ condition: qbs.targetOS && !qbs.targetOS.containsAny(['darwin', 'linux']) &&
qbs.toolchain && qbs.toolchain.contains('gcc') && !qbs.toolchain.contains('mingw')
}
diff --git a/share/qbs/modules/cpp/msvc.js b/share/qbs/modules/cpp/msvc.js
index aff810c27..c671f8abe 100644
--- a/share/qbs/modules/cpp/msvc.js
+++ b/share/qbs/modules/cpp/msvc.js
@@ -47,8 +47,27 @@ function prepareCompiler(project, product, inputs, outputs, input, output) {
// Whether we're compiling a precompiled header or normal source file
var pchOutput = outputs[tag + "_pch"] ? outputs[tag + "_pch"][0] : undefined;
- // enable unwind semantics
- args.push("/EHsc")
+ var enableExceptions = ModUtils.moduleProperty(input, "enableExceptions");
+ if (enableExceptions) {
+ var ehModel = ModUtils.moduleProperty(input, "exceptionHandlingModel");
+ switch (ehModel) {
+ case "default":
+ args.push("/EHsc"); // "Yes" in VS
+ break;
+ case "seh":
+ args.push("/EHa"); // "Yes with SEH exceptions" in VS
+ break;
+ case "externc":
+ args.push("/EHs"); // "Yes with Extern C functions" in VS
+ break;
+ }
+ }
+
+ var enableRtti = ModUtils.moduleProperty(input, "enableRtti");
+ if (enableRtti !== undefined) {
+ args.push(enableRtti ? "/GR" : "/GR-");
+ }
+
// optimization:
if (optimization === 'small')
args.push('/Os')
diff --git a/share/qbs/modules/ib/ib.js b/share/qbs/modules/ib/ib.js
index 198f8fe88..91048752b 100644
--- a/share/qbs/modules/ib/ib.js
+++ b/share/qbs/modules/ib/ib.js
@@ -67,7 +67,9 @@ function ibtooldArguments(product, inputs, outputs, overrideOutput) {
}
if (inputs.assetcatalog) {
- args.push("--platform", DarwinTools.applePlatformName(product.moduleProperty("qbs", "targetOS")));
+ args.push("--platform", DarwinTools.applePlatformName(
+ product.moduleProperty("qbs", "targetOS"),
+ product.moduleProperty("xcode", "platformType")));
var appIconName = ModUtils.modulePropertyFromArtifacts(product, inputs.assetcatalog, product.moduleName, "appIconName");
if (appIconName)
diff --git a/share/qbs/modules/java/utils.js b/share/qbs/modules/java/utils.js
index c1104a138..9477125f0 100644
--- a/share/qbs/modules/java/utils.js
+++ b/share/qbs/modules/java/utils.js
@@ -119,7 +119,8 @@ function findJdkPath(hostOS, arch, environmentPaths, searchPaths) {
return FileInfo.joinPaths(searchPaths[i], "bin", tool);
}
- if (requiredTools.map(fullToolPath).every(File.exists)) {
+ if (requiredTools.map(function(p) { return fullToolPath(p); })
+ .every(function(p) { return File.exists(p); })) {
return searchPaths[i];
}
}
diff --git a/share/qbs/modules/nodejs/NodeJS.qbs b/share/qbs/modules/nodejs/NodeJS.qbs
index f411e06da..1c04b09c2 100644
--- a/share/qbs/modules/nodejs/NodeJS.qbs
+++ b/share/qbs/modules/nodejs/NodeJS.qbs
@@ -56,6 +56,8 @@ Module {
description: "file whose corresponding output will be executed when running the Node.js app"
}
+ Group { name: "Application file"; files: nodejs.applicationFile ? [nodejs.applicationFile] : [] }
+
property path toolchainInstallPath: {
if (nodejs.path && npm.path && nodejs.path !== npm.path)
throw("node and npm binaries do not belong to the same installation ("
diff --git a/share/qbs/modules/typescript/TypeScriptModule.qbs b/share/qbs/modules/typescript/TypeScriptModule.qbs
index 5173fb916..fbcd4fcf0 100644
--- a/share/qbs/modules/typescript/TypeScriptModule.qbs
+++ b/share/qbs/modules/typescript/TypeScriptModule.qbs
@@ -47,6 +47,7 @@ Module {
Probes.TypeScriptProbe {
id: tsc
+ interpreterPath: FileInfo.path(nodejs.interpreterFilePath)
packageManagerBinPath: nodejs.packageManagerBinPath
packageManagerRootPath: nodejs.packageManagerRootPath
}
@@ -78,7 +79,7 @@ Module {
PropertyOptions {
name: "targetVersion"
description: "ECMAScript target version"
- allowedValues: ["ES3", "ES5"]
+ allowedValues: ["ES3", "ES5", "ES2015"]
}
property string moduleLoader
@@ -120,6 +121,22 @@ Module {
}
validate: {
+ var interpreterMessage = "TypeScript requires the Node.js interpreter to be called 'node'.";
+ if (File.exists("/etc/debian_version")) {
+ interpreterMessage += " Did you forget to install the nodejs-legacy package? " +
+ "See https://lists.debian.org/debian-devel-announce/2012/07/msg00002.html " +
+ "for more information.";
+ }
+
+ var preValidator = new ModUtils.PropertyValidator("nodejs");
+ preValidator.addCustomValidator("interpreterFileName", nodejs.interpreterFileName, function (value) {
+ return value === "node" + (qbs.hostOS.contains("windows") ? ".exe" : "");
+ }, interpreterMessage);
+ preValidator.addCustomValidator("interpreterFilePath", nodejs.interpreterFilePath, function (value) {
+ return value.endsWith(nodejs.interpreterFileName);
+ }, interpreterMessage);
+ preValidator.validate();
+
var validator = new ModUtils.PropertyValidator("typescript");
validator.setRequiredProperty("toolchainInstallPath", toolchainInstallPath);
validator.setRequiredProperty("compilerName", compilerName);
@@ -158,7 +175,8 @@ Module {
name: "io.qt.qbs.internal.typescript-helper"
files: [
FileInfo.joinPaths(path, "qbs-tsc-scan", "qbs-tsc-scan.ts"),
- FileInfo.joinPaths(typescript.toolchainLibInstallPath, "typescript.d.ts")
+ FileInfo.joinPaths(typescript.toolchainLibInstallPath, "typescript.d.ts"),
+ FileInfo.joinPaths(typescript.toolchainLibInstallPath, "..", "package.json")
]
fileTags: ["typescript.typescript-internal"]
}
@@ -173,6 +191,23 @@ Module {
return [];
return [{
filePath: FileInfo.joinPaths(product.buildDirectory,
+ ".io.qt.qbs.internal.typescript", "qbs-tsc-scan.ts"),
+ fileTags: ["typescript.typescript-internal.copy"]
+ },
+ {
+ filePath: FileInfo.joinPaths(product.buildDirectory,
+ ".io.qt.qbs.internal.typescript",
+ "node_modules", "typescript", "lib", "typescript.d.ts"),
+ fileTags: ["typescript.typescript-internal.copy"]
+ },
+ {
+ filePath: FileInfo.joinPaths(product.buildDirectory,
+ ".io.qt.qbs.internal.typescript",
+ "node_modules", "typescript", "package.json"),
+ fileTags: ["typescript.typescript-internal.copy"]
+ },
+ {
+ filePath: FileInfo.joinPaths(product.buildDirectory,
".io.qt.qbs.internal.typescript", "qbs-tsc-scan.js"),
fileTags: ["typescript.compiled_typescript-internal"]
}];
@@ -183,11 +218,30 @@ Module {
return input.filePath;
});
+ var outputPaths = outputs["typescript.typescript-internal.copy"].map(function (output) {
+ return output.filePath;
+ });
+
+ var sortFunc = function (a, b) {
+ return FileInfo.fileName(a).localeCompare(FileInfo.fileName(b));
+ };
+
+ var jcmd = new JavaScriptCommand();
+ jcmd.silent = true;
+ jcmd.inputPaths = inputPaths.sort(sortFunc);
+ jcmd.outputPaths = outputPaths.sort(sortFunc);
+ jcmd.sourceCode = function() {
+ for (var i = 0; i < inputPaths.length; ++i)
+ File.copy(inputPaths[i], outputPaths[i]);
+ };
+
+ var outDir = FileInfo.path(
+ outputs["typescript.compiled_typescript-internal"][0].filePath);
var args = ["--module", "commonjs",
- "--outDir", FileInfo.path(output.filePath)].concat(inputPaths);
+ "--outDir", outDir].concat(outputPaths.filter(function (f) { return !f.endsWith(".json"); }));
var cmd = new Command(ModUtils.moduleProperty(product, "compilerPath"), args);
cmd.silent = true;
- return [cmd];
+ return [jcmd, cmd];
}
}
diff --git a/share/qbs/modules/typescript/typescript.js b/share/qbs/modules/typescript/typescript.js
index 96bd6ec69..d7b7db9b7 100644
--- a/share/qbs/modules/typescript/typescript.js
+++ b/share/qbs/modules/typescript/typescript.js
@@ -92,7 +92,7 @@ function tscArguments(product, inputs) {
args.push("--outDir", product.buildDirectory);
if (ModUtils.moduleProperty(product, "singleFile")) {
- args.push("--out",
+ args.push(outOption(product),
FileInfo.joinPaths(product.destinationDirectory, product.targetName) + ".js");
}
@@ -129,7 +129,10 @@ function outputArtifacts(product, inputs) {
var process;
try {
process = new Process();
- process.setEnv("NODE_PATH", ModUtils.moduleProperty(product, "toolchainInstallPath"));
+ process.setEnv("NODE_PATH", [
+ ModUtils.moduleProperty(product, "toolchainInstallPath"),
+ product.moduleProperty("nodejs", "packageManagerRootPath")
+ ].join(product.moduleProperty("qbs", "pathListSeparator")));
process.exec(product.moduleProperty("nodejs", "interpreterFilePath"),
[FileInfo.joinPaths(product.buildDirectory,
".io.qt.qbs.internal.typescript",
@@ -247,6 +250,17 @@ function legacyOutputArtifacts(product, inputs) {
return artifacts;
}
+function outOption(product) {
+ var compilerVersionMajor = ModUtils.moduleProperty(product, "versionMajor");
+ if (compilerVersionMajor === 1) {
+ if (ModUtils.moduleProperty(product, "versionMinor") < 6) {
+ return "--out";
+ }
+ }
+
+ return "--outFile";
+}
+
function supportsModernFeatures(product) {
var compilerVersionMajor = ModUtils.moduleProperty(product, "versionMajor");
if (compilerVersionMajor === 1) {
diff --git a/share/qbs/modules/xcode/xcode.js b/share/qbs/modules/xcode/xcode.js
index afe3babfa..e170b154a 100644
--- a/share/qbs/modules/xcode/xcode.js
+++ b/share/qbs/modules/xcode/xcode.js
@@ -33,27 +33,6 @@ var FileInfo = loadExtension("qbs.FileInfo");
var Process = loadExtension("qbs.Process");
var PropertyList = loadExtension("qbs.PropertyList");
-function applePlatformDirectoryName(targetOSList, version, throwOnError) {
- if (!version)
- version = "";
- if (targetOSList.contains("ios-simulator"))
- return "iPhoneSimulator" + version;
- else if (targetOSList.contains("ios"))
- return "iPhoneOS" + version;
- else if (targetOSList.contains("osx"))
- return "MacOSX" + version;
- else if (targetOSList.contains("tvos-simulator"))
- return "AppleTVSimulator" + version;
- else if (targetOSList.contains("tvos"))
- return "AppleTVOS" + version;
- else if (targetOSList.contains("watchos-simulator"))
- return "WatchSimulator" + version;
- else if (targetOSList.contains("watchos"))
- return "WatchOS" + version;
- if (throwOnError || throwOnError === undefined)
- throw("No Apple platform corresponds to target OS list: " + targetOSList);
-}
-
function sdkInfoList(sdksPath) {
var sdkInfo = [];
var sdks = File.directoryEntries(sdksPath, File.Dirs | File.NoDotAndDotDot);
diff --git a/share/qbs/modules/xcode/xcode.qbs b/share/qbs/modules/xcode/xcode.qbs
index f9b717867..22b39cdb8 100644
--- a/share/qbs/modules/xcode/xcode.qbs
+++ b/share/qbs/modules/xcode/xcode.qbs
@@ -10,12 +10,19 @@ import 'xcode.js' as Utils
Module {
condition: qbs.hostOS.contains("darwin") && qbs.targetOS.contains("darwin") &&
- qbs.toolchain.contains("xcode")
+ qbs.toolchain && qbs.toolchain.contains("xcode")
property path developerPath: "/Applications/Xcode.app/Contents/Developer"
property string sdk: DarwinTools.applePlatformName(qbs.targetOS)
property stringList targetDevices: DarwinTools.targetDevices(qbs.targetOS)
+ property string platformType: {
+ if (qbs.targetOS.containsAny(["ios-simulator", "tvos-simulator", "watchos-simulator"]))
+ return "simulator";
+ if (qbs.targetOS.containsAny(["ios", "tvos", "watchos"]))
+ return "device";
+ }
+
readonly property string sdkName: {
if (_sdkSettings) {
return _sdkSettings["CanonicalName"];
@@ -77,12 +84,12 @@ Module {
readonly property path toolchainPath: FileInfo.joinPaths(toolchainsPath,
"XcodeDefault" + ".xctoolchain")
readonly property path platformPath: FileInfo.joinPaths(platformsPath,
- Utils.applePlatformDirectoryName(
- qbs.targetOS)
+ DarwinTools.applePlatformDirectoryName(
+ qbs.targetOS, platformType)
+ ".platform")
readonly property path sdkPath: FileInfo.joinPaths(sdksPath,
- Utils.applePlatformDirectoryName(
- qbs.targetOS, sdkVersion)
+ DarwinTools.applePlatformDirectoryName(
+ qbs.targetOS, platformType, sdkVersion)
+ ".sdk")
// private properties
@@ -153,8 +160,8 @@ Module {
validator.setRequiredProperty("sdkPath", sdkPath);
validator.addVersionValidator("sdkVersion", sdkVersion, 2, 2);
validator.addCustomValidator("sdkName", sdkName, function (value) {
- return value === Utils.applePlatformDirectoryName(
- qbs.targetOS, sdkVersion, false).toLowerCase();
+ return value === DarwinTools.applePlatformDirectoryName(
+ qbs.targetOS, platformType, sdkVersion, false).toLowerCase();
}, " is '" + sdkName + "', but target OS is [" + qbs.targetOS.join(",")
+ "] and Xcode SDK version is '" + sdkVersion + "'");
validator.validate();
@@ -195,6 +202,7 @@ Module {
name: "Provisioning Profiles"
prefix: xcode.provisioningProfilesPath + "/"
files: ["*.mobileprovision", "*.provisionprofile"]
+ fileTags: [] // HACK: provisioning profile handling is not yet ready and can break autotests
}
FileTagger {
diff --git a/src/app/qbs-setup-toolchains/probe.cpp b/src/app/qbs-setup-toolchains/probe.cpp
index aa3a2f3ef..fb245c4eb 100644
--- a/src/app/qbs-setup-toolchains/probe.cpp
+++ b/src/app/qbs-setup-toolchains/probe.cpp
@@ -66,7 +66,7 @@ static QString findExecutable(const QString &fileName)
const QString path = QString::fromLocal8Bit(qgetenv("PATH"));
foreach (const QString &ppath, path.split(HostOsInfo::pathListSeparator())) {
const QString fullPath = ppath + QLatin1Char('/') + fullFileName;
- if (QFileInfo(fullPath).exists())
+ if (QFileInfo::exists(fullPath))
return QDir::cleanPath(fullPath);
}
return QString();
@@ -138,7 +138,7 @@ static void setCommonProperties(Profile &profile, const QString &compilerFilePat
const QStringList &toolchainTypes, const QString &architecture)
{
const QFileInfo cfi(compilerFilePath);
- const QString compilerName = QFileInfo(compilerFilePath).fileName();
+ const QString compilerName = cfi.fileName();
if (toolchainTypes.contains(QStringLiteral("mingw")))
profile.setValue(QStringLiteral("qbs.targetOS"), QStringList(QStringLiteral("windows")));
@@ -185,8 +185,8 @@ public:
private:
Profile * const m_profile;
- const QString &m_compilerDirPath;
- const QString &m_toolchainPrefix;
+ QString m_compilerDirPath;
+ QString m_toolchainPrefix;
};
static Profile createGccProfile(const QString &compilerFilePath, Settings *settings,
@@ -237,11 +237,12 @@ static void gccProbe(Settings *settings, QList<Profile> &profiles, const QString
const QString crossCompilePrefix = QString::fromLocal8Bit(qgetenv("CROSS_COMPILE"));
const QString compilerFilePath = findExecutable(crossCompilePrefix + compilerName);
- if (!QFileInfo(compilerFilePath).exists()) {
+ QFileInfo cfi(compilerFilePath);
+ if (!cfi.exists()) {
qStderr << Tr::tr("%1 not found.").arg(compilerName) << endl;
return;
}
- const QString profileName = QFileInfo(compilerFilePath).completeBaseName();
+ const QString profileName = cfi.completeBaseName();
const QStringList toolchainTypes = toolchainTypeFromCompilerName(compilerName);
profiles << createGccProfile(compilerFilePath, settings, toolchainTypes, profileName);
}
diff --git a/src/app/qbs/commandlinefrontend.cpp b/src/app/qbs/commandlinefrontend.cpp
index 36f1522d3..fb26bca83 100644
--- a/src/app/qbs/commandlinefrontend.cpp
+++ b/src/app/qbs/commandlinefrontend.cpp
@@ -416,7 +416,7 @@ int CommandLineFrontend::runShell()
RunEnvironment runEnvironment = m_projects.first().getRunEnvironment(productToRun,
m_parser.installOptions(m_projects.first().profile()),
QProcessEnvironment::systemEnvironment(), m_settings);
- return runEnvironment.runShell();
+ return runEnvironment.doRunShell();
}
BuildOptions CommandLineFrontend::buildOptions(const Project &project) const
@@ -513,7 +513,7 @@ int CommandLineFrontend::runTarget()
RunEnvironment runEnvironment = m_projects.first().getRunEnvironment(productToRun,
m_parser.installOptions(m_projects.first().profile()),
QProcessEnvironment::systemEnvironment(), m_settings);
- return runEnvironment.runTarget(executableFilePath, m_parser.runArgs());
+ return runEnvironment.doRunTarget(executableFilePath, m_parser.runArgs());
}
void CommandLineFrontend::updateTimestamps()
diff --git a/src/lib/corelib/api/project.cpp b/src/lib/corelib/api/project.cpp
index a8707a7b6..12236e00c 100644
--- a/src/lib/corelib/api/project.cpp
+++ b/src/lib/corelib/api/project.cpp
@@ -72,6 +72,7 @@
#include <QMutexLocker>
#include <QRegExp>
#include <QSharedData>
+#include <QtDebug>
namespace qbs {
namespace Internal {
@@ -1010,16 +1011,20 @@ QList<InstallableFile> Project::installableFilesForProduct(const ProductData &pr
foreach (const GroupConstPtr &group, internalProduct->groups) {
foreach (const SourceArtifactConstPtr &artifact, group->allFiles()) {
InstallableFile f;
- const QString &targetFilePath = ProductInstaller::targetFilePath(internalProduct->topLevelProject(),
+ try {
+ const QString &targetFilePath = ProductInstaller::targetFilePath(internalProduct->topLevelProject(),
internalProduct->sourceDirectory,
artifact->absoluteFilePath, artifact->properties, mutableOptions);
- if (targetFilePath.isEmpty())
- continue;
- f.d->sourceFilePath = artifact->absoluteFilePath;
- f.d->fileTags = artifact->fileTags.toStringList();
- f.d->targetFilePath = targetFilePath;
- f.d->isValid = true;
- installableFiles << f;
+ if (targetFilePath.isEmpty())
+ continue;
+ f.d->sourceFilePath = artifact->absoluteFilePath;
+ f.d->fileTags = artifact->fileTags.toStringList();
+ f.d->targetFilePath = targetFilePath;
+ f.d->isValid = true;
+ installableFiles << f;
+ } catch (const ErrorInfo &e) {
+ qDebug() << e.toString();
+ }
}
}
if (internalProduct->enabled) {
@@ -1028,17 +1033,21 @@ QList<InstallableFile> Project::installableFilesForProduct(const ProductData &pr
ArtifactSet::fromNodeSet(internalProduct->buildData->nodes)) {
if (artifact->artifactType == Artifact::SourceFile)
continue;
- InstallableFile f;
- const QString &targetFilePath = ProductInstaller::targetFilePath(internalProduct->topLevelProject(),
- internalProduct->sourceDirectory,
- artifact->filePath(), artifact->properties, mutableOptions);
- if (targetFilePath.isEmpty())
- continue;
- f.d->sourceFilePath = artifact->filePath();
- f.d->fileTags = artifact->fileTags().toStringList();
- f.d->targetFilePath = targetFilePath;
- f.d->isValid = true;
- installableFiles << f;
+ try {
+ InstallableFile f;
+ const QString &targetFilePath = ProductInstaller::targetFilePath(internalProduct->topLevelProject(),
+ internalProduct->sourceDirectory, artifact->filePath(),
+ artifact->properties, mutableOptions);
+ if (targetFilePath.isEmpty())
+ continue;
+ f.d->sourceFilePath = artifact->filePath();
+ f.d->fileTags = artifact->fileTags().toStringList();
+ f.d->targetFilePath = targetFilePath;
+ f.d->isValid = true;
+ installableFiles << f;
+ } catch (const ErrorInfo &e) {
+ qDebug() << e.toString();
+ }
}
}
qSort(installableFiles);
diff --git a/src/lib/corelib/api/runenvironment.cpp b/src/lib/corelib/api/runenvironment.cpp
index e0f0a0c91..aee7aa31a 100644
--- a/src/lib/corelib/api/runenvironment.cpp
+++ b/src/lib/corelib/api/runenvironment.cpp
@@ -92,7 +92,52 @@ RunEnvironment::~RunEnvironment()
delete d;
}
-int RunEnvironment::runShell()
+int RunEnvironment::runShell(ErrorInfo *error)
+{
+ try {
+ return doRunShell();
+ } catch (const ErrorInfo &e) {
+ if (error)
+ *error = e;
+ return -1;
+ }
+}
+
+int RunEnvironment::runTarget(const QString &targetBin, const QStringList &arguments,
+ ErrorInfo *error)
+{
+ try {
+ return doRunTarget(targetBin, arguments);
+ } catch (const ErrorInfo &e) {
+ if (error)
+ *error = e;
+ return -1;
+ }
+}
+
+const QProcessEnvironment RunEnvironment::runEnvironment(ErrorInfo *error) const
+{
+ try {
+ return getRunEnvironment();
+ } catch (const ErrorInfo &e) {
+ if (error)
+ *error = e;
+ return QProcessEnvironment();
+ }
+}
+
+const QProcessEnvironment RunEnvironment::buildEnvironment(ErrorInfo *error) const
+{
+ try {
+ return getBuildEnvironment();
+ } catch (const ErrorInfo &e) {
+ if (error)
+ *error = e;
+ return QProcessEnvironment();
+ }
+}
+
+int RunEnvironment::doRunShell()
{
d->resolvedProduct->setupBuildEnvironment(&d->engine, d->environment);
@@ -156,7 +201,7 @@ static QString findExecutable(const QStringList &fileNames)
return QString();
}
-int RunEnvironment::runTarget(const QString &targetBin, const QStringList &arguments)
+int RunEnvironment::doRunTarget(const QString &targetBin, const QStringList &arguments)
{
const QStringList targetOS = PropertyFinder().propertyValue(
d->resolvedProduct->moduleProperties->value(),
@@ -287,13 +332,13 @@ int RunEnvironment::runTarget(const QString &targetBin, const QStringList &argum
return process.exitCode();
}
-const QProcessEnvironment RunEnvironment::runEnvironment() const
+const QProcessEnvironment RunEnvironment::getRunEnvironment() const
{
d->resolvedProduct->setupRunEnvironment(&d->engine, d->environment);
return d->resolvedProduct->runEnvironment;
}
-const QProcessEnvironment RunEnvironment::buildEnvironment() const
+const QProcessEnvironment RunEnvironment::getBuildEnvironment() const
{
d->resolvedProduct->setupBuildEnvironment(&d->engine, d->environment);
return d->resolvedProduct->buildEnvironment;
diff --git a/src/lib/corelib/api/runenvironment.h b/src/lib/corelib/api/runenvironment.h
index 93f3de7b2..7c276454e 100644
--- a/src/lib/corelib/api/runenvironment.h
+++ b/src/lib/corelib/api/runenvironment.h
@@ -41,6 +41,7 @@ class QProcessEnvironment;
QT_END_NAMESPACE
namespace qbs {
+class ErrorInfo;
class InstallOptions;
class Settings;
@@ -51,16 +52,17 @@ class ResolvedProduct;
class QBS_EXPORT RunEnvironment
{
+ friend class CommandLineFrontend;
friend class Project;
public:
~RunEnvironment();
- // These can throw an Error
- int runShell();
- int runTarget(const QString &targetBin, const QStringList &arguments);
+ int runShell(ErrorInfo *error = nullptr);
+ int runTarget(const QString &targetBin, const QStringList &arguments,
+ ErrorInfo *error = nullptr);
- const QProcessEnvironment runEnvironment() const;
- const QProcessEnvironment buildEnvironment() const;
+ const QProcessEnvironment runEnvironment(ErrorInfo *error = nullptr) const;
+ const QProcessEnvironment buildEnvironment(ErrorInfo *error = nullptr) const;
private:
RunEnvironment(const Internal::ResolvedProductPtr &product,
@@ -68,6 +70,12 @@ private:
const QProcessEnvironment &environment, Settings *settings,
const Internal::Logger &logger);
+ int doRunShell();
+ int doRunTarget(const QString &targetBin, const QStringList &arguments);
+
+ const QProcessEnvironment getRunEnvironment() const;
+ const QProcessEnvironment getBuildEnvironment() const;
+
class RunEnvironmentPrivate;
RunEnvironmentPrivate * const d;
};
diff --git a/src/lib/corelib/buildgraph/jscommandexecutor.cpp b/src/lib/corelib/buildgraph/jscommandexecutor.cpp
index 914d2c9e1..5cf4840fe 100644
--- a/src/lib/corelib/buildgraph/jscommandexecutor.cpp
+++ b/src/lib/corelib/buildgraph/jscommandexecutor.cpp
@@ -213,8 +213,10 @@ void JsCommandExecutor::onJavaScriptCommandFinished()
if (!result.success) {
logger().qbsDebug() << "JS context:\n" << jsCommand()->properties();
logger().qbsDebug() << "JS code:\n" << jsCommand()->sourceCode();
- err.append(tr("Error while executing JavaScriptCommand:"), result.errorLocation);
err.append(result.errorMessage);
+ // ### We don't know the line number of the command's sourceCode property assignment.
+ err.appendBacktrace(QStringLiteral("JavaScriptCommand.sourceCode"));
+ err.appendBacktrace(QStringLiteral("Rule.prepare"), result.errorLocation);
}
emit finished(err);
}
diff --git a/src/lib/corelib/buildgraph/qtmocscanner.cpp b/src/lib/corelib/buildgraph/qtmocscanner.cpp
index d74e646d2..b03e06a85 100644
--- a/src/lib/corelib/buildgraph/qtmocscanner.cpp
+++ b/src/lib/corelib/buildgraph/qtmocscanner.cpp
@@ -67,6 +67,15 @@ QtMocScanner::~QtMocScanner()
delete m_scanResultCache;
}
+ScannerPlugin *QtMocScanner::scannerPluginForFileTags(const FileTags &ft)
+{
+ if (ft.contains("objcpp"))
+ return m_objcppScanner;
+ if (ft.contains("cpp"))
+ return m_cppScanner;
+ return m_hppScanner;
+}
+
static ScanResultCache::Result runScanner(ScannerPlugin *scanner, const Artifact *artifact,
ScanResultCache *scanResultCache)
{
@@ -118,9 +127,13 @@ void QtMocScanner::findIncludedMocCppFiles()
if (m_logger.traceEnabled())
m_logger.qbsTrace() << "[QtMocScanner] looking for included moc_XXX.cpp files";
- foreach (Artifact *artifact, m_product->lookupArtifactsByFileTag("cpp")) {
+ static const FileTags mocCppTags = FileTags::fromStringList(QStringList()
+ << QStringLiteral("cpp")
+ << QStringLiteral("objcpp"));
+ foreach (Artifact *artifact, m_product->lookupArtifactsByFileTags(mocCppTags)) {
const ScanResultCache::Result scanResult
- = runScanner(m_cppScanner, artifact, m_scanResultCache);
+ = runScanner(scannerPluginForFileTags(artifact->fileTags()),
+ artifact, m_scanResultCache);
foreach (const ScanResultCache::Dependency &dependency, scanResult.deps) {
QString includedFileName = dependency.fileName();
if (includedFileName.startsWith(QLatin1String("moc_"))
@@ -158,6 +171,10 @@ QScriptValue QtMocScanner::apply(QScriptEngine *engine, const Artifact *artifact
if (scanners.count() != 1)
return scannerCountError(engine, scanners.count(), QLatin1String("cpp"));
m_cppScanner = scanners.first();
+ scanners = ScannerPluginManager::scannersForFileTag("objcpp");
+ if (scanners.count() != 1)
+ return scannerCountError(engine, scanners.count(), QLatin1String("objcpp"));
+ m_objcppScanner = scanners.first();
scanners = ScannerPluginManager::scannersForFileTag("hpp");
if (scanners.count() != 1)
return scannerCountError(engine, scanners.count(), QLatin1String("hpp"));
@@ -174,7 +191,8 @@ QScriptValue QtMocScanner::apply(QScriptEngine *engine, const Artifact *artifact
bool hasPluginMetaDataMacro = false;
const bool isHeaderFile = artifact->fileTags().contains("hpp");
- ScannerPlugin * const scanner = isHeaderFile ? m_hppScanner : m_cppScanner;
+ ScannerPlugin * const scanner = scannerPluginForFileTags(artifact->fileTags());
+
const ScanResultCache::Result scanResult = runScanner(scanner, artifact, m_scanResultCache);
if (!scanResult.additionalFileTags.isEmpty()) {
if (isHeaderFile) {
diff --git a/src/lib/corelib/buildgraph/qtmocscanner.h b/src/lib/corelib/buildgraph/qtmocscanner.h
index 0d903789f..d53f57f5f 100644
--- a/src/lib/corelib/buildgraph/qtmocscanner.h
+++ b/src/lib/corelib/buildgraph/qtmocscanner.h
@@ -58,6 +58,7 @@ public:
~QtMocScanner();
private:
+ ScannerPlugin *scannerPluginForFileTags(const FileTags &ft);
void findIncludedMocCppFiles();
static QScriptValue js_apply(QScriptContext *ctx, QScriptEngine *engine, void *data);
QScriptValue apply(QScriptEngine *engine, const Artifact *artifact);
@@ -68,6 +69,7 @@ private:
ScanResultCache *m_scanResultCache;
QHash<QString, QString> m_includedMocCppFiles;
ScannerPlugin *m_cppScanner;
+ ScannerPlugin *m_objcppScanner;
ScannerPlugin *m_hppScanner;
};
diff --git a/src/lib/corelib/buildgraph/rulenode.cpp b/src/lib/corelib/buildgraph/rulenode.cpp
index 20238e8e3..dfc12c3ab 100644
--- a/src/lib/corelib/buildgraph/rulenode.cpp
+++ b/src/lib/corelib/buildgraph/rulenode.cpp
@@ -125,7 +125,7 @@ void RuleNode::apply(const Logger &logger, const ArtifactSet &changedInputs,
}
if (!inputs.isEmpty()) {
RulesApplicator applicator(product, logger);
- applicator.applyRuleInEvaluationContext(m_rule, inputs);
+ applicator.applyRule(m_rule, inputs);
result->createdNodes = applicator.createdArtifacts();
result->invalidatedNodes = applicator.invalidatedArtifacts();
m_oldInputArtifacts.unite(inputs);
diff --git a/src/lib/corelib/buildgraph/rulesapplicator.cpp b/src/lib/corelib/buildgraph/rulesapplicator.cpp
index a265e6564..07b3969d7 100644
--- a/src/lib/corelib/buildgraph/rulesapplicator.cpp
+++ b/src/lib/corelib/buildgraph/rulesapplicator.cpp
@@ -70,20 +70,15 @@ RulesApplicator::~RulesApplicator()
delete m_mocScanner;
}
-void RulesApplicator::applyRuleInEvaluationContext(const RuleConstPtr &rule,
- const ArtifactSet &inputArtifacts)
-{
- m_createdArtifacts.clear();
- m_invalidatedArtifacts.clear();
- RulesEvaluationContext::Scope s(m_product->topLevelProject()->buildData->evaluationContext.data());
- applyRule(rule, inputArtifacts);
-}
-
void RulesApplicator::applyRule(const RuleConstPtr &rule, const ArtifactSet &inputArtifacts)
{
if (inputArtifacts.isEmpty())
return;
+ m_createdArtifacts.clear();
+ m_invalidatedArtifacts.clear();
+ RulesEvaluationContext::Scope s(evalContext().data());
+
m_rule = rule;
m_completeInputSet = inputArtifacts;
if (rule->name == QLatin1String("QtCoreMocRule")) {
@@ -270,11 +265,14 @@ Artifact *RulesApplicator::createOutputArtifactFromRuleArtifact(
const RuleArtifactConstPtr &ruleArtifact, const ArtifactSet &inputArtifacts,
QSet<QString> *outputFilePaths)
{
- QScriptValue scriptValue = engine()->evaluate(ruleArtifact->filePath);
+ QScriptValue scriptValue = engine()->evaluate(ruleArtifact->filePath,
+ ruleArtifact->filePathLocation.filePath(),
+ ruleArtifact->filePathLocation.line());
if (Q_UNLIKELY(engine()->hasErrorOrException(scriptValue))) {
- throw ErrorInfo(Tr::tr("Error in Rule.Artifact fileName at %1: %2")
- .arg(ruleArtifact->location.toString(),
- engine()->lastErrorString(scriptValue)));
+ ErrorInfo errorInfo(engine()->lastErrorString(scriptValue),
+ engine()->uncaughtExceptionBacktraceOrEmpty());
+ errorInfo.append(QStringLiteral("Artifact.filePath"), ruleArtifact->filePathLocation);
+ throw errorInfo;
}
QString outputPath = FileInfo::resolvePath(m_product->buildDirectory(), scriptValue.toString());
if (Q_UNLIKELY(outputFilePaths->contains(outputPath))) {
@@ -377,14 +375,20 @@ QList<Artifact *> RulesApplicator::runOutputArtifactsScript(const ArtifactSet &i
const QScriptValueList &args)
{
QList<Artifact *> lst;
- QScriptValue fun = engine()->evaluate(m_rule->outputArtifactsScript->sourceCode);
+ QScriptValue fun = engine()->evaluate(m_rule->outputArtifactsScript->sourceCode,
+ m_rule->outputArtifactsScript->location.filePath(),
+ m_rule->outputArtifactsScript->location.line());
if (!fun.isFunction())
throw ErrorInfo(QLatin1String("Function expected."),
m_rule->outputArtifactsScript->location);
QScriptValue res = fun.call(QScriptValue(), args);
- if (res.isError() || engine()->hasUncaughtException())
- throw ErrorInfo(Tr::tr("Error while calling Rule.outputArtifacts: %1").arg(res.toString()),
- m_rule->outputArtifactsScript->location);
+ if (engine()->hasErrorOrException(res)) {
+ ErrorInfo errorInfo(engine()->lastErrorString(res),
+ engine()->uncaughtExceptionBacktraceOrEmpty());
+ errorInfo.append(QStringLiteral("Rule.outputArtifacts"),
+ m_rule->outputArtifactsScript->location);
+ throw errorInfo;
+ }
if (!res.isArray())
throw ErrorInfo(Tr::tr("Rule.outputArtifacts must return an array of objects."),
m_rule->outputArtifactsScript->location);
@@ -525,7 +529,7 @@ QString RulesApplicator::resolveOutPath(const QString &path) const
return result;
}
-RulesEvaluationContextPtr RulesApplicator::evalContext() const
+const RulesEvaluationContextPtr &RulesApplicator::evalContext() const
{
return m_product->topLevelProject()->buildData->evaluationContext;
}
diff --git a/src/lib/corelib/buildgraph/rulesapplicator.h b/src/lib/corelib/buildgraph/rulesapplicator.h
index 9365483d3..f0e530e02 100644
--- a/src/lib/corelib/buildgraph/rulesapplicator.h
+++ b/src/lib/corelib/buildgraph/rulesapplicator.h
@@ -53,8 +53,6 @@ public:
RulesApplicator(const ResolvedProductPtr &product, const Logger &logger);
~RulesApplicator();
- void applyRuleInEvaluationContext(const RuleConstPtr &rule,
- const ArtifactSet &inputArtifacts);
const NodeSet &createdArtifacts() const { return m_createdArtifacts; }
const NodeSet &invalidatedArtifacts() const { return m_invalidatedArtifacts; }
@@ -74,7 +72,7 @@ private:
Artifact *createOutputArtifactFromScriptValue(const QScriptValue &obj,
const ArtifactSet &inputArtifacts);
QString resolveOutPath(const QString &path) const;
- RulesEvaluationContextPtr evalContext() const;
+ const RulesEvaluationContextPtr &evalContext() const;
ScriptEngine *engine() const;
QScriptValue scope() const;
diff --git a/src/lib/corelib/buildgraph/rulesevaluationcontext.cpp b/src/lib/corelib/buildgraph/rulesevaluationcontext.cpp
index eed00cdac..1b7efb33c 100644
--- a/src/lib/corelib/buildgraph/rulesevaluationcontext.cpp
+++ b/src/lib/corelib/buildgraph/rulesevaluationcontext.cpp
@@ -86,9 +86,6 @@ void RulesEvaluationContext::initScope()
if (m_initScopeCalls++ > 0)
return;
- m_engine->setProperty("lastSetupProject", QVariant());
- m_engine->setProperty("lastSetupProduct", QVariant());
-
m_engine->clearImportsCache();
m_engine->pushContext();
m_scope = m_engine->newObject();
diff --git a/src/lib/corelib/buildgraph/transformer.cpp b/src/lib/corelib/buildgraph/transformer.cpp
index c0ad6ed07..9278df64d 100644
--- a/src/lib/corelib/buildgraph/transformer.cpp
+++ b/src/lib/corelib/buildgraph/transformer.cpp
@@ -208,7 +208,9 @@ void Transformer::createCommands(const ScriptFunctionConstPtr &script,
{
ScriptEngine * const engine = evalContext->engine();
if (!script->scriptFunction.isValid() || script->scriptFunction.engine() != engine) {
- script->scriptFunction = engine->evaluate(script->sourceCode);
+ script->scriptFunction = engine->evaluate(script->sourceCode,
+ script->location.filePath(),
+ script->location.line());
if (Q_UNLIKELY(!script->scriptFunction.isFunction()))
throw ErrorInfo(Tr::tr("Invalid prepare script."), script->location);
}
@@ -217,11 +219,15 @@ void Transformer::createCommands(const ScriptFunctionConstPtr &script,
propertiesRequestedInPrepareScript = engine->propertiesRequestedInScript();
propertiesRequestedFromArtifactInPrepareScript = engine->propertiesRequestedFromArtifact();
engine->clearRequestedProperties();
- if (Q_UNLIKELY(engine->hasErrorOrException(scriptValue)))
- throw ErrorInfo(Tr::tr("evaluating prepare script: ")
- + engine->lastErrorString(scriptValue),
- CodeLocation(script->location.filePath(),
- script->location.line() + engine->uncaughtExceptionLineNumber() - 1));
+ if (Q_UNLIKELY(engine->hasErrorOrException(scriptValue))) {
+ ErrorInfo errorInfo(engine->lastErrorString(scriptValue),
+ engine->uncaughtExceptionBacktraceOrEmpty());
+ if (rule)
+ errorInfo.append(QStringLiteral("Rule.prepare"), script->location);
+ else
+ errorInfo.append(QStringLiteral("Transformer.prepare"), script->location);
+ throw errorInfo;
+ }
commands.clear();
if (scriptValue.isArray()) {
diff --git a/src/lib/corelib/corelib.pro b/src/lib/corelib/corelib.pro
index 1c3213c5e..8644f9977 100644
--- a/src/lib/corelib/corelib.pro
+++ b/src/lib/corelib/corelib.pro
@@ -1,7 +1,7 @@
TARGET = qbscore
include(../library.pri)
-QT += script
+QT += core-private network script
qbs_enable_unit_tests:QT += testlib
qbs_enable_project_file_updates: QT += gui
diff --git a/src/lib/corelib/corelib.qbs b/src/lib/corelib/corelib.qbs
index b57f859ad..d20378764 100644
--- a/src/lib/corelib/corelib.qbs
+++ b/src/lib/corelib/corelib.qbs
@@ -3,7 +3,7 @@ import QbsFunctions
QbsLibrary {
Depends { name: "cpp" }
- Depends { name: "Qt"; submodules: ["script", "xml"] }
+ Depends { name: "Qt"; submodules: ["core-private", "network", "script", "xml"] }
Depends { condition: project.enableProjectFileUpdates; name: "Qt.gui" }
Depends { condition: project.enableUnitTests; name: "Qt.test" }
name: "qbscore"
@@ -31,7 +31,7 @@ QbsLibrary {
Properties {
condition: qbs.targetOS.contains("darwin")
- cpp.frameworks: "Foundation"
+ cpp.frameworks: ["Foundation", "Security"]
}
Group {
@@ -409,6 +409,15 @@ QbsLibrary {
]
}
Group {
+ condition: qbs.targetOS.contains("osx")
+ name: "tools (OS X)"
+ prefix: "tools/"
+ files: [
+ "applecodesignutils.cpp",
+ "applecodesignutils.h"
+ ]
+ }
+ Group {
condition: qbs.targetOS.contains("unix")
name: "tools (Unix)"
prefix: "tools/"
diff --git a/src/lib/corelib/jsextensions/propertylist.mm b/src/lib/corelib/jsextensions/propertylist.mm
index b236d7225..dae241e5f 100644
--- a/src/lib/corelib/jsextensions/propertylist.mm
+++ b/src/lib/corelib/jsextensions/propertylist.mm
@@ -128,15 +128,14 @@ void PropertyList::readFromFile(const QString &filePath)
QFile file(filePath);
if (file.open(QIODevice::ReadOnly)) {
- QByteArray data = file.readAll();
- if (!data.isEmpty()) {
+ const QByteArray data = file.readAll();
+ if (file.error() == QFile::NoError) {
p->d->readFromData(p->context(), data);
- } else {
- p->context()->throwError(file.errorString());
+ return;
}
- } else {
- p->context()->throwError(file.errorString());
}
+
+ p->context()->throwError(QStringLiteral("%1: %2").arg(filePath).arg(file.errorString()));
}
void PropertyList::readFromData(const QByteArray &data)
@@ -151,17 +150,15 @@ void PropertyList::writeToFile(const QString &filePath, const QString &plistForm
Q_ASSERT(thisObject().engine() == engine());
PropertyList *p = qscriptvalue_cast<PropertyList*>(thisObject());
+ QFile file(filePath);
QByteArray data = p->d->writeToData(p->context(), plistFormat);
if (Q_LIKELY(!data.isEmpty())) {
- QFile file(filePath);
- if (file.open(QIODevice::WriteOnly)) {
- if (Q_UNLIKELY(file.write(data) != data.size())) {
- p->context()->throwError(file.errorString());
- }
- } else {
- p->context()->throwError(file.errorString());
+ if (file.open(QIODevice::WriteOnly) && file.write(data) == data.size()) {
+ return;
}
}
+
+ p->context()->throwError(QStringLiteral("%1: %2").arg(filePath).arg(file.errorString()));
}
QScriptValue PropertyList::format() const
@@ -300,7 +297,7 @@ QByteArray PropertyListPrivate::writeToData(QScriptContext *context, const QStri
id obj = QPropertyListUtils::toPropertyList(propertyListObject);
if (!obj) {
context->throwError(QLatin1String("error converting property list"));
- return 0;
+ return QByteArray();
}
if (format == QLatin1String("json") || format == QLatin1String("json-pretty") ||
diff --git a/src/lib/corelib/jsextensions/utilitiesextension.cpp b/src/lib/corelib/jsextensions/utilitiesextension.cpp
index 10ded8bda..6ce37b6bf 100644
--- a/src/lib/corelib/jsextensions/utilitiesextension.cpp
+++ b/src/lib/corelib/jsextensions/utilitiesextension.cpp
@@ -35,6 +35,10 @@
#include <tools/architectures.h>
#include <tools/fileinfo.h>
+#ifdef Q_OS_OSX
+#include <tools/applecodesignutils.h>
+#endif
+
#include <QCryptographicHash>
#include <QDir>
#include <QFileInfo>
@@ -55,6 +59,10 @@ public:
static QScriptValue js_getNativeSetting(QScriptContext *context, QScriptEngine *engine);
static QScriptValue js_nativeSettingGroups(QScriptContext *context, QScriptEngine *engine);
static QScriptValue js_rfc1034identifier(QScriptContext *context, QScriptEngine *engine);
+
+ static QScriptValue js_smimeMessageContent(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue js_certificateInfo(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue js_signingIdentities(QScriptContext *context, QScriptEngine *engine);
};
void initializeJsExtensionUtilities(QScriptValue extensionObject)
@@ -72,6 +80,12 @@ void initializeJsExtensionUtilities(QScriptValue extensionObject)
engine->newFunction(UtilitiesExtension::js_nativeSettingGroups, 1));
environmentObj.setProperty(QStringLiteral("rfc1034Identifier"),
engine->newFunction(UtilitiesExtension::js_rfc1034identifier, 1));
+ environmentObj.setProperty(QStringLiteral("smimeMessageContent"),
+ engine->newFunction(UtilitiesExtension::js_smimeMessageContent, 1));
+ environmentObj.setProperty(QStringLiteral("certificateInfo"),
+ engine->newFunction(UtilitiesExtension::js_certificateInfo, 1));
+ environmentObj.setProperty(QStringLiteral("signingIdentities"),
+ engine->newFunction(UtilitiesExtension::js_signingIdentities, 0));
extensionObject.setProperty(QStringLiteral("Utilities"), environmentObj);
}
@@ -147,6 +161,69 @@ QScriptValue UtilitiesExtension::js_rfc1034identifier(QScriptContext *context,
return engine->toScriptValue(HostOsInfo::rfc1034Identifier(identifier));
}
+/**
+ * Reads the contents of the S/MIME message located at \p filePath.
+ * An equivalent command line would be:
+ * \code security cms -D -i <infile> -o <outfile> \endcode
+ * or:
+ * \code openssl smime -verify -noverify -inform DER -in <infile> -out <outfile> \endcode
+ *
+ * \note A provisioning profile is an S/MIME message whose contents are an XML property list,
+ * so this method can be used to read such files.
+ */
+QScriptValue UtilitiesExtension::js_smimeMessageContent(QScriptContext *context,
+ QScriptEngine *engine)
+{
+#ifndef Q_OS_OSX
+ Q_UNUSED(engine);
+ return context->throwError(QScriptContext::UnknownError,
+ QLatin1String("smimeMessageContent is not available on this platform"));
+#else
+ if (Q_UNLIKELY(context->argumentCount() != 1))
+ return context->throwError(QScriptContext::SyntaxError,
+ QLatin1String("smimeMessageContent expects 1 argument"));
+
+ const QString filePath = context->argument(0).toString();
+ QFile file(filePath);
+ if (!file.open(QIODevice::ReadOnly))
+ return engine->undefinedValue();
+
+ QByteArray content = smimeMessageContent(file.readAll());
+ if (content.isEmpty())
+ return engine->undefinedValue();
+ return engine->toScriptValue(content);
+#endif
+}
+
+QScriptValue UtilitiesExtension::js_certificateInfo(QScriptContext *context,
+ QScriptEngine *engine)
+{
+#ifndef Q_OS_OSX
+ Q_UNUSED(engine);
+ return context->throwError(QScriptContext::UnknownError,
+ QLatin1String("certificateInfo is not available on this platform"));
+#else
+ if (Q_UNLIKELY(context->argumentCount() != 1))
+ return context->throwError(QScriptContext::SyntaxError,
+ QLatin1String("certificateInfo expects 1 argument"));
+ return engine->toScriptValue(certificateInfo(context->argument(0).toVariant().toByteArray()));
+#endif
+}
+
+// Rough command line equivalent: security find-identity -p codesigning -v
+QScriptValue UtilitiesExtension::js_signingIdentities(QScriptContext *context,
+ QScriptEngine *engine)
+{
+#ifndef Q_OS_OSX
+ Q_UNUSED(engine);
+ return context->throwError(QScriptContext::UnknownError,
+ QLatin1String("signingIdentities is not available on this platform"));
+#else
+ Q_UNUSED(context);
+ return engine->toScriptValue(identitiesProperties());
+#endif
+}
+
} // namespace Internal
} // namespace qbs
diff --git a/src/lib/corelib/language/evaluatorscriptclass.cpp b/src/lib/corelib/language/evaluatorscriptclass.cpp
index 89c71e2ad..7293f35d7 100644
--- a/src/lib/corelib/language/evaluatorscriptclass.cpp
+++ b/src/lib/corelib/language/evaluatorscriptclass.cpp
@@ -394,7 +394,7 @@ static QString overriddenSourceDirectory(const Item *item)
inline void convertToPropertyType(const Item *item, const PropertyDeclaration::Type t,
QScriptValue &v)
{
- if (v.isUndefined())
+ if (v.isUndefined() || v.isError())
return;
switch (t) {
case PropertyDeclaration::UnknownType:
diff --git a/src/lib/corelib/language/language.cpp b/src/lib/corelib/language/language.cpp
index 6abba8d20..15c9bcc9f 100644
--- a/src/lib/corelib/language/language.cpp
+++ b/src/lib/corelib/language/language.cpp
@@ -219,6 +219,7 @@ void RuleArtifact::load(PersistentPool &pool)
>> fileTags
>> alwaysUpdated;
location.load(pool);
+ filePathLocation.load(pool);
int i;
pool.stream() >> i;
@@ -240,6 +241,7 @@ void RuleArtifact::store(PersistentPool &pool) const
<< fileTags
<< alwaysUpdated;
location.store(pool);
+ filePathLocation.store(pool);
pool.stream() << bindings.count();
for (int i = bindings.count(); --i >= 0;) {
@@ -701,6 +703,15 @@ ArtifactSet ResolvedProduct::lookupArtifactsByFileTag(const FileTag &tag) const
return buildData->artifactsByFileTag.value(tag);
}
+ArtifactSet ResolvedProduct::lookupArtifactsByFileTags(const FileTags &tags) const
+{
+ QBS_CHECK(buildData);
+ ArtifactSet set;
+ for (const FileTag &tag : tags)
+ set = set.unite(buildData->artifactsByFileTag.value(tag));
+ return set;
+}
+
ArtifactSet ResolvedProduct::targetArtifacts() const
{
QBS_CHECK(buildData);
diff --git a/src/lib/corelib/language/language.h b/src/lib/corelib/language/language.h
index d098d189d..00d0a513b 100644
--- a/src/lib/corelib/language/language.h
+++ b/src/lib/corelib/language/language.h
@@ -96,6 +96,7 @@ public:
FileTags fileTags;
bool alwaysUpdated;
CodeLocation location;
+ CodeLocation filePathLocation;
class Binding
{
@@ -388,6 +389,7 @@ public:
void unmarkForReapplication(const RuleConstPtr &rule);
bool isMarkedForReapplication(const RuleConstPtr &rule) const;
ArtifactSet lookupArtifactsByFileTag(const FileTag &tag) const;
+ ArtifactSet lookupArtifactsByFileTags(const FileTags &tags) const;
ArtifactSet targetArtifacts() const;
TopLevelProject *topLevelProject() const;
diff --git a/src/lib/corelib/language/moduleloader.cpp b/src/lib/corelib/language/moduleloader.cpp
index 37ecdc79b..2b84e32b4 100644
--- a/src/lib/corelib/language/moduleloader.cpp
+++ b/src/lib/corelib/language/moduleloader.cpp
@@ -1526,6 +1526,7 @@ void ModuleLoader::resolveProbes(Item *item)
void ModuleLoader::resolveProbe(Item *parent, Item *probe)
{
+ m_logger.qbsTrace() << "Resolving Probe at " << probe->location().toString();
const JSSourceValueConstPtr configureScript = probe->sourceProperty(QLatin1String("configure"));
if (Q_UNLIKELY(!configureScript))
throw ErrorInfo(Tr::tr("Probe.configure must be set."), probe->location());
@@ -1544,9 +1545,15 @@ void ModuleLoader::resolveProbe(Item *parent, Item *probe)
m_engine->currentContext()->pushScope(scope);
foreach (const ProbeProperty &b, probeBindings)
scope.setProperty(b.first, b.second);
- QScriptValue sv = m_engine->evaluate(configureScript->sourceCodeForEvaluation());
- if (Q_UNLIKELY(m_engine->hasErrorOrException(sv)))
- throw ErrorInfo(m_engine->lastErrorString(sv), configureScript->location());
+ const bool runProbe = m_evaluator->boolValue(probe, QLatin1String("condition"));
+ ErrorInfo evalError;
+ if (runProbe) {
+ QScriptValue sv = m_engine->evaluate(configureScript->sourceCodeForEvaluation());
+ if (Q_UNLIKELY(m_engine->hasErrorOrException(sv)))
+ evalError = ErrorInfo(m_engine->lastErrorString(sv), configureScript->location());
+ } else {
+ m_logger.qbsDebug() << "Probe disabled; skipping";
+ }
foreach (const ProbeProperty &b, probeBindings) {
const QVariant newValue = scope.property(b.first).toVariant();
if (newValue != b.second.toVariant())
@@ -1555,6 +1562,8 @@ void ModuleLoader::resolveProbe(Item *parent, Item *probe)
m_engine->currentContext()->popScope();
m_engine->currentContext()->popScope();
m_engine->currentContext()->popScope();
+ if (evalError.hasError())
+ throw evalError;
}
void ModuleLoader::checkCancelation() const
diff --git a/src/lib/corelib/language/projectresolver.cpp b/src/lib/corelib/language/projectresolver.cpp
index 21d393c80..47ad5deca 100644
--- a/src/lib/corelib/language/projectresolver.cpp
+++ b/src/lib/corelib/language/projectresolver.cpp
@@ -730,6 +730,9 @@ void ProjectResolver::resolveRuleArtifact(const RulePtr &rule, Item *item)
rule->artifacts += artifact;
artifact->location = item->location();
+ if (const auto sourceProperty = item->sourceProperty(QStringLiteral("filePath")))
+ artifact->filePathLocation = sourceProperty->location();
+
artifact->filePath = verbatimValue(item, QLatin1String("filePath"));
artifact->fileTags = m_evaluator->fileTagsValue(item, QLatin1String("fileTags"));
artifact->alwaysUpdated = m_evaluator->boolValue(item, QLatin1String("alwaysUpdated"));
diff --git a/src/lib/corelib/language/scriptengine.cpp b/src/lib/corelib/language/scriptengine.cpp
index c67efbfc9..03b0681d5 100644
--- a/src/lib/corelib/language/scriptengine.cpp
+++ b/src/lib/corelib/language/scriptengine.cpp
@@ -576,6 +576,12 @@ void ScriptEngine::extendJavaScriptBuiltins()
JSTypeExtender arrayExtender(this, QLatin1String("Array"));
arrayExtender.addFunction(QLatin1String("contains"),
QLatin1String("(function(e){return this.indexOf(e) !== -1;})"));
+ arrayExtender.addFunction(QLatin1String("containsAll"),
+ QLatin1String("(function(e){var $this = this;"
+ "return e.every(function (v) { return $this.contains(v) });})"));
+ arrayExtender.addFunction(QLatin1String("containsAny"),
+ QLatin1String("(function(e){var $this = this;"
+ "return e.some(function (v) { return $this.contains(v) });})"));
arrayExtender.addFunction(QLatin1String("uniqueConcat"),
QLatin1String("(function(other){"
"var r = this.concat();"
diff --git a/src/lib/corelib/language/scriptengine.h b/src/lib/corelib/language/scriptengine.h
index 0059479ef..481d8fd91 100644
--- a/src/lib/corelib/language/scriptengine.h
+++ b/src/lib/corelib/language/scriptengine.h
@@ -112,7 +112,9 @@ public:
const QScriptValue &context);
void registerOwnedVariantMap(QVariantMap *vm) { m_ownedVariantMaps.append(vm); }
-
+ QStringList uncaughtExceptionBacktraceOrEmpty() const {
+ return hasUncaughtException() ? uncaughtExceptionBacktrace() : QStringList();
+ }
bool hasErrorOrException(const QScriptValue &v) const {
return v.isError() || hasUncaughtException();
}
diff --git a/src/lib/corelib/language/testdata/throwing-probe.qbs b/src/lib/corelib/language/testdata/throwing-probe.qbs
new file mode 100644
index 000000000..7f4a77a57
--- /dev/null
+++ b/src/lib/corelib/language/testdata/throwing-probe.qbs
@@ -0,0 +1,12 @@
+import qbs
+
+Product {
+ name: "theProduct"
+ property bool enableProbe
+ Probe {
+ condition: enableProbe
+ configure: {
+ throw "Error!";
+ }
+ }
+}
diff --git a/src/lib/corelib/language/tst_language.cpp b/src/lib/corelib/language/tst_language.cpp
index 81edcdd29..702af884e 100644
--- a/src/lib/corelib/language/tst_language.cpp
+++ b/src/lib/corelib/language/tst_language.cpp
@@ -1595,6 +1595,31 @@ void TestLanguage::relaxedErrorMode_data()
QTest::newRow("relaxed mode") << false;
}
+void TestLanguage::throwingProbe()
+{
+ QFETCH(bool, enableProbe);
+ try {
+ SetupProjectParameters params = defaultParameters;
+ params.setProjectFilePath(testProject("throwing-probe.qbs"));
+ QVariantMap properties;
+ properties.insert(QLatin1String("theProduct.enableProbe"), enableProbe);
+ params.setOverriddenValues(properties);
+ const TopLevelProjectPtr project = loader->loadProject(params);
+ QVERIFY(project);
+ QVERIFY(!enableProbe);
+ } catch (const ErrorInfo &e) {
+ QVERIFY2(enableProbe, qPrintable(e.toString()));
+ }
+}
+
+void TestLanguage::throwingProbe_data()
+{
+ QTest::addColumn<bool>("enableProbe");
+
+ QTest::newRow("enabled probe") << true;
+ QTest::newRow("disabled probe") << false;
+}
+
void TestLanguage::qualifiedId()
{
QString str = "foo.bar.baz";
@@ -1887,7 +1912,7 @@ void TestLanguage::wildcards()
QVERIFY(product);
GroupPtr group;
if (useGroup) {
- QCOMPARE(product->groups.count(), 3);
+ QCOMPARE(product->groups.count(), HostOsInfo::isOsxHost() ? 4 : 3);
foreach (const GroupPtr &rg, product->groups) {
if (rg->name == groupName) {
group = rg;
@@ -1895,7 +1920,7 @@ void TestLanguage::wildcards()
}
}
} else {
- QCOMPARE(product->groups.count(), 2);
+ QCOMPARE(product->groups.count(), HostOsInfo::isOsxHost() ? 3 : 2);
group = product->groups.first();
}
QVERIFY(group);
diff --git a/src/lib/corelib/language/tst_language.h b/src/lib/corelib/language/tst_language.h
index 93ae173ea..60a1f08f8 100644
--- a/src/lib/corelib/language/tst_language.h
+++ b/src/lib/corelib/language/tst_language.h
@@ -113,6 +113,8 @@ private slots:
void qbsPropertiesInProjectCondition();
void relaxedErrorMode();
void relaxedErrorMode_data();
+ void throwingProbe();
+ void throwingProbe_data();
void defaultValue();
void defaultValue_data();
void qualifiedId();
diff --git a/src/lib/corelib/tools/applecodesignutils.cpp b/src/lib/corelib/tools/applecodesignutils.cpp
new file mode 100644
index 000000000..9ca00c314
--- /dev/null
+++ b/src/lib/corelib/tools/applecodesignutils.cpp
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of the Qt Build Suite.
+**
+** 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.
+**
+****************************************************************************/
+
+#include "applecodesignutils.h"
+#include <QByteArray>
+#include <QCryptographicHash>
+#include <QDateTime>
+#include <QSslCertificate>
+#include <QSslCertificateExtension>
+
+#include <QtCore/private/qcore_mac_p.h>
+#include <Security/Security.h>
+
+#include <QDebug>
+
+namespace qbs {
+namespace Internal {
+
+QByteArray smimeMessageContent(const QByteArray &data)
+{
+ QCFType<CMSDecoderRef> decoder = NULL;
+ if (CMSDecoderCreate(&decoder) != noErr)
+ return QByteArray();
+
+ if (CMSDecoderUpdateMessage(decoder, data.constData(), data.size()) != noErr)
+ return QByteArray();
+
+ if (CMSDecoderFinalizeMessage(decoder) != noErr)
+ return QByteArray();
+
+ QCFType<CFDataRef> content = NULL;
+ if (CMSDecoderCopyContent(decoder, &content) != noErr)
+ return QByteArray();
+
+ return QByteArray::fromCFData(content);
+}
+
+QVariantMap certificateInfo(const QByteArray &data)
+{
+ const QSslCertificate cert(data, QSsl::Der);
+
+ // Also potentially useful, but these are for signing pkgs which aren't used here
+ // 1.2.840.113635.100.4.9 - 3rd Party Mac Developer Installer: <name>
+ // 1.2.840.113635.100.4.13 - Developer ID Installer: <name>
+ for (const auto &extension : cert.extensions()) {
+ if (extension.name() == QStringLiteral("extendedKeyUsage")) {
+ if (!extension.value().toStringList().contains(QStringLiteral("Code Signing")))
+ return QVariantMap();
+ }
+ }
+
+ const auto subjectInfo = [](const QSslCertificate &cert) {
+ QVariantMap map;
+ for (const auto &attr : cert.subjectInfoAttributes())
+ map.insert(QString::fromLatin1(attr), cert.subjectInfo(attr).first());
+ return map;
+ };
+
+ return {
+ {QStringLiteral("SHA1"), cert.digest(QCryptographicHash::Sha1).toHex().toUpper()},
+ {QStringLiteral("subjectInfo"), subjectInfo(cert)},
+ {QStringLiteral("validBefore"), cert.effectiveDate()},
+ {QStringLiteral("validAfter"), cert.expiryDate()}
+ };
+}
+
+QVariantMap identitiesProperties()
+{
+ // Apple documentation states that the Sec* family of functions are not thread-safe on OS X
+ // https://developer.apple.com/library/mac/documentation/Security/Reference/certifkeytrustservices/
+ static QMutex securityMutex;
+ QMutexLocker locker(&securityMutex);
+ Q_UNUSED(locker);
+
+ const void *keys[] = {kSecClass, kSecMatchLimit, kSecAttrCanSign};
+ const void *values[] = {kSecClassIdentity, kSecMatchLimitAll, kCFBooleanTrue};
+ QCFType<CFDictionaryRef> query = CFDictionaryCreate(kCFAllocatorDefault,
+ keys,
+ values,
+ sizeof(keys) / sizeof(keys[0]),
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ QCFType<CFTypeRef> result = NULL;
+ if (SecItemCopyMatching(query, &result) != errSecSuccess)
+ return QVariantMap();
+
+ QVariantMap items;
+ const auto tryAppend = [&](SecIdentityRef identity) {
+ if (!identity)
+ return;
+
+ QCFType<SecCertificateRef> certificate = NULL;
+ if (SecIdentityCopyCertificate(identity, &certificate) != errSecSuccess)
+ return;
+
+ QCFType<CFDataRef> certificateData = SecCertificateCopyData(certificate);
+ if (!certificateData)
+ return;
+
+ auto props = certificateInfo(QByteArray::fromRawCFData(certificateData));
+ if (!props.isEmpty())
+ items.insert(props[QStringLiteral("SHA1")].toString(), props);
+ };
+
+ if (CFGetTypeID(result) == SecIdentityGetTypeID()) {
+ tryAppend((SecIdentityRef)result.operator const void *());
+ } else if (CFGetTypeID(result) == CFArrayGetTypeID()) {
+ for (CFIndex i = 0; i < CFArrayGetCount((CFArrayRef)result.operator const void *()); ++i)
+ tryAppend((SecIdentityRef)CFArrayGetValueAtIndex(result.as<CFArrayRef>(), i));
+ }
+
+ return items;
+}
+
+} // namespace Internal
+} // namespace qbs
diff --git a/src/lib/corelib/tools/applecodesignutils.h b/src/lib/corelib/tools/applecodesignutils.h
new file mode 100644
index 000000000..4dc456289
--- /dev/null
+++ b/src/lib/corelib/tools/applecodesignutils.h
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of the Qt Build Suite.
+**
+** 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.
+**
+****************************************************************************/
+
+#ifndef QBS_APPLECODESIGNUTILS_H
+#define QBS_APPLECODESIGNUTILS_H
+
+#include "qbs_export.h"
+#include <QVariantMap>
+
+namespace qbs {
+namespace Internal {
+
+QByteArray smimeMessageContent(const QByteArray &data);
+QVariantMap certificateInfo(const QByteArray &data);
+QVariantMap identitiesProperties();
+
+} // namespace Internal
+} // namespace qbs
+
+#endif // QBS_APPLECODESIGNUTILS_H
diff --git a/src/lib/corelib/tools/codelocation.h b/src/lib/corelib/tools/codelocation.h
index f5b882ead..3550c78ea 100644
--- a/src/lib/corelib/tools/codelocation.h
+++ b/src/lib/corelib/tools/codelocation.h
@@ -49,7 +49,8 @@ class QBS_EXPORT CodeLocation
friend QBS_EXPORT bool operator==(const CodeLocation &cl1, const CodeLocation &cl2);
public:
CodeLocation();
- CodeLocation(const QString &aFilePath, int aLine = -1, int aColumn = -1, bool checkPath = true);
+ explicit CodeLocation(const QString &aFilePath, int aLine = -1, int aColumn = -1,
+ bool checkPath = true);
CodeLocation(const CodeLocation &other);
CodeLocation &operator=(const CodeLocation &other);
~CodeLocation();
diff --git a/src/lib/corelib/tools/error.cpp b/src/lib/corelib/tools/error.cpp
index d114fda7c..78fc5cdcd 100644
--- a/src/lib/corelib/tools/error.cpp
+++ b/src/lib/corelib/tools/error.cpp
@@ -30,6 +30,7 @@
#include "error.h"
+#include <QRegularExpression>
#include <QSharedData>
#include <QStringList>
@@ -40,6 +41,7 @@ class ErrorItem::ErrorItemPrivate : public QSharedData
public:
QString description;
CodeLocation codeLocation;
+ bool isBacktraceItem = false;
};
/*!
@@ -53,11 +55,13 @@ ErrorItem::ErrorItem() : d(new ErrorItemPrivate)
{
}
-ErrorItem::ErrorItem(const QString &description, const CodeLocation &codeLocation)
+ErrorItem::ErrorItem(const QString &description, const CodeLocation &codeLocation,
+ bool isBacktraceItem)
: d(new ErrorItemPrivate)
{
d->description = description;
d->codeLocation = codeLocation;
+ d->isBacktraceItem = isBacktraceItem;
}
ErrorItem::ErrorItem(const ErrorItem &rhs) : d(rhs.d)
@@ -84,6 +88,11 @@ CodeLocation ErrorItem::codeLocation() const
return d->codeLocation;
}
+bool ErrorItem::isBacktraceItem() const
+{
+ return d->isBacktraceItem;
+}
+
/*!
* \fn const QString &ErrorData::description() const
* \brief A general description of the error.
@@ -138,6 +147,23 @@ ErrorInfo::ErrorInfo(const QString &description, const CodeLocation &location, b
d->internalError = internalError;
}
+ErrorInfo::ErrorInfo(const QString &description, const QStringList &backtrace)
+ : d(new ErrorInfoPrivate)
+{
+ append(description);
+ for (const QString &traceLine : backtrace) {
+ QRegularExpression regexp(
+ QStringLiteral("^(?<message>.+) at (?<file>.+):(?<line>\\-?[0-9]+)$"));
+ QRegularExpressionMatch match = regexp.match(traceLine);
+ if (match.hasMatch()) {
+ const CodeLocation location(match.captured(QStringLiteral("file")),
+ match.captured(QStringLiteral("line")).toInt());
+ appendBacktrace(match.captured(QStringLiteral("message")), location);
+ }
+ }
+}
+
+
ErrorInfo &ErrorInfo::operator =(const ErrorInfo &other)
{
d = other.d;
@@ -148,6 +174,11 @@ ErrorInfo::~ErrorInfo()
{
}
+void ErrorInfo::appendBacktrace(const QString &description, const CodeLocation &location)
+{
+ d->items.append(ErrorItem(description, location, true));
+}
+
void ErrorInfo::append(const QString &description, const CodeLocation &location)
{
d->items.append(ErrorItem(description, location));
@@ -181,8 +212,19 @@ void ErrorInfo::clear()
QString ErrorInfo::toString() const
{
QStringList lines;
- foreach (const ErrorItem &e, d->items)
- lines.append(e.toString());
+ foreach (const ErrorItem &e, d->items) {
+ if (e.isBacktraceItem()) {
+ QString line;
+ if (!e.description().isEmpty())
+ line.append(QStringLiteral(" at %1").arg(e.description()));
+ if (e.codeLocation().isValid())
+ line.append(QStringLiteral(" in %1").arg(e.codeLocation().toString()));
+ if (!line.isEmpty())
+ lines.append(QStringLiteral("\t") + line);
+ } else {
+ lines.append(e.toString());
+ }
+ }
return lines.join(QLatin1Char('\n'));
}
diff --git a/src/lib/corelib/tools/error.h b/src/lib/corelib/tools/error.h
index 5c0ea0726..1aa83d485 100644
--- a/src/lib/corelib/tools/error.h
+++ b/src/lib/corelib/tools/error.h
@@ -58,8 +58,11 @@ public:
CodeLocation codeLocation() const;
QString toString() const;
+ bool isBacktraceItem() const;
+
private:
- ErrorItem(const QString &description, const CodeLocation &codeLocation);
+ ErrorItem(const QString &description, const CodeLocation &codeLocation,
+ bool isBacktraceItem = false);
class ErrorItemPrivate;
QExplicitlySharedDataPointer<ErrorItemPrivate> d;
@@ -72,9 +75,11 @@ public:
ErrorInfo(const ErrorInfo &rhs);
ErrorInfo(const QString &description, const CodeLocation &location = CodeLocation(),
bool internalError = false);
+ ErrorInfo(const QString &description, const QStringList &backtrace);
ErrorInfo &operator=(const ErrorInfo &other);
~ErrorInfo();
+ void appendBacktrace(const QString &description, const CodeLocation &location = CodeLocation());
void append(const QString &description, const CodeLocation &location = CodeLocation());
void prepend(const QString &description, const CodeLocation &location = CodeLocation());
QList<ErrorItem> items() const;
diff --git a/src/lib/corelib/tools/persistence.cpp b/src/lib/corelib/tools/persistence.cpp
index 1455f4e16..885cd2b5d 100644
--- a/src/lib/corelib/tools/persistence.cpp
+++ b/src/lib/corelib/tools/persistence.cpp
@@ -41,7 +41,7 @@
namespace qbs {
namespace Internal {
-static const char QBS_PERSISTENCE_MAGIC[] = "QBSPERSISTENCE-84";
+static const char QBS_PERSISTENCE_MAGIC[] = "QBSPERSISTENCE-85";
PersistentPool::PersistentPool(const Logger &logger) : m_logger(logger)
{
diff --git a/src/lib/corelib/tools/tools.pri b/src/lib/corelib/tools/tools.pri
index 4722b7aa1..618b08bb3 100644
--- a/src/lib/corelib/tools/tools.pri
+++ b/src/lib/corelib/tools/tools.pri
@@ -74,6 +74,12 @@ SOURCES += \
$$PWD/version.cpp \
$$PWD/visualstudioversioninfo.cpp
+osx {
+ HEADERS += $$PWD/applecodesignutils.h
+ SOURCES += $$PWD/applecodesignutils.cpp
+ LIBS += -framework Security
+}
+
win32 {
SOURCES += $$PWD/filetime_win.cpp
}
diff --git a/src/lib/qtprofilesetup/qtmoduleinfo.cpp b/src/lib/qtprofilesetup/qtmoduleinfo.cpp
index d15e06ac9..03cc042b4 100644
--- a/src/lib/qtprofilesetup/qtmoduleinfo.cpp
+++ b/src/lib/qtprofilesetup/qtmoduleinfo.cpp
@@ -239,19 +239,20 @@ void QtModuleInfo::setupLibraries(const QtEnvironment &qtEnv, bool debugBuild,
if (simplifiedLine.startsWith("QMAKE_PRL_TARGET")) {
const bool isMingw = qtEnv.mkspecName.startsWith(QLatin1String("win"))
&& qtEnv.mkspecName.contains(QLatin1String("g++"));
+ const bool isQtVersionBefore56 = qtEnv.qtMajorVersion < 5
+ || (qtEnv.qtMajorVersion == 5 && qtEnv.qtMinorVersion < 6);
libFilePath = libDir;
// QMAKE_PRL_TARGET has a "lib" prefix, except for mingw.
// Of course, the exception has an exception too: For static libs, mingw *does*
// have the "lib" prefix. TODO: Shoot the people responsible for this.
- if (isMingw && !isStaticLibrary)
+ if (isQtVersionBefore56 && isMingw && !isStaticLibrary)
libFilePath += QLatin1String("lib");
libFilePath += QString::fromLatin1(simplifiedLine.mid(equalsOffset + 1).trimmed());
if (isNonStaticQt4OnWindows)
libFilePath += QString::number(4); // This is *not* part of QMAKE_PRL_TARGET...
- if (qtEnv.qtMajorVersion < 5
- || (qtEnv.qtMajorVersion == 5 && qtEnv.qtMinorVersion < 6)) {
+ if (isQtVersionBefore56) {
if (qtEnv.mkspecName.contains(QLatin1String("msvc")))
libFilePath += QLatin1String(".lib");
else if (isMingw)
diff --git a/src/plugins/scanner/cpp/cppscanner.cpp b/src/plugins/scanner/cpp/cppscanner.cpp
index 1d5f4c156..226e75bcb 100644
--- a/src/plugins/scanner/cpp/cppscanner.cpp
+++ b/src/plugins/scanner/cpp/cppscanner.cpp
@@ -173,7 +173,9 @@ static void scanCppFile(void *opaq, Lexer &yylex, bool scanForFileTags, bool sca
opaque->hasPluginMetaDataMacro = true;
}
if (!scanForDependencies && opaque->hasQObjectMacro
- && (opaque->fileType == Opaq::FT_CPP || opaque->hasPluginMetaDataMacro))
+ && (opaque->hasPluginMetaDataMacro
+ || opaque->fileType == Opaq::FT_CPP
+ || opaque->fileType == Opaq::FT_OBJCPP))
break;
}
}
@@ -265,6 +267,7 @@ static const char **additionalFileTags(void *opaq, int *size)
*size = 1;
switch (opaque->fileType) {
case Opaq::FT_CPP:
+ case Opaq::FT_OBJCPP:
return thMocCpp;
case Opaq::FT_HPP:
return opaque->hasPluginMetaDataMacro ? thMocPluginHpp : thMocHpp;
diff --git a/tests/auto/api/testdata/error-in-setup-run-environment/error-in-setup-run-environment.qbs b/tests/auto/api/testdata/error-in-setup-run-environment/error-in-setup-run-environment.qbs
new file mode 100644
index 000000000..f3247f6f8
--- /dev/null
+++ b/tests/auto/api/testdata/error-in-setup-run-environment/error-in-setup-run-environment.qbs
@@ -0,0 +1,5 @@
+import qbs
+
+CppApplication {
+ Depends { name: "mymodule" }
+}
diff --git a/tests/auto/api/testdata/error-in-setup-run-environment/modules/mymodule/mymodule.qbs b/tests/auto/api/testdata/error-in-setup-run-environment/modules/mymodule/mymodule.qbs
new file mode 100644
index 000000000..e698b45b5
--- /dev/null
+++ b/tests/auto/api/testdata/error-in-setup-run-environment/modules/mymodule/mymodule.qbs
@@ -0,0 +1,7 @@
+import qbs
+
+Module {
+ setupRunEnvironment: {
+ trallala
+ }
+}
diff --git a/tests/auto/api/testdata/moc-hpp-included/object2.h b/tests/auto/api/testdata/moc-hpp-included/object2.h
new file mode 100644
index 000000000..14e811124
--- /dev/null
+++ b/tests/auto/api/testdata/moc-hpp-included/object2.h
@@ -0,0 +1,13 @@
+#ifndef OBJECT2_H
+#define OBJECT2_H
+#include <QObject>
+
+class Object2 : public QObject
+{
+ Q_OBJECT
+public:
+ Object2(QObject *parent = 0);
+};
+
+#endif
+
diff --git a/tests/auto/api/testdata/moc-hpp-included/object2.mm b/tests/auto/api/testdata/moc-hpp-included/object2.mm
new file mode 100644
index 000000000..6fd95d31f
--- /dev/null
+++ b/tests/auto/api/testdata/moc-hpp-included/object2.mm
@@ -0,0 +1,16 @@
+#include "object2.h"
+
+Object2::Object2(QObject *parent)
+ : QObject(parent)
+{}
+
+#include "moc_object2.cpp"
+#include <cstdio>
+
+int main2()
+{
+ Object2 obj;
+ printf("Hello World\n");
+ return 0;
+}
+
diff --git a/tests/auto/api/testdata/moc-hpp-included/project.qbs b/tests/auto/api/testdata/moc-hpp-included/project.qbs
index d78493b2f..554b0a2b3 100644
--- a/tests/auto/api/testdata/moc-hpp-included/project.qbs
+++ b/tests/auto/api/testdata/moc-hpp-included/project.qbs
@@ -8,11 +8,11 @@ Project {
Depends { name: "Qt.core" }
- files : [ "object.cpp" ]
+ files: ["object.cpp", "object.h"]
Group {
- files : [ "object.h" ]
- fileTags: [ "hpp" ]
+ condition: qbs.targetOS.contains("darwin")
+ files: ["object2.mm", "object2.h"]
}
}
}
diff --git a/tests/auto/api/testdata/simple-probe/project.qbs b/tests/auto/api/testdata/simple-probe/project.qbs
index 9a869c3de..34700a99b 100644
--- a/tests/auto/api/testdata/simple-probe/project.qbs
+++ b/tests/auto/api/testdata/simple-probe/project.qbs
@@ -16,17 +16,17 @@ CppApplication {
found = false;
}
}
+ type: ["application"]
name: "MyApp"
- type: {
+ consoleApplication: {
if (!probe1.found)
throw "probe1 not found";
if (probe2.found)
throw "probe2 unexpectedly found";
if (probe1.someString !== "one")
throw "probe1.someString expected to be \"one\"."
- return "application"
+ return true
}
- consoleApplication: true
files: ["main.cpp"]
}
diff --git a/tests/auto/api/tst_api.cpp b/tests/auto/api/tst_api.cpp
index de930a13d..e90237f40 100644
--- a/tests/auto/api/tst_api.cpp
+++ b/tests/auto/api/tst_api.cpp
@@ -32,6 +32,7 @@
#include "../shared.h"
+#include <api/runenvironment.h>
#include <qbs.h>
#include <tools/fileinfo.h>
#include <tools/hostosinfo.h>
@@ -828,6 +829,35 @@ void TestApi::enableAndDisableProduct()
QVERIFY(!bdr.descriptions.contains("compiling"));
}
+void TestApi::errorInSetupRunEnvironment()
+{
+ qbs::SetupProjectParameters setupParams
+ = defaultSetupParameters("error-in-setup-run-environment/"
+ "error-in-setup-run-environment.qbs");
+ QScopedPointer<qbs::SetupProjectJob> job(qbs::Project().setupProject(setupParams,
+ m_logSink, 0));
+ waitForFinished(job.data());
+ QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString()));
+ const qbs::Project project = job->project();
+ QVERIFY(project.isValid());
+ QCOMPARE(project.projectData().products().count(), 1);
+ const qbs::ProductData product = project.projectData().products().first();
+
+ bool exceptionCaught = false;
+ try {
+ qbs::Settings settings((QString()));
+ qbs::RunEnvironment runEnv = project.getRunEnvironment(product, qbs::InstallOptions(),
+ QProcessEnvironment(), &settings);
+ qbs::ErrorInfo error;
+ const QProcessEnvironment env = runEnv.runEnvironment(&error);
+ QVERIFY(error.hasError());
+ QVERIFY(error.toString().contains("trallala"));
+ } catch (const qbs::ErrorInfo &e) {
+ exceptionCaught = true;
+ }
+ QVERIFY(!exceptionCaught);
+}
+
static qbs::ErrorInfo forceRuleEvaluation(const qbs::Project project)
{
qbs::BuildOptions buildOptions;
diff --git a/tests/auto/api/tst_api.h b/tests/auto/api/tst_api.h
index 57be0d660..92571781b 100644
--- a/tests/auto/api/tst_api.h
+++ b/tests/auto/api/tst_api.h
@@ -79,6 +79,7 @@ private slots:
void emptyFileTagList();
void emptySubmodulesList();
void enableAndDisableProduct();
+ void errorInSetupRunEnvironment();
void explicitlyDependsOn();
void exportSimple();
void exportWithRecursiveDepends();
diff --git a/tests/auto/blackbox/testdata/bundle-structure/bundle-structure.qbs b/tests/auto/blackbox/testdata/bundle-structure/bundle-structure.qbs
new file mode 100644
index 000000000..19586522c
--- /dev/null
+++ b/tests/auto/blackbox/testdata/bundle-structure/bundle-structure.qbs
@@ -0,0 +1,167 @@
+import qbs
+
+Project {
+ property stringList bundleFileTags: [
+ "aggregate_infoplist", "pkginfo", "hpp",
+ "icns", "resourcerules", "xcent",
+ "compiled_ibdoc", "compiled_assetcatalog",
+ "bundle.symlink.headers", "bundle.symlink.private-headers",
+ "bundle.symlink.resources", "bundle.symlink.executable",
+ "bundle.symlink.version", "bundle.hpp", "bundle.resource",
+ ]
+
+ property stringList buildableProducts: ["A", "B", "C", "D", "E", "F", "G"]
+
+ Application {
+ Depends { name: "cpp" }
+ Depends { name: "B" }
+ Depends { name: "C" }
+ Depends { name: "D" }
+ condition: buildableProducts.contains("A")
+ name: "A"
+ bundle.isBundle: true
+ bundle.publicHeaders: ["dummy.h"]
+ bundle.privateHeaders: ["dummy_p.h"]
+ bundle.resources: ["resource.txt"]
+ files: ["dummy.c"]
+ Group {
+ fileTagsFilter: product.type.concat(project.bundleFileTags)
+ qbs.install: true
+ qbs.installSourceBase: product.buildDirectory
+ }
+ }
+
+ Application {
+ Depends { name: "cpp" }
+ Depends { name: "B" }
+ Depends { name: "C" }
+ Depends { name: "D" }
+ condition: buildableProducts.contains("ABadApple")
+ name: "ABadApple"
+ bundle._productTypeIdentifier: "com.apple.product-type.will.never.exist.ever.guaranteed"
+ bundle.isBundle: true
+ bundle.publicHeaders: ["dummy.h"]
+ bundle.privateHeaders: ["dummy_p.h"]
+ bundle.resources: ["resource.txt"]
+ files: ["dummy.c"]
+ Group {
+ fileTagsFilter: product.type.concat(project.bundleFileTags)
+ qbs.install: true
+ qbs.installSourceBase: product.buildDirectory
+ }
+ }
+
+ Application {
+ Depends { name: "cpp" }
+ Depends { name: "B" }
+ Depends { name: "C" }
+ Depends { name: "D" }
+ condition: buildableProducts.contains("ABadThirdParty")
+ name: "ABadThirdParty"
+ bundle._productTypeIdentifier: "org.special.third.party.non.existent.product.type"
+ bundle.isBundle: true
+ bundle.publicHeaders: ["dummy.h"]
+ bundle.privateHeaders: ["dummy_p.h"]
+ bundle.resources: ["resource.txt"]
+ files: ["dummy.c"]
+ Group {
+ fileTagsFilter: product.type.concat(project.bundleFileTags)
+ qbs.install: true
+ qbs.installSourceBase: product.buildDirectory
+ }
+ }
+
+ DynamicLibrary {
+ Depends { name: "cpp" }
+ condition: buildableProducts.containsAny(["A", "B", "ABadApple", "ABadThirdParty"])
+ name: "B"
+ bundle.isBundle: true
+ bundle.publicHeaders: ["dummy.h"]
+ bundle.privateHeaders: ["dummy_p.h"]
+ bundle.resources: ["resource.txt"]
+ files: ["dummy.c"]
+ Group {
+ fileTagsFilter: product.type.concat(project.bundleFileTags)
+ qbs.install: true
+ qbs.installSourceBase: product.buildDirectory
+ }
+ }
+
+ StaticLibrary {
+ Depends { name: "cpp" }
+ condition: buildableProducts.containsAny(["A", "C", "ABadApple", "ABadThirdParty"])
+ name: "C"
+ bundle.isBundle: true
+ bundle.publicHeaders: ["dummy.h"]
+ bundle.privateHeaders: ["dummy_p.h"]
+ bundle.resources: ["resource.txt"]
+ files: ["dummy.c"]
+ Group {
+ fileTagsFilter: product.type.concat(project.bundleFileTags)
+ qbs.install: true
+ qbs.installSourceBase: product.buildDirectory
+ }
+ }
+
+ LoadableModule {
+ Depends { name: "cpp" }
+ condition: buildableProducts.containsAny(["A", "D", "ABadApple", "ABadThirdParty"])
+ name: "D"
+ bundle.isBundle: true
+ bundle.publicHeaders: ["dummy.h"]
+ bundle.privateHeaders: ["dummy_p.h"]
+ bundle.resources: ["resource.txt"]
+ files: ["dummy.c"]
+ Group {
+ fileTagsFilter: product.type.concat(project.bundleFileTags)
+ qbs.install: true
+ qbs.installSourceBase: product.buildDirectory
+ }
+ }
+
+ ApplicationExtension {
+ Depends { name: "cpp" }
+ condition: buildableProducts.contains("E")
+ name: "E"
+ bundle.isBundle: true
+ bundle.publicHeaders: ["dummy.h"]
+ bundle.privateHeaders: ["dummy_p.h"]
+ bundle.resources: ["resource.txt"]
+ files: ["dummy.c"]
+ Group {
+ fileTagsFilter: product.type.concat(project.bundleFileTags)
+ qbs.install: true
+ qbs.installSourceBase: product.buildDirectory
+ }
+ }
+
+ XPCService {
+ Depends { name: "cpp" }
+ condition: buildableProducts.contains("F")
+ name: "F"
+ bundle.isBundle: true
+ bundle.publicHeaders: ["dummy.h"]
+ bundle.privateHeaders: ["dummy_p.h"]
+ bundle.resources: ["resource.txt"]
+ files: ["dummy.c"]
+ Group {
+ fileTagsFilter: product.type.concat(project.bundleFileTags)
+ qbs.install: true
+ qbs.installSourceBase: product.buildDirectory
+ }
+ }
+
+ Product {
+ Depends { name: "bundle" }
+ condition: buildableProducts.contains("G")
+ type: ["inapppurchase"]
+ name: "G"
+ bundle.isBundle: true
+ bundle.resources: ["resource.txt"]
+ Group {
+ fileTagsFilter: product.type.concat(project.bundleFileTags)
+ qbs.install: true
+ qbs.installSourceBase: product.buildDirectory
+ }
+ }
+}
diff --git a/tests/auto/blackbox/testdata/bundle-structure/dummy.c b/tests/auto/blackbox/testdata/bundle-structure/dummy.c
new file mode 100644
index 000000000..76e819701
--- /dev/null
+++ b/tests/auto/blackbox/testdata/bundle-structure/dummy.c
@@ -0,0 +1 @@
+int main() { return 0; }
diff --git a/tests/auto/blackbox/testdata/bundle-structure/dummy.h b/tests/auto/blackbox/testdata/bundle-structure/dummy.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/auto/blackbox/testdata/bundle-structure/dummy.h
diff --git a/tests/auto/blackbox/testdata/bundle-structure/dummy_p.h b/tests/auto/blackbox/testdata/bundle-structure/dummy_p.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/auto/blackbox/testdata/bundle-structure/dummy_p.h
diff --git a/tests/auto/blackbox/testdata/bundle-structure/resource.txt b/tests/auto/blackbox/testdata/bundle-structure/resource.txt
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/auto/blackbox/testdata/bundle-structure/resource.txt
diff --git a/tests/auto/blackbox/testdata/change-in-imported-file/prepare.js b/tests/auto/blackbox/testdata/change-in-imported-file/prepare.js
index 8d1b44c61..fa73f0ff1 100644
--- a/tests/auto/blackbox/testdata/change-in-imported-file/prepare.js
+++ b/tests/auto/blackbox/testdata/change-in-imported-file/prepare.js
@@ -1,3 +1,3 @@
function prepare(cmd) {
- cmd.sourceCode = function() { print("old output"); };
+ cmd.sourceCode = function() { console.info("old output"); };
}
diff --git a/tests/auto/blackbox/testdata/concurrent-executor/concurrent-executor.qbs b/tests/auto/blackbox/testdata/concurrent-executor/concurrent-executor.qbs
index 672576263..9031890bd 100644
--- a/tests/auto/blackbox/testdata/concurrent-executor/concurrent-executor.qbs
+++ b/tests/auto/blackbox/testdata/concurrent-executor/concurrent-executor.qbs
@@ -27,7 +27,7 @@ Product {
cmd.createFile = i == 9;
cmd.sourceCode = function() {
if (createFile) {
- print("Creating file");
+ console.info("Creating file");
var file = new TextFile(output.filePath, TextFile.WriteOnly);
file.close();
}
diff --git a/tests/auto/blackbox/testdata/deploymentTarget/deployment.qbs b/tests/auto/blackbox/testdata/deploymentTarget/deployment.qbs
new file mode 100644
index 000000000..104bbae81
--- /dev/null
+++ b/tests/auto/blackbox/testdata/deploymentTarget/deployment.qbs
@@ -0,0 +1,9 @@
+import qbs
+
+CppApplication {
+ files: ["main.c"]
+ cpp.minimumOsxVersion: "10.4"
+ cpp.minimumIosVersion: "5.0"
+ cpp.cFlags: ["-v"]
+ cpp.linkerFlags: ["-v"]
+}
diff --git a/tests/auto/blackbox/testdata/deploymentTarget/main.c b/tests/auto/blackbox/testdata/deploymentTarget/main.c
new file mode 100644
index 000000000..76e819701
--- /dev/null
+++ b/tests/auto/blackbox/testdata/deploymentTarget/main.c
@@ -0,0 +1 @@
+int main() { return 0; }
diff --git a/tests/auto/blackbox/testdata/enableExceptions/empty.m b/tests/auto/blackbox/testdata/enableExceptions/empty.m
new file mode 100644
index 000000000..d3714dc09
--- /dev/null
+++ b/tests/auto/blackbox/testdata/enableExceptions/empty.m
@@ -0,0 +1 @@
+int main2() { return 0; }
diff --git a/tests/auto/blackbox/testdata/enableExceptions/empty.mm b/tests/auto/blackbox/testdata/enableExceptions/empty.mm
new file mode 100644
index 000000000..fe94a49a3
--- /dev/null
+++ b/tests/auto/blackbox/testdata/enableExceptions/empty.mm
@@ -0,0 +1 @@
+int main3() { return 0; }
diff --git a/tests/auto/blackbox/testdata/enableExceptions/emptymain.cpp b/tests/auto/blackbox/testdata/enableExceptions/emptymain.cpp
new file mode 100644
index 000000000..76e819701
--- /dev/null
+++ b/tests/auto/blackbox/testdata/enableExceptions/emptymain.cpp
@@ -0,0 +1 @@
+int main() { return 0; }
diff --git a/tests/auto/blackbox/testdata/enableExceptions/exceptions-objc.qbs b/tests/auto/blackbox/testdata/enableExceptions/exceptions-objc.qbs
new file mode 100644
index 000000000..74738ad12
--- /dev/null
+++ b/tests/auto/blackbox/testdata/enableExceptions/exceptions-objc.qbs
@@ -0,0 +1,6 @@
+import qbs
+
+CppApplication {
+ files: ["main.m"]
+ cpp.frameworks: ["Foundation"]
+}
diff --git a/tests/auto/blackbox/testdata/enableExceptions/exceptions-objcpp-cpp.qbs b/tests/auto/blackbox/testdata/enableExceptions/exceptions-objcpp-cpp.qbs
new file mode 100644
index 000000000..679cdebbe
--- /dev/null
+++ b/tests/auto/blackbox/testdata/enableExceptions/exceptions-objcpp-cpp.qbs
@@ -0,0 +1,6 @@
+import qbs
+
+CppApplication {
+ files: ["main.cpp"]
+ fileTags: ["objcpp"]
+}
diff --git a/tests/auto/blackbox/testdata/enableExceptions/exceptions-objcpp.qbs b/tests/auto/blackbox/testdata/enableExceptions/exceptions-objcpp.qbs
new file mode 100644
index 000000000..6856f53bb
--- /dev/null
+++ b/tests/auto/blackbox/testdata/enableExceptions/exceptions-objcpp.qbs
@@ -0,0 +1,7 @@
+import qbs
+
+CppApplication {
+ files: ["main.m"]
+ fileTags: ["objcpp"]
+ cpp.frameworks: ["Foundation"]
+}
diff --git a/tests/auto/blackbox/testdata/enableExceptions/exceptions.qbs b/tests/auto/blackbox/testdata/enableExceptions/exceptions.qbs
new file mode 100644
index 000000000..da6fdbc2d
--- /dev/null
+++ b/tests/auto/blackbox/testdata/enableExceptions/exceptions.qbs
@@ -0,0 +1,7 @@
+import qbs
+
+CppApplication {
+ files: ["main.cpp"]
+ cpp.treatWarningsAsErrors: true
+ cpp.defines: qbs.toolchain.contains("msvc") && !cpp.enableExceptions ? ["FORCE_FAIL_VS"] : []
+}
diff --git a/tests/auto/blackbox/testdata/enableExceptions/main.cpp b/tests/auto/blackbox/testdata/enableExceptions/main.cpp
new file mode 100644
index 000000000..1b99ea96d
--- /dev/null
+++ b/tests/auto/blackbox/testdata/enableExceptions/main.cpp
@@ -0,0 +1,8 @@
+#include <stdexcept>
+
+int main() {
+#ifdef FORCE_FAIL_VS
+#error "Microsoft Visual C++ cannot disable exceptions at compile-time"
+#endif
+ throw std::runtime_error("failed");
+}
diff --git a/tests/auto/blackbox/testdata/enableExceptions/main.m b/tests/auto/blackbox/testdata/enableExceptions/main.m
new file mode 100644
index 000000000..86b45fc37
--- /dev/null
+++ b/tests/auto/blackbox/testdata/enableExceptions/main.m
@@ -0,0 +1,5 @@
+#import <Foundation/Foundation.h>
+
+int main() {
+ @throw [NSError new];
+}
diff --git a/tests/auto/blackbox/testdata/enableExceptions/none.qbs b/tests/auto/blackbox/testdata/enableExceptions/none.qbs
new file mode 100644
index 000000000..332af7614
--- /dev/null
+++ b/tests/auto/blackbox/testdata/enableExceptions/none.qbs
@@ -0,0 +1,10 @@
+import qbs
+
+CppApplication {
+ files: ["emptymain.cpp"]
+
+ Group {
+ condition: qbs.targetOS.contains("darwin")
+ files: ["empty.m", "empty.mm"]
+ }
+}
diff --git a/tests/auto/blackbox/testdata/enableRtti/main.cpp b/tests/auto/blackbox/testdata/enableRtti/main.cpp
new file mode 100644
index 000000000..630e75170
--- /dev/null
+++ b/tests/auto/blackbox/testdata/enableRtti/main.cpp
@@ -0,0 +1,23 @@
+#include <typeinfo>
+
+class I {
+public:
+ virtual ~I() { }
+ virtual void x() { }
+};
+
+class A : public I {
+ void x() override { }
+};
+
+class B : public I {
+ void x() override { }
+};
+
+int main() {
+ I *a = new A();
+ B *b = dynamic_cast<B *>(a);
+ (void)b;
+ delete a;
+ return 0;
+}
diff --git a/tests/auto/blackbox/testdata/enableRtti/rtti.qbs b/tests/auto/blackbox/testdata/enableRtti/rtti.qbs
new file mode 100644
index 000000000..f032bb16b
--- /dev/null
+++ b/tests/auto/blackbox/testdata/enableRtti/rtti.qbs
@@ -0,0 +1,13 @@
+import qbs
+
+Project {
+ property bool treatAsObjcpp: false
+ CppApplication {
+ cpp.cxxLanguageVersion: "c++11"
+ cpp.treatWarningsAsErrors: true
+ Group {
+ files: ["main.cpp"]
+ fileTags: [project.treatAsObjcpp ? "objcpp" : "cpp"]
+ }
+ }
+}
diff --git a/tests/auto/blackbox/testdata/error-info/helper.js b/tests/auto/blackbox/testdata/error-info/helper.js
new file mode 100644
index 000000000..18323df4a
--- /dev/null
+++ b/tests/auto/blackbox/testdata/error-info/helper.js
@@ -0,0 +1,9 @@
+var x;
+
+function doSomethingBad() {
+ nothinghere.works;
+}
+
+function doSomethingEvil() {
+ throw "OUCH!";
+}
diff --git a/tests/auto/blackbox/testdata/error-info/project.qbs b/tests/auto/blackbox/testdata/error-info/project.qbs
new file mode 100644
index 000000000..f2c65597f
--- /dev/null
+++ b/tests/auto/blackbox/testdata/error-info/project.qbs
@@ -0,0 +1,71 @@
+import qbs
+import "helper.js" as Helper
+
+Project {
+ property bool fail1: false
+ property bool fail2: false
+ property bool fail3: false
+ property bool fail4: false
+ property bool fail5: false
+ property bool fail6: false
+ property bool fail7: false
+
+ Product {
+ type: ["foo", "bar"]
+
+ Rule {
+ inputs: ["qbs"]
+
+ Artifact {
+ fileTags: ["foo"]
+ filePath: {
+ var path = "foo";
+ if (project.fail1)
+ throw "fail1";
+ return path;
+ }
+ }
+
+ prepare: {
+ var cmd = new JavaScriptCommand();
+ cmd.sourceCode = function () {
+
+ };
+ cmd.silent = true;
+ if (project.fail2)
+ generate.an.error;
+ if (project.fail6)
+ Helper.doSomethingEvil();
+ return cmd;
+ }
+ }
+
+ Rule {
+ inputs: ["qbs"]
+
+ outputFileTags: ["bar"]
+ outputArtifacts: {
+ var list = [];
+ list.push({ fileTags: ["bar"], filePath: "bar" });
+ if (project.fail3)
+ throw "fail3";
+ if (project.fail5)
+ Helper.doSomethingBad();
+ return list;
+ }
+
+ prepare: {
+ var cmd = new JavaScriptCommand();
+ cmd.fail7 = project.fail7;
+ cmd.sourceCode = function () {
+ if (fail7)
+ will.fail;
+ };
+ cmd.silent = true;
+ if (project.fail4)
+ generate.an.error;
+ return cmd;
+ }
+ }
+ }
+}
diff --git a/tests/auto/blackbox/testdata/linkerscripts/linkerscripts.qbs b/tests/auto/blackbox/testdata/linkerscripts/linkerscripts.qbs
index 1f3bf010c..4423d68e0 100644
--- a/tests/auto/blackbox/testdata/linkerscripts/linkerscripts.qbs
+++ b/tests/auto/blackbox/testdata/linkerscripts/linkerscripts.qbs
@@ -20,7 +20,7 @@ DynamicLibrary {
var cmd = new JavaScriptCommand();
cmd.silent = true;
cmd.sourceCode = function() {
- print("---" + product.moduleProperty("cpp", "nmPath") + "---");
+ console.info("---" + product.moduleProperty("cpp", "nmPath") + "---");
}
return [cmd];
}
diff --git a/tests/auto/blackbox/testdata/nodejs/hello.qbs b/tests/auto/blackbox/testdata/nodejs/hello.qbs
index e11b1a599..d5e92209a 100644
--- a/tests/auto/blackbox/testdata/nodejs/hello.qbs
+++ b/tests/auto/blackbox/testdata/nodejs/hello.qbs
@@ -3,5 +3,4 @@ import qbs
NodeJSApplication {
nodejs.applicationFile: "hello.js"
name: "hello"
- files: "hello.js"
}
diff --git a/tests/auto/blackbox/testdata/probe-in-exported-module/dependee.qbs b/tests/auto/blackbox/testdata/probe-in-exported-module/dependee.qbs
new file mode 100644
index 000000000..94e266499
--- /dev/null
+++ b/tests/auto/blackbox/testdata/probe-in-exported-module/dependee.qbs
@@ -0,0 +1,15 @@
+import qbs
+
+Product {
+ name: "dependee"
+ Depends { name: "dependency" }
+ type: ["out", "dep-out"]
+ Group {
+ files: "test.in"
+ fileTags: ["dep-in"]
+ }
+ Group {
+ files: "test2.in"
+ fileTags: ["in"]
+ }
+}
diff --git a/tests/auto/blackbox/testdata/probe-in-exported-module/dependency.qbs b/tests/auto/blackbox/testdata/probe-in-exported-module/dependency.qbs
new file mode 100644
index 000000000..1413777dc
--- /dev/null
+++ b/tests/auto/blackbox/testdata/probe-in-exported-module/dependency.qbs
@@ -0,0 +1,8 @@
+import qbs
+
+Product {
+ name: "dependency"
+ Export {
+ Depends { name: "mymodule" }
+ }
+}
diff --git a/tests/auto/blackbox/testdata/probe-in-exported-module/modules/depmodule/depmodule.qbs b/tests/auto/blackbox/testdata/probe-in-exported-module/modules/depmodule/depmodule.qbs
new file mode 100644
index 000000000..b477e2bf7
--- /dev/null
+++ b/tests/auto/blackbox/testdata/probe-in-exported-module/modules/depmodule/depmodule.qbs
@@ -0,0 +1,21 @@
+import qbs
+
+Module {
+ property string prop
+
+ Rule {
+ inputs: ["dep-in"]
+ Artifact {
+ filePath: "dummy.txt"
+ fileTags: ["dep-out"]
+ }
+ prepare: {
+ var cmd = new JavaScriptCommand();
+ cmd.description = "Creating dep-out artifact";
+ cmd.sourceCode = function() {
+ console.info("prop: " + product.moduleProperty("depmodule", "prop"));
+ };
+ return [cmd];
+ }
+ }
+}
diff --git a/tests/auto/blackbox/testdata/probe-in-exported-module/modules/mymodule/mymodule.qbs b/tests/auto/blackbox/testdata/probe-in-exported-module/modules/mymodule/mymodule.qbs
new file mode 100644
index 000000000..af1c33049
--- /dev/null
+++ b/tests/auto/blackbox/testdata/probe-in-exported-module/modules/mymodule/mymodule.qbs
@@ -0,0 +1,27 @@
+import qbs
+
+Module {
+ Depends { name: "depmodule" }
+ Probe {
+ id: theProbe
+ configure: { found = true; }
+ }
+ property bool found: theProbe.found
+ depmodule.prop: found ? "yes" : "no"
+
+ Rule {
+ inputs: ["in"]
+ Artifact {
+ filePath: "dummy2.txt"
+ fileTags: ["out"]
+ }
+ prepare: {
+ var cmd = new JavaScriptCommand();
+ cmd.description = "Creating out artifact";
+ cmd.sourceCode = function() {
+ console.info("found: " + product.moduleProperty("mymodule", "found"));
+ };
+ return [cmd];
+ }
+ }
+}
diff --git a/tests/auto/blackbox/testdata/probe-in-exported-module/probe-in-exported-module.qbs b/tests/auto/blackbox/testdata/probe-in-exported-module/probe-in-exported-module.qbs
new file mode 100644
index 000000000..4e0f13f60
--- /dev/null
+++ b/tests/auto/blackbox/testdata/probe-in-exported-module/probe-in-exported-module.qbs
@@ -0,0 +1,5 @@
+import qbs
+
+Project {
+ references: [ "dependee.qbs", "dependency.qbs" ]
+}
diff --git a/tests/auto/blackbox/testdata/probe-in-exported-module/test.in b/tests/auto/blackbox/testdata/probe-in-exported-module/test.in
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/auto/blackbox/testdata/probe-in-exported-module/test.in
diff --git a/tests/auto/blackbox/testdata/probe-in-exported-module/test2.in b/tests/auto/blackbox/testdata/probe-in-exported-module/test2.in
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/auto/blackbox/testdata/probe-in-exported-module/test2.in
diff --git a/tests/auto/blackbox/testdata/probeProperties/bin/tool b/tests/auto/blackbox/testdata/probeProperties/bin/tool
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/auto/blackbox/testdata/probeProperties/bin/tool
diff --git a/tests/auto/blackbox/testdata/probeProperties/main.c b/tests/auto/blackbox/testdata/probeProperties/main.c
new file mode 100644
index 000000000..76e819701
--- /dev/null
+++ b/tests/auto/blackbox/testdata/probeProperties/main.c
@@ -0,0 +1 @@
+int main() { return 0; }
diff --git a/tests/auto/blackbox/testdata/probeProperties/probeProperties.qbs b/tests/auto/blackbox/testdata/probeProperties/probeProperties.qbs
new file mode 100644
index 000000000..36842e40b
--- /dev/null
+++ b/tests/auto/blackbox/testdata/probeProperties/probeProperties.qbs
@@ -0,0 +1,30 @@
+import qbs
+import qbs.Probes
+
+CppApplication {
+ Probes.PathProbe {
+ id: probe1
+ names: ["bin/tool"]
+ platformPaths: [product.sourceDirectory]
+ }
+
+ Probes.PathProbe {
+ id: probe2
+ names: ["tool"]
+ platformPaths: [product.sourceDirectory + "/bin"]
+ }
+
+ targetName: {
+ console.info("probe1.fileName=" + probe1.fileName);
+ console.info("probe1.path=" + probe1.path);
+ console.info("probe1.filePath=" + probe1.filePath);
+
+ console.info("probe2.fileName=" + probe2.fileName);
+ console.info("probe2.path=" + probe2.path);
+ console.info("probe2.filePath=" + probe2.filePath);
+
+ return name;
+ }
+
+ files: ["main.c"]
+}
diff --git a/tests/auto/blackbox/testdata/referenceErrorInExport/main.c b/tests/auto/blackbox/testdata/referenceErrorInExport/main.c
new file mode 100644
index 000000000..76e819701
--- /dev/null
+++ b/tests/auto/blackbox/testdata/referenceErrorInExport/main.c
@@ -0,0 +1 @@
+int main() { return 0; }
diff --git a/tests/auto/blackbox/testdata/referenceErrorInExport/project.qbs b/tests/auto/blackbox/testdata/referenceErrorInExport/project.qbs
new file mode 100644
index 000000000..91069f629
--- /dev/null
+++ b/tests/auto/blackbox/testdata/referenceErrorInExport/project.qbs
@@ -0,0 +1,20 @@
+import qbs
+
+Project {
+ CppApplication {
+ Depends { name: "other" }
+ files: ["main.c"]
+ cpp.includePaths: ["."]
+ }
+
+ DynamicLibrary {
+ name: "other"
+ files: ["main.c"]
+
+ property stringList includePaths: []
+ Export {
+ Depends { name: "cpp" }
+ cpp.includePaths: includePaths
+ }
+ }
+}
diff --git a/tests/auto/blackbox/testdata/separate-debug-info/project.qbs b/tests/auto/blackbox/testdata/separate-debug-info/project.qbs
index 0939f7227..c0498df3d 100644
--- a/tests/auto/blackbox/testdata/separate-debug-info/project.qbs
+++ b/tests/auto/blackbox/testdata/separate-debug-info/project.qbs
@@ -20,6 +20,7 @@ Project {
files: ["foo.cpp"]
cpp.separateDebugInformation: true
}
+
CppApplication {
name: "app2"
type: ["application"]
@@ -39,4 +40,76 @@ Project {
files: ["foo.cpp"]
cpp.separateDebugInformation: false
}
+
+ CppApplication {
+ name: "app3"
+ type: ["application"]
+ files: ["main.cpp"]
+ cpp.separateDebugInformation: true
+ cpp.dsymutilFlags: ["--flat"]
+ }
+ DynamicLibrary {
+ Depends { name: "cpp" }
+ name: "foo3"
+ type: ["dynamiclibrary"]
+ files: ["foo.cpp"]
+ cpp.separateDebugInformation: true
+ cpp.dsymutilFlags: ["--flat"]
+ }
+ LoadableModule {
+ Depends { name: "cpp" }
+ name: "bar3"
+ files: ["foo.cpp"]
+ cpp.separateDebugInformation: true
+ cpp.dsymutilFlags: ["--flat"]
+ }
+
+ CppApplication {
+ name: "app4"
+ type: ["application"]
+ files: ["main.cpp"]
+ bundle.isBundle: false
+ cpp.separateDebugInformation: true
+ }
+ DynamicLibrary {
+ Depends { name: "cpp" }
+ name: "foo4"
+ type: ["dynamiclibrary"]
+ files: ["foo.cpp"]
+ bundle.isBundle: false
+ cpp.separateDebugInformation: true
+ }
+ LoadableModule {
+ Depends { name: "cpp" }
+ name: "bar4"
+ files: ["foo.cpp"]
+ bundle.isBundle: false
+ cpp.separateDebugInformation: true
+ }
+
+ CppApplication {
+ name: "app5"
+ type: ["application"]
+ files: ["main.cpp"]
+ bundle.isBundle: false
+ cpp.separateDebugInformation: true
+ cpp.dsymutilFlags: ["--flat"]
+ }
+ DynamicLibrary {
+ Depends { name: "cpp" }
+ name: "foo5"
+ type: ["dynamiclibrary"]
+ files: ["foo.cpp"]
+ bundle.isBundle: false
+ cpp.separateDebugInformation: true
+ cpp.dsymutilFlags: ["--flat"]
+ }
+ LoadableModule {
+ Depends { name: "cpp" }
+ name: "bar5"
+ files: ["foo.cpp"]
+ bundle.isBundle: false
+ cpp.separateDebugInformation: true
+ cpp.dsymutilFlags: ["--flat"]
+ }
}
diff --git a/tests/auto/blackbox/testdata/trackExternalProductChanges/fileList.js b/tests/auto/blackbox/testdata/trackExternalProductChanges/fileList.js
index c3dfe2b11..159a7d32a 100644
--- a/tests/auto/blackbox/testdata/trackExternalProductChanges/fileList.js
+++ b/tests/auto/blackbox/testdata/trackExternalProductChanges/fileList.js
@@ -1,4 +1,4 @@
function fileList() { return []; }
-function filesFromFs(qbs) { return File.exists(path + "/fileExists.cpp") ? ["fileExists.cpp"] : []; }
+function filesFromFs(path) { return File.exists(path + "/fileExists.cpp") ? ["fileExists.cpp"] : []; }
diff --git a/tests/auto/blackbox/testdata/trackExternalProductChanges/project.qbs b/tests/auto/blackbox/testdata/trackExternalProductChanges/project.qbs
index 05060acd7..e99d6b350 100644
--- a/tests/auto/blackbox/testdata/trackExternalProductChanges/project.qbs
+++ b/tests/auto/blackbox/testdata/trackExternalProductChanges/project.qbs
@@ -6,7 +6,7 @@ import "fileList.js" as FileList
CppApplication {
property stringList filesFromEnv: Environment.getEnv("QBS_TEST_PULL_IN_FILE_VIA_ENV")
? ["environmentChange.cpp"] : []
- files: ["main.cpp"].concat(FileList.fileList()).concat(filesFromEnv).concat(FileList.filesFromFs(qbs))
+ files: ["main.cpp"].concat(FileList.fileList()).concat(filesFromEnv).concat(FileList.filesFromFs(path))
Group {
condition: Environment.getEnv("INCLUDE_PATH_TEST")
diff --git a/tests/auto/blackbox/testdata/typescript/typescript.qbs b/tests/auto/blackbox/testdata/typescript/typescript.qbs
index 1b4c675c3..d15e9db50 100644
--- a/tests/auto/blackbox/testdata/typescript/typescript.qbs
+++ b/tests/auto/blackbox/testdata/typescript/typescript.qbs
@@ -15,8 +15,7 @@ Project {
files: [
"animals.ts",
"extra.js",
- "woosh/extra.ts",
- "main.ts"
+ "woosh/extra.ts"
]
}
diff --git a/tests/auto/blackbox/testdata/versionscript/versionscript.qbs b/tests/auto/blackbox/testdata/versionscript/versionscript.qbs
index f845f2457..56260a022 100644
--- a/tests/auto/blackbox/testdata/versionscript/versionscript.qbs
+++ b/tests/auto/blackbox/testdata/versionscript/versionscript.qbs
@@ -20,7 +20,7 @@ DynamicLibrary {
var cmd = new JavaScriptCommand();
cmd.silent = true;
cmd.sourceCode = function() {
- print("---" + product.moduleProperty("cpp", "nmPath") + "---");
+ console.info("---" + product.moduleProperty("cpp", "nmPath") + "---");
}
return [cmd];
}
diff --git a/tests/auto/blackbox/tst_blackbox.cpp b/tests/auto/blackbox/tst_blackbox.cpp
index d58d70b00..0c20eb1c9 100644
--- a/tests/auto/blackbox/tst_blackbox.cpp
+++ b/tests/auto/blackbox/tst_blackbox.cpp
@@ -327,14 +327,12 @@ void TestBlackbox::sevenZip()
const QString outputFile = relativeProductBuildDir("archivable") + "/archivable.7z";
QVERIFY2(regularFileExists(outputFile), qPrintable(outputFile));
QProcess listContents;
- listContents.start(binary, QStringList() << "t" << outputFile);
+ listContents.start(binary, QStringList() << "l" << outputFile);
QVERIFY2(listContents.waitForStarted(), qPrintable(listContents.errorString()));
QVERIFY2(listContents.waitForFinished(), qPrintable(listContents.errorString()));
QVERIFY2(listContents.exitCode() == 0, listContents.readAllStandardError().constData());
const QByteArray output = listContents.readAllStandardOutput();
- if (output.count("Testing") != 2)
- qDebug("%s", output.constData());
- QCOMPARE(output.count("Testing"), 2);
+ QVERIFY2(output.contains("2 files"), output.constData());
QVERIFY2(output.contains("test.txt"), output.constData());
QVERIFY2(output.contains("archivable.qbs"), output.constData());
}
@@ -462,6 +460,12 @@ void TestBlackbox::android()
int status;
const auto androidPaths = findAndroid(&status);
+ const auto ndkPath = androidPaths["ndk"];
+ static const QStringList ndkSamplesDirs = QStringList() << "teapot" << "no-native";
+ if (!ndkPath.isEmpty() && !QFileInfo(ndkPath + "/samples").isDir()
+ && ndkSamplesDirs.contains(projectDir))
+ QSKIP("NDK samples directory not present");
+
QDir::setCurrent(testDataDir + "/android/" + projectDir);
Settings s((QString()));
Profile p("qbs_autotests-android", &s);
@@ -520,6 +524,254 @@ void TestBlackbox::buildDirectories()
QVERIFY2(outputLines.contains(projectDir), m_qbsStdout.constData());
}
+class QFileInfo2 : public QFileInfo {
+public:
+ QFileInfo2(const QString &path) : QFileInfo(path) { }
+ bool isRegularFile() const { return isFile() && !isSymLink(); }
+ bool isRegularDir() const { return isDir() && !isSymLink(); }
+ bool isFileSymLink() const { return isFile() && isSymLink(); }
+ bool isDirSymLink() const { return isDir() && isSymLink(); }
+};
+
+void TestBlackbox::bundleStructure()
+{
+ if (!HostOsInfo::isOsxHost())
+ QSKIP("only applies on OS X");
+
+ QFETCH(QString, productName);
+ QFETCH(QString, productTypeIdentifier);
+ QFETCH(bool, isShallow);
+
+ QDir::setCurrent(testDataDir + "/bundle-structure");
+ QbsRunParameters params;
+ params.arguments << "project.buildableProducts:" + productName;
+ if (isShallow) {
+ // Coerce shallow bundles - don't set bundle.isShallow directly because we want to test the
+ // automatic detection
+ params.arguments
+ << "qbs.targetOS:ios,darwin,bsd,unix"
+ << "qbs.architecture:arm64";
+ }
+
+ if (productName == "ABadApple" || productName == "ABadThirdParty")
+ params.expectFailure = true;
+
+ rmDirR(relativeBuildDir());
+ const int status = runQbs(params);
+ if (status != 0) {
+ QVERIFY2(m_qbsStderr.contains("Bundle product type "
+ + productTypeIdentifier.toLatin1()
+ + " is not supported."),
+ m_qbsStderr.constData());
+ return;
+ }
+
+ QCOMPARE(status, 0);
+
+ if (!isShallow) {
+ if (productName == "A") {
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app/Contents").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app/Contents/Info.plist").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app/Contents/MacOS").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app/Contents/MacOS/A").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app/Contents/PkgInfo").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app/Contents/Resources").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app/Contents/Resources/resource.txt").isRegularFile());
+ }
+
+ if (productName == "B") {
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/B").isFileSymLink());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Headers").isDirSymLink());
+ //QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Modules").isDirSymLink());
+ QVERIFY(!QFileInfo2(defaultInstallRoot + "/B.framework/PkgInfo").exists());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/PrivateHeaders").isDirSymLink());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Resources").isDirSymLink());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Versions").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Versions/A").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Versions/A/B").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Versions/A/Headers").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Versions/A/Headers/dummy.h").isRegularFile());
+ //QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Versions/A/Modules").isRegularDir());
+ //QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Versions/A/Modules/module.modulemap").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Versions/A/PrivateHeaders").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Versions/A/PrivateHeaders/dummy_p.h").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Versions/A/Resources").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Versions/A/Resources/Info.plist").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Versions/Current").isDirSymLink());
+ }
+
+ if (productName == "C") {
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/C").isFileSymLink());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Headers").isDirSymLink());
+ //QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Modules").isDirSymLink());
+ QVERIFY(!QFileInfo2(defaultInstallRoot + "/C.framework/PkgInfo").exists());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/PrivateHeaders").isDirSymLink());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Resources").isDirSymLink());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Versions").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Versions/A").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Versions/A/C").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Versions/A/Headers").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Versions/A/Headers/dummy.h").isRegularFile());
+ //QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Versions/A/Modules").isRegularDir());
+ //QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Versions/A/Modules/module.modulemap").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Versions/A/PrivateHeaders").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Versions/A/PrivateHeaders/dummy_p.h").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Versions/A/Resources").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Versions/A/Resources/Info.plist").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Versions/Current").isDirSymLink());
+ }
+
+ if (productName == "D") {
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle/Contents").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle/Contents/Info.plist").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle/Contents/MacOS").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle/Contents/MacOS/D").isRegularFile());
+ QVERIFY(!QFileInfo2(defaultInstallRoot + "/D.bundle/Contents/PkgInfo").exists());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle/Contents/Resources").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle/Contents/Resources/resource.txt").isRegularFile());
+ }
+
+ if (productName == "E") {
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex/Contents").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex/Contents/Info.plist").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex/Contents/MacOS").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex/Contents/MacOS/E").isRegularFile());
+ QVERIFY(!QFileInfo2(defaultInstallRoot + "/E.appex/Contents/PkgInfo").exists());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex/Contents/Resources").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex/Contents/Resources/resource.txt").isRegularFile());
+ }
+
+ if (productName == "F") {
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc/Contents").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc/Contents/Info.plist").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc/Contents/MacOS").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc/Contents/MacOS/F").isRegularFile());
+ QVERIFY(!QFileInfo2(defaultInstallRoot + "/F.xpc/Contents/PkgInfo").exists());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc/Contents/Resources").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc/Contents/Resources/resource.txt").isRegularFile());
+ }
+
+ if (productName == "G") {
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/G").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/G/ContentInfo.plist").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/G/Contents/resource.txt").isRegularFile());
+ }
+ } else {
+ if (productName == "A") {
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app/A").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app/Info.plist").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app/PkgInfo").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app/resource.txt").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app/ResourceRules.plist").isRegularFile());
+ }
+
+ if (productName == "B") {
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/B").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Headers").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Headers/dummy.h").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Info.plist").isRegularFile());
+ //QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Modules").isRegularDir());
+ //QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Modules/module.modulemap").isRegularFile());
+ QVERIFY(!QFileInfo2(defaultInstallRoot + "/B.framework/PkgInfo").exists());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/PrivateHeaders").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/PrivateHeaders/dummy_p.h").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/resource.txt").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/ResourceRules.plist").isRegularFile());
+ }
+
+ if (productName == "C") {
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/C").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Headers").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Headers/dummy.h").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Info.plist").isRegularFile());
+ //QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Modules").isRegularDir());
+ //QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Modules/module.modulemap").isRegularFile());
+ QVERIFY(!QFileInfo2(defaultInstallRoot + "/C.framework/PkgInfo").exists());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/PrivateHeaders").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/PrivateHeaders/dummy_p.h").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/resource.txt").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/ResourceRules.plist").isRegularFile());
+ }
+
+ if (productName == "D") {
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle/D").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle/Headers").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle/Headers/dummy.h").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle/Info.plist").isRegularFile());
+ QVERIFY(!QFileInfo2(defaultInstallRoot + "/D.bundle/PkgInfo").exists());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle/PrivateHeaders").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle/PrivateHeaders/dummy_p.h").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle/resource.txt").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle/ResourceRules.plist").isRegularFile());
+ }
+
+ if (productName == "E") {
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex/E").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex/Headers").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex/Headers/dummy.h").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex/Info.plist").isRegularFile());
+ QVERIFY(!QFileInfo2(defaultInstallRoot + "/E.appex/PkgInfo").exists());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex/PrivateHeaders").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex/PrivateHeaders/dummy_p.h").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex/resource.txt").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex/ResourceRules.plist").isRegularFile());
+ }
+
+ if (productName == "F") {
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc/F").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc/Headers").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc/Headers/dummy.h").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc/Info.plist").isRegularFile());
+ QVERIFY(!QFileInfo2(defaultInstallRoot + "/F.xpc/PkgInfo").exists());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc/PrivateHeaders").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc/PrivateHeaders/dummy_p.h").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc/resource.txt").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc/ResourceRules.plist").isRegularFile());
+ }
+
+ if (productName == "G") {
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/G").isRegularDir());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/G/ContentInfo.plist").isRegularFile());
+ QVERIFY(QFileInfo2(defaultInstallRoot + "/G/Contents/resource.txt").isRegularFile());
+ }
+ }
+}
+
+void TestBlackbox::bundleStructure_data()
+{
+ QTest::addColumn<QString>("productName");
+ QTest::addColumn<QString>("productTypeIdentifier");
+ QTest::addColumn<bool>("isShallow");
+
+ const auto addRows = [](bool isShallow) {
+ const QString s = (isShallow ? " shallow" : "");
+ QTest::newRow(("A" + s).toLatin1()) << "A" << "com.apple.product-type.application" << isShallow;
+ QTest::newRow(("ABadApple" + s).toLatin1()) << "ABadApple" << "com.apple.product-type.will.never.exist.ever.guaranteed" << isShallow;
+ QTest::newRow(("ABadThirdParty" + s).toLatin1()) << "ABadThirdParty" << "org.special.third.party.non.existent.product.type" << isShallow;
+ QTest::newRow(("B" + s).toLatin1()) << "B" << "com.apple.product-type.framework" << isShallow;
+ QTest::newRow(("C" + s).toLatin1()) << "C" << "com.apple.product-type.framework.static" << isShallow;
+ QTest::newRow(("D" + s).toLatin1()) << "D" << "com.apple.product-type.bundle" << isShallow;
+ QTest::newRow(("E" + s).toLatin1()) << "E" << "com.apple.product-type.app-extension" << isShallow;
+ QTest::newRow(("F" + s).toLatin1()) << "F" << "com.apple.product-type.xpc-service" << isShallow;
+ QTest::newRow(("G" + s).toLatin1()) << "G" << "com.apple.product-type.in-app-purchase-content" << isShallow;
+ };
+
+ addRows(true);
+ addRows(false);
+}
+
void TestBlackbox::changedFiles_data()
{
QTest::addColumn<bool>("useChangedFilesForInitialBuild");
@@ -575,7 +827,7 @@ void TestBlackbox::changeInImportedFile()
{
QDir::setCurrent(testDataDir + "/change-in-imported-file");
QCOMPARE(runQbs(), 0);
- QVERIFY2(m_qbsStderr.contains("old output"), m_qbsStderr.constData());
+ QVERIFY2(m_qbsStdout.contains("old output"), m_qbsStdout.constData());
WAIT_FOR_NEW_TIMESTAMP();
QFile jsFile("prepare.js");
@@ -586,7 +838,7 @@ void TestBlackbox::changeInImportedFile()
jsFile.write(content);
jsFile.close();
QCOMPARE(runQbs(), 0);
- QVERIFY2(m_qbsStderr.contains("new output"), m_qbsStderr.constData());
+ QVERIFY2(m_qbsStdout.contains("new output"), m_qbsStdout.constData());
WAIT_FOR_NEW_TIMESTAMP();
QVERIFY2(jsFile.open(QIODevice::ReadWrite), qPrintable(jsFile.errorString()));
@@ -594,7 +846,7 @@ void TestBlackbox::changeInImportedFile()
jsFile.write(content);
jsFile.close();
QCOMPARE(runQbs(), 0);
- QVERIFY2(!m_qbsStderr.contains("output"), m_qbsStderr.constData());
+ QVERIFY2(!m_qbsStdout.contains("output"), m_qbsStdout.constData());
}
void TestBlackbox::dependenciesProperty()
@@ -662,6 +914,48 @@ void TestBlackbox::dependencyProfileMismatch()
m_qbsStderr.constData());
}
+void TestBlackbox::deploymentTarget()
+{
+ if (!HostOsInfo::isOsxHost())
+ QSKIP("only applies on OS X");
+
+ QFETCH(QString, os);
+ QFETCH(QString, arch);
+ QFETCH(QString, cflags);
+ QFETCH(QString, lflags);
+
+ QDir::setCurrent(testDataDir + "/deploymentTarget");
+
+ QbsRunParameters params;
+ params.arguments = QStringList()
+ << "--command-echo-mode"
+ << "command-line"
+ << "qbs.targetOS:" + os
+ << "qbs.architecture:" + arch;
+
+ rmDirR(relativeBuildDir());
+ QCOMPARE(runQbs(params), 0);
+ QVERIFY2(m_qbsStdout.contains(cflags.toLatin1()), m_qbsStdout.constData());
+ QVERIFY2(m_qbsStdout.contains(lflags.toLatin1()), m_qbsStdout.constData());
+}
+
+void TestBlackbox::deploymentTarget_data()
+{
+ QTest::addColumn<QString>("os");
+ QTest::addColumn<QString>("arch");
+ QTest::addColumn<QString>("cflags");
+ QTest::addColumn<QString>("lflags");
+ QTest::newRow("osx") << "osx,darwin,bsd,unix" << "x86_64"
+ << "-triple x86_64-apple-macosx10.4"
+ << "-macosx_version_min 10.4";
+ QTest::newRow("ios") << "ios,darwin,bsd,unix" << "arm64"
+ << "-triple arm64-apple-ios5.0"
+ << "-iphoneos_version_min 5.0";
+ QTest::newRow("ios-sim") << "ios-simulator,ios,darwin,bsd,unix" << "x86_64"
+ << "-triple x86_64-apple-ios5.0"
+ << "-ios_simulator_version_min 5.0";
+}
+
void TestBlackbox::symlinkRemoval()
{
if (HostOsInfo::isWindowsHost())
@@ -699,7 +993,7 @@ void TestBlackbox::versionScript()
QDir::setCurrent(testDataDir + "/versionscript");
QCOMPARE(runQbs(QbsRunParameters(QStringList("-qq")
<< ("qbs.installRoot:" + QDir::currentPath()))), 0);
- const QString output = QString::fromLocal8Bit(m_qbsStderr);
+ const QString output = QString::fromLocal8Bit(m_qbsStdout);
QRegExp pattern(".*---(.*)---.*");
QVERIFY2(pattern.exactMatch(output), qPrintable(output));
QCOMPARE(pattern.captureCount(), 1);
@@ -861,12 +1155,69 @@ void TestBlackbox::separateDebugInfo()
QStringList toolchain = buildProfile.value("qbs.toolchain").toStringList();
QStringList targetOS = buildProfile.value("qbs.targetOS").toStringList();
if (targetOS.contains("darwin") || (targetOS.isEmpty() && HostOsInfo::isOsxHost())) {
- QVERIFY(QFile::exists(relativeProductBuildDir("app1") + "/app1.app.dSYM"));
+ QVERIFY(directoryExists(relativeProductBuildDir("app1") + "/app1.app.dSYM"));
+ QVERIFY(regularFileExists(relativeProductBuildDir("app1")
+ + "/app1.app.dSYM/Contents/Info.plist"));
+ QVERIFY(regularFileExists(relativeProductBuildDir("app1")
+ + "/app1.app.dSYM/Contents/Resources/DWARF/app1"));
+ QCOMPARE(QDir(relativeProductBuildDir("app1")
+ + "/app1.app.dSYM/Contents/Resources/DWARF")
+ .entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).size(), 1);
QVERIFY(!QFile::exists(relativeProductBuildDir("app2") + "/app2.app.dSYM"));
- QVERIFY(QFile::exists(relativeProductBuildDir("foo1") + "/foo1.framework.dSYM"));
+ QVERIFY(!QFile::exists(relativeProductBuildDir("app3") + "/app3.app.dSYM"));
+ QVERIFY(regularFileExists(relativeProductBuildDir("app3")
+ + "/app3.app/Contents/MacOS/app3.dwarf"));
+ QVERIFY(directoryExists(relativeProductBuildDir("app4") + "/app4.dSYM"));
+ QVERIFY(regularFileExists(relativeProductBuildDir("app4")
+ + "/app4.dSYM/Contents/Info.plist"));
+ QVERIFY(regularFileExists(relativeProductBuildDir("app4")
+ + "/app4.dSYM/Contents/Resources/DWARF/app4"));
+ QCOMPARE(QDir(relativeProductBuildDir("app4")
+ + "/app4.dSYM/Contents/Resources/DWARF")
+ .entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).size(), 1);
+ QVERIFY(regularFileExists(relativeProductBuildDir("app5") + "/app5.dwarf"));
+ QVERIFY(directoryExists(relativeProductBuildDir("foo1") + "/foo1.framework.dSYM"));
+ QVERIFY(regularFileExists(relativeProductBuildDir("foo1")
+ + "/foo1.framework.dSYM/Contents/Info.plist"));
+ QVERIFY(regularFileExists(relativeProductBuildDir("foo1")
+ + "/foo1.framework.dSYM/Contents/Resources/DWARF/foo1"));
+ QCOMPARE(QDir(relativeProductBuildDir("foo1")
+ + "/foo1.framework.dSYM/Contents/Resources/DWARF")
+ .entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).size(), 1);
QVERIFY(!QFile::exists(relativeProductBuildDir("foo2") + "/foo2.framework.dSYM"));
- QVERIFY(QFile::exists(relativeProductBuildDir("bar1") + "/bar1.bundle.dSYM"));
+ QVERIFY(!QFile::exists(relativeProductBuildDir("foo3") + "/foo3.framework.dSYM"));
+ QVERIFY(regularFileExists(relativeProductBuildDir("foo3")
+ + "/foo3.framework/Versions/A/foo3.dwarf"));
+ QVERIFY(directoryExists(relativeProductBuildDir("foo4") + "/libfoo4.dylib.dSYM"));
+ QVERIFY(regularFileExists(relativeProductBuildDir("foo4")
+ + "/libfoo4.dylib.dSYM/Contents/Info.plist"));
+ QVERIFY(regularFileExists(relativeProductBuildDir("foo4")
+ + "/libfoo4.dylib.dSYM/Contents/Resources/DWARF/libfoo4.dylib"));
+ QCOMPARE(QDir(relativeProductBuildDir("foo4")
+ + "/libfoo4.dylib.dSYM/Contents/Resources/DWARF")
+ .entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).size(), 1);
+ QVERIFY(regularFileExists(relativeProductBuildDir("foo5") + "/libfoo5.dylib.dwarf"));
+ QVERIFY(directoryExists(relativeProductBuildDir("bar1") + "/bar1.bundle.dSYM"));
+ QVERIFY(regularFileExists(relativeProductBuildDir("bar1")
+ + "/bar1.bundle.dSYM/Contents/Info.plist"));
+ QVERIFY(regularFileExists(relativeProductBuildDir("bar1")
+ + "/bar1.bundle.dSYM/Contents/Resources/DWARF/bar1"));
+ QCOMPARE(QDir(relativeProductBuildDir("bar1")
+ + "/bar1.bundle.dSYM/Contents/Resources/DWARF")
+ .entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).size(), 1);
QVERIFY(!QFile::exists(relativeProductBuildDir("bar2") + "/bar2.bundle.dSYM"));
+ QVERIFY(!QFile::exists(relativeProductBuildDir("bar3") + "/bar3.bundle.dSYM"));
+ QVERIFY(regularFileExists(relativeProductBuildDir("bar3")
+ + "/bar3.bundle/Contents/MacOS/bar3.dwarf"));
+ QVERIFY(directoryExists(relativeProductBuildDir("bar4") + "/bar4.bundle.dSYM"));
+ QVERIFY(regularFileExists(relativeProductBuildDir("bar4")
+ + "/bar4.bundle.dSYM/Contents/Info.plist"));
+ QVERIFY(regularFileExists(relativeProductBuildDir("bar4")
+ + "/bar4.bundle.dSYM/Contents/Resources/DWARF/bar4.bundle"));
+ QCOMPARE(QDir(relativeProductBuildDir("bar4")
+ + "/bar4.bundle.dSYM/Contents/Resources/DWARF")
+ .entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).size(), 1);
+ QVERIFY(regularFileExists(relativeProductBuildDir("bar5") + "/bar5.bundle.dwarf"));
} else if (toolchain.contains("gcc")) {
QVERIFY(QFile::exists(relativeProductBuildDir("app1") + "/app1.debug"));
QVERIFY(!QFile::exists(relativeProductBuildDir("app2") + "/app2.debug"));
@@ -1301,6 +1652,17 @@ void TestBlackbox::recursiveWildcards()
QVERIFY(QFileInfo(defaultInstallRoot + "/dir/file2.txt").exists());
}
+void TestBlackbox::referenceErrorInExport()
+{
+ QDir::setCurrent(testDataDir + "/referenceErrorInExport");
+ QbsRunParameters params;
+ params.expectFailure = true;
+ QVERIFY(runQbs(params) != 0);
+ QEXPECT_FAIL(0, "QBS-946", Abort);
+ QVERIFY(m_qbsStderr.contains(
+ "project.qbs:17:31 ReferenceError: Can't find variable: includePaths"));
+}
+
void TestBlackbox::reproducibleBuild()
{
Settings s((QString()));
@@ -1384,6 +1746,29 @@ void TestBlackbox::overrideProjectProperties()
QCOMPARE(runQbs(params), 0);
}
+void TestBlackbox::probeProperties()
+{
+ QDir::setCurrent(testDataDir + "/probeProperties");
+ const QByteArray dir = QDir::cleanPath(testDataDir).toLatin1() + "/probeProperties";
+ QCOMPARE(runQbs(), 0);
+ QVERIFY2(m_qbsStdout.contains("probe1.fileName=bin/tool"), m_qbsStdout.constData());
+ QVERIFY2(m_qbsStdout.contains("probe1.path=" + dir), m_qbsStdout.constData());
+ QVERIFY2(m_qbsStdout.contains("probe1.filePath=" + dir + "/bin/tool"), m_qbsStdout.constData());
+ QVERIFY2(m_qbsStdout.contains("probe2.fileName=tool"), m_qbsStdout.constData());
+ QVERIFY2(m_qbsStdout.contains("probe2.path=" + dir + "/bin"), m_qbsStdout.constData());
+ QVERIFY2(m_qbsStdout.contains("probe2.filePath=" + dir + "/bin/tool"), m_qbsStdout.constData());
+}
+
+void TestBlackbox::probeInExportedModule()
+{
+ QDir::setCurrent(testDataDir + "/probe-in-exported-module");
+ QCOMPARE(runQbs(QbsRunParameters(QStringList() << QLatin1String("-f")
+ << QLatin1String("probe-in-exported-module.qbs"))), 0);
+ QVERIFY2(m_qbsStdout.contains("found: true"), m_qbsStdout.constData());
+ QEXPECT_FAIL(0, "QBS-955", Abort);
+ QVERIFY2(m_qbsStdout.contains("prop: yes"), m_qbsStdout.constData());
+}
+
void TestBlackbox::productProperties()
{
QDir::setCurrent(testDataDir + "/productproperties");
@@ -1713,6 +2098,44 @@ void TestBlackbox::erroneousFiles()
}
}
+void TestBlackbox::errorInfo()
+{
+ QDir::setCurrent(testDataDir + "/error-info");
+ QCOMPARE(runQbs(), 0);
+
+ QbsRunParameters params;
+ params.expectFailure = true;
+
+ params.arguments = QStringList() << "project.fail1:true";
+ QVERIFY(runQbs(params) != 0);
+ QVERIFY2(m_qbsStderr.contains("project.qbs:24"), m_qbsStderr);
+
+ params.arguments = QStringList() << "project.fail2:true";
+ QVERIFY(runQbs(params) != 0);
+ QVERIFY2(m_qbsStderr.contains("project.qbs:36"), m_qbsStderr);
+
+ params.arguments = QStringList() << "project.fail3:true";
+ QVERIFY(runQbs(params) != 0);
+ QVERIFY2(m_qbsStderr.contains("project.qbs:51"), m_qbsStderr);
+
+ params.arguments = QStringList() << "project.fail4:true";
+ QVERIFY(runQbs(params) != 0);
+ QVERIFY2(m_qbsStderr.contains("project.qbs:66"), m_qbsStderr);
+
+ params.arguments = QStringList() << "project.fail5:true";
+ QVERIFY(runQbs(params) != 0);
+ QVERIFY2(m_qbsStderr.contains("helper.js:4"), m_qbsStderr);
+
+ params.arguments = QStringList() << "project.fail6:true";
+ QVERIFY(runQbs(params) != 0);
+ QVERIFY2(m_qbsStderr.contains("helper.js:8"), m_qbsStderr);
+
+ params.arguments = QStringList() << "project.fail7:true";
+ QVERIFY(runQbs(params) != 0);
+ QVERIFY2(m_qbsStderr.contains("JavaScriptCommand.sourceCode"), m_qbsStderr);
+ QVERIFY2(m_qbsStderr.contains("project.qbs:57"), m_qbsStderr);
+}
+
void TestBlackbox::exportRule()
{
QDir::setCurrent(testDataDir + "/export-rule");
@@ -2087,7 +2510,7 @@ void TestBlackbox::linkerScripts()
QDir::setCurrent(testDataDir + "/linkerscripts");
QCOMPARE(runQbs(QbsRunParameters(QStringList("-qq")
<< ("qbs.installRoot:" + QDir::currentPath()))), 0);
- const QString output = QString::fromLocal8Bit(m_qbsStderr);
+ const QString output = QString::fromLocal8Bit(m_qbsStdout);
QRegExp pattern(".*---(.*)---.*");
QVERIFY2(pattern.exactMatch(output), qPrintable(output));
QCOMPARE(pattern.captureCount(), 1);
@@ -2760,12 +3183,12 @@ void TestBlackbox::assembly()
bool haveMSVC = profile.value("qbs.toolchain").toStringList().contains("msvc");
QDir::setCurrent(testDataDir + "/assembly");
QVERIFY(runQbs() == 0);
- QCOMPARE((bool)m_qbsStdout.contains("assembling testa.s"), haveGcc);
- QCOMPARE((bool)m_qbsStdout.contains("compiling testb.S"), haveGcc);
- QCOMPARE((bool)m_qbsStdout.contains("compiling testc.sx"), haveGcc);
- QCOMPARE((bool)m_qbsStdout.contains("creating libtesta.a"), haveGcc);
- QCOMPARE((bool)m_qbsStdout.contains("creating libtestb.a"), haveGcc);
- QCOMPARE((bool)m_qbsStdout.contains("creating libtestc.a"), haveGcc);
+ QCOMPARE(m_qbsStdout.contains("assembling testa.s"), haveGcc);
+ QCOMPARE(m_qbsStdout.contains("compiling testb.S"), haveGcc);
+ QCOMPARE(m_qbsStdout.contains("compiling testc.sx"), haveGcc);
+ QCOMPARE(m_qbsStdout.contains("creating libtesta.a"), haveGcc);
+ QCOMPARE(m_qbsStdout.contains("creating libtestb.a"), haveGcc);
+ QCOMPARE(m_qbsStdout.contains("creating libtestc.a"), haveGcc);
QCOMPARE(m_qbsStdout.contains("creating testd.lib"), haveMSVC);
}
@@ -2841,6 +3264,76 @@ void TestBlackbox::embedInfoPlist()
QVERIFY(getEmbeddedBinaryPlist(defaultInstallRoot + "/mod.bundle").isEmpty());
}
+void TestBlackbox::enableExceptions()
+{
+ QFETCH(QString, file);
+ QFETCH(bool, enable);
+ QFETCH(bool, expectSuccess);
+
+ QDir::setCurrent(testDataDir + QStringLiteral("/enableExceptions"));
+
+ QbsRunParameters params;
+ params.arguments = QStringList() << "-f" << file << (QStringLiteral("cpp.enableExceptions:")
+ + (enable ? "true" : "false"));
+ params.expectFailure = !expectSuccess;
+ rmDirR(relativeBuildDir());
+ if (!params.expectFailure)
+ QCOMPARE(runQbs(params), 0);
+ else
+ QVERIFY(runQbs(params) != 0);
+}
+
+void TestBlackbox::enableExceptions_data()
+{
+ QTest::addColumn<QString>("file");
+ QTest::addColumn<bool>("enable");
+ QTest::addColumn<bool>("expectSuccess");
+
+ QTest::newRow("no exceptions, enabled") << "none.qbs" << true << true;
+ QTest::newRow("no exceptions, disabled") << "none.qbs" << false << true;
+
+ QTest::newRow("C++ exceptions, enabled") << "exceptions.qbs" << true << true;
+ QTest::newRow("C++ exceptions, disabled") << "exceptions.qbs" << false << false;
+
+ if (HostOsInfo::isOsxHost()) {
+ QTest::newRow("Objective-C exceptions, enabled") << "exceptions-objc.qbs" << true << true;
+ QTest::newRow("Objective-C exceptions in Objective-C++ source, enabled") << "exceptions-objcpp.qbs" << true << true;
+ QTest::newRow("C++ exceptions in Objective-C++ source, enabled") << "exceptions-objcpp-cpp.qbs" << true << true;
+ QTest::newRow("Objective-C, disabled") << "exceptions-objc.qbs" << false << false;
+ QTest::newRow("Objective-C exceptions in Objective-C++ source, disabled") << "exceptions-objcpp.qbs" << false << false;
+ QTest::newRow("C++ exceptions in Objective-C++ source, disabled") << "exceptions-objcpp-cpp.qbs" << false << false;
+ }
+}
+
+void TestBlackbox::enableRtti()
+{
+ QDir::setCurrent(testDataDir + QStringLiteral("/enableRtti"));
+
+ QbsRunParameters params;
+
+ params.arguments = QStringList() << "cpp.enableRtti:true";
+ rmDirR(relativeBuildDir());
+ QCOMPARE(runQbs(params), 0);
+
+ if (HostOsInfo::isOsxHost()) {
+ params.arguments = QStringList() << "cpp.enableRtti:true" << "project.treatAsObjcpp:true";
+ rmDirR(relativeBuildDir());
+ QCOMPARE(runQbs(params), 0);
+ }
+
+ params.expectFailure = true;
+
+ params.arguments = QStringList() << "cpp.enableRtti:false";
+ rmDirR(relativeBuildDir());
+ QVERIFY(runQbs(params) != 0);
+
+ if (HostOsInfo::isOsxHost()) {
+ params.arguments = QStringList() << "cpp.enableRtti:false" << "project.treatAsObjcpp:true";
+ rmDirR(relativeBuildDir());
+ QVERIFY(runQbs(params) != 0);
+ }
+}
+
void TestBlackbox::frameworkStructure()
{
if (!HostOsInfo::isOsxHost())
@@ -2977,9 +3470,11 @@ void TestBlackbox::typescript()
QDir::setCurrent(testDataDir + QLatin1String("/typescript"));
status = runQbs();
- if (p.value("typescript.toolchainInstallPath").toString().isEmpty()
- && status != 0 && m_qbsStderr.contains("toolchainInstallPath")) {
- QSKIP("typescript.toolchainInstallPath not set and automatic detection failed");
+ if (p.value("typescript.toolchainInstallPath").toString().isEmpty() && status != 0) {
+ if (m_qbsStderr.contains("typescript.toolchainInstallPath"))
+ QSKIP("typescript.toolchainInstallPath not set and automatic detection failed");
+ if (m_qbsStderr.contains("nodejs.interpreterFilePath"))
+ QSKIP("nodejs.interpreterFilePath not set and automatic detection failed");
}
QCOMPARE(status, 0);
diff --git a/tests/auto/blackbox/tst_blackbox.h b/tests/auto/blackbox/tst_blackbox.h
index 9ac814960..72dff6088 100644
--- a/tests/auto/blackbox/tst_blackbox.h
+++ b/tests/auto/blackbox/tst_blackbox.h
@@ -103,6 +103,8 @@ private slots:
void assetCatalog_data();
void badInterpreter();
void buildDirectories();
+ void bundleStructure();
+ void bundleStructure_data();
void changedFiles_data();
void changedFiles();
void changeInDisabledProduct();
@@ -113,11 +115,17 @@ private slots:
void concurrentExecutor();
void dependenciesProperty();
void dependencyProfileMismatch();
+ void deploymentTarget();
+ void deploymentTarget_data();
void dynamicMultiplexRule();
void dynamicRuleOutputs();
void embedInfoPlist();
+ void enableExceptions();
+ void enableExceptions_data();
+ void enableRtti();
void erroneousFiles_data();
void erroneousFiles();
+ void errorInfo();
void exportRule();
void fileDependencies();
void frameworkStructure();
@@ -156,6 +164,8 @@ private slots:
void objcArc();
void outputArtifactAutoTagging();
void overrideProjectProperties();
+ void probeProperties();
+ void probeInExportedModule();
void probesInNestedModules();
void productDependenciesByType();
void productProperties();
@@ -169,6 +179,7 @@ private slots:
void radAfterIncompleteBuild();
void recursiveRenaming();
void recursiveWildcards();
+ void referenceErrorInExport();
void reproducibleBuild();
void reproducibleBuild_data();
void ruleConditions();