summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJake Petroules <jake.petroules@theqtcompany.com>2016-03-14 20:59:01 -0700
committerJake Petroules <jake.petroules@qt.io>2016-04-14 12:10:20 +0000
commita235900a7368fd2edf269454016c7577cb674323 (patch)
treead086fd5435f5adb5184385681dd400371216bff
parent60a2203b9cf41f352e418d611d7953f1edddec2e (diff)
downloadqbs-a235900a7368fd2edf269454016c7577cb674323.tar.gz
Implement properties to control use of exception handling.
Task-number: QBS-387 Change-Id: Ia3d8bfe30b0362f1e7b6892cba32ddfb569bdbc4 Reviewed-by: Christian Kandeler <christian.kandeler@theqtcompany.com>
-rw-r--r--doc/reference/modules/android-ndk-module.qdoc6
-rw-r--r--doc/reference/modules/cpp-module.qdoc15
-rw-r--r--share/qbs/modules/Android/ndk/ndk.qbs7
-rw-r--r--share/qbs/modules/cpp/CppModule.qbs3
-rw-r--r--share/qbs/modules/cpp/GenericGCC.qbs20
-rw-r--r--share/qbs/modules/cpp/gcc.js12
-rw-r--r--share/qbs/modules/cpp/msvc.js18
-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.qbs5
-rw-r--r--tests/auto/blackbox/tst_blackbox.cpp41
-rw-r--r--tests/auto/blackbox/tst_blackbox.h2
19 files changed, 157 insertions, 14 deletions
diff --git a/doc/reference/modules/android-ndk-module.qdoc b/doc/reference/modules/android-ndk-module.qdoc
index 0d9e10e52..533e3183a 100644
--- a/doc/reference/modules/android-ndk-module.qdoc
+++ b/doc/reference/modules/android-ndk-module.qdoc
@@ -97,12 +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
diff --git a/doc/reference/modules/cpp-module.qdoc b/doc/reference/modules/cpp-module.qdoc
index 49d681260..25a3a8467 100644
--- a/doc/reference/modules/cpp-module.qdoc
+++ b/doc/reference/modules/cpp-module.qdoc
@@ -329,7 +329,20 @@
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 enableReproducibleBuilds
\li \c{bool}
diff --git a/share/qbs/modules/Android/ndk/ndk.qbs b/share/qbs/modules/Android/ndk/ndk.qbs
index d9ea534d5..030293ebf 100644
--- a/share/qbs/modules/Android/ndk/ndk.qbs
+++ b/share/qbs/modules/Android/ndk/ndk.qbs
@@ -77,7 +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
@@ -206,16 +205,14 @@ Module {
qbs.optimization: cpp.targetAbi === "androideabi" ? "small" : base
+ cpp.enableExceptions: 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
diff --git a/share/qbs/modules/cpp/CppModule.qbs b/share/qbs/modules/cpp/CppModule.qbs
index df10fd1dc..58bac982a 100644
--- a/share/qbs/modules/cpp/CppModule.qbs
+++ b/share/qbs/modules/cpp/CppModule.qbs
@@ -271,6 +271,9 @@ Module {
description: "version of the C++ standard library to use"
}
+ property bool enableExceptions
+ property string exceptionHandlingModel: "default"
+
// 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/GenericGCC.qbs b/share/qbs/modules/cpp/GenericGCC.qbs
index 1424e5297..28f2652bd 100644
--- a/share/qbs/modules/cpp/GenericGCC.qbs
+++ b/share/qbs/modules/cpp/GenericGCC.qbs
@@ -137,6 +137,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,
diff --git a/share/qbs/modules/cpp/gcc.js b/share/qbs/modules/cpp/gcc.js
index 8c1a3160f..0154c8ac4 100644
--- a/share/qbs/modules/cpp/gcc.js
+++ b/share/qbs/modules/cpp/gcc.js
@@ -420,6 +420,18 @@ 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 visibility = ModUtils.moduleProperty(input, 'visibility');
if (!product.type.contains('staticlibrary')
&& !product.moduleProperty("qbs", "toolchain").contains("mingw")) {
diff --git a/share/qbs/modules/cpp/msvc.js b/share/qbs/modules/cpp/msvc.js
index aff810c27..70636aa3b 100644
--- a/share/qbs/modules/cpp/msvc.js
+++ b/share/qbs/modules/cpp/msvc.js
@@ -47,8 +47,22 @@ 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;
+ }
+ }
+
// optimization:
if (optimization === 'small')
args.push('/Os')
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..102e4c261
--- /dev/null
+++ b/tests/auto/blackbox/testdata/enableExceptions/none.qbs
@@ -0,0 +1,5 @@
+import qbs
+
+CppApplication {
+ files: ["emptymain.cpp", "empty.m", "empty.mm"]
+}
diff --git a/tests/auto/blackbox/tst_blackbox.cpp b/tests/auto/blackbox/tst_blackbox.cpp
index 98765d9e1..dc34aeb28 100644
--- a/tests/auto/blackbox/tst_blackbox.cpp
+++ b/tests/auto/blackbox/tst_blackbox.cpp
@@ -3171,6 +3171,47 @@ 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::frameworkStructure()
{
if (!HostOsInfo::isOsxHost())
diff --git a/tests/auto/blackbox/tst_blackbox.h b/tests/auto/blackbox/tst_blackbox.h
index 770ffed5f..0ac257b88 100644
--- a/tests/auto/blackbox/tst_blackbox.h
+++ b/tests/auto/blackbox/tst_blackbox.h
@@ -120,6 +120,8 @@ private slots:
void dynamicMultiplexRule();
void dynamicRuleOutputs();
void embedInfoPlist();
+ void enableExceptions();
+ void enableExceptions_data();
void erroneousFiles_data();
void erroneousFiles();
void exportRule();