diff options
Diffstat (limited to 'tests/auto/blackbox')
654 files changed, 11627 insertions, 1733 deletions
diff --git a/tests/auto/blackbox/CMakeLists.txt b/tests/auto/blackbox/CMakeLists.txt new file mode 100644 index 000000000..88e19acdf --- /dev/null +++ b/tests/auto/blackbox/CMakeLists.txt @@ -0,0 +1,99 @@ +add_qbs_test(blackbox + DEFINES + ${QBS_UNIT_TESTS_DEFINES} + "QBS_VERSION=\"${QBS_VERSION}\"" + SOURCES + ../shared.h + tst_blackboxbase.cpp + tst_blackboxbase.h + tst_blackbox.cpp + tst_blackbox.h + ) + +add_qbs_test(blackbox-android + SOURCES + ../shared.h + tst_blackboxbase.cpp + tst_blackboxbase.h + tst_blackboxandroid.cpp + tst_blackboxandroid.h + ) + +add_qbs_test(blackbox-apple + SOURCES + ../shared.h + tst_blackboxbase.cpp + tst_blackboxbase.h + tst_blackboxapple.cpp + tst_blackboxapple.h + ) + +add_qbs_test(blackbox-baremetal + SOURCES + ../shared.h + tst_blackboxbase.cpp + tst_blackboxbase.h + tst_blackboxbaremetal.cpp + tst_blackboxbaremetal.h + ) + +add_qbs_test(blackbox-clangdb + SOURCES + ../shared.h + tst_blackboxbase.cpp + tst_blackboxbase.h + tst_clangdb.cpp + tst_clangdb.h + ) + +add_qbs_test(blackbox-java + SOURCES + ../shared.h + tst_blackboxbase.cpp + tst_blackboxbase.h + tst_blackboxjava.cpp + tst_blackboxjava.h + ) + +add_qbs_test(blackbox-joblimits + SOURCES + ../shared.h + tst_blackboxbase.cpp + tst_blackboxbase.h + tst_blackboxjoblimits.cpp + ) + +add_qbs_test(blackbox-providers + SOURCES + ../shared.h + tst_blackboxbase.cpp + tst_blackboxbase.h + tst_blackboxproviders.cpp + ) + +add_qbs_test(blackbox-qt + SOURCES + ../shared.h + tst_blackboxbase.cpp + tst_blackboxbase.h + tst_blackboxqt.cpp + tst_blackboxqt.h + ) + +add_qbs_test(blackbox-tutorial + SOURCES + ../shared.h + tst_blackboxbase.cpp + tst_blackboxbase.h + tst_blackboxtutorial.h + tst_blackboxtutorial.cpp + ) + +add_qbs_test(blackbox-windows + SOURCES + ../shared.h + tst_blackboxbase.cpp + tst_blackboxbase.h + tst_blackboxwindows.cpp + tst_blackboxwindows.h + ) diff --git a/tests/auto/blackbox/blackbox-android.pro b/tests/auto/blackbox/blackbox-android.pro deleted file mode 100644 index 7aca99e8d..000000000 --- a/tests/auto/blackbox/blackbox-android.pro +++ /dev/null @@ -1,21 +0,0 @@ -TARGET = tst_blackbox-android - -HEADERS = tst_blackboxandroid.h tst_blackboxbase.h -SOURCES = tst_blackboxandroid.cpp tst_blackboxbase.cpp -OBJECTS_DIR = android -MOC_DIR = $${OBJECTS_DIR}-moc - -include(../auto.pri) - -DATA_DIRS = testdata-android ../find - -for(data_dir, DATA_DIRS) { - files = $$files($$PWD/$$data_dir/*, true) - win32:files ~= s|\\\\|/|g - for(file, files):!exists($$file/*):FILES += $$file -} - -OTHER_FILES += $$FILES - -DISTFILES += \ - testdata/texttemplate/expected-output-one.txt diff --git a/tests/auto/blackbox/blackbox-apple.pro b/tests/auto/blackbox/blackbox-apple.pro deleted file mode 100644 index 1a009e222..000000000 --- a/tests/auto/blackbox/blackbox-apple.pro +++ /dev/null @@ -1,20 +0,0 @@ -TARGET = tst_blackbox-apple - -HEADERS = tst_blackboxapple.h tst_blackboxbase.h -SOURCES = tst_blackboxapple.cpp tst_blackboxbase.cpp -OBJECTS_DIR = apple -MOC_DIR = $${OBJECTS_DIR}-moc - -include(../auto.pri) - -QT += xml - -DATA_DIRS = testdata-apple ../find - -for(data_dir, DATA_DIRS) { - files = $$files($$PWD/$$data_dir/*, true) - win32:files ~= s|\\\\|/|g - for(file, files):!exists($$file/*):FILES += $$file -} - -OTHER_FILES += $$FILES diff --git a/tests/auto/blackbox/blackbox-baremetal.qbs b/tests/auto/blackbox/blackbox-baremetal.qbs new file mode 100644 index 000000000..18ae588fe --- /dev/null +++ b/tests/auto/blackbox/blackbox-baremetal.qbs @@ -0,0 +1,21 @@ +import qbs.Utilities + +QbsAutotest { + testName: "blackbox-baremetal" + Depends { name: "qbs_app" } + Depends { name: "qbs-setup-toolchains" } + Group { + name: "testdata" + prefix: "testdata-baremetal/" + files: ["**/*"] + fileTags: [] + } + files: [ + "../shared.h", + "tst_blackboxbase.cpp", + "tst_blackboxbase.h", + "tst_blackboxbaremetal.cpp", + "tst_blackboxbaremetal.h", + ] + cpp.defines: base.concat(["SRCDIR=" + Utilities.cStringQuote(path)]) +} diff --git a/tests/auto/blackbox/blackbox-clangdb.pro b/tests/auto/blackbox/blackbox-clangdb.pro deleted file mode 100644 index 6e4075175..000000000 --- a/tests/auto/blackbox/blackbox-clangdb.pro +++ /dev/null @@ -1,18 +0,0 @@ -TARGET = tst_blackbox-clangdb - -HEADERS = tst_blackboxbase.h tst_clangdb.h -SOURCES = tst_blackboxbase.cpp tst_clangdb.cpp -OBJECTS_DIR = clangdb -MOC_DIR = $${OBJECTS_DIR}-moc - -include(../auto.pri) - -DATA_DIRS = testdata-clangdb - -for(data_dir, DATA_DIRS) { - files = $$files($$PWD/$$data_dir/*, true) - win32:files ~= s|\\\\|/|g - for(file, files):!exists($$file/*):FILES += $$file -} - -OTHER_FILES += $$FILES diff --git a/tests/auto/blackbox/blackbox-examples.qbs b/tests/auto/blackbox/blackbox-examples.qbs new file mode 100644 index 000000000..77d32636c --- /dev/null +++ b/tests/auto/blackbox/blackbox-examples.qbs @@ -0,0 +1,21 @@ +import qbs.Utilities + +QbsAutotest { + testName: "blackbox-examples" + Depends { name: "qbs_app" } + Depends { name: "qbs-setup-toolchains" } + Group { + name: "testdata" + prefix: "../../../examples/" + files: ["**/*"] + fileTags: [] + } + files: [ + "../shared.h", + "tst_blackboxexamples.cpp", + "tst_blackboxexamples.h", + "tst_blackboxbase.cpp", + "tst_blackboxbase.h", + ] + cpp.defines: base.concat(["SRCDIR=" + Utilities.cStringQuote(path)]) +} diff --git a/tests/auto/blackbox/blackbox-java.pro b/tests/auto/blackbox/blackbox-java.pro deleted file mode 100644 index d297d9e09..000000000 --- a/tests/auto/blackbox/blackbox-java.pro +++ /dev/null @@ -1,18 +0,0 @@ -TARGET = tst_blackbox-java - -HEADERS = tst_blackboxjava.h tst_blackboxbase.h -SOURCES = tst_blackboxjava.cpp tst_blackboxbase.cpp -OBJECTS_DIR = java -MOC_DIR = $${OBJECTS_DIR}-moc - -include(../auto.pri) - -DATA_DIRS = testdata-java ../find - -for(data_dir, DATA_DIRS) { - files = $$files($$PWD/$$data_dir/*, true) - win32:files ~= s|\\\\|/|g - for(file, files):!exists($$file/*):FILES += $$file -} - -OTHER_FILES += $$FILES diff --git a/tests/auto/blackbox/blackbox-joblimits.pro b/tests/auto/blackbox/blackbox-joblimits.pro deleted file mode 100644 index 85413473e..000000000 --- a/tests/auto/blackbox/blackbox-joblimits.pro +++ /dev/null @@ -1,18 +0,0 @@ -TARGET = tst_blackbox-joblimits - -HEADERS = tst_blackboxbase.h -SOURCES = tst_blackboxjoblimits.cpp tst_blackboxbase.cpp -OBJECTS_DIR = joblimits -MOC_DIR = $${OBJECTS_DIR}-moc - -include(../auto.pri) - -DATA_DIRS = testdata-joblimits ../find - -for(data_dir, DATA_DIRS) { - files = $$files($$PWD/$$data_dir/*, true) - win32:files ~= s|\\\\|/|g - for(file, files):!exists($$file/*):FILES += $$file -} - -OTHER_FILES += $$FILES diff --git a/tests/auto/blackbox/blackbox-providers.qbs b/tests/auto/blackbox/blackbox-providers.qbs new file mode 100644 index 000000000..95ebaa423 --- /dev/null +++ b/tests/auto/blackbox/blackbox-providers.qbs @@ -0,0 +1,21 @@ +import qbs.Utilities + +QbsAutotest { + testName: "blackbox-providers" + Depends { name: "qbs_app" } + Depends { name: "qbs-setup-toolchains" } + Group { + name: "testdata" + prefix: "testdata-providers/" + files: ["**/*"] + fileTags: [] + } + files: [ + "../shared.h", + "tst_blackboxbase.cpp", + "tst_blackboxbase.h", + "tst_blackboxproviders.cpp", + "tst_blackboxproviders.h", + ] + cpp.defines: base.concat(["SRCDIR=" + Utilities.cStringQuote(path)]) +} diff --git a/tests/auto/blackbox/blackbox-qt.pro b/tests/auto/blackbox/blackbox-qt.pro deleted file mode 100644 index e17a04a7e..000000000 --- a/tests/auto/blackbox/blackbox-qt.pro +++ /dev/null @@ -1,18 +0,0 @@ -TARGET = tst_blackbox-qt - -HEADERS = tst_blackboxqt.h tst_blackboxbase.h -SOURCES = tst_blackboxqt.cpp tst_blackboxbase.cpp -OBJECTS_DIR = qt -MOC_DIR = $${OBJECTS_DIR}-moc - -include(../auto.pri) - -DATA_DIRS = testdata-qt ../find - -for(data_dir, DATA_DIRS) { - files = $$files($$PWD/$$data_dir/*, true) - win32:files ~= s|\\\\|/|g - for(file, files):!exists($$file/*):FILES += $$file -} - -OTHER_FILES += $$FILES diff --git a/tests/auto/blackbox/blackbox-tutorial.qbs b/tests/auto/blackbox/blackbox-tutorial.qbs new file mode 100644 index 000000000..174821ffa --- /dev/null +++ b/tests/auto/blackbox/blackbox-tutorial.qbs @@ -0,0 +1,21 @@ +import qbs.Utilities + +QbsAutotest { + testName: "blackbox-tutorial" + Depends { name: "qbs_app" } + Depends { name: "qbs-setup-toolchains" } + Group { + name: "testdata" + prefix: "../../../tutorial/" + files: ["**/*"] + fileTags: [] + } + files: [ + "../shared.h", + "tst_blackboxtutorial.cpp", + "tst_blackboxtutorial.h", + "tst_blackboxbase.cpp", + "tst_blackboxbase.h", + ] + cpp.defines: base.concat(["SRCDIR=" + Utilities.cStringQuote(path)]) +} diff --git a/tests/auto/blackbox/blackbox-windows.qbs b/tests/auto/blackbox/blackbox-windows.qbs new file mode 100644 index 000000000..e32421e3b --- /dev/null +++ b/tests/auto/blackbox/blackbox-windows.qbs @@ -0,0 +1,21 @@ +import qbs.Utilities + +QbsAutotest { + testName: "blackbox-windows" + Depends { name: "qbs_app" } + Depends { name: "qbs-setup-toolchains" } + Group { + name: "testdata" + prefix: "testdata-windows/" + files: ["**/*"] + fileTags: [] + } + files: [ + "../shared.h", + "tst_blackboxbase.cpp", + "tst_blackboxbase.h", + "tst_blackboxwindows.cpp", + "tst_blackboxwindows.h", + ] + cpp.defines: base.concat(["SRCDIR=" + Utilities.cStringQuote(path)]) +} diff --git a/tests/auto/blackbox/blackbox.pro b/tests/auto/blackbox/blackbox.pro deleted file mode 100644 index 42848d077..000000000 --- a/tests/auto/blackbox/blackbox.pro +++ /dev/null @@ -1,21 +0,0 @@ -TARGET = tst_blackbox - -HEADERS = tst_blackbox.h tst_blackboxbase.h -SOURCES = tst_blackbox.cpp tst_blackboxbase.cpp -OBJECTS_DIR = generic -MOC_DIR = $${OBJECTS_DIR}-moc -qbs_enable_unit_tests:DEFINES += QBS_ENABLE_UNIT_TESTS - -include(../auto.pri) - -QT += xml - -DATA_DIRS = testdata ../find - -for(data_dir, DATA_DIRS) { - files = $$files($$PWD/$$data_dir/*, true) - win32:files ~= s|\\\\|/|g - for(file, files):!exists($$file/*):FILES += $$file -} - -OTHER_FILES += $$FILES diff --git a/tests/auto/blackbox/blackbox.qbs b/tests/auto/blackbox/blackbox.qbs index 3f0ff959a..ac6bf750e 100644 --- a/tests/auto/blackbox/blackbox.qbs +++ b/tests/auto/blackbox/blackbox.qbs @@ -25,4 +25,5 @@ QbsAutotest { ] cpp.defines: base.concat(["SRCDIR=" + Utilities.cStringQuote(path)]) .concat(qbsbuildconfig.enableUnitTests ? ["QBS_ENABLE_UNIT_TESTS"] : []) + .concat("QBS_VERSION=" + Utilities.cStringQuote(qbsversion.version)) } diff --git a/tests/auto/blackbox/find/find-android.qbs b/tests/auto/blackbox/find/find-android.qbs index 26dedc60f..1cde0ed84 100644 --- a/tests/auto/blackbox/find/find-android.qbs +++ b/tests/auto/blackbox/find/find-android.qbs @@ -3,12 +3,23 @@ import qbs.TextFile Product { property string packageName: "" qbs.targetPlatform: "android" + multiplexByQbsProperties: ["architectures"] + + Properties { + condition: qbs.architectures && qbs.architectures.length > 1 + aggregate: true + multiplexedType: "json_arch" + } Depends { name: "Android.sdk"; required: false } Depends { name: "Android.ndk"; required: false } type: ["json"] + Rule { multiplex: true + property stringList inputTags: "json_arch" + inputsFromDependencies: inputTags + inputs: product.aggregate ? [] : inputTags Artifact { filePath: ["android.json"] fileTags: ["json"] @@ -18,17 +29,51 @@ Product { cmd.description = output.filePath; cmd.sourceCode = function() { var tools = {}; + + for (var i in inputs["json_arch"]) { + var tf = new TextFile(inputs["json_arch"][i].filePath, TextFile.ReadOnly); + var json = JSON.parse(tf.readAll()); + tools["ndk"] = json["ndk"]; + tools["ndk-samples"] = json["ndk-samples"]; + tf.close(); + } + if (product.moduleProperty("Android.sdk", "present")) { tools["sdk"] = product.moduleProperty("Android.sdk", "sdkDir"); tools["sdk-build-tools-dx"] = product.Android.sdk.dxFilePath; + tools["sdk-build-tools-d8"] = product.Android.sdk.d8FilePath; } + if (product.java && product.java.present) + tools["jar"] = product.java.jarFilePath; + + var tf; + try { + tf = new TextFile(output.filePath, TextFile.WriteOnly); + tf.writeLine(JSON.stringify(tools, undefined, 4)); + } finally { + if (tf) + tf.close(); + } + }; + return cmd; + } + } + Rule { + multiplex: true + Artifact { + filePath: ["android_arch.json"] + fileTags: ["json_arch"] + } + prepare: { + var cmd = new JavaScriptCommand(); + cmd.description = output.filePath; + cmd.sourceCode = function() { + var tools = {}; if (product.moduleProperty("Android.ndk", "present")) { tools["ndk"] = product.moduleProperty("Android.ndk", "ndkDir"); tools["ndk-samples"] = product.Android.ndk.ndkSamplesDir; } - if (product.java && product.java.present) - tools["jar"] = product.java.jarFilePath; var tf; try { @@ -43,3 +88,4 @@ Product { } } } + diff --git a/tests/auto/blackbox/find/find-xcode.qbs b/tests/auto/blackbox/find/find-xcode.qbs index bb6ee9718..15c2aa17e 100644 --- a/tests/auto/blackbox/find/find-xcode.qbs +++ b/tests/auto/blackbox/find/find-xcode.qbs @@ -14,7 +14,9 @@ Product { cmd.description = output.filePath; cmd.sourceCode = function() { var tools = {}; - if (product.moduleProperty("xcode", "present")) { + var present = product.moduleProperty("xcode", "present"); + tools["present"] = !!present; + if (present) { var keys = [ "developerPath", "version" diff --git a/tests/auto/blackbox/testdata-android/aidl/AndroidManifest.xml b/tests/auto/blackbox/testdata-android/aidl/AndroidManifest.xml index e8a950847..1d27681ac 100644 --- a/tests/auto/blackbox/testdata-android/aidl/AndroidManifest.xml +++ b/tests/auto/blackbox/testdata-android/aidl/AndroidManifest.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" + android:versionName="1.0" android:versionCode="1" package="io.qbs.aidltest"> <application android:label="AidlTest"> <activity android:name="MainActivity"> diff --git a/tests/auto/blackbox/testdata-android/minimal-native/minimal-native.qbs b/tests/auto/blackbox/testdata-android/minimal-native/minimal-native.qbs index 570152707..7231f7e62 100644 --- a/tests/auto/blackbox/testdata-android/minimal-native/minimal-native.qbs +++ b/tests/auto/blackbox/testdata-android/minimal-native/minimal-native.qbs @@ -1,7 +1,7 @@ CppApplication { name: "minimalnative" qbs.buildVariant: "release" - Properties { condition: qbs.toolchain.contains("clang"); Android.ndk.appStl: "c++_shared" } + Properties { condition: qbs.toolchain.includes("clang"); Android.ndk.appStl: "c++_shared" } Android.sdk.packageName: "my.minimalnative" Android.sdk.apkBaseName: name Android.ndk.appStl: "stlport_shared" diff --git a/tests/auto/blackbox/testdata-android/minimal-native/src/main/AndroidManifest.xml b/tests/auto/blackbox/testdata-android/minimal-native/src/main/AndroidManifest.xml index 575e95e8d..f61dc9850 100644 --- a/tests/auto/blackbox/testdata-android/minimal-native/src/main/AndroidManifest.xml +++ b/tests/auto/blackbox/testdata-android/minimal-native/src/main/AndroidManifest.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" + android:versionName="1.0" android:versionCode="1" package="somedefault"> <application android:label="MinimalNative"> <activity android:name="MainActivity"> diff --git a/tests/auto/blackbox/testdata-android/minimal-native/src/main/native/native.c b/tests/auto/blackbox/testdata-android/minimal-native/src/main/native/native.c index 6b625858b..f49b4f90f 100644 --- a/tests/auto/blackbox/testdata-android/minimal-native/src/main/native/native.c +++ b/tests/auto/blackbox/testdata-android/minimal-native/src/main/native/native.c @@ -4,5 +4,6 @@ jstring Java_minimalnative_MinimalNative_stringFromNative(JNIEnv* env, jobject thiz) { + (void)thiz; return (*env)->NewStringUTF(env, "This message comes from native code."); } diff --git a/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/product1.qbs b/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/product1.qbs index c4a78a30b..c7b9b3de2 100644 --- a/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/product1.qbs +++ b/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/product1.qbs @@ -5,9 +5,12 @@ Project { name: "p1lib1" files: ["src/main/jni/lib1.cpp"] qbs.targetPlatform: "android" - Properties { condition: qbs.toolchain.contains("clang"); Android.ndk.appStl: "c++_shared" } + Properties { condition: qbs.toolchain.includes("clang"); Android.ndk.appStl: "c++_shared" } Android.ndk.appStl: "stlport_shared" - qbs.architectures: !qbs.architecture ? ["armv7a", "x86"] : undefined + Properties { + qbs.architectures: !qbs.architecture ? ["armv7a", "x86"] : undefined + overrideListProperties: true + } cpp.useRPaths: false } @@ -17,7 +20,7 @@ Project { name: "p1lib2" files: ["src/main/jni/lib2.cpp"] qbs.targetPlatform: "android" - Properties { condition: qbs.toolchain.contains("clang"); Android.ndk.appStl: "c++_shared" } + Properties { condition: qbs.toolchain.includes("clang"); Android.ndk.appStl: "c++_shared" } Android.ndk.appStl: "stlport_shared" cpp.useRPaths: false } diff --git a/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/AndroidManifest.xml b/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/AndroidManifest.xml index 289969409..272fe55de 100644 --- a/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/AndroidManifest.xml +++ b/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/AndroidManifest.xml @@ -1,6 +1,6 @@ <?xml version="1.0"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="io.qt.dummy1" android:versionCode="1" android:versionName="1.0"> - <uses-sdk android:minSdkVersion="11" android:targetSdkVersion="19"/> + <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/> <uses-feature android:glEsVersion="0x00020000"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <application android:allowBackup="true" android:hasCode="true"> diff --git a/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/product2.qbs b/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/product2.qbs index 9be70dcda..f880a576d 100644 --- a/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/product2.qbs +++ b/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/product2.qbs @@ -13,7 +13,7 @@ Project { name: "p2lib2" files: ["src/main/jni/lib2.cpp"] qbs.targetPlatform: "android" - Properties { condition: qbs.toolchain.contains("clang"); Android.ndk.appStl: "c++_shared" } + Properties { condition: qbs.toolchain.includes("clang"); Android.ndk.appStl: "c++_shared" } Android.ndk.appStl: "stlport_shared" } diff --git a/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/AndroidManifest.xml b/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/AndroidManifest.xml index ef0fbe54f..871aadbe6 100644 --- a/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/AndroidManifest.xml +++ b/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/AndroidManifest.xml @@ -1,6 +1,6 @@ <?xml version="1.0"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="io.qt.dummy2" android:versionCode="1" android:versionName="1.0"> - <uses-sdk android:minSdkVersion="11" android:targetSdkVersion="19"/> + <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/> <uses-feature android:glEsVersion="0x00020000"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <application android:allowBackup="true" android:hasCode="true"> diff --git a/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/multiple-libs-per-apk.qbs b/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/multiple-libs-per-apk.qbs index 8b9ded211..a5e193905 100644 --- a/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/multiple-libs-per-apk.qbs +++ b/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/multiple-libs-per-apk.qbs @@ -5,7 +5,7 @@ Project { name: "lib1" files: ["src/main/jni/lib1.cpp"] qbs.targetPlatform: "android" - Properties { condition: qbs.toolchain.contains("clang"); Android.ndk.appStl: "c++_shared" } + Properties { condition: qbs.toolchain.includes("clang"); Android.ndk.appStl: "c++_shared" } Android.ndk.appStl: "stlport_shared" cpp.useRPaths: false } @@ -16,7 +16,7 @@ Project { name: "lib2" files: ["src/main/jni/lib2.cpp"] qbs.targetPlatform: "android" - Properties { condition: qbs.toolchain.contains("clang"); Android.ndk.appStl: "c++_shared" } + Properties { condition: qbs.toolchain.includes("clang"); Android.ndk.appStl: "c++_shared" } Android.ndk.appStl: "stlport_shared" cpp.useRPaths: false } diff --git a/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/AndroidManifest.xml b/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/AndroidManifest.xml index 6694afc18..f184a8f1f 100644 --- a/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/AndroidManifest.xml +++ b/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/AndroidManifest.xml @@ -1,6 +1,6 @@ <?xml version="1.0"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="io.qt.dummy" android:versionCode="1" android:versionName="1.0"> - <uses-sdk android:minSdkVersion="11" android:targetSdkVersion="19"/> + <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/> <uses-feature android:glEsVersion="0x00020000"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <application android:allowBackup="true" android:hasCode="true"> diff --git a/tests/auto/blackbox/testdata-android/qml-app/qml-app.qbs b/tests/auto/blackbox/testdata-android/qml-app/qml-app.qbs index e91a14902..5760fa4f0 100644 --- a/tests/auto/blackbox/testdata-android/qml-app/qml-app.qbs +++ b/tests/auto/blackbox/testdata-android/qml-app/qml-app.qbs @@ -3,12 +3,12 @@ QtApplication { Depends { name: "Qt.quick" } Depends { name: "Qt.android_support" } Properties { - condition: qbs.targetOS.contains("android") + condition: qbs.targetOS.includes("android") Qt.android_support.extraPrefixDirs: path } Android.sdk.packageName: "my.qmlapp" Android.sdk.apkBaseName: name - property stringList qmlImportPaths: path + Qt.android_support.qmlImportPaths: path files: [ "main.cpp", "qml.qrc", diff --git a/tests/auto/blackbox/testdata-android/qml-app/src/main/AndroidManifest.xml b/tests/auto/blackbox/testdata-android/qml-app/src/main/AndroidManifest.xml index 066ec0a63..c8237c639 100644 --- a/tests/auto/blackbox/testdata-android/qml-app/src/main/AndroidManifest.xml +++ b/tests/auto/blackbox/testdata-android/qml-app/src/main/AndroidManifest.xml @@ -16,7 +16,6 @@ <!-- Application arguments --> <meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/> - <meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/> <meta-data android:name="android.app.repository" android:value="default"/> <meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/> <meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/> @@ -31,8 +30,6 @@ <meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/> <meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/> <!-- Messages maps --> - <meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/> - <meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/> <meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/> <!-- Messages maps --> @@ -67,7 +64,7 @@ </application> - <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="16"/> + <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/> <supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/> <!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application. diff --git a/tests/auto/blackbox/testdata-android/qt-app/MainWindow.cpp b/tests/auto/blackbox/testdata-android/qt-app/MainWindow.cpp new file mode 100644 index 000000000..b2e08c83e --- /dev/null +++ b/tests/auto/blackbox/testdata-android/qt-app/MainWindow.cpp @@ -0,0 +1,11 @@ +#include "MainWindow.h" + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) +{ +} + +MainWindow::~MainWindow() +{ +} + diff --git a/tests/auto/blackbox/testdata-android/qt-app/MainWindow.h b/tests/auto/blackbox/testdata-android/qt-app/MainWindow.h new file mode 100644 index 000000000..ace53a4a0 --- /dev/null +++ b/tests/auto/blackbox/testdata-android/qt-app/MainWindow.h @@ -0,0 +1,15 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include <QMainWindow> + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(QWidget *parent = nullptr); + ~MainWindow(); +}; + +#endif // MAINWINDOW_H diff --git a/tests/auto/blackbox/testdata-android/qt-app/Test.java b/tests/auto/blackbox/testdata-android/qt-app/Test.java new file mode 100644 index 000000000..c57486d56 --- /dev/null +++ b/tests/auto/blackbox/testdata-android/qt-app/Test.java @@ -0,0 +1,54 @@ +package org.qbs.example; + +import org.qtproject.qt5.android.bindings.QtActivity; +import android.os.*; +import android.content.*; +import android.app.*; +import android.util.Log; + +import java.lang.String; +import android.content.Intent; + +import org.qbs.example.*; + + +public class Test extends QtActivity +{ + public static native void testFunc(String test); + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Log.d("qbs", "onCreate Test"); + Intent theIntent = getIntent(); + if (theIntent != null) { + String theAction = theIntent.getAction(); + if (theAction != null) { + Log.d("qbs onCreate ", theAction); + } + } + } + + @Override + public void onDestroy() { + Log.d("qbs", "onDestroy"); + System.exit(0); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + Log.d("qbs onActivityResult", "requestCode: "+requestCode); + if (resultCode == RESULT_OK) { + Log.d("qbs onActivityResult - resultCode: ", "SUCCESS"); + } else { + Log.d("qbs onActivityResult - resultCode: ", "CANCEL"); + } + } + + @Override + public void onNewIntent(Intent intent) { + Log.d("qbs", "onNewIntent"); + super.onNewIntent(intent); + setIntent(intent); + } +} diff --git a/tests/auto/blackbox/testdata-android/qt-app/TestQt6.java b/tests/auto/blackbox/testdata-android/qt-app/TestQt6.java new file mode 100644 index 000000000..239507122 --- /dev/null +++ b/tests/auto/blackbox/testdata-android/qt-app/TestQt6.java @@ -0,0 +1,54 @@ +package org.qbs.example; + +import org.qtproject.qt.android.bindings.QtActivity; +import android.os.*; +import android.content.*; +import android.app.*; +import android.util.Log; + +import java.lang.String; +import android.content.Intent; + +import org.qbs.example.*; + + +public class TestQt6 extends QtActivity +{ + public static native void testFunc(String test); + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Log.d("qbs", "onCreate Test"); + Intent theIntent = getIntent(); + if (theIntent != null) { + String theAction = theIntent.getAction(); + if (theAction != null) { + Log.d("qbs onCreate ", theAction); + } + } + } + + @Override + public void onDestroy() { + Log.d("qbs", "onDestroy"); + System.exit(0); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + Log.d("qbs onActivityResult", "requestCode: "+requestCode); + if (resultCode == RESULT_OK) { + Log.d("qbs onActivityResult - resultCode: ", "SUCCESS"); + } else { + Log.d("qbs onActivityResult - resultCode: ", "CANCEL"); + } + } + + @Override + public void onNewIntent(Intent intent) { + Log.d("qbs", "onNewIntent"); + super.onNewIntent(intent); + setIntent(intent); + } +} diff --git a/tests/auto/blackbox/testdata-android/qt-app/main.cpp b/tests/auto/blackbox/testdata-android/qt-app/main.cpp new file mode 100644 index 000000000..0a0916fca --- /dev/null +++ b/tests/auto/blackbox/testdata-android/qt-app/main.cpp @@ -0,0 +1,11 @@ +#include "MainWindow.h" + +#include <QApplication> + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; + w.show(); + return a.exec(); +} diff --git a/tests/auto/blackbox/testdata-android/qt-app/qt-app.qbs b/tests/auto/blackbox/testdata-android/qt-app/qt-app.qbs new file mode 100644 index 000000000..04dcbf403 --- /dev/null +++ b/tests/auto/blackbox/testdata-android/qt-app/qt-app.qbs @@ -0,0 +1,27 @@ +Project { + QtGuiApplication { + Depends { name: "Lib" } + files: ["main.cpp", "MainWindow.cpp", "MainWindow.h" ] + Group { + condition: Qt.core.versionMajor == 5 + files: ["Test.java"] + } + Group { + condition: Qt.core.versionMajor == 6 + files: ["TestQt6.java"] + } + + Android.sdk.packageName: "my.qtapp" + Android.sdk.apkBaseName: name + Depends { name: "Qt"; submodules: ["core", "widgets"] } + } + + StaticLibrary { + name: "Lib" + Export { + Depends { + name: "Qt.android_support"; + } + } + } +} diff --git a/tests/auto/blackbox/testdata-android/qt-app/test.keystore b/tests/auto/blackbox/testdata-android/qt-app/test.keystore Binary files differnew file mode 100644 index 000000000..5713d10d2 --- /dev/null +++ b/tests/auto/blackbox/testdata-android/qt-app/test.keystore diff --git a/tests/auto/blackbox/testdata-android/teapot/teapot.qbs b/tests/auto/blackbox/testdata-android/teapot/teapot.qbs index 2b5cb8aba..0b1dead6e 100644 --- a/tests/auto/blackbox/testdata-android/teapot/teapot.qbs +++ b/tests/auto/blackbox/testdata-android/teapot/teapot.qbs @@ -51,7 +51,7 @@ Project { files: ["*.cpp", "*.h"].concat( !File.exists(ndkHelperProbe.dir + "/gl3stub.cpp") ? ["gl3stub.c"] : []) } - Properties { condition: qbs.toolchain.contains("clang"); Android.ndk.appStl: "c++_shared" } + Properties { condition: qbs.toolchain.includes("clang"); Android.ndk.appStl: "c++_shared" } Android.ndk.appStl: "gnustl_shared" cpp.cxxLanguageVersion: "c++11" @@ -133,10 +133,11 @@ Project { FileTagger { patterns: ["*.inl"]; fileTags: ["hpp"] } + version: "2.0" Android.sdk.apkBaseName: name Android.sdk.packageName: "com.sample.teapot" Android.sdk.sourceSetDir: teapotProbe.dir - Properties { condition: qbs.toolchain.contains("clang"); Android.ndk.appStl: "c++_shared" } + Properties { condition: qbs.toolchain.includes("clang"); Android.ndk.appStl: "c++_shared" } Android.ndk.appStl: "gnustl_shared" cpp.cxxLanguageVersion: "c++11" cpp.dynamicLibraries: ["log", "android", "EGL", "GLESv2"] diff --git a/tests/auto/blackbox/testdata-apple/aggregateDependencyLinking/aggregateDependencyLinking.qbs b/tests/auto/blackbox/testdata-apple/aggregateDependencyLinking/aggregateDependencyLinking.qbs index e7c8867bd..6f57c1e44 100644 --- a/tests/auto/blackbox/testdata-apple/aggregateDependencyLinking/aggregateDependencyLinking.qbs +++ b/tests/auto/blackbox/testdata-apple/aggregateDependencyLinking/aggregateDependencyLinking.qbs @@ -1,5 +1,3 @@ -import qbs - Project { minimumQbsVersion: "1.8" @@ -9,11 +7,27 @@ Project { Depends { name: "cpp" } Depends { name: "bundle" } + property bool hasX86Mac: true // cannot use xcode.version in qbs.architectures + property bool hasArmMac: false bundle.isBundle: false // This will generate 2 multiplex configs and an aggregate. - qbs.architectures: ["x86", "x86_64"] + qbs.architectures: { + if (qbs.targetPlatform === "macos") { + if (hasX86Mac) + return ["x86_64", "x86"]; + else if (hasArmMac) + return ["arm64", "x86_64"]; + } else if (qbs.targetPlatform === "ios") { + return ["arm64", "armv7a"]; + } + console.info("Cannot build fat binaries for this target platform (" + + qbs.targetPlatform + ")"); + return original; + } + qbs.buildVariant: "debug" + cpp.minimumMacosVersion: "10.8" } CppApplication { @@ -21,15 +35,22 @@ Project { files: ["app.c"] // This should link only against the aggregate static library, and not against - // the {debug, x86_64} variant, or worse - against both the single arch variant + // the {debug, arm64} variant, or worse - against both the single arch variant // and the lipo-ed one. Depends { name: "multi_arch_lib" } Depends { name: "bundle" } bundle.isBundle: false - qbs.architecture: "x86_64" + qbs.architecture: { + if (qbs.targetPlatform === "macos") + return "x86_64"; + else if (qbs.targetPlatform === "ios") + return "arm64"; + return original; + } qbs.buildVariant: "debug" + cpp.minimumMacosVersion: "10.8" multiplexByQbsProperties: [] } } diff --git a/tests/auto/blackbox/testdata-apple/apple-multiconfig/apple-multiconfig.qbs b/tests/auto/blackbox/testdata-apple/apple-multiconfig/apple-multiconfig.qbs index 438624f70..5615722d5 100644 --- a/tests/auto/blackbox/testdata-apple/apple-multiconfig/apple-multiconfig.qbs +++ b/tests/auto/blackbox/testdata-apple/apple-multiconfig/apple-multiconfig.qbs @@ -1,23 +1,32 @@ import qbs.Utilities +import "../multiarch-helpers.js" as Helpers + Project { minimumQbsVersion: "1.8" - property bool enableX86 + condition: xcodeVersion + property string xcodeVersion CppApplication { Depends { name: "singlelib" } Depends { name: "bundle" } + property bool isShallow: { + console.info("isShallow: " + bundle.isShallow); + return bundle.isShallow; + } name: "singleapp" targetName: "singleapp" files: ["app.c"] cpp.rpaths: [cpp.rpathOrigin + "/../../../"] cpp.minimumMacosVersion: "10.6" + cpp.minimumIosVersion: "8.0" // Turn off multiplexing aggregate: false multiplexByQbsProperties: [] install: true + installDebugInformation: false installDir: "" } @@ -29,13 +38,15 @@ Project { files: ["app.c"] cpp.rpaths: [cpp.rpathOrigin + "/../../../"] cpp.minimumMacosVersion: "10.6" + cpp.minimumIosVersion: "8.0" // Force aggregation when not needed aggregate: true - qbs.architectures: ["x86_64"] + qbs.architectures: [Helpers.getNewArch(qbs)] qbs.buildVariants: ["release"] install: true + installDebugInformation: false installDir: "" } @@ -45,7 +56,7 @@ Project { name: "singlelib" targetName: "singlelib" files: ["lib.c"] - cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined + cpp.sonamePrefix: qbs.targetOS.includes("darwin") ? "@rpath" : undefined cpp.defines: ["VARIANT=" + Utilities.cStringQuote(qbs.buildVariant)] // Turn off multiplexing @@ -53,6 +64,7 @@ Project { multiplexByQbsProperties: [] install: true + installDebugInformation: false installDir: "" } @@ -64,8 +76,10 @@ Project { files: ["app.c"] cpp.rpaths: [cpp.rpathOrigin + "/../../../"] cpp.minimumMacosVersion: "10.6" + cpp.minimumIosVersion: "8.0" install: true + installDebugInformation: false installDir: "" } @@ -77,13 +91,16 @@ Project { files: ["app.c"] cpp.rpaths: [cpp.rpathOrigin + "/../../../"] cpp.minimumMacosVersion: "10.6" - qbs.architectures: project.enableX86 ? ["x86", "x86_64"] : ["x86_64"] - qbs.architecture: "x86_64" - multiplexByQbsProperties: project.enableX86 ? ["architectures", "buildVariants"] - : ["buildVariants"] + cpp.minimumIosVersion: "8.0" + qbs.architectures: Helpers.getArchitectures(qbs, project.xcodeVersion) + qbs.architecture: Helpers.getNewArch(qbs) + multiplexByQbsProperties: Helpers.enableOldArch(qbs, project.xcodeVersion) + ? ["architectures", "buildVariants"] + : ["buildVariants"] qbs.buildVariants: "debug" install: true + installDebugInformation: false installDir: "" } @@ -95,10 +112,12 @@ Project { files: ["app.c"] cpp.rpaths: [cpp.rpathOrigin + "/../../../"] cpp.minimumMacosVersion: "10.6" - qbs.architectures: project.enableX86 ? ["x86", "x86_64"] : ["x86_64"] - qbs.buildVariants: ["debug", "profile"] + cpp.minimumIosVersion: "8.0" + qbs.architectures: Helpers.getArchitectures(qbs, project.xcodeVersion) + qbs.buildVariants: ["debug", "profiling"] install: true + installDebugInformation: false installDir: "" } @@ -108,12 +127,14 @@ Project { name: "multilib" targetName: "multilib" files: ["lib.c"] - cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined + cpp.minimumIosVersion: "8.0" + cpp.sonamePrefix: qbs.targetOS.includes("darwin") ? "@rpath" : undefined cpp.defines: ["VARIANT=" + Utilities.cStringQuote(qbs.buildVariant)] - qbs.architectures: project.enableX86 ? ["x86", "x86_64"] : ["x86_64"] - qbs.buildVariants: ["release", "debug", "profile"] + qbs.architectures: Helpers.getArchitectures(qbs, project.xcodeVersion) + qbs.buildVariants: ["release", "debug", "profiling"] install: true + installDebugInformation: false installDir: "" } @@ -123,12 +144,14 @@ Project { name: "multilib-no-release" targetName: "multilib-no-release" files: ["lib.c"] - cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined + cpp.minimumIosVersion: "8.0" + cpp.sonamePrefix: qbs.targetOS.includes("darwin") ? "@rpath" : undefined cpp.defines: ["VARIANT=" + Utilities.cStringQuote(qbs.buildVariant)] - qbs.architectures: project.enableX86 ? ["x86", "x86_64"] : ["x86_64"] - qbs.buildVariants: ["debug", "profile"] + qbs.architectures: Helpers.getArchitectures(qbs, project.xcodeVersion) + qbs.buildVariants: ["debug", "profiling"] install: true + installDebugInformation: false installDir: "" } @@ -138,11 +161,13 @@ Project { Depends { name: "multilibB" } name: "multilibA" files: ["lib.c"] + cpp.minimumIosVersion: "8.0" cpp.sonamePrefix: "@rpath" cpp.defines: ["VARIANT=" + Utilities.cStringQuote(qbs.buildVariant)] - qbs.architectures: project.enableX86 ? ["x86", "x86_64"] : ["x86_64"] - qbs.buildVariants: ["debug", "profile"] + qbs.architectures: Helpers.getArchitectures(qbs, project.xcodeVersion) + qbs.buildVariants: ["debug", "profiling"] install: true + installDebugInformation: false installDir: "" } DynamicLibrary { @@ -150,11 +175,13 @@ Project { Depends { name: "bundle" } name: "multilibB" files: ["lib.c"] + cpp.minimumIosVersion: "8.0" cpp.sonamePrefix: "@rpath" cpp.defines: ["VARIANT=" + Utilities.cStringQuote(qbs.buildVariant)] - qbs.architectures: project.enableX86 ? ["x86", "x86_64"] : ["x86_64"] - qbs.buildVariants: ["debug", "profile"] + qbs.architectures: Helpers.getArchitectures(qbs, project.xcodeVersion) + qbs.buildVariants: ["debug", "profiling"] install: true + installDebugInformation: false installDir: "" } } diff --git a/tests/auto/blackbox/testdata-apple/bundle-structure/bundle-structure.qbs b/tests/auto/blackbox/testdata-apple/bundle-structure/bundle-structure.qbs index 8cf031e33..33ac58967 100644 --- a/tests/auto/blackbox/testdata-apple/bundle-structure/bundle-structure.qbs +++ b/tests/auto/blackbox/testdata-apple/bundle-structure/bundle-structure.qbs @@ -3,12 +3,21 @@ Project { property stringList buildableProducts: ["A", "B", "C", "D", "E", "F", "G"] + Product { + Depends { name: "bundle" } + condition: { + console.info("bundle.isShallow: " + bundle.isShallow); + console.info("qbs.targetOS: " + qbs.targetOS); + return false; + } + } + Application { Depends { name: "cpp" } Depends { name: "B" } Depends { name: "C" } Depends { name: "D" } - condition: buildableProducts.contains("A") + condition: buildableProducts.includes("A") name: "A" bundle.isBundle: true bundle.publicHeaders: ["dummy.h"] @@ -24,7 +33,7 @@ Project { Depends { name: "B" } Depends { name: "C" } Depends { name: "D" } - condition: buildableProducts.contains("ABadApple") + condition: buildableProducts.includes("ABadApple") name: "ABadApple" bundle._productTypeIdentifier: "com.apple.product-type.will.never.exist.ever.guaranteed" bundle.isBundle: true @@ -41,7 +50,7 @@ Project { Depends { name: "B" } Depends { name: "C" } Depends { name: "D" } - condition: buildableProducts.contains("ABadThirdParty") + condition: buildableProducts.includes("ABadThirdParty") name: "ABadThirdParty" bundle._productTypeIdentifier: "org.special.third.party.non.existent.product.type" bundle.isBundle: true @@ -94,7 +103,7 @@ Project { ApplicationExtension { Depends { name: "cpp" } - condition: buildableProducts.contains("E") + condition: buildableProducts.includes("E") name: "E" bundle.isBundle: true bundle.publicHeaders: ["dummy.h"] @@ -107,7 +116,7 @@ Project { XPCService { Depends { name: "cpp" } - condition: buildableProducts.contains("F") + condition: buildableProducts.includes("F") name: "F" bundle.isBundle: true bundle.publicHeaders: ["dummy.h"] @@ -120,11 +129,14 @@ Project { Product { Depends { name: "bundle" } - condition: buildableProducts.contains("G") + condition: buildableProducts.includes("G") type: ["inapppurchase"] name: "G" bundle.isBundle: true bundle.resources: ["resource.txt"] + // XCode 12.5 does not support com.apple.product-type.in-app-purchase-content type anymore, + // so use older specs from Qbs + bundle._useXcodeBuildSpecs: false Group { fileTagsFilter: product.type.concat(project.bundleFileTags) qbs.install: true diff --git a/tests/auto/blackbox/testdata-apple/byteArrayInfoPlist/ByteArray-Info.plist b/tests/auto/blackbox/testdata-apple/byteArrayInfoPlist/ByteArray-Info.plist new file mode 100644 index 000000000..df0429f25 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/byteArrayInfoPlist/ByteArray-Info.plist @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>DataKey</key> + <!--The data value--> + <data>VGhlIGRhdGEgdmFsdWU=</data> + <key>StringKey</key> + <string>The string value</string> +</dict> +</plist> diff --git a/tests/auto/blackbox/testdata-apple/byteArrayInfoPlist/byteArrayInfoPlist.qbs b/tests/auto/blackbox/testdata-apple/byteArrayInfoPlist/byteArrayInfoPlist.qbs new file mode 100644 index 000000000..4df0886ff --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/byteArrayInfoPlist/byteArrayInfoPlist.qbs @@ -0,0 +1,37 @@ +import qbs.BundleTools +import qbs.TextFile + +CppApplication { + Depends { name: "bundle" } + cpp.minimumMacosVersion: "10.7" + files: ["main.c", "ByteArray-Info.plist"] + type: base.concat(["txt_output"]) + + Properties { + condition: qbs.targetOS.includes("darwin") + bundle.isBundle: true + bundle.identifierPrefix: "com.test" + } + + Rule { + inputs: ["aggregate_infoplist"] + Artifact { + filePath: input.fileName + ".out" + fileTags: ["txt_output"] + } + prepare: { + var cmd = new JavaScriptCommand(); + cmd.description = "generating" + output.fileName + " from " + input.fileName; + cmd.highlight = "codegen"; + cmd.sourceCode = function() { + var plist = new BundleTools.infoPlistContents(input.filePath); + var content = plist["DataKey"]; + var int8view = new Uint8Array(content); + file = new TextFile(output.filePath, TextFile.WriteOnly); + file.write(String.fromCharCode.apply(null, int8view)); + file.close(); + } + return [cmd]; + } + } +} diff --git a/tests/auto/blackbox/testdata/innosetupDependencies/main.c b/tests/auto/blackbox/testdata-apple/byteArrayInfoPlist/main.c index 76e819701..76e819701 100644 --- a/tests/auto/blackbox/testdata/innosetupDependencies/main.c +++ b/tests/auto/blackbox/testdata-apple/byteArrayInfoPlist/main.c diff --git a/tests/auto/blackbox/testdata/path-probe/main.cpp b/tests/auto/blackbox/testdata-apple/codesign/app.cpp index 76e819701..76e819701 100644 --- a/tests/auto/blackbox/testdata/path-probe/main.cpp +++ b/tests/auto/blackbox/testdata-apple/codesign/app.cpp diff --git a/tests/auto/blackbox/testdata-apple/codesign/codesign.qbs b/tests/auto/blackbox/testdata-apple/codesign/codesign.qbs new file mode 100644 index 000000000..c1fc0502a --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/codesign/codesign.qbs @@ -0,0 +1,57 @@ +import "../multiarch-helpers.js" as Helpers + +Project { + name: "p" + // we do not have the access to xcode version in qbs.architectures so we need to pass it here + property string xcodeVersion + + property bool isBundle: true + property bool enableSigning: true + property bool multiArch: false + property bool multiVariant: false + + CppApplication { + name: "A" + version: "1.0.0" + bundle.isBundle: project.isBundle + files: "app.cpp" + codesign.enableCodeSigning: project.enableSigning + codesign.signingType: "ad-hoc" + install: true + installDir: "" + + qbs.architectures: + multiArch ? Helpers.getArchitectures(qbs, project.xcodeVersion) : [] + qbs.buildVariants: project.multiVariant ? ["debug", "release"] : [] + } + + DynamicLibrary { + Depends { name: "cpp" } + name: "B" + version: "1.0.0" + bundle.isBundle: project.isBundle + files: "app.cpp" + codesign.enableCodeSigning: project.enableSigning + codesign.signingType: "ad-hoc" + install: true + installDir: "" + qbs.architectures: + multiArch ? Helpers.getArchitectures(qbs, project.xcodeVersion) : [] + qbs.buildVariants: project.multiVariant ? ["debug", "release"] : [] + } + + LoadableModule { + Depends { name: "cpp" } + name: "C" + version: "1.0.0" + bundle.isBundle: project.isBundle + files: "app.cpp" + codesign.enableCodeSigning: project.enableSigning + codesign.signingType: "ad-hoc" + install: true + installDir: "" + qbs.architectures: + multiArch ? Helpers.getArchitectures(qbs, project.xcodeVersion) : [] + qbs.buildVariants: project.multiVariant ? ["debug", "release"] : [] + } +} diff --git a/tests/auto/blackbox/testdata-apple/deploymentTarget/deployment.qbs b/tests/auto/blackbox/testdata-apple/deploymentTarget/deployment.qbs index 9eff57b60..2179e9c84 100644 --- a/tests/auto/blackbox/testdata-apple/deploymentTarget/deployment.qbs +++ b/tests/auto/blackbox/testdata-apple/deploymentTarget/deployment.qbs @@ -5,7 +5,7 @@ CppApplication { // - will actually link (as of Xcode 8.1) // - exist for the given architecture(s) cpp.minimumMacosVersion: qbs.architecture === "x86_64h" ? "10.12" : "10.6" - cpp.minimumIosVersion: ["armv7s", "arm64", "x86_64"].contains(qbs.architecture) ? "7.0" : "6.0" + cpp.minimumIosVersion: ["armv7s", "arm64", "x86_64"].includes(qbs.architecture) ? "7.0" : "6.0" cpp.minimumTvosVersion: "9.0" cpp.minimumWatchosVersion: "2.0" diff --git a/tests/auto/blackbox/testdata-apple/frameworkStructure/frameworkStructure.qbs b/tests/auto/blackbox/testdata-apple/frameworkStructure/frameworkStructure.qbs index a812ae513..3c6d39332 100644 --- a/tests/auto/blackbox/testdata-apple/frameworkStructure/frameworkStructure.qbs +++ b/tests/auto/blackbox/testdata-apple/frameworkStructure/frameworkStructure.qbs @@ -2,6 +2,12 @@ Project { property bool includeHeaders: true Library { Depends { name: "cpp" } + Depends { name: "bundle" } + + property bool isShallow: { + console.info("isShallow: " + bundle.isShallow); + return bundle.isShallow; + } name: "Widget" bundle.isBundle: true diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/100.png b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/100.png Binary files differnew file mode 100644 index 000000000..98f8eaeb7 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/100.png diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/114.png b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/114.png Binary files differnew file mode 100644 index 000000000..a14be545e --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/114.png diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/120.png b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/120.png Binary files differnew file mode 100644 index 000000000..b910f96df --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/120.png diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/128.png b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/128.png Binary files differnew file mode 100644 index 000000000..7cf0327dc --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/128.png diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/144.png b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/144.png Binary files differnew file mode 100644 index 000000000..c7f18cda1 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/144.png diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/152.png b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/152.png Binary files differnew file mode 100644 index 000000000..af411d7e3 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/152.png diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/16.png b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/16.png Binary files differnew file mode 100644 index 000000000..be3743a22 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/16.png diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/167.png b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/167.png Binary files differnew file mode 100644 index 000000000..855952774 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/167.png diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/172.png b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/172.png Binary files differnew file mode 100644 index 000000000..a410f8bb2 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/172.png diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/180.png b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/180.png Binary files differnew file mode 100644 index 000000000..fcef493f4 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/180.png diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/196.png b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/196.png Binary files differnew file mode 100644 index 000000000..c974bf14a --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/196.png diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/20.png b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/20.png Binary files differnew file mode 100644 index 000000000..25897fc42 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/20.png diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/216.png b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/216.png Binary files differnew file mode 100644 index 000000000..ea0703112 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/216.png diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/256.png b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/256.png Binary files differnew file mode 100644 index 000000000..f1a3ef352 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/256.png diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/29.png b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/29.png Binary files differnew file mode 100644 index 000000000..1f9ef0678 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/29.png diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/32.png b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/32.png Binary files differnew file mode 100644 index 000000000..d969ed1df --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/32.png diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/40.png b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/40.png Binary files differnew file mode 100644 index 000000000..1f76c0b09 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/40.png diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/48.png b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/48.png Binary files differnew file mode 100644 index 000000000..5279cb807 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/48.png diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/50.png b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/50.png Binary files differnew file mode 100644 index 000000000..8045e514d --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/50.png diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/512.png b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/512.png Binary files differnew file mode 100644 index 000000000..c8f3cb758 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/512.png diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/55.png b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/55.png Binary files differnew file mode 100644 index 000000000..c3d8811f6 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/55.png diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/57.png b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/57.png Binary files differnew file mode 100644 index 000000000..5abf4b377 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/57.png diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/58.png b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/58.png Binary files differnew file mode 100644 index 000000000..fc8cf5df5 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/58.png diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/60.png b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/60.png Binary files differnew file mode 100644 index 000000000..ddc66846c --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/60.png diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/64.png b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/64.png Binary files differnew file mode 100644 index 000000000..ad87d2af1 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/64.png diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/72.png b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/72.png Binary files differnew file mode 100644 index 000000000..b78c47708 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/72.png diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/76.png b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/76.png Binary files differnew file mode 100644 index 000000000..50bab502d --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/76.png diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/80.png b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/80.png Binary files differnew file mode 100644 index 000000000..6a3a31fa6 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/80.png diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/87.png b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/87.png Binary files differnew file mode 100644 index 000000000..13fb01fef --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/87.png diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/88.png b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/88.png Binary files differnew file mode 100644 index 000000000..8eb955ca8 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/88.png diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/Contents.json b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..87ae131b9 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/AppIconSet.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,299 @@ +{ + "images" : [ + { + "filename" : "40.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "filename" : "60.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "filename" : "29.png", + "idiom" : "iphone", + "scale" : "1x", + "size" : "29x29" + }, + { + "filename" : "58.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "filename" : "87.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "filename" : "80.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "filename" : "120.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "filename" : "57.png", + "idiom" : "iphone", + "scale" : "1x", + "size" : "57x57" + }, + { + "filename" : "114.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "57x57" + }, + { + "filename" : "120.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "filename" : "180.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "filename" : "20.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "20x20" + }, + { + "filename" : "40.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "20x20" + }, + { + "filename" : "29.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "29x29" + }, + { + "filename" : "58.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "29x29" + }, + { + "filename" : "40.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "40x40" + }, + { + "filename" : "80.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "40x40" + }, + { + "filename" : "50.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "50x50" + }, + { + "filename" : "100.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "50x50" + }, + { + "filename" : "72.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "72x72" + }, + { + "filename" : "144.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "72x72" + }, + { + "filename" : "76.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "76x76" + }, + { + "filename" : "152.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "76x76" + }, + { + "filename" : "167.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "83.5x83.5" + }, + { + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + }, + { + "filename" : "48.png", + "idiom" : "watch", + "role" : "notificationCenter", + "scale" : "2x", + "size" : "24x24", + "subtype" : "38mm" + }, + { + "filename" : "55.png", + "idiom" : "watch", + "role" : "notificationCenter", + "scale" : "2x", + "size" : "27.5x27.5", + "subtype" : "42mm" + }, + { + "filename" : "58.png", + "idiom" : "watch", + "role" : "companionSettings", + "scale" : "2x", + "size" : "29x29" + }, + { + "filename" : "87.png", + "idiom" : "watch", + "role" : "companionSettings", + "scale" : "3x", + "size" : "29x29" + }, + { + "filename" : "80.png", + "idiom" : "watch", + "role" : "appLauncher", + "scale" : "2x", + "size" : "40x40", + "subtype" : "38mm" + }, + { + "filename" : "88.png", + "idiom" : "watch", + "role" : "appLauncher", + "scale" : "2x", + "size" : "44x44", + "subtype" : "40mm" + }, + { + "filename" : "100.png", + "idiom" : "watch", + "role" : "appLauncher", + "scale" : "2x", + "size" : "50x50", + "subtype" : "44mm" + }, + { + "filename" : "172.png", + "idiom" : "watch", + "role" : "quickLook", + "scale" : "2x", + "size" : "86x86", + "subtype" : "38mm" + }, + { + "filename" : "196.png", + "idiom" : "watch", + "role" : "quickLook", + "scale" : "2x", + "size" : "98x98", + "subtype" : "42mm" + }, + { + "filename" : "216.png", + "idiom" : "watch", + "role" : "quickLook", + "scale" : "2x", + "size" : "108x108", + "subtype" : "44mm" + }, + { + "idiom" : "watch-marketing", + "scale" : "1x", + "size" : "1024x1024" + }, + { + "filename" : "16.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "16x16" + }, + { + "filename" : "32.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "16x16" + }, + { + "filename" : "32.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "32x32" + }, + { + "filename" : "64.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "32x32" + }, + { + "filename" : "128.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "128x128" + }, + { + "filename" : "256.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "128x128" + }, + { + "filename" : "256.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "256x256" + }, + { + "filename" : "512.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "256x256" + }, + { + "filename" : "512.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "512x512" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "512x512" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/tests/auto/blackbox/testdata-apple/ib/appiconset/appiconset.qbs b/tests/auto/blackbox/testdata-apple/ib/appiconset/appiconset.qbs new file mode 100644 index 000000000..2015032ea --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/appiconset.qbs @@ -0,0 +1,10 @@ +CppApplication { + Depends { name: "ib" } + Depends { name: "bundle" } + property bool isShallow: { + console.info("bundle.isShallow: " + bundle.isShallow); + return bundle.isShallow; + } + files: ["main.c", "AppIconSet.xcassets"] + ib.appIconName: "AppIcon" +} diff --git a/tests/auto/blackbox/testdata/wixDependencies/main.c b/tests/auto/blackbox/testdata-apple/ib/appiconset/main.c index 76e819701..76e819701 100644 --- a/tests/auto/blackbox/testdata/wixDependencies/main.c +++ b/tests/auto/blackbox/testdata-apple/ib/appiconset/main.c diff --git a/tests/auto/blackbox/testdata-apple/ib/assetcatalog/assetcatalogempty.qbs b/tests/auto/blackbox/testdata-apple/ib/assetcatalog/assetcatalogempty.qbs index 622fa46cb..d06e24eb3 100644 --- a/tests/auto/blackbox/testdata-apple/ib/assetcatalog/assetcatalogempty.qbs +++ b/tests/auto/blackbox/testdata-apple/ib/assetcatalog/assetcatalogempty.qbs @@ -1,6 +1,13 @@ +import qbs.Host import qbs.Utilities Project { + condition: { + var result = qbs.targetOS.includes("macos"); + if (!result) + console.info("Skip this test"); + return result; + } property bool includeIconset CppApplication { @@ -11,7 +18,8 @@ Project { filez.push("empty.xcassets/empty.iconset"); else if (Utilities.versionCompare(xcode.version, "5") >= 0) filez.push("empty.xcassets"); - if (qbs.hostOSVersionMinor >= 10 // need macOS 10.10 to build SBs + if ((Host.osVersionMajor() >= 11 + || Host.osVersionMinor() >= 10) // need macOS 10.10 or higher to build SBs && cpp.minimumMacosVersion !== undefined && Utilities.versionCompare(cpp.minimumMacosVersion, "10.10") >= 0) filez.push("Storyboard.storyboard"); diff --git a/tests/auto/blackbox/testdata-apple/ib/iconsetapp/iconsetapp.qbs b/tests/auto/blackbox/testdata-apple/ib/iconsetapp/iconsetapp.qbs index 04e6ce0ce..dd39d1639 100644 --- a/tests/auto/blackbox/testdata-apple/ib/iconsetapp/iconsetapp.qbs +++ b/tests/auto/blackbox/testdata-apple/ib/iconsetapp/iconsetapp.qbs @@ -1,4 +1,9 @@ CppApplication { Depends { name: "ib" } + Depends { name: "bundle" } + property bool isShallow: { + console.info("isShallow: " + bundle.isShallow); + return bundle.isShallow; + } files: ["main.c", "white.iconset"] } diff --git a/tests/auto/blackbox/testdata-apple/infoPlistVariables/Info.plist b/tests/auto/blackbox/testdata-apple/infoPlistVariables/Info.plist new file mode 100644 index 000000000..cb879d70c --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/infoPlistVariables/Info.plist @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>Curly</key> + <string>${EXECUTABLE_NAME}</string> + <key>Braces</key> + <string>$(EXECUTABLE_NAME)</string> + <key>At</key> + <string>@EXECUTABLE_NAME@</string> + <key>CurlyMult</key> + <string>${EXECUTABLE_NAME}_${PRODUCT_NAME}</string> + <key>BracesMult</key> + <string>$(EXECUTABLE_NAME)_$(PRODUCT_NAME)</string> + <key>AtMult</key> + <string>@EXECUTABLE_NAME@_@PRODUCT_NAME@</string> + <key>CurlyNested</key> + <string>${${EXE}_NAME}</string> + <key>BracesNested</key> + <string>${${EXE}_NAME}</string> + <key>WithDefault</key> + <string>${NON_EXISTING:default=DEFAULT}</string> +</dict> +</plist> diff --git a/tests/auto/blackbox/testdata-apple/infoPlistVariables/infoPlistVariables.qbs b/tests/auto/blackbox/testdata-apple/infoPlistVariables/infoPlistVariables.qbs new file mode 100644 index 000000000..47ca80f07 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/infoPlistVariables/infoPlistVariables.qbs @@ -0,0 +1,16 @@ +CppApplication { + Depends { name: "bundle" } + cpp.minimumMacosVersion: "10.7" + files: ["main.c", "Info.plist"] + + Properties { + condition: qbs.targetOS.includes("darwin") + bundle.isBundle: true + bundle.identifierPrefix: "com.test" + bundle.extraEnv: { + var result = original; + result["EXE"] = "EXECUTABLE"; + return result; + } + } +} diff --git a/tests/auto/blackbox/testdata-apple/infoPlistVariables/main.c b/tests/auto/blackbox/testdata-apple/infoPlistVariables/main.c new file mode 100644 index 000000000..76e819701 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/infoPlistVariables/main.c @@ -0,0 +1 @@ +int main() { return 0; } diff --git a/tests/auto/blackbox/testdata-apple/multiarch-helpers.js b/tests/auto/blackbox/testdata-apple/multiarch-helpers.js new file mode 100644 index 000000000..a8054b63c --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/multiarch-helpers.js @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2020 Ivan Komissarov (abbapoh@gmail.com) +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +var Utilities = require("qbs.Utilities"); + +// Typically, multiple architectures are used for migration from "old" arch to a "new" one +// For example: x86 -> x86_64 on macOS, armv7 -> arm64 on iOS + +function enableOldArch(qbs, xcodeVersion) { + return qbs.targetOS.includes("macos") + && xcodeVersion + && (Utilities.versionCompare(xcodeVersion, "10") < 0 + || Utilities.versionCompare(xcodeVersion, "12.2") >= 0) + || qbs.targetOS.includes("ios") +} + +function getNewArch(qbs, xcodeVersion) { + if (qbs.targetOS.includes("macos")) + return xcodeVersion + && Utilities.versionCompare(xcodeVersion, "12.2") >= 0 ? "arm64" : "x86_64"; + else if (qbs.targetOS.includes("ios-simulator")) + return "x86_64" + else if (qbs.targetOS.includes("ios")) + return "arm64" + else if (qbs.targetOS.includes("tvos")) + return "arm64" + else if (qbs.targetOS.includes("watchos")) + return "armv7k" + throw "unsupported targetOS: " + qbs.targetOS; +} + +function getOldArch(qbs, xcodeVersion) { + if (qbs.targetOS.includes("macos")) + return xcodeVersion + && Utilities.versionCompare(xcodeVersion, "12.2") >= 0 ? "x86_64" : "x86"; + else if (qbs.targetOS.includes("ios-simulator")) + return "x86" + else if (qbs.targetOS.includes("ios")) + return "armv7a" + throw "unsupported targetOS: " + qbs.targetOS; +} + +function getArchitectures(qbs, xcodeVersion) { + return enableOldArch(qbs, xcodeVersion) + ? [getOldArch(qbs, xcodeVersion), getNewArch(qbs, xcodeVersion)] + : [getNewArch(qbs, xcodeVersion)]; +} diff --git a/tests/auto/blackbox/testdata-apple/objc-arc/objc-arc.qbs b/tests/auto/blackbox/testdata-apple/objc-arc/objc-arc.qbs index 545d5701c..ce128059f 100644 --- a/tests/auto/blackbox/testdata-apple/objc-arc/objc-arc.qbs +++ b/tests/auto/blackbox/testdata-apple/objc-arc/objc-arc.qbs @@ -2,7 +2,7 @@ Product { Depends { name: "cpp" } consoleApplication: true type: ["application"] - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") Group { cpp.automaticReferenceCounting: true diff --git a/tests/auto/blackbox/testdata-apple/overrideInfoPlist/Override-Info.plist b/tests/auto/blackbox/testdata-apple/overrideInfoPlist/Override-Info.plist new file mode 100644 index 000000000..f2621e983 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/overrideInfoPlist/Override-Info.plist @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>DefaultValue</key> + <string>The default value</string> + <key>OverriddenValue</key> + <string>The default value</string> +</dict> +</plist> diff --git a/tests/auto/blackbox/testdata-apple/overrideInfoPlist/main.c b/tests/auto/blackbox/testdata-apple/overrideInfoPlist/main.c new file mode 100644 index 000000000..76e819701 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/overrideInfoPlist/main.c @@ -0,0 +1 @@ +int main() { return 0; } diff --git a/tests/auto/blackbox/testdata-apple/overrideInfoPlist/overrideInfoPlist.qbs b/tests/auto/blackbox/testdata-apple/overrideInfoPlist/overrideInfoPlist.qbs new file mode 100644 index 000000000..270a0792c --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/overrideInfoPlist/overrideInfoPlist.qbs @@ -0,0 +1,16 @@ +CppApplication { + Depends { name: "bundle" } + cpp.minimumMacosVersion: "10.7" + files: ["main.c", "Override-Info.plist"] + + Properties { + condition: qbs.targetOS.includes("darwin") + bundle.isBundle: true + bundle.identifierPrefix: "com.test" + + bundle.infoPlist: ({ + "CFBundleName": "My Bundle", + "OverriddenValue": "The overridden value", + }) + } +} diff --git a/tests/auto/blackbox/testdata-apple/xcode/xcode-project.qbs b/tests/auto/blackbox/testdata-apple/xcode/xcode-project.qbs index fbab6d0b1..e7bf4739a 100644 --- a/tests/auto/blackbox/testdata-apple/xcode/xcode-project.qbs +++ b/tests/auto/blackbox/testdata-apple/xcode/xcode-project.qbs @@ -16,19 +16,19 @@ Project { console.info("Available SDK versions: " + xcode.availableSdkVersions.join(", ")); var targetOsToKey = function(targetOS) { - if (targetOS.contains("ios")) + if (targetOS.includes("ios")) return "iphoneos"; - if (targetOS.contains("ios-simulator")) + if (targetOS.includes("ios-simulator")) return "iphonesimulator"; - if (targetOS.contains("macos")) + if (targetOS.includes("macos")) return "macosx"; - if (targetOS.contains("tvos")) + if (targetOS.includes("tvos")) return "appletvos"; - if (targetOS.contains("tvos-simulator")) + if (targetOS.includes("tvos-simulator")) return "appletvsimulator"; - if (targetOS.contains("watchos")) + if (targetOS.includes("watchos")) return "watchos"; - if (targetOS.contains("watchos-simulator")) + if (targetOS.includes("watchos-simulator")) return "watchossimulator"; throw "Unsupported OS" + targetOS; } @@ -43,8 +43,11 @@ Project { } for (var i = 0; i < a.length; ++i) { - if (a[i] !== b[i]) { - throw msg; + var version1 = a[i].split('.'); + var version2 = b[i].split('.'); + for (var j = 0; j < version1.length; ++j) { + if (version1[j] !== version2[j]) + throw msg; } } } diff --git a/tests/auto/blackbox/testdata-baremetal/BareMetalApplication.qbs b/tests/auto/blackbox/testdata-baremetal/BareMetalApplication.qbs new file mode 100644 index 000000000..7a35e4e13 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/BareMetalApplication.qbs @@ -0,0 +1,29 @@ +import qbs.Host + +BareMetalProduct { + type: "application" + consoleApplication: true + + property bool dummy: { + if (qbs.targetPlatform !== Host.platform() + || qbs.architecture !== Host.architecture()) { + + function supportsCrossRun() { + // We can run 32 bit applications on 64 bit Windows. + if (Host.platform() === "windows" && Host.architecture() === "x86_64" + && qbs.targetPlatform === "windows" && qbs.architecture === "x86") { + return true; + } + } + + if (!supportsCrossRun()) + console.info("targetPlatform differs from hostPlatform") + } + } + + Group { + condition: qbs.toolchain.includes("cosmic") + files: "cosmic.lkf" + fileTags: "linkerscript" + } +} diff --git a/tests/auto/blackbox/testdata-baremetal/BareMetalProduct.qbs b/tests/auto/blackbox/testdata-baremetal/BareMetalProduct.qbs new file mode 100644 index 000000000..446cfe086 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/BareMetalProduct.qbs @@ -0,0 +1,158 @@ +Product { + Depends { name: "cpp" } + cpp.positionIndependentCode: false + Properties { + condition: qbs.toolchain.includes("iar") + && qbs.architecture === "stm8" + cpp.driverLinkerFlags: [ + "--config_def", "_CSTACK_SIZE=0x100", + "--config_def", "_HEAP_SIZE=0x100", + ] + } + Properties { + condition: qbs.toolchain.includes("iar") + && qbs.architecture === "rl78" + cpp.driverLinkerFlags: [ + "--config_def", "_NEAR_HEAP_SIZE=256", + "--config_def", "_FAR_HEAP_SIZE=4096", + "--config_def", "_HUGE_HEAP_SIZE=0", + "--config_def", "_STACK_SIZE=128", + "--config_def", "_NEAR_CONST_LOCATION_SIZE=0x6F00", + "--config_def", "_NEAR_CONST_LOCATION_START=0x3000", + "--define_symbol", "_NEAR_CONST_LOCATION=0", + "--config", cpp.toolchainInstallPath + "/../config/lnkrl78_s3.icf" + ] + } + Properties { + condition: qbs.toolchain.includes("iar") + && qbs.architecture === "rh850" + cpp.driverLinkerFlags: [ + "--config_def", "CSTACK_SIZE=0x1000", + "--config_def", "HEAP_SIZE=0x1000", + "--config", cpp.toolchainInstallPath + "/../config/lnkrh850_g3m.icf" + ] + } + Properties { + condition: qbs.toolchain.includes("iar") + && qbs.architecture === "v850" + cpp.driverLinkerFlags: [ + "-D_CSTACK_SIZE=1000", + "-D_HEAP_SIZE=1000", + "-f", cpp.toolchainInstallPath + "/../config/lnk85.xcl" + ] + } + Properties { + condition: qbs.toolchain.includes("iar") + && qbs.architecture === "78k" + cpp.commonCompilerFlags: [ + "--core", "78k0", + "--code_model", "standard" + ] + cpp.driverLinkerFlags: [ + "-D_CSTACK_SIZE=80", + "-D_HEAP_SIZE=200", + "-D_CODEBANK_START=0", + "-D_CODEBANK_END=0", + "-D_CODEBANK_BANKS=0", + "-f", cpp.toolchainInstallPath + "/../config/lnk.xcl", + cpp.toolchainInstallPath + "/../lib/clib/cl78ks1.r26" + ] + } + Properties { + condition: qbs.toolchain.includes("iar") + && qbs.architecture === "sh" + cpp.driverLinkerFlags: [ + "--config_def", "_CSTACK_SIZE=0x800", + "--config_def", "_HEAP_SIZE=0x800", + "--config_def", "_INT_TABLE=0x10", + "--config", cpp.toolchainInstallPath + "/../config/generic.icf" + ] + } + Properties { + condition: qbs.toolchain.includes("iar") + && qbs.architecture === "hcs8" + cpp.driverLinkerFlags: [ + "-D_CSTACK_SIZE=200", + "-D_HEAP_SIZE=200", + "-f", cpp.toolchainInstallPath + "/../config/lnkunspecifieds08.xcl" + ] + } + Properties { + condition: qbs.toolchain.includes("iar") + && qbs.architecture === "m32c" + cpp.driverLinkerFlags: [ + "-D_CSTACK_SIZE=100", + "-D_NEAR_HEAP_SIZE=400", + "-D_FAR_HEAP_SIZE=400", + "-D_HUGE_HEAP_SIZE=400", + "-D_ISTACK_SIZE=40", + "-f", cpp.toolchainInstallPath + "/../config/lnkm32c.xcl", + cpp.toolchainInstallPath + (qbs.debugInformation ? "/../lib/dlib/dlm32cnf.r48" : "/../lib/clib/clm32cf.r48") + ] + } + Properties { + condition: qbs.toolchain.includes("iar") + && qbs.architecture === "riscv" + cpp.driverLinkerFlags: [ + "--config_def", "CSTACK_SIZE=0x1000", + "--config_def", "HEAP_SIZE=0x1000" + ] + } + Properties { + condition: qbs.toolchain.includes("iar") + && qbs.architecture === "m68k" + cpp.cFlags: [ + "--no_div" + ] + cpp.driverLinkerFlags: [ + "-D__FLASHBEGIN=0", + "-D__FLASHEND=1FFFF", + "-D__RAMBEGIN=800000", + "-D__RAMEND=803FFF", + "-D_CSTACK_SIZE=200", + "-D_HEAP_SIZE=1000", + "-D_VBR_ADDRESS=0", + "-f", cpp.toolchainInstallPath + "/../config/lnkm51ac128.xcl", + cpp.toolchainInstallPath + "/../lib/dlcfcffdn.r68" + ] + } + Properties { + condition: qbs.toolchain.includes("keil") + && qbs.architecture.startsWith("arm") + && cpp.compilerName.startsWith("armcc") + cpp.assemblerFlags: ["--cpu", "cortex-m0"] + cpp.commonCompilerFlags: ["--cpu", "cortex-m0"] + } + Properties { + condition: qbs.toolchain.includes("keil") + && qbs.architecture.startsWith("arm") + && cpp.compilerName.startsWith("armclang") + cpp.assemblerFlags: ["--cpu", "cortex-m0"] + cpp.commonCompilerFlags: ["-mcpu=cortex-m0", "--target=arm-arm-none-eabi"] + } + Properties { + condition: qbs.toolchain.includes("gcc") + && qbs.architecture.startsWith("arm") + cpp.driverFlags: ["-specs=nosys.specs"] + } + Properties { + condition: qbs.toolchain.includes("gcc") + && qbs.architecture === "xtensa" + cpp.driverFlags: ["-nostdlib"] + } + Properties { + condition: qbs.toolchain.includes("gcc") + && qbs.architecture === "msp430" + cpp.driverFlags: ["-mmcu=msp430f5529", "-nostdlib"] + } + Properties { + condition: qbs.toolchain.includes("gcc") + && qbs.architecture === "m32r" + cpp.driverFlags: ["-nostdlib"] + } + Properties { + condition: qbs.toolchain.includes("gcc") + && qbs.architecture === "riscv" + cpp.driverFlags: ["-nostdlib"] + } +} diff --git a/tests/auto/blackbox/testdata-baremetal/BareMetalStaticLibrary.qbs b/tests/auto/blackbox/testdata-baremetal/BareMetalStaticLibrary.qbs new file mode 100644 index 000000000..7259b1446 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/BareMetalStaticLibrary.qbs @@ -0,0 +1,3 @@ +BareMetalProduct { + type: "staticlibrary" +} diff --git a/tests/auto/blackbox/testdata-baremetal/compiler-defines-by-language/app.c b/tests/auto/blackbox/testdata-baremetal/compiler-defines-by-language/app.c new file mode 100644 index 000000000..58fe69254 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/compiler-defines-by-language/app.c @@ -0,0 +1,4 @@ +int main(void) +{ + return 0; +} diff --git a/tests/auto/blackbox/testdata-baremetal/compiler-defines-by-language/compiler-defines-by-language.qbs b/tests/auto/blackbox/testdata-baremetal/compiler-defines-by-language/compiler-defines-by-language.qbs new file mode 100644 index 000000000..73365ada4 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/compiler-defines-by-language/compiler-defines-by-language.qbs @@ -0,0 +1,73 @@ +import "../BareMetalApplication.qbs" as BareMetalApplication + +Project { + property bool supportsCpp: { + if (qbs.toolchain.includes("cosmic")) + return false; + if (qbs.toolchain.includes("sdcc")) + return false; + if (qbs.toolchain.includes("keil")) { + if (qbs.architecture === "mcs51" + || qbs.architecture === "mcs251" + || qbs.architecture === "c166") { + return false; + } + } + return true; + } + + BareMetalApplication { + name: "c_language" + files: ["app.c", "ctest.c"] + cpp.enableCompilerDefinesByLanguage: [] + property var foo: { + if (!cpp.compilerDefinesByLanguage) + throw "ASSERT cpp.compilerDefinesByLanguage: " + + cpp.compilerDefinesByLanguage; + if (!cpp.compilerDefinesByLanguage["c"]) + throw "ASSERT cpp.compilerDefinesByLanguage[\"c\"]: " + + cpp.compilerDefinesByLanguage["c"]; + if (cpp.compilerDefinesByLanguage["cpp"]) + throw "ASSERT !cpp.compilerDefinesByLanguage[\"cpp\"]: " + + cpp.compilerDefinesByLanguage["cpp"]; + } + } + + BareMetalApplication { + condition: supportsCpp + name: "cpp_language" + files: ["app.c", "cpptest.cpp"] + cpp.enableCompilerDefinesByLanguage: ["cpp"] + cpp.enableExceptions: false + property var foo: { + if (!cpp.compilerDefinesByLanguage) + throw "ASSERT cpp.compilerDefinesByLanguage: " + + cpp.compilerDefinesByLanguage; + if (cpp.compilerDefinesByLanguage["c"]) + throw "ASSERT !cpp.compilerDefinesByLanguage[\"c\"]: " + + cpp.compilerDefinesByLanguage["c"]; + if (!cpp.compilerDefinesByLanguage["cpp"]) + throw "ASSERT cpp.compilerDefinesByLanguage[\"cpp\"]: " + + cpp.compilerDefinesByLanguage["cpp"]; + } + } + + BareMetalApplication { + condition: supportsCpp + name: "c_and_cpp_language" + files: ["app.c", "ctest.c", "cpptest.cpp"] + cpp.enableCompilerDefinesByLanguage: ["c", "cpp"] + cpp.enableExceptions: false + property var foo: { + if (!cpp.compilerDefinesByLanguage) + throw "ASSERT cpp.compilerDefinesByLanguage: " + + cpp.compilerDefinesByLanguage; + if (!cpp.compilerDefinesByLanguage["c"]) + throw "ASSERT cpp.compilerDefinesByLanguage[\"c\"]: " + + cpp.compilerDefinesByLanguage["c"]; + if (!cpp.compilerDefinesByLanguage["cpp"]) + throw "ASSERT cpp.compilerDefinesByLanguage[\"cpp\"]: " + + cpp.compilerDefinesByLanguage["cpp"]; + } + } +} diff --git a/tests/auto/blackbox/testdata/concurrent-executor/dummy1.input b/tests/auto/blackbox/testdata-baremetal/compiler-defines-by-language/cpptest.cpp index e69de29bb..e69de29bb 100644 --- a/tests/auto/blackbox/testdata/concurrent-executor/dummy1.input +++ b/tests/auto/blackbox/testdata-baremetal/compiler-defines-by-language/cpptest.cpp diff --git a/tests/auto/blackbox/testdata/concurrent-executor/dummy2.input b/tests/auto/blackbox/testdata-baremetal/compiler-defines-by-language/ctest.c index e69de29bb..e69de29bb 100644 --- a/tests/auto/blackbox/testdata/concurrent-executor/dummy2.input +++ b/tests/auto/blackbox/testdata-baremetal/compiler-defines-by-language/ctest.c diff --git a/tests/auto/blackbox/testdata-baremetal/compiler-include-paths/compiler-include-paths.qbs b/tests/auto/blackbox/testdata-baremetal/compiler-include-paths/compiler-include-paths.qbs new file mode 100644 index 000000000..5c73302ad --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/compiler-include-paths/compiler-include-paths.qbs @@ -0,0 +1,9 @@ +import "../BareMetalApplication.qbs" as BareMetalApplication + +BareMetalApplication { + files: ["main.c"] + property bool dummy: { + console.info("compilerIncludePaths: %%" + cpp.compilerIncludePaths + "%%"); + return true; + } +} diff --git a/tests/auto/blackbox/testdata-baremetal/compiler-include-paths/main.c b/tests/auto/blackbox/testdata-baremetal/compiler-include-paths/main.c new file mode 100644 index 000000000..58fe69254 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/compiler-include-paths/main.c @@ -0,0 +1,4 @@ +int main(void) +{ + return 0; +} diff --git a/tests/auto/blackbox/testdata-baremetal/compiler-listing/compiler-listing.qbs b/tests/auto/blackbox/testdata-baremetal/compiler-listing/compiler-listing.qbs new file mode 100644 index 000000000..6bd51e3bd --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/compiler-listing/compiler-listing.qbs @@ -0,0 +1,14 @@ +import "../BareMetalApplication.qbs" as BareMetalApplication + +BareMetalApplication { + condition: { + if (!qbs.toolchain.includes("gcc")) { + console.info("compiler listing suffix: %%" + cpp.compilerListingSuffix + "%%"); + return true; + } + console.info("unsupported toolset: %%" + + qbs.toolchainType + "%%, %%" + qbs.architecture + "%%"); + return false; + } + files: ["main.c", "fun.c"] +} diff --git a/tests/auto/blackbox/testdata-baremetal/compiler-listing/fun.c b/tests/auto/blackbox/testdata-baremetal/compiler-listing/fun.c new file mode 100644 index 000000000..3b8c8f2f4 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/compiler-listing/fun.c @@ -0,0 +1,4 @@ +int f(void) +{ + return 0; +} diff --git a/tests/auto/blackbox/testdata-baremetal/compiler-listing/main.c b/tests/auto/blackbox/testdata-baremetal/compiler-listing/main.c new file mode 100644 index 000000000..2c3d7726c --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/compiler-listing/main.c @@ -0,0 +1,6 @@ +extern int f(void); + +int main(void) +{ + return f(); +} diff --git a/tests/auto/blackbox/testdata-baremetal/cosmic.lkf b/tests/auto/blackbox/testdata-baremetal/cosmic.lkf new file mode 100644 index 000000000..90c254d1e --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/cosmic.lkf @@ -0,0 +1 @@ +@* diff --git a/tests/auto/blackbox/testdata-baremetal/defines/defines.qbs b/tests/auto/blackbox/testdata-baremetal/defines/defines.qbs new file mode 100644 index 000000000..b257a8a4b --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/defines/defines.qbs @@ -0,0 +1,6 @@ +import "../BareMetalApplication.qbs" as BareMetalApplication + +BareMetalApplication { + cpp.defines: ["FOO", "BAR"] + files: ["main.c"] +} diff --git a/tests/auto/blackbox/testdata-baremetal/defines/main.c b/tests/auto/blackbox/testdata-baremetal/defines/main.c new file mode 100644 index 000000000..d2d4769e4 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/defines/main.c @@ -0,0 +1,11 @@ +#ifndef FOO +#error FOO missing! +#endif +#ifndef BAR +#error BAR missing! +#endif + +int main(void) +{ + return 0; +} diff --git a/tests/auto/blackbox/testdata-baremetal/distribution-include-paths/bar/bar.h b/tests/auto/blackbox/testdata-baremetal/distribution-include-paths/bar/bar.h new file mode 100644 index 000000000..49ffa0b12 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/distribution-include-paths/bar/bar.h @@ -0,0 +1,6 @@ +#ifndef BAR_H +#define BAR_H + +#define BAR_VALUE 1 + +#endif // BAR_H diff --git a/tests/auto/blackbox/testdata-baremetal/distribution-include-paths/distribution-include-paths.qbs b/tests/auto/blackbox/testdata-baremetal/distribution-include-paths/distribution-include-paths.qbs new file mode 100644 index 000000000..0fded6a46 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/distribution-include-paths/distribution-include-paths.qbs @@ -0,0 +1,6 @@ +import "../BareMetalApplication.qbs" as BareMetalApplication + +BareMetalApplication { + files: ["main.c"] + cpp.distributionIncludePaths: ["foo", "bar"] +} diff --git a/tests/auto/blackbox/testdata-baremetal/distribution-include-paths/foo/foo.h b/tests/auto/blackbox/testdata-baremetal/distribution-include-paths/foo/foo.h new file mode 100644 index 000000000..dc510379d --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/distribution-include-paths/foo/foo.h @@ -0,0 +1,6 @@ +#ifndef FOO_H +#define FOO_H + +#define FOO_VALUE 1 + +#endif // FOO_H diff --git a/tests/auto/blackbox/testdata-baremetal/distribution-include-paths/main.c b/tests/auto/blackbox/testdata-baremetal/distribution-include-paths/main.c new file mode 100644 index 000000000..aabc97a0c --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/distribution-include-paths/main.c @@ -0,0 +1,7 @@ +#include <foo.h> +#include <bar.h> + +int main(void) +{ + return FOO_VALUE - BAR_VALUE; +} diff --git a/tests/auto/blackbox/testdata-baremetal/external-static-libraries/external-static-libraries.qbs b/tests/auto/blackbox/testdata-baremetal/external-static-libraries/external-static-libraries.qbs new file mode 100644 index 000000000..7336e3970 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/external-static-libraries/external-static-libraries.qbs @@ -0,0 +1,34 @@ +import "../BareMetalApplication.qbs" as BareMetalApplication +import "../BareMetalStaticLibrary.qbs" as BareMetalStaticLibrary + +Project { + property string outputLibrariesDirectory: buildDirectory + "/libs" + BareMetalStaticLibrary { + name: "lib-a" + destinationDirectory: project.outputLibrariesDirectory + Depends { name: "cpp" } + Properties { + condition: qbs.targetOS.includes("darwin") + bundle.isBundle: false + } + files: ["lib-a.c"] + } + BareMetalStaticLibrary { + name: "lib-b" + destinationDirectory: project.outputLibrariesDirectory + Depends { name: "cpp" } + Depends { name: "lib-a" } + Properties { + condition: qbs.targetOS.includes("darwin") + bundle.isBundle: false + } + files: ["lib-b.c"] + } + BareMetalApplication { + Depends { name: "lib-a"; cpp.link: false } + Depends { name: "lib-b"; cpp.link: false } + files: ["main.c"] + cpp.libraryPaths: [project.outputLibrariesDirectory] + cpp.staticLibraries: ["lib-b", "lib-a"] + } +} diff --git a/tests/auto/blackbox/testdata-baremetal/external-static-libraries/lib-a.c b/tests/auto/blackbox/testdata-baremetal/external-static-libraries/lib-a.c new file mode 100644 index 000000000..13401861f --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/external-static-libraries/lib-a.c @@ -0,0 +1,4 @@ +int a(void) +{ + return 0; +} diff --git a/tests/auto/blackbox/testdata-baremetal/external-static-libraries/lib-b.c b/tests/auto/blackbox/testdata-baremetal/external-static-libraries/lib-b.c new file mode 100644 index 000000000..5d45b8175 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/external-static-libraries/lib-b.c @@ -0,0 +1,6 @@ +extern int a(void); + +int b(void) +{ + return a(); +} diff --git a/tests/auto/blackbox/testdata-baremetal/external-static-libraries/main.c b/tests/auto/blackbox/testdata-baremetal/external-static-libraries/main.c new file mode 100644 index 000000000..84ef5e51e --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/external-static-libraries/main.c @@ -0,0 +1,6 @@ +extern int b(); + +int main(void) +{ + return b(); +} diff --git a/tests/auto/blackbox/testdata-baremetal/linker-map/linker-map.qbs b/tests/auto/blackbox/testdata-baremetal/linker-map/linker-map.qbs new file mode 100644 index 000000000..fe93ac144 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/linker-map/linker-map.qbs @@ -0,0 +1,8 @@ +import "../BareMetalApplication.qbs" as BareMetalApplication + +BareMetalApplication { + property bool dummy: { + console.info("linker map suffix: %%" + cpp.linkerMapSuffix + "%%"); + } + files: ["main.c"] +} diff --git a/tests/auto/blackbox/testdata-baremetal/linker-map/main.c b/tests/auto/blackbox/testdata-baremetal/linker-map/main.c new file mode 100644 index 000000000..58fe69254 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/linker-map/main.c @@ -0,0 +1,4 @@ +int main(void) +{ + return 0; +} diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-application/main.c b/tests/auto/blackbox/testdata-baremetal/one-object-application/main.c new file mode 100644 index 000000000..58fe69254 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-application/main.c @@ -0,0 +1,4 @@ +int main(void) +{ + return 0; +} diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-application/one-object-application.qbs b/tests/auto/blackbox/testdata-baremetal/one-object-application/one-object-application.qbs new file mode 100644 index 000000000..482425b5f --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-application/one-object-application.qbs @@ -0,0 +1,5 @@ +import "../BareMetalApplication.qbs" as BareMetalApplication + +BareMetalApplication { + files: ["main.c"] +} diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/78k-iar.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/78k-iar.s new file mode 100644 index 000000000..25f0e2bbd --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/78k-iar.s @@ -0,0 +1,6 @@ + PUBLIC main + RSEG CODE:CODE:NOROOT(0) +main: + MOVW AX, #0 + RET + END diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/arm-cosmic.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/arm-cosmic.s new file mode 100644 index 000000000..4b45cc989 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/arm-cosmic.s @@ -0,0 +1,5 @@ +_main: + movs r0, #0 + bx lr + xdef _main + end diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/arm-gcc.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/arm-gcc.s new file mode 100644 index 000000000..c7b894230 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/arm-gcc.s @@ -0,0 +1,5 @@ + .global main + .type main, %function +main: + mov r0, #0 + bx lr diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/arm-iar.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/arm-iar.s new file mode 100644 index 000000000..0a13a5dc2 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/arm-iar.s @@ -0,0 +1,7 @@ + PUBLIC main + SECTION `.text`:CODE:NOROOT(1) + THUMB +main: + MOVS R0, #+0 + BX LR + END diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/arm-keil.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/arm-keil.s new file mode 100644 index 000000000..f3fcd50fe --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/arm-keil.s @@ -0,0 +1,7 @@ + THUMB + AREA ||.text||, CODE, READONLY, ALIGN = 1 +main PROC + MOVS r0, #0 + BX lr + ENDP + END diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/avr-gcc.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/avr-gcc.s new file mode 100644 index 000000000..4ba005a47 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/avr-gcc.s @@ -0,0 +1,6 @@ + .global main + .type main, %function +main: + ldi r24, 0 + ldi r25, 0 + ret diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/avr-iar.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/avr-iar.s new file mode 100644 index 000000000..49e9d476e --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/avr-iar.s @@ -0,0 +1,7 @@ + PUBLIC main + RSEG CODE:CODE:NOROOT(1) +main: + LDI R16, 0 + LDI R17, 0 + RET + END diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/avr32-gcc.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/avr32-gcc.s new file mode 100644 index 000000000..879e54150 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/avr32-gcc.s @@ -0,0 +1,8 @@ + .global main + .type main, @function +main: + stm --sp, r7, lr + mov r7, sp + mov r8, 0 + mov r12, r8 + ldm sp++, r7, pc diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/avr32-iar.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/avr32-iar.s new file mode 100644 index 000000000..c5e78896f --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/avr32-iar.s @@ -0,0 +1,7 @@ + PUBLIC main + RSEG CODE32:CODE:REORDER:NOROOT(2) + CODE +main: + MOV R12, 0x0 + RET R12 + END diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/c166-keil.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/c166-keil.s new file mode 100644 index 000000000..394bc2ae4 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/c166-keil.s @@ -0,0 +1,7 @@ +MAIN_SEG SECTION CODE WORD 'NCODE' +main PROC NEAR + MOV R4, #0 + RET +main ENDP +MAIN_SEG ENDS + END diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/cr16-iar.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/cr16-iar.s new file mode 100644 index 000000000..4a14de6a1 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/cr16-iar.s @@ -0,0 +1,6 @@ + PUBLIC main + RSEG CODE:CODE:NOROOT(0) +main: + MOVW $0, R0 + JUMP (RA) + END diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/hcs12-cosmic.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/hcs12-cosmic.s new file mode 100644 index 000000000..c33c2b32d --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/hcs12-cosmic.s @@ -0,0 +1,5 @@ +_main: + .dcall "2,0,_main" + rts + xdef _main + end diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/hcs12-iar.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/hcs12-iar.s new file mode 100644 index 000000000..4344e757f --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/hcs12-iar.s @@ -0,0 +1,7 @@ + PUBLIC main + RSEG CODE:CODE:REORDER:NOROOT(0) +main: + CLRB + CLRA + RTS + END diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/hcs8-cosmic.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/hcs8-cosmic.s new file mode 100644 index 000000000..c33c2b32d --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/hcs8-cosmic.s @@ -0,0 +1,5 @@ +_main: + .dcall "2,0,_main" + rts + xdef _main + end diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/hcs8-iar.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/hcs8-iar.s new file mode 100644 index 000000000..883dfdcad --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/hcs8-iar.s @@ -0,0 +1,6 @@ + PUBLIC main + RSEG CODE:CODE:REORDER:NOROOT(0) +main: + LDHX #0x0000 + RTS + END diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/hcs8-sdcc.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/hcs8-sdcc.s new file mode 100644 index 000000000..f47fed1be --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/hcs8-sdcc.s @@ -0,0 +1,6 @@ + .globl main + .area DSEG (PAG) + .area HOME (CODE) +main: + clra + tax diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/m16c-iar.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/m16c-iar.s new file mode 100644 index 000000000..4153f290e --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/m16c-iar.s @@ -0,0 +1,6 @@ + PUBLIC main + RSEG CODE:CODE:REORDER:NOROOT(0) +main: + MOV.W #0x0, R0 + RTS + END diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/m32c-gcc.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/m32c-gcc.s new file mode 100644 index 000000000..173c04c39 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/m32c-gcc.s @@ -0,0 +1,5 @@ + .global _main + .type _main, @function +_main: + mov.w #0, r0 + rts diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/m32c-iar.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/m32c-iar.s new file mode 100644 index 000000000..4153f290e --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/m32c-iar.s @@ -0,0 +1,6 @@ + PUBLIC main + RSEG CODE:CODE:REORDER:NOROOT(0) +main: + MOV.W #0x0, R0 + RTS + END diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/m32r-gcc.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/m32r-gcc.s new file mode 100644 index 000000000..dfcf42ca1 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/m32r-gcc.s @@ -0,0 +1,9 @@ + .global main + .type main, @function +main: + push fp + mv fp, sp + ldi r4, #0 + mv r0, r4 + pop fp + jmp lr diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/m68k-cosmic.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/m68k-cosmic.s new file mode 100644 index 000000000..811b1d79e --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/m68k-cosmic.s @@ -0,0 +1,5 @@ +_main: + .dcall "8,0,_main" + rts + xdef _main + end diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/m68k-gcc.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/m68k-gcc.s new file mode 100644 index 000000000..fdde81dae --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/m68k-gcc.s @@ -0,0 +1,7 @@ + .global main + .type main, @function +main: + link.w %fp, #0 + clr.l %d0 + unlk %fp + rts diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/m68k-iar.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/m68k-iar.s new file mode 100644 index 000000000..9811be134 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/m68k-iar.s @@ -0,0 +1,6 @@ + PUBLIC main + RSEG FCODE:CODE:NOROOT(1) +main: + CLR.L D0 + RTS + END diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/mcs251-keil.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/mcs251-keil.s new file mode 100644 index 000000000..312cc9680 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/mcs251-keil.s @@ -0,0 +1,8 @@ +PUBLIC main +MAIN_SEG SEGMENT CODE + RSEG MAIN_SEG +main PROC + XRL WR6,WR6 + RET + ENDP + END diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/mcs51-iar.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/mcs51-iar.s new file mode 100644 index 000000000..09cc64613 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/mcs51-iar.s @@ -0,0 +1,7 @@ + PUBLIC main + RSEG NEAR_CODE:CODE:NOROOT(0) +main: + MOV R2, #0x0 + MOV R3, #0x0 + RET + END diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/mcs51-keil.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/mcs51-keil.s new file mode 100644 index 000000000..28174d0e2 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/mcs51-keil.s @@ -0,0 +1,8 @@ +PUBLIC main +MAIN_SEG SEGMENT CODE + RSEG MAIN_SEG +main: + MOV R6, #0x0 + MOV R7, #0x0 + RET + END diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/mcs51-sdcc.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/mcs51-sdcc.s new file mode 100644 index 000000000..eaa6467e3 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/mcs51-sdcc.s @@ -0,0 +1,7 @@ + .globl main + .area PSEG (PAG,XDATA) + .area XSEG (XDATA) + .area HOME (CODE) +main: + mov dptr, #0x0000 + ret diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/msp430-gcc.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/msp430-gcc.s new file mode 100644 index 000000000..8e8a24980 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/msp430-gcc.s @@ -0,0 +1,5 @@ + .global main + .type main, %function +main: + mov #0, r15 + .LIRD0: diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/msp430-iar.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/msp430-iar.s new file mode 100644 index 000000000..fbabe3ba8 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/msp430-iar.s @@ -0,0 +1,6 @@ + PUBLIC main + RSEG `CODE`:CODE:REORDER:NOROOT(1) +main: + MOV.W #0x0, R12 + RET + END diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/one-object-asm-application.qbs b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/one-object-asm-application.qbs new file mode 100644 index 000000000..e8805225c --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/one-object-asm-application.qbs @@ -0,0 +1,122 @@ +import "../BareMetalApplication.qbs" as BareMetalApplication + +BareMetalApplication { + condition: { + if (qbs.toolchainType === "cosmic") { + if (qbs.architecture.startsWith("arm")) + return true; + if (qbs.architecture === "stm8") + return true; + if (qbs.architecture === "hcs8") + return true; + if (qbs.architecture === "hcs12") + return true; + if (qbs.architecture === "m68k") + return true; + } else if (qbs.toolchainType === "keil") { + if (qbs.architecture.startsWith("arm")) + return true; + if (qbs.architecture === "mcs51") + return true; + if (qbs.architecture === "mcs251") + return true; + if (qbs.architecture === "c166") + return true; + } else if (qbs.toolchainType === "iar") { + if (qbs.architecture.startsWith("arm")) + return true; + if (qbs.architecture === "mcs51") + return true; + if (qbs.architecture === "stm8") + return true; + if (qbs.architecture === "avr") + return true; + if (qbs.architecture === "avr32") + return true; + if (qbs.architecture === "msp430") + return true; + if (qbs.architecture === "rl78") + return true; + if (qbs.architecture === "rh850") + return true; + if (qbs.architecture === "v850") + return true; + if (qbs.architecture === "78k") + return true; + if (qbs.architecture === "r32c") + return true; + if (qbs.architecture === "sh") + return true; + if (qbs.architecture === "cr16") + return true; + if (qbs.architecture === "m16c") + return true; + if (qbs.architecture === "hcs8") + return true; + if (qbs.architecture === "hcs12") + return true; + if (qbs.architecture === "rx") + return true; + if (qbs.architecture === "m32c") + return true; + if (qbs.architecture === "riscv") + return true; + if (qbs.architecture === "m68k") + return true; + } else if (qbs.toolchainType === "sdcc") { + if (qbs.architecture === "mcs51") + return true; + if (qbs.architecture === "stm8") + return true; + if (qbs.architecture === "hcs8") + return true; + } else if (qbs.toolchainType === "gcc") { + if (qbs.architecture.startsWith("arm")) + return true; + if (qbs.architecture === "avr") + return true; + if (qbs.architecture === "avr32") + return true; + if (qbs.architecture === "msp430") + return true; + if (qbs.architecture === "xtensa") + return true; + if (qbs.architecture === "rl78") + return true; + if (qbs.architecture === "m32c") + return true; + if (qbs.architecture === "m32r") + return true; + if (qbs.architecture === "m68k") + return true; + if (qbs.architecture === "v850") + return true; + if (qbs.architecture === "riscv") + return true; + if (qbs.architecture === "rx") + return true; + } + console.info("unsupported toolset: %%" + + qbs.toolchainType + "%%, %%" + qbs.architecture + "%%"); + return false; + } + + Properties { + condition: qbs.toolchainType === "gcc" + && qbs.architecture === "msp430" + // We need to use this workaround to enable + // the cpp.driverFlags property. + cpp.linkerPath: cpp.compilerPathByLanguage["c"] + } + + Properties { + condition: qbs.toolchainType === "iar" + && qbs.architecture.startsWith("arm") + cpp.entryPoint: "main" + } + + cpp.linkerPath: original + + files: [(qbs.architecture.startsWith("arm") ? "arm" : qbs.architecture) + + "-" + qbs.toolchainType + ".s"] +} diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/r32c-iar.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/r32c-iar.s new file mode 100644 index 000000000..844306811 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/r32c-iar.s @@ -0,0 +1,7 @@ + PUBLIC main + RSEG CODE24:CODE:REORDER:NOROOT(0) +main: + MOV.L:Z #0x0, R2R0 + RTS + RSEG SBREF:DATA:NOROOT(0) + END diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/rh850-iar.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/rh850-iar.s new file mode 100644 index 000000000..8901027aa --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/rh850-iar.s @@ -0,0 +1,7 @@ + PUBLIC _main + SECTION `.text`:CODE:NOROOT(2) + CODE +_main: + MOV r0, r10 + JMP [lp] + END diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/riscv-gcc.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/riscv-gcc.s new file mode 100644 index 000000000..d09097804 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/riscv-gcc.s @@ -0,0 +1,11 @@ + .globl main + .type main, @function +main: + add sp, sp, -16 + sd s0, 8(sp) + add s0, sp, 16 + li a5, 0 + mv a0, a5 + ld s0, 8(sp) + add sp, sp, 16 + jr ra diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/riscv-iar.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/riscv-iar.s new file mode 100644 index 000000000..e19fdfddb --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/riscv-iar.s @@ -0,0 +1,7 @@ + PUBLIC main + SECTION `.text`:CODE:REORDER:NOROOT(2) + CODE +main: + MV A0, ZERO + RET + END diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/rl78-gcc.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/rl78-gcc.s new file mode 100644 index 000000000..59510bd01 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/rl78-gcc.s @@ -0,0 +1,11 @@ +r8 = 0xffef0 +.text + .global _main + .type _main, @function +_main: + subw sp, #2 + clrw ax + movw [sp], ax + movw r8, ax + addw sp, #2 + ret diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/rl78-iar.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/rl78-iar.s new file mode 100644 index 000000000..1f00996cc --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/rl78-iar.s @@ -0,0 +1,7 @@ + PUBLIC _main + SECTION `.text`:CODE:NOROOT(0) + CODE +_main: + CLRW AX + RET + END diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/rx-gcc.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/rx-gcc.s new file mode 100644 index 000000000..501d4cd7e --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/rx-gcc.s @@ -0,0 +1,8 @@ + .global _main + .type _main, @function +_main: + push.l r10 + mov.L r0, r10 + mov.L #0, r5 + mov.L r5, r1 + rtsd #4, r10-r10 diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/rx-iar.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/rx-iar.s new file mode 100644 index 000000000..cc1573431 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/rx-iar.s @@ -0,0 +1,5 @@ + PUBLIC _main + SECTION CODE:CODE:ROOT(2) +_main: + BRA _main + END diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/sh-iar.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/sh-iar.s new file mode 100644 index 000000000..d86780310 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/sh-iar.s @@ -0,0 +1,7 @@ + PUBLIC _main + SECTION `.code32.text`:CODE:NOROOT(2) +_main: + CODE + MOV #0, R0 + RTS/N + END diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/stm8-cosmic.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/stm8-cosmic.s new file mode 100644 index 000000000..818b0d680 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/stm8-cosmic.s @@ -0,0 +1,7 @@ + scross off +_main: + .dcall "2,0,_main" + ret + .scheck _main + xdef _main + end diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/stm8-iar.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/stm8-iar.s new file mode 100644 index 000000000..674e20de6 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/stm8-iar.s @@ -0,0 +1,7 @@ + PUBLIC main + SECTION `.near_func.text`:CODE:REORDER:NOROOT(0) + CODE +main: + CLRW X + RET + END diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/stm8-sdcc.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/stm8-sdcc.s new file mode 100644 index 000000000..1a552f4a4 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/stm8-sdcc.s @@ -0,0 +1,7 @@ + .globl main + .area DATA + .area SSEG + .area HOME +main: + clrw x + ret diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/v850-gcc.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/v850-gcc.s new file mode 100644 index 000000000..3599a1fb1 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/v850-gcc.s @@ -0,0 +1,11 @@ + .global _main + .type _main, @function +_main: + add -4, sp + st.w r29, 0[sp] + mov sp, r29 + mov 0, r10 + mov r29, sp + ld.w 0[sp], r29 + add 4, sp + jmp [r31] diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/v850-iar.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/v850-iar.s new file mode 100644 index 000000000..4ccfacd64 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/v850-iar.s @@ -0,0 +1,7 @@ + PUBLIC _main + RSEG `CODE`:CODE:NOROOT(2) + CODE +_main: + MOV zero, r1 + JMP [lp] + END diff --git a/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/xtensa-gcc.s b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/xtensa-gcc.s new file mode 100644 index 000000000..c21000905 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/one-object-asm-application/xtensa-gcc.s @@ -0,0 +1,11 @@ + .global main + .type main, @function +main: + addi sp, sp, -16 + s32i.n a15, sp, 12 + mov.n a15, sp + movi.n a2, 0 + mov.n sp, a15 + l32i.n a15, sp, 12 + addi sp, sp, 16 + ret.n diff --git a/tests/auto/blackbox/testdata-baremetal/preinclude-headers/main.c b/tests/auto/blackbox/testdata-baremetal/preinclude-headers/main.c new file mode 100644 index 000000000..755192287 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/preinclude-headers/main.c @@ -0,0 +1,4 @@ +int main(void) +{ + return PREINCLUDE_VALUE; +} diff --git a/tests/auto/blackbox/testdata-baremetal/preinclude-headers/preinclude-headers.qbs b/tests/auto/blackbox/testdata-baremetal/preinclude-headers/preinclude-headers.qbs new file mode 100644 index 000000000..0ded6ff15 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/preinclude-headers/preinclude-headers.qbs @@ -0,0 +1,18 @@ +import "../BareMetalApplication.qbs" as BareMetalApplication + +BareMetalApplication { + condition: { + if (qbs.toolchainType === "keil") { + if (qbs.architecture === "mcs51" + || qbs.architecture === "mcs251" + || qbs.architecture === "c166") { + console.info("unsupported toolset: %%" + + qbs.toolchainType + "%%, %%" + qbs.architecture + "%%"); + return false; + } + } + return true; + } + cpp.prefixHeaders: ["preinclude.h"] + files: ["main.c"] +} diff --git a/tests/auto/blackbox/testdata-baremetal/preinclude-headers/preinclude.h b/tests/auto/blackbox/testdata-baremetal/preinclude-headers/preinclude.h new file mode 100644 index 000000000..6b68e4826 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/preinclude-headers/preinclude.h @@ -0,0 +1,6 @@ +#ifndef PREINCLUDE_H +#define PREINCLUDE_H + +#define PREINCLUDE_VALUE 0 + +#endif // PREINCLUDE_H diff --git a/tests/auto/blackbox/testdata-baremetal/shared-libraries/app.c b/tests/auto/blackbox/testdata-baremetal/shared-libraries/app.c new file mode 100644 index 000000000..f2ecb5f55 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/shared-libraries/app.c @@ -0,0 +1,12 @@ +#include "../dllexport.h" + +#include <stdio.h> + +DLL_IMPORT void foo(void); + +int main(void) +{ + printf("Hello from app\n"); + foo(); + return 0; +} diff --git a/tests/auto/blackbox/testdata-baremetal/shared-libraries/shared-libraries.qbs b/tests/auto/blackbox/testdata-baremetal/shared-libraries/shared-libraries.qbs new file mode 100644 index 000000000..fded553f6 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/shared-libraries/shared-libraries.qbs @@ -0,0 +1,32 @@ +import "../BareMetalApplication.qbs" as BareMetalApplication + +Project { + condition: { + if (qbs.targetPlatform === "windows" && qbs.architecture === "x86") { + if (qbs.toolchainType === "watcom") + return true; + if (qbs.toolchainType === "dmc") + return true; + } + + if (qbs.toolchainType === "msvc") + return true; + + console.info("unsupported toolset: %%" + + qbs.toolchainType + "%%, %%" + qbs.architecture + "%%"); + return false; + } + + DynamicLibrary { + Depends { name: "cpp" } + destinationDirectory: "bin" + name: "shared" + files: ["shared.c"] + } + BareMetalApplication { + Depends { name: "shared" } + destinationDirectory: "bin" + name: "app" + files: ["app.c"] + } +} diff --git a/tests/auto/blackbox/testdata-baremetal/shared-libraries/shared.c b/tests/auto/blackbox/testdata-baremetal/shared-libraries/shared.c new file mode 100644 index 000000000..ab0c110fb --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/shared-libraries/shared.c @@ -0,0 +1,19 @@ +#include "../dllexport.h" + +#include <stdio.h> + +#ifdef __DMC__ +#include <windows.h> +#define EXPORT_FUN _export +BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) +{ + return TRUE; +} +#else +#define EXPORT_FUN +#endif // __DMC__ + +DLL_EXPORT void EXPORT_FUN foo(void) +{ + printf("Hello from lib\n"); +} diff --git a/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/a1.c b/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/a1.c new file mode 100644 index 000000000..b593e95d8 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/a1.c @@ -0,0 +1,4 @@ +int a1(void) +{ + return 0; +} diff --git a/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/a2.c b/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/a2.c new file mode 100644 index 000000000..35ab7feb3 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/a2.c @@ -0,0 +1,4 @@ +int a2(void) +{ + return 0; +} diff --git a/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/app.c b/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/app.c new file mode 100644 index 000000000..9814bfd9c --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/app.c @@ -0,0 +1,6 @@ +extern int e(void); + +int main(void) +{ + return e(); +} diff --git a/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/b.c b/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/b.c new file mode 100644 index 000000000..92df418d1 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/b.c @@ -0,0 +1,6 @@ +extern int a1(void); + +int b(void) +{ + return a1(); +} diff --git a/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/c.c b/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/c.c new file mode 100644 index 000000000..0c0e350f2 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/c.c @@ -0,0 +1,6 @@ +extern int a2(void); + +int c(void) +{ + return a2(); +} diff --git a/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/d.c b/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/d.c new file mode 100644 index 000000000..a3fc084f5 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/d.c @@ -0,0 +1,7 @@ +extern int b(void); +extern int c(void); + +int d(void) +{ + return b() + c(); +} diff --git a/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/e.c b/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/e.c new file mode 100644 index 000000000..9381e845c --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/e.c @@ -0,0 +1,7 @@ +extern int d(void); + +int e(void) +{ + return d(); +} + diff --git a/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/static-library-dependencies.qbs b/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/static-library-dependencies.qbs new file mode 100644 index 000000000..7184f47ea --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/static-library-dependencies/static-library-dependencies.qbs @@ -0,0 +1,40 @@ +import "../BareMetalApplication.qbs" as BareMetalApplication +import "../BareMetalStaticLibrary.qbs" as BareMetalStaticLibrary + +Project { + BareMetalStaticLibrary { + name: "lib-a" + Depends { name: "cpp" } + files: ["a1.c", "a2.c"] + } + BareMetalStaticLibrary { + name: "lib-b" + Depends { name: "cpp" } + Depends { name: "lib-a" } + files: ["b.c"] + } + BareMetalStaticLibrary { + name: "lib-c" + Depends { name: "cpp" } + Depends { name: "lib-a" } + files: ["c.c"] + } + BareMetalStaticLibrary { + name: "lib-d" + Depends { name: "cpp" } + Depends { name: "lib-b" } + Depends { name: "lib-c" } + files: ["d.c"] + } + BareMetalStaticLibrary { + name: "lib-e" + Depends { name: "cpp" } + Depends { name: "lib-d" } + files: ["e.c"] + } + BareMetalApplication { + name: "app" + Depends { name: "lib-e" } + files: ["app.c"] + } +} diff --git a/tests/auto/blackbox/testdata-baremetal/system-include-paths/bar/bar.h b/tests/auto/blackbox/testdata-baremetal/system-include-paths/bar/bar.h new file mode 100644 index 000000000..49ffa0b12 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/system-include-paths/bar/bar.h @@ -0,0 +1,6 @@ +#ifndef BAR_H +#define BAR_H + +#define BAR_VALUE 1 + +#endif // BAR_H diff --git a/tests/auto/blackbox/testdata-baremetal/system-include-paths/foo/foo.h b/tests/auto/blackbox/testdata-baremetal/system-include-paths/foo/foo.h new file mode 100644 index 000000000..dc510379d --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/system-include-paths/foo/foo.h @@ -0,0 +1,6 @@ +#ifndef FOO_H +#define FOO_H + +#define FOO_VALUE 1 + +#endif // FOO_H diff --git a/tests/auto/blackbox/testdata-baremetal/system-include-paths/main.c b/tests/auto/blackbox/testdata-baremetal/system-include-paths/main.c new file mode 100644 index 000000000..aabc97a0c --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/system-include-paths/main.c @@ -0,0 +1,7 @@ +#include <foo.h> +#include <bar.h> + +int main(void) +{ + return FOO_VALUE - BAR_VALUE; +} diff --git a/tests/auto/blackbox/testdata-baremetal/system-include-paths/system-include-paths.qbs b/tests/auto/blackbox/testdata-baremetal/system-include-paths/system-include-paths.qbs new file mode 100644 index 000000000..1f9fd1231 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/system-include-paths/system-include-paths.qbs @@ -0,0 +1,6 @@ +import "../BareMetalApplication.qbs" as BareMetalApplication + +BareMetalApplication { + files: ["main.c"] + cpp.systemIncludePaths: ["foo", "bar"] +} diff --git a/tests/auto/blackbox/testdata-baremetal/target-platform/target-platform.qbs b/tests/auto/blackbox/testdata-baremetal/target-platform/target-platform.qbs new file mode 100644 index 000000000..d29e7e619 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/target-platform/target-platform.qbs @@ -0,0 +1,19 @@ +Product { + Depends { name: "cpp" } + condition: { + if (qbs.toolchainType === "keil" + || qbs.toolchainType === "iar" + || qbs.toolchainType === "sdcc" + || qbs.toolchainType === "cosmic") { + var hasNoPlatform = (qbs.targetPlatform === "none"); + var hasNoOS = (qbs.targetOS.length === 1 && qbs.targetOS[0] === "none"); + console.info("has no platform: " + hasNoPlatform); + console.info("has no os: " + hasNoOS); + } else { + console.info("unsupported toolset: %%" + + qbs.toolchainType + "%%, %%" + qbs.architecture + "%%"); + return false; + } + return true; + } +} diff --git a/tests/auto/blackbox/testdata-baremetal/toolchain-probe/probes/dmc.qbs b/tests/auto/blackbox/testdata-baremetal/toolchain-probe/probes/dmc.qbs new file mode 100644 index 000000000..13f751669 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/toolchain-probe/probes/dmc.qbs @@ -0,0 +1,31 @@ +import qbs.Probes + +Product { + id: product + condition: qbs.toolchainType === "dmc" + + Depends { name: "cpp" } + + Probes.DmcProbe { + id: probe + compilerFilePath: cpp.compilerPath + enableDefinesByLanguage: cpp.enableCompilerDefinesByLanguage + _targetPlatform: qbs.targetPlatform + _targetArchitecture: qbs.architecture + _targetExtender: cpp.extenderName + } + + property bool dummy: { + if (!product.condition) + return; + if (!probe.found + || !probe.compilerDefinesByLanguage + || !probe.includePaths + || (probe.includePaths.length === 0) + || (qbs.architecture !== probe.architecture) + || (qbs.targetPlatform !== probe.targetPlatform)) { + console.info("broken probe: %%" + qbs.toolchainType + "%%, %%" + + qbs.architecture + "%%"); + } + } +} diff --git a/tests/auto/blackbox/testdata-baremetal/toolchain-probe/probes/sdcc.qbs b/tests/auto/blackbox/testdata-baremetal/toolchain-probe/probes/sdcc.qbs new file mode 100644 index 000000000..fa5f519a9 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/toolchain-probe/probes/sdcc.qbs @@ -0,0 +1,29 @@ +import qbs.Probes + +Product { + id: product + condition: qbs.toolchainType === "sdcc" + + Depends { name: "cpp" } + + Probes.SdccProbe { + id: probe + compilerFilePath: cpp.compilerPath + enableDefinesByLanguage: cpp.enableCompilerDefinesByLanguage + preferredArchitecture: qbs.architecture + } + + property bool dummy: { + if (!product.condition) + return; + if (!probe.found + || !probe.endianness + || !probe.compilerDefinesByLanguage + || !probe.includePaths + || (probe.includePaths.length === 0) + || (qbs.architecture !== probe.architecture)) { + console.info("broken probe: %%" + qbs.toolchainType + "%%, %%" + + qbs.architecture + "%%"); + } + } +} diff --git a/tests/auto/blackbox/testdata-baremetal/toolchain-probe/probes/watcom.qbs b/tests/auto/blackbox/testdata-baremetal/toolchain-probe/probes/watcom.qbs new file mode 100644 index 000000000..b7c92dc21 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/toolchain-probe/probes/watcom.qbs @@ -0,0 +1,34 @@ +import qbs.Probes + +Product { + id: product + condition: qbs.toolchainType === "watcom" + + Depends { name: "cpp" } + + Probes.WatcomProbe { + id: probe + compilerFilePath: cpp.compilerPath + enableDefinesByLanguage: cpp.enableCompilerDefinesByLanguage + _pathListSeparator: qbs.pathListSeparator + _toolchainInstallPath: cpp.toolchainInstallPath + _targetPlatform: qbs.targetPlatform + _targetArchitecture: qbs.architecture + } + + property bool dummy: { + if (!product.condition) + return; + if (!probe.found + || !probe.endianness + || !probe.compilerDefinesByLanguage + || !probe.environment + || !probe.includePaths + || (probe.includePaths.length === 0) + || (qbs.architecture !== probe.architecture) + || (qbs.targetPlatform !== probe.targetPlatform)) { + console.info("broken probe: %%" + qbs.toolchainType + "%%, %%" + + qbs.architecture + "%%"); + } + } +} diff --git a/tests/auto/blackbox/testdata-baremetal/toolchain-probe/toolchain-probe.qbs b/tests/auto/blackbox/testdata-baremetal/toolchain-probe/toolchain-probe.qbs new file mode 100644 index 000000000..36725cfde --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/toolchain-probe/toolchain-probe.qbs @@ -0,0 +1,7 @@ +Project { + references: [ + "probes/dmc.qbs", + "probes/sdcc.qbs", + "probes/watcom.qbs", + ] +} diff --git a/tests/auto/blackbox/testdata-baremetal/two-object-application/fun.c b/tests/auto/blackbox/testdata-baremetal/two-object-application/fun.c new file mode 100644 index 000000000..3b8c8f2f4 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/two-object-application/fun.c @@ -0,0 +1,4 @@ +int f(void) +{ + return 0; +} diff --git a/tests/auto/blackbox/testdata-baremetal/two-object-application/main.c b/tests/auto/blackbox/testdata-baremetal/two-object-application/main.c new file mode 100644 index 000000000..2c3d7726c --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/two-object-application/main.c @@ -0,0 +1,6 @@ +extern int f(void); + +int main(void) +{ + return f(); +} diff --git a/tests/auto/blackbox/testdata-baremetal/two-object-application/two-object-application.qbs b/tests/auto/blackbox/testdata-baremetal/two-object-application/two-object-application.qbs new file mode 100644 index 000000000..2947975ca --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/two-object-application/two-object-application.qbs @@ -0,0 +1,5 @@ +import "../BareMetalApplication.qbs" as BareMetalApplication + +BareMetalApplication { + files: ["main.c", "fun.c"] +} diff --git a/tests/auto/blackbox/testdata-baremetal/user-include-paths/bar/bar.h b/tests/auto/blackbox/testdata-baremetal/user-include-paths/bar/bar.h new file mode 100644 index 000000000..49ffa0b12 --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/user-include-paths/bar/bar.h @@ -0,0 +1,6 @@ +#ifndef BAR_H +#define BAR_H + +#define BAR_VALUE 1 + +#endif // BAR_H diff --git a/tests/auto/blackbox/testdata-baremetal/user-include-paths/foo/foo.h b/tests/auto/blackbox/testdata-baremetal/user-include-paths/foo/foo.h new file mode 100644 index 000000000..dc510379d --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/user-include-paths/foo/foo.h @@ -0,0 +1,6 @@ +#ifndef FOO_H +#define FOO_H + +#define FOO_VALUE 1 + +#endif // FOO_H diff --git a/tests/auto/blackbox/testdata-baremetal/user-include-paths/main.c b/tests/auto/blackbox/testdata-baremetal/user-include-paths/main.c new file mode 100644 index 000000000..e76e08cbe --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/user-include-paths/main.c @@ -0,0 +1,7 @@ +#include "foo.h" +#include "bar.h" + +int main(void) +{ + return FOO_VALUE - BAR_VALUE; +} diff --git a/tests/auto/blackbox/testdata-baremetal/user-include-paths/user-include-paths.qbs b/tests/auto/blackbox/testdata-baremetal/user-include-paths/user-include-paths.qbs new file mode 100644 index 000000000..23d5dbced --- /dev/null +++ b/tests/auto/blackbox/testdata-baremetal/user-include-paths/user-include-paths.qbs @@ -0,0 +1,6 @@ +import "../BareMetalApplication.qbs" as BareMetalApplication + +BareMetalApplication { + files: ["main.c"] + cpp.includePaths: ["foo", "bar"] +} diff --git a/tests/auto/blackbox/testdata-clangdb/project1/project.qbs b/tests/auto/blackbox/testdata-clangdb/project1/project.qbs index ecfc562b0..313f33ead 100644 --- a/tests/auto/blackbox/testdata-clangdb/project1/project.qbs +++ b/tests/auto/blackbox/testdata-clangdb/project1/project.qbs @@ -7,8 +7,8 @@ Project { Application { Probe { id: dummy - property bool isMingw: qbs.toolchain.contains("mingw") - property bool isMsvc: qbs.toolchain.contains("msvc") + property bool isMingw: qbs.toolchain.includes("mingw") + property bool isMsvc: qbs.toolchain.includes("msvc") property var buildEnv: cpp.buildEnv configure: { if (!buildEnv) diff --git a/tests/auto/blackbox/testdata-java/java/vehicles.qbs b/tests/auto/blackbox/testdata-java/java/vehicles.qbs index 8153efe00..8a4bb732f 100644 --- a/tests/auto/blackbox/testdata-java/java/vehicles.qbs +++ b/tests/auto/blackbox/testdata-java/java/vehicles.qbs @@ -1,4 +1,5 @@ import qbs.FileInfo +import qbs.Host import qbs.Utilities Project { @@ -6,10 +7,17 @@ Project { Depends { name: "cpp" } Depends { name: "car_jar" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } + property bool _testPlatform: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } + name: "native" files: ["engine.c"] @@ -34,7 +42,7 @@ Project { Export { Depends { name: "java" } - java.manifestClassPath: [product.targetName + ".jar"] + java.manifestClassPath: [exportingProduct.targetName + ".jar"] } } @@ -50,7 +58,7 @@ Project { Export { Depends { name: "java" } - java.manifestClassPath: [product.targetName + ".jar"] + java.manifestClassPath: [exportingProduct.targetName + ".jar"] } } @@ -68,13 +76,13 @@ Project { cpp.systemIncludePaths: { var paths = importingProduct.java.jdkIncludePaths; if (Utilities.versionCompare(importingProduct.java.version, "1.8") >= 0) { - paths.push(product.buildDirectory); // generated JNI headers + paths.push(exportingProduct.buildDirectory); // generated JNI headers } return paths; } Depends { name: "java" } - java.manifestClassPath: [product.targetName + ".jar"] + java.manifestClassPath: [exportingProduct.targetName + ".jar"] } qbs.installPrefix: "" diff --git a/tests/auto/blackbox/testdata-joblimits/job-limits-init/job-limits-init.qbs b/tests/auto/blackbox/testdata-joblimits/job-limits-init/job-limits-init.qbs new file mode 100644 index 000000000..3a0075530 --- /dev/null +++ b/tests/auto/blackbox/testdata-joblimits/job-limits-init/job-limits-init.qbs @@ -0,0 +1,10 @@ +import qbs.Host + +Product { + property bool _testPlatform: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } +} diff --git a/tests/auto/blackbox/testdata-joblimits/job-limits/job-limits.qbs b/tests/auto/blackbox/testdata-joblimits/job-limits/job-limits.qbs index 221105a64..76f54807a 100644 --- a/tests/auto/blackbox/testdata-joblimits/job-limits/job-limits.qbs +++ b/tests/auto/blackbox/testdata-joblimits/job-limits/job-limits.qbs @@ -19,7 +19,7 @@ Project { consoleApplication: true cpp.cxxLanguageVersion: "c++14" Properties { - condition: qbs.targetOS.contains("macos") + condition: qbs.targetOS.includes("macos") cpp.minimumMacosVersion: "10.9" } files: "main.cpp" @@ -37,7 +37,7 @@ Project { var cmd = new Command(explicitlyDependsOn.tool_tag[0].filePath, [output.filePath]); cmd.workingDirectory = product.buildDirectory; - cmd.description = "Running tool"; + cmd.description = "running tool"; cmd.jobPool = "singleton"; return cmd; } diff --git a/tests/auto/blackbox/testdata-joblimits/job-limits/main.cpp b/tests/auto/blackbox/testdata-joblimits/job-limits/main.cpp index ec9acba80..5f436b0e9 100644 --- a/tests/auto/blackbox/testdata-joblimits/job-limits/main.cpp +++ b/tests/auto/blackbox/testdata-joblimits/job-limits/main.cpp @@ -63,7 +63,7 @@ int main(int argc, char *argv[]) const std::string lockFilePath = std::string(argv[0]) + ".lock"; std::FILE * const lockFile = std::fopen(lockFilePath.c_str(), "w"); if (!lockFile) { - std::cerr << "cannot open lock file: " << strerror(errno) << std::endl; + std::cerr << "cannot open lock file: " << std::strerror(errno) << std::endl; return 2; } if (!tryLock(lockFile)) { @@ -71,17 +71,17 @@ int main(int argc, char *argv[]) std::cerr << "tool is exclusive" << std::endl; return 3; } else { - std::cerr << "unexpected lock failure: " << strerror(errno) << std::endl; - fclose(lockFile); + std::cerr << "unexpected lock failure: " << std::strerror(errno) << std::endl; + std::fclose(lockFile); return 4; } } std::this_thread::sleep_for(std::chrono::milliseconds(50)); - fclose(lockFile); + std::fclose(lockFile); std::FILE * const output = std::fopen(argv[1], "w"); if (!output) { - std::cerr << "cannot create output file: " << strerror(errno) << std::endl; + std::cerr << "cannot create output file: " << std::strerror(errno) << std::endl; return 5; } - fclose(output); + std::fclose(output); } diff --git a/tests/auto/blackbox/testdata-providers/allowed-values/allowed-values.qbs b/tests/auto/blackbox/testdata-providers/allowed-values/allowed-values.qbs new file mode 100644 index 000000000..e6dbaddde --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/allowed-values/allowed-values.qbs @@ -0,0 +1,4 @@ +Product { + Depends { name: "qbsmetatestmodule" } + qbsModuleProviders: "provider" +} diff --git a/tests/auto/blackbox/testdata-providers/allowed-values/module-providers/provider.qbs b/tests/auto/blackbox/testdata-providers/allowed-values/module-providers/provider.qbs new file mode 100644 index 000000000..c0e426c96 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/allowed-values/module-providers/provider.qbs @@ -0,0 +1,14 @@ +import "../../qbs-module-providers-helpers.js" as Helpers + +ModuleProvider { + isEager: false + property stringList aProperty: "zero" + PropertyOptions { + name: "aProperty" + allowedValues: ["one", "two"] + } + relativeSearchPaths: { + Helpers.writeModule(outputBaseDir, moduleName, "from_provider"); + return ""; + } +} diff --git a/tests/auto/blackbox/testdata-providers/broken-provider/broken-provider.qbs b/tests/auto/blackbox/testdata-providers/broken-provider/broken-provider.qbs new file mode 100644 index 000000000..461c7e30e --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/broken-provider/broken-provider.qbs @@ -0,0 +1,13 @@ +Project { + qbsModuleProviders: "provider_a" + name: "project" + Project { + name: "innerProject" + Product { + name: "p1" + Depends { name: "qbsothermodule"; required: false } + Depends { name: "qbsmetatestmodule" } + } + } + +} diff --git a/tests/auto/blackbox/testdata-providers/broken-provider/module-providers/provider_a.qbs b/tests/auto/blackbox/testdata-providers/broken-provider/module-providers/provider_a.qbs new file mode 100644 index 000000000..f446d2d13 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/broken-provider/module-providers/provider_a.qbs @@ -0,0 +1,5 @@ +ModuleProvider { + relativeSearchPaths: { + throw "This provider is broken"; + } +} diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/conan-module-provider.qbs b/tests/auto/blackbox/testdata-providers/conan-provider/conan-module-provider.qbs new file mode 100644 index 000000000..e8880fc96 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/conan-provider/conan-module-provider.qbs @@ -0,0 +1,11 @@ +CppApplication { + consoleApplication: true + name: "p" + files: "main.cpp" + qbsModuleProviders: "conan" + qbs.buildVariant: "release" + qbs.installPrefix: "" + install: true + Depends { name: "conanmoduleprovider.testlib" } + Depends { name: "conanmoduleprovider.testlibheader" } +} diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/conanfile.txt b/tests/auto/blackbox/testdata-providers/conan-provider/conanfile.txt new file mode 100644 index 000000000..7c40ff7d6 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/conan-provider/conanfile.txt @@ -0,0 +1,3 @@ +[requires] +conanmoduleprovider.testlib/1.2.3 +conanmoduleprovider.testlibheader/0.1.0 diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/main.cpp b/tests/auto/blackbox/testdata-providers/conan-provider/main.cpp new file mode 100644 index 000000000..6250927b3 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/conan-provider/main.cpp @@ -0,0 +1,8 @@ +#include <testlib.h> + +#include <header.h> + +int main() +{ + HelloWorld h(42 + hello()); +} diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlib/CMakeLists.txt b/tests/auto/blackbox/testdata-providers/conan-provider/testlib/CMakeLists.txt new file mode 100644 index 000000000..d186d1906 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlib/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 3.15) +project(conanmoduleprovider.testlib) + +find_package(conanmoduleprovider.testlibdep REQUIRED) + +add_library(${PROJECT_NAME} STATIC testlib.cpp) +set_target_properties(${PROJECT_NAME} PROPERTIES PUBLIC_HEADER "testlib.h") +target_link_libraries(${PROJECT_NAME} conanmoduleprovider.testlibdep::conanmoduleprovider.testlibdep) +install(TARGETS ${PROJECT_NAME}) diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlib/conanfile.py b/tests/auto/blackbox/testdata-providers/conan-provider/testlib/conanfile.py new file mode 100644 index 000000000..7cb91f9ef --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlib/conanfile.py @@ -0,0 +1,36 @@ +from conan import ConanFile +from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout, CMakeDeps +from conan.tools.files import collect_libs +import os + +class ConanModuleProviderTestlib(ConanFile): + name = "conanmoduleprovider.testlib" + license = "none" + version = "1.2.3" + + exports_sources = "*.cpp", "*.h", "CMakeLists.txt" + settings = "os", "compiler", "build_type", "arch" + + def requirements(self): + self.requires("conanmoduleprovider.testlibdep/1.2.3") + + def layout(self): + cmake_layout(self) + + def generate(self): + deps = CMakeDeps(self) + deps.generate() + tc = CMakeToolchain(self, generator="Ninja") + tc.generate() + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def package(self): + cmake = CMake(self) + cmake.install() + + def package_info(self): + self.cpp_info.libs = collect_libs(self) diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlib/testlib.cpp b/tests/auto/blackbox/testdata-providers/conan-provider/testlib/testlib.cpp new file mode 100644 index 000000000..7118dfda9 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlib/testlib.cpp @@ -0,0 +1,7 @@ +#include "testlib.h" + +#include <testlibdep.h> + +HelloWorld::HelloWorld(int x) + : m_x(foo(x)) +{} diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlib/testlib.h b/tests/auto/blackbox/testdata-providers/conan-provider/testlib/testlib.h new file mode 100644 index 000000000..11a354b70 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlib/testlib.h @@ -0,0 +1,10 @@ +#pragma once + +class HelloWorld +{ +public: + explicit HelloWorld(int x); + +private: + int m_x; +}; diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/CMakeLists.txt b/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/CMakeLists.txt new file mode 100644 index 000000000..5510a9250 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.15) +project(conanmoduleprovider.testlibdep) + +add_library(${PROJECT_NAME} STATIC testlibdep.cpp) +set_target_properties(${PROJECT_NAME} PROPERTIES PUBLIC_HEADER "testlibdep.h") +install(TARGETS ${PROJECT_NAME}) +install(FILES lorem_ipsum.txt DESTINATION share)
\ No newline at end of file diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/conanfile.py b/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/conanfile.py new file mode 100644 index 000000000..f2c577c5e --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/conanfile.py @@ -0,0 +1,35 @@ +from conan import ConanFile +from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout, CMakeDeps +from conan.tools.files import collect_libs, copy +import os + +class ConanModuleProviderTestlib(ConanFile): + name = "conanmoduleprovider.testlibdep" + license = "none" + version = "1.2.3" + + exports_sources = "*.cpp", "*.h", "*.txt" + settings = "os", "compiler", "build_type", "arch" + + def layout(self): + cmake_layout(self) + + def generate(self): + deps = CMakeDeps(self) + deps.generate() + tc = CMakeToolchain(self, generator="Ninja") + tc.generate() + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def package(self): + cmake = CMake(self) + cmake.install() + + def package_info(self): + self.cpp_info.libs = collect_libs(self) + self.cpp_info.resdirs = ['share'] + diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/lorem_ipsum.txt b/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/lorem_ipsum.txt new file mode 100644 index 000000000..d8634396c --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/lorem_ipsum.txt @@ -0,0 +1 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit.
\ No newline at end of file diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/testlibdep.cpp b/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/testlibdep.cpp new file mode 100644 index 000000000..893478c82 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/testlibdep.cpp @@ -0,0 +1,6 @@ +#include "testlibdep.h" + +int foo(int i) +{ + return i * i; +}
\ No newline at end of file diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/testlibdep.h b/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/testlibdep.h new file mode 100644 index 000000000..ca7bd3cbc --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/testlibdep.h @@ -0,0 +1,3 @@ +#pragma once + +int foo(int i);
\ No newline at end of file diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlibheader/conanfile.py b/tests/auto/blackbox/testdata-providers/conan-provider/testlibheader/conanfile.py new file mode 100644 index 000000000..6078b9750 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlibheader/conanfile.py @@ -0,0 +1,15 @@ +from conan import ConanFile +from conan.tools.files import copy + +import os + +class Recipe(ConanFile): + exports_sources = ("header.h") + version = '0.1.0' + name = 'conanmoduleprovider.testlibheader' + + def package(self): + copy(self, + "header.h", + src=self.source_folder, + dst=os.path.join(self.package_folder, "include"))
\ No newline at end of file diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlibheader/header.h b/tests/auto/blackbox/testdata-providers/conan-provider/testlibheader/header.h new file mode 100644 index 000000000..66bd50d57 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlibheader/header.h @@ -0,0 +1,6 @@ +#pragma once + +inline int hello() +{ + return 0; +}
\ No newline at end of file diff --git a/tests/auto/blackbox/testdata/fallback-module-provider/fallback-module-provider.qbs b/tests/auto/blackbox/testdata-providers/fallback-module-provider/fallback-module-provider.qbs index a798e15b3..a798e15b3 100644 --- a/tests/auto/blackbox/testdata/fallback-module-provider/fallback-module-provider.qbs +++ b/tests/auto/blackbox/testdata-providers/fallback-module-provider/fallback-module-provider.qbs diff --git a/tests/auto/blackbox/testdata/fallback-module-provider/libdir/qbsmetatestmodule.pc b/tests/auto/blackbox/testdata-providers/fallback-module-provider/libdir/qbsmetatestmodule.pc index ae4daba89..ae4daba89 100644 --- a/tests/auto/blackbox/testdata/fallback-module-provider/libdir/qbsmetatestmodule.pc +++ b/tests/auto/blackbox/testdata-providers/fallback-module-provider/libdir/qbsmetatestmodule.pc diff --git a/tests/auto/blackbox/testdata/fallback-module-provider/main.cpp b/tests/auto/blackbox/testdata-providers/fallback-module-provider/main.cpp index 442b755bf..442b755bf 100644 --- a/tests/auto/blackbox/testdata/fallback-module-provider/main.cpp +++ b/tests/auto/blackbox/testdata-providers/fallback-module-provider/main.cpp diff --git a/tests/auto/blackbox/testdata-providers/module-providers-cache/module-providers-cache.qbs b/tests/auto/blackbox/testdata-providers/module-providers-cache/module-providers-cache.qbs new file mode 100644 index 000000000..508ed84d2 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/module-providers-cache/module-providers-cache.qbs @@ -0,0 +1,11 @@ +Project { + qbsModuleProviders: ["provider_a"] + name: "project" + property string dummyProp + + Product { + name: "p1" + Depends { name: "qbsothermodule" } + Depends { name: "qbsmetatestmodule" } + } +} diff --git a/tests/auto/blackbox/testdata-providers/module-providers-cache/module-providers/provider_a.qbs b/tests/auto/blackbox/testdata-providers/module-providers-cache/module-providers/provider_a.qbs new file mode 100644 index 000000000..782cf7d25 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/module-providers-cache/module-providers/provider_a.qbs @@ -0,0 +1,9 @@ +import "../../qbs-module-providers-helpers.js" as Helpers + +ModuleProvider { + relativeSearchPaths: { + Helpers.writeModule(outputBaseDir, "qbsmetatestmodule", "from_provider_a"); + Helpers.writeModule(outputBaseDir, "qbsothermodule", "from_provider_a"); + return ""; + } +} diff --git a/tests/auto/blackbox/testdata/module-providers/main.cpp b/tests/auto/blackbox/testdata-providers/module-providers/main.cpp index 9cd29b1fe..85a4f551c 100644 --- a/tests/auto/blackbox/testdata/module-providers/main.cpp +++ b/tests/auto/blackbox/testdata-providers/module-providers/main.cpp @@ -3,4 +3,6 @@ int main() { std::cout << "The letters are " << LETTER1 << " and " << LETTER2 << std::endl; + std::cout << "The MY_DEFINE is " << MY_DEFINE << std::endl; + return 0; } diff --git a/tests/auto/blackbox/testdata-providers/module-providers/module-providers.qbs b/tests/auto/blackbox/testdata-providers/module-providers/module-providers.qbs new file mode 100644 index 000000000..89bd1a11d --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/module-providers/module-providers.qbs @@ -0,0 +1,36 @@ +import qbs.Host + +Project { + property bool enabled: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } + readonly property string beginning: "beginning" + CppApplication { + name: "app1" + property string chooseLettersFrom: project.beginning // This indirection tests QBS-1747. + Depends { name: "mygenerator.module1" } + Depends { name: "mygenerator.module2" } + Depends { name: "othergenerator" } + moduleProviders.mygenerator.chooseLettersFrom: chooseLettersFrom + moduleProviders.othergenerator.someDefines: name + files: "main.cpp" + } + CppApplication { + readonly property string end: "end" + name: "app2" + Depends { name: "mygenerator.module1" } + Depends { name: "mygenerator.module2" } + Depends { name: "othergenerator" } + Profile { + name: "myProfile" + baseProfile: project.profile + moduleProviders.mygenerator.chooseLettersFrom: product.end + moduleProviders.othergenerator.someDefines: "app2" + } + qbs.profile: "myProfile" + files: "main.cpp" + } +} diff --git a/tests/auto/blackbox/testdata/module-providers/module-providers/mygenerator/provider.qbs b/tests/auto/blackbox/testdata-providers/module-providers/module-providers/mygenerator/provider.qbs index dae02c03a..dae02c03a 100644 --- a/tests/auto/blackbox/testdata/module-providers/module-providers/mygenerator/provider.qbs +++ b/tests/auto/blackbox/testdata-providers/module-providers/module-providers/mygenerator/provider.qbs diff --git a/tests/auto/blackbox/testdata-providers/module-providers/module-providers/othergenerator/provider.qbs b/tests/auto/blackbox/testdata-providers/module-providers/module-providers/othergenerator/provider.qbs new file mode 100644 index 000000000..66557037c --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/module-providers/module-providers/othergenerator/provider.qbs @@ -0,0 +1,19 @@ +import qbs.File; +import qbs.FileInfo; +import qbs.TextFile; + +ModuleProvider { + property string someDefines + relativeSearchPaths: { + console.info("Running setup script for " + name); + var moduleDir = FileInfo.joinPaths(outputBaseDir, "modules", "othergenerator"); + File.makePath(moduleDir); + var module = new TextFile(FileInfo.joinPaths(moduleDir, "module.qbs"), TextFile.WriteOnly); + module.writeLine("Module {"); + module.writeLine(" Depends { name: 'cpp' }"); + module.writeLine(" cpp.defines: 'MY_DEFINE=\"" + someDefines + "\"'"); + module.writeLine("}"); + module.close(); + return ""; + } +} diff --git a/tests/auto/blackbox/testdata-providers/non-eager-provider/module-providers/provider_a.qbs b/tests/auto/blackbox/testdata-providers/non-eager-provider/module-providers/provider_a.qbs new file mode 100644 index 000000000..6cd9177db --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/non-eager-provider/module-providers/provider_a.qbs @@ -0,0 +1,11 @@ +import "../../qbs-module-providers-helpers.js" as Helpers + +ModuleProvider { + isEager: false + relativeSearchPaths: { + if (moduleName === "nonexistentmodule") + return undefined; + Helpers.writeModule(outputBaseDir, moduleName, "from_provider_a"); + return ""; + } +} diff --git a/tests/auto/blackbox/testdata-providers/non-eager-provider/non-eager-provider.qbs b/tests/auto/blackbox/testdata-providers/non-eager-provider/non-eager-provider.qbs new file mode 100644 index 000000000..bd3662de3 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/non-eager-provider/non-eager-provider.qbs @@ -0,0 +1,13 @@ +Project { + Product { + name: "p1" + Depends { name: "qbsmetatestmodule" } + Depends { name: "qbsothermodule" } + Depends { name: "nonexistentmodule"; required: false } + property bool dummy: { + console.info("p1.qbsmetatestmodule.prop: " + qbsmetatestmodule.prop); + console.info("p1.qbsothermodule.prop: " + qbsothermodule.prop); + } + qbsModuleProviders: "provider_a" + } +} diff --git a/tests/auto/blackbox/testdata-providers/probe-in-module-provider/module-providers/provider_a.qbs b/tests/auto/blackbox/testdata-providers/probe-in-module-provider/module-providers/provider_a.qbs new file mode 100644 index 000000000..476a83143 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/probe-in-module-provider/module-providers/provider_a.qbs @@ -0,0 +1,23 @@ +import "../../qbs-module-providers-helpers.js" as Helpers + +ModuleProvider { + property string sysroot: qbs.sysroot + Probe { + id: theProbe + property string theValue: "value" + property string dummy: sysroot + configure: { + console.info("Running probe with irrelevant value '" + dummy + "'"); + found = true; + } + } + isEager: false + property bool found: theProbe.found + property string theValue: theProbe.theValue + relativeSearchPaths: { + Helpers.writeModule(outputBaseDir, "qbsmetatestmodule", theValue, undefined, found); + if (sysroot !== qbs.sysroot) + throw "this is unexpected"; + return ""; + } +} diff --git a/tests/auto/blackbox/testdata-providers/probe-in-module-provider/probe-in-module-provider.qbs b/tests/auto/blackbox/testdata-providers/probe-in-module-provider/probe-in-module-provider.qbs new file mode 100644 index 000000000..1f2b3d387 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/probe-in-module-provider/probe-in-module-provider.qbs @@ -0,0 +1,9 @@ +Product { + qbsModuleProviders: ["provider_a"] + name: "p" + Depends { name: "qbsmetatestmodule" } + property bool dummy: { + console.info("p.qbsmetatestmodule.boolProp: " + JSON.stringify(qbsmetatestmodule.boolProp)); + console.info("p.qbsmetatestmodule.prop: " + JSON.stringify(qbsmetatestmodule.prop)); + } +} diff --git a/tests/auto/blackbox/testdata-providers/providers-properties/module-providers/provider_a.qbs b/tests/auto/blackbox/testdata-providers/providers-properties/module-providers/provider_a.qbs new file mode 100644 index 000000000..ab9d475d8 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/providers-properties/module-providers/provider_a.qbs @@ -0,0 +1,9 @@ +import "../../qbs-module-providers-helpers.js" as Helpers + +ModuleProvider { + property stringList someProp: "provider_a" + relativeSearchPaths: { + Helpers.writeModule(outputBaseDir, "qbsmetatestmodule", undefined, someProp); + return ""; + } +} diff --git a/tests/auto/blackbox/testdata-providers/providers-properties/module-providers/provider_b.qbs b/tests/auto/blackbox/testdata-providers/providers-properties/module-providers/provider_b.qbs new file mode 100644 index 000000000..1b2a79979 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/providers-properties/module-providers/provider_b.qbs @@ -0,0 +1,9 @@ +import "../../qbs-module-providers-helpers.js" as Helpers + +ModuleProvider { + property stringList someProp: "provider_b" + relativeSearchPaths: { + Helpers.writeModule(outputBaseDir, "qbsothermodule", undefined, someProp); + return ""; + } +} diff --git a/tests/auto/blackbox/testdata-providers/providers-properties/providers-properties.qbs b/tests/auto/blackbox/testdata-providers/providers-properties/providers-properties.qbs new file mode 100644 index 000000000..258a973fa --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/providers-properties/providers-properties.qbs @@ -0,0 +1,12 @@ +Product { + qbsModuleProviders: ["provider_a", "provider_b"] + name: "p" + Depends { name: "qbsmetatestmodule" } + Depends { name: "qbsothermodule" } + moduleProviders.provider_a.someProp: "someValue" + property bool dummy: { + console.info("p.qbsmetatestmodule.listProp: " + + JSON.stringify(qbsmetatestmodule.listProp)); + console.info("p.qbsothermodule.listProp: " + JSON.stringify(qbsothermodule.listProp)); + } +} diff --git a/tests/auto/blackbox/testdata-providers/qbs-module-properties-in-providers/module-providers/provider_a.qbs b/tests/auto/blackbox/testdata-providers/qbs-module-properties-in-providers/module-providers/provider_a.qbs new file mode 100644 index 000000000..95c89cd1c --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/qbs-module-properties-in-providers/module-providers/provider_a.qbs @@ -0,0 +1,9 @@ +import "../../qbs-module-providers-helpers.js" as Helpers + +ModuleProvider { + property string sysroot: qbs.sysroot + relativeSearchPaths: { + Helpers.writeModule(outputBaseDir, "qbsmetatestmodule", sysroot); + return ""; + } +} diff --git a/tests/auto/blackbox/testdata-providers/qbs-module-properties-in-providers/qbs-module-properties-in-providers.qbs b/tests/auto/blackbox/testdata-providers/qbs-module-properties-in-providers/qbs-module-properties-in-providers.qbs new file mode 100644 index 000000000..c2fc58299 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/qbs-module-properties-in-providers/qbs-module-properties-in-providers.qbs @@ -0,0 +1,34 @@ +Project { + qbsModuleProviders: "provider_a" + name: "project" + + Profile { + name: "profile1" + qbs.sysroot: "/sysroot1" + } + + Profile { + name: "profile2" + qbs.sysroot: "/sysroot2" + } + + Product { + name: "product1" + Depends { name: "qbsmetatestmodule" } + property bool dummy: { + console.info("product1.qbsmetatestmodule.prop: " + qbsmetatestmodule.prop); + } + // multiplex over profiles, sysroot should not be cached + qbs.profiles: ["profile1", "profile2"] + } + + Product { + name: "product2" + Depends { name: "qbsmetatestmodule" } + property bool dummy: { + console.info("product2.qbsmetatestmodule.prop: " + qbsmetatestmodule.prop); + } + // multiplex over profiles, sysroot should not be cached + qbs.profiles: ["profile1", "profile2"] + } +} diff --git a/tests/auto/blackbox/testdata-providers/qbs-module-providers-cli-override/module-providers/provider_a.qbs b/tests/auto/blackbox/testdata-providers/qbs-module-providers-cli-override/module-providers/provider_a.qbs new file mode 100644 index 000000000..d34d1cac5 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/qbs-module-providers-cli-override/module-providers/provider_a.qbs @@ -0,0 +1,8 @@ +import "../../qbs-module-providers-helpers.js" as Helpers + +ModuleProvider { + relativeSearchPaths: { + Helpers.writeModule(outputBaseDir, "qbsmetatestmodule", "from_provider_a"); + return ""; + } +} diff --git a/tests/auto/blackbox/testdata-providers/qbs-module-providers-cli-override/module-providers/provider_b.qbs b/tests/auto/blackbox/testdata-providers/qbs-module-providers-cli-override/module-providers/provider_b.qbs new file mode 100644 index 000000000..767e30923 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/qbs-module-providers-cli-override/module-providers/provider_b.qbs @@ -0,0 +1,9 @@ +import "../../qbs-module-providers-helpers.js" as Helpers + +ModuleProvider { + relativeSearchPaths: { + Helpers.writeModule(outputBaseDir, "qbsmetatestmodule", "from_provider_b"); + Helpers.writeModule(outputBaseDir, "qbsothermodule", "from_provider_b"); + return ""; + } +} diff --git a/tests/auto/blackbox/testdata-providers/qbs-module-providers-cli-override/qbs-module-providers-cli-override.qbs b/tests/auto/blackbox/testdata-providers/qbs-module-providers-cli-override/qbs-module-providers-cli-override.qbs new file mode 100644 index 000000000..6f94ab207 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/qbs-module-providers-cli-override/qbs-module-providers-cli-override.qbs @@ -0,0 +1,13 @@ +Project { + name: "project" + Project { + name: "innerProject" + Product { + name: "product" + Depends { name: "qbsmetatestmodule"; required: false } + property bool dummy: { + console.info("qbsmetatestmodule.prop: " + qbsmetatestmodule.prop); + } + } + } +} diff --git a/tests/auto/blackbox/testdata-providers/qbs-module-providers-compatibility/module-providers/named_provider.qbs b/tests/auto/blackbox/testdata-providers/qbs-module-providers-compatibility/module-providers/named_provider.qbs new file mode 100644 index 000000000..07114b5ef --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/qbs-module-providers-compatibility/module-providers/named_provider.qbs @@ -0,0 +1,8 @@ +import "../../qbs-module-providers-helpers.js" as Helpers + +ModuleProvider { + relativeSearchPaths: { + Helpers.writeModule(outputBaseDir, "qbsmetatestmodule", "from_named_provider"); + return ""; + } +} diff --git a/tests/auto/blackbox/testdata-providers/qbs-module-providers-compatibility/module-providers/qbsmetatestmodule/provider.qbs b/tests/auto/blackbox/testdata-providers/qbs-module-providers-compatibility/module-providers/qbsmetatestmodule/provider.qbs new file mode 100644 index 000000000..b04a52261 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/qbs-module-providers-compatibility/module-providers/qbsmetatestmodule/provider.qbs @@ -0,0 +1,8 @@ +import "../../../qbs-module-providers-helpers.js" as Helpers + +ModuleProvider { + relativeSearchPaths: { + Helpers.writeModule(outputBaseDir, "qbsmetatestmodule", "from_scoped_provider"); + return ""; + } +} diff --git a/tests/auto/blackbox/testdata-providers/qbs-module-providers-compatibility/qbs-module-providers-compatibility.qbs b/tests/auto/blackbox/testdata-providers/qbs-module-providers-compatibility/qbs-module-providers-compatibility.qbs new file mode 100644 index 000000000..7885b540a --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/qbs-module-providers-compatibility/qbs-module-providers-compatibility.qbs @@ -0,0 +1,7 @@ +Product { + name: "p" + Depends { name: "qbsmetatestmodule" } + property bool dummy: { + console.info("qbsmetatestmodule.prop: " + qbsmetatestmodule.prop); + } +} diff --git a/tests/auto/blackbox/testdata-providers/qbs-module-providers-helpers.js b/tests/auto/blackbox/testdata-providers/qbs-module-providers-helpers.js new file mode 100644 index 000000000..8b6d9e275 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/qbs-module-providers-helpers.js @@ -0,0 +1,23 @@ +var File = require("qbs.File"); +var FileInfo = require("qbs.FileInfo"); +var TextFile = require("qbs.TextFile"); +var ModUtils = require("qbs.ModUtils"); + +function writeModule(outputBaseDir, name, prop, listProp, boolProp) { + console.info("Running setup script for " + name); + var moduleDir = FileInfo.joinPaths(outputBaseDir, "modules", name); + File.makePath(moduleDir); + var module = new TextFile(FileInfo.joinPaths(moduleDir, "module.qbs"), TextFile.WriteOnly); + module.writeLine("Module {"); + module.writeLine(" property string prop: " + ModUtils.toJSLiteral(prop)); + if (listProp) { + module.writeLine(" property stringList listProp: " + + ModUtils.toJSLiteral(listProp)); + } + if (boolProp) { + module.writeLine(" property bool boolProp: " + + ModUtils.toJSLiteral(boolProp)); + } + module.writeLine("}"); + module.close(); +} diff --git a/tests/auto/blackbox/testdata-providers/qbs-module-providers/module-providers/provider_a.qbs b/tests/auto/blackbox/testdata-providers/qbs-module-providers/module-providers/provider_a.qbs new file mode 100644 index 000000000..d34d1cac5 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/qbs-module-providers/module-providers/provider_a.qbs @@ -0,0 +1,8 @@ +import "../../qbs-module-providers-helpers.js" as Helpers + +ModuleProvider { + relativeSearchPaths: { + Helpers.writeModule(outputBaseDir, "qbsmetatestmodule", "from_provider_a"); + return ""; + } +} diff --git a/tests/auto/blackbox/testdata-providers/qbs-module-providers/module-providers/provider_b.qbs b/tests/auto/blackbox/testdata-providers/qbs-module-providers/module-providers/provider_b.qbs new file mode 100644 index 000000000..767e30923 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/qbs-module-providers/module-providers/provider_b.qbs @@ -0,0 +1,9 @@ +import "../../qbs-module-providers-helpers.js" as Helpers + +ModuleProvider { + relativeSearchPaths: { + Helpers.writeModule(outputBaseDir, "qbsmetatestmodule", "from_provider_b"); + Helpers.writeModule(outputBaseDir, "qbsothermodule", "from_provider_b"); + return ""; + } +} diff --git a/tests/auto/blackbox/testdata-providers/qbs-module-providers/qbs-module-providers.qbs b/tests/auto/blackbox/testdata-providers/qbs-module-providers/qbs-module-providers.qbs new file mode 100644 index 000000000..00776a62e --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/qbs-module-providers/qbs-module-providers.qbs @@ -0,0 +1,28 @@ +Project { + qbsModuleProviders: "provider_a" + property stringList wantedProviders: qbsModuleProviders + name: "project" + Project { + name: "innerProject" + qbsModuleProviders: project.wantedProviders + Product { + name: "p1" + Depends { name: "qbsmetatestmodule" } + Depends { name: "qbsothermodule"; required: false } + property bool dummy: { + console.info("p1.qbsmetatestmodule.prop: " + qbsmetatestmodule.prop); + console.info("p1.qbsothermodule.prop: " + qbsothermodule.prop); + } + } + } + + Product { + name: "p2" + Depends { name: "qbsmetatestmodule" } + Depends { name: "qbsothermodule"; required: false } + property bool dummy: { + console.info("p2.qbsmetatestmodule.prop: " + qbsmetatestmodule.prop); + console.info("p2.qbsothermodule.prop: " + qbsothermodule.prop); + } + } +} diff --git a/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/libs/libA.cpp b/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/libs/libA.cpp new file mode 100644 index 000000000..0c5274415 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/libs/libA.cpp @@ -0,0 +1,14 @@ +#include "libA.h" + +#include <iostream> + +void foo() +{ + std::cout << "hello from foo: "; +#ifdef MYLIB_FRAMEWORK + std::cout << "bundled: yes"; +#else + std::cout << "bundled: no"; +#endif + std::cout << std::endl; +} diff --git a/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/libs/libA.h b/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/libs/libA.h new file mode 100644 index 000000000..ddaaf1609 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/libs/libA.h @@ -0,0 +1,21 @@ +#pragma once + +#if defined(_WIN32) || defined(WIN32) +# define DECL_EXPORT __declspec(dllexport) +# define DECL_IMPORT __declspec(dllimport) +#else +# define DECL_EXPORT __attribute__((visibility("default"))) +# define DECL_IMPORT __attribute__((visibility("default"))) +# endif + +#if defined(LIBA_STATIC_LIBRARY) +# define LIBA_EXPORT +#else +# if defined(MYLIB_LIBRARY) +# define LIBA_EXPORT DECL_EXPORT +# else +# define LIBA_EXPORT DECL_IMPORT +# endif +#endif + +LIBA_EXPORT void foo(); diff --git a/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/libs/libs.qbs b/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/libs/libs.qbs new file mode 100644 index 000000000..b473083c6 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/libs/libs.qbs @@ -0,0 +1,42 @@ +import qbs.FileInfo + +Project { + property bool isBundle: false + + DynamicLibrary { + Depends { name: "cpp" } + Depends { name: "bundle" } + Depends { name: "Exporter.pkgconfig" } + Exporter.pkgconfig.versionEntry: "1.0" + name: "libA" + bundle.isBundle: project.isBundle + bundle.publicHeaders: ["libA.h"] + files: "libA.cpp" + cpp.defines: { + var result = []; + if (project.isBundle) + result.push("MYLIB_FRAMEWORK"); + return result; + } + qbs.installPrefix: "/usr" + install: true + installImportLib: true + installDir: "lib" + Group { + files: ["libA.h"] + qbs.install: !project.isBundle + qbs.installDir: FileInfo.joinPaths("include", product.name) + } + Group { + fileTagsFilter: ["Exporter.pkgconfig.pc"] + qbs.install: !project.isBundle + qbs.installDir: FileInfo.joinPaths("share", "pkgconfig") + } + Export { + Depends { name: "cpp" } + cpp.defines: ["THE_MAGIC_DEFINE"] + cpp.includePaths: [FileInfo.joinPaths(exportingProduct.qbs.installPrefix, "include")] + cpp.libraryPaths: [FileInfo.joinPaths(exportingProduct.qbs.installPrefix, "lib")] + } + } +} diff --git a/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/main.cpp b/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/main.cpp new file mode 100644 index 000000000..5fa0f7eed --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/main.cpp @@ -0,0 +1,11 @@ +#include <libA/libA.h> + +#ifndef THE_MAGIC_DEFINE +#error "missing the magic define" +#endif + +int main() +{ + foo(); + return 0; +} diff --git a/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/qbspkgconfig-module-provider.qbs b/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/qbspkgconfig-module-provider.qbs new file mode 100644 index 000000000..d2b3654ae --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/qbspkgconfig-module-provider.qbs @@ -0,0 +1,6 @@ +CppApplication { + name: "p" + Depends { name: "libA" } + files: "main.cpp" + qbsModuleProviders: "qbspkgconfig" +} diff --git a/tests/auto/blackbox/testdata-providers/removal-version/module-providers/provider_a.qbs b/tests/auto/blackbox/testdata-providers/removal-version/module-providers/provider_a.qbs new file mode 100644 index 000000000..7f358acbc --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/removal-version/module-providers/provider_a.qbs @@ -0,0 +1,14 @@ +import "../../qbs-module-providers-helpers.js" as Helpers + +ModuleProvider { + isEager: false + property bool deprecated: false + PropertyOptions { + name: "deprecated" + removalVersion: "2.2.0" + } + relativeSearchPaths: { + Helpers.writeModule(outputBaseDir, moduleName, "from_provider_a"); + return ""; + } +} diff --git a/tests/auto/blackbox/testdata-providers/removal-version/removal-version.qbs b/tests/auto/blackbox/testdata-providers/removal-version/removal-version.qbs new file mode 100644 index 000000000..1aa5e2ce9 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/removal-version/removal-version.qbs @@ -0,0 +1,12 @@ +Project { + qbsModuleProviders: "provider_a" + name: "project" + Project { + name: "innerProject" + Product { + name: "p1" + Depends { name: "qbsmetatestmodule" } + } + } + +} diff --git a/tests/auto/blackbox/testdata-qt/auto-qrc/auto-qrc.qbs b/tests/auto/blackbox/testdata-qt/auto-qrc/auto-qrc.qbs index e08f89032..bdbf8b2a1 100644 --- a/tests/auto/blackbox/testdata-qt/auto-qrc/auto-qrc.qbs +++ b/tests/auto/blackbox/testdata-qt/auto-qrc/auto-qrc.qbs @@ -1,5 +1,14 @@ +import qbs.Host + Project { QtApplication { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } + name: "app" files: ["main.cpp"] diff --git a/tests/auto/blackbox/testdata-qt/dbus-adaptors/car.cpp b/tests/auto/blackbox/testdata-qt/dbus-adaptors/car.cpp index 5e4f348d2..ce1d33ed6 100644 --- a/tests/auto/blackbox/testdata-qt/dbus-adaptors/car.cpp +++ b/tests/auto/blackbox/testdata-qt/dbus-adaptors/car.cpp @@ -49,7 +49,9 @@ ****************************************************************************/ #include "car.h" -#include <QtWidgets/QtWidgets> + +#include <QtGui/QPainter> + #include <math.h> static const double Pi = 3.14159265358979323846264338327950288419717; diff --git a/tests/auto/blackbox/testdata-qt/dbus-adaptors/main.cpp b/tests/auto/blackbox/testdata-qt/dbus-adaptors/main.cpp index 0491719d7..197005215 100644 --- a/tests/auto/blackbox/testdata-qt/dbus-adaptors/main.cpp +++ b/tests/auto/blackbox/testdata-qt/dbus-adaptors/main.cpp @@ -50,9 +50,15 @@ #include "car.h" #include "car_adaptor.h" +#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) #include <QtWidgets/QApplication> #include <QtWidgets/QGraphicsView> #include <QtWidgets/QGraphicsScene> +#else +#include <QApplication> +#include <QGraphicsView> +#include <QGraphicsScene> +#endif #include <QtDBus/QDBusConnection> int main(int argc, char *argv[]) diff --git a/tests/auto/blackbox/testdata-qt/dbus-interfaces/controller.cpp b/tests/auto/blackbox/testdata-qt/dbus-interfaces/controller.cpp index eaff5c775..0f7a77efa 100644 --- a/tests/auto/blackbox/testdata-qt/dbus-interfaces/controller.cpp +++ b/tests/auto/blackbox/testdata-qt/dbus-interfaces/controller.cpp @@ -48,7 +48,8 @@ ** ****************************************************************************/ -#include <QtWidgets> +#include <QtGlobal> +#include <QtDBus/QDBusConnection> #include "controller.h" #include "car_interface.h" diff --git a/tests/auto/blackbox/testdata-qt/dbus-interfaces/main.cpp b/tests/auto/blackbox/testdata-qt/dbus-interfaces/main.cpp index fdd9fc590..c4e6ee485 100644 --- a/tests/auto/blackbox/testdata-qt/dbus-interfaces/main.cpp +++ b/tests/auto/blackbox/testdata-qt/dbus-interfaces/main.cpp @@ -48,7 +48,12 @@ ** ****************************************************************************/ -#include <QtWidgets> +#include <QtGlobal> +#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) +#include <QtWidgets/QApplication> +#else +#include <QtGui/QApplication>> +#endif #include <QtDBus> #include "controller.h" diff --git a/tests/auto/blackbox/testdata-qt/forced-moc/forced-moc.qbs b/tests/auto/blackbox/testdata-qt/forced-moc/forced-moc.qbs index a59aaa28e..064470a79 100644 --- a/tests/auto/blackbox/testdata-qt/forced-moc/forced-moc.qbs +++ b/tests/auto/blackbox/testdata-qt/forced-moc/forced-moc.qbs @@ -1,4 +1,17 @@ +import qbs.Host +import qbs.Utilities + QtApplication { + condition: { + if (Utilities.versionCompare(Qt.core.version, "5.0") < 0) { + console.info("using qt4"); + return false; + } + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } files: "main.cpp" Group { name: "QObject service provider" diff --git a/tests/auto/blackbox/testdata-qt/included-moc-cpp/included-moc-cpp.qbs b/tests/auto/blackbox/testdata-qt/included-moc-cpp/included-moc-cpp.qbs index 1ed85ccdd..265b0c9e3 100644 --- a/tests/auto/blackbox/testdata-qt/included-moc-cpp/included-moc-cpp.qbs +++ b/tests/auto/blackbox/testdata-qt/included-moc-cpp/included-moc-cpp.qbs @@ -1,6 +1,13 @@ -import qbs +import qbs.Utilities QtApplication { + condition: { + if (Utilities.versionCompare(Qt.core.version, "5.0") < 0) { + console.info("using qt4"); + return false; + } + return true; + } files: [ "main.cpp", "myobject.cpp", diff --git a/tests/auto/blackbox/testdata-qt/linker-variant/qt-linker-variant.qbs b/tests/auto/blackbox/testdata-qt/linker-variant/qt-linker-variant.qbs index ab5889007..c1a77d696 100644 --- a/tests/auto/blackbox/testdata-qt/linker-variant/qt-linker-variant.qbs +++ b/tests/auto/blackbox/testdata-qt/linker-variant/qt-linker-variant.qbs @@ -3,7 +3,7 @@ QtApplication { id: qtConfigProbe property stringList moduleConfig: Qt.core.moduleConfig configure: { - console.info("Qt requires gold: " + moduleConfig.contains("use_gold_linker")); + console.info("Qt requires gold: " + moduleConfig.includes("use_gold_linker")); } } files: "main.cpp" diff --git a/tests/auto/blackbox/testdata-qt/metatypes/metatypes.qbs b/tests/auto/blackbox/testdata-qt/metatypes/metatypes.qbs new file mode 100644 index 000000000..bbc98c934 --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/metatypes/metatypes.qbs @@ -0,0 +1,28 @@ +import qbs.Utilities + +StaticLibrary { + name: "mylib" + + Depends { name: "Qt.core" } + + qbs.installPrefix: "some-prefix" + + Probe { + id: capabilitiesChecker + property string version: Qt.core.version + configure: { + if (Utilities.versionCompare(version, "5.15") >= 0) + console.info("can generate"); + else + console.info("cannot generate"); + found = true; + } + } + + files: [ + "mocableclass1.cpp", + "mocableclass1.h", + "mocableclass2.cpp", + "unmocableclass.cpp", + ] +} diff --git a/tests/auto/blackbox/testdata-qt/metatypes/mocableclass1.cpp b/tests/auto/blackbox/testdata-qt/metatypes/mocableclass1.cpp new file mode 100644 index 000000000..06adc8ca5 --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/metatypes/mocableclass1.cpp @@ -0,0 +1,3 @@ +#include "mocableclass1.h" + +MocableClass1::MocableClass1(QObject *parent) : QObject(parent) {} diff --git a/tests/auto/blackbox/testdata-qt/metatypes/mocableclass1.h b/tests/auto/blackbox/testdata-qt/metatypes/mocableclass1.h new file mode 100644 index 000000000..020c15179 --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/metatypes/mocableclass1.h @@ -0,0 +1,8 @@ +#include <QObject> + +class MocableClass1 : public QObject +{ + Q_OBJECT +public: + MocableClass1(QObject *parent = nullptr); +}; diff --git a/tests/auto/blackbox/testdata-qt/metatypes/mocableclass2.cpp b/tests/auto/blackbox/testdata-qt/metatypes/mocableclass2.cpp new file mode 100644 index 000000000..bf538913a --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/metatypes/mocableclass2.cpp @@ -0,0 +1,10 @@ +#include <QObject> + +class MocableClass2 : public QObject +{ + Q_OBJECT +public: + MocableClass2(QObject *parent) : QObject(parent) {} +}; + +#include <mocableclass2.moc> diff --git a/tests/auto/blackbox/testdata-qt/metatypes/unmocableclass.cpp b/tests/auto/blackbox/testdata-qt/metatypes/unmocableclass.cpp new file mode 100644 index 000000000..34330d189 --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/metatypes/unmocableclass.cpp @@ -0,0 +1,7 @@ +#include <QObject> + +class UnmocableClass : public QObject +{ +public: + UnmocableClass(QObject *parent) : QObject(parent) {} +}; diff --git a/tests/auto/blackbox/testdata-qt/mixed-build-variants/mixed-build-variants.qbs b/tests/auto/blackbox/testdata-qt/mixed-build-variants/mixed-build-variants.qbs index 7d8ab1b90..dea30eef4 100644 --- a/tests/auto/blackbox/testdata-qt/mixed-build-variants/mixed-build-variants.qbs +++ b/tests/auto/blackbox/testdata-qt/mixed-build-variants/mixed-build-variants.qbs @@ -1,6 +1,6 @@ QtApplication { Properties { - condition: qbs.toolchain.contains("msvc") + condition: qbs.toolchain.includes("msvc") Qt.core.qtBuildVariant: "release" } Qt.core.qtBuildVariant: "dummy" diff --git a/tests/auto/blackbox/testdata-qt/moc-compiler-defines/main.cpp b/tests/auto/blackbox/testdata-qt/moc-compiler-defines/main.cpp new file mode 100644 index 000000000..d3b8f310e --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/moc-compiler-defines/main.cpp @@ -0,0 +1,7 @@ +#include "object.h" + +int main() +{ + QObject o; + return 0; +} diff --git a/tests/auto/blackbox/testdata-qt/moc-compiler-defines/moc-compiler-defines.qbs b/tests/auto/blackbox/testdata-qt/moc-compiler-defines/moc-compiler-defines.qbs new file mode 100644 index 000000000..e184f554e --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/moc-compiler-defines/moc-compiler-defines.qbs @@ -0,0 +1,3 @@ +QtApplication { + files: ["main.cpp", "object.h", "object.cpp"] +} diff --git a/tests/auto/blackbox/testdata-qt/moc-compiler-defines/object.cpp b/tests/auto/blackbox/testdata-qt/moc-compiler-defines/object.cpp new file mode 100644 index 000000000..7ffcf419b --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/moc-compiler-defines/object.cpp @@ -0,0 +1,6 @@ +#include "object.h" + +Object::Object(QObject *parent) : QObject(parent) +{ + +} diff --git a/tests/auto/blackbox/testdata-qt/moc-compiler-defines/object.h b/tests/auto/blackbox/testdata-qt/moc-compiler-defines/object.h new file mode 100644 index 000000000..3221d1173 --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/moc-compiler-defines/object.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2020 Ivan Komissarov (abbapoh@gmail.com) +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef OBJECT_H +#define OBJECT_H + +#include <QtCore/QObject> + +// These were not defined during the moc run (QBS-1592). +// Do not use Q_OS_UNIX here as it is a fallback value which is defined when nothing else is. +#if defined(Q_OS_DARWIN) || defined(Q_OS_LINUX) || defined(Q_OS_WIN) + +class Object : public QObject +{ + Q_OBJECT +public: + explicit Object(QObject *parent = nullptr); +}; + +#endif + +#endif // OBJECT_H diff --git a/tests/auto/blackbox/testdata-qt/no-relink-on-qdebug/lib.cpp b/tests/auto/blackbox/testdata-qt/no-relink-on-qdebug/lib.cpp new file mode 100644 index 000000000..675960f2d --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/no-relink-on-qdebug/lib.cpp @@ -0,0 +1,8 @@ +#include <QtDebug> + +#include "lib.h" + +SymbolsTest::SymbolsTest() +{ + // qDebug() << "hallo"; +} diff --git a/tests/auto/blackbox/testdata-qt/no-relink-on-qdebug/lib.h b/tests/auto/blackbox/testdata-qt/no-relink-on-qdebug/lib.h new file mode 100644 index 000000000..0cb4a23c4 --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/no-relink-on-qdebug/lib.h @@ -0,0 +1,18 @@ +#ifndef SYMBOLSTEST_H +#define SYMBOLSTEST_H + +#include <QtCore/qglobal.h> + +#if defined(SYMBOLSTEST_LIBRARY) +# define SYMBOLSTEST_EXPORT Q_DECL_EXPORT +#else +# define SYMBOLSTEST_EXPORT Q_DECL_IMPORT +#endif + +class SYMBOLSTEST_EXPORT SymbolsTest +{ + public: + SymbolsTest(); +}; + +#endif // SYMBOLSTEST_H diff --git a/tests/auto/blackbox/testdata-qt/no-relink-on-qdebug/main.cpp b/tests/auto/blackbox/testdata-qt/no-relink-on-qdebug/main.cpp new file mode 100644 index 000000000..5047a34e3 --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/no-relink-on-qdebug/main.cpp @@ -0,0 +1,3 @@ +int main() +{ +} diff --git a/tests/auto/blackbox/testdata-qt/no-relink-on-qdebug/symbols-test.qbs b/tests/auto/blackbox/testdata-qt/no-relink-on-qdebug/symbols-test.qbs new file mode 100644 index 000000000..a614d96c4 --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/no-relink-on-qdebug/symbols-test.qbs @@ -0,0 +1,27 @@ +Project { + CppApplication { + name: "app" + Depends { name: "lib" } + property bool dummy: { + console.info("is GCC: " + qbs.toolchain.includes("gcc")); + console.info("is MinGW: " + qbs.toolchain.includes("mingw")); + console.info("is Darwin: " + qbs.targetOS.includes("darwin")); + } + files: "main.cpp" + } + + DynamicLibrary { + name: "lib" + Depends { name: "Qt.core" } + + cpp.cxxLanguageVersion: "c++11" + cpp.defines: "SYMBOLSTEST_LIBRARY" + + files: [ + "lib.cpp", + "lib.h", + ] + + Export { Depends { name: "Qt.core" } } + } +} diff --git a/tests/auto/blackbox/testdata-qt/pkgconfig-qt/dump-libpath.qbs b/tests/auto/blackbox/testdata-qt/pkgconfig-qt/dump-libpath.qbs new file mode 100644 index 000000000..9aa1c5d17 --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/pkgconfig-qt/dump-libpath.qbs @@ -0,0 +1,6 @@ +QtApplication { + files: "main.cpp" + property bool test: { + console.info("libPath="+Qt.core.libPath) + } +} diff --git a/tests/auto/blackbox/testdata-qt/pkgconfig-qt/main.cpp b/tests/auto/blackbox/testdata-qt/pkgconfig-qt/main.cpp new file mode 100644 index 000000000..237c8ce18 --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/pkgconfig-qt/main.cpp @@ -0,0 +1 @@ +int main() {} diff --git a/tests/auto/blackbox/testdata-qt/pkgconfig-qt/module-providers/dummyProvider.qbs b/tests/auto/blackbox/testdata-qt/pkgconfig-qt/module-providers/dummyProvider.qbs new file mode 100644 index 000000000..6ed2ca82e --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/pkgconfig-qt/module-providers/dummyProvider.qbs @@ -0,0 +1,3 @@ +ModuleProvider { + relativeSearchPaths: "" +} diff --git a/tests/auto/blackbox/testdata-qt/pkgconfig-qt/pkgconfig-qt.qbs b/tests/auto/blackbox/testdata-qt/pkgconfig-qt/pkgconfig-qt.qbs new file mode 100644 index 000000000..a1d8d8974 --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/pkgconfig-qt/pkgconfig-qt.qbs @@ -0,0 +1,6 @@ +QtApplication { + name: "p" + files: "main.cpp" + qbsSearchPaths: "." + qbsModuleProviders: "qbspkgconfig" +} diff --git a/tests/auto/blackbox/testdata-qt/pkgconfig/pkgconfig.qbs b/tests/auto/blackbox/testdata-qt/pkgconfig/pkgconfig.qbs index 04b0097ef..b2d411154 100644 --- a/tests/auto/blackbox/testdata-qt/pkgconfig/pkgconfig.qbs +++ b/tests/auto/blackbox/testdata-qt/pkgconfig/pkgconfig.qbs @@ -1,8 +1,15 @@ +import qbs.Host import qbs.Probes Project { property string name: 'pkgconfig' CppApplication { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } name: project.name Probes.PkgConfigProbe { id: pkgConfig diff --git a/tests/auto/blackbox/testdata-qt/plugin-meta-data/plugin-meta-data.qbs b/tests/auto/blackbox/testdata-qt/plugin-meta-data/plugin-meta-data.qbs index f018b34e0..dbe64d5ea 100644 --- a/tests/auto/blackbox/testdata-qt/plugin-meta-data/plugin-meta-data.qbs +++ b/tests/auto/blackbox/testdata-qt/plugin-meta-data/plugin-meta-data.qbs @@ -1,5 +1,20 @@ +import qbs.Host +import qbs.Utilities + Project { QtApplication { + condition: { + if (Utilities.versionCompare(Qt.core.version, "5.0") < 0) { + // qt4 moc can't be used with pluginMetaData + console.info("using qt4"); + return false; + } + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } + name: "app" consoleApplication: true @@ -8,7 +23,7 @@ Project { cpp.cxxLanguageVersion: "c++11" Properties { - condition: qbs.targetOS.contains("unix") + condition: qbs.targetOS.includes("unix") cpp.rpaths: [cpp.rpathOrigin] } @@ -28,12 +43,12 @@ Project { Depends { name: "Qt.core" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } cpp.defines: [Qt.core.staticBuild ? "QT_STATICPLUGIN" : "QT_PLUGIN"] cpp.cxxLanguageVersion: "c++11" - cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined + cpp.sonamePrefix: qbs.targetOS.includes("darwin") ? "@rpath" : undefined cpp.includePaths: ["."] Qt.core.pluginMetaData: ["theKey=theValue"] diff --git a/tests/auto/blackbox/testdata-qt/plugin-support/plugin-support.qbs b/tests/auto/blackbox/testdata-qt/plugin-support/plugin-support.qbs index c554a7dc2..8e0923e94 100644 --- a/tests/auto/blackbox/testdata-qt/plugin-support/plugin-support.qbs +++ b/tests/auto/blackbox/testdata-qt/plugin-support/plugin-support.qbs @@ -1,4 +1,14 @@ +import qbs.Utilities + QtGuiApplication { + condition: { + // pluginTypes empty for Qt4 + if (Utilities.versionCompare(Qt.core.version, "5.0") < 0) { + console.info("using qt4"); + return false; + } + return true; + } Probe { id: staticProbe property bool isStaticQt: Qt.gui.isStaticLibrary diff --git a/tests/auto/blackbox/testdata-qt/qdoc/qdoc.qbs b/tests/auto/blackbox/testdata-qt/qdoc/qdoc.qbs new file mode 100644 index 000000000..4b82bc405 --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/qdoc/qdoc.qbs @@ -0,0 +1,22 @@ +import qbs.Utilities + +Product { + condition: { + var ok = Utilities.versionCompare(Qt.core.version, "5.0.0") >= 0; + if (!ok) + console.info("Qt is too old"); + return ok; + } + name: "QDoc Test" + type: ["qdoc-html", "qch"] + + Depends { name: "Qt.core" } + + files: ["qdoc.qdoc"] + + Group { + name: "main qdocconf file" + files: "qdoc.qdocconf" + fileTags: "qdocconf-main" + } +} diff --git a/tests/auto/blackbox/testdata-qt/qdoc/qdoc.qdoc b/tests/auto/blackbox/testdata-qt/qdoc/qdoc.qdoc new file mode 100644 index 000000000..9e44e0948 --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/qdoc/qdoc.qdoc @@ -0,0 +1,7 @@ +/*! + \page index.html + + \title QDoc Test + + QDoc Test is a test for QDoc. +*/
\ No newline at end of file diff --git a/tests/auto/blackbox/testdata-qt/qdoc/qdoc.qdocconf b/tests/auto/blackbox/testdata-qt/qdoc/qdoc.qdocconf new file mode 100644 index 000000000..8c82bb575 --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/qdoc/qdoc.qdocconf @@ -0,0 +1,13 @@ +project = QDoc Test +description = QDoc Test + +headerdirs = . +sourcedirs = . +exampledirs = . + +outputdir = doc/html + +qhp.projects = QDocTest +qhp.QDocTest.file = qdoctest.qhp +qhp.QDocTest.namespace = org.qt-project.QDocTest +qhp.QDocTest.virtualFolder = doc diff --git a/tests/auto/blackbox/testdata-qt/qml-debugging/qml-debugging.qbs b/tests/auto/blackbox/testdata-qt/qml-debugging/qml-debugging.qbs index 8176a7c3e..0885e6b0b 100644 --- a/tests/auto/blackbox/testdata-qt/qml-debugging/qml-debugging.qbs +++ b/tests/auto/blackbox/testdata-qt/qml-debugging/qml-debugging.qbs @@ -4,4 +4,9 @@ QtApplication { Depends { name: "Qt.quick" } Qt.quick.qmlDebugging: true files: "main.cpp" + Probe { + id: checker + property bool isGcc: qbs.toolchain.contains("gcc") + configure: { console.info("is gcc: " + isGcc); } + } } diff --git a/tests/auto/blackbox/testdata-qt/qmltyperegistrar/example.qml b/tests/auto/blackbox/testdata-qt/qmltyperegistrar/example.qml new file mode 100644 index 000000000..ef97df12d --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/qmltyperegistrar/example.qml @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// ![0] +import People 1.0 + +Person { + name: "Bob Jones" + shoeSize: 12 +} +// ![0] diff --git a/tests/auto/blackbox/testdata-qt/qmltyperegistrar/main.cpp b/tests/auto/blackbox/testdata-qt/qmltyperegistrar/main.cpp new file mode 100644 index 000000000..6c3920f04 --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/qmltyperegistrar/main.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <QCoreApplication> +#include <QQmlEngine> +#include <QQmlComponent> +#include <QDebug> +#include "person.h" + +int main(int argc, char ** argv) +{ + QCoreApplication app(argc, argv); + + QQmlEngine engine; + QQmlComponent component(&engine, QUrl("qrc:example.qml")); + auto *person = qobject_cast<Person *>(component.create()); + if (person) { + qWarning() << "The person's name is" << person->name(); + qWarning() << "They wear a" << person->shoeSize() << "sized shoe"; + } else { + qWarning() << component.errors(); + } + + return EXIT_SUCCESS; +} diff --git a/tests/auto/blackbox/testdata-qt/qmltyperegistrar/person.cpp b/tests/auto/blackbox/testdata-qt/qmltyperegistrar/person.cpp new file mode 100644 index 000000000..de4a33dd0 --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/qmltyperegistrar/person.cpp @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "person.h" + +// ![0] +Person::Person(QObject *parent) +: QObject(parent), m_shoeSize(0) +{ +} + +QString Person::name() const +{ + return m_name; +} + +void Person::setName(const QString &n) +{ + m_name = n; +} + +int Person::shoeSize() const +{ + return m_shoeSize; +} + +void Person::setShoeSize(int s) +{ + m_shoeSize = s; +} + +// ![0] diff --git a/tests/auto/blackbox/testdata-qt/qmltyperegistrar/person.h b/tests/auto/blackbox/testdata-qt/qmltyperegistrar/person.h new file mode 100644 index 000000000..530c335de --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/qmltyperegistrar/person.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef PERSON_H +#define PERSON_H + +#include <QObject> +#include <QtQml/qqml.h> + +//![0] +class Person : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString name READ name WRITE setName) + Q_PROPERTY(int shoeSize READ shoeSize WRITE setShoeSize) + QML_ELEMENT +public: + Person(QObject *parent = nullptr); + + QString name() const; + void setName(const QString &); + + int shoeSize() const; + void setShoeSize(int); + +private: + QString m_name; + int m_shoeSize; +}; +//![0] + +#endif // PERSON_H diff --git a/tests/auto/blackbox/testdata-qt/qmltyperegistrar/qmltyperegistrar.qbs b/tests/auto/blackbox/testdata-qt/qmltyperegistrar/qmltyperegistrar.qbs new file mode 100644 index 000000000..68dc83743 --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/qmltyperegistrar/qmltyperegistrar.qbs @@ -0,0 +1,33 @@ +import qbs.Utilities + +CppApplication { + name: "myapp" + Depends { name: "Qt.qml" } + + Qt.qml.importVersion: "1" + cpp.includePaths: sourceDirectory + qbs.installPrefix: "" + + files: [ + "main.cpp", + "person.cpp", + "person.h", + ] + + Group { + files: "example.qml" + fileTags: "qt.core.resource_data" + } + + Probe { + id: versionProbe + property string version: Qt.core.version + configure: { + if (Utilities.versionCompare(version, "5.15") >= 0) + console.info("has registrar"); + else + console.info("does not have registrar"); + found = true; + } + } +} diff --git a/tests/auto/blackbox/testdata-qt/qrc/i.qbs b/tests/auto/blackbox/testdata-qt/qrc/i.qbs index c005490c4..45275106d 100644 --- a/tests/auto/blackbox/testdata-qt/qrc/i.qbs +++ b/tests/auto/blackbox/testdata-qt/qrc/i.qbs @@ -1,5 +1,18 @@ +import qbs.Host +import qbs.Utilities + Project { Product { + condition: { + if (Utilities.versionCompare(Qt.core.version, "5.0") < 0) { + console.info("using qt4"); + return false; + } + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } consoleApplication: true type: "application" name: "i" diff --git a/tests/auto/blackbox/testdata-qt/qtscxml/qtscxml.qbs b/tests/auto/blackbox/testdata-qt/qtscxml/qtscxml.qbs index 991e4ddcb..6fee91479 100644 --- a/tests/auto/blackbox/testdata-qt/qtscxml/qtscxml.qbs +++ b/tests/auto/blackbox/testdata-qt/qtscxml/qtscxml.qbs @@ -1,5 +1,6 @@ import qbs.Environment import qbs.FileInfo +import qbs.Host import qbs.Utilities Project { @@ -24,6 +25,12 @@ Project { } Product { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } name: "runner" type: ["runner"] Depends { name: "app" } @@ -33,18 +40,22 @@ Project { prepare: { var cmd = new Command(input.filePath); cmd.description = "running " + input.filePath; - var pathVar; - var pathValue; - if (product.qbs.hostOS.contains("windows")) { - pathVar = "PATH"; - pathValue = FileInfo.toWindowsSeparators(input["Qt.core"].binPath); + + var envVars = {}; + if (Host.os().includes("windows")) { + envVars["PATH"] = FileInfo.toWindowsSeparators(input["Qt.core"].binPath); + } else if (Host.os().includes("macos")) { + envVars["DYLD_LIBRARY_PATH"] = input["Qt.core"].libPath; + envVars["DYLD_FRAMEWORK_PATH"] = input["Qt.core"].libPath; } else { - pathVar = "LD_LIBRARY_PATH"; - pathValue = input["Qt.core"].libPath; + envVars["LD_LIBRARY_PATH"] = input["Qt.core"].libPath; } - var oldValue = Environment.getEnv(pathVar) || ""; - var newValue = pathValue + product.qbs.pathListSeparator + oldValue; - cmd.environment = [pathVar + '=' + newValue]; + for (var varName in envVars) { + var oldValue = Environment.getEnv(varName) || ""; + var newValue = envVars[varName] + FileInfo.pathListSeparator() + oldValue; + cmd.environment.push(varName + '=' + newValue); + } + return [cmd]; } } diff --git a/tests/auto/blackbox/testdata-qt/quick-compiler/quick-compiler.qbs b/tests/auto/blackbox/testdata-qt/quick-compiler/quick-compiler.qbs index b141c8672..793d261e9 100644 --- a/tests/auto/blackbox/testdata-qt/quick-compiler/quick-compiler.qbs +++ b/tests/auto/blackbox/testdata-qt/quick-compiler/quick-compiler.qbs @@ -1,5 +1,9 @@ CppApplication { - Depends { name: "Qt.quick" } + Depends { + name: "Qt.quick" + // Must fail when using Qt4 + versionAtLeast: "5" + } Qt.quick.useCompiler: Qt.quick.compilerAvailable cpp.cxxLanguageVersion: "c++11" diff --git a/tests/auto/blackbox/testdata-qt/static-qt-plugin-linking/lib.cpp b/tests/auto/blackbox/testdata-qt/static-qt-plugin-linking/lib.cpp new file mode 100644 index 000000000..dd79cbe6c --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/static-qt-plugin-linking/lib.cpp @@ -0,0 +1 @@ +void function() {} diff --git a/tests/auto/blackbox/testdata-qt/static-qt-plugin-linking/static-qt-plugin-linking.qbs b/tests/auto/blackbox/testdata-qt/static-qt-plugin-linking/static-qt-plugin-linking.qbs index 745fe5527..e4e56bb4b 100644 --- a/tests/auto/blackbox/testdata-qt/static-qt-plugin-linking/static-qt-plugin-linking.qbs +++ b/tests/auto/blackbox/testdata-qt/static-qt-plugin-linking/static-qt-plugin-linking.qbs @@ -11,11 +11,16 @@ Product { } Group { - condition: type.contains("application") + condition: type.includes("application") files: "main.cpp" } + Group { + condition: type.includes("staticlibrary") + files: "lib.cpp" + } + Depends { name: "Qt.core" } Depends { name: "Qt.gui" } - Depends { name: "Qt.qminimal"; condition: Qt.core.staticBuild; } + Depends { name: "Qt.qminimal"; condition: Qt.core.staticBuild } } diff --git a/tests/auto/blackbox/testdata-windows/codesign/app.cpp b/tests/auto/blackbox/testdata-windows/codesign/app.cpp new file mode 100644 index 000000000..76e819701 --- /dev/null +++ b/tests/auto/blackbox/testdata-windows/codesign/app.cpp @@ -0,0 +1 @@ +int main() { return 0; } diff --git a/tests/auto/blackbox/testdata-windows/codesign/codesign.qbs b/tests/auto/blackbox/testdata-windows/codesign/codesign.qbs new file mode 100644 index 000000000..1963f6926 --- /dev/null +++ b/tests/auto/blackbox/testdata-windows/codesign/codesign.qbs @@ -0,0 +1,43 @@ +Project { + name: "p" + + property bool enableSigning: true + property string hashAlgorithm + property string subjectName + property string signingTimestamp + + CppApplication { + name: "A" + files: "app.cpp" + condition: qbs.toolchain.includes("msvc") + codesign.enableCodeSigning: project.enableSigning + codesign.hashAlgorithm: project.hashAlgorithm + codesign.subjectName: project.subjectName + codesign.signingTimestamp: project.signingTimestamp + codesign.timestampAlgorithm: "sha256" + install: true + installDir: "" + property bool dummy: { + if (codesign.codesignPath) + console.info("signtool path: %%" + codesign.codesignPath + "%%"); + } + } + + DynamicLibrary { + Depends { name: "cpp" } + name: "B" + files: "app.cpp" + condition: qbs.toolchain.includes("msvc") + codesign.enableCodeSigning: project.enableSigning + codesign.hashAlgorithm: project.hashAlgorithm + codesign.subjectName: project.subjectName + codesign.signingTimestamp: project.signingTimestamp + codesign.timestampAlgorithm: "sha256" + install: true + installDir: "" + property bool dummy: { + if (codesign.codesignPath) + console.info("signtool path: %%" + codesign.codesignPath + "%%"); + } + } +} diff --git a/tests/auto/blackbox/testdata/innosetup/inc/qbsinc.iss b/tests/auto/blackbox/testdata-windows/innosetup/inc/qbsinc.iss index e69de29bb..e69de29bb 100644 --- a/tests/auto/blackbox/testdata/innosetup/inc/qbsinc.iss +++ b/tests/auto/blackbox/testdata-windows/innosetup/inc/qbsinc.iss diff --git a/tests/auto/blackbox/testdata/innosetup/innosetup.qbs b/tests/auto/blackbox/testdata-windows/innosetup/innosetup.qbs index c9f6a22e8..fd8868900 100644 --- a/tests/auto/blackbox/testdata/innosetup/innosetup.qbs +++ b/tests/auto/blackbox/testdata-windows/innosetup/innosetup.qbs @@ -2,6 +2,11 @@ import qbs.FileInfo Project { InnoSetup { + property bool _test: { + var present = qbs.targetOS.includes("windows") && innosetup.present; + console.info("has innosetup: " + present); + } + name: "QbsSetup" targetName: "qbs.setup.test" version: "1.5" @@ -12,11 +17,9 @@ Project { innosetup.includePaths: ["inc"] innosetup.defines: ["MyProgram=" + name, "MyProgramVersion=" + version] innosetup.compilerFlags: ["/V9"] - qbs.targetPlatform: "windows" } InnoSetup { name: "Example1" files: [FileInfo.joinPaths(innosetup.toolchainInstallPath, "Examples", name + ".iss")] - qbs.targetPlatform: "windows" } } diff --git a/tests/auto/blackbox/testdata/innosetup/test.iss b/tests/auto/blackbox/testdata-windows/innosetup/test.iss index f9f9195a6..f9f9195a6 100644 --- a/tests/auto/blackbox/testdata/innosetup/test.iss +++ b/tests/auto/blackbox/testdata-windows/innosetup/test.iss diff --git a/tests/auto/blackbox/testdata/innosetupDependencies/innosetupDependencies.qbs b/tests/auto/blackbox/testdata-windows/innosetupDependencies/innosetupDependencies.qbs index db65e127f..3ef8c30e7 100644 --- a/tests/auto/blackbox/testdata/innosetupDependencies/innosetupDependencies.qbs +++ b/tests/auto/blackbox/testdata-windows/innosetupDependencies/innosetupDependencies.qbs @@ -2,6 +2,10 @@ import qbs.TextFile Project { InnoSetup { + property bool _test: { + var present = qbs.targetOS.includes("windows") && innosetup.present; + console.info("has innosetup: " + present); + } Depends { name: "app" } Depends { name: "lib" } name: "QbsSetup" diff --git a/tests/auto/blackbox/testdata-windows/innosetupDependencies/main.c b/tests/auto/blackbox/testdata-windows/innosetupDependencies/main.c new file mode 100644 index 000000000..76e819701 --- /dev/null +++ b/tests/auto/blackbox/testdata-windows/innosetupDependencies/main.c @@ -0,0 +1 @@ +int main() { return 0; } diff --git a/tests/auto/blackbox/testdata/innosetupDependencies/test.iss b/tests/auto/blackbox/testdata-windows/innosetupDependencies/test.iss index 430f9941b..430f9941b 100644 --- a/tests/auto/blackbox/testdata/innosetupDependencies/test.iss +++ b/tests/auto/blackbox/testdata-windows/innosetupDependencies/test.iss diff --git a/tests/auto/blackbox/testdata/wix/ExampleScript.bat b/tests/auto/blackbox/testdata-windows/wix/ExampleScript.bat index 3af583cd8..3af583cd8 100644 --- a/tests/auto/blackbox/testdata/wix/ExampleScript.bat +++ b/tests/auto/blackbox/testdata-windows/wix/ExampleScript.bat diff --git a/tests/auto/blackbox/testdata/wix/QbsBootstrapper.wxs b/tests/auto/blackbox/testdata-windows/wix/QbsBootstrapper.wxs index 272f6af5b..272f6af5b 100644 --- a/tests/auto/blackbox/testdata/wix/QbsBootstrapper.wxs +++ b/tests/auto/blackbox/testdata-windows/wix/QbsBootstrapper.wxs diff --git a/tests/auto/blackbox/testdata/wix/QbsSetup.wxs b/tests/auto/blackbox/testdata-windows/wix/QbsSetup.wxs index 8f97ff667..8f97ff667 100644 --- a/tests/auto/blackbox/testdata/wix/QbsSetup.wxs +++ b/tests/auto/blackbox/testdata-windows/wix/QbsSetup.wxs diff --git a/tests/auto/blackbox/testdata/wix/Qt.wxs b/tests/auto/blackbox/testdata-windows/wix/Qt.wxs index fbd992c43..fbd992c43 100644 --- a/tests/auto/blackbox/testdata/wix/Qt.wxs +++ b/tests/auto/blackbox/testdata-windows/wix/Qt.wxs diff --git a/tests/auto/blackbox/testdata/wix/WiXInstallers.qbs b/tests/auto/blackbox/testdata-windows/wix/WiXInstallers.qbs index 07f61ba2c..acc7cf7b3 100644 --- a/tests/auto/blackbox/testdata/wix/WiXInstallers.qbs +++ b/tests/auto/blackbox/testdata-windows/wix/WiXInstallers.qbs @@ -1,4 +1,5 @@ import qbs.FileInfo +import qbs.Host Project { WindowsInstallerPackage { @@ -12,14 +13,14 @@ Project { Export { Depends { name: "wix" } wix.defines: base.concat(["msiName=" + - FileInfo.joinPaths(product.buildDirectory, - product.targetName + wix.windowsInstallerSuffix)]) + FileInfo.joinPaths(exportingProduct.buildDirectory, + exportingProduct.targetName + wix.windowsInstallerSuffix)]) } } WindowsSetupPackage { Depends { name: "QbsSetup" } - condition: qbs.hostOS.contains("windows") // currently does not work in Wine with WiX 3.9 + condition: Host.os().includes("windows") // currently does not work in Wine with WiX 3.9 name: "QbsBootstrapper" targetName: "qbs-setup-" + qbs.architecture files: ["QbsBootstrapper.wxs"] diff --git a/tests/auto/blackbox/testdata/wix/de.wxl b/tests/auto/blackbox/testdata-windows/wix/de.wxl index 75394cfdd..75394cfdd 100644 --- a/tests/auto/blackbox/testdata/wix/de.wxl +++ b/tests/auto/blackbox/testdata-windows/wix/de.wxl diff --git a/tests/auto/blackbox/testdata/wixDependencies/QbsSetup.wxs b/tests/auto/blackbox/testdata-windows/wixDependencies/QbsSetup.wxs index ec839a269..ec839a269 100644 --- a/tests/auto/blackbox/testdata/wixDependencies/QbsSetup.wxs +++ b/tests/auto/blackbox/testdata-windows/wixDependencies/QbsSetup.wxs diff --git a/tests/auto/blackbox/testdata-windows/wixDependencies/main.c b/tests/auto/blackbox/testdata-windows/wixDependencies/main.c new file mode 100644 index 000000000..76e819701 --- /dev/null +++ b/tests/auto/blackbox/testdata-windows/wixDependencies/main.c @@ -0,0 +1 @@ +int main() { return 0; } diff --git a/tests/auto/blackbox/testdata/wixDependencies/wixDependencies.qbs b/tests/auto/blackbox/testdata-windows/wixDependencies/wixDependencies.qbs index d42a18054..d42a18054 100644 --- a/tests/auto/blackbox/testdata/wixDependencies/wixDependencies.qbs +++ b/tests/auto/blackbox/testdata-windows/wixDependencies/wixDependencies.qbs diff --git a/tests/auto/blackbox/testdata/allowed-values/allowed-values.qbs b/tests/auto/blackbox/testdata/allowed-values/allowed-values.qbs new file mode 100644 index 000000000..699713770 --- /dev/null +++ b/tests/auto/blackbox/testdata/allowed-values/allowed-values.qbs @@ -0,0 +1,19 @@ +Product { + Depends { name: "a" } + // tests VariantValue + property string prop + PropertyOptions { + name: "prop" + description: "Some prop" + allowedValues: "foo" + } + // tests JSValue + property string prop2 // setter for otherProp + property string otherProp: prop2 + PropertyOptions { + name: "otherProp" + description: "Some other prop" + allowedValues: "foo" + } + name: "p" +} diff --git a/tests/auto/blackbox/testdata/allowed-values/modules/a/a.qbs b/tests/auto/blackbox/testdata/allowed-values/modules/a/a.qbs new file mode 100644 index 000000000..2bbcde525 --- /dev/null +++ b/tests/auto/blackbox/testdata/allowed-values/modules/a/a.qbs @@ -0,0 +1,18 @@ +Module { + // tests VariantValue + property stringList prop + PropertyOptions { + name: "prop" + description: "Some prop" + allowedValues: ["foo", "bar"] + } + // tests JSValue + property stringList prop2 // setter for otherProp + property stringList otherProp: prop2 + PropertyOptions { + name: "otherProp" + description: "Some other prop" + allowedValues: ["foo", "bar"] + } +} + diff --git a/tests/auto/blackbox/testdata/assembly/assembly.qbs b/tests/auto/blackbox/testdata/assembly/assembly.qbs index f7bd4ecad..9d5584af5 100644 --- a/tests/auto/blackbox/testdata/assembly/assembly.qbs +++ b/tests/auto/blackbox/testdata/assembly/assembly.qbs @@ -30,9 +30,9 @@ Project { name : "testa" files : [ "testa.s" ] Depends { name: "cpp" } - condition: qbs.toolchain.contains("gcc") + condition: qbs.toolchain.includes("gcc") Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } @@ -40,9 +40,9 @@ Project { name : "testb" files : [ "testb.S" ] Depends { name: "cpp" } - condition: qbs.toolchain.contains("gcc") + condition: qbs.toolchain.includes("gcc") Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } @@ -50,9 +50,9 @@ Project { name : "testc" files : [ "testc.sx" ] Depends { name: "cpp" } - condition: qbs.toolchain.contains("gcc") + condition: qbs.toolchain.includes("gcc") Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } @@ -63,10 +63,10 @@ Project { files: ["testd_" + qbs.architecture + ".asm"] } Depends { name: "cpp" } - condition: qbs.toolchain.contains("msvc") + condition: qbs.toolchain.includes("msvc") && (qbs.architecture === "x86" || qbs.architecture === "x86_64") Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } diff --git a/tests/auto/blackbox/testdata/autotest-timeout/autotests-timeout.qbs b/tests/auto/blackbox/testdata/autotest-timeout/autotests-timeout.qbs index 49ee35d3a..b6094ed22 100644 --- a/tests/auto/blackbox/testdata/autotest-timeout/autotests-timeout.qbs +++ b/tests/auto/blackbox/testdata/autotest-timeout/autotests-timeout.qbs @@ -1,12 +1,20 @@ +import qbs.Host + Project { CppApplication { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } name: "testApp" type: ["application", "autotest"] Depends { name: "autotest" } cpp.cxxLanguageVersion: "c++11" cpp.minimumOsxVersion: "10.8" // For <chrono> Properties { - condition: qbs.toolchain.contains("gcc") + condition: qbs.toolchain.includes("gcc") cpp.driverFlags: "-pthread" } files: "test-main.cpp" @@ -14,7 +22,7 @@ Project { AutotestRunner { Depends { name: "cpp" // Make sure build environment is set up properly. - condition: qbs.hostOS.contains("windows") && qbs.toolchain.contains("gcc") + condition: Host.os().includes("windows") && qbs.toolchain.includes("gcc") } } } diff --git a/tests/auto/blackbox/testdata/autotest-with-dependencies/autotest-with-dependencies.qbs b/tests/auto/blackbox/testdata/autotest-with-dependencies/autotest-with-dependencies.qbs index 7ae6cef73..bea74796a 100644 --- a/tests/auto/blackbox/testdata/autotest-with-dependencies/autotest-with-dependencies.qbs +++ b/tests/auto/blackbox/testdata/autotest-with-dependencies/autotest-with-dependencies.qbs @@ -1,7 +1,14 @@ import qbs.FileInfo +import qbs.Host Project { CppApplication { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } name: "helper-app" type: ["application", "test-helper"] consoleApplication: true @@ -23,7 +30,7 @@ Project { AutotestRunner { Depends { name: "cpp" // Make sure build environment is set up properly. - condition: qbs.hostOS.contains("windows") && qbs.toolchain.contains("gcc") + condition: Host.os().includes("windows") && qbs.toolchain.includes("gcc") } arguments: FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix, "bin") auxiliaryInputs: "test-helper" diff --git a/tests/auto/blackbox/testdata/autotests/autotests.qbs b/tests/auto/blackbox/testdata/autotests/autotests.qbs index 10334156e..cfb7fc560 100644 --- a/tests/auto/blackbox/testdata/autotests/autotests.qbs +++ b/tests/auto/blackbox/testdata/autotests/autotests.qbs @@ -1,9 +1,17 @@ +import qbs.Host + Project { references: ["test1", "test2", "test3"] AutotestRunner { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } Depends { name: "cpp" // Make sure build environment is set up properly. - condition: qbs.hostOS.contains("windows") && qbs.toolchain.contains("gcc") + condition: Host.os().includes("windows") && qbs.toolchain.includes("gcc") } } } diff --git a/tests/auto/blackbox/testdata/badInterpreter/badInterpreter.qbs b/tests/auto/blackbox/testdata/badInterpreter/badInterpreter.qbs index bef82a003..3c8f64c6c 100644 --- a/tests/auto/blackbox/testdata/badInterpreter/badInterpreter.qbs +++ b/tests/auto/blackbox/testdata/badInterpreter/badInterpreter.qbs @@ -1,4 +1,13 @@ +import qbs.Host + Project { + property bool enabled: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } + qbsSearchPaths: base.concat(["qbs"]) Product { diff --git a/tests/auto/blackbox/testdata/build-variant-defaults/build-variant-defaults.qbs b/tests/auto/blackbox/testdata/build-variant-defaults/build-variant-defaults.qbs new file mode 100644 index 000000000..4015817ca --- /dev/null +++ b/tests/auto/blackbox/testdata/build-variant-defaults/build-variant-defaults.qbs @@ -0,0 +1,16 @@ +CppApplication { + property bool validate: { + var valid = true; + if (qbs.buildVariant === "release") { + valid = !qbs.enableDebugCode && !qbs.debugInformation && qbs.optimization === "fast"; + } else if (qbs.buildVariant === "debug") { + valid = qbs.enableDebugCode && qbs.debugInformation && qbs.optimization === "none"; + } else if (qbs.buildVariant === "profiling") { + valid = !qbs.enableDebugCode && qbs.debugInformation && qbs.optimization === "fast"; + } + + if (!valid) + throw "Invalid defaults"; + return valid; + } +} diff --git a/tests/auto/blackbox/testdata/build-variant-defaults/main.cpp b/tests/auto/blackbox/testdata/build-variant-defaults/main.cpp new file mode 100644 index 000000000..76e819701 --- /dev/null +++ b/tests/auto/blackbox/testdata/build-variant-defaults/main.cpp @@ -0,0 +1 @@ +int main() { return 0; } diff --git a/tests/auto/blackbox/testdata/buildenv-change/buildenv-change.qbs b/tests/auto/blackbox/testdata/buildenv-change/buildenv-change.qbs index 6c0bcc73e..54005e76a 100644 --- a/tests/auto/blackbox/testdata/buildenv-change/buildenv-change.qbs +++ b/tests/auto/blackbox/testdata/buildenv-change/buildenv-change.qbs @@ -3,7 +3,7 @@ CppApplication { id: dummy property stringList toolchain: qbs.toolchain configure: { - if (toolchain.contains("msvc")) + if (toolchain.includes("msvc")) console.info("msvc"); } } diff --git a/tests/auto/blackbox/testdata/capnproto/bar.capnp b/tests/auto/blackbox/testdata/capnproto/bar.capnp new file mode 100644 index 000000000..a0e8a0f8c --- /dev/null +++ b/tests/auto/blackbox/testdata/capnproto/bar.capnp @@ -0,0 +1,8 @@ +@0xc967c84bcca70a1d; + +using Foo = import "foo.capnp"; + +struct Bar { + foo @0 :Foo.Foo; + # Use type "Foo" defined in foo.capnp. +} diff --git a/tests/auto/blackbox/testdata/capnproto/baz.capnp b/tests/auto/blackbox/testdata/capnproto/baz.capnp new file mode 100644 index 000000000..8b2fe4faf --- /dev/null +++ b/tests/auto/blackbox/testdata/capnproto/baz.capnp @@ -0,0 +1,8 @@ +@0xc967c84bcca70a1d; + +using Foo = import "/imports/foo.capnp"; + +struct Baz { + foo @0 :Foo.Foo; + # Use type "Foo" defined in foo.capnp. +} diff --git a/tests/auto/blackbox/testdata/capnproto/capnproto_absolute_import.cpp b/tests/auto/blackbox/testdata/capnproto/capnproto_absolute_import.cpp new file mode 100644 index 000000000..0e8979eec --- /dev/null +++ b/tests/auto/blackbox/testdata/capnproto/capnproto_absolute_import.cpp @@ -0,0 +1,14 @@ +#include "baz.capnp.h" + +#include <capnp/message.h> + +int main() +{ + ::capnp::MallocMessageBuilder message; + + auto baz = message.initRoot<Baz>(); + auto foo = baz.initFoo(); + foo.setStr("hello"); + + return 0; +} diff --git a/tests/auto/blackbox/testdata/capnproto/capnproto_absolute_import.qbs b/tests/auto/blackbox/testdata/capnproto/capnproto_absolute_import.qbs new file mode 100644 index 000000000..4674d6a6a --- /dev/null +++ b/tests/auto/blackbox/testdata/capnproto/capnproto_absolute_import.qbs @@ -0,0 +1,21 @@ +import qbs.Host + +CppApplication { + Depends { name: "capnproto.cpp"; required: false } + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + if (!capnproto.cpp.present) + console.info("capnproto is not present"); + return result && capnproto.cpp.present; + } + cpp.minimumMacosVersion: "10.8" + capnproto.cpp.importPaths: "." + files: [ + "baz.capnp", + "capnproto_absolute_import.cpp", + "imports/foo.capnp", + ] + qbs.buildVariant: "release" +} diff --git a/tests/auto/blackbox/testdata/capnproto/capnproto_cpp.cpp b/tests/auto/blackbox/testdata/capnproto/capnproto_cpp.cpp new file mode 100644 index 000000000..b9f729955 --- /dev/null +++ b/tests/auto/blackbox/testdata/capnproto/capnproto_cpp.cpp @@ -0,0 +1,13 @@ +#include "foo.capnp.h" + +#include <capnp/message.h> + +int main() +{ + ::capnp::MallocMessageBuilder message; + + auto foo = message.initRoot<Foo>(); + foo.setStr("hello"); + + return 0; +} diff --git a/tests/auto/blackbox/testdata/capnproto/capnproto_cpp.qbs b/tests/auto/blackbox/testdata/capnproto/capnproto_cpp.qbs new file mode 100644 index 000000000..9f287e906 --- /dev/null +++ b/tests/auto/blackbox/testdata/capnproto/capnproto_cpp.qbs @@ -0,0 +1,19 @@ +import qbs.Host + +CppApplication { + Depends { name: "capnproto.cpp"; required: false } + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + if (!capnproto.cpp.present) + console.info("capnproto is not present"); + return result && capnproto.cpp.present; + } + cpp.minimumMacosVersion: "10.8" + files: [ + "capnproto_cpp.cpp", + "foo.capnp" + ] + qbs.buildVariant: "release" +} diff --git a/tests/auto/blackbox/testdata/capnproto/capnproto_relative_import.cpp b/tests/auto/blackbox/testdata/capnproto/capnproto_relative_import.cpp new file mode 100644 index 000000000..5116bd3d6 --- /dev/null +++ b/tests/auto/blackbox/testdata/capnproto/capnproto_relative_import.cpp @@ -0,0 +1,14 @@ +#include "bar.capnp.h" + +#include <capnp/message.h> + +int main() +{ + ::capnp::MallocMessageBuilder message; + + auto bar = message.initRoot<Bar>(); + auto foo = bar.initFoo(); + foo.setStr("hello"); + + return 0; +} diff --git a/tests/auto/blackbox/testdata/capnproto/capnproto_relative_import.qbs b/tests/auto/blackbox/testdata/capnproto/capnproto_relative_import.qbs new file mode 100644 index 000000000..333a3cdb9 --- /dev/null +++ b/tests/auto/blackbox/testdata/capnproto/capnproto_relative_import.qbs @@ -0,0 +1,19 @@ +import qbs.Host + +CppApplication { + Depends { name: "capnproto.cpp"; required: false } + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + if (!capnproto.cpp.present) + console.info("capnproto is not present"); + return result && capnproto.cpp.present; + } + cpp.minimumMacosVersion: "10.8" + files: [ + "bar.capnp", + "capnproto_relative_import.cpp", + "foo.capnp", + ] +} diff --git a/tests/auto/blackbox/testdata/capnproto/conanfile.txt b/tests/auto/blackbox/testdata/capnproto/conanfile.txt new file mode 100644 index 000000000..7313bb82e --- /dev/null +++ b/tests/auto/blackbox/testdata/capnproto/conanfile.txt @@ -0,0 +1,6 @@ +[requires] +capnproto/1.0.2 +[tool_requires] +capnproto/1.0.2 +[generators] +QbsDeps diff --git a/tests/auto/blackbox/testdata/capnproto/foo.capnp b/tests/auto/blackbox/testdata/capnproto/foo.capnp new file mode 100644 index 000000000..146a2969f --- /dev/null +++ b/tests/auto/blackbox/testdata/capnproto/foo.capnp @@ -0,0 +1,6 @@ +@0x8a2efe67220790be; + +struct Foo { + num @0 :UInt32; + str @1 :Text; +} diff --git a/tests/auto/blackbox/testdata/capnproto/greeter-client.cpp b/tests/auto/blackbox/testdata/capnproto/greeter-client.cpp new file mode 100644 index 000000000..d3fcdb4e3 --- /dev/null +++ b/tests/auto/blackbox/testdata/capnproto/greeter-client.cpp @@ -0,0 +1,25 @@ +#include "greeter.capnp.h" + +#include <capnp/ez-rpc.h> + +#include <iostream> + +int main(int argc, char *argv[]) +{ + const char address[] = "localhost:5050"; + capnp::EzRpcClient client(address); + Greeter::Client greeter = client.getMain<Greeter>(); + + auto& waitScope = client.getWaitScope(); + + for (int i = 0; i < 2; ++i) { + auto request = greeter.sayHelloRequest(); + request.initRequest().setName("hello workd"); + auto promise = request.send(); + + auto response = promise.wait(waitScope); + std::cout << response.getResponse().getName().cStr() << std::endl; + } + + return 0; +} diff --git a/tests/auto/blackbox/testdata/capnproto/greeter-server.cpp b/tests/auto/blackbox/testdata/capnproto/greeter-server.cpp new file mode 100644 index 000000000..a7f482cc8 --- /dev/null +++ b/tests/auto/blackbox/testdata/capnproto/greeter-server.cpp @@ -0,0 +1,27 @@ +#include "greeter.capnp.h" + +#include <capnp/ez-rpc.h> +#include <capnp/message.h> + +#include <iostream> + +class GreeterImpl final: public Greeter::Server +{ +public: + ::kj::Promise<void> sayHello(SayHelloContext context) override + { + auto response = context.getResults().initResponse(); + response.setName(context.getParams().getRequest().getName()); + return kj::READY_NOW; + }; +}; + +int main(int argc, char *argv[]) +{ + const char address[] = "localhost:5050"; + capnp::EzRpcServer server(kj::heap<GreeterImpl>(), address); + + auto& waitScope = server.getWaitScope(); + // Run forever, accepting connections and handling requests. + kj::NEVER_DONE.wait(waitScope); +} diff --git a/tests/auto/blackbox/testdata/capnproto/greeter.capnp b/tests/auto/blackbox/testdata/capnproto/greeter.capnp new file mode 100644 index 000000000..b9188f634 --- /dev/null +++ b/tests/auto/blackbox/testdata/capnproto/greeter.capnp @@ -0,0 +1,13 @@ +@0x85150b117366d14b; + +struct HelloRequest { + name @0 :Text; +} + +struct HelloResponse { + name @0 :Text; +} + +interface Greeter { + sayHello @0 (request: HelloRequest) -> (response: HelloResponse); +} diff --git a/tests/auto/blackbox/testdata/capnproto/greeter_cpp.qbs b/tests/auto/blackbox/testdata/capnproto/greeter_cpp.qbs new file mode 100644 index 000000000..5fc5464b1 --- /dev/null +++ b/tests/auto/blackbox/testdata/capnproto/greeter_cpp.qbs @@ -0,0 +1,39 @@ +import qbs.Host + +Project { + CppApplication { + Depends { name: "capnproto.cpp"; required: false } + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + if (!capnproto.cpp.present) + console.info("capnproto is not present"); + return result && capnproto.cpp.present; + } + name: "server" + consoleApplication: true + cpp.minimumMacosVersion: "10.8" + // workaround for broken capnproto + cpp.staticLibraries: qbs.targetOS.contains("windows") ? "Advapi32" : [] + capnproto.cpp.useRpc: true + files: [ + "greeter.capnp", + "greeter-server.cpp" + ] + qbs.buildVariant: "release" + } + CppApplication { + Depends { name: "capnproto.cpp"; required: false } + name: "client" + consoleApplication: true + capnproto.cpp.useRpc: true + cpp.minimumMacosVersion: "10.8" + cpp.staticLibraries: qbs.targetOS.contains("windows") ? "Advapi32" : [] + files: [ + "greeter.capnp", + "greeter-client.cpp" + ] + qbs.buildVariant: "release" + } +} diff --git a/tests/auto/blackbox/testdata/capnproto/imports/foo.capnp b/tests/auto/blackbox/testdata/capnproto/imports/foo.capnp new file mode 100644 index 000000000..146a2969f --- /dev/null +++ b/tests/auto/blackbox/testdata/capnproto/imports/foo.capnp @@ -0,0 +1,6 @@ +@0x8a2efe67220790be; + +struct Foo { + num @0 :UInt32; + str @1 :Text; +} diff --git a/tests/auto/blackbox/testdata/change-in-imported-file/change-in-imported-file.qbs b/tests/auto/blackbox/testdata/change-in-imported-file/change-in-imported-file.qbs index cf5354268..011eedc91 100644 --- a/tests/auto/blackbox/testdata/change-in-imported-file/change-in-imported-file.qbs +++ b/tests/auto/blackbox/testdata/change-in-imported-file/change-in-imported-file.qbs @@ -15,7 +15,7 @@ Product { prepare: { var cmd = new JavaScriptCommand(); PrepareHelper.prepare(cmd); - cmd.description = "Creating output"; + cmd.description = "creating output"; return [cmd]; } } diff --git a/tests/auto/blackbox/testdata/change-tracking-and-multiplexing/change-tracking-and-multiplexing.qbs b/tests/auto/blackbox/testdata/change-tracking-and-multiplexing/change-tracking-and-multiplexing.qbs index d1215355c..096778cd3 100644 --- a/tests/auto/blackbox/testdata/change-tracking-and-multiplexing/change-tracking-and-multiplexing.qbs +++ b/tests/auto/blackbox/testdata/change-tracking-and-multiplexing/change-tracking-and-multiplexing.qbs @@ -1,8 +1,8 @@ StaticLibrary { name: "l" - Depends { condition: qbs.targetOS.contains("darwin"); name: "bundle" } - Properties { condition: qbs.targetOS.contains("darwin"); bundle.isBundle: false } + Depends { condition: qbs.targetOS.includes("darwin"); name: "bundle" } + Properties { condition: qbs.targetOS.includes("darwin"); bundle.isBundle: false } multiplexByQbsProperties: ["buildVariants"] qbs.buildVariants: ["debug", "release"] diff --git a/tests/auto/blackbox/testdata/choose-module-instance/other-searchpath/modules/limerick/generic.qbs b/tests/auto/blackbox/testdata/choose-module-instance/other-searchpath/modules/limerick/generic.qbs index 2ebaaac11..bd8e901c7 100644 --- a/tests/auto/blackbox/testdata/choose-module-instance/other-searchpath/modules/limerick/generic.qbs +++ b/tests/auto/blackbox/testdata/choose-module-instance/other-searchpath/modules/limerick/generic.qbs @@ -1,3 +1,3 @@ Module { - condition: !qbs.targetOS.contains("Beatles") + condition: !qbs.targetOS.includes("Beatles") } diff --git a/tests/auto/blackbox/testdata/clean/clean.qbs b/tests/auto/blackbox/testdata/clean/clean.qbs index ce3a8eb12..10eca2d41 100644 --- a/tests/auto/blackbox/testdata/clean/clean.qbs +++ b/tests/auto/blackbox/testdata/clean/clean.qbs @@ -5,7 +5,7 @@ Project { name: "dep" files: "dep.cpp" Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } diff --git a/tests/auto/blackbox/testdata/cli/dotnettest.qbs b/tests/auto/blackbox/testdata/cli/dotnettest.qbs index 9a10b8068..5685be8c4 100644 --- a/tests/auto/blackbox/testdata/cli/dotnettest.qbs +++ b/tests/auto/blackbox/testdata/cli/dotnettest.qbs @@ -1,7 +1,7 @@ Project { Application { Depends { name: "cli" } - Depends { name: "HelloWorldModule"; condition: !qbs.toolchain.contains("mono") } + Depends { name: "HelloWorldModule"; condition: !qbs.toolchain.includes("mono") } Depends { name: "NetLib" } type: "application" @@ -16,7 +16,7 @@ Project { // Mono's VB compiler doesn't support modules yet, and if we try with C#, it crashes anyways NetModule { - condition: !qbs.toolchain.contains("mono") + condition: !qbs.toolchain.includes("mono") Depends { name: "cli" } name: "HelloWorldModule" @@ -37,7 +37,7 @@ Project { // fill-in for missing NetModule Group { - condition: qbs.toolchain.contains("mono") + condition: qbs.toolchain.includes("mono") files: ["Module.cs"] } diff --git a/tests/auto/blackbox/testdata/command-file/command-file.qbs b/tests/auto/blackbox/testdata/command-file/command-file.qbs index 8e25221c5..87dd0e054 100644 --- a/tests/auto/blackbox/testdata/command-file/command-file.qbs +++ b/tests/auto/blackbox/testdata/command-file/command-file.qbs @@ -4,7 +4,7 @@ Project { destinationDirectory: project.buildDirectory Depends { name: "cpp" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } files: ["lib.cpp"] @@ -14,6 +14,6 @@ Project { cpp.libraryPaths: project.buildDirectory files: ["main.cpp"] cpp.staticLibraries: ['@' + sourceDirectory + '/' - + (qbs.toolchain.contains("msvc") ? "list.msvc" : "list.gcc")] + + (qbs.toolchain.includes("msvc") ? "list.msvc" : "list.gcc")] } } diff --git a/tests/auto/blackbox/testdata/compilerDefinesByLanguage/CppDefinesApp.qbs b/tests/auto/blackbox/testdata/compilerDefinesByLanguage/CppDefinesApp.qbs index b205ef2a7..f2da212f6 100644 --- a/tests/auto/blackbox/testdata/compilerDefinesByLanguage/CppDefinesApp.qbs +++ b/tests/auto/blackbox/testdata/compilerDefinesByLanguage/CppDefinesApp.qbs @@ -1,7 +1,7 @@ CppApplication { files: ["app.c"] - property bool enableObjectiveC: qbs.targetOS.contains("darwin") + property bool enableObjectiveC: qbs.targetOS.includes("darwin") Group { name: "C/C++" diff --git a/tests/auto/blackbox/testdata/conanfile-probe/testapp/conanfile-probe-project.qbs b/tests/auto/blackbox/testdata/conanfile-probe/testapp/conanfile-probe-project.qbs new file mode 100644 index 000000000..adcb2bd9c --- /dev/null +++ b/tests/auto/blackbox/testdata/conanfile-probe/testapp/conanfile-probe-project.qbs @@ -0,0 +1,23 @@ +import qbs.Probes +import qbs.TextFile + +Project { + readonly property bool forceFailure: false + + Probes.ConanfileProbe { + id: conan + conanfilePath: path + "/conanfile.py" + options: ({opt: "True", forceFailure: (project.forceFailure ? "True" : "False")}) + settings: ({os: "AIX"}) + } + + property var check: { + var tf = new TextFile(buildDirectory + "/results.json", TextFile.WriteOnly); + var o = { + json: conan.json.deps_env_info["ENV_VAR"], + dependencies: conan.dependencies["testlib"].libs, + generatedFilesPath: conan.generatedFilesPath + }; + tf.write(JSON.stringify(o)); + } +} diff --git a/tests/auto/blackbox/testdata/conanfile-probe/testapp/conanfile.py b/tests/auto/blackbox/testdata/conanfile-probe/testapp/conanfile.py new file mode 100644 index 000000000..59e40cc80 --- /dev/null +++ b/tests/auto/blackbox/testdata/conanfile-probe/testapp/conanfile.py @@ -0,0 +1,26 @@ +from conans import ConanFile + +class TestApp(ConanFile): + name = "testapp" + description = "Our project package, to be inspected by the Qbs ConanfileProbe" + license = "none" + version = "6.6.6" + + settings = "os" + options = {"opt": [True, False], "forceFailure": [True, False]} + default_options = {"opt": False, "forceFailure": False} + + requires = "testlib/1.2.3@qbs/testing" + + def configure(self): + assert(not self.options.forceFailure) + self.options["testlib"].opt = self.options.opt + + def source(self): + pass + + def build(self): + pass + + def package(self): + pass diff --git a/tests/auto/blackbox/testdata/conanfile-probe/testlib/conanfile.py b/tests/auto/blackbox/testdata/conanfile-probe/testlib/conanfile.py new file mode 100644 index 000000000..983c22599 --- /dev/null +++ b/tests/auto/blackbox/testdata/conanfile-probe/testlib/conanfile.py @@ -0,0 +1,25 @@ +from conans import ConanFile + +class Testlib(ConanFile): + name = "testlib" + description = "Represents an arbitrary package, for instance on bintray" + license = "none" + version = "1.2.3" + + settings = "os" + options = {"opt": [True, False]} + default_options = {"opt": False} + + def source(self): + pass + + def build(self): + pass + + def package(self): + pass + + def package_info(self): + self.cpp_info.libs = ["testlib1","testlib2"] + self.env_info.ENV_VAR = "TESTLIB_ENV_VAL" + self.user_info.user_var = "testlib_user_val" diff --git a/tests/auto/blackbox/testdata/concurrent-executor/concurrent-executor.qbs b/tests/auto/blackbox/testdata/concurrent-executor/concurrent-executor.qbs deleted file mode 100644 index 802aa1450..000000000 --- a/tests/auto/blackbox/testdata/concurrent-executor/concurrent-executor.qbs +++ /dev/null @@ -1,67 +0,0 @@ -import qbs.File -import qbs.TextFile -import "util.js" as Utils - -Product { - type: ["final1", "final2"] - Group { - files: ["dummy1.input"] - fileTags: ["input1"] - } - Group { - files: ["dummy2.input"] - fileTags: ["input2"] - } - Rule { - inputs: ["input1"] - Artifact { - filePath: project.buildDirectory + "/dummy1.final" - fileTags: ["final1"] - } - prepare: { - var cmds = []; - for (var i = 0; i < 10; ++i) { - var cmd = new JavaScriptCommand(); - cmd.silent = true; - cmd.createFile = i == 9; - cmd.sourceCode = function() { - if (createFile) { - console.info("Creating file"); - var file = new TextFile(output.filePath, TextFile.WriteOnly); - file.close(); - } - }; - cmds.push(cmd); - } - return cmds; - } - } - Rule { - inputs: ["input2"] - Artifact { - filePath: "dummy.intermediate" - fileTags: ["intermediate"] - } - prepare: { - var cmd = new JavaScriptCommand(); - cmd.silent = true; - cmd.sourceCode = function() { }; - return [cmd]; - } - } - Rule { - inputs: ["intermediate"] - outputFileTags: "final2" - prepare: { - do - Utils.sleep(6000); - while (!File.exists(project.buildDirectory + "/dummy1.final")); - var cmd = new JavaScriptCommand(); - cmd.silent = true; - cmd.sourceCode = function() { }; - return [cmd]; - } - } -} - - diff --git a/tests/auto/blackbox/testdata/concurrent-executor/util.js b/tests/auto/blackbox/testdata/concurrent-executor/util.js deleted file mode 100644 index a37a8cbb1..000000000 --- a/tests/auto/blackbox/testdata/concurrent-executor/util.js +++ /dev/null @@ -1,8 +0,0 @@ -function sleep(timeInMs) -{ - var referenceTime = new Date(); - var time = null; - do { - time = new Date(); - } while (time - referenceTime < timeInMs); -} diff --git a/tests/auto/blackbox/testdata/conditional-filetagger/conditional-filetagger.qbs b/tests/auto/blackbox/testdata/conditional-filetagger/conditional-filetagger.qbs index 5f0c93e46..f5d7ad676 100644 --- a/tests/auto/blackbox/testdata/conditional-filetagger/conditional-filetagger.qbs +++ b/tests/auto/blackbox/testdata/conditional-filetagger/conditional-filetagger.qbs @@ -1,7 +1,7 @@ CppApplication { name: "theApp" property bool enableTagger - files: ["main.custom"]; + files: ["main.custom"] FileTagger { condition: enableTagger patterns: ["*.custom"] diff --git a/tests/auto/blackbox/testdata/configure/configure.qbs b/tests/auto/blackbox/testdata/configure/configure.qbs index af5638dde..be0e65247 100644 --- a/tests/auto/blackbox/testdata/configure/configure.qbs +++ b/tests/auto/blackbox/testdata/configure/configure.qbs @@ -1,6 +1,13 @@ import qbs.FileInfo +import qbs.Host Project { + property bool enabled: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } property string name: 'configure' qbsSearchPaths: '.' Product { diff --git a/tests/auto/blackbox/testdata/configure/main.cpp b/tests/auto/blackbox/testdata/configure/main.cpp index c7213c768..a91914f73 100644 --- a/tests/auto/blackbox/testdata/configure/main.cpp +++ b/tests/auto/blackbox/testdata/configure/main.cpp @@ -30,7 +30,7 @@ int main() { - printf("%s..\n", TEXT); + std::printf("%s..\n", TEXT); return 0; } diff --git a/tests/auto/blackbox/testdata/configure/modules/definition/module.qbs b/tests/auto/blackbox/testdata/configure/modules/definition/module.qbs index 1d647faa2..6a1dbe67d 100644 --- a/tests/auto/blackbox/testdata/configure/modules/definition/module.qbs +++ b/tests/auto/blackbox/testdata/configure/modules/definition/module.qbs @@ -12,7 +12,7 @@ Module { var cmd; var args; var p = path; - if (targetOS.contains("windows")) { + if (targetOS.includes("windows")) { cmd = windowsShellPath; args = ["/c", "date", "/t"]; } else { diff --git a/tests/auto/blackbox/testdata/conflicting-property-values/conflicting-property-values.qbs b/tests/auto/blackbox/testdata/conflicting-property-values/conflicting-property-values.qbs new file mode 100644 index 000000000..23b6ee5a3 --- /dev/null +++ b/tests/auto/blackbox/testdata/conflicting-property-values/conflicting-property-values.qbs @@ -0,0 +1,41 @@ +Project { + Product { + name: "low" + Export { property string prop: "low"; property string prop2: "low" } + } + Product { + name: "higher1" + Export { Depends { name: "low" } low.prop: "higher1" } + } + Product { + name: "higher2" + Export { Depends { name: "low" } low.prop: "higher2" } + } + Product { + name: "highest1" + Export { + Depends { name: "low" } + Depends { name: "higher1" } + Depends { name: "higher2" } + low.prop: "highest1" + low.prop2: "highest" + } + } + Product { + name: "highest2" + Export { + Depends { name: "low" } + Depends { name: "higher1" } + Depends { name: "higher2" } + low.prop: "highest2" + low.prop2: "highest" + } + } + Product { + name: "toplevel" + Depends { name: "highest1" } + Depends { name: "highest2" } + low.prop: name + property bool dummy: { console.info("final prop value: " + low.prop); } + } +} diff --git a/tests/auto/blackbox/testdata/cpu-features/cpu-features.qbs b/tests/auto/blackbox/testdata/cpu-features/cpu-features.qbs index 0bfdaceba..36e805516 100644 --- a/tests/auto/blackbox/testdata/cpu-features/cpu-features.qbs +++ b/tests/auto/blackbox/testdata/cpu-features/cpu-features.qbs @@ -8,7 +8,7 @@ CppApplication { property bool dummy: { console.info("is x86: " + (qbs.architecture === "x86")); console.info("is x64: " + (qbs.architecture === "x86_64")); - console.info("is gcc: " + qbs.toolchain.contains("gcc")); - console.info("is msvc: " + qbs.toolchain.contains("msvc")); + console.info("is gcc: " + qbs.toolchain.includes("gcc")); + console.info("is msvc: " + qbs.toolchain.includes("msvc")); } } diff --git a/tests/auto/blackbox/testdata/cxx-language-version/cxx-language-version.qbs b/tests/auto/blackbox/testdata/cxx-language-version/cxx-language-version.qbs index 322ded85c..24c37951c 100644 --- a/tests/auto/blackbox/testdata/cxx-language-version/cxx-language-version.qbs +++ b/tests/auto/blackbox/testdata/cxx-language-version/cxx-language-version.qbs @@ -13,10 +13,10 @@ CppApplication { var isEvenNewerMsvc; var isOlderMsvc; var isGcc; - if (toolchain.contains("clang-cl")) { + if (toolchain.includes("clang-cl")) { isEvenNewerMsvc = true; isNewerMsvc = true; - } else if (toolchain.contains("msvc")) { + } else if (toolchain.includes("msvc")) { if (compilerVersion >= "19.12.25831") isEvenNewerMsvc = true; if (compilerVersion >= "18.00.30723") diff --git a/tests/auto/blackbox/testdata/date-property/date-property.qbs b/tests/auto/blackbox/testdata/date-property/date-property.qbs new file mode 100644 index 000000000..ffd584802 --- /dev/null +++ b/tests/auto/blackbox/testdata/date-property/date-property.qbs @@ -0,0 +1,18 @@ +Product { + type: "date" + property var theDate: new Date(1999, 11, 31); + Rule { + multiplex: true + Artifact { filePath: "dummy"; fileTags: "date" } + prepare: { + var cmd = new JavaScriptCommand; + cmd.silent = true; + cmd.sourceCode = function() { + var d = product.theDate; + console.info("The stored date was " + d.getFullYear() + '-' + (d.getMonth() + 1) + '-' + + d.getDate()); + }; + return cmd; + } + } +} diff --git a/tests/auto/blackbox/testdata/dependenciesProperty/dependenciesProperty.qbs b/tests/auto/blackbox/testdata/dependenciesProperty/dependenciesProperty.qbs index 735bfffbc..681ffeab0 100644 --- a/tests/auto/blackbox/testdata/dependenciesProperty/dependenciesProperty.qbs +++ b/tests/auto/blackbox/testdata/dependenciesProperty/dependenciesProperty.qbs @@ -18,7 +18,7 @@ Project { } prepare: { var cmd = new JavaScriptCommand(); - cmd.description = 'generate ' + FileInfo.fileName(output.filePath); + cmd.description = 'generating ' + FileInfo.fileName(output.filePath); cmd.highlight = 'codegen'; cmd.sourceCode = function() { file = new TextFile(output.filePath, TextFile.WriteOnly); diff --git a/tests/auto/blackbox/testdata/dependency-profile-mismatch/dependency-profile-mismatch.qbs b/tests/auto/blackbox/testdata/dependency-profile-mismatch/dependency-profile-mismatch.qbs deleted file mode 100644 index 8a6f733c0..000000000 --- a/tests/auto/blackbox/testdata/dependency-profile-mismatch/dependency-profile-mismatch.qbs +++ /dev/null @@ -1,12 +0,0 @@ -Project { - property string mainProfile - property string depProfile - Product { - name: "dep" - qbs.profiles: [project.depProfile] - } - Product { - name: "main" - Depends { name: "dep"; profiles: [project.mainProfile]; } - } -} diff --git a/tests/auto/blackbox/testdata/dependency-scanning-loop/dependency-scanning-loop.qbs b/tests/auto/blackbox/testdata/dependency-scanning-loop/dependency-scanning-loop.qbs new file mode 100644 index 000000000..ac8e7258c --- /dev/null +++ b/tests/auto/blackbox/testdata/dependency-scanning-loop/dependency-scanning-loop.qbs @@ -0,0 +1,34 @@ +import qbs.FileInfo +import qbs.TextFile + +CppApplication { + name: "app" + cpp.includePaths: buildDirectory + Group { + files: "main.cpp" + fileTags: ["cpp", "custom.in"] + } + Rule { + inputs: "custom.in" + Artifact { + filePath: FileInfo.completeBaseName(input.filePath) + ".h" + fileTags: "hpp" + } + Artifact { + filePath: "custom.txt" + fileTags: "whatever" + } + prepare: { + var cmd = new JavaScriptCommand(); + cmd.description = "generating " + outputs.hpp[0].fileName; + cmd.sourceCode = function() { + var f = new TextFile(outputs.hpp[0].filePath, TextFile.WriteOnly); + f.writeLine("int main() {}"); + f.close(); + f = new TextFile(outputs.whatever[0].filePath, TextFile.WriteOnly); + f.close(); + } + return cmd; + } + } +} diff --git a/tests/auto/blackbox/testdata/dependency-scanning-loop/main.cpp b/tests/auto/blackbox/testdata/dependency-scanning-loop/main.cpp new file mode 100644 index 000000000..5e8dda41b --- /dev/null +++ b/tests/auto/blackbox/testdata/dependency-scanning-loop/main.cpp @@ -0,0 +1 @@ +#include <main.h> diff --git a/tests/auto/blackbox/testdata/deprecated-property/deprecated-property.qbs b/tests/auto/blackbox/testdata/deprecated-property/deprecated-property.qbs index a8efb97b5..7d1550312 100644 --- a/tests/auto/blackbox/testdata/deprecated-property/deprecated-property.qbs +++ b/tests/auto/blackbox/testdata/deprecated-property/deprecated-property.qbs @@ -1,8 +1,6 @@ -import qbs - Product { Depends { name: "themodule" } themodule.newProp: true - themodule.oldProp: false + themodule.expiringProp: false themodule.veryOldProp: false } diff --git a/tests/auto/blackbox/testdata/deprecated-property/modules/themodule/m.qbs b/tests/auto/blackbox/testdata/deprecated-property/modules/themodule/m.qbs index 106ed4135..58164e918 100644 --- a/tests/auto/blackbox/testdata/deprecated-property/modules/themodule/m.qbs +++ b/tests/auto/blackbox/testdata/deprecated-property/modules/themodule/m.qbs @@ -1,8 +1,8 @@ -import qbs +import qbs.Environment Module { property bool newProp - property bool oldProp + property bool expiringProp property bool forgottenProp PropertyOptions { @@ -10,9 +10,9 @@ Module { description: "Use this, it's good!" } PropertyOptions { - name: "oldProp" + name: "expiringProp" description: "Use newProp instead." - removalVersion: "99.9" + removalVersion: Environment.getEnv("REMOVAL_VERSION") } PropertyOptions { name: "veryOldProp" diff --git a/tests/auto/blackbox/testdata/disappeared-profile/modules-dir/modules/m/m.qbs b/tests/auto/blackbox/testdata/disappeared-profile/modules-dir/modules/m/m.qbs index 3e1747ade..fd755ce86 100644 --- a/tests/auto/blackbox/testdata/disappeared-profile/modules-dir/modules/m/m.qbs +++ b/tests/auto/blackbox/testdata/disappeared-profile/modules-dir/modules/m/m.qbs @@ -10,7 +10,7 @@ Module { } prepare: { var cmd = new JavaScriptCommand(); - cmd.description = "Creating " + output.fileName + " with " + product.m.p1; + cmd.description = "creating " + output.fileName + " with " + product.m.p1; cmd.sourceCode = function() {}; return [cmd]; } @@ -24,7 +24,7 @@ Module { } prepare: { var cmd = new JavaScriptCommand(); - cmd.description = "Creating " + output.fileName + " with " + product.m.p2; + cmd.description = "creating " + output.fileName + " with " + product.m.p2; cmd.sourceCode = function() {}; return [cmd]; } diff --git a/tests/auto/blackbox/testdata/discard-unused-data/discard-unused-data.qbs b/tests/auto/blackbox/testdata/discard-unused-data/discard-unused-data.qbs index fdd3aa1f7..367bb665c 100644 --- a/tests/auto/blackbox/testdata/discard-unused-data/discard-unused-data.qbs +++ b/tests/auto/blackbox/testdata/discard-unused-data/discard-unused-data.qbs @@ -4,9 +4,9 @@ CppApplication { files: "main.cpp" - Depends { name: "bundle"; condition: qbs.targetOS.contains("darwin") } + Depends { name: "bundle"; condition: qbs.targetOS.includes("darwin") } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } @@ -17,7 +17,7 @@ CppApplication { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { - console.info("is Darwin: " + product.qbs.targetOS.contains("darwin")); + console.info("is Darwin: " + product.qbs.targetOS.includes("darwin")); console.info("---" + product.cpp.nmPath + "---"); } return [cmd]; diff --git a/tests/auto/blackbox/testdata/distribution-include-paths/distribution-include-paths.qbs b/tests/auto/blackbox/testdata/distribution-include-paths/distribution-include-paths.qbs new file mode 100644 index 000000000..3e6fb9b00 --- /dev/null +++ b/tests/auto/blackbox/testdata/distribution-include-paths/distribution-include-paths.qbs @@ -0,0 +1,4 @@ +CppApplication { + files: ["main.cpp"] + cpp.distributionIncludePaths: ["subdir"] +} diff --git a/tests/auto/blackbox/testdata/distribution-include-paths/main.cpp b/tests/auto/blackbox/testdata/distribution-include-paths/main.cpp new file mode 100644 index 000000000..10d376a31 --- /dev/null +++ b/tests/auto/blackbox/testdata/distribution-include-paths/main.cpp @@ -0,0 +1,8 @@ +#include <cstdio> +#include <gagagugu.h> + +int main() +{ + printStuff(); + return 0; +} diff --git a/tests/auto/blackbox/testdata/distribution-include-paths/subdir/gagagugu.h b/tests/auto/blackbox/testdata/distribution-include-paths/subdir/gagagugu.h new file mode 100644 index 000000000..b951d8855 --- /dev/null +++ b/tests/auto/blackbox/testdata/distribution-include-paths/subdir/gagagugu.h @@ -0,0 +1,4 @@ +void printStuff() +{ + puts("alalalalonglonglilonglonglong"); +} diff --git a/tests/auto/blackbox/testdata/dot-dot-pc-file/dot-dot-pc-file.qbs b/tests/auto/blackbox/testdata/dot-dot-pc-file/dot-dot-pc-file.qbs new file mode 100644 index 000000000..60c4ea2bc --- /dev/null +++ b/tests/auto/blackbox/testdata/dot-dot-pc-file/dot-dot-pc-file.qbs @@ -0,0 +1,7 @@ +CppApplication { + name: "p" + Depends { name: "qbs-metatest-module"; } + files: "main.cpp" + moduleProviders.qbspkgconfig.libDirs: "libdir" + qbsModuleProviders: "qbspkgconfig" +} diff --git a/tests/auto/blackbox/testdata/dot-dot-pc-file/libdir/qbs.metatest.module.pc b/tests/auto/blackbox/testdata/dot-dot-pc-file/libdir/qbs.metatest.module.pc new file mode 100644 index 000000000..c00fd26d6 --- /dev/null +++ b/tests/auto/blackbox/testdata/dot-dot-pc-file/libdir/qbs.metatest.module.pc @@ -0,0 +1,5 @@ +Name: qbs.metatest.module +Description: just a test +Version: 0.0.1 + +Cflags: -DTHE_MAGIC_DEFINE diff --git a/tests/auto/blackbox/testdata/dot-dot-pc-file/main.cpp b/tests/auto/blackbox/testdata/dot-dot-pc-file/main.cpp new file mode 100644 index 000000000..442b755bf --- /dev/null +++ b/tests/auto/blackbox/testdata/dot-dot-pc-file/main.cpp @@ -0,0 +1,5 @@ +#ifndef THE_MAGIC_DEFINE +#error "missing the magic define" +#endif + +int main() {} diff --git a/tests/auto/blackbox/testdata/driver-linker-flags/driver-linker-flags.qbs b/tests/auto/blackbox/testdata/driver-linker-flags/driver-linker-flags.qbs index 5de0fe053..57f096494 100644 --- a/tests/auto/blackbox/testdata/driver-linker-flags/driver-linker-flags.qbs +++ b/tests/auto/blackbox/testdata/driver-linker-flags/driver-linker-flags.qbs @@ -8,7 +8,7 @@ CppApplication { Probe { id: toolchainProbe - condition: qbs.toolchain.contains("gcc") + condition: qbs.toolchain.includes("gcc") configure: { console.info("toolchain is GCC-like"); found = true; diff --git a/tests/auto/blackbox/testdata/dynamic-library-in-module/Dll.qbs b/tests/auto/blackbox/testdata/dynamic-library-in-module/Dll.qbs index 1acf606dc..c95d88052 100644 --- a/tests/auto/blackbox/testdata/dynamic-library-in-module/Dll.qbs +++ b/tests/auto/blackbox/testdata/dynamic-library-in-module/Dll.qbs @@ -1,8 +1,8 @@ DynamicLibrary { Depends { name: "cpp" } - Depends { name: "bundle"; condition: qbs.targetOS.contains("darwin") } + Depends { name: "bundle"; condition: qbs.targetOS.includes("darwin") } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false cpp.minimumMacosVersion: "10.7" // For -rpath } diff --git a/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/thelib/thelib.qbs b/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/thelib/thelib.qbs index 30f87337d..3059fa5e9 100644 --- a/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/thelib/thelib.qbs +++ b/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/thelib/thelib.qbs @@ -13,7 +13,7 @@ Module { } Group { name: "thelib dll import" - condition: qbs.targetOS.contains("windows") + condition: qbs.targetOS.includes("windows") files: FileInfo.joinPaths(product.thelib.baseDir, "thelib.lib") fileTags: ["dynamiclibrary_import"] filesAreTargets: true diff --git a/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/theotherlib/theotherlib.qbs b/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/theotherlib/theotherlib.qbs index 1eb1e01a5..f387feb80 100644 --- a/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/theotherlib/theotherlib.qbs +++ b/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/theotherlib/theotherlib.qbs @@ -13,7 +13,7 @@ Module { } Group { name: "theotherlib dll import" - condition: qbs.targetOS.contains("windows") + condition: qbs.targetOS.includes("windows") files: FileInfo.joinPaths(product.theotherlib.baseDir, "theotherlib.lib") fileTags: ["dynamiclibrary_import"] filesAreTargets: true diff --git a/tests/auto/blackbox/testdata/dynamic-library-in-module/theapp.qbs b/tests/auto/blackbox/testdata/dynamic-library-in-module/theapp.qbs index b9149d091..5ea8cef23 100644 --- a/tests/auto/blackbox/testdata/dynamic-library-in-module/theapp.qbs +++ b/tests/auto/blackbox/testdata/dynamic-library-in-module/theapp.qbs @@ -1,5 +1,13 @@ +import qbs.Host + Project { CppApplication { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } name: "theapp" cpp.minimumMacosVersion: "10.7" // For -rpath Depends { name: "theotherlib" } diff --git a/tests/auto/blackbox/testdata/dynamic-project/dynamic-project.qbs b/tests/auto/blackbox/testdata/dynamic-project/dynamic-project.qbs index 166648c80..5acdb8892 100644 --- a/tests/auto/blackbox/testdata/dynamic-project/dynamic-project.qbs +++ b/tests/auto/blackbox/testdata/dynamic-project/dynamic-project.qbs @@ -17,13 +17,12 @@ Project var srcDir = FileInfo.joinPaths(sourceDir, "src"); var projectDirs = File.directoryEntries(srcDir, File.Dirs | File.NoDotAndDotDot); var list = []; - for (it in projectDirs) { + for (var it = 0; it < projectDirs.length; ++it) { var name = projectDirs[it]; var productSrcDir = FileInfo.joinPaths(srcDir, name); var productFilePath = FileInfo.joinPaths(tempDir, name + ".qbs"); var file = new TextFile(productFilePath, TextFile.WriteOnly); try { - file.writeLine("import qbs"); file.writeLine("CppApplication"); file.writeLine("{"); file.writeLine("\tfiles: [ \"" + productSrcDir + "/*.cpp\" ]"); diff --git a/tests/auto/blackbox/testdata/dynamicRuleOutputs/before/flexoptionsreader.js b/tests/auto/blackbox/testdata/dynamicRuleOutputs/before/flexoptionsreader.js index bd596fbca..b925effcf 100644 --- a/tests/auto/blackbox/testdata/dynamicRuleOutputs/before/flexoptionsreader.js +++ b/tests/auto/blackbox/testdata/dynamicRuleOutputs/before/flexoptionsreader.js @@ -35,7 +35,7 @@ ** ****************************************************************************/ -// needs import qbs.TextFile +var TextFile = require("qbs.TextFile"); function readFlexOptions(filePath) { @@ -82,7 +82,7 @@ function readFlexOptions(filePath) } } - var tf = new TextFile(input.filePath); + var tf = new TextFile(filePath); var line; var optrex = /^%option\s+(.*$)/; var res; diff --git a/tests/auto/blackbox/testdata/empty-profile/empty-profile.qbs b/tests/auto/blackbox/testdata/empty-profile/empty-profile.qbs new file mode 100644 index 000000000..da7536315 --- /dev/null +++ b/tests/auto/blackbox/testdata/empty-profile/empty-profile.qbs @@ -0,0 +1,3 @@ +CppApplication { + files: ["main.cpp"] +} diff --git a/tests/auto/blackbox/testdata/empty-profile/main.cpp b/tests/auto/blackbox/testdata/empty-profile/main.cpp new file mode 100644 index 000000000..76e819701 --- /dev/null +++ b/tests/auto/blackbox/testdata/empty-profile/main.cpp @@ -0,0 +1 @@ +int main() { return 0; } diff --git a/tests/auto/blackbox/testdata/enableExceptions/exceptions.qbs b/tests/auto/blackbox/testdata/enableExceptions/exceptions.qbs index 9a75043a8..e1d09f7e0 100644 --- a/tests/auto/blackbox/testdata/enableExceptions/exceptions.qbs +++ b/tests/auto/blackbox/testdata/enableExceptions/exceptions.qbs @@ -1,5 +1,5 @@ CppApplication { files: ["main.cpp"] cpp.treatWarningsAsErrors: true - cpp.defines: qbs.toolchain.contains("msvc") && !cpp.enableExceptions ? ["FORCE_FAIL_VS"] : [] + cpp.defines: qbs.toolchain.includes("msvc") && !cpp.enableExceptions ? ["FORCE_FAIL_VS"] : [] } diff --git a/tests/auto/blackbox/testdata/enableExceptions/none.qbs b/tests/auto/blackbox/testdata/enableExceptions/none.qbs index 8fb052476..439ea3037 100644 --- a/tests/auto/blackbox/testdata/enableExceptions/none.qbs +++ b/tests/auto/blackbox/testdata/enableExceptions/none.qbs @@ -2,7 +2,7 @@ CppApplication { files: ["emptymain.cpp"] Group { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") files: ["empty.m", "empty.mm"] } } diff --git a/tests/auto/blackbox/testdata/env-merging/env-merging.qbs b/tests/auto/blackbox/testdata/env-merging/env-merging.qbs index 6edeca444..eb681f36b 100644 --- a/tests/auto/blackbox/testdata/env-merging/env-merging.qbs +++ b/tests/auto/blackbox/testdata/env-merging/env-merging.qbs @@ -1,3 +1,5 @@ +import qbs.Host + Project { CppApplication { name: "tool" @@ -5,6 +7,12 @@ Project { } Product { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } name: "p" type: "custom" Depends { name: "tool" } diff --git a/tests/auto/blackbox/testdata/escaped-linker-flags/escaped-linker-flags.qbs b/tests/auto/blackbox/testdata/escaped-linker-flags/escaped-linker-flags.qbs index f48bf8d1f..b4fb0df4d 100644 --- a/tests/auto/blackbox/testdata/escaped-linker-flags/escaped-linker-flags.qbs +++ b/tests/auto/blackbox/testdata/escaped-linker-flags/escaped-linker-flags.qbs @@ -10,4 +10,9 @@ CppApplication { cpp.linkerFlags: ["-s"] } files: ["main.cpp"] + Probe { + id: checker + property bool isUnixGcc: qbs.toolchain.contains("gcc") && !qbs.targetOS.contains("macos") + configure: { console.info("is gcc: " + isUnixGcc); } + } } diff --git a/tests/auto/blackbox/testdata/export-rule/export-rule.qbs b/tests/auto/blackbox/testdata/export-rule/export-rule.qbs index 29899e728..455ccba0d 100644 --- a/tests/auto/blackbox/testdata/export-rule/export-rule.qbs +++ b/tests/auto/blackbox/testdata/export-rule/export-rule.qbs @@ -13,7 +13,7 @@ Project { Export { Depends { name: "cpp" } property bool enableTagger - property string description: "Creating C++ source file."; + property string description: "creating C++ source file."; FileTagger { condition: enableTagger patterns: ["*.blubb"] diff --git a/tests/auto/blackbox/testdata/exports-cmake/Foo.cpp b/tests/auto/blackbox/testdata/exports-cmake/Foo.cpp new file mode 100644 index 000000000..ea334f9af --- /dev/null +++ b/tests/auto/blackbox/testdata/exports-cmake/Foo.cpp @@ -0,0 +1,5 @@ +#include "Foo.h" +int someFooWork() +{ + return 42; +} diff --git a/tests/auto/blackbox/testdata/exports-cmake/Foo.h b/tests/auto/blackbox/testdata/exports-cmake/Foo.h new file mode 100644 index 000000000..2f279f577 --- /dev/null +++ b/tests/auto/blackbox/testdata/exports-cmake/Foo.h @@ -0,0 +1,16 @@ +#ifndef FOO_H +#define FOO_H +#include <dllexport.h> + +#ifdef FOO_LIB_STATIC +#define FOO_LIB_EXPORT +#else +#ifdef FOO_LIB +#define FOO_LIB_EXPORT DLL_EXPORT +#else +#define FOO_LIB_EXPORT DLL_IMPORT +#endif +#endif + +FOO_LIB_EXPORT int someFooWork(); +#endif // FOO_H diff --git a/tests/auto/blackbox/testdata/exports-cmake/cmake/CMakeLists.txt b/tests/auto/blackbox/testdata/exports-cmake/cmake/CMakeLists.txt new file mode 100644 index 000000000..d874e0e92 --- /dev/null +++ b/tests/auto/blackbox/testdata/exports-cmake/cmake/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.10) + +project(qbs_import) + +find_package(Bar PATHS REQUIRED) +add_executable(Consumer main.cpp) +target_link_libraries(Consumer Bar) diff --git a/tests/auto/blackbox/testdata/exports-cmake/cmake/main.cpp b/tests/auto/blackbox/testdata/exports-cmake/cmake/main.cpp new file mode 100644 index 000000000..1a1fa90ec --- /dev/null +++ b/tests/auto/blackbox/testdata/exports-cmake/cmake/main.cpp @@ -0,0 +1,6 @@ +#include <Foo.h> + +int main() +{ + return someFooWork(); +} diff --git a/tests/auto/blackbox/testdata/exports-cmake/exports-cmake.qbs b/tests/auto/blackbox/testdata/exports-cmake/exports-cmake.qbs new file mode 100644 index 000000000..6464af705 --- /dev/null +++ b/tests/auto/blackbox/testdata/exports-cmake/exports-cmake.qbs @@ -0,0 +1,70 @@ +import qbs.FileInfo + +Project { + property bool isStatic: false + property bool isBundle: false + + property string headersInstallDir: "include" + + Product { + name: "DllExport" + Depends { name: "Exporter.cmake" } + Group { + name: "API headers" + files: ["../dllexport.h"] + qbs.install: true + qbs.installDir: project.headersInstallDir + } + Group { + fileTagsFilter: ["Exporter.cmake.package"] + qbs.install: true + qbs.installDir: "/lib/cmake/DllExport" + } + Export { + Depends { name: "cpp" } + cpp.includePaths: FileInfo.joinPaths( + exportingProduct.qbs.installRoot, + exportingProduct.qbs.installPrefix, + project.headersInstallDir) + } + } + + Library { + type: project.isStatic ? "staticlibrary" : "dynamiclibrary" + Depends { name: "cpp" } + Depends { name: "DllExport" } + Depends { name: "Exporter.cmake" } + Exporter.cmake.packageName: "Bar" + name: "Foo" + files: ["Foo.cpp"] + version: "1.2.3" + cpp.includePaths: "." + cpp.defines: "FOO_LIB" + Group { + name: "API headers" + files: ["Foo.h"] + qbs.install: true + qbs.installDir: project.headersInstallDir + } + install: true + installImportLib: true + Group { + fileTagsFilter: ["Exporter.cmake.package"] + qbs.install: true + qbs.installDir: "/lib/cmake/Bar" + } + Export { + Depends { name: "cpp" } + cpp.includePaths: FileInfo.joinPaths( + exportingProduct.qbs.installRoot, + exportingProduct.qbs.installPrefix, + project.headersInstallDir) + cpp.defines: ["FOO=1"].concat(project.isStatic ? ["FOO_LIB_STATIC"] : []) + cpp.commonCompilerFlags: "-DOTHER_DEF=1" + cpp.linkerFlags: exportingProduct.qbs.toolchain.contains("gcc") ? ["-s"] : [] + } + + Depends { name: 'bundle' } + bundle.isBundle: qbs.targetOS.includes("darwin") && project.isBundle + } +} diff --git a/tests/auto/blackbox/testdata/exports-cmake/find-cmake.qbs b/tests/auto/blackbox/testdata/exports-cmake/find-cmake.qbs new file mode 100644 index 000000000..52f388966 --- /dev/null +++ b/tests/auto/blackbox/testdata/exports-cmake/find-cmake.qbs @@ -0,0 +1,46 @@ +import qbs.Probes + +Product { + Depends { name: "cpp" } + + Probes.BinaryProbe { + id: cmakeProbe + names: "cmake" + } + + Probes.BinaryProbe { + id: ninjaProbe + names: ["ninja"] + } + + property bool test: { + var data = { + cmakeFound: cmakeProbe.found, + cmakeFilePath: cmakeProbe.filePath, + crossCompiling: qbs.targetPlatform !== qbs.hostPlatform, + installPrefix: qbs.installPrefix + }; + data.buildEnv = {} + Object.assign(data.buildEnv, cpp.buildEnv); // deep copy buildEnv from a probe + if (qbs.toolchain.includes("gcc")) { + data.buildEnv["CC"] = cpp.cCompilerName; + data.buildEnv["CXX"] = cpp.cxxCompilerName; + } else { + data.buildEnv["CC"] = cpp.compilerName; + data.buildEnv["CXX"] = cpp.compilerName; + } + + if (ninjaProbe.found) { + data.generator = "Ninja"; + } else { + if (qbs.toolchain.includes("msvc")) { + data.generator = "NMake Makefiles" + } else if (qbs.toolchain.includes("mingw")) { + data.generator = "MinGW Makefiles"; + } else if (qbs.toolchain.includes("gcc")) { + data.generator = "Unix Makefiles"; + } + } + console.info("---" + JSON.stringify(data) + "---"); + } +} diff --git a/tests/auto/blackbox/testdata/exports-pkgconfig/exports-pkgconfig.qbs b/tests/auto/blackbox/testdata/exports-pkgconfig/exports-pkgconfig.qbs index 96d1cabb9..23331f93f 100644 --- a/tests/auto/blackbox/testdata/exports-pkgconfig/exports-pkgconfig.qbs +++ b/tests/auto/blackbox/testdata/exports-pkgconfig/exports-pkgconfig.qbs @@ -1,4 +1,5 @@ import qbs.FileInfo +import qbs.Host Project { Product { @@ -42,14 +43,14 @@ Project { Depends { name: "Qt.core"; required: false } Depends { name: "helper1" } Depends { name: "helper3" } - property bool someCondition: qbs.hostOS.contains("windows") // hostOS for easier testing + property bool someCondition: Host.os().includes("windows") // hostOS for easier testing property bool someOtherCondition: someCondition Properties { condition: !someOtherCondition cpp.driverFlags: ["-pthread"] } - cpp.defines: product.name - cpp.includePaths: [FileInfo.joinPaths(product.qbs.installPrefix, "include")] + cpp.defines: exportingProduct.name + cpp.includePaths: [FileInfo.joinPaths(exportingProduct.qbs.installPrefix, "include")] Qt.core.mocName: "muck" } @@ -94,7 +95,7 @@ Project { Depends { name: "cpp" } cpp.includePaths: [ "/opt/thesecondlib/include", - product.sourceDirectory, + exportingProduct.sourceDirectory, importingProduct.buildDirectory ] property string hurz: importingProduct.name diff --git a/tests/auto/blackbox/testdata/exports-qbs/consumer.qbs b/tests/auto/blackbox/testdata/exports-qbs/consumer.qbs index 02affdfe8..073504400 100644 --- a/tests/auto/blackbox/testdata/exports-qbs/consumer.qbs +++ b/tests/auto/blackbox/testdata/exports-qbs/consumer.qbs @@ -1,4 +1,12 @@ +import qbs.Host + CppApplication { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } name: "consumer" qbsSearchPaths: "default/install-root/usr/qbs" property string outTag: "cpp" diff --git a/tests/auto/blackbox/testdata/exports-qbs/lib.qbs b/tests/auto/blackbox/testdata/exports-qbs/lib.qbs index 53a472dbb..01f89a221 100644 --- a/tests/auto/blackbox/testdata/exports-qbs/lib.qbs +++ b/tests/auto/blackbox/testdata/exports-qbs/lib.qbs @@ -16,7 +16,7 @@ DynamicLibrary { cpp.defines: ["MYLIB_BUILD"] cpp.variantSuffix: qbs.buildVariant === "debug" ? "d" : "" Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } files: ["mylib.cpp"] @@ -38,8 +38,8 @@ DynamicLibrary { Export { Depends { name: "cpp" } - property string includeDir: product.sourceDirectory - property var config: product.config + property string includeDir: exportingProduct.sourceDirectory + property var config: exportingProduct.config Properties { condition: true cpp.includePaths: [includeDir] @@ -52,7 +52,7 @@ DynamicLibrary { condition: true prefixMapping: [{ prefix: includeDir, - replacement: FileInfo.joinPaths(qbs.installPrefix, product.headersInstallDir) + replacement: FileInfo.joinPaths(exportingProduct.qbs.installPrefix, exportingProduct.headersInstallDir) }] } } diff --git a/tests/auto/blackbox/testdata/exports-qbs/tool.qbs b/tests/auto/blackbox/testdata/exports-qbs/tool.qbs index 655597cf7..d3626bead 100644 --- a/tests/auto/blackbox/testdata/exports-qbs/tool.qbs +++ b/tests/auto/blackbox/testdata/exports-qbs/tool.qbs @@ -33,7 +33,7 @@ CppApplication { } Export { - property stringList toolTags: product.toolTags + property stringList toolTags: exportingProduct.toolTags property stringList outTags: [importingProduct.outTag] property var helper2Obj: Helper2 Rule { @@ -49,7 +49,7 @@ CppApplication { prepare: { var cmd = new Command(explicitlyDependsOn["MyTool.tool"][0].filePath, [input.filePath, output.filePath]); - cmd.description = input.fileName + " -> " + output.fileName; + cmd.description = "compiling" + input.fileName + " to " + output.fileName; return [cmd]; } } diff --git a/tests/auto/blackbox/testdata/external-libs/external-libs.qbs b/tests/auto/blackbox/testdata/external-libs/external-libs.qbs index 619f40867..326bf5dae 100644 --- a/tests/auto/blackbox/testdata/external-libs/external-libs.qbs +++ b/tests/auto/blackbox/testdata/external-libs/external-libs.qbs @@ -1,13 +1,13 @@ import qbs.TextFile Project { - property string libDir: sourceDirectory + "/libs" + property string libDir: buildDirectory + "/libs" StaticLibrary { name: "lib1" destinationDirectory: project.libDir Depends { name: "cpp" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } files: ["lib1.cpp"] @@ -18,7 +18,7 @@ Project { Depends { name: "cpp" } Depends { name: "lib1" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } files: ["lib2.cpp"] diff --git a/tests/auto/blackbox/testdata/fileDependencies/awesomelib/awesome.h b/tests/auto/blackbox/testdata/fileDependencies/awesomelib/awesome.h index 4633f9746..8f1f25087 100644 --- a/tests/auto/blackbox/testdata/fileDependencies/awesomelib/awesome.h +++ b/tests/auto/blackbox/testdata/fileDependencies/awesomelib/awesome.h @@ -31,6 +31,6 @@ void doAwesomeStuff() { - printf(magnificentMessage); + std::printf(magnificentMessage); } diff --git a/tests/auto/blackbox/testdata/flatbuf/bar.fbs b/tests/auto/blackbox/testdata/flatbuf/bar.fbs new file mode 100644 index 000000000..47148f800 --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/bar.fbs @@ -0,0 +1,9 @@ +include "foo.fbs"; + +namespace QbsTest; + +table Bar { + foo:Foo; +} + +root_type Bar; diff --git a/tests/auto/blackbox/testdata/flatbuf/baz.fbs b/tests/auto/blackbox/testdata/flatbuf/baz.fbs new file mode 100644 index 000000000..312183710 --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/baz.fbs @@ -0,0 +1,9 @@ +include "imported_foo/imported_foo.fbs"; + +namespace QbsTest; + +table Baz { + foo:Foo; +} + +root_type Baz; diff --git a/tests/auto/blackbox/testdata/flatbuf/conanfile.txt b/tests/auto/blackbox/testdata/flatbuf/conanfile.txt new file mode 100644 index 000000000..188da5897 --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/conanfile.txt @@ -0,0 +1,6 @@ +[requires] +flatbuffers/24.3.25 +[tool_requires] +flatbuffers/24.3.25 +[generators] +QbsDeps diff --git a/tests/auto/blackbox/testdata/flatbuf/flat.c b/tests/auto/blackbox/testdata/flatbuf/flat.c new file mode 100644 index 000000000..55e25e556 --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/flat.c @@ -0,0 +1,36 @@ +#include "foo_builder.h" + +#include <stdio.h> + +#undef ns +#define ns(x) FLATBUFFERS_WRAP_NAMESPACE(QbsTest, x) // Specified in the schema. + +#define test_assert(x) do { if (!(x)) { assert(0); return -1; }} while (0) + +int main() +{ + void *buffer = NULL; + size_t size = 0; + + flatcc_builder_t builder; + flatcc_builder_init(&builder); + + flatbuffers_string_ref_t name = flatbuffers_string_create_str(&builder, "John Doe"); + + ns(Foo_create_as_root(&builder, name, 42)); + + buffer = flatcc_builder_finalize_aligned_buffer(&builder, &size); + + ns(Foo_table_t) foo = ns(Foo_as_root(buffer)); + + test_assert(strcmp(ns(Foo_name(foo)), "John Doe") == 0); + test_assert(ns(Foo_count(foo)) == 42); + + free(buffer); + + flatcc_builder_clear(&builder); + + printf("The FlatBuffer was successfully created and accessed!\n"); + + return 0; +} diff --git a/tests/auto/blackbox/testdata/flatbuf/flat.cpp b/tests/auto/blackbox/testdata/flatbuf/flat.cpp new file mode 100644 index 000000000..56332bacd --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/flat.cpp @@ -0,0 +1,22 @@ +#include "foo_generated.h" + +#include <iostream> + +using namespace QbsTest; + +int main() +{ + flatbuffers::FlatBufferBuilder builder; + auto name = builder.CreateString("John Doe"); + auto newFoo = QbsTest::CreateFoo(builder, name, 42); + builder.Finish(newFoo); + + auto foo = GetFoo(builder.GetBufferPointer()); + + assert(foo->name()->str() == "John Doe"); + assert(foo->count() == 42); + + std::cout << "The FlatBuffer was successfully created and accessed!" << std::endl; + + return 0; +} diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_absolute_import.cpp b/tests/auto/blackbox/testdata/flatbuf/flat_absolute_import.cpp new file mode 100644 index 000000000..b7c43d8a5 --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/flat_absolute_import.cpp @@ -0,0 +1,25 @@ +#include "baz_generated.h" + +#include <iostream> + +using namespace QbsTest; + +int main() +{ + flatbuffers::FlatBufferBuilder builder; + + auto name = builder.CreateString("John Doe"); + auto newFoo = QbsTest::CreateFoo(builder, name, 42); + + auto newBaz = QbsTest::CreateBaz(builder, newFoo); + builder.Finish(newBaz); + + auto baz = GetBaz(builder.GetBufferPointer()); + + assert(baz->foo()->name()->str() == "John Doe"); + assert(baz->foo()->count() == 42); + + std::cout << "The FlatBuffer was successfully created and accessed!" << std::endl; + + return 0; +} diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_absolute_import.qbs b/tests/auto/blackbox/testdata/flatbuf/flat_absolute_import.qbs new file mode 100644 index 000000000..888bfd4e3 --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/flat_absolute_import.qbs @@ -0,0 +1,24 @@ +CppApplication { + Depends { name: "flatbuf.cpp"; required: false } + + consoleApplication: true + condition: { + var result = qbs.targetPlatform === qbs.hostPlatform; + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result && hasFlatbuffers; + } + property bool hasFlatbuffers: { + console.info("has flatbuffers: " + flatbuf.cpp.present); + return flatbuf.cpp.present; + } + + flatbuf.cpp.importPaths: "imports/" + + files: [ + "flat_absolute_import.cpp", + "baz.fbs", + "imports/imported_foo/imported_foo.fbs", + ] + qbsModuleProviders: "conan" +} diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_c.qbs b/tests/auto/blackbox/testdata/flatbuf/flat_c.qbs new file mode 100644 index 000000000..6d365252e --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/flat_c.qbs @@ -0,0 +1,21 @@ +CppApplication { + Depends { name: "flatbuffers.c"; required: false } + + consoleApplication: true + condition: { + var result = qbs.targetPlatform === qbs.hostPlatform; + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result && hasFlatbuffers; + } + property bool hasFlatbuffers: { + console.info("has flatbuffers: " + flatbuffers.c.present); + return flatbuffers.c.present; + } + + files: [ + "flat.c", + "foo.fbs", + ] + qbsModuleProviders: "conan" +} diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_cpp.qbs b/tests/auto/blackbox/testdata/flatbuf/flat_cpp.qbs new file mode 100644 index 000000000..99e89a5fa --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/flat_cpp.qbs @@ -0,0 +1,21 @@ +CppApplication { + Depends { name: "flatbuf.cpp"; required: false } + + consoleApplication: true + condition: { + var result = qbs.targetPlatform === qbs.hostPlatform; + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result && hasFlatbuffers; + } + property bool hasFlatbuffers: { + console.info("has flatbuffers: " + flatbuf.cpp.present); + return flatbuf.cpp.present; + } + + files: [ + "flat.cpp", + "foo.fbs", + ] + qbsModuleProviders: "conan" +} diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_filename_extension.cpp b/tests/auto/blackbox/testdata/flatbuf/flat_filename_extension.cpp new file mode 100644 index 000000000..77ed64acd --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/flat_filename_extension.cpp @@ -0,0 +1,22 @@ +#include "foo_generated.hpp" + +#include <iostream> + +using namespace QbsTest; + +int main() +{ + flatbuffers::FlatBufferBuilder builder; + auto name = builder.CreateString("John Doe"); + auto newFoo = QbsTest::CreateFoo(builder, name, 42); + builder.Finish(newFoo); + + auto foo = GetFoo(builder.GetBufferPointer()); + + assert(foo->name()->str() == "John Doe"); + assert(foo->count() == 42); + + std::cout << "The FlatBuffer was successfully created and accessed!" << std::endl; + + return 0; +} diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_filename_extension.qbs b/tests/auto/blackbox/testdata/flatbuf/flat_filename_extension.qbs new file mode 100644 index 000000000..31eec7629 --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/flat_filename_extension.qbs @@ -0,0 +1,23 @@ +CppApplication { + Depends { name: "flatbuf.cpp"; required: false } + + consoleApplication: true + condition: { + var result = qbs.targetPlatform === qbs.hostPlatform; + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result && hasFlatbuffers; + } + property bool hasFlatbuffers: { + console.info("has flatbuffers: " + flatbuf.cpp.present); + return flatbuf.cpp.present; + } + + flatbuf.cpp.filenameExtension: "hpp" + + files: [ + "flat_filename_extension.cpp", + "foo.fbs", + ] + qbsModuleProviders: "conan" +} diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_filename_suffix.cpp b/tests/auto/blackbox/testdata/flatbuf/flat_filename_suffix.cpp new file mode 100644 index 000000000..630e4aaef --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/flat_filename_suffix.cpp @@ -0,0 +1,22 @@ +#include "foo.fbs.h" + +#include <iostream> + +using namespace QbsTest; + +int main() +{ + flatbuffers::FlatBufferBuilder builder; + auto name = builder.CreateString("John Doe"); + auto newFoo = QbsTest::CreateFoo(builder, name, 42); + builder.Finish(newFoo); + + auto foo = GetFoo(builder.GetBufferPointer()); + + assert(foo->name()->str() == "John Doe"); + assert(foo->count() == 42); + + std::cout << "The FlatBuffer was successfully created and accessed!" << std::endl; + + return 0; +} diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_filename_suffix.qbs b/tests/auto/blackbox/testdata/flatbuf/flat_filename_suffix.qbs new file mode 100644 index 000000000..5103b041f --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/flat_filename_suffix.qbs @@ -0,0 +1,23 @@ +CppApplication { + Depends { name: "flatbuf.cpp"; required: false } + + consoleApplication: true + condition: { + var result = qbs.targetPlatform === qbs.hostPlatform; + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result && hasFlatbuffers; + } + property bool hasFlatbuffers: { + console.info("has flatbuffers: " + flatbuf.cpp.present); + return flatbuf.cpp.present; + } + + flatbuf.cpp.filenameSuffix: ".fbs" + + files: [ + "flat_filename_suffix.cpp", + "foo.fbs", + ] + qbsModuleProviders: "conan" +} diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_keep_prefix.cpp b/tests/auto/blackbox/testdata/flatbuf/flat_keep_prefix.cpp new file mode 100644 index 000000000..5f4b55e96 --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/flat_keep_prefix.cpp @@ -0,0 +1,26 @@ +#include "baz_generated.h" +#include "imported_foo/imported_foo_generated.h" + +#include <iostream> + +using namespace QbsTest; + +int main() +{ + flatbuffers::FlatBufferBuilder builder; + + auto name = builder.CreateString("John Doe"); + auto newFoo = QbsTest::CreateFoo(builder, name, 42); + + auto newBaz = QbsTest::CreateBaz(builder, newFoo); + builder.Finish(newBaz); + + auto baz = GetBaz(builder.GetBufferPointer()); + + assert(baz->foo()->name()->str() == "John Doe"); + assert(baz->foo()->count() == 42); + + std::cout << "The FlatBuffer was successfully created and accessed!" << std::endl; + + return 0; +} diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_keep_prefix.qbs b/tests/auto/blackbox/testdata/flatbuf/flat_keep_prefix.qbs new file mode 100644 index 000000000..0ea0d1dac --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/flat_keep_prefix.qbs @@ -0,0 +1,25 @@ +CppApplication { + Depends { name: "flatbuf.cpp"; required: false } + + consoleApplication: true + condition: { + var result = qbs.targetPlatform === qbs.hostPlatform; + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result && hasFlatbuffers; + } + property bool hasFlatbuffers: { + console.info("has flatbuffers: " + flatbuf.cpp.present); + return flatbuf.cpp.present; + } + + flatbuf.cpp.importPaths: "imports/" + flatbuf.cpp.keepPrefix: true + + files: [ + "flat_keep_prefix.cpp", + "baz.fbs", + "imports/imported_foo/imported_foo.fbs", + ] + qbsModuleProviders: "conan" +} diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_relative_import.cpp b/tests/auto/blackbox/testdata/flatbuf/flat_relative_import.cpp new file mode 100644 index 000000000..bec6dadfd --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/flat_relative_import.cpp @@ -0,0 +1,25 @@ +#include "bar_generated.h" + +#include <iostream> + +using namespace QbsTest; + +int main() +{ + flatbuffers::FlatBufferBuilder builder; + + auto name = builder.CreateString("John Doe"); + auto newFoo = QbsTest::CreateFoo(builder, name, 42); + + auto newBar = QbsTest::CreateBar(builder, newFoo); + builder.Finish(newBar); + + auto bar = GetBar(builder.GetBufferPointer()); + + assert(bar->foo()->name()->str() == "John Doe"); + assert(bar->foo()->count() == 42); + + std::cout << "The FlatBuffer was successfully created and accessed!" << std::endl; + + return 0; +} diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_relative_import.qbs b/tests/auto/blackbox/testdata/flatbuf/flat_relative_import.qbs new file mode 100644 index 000000000..f5a2c5d0b --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/flat_relative_import.qbs @@ -0,0 +1,22 @@ +CppApplication { + Depends { name: "flatbuf.cpp"; required: false } + + consoleApplication: true + condition: { + var result = qbs.targetPlatform === qbs.hostPlatform; + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result && hasFlatbuffers; + } + property bool hasFlatbuffers: { + console.info("has flatbuffers: " + flatbuf.cpp.present); + return flatbuf.cpp.present; + } + + files: [ + "flat_relative_import.cpp", + "bar.fbs", + "foo.fbs", + ] + qbsModuleProviders: "conan" +} diff --git a/tests/auto/blackbox/testdata/flatbuf/foo.fbs b/tests/auto/blackbox/testdata/flatbuf/foo.fbs new file mode 100644 index 000000000..dff3b488f --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/foo.fbs @@ -0,0 +1,8 @@ +namespace QbsTest; + +table Foo { + name:string; + count:int; +} + +root_type Foo; diff --git a/tests/auto/blackbox/testdata/flatbuf/imports/imported_foo/imported_foo.fbs b/tests/auto/blackbox/testdata/flatbuf/imports/imported_foo/imported_foo.fbs new file mode 100644 index 000000000..dff3b488f --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/imports/imported_foo/imported_foo.fbs @@ -0,0 +1,8 @@ +namespace QbsTest; + +table Foo { + name:string; + count:int; +} + +root_type Foo; diff --git a/tests/auto/blackbox/testdata/freedesktop/freedesktop.qbs b/tests/auto/blackbox/testdata/freedesktop/freedesktop.qbs new file mode 100644 index 000000000..1efe5c91c --- /dev/null +++ b/tests/auto/blackbox/testdata/freedesktop/freedesktop.qbs @@ -0,0 +1,23 @@ +Project { + CppApplication { + name: "main" + install: true + files: [ + "main.cpp", + "myapp.desktop", + "myapp.appdata.xml", + ] + + Depends { name: "freedesktop" } + + freedesktop.appName: "My App" + freedesktop.desktopKeys: ({ + 'Icon': "myapp.png" + }) + + Group { + files: "myapp.png" + fileTags: "freedesktop.appIcon" + } + } +} diff --git a/tests/auto/blackbox/testdata/freedesktop/main.cpp b/tests/auto/blackbox/testdata/freedesktop/main.cpp new file mode 100644 index 000000000..905869dfa --- /dev/null +++ b/tests/auto/blackbox/testdata/freedesktop/main.cpp @@ -0,0 +1,4 @@ +int main() +{ + return 0; +} diff --git a/tests/auto/blackbox/testdata/freedesktop/myapp.appdata.xml b/tests/auto/blackbox/testdata/freedesktop/myapp.appdata.xml new file mode 100644 index 000000000..3cf0a5641 --- /dev/null +++ b/tests/auto/blackbox/testdata/freedesktop/myapp.appdata.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<component type="desktop"> + <id>myapp.desktop</id> + <metadata_license>CC0</metadata_license> + <name>MyApp</name> + <summary>The coolest app ever</summary> + + <description> + <p>This is a cool application.</p> + </description> + + <url type="homepage">https://software.house/myapp</url> + <project_license>GPL-2.0+</project_license> + <developer_name>Coding Wizard</developer_name> +</component> diff --git a/tests/auto/blackbox/testdata/freedesktop/myapp.desktop b/tests/auto/blackbox/testdata/freedesktop/myapp.desktop new file mode 100644 index 000000000..dac3014c3 --- /dev/null +++ b/tests/auto/blackbox/testdata/freedesktop/myapp.desktop @@ -0,0 +1,4 @@ +[Desktop Entry] +GenericName=Image Editor +Comment=Create images and edit photographs +Icon=overridden.png diff --git a/tests/auto/blackbox/testdata/freedesktop/myapp.png b/tests/auto/blackbox/testdata/freedesktop/myapp.png new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/auto/blackbox/testdata/freedesktop/myapp.png diff --git a/tests/auto/blackbox/testdata/generate-linker-map-file/generate-linker-map-file.qbs b/tests/auto/blackbox/testdata/generate-linker-map-file/generate-linker-map-file.qbs index 815e64853..0d67fa54c 100644 --- a/tests/auto/blackbox/testdata/generate-linker-map-file/generate-linker-map-file.qbs +++ b/tests/auto/blackbox/testdata/generate-linker-map-file/generate-linker-map-file.qbs @@ -2,11 +2,14 @@ Project { CppApplication { name: "app-map" files: ["main.cpp"] + // lld-link has different flag for map files, test it by switching to "lld" linkerVariant + Properties { condition: qbs.toolchain.includes("clang-cl"); cpp.linkerVariant: "lld" } cpp.generateLinkerMapFile: true } CppApplication { name: "app-nomap" files: ["main.cpp"] + Properties { condition: qbs.toolchain.includes("clang-cl"); cpp.linkerVariant: "lld" } cpp.generateLinkerMapFile: false } CppApplication { @@ -16,8 +19,8 @@ Project { Probe { id: toolchainProbe - property bool isUsed: qbs.toolchain.contains("msvc") - || qbs.toolchain.contains("gcc") + property bool isUsed: qbs.toolchain.includes("msvc") + || qbs.toolchain.includes("gcc") configure: { console.info("use test: " + isUsed); } diff --git a/tests/auto/blackbox/testdata/generator/generator.qbs b/tests/auto/blackbox/testdata/generator/generator.qbs index d0857beb5..9f6d452e7 100644 --- a/tests/auto/blackbox/testdata/generator/generator.qbs +++ b/tests/auto/blackbox/testdata/generator/generator.qbs @@ -18,12 +18,12 @@ CppApplication { var f = new TextFile(input.filePath, TextFile.ReadOnly); var content = f.readAll(); f.close(); - if (content.contains("file1")) { + if (content.includes("file1")) { f = new TextFile(outputs.file1[0].filePath, TextFile.WriteOnly); f.writeLine("void f1() {}"); f.close(); } - if (content.contains("file2")) { + if (content.includes("file2")) { f = new TextFile(outputs.file2[0].filePath, TextFile.WriteOnly); f.writeLine("void f2() {}"); f.close(); diff --git a/tests/auto/blackbox/testdata/groups-in-modules/groups-in-modules.qbs b/tests/auto/blackbox/testdata/groups-in-modules/groups-in-modules.qbs index 7347b1211..47275821f 100644 --- a/tests/auto/blackbox/testdata/groups-in-modules/groups-in-modules.qbs +++ b/tests/auto/blackbox/testdata/groups-in-modules/groups-in-modules.qbs @@ -1,11 +1,22 @@ +import qbs.Host + Project { Product { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } Depends { name: "dep" } Depends { name: "helper" } Depends { name: "helper3" required: false } + Depends { name: "helper7" } + helper7.fileName: "helper7.c" + type: ["diamond"] files: [ diff --git a/tests/auto/blackbox/testdata/groups-in-modules/imports/Helper7Base.qbs b/tests/auto/blackbox/testdata/groups-in-modules/imports/Helper7Base.qbs new file mode 100644 index 000000000..cc55e6351 --- /dev/null +++ b/tests/auto/blackbox/testdata/groups-in-modules/imports/Helper7Base.qbs @@ -0,0 +1,8 @@ +Module { + property string directory + property string fileName + Group { + prefix: directory + "/" + files: fileName + } +} diff --git a/tests/auto/blackbox/testdata/groups-in-modules/modules/helper/helper.qbs b/tests/auto/blackbox/testdata/groups-in-modules/modules/helper/helper.qbs index cbd30a35d..9dc903411 100644 --- a/tests/auto/blackbox/testdata/groups-in-modules/modules/helper/helper.qbs +++ b/tests/auto/blackbox/testdata/groups-in-modules/modules/helper/helper.qbs @@ -39,7 +39,7 @@ Module { prepare: { var cmd = new Command(FileInfo.joinPaths(product.buildDirectory, product.targetName), [input.filePath, output.filePath]); - cmd.description = "compile " + input.fileName + " => " + output.fileName; + cmd.description = "compiling " + input.fileName + " to " + output.fileName; return [cmd]; } } diff --git a/tests/auto/blackbox/testdata/groups-in-modules/modules/helper7/helper7.c b/tests/auto/blackbox/testdata/groups-in-modules/modules/helper7/helper7.c new file mode 100644 index 000000000..a83f5476e --- /dev/null +++ b/tests/auto/blackbox/testdata/groups-in-modules/modules/helper7/helper7.c @@ -0,0 +1 @@ +void helper7(void) {} diff --git a/tests/auto/blackbox/testdata/groups-in-modules/modules/helper7/helper7.qbs b/tests/auto/blackbox/testdata/groups-in-modules/modules/helper7/helper7.qbs new file mode 100644 index 000000000..90e1f11e2 --- /dev/null +++ b/tests/auto/blackbox/testdata/groups-in-modules/modules/helper7/helper7.qbs @@ -0,0 +1,3 @@ +Helper7Base { + directory: path +} diff --git a/tests/auto/blackbox/testdata/grpc/conanfile.txt b/tests/auto/blackbox/testdata/grpc/conanfile.txt new file mode 100644 index 000000000..f88e6e8d6 --- /dev/null +++ b/tests/auto/blackbox/testdata/grpc/conanfile.txt @@ -0,0 +1,7 @@ +[requires] +grpc/1.54.3 +[tool_requires] +protobuf/3.21.12 +grpc/1.54.3 +[generators] +QbsDeps diff --git a/tests/auto/blackbox/testdata/grpc/grpc.cpp b/tests/auto/blackbox/testdata/grpc/grpc.cpp index 81995601d..5f85c5b40 100644 --- a/tests/auto/blackbox/testdata/grpc/grpc.cpp +++ b/tests/auto/blackbox/testdata/grpc/grpc.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2019 Ivan Komissarov -** Contact: abbapoh@gmail.com +** Copyright (C) 2019 Ivan Komissarov (abbapoh@gmail.com) +** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** diff --git a/tests/auto/blackbox/testdata/grpc/grpc_cpp.qbs b/tests/auto/blackbox/testdata/grpc/grpc_cpp.qbs index 8ee3dd9c9..d1bdd5d60 100644 --- a/tests/auto/blackbox/testdata/grpc/grpc_cpp.qbs +++ b/tests/auto/blackbox/testdata/grpc/grpc_cpp.qbs @@ -1,20 +1,29 @@ -import qbs +import qbs.Host CppApplication { name: "grpc_cpp" consoleApplication: true - condition: hasDependencies + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result && hasDependencies; + } Depends { name: "cpp" } - cpp.cxxLanguageVersion: "c++11" + cpp.cxxLanguageVersion: "c++17" + cpp.minimumMacosVersion: "10.15" cpp.warningLevel: "none" + qbs.buildVariant: "release" Depends { name: "protobuf.cpp"; required: false } + Depends { name: "grpc++"; id: grpcpp; required: false } protobuf.cpp.useGrpc: true property bool hasDependencies: { console.info("has grpc: " + protobuf.cpp.present); - return protobuf.cpp.present; + console.info("has modules: " + grpcpp.present); + return protobuf.cpp.present && grpcpp.present; } files: "grpc.cpp" diff --git a/tests/auto/blackbox/testdata/host-os-properties/host-os-properties.qbs b/tests/auto/blackbox/testdata/host-os-properties/host-os-properties.qbs new file mode 100644 index 000000000..9d050e166 --- /dev/null +++ b/tests/auto/blackbox/testdata/host-os-properties/host-os-properties.qbs @@ -0,0 +1,16 @@ +import qbs.Host + +CppApplication { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } + consoleApplication: true + cpp.defines: [ + 'HOST_ARCHITECTURE="' + Host.architecture() + '"', + 'HOST_PLATFORM="' + Host.platform() + '"' + ] + files: "main.cpp" +} diff --git a/tests/auto/blackbox/testdata/host-os-properties/main.cpp b/tests/auto/blackbox/testdata/host-os-properties/main.cpp new file mode 100644 index 000000000..129c16379 --- /dev/null +++ b/tests/auto/blackbox/testdata/host-os-properties/main.cpp @@ -0,0 +1,7 @@ +#include <cstdio> + +int main() { + std::printf("HOST_ARCHITECTURE = %s\n", HOST_ARCHITECTURE); + std::printf("HOST_PLATFORM = %s\n", HOST_PLATFORM); + return 0; +} diff --git a/tests/auto/blackbox/testdata/importing-product/importing-product.qbs b/tests/auto/blackbox/testdata/importing-product/importing-product.qbs index dfc4cd65e..54ad727b7 100644 --- a/tests/auto/blackbox/testdata/importing-product/importing-product.qbs +++ b/tests/auto/blackbox/testdata/importing-product/importing-product.qbs @@ -16,7 +16,7 @@ Project { } prepare: { var cmd = new JavaScriptCommand(); - cmd.description = "Copying file"; + cmd.description = "copying file"; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } diff --git a/tests/auto/blackbox/testdata/includeLookup/includeLookup.qbs b/tests/auto/blackbox/testdata/includeLookup/includeLookup.qbs index 182d1e232..903d170d0 100644 --- a/tests/auto/blackbox/testdata/includeLookup/includeLookup.qbs +++ b/tests/auto/blackbox/testdata/includeLookup/includeLookup.qbs @@ -1,9 +1,16 @@ import qbs.FileInfo +import qbs.Host Project { property string name: 'includeLookup' qbsSearchPaths: '.' Product { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } type: 'application' consoleApplication: true name: project.name diff --git a/tests/auto/blackbox/testdata/includeLookup/main.cpp b/tests/auto/blackbox/testdata/includeLookup/main.cpp index c7213c768..a91914f73 100644 --- a/tests/auto/blackbox/testdata/includeLookup/main.cpp +++ b/tests/auto/blackbox/testdata/includeLookup/main.cpp @@ -30,7 +30,7 @@ int main() { - printf("%s..\n", TEXT); + std::printf("%s..\n", TEXT); return 0; } diff --git a/tests/auto/blackbox/testdata/input-tags-change-tracking/input-tags-change-tracking.qbs b/tests/auto/blackbox/testdata/input-tags-change-tracking/input-tags-change-tracking.qbs index ef2c5c55b..1e4248009 100644 --- a/tests/auto/blackbox/testdata/input-tags-change-tracking/input-tags-change-tracking.qbs +++ b/tests/auto/blackbox/testdata/input-tags-change-tracking/input-tags-change-tracking.qbs @@ -43,10 +43,10 @@ Product { inputs: "txt" outputFileTags: "p_tag" outputArtifacts: { - if (input.fileTags.contains("empty")) + if (input.fileTags.includes("empty")) return []; return [{ - filePath: input.fileTags.contains("y") ? "y.out" : "x.out", + filePath: input.fileTags.includes("y") ? "y.out" : "x.out", fileTags: "p_tag" }] } diff --git a/tests/auto/blackbox/testdata/inputs-from-dependencies/inputs-from-dependencies.qbs b/tests/auto/blackbox/testdata/inputs-from-dependencies/inputs-from-dependencies.qbs index 919060c73..f9993ecf3 100644 --- a/tests/auto/blackbox/testdata/inputs-from-dependencies/inputs-from-dependencies.qbs +++ b/tests/auto/blackbox/testdata/inputs-from-dependencies/inputs-from-dependencies.qbs @@ -37,7 +37,7 @@ Project { } prepare: { var cmd = new JavaScriptCommand(); - cmd.description = "Gathering text files"; + cmd.description = "gathering text files"; cmd.sourceCode = function() { for (i in inputs.txt) console.info(inputs.txt[i].filePath); diff --git a/tests/auto/blackbox/testdata/install-locations/install-locations.qbs b/tests/auto/blackbox/testdata/install-locations/install-locations.qbs index 8a97f74a1..ba51c0dc1 100644 --- a/tests/auto/blackbox/testdata/install-locations/install-locations.qbs +++ b/tests/auto/blackbox/testdata/install-locations/install-locations.qbs @@ -1,16 +1,24 @@ Project { property bool dummy: { - if (qbs.targetOS.contains("windows")) + if (qbs.targetOS.includes("windows")) { console.info("is windows"); - else if (qbs.targetOS.contains("macos")) - console.info("is mac"); - else + } else if (qbs.targetOS.includes("darwin")) { + console.info("is darwin"); + if (qbs.targetOS.includes("macos")) + console.info("is mac"); + } else { console.info("is unix"); + } + + if (qbs.toolchain.includes("mingw")) + console.info("is mingw"); } CppApplication { name: "theapp" install: true + installDebugInformation: true files: "main.cpp" + cpp.separateDebugInformation: true Group { fileTagsFilter: "application" fileTags: "some-tag" @@ -20,7 +28,17 @@ Project { name: "thelib" install: true installImportLib: true + installDebugInformation: true Depends { name: "cpp" } + cpp.separateDebugInformation: true files: "thelib.cpp" } + LoadableModule { + name: "theplugin" + install: true + installDebugInformation: true + Depends { name: "cpp" } + cpp.separateDebugInformation: true + files: "theplugin.cpp" + } } diff --git a/tests/auto/blackbox/testdata/install-locations/theplugin.cpp b/tests/auto/blackbox/testdata/install-locations/theplugin.cpp new file mode 100644 index 000000000..ac1ede090 --- /dev/null +++ b/tests/auto/blackbox/testdata/install-locations/theplugin.cpp @@ -0,0 +1,3 @@ +#include "../dllexport.h" + +DLL_EXPORT void pluginFunc() {} diff --git a/tests/auto/blackbox/testdata/installable-as-auxiliary-input/installable-as-auxiliary-input.qbs b/tests/auto/blackbox/testdata/installable-as-auxiliary-input/installable-as-auxiliary-input.qbs index 2d37e85d6..a445fc35b 100644 --- a/tests/auto/blackbox/testdata/installable-as-auxiliary-input/installable-as-auxiliary-input.qbs +++ b/tests/auto/blackbox/testdata/installable-as-auxiliary-input/installable-as-auxiliary-input.qbs @@ -1,10 +1,17 @@ import qbs.File import qbs.FileInfo +import qbs.Host import qbs.TextFile Project { name: "p" CppApplication { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } name: "app" Depends { name: "installed-header" } Rule { @@ -42,7 +49,7 @@ Project { Export { Depends { name: "cpp" } - cpp.includePaths: FileInfo.joinPaths(qbs.installRoot, product.installDir); + cpp.includePaths: FileInfo.joinPaths(qbs.installRoot, exportingProduct.installDir); } Rule { @@ -50,7 +57,7 @@ Project { Artifact { filePath: "theheader.h.in"; fileTags: "header.in" } prepare: { var cmd = new JavaScriptCommand(); - cmd.description = "Creating " + output.fileName; + cmd.description = "creating " + output.fileName; cmd.sourceCode = function() { for (var i = 0; i < 1000; ++i) { // Artificial delay. var file = new TextFile(output.filePath, TextFile.WriteOnly); @@ -69,7 +76,7 @@ Project { Artifact { filePath: "theheader.h"; fileTags: "header" } prepare: { var cmd = new JavaScriptCommand(); - cmd.description = "Creating " + output.fileName; + cmd.description = "creating " + output.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); }; return [cmd]; } diff --git a/tests/auto/blackbox/testdata/installable/installable.qbs b/tests/auto/blackbox/testdata/installable/installable.qbs index 56feb6ec5..de93cf61f 100644 --- a/tests/auto/blackbox/testdata/installable/installable.qbs +++ b/tests/auto/blackbox/testdata/installable/installable.qbs @@ -11,6 +11,7 @@ Project { } install: true + installDebugInformation: false installDir: "" } @@ -27,7 +28,7 @@ Project { } prepare: { var cmd = new JavaScriptCommand(); - cmd.description = "Creating " + output.fileName; + cmd.description = "creating " + output.fileName; cmd.sourceCode = function() { var file = new TextFile(output.filePath, TextFile.WriteOnly); for (var i = 0; i < inputs.installable.length; ++i) diff --git a/tests/auto/blackbox/testdata/installed-transformer-output/qbs668.qbs b/tests/auto/blackbox/testdata/installed-transformer-output/qbs668.qbs index aa40b7691..6f84206be 100644 --- a/tests/auto/blackbox/testdata/installed-transformer-output/qbs668.qbs +++ b/tests/auto/blackbox/testdata/installed-transformer-output/qbs668.qbs @@ -18,7 +18,7 @@ Product { } prepare: { var cmd = new JavaScriptCommand(); - cmd.description = "Creating file:'" + output.fileName + "'"; + cmd.description = "creating file:'" + output.fileName + "'"; cmd.highlight = "codegen"; cmd.sourceCode = function() { var file = new TextFile(output.filePath, TextFile.WriteOnly); diff --git a/tests/auto/blackbox/testdata/installpackage/installpackage.qbs b/tests/auto/blackbox/testdata/installpackage/installpackage.qbs index a0649a578..3396b79a4 100644 --- a/tests/auto/blackbox/testdata/installpackage/installpackage.qbs +++ b/tests/auto/blackbox/testdata/installpackage/installpackage.qbs @@ -2,7 +2,7 @@ Project { CppApplication { name: "public_tool" Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } Depends { name: "mylib" } @@ -20,7 +20,7 @@ Project { } DynamicLibrary { Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } Depends { name: "cpp" } diff --git a/tests/auto/blackbox/testdata/invalid-artifact-path/invalid-artifact-path.qbs b/tests/auto/blackbox/testdata/invalid-artifact-path/invalid-artifact-path.qbs new file mode 100644 index 000000000..650233d86 --- /dev/null +++ b/tests/auto/blackbox/testdata/invalid-artifact-path/invalid-artifact-path.qbs @@ -0,0 +1,18 @@ +Project { + property string artifactDir + Product { + type: "t" + Rule { + multiplex: true + Artifact { + filePath: project.artifactDir + "/file.out" + fileTags: "t" + } + prepare: { + var cmd = new JavaScriptCommand(); + cmd.sourceCode = function() {}; + return cmd; + } + } + } +} diff --git a/tests/auto/blackbox/testdata/invalid-command-property/invalid-command-property.qbs b/tests/auto/blackbox/testdata/invalid-command-property/invalid-command-property.qbs index b08fcd4a3..a07beda57 100644 --- a/tests/auto/blackbox/testdata/invalid-command-property/invalid-command-property.qbs +++ b/tests/auto/blackbox/testdata/invalid-command-property/invalid-command-property.qbs @@ -16,7 +16,7 @@ Product { } prepare: { var cmd = new JavaScriptCommand(); - cmd.description = "Creating output"; + cmd.description = "creating output"; if (product.errorType === "qobject") cmd.dummy = new TextFile(input.filePath, TextFile.ReadOnly); else if (product.errorType === "input") diff --git a/tests/auto/blackbox/testdata/jsextensions-binaryfile/binaryfile.qbs b/tests/auto/blackbox/testdata/jsextensions-binaryfile/binaryfile.qbs index 1e7426744..5824fe518 100644 --- a/tests/auto/blackbox/testdata/jsextensions-binaryfile/binaryfile.qbs +++ b/tests/auto/blackbox/testdata/jsextensions-binaryfile/binaryfile.qbs @@ -36,6 +36,9 @@ Product { destination.write(source.atEof() ? [ 0xFF ] : [ 0x00 ]); source.close(); destination.close(); + source = new BinaryFile("destination.dat", BinaryFile.ReadOnly); + destination = new BinaryFile("destination2.dat", BinaryFile.WriteOnly); + destination.write(source.read(8)); }; commands.push(cmd); return commands; diff --git a/tests/auto/blackbox/testdata/jsextensions-file/file.qbs b/tests/auto/blackbox/testdata/jsextensions-file/file.qbs index 6adf714e2..7a47cf3cd 100644 --- a/tests/auto/blackbox/testdata/jsextensions-file/file.qbs +++ b/tests/auto/blackbox/testdata/jsextensions-file/file.qbs @@ -33,10 +33,10 @@ Product { if (!created || !File.exists(zePath)) throw new Error("zePath was not created."); var entries = File.directoryEntries(product.sourceDirectory, File.AllEntries | File.NoDotAndDotDot); - if (entries.length < 3 || !entries.contains("file.qbs")) + if (entries.length < 3 || !entries.includes("file.qbs")) throw new Error("Directory did not contain file.qbs"); entries = File.directoryEntries(product.sourceDirectory, File.Dirs | File.NoDotAndDotDot); - if (entries.length < 1 || !entries.contains("zePath")) + if (entries.length < 1 || !entries.includes("zePath")) throw new Error("Directory did not contain only zePath"); var moveSource = FileInfo.joinPaths(product.sourceDirectory, "tomove.txt"); var moveTarget = FileInfo.joinPaths(product.sourceDirectory, "moved.txt"); diff --git a/tests/auto/blackbox/testdata/jsextensions-fileinfo/fileinfo.qbs b/tests/auto/blackbox/testdata/jsextensions-fileinfo/fileinfo.qbs index d63ba2962..0e727d04b 100644 --- a/tests/auto/blackbox/testdata/jsextensions-fileinfo/fileinfo.qbs +++ b/tests/auto/blackbox/testdata/jsextensions-fileinfo/fileinfo.qbs @@ -39,6 +39,8 @@ Product { output.writeLine(FileInfo.relativePath("/tmp", "/blubb.tar.gz")); output.writeLine(FileInfo.toWindowsSeparators("/tmp/blubb.tar.gz")); output.writeLine(FileInfo.toWindowsSeparators("c:\\tmp\\blubb.tar.gz")); + output.writeLine(FileInfo.pathListSeparator()); + output.writeLine(FileInfo.pathSeparator()); output.close(); }; return [cmd]; diff --git a/tests/auto/blackbox/testdata/jsextensions-host/host.qbs b/tests/auto/blackbox/testdata/jsextensions-host/host.qbs new file mode 100644 index 000000000..08d13b25d --- /dev/null +++ b/tests/auto/blackbox/testdata/jsextensions-host/host.qbs @@ -0,0 +1,31 @@ +import qbs.FileInfo +import qbs.Host +import qbs.TextFile + +Product { + type: ["dummy"] + Rule { + multiplex: true + outputFileTags: "dummy" + prepare: { + var cmd = new JavaScriptCommand(); + cmd.silent = true; + cmd.sourceCode = function() { + var output = new TextFile(FileInfo.joinPaths(product.sourceDirectory, "output.txt"), + TextFile.WriteOnly); + output.writeLine("architecture: " +Host.architecture()); + output.writeLine("os: " + Host.os()); + output.writeLine("platform: " + Host.platform()); + output.writeLine("osVersion: " + Host.osVersion()); + output.writeLine("osBuildVersion: " + Host.osBuildVersion()); + output.writeLine("osVersionParts: " + Host.osVersionParts()); + output.writeLine("osVersionMajor: " + Host.osVersionMajor()); + output.writeLine("osVersionMinor: " + Host.osVersionMinor()); + output.writeLine("osVersionPatch: " + Host.osVersionPatch()); + output.writeLine("nullDevice: " + Host.nullDevice()); + output.close(); + }; + return [cmd]; + } + } +} diff --git a/tests/auto/blackbox/testdata/jsextensions-process/main.cpp b/tests/auto/blackbox/testdata/jsextensions-process/main.cpp index df769de87..3f28fe091 100644 --- a/tests/auto/blackbox/testdata/jsextensions-process/main.cpp +++ b/tests/auto/blackbox/testdata/jsextensions-process/main.cpp @@ -4,17 +4,17 @@ int main(int argc, char *argv[]) { - if (argc != 2 || strcmp(argv[1], "help") != 0) { - fprintf(stderr, "First argument to this program must be 'help'.\n"); + if (argc != 2 || std::strcmp(argv[1], "help") != 0) { + std::fprintf(stderr, "First argument to this program must be 'help'.\n"); return 1; } const char *env = std::getenv("SOME_ENV"); - if (!env || strcmp(env, "why, hello!") != 0) { - fprintf(stderr, "The SOME_ENV environment variable must be 'why, hello!'.\n"); + if (!env || std::strcmp(env, "why, hello!") != 0) { + std::fprintf(stderr, "The SOME_ENV environment variable must be 'why, hello!'.\n"); return 1; } - printf("qbs jsextensions-process test\n"); + std::printf("qbs jsextensions-process test\n"); return 0; } diff --git a/tests/auto/blackbox/testdata/jsextensions-process/process.qbs b/tests/auto/blackbox/testdata/jsextensions-process/process.qbs index eba95d005..50f22cdfc 100644 --- a/tests/auto/blackbox/testdata/jsextensions-process/process.qbs +++ b/tests/auto/blackbox/testdata/jsextensions-process/process.qbs @@ -1,10 +1,17 @@ import qbs.Environment import qbs.FileInfo +import qbs.Host import qbs.Process import qbs.TextFile Project { Product { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } Depends { name: "cpp" } type: ["dummy"] name: "dummy" @@ -48,7 +55,7 @@ Project { // closeWriteChannel test process = new Process(); - if (product.qbs.hostOS.contains("windows")) + if (Host.os().includes("windows")) process.start(product.qbs.windowsShellPath, ["/C", product.qbs.windowsSystemRoot + "\\system32\\sort.exe"]); else @@ -69,7 +76,7 @@ Project { testReadlineFile.close(); process = new Process(); - if (product.qbs.hostOS.contains("windows")) + if (Host.os().includes("windows")) process.exec(product.qbs.windowsShellPath, ["/C", "type", "123.txt"], true); diff --git a/tests/auto/blackbox/testdata/last-module-candidate-broken/last-module-candidate-broken.qbs b/tests/auto/blackbox/testdata/last-module-candidate-broken/last-module-candidate-broken.qbs new file mode 100644 index 000000000..db7dc2265 --- /dev/null +++ b/tests/auto/blackbox/testdata/last-module-candidate-broken/last-module-candidate-broken.qbs @@ -0,0 +1,5 @@ +CppApplication { + qbsSearchPaths: "qbs" + Depends { name: "Foo" } + files: "main.cpp" +} diff --git a/tests/auto/blackbox/testdata/last-module-candidate-broken/main.cpp b/tests/auto/blackbox/testdata/last-module-candidate-broken/main.cpp new file mode 100644 index 000000000..76e819701 --- /dev/null +++ b/tests/auto/blackbox/testdata/last-module-candidate-broken/main.cpp @@ -0,0 +1 @@ +int main() { return 0; } diff --git a/tests/auto/blackbox/testdata/last-module-candidate-broken/qbs/modules/Foo/Foo1.qbs b/tests/auto/blackbox/testdata/last-module-candidate-broken/qbs/modules/Foo/Foo1.qbs new file mode 100644 index 000000000..ba08b862b --- /dev/null +++ b/tests/auto/blackbox/testdata/last-module-candidate-broken/qbs/modules/Foo/Foo1.qbs @@ -0,0 +1,3 @@ +Module { + condition: false +} diff --git a/tests/auto/blackbox/testdata/last-module-candidate-broken/qbs/modules/Foo/Foo2.qbs b/tests/auto/blackbox/testdata/last-module-candidate-broken/qbs/modules/Foo/Foo2.qbs new file mode 100644 index 000000000..0bc383b86 --- /dev/null +++ b/tests/auto/blackbox/testdata/last-module-candidate-broken/qbs/modules/Foo/Foo2.qbs @@ -0,0 +1,2 @@ +Group { +} diff --git a/tests/auto/blackbox/testdata/ld/ld.qbs b/tests/auto/blackbox/testdata/ld/ld.qbs index 25fede1b0..cb04d3d9a 100644 --- a/tests/auto/blackbox/testdata/ld/ld.qbs +++ b/tests/auto/blackbox/testdata/ld/ld.qbs @@ -5,7 +5,7 @@ Project { targetName: "qbs can handle any file paths, even the crazy ones! ;)" files: ["coreutils.cpp", "coreutils.h"] Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false cpp.sonamePrefix: "@rpath" } diff --git a/tests/auto/blackbox/testdata/ld/main.cpp b/tests/auto/blackbox/testdata/ld/main.cpp index fd6b72f3b..bcf293705 100644 --- a/tests/auto/blackbox/testdata/ld/main.cpp +++ b/tests/auto/blackbox/testdata/ld/main.cpp @@ -27,10 +27,11 @@ ****************************************************************************/ #include "coreutils.h" -#include <stdio.h> + +#include <cstdio> int main(int argc, char *argv[]) { - printf("%d\n", foo()); + std::printf("%d\n", foo()); return 0; } diff --git a/tests/auto/blackbox/testdata/lexyacc/modules/bisonhelper/bisonhelper.qbs b/tests/auto/blackbox/testdata/lexyacc/modules/bisonhelper/bisonhelper.qbs index 449b130e2..4cce9a1e3 100644 --- a/tests/auto/blackbox/testdata/lexyacc/modules/bisonhelper/bisonhelper.qbs +++ b/tests/auto/blackbox/testdata/lexyacc/modules/bisonhelper/bisonhelper.qbs @@ -1,4 +1,3 @@ -import qbs import qbs.Process Module { @@ -8,7 +7,7 @@ Module { property string yaccBinary: lex_yacc.yaccBinary configure: { var p = Process(); - found = p.exec(yaccBinary, ["-V"]) == 0 && p.readStdOut().contains("bison"); + found = p.exec(yaccBinary, ["-V"]) == 0 && p.readStdOut().includes("bison"); p.close(); } } diff --git a/tests/auto/blackbox/testdata/lexyacc/one-grammar/one-grammar.qbs b/tests/auto/blackbox/testdata/lexyacc/one-grammar/one-grammar.qbs index 6cd334247..faa5d1fac 100644 --- a/tests/auto/blackbox/testdata/lexyacc/one-grammar/one-grammar.qbs +++ b/tests/auto/blackbox/testdata/lexyacc/one-grammar/one-grammar.qbs @@ -1,4 +1,12 @@ +import qbs.Host + CppApplication { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } qbsSearchPaths: ".." Depends { name: "bisonhelper" } Depends { name: "lex_yacc" } @@ -11,10 +19,10 @@ CppApplication { Probe { id: pathCheck property string theDir: { - if (qbs.targetOS.contains("windows")) { - if (qbs.toolchain.contains("mingw")) + if (qbs.targetOS.includes("windows")) { + if (qbs.toolchain.includes("mingw")) return cpp.toolchainInstallPath; - if (qbs.toolchain.contains("clang") && qbs.sysroot) + if (qbs.toolchain.includes("clang") && qbs.sysroot) return qbs.sysroot + "/bin"; } } diff --git a/tests/auto/blackbox/testdata/lexyacc/two-grammars/two-grammars.qbs b/tests/auto/blackbox/testdata/lexyacc/two-grammars/two-grammars.qbs index 7b0c1e515..648860d9c 100644 --- a/tests/auto/blackbox/testdata/lexyacc/two-grammars/two-grammars.qbs +++ b/tests/auto/blackbox/testdata/lexyacc/two-grammars/two-grammars.qbs @@ -1,7 +1,13 @@ +import qbs.Host + CppApplication { Depends { name: "lex_yacc" } consoleApplication: true cpp.includePaths: ".." + Properties { + condition: Host.os().includes("darwin") && qbs.toolchain.includes("clang") + cpp.cFlags: "-Wno-implicit-function-declaration" + } files: [ "g1.l", "g1.y", diff --git a/tests/auto/blackbox/testdata/linker-library-duplicates/setup-run-environment.qbs b/tests/auto/blackbox/testdata/linker-library-duplicates/setup-run-environment.qbs index 9723fd3f5..c41e8f1d7 100644 --- a/tests/auto/blackbox/testdata/linker-library-duplicates/setup-run-environment.qbs +++ b/tests/auto/blackbox/testdata/linker-library-duplicates/setup-run-environment.qbs @@ -1,5 +1,3 @@ -import qbs 1.0 - Project { DynamicLibrary { id: idLib1 @@ -8,6 +6,11 @@ Project { files: ["lib1.cpp"] Depends { name: "bundle" } bundle.isBundle: false + Probe { + id: checker + property bool isGcc: qbs.toolchain.contains("gcc") + configure: { console.info("is gcc: " + isGcc); } + } } DynamicLibrary { diff --git a/tests/auto/blackbox/testdata/linker-module-definition/linker-module-definition.qbs b/tests/auto/blackbox/testdata/linker-module-definition/linker-module-definition.qbs new file mode 100644 index 000000000..cae80e651 --- /dev/null +++ b/tests/auto/blackbox/testdata/linker-module-definition/linker-module-definition.qbs @@ -0,0 +1,20 @@ +import qbs.Host + +Project { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } + DynamicLibrary { + name: "testlib" + Depends { name: "cpp"} + files: ["testlib.cpp", "testlib.def"] + } + CppApplication { + name: "testapp" + Depends { name: "testlib"} + files: ["testapp.cpp"] + } +} diff --git a/tests/auto/blackbox/testdata/linker-module-definition/testapp.cpp b/tests/auto/blackbox/testdata/linker-module-definition/testapp.cpp new file mode 100644 index 000000000..7cb5ee901 --- /dev/null +++ b/tests/auto/blackbox/testdata/linker-module-definition/testapp.cpp @@ -0,0 +1,39 @@ +/**************************************************************************** +** +** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +extern void foo(); +extern void bar(); + +int main() +{ + foo(); + bar(); + return 0; +} diff --git a/tests/auto/blackbox/testdata/linker-module-definition/testlib.cpp b/tests/auto/blackbox/testdata/linker-module-definition/testlib.cpp new file mode 100644 index 000000000..4af8dd9bb --- /dev/null +++ b/tests/auto/blackbox/testdata/linker-module-definition/testlib.cpp @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include <cstdio> + +void foo() +{ + std::printf("foo\n"); +} + +void bar() +{ + std::printf("bar\n"); +} diff --git a/tests/auto/blackbox/testdata/linker-module-definition/testlib.def b/tests/auto/blackbox/testdata/linker-module-definition/testlib.def new file mode 100644 index 000000000..36967ddd5 --- /dev/null +++ b/tests/auto/blackbox/testdata/linker-module-definition/testlib.def @@ -0,0 +1,3 @@ +EXPORTS +foo +bar diff --git a/tests/auto/blackbox/testdata/linker-variant/linker-variant.qbs b/tests/auto/blackbox/testdata/linker-variant/linker-variant.qbs index 57bd4ccba..9256bf767 100644 --- a/tests/auto/blackbox/testdata/linker-variant/linker-variant.qbs +++ b/tests/auto/blackbox/testdata/linker-variant/linker-variant.qbs @@ -3,7 +3,7 @@ CppApplication { property string linkerVariant Probe { id: gccProbe - property bool isGcc: qbs.toolchain.contains("gcc") + property bool isGcc: qbs.toolchain.includes("gcc") configure: { console.info("is GCC: " + isGcc); if (isGcc) diff --git a/tests/auto/blackbox/testdata/linkerMode/darwin.s b/tests/auto/blackbox/testdata/linkerMode/darwin.s new file mode 100644 index 000000000..fb165114b --- /dev/null +++ b/tests/auto/blackbox/testdata/linkerMode/darwin.s @@ -0,0 +1,6 @@ +.globl _main +.globl main + +_main: +main: + ret diff --git a/tests/auto/blackbox/testdata/linkerMode/linkerMode.qbs b/tests/auto/blackbox/testdata/linkerMode/linkerMode.qbs index 1be50c0aa..176730ce0 100644 --- a/tests/auto/blackbox/testdata/linkerMode/linkerMode.qbs +++ b/tests/auto/blackbox/testdata/linkerMode/linkerMode.qbs @@ -2,7 +2,7 @@ Project { CppApplication { consoleApplication: true name: "LinkedProduct-Assembly" - files: ["main.s"] + files: qbs.targetOS.includes("darwin") ? "darwin.s" : "main.s" cpp.linkerPath: cpp.compilerPathByLanguage["c"] @@ -24,7 +24,7 @@ Project { } CppApplication { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") consoleApplication: true name: "LinkedProduct-Objective-C" @@ -50,7 +50,7 @@ Project { } CppApplication { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") consoleApplication: true name: "LinkedProduct-Objective-C++" diff --git a/tests/auto/blackbox/testdata/linkerscripts/linkerscripts.qbs b/tests/auto/blackbox/testdata/linkerscripts/linkerscripts.qbs index 0b4de0ab9..6d068b6a2 100644 --- a/tests/auto/blackbox/testdata/linkerscripts/linkerscripts.qbs +++ b/tests/auto/blackbox/testdata/linkerscripts/linkerscripts.qbs @@ -55,6 +55,13 @@ DynamicLibrary { } } + Probe { + id: checker + property bool isGcc: qbs.toolchain.contains("gcc") + property bool isLinux: qbs.targetOS.contains("linux") + configure: { console.info("is Linux gcc: " + (isGcc && isLinux)) } + } + qbs.installPrefix: "" install: true installDir: "" diff --git a/tests/auto/blackbox/testdata/list-property-order/modules/lower/lower.qbs b/tests/auto/blackbox/testdata/list-property-order/modules/lower/lower.qbs index df9181641..c47a40aea 100644 --- a/tests/auto/blackbox/testdata/list-property-order/modules/lower/lower.qbs +++ b/tests/auto/blackbox/testdata/list-property-order/modules/lower/lower.qbs @@ -1,5 +1,5 @@ Module { - property stringList listProp + property stringList listProp: [ "lower" ] Rule { inputs: ["intype"] diff --git a/tests/auto/blackbox/testdata/list-property-order/product.qbs b/tests/auto/blackbox/testdata/list-property-order/product.qbs index e92494693..bec122214 100644 --- a/tests/auto/blackbox/testdata/list-property-order/product.qbs +++ b/tests/auto/blackbox/testdata/list-property-order/product.qbs @@ -4,6 +4,7 @@ Product { Depends { name: "higher1" } Depends { name: "higher2" } Depends { name: "higher3" } + lower.listProp: ["product"] Group { files: ["dummy.txt"] fileTags: ["intype"] diff --git a/tests/auto/blackbox/testdata/loadablemodule/loadablemodule.qbs b/tests/auto/blackbox/testdata/loadablemodule/loadablemodule.qbs index ec5b0b358..8023eed36 100644 --- a/tests/auto/blackbox/testdata/loadablemodule/loadablemodule.qbs +++ b/tests/auto/blackbox/testdata/loadablemodule/loadablemodule.qbs @@ -1,8 +1,10 @@ +import qbs.Host + Project { LoadableModule { Depends { name: "cpp" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } name: "CoolPlugIn" @@ -15,6 +17,12 @@ Project { } CppApplication { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } Depends { name: "cpp" } Depends { name: "CoolPlugIn"; cpp.link: false } consoleApplication: true @@ -22,10 +30,10 @@ Project { files: ["main.cpp"] cpp.cxxLanguageVersion: "c++11" - cpp.dynamicLibraries: [qbs.targetOS.contains("windows") ? "kernel32" : "dl"] + cpp.dynamicLibraries: [qbs.targetOS.includes("windows") ? "kernel32" : "dl"] Properties { - condition: qbs.targetOS.contains("unix") && !qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("unix") && !qbs.targetOS.includes("darwin") cpp.rpaths: [cpp.rpathOrigin] } diff --git a/tests/auto/blackbox/testdata/localDeployment/localDeployment.qbs b/tests/auto/blackbox/testdata/localDeployment/localDeployment.qbs index 650f07104..b3fa86d32 100644 --- a/tests/auto/blackbox/testdata/localDeployment/localDeployment.qbs +++ b/tests/auto/blackbox/testdata/localDeployment/localDeployment.qbs @@ -1,5 +1,13 @@ +import qbs.Host + Project { Product { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } type: ["application"] consoleApplication: true name: "HelloWorld" diff --git a/tests/auto/blackbox/testdata/lsp/lsp.qbs b/tests/auto/blackbox/testdata/lsp/lsp.qbs new file mode 100644 index 000000000..24479e0ec --- /dev/null +++ b/tests/auto/blackbox/testdata/lsp/lsp.qbs @@ -0,0 +1,11 @@ +Project { + Product { + name: "dep" + Depends { name: "m" } + Depends { name: "Prefix"; submodules: ["m1", "m2", "m3"] } + + } + Product { + Depends { name: "dep" } + } +} diff --git a/tests/auto/blackbox/testdata/lsp/modules/Prefix/m1/m1.qbs b/tests/auto/blackbox/testdata/lsp/modules/Prefix/m1/m1.qbs new file mode 100644 index 000000000..09bac2dc2 --- /dev/null +++ b/tests/auto/blackbox/testdata/lsp/modules/Prefix/m1/m1.qbs @@ -0,0 +1,5 @@ +Module { + property bool p1 + property string p2 + property bool x +} diff --git a/tests/auto/blackbox/testdata/lsp/modules/Prefix/m2/m2.qbs b/tests/auto/blackbox/testdata/lsp/modules/Prefix/m2/m2.qbs new file mode 100644 index 000000000..84957060c --- /dev/null +++ b/tests/auto/blackbox/testdata/lsp/modules/Prefix/m2/m2.qbs @@ -0,0 +1,2 @@ +Module { +} diff --git a/tests/auto/blackbox/testdata/lsp/modules/Prefix/m3/m3.qbs b/tests/auto/blackbox/testdata/lsp/modules/Prefix/m3/m3.qbs new file mode 100644 index 000000000..84957060c --- /dev/null +++ b/tests/auto/blackbox/testdata/lsp/modules/Prefix/m3/m3.qbs @@ -0,0 +1,2 @@ +Module { +} diff --git a/tests/auto/blackbox/testdata/lsp/modules/m/m.qbs b/tests/auto/blackbox/testdata/lsp/modules/m/m.qbs new file mode 100644 index 000000000..84957060c --- /dev/null +++ b/tests/auto/blackbox/testdata/lsp/modules/m/m.qbs @@ -0,0 +1,2 @@ +Module { +} diff --git a/tests/auto/blackbox/testdata/makefile-generator/app.qbs b/tests/auto/blackbox/testdata/makefile-generator/app.qbs index dfd67276e..fd3fbb91b 100644 --- a/tests/auto/blackbox/testdata/makefile-generator/app.qbs +++ b/tests/auto/blackbox/testdata/makefile-generator/app.qbs @@ -1,11 +1,19 @@ +import qbs.Host + CppApplication { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } name: "the app" consoleApplication: true cpp.cxxLanguageVersion: "c++11" cpp.separateDebugInformation: false Properties { - condition: qbs.targetOS.contains("macos") + condition: qbs.targetOS.includes("macos") bundle.embedInfoPlist: false cpp.minimumMacosVersion: "10.7" } diff --git a/tests/auto/blackbox/testdata/maximum-c-language-version/maximum-c-language-version.qbs b/tests/auto/blackbox/testdata/maximum-c-language-version/maximum-c-language-version.qbs index 320494d00..9f41570f8 100644 --- a/tests/auto/blackbox/testdata/maximum-c-language-version/maximum-c-language-version.qbs +++ b/tests/auto/blackbox/testdata/maximum-c-language-version/maximum-c-language-version.qbs @@ -4,10 +4,13 @@ CppApplication { Probe { id: osProbe - property stringList toolchain: qbs.toolchain + property string toolchainType: qbs.toolchainType + property string compilerVersion: cpp.compilerVersion configure: { - if (toolchain.contains("msvc")) - console.info("is msvc"); + console.info("is msvc: " + (toolchainType === "msvc" || toolchainType === "clang-cl")); + var isOld = (toolchainType === "msvc" && compilerVersion < "19.29.30138") + || (toolchainType === "clang-cl" && compilerVersion < "13"); + console.info("is old msvc: " + isOld); found = true; } } diff --git a/tests/auto/blackbox/testdata/maximum-cxx-language-version/modules/newestmodule/newestmodule.qbs b/tests/auto/blackbox/testdata/maximum-cxx-language-version/modules/newestmodule/newestmodule.qbs index f99932b10..305cb29f1 100644 --- a/tests/auto/blackbox/testdata/maximum-cxx-language-version/modules/newestmodule/newestmodule.qbs +++ b/tests/auto/blackbox/testdata/maximum-cxx-language-version/modules/newestmodule/newestmodule.qbs @@ -1,4 +1,4 @@ Module { Depends { name: "cpp" } - cpp.cxxLanguageVersion: "c++17" + cpp.cxxLanguageVersion: "c++23" } diff --git a/tests/auto/blackbox/testdata/minimumSystemVersion/fakewindows.qbs b/tests/auto/blackbox/testdata/minimumSystemVersion/fakewindows.qbs index 1a56e0b7e..da836e609 100644 --- a/tests/auto/blackbox/testdata/minimumSystemVersion/fakewindows.qbs +++ b/tests/auto/blackbox/testdata/minimumSystemVersion/fakewindows.qbs @@ -4,7 +4,7 @@ import qbs.Utilities // (but will still compile and link since we avoid passing a // bad value to the linker) CppApplication { - condition: qbs.targetOS.contains("windows") + condition: qbs.targetOS.includes("windows") files: ["main.cpp"] consoleApplication: true cpp.minimumWindowsVersion: "5.3" diff --git a/tests/auto/blackbox/testdata/minimumSystemVersion/macappstore.qbs b/tests/auto/blackbox/testdata/minimumSystemVersion/macappstore.qbs index 8440da779..26a94e132 100644 --- a/tests/auto/blackbox/testdata/minimumSystemVersion/macappstore.qbs +++ b/tests/auto/blackbox/testdata/minimumSystemVersion/macappstore.qbs @@ -1,8 +1,15 @@ // just to make sure three-digit minimum versions work on macOS // this only affects the value of __MAC_OS_X_VERSION_MIN_REQUIRED, // not the actual LC_VERSION_MIN_MACOSX command which is limited to two +import qbs.Host + CppApplication { - condition: qbs.targetOS.contains("macos") + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result && qbs.targetOS.includes("macos"); + } files: ["main.mm"] consoleApplication: true cpp.frameworks: "Foundation" diff --git a/tests/auto/blackbox/testdata/minimumSystemVersion/specific.qbs b/tests/auto/blackbox/testdata/minimumSystemVersion/specific.qbs index f6ecab418..b2b67642a 100644 --- a/tests/auto/blackbox/testdata/minimumSystemVersion/specific.qbs +++ b/tests/auto/blackbox/testdata/minimumSystemVersion/specific.qbs @@ -3,22 +3,29 @@ import qbs.Utilities // a specific version of the operating systems is specified // when the application is run its output should confirm // that the given values took effect +import qbs.Host + CppApplication { - condition: qbs.targetOS.contains("windows") || qbs.targetOS.contains("macos") - files: [qbs.targetOS.contains("darwin") ? "main.mm" : "main.cpp"] + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result && qbs.targetOS.includes("windows") || qbs.targetOS.includes("macos"); + } + files: [qbs.targetOS.includes("darwin") ? "main.mm" : "main.cpp"] consoleApplication: true Properties { - condition: qbs.targetOS.contains("windows") - cpp.minimumWindowsVersion: "6.0" + condition: qbs.targetOS.includes("windows") + cpp.minimumWindowsVersion: "6.2" cpp.defines: [ - "QBS_WINVER=0x600", + "QBS_WINVER=0x602", "TOOLCHAIN_INSTALL_PATH=" + Utilities.cStringQuote(cpp.toolchainInstallPath) ] } Properties { - condition: qbs.targetOS.contains("macos") + condition: qbs.targetOS.includes("macos") cpp.frameworks: "Foundation" cpp.minimumMacosVersion: "10.7" } diff --git a/tests/auto/blackbox/testdata/minimumSystemVersion/unspecified-forced.qbs b/tests/auto/blackbox/testdata/minimumSystemVersion/unspecified-forced.qbs index a5ea620fd..adb61a6d8 100644 --- a/tests/auto/blackbox/testdata/minimumSystemVersion/unspecified-forced.qbs +++ b/tests/auto/blackbox/testdata/minimumSystemVersion/unspecified-forced.qbs @@ -2,8 +2,16 @@ import qbs.Utilities // no minimum versions are specified, and explicitly set to undefined in // case the profile has set it +import qbs.Host + CppApplication { - files: [qbs.targetOS.contains("darwin") ? "main.mm" : "main.cpp"] + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } + files: [qbs.targetOS.includes("darwin") ? "main.mm" : "main.cpp"] consoleApplication: true cpp.minimumWindowsVersion: undefined cpp.minimumMacosVersion: undefined @@ -11,12 +19,12 @@ CppApplication { cpp.minimumAndroidVersion: undefined Properties { - condition: qbs.targetOS.contains("windows") + condition: qbs.targetOS.includes("windows") cpp.defines: ["TOOLCHAIN_INSTALL_PATH=" + Utilities.cStringQuote(cpp.toolchainInstallPath)] } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") cpp.frameworks: "Foundation" } } diff --git a/tests/auto/blackbox/testdata/minimumSystemVersion/unspecified.qbs b/tests/auto/blackbox/testdata/minimumSystemVersion/unspecified.qbs index 0eeb2d547..3c6559c39 100644 --- a/tests/auto/blackbox/testdata/minimumSystemVersion/unspecified.qbs +++ b/tests/auto/blackbox/testdata/minimumSystemVersion/unspecified.qbs @@ -1,17 +1,25 @@ import qbs.Utilities // no minimum versions are specified so the profile defaults will be used +import qbs.Host + CppApplication { - files: [qbs.targetOS.contains("darwin") ? "main.mm" : "main.cpp"] + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } + files: [qbs.targetOS.includes("darwin") ? "main.mm" : "main.cpp"] consoleApplication: true Properties { - condition: qbs.targetOS.contains("windows") + condition: qbs.targetOS.includes("windows") cpp.defines: ["TOOLCHAIN_INSTALL_PATH=" + Utilities.cStringQuote(cpp.toolchainInstallPath)] } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") cpp.frameworks: "Foundation" } } diff --git a/tests/auto/blackbox/testdata/module-conditions/module-conditions.qbs b/tests/auto/blackbox/testdata/module-conditions/module-conditions.qbs index dc3768203..207df5ded 100644 --- a/tests/auto/blackbox/testdata/module-conditions/module-conditions.qbs +++ b/tests/auto/blackbox/testdata/module-conditions/module-conditions.qbs @@ -1,5 +1,3 @@ -import qbs - Project { Product { name: "p1" diff --git a/tests/auto/blackbox/testdata/module-providers/module-providers.qbs b/tests/auto/blackbox/testdata/module-providers/module-providers.qbs deleted file mode 100644 index d1ff79269..000000000 --- a/tests/auto/blackbox/testdata/module-providers/module-providers.qbs +++ /dev/null @@ -1,20 +0,0 @@ -Project { - CppApplication { - name: "app1" - Depends { name: "mygenerator.module1" } - Depends { name: "mygenerator.module2" } - moduleProviders.mygenerator.chooseLettersFrom: "beginning" - files: "main.cpp" - } - CppApplication { - name: "app2" - Depends { name: "mygenerator.module1" } - Depends { name: "mygenerator.module2" } - Profile { - name: "myProfile" - moduleProviders.mygenerator.chooseLettersFrom: "end" - } - qbs.profile: "myProfile" - files: "main.cpp" - } -} diff --git a/tests/auto/blackbox/testdata/msvc-asm-flags/include/header.inc b/tests/auto/blackbox/testdata/msvc-asm-flags/include/header.inc new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/auto/blackbox/testdata/msvc-asm-flags/include/header.inc diff --git a/tests/auto/blackbox/testdata/msvc-asm-flags/msvc-asm-flags.asm b/tests/auto/blackbox/testdata/msvc-asm-flags/msvc-asm-flags.asm new file mode 100644 index 000000000..eddc49131 --- /dev/null +++ b/tests/auto/blackbox/testdata/msvc-asm-flags/msvc-asm-flags.asm @@ -0,0 +1,8 @@ +include header.inc + +.code +main proc + mov ecx, 16 +main endp + +end
\ No newline at end of file diff --git a/tests/auto/blackbox/testdata/msvc-asm-flags/msvc-asm-flags.qbs b/tests/auto/blackbox/testdata/msvc-asm-flags/msvc-asm-flags.qbs new file mode 100644 index 000000000..d632098c9 --- /dev/null +++ b/tests/auto/blackbox/testdata/msvc-asm-flags/msvc-asm-flags.qbs @@ -0,0 +1,6 @@ +StaticLibrary { + condition: qbs.toolchain.includes("msvc") + Depends { name: "cpp" } + files: "msvc-asm-flags.asm" + cpp.assemblerFlags: ["/I", "include"] +} diff --git a/tests/auto/blackbox/testdata/multiplexed-tool/multiplexed-tool.qbs b/tests/auto/blackbox/testdata/multiplexed-tool/multiplexed-tool.qbs index 3994bd95f..1ec51c354 100644 --- a/tests/auto/blackbox/testdata/multiplexed-tool/multiplexed-tool.qbs +++ b/tests/auto/blackbox/testdata/multiplexed-tool/multiplexed-tool.qbs @@ -1,13 +1,23 @@ +import qbs.Host + Project { CppApplication { name: "tool" consoleApplication: true + property bool _testPlatform: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } Profile { name: "debugProfile" + baseProfile: project.profile qbs.buildVariant: "debug" } Profile { name: "releaseProfile" + baseProfile: project.profile qbs.buildVariant: "release" } multiplexByQbsProperties: "profiles" diff --git a/tests/auto/blackbox/testdata/nested-properties/modules/lowerlevel/lower-level.qbs b/tests/auto/blackbox/testdata/nested-properties/modules/lowerlevel/lower-level.qbs index f8b6a7dc0..a5a6c7d4b 100644 --- a/tests/auto/blackbox/testdata/nested-properties/modules/lowerlevel/lower-level.qbs +++ b/tests/auto/blackbox/testdata/nested-properties/modules/lowerlevel/lower-level.qbs @@ -10,7 +10,7 @@ Module { var cmd = new JavaScriptCommand(); cmd.sourceCode = function() { }; var prop = product.lowerlevel.prop; - cmd.description = "lowerlevel.prop is '" + prop + "'."; + cmd.description = "lowerlevel.prop is '" + prop + "'"; return [cmd]; } } diff --git a/tests/auto/blackbox/testdata/no-exported-symbols/no-exported-symbols.qbs b/tests/auto/blackbox/testdata/no-exported-symbols/no-exported-symbols.qbs index 346a94e21..9aad3d032 100644 --- a/tests/auto/blackbox/testdata/no-exported-symbols/no-exported-symbols.qbs +++ b/tests/auto/blackbox/testdata/no-exported-symbols/no-exported-symbols.qbs @@ -12,7 +12,7 @@ Project { id: toolchainProbe property stringList toolchain: qbs.toolchain configure: { - if (toolchain.contains("msvc") && !toolchain.contains("clang-cl")) + if (toolchain.includes("msvc") && !toolchain.includes("clang-cl")) console.info("compiler is MSVC") else console.info("compiler is not MSVC") diff --git a/tests/auto/blackbox/testdata/no-such-profile/no-such-profile.qbs b/tests/auto/blackbox/testdata/no-such-profile/no-such-profile.qbs index 8e64ba478..1de3a4b10 100644 --- a/tests/auto/blackbox/testdata/no-such-profile/no-such-profile.qbs +++ b/tests/auto/blackbox/testdata/no-such-profile/no-such-profile.qbs @@ -1,5 +1,3 @@ -import qbs - Product { name: "theProduct" property int p diff --git a/tests/auto/blackbox/testdata/nodejs/hello.qbs b/tests/auto/blackbox/testdata/nodejs/hello.qbs index c19e455db..849a8789f 100644 --- a/tests/auto/blackbox/testdata/nodejs/hello.qbs +++ b/tests/auto/blackbox/testdata/nodejs/hello.qbs @@ -1,4 +1,12 @@ +import qbs.Host + NodeJSApplication { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } nodejs.applicationFile: "hello.js" name: "hello" } diff --git a/tests/auto/blackbox/testdata/nsis/hello.qbs b/tests/auto/blackbox/testdata/nsis/hello.qbs index a161a6998..f70f27e2b 100644 --- a/tests/auto/blackbox/testdata/nsis/hello.qbs +++ b/tests/auto/blackbox/testdata/nsis/hello.qbs @@ -1,5 +1,5 @@ NSISSetup { - condition: qbs.targetOS.contains("windows") + condition: qbs.targetOS.includes("windows") name: "Qbs Hello" targetName: "qbs-hello-" + qbs.architecture files: ["hello.nsi", "hello.bat"] diff --git a/tests/auto/blackbox/testdata/nsisDependencies/nsisDependencies.qbs b/tests/auto/blackbox/testdata/nsisDependencies/nsisDependencies.qbs index d8185aabf..a4ce92067 100644 --- a/tests/auto/blackbox/testdata/nsisDependencies/nsisDependencies.qbs +++ b/tests/auto/blackbox/testdata/nsisDependencies/nsisDependencies.qbs @@ -2,7 +2,7 @@ import qbs.FileInfo import qbs.TextFile Project { - condition: qbs.targetOS.contains("windows") + condition: qbs.targetOS.includes("windows") NSISSetup { Depends { name: "app" } diff --git a/tests/auto/blackbox/testdata/output-redirection/output-redirection.qbs b/tests/auto/blackbox/testdata/output-redirection/output-redirection.qbs index 3ee443438..d2474cecf 100644 --- a/tests/auto/blackbox/testdata/output-redirection/output-redirection.qbs +++ b/tests/auto/blackbox/testdata/output-redirection/output-redirection.qbs @@ -1,4 +1,5 @@ import qbs.FileInfo +import qbs.Host Product { name: "the-product" @@ -21,7 +22,7 @@ Product { prepare: { var binary; var prefixArgs; - if (product.qbs.hostOS.contains("windows")) { + if (Host.os().includes("windows")) { binary = product.qbs.windowsShellPath; prefixArgs = ["/c", "type"]; } else { diff --git a/tests/auto/blackbox/testdata/overrideProjectProperties/helper_lib.qbs b/tests/auto/blackbox/testdata/overrideProjectProperties/helper_lib.qbs index b69dd0da8..c7eab99e2 100644 --- a/tests/auto/blackbox/testdata/overrideProjectProperties/helper_lib.qbs +++ b/tests/auto/blackbox/testdata/overrideProjectProperties/helper_lib.qbs @@ -3,7 +3,7 @@ DynamicLibrary { files: "helperlib.cpp" Depends { name: "cpp" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } diff --git a/tests/auto/blackbox/testdata/path-list-in-probe/main.cpp b/tests/auto/blackbox/testdata/path-list-in-probe/main.cpp new file mode 100644 index 000000000..5bc549337 --- /dev/null +++ b/tests/auto/blackbox/testdata/path-list-in-probe/main.cpp @@ -0,0 +1,4 @@ +int main() +{ + return 0; +}
\ No newline at end of file diff --git a/tests/auto/blackbox/testdata/path-list-in-probe/path-list-in-probe.qbs b/tests/auto/blackbox/testdata/path-list-in-probe/path-list-in-probe.qbs new file mode 100644 index 000000000..3bf36367a --- /dev/null +++ b/tests/auto/blackbox/testdata/path-list-in-probe/path-list-in-probe.qbs @@ -0,0 +1,18 @@ +Project { + CppApplication { + Probe { + id: theProbe + property pathList result + configure: { + result = ["main.cpp"] + found = true + } + } + property pathList res: theProbe.found ? theProbe.result : [] + + Group { + name: "files" + files: res + } + } +} diff --git a/tests/auto/blackbox/testdata/path-probe/BaseApp.qbs b/tests/auto/blackbox/testdata/path-probe/BaseApp.qbs index 84c00c240..62871698e 100644 --- a/tests/auto/blackbox/testdata/path-probe/BaseApp.qbs +++ b/tests/auto/blackbox/testdata/path-probe/BaseApp.qbs @@ -28,9 +28,10 @@ ** ****************************************************************************/ +import qbs.FileInfo import qbs.Probes -CppApplication { +Product { property varList inputSelectors property varList inputNames @@ -38,8 +39,10 @@ CppApplication { property pathList inputSearchPaths property var inputNameFilter property var inputCandidateFilter + property stringList inputEnvironmentPaths property stringList outputFilePaths + property var outputCandidatePaths Probes.PathProbe { id: probe @@ -49,6 +52,8 @@ CppApplication { nameFilter: inputNameFilter candidateFilter: inputCandidateFilter searchPaths: inputSearchPaths + platformSearchPaths: [] + environmentPaths: inputEnvironmentPaths } property bool validate: { @@ -56,21 +61,72 @@ CppApplication { if (lhs.length !== rhs.length) return false; for (var i = 0; i < lhs.length; ++i) { - if (lhs[i] !== rhs[i]) + if ((lhs[i] instanceof Array) && (rhs[i] instanceof Array)) { + if (!compareArrays(lhs[i], rhs[i])) + return false; + } else if (FileInfo.resolvePath(path, lhs[i]) !== FileInfo.resolvePath(path, rhs[i])) { return false; + } } return true; }; - if (!probe.found) + if (outputCandidatePaths) { + var actual = probe.allResults.map(function(file) { return file.candidatePaths; }); + if (!compareArrays(actual, outputCandidatePaths)) { + throw "Invalid canndidatePaths: actual = " + JSON.stringify(actual) + + ", expected = " + JSON.stringify(outputCandidatePaths); + } + } + + if (!probe.found) { + if (probe.filePath) { + throw "Invalid filePath: actual = " + JSON.stringify(probe.filePath) + + ", expected = 'undefined'"; + } + if (probe.fileName) { + throw "Invalid fileName: actual = " + JSON.stringify(probe.fileName) + + ", expected = 'undefined'"; + } + if (probe.path) { + throw "Invalid path: actual = " + JSON.stringify(probe.path) + + ", expected = 'undefined'"; + } + throw "Probe failed to find files"; + } if (outputFilePaths) { var actual = probe.allResults.map(function(file) { return file.filePath; }); - if (!compareArrays(actual, outputFilePaths)) - throw "Invalid filePaths: actual = " + actual + ", expected = " + outputFilePaths; + if (!compareArrays(actual, outputFilePaths)) { + throw "Invalid filePaths: actual = " + JSON.stringify(actual) + + ", expected = " + JSON.stringify(outputFilePaths); + } } - } - files: ["main.cpp"] + if (probe.allResults.length !== 1) + return; + + // check that single-file interface matches the first value in allResults + var expectedFilePath = probe.allResults[0].filePath; + if (probe.filePath !== expectedFilePath) { + throw "Invalid filePath: actual = " + probe.filePath + + ", expected = " + expectedFilePath; + } + var expectedFileName = probe.allResults[0].fileName; + if (probe.fileName !== expectedFileName) { + throw "Invalid fileName: actual = " + probe.fileName + + ", expected = " + expectedFileName; + } + var expectedPath = probe.allResults[0].path; + if (FileInfo.resolvePath(path, probe.path) !== FileInfo.resolvePath(path, expectedPath)) { + throw "Invalid path: actual = " + probe.path + + ", expected = " + expectedPath; + } + var expectedCandidatePaths = probe.allResults[0].candidatePaths; + if (!compareArrays(probe.candidatePaths, expectedCandidatePaths)) { + throw "Invalid candidatePaths: actual = " + JSON.stringify(probe.candidatePaths) + + ", expected = " + JSON.stringify(expectedCandidatePaths); + } + } } diff --git a/tests/auto/blackbox/testdata/path-probe/candidate-filter.qbs b/tests/auto/blackbox/testdata/path-probe/candidate-filter.qbs index a65256a68..5c259ae9b 100644 --- a/tests/auto/blackbox/testdata/path-probe/candidate-filter.qbs +++ b/tests/auto/blackbox/testdata/path-probe/candidate-filter.qbs @@ -3,10 +3,12 @@ import qbs.FileInfo BaseApp { inputNames: ["tool.1", "tool.2"] inputSearchPaths: "bin" - outputFilePaths: ["bin/tool.2"] inputCandidateFilter: { + var fi = FileInfo; return function(f) { - return FileInfo.fileName(f) == "tool.2"; + return fi.fileName(f) == "tool.2"; } } + outputFilePaths: ["bin/tool.2"] + outputCandidatePaths: [["bin/tool.1", "bin/tool.2"]] } diff --git a/tests/auto/blackbox/testdata/path-probe/environment-paths.qbs b/tests/auto/blackbox/testdata/path-probe/environment-paths.qbs new file mode 100644 index 000000000..fca824bfb --- /dev/null +++ b/tests/auto/blackbox/testdata/path-probe/environment-paths.qbs @@ -0,0 +1,10 @@ +import qbs.FileInfo + +BaseApp { + inputNames: "tool" + inputSearchPaths: ["bin", "usr/bin"] + // env takes precedence + inputEnvironmentPaths: "SEARCH_PATH" + outputFilePaths: ["usr/bin/tool"] + outputCandidatePaths: [["usr/bin/tool"]] +} diff --git a/tests/auto/blackbox/testdata/path-probe/mult-files-common-suffixes.qbs b/tests/auto/blackbox/testdata/path-probe/mult-files-common-suffixes.qbs new file mode 100644 index 000000000..c4d53a715 --- /dev/null +++ b/tests/auto/blackbox/testdata/path-probe/mult-files-common-suffixes.qbs @@ -0,0 +1,10 @@ +BaseApp { + inputSelectors: [ + {names : "tool"}, + {names : "super-tool"}, + ] + inputNameSuffixes: ".1" + inputSearchPaths: "bin" + outputFilePaths: ["bin/tool.1", "bin/super-tool.1"] + outputCandidatePaths: [["bin/tool.1"], ["bin/super-tool.1"]] +} diff --git a/tests/auto/blackbox/testdata/path-probe/mult-files-mult-suffixes.qbs b/tests/auto/blackbox/testdata/path-probe/mult-files-mult-suffixes.qbs index b112db44d..33656d4e6 100644 --- a/tests/auto/blackbox/testdata/path-probe/mult-files-mult-suffixes.qbs +++ b/tests/auto/blackbox/testdata/path-probe/mult-files-mult-suffixes.qbs @@ -1,8 +1,9 @@ BaseApp { inputSelectors: [ - {names : "tool", nameSuffixes: [".1", ".2"]}, + {names : "tool", nameSuffixes: [".0", ".1", ".2"]}, {names : "super-tool", nameSuffixes: [".1"]}, ] inputSearchPaths: "bin" outputFilePaths: ["bin/tool.1", "bin/super-tool.1"] + outputCandidatePaths: [["bin/tool.0", "bin/tool.1"], ["bin/super-tool.1"]] } diff --git a/tests/auto/blackbox/testdata/path-probe/mult-files-mult-variants.qbs b/tests/auto/blackbox/testdata/path-probe/mult-files-mult-variants.qbs index 60c56e6b4..dd0b58aa2 100644 --- a/tests/auto/blackbox/testdata/path-probe/mult-files-mult-variants.qbs +++ b/tests/auto/blackbox/testdata/path-probe/mult-files-mult-variants.qbs @@ -1,9 +1,10 @@ BaseApp { inputSelectors: [ "tool", - ["tool.1", "tool.2"], + ["tool.0", "tool.1", "tool.2"], {names : ["tool.3", "tool.4"]}, ] inputSearchPaths: "bin" outputFilePaths: ["bin/tool", "bin/tool.1", "bin/tool.3"] + outputCandidatePaths: [["bin/tool"], ["bin/tool.0", "bin/tool.1"], ["bin/tool.3"]] } diff --git a/tests/auto/blackbox/testdata/path-probe/mult-files-suffixes.qbs b/tests/auto/blackbox/testdata/path-probe/mult-files-suffixes.qbs index 5e4fc27ca..7ae78de24 100644 --- a/tests/auto/blackbox/testdata/path-probe/mult-files-suffixes.qbs +++ b/tests/auto/blackbox/testdata/path-probe/mult-files-suffixes.qbs @@ -5,4 +5,5 @@ BaseApp { ] inputSearchPaths: "bin" outputFilePaths: ["bin/tool.2", "bin/super-tool.1"] + outputCandidatePaths: [["bin/tool.2"], ["bin/super-tool.1"]] } diff --git a/tests/auto/blackbox/testdata/path-probe/mult-files.qbs b/tests/auto/blackbox/testdata/path-probe/mult-files.qbs index 08727ac01..aa08befc8 100644 --- a/tests/auto/blackbox/testdata/path-probe/mult-files.qbs +++ b/tests/auto/blackbox/testdata/path-probe/mult-files.qbs @@ -7,4 +7,5 @@ BaseApp { ] inputSearchPaths: "bin" outputFilePaths: ["bin/tool.1", "bin/tool.2", "bin/tool.3", "bin/tool.4"] + outputCandidatePaths: [["bin/tool.1"], ["bin/tool.2"], ["bin/tool.3"], ["bin/tool.4"]] } diff --git a/tests/auto/blackbox/testdata/path-probe/name-filter.qbs b/tests/auto/blackbox/testdata/path-probe/name-filter.qbs index 406988fed..b2840443b 100644 --- a/tests/auto/blackbox/testdata/path-probe/name-filter.qbs +++ b/tests/auto/blackbox/testdata/path-probe/name-filter.qbs @@ -7,4 +7,5 @@ BaseApp { }; } outputFilePaths: ["bin/tool.2"] + outputCandidatePaths: [["bin/tool.2"]] } diff --git a/tests/auto/blackbox/testdata/path-probe/non-existent-selector.qbs b/tests/auto/blackbox/testdata/path-probe/non-existent-selector.qbs index aaa27042c..aabb0fe7b 100644 --- a/tests/auto/blackbox/testdata/path-probe/non-existent-selector.qbs +++ b/tests/auto/blackbox/testdata/path-probe/non-existent-selector.qbs @@ -5,4 +5,5 @@ BaseApp { "tool.2", ] inputSearchPaths: "bin" + outputCandidatePaths: [["bin/tool.1"], ["bin/nonexistent"], ["bin/tool.2"]] } diff --git a/tests/auto/blackbox/testdata/path-probe/non-existent.qbs b/tests/auto/blackbox/testdata/path-probe/non-existent.qbs index f0c58fa6c..aad01c31b 100644 --- a/tests/auto/blackbox/testdata/path-probe/non-existent.qbs +++ b/tests/auto/blackbox/testdata/path-probe/non-existent.qbs @@ -1,4 +1,5 @@ BaseApp { inputNames: "nonexistent" inputSearchPaths: "bin" + outputCandidatePaths: [["bin/nonexistent"]] } diff --git a/tests/auto/blackbox/testdata/path-probe/single-file-mult-variants.qbs b/tests/auto/blackbox/testdata/path-probe/single-file-mult-variants.qbs index 992a0bea4..98f5b141a 100644 --- a/tests/auto/blackbox/testdata/path-probe/single-file-mult-variants.qbs +++ b/tests/auto/blackbox/testdata/path-probe/single-file-mult-variants.qbs @@ -2,4 +2,5 @@ BaseApp { inputNames: ["tool.1", "tool.2"] inputSearchPaths: "bin" outputFilePaths: ["bin/tool.1"] + outputCandidatePaths: [["bin/tool.1"]] } diff --git a/tests/auto/blackbox/testdata/path-probe/single-file-selector-array.qbs b/tests/auto/blackbox/testdata/path-probe/single-file-selector-array.qbs index 697665242..292df4add 100644 --- a/tests/auto/blackbox/testdata/path-probe/single-file-selector-array.qbs +++ b/tests/auto/blackbox/testdata/path-probe/single-file-selector-array.qbs @@ -2,4 +2,5 @@ BaseApp { inputSelectors: ["tool"] inputSearchPaths: "bin" outputFilePaths: ["bin/tool"] + outputCandidatePaths: [["bin/tool"]] } diff --git a/tests/auto/blackbox/testdata/path-probe/single-file-selector.qbs b/tests/auto/blackbox/testdata/path-probe/single-file-selector.qbs index d57700baf..cf7cfe436 100644 --- a/tests/auto/blackbox/testdata/path-probe/single-file-selector.qbs +++ b/tests/auto/blackbox/testdata/path-probe/single-file-selector.qbs @@ -2,4 +2,5 @@ BaseApp { inputSelectors: "tool" inputSearchPaths: "bin" outputFilePaths: ["bin/tool"] + outputCandidatePaths: [["bin/tool"]] } diff --git a/tests/auto/blackbox/testdata/path-probe/single-file-suffixes.qbs b/tests/auto/blackbox/testdata/path-probe/single-file-suffixes.qbs index 4442e719a..3436a49c3 100644 --- a/tests/auto/blackbox/testdata/path-probe/single-file-suffixes.qbs +++ b/tests/auto/blackbox/testdata/path-probe/single-file-suffixes.qbs @@ -1,6 +1,7 @@ BaseApp { inputNames: "tool" inputSearchPaths: "bin" - inputNameSuffixes: [".1", ".2"] + inputNameSuffixes: [".0", ".1", ".2"] outputFilePaths: ["bin/tool.1"] + outputCandidatePaths: [["bin/tool.0", "bin/tool.1"]] } diff --git a/tests/auto/blackbox/testdata/path-probe/single-file.qbs b/tests/auto/blackbox/testdata/path-probe/single-file.qbs index 3590e7664..e22d7ba0d 100644 --- a/tests/auto/blackbox/testdata/path-probe/single-file.qbs +++ b/tests/auto/blackbox/testdata/path-probe/single-file.qbs @@ -2,4 +2,5 @@ BaseApp { inputNames: "tool" inputSearchPaths: "bin" outputFilePaths: ["bin/tool"] + outputCandidatePaths: [["bin/tool"]] } diff --git a/tests/auto/blackbox/testdata/path-probe/usr/bin/tool b/tests/auto/blackbox/testdata/path-probe/usr/bin/tool new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/auto/blackbox/testdata/path-probe/usr/bin/tool diff --git a/tests/auto/blackbox/testdata/plugin-dependency/helper1.cpp b/tests/auto/blackbox/testdata/plugin-dependency/helper1.cpp index 72331da80..15a3e0d86 100644 --- a/tests/auto/blackbox/testdata/plugin-dependency/helper1.cpp +++ b/tests/auto/blackbox/testdata/plugin-dependency/helper1.cpp @@ -1,4 +1,4 @@ -#include <stdio.h> +#include <cstdio> #if defined(_WIN32) || defined(WIN32) # define EXPORT __declspec(dllexport) @@ -12,5 +12,5 @@ EXPORT void helper1_hello() { - puts("helper1 says hello!"); + std::puts("helper1 says hello!"); } diff --git a/tests/auto/blackbox/testdata/plugin-dependency/helper2.cpp b/tests/auto/blackbox/testdata/plugin-dependency/helper2.cpp index cdcdfc942..dccd72a04 100644 --- a/tests/auto/blackbox/testdata/plugin-dependency/helper2.cpp +++ b/tests/auto/blackbox/testdata/plugin-dependency/helper2.cpp @@ -1,7 +1,7 @@ #include "../dllexport.h" -#include <stdio.h> +#include <cstdio> DLL_EXPORT void helper2_hello() { - puts("Hello from helper2!"); + std::puts("Hello from helper2!"); } diff --git a/tests/auto/blackbox/testdata/plugin-dependency/plugin-dependency.qbs b/tests/auto/blackbox/testdata/plugin-dependency/plugin-dependency.qbs index c619b33ef..752673b78 100644 --- a/tests/auto/blackbox/testdata/plugin-dependency/plugin-dependency.qbs +++ b/tests/auto/blackbox/testdata/plugin-dependency/plugin-dependency.qbs @@ -1,16 +1,18 @@ +import qbs.Host + Project { CppApplication { name: "myapp" files: ["main.cpp"] Depends { name: "plugin1" // not to be linked - cpp.link: qbs.hostOS === undefined + cpp.link: Host.os() === undefined } Depends { name: "plugin2" } // not to be linked Depends { name: "plugin3" // supposed to be linked - //property bool theCondition: true - cpp.link: /*theCondition && */product.name === "myapp" // TODO: Make this work + property bool theCondition: true + cpp.link: theCondition && product.name === "myapp" } Depends { name: "plugin4" } // supposed to be linked Depends { name: "helper1" } // supposed to be linked diff --git a/tests/auto/blackbox/testdata/plugin-dependency/plugin1.cpp b/tests/auto/blackbox/testdata/plugin-dependency/plugin1.cpp index 2535bd85e..8cf7e3851 100644 --- a/tests/auto/blackbox/testdata/plugin-dependency/plugin1.cpp +++ b/tests/auto/blackbox/testdata/plugin-dependency/plugin1.cpp @@ -1,7 +1,7 @@ #include "../dllexport.h" -#include <stdio.h> +#include <cstdio> DLL_EXPORT void plugin1_hello() { - puts("plugin1 says hello!"); + std::puts("plugin1 says hello!"); } diff --git a/tests/auto/blackbox/testdata/plugin-dependency/plugin2.cpp b/tests/auto/blackbox/testdata/plugin-dependency/plugin2.cpp index fb2030d60..9efc83e2b 100644 --- a/tests/auto/blackbox/testdata/plugin-dependency/plugin2.cpp +++ b/tests/auto/blackbox/testdata/plugin-dependency/plugin2.cpp @@ -1,7 +1,7 @@ #include "../dllexport.h" -#include <stdio.h> +#include <cstdio> DLL_EXPORT void plugin2_hello() { - puts("plugin2 says hello!"); + std::puts("plugin2 says hello!"); } diff --git a/tests/auto/blackbox/testdata/plugin-dependency/plugin3.cpp b/tests/auto/blackbox/testdata/plugin-dependency/plugin3.cpp index 8a9f5ee76..0e08ac85a 100644 --- a/tests/auto/blackbox/testdata/plugin-dependency/plugin3.cpp +++ b/tests/auto/blackbox/testdata/plugin-dependency/plugin3.cpp @@ -1,7 +1,7 @@ #include "../dllexport.h" -#include <stdio.h> +#include <cstdio> DLL_EXPORT void plugin3_hello() { - puts("plugin3 says hello!"); + std::puts("plugin3 says hello!"); } diff --git a/tests/auto/blackbox/testdata/plugin-dependency/plugin4.cpp b/tests/auto/blackbox/testdata/plugin-dependency/plugin4.cpp index 4663247fa..cee2362ec 100644 --- a/tests/auto/blackbox/testdata/plugin-dependency/plugin4.cpp +++ b/tests/auto/blackbox/testdata/plugin-dependency/plugin4.cpp @@ -1,7 +1,7 @@ #include "../dllexport.h" -#include <stdio.h> +#include <cstdio> DLL_EXPORT void plugin4_hello() { - puts("plugin4 says hello!"); + std::puts("plugin4 says hello!"); } diff --git a/tests/auto/blackbox/testdata/precompiled-headers-and-redefine/precompiled-headers-and-redefine.qbs b/tests/auto/blackbox/testdata/precompiled-headers-and-redefine/precompiled-headers-and-redefine.qbs index 55b53a7af..3974b514e 100644 --- a/tests/auto/blackbox/testdata/precompiled-headers-and-redefine/precompiled-headers-and-redefine.qbs +++ b/tests/auto/blackbox/testdata/precompiled-headers-and-redefine/precompiled-headers-and-redefine.qbs @@ -8,7 +8,7 @@ CppApplication { Group { files: ["file.cpp"] cpp.defines: ["MYDEF=1"] - cpp.cxxFlags: base.concat(qbs.toolchain.contains("clang-cl") ? ["-Wno-clang-cl-pch"] : []) + cpp.cxxFlags: base.concat(qbs.toolchain.includes("clang-cl") ? ["-Wno-clang-cl-pch"] : []) } cpp.treatWarningsAsErrors: true 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 index 41c6cfe50..45b8e157f 100644 --- 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 @@ -7,7 +7,7 @@ Module { outputFileTags: "dep-out" prepare: { var cmd = new JavaScriptCommand(); - cmd.description = "Creating dep-out artifact"; + cmd.description = "creating dep-out artifact"; cmd.sourceCode = function() { console.info("prop: " + product.depmodule.prop); console.info("listProp: " + product.depmodule.listProp); 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 index 89d544f7e..31275aa40 100644 --- 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 @@ -13,7 +13,7 @@ Module { outputFileTags: "out" prepare: { var cmd = new JavaScriptCommand(); - cmd.description = "Creating out artifact"; + cmd.description = "creating out artifact"; cmd.sourceCode = function() { console.info("found: " + product.mymodule.found); }; diff --git a/tests/auto/blackbox/testdata/probeProperties/probeProperties.qbs b/tests/auto/blackbox/testdata/probeProperties/probeProperties.qbs index 9846eacef..ce89d11f4 100644 --- a/tests/auto/blackbox/testdata/probeProperties/probeProperties.qbs +++ b/tests/auto/blackbox/testdata/probeProperties/probeProperties.qbs @@ -1,29 +1,40 @@ import qbs.Probes -CppApplication { - Probes.PathProbe { - id: probe1 - names: ["bin/tool"] - platformSearchPaths: [product.sourceDirectory] - } +Project { - Probes.PathProbe { - id: probe2 - names: ["tool"] - platformSearchPaths: [product.sourceDirectory + "/bin"] - } + CppApplication { + Probes.PathProbe { + id: probe1 + names: ["bin/tool"] + platformSearchPaths: [product.sourceDirectory] + } - targetName: { - console.info("probe1.fileName=" + probe1.fileName); - console.info("probe1.path=" + probe1.path); - console.info("probe1.filePath=" + probe1.filePath); + Probes.PathProbe { + id: probe2 + names: ["tool"] + platformSearchPaths: [product.sourceDirectory + "/bin"] + } - console.info("probe2.fileName=" + probe2.fileName); - console.info("probe2.path=" + probe2.path); - console.info("probe2.filePath=" + probe2.filePath); + targetName: { + console.info("probe1.fileName=" + probe1.fileName); + console.info("probe1.path=" + probe1.path); + console.info("probe1.filePath=" + probe1.filePath); - return name; + console.info("probe2.fileName=" + probe2.fileName); + console.info("probe2.path=" + probe2.path); + console.info("probe2.filePath=" + probe2.filePath); + + console.info("probe3.fileName=" + probe3.fileName); + console.info("probe3.path=" + probe3.path); + console.info("probe3.filePath=" + probe3.filePath); + return name; + } + } + + Probes.PathProbe { + id: probe3 + names: ["tool"] + platformSearchPaths: [project.sourceDirectory + "/bin"] } - files: ["main.c"] } diff --git a/tests/auto/blackbox/testdata/probes-and-array-properties/modules/mymodule/mymodule.qbs b/tests/auto/blackbox/testdata/probes-and-array-properties/modules/mymodule/mymodule.qbs index e5c368a88..92ece5be7 100644 --- a/tests/auto/blackbox/testdata/probes-and-array-properties/modules/mymodule/mymodule.qbs +++ b/tests/auto/blackbox/testdata/probes-and-array-properties/modules/mymodule/mymodule.qbs @@ -3,8 +3,7 @@ Module { id: propProbe property stringList prop: [] configure: { - prop = []; - prop.push("probe"); + prop = ["probe"]; found = true; } } diff --git a/tests/auto/blackbox/testdata/product-dependencies-by-type/product-dependencies-by-type.qbs b/tests/auto/blackbox/testdata/product-dependencies-by-type/product-dependencies-by-type.qbs index 8fa761a2d..8e1f291f3 100644 --- a/tests/auto/blackbox/testdata/product-dependencies-by-type/product-dependencies-by-type.qbs +++ b/tests/auto/blackbox/testdata/product-dependencies-by-type/product-dependencies-by-type.qbs @@ -91,7 +91,7 @@ Project { name: "lib-product" files: "main.cpp" Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } @@ -116,7 +116,7 @@ Project { } prepare: { var cmd = new JavaScriptCommand(); - cmd.description = "Collecting apps"; + cmd.description = "collecting apps"; cmd.sourceCode = function() { var file = new TextFile(output.filePath, TextFile.WriteOnly); for (var i = 0; i < inputs["application"].length; ++i) diff --git a/tests/auto/blackbox/testdata/product-in-exported-module/modules/m/m.qbs b/tests/auto/blackbox/testdata/product-in-exported-module/modules/m/m.qbs new file mode 100644 index 000000000..0e79d0abe --- /dev/null +++ b/tests/auto/blackbox/testdata/product-in-exported-module/modules/m/m.qbs @@ -0,0 +1,3 @@ +Module { + Depends { name: "dummy"; condition: { console.info("product: " + product.name); return false; } } +} diff --git a/tests/auto/blackbox/testdata/product-in-exported-module/product-in-exported-module.qbs b/tests/auto/blackbox/testdata/product-in-exported-module/product-in-exported-module.qbs new file mode 100644 index 000000000..3ead0ca6c --- /dev/null +++ b/tests/auto/blackbox/testdata/product-in-exported-module/product-in-exported-module.qbs @@ -0,0 +1,10 @@ +Project { + Product { + name: "importing" + Depends { name: "dep" } + } + Product { + name: "dep" + Export { Depends { name: "m" } } + } +} diff --git a/tests/auto/blackbox/testdata/productproperties/header.qbs b/tests/auto/blackbox/testdata/productproperties/header.qbs index 42f9c88d9..13a62035f 100644 --- a/tests/auto/blackbox/testdata/productproperties/header.qbs +++ b/tests/auto/blackbox/testdata/productproperties/header.qbs @@ -29,6 +29,6 @@ Product { Export { Depends { name: "cpp" } - cpp.includePaths: product.buildDirectory + cpp.includePaths: exportingProduct.buildDirectory } } diff --git a/tests/auto/blackbox/testdata/proper quoting/main.cpp b/tests/auto/blackbox/testdata/proper quoting/main.cpp index 22cafeaa9..6e9be6df1 100644 --- a/tests/auto/blackbox/testdata/proper quoting/main.cpp +++ b/tests/auto/blackbox/testdata/proper quoting/main.cpp @@ -26,16 +26,16 @@ ** ****************************************************************************/ -#include <stdio.h> +#include <cstdio> int bla(); int main() { - printf(DEFINE"\n"); - printf(DEFINEWITHSPACE"\n"); - printf(DEFINEWITHTAB"\n"); - printf(DEFINEWITHBACKSLASH"\n"); + std::printf(DEFINE"\n"); + std::printf(DEFINEWITHSPACE"\n"); + std::printf(DEFINEWITHTAB"\n"); + std::printf(DEFINEWITHBACKSLASH"\n"); return bla(); } diff --git a/tests/auto/blackbox/testdata/proper quoting/my static lib.cpp b/tests/auto/blackbox/testdata/proper quoting/my static lib.cpp index e7490e807..7c07fd4c9 100644 --- a/tests/auto/blackbox/testdata/proper quoting/my static lib.cpp +++ b/tests/auto/blackbox/testdata/proper quoting/my static lib.cpp @@ -26,12 +26,13 @@ ** ****************************************************************************/ -#include <stdio.h> #include <some helper.h> +#include <cstdio> + int bla() { int n = getSomeNumber(); - printf("Hello World! The magic number is %d.", n); + std::printf("Hello World! The magic number is %d.", n); return n; } diff --git a/tests/auto/blackbox/testdata/proper quoting/proper quoting.qbs b/tests/auto/blackbox/testdata/proper quoting/proper quoting.qbs index 184ee13e3..1587940a2 100644 --- a/tests/auto/blackbox/testdata/proper quoting/proper quoting.qbs +++ b/tests/auto/blackbox/testdata/proper quoting/proper quoting.qbs @@ -1,7 +1,13 @@ -import qbs 1.0 +import qbs.Host Project { Product { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } type: "application" consoleApplication: true name: "Hello World" @@ -34,7 +40,7 @@ Project { Depends { name: "cpp" } Export { Depends { name: "cpp" } - cpp.includePaths: [product.sourceDirectory + '/some helper'] + cpp.includePaths: [exportingProduct.sourceDirectory + '/some helper'] } } } diff --git a/tests/auto/blackbox/testdata/property-assignment-on-non-present-module/property-assignment-on-non-present-module.qbs b/tests/auto/blackbox/testdata/property-assignment-on-non-present-module/property-assignment-on-non-present-module.qbs deleted file mode 100644 index a01d6c561..000000000 --- a/tests/auto/blackbox/testdata/property-assignment-on-non-present-module/property-assignment-on-non-present-module.qbs +++ /dev/null @@ -1,4 +0,0 @@ -Product { - Depends { name: "nein"; required: false } - nein.doch: "ohhh!" -} diff --git a/tests/auto/blackbox/testdata/property-evaluation-context/modules/base/base.qbs b/tests/auto/blackbox/testdata/property-evaluation-context/modules/base/base.qbs new file mode 100644 index 000000000..a97538751 --- /dev/null +++ b/tests/auto/blackbox/testdata/property-evaluation-context/modules/base/base.qbs @@ -0,0 +1,4 @@ +Module { + property string productInBase: product.name + property string productInTop: "" +} diff --git a/tests/auto/blackbox/testdata/property-evaluation-context/modules/top/top.qbs b/tests/auto/blackbox/testdata/property-evaluation-context/modules/top/top.qbs new file mode 100644 index 000000000..fa073ff78 --- /dev/null +++ b/tests/auto/blackbox/testdata/property-evaluation-context/modules/top/top.qbs @@ -0,0 +1,6 @@ +Module { + Depends { name: "base" } + base.productInTop: product.name + property string productInTop: product.name + property string productInExport: "" +} diff --git a/tests/auto/blackbox/testdata/property-evaluation-context/property-evaluation-context.qbs b/tests/auto/blackbox/testdata/property-evaluation-context/property-evaluation-context.qbs new file mode 100644 index 000000000..ede32cf74 --- /dev/null +++ b/tests/auto/blackbox/testdata/property-evaluation-context/property-evaluation-context.qbs @@ -0,0 +1,34 @@ +Project { + qbsSearchPaths: [ path ] + Product { + name: "mylib" + Export { + Depends { name: "top" } + top.productInExport: exportingProduct.name + } + } + + Product { + type: "rule-output" + name: "myapp" + Depends { name: "mylib" } + + Rule { + alwaysRun: true + multiplex: true + requiresInputs: false + outputFileTags: "rule-output" + prepare: { + var cmd = new JavaScriptCommand(); + cmd.silent = true; + cmd.sourceCode = function() { + console.info("base.productInBase evaluated in: " + product.base.productInBase); + console.info("base.productInTop evaluated in: " + product.base.productInTop); + console.info("top.productInExport evaluated in: " + product.top.productInExport); + console.info("top.productInTop evaluated in: " + product.top.productInTop); + } + return [cmd]; + } + } + } +} diff --git a/tests/auto/blackbox/testdata/propertyChanges/modules/TestModule/module.qbs b/tests/auto/blackbox/testdata/propertyChanges/modules/TestModule/module.qbs index b1e4a1fdc..590736f6a 100644 --- a/tests/auto/blackbox/testdata/propertyChanges/modules/TestModule/module.qbs +++ b/tests/auto/blackbox/testdata/propertyChanges/modules/TestModule/module.qbs @@ -18,7 +18,7 @@ Module { prepare: { var cmd = new JavaScriptCommand(); cmd.highlight = "codegen"; - cmd.description = "Making output from input"; + cmd.description = "making output from input"; cmd.sourceCode = function() { // console.info('Change in source code'); console.info(input.TestModule.testProperty); diff --git a/tests/auto/blackbox/testdata/propertyChanges/propertyChanges.qbs b/tests/auto/blackbox/testdata/propertyChanges/propertyChanges.qbs index f13b1986e..29365a887 100644 --- a/tests/auto/blackbox/testdata/propertyChanges/propertyChanges.qbs +++ b/tests/auto/blackbox/testdata/propertyChanges/propertyChanges.qbs @@ -27,7 +27,7 @@ Project { name: "library" files: "lib.cpp" Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } @@ -80,7 +80,7 @@ Project { prepare: { var cmd = new JavaScriptCommand(); cmd.highlight = "codegen"; - cmd.description = "Making output from other output"; + cmd.description = "making output from other output"; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } return cmd; } diff --git a/tests/auto/blackbox/testdata/protobuf-library-install/hello.proto b/tests/auto/blackbox/testdata/protobuf-library-install/hello.proto new file mode 100644 index 000000000..946108ddc --- /dev/null +++ b/tests/auto/blackbox/testdata/protobuf-library-install/hello.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; +package protobuf.library; + +import "hello/world.proto"; + +message Hello { + hello.World world = 1; +}; diff --git a/tests/auto/blackbox/testdata/protobuf-library-install/hello/world.proto b/tests/auto/blackbox/testdata/protobuf-library-install/hello/world.proto new file mode 100644 index 000000000..f718621b6 --- /dev/null +++ b/tests/auto/blackbox/testdata/protobuf-library-install/hello/world.proto @@ -0,0 +1,6 @@ +syntax = "proto3"; +package protobuf.library.hello; + +message World { + int32 value = 1; +}; diff --git a/tests/auto/blackbox/testdata/protobuf-library-install/protobuf-library.qbs b/tests/auto/blackbox/testdata/protobuf-library-install/protobuf-library.qbs new file mode 100644 index 000000000..501675c15 --- /dev/null +++ b/tests/auto/blackbox/testdata/protobuf-library-install/protobuf-library.qbs @@ -0,0 +1,34 @@ +import qbs.Host + +StaticLibrary { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result && hasProtobuf; + } + + Depends { name: "cpp" } + cpp.cxxLanguageVersion: "c++11" + cpp.minimumMacosVersion: "10.8" + + protobuf.cpp.importPaths: product.sourceDirectory + + Depends { name: "protobuf.cpp"; required: false } + property bool hasProtobuf: { + console.info("has protobuf: " + protobuf.cpp.present); + return protobuf.cpp.present; + } + + Group { + fileTagsFilter: "protobuf.hpp" + qbs.installDir: "include" + qbs.installSourceBase: protobuf.cpp.outputDir + qbs.install: true + } + + files: [ + "hello.proto", + "hello/world.proto", + ] +} diff --git a/tests/auto/blackbox/testdata/protobuf/addressbook_cpp.qbs b/tests/auto/blackbox/testdata/protobuf/addressbook_cpp.qbs index a5a4caf75..959552ea5 100644 --- a/tests/auto/blackbox/testdata/protobuf/addressbook_cpp.qbs +++ b/tests/auto/blackbox/testdata/protobuf/addressbook_cpp.qbs @@ -1,16 +1,22 @@ -import qbs +import qbs.Host CppApplication { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result && hasProtobuf; + } name: "addressbook_cpp" consoleApplication: true - condition: hasProtobuf Depends { name: "cpp" } - cpp.cxxLanguageVersion: "c++11" + cpp.minimumMacosVersion: "10.15" Depends { name: "protobuf.cpp"; required: false } property bool hasProtobuf: { console.info("has protobuf: " + protobuf.cpp.present); + console.info("has modules: " + protobuflib.present); return protobuf.cpp.present; } diff --git a/tests/auto/blackbox/testdata/protobuf/addressbook_nanopb.options b/tests/auto/blackbox/testdata/protobuf/addressbook_nanopb.options new file mode 100644 index 000000000..60726de93 --- /dev/null +++ b/tests/auto/blackbox/testdata/protobuf/addressbook_nanopb.options @@ -0,0 +1,3 @@ +tutorial.Person.name max_size:128 +tutorial.Person.email max_size:256 +tutorial.Person.phones max_count:16 diff --git a/tests/auto/blackbox/testdata/protobuf/addressbook_nanopb.proto b/tests/auto/blackbox/testdata/protobuf/addressbook_nanopb.proto new file mode 100644 index 000000000..5db0bedbf --- /dev/null +++ b/tests/auto/blackbox/testdata/protobuf/addressbook_nanopb.proto @@ -0,0 +1,38 @@ +// See README.txt for information and build instructions. +// +// Note: START and END tags are used in comments to define sections used in +// tutorials. They are not part of the syntax for Protocol Buffers. +// +// To get an in-depth walkthrough of this file and the related examples, see: +// https://developers.google.com/protocol-buffers/docs/tutorials + +// [START declaration] +syntax = "proto3"; +package tutorial; +// [END declaration] + +// [START messages] +message Person { + string name = 1; + int32 id = 2; // Unique ID number for this person. + string email = 3; + + enum PhoneType { + MOBILE = 0; + HOME = 1; + WORK = 2; + } + + message PhoneNumber { + string number = 1; + PhoneType type = 2; + } + + repeated PhoneNumber phones = 4; +} + +// Our address book file is just one of these. +message AddressBook { + repeated Person people = 1; +} +// [END messages] diff --git a/tests/auto/blackbox/testdata/protobuf/addressbook_nanopb.qbs b/tests/auto/blackbox/testdata/protobuf/addressbook_nanopb.qbs new file mode 100644 index 000000000..3dfc911e1 --- /dev/null +++ b/tests/auto/blackbox/testdata/protobuf/addressbook_nanopb.qbs @@ -0,0 +1,29 @@ +import qbs.Host + +CppApplication { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result && hasProtobuf; + } + name: "addressbook_nanopb" + consoleApplication: true + + Depends { name: "cpp" } + cpp.minimumMacosVersion: "10.8" + + Depends { name: "protobuf.nanopb"; required: false } + property bool hasProtobuf: { + console.info("has protobuf: " + protobuf.nanopb.present); + console.info("has modules: false"); + return protobuf.nanopb.present; + } + protobuf.nanopb.importPaths: product.sourceDirectory + + files: [ + "addressbook_nanopb.proto", + "addressbook_nanopb.options", + "main_nanopb.cpp", + ] +} diff --git a/tests/auto/blackbox/testdata/protobuf/addressbook_objc.qbs b/tests/auto/blackbox/testdata/protobuf/addressbook_objc.qbs index be68abfee..7f0b999aa 100644 --- a/tests/auto/blackbox/testdata/protobuf/addressbook_objc.qbs +++ b/tests/auto/blackbox/testdata/protobuf/addressbook_objc.qbs @@ -1,14 +1,20 @@ -import qbs +import qbs.Host CppApplication { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result && hasProtobuf; + } name: "addressbook_objc" consoleApplication: true - condition: hasProtobuf Depends { name: "cpp" } Depends { name: "protobuf.objc"; required: false } property bool hasProtobuf: { console.info("has protobuf: " + protobuf.objc.present); + console.info("has modules: false"); return protobuf.objc.present; } diff --git a/tests/auto/blackbox/testdata/protobuf/conanfile.txt b/tests/auto/blackbox/testdata/protobuf/conanfile.txt new file mode 100644 index 000000000..e7d849b1a --- /dev/null +++ b/tests/auto/blackbox/testdata/protobuf/conanfile.txt @@ -0,0 +1,6 @@ +[requires] +protobuf/3.21.12 +[tool_requires] +protobuf/3.21.12 +[generators] +QbsDeps diff --git a/tests/auto/blackbox/testdata/protobuf/create-proto-library.qbs b/tests/auto/blackbox/testdata/protobuf/create-proto-library.qbs new file mode 100644 index 000000000..005752fd8 --- /dev/null +++ b/tests/auto/blackbox/testdata/protobuf/create-proto-library.qbs @@ -0,0 +1,53 @@ +import qbs.Host + +Project { + StaticLibrary { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result && hasProtobuf; + } + name: "proto_lib" + + Depends { name: "cpp" } + cpp.minimumMacosVersion: "10.8" + + protobuf.cpp.importPaths: product.sourceDirectory + + Depends { name: "protobuf.cpp"; required: false } + property bool hasProtobuf: { + console.info("has protobuf: " + protobuf.cpp.present); + console.info("has modules: " + protobuflib.present); + return protobuf.cpp.present; + } + + files: [ + "import.proto", + "subdir/myenum.proto", + ] + + Export { + Depends { name: "cpp" } + Depends { name: "protobuf.cpp"; required: false } + cpp.cxxLanguageVersion: "c++11" + cpp.minimumMacosVersion: "10.8" + cpp.includePaths: exportingProduct.protobuf.cpp.outputDir + } + } + + CppApplication { + condition: proto_lib.present + name: "consumes_proto_lib" + consoleApplication: true + + files: [ + "import-main.cpp", + ] + + Depends { + name: "proto_lib" + required: false + } + } +} diff --git a/tests/auto/blackbox/testdata/protobuf/import-main.cpp b/tests/auto/blackbox/testdata/protobuf/import-main.cpp index 6d90cdf16..65048dd83 100644 --- a/tests/auto/blackbox/testdata/protobuf/import-main.cpp +++ b/tests/auto/blackbox/testdata/protobuf/import-main.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2018 Ivan Komissarov -** Contact: abbapoh@gmail.com +** Copyright (C) 2018 Ivan Komissarov (abbapoh@gmail.com) +** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** diff --git a/tests/auto/blackbox/testdata/protobuf/import.qbs b/tests/auto/blackbox/testdata/protobuf/import.qbs index 4c4de063f..56d489de8 100644 --- a/tests/auto/blackbox/testdata/protobuf/import.qbs +++ b/tests/auto/blackbox/testdata/protobuf/import.qbs @@ -1,17 +1,23 @@ -import qbs +import qbs.Host CppApplication { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result && hasProtobuf; + } name: "app" consoleApplication: true - condition: hasProtobuf protobuf.cpp.importPaths: [sourceDirectory] - cpp.cxxLanguageVersion: "c++11" + cpp.minimumMacosVersion: "10.8" Depends { name: "protobuf.cpp"; required: false } property bool hasProtobuf: { console.info("has protobuf: " + protobuf.cpp.present); + console.info("has modules: " + protobuflib.present); return protobuf.cpp.present; } diff --git a/tests/auto/blackbox/testdata/protobuf/main.cpp b/tests/auto/blackbox/testdata/protobuf/main.cpp index c93c46717..d4b1c431b 100644 --- a/tests/auto/blackbox/testdata/protobuf/main.cpp +++ b/tests/auto/blackbox/testdata/protobuf/main.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2018 Ivan Komissarov -** Contact: abbapoh@gmail.com +** Copyright (C) 2018 Ivan Komissarov (abbapoh@gmail.com) +** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** diff --git a/tests/auto/blackbox/testdata/protobuf/main.m b/tests/auto/blackbox/testdata/protobuf/main.m index e9d7ce66a..414d1aa2f 100644 --- a/tests/auto/blackbox/testdata/protobuf/main.m +++ b/tests/auto/blackbox/testdata/protobuf/main.m @@ -1,7 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2018 Ivan Komissarov -** Contact: abbapoh@gmail.com +** Copyright (C) 2018 Ivan Komissarov (abbapoh@gmail.com) +** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** diff --git a/tests/auto/blackbox/testdata/protobuf/main_nanopb.cpp b/tests/auto/blackbox/testdata/protobuf/main_nanopb.cpp new file mode 100644 index 000000000..76fa03fca --- /dev/null +++ b/tests/auto/blackbox/testdata/protobuf/main_nanopb.cpp @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2020 Kai Dohmen (psykai1993@gmail.com) +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include <array> +#include <cassert> +#include <pb_encode.h> + +#include "addressbook_nanopb.pb.h" + +static_assert(std::is_array<decltype(std::declval<tutorial_Person>().name)>::value, ""); +static_assert(std::is_array<decltype(std::declval<tutorial_Person>().email)>::value, ""); +static_assert(std::is_array<decltype(std::declval<tutorial_Person>().phones)>::value, ""); + +bool writeString(pb_ostream_t *stream, const pb_field_t *field, void *const *) +{ + constexpr auto str = "0123456789"; + if (!pb_encode_tag_for_field(stream, field)) + return false; + return pb_encode_string(stream, reinterpret_cast<const uint8_t*>(str), strlen(str)); +} + +int main() +{ + std::array<uint8_t, 32> buffer = {}; + + tutorial_Person_PhoneNumber phoneNumber; + phoneNumber.number.funcs.encode = writeString; + phoneNumber.type = tutorial_Person_PhoneType_WORK; + + auto ostream = pb_ostream_from_buffer(buffer.data(), buffer.size()); + assert(pb_encode(&ostream, tutorial_Person_PhoneNumber_fields, &phoneNumber)); + + return 0; +} diff --git a/tests/auto/blackbox/testdata/protobuf/needs-import-dir-main.cpp b/tests/auto/blackbox/testdata/protobuf/needs-import-dir-main.cpp index d6faf9e84..5d62a0d06 100644 --- a/tests/auto/blackbox/testdata/protobuf/needs-import-dir-main.cpp +++ b/tests/auto/blackbox/testdata/protobuf/needs-import-dir-main.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2018 Ivan Komissarov -** Contact: abbapoh@gmail.com +** Copyright (C) 2018 Ivan Komissarov (abbapoh@gmail.com) +** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** diff --git a/tests/auto/blackbox/testdata/protobuf/needs-import-dir.qbs b/tests/auto/blackbox/testdata/protobuf/needs-import-dir.qbs index 788bbc93c..07be566cb 100644 --- a/tests/auto/blackbox/testdata/protobuf/needs-import-dir.qbs +++ b/tests/auto/blackbox/testdata/protobuf/needs-import-dir.qbs @@ -1,18 +1,24 @@ -import qbs +import qbs.Host CppApplication { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result && hasProtobuf; + } name: "app" consoleApplication: true - condition: hasProtobuf property path theImportDir protobuf.cpp.importPaths: (theImportDir ? [theImportDir] : []).concat([sourceDirectory]) - cpp.cxxLanguageVersion: "c++11" + cpp.minimumMacosVersion: "10.8" Depends { name: "protobuf.cpp"; required: false } property bool hasProtobuf: { console.info("has protobuf: " + protobuf.cpp.present); + console.info("has modules: " + protobuflib.present); return protobuf.cpp.present; } diff --git a/tests/auto/blackbox/testdata/qbs-config-import-export/config.json b/tests/auto/blackbox/testdata/qbs-config-import-export/config.json new file mode 100644 index 000000000..edcaf238a --- /dev/null +++ b/tests/auto/blackbox/testdata/qbs-config-import-export/config.json @@ -0,0 +1,11 @@ +{ + "group": { + "key1": "value1", + "key2": "value2" + }, + "key": "value", + "listKey": [ + "valueOne", + "valueTwo" + ] +} diff --git a/tests/auto/blackbox/testdata/qbs-config-import-export/config.txt b/tests/auto/blackbox/testdata/qbs-config-import-export/config.txt new file mode 100644 index 000000000..2bd19c422 --- /dev/null +++ b/tests/auto/blackbox/testdata/qbs-config-import-export/config.txt @@ -0,0 +1,4 @@ +group.key1: "value1" +group.key2: "value2" +key: "value" +listKey: ["valueOne", "valueTwo"] diff --git a/tests/auto/blackbox/testdata/recursive_wildcards/recursive_wildcards.qbs b/tests/auto/blackbox/testdata/recursive_wildcards/recursive_wildcards.qbs index 4e9da01d3..4fc275877 100644 --- a/tests/auto/blackbox/testdata/recursive_wildcards/recursive_wildcards.qbs +++ b/tests/auto/blackbox/testdata/recursive_wildcards/recursive_wildcards.qbs @@ -23,7 +23,7 @@ Product { } prepare: { var cmd = new JavaScriptCommand(); - cmd.description = "Creating " + output.fileName; + cmd.description = "creating " + output.fileName; cmd.sourceCode = function() { var inputList = explicitlyDependsOn["txt.in"]; var fileNameList = []; diff --git a/tests/auto/blackbox/testdata/remove-duplicate-libs/remove-duplicate-libs.qbs b/tests/auto/blackbox/testdata/remove-duplicate-libs/remove-duplicate-libs.qbs index 4ffb8d0e2..d89e47414 100644 --- a/tests/auto/blackbox/testdata/remove-duplicate-libs/remove-duplicate-libs.qbs +++ b/tests/auto/blackbox/testdata/remove-duplicate-libs/remove-duplicate-libs.qbs @@ -1,11 +1,13 @@ import "MyStaticLib.qbs" as MyStaticLib +import qbs.Host Project { property bool removeDuplicates property string libDir: buildDirectory + "/lib" property bool dummy: { + // most BSD systems (including macOS) use LLVM linker now console.info("is bfd linker: " - + (qbs.toolchain.contains("gcc") && !qbs.hostOS.contains("macos"))) + + (qbs.toolchain.includes("gcc") && !Host.os().includes("bsd"))) } qbsSearchPaths: "." diff --git a/tests/auto/blackbox/testdata/reproducible-build/reproducible-build.qbs b/tests/auto/blackbox/testdata/reproducible-build/reproducible-build.qbs index f7ed8e61a..fabdf48db 100644 --- a/tests/auto/blackbox/testdata/reproducible-build/reproducible-build.qbs +++ b/tests/auto/blackbox/testdata/reproducible-build/reproducible-build.qbs @@ -2,4 +2,9 @@ CppApplication { name: "the product" files: ["file1.cpp", "file2.cpp", "main.cpp"] cpp.cxxFlags: ["-flto"] + Probe { + id: checker + property bool isGcc: qbs.toolchain.contains("gcc") && !qbs.toolchain.contains("clang") + configure: { console.info("is gcc: " + isGcc); } + } } diff --git a/tests/auto/blackbox/testdata/require-deprecated/blubb.js b/tests/auto/blackbox/testdata/require-deprecated/blubb.js deleted file mode 100644 index 9acc13968..000000000 --- a/tests/auto/blackbox/testdata/require-deprecated/blubb.js +++ /dev/null @@ -1,13 +0,0 @@ -var TextFile = loadExtension("qbs.TextFile") -var zort = loadFile("zort.js") - -function createCommands(filePaths) { - var cmd = new JavaScriptCommand(); - cmd.description = "Write an empty file"; - cmd.filePath = filePaths[0]; - cmd.sourceCode = function() { - var f = new TextFile(filePath, TextFile.WriteOnly); - f.close(); - } - return [cmd, zort.createCommand(filePaths)]; -} diff --git a/tests/auto/blackbox/testdata/require-deprecated/require.qbs b/tests/auto/blackbox/testdata/require-deprecated/require.qbs deleted file mode 100644 index 87d8b054b..000000000 --- a/tests/auto/blackbox/testdata/require-deprecated/require.qbs +++ /dev/null @@ -1,21 +0,0 @@ -import 'blubb.js' as blubb - -Product { - type: ["text"] - Rule { - multiplex: true - Artifact { - fileTags: ["text"] - filePath: "one.txt" - } - Artifact { - fileTags: ["text"] - filePath: "two.txt" - } - prepare: { - var filePaths = outputs.text.map(function (artifact) {return artifact.filePath; }); - return blubb.createCommands(filePaths); - } - } -} - diff --git a/tests/auto/blackbox/testdata/require-deprecated/zort.js b/tests/auto/blackbox/testdata/require-deprecated/zort.js deleted file mode 100644 index 0dcffb767..000000000 --- a/tests/auto/blackbox/testdata/require-deprecated/zort.js +++ /dev/null @@ -1,11 +0,0 @@ -var File = loadExtension("qbs.File") - -function createCommand(filePaths) { - var cmd = new JavaScriptCommand(); - cmd.description = "Create another empty file"; - cmd.filePaths = filePaths; - cmd.sourceCode = function() { - File.copy(filePaths[0], filePaths[1]); - }; - return cmd; -} diff --git a/tests/auto/blackbox/testdata/response-files/response-files.qbs b/tests/auto/blackbox/testdata/response-files/response-files.qbs index fbb6f0518..c18fcac43 100644 --- a/tests/auto/blackbox/testdata/response-files/response-files.qbs +++ b/tests/auto/blackbox/testdata/response-files/response-files.qbs @@ -1,4 +1,5 @@ import qbs.FileInfo +import qbs.Host import qbs.TextFile Project { @@ -8,6 +9,12 @@ Project { cpp.enableExceptions: true } Product { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } name: "response-file-text" type: ["text"] Depends { name: "cpp" } @@ -38,6 +45,9 @@ Project { Product { name: "lotsofobjects" type: ["dynamiclibrary"] + // clang-cl does not use response file internally, thus linker complains that command is + // too long. This can be worked around by calling the linker directly + cpp.linkerMode: qbs.toolchain.includes("clang-cl") ? "manual" : original Depends { name: "cpp" } Rule { multiplex: true diff --git a/tests/auto/blackbox/testdata/rpathlink-deduplication/rpathlink-deduplication-lib.cpp b/tests/auto/blackbox/testdata/rpathlink-deduplication/rpathlink-deduplication-lib.cpp new file mode 100644 index 000000000..6418df94d --- /dev/null +++ b/tests/auto/blackbox/testdata/rpathlink-deduplication/rpathlink-deduplication-lib.cpp @@ -0,0 +1,3 @@ +int dynamicFunc() { + return 1; +}
\ No newline at end of file diff --git a/tests/auto/blackbox/testdata/rpathlink-deduplication/rpathlink-deduplication-main.cpp b/tests/auto/blackbox/testdata/rpathlink-deduplication/rpathlink-deduplication-main.cpp new file mode 100644 index 000000000..60f8494f6 --- /dev/null +++ b/tests/auto/blackbox/testdata/rpathlink-deduplication/rpathlink-deduplication-main.cpp @@ -0,0 +1,5 @@ +extern int dynamicFunc(); + +int main() { + return dynamicFunc(); +}
\ No newline at end of file diff --git a/tests/auto/blackbox/testdata/rpathlink-deduplication/rpathlink-deduplication.qbs b/tests/auto/blackbox/testdata/rpathlink-deduplication/rpathlink-deduplication.qbs new file mode 100644 index 000000000..adb63872a --- /dev/null +++ b/tests/auto/blackbox/testdata/rpathlink-deduplication/rpathlink-deduplication.qbs @@ -0,0 +1,47 @@ +Project { + DynamicLibrary { + Depends { name: "bundle" } + Depends { name: "cpp" } + + bundle.isBundle: false + name: "DynamicLibraryA" + files: ["rpathlink-deduplication-lib.cpp"] + } + + DynamicLibrary { + Depends { name: "bundle" } + Depends { name: "cpp" } + Depends { name: "DynamicLibraryA" } + + bundle.isBundle: false + name: "DynamicLibraryB" + files: ["rpathlink-deduplication-lib.cpp"] + } + + DynamicLibrary { + Depends { name: "bundle" } + Depends { name: "cpp" } + Depends { name: "DynamicLibraryA" } + + bundle.isBundle: false + name: "DynamicLibraryC" + files: ["rpathlink-deduplication-lib.cpp"] + } + + CppApplication { + Depends { name: "bundle" } + Depends { name: "DynamicLibraryB" } + Depends { name: "DynamicLibraryC" } + consoleApplication: true + bundle.isBundle: false + cpp.removeDuplicateLibraries: false + files: "rpathlink-deduplication-main.cpp" + property bool test: { + if (cpp.useRPathLink) + console.info("useRPathLink: true"); + else + console.info("useRPathLink: false"); + console.info("===" + cpp.rpathLinkFlag + "==="); + } + } +}
\ No newline at end of file diff --git a/tests/auto/blackbox/testdata/rule-with-non-required-inputs/rule-with-non-required-inputs.qbs b/tests/auto/blackbox/testdata/rule-with-non-required-inputs/rule-with-non-required-inputs.qbs index 1bd9beebf..9d861b674 100644 --- a/tests/auto/blackbox/testdata/rule-with-non-required-inputs/rule-with-non-required-inputs.qbs +++ b/tests/auto/blackbox/testdata/rule-with-non-required-inputs/rule-with-non-required-inputs.qbs @@ -22,7 +22,7 @@ Product { } prepare: { var cmd = new JavaScriptCommand(); - cmd.description = "Generating " + output.fileName; + cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.write('('); diff --git a/tests/auto/blackbox/testdata/run-multiplexed/main.cpp b/tests/auto/blackbox/testdata/run-multiplexed/main.cpp new file mode 100644 index 000000000..237c8ce18 --- /dev/null +++ b/tests/auto/blackbox/testdata/run-multiplexed/main.cpp @@ -0,0 +1 @@ +int main() {} diff --git a/tests/auto/blackbox/testdata/run-multiplexed/run-multiplexed.qbs b/tests/auto/blackbox/testdata/run-multiplexed/run-multiplexed.qbs new file mode 100644 index 000000000..11577b54a --- /dev/null +++ b/tests/auto/blackbox/testdata/run-multiplexed/run-multiplexed.qbs @@ -0,0 +1,21 @@ +import qbs.Host + +CppApplication { + aggregate: false + consoleApplication: true + name: "app" + multiplexByQbsProperties: "buildVariants" + + qbs.buildVariants: ["debug", "release"] + + files: "main.cpp" + + Probe { + id: checker + property string targetPlatform: qbs.targetPlatform + configure: { + if (targetPlatform !== Host.platform()) + console.info("targetPlatform differs from hostPlatform"); + } + } +} diff --git a/tests/auto/blackbox/testdata/sanitizer/sanitizer.cpp b/tests/auto/blackbox/testdata/sanitizer/sanitizer.cpp new file mode 100644 index 000000000..4a7c3ee32 --- /dev/null +++ b/tests/auto/blackbox/testdata/sanitizer/sanitizer.cpp @@ -0,0 +1,4 @@ +int main(int argc, char *argv[]) +{ + return 0; +} diff --git a/tests/auto/blackbox/testdata/sanitizer/sanitizer.qbs b/tests/auto/blackbox/testdata/sanitizer/sanitizer.qbs new file mode 100644 index 000000000..438f3cc39 --- /dev/null +++ b/tests/auto/blackbox/testdata/sanitizer/sanitizer.qbs @@ -0,0 +1,44 @@ +CppApplication { + Depends { name: "Sanitizers.address" } + Sanitizers.address.enabled: sanitizer === "address" + property string sanitizer + + property bool supportsSanitizer: { + if (qbs.toolchain.includes("mingw")) + return false; + if (sanitizer === "address") + return Sanitizers.address._supported; + if (qbs.toolchain.includes("clang-cl")) { + if (cpp.toolchainInstallPath.includes("Microsoft Visual Studio") + && qbs.architecture === "x86_64") { + // 32 bit sanitizer shipped with VS misses the x86_64 libraries + return false; + } + // only these are supported + return sanitizer === "address" || sanitizer === "undefined"; + } + if (!qbs.toolchain.includes("gcc")) + return false; + if (qbs.targetOS.includes("ios")) { + // thread sanitizer is not supported + return sanitizer !== "thread"; + } + return true; + } + + condition: { + if (!sanitizer) + return true; + if (!supportsSanitizer) + console.info("Compiler does not support sanitizer"); + return supportsSanitizer; + } + qbs.buildVariant: "release" + cpp.cxxLanguageVersion: "c++11" + cpp.minimumMacosVersion: "10.8" + consoleApplication: true + cpp.runtimeLibrary: "static" + cpp.driverFlags: sanitizer && sanitizer !== "address" ? ["-fsanitize=" + sanitizer] : [] + cpp.debugInformation: true + files: "sanitizer.cpp" +} diff --git a/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/app.h b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/app.h new file mode 100644 index 000000000..a82b12fbd --- /dev/null +++ b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/app.h @@ -0,0 +1 @@ +#include "lib.h" diff --git a/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/app.qbs b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/app.qbs new file mode 100644 index 000000000..e931b853c --- /dev/null +++ b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/app.qbs @@ -0,0 +1,4 @@ +CppApplication { + cpp.includePaths: project.sourceDirectory + "/lib" + files: "main.cpp" +} diff --git a/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/main.cpp b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/main.cpp new file mode 100644 index 000000000..2e7bedac8 --- /dev/null +++ b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/main.cpp @@ -0,0 +1,3 @@ +#include "app.h" + +int main() { } diff --git a/tests/auto/blackbox/testdata/scan-result-in-non-dependency/lib/lib.h b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/lib/lib.h new file mode 100644 index 000000000..af6f627b7 --- /dev/null +++ b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/lib/lib.h @@ -0,0 +1,3 @@ +#pragma once + +void lib1_foo();
\ No newline at end of file diff --git a/tests/auto/blackbox/testdata/scan-result-in-non-dependency/other/other.qbs b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/other/other.qbs new file mode 100644 index 000000000..29682da1c --- /dev/null +++ b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/other/other.qbs @@ -0,0 +1,24 @@ +import qbs.TextFile + +Product { + type: "testproduct" + files: "../lib/lib.h" + + Rule { + multiplex: true + Artifact { + fileTags: ["testproduct"] + filePath: "fubar" + } + prepare: { + var cmd = new JavaScriptCommand(); + cmd.description = "generating text file"; + cmd.sourceCode = function() { + var tf = new TextFile(output.filePath, TextFile.WriteOnly); + tf.writeLine("blubb"); + tf.close(); + } + return cmd; + } + } +} diff --git a/tests/auto/blackbox/testdata/scan-result-in-non-dependency/p.qbs b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/p.qbs new file mode 100644 index 000000000..bcbd5ebce --- /dev/null +++ b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/p.qbs @@ -0,0 +1,6 @@ +Project { + references: [ + "app/app.qbs", + "other/other.qbs", + ] +} diff --git a/tests/auto/blackbox/testdata/scan-result-in-other-product/app/app.h b/tests/auto/blackbox/testdata/scan-result-in-other-product/app/app.h new file mode 100644 index 000000000..a82b12fbd --- /dev/null +++ b/tests/auto/blackbox/testdata/scan-result-in-other-product/app/app.h @@ -0,0 +1 @@ +#include "lib.h" diff --git a/tests/auto/blackbox/testdata/scan-result-in-other-product/app/app.qbs b/tests/auto/blackbox/testdata/scan-result-in-other-product/app/app.qbs new file mode 100644 index 000000000..984e9aca9 --- /dev/null +++ b/tests/auto/blackbox/testdata/scan-result-in-other-product/app/app.qbs @@ -0,0 +1,4 @@ +CppApplication { + Depends { name: "lib" } + files: "main.cpp" +} diff --git a/tests/auto/blackbox/testdata/scan-result-in-other-product/app/main.cpp b/tests/auto/blackbox/testdata/scan-result-in-other-product/app/main.cpp new file mode 100644 index 000000000..2e7bedac8 --- /dev/null +++ b/tests/auto/blackbox/testdata/scan-result-in-other-product/app/main.cpp @@ -0,0 +1,3 @@ +#include "app.h" + +int main() { } diff --git a/tests/auto/blackbox/testdata/scan-result-in-other-product/lib/lib.h b/tests/auto/blackbox/testdata/scan-result-in-other-product/lib/lib.h new file mode 100644 index 000000000..af6f627b7 --- /dev/null +++ b/tests/auto/blackbox/testdata/scan-result-in-other-product/lib/lib.h @@ -0,0 +1,3 @@ +#pragma once + +void lib1_foo();
\ No newline at end of file diff --git a/tests/auto/blackbox/testdata/scan-result-in-other-product/lib/lib.qbs b/tests/auto/blackbox/testdata/scan-result-in-other-product/lib/lib.qbs new file mode 100644 index 000000000..a6ed0c990 --- /dev/null +++ b/tests/auto/blackbox/testdata/scan-result-in-other-product/lib/lib.qbs @@ -0,0 +1,7 @@ +Product { + files: "lib.h" + Export { + Depends { name: "cpp" } + cpp.includePaths: exportingProduct.sourceDirectory + } +} diff --git a/tests/auto/blackbox/testdata/scan-result-in-other-product/other/other.qbs b/tests/auto/blackbox/testdata/scan-result-in-other-product/other/other.qbs new file mode 100644 index 000000000..29682da1c --- /dev/null +++ b/tests/auto/blackbox/testdata/scan-result-in-other-product/other/other.qbs @@ -0,0 +1,24 @@ +import qbs.TextFile + +Product { + type: "testproduct" + files: "../lib/lib.h" + + Rule { + multiplex: true + Artifact { + fileTags: ["testproduct"] + filePath: "fubar" + } + prepare: { + var cmd = new JavaScriptCommand(); + cmd.description = "generating text file"; + cmd.sourceCode = function() { + var tf = new TextFile(output.filePath, TextFile.WriteOnly); + tf.writeLine("blubb"); + tf.close(); + } + return cmd; + } + } +} diff --git a/tests/auto/blackbox/testdata/scan-result-in-other-product/p.qbs b/tests/auto/blackbox/testdata/scan-result-in-other-product/p.qbs new file mode 100644 index 000000000..fedf84989 --- /dev/null +++ b/tests/auto/blackbox/testdata/scan-result-in-other-product/p.qbs @@ -0,0 +1,7 @@ +Project { + references: [ + "app/app.qbs", + "lib/lib.qbs", + "other/other.qbs", + ] +} diff --git a/tests/auto/blackbox/testdata/separate-debug-info/separate-debug-info.qbs b/tests/auto/blackbox/testdata/separate-debug-info/separate-debug-info.qbs index 0b16d1984..4198b863f 100644 --- a/tests/auto/blackbox/testdata/separate-debug-info/separate-debug-info.qbs +++ b/tests/auto/blackbox/testdata/separate-debug-info/separate-debug-info.qbs @@ -8,9 +8,13 @@ Project { Probe { id: osProbe property stringList targetOS: qbs.targetOS + property stringList toolchain: qbs.toolchain configure: { - console.info("is windows: " + (targetOS.contains("windows") ? "yes" : "no")); - console.info("is darwin: " + (targetOS.contains("darwin") ? "yes" : "no")); + console.info("is windows: " + (targetOS.includes("windows") ? "yes" : "no")); + console.info("is macos: " + (targetOS.includes("macos") ? "yes" : "no")); + console.info("is darwin: " + (targetOS.includes("darwin") ? "yes" : "no")); + console.info("is gcc: " + (toolchain.includes("gcc") ? "yes" : "no")); + console.info("is msvc: " + (toolchain.includes("msvc") ? "yes" : "no")); } } } @@ -54,7 +58,7 @@ Project { files: ["main.cpp"] cpp.separateDebugInformation: true Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") cpp.dsymutilFlags: ["--flat"] } } @@ -65,7 +69,7 @@ Project { files: ["foo.cpp"] cpp.separateDebugInformation: true Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") cpp.dsymutilFlags: ["--flat"] } } @@ -75,7 +79,7 @@ Project { files: ["foo.cpp"] cpp.separateDebugInformation: true Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") cpp.dsymutilFlags: ["--flat"] } } @@ -93,7 +97,7 @@ Project { type: ["dynamiclibrary"] files: ["foo.cpp"] Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } cpp.separateDebugInformation: true @@ -103,7 +107,7 @@ Project { name: "bar4" files: ["foo.cpp"] Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } cpp.separateDebugInformation: true @@ -114,12 +118,12 @@ Project { type: ["application"] files: ["main.cpp"] Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } cpp.separateDebugInformation: true Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") cpp.dsymutilFlags: ["--flat"] } } @@ -129,12 +133,12 @@ Project { type: ["dynamiclibrary"] files: ["foo.cpp"] Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } cpp.separateDebugInformation: true Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") cpp.dsymutilFlags: ["--flat"] } } @@ -143,12 +147,12 @@ Project { name: "bar5" files: ["foo.cpp"] Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } cpp.separateDebugInformation: true Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") cpp.dsymutilFlags: ["--flat"] } } diff --git a/tests/auto/blackbox/testdata/setup-run-environment/setup-run-environment.qbs b/tests/auto/blackbox/testdata/setup-run-environment/setup-run-environment.qbs index d2d47b767..b1310c005 100644 --- a/tests/auto/blackbox/testdata/setup-run-environment/setup-run-environment.qbs +++ b/tests/auto/blackbox/testdata/setup-run-environment/setup-run-environment.qbs @@ -1,4 +1,5 @@ import qbs.FileInfo +import qbs.Host Project { DynamicLibrary { // Product dependency, installed @@ -7,13 +8,13 @@ Project { files: ["lib1.cpp"] - install: !qbs.targetOS.contains("darwin") + install: !qbs.targetOS.includes("darwin") installImportLib: true installDir: "lib1" importLibInstallDir: installDir Group { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") fileTagsFilter: ["bundle.content"] qbs.install: true qbs.installSourceBase: destinationDirectory @@ -26,7 +27,7 @@ Project { Depends { name: "lib5" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } @@ -40,7 +41,7 @@ Project { files: ["lib3.cpp"] Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } @@ -57,14 +58,14 @@ Project { files: ["lib4.cpp"] Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } // Testing shows that clang (8.0) does not find dynamic libraries via // the -L<dir> and -l<libname> mechanism unless the name is "lib<libname>.a". Properties { - condition: qbs.hostOS.contains("windows") && qbs.toolchain.contains("clang") + condition: Host.os().includes("windows") && qbs.toolchain.includes("clang") cpp.dynamicLibraryPrefix: "lib" cpp.dynamicLibraryImportSuffix: ".a" } @@ -82,7 +83,7 @@ Project { Depends { name: "cpp" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } @@ -90,6 +91,12 @@ Project { } CppApplication { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } name: "app" consoleApplication: true files: "main.cpp" @@ -101,7 +108,7 @@ Project { property string fullInstallPrefix: FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix) property string lib3FilePath: FileInfo.joinPaths(fullInstallPrefix, "lib3", - cpp.dynamicLibraryPrefix + "lib3" + (qbs.targetOS.contains("windows") + cpp.dynamicLibraryPrefix + "lib3" + (qbs.targetOS.includes("windows") ? cpp.dynamicLibraryImportSuffix : cpp.dynamicLibrarySuffix)) cpp.dynamicLibraries: [lib3FilePath, "lib4"] @@ -110,7 +117,7 @@ Project { Probe { id: osPrinter - property bool isWindows: qbs.targetOS.contains("windows") + property bool isWindows: qbs.targetOS.includes("windows") configure: { console.info("is windows"); found = true; diff --git a/tests/auto/blackbox/testdata/smart-relinking/smart-relinking.qbs b/tests/auto/blackbox/testdata/smart-relinking/smart-relinking.qbs index aac0692a8..29e6c2e17 100644 --- a/tests/auto/blackbox/testdata/smart-relinking/smart-relinking.qbs +++ b/tests/auto/blackbox/testdata/smart-relinking/smart-relinking.qbs @@ -5,7 +5,7 @@ Project { property stringList toolchain: qbs.toolchain property stringList targetOS: qbs.targetOS configure: { - found = toolchain.contains("gcc") && targetOS.contains("unix"); + found = toolchain.includes("gcc") && targetOS.includes("unix"); if (!found) console.info("project disabled"); } diff --git a/tests/auto/blackbox/testdata/source-artifact-changes/source-artifact-changes.qbs b/tests/auto/blackbox/testdata/source-artifact-changes/source-artifact-changes.qbs index de56376df..a53819753 100644 --- a/tests/auto/blackbox/testdata/source-artifact-changes/source-artifact-changes.qbs +++ b/tests/auto/blackbox/testdata/source-artifact-changes/source-artifact-changes.qbs @@ -4,7 +4,7 @@ CppApplication { consoleApplication: true Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.embedInfoPlist: false } @@ -12,7 +12,7 @@ CppApplication { id: toolchainProbe property stringList toolchain: qbs.toolchain configure: { - console.info("is gcc: " + toolchain.contains("gcc")); + console.info("is gcc: " + toolchain.includes("gcc")); found = true; } } diff --git a/tests/auto/blackbox/testdata/static-lib-without-sources/static-lib-without-sources.qbs b/tests/auto/blackbox/testdata/static-lib-without-sources/static-lib-without-sources.qbs index 32a58c94b..54ec5e230 100644 --- a/tests/auto/blackbox/testdata/static-lib-without-sources/static-lib-without-sources.qbs +++ b/tests/auto/blackbox/testdata/static-lib-without-sources/static-lib-without-sources.qbs @@ -6,7 +6,7 @@ StaticLibrary { } Product { - type: qbs.targetOS.contains("darwin") ? undefined : ["staticlibrary"] + type: qbs.targetOS.includes("darwin") ? undefined : ["staticlibrary"] name: "b" Depends { name: "cpp" } Depends { name: "a" } diff --git a/tests/auto/blackbox/testdata/successive-changes/successive-changes.qbs b/tests/auto/blackbox/testdata/successive-changes/successive-changes.qbs index 77df81e39..c33e24d34 100644 --- a/tests/auto/blackbox/testdata/successive-changes/successive-changes.qbs +++ b/tests/auto/blackbox/testdata/successive-changes/successive-changes.qbs @@ -17,7 +17,7 @@ Project { } prepare: { var cmd = new JavaScriptCommand(); - cmd.description = "Creating output"; + cmd.description = "creating output"; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.write(project.version); diff --git a/tests/auto/blackbox/testdata/symbolLinkMode/lib.cpp b/tests/auto/blackbox/testdata/symbolLinkMode/lib.cpp index 8d96f5094..9dcb48738 100644 --- a/tests/auto/blackbox/testdata/symbolLinkMode/lib.cpp +++ b/tests/auto/blackbox/testdata/symbolLinkMode/lib.cpp @@ -3,9 +3,9 @@ int somefunction() return 42; } -#include <stdio.h> +#include <cstdio> static const auto func = []() { - printf("Lib was loaded!\n"); + std::printf("Lib was loaded!\n"); return 0; }(); diff --git a/tests/auto/blackbox/testdata/symbolLinkMode/main.cpp b/tests/auto/blackbox/testdata/symbolLinkMode/main.cpp index 801491634..4d847ba19 100644 --- a/tests/auto/blackbox/testdata/symbolLinkMode/main.cpp +++ b/tests/auto/blackbox/testdata/symbolLinkMode/main.cpp @@ -1,15 +1,15 @@ extern WEAK_IMPORT int somefunction(); extern void indirect(); -#include <stdio.h> +#include <cstdio> int main() { - printf("meow\n"); + std::printf("meow\n"); if (&somefunction != nullptr) - printf("somefunction existed and it returned %d\n", somefunction()); + std::printf("somefunction existed and it returned %d\n", somefunction()); else - printf("somefunction did not exist\n"); + std::printf("somefunction did not exist\n"); #if SHOULD_INSTALL_LIB indirect(); #endif diff --git a/tests/auto/blackbox/testdata/symbolLinkMode/symbolLinkMode.qbs b/tests/auto/blackbox/testdata/symbolLinkMode/symbolLinkMode.qbs index 2d3d64b00..49bcd9951 100644 --- a/tests/auto/blackbox/testdata/symbolLinkMode/symbolLinkMode.qbs +++ b/tests/auto/blackbox/testdata/symbolLinkMode/symbolLinkMode.qbs @@ -1,15 +1,22 @@ import qbs.FileInfo +import qbs.Host Project { property bool shouldInstallLibrary: true property bool lazy: false Application { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } Depends { name: "cpp" } Depends { name: "functions"; cpp.symbolLinkMode: product.symbolLinkMode - cpp.link: !(product.qbs.targetOS.contains("linux") && product.symbolLinkMode === "weak") + cpp.link: !(product.qbs.targetOS.includes("linux") && product.symbolLinkMode === "weak") } property string symbolLinkMode: project.lazy ? "lazy" : "weak" @@ -20,7 +27,7 @@ Project { property string installLib: "SHOULD_INSTALL_LIB=" + project.shouldInstallLibrary cpp.defines: { if (symbolLinkMode === "weak") { - return qbs.targetOS.contains("darwin") + return qbs.targetOS.includes("darwin") ? ["WEAK_IMPORT=__attribute__((weak_import))", installLib] : ["WEAK_IMPORT=__attribute__((weak))", installLib]; } @@ -42,7 +49,7 @@ Project { Depends { name: "indirect"; cpp.symbolLinkMode: "reexport" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } name: "functions" @@ -52,7 +59,7 @@ Project { cpp.rpaths: [cpp.rpathOrigin] Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") cpp.sonamePrefix: "@rpath" } @@ -65,7 +72,7 @@ Project { Export { // let the autotest pass on Linux where reexport is not supported - Depends { name: "indirect"; condition: !qbs.targetOS.contains("darwin") } + Depends { name: "indirect"; condition: !qbs.targetOS.includes("darwin") } // on Linux, there is no LC_WEAK_LOAD_DYLIB equivalent (the library is simply omitted // from the list of load commands entirely), so use LD_PRELOAD to emulate @@ -84,7 +91,7 @@ Project { Depends { name: "cpp" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } name: "indirect" @@ -93,7 +100,7 @@ Project { cpp.minimumMacosVersion: "10.7" Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") // reexport is incompatible with rpath, // "ERROR: ld: file not found: @rpath/libindirect.dylib for architecture x86_64" cpp.sonamePrefix: qbs.installRoot + "/lib" diff --git a/tests/auto/blackbox/testdata/system-include-paths/main.cpp b/tests/auto/blackbox/testdata/system-include-paths/main.cpp index e449173d3..10d376a31 100644 --- a/tests/auto/blackbox/testdata/system-include-paths/main.cpp +++ b/tests/auto/blackbox/testdata/system-include-paths/main.cpp @@ -1,4 +1,4 @@ -#include <stdio.h> +#include <cstdio> #include <gagagugu.h> int main() diff --git a/tests/auto/blackbox/testdata/system-run-paths/system-run-paths.qbs b/tests/auto/blackbox/testdata/system-run-paths/system-run-paths.qbs index 6e2137173..35dd7a00f 100644 --- a/tests/auto/blackbox/testdata/system-run-paths/system-run-paths.qbs +++ b/tests/auto/blackbox/testdata/system-run-paths/system-run-paths.qbs @@ -20,4 +20,9 @@ Project { cpp.rpaths: qbs.installRoot + "/lib" cpp.systemRunPaths: project.setRunPaths ? [qbs.installRoot + "/lib"] : [] } + Probe { + id: checker + property bool isUnix: qbs.targetOS.contains("unix") + configure: { console.info("is unix: " + isUnix); } + } } diff --git a/tests/auto/blackbox/testdata/trackAddFile/after/main.cpp b/tests/auto/blackbox/testdata/trackAddFile/after/main.cpp index 0e474b221..d108825d6 100644 --- a/tests/auto/blackbox/testdata/trackAddFile/after/main.cpp +++ b/tests/auto/blackbox/testdata/trackAddFile/after/main.cpp @@ -31,7 +31,7 @@ int main(int argc, char **argv) { - printf("Hello World!\n"); + std::printf("Hello World!\n"); Narf narf; narf.shout(); Zort zort; diff --git a/tests/auto/blackbox/testdata/trackAddFile/after/trackAddFile.qbs b/tests/auto/blackbox/testdata/trackAddFile/after/trackAddFile.qbs index f4b9ba21f..4d454d4ff 100644 --- a/tests/auto/blackbox/testdata/trackAddFile/after/trackAddFile.qbs +++ b/tests/auto/blackbox/testdata/trackAddFile/after/trackAddFile.qbs @@ -1,5 +1,13 @@ +import qbs.Host + Project { Product { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } name: 'someapp' type: 'application' consoleApplication: true diff --git a/tests/auto/blackbox/testdata/trackAddFile/after/zort.cpp b/tests/auto/blackbox/testdata/trackAddFile/after/zort.cpp index 1915ea869..55a9dfa6d 100644 --- a/tests/auto/blackbox/testdata/trackAddFile/after/zort.cpp +++ b/tests/auto/blackbox/testdata/trackAddFile/after/zort.cpp @@ -30,6 +30,6 @@ void Zort::shout() { - printf("ZORT!\n"); + std::printf("ZORT!\n"); } diff --git a/tests/auto/blackbox/testdata/trackAddFile/before/main.cpp b/tests/auto/blackbox/testdata/trackAddFile/before/main.cpp index f989e1d9b..e8915030e 100644 --- a/tests/auto/blackbox/testdata/trackAddFile/before/main.cpp +++ b/tests/auto/blackbox/testdata/trackAddFile/before/main.cpp @@ -30,7 +30,7 @@ int main(int argc, char **argv) { - printf("Hello World!\n"); + std::printf("Hello World!\n"); Narf narf; narf.shout(); return 0; diff --git a/tests/auto/blackbox/testdata/trackAddFile/before/narf.cpp b/tests/auto/blackbox/testdata/trackAddFile/before/narf.cpp index 280d5f3bd..c301b57df 100644 --- a/tests/auto/blackbox/testdata/trackAddFile/before/narf.cpp +++ b/tests/auto/blackbox/testdata/trackAddFile/before/narf.cpp @@ -30,6 +30,6 @@ void Narf::shout() { - printf("NARF!\n"); + std::printf("NARF!\n"); } diff --git a/tests/auto/blackbox/testdata/trackAddFile/before/trackAddFile.qbs b/tests/auto/blackbox/testdata/trackAddFile/before/trackAddFile.qbs index bb0ab7d44..fd858b247 100644 --- a/tests/auto/blackbox/testdata/trackAddFile/before/trackAddFile.qbs +++ b/tests/auto/blackbox/testdata/trackAddFile/before/trackAddFile.qbs @@ -1,5 +1,13 @@ +import qbs.Host + Project { Product { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } name: 'someapp' type: 'application' consoleApplication: true diff --git a/tests/auto/blackbox/testdata/trackExternalProductChanges/trackExternalProductChanges.qbs b/tests/auto/blackbox/testdata/trackExternalProductChanges/trackExternalProductChanges.qbs index 534f49ff2..0e28e5687 100644 --- a/tests/auto/blackbox/testdata/trackExternalProductChanges/trackExternalProductChanges.qbs +++ b/tests/auto/blackbox/testdata/trackExternalProductChanges/trackExternalProductChanges.qbs @@ -11,4 +11,9 @@ CppApplication { name: "file that needs help from the environment to find a header" files: "including.cpp" } + Probe { + id: checker + property bool isGcc: qbs.toolchain.contains("gcc") + configure: { console.info("is gcc: " + isGcc); } + } } diff --git a/tests/auto/blackbox/testdata/trackFileTags/after/main.cpp b/tests/auto/blackbox/testdata/trackFileTags/after/main.cpp index 1d2c8ebb7..7520b5ed7 100644 --- a/tests/auto/blackbox/testdata/trackFileTags/after/main.cpp +++ b/tests/auto/blackbox/testdata/trackFileTags/after/main.cpp @@ -31,7 +31,7 @@ int foo(); int main(int argc, char **argv) { - printf("there's %d foo here\n", foo()); + std::printf("there's %d foo here\n", foo()); return 0; } diff --git a/tests/auto/blackbox/testdata/trackFileTags/after/trackFileTags.qbs b/tests/auto/blackbox/testdata/trackFileTags/after/trackFileTags.qbs index 869ce238b..1c5b6b56f 100644 --- a/tests/auto/blackbox/testdata/trackFileTags/after/trackFileTags.qbs +++ b/tests/auto/blackbox/testdata/trackFileTags/after/trackFileTags.qbs @@ -1,7 +1,15 @@ import qbs.TextFile +import qbs.Host + Project { Product { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } name: 'someapp' type: 'application' consoleApplication: true diff --git a/tests/auto/blackbox/testdata/trackFileTags/before/main.cpp b/tests/auto/blackbox/testdata/trackFileTags/before/main.cpp index 3016f8bb1..b4d71f995 100644 --- a/tests/auto/blackbox/testdata/trackFileTags/before/main.cpp +++ b/tests/auto/blackbox/testdata/trackFileTags/before/main.cpp @@ -29,7 +29,7 @@ int main(int argc, char **argv) { - printf("there's no foo here\n"); + std::printf("there's no foo here\n"); return 0; } diff --git a/tests/auto/blackbox/testdata/trackFileTags/before/trackFileTags.qbs b/tests/auto/blackbox/testdata/trackFileTags/before/trackFileTags.qbs index ebe31bf26..86771ab8f 100644 --- a/tests/auto/blackbox/testdata/trackFileTags/before/trackFileTags.qbs +++ b/tests/auto/blackbox/testdata/trackFileTags/before/trackFileTags.qbs @@ -1,7 +1,15 @@ import qbs.TextFile +import qbs.Host + Project { Product { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } name: 'someapp' type: 'application' consoleApplication: true diff --git a/tests/auto/blackbox/testdata/trackProducts/after/zoo.cpp b/tests/auto/blackbox/testdata/trackProducts/after/zoo.cpp index b65fb3f9d..fc0d13e4b 100644 --- a/tests/auto/blackbox/testdata/trackProducts/after/zoo.cpp +++ b/tests/auto/blackbox/testdata/trackProducts/after/zoo.cpp @@ -30,5 +30,5 @@ int main() { - printf("zoo\n"); + std::printf("zoo\n"); } diff --git a/tests/auto/blackbox/testdata/trackProducts/before/bar.cpp b/tests/auto/blackbox/testdata/trackProducts/before/bar.cpp index 7880c8669..3664897de 100644 --- a/tests/auto/blackbox/testdata/trackProducts/before/bar.cpp +++ b/tests/auto/blackbox/testdata/trackProducts/before/bar.cpp @@ -30,5 +30,5 @@ int main() { - printf("bar\n"); + std::printf("bar\n"); } diff --git a/tests/auto/blackbox/testdata/trackProducts/before/foo.cpp b/tests/auto/blackbox/testdata/trackProducts/before/foo.cpp index 865fb1299..fb5c32769 100644 --- a/tests/auto/blackbox/testdata/trackProducts/before/foo.cpp +++ b/tests/auto/blackbox/testdata/trackProducts/before/foo.cpp @@ -30,5 +30,5 @@ int main() { - printf("foo\n"); + std::printf("foo\n"); } diff --git a/tests/auto/blackbox/testdata/transitive-invalid-dependencies/modules/a/a.qbs b/tests/auto/blackbox/testdata/transitive-invalid-dependencies/modules/a/a.qbs new file mode 100644 index 000000000..fd52488fb --- /dev/null +++ b/tests/auto/blackbox/testdata/transitive-invalid-dependencies/modules/a/a.qbs @@ -0,0 +1,5 @@ +Module { + validate: { + throw "Module cannot be loaded"; + } +} diff --git a/tests/auto/blackbox/testdata/transitive-invalid-dependencies/modules/b/b.qbs b/tests/auto/blackbox/testdata/transitive-invalid-dependencies/modules/b/b.qbs new file mode 100644 index 000000000..605a2aaee --- /dev/null +++ b/tests/auto/blackbox/testdata/transitive-invalid-dependencies/modules/b/b.qbs @@ -0,0 +1,3 @@ +Module { + Depends { name: "a" } +} diff --git a/tests/auto/blackbox/testdata/transitive-invalid-dependencies/modules/c/c.qbs b/tests/auto/blackbox/testdata/transitive-invalid-dependencies/modules/c/c.qbs new file mode 100644 index 000000000..ac7dbbec6 --- /dev/null +++ b/tests/auto/blackbox/testdata/transitive-invalid-dependencies/modules/c/c.qbs @@ -0,0 +1,3 @@ +Module { + Depends { name: "a"; required: false } +} diff --git a/tests/auto/blackbox/testdata/transitive-invalid-dependencies/modules/d/d.qbs b/tests/auto/blackbox/testdata/transitive-invalid-dependencies/modules/d/d.qbs new file mode 100644 index 000000000..0bdd8c3b7 --- /dev/null +++ b/tests/auto/blackbox/testdata/transitive-invalid-dependencies/modules/d/d.qbs @@ -0,0 +1,4 @@ +Module { + Depends { name: "b"; } + Depends { name: "c"; } +} diff --git a/tests/auto/blackbox/testdata/transitive-invalid-dependencies/transitive-invalid-dependencies.qbs b/tests/auto/blackbox/testdata/transitive-invalid-dependencies/transitive-invalid-dependencies.qbs new file mode 100644 index 000000000..209b1e47d --- /dev/null +++ b/tests/auto/blackbox/testdata/transitive-invalid-dependencies/transitive-invalid-dependencies.qbs @@ -0,0 +1,11 @@ +Product { + property bool modulePresent: { + console.info("b.present = " + b.present); + console.info("c.present = " + c.present); + console.info("d.present = " + d.present); + } + + Depends { name: "b"; required: false } + Depends { name: "c"; required: false } + Depends { name: "d"; required: false } +} diff --git a/tests/auto/blackbox/testdata/undefined-target-platform/undefined-target-platform.qbs b/tests/auto/blackbox/testdata/undefined-target-platform/undefined-target-platform.qbs new file mode 100644 index 000000000..4a738afcc --- /dev/null +++ b/tests/auto/blackbox/testdata/undefined-target-platform/undefined-target-platform.qbs @@ -0,0 +1,13 @@ +import qbs.File +import qbs.FileInfo + +Product { + name: "undefined-target-platform" + qbs.targetPlatform: undefined + + readonly property bool _validate: { + if ((qbs.targetOS instanceof Array) && qbs.targetOS.length === 0) + return true; + throw "Invalid qbs.targetOS value: " + qbs.targetOS; + } +} diff --git a/tests/auto/blackbox/testdata/variant-suffix/variant-suffix.qbs b/tests/auto/blackbox/testdata/variant-suffix/variant-suffix.qbs index b6e025e4c..1131e6a2f 100644 --- a/tests/auto/blackbox/testdata/variant-suffix/variant-suffix.qbs +++ b/tests/auto/blackbox/testdata/variant-suffix/variant-suffix.qbs @@ -1,8 +1,8 @@ StaticLibrary { name: "l" - Depends { condition: qbs.targetOS.contains("darwin"); name: "bundle" } - Properties { condition: qbs.targetOS.contains("darwin"); bundle.isBundle: false } + Depends { condition: qbs.targetOS.includes("darwin"); name: "bundle" } + Properties { condition: qbs.targetOS.includes("darwin"); bundle.isBundle: false } aggregate: false property string variantSuffix @@ -31,8 +31,8 @@ StaticLibrary { id: targetOSProbe property stringList targetOS: qbs.targetOS configure: { - console.info("is Windows: " + targetOS.contains("windows")); - console.info("is Apple: " + targetOS.contains("darwin")); + console.info("is Windows: " + targetOS.includes("windows")); + console.info("is Apple: " + targetOS.includes("darwin")); } } } diff --git a/tests/auto/blackbox/testdata/vcs/vcstest.qbs b/tests/auto/blackbox/testdata/vcs/vcstest.qbs index 5d359e2c7..4f861654b 100644 --- a/tests/auto/blackbox/testdata/vcs/vcstest.qbs +++ b/tests/auto/blackbox/testdata/vcs/vcstest.qbs @@ -1,4 +1,12 @@ +import qbs.Host + CppApplication { + condition: { + var result = qbs.targetPlatform === Host.platform(); + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result; + } Depends { name: "vcs" } vcs.headerFileName: "my-repo-state.h" files: ["main.cpp"] diff --git a/tests/auto/blackbox/testdata/versionscript/versionscript.qbs b/tests/auto/blackbox/testdata/versionscript/versionscript.qbs index cc5c7b1cc..fcb4314a2 100644 --- a/tests/auto/blackbox/testdata/versionscript/versionscript.qbs +++ b/tests/auto/blackbox/testdata/versionscript/versionscript.qbs @@ -20,6 +20,12 @@ DynamicLibrary { return [cmd]; } } + Probe { + id: checker + property bool isLinux: qbs.targetOS.includes("linux") + property bool isGcc: qbs.toolchain.contains("gcc") + configure: { console.info("is gcc for Linux: " + (isLinux && isGcc)); } + } qbs.installPrefix: "" install: true diff --git a/tests/auto/blackbox/testdata/whole-archive/whole-archive.qbs b/tests/auto/blackbox/testdata/whole-archive/whole-archive.qbs index f3bcff2cd..c138e46c0 100644 --- a/tests/auto/blackbox/testdata/whole-archive/whole-archive.qbs +++ b/tests/auto/blackbox/testdata/whole-archive/whole-archive.qbs @@ -32,7 +32,8 @@ Project { property string compilerVersion: cpp.compilerVersion property string dummy: product.linkWholeArchive // To force probe re-execution configure: { - if (!toolchain.contains("msvc") + if (!toolchain.includes("msvc") + || toolchain.includes("clang-cl") || Utilities.versionCompare(compilerVersion, "19.0.24215.1") >= 0) { console.info("can link whole archives"); } else { diff --git a/tests/auto/blackbox/testdata/wildcards-and-change-tracking/nonrecursive/subdir1/file.txt b/tests/auto/blackbox/testdata/wildcards-and-change-tracking/nonrecursive/subdir1/file.txt new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/auto/blackbox/testdata/wildcards-and-change-tracking/nonrecursive/subdir1/file.txt diff --git a/tests/auto/blackbox/testdata/wildcards-and-change-tracking/nonrecursive/subdir2/file.txt b/tests/auto/blackbox/testdata/wildcards-and-change-tracking/nonrecursive/subdir2/file.txt new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/auto/blackbox/testdata/wildcards-and-change-tracking/nonrecursive/subdir2/file.txt diff --git a/tests/auto/blackbox/testdata/wildcards-and-change-tracking/recursive1/recursive.txt b/tests/auto/blackbox/testdata/wildcards-and-change-tracking/recursive1/recursive.txt new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/auto/blackbox/testdata/wildcards-and-change-tracking/recursive1/recursive.txt diff --git a/tests/auto/blackbox/testdata/wildcards-and-change-tracking/recursive2/recursive.txt b/tests/auto/blackbox/testdata/wildcards-and-change-tracking/recursive2/recursive.txt new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/auto/blackbox/testdata/wildcards-and-change-tracking/recursive2/recursive.txt diff --git a/tests/auto/blackbox/testdata/wildcards-and-change-tracking/wildcards-and-change-tracking.qbs b/tests/auto/blackbox/testdata/wildcards-and-change-tracking/wildcards-and-change-tracking.qbs new file mode 100644 index 000000000..0a889bab3 --- /dev/null +++ b/tests/auto/blackbox/testdata/wildcards-and-change-tracking/wildcards-and-change-tracking.qbs @@ -0,0 +1,16 @@ +Product { + Group { + name: "recursive" + files: "**/file.txt" + } + Group { + name: "directories" + prefix: "nonrecursive/" + files: "subdi?/file.txt" + } + Group { + prefix: "nonrecursive/empty/" + name: "no files" + files: "*.txt" + } +} diff --git a/tests/auto/blackbox/testdata/wildcards-and-rules/wildcards-and-rules.qbs b/tests/auto/blackbox/testdata/wildcards-and-rules/wildcards-and-rules.qbs index f6662529d..fe6088943 100644 --- a/tests/auto/blackbox/testdata/wildcards-and-rules/wildcards-and-rules.qbs +++ b/tests/auto/blackbox/testdata/wildcards-and-rules/wildcards-and-rules.qbs @@ -22,7 +22,7 @@ Product { } prepare: { var cmd = new JavaScriptCommand(); - cmd.description = "Creating output artifact"; + cmd.description = "creating output artifact"; cmd.highlight = "codegen"; cmd.sourceCode = function() { var file = new TextFile(output.filePath, TextFile.WriteOnly); diff --git a/tests/auto/blackbox/tst_blackbox.cpp b/tests/auto/blackbox/tst_blackbox.cpp index faada314f..dbabfb311 100644 --- a/tests/auto/blackbox/tst_blackbox.cpp +++ b/tests/auto/blackbox/tst_blackbox.cpp @@ -49,10 +49,11 @@ #include <QtCore/qjsonobject.h> #include <QtCore/qjsonvalue.h> #include <QtCore/qlocale.h> -#include <QtCore/qregexp.h> +#include <QtCore/qregularexpression.h> #include <QtCore/qsettings.h> #include <QtCore/qtemporarydir.h> #include <QtCore/qtemporaryfile.h> +#include <QtCore/qversionnumber.h> #include <algorithm> #include <functional> @@ -62,7 +63,6 @@ #define WAIT_FOR_NEW_TIMESTAMP() waitForNewTimestamp(testDataDir) using qbs::Internal::HostOsInfo; -using qbs::Profile; class MacosTarHealer { public: @@ -138,12 +138,32 @@ QString TestBlackbox::findArchiver(const QString &fileName, int *status) QString binary = findExecutable(QStringList(fileName)); if (binary.isEmpty()) { const SettingsPtr s = settings(); - Profile p(profileName(), s.get()); + qbs::Profile p(profileName(), s.get()); binary = findExecutable(p.value("archiver.command").toStringList()); } return binary; } +bool TestBlackbox::prepareAndRunConan() +{ + QString executable = findExecutable({"conan"}); + if (executable.isEmpty()) { + qInfo() << "conan is not installed or not available in PATH."; + return false; + } + const auto profilePath = QDir::homePath() + "/.conan2/profiles/qbs-test"; + if (!QFileInfo(profilePath).exists()) { + qInfo() << "conan profile is not installed, run './scripts/setup-conan-profiles.sh'"; + return false; + } + QProcess conan; + QDir::setCurrent(testDataDir + "/conan-provider/testlibdep"); + rmDirR("build"); + QStringList arguments{"install", ".", "--profile:all=qbs-test", "--output-folder=build"}; + conan.start(executable, arguments); + return waitForProcessSuccess(conan, 60000); +} + bool TestBlackbox::lexYaccExist() { return !findExecutable(QStringList("lex")).isEmpty() @@ -253,6 +273,13 @@ void TestBlackbox::systemIncludePaths() QCOMPARE(runQbs(), 0); } +void TestBlackbox::distributionIncludePaths() +{ + const QString projectDir = testDataDir + "/distribution-include-paths"; + QDir::setCurrent(projectDir); + QCOMPARE(runQbs(), 0); +} + void TestBlackbox::tar() { if (HostOsInfo::hostOs() == HostOsInfo::HostOsWindows) @@ -291,7 +318,7 @@ void TestBlackbox::textTemplate() static QStringList sortedFileList(const QByteArray &ba) { - auto list = QString::fromUtf8(ba).split(QRegExp("[\r\n]"), QString::SkipEmptyParts); + auto list = QString::fromUtf8(ba).split(QRegularExpression("[\r\n]"), Qt::SkipEmptyParts); std::sort(list.begin(), list.end()); return list; } @@ -356,6 +383,57 @@ TestBlackbox::TestBlackbox() : TestBlackboxBase (SRCDIR "/testdata", "blackbox") { } +void TestBlackbox::allowedValues() +{ + QFETCH(QString, property); + QFETCH(QString, value); + QFETCH(QString, invalidValue); + + QDir::setCurrent(testDataDir + "/allowed-values"); + rmDirR(relativeBuildDir()); + + QbsRunParameters params; + if (!property.isEmpty() && !value.isEmpty()) { + params.arguments << QStringLiteral("%1:%2").arg(property, value); + } + + params.expectFailure = !invalidValue.isEmpty(); + QCOMPARE(runQbs(params) == 0, !params.expectFailure); + if (params.expectFailure) { + const auto errorString = + QStringLiteral("Value '%1' is not allowed for property").arg(invalidValue); + QVERIFY2(m_qbsStderr.contains(errorString.toUtf8()), m_qbsStderr.constData()); + } +} + +void TestBlackbox::allowedValues_data() +{ + QTest::addColumn<QString>("property"); + QTest::addColumn<QString>("value"); + QTest::addColumn<QString>("invalidValue"); + + QTest::newRow("default") << QString() << QString() << QString(); + + QTest::newRow("allowed (product, CLI)") << "products.p.prop" << "foo" << QString(); + QTest::newRow("not allowed (product, CLI)") << "products.p.prop" << "bar" << "bar"; + QTest::newRow("allowed (product, JS)") << "products.p.prop2" << "foo" << QString(); + QTest::newRow("not allowed (product, JS)") << "products.p.prop2" << "bar" << "bar"; + + QTest::newRow("allowed single (module, CLI)") << "modules.a.prop" << "foo" << QString(); + QTest::newRow("not allowed single (module, CLI)") << "modules.a.prop" << "baz" << "baz"; + QTest::newRow("allowed mult (module, CLI)") << "modules.a.prop" << "foo,bar" << QString(); + QTest::newRow("not allowed mult (module, CLI)") << "modules.a.prop" << "foo,baz" << "baz"; + + QTest::newRow("allowed single (module, JS)") << "modules.a.prop2" << "foo" << QString(); + QTest::newRow("not allowed single (module, JS)") << "modules.a.prop2" << "baz" << "baz"; + QTest::newRow("allowed mult (module, JS)") << "modules.a.prop2" << "foo,bar" << QString(); + QTest::newRow("not allowed mult (module, JS)") << "modules.a.prop2" << "foo,baz" << "baz"; + + // undefined should always be allowed + QTest::newRow("undefined (product)") << "products.p.prop" << "undefined" << QString(); + QTest::newRow("undefined (module)") << "modules.a.prop" << "undefined" << QString(); +} + void TestBlackbox::addFileTagToGeneratedArtifact() { QDir::setCurrent(testDataDir + "/add-filetag-to-generated-artifact"); @@ -640,7 +718,7 @@ void TestBlackbox::buildDirectories() QDir::setCurrent(projectDir); QCOMPARE(runQbs(), 0); const QStringList outputLines - = QString::fromLocal8Bit(m_qbsStdout.trimmed()).split('\n', QString::SkipEmptyParts); + = QString::fromLocal8Bit(m_qbsStdout.trimmed()).split('\n', Qt::SkipEmptyParts); QVERIFY2(outputLines.contains(projectDir + '/' + relativeProductBuildDir("p1")), m_qbsStdout.constData()); QVERIFY2(outputLines.contains(projectDir + '/' + relativeProductBuildDir("p2")), @@ -649,6 +727,45 @@ void TestBlackbox::buildDirectories() QVERIFY2(outputLines.contains(projectDir), m_qbsStdout.constData()); } +void TestBlackbox::buildDirPlaceholders_data() +{ + QTest::addColumn<QString>("buildDir"); + QTest::addColumn<bool>("setProjectFile"); + QTest::addColumn<bool>("successExpected"); + + QTest::newRow("normal dir, with project file") << "somedir" << true << true; + QTest::newRow("normal dir, without project file") << "somedir" << false << true; + QTest::newRow("@project, with project file") << "somedir/@project" << true << true; + QTest::newRow("@project, without project file") << "somedir/@project" << false << false; + QTest::newRow("@path, with project file") << "somedir/@path" << true << true; + QTest::newRow("@path, without project file") << "somedir/@path" << false << false; +} + +void TestBlackbox::buildDirPlaceholders() +{ + QFETCH(QString, buildDir); + QFETCH(bool, setProjectFile); + QFETCH(bool, successExpected); + + const QString projectDir = testDataDir + "/build-dir-placeholders"; + rmDirR(projectDir); + QVERIFY(QDir().mkpath(projectDir)); + QDir::setCurrent(projectDir); + QFile projectFile("build-dir-placeholders.qbs"); + QVERIFY(projectFile.open(QIODevice::WriteOnly)); + projectFile.write("Product {\n}\n"); + projectFile.flush(); + rmDirR(relativeBuildDir()); + QbsRunParameters params; + params.buildDirectory = buildDir; + if (setProjectFile) { + params.arguments << "-f" + << "build-dir-placeholders.qbs"; + } + params.expectFailure = !successExpected; + QCOMPARE(runQbs(params) == 0, successExpected); +} + void TestBlackbox::buildEnvChange() { QDir::setCurrent(testDataDir + "/buildenv-change"); @@ -713,6 +830,69 @@ void TestBlackbox::buildGraphVersions() QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); } +void TestBlackbox::buildVariantDefaults_data() +{ + QTest::addColumn<QString>("buildVariant"); + QTest::newRow("default") << QString(); + QTest::newRow("debug") << QStringLiteral("debug"); + QTest::newRow("release") << QStringLiteral("release"); + QTest::newRow("profiling") << QStringLiteral("profiling"); +} + +void TestBlackbox::buildVariantDefaults() +{ + QFETCH(QString, buildVariant); + QDir::setCurrent(testDataDir + "/build-variant-defaults"); + QbsRunParameters params{QStringLiteral("resolve")}; + if (!buildVariant.isEmpty()) + params.arguments << ("modules.qbs.buildVariant:" + buildVariant); + QCOMPARE(runQbs(params), 0); +} + +void TestBlackbox::capnproto() +{ + QFETCH(QString, projectFile); + QFETCH(QStringList, arguments); + QDir::setCurrent(testDataDir + "/capnproto"); + rmDirR(relativeBuildDir()); + + if (QTest::currentDataTag() == QLatin1String("cpp-conan") + || QTest::currentDataTag() == QLatin1String("rpc-conan")) { + if (!prepareAndRunConan()) + QSKIP("conan is not prepared, check messages above"); + } + + QbsRunParameters params{QStringLiteral("resolve"), {QStringLiteral("-f"), projectFile}}; + params.arguments << arguments; + QCOMPARE(runQbs(params), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); + if (m_qbsStdout.contains("capnproto is not present")) + QSKIP("capnproto is not present"); + + params.command = QStringLiteral("build"); + QCOMPARE(runQbs(params), 0); +} + +void TestBlackbox::capnproto_data() +{ + QTest::addColumn<QString>("projectFile"); + QTest::addColumn<QStringList>("arguments"); + + QStringList pkgConfigArgs({"project.qbsModuleProviders:qbspkgconfig"}); + QTest::newRow("cpp-pkgconfig") << QStringLiteral("capnproto_cpp.qbs") << pkgConfigArgs; + QTest::newRow("rpc-pkgconfig") << QStringLiteral("greeter_cpp.qbs") << pkgConfigArgs; + QTest::newRow("relative import") + << QStringLiteral("capnproto_relative_import.qbs") << pkgConfigArgs; + QTest::newRow("absolute import") + << QStringLiteral("capnproto_absolute_import.qbs") << pkgConfigArgs; + + QStringList conanArgs( + {"project.qbsModuleProviders:conan", "moduleProviders.conan.installDirectory:build"}); + QTest::newRow("cpp-conan") << QStringLiteral("capnproto_cpp.qbs") << conanArgs; + QTest::newRow("rpc-conan") << QStringLiteral("greeter_cpp.qbs") << conanArgs; +} + void TestBlackbox::changedFiles_data() { QTest::addColumn<bool>("useChangedFilesForInitialBuild"); @@ -885,7 +1065,7 @@ void TestBlackbox::dependenciesProperty() QJsonArray cpp_dependencies = product2_cpp.value("dependencies").toArray(); QVERIFY(!cpp_dependencies.isEmpty()); int qbsCount = 0; - for (const auto &dep : cpp_dependencies) { + for (const auto dep : cpp_dependencies) { if (dep.toObject().value("name").toString() == "qbs") ++qbsCount; } @@ -897,7 +1077,7 @@ void TestBlackbox::dependenciesProperty() REPLACE_IN_FILE(projectFile, "// Depends { name: 'newDependency' }", "Depends { name: 'newDependency' }"); QCOMPARE(runQbs(), 0); - QVERIFY2(m_qbsStdout.contains("generate product1.deps"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("generating product1.deps"), m_qbsStdout.constData()); readDepsOutput(depsFile, jsondoc); dependencies = jsondoc.array(); QCOMPARE(dependencies.size(), 3); @@ -908,7 +1088,7 @@ void TestBlackbox::dependenciesProperty() REPLACE_IN_FILE(projectFile, "// Depends { name: 'product2' }", "Depends { name: 'product2' }"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); - QVERIFY2(!m_qbsStdout.contains("generate product1.deps"), m_qbsStdout.constData()); + QVERIFY2(!m_qbsStdout.contains("generating product1.deps"), m_qbsStdout.constData()); readDepsOutput(depsFile, jsondoc); dependencies = jsondoc.array(); QCOMPARE(dependencies.size(), 3); @@ -918,7 +1098,7 @@ void TestBlackbox::dependenciesProperty() 0); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("compiling product2.cpp"), m_qbsStdout.constData()); - QVERIFY2(m_qbsStdout.contains("generate product1.deps"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("generating product1.deps"), m_qbsStdout.constData()); readDepsOutput(depsFile, jsondoc); dependencies = jsondoc.array(); QCOMPARE(dependencies.size(), 3); @@ -930,7 +1110,7 @@ void TestBlackbox::dependenciesProperty() "products.product2.cpp.defines:DIGEDAG"})), 0); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling product2.cpp"), m_qbsStdout.constData()); - QVERIFY2(m_qbsStdout.contains("generate product1.deps"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("generating product1.deps"), m_qbsStdout.constData()); readDepsOutput(depsFile, jsondoc); dependencies = jsondoc.array(); QCOMPARE(dependencies.size(), 3); @@ -942,40 +1122,77 @@ void TestBlackbox::dependenciesProperty() QCOMPARE(product2_cpp_defines.first().toString(), QLatin1String("DIGEDAG")); } -void TestBlackbox::dependencyProfileMismatch() +void TestBlackbox::dependencyScanningLoop() { - QDir::setCurrent(testDataDir + "/dependency-profile-mismatch"); - const SettingsPtr s = settings(); - qbs::Internal::TemporaryProfile depProfile("qbs_autotests_profileMismatch", s.get()); - depProfile.p.setValue("qbs.architecture", "x86"); // Profiles must not be empty... - s->sync(); - QbsRunParameters params(QStringList() << ("project.mainProfile:" + profileName()) - << ("project.depProfile:" + depProfile.p.name())); - params.expectFailure = true; - QVERIFY2(runQbs(params) != 0, m_qbsStderr.constData()); - QVERIFY2(m_qbsStderr.contains(profileName().toLocal8Bit()) - && m_qbsStderr.contains("', which does not exist"), - m_qbsStderr.constData()); + QDir::setCurrent(testDataDir + "/dependency-scanning-loop"); + QCOMPARE(runQbs(), 0); + QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); } void TestBlackbox::deprecatedProperty() { + QFETCH(QString, version); + QFETCH(QString, mode); + QFETCH(bool, expiringWarning); + QFETCH(bool, expiringError); + QDir::setCurrent(testDataDir + "/deprecated-property"); QbsRunParameters params(QStringList("-q")); params.expectFailure = true; + params.environment.insert("REMOVAL_VERSION", version); + if (!mode.isEmpty()) + params.arguments << "--deprecation-warnings" << mode; QVERIFY(runQbs(params) != 0); m_qbsStderr = QDir::fromNativeSeparators(QString::fromLocal8Bit(m_qbsStderr)).toLocal8Bit(); - QVERIFY2(m_qbsStderr.contains("deprecated-property.qbs:6:24 The property 'oldProp' is " - "deprecated and will be removed in Qbs 99.9.0."), m_qbsStderr.constData()); - QVERIFY2(m_qbsStderr.contains("deprecated-property.qbs:7:28 The property 'veryOldProp' can no " - "longer be used. It was removed in Qbs 1.3.0."), m_qbsStderr.constData()); + const bool hasExpiringWarning = m_qbsStderr.contains(QByteArray( + "deprecated-property.qbs:4:29 The property 'expiringProp' is " + "deprecated and will be removed in Qbs ") + version.toLocal8Bit()); + QVERIFY2(expiringWarning == hasExpiringWarning, m_qbsStderr.constData()); + const bool hasRemovedOutput = m_qbsStderr.contains( + "deprecated-property.qbs:5:28 The property 'veryOldProp' can no " + "longer be used. It was removed in Qbs 1.3.0."); + QVERIFY2(hasRemovedOutput == !expiringError, m_qbsStderr.constData()); QVERIFY2(m_qbsStderr.contains("Property 'forgottenProp' was scheduled for removal in version " "1.8.0, but is still present."), m_qbsStderr.constData()); QVERIFY2(m_qbsStderr.contains("themodule/m.qbs:22:5 Removal version for 'forgottenProp' " "specified here."), m_qbsStderr.constData()); - QVERIFY2(m_qbsStderr.count("Use newProp instead.") == 2, m_qbsStderr.constData()); - QVERIFY2(m_qbsStderr.count("is deprecated") == 1, m_qbsStderr.constData()); - QVERIFY2(m_qbsStderr.count("was removed") == 1, m_qbsStderr.constData()); + QVERIFY2(m_qbsStderr.count("Use newProp instead.") == 1 + + int(expiringWarning && !expiringError), m_qbsStderr.constData()); + QVERIFY2(m_qbsStderr.count("is deprecated") == int(expiringWarning), m_qbsStderr.constData()); + QVERIFY2(m_qbsStderr.count("was removed") == int(!expiringError), m_qbsStderr.constData()); +} + +void TestBlackbox::deprecatedProperty_data() +{ + QTest::addColumn<QString>("version"); + QTest::addColumn<QString>("mode"); + QTest::addColumn<bool>("expiringWarning"); + QTest::addColumn<bool>("expiringError"); + + const auto current = QVersionNumber::fromString(QBS_VERSION); + const QString next = QVersionNumber(current.majorVersion(), current.minorVersion() + 1) + .toString(); + const QString nextNext = QVersionNumber(current.majorVersion(), current.minorVersion() + 2) + .toString(); + const QString nextMajor = QVersionNumber(current.majorVersion() + 1).toString(); + + QTest::newRow("default/next") << next << QString() << true << false; + QTest::newRow("default/nextnext") << nextNext << QString() << false << false; + QTest::newRow("default/nextmajor") << nextMajor << QString() << true << false; + QTest::newRow("error/next") << next << QString("error") << true << true; + QTest::newRow("error/nextnext") << nextNext << QString("error") << true << true; + QTest::newRow("error/nextmajor") << nextMajor << QString("error") << true << true; + QTest::newRow("on/next") << next << QString("on") << true << false; + QTest::newRow("on/nextnext") << nextNext << QString("on") << true << false; + QTest::newRow("on/nextmajor") << nextMajor << QString("on") << true << false; + QTest::newRow("before-removal/next") << next << QString("before-removal") << true << false; + QTest::newRow("before-removal/nextnext") << nextNext << QString("before-removal") + << false << false; + QTest::newRow("before-removal/nextmajor") << nextMajor << QString("before-removal") + << true << false; + QTest::newRow("off/next") << next << QString("off") << false << false; + QTest::newRow("off/nextnext") << nextNext << QString("off") << false << false; + QTest::newRow("off/nextmajor") << nextMajor << QString("off") << false << false; } void TestBlackbox::disappearedProfile() @@ -1008,16 +1225,16 @@ void TestBlackbox::disappearedProfile() QbsRunParameters buildParams; buildParams.profile.clear(); QCOMPARE(runQbs(buildParams), 0); - QVERIFY2(m_qbsStdout.contains("Creating dummy1.txt with p1 from profile"), + QVERIFY2(m_qbsStdout.contains("creating dummy1.txt with p1 from profile"), m_qbsStdout.constData()); - QVERIFY2(m_qbsStdout.contains("Creating dummy2.txt with p2 from profile"), + QVERIFY2(m_qbsStdout.contains("creating dummy2.txt with p2 from profile"), m_qbsStdout.constData()); // Now we do use the "resolve" command, so the new property value is taken into account. QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(buildParams), 0); - QVERIFY2(!m_qbsStdout.contains("Creating dummy1.txt"), m_qbsStdout.constData()); - QVERIFY2(m_qbsStdout.contains("Creating dummy2.txt with p2 new from profile"), + QVERIFY2(!m_qbsStdout.contains("creating dummy1.txt"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("creating dummy2.txt with p2 new from profile"), m_qbsStdout.constData()); // Now we change the profile again without a "resolve" command. However, this time we @@ -1030,8 +1247,8 @@ void TestBlackbox::disappearedProfile() "property string p1: 'p1 from module'"); QCOMPARE(runQbs(buildParams), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); - QVERIFY2(!m_qbsStdout.contains("Creating dummy1.txt"), m_qbsStdout.constData()); - QVERIFY2(!m_qbsStdout.contains("Creating dummy2.txt"), m_qbsStdout.constData()); + QVERIFY2(!m_qbsStdout.contains("creating dummy1.txt"), m_qbsStdout.constData()); + QVERIFY2(!m_qbsStdout.contains("creating dummy2.txt"), m_qbsStdout.constData()); // Now we run the "resolve" command without giving the necessary settings path to find // the profile. @@ -1055,10 +1272,12 @@ void TestBlackbox::discardUnusedData() QVERIFY2(m_qbsStdout.contains("is Darwin"), m_qbsStdout.constData()); const bool isDarwin = m_qbsStdout.contains("is Darwin: true"); const QString output = QString::fromLocal8Bit(m_qbsStdout); - QRegExp pattern(".*---(.*)---.*"); - QVERIFY2(pattern.exactMatch(output), qPrintable(output)); - QCOMPARE(pattern.captureCount(), 1); - const QString nmPath = pattern.capturedTexts().at(1); + const QRegularExpression pattern(QRegularExpression::anchoredPattern(".*---(.*)---.*"), + QRegularExpression::DotMatchesEverythingOption); + const QRegularExpressionMatch match = pattern.match(output); + QVERIFY2(match.hasMatch(), qPrintable(output)); + QCOMPARE(match.lastCapturedIndex(), 1); + const QString nmPath = match.captured(1); if (!QFile::exists(nmPath)) QSKIP("Cannot check for symbol presence: No nm found."); QProcess nm; @@ -1082,6 +1301,13 @@ void TestBlackbox::discardUnusedData_data() QTest::newRow("default") << QString() << true; } +void TestBlackbox::dotDotPcFile() +{ + QDir::setCurrent(testDataDir + "/dot-dot-pc-file"); + + QCOMPARE(runQbs(), 0); +} + void TestBlackbox::driverLinkerFlags() { QDir::setCurrent(testDataDir + QLatin1String("/driver-linker-flags")); @@ -1124,9 +1350,13 @@ void TestBlackbox::dynamicLibraryInModule() QbsRunParameters libParams(QStringList({"-f", "thelibs.qbs", installRootSpec})); libParams.buildDirectory = "libbuild"; QCOMPARE(runQbs(libParams), 0); - QbsRunParameters appParams("run", QStringList({"-f", "theapp.qbs", installRootSpec})); + QbsRunParameters appParams("build", QStringList({"-f", "theapp.qbs", installRootSpec})); appParams.buildDirectory = "appbuild"; QCOMPARE(runQbs(appParams), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); + appParams.command = "run"; + QCOMPARE(runQbs(appParams), 0); QVERIFY2(m_qbsStdout.contains("Hello from thelib"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("Hello from theotherlib"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("thirdlib"), m_qbsStdout.constData()); @@ -1232,19 +1462,6 @@ void TestBlackbox::variantSuffix_data() std::make_pair(QString("unix"), QStringList())}); } -static bool waitForProcessSuccess(QProcess &p) -{ - if (!p.waitForStarted() || !p.waitForFinished()) { - qDebug() << p.errorString(); - return false; - } - if (p.exitCode() != 0) { - qDebug() << p.readAllStandardError(); - return false; - } - return true; -} - void TestBlackbox::vcsGit() { const QString gitFilePath = findExecutable(QStringList("git")); @@ -1275,6 +1492,9 @@ void TestBlackbox::vcsGit() return m_qbsStdout.mid(startIndex + 2, endIndex - startIndex - 2); }; + QCOMPARE(runQbs({"resolve", {"-f", repoDir.path()}}), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); // Run without git metadata. QbsRunParameters params("run", QStringList{"-f", repoDir.path()}); params.workingDir = repoDir.path() + "/.."; @@ -1340,6 +1560,9 @@ void TestBlackbox::vcsSubversion() if (svnFilePath.isEmpty()) QSKIP("svn not found"); + if (HostOsInfo::isWindowsHost() && qEnvironmentVariableIsSet("GITHUB_ACTIONS")) + QSKIP("Skip this test when running on GitHub"); + // Set up repo. QTemporaryDir repoDir; QVERIFY(repoDir.isValid()); @@ -1363,6 +1586,8 @@ void TestBlackbox::vcsSubversion() failParams.command = "run"; failParams.expectFailure = true; const int retval = runQbs(failParams); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); if (m_qbsStderr.contains("svn too old")) QSKIP("svn too old"); QCOMPARE(retval, 0); @@ -1431,19 +1656,21 @@ void TestBlackbox::versionCheck_data() void TestBlackbox::versionScript() { - const SettingsPtr s = settings(); - Profile buildProfile(profileName(), s.get()); - QStringList toolchain = buildProfile.value("qbs.toolchain").toStringList(); - if (!toolchain.contains("gcc") || targetOs() != HostOsInfo::HostOsLinux) - QSKIP("version script test only applies to Linux"); QDir::setCurrent(testDataDir + "/versionscript"); - QCOMPARE(runQbs(QbsRunParameters(QStringList("-q") - << ("qbs.installRoot:" + QDir::currentPath()))), 0); + QCOMPARE(runQbs(QbsRunParameters("resolve", {"qbs.installRoot:" + QDir::currentPath()})), 0); + const bool isLinuxGcc = m_qbsStdout.contains("is gcc for Linux: true"); + const bool isNotLinuxGcc = m_qbsStdout.contains("is gcc for Linux: false"); + if (isNotLinuxGcc) + QSKIP("version script test only applies to Linux"); + QVERIFY(isLinuxGcc); + QCOMPARE(runQbs(QbsRunParameters(QStringList("-q"))), 0); const QString output = QString::fromLocal8Bit(m_qbsStderr); - QRegExp pattern(".*---(.*)---.*"); - QVERIFY2(pattern.exactMatch(output), qPrintable(output)); + const QRegularExpression pattern(QRegularExpression::anchoredPattern(".*---(.*)---.*"), + QRegularExpression::DotMatchesEverythingOption); + const QRegularExpressionMatch match = pattern.match(output); + QVERIFY2(match.hasMatch(), qPrintable(output)); QCOMPARE(pattern.captureCount(), 1); - const QString nmPath = pattern.capturedTexts().at(1); + const QString nmPath = match.captured(1); if (!QFile::exists(nmPath)) QSKIP("Cannot check for symbol presence: No nm found."); QProcess nm; @@ -1554,7 +1781,7 @@ void TestBlackbox::clean() QVERIFY(!QFile(appExeFilePath).exists()); QVERIFY(!QFile(depObjectFilePath).exists()); QVERIFY(!QFile(depLibFilePath).exists()); - for (const QString &symLink : qAsConst(symlinks)) + for (const QString &symLink : std::as_const(symlinks)) QVERIFY2(!symlinkExists(symLink), qPrintable(symLink)); // Remove all, with a forced re-resolve in between. @@ -1573,7 +1800,7 @@ void TestBlackbox::clean() QVERIFY(!QFile(appExeFilePath).exists()); QVERIFY(!QFile(depObjectFilePath).exists()); QVERIFY(!QFile(depLibFilePath).exists()); - for (const QString &symLink : qAsConst(symlinks)) + for (const QString &symLink : std::as_const(symlinks)) QVERIFY2(!symlinkExists(symLink), qPrintable(symLink)); // Dry run. @@ -1585,7 +1812,7 @@ void TestBlackbox::clean() QVERIFY(regularFileExists(appExeFilePath)); QVERIFY(regularFileExists(depObjectFilePath)); QVERIFY(regularFileExists(depLibFilePath)); - for (const QString &symLink : qAsConst(symlinks)) + for (const QString &symLink : std::as_const(symlinks)) QVERIFY2(symlinkExists(symLink), qPrintable(symLink)); // Product-wise, dependency only. @@ -1599,7 +1826,7 @@ void TestBlackbox::clean() QVERIFY(regularFileExists(appExeFilePath)); QVERIFY(!QFile(depObjectFilePath).exists()); QVERIFY(!QFile(depLibFilePath).exists()); - for (const QString &symLink : qAsConst(symlinks)) + for (const QString &symLink : std::as_const(symlinks)) QVERIFY2(!symlinkExists(symLink), qPrintable(symLink)); // Product-wise, dependent product only. @@ -1613,17 +1840,10 @@ void TestBlackbox::clean() QVERIFY(!QFile(appExeFilePath).exists()); QVERIFY(regularFileExists(depObjectFilePath)); QVERIFY(regularFileExists(depLibFilePath)); - for (const QString &symLink : qAsConst(symlinks)) + for (const QString &symLink : std::as_const(symlinks)) QVERIFY2(symlinkExists(symLink), qPrintable(symLink)); } -void TestBlackbox::concurrentExecutor() -{ - QDir::setCurrent(testDataDir + "/concurrent-executor"); - QCOMPARE(runQbs(QStringList() << "-j" << "2"), 0); - QVERIFY2(!m_qbsStderr.contains("ASSERT"), m_qbsStderr.constData()); -} - void TestBlackbox::conditionalExport() { QDir::setCurrent(testDataDir + "/conditional-export"); @@ -1657,6 +1877,9 @@ void TestBlackbox::conditionalFileTagger() void TestBlackbox::configure() { QDir::setCurrent(testDataDir + "/configure"); + QCOMPARE(runQbs({"resolve"}), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); QbsRunParameters params; params.command = "run"; QCOMPARE(runQbs(params), 0); @@ -1753,6 +1976,92 @@ void TestBlackbox::cxxLanguageVersion_data() std::make_pair(QString("msvc-new"), QString("/std:"))}); } +void TestBlackbox::conanfileProbe_data() +{ + QTest::addColumn<bool>("forceFailure"); + + QTest::newRow("success") << false; + QTest::newRow("failure") << true; +} + +void TestBlackbox::conanfileProbe() +{ + QFETCH(bool, forceFailure); + + if (qEnvironmentVariableIsSet("GITHUB_ACTIONS")) + QSKIP("Skip this test when running on GitHub"); + + QString executable = findExecutable({"conan"}); + if (executable.isEmpty()) + QSKIP("conan is not installed or not available in PATH."); + + // We first build a dummy package testlib and use that as dependency + // in the testapp package. + QDir::setCurrent(testDataDir + "/conanfile-probe/testlib"); + QStringList arguments { "create", "-o", "opt=True", "-s", "os=AIX", ".", + "testlib/1.2.3@qbs/testing" }; + QProcess conan; + conan.start(executable, arguments); + QVERIFY(waitForProcessSuccess(conan)); + + QDir::setCurrent(testDataDir + "/conanfile-probe/testapp"); + QCOMPARE(runQbs(QbsRunParameters("resolve", + {"--force-probe-execution", + QStringLiteral("projects.conanfile-probe-project.forceFailure:") + + (forceFailure ? "true" : "false")})), forceFailure ? 1 : 0); + + QFile file(relativeBuildDir() + "/results.json"); + QVERIFY(file.open(QIODevice::ReadOnly)); + QVariantMap actualResults = QJsonDocument::fromJson(file.readAll()).toVariant().toMap(); + const auto generatedFilesPath = actualResults.take("generatedFilesPath").toString(); + // We want to make sure that generatedFilesPath is under the project directory, + // but we don't care about the actual name. + QVERIFY(directoryExists(relativeBuildDir() + "/genconan/" + + QFileInfo(generatedFilesPath).baseName())); + + const QVariantMap expectedResults = { + { "json", "TESTLIB_ENV_VAL" }, + { "dependencies", QVariantList{"testlib1", "testlib2"} }, + }; + QCOMPARE(actualResults, expectedResults); +} + +void TestBlackbox::conflictingPropertyValues_data() +{ + QTest::addColumn<bool>("overrideInProduct"); + QTest::newRow("don't override in product") << false; + QTest::newRow("override in product") << true; +} + +void TestBlackbox::conflictingPropertyValues() +{ + QFETCH(bool, overrideInProduct); + + QDir::setCurrent(testDataDir + "/conflicting-property-values"); + if (overrideInProduct) + REPLACE_IN_FILE("conflicting-property-values.qbs", "// low.prop: name", "low.prop: name"); + else + REPLACE_IN_FILE("conflicting-property-values.qbs", "low.prop: name", "// low.prop: name"); + WAIT_FOR_NEW_TIMESTAMP(); + QCOMPARE(runQbs(QString("resolve")), 0); + if (overrideInProduct) { + // Binding in product itself overrides everything else, module-level conflicts + // are irrelevant. + QVERIFY2(m_qbsStdout.contains("final prop value: toplevel"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); + } else { + // Only the conflicts in the highest-level modules are reported, lower-level conflicts + // are irrelevant. + // prop2 does not cause a conflict, because the values are the same. + QVERIFY2(m_qbsStdout.contains("final prop value: highest"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStderr.contains("Conflicting scalar values for property 'prop'"), + m_qbsStderr.constData()); + QVERIFY2(m_qbsStderr.count("values.qbs") == 2, m_qbsStderr.constData()); + QVERIFY2(m_qbsStderr.contains("values.qbs:20:23"), m_qbsStderr.constData()); + QVERIFY2(m_qbsStderr.contains("values.qbs:30:23"), m_qbsStderr.constData()); + } +} + void TestBlackbox::cpuFeatures() { QDir::setCurrent(testDataDir + "/cpu-features"); @@ -1784,6 +2093,13 @@ void TestBlackbox::cpuFeatures() } } +void TestBlackbox::dateProperty() +{ + QDir::setCurrent(testDataDir + "/date-property"); + QCOMPARE(runQbs(), 0); + QVERIFY2(m_qbsStdout.contains("The stored date was 1999-12-31"), m_qbsStdout.constData()); +} + void TestBlackbox::renameDependency() { QDir::setCurrent(testDataDir + "/renameDependency"); @@ -1811,13 +2127,19 @@ void TestBlackbox::separateDebugInfo() const bool isWindows = m_qbsStdout.contains("is windows: yes"); const bool isNotWindows = m_qbsStdout.contains("is windows: no"); QVERIFY(isWindows != isNotWindows); + const bool isMacos = m_qbsStdout.contains("is macos: yes"); + const bool isNotMacos = m_qbsStdout.contains("is macos: no"); + QVERIFY(isMacos != isNotMacos); const bool isDarwin = m_qbsStdout.contains("is darwin: yes"); const bool isNotDarwin = m_qbsStdout.contains("is darwin: no"); QVERIFY(isDarwin != isNotDarwin); + const bool isGcc = m_qbsStdout.contains("is gcc: yes"); + const bool isNotGcc = m_qbsStdout.contains("is gcc: no"); + QVERIFY(isGcc != isNotGcc); + const bool isMsvc = m_qbsStdout.contains("is msvc: yes"); + const bool isNotMsvc = m_qbsStdout.contains("is msvc: no"); + QVERIFY(isMsvc != isNotMsvc); - const SettingsPtr s = settings(); - Profile buildProfile(profileName(), s.get()); - QStringList toolchain = buildProfile.value("qbs.toolchain").toStringList(); if (isDarwin) { QVERIFY(directoryExists(relativeProductBuildDir("app1") + "/app1.app.dSYM")); QVERIFY(regularFileExists(relativeProductBuildDir("app1") @@ -1829,8 +2151,13 @@ void TestBlackbox::separateDebugInfo() .entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).size(), 1); QVERIFY(!QFile::exists(relativeProductBuildDir("app2") + "/app2.app.dSYM")); QVERIFY(!QFile::exists(relativeProductBuildDir("app3") + "/app3.app.dSYM")); - QVERIFY(regularFileExists(relativeProductBuildDir("app3") - + "/app3.app/Contents/MacOS/app3.dwarf")); + if (isMacos) { + QVERIFY(regularFileExists(relativeProductBuildDir("app3") + + "/app3.app/Contents/MacOS/app3.dwarf")); + } else { + QVERIFY(regularFileExists(relativeProductBuildDir("app3") + + "/app3.app/app3.dwarf")); + } QVERIFY(directoryExists(relativeProductBuildDir("app4") + "/app4.dSYM")); QVERIFY(regularFileExists(relativeProductBuildDir("app4") + "/app4.dSYM/Contents/Info.plist")); @@ -1850,8 +2177,13 @@ void TestBlackbox::separateDebugInfo() .entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).size(), 1); QVERIFY(!QFile::exists(relativeProductBuildDir("foo2") + "/foo2.framework.dSYM")); QVERIFY(!QFile::exists(relativeProductBuildDir("foo3") + "/foo3.framework.dSYM")); - QVERIFY(regularFileExists(relativeProductBuildDir("foo3") - + "/foo3.framework/Versions/A/foo3.dwarf")); + if (isMacos) { + QVERIFY(regularFileExists(relativeProductBuildDir("foo3") + + "/foo3.framework/Versions/A/foo3.dwarf")); + } else { + QVERIFY(regularFileExists(relativeProductBuildDir("foo3") + + "/foo3.framework/foo3.dwarf")); + } QVERIFY(directoryExists(relativeProductBuildDir("foo4") + "/libfoo4.dylib.dSYM")); QVERIFY(regularFileExists(relativeProductBuildDir("foo4") + "/libfoo4.dylib.dSYM/Contents/Info.plist")); @@ -1871,8 +2203,13 @@ void TestBlackbox::separateDebugInfo() .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")); + if (isMacos) { + QVERIFY(regularFileExists(relativeProductBuildDir("bar3") + + "/bar3.bundle/Contents/MacOS/bar3.dwarf")); + } else { + QVERIFY(regularFileExists(relativeProductBuildDir("bar3") + + "/bar3.bundle/bar3.dwarf")); + } QVERIFY(directoryExists(relativeProductBuildDir("bar4") + "/bar4.bundle.dSYM")); QVERIFY(regularFileExists(relativeProductBuildDir("bar4") + "/bar4.bundle.dSYM/Contents/Info.plist")); @@ -1882,7 +2219,7 @@ void TestBlackbox::separateDebugInfo() + "/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")) { + } else if (isGcc) { const QString exeSuffix = isWindows ? ".exe" : ""; const QString dllPrefix = isWindows ? "" : "lib"; const QString dllSuffix = isWindows ? ".dll" : ".so"; @@ -1896,7 +2233,7 @@ void TestBlackbox::separateDebugInfo() + '/' + dllPrefix + "bar1" + dllSuffix + ".debug")); QVERIFY(!QFile::exists(relativeProductBuildDir("bar2") + '/' + dllPrefix + "bar2" + dllSuffix + ".debug")); - } else if (toolchain.contains("msvc")) { + } else if (isMsvc) { QVERIFY(QFile::exists(relativeProductBuildDir("app1") + "/app1.pdb")); QVERIFY(QFile::exists(relativeProductBuildDir("foo1") + "/foo1.pdb")); QVERIFY(QFile::exists(relativeProductBuildDir("bar1") + "/bar1.pdb")); @@ -1915,6 +2252,9 @@ void TestBlackbox::trackAddFile() QDir().mkdir("work"); ccp("before", "work"); QDir::setCurrent(testDataDir + "/trackAddFile/work"); + QCOMPARE(runQbs({"resolve"}), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); const QbsRunParameters runParams("run", QStringList{"-qp", "someapp"}); QCOMPARE(runQbs(runParams), 0); @@ -1950,6 +2290,9 @@ void TestBlackbox::trackExternalProductChanges() QVERIFY(!m_qbsStdout.contains("compiling jsFileChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling fileExists.cpp")); + const bool isGcc = m_qbsStdout.contains("is gcc: true"); + const bool isNotGcc = m_qbsStdout.contains("is gcc: false"); + QbsRunParameters params; params.environment.insert("QBS_TEST_PULL_IN_FILE_VIA_ENV", "1"); QCOMPARE(runQbs(params), 0); @@ -1999,13 +2342,12 @@ void TestBlackbox::trackExternalProductChanges() QVERIFY(!m_qbsStdout.contains("compiling jsFileChange.cpp")); QVERIFY(m_qbsStdout.contains("compiling fileExists.cpp")); + if (isNotGcc) + QSKIP("The remainder of this test requires a GCC-like toolchain"); + QVERIFY(isGcc); + rmDirR(relativeBuildDir()); - const SettingsPtr s = settings(); - const Profile profile(profileName(), s.get()); - const QStringList toolchainTypes = profile.value("qbs.toolchain").toStringList(); - if (!toolchainTypes.contains("gcc")) - QSKIP("Need GCC-like compiler to run this test"); - params.environment = QProcessEnvironment::systemEnvironment(); + params.environment = QbsRunParameters::defaultEnvironment(); params.environment.insert("INCLUDE_PATH_TEST", "1"); params.expectFailure = true; QVERIFY(runQbs(params) != 0); @@ -2044,6 +2386,9 @@ void TestBlackbox::trackRemoveFile() ccp("before", "work"); ccp("after", "work"); QDir::setCurrent(testDataDir + "/trackAddFile/work"); + QCOMPARE(runQbs({"resolve"}), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); const QbsRunParameters runParams("run", QStringList{"-qp", "someapp"}); QCOMPARE(runQbs(runParams), 0); output = m_qbsStdout.split('\n'); @@ -2088,6 +2433,9 @@ void TestBlackbox::trackAddFileTag() QDir().mkdir("work"); ccp("before", "work"); QDir::setCurrent(testDataDir + "/trackFileTags/work"); + QCOMPARE(runQbs({"resolve"}), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); const QbsRunParameters runParams("run", QStringList{"-qp", "someapp"}); QCOMPARE(runQbs(runParams), 0); output = m_qbsStdout.split('\n'); @@ -2112,6 +2460,9 @@ void TestBlackbox::trackRemoveFileTag() QDir().mkdir("work"); ccp("after", "work"); QDir::setCurrent(testDataDir + "/trackFileTags/work"); + QCOMPARE(runQbs({"resolve"}), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); const QbsRunParameters runParams("run", QStringList{"-qp", "someapp"}); QCOMPARE(runQbs(runParams), 0); @@ -2260,8 +2611,8 @@ void TestBlackbox::referenceErrorInExport() QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); - QVERIFY(m_qbsStderr.contains( - "referenceErrorInExport.qbs:15:12 ReferenceError: Can't find variable: includePaths")); + QVERIFY2(m_qbsStderr.contains("referenceErrorInExport.qbs:5:27 'includePaths' is not defined"), + m_qbsStderr.constData()); } void TestBlackbox::removeDuplicateLibraries_data() @@ -2288,20 +2639,21 @@ void TestBlackbox::removeDuplicateLibraries() void TestBlackbox::reproducibleBuild() { - const SettingsPtr s = settings(); - const Profile profile(profileName(), s.get()); - const QStringList toolchains = profile.value("qbs.toolchain").toStringList(); - if (!toolchains.contains("gcc") || toolchains.contains("clang")) - QSKIP("reproducible builds only supported for gcc"); - QFETCH(bool, reproducible); QDir::setCurrent(testDataDir + "/reproducible-build"); - QbsRunParameters params; + QbsRunParameters params("resolve"); params.arguments << QString("modules.cpp.enableReproducibleBuilds:") + (reproducible ? "true" : "false"); rmDirR(relativeBuildDir()); QCOMPARE(runQbs(params), 0); + const bool isGcc = m_qbsStdout.contains("is gcc: true"); + const bool isNotGcc = m_qbsStdout.contains("is gcc: false"); + if (isNotGcc) + QSKIP("reproducible builds only supported for gcc"); + QVERIFY(isGcc); + + QCOMPARE(runQbs(), 0); QFile object(relativeProductBuildDir("the product") + '/' + inputDirHash(".") + '/' + objectFileName("file1.cpp", profileName())); QVERIFY2(object.open(QIODevice::ReadOnly), qPrintable(object.fileName())); @@ -2309,6 +2661,7 @@ void TestBlackbox::reproducibleBuild() object.close(); QCOMPARE(runQbs(QbsRunParameters("clean")), 0); QVERIFY(!object.exists()); + params.command = "build"; QCOMPARE(runQbs(params), 0); if (reproducible) { QVERIFY(object.open(QIODevice::ReadOnly)); @@ -2329,6 +2682,9 @@ void TestBlackbox::reproducibleBuild_data() void TestBlackbox::responseFiles() { QDir::setCurrent(testDataDir + "/response-files"); + QCOMPARE(runQbs({"resolve"}), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); QbsRunParameters params; params.command = "install"; params.arguments << "--install-root" << "installed"; @@ -2367,6 +2723,32 @@ void TestBlackbox::retaggedOutputArtifact() QVERIFY2(!QFile::exists(a3), qPrintable(a3)); } +void TestBlackbox::rpathlinkDeduplication() +{ + QDir::setCurrent(testDataDir + "/rpathlink-deduplication"); + QbsRunParameters resolveParams{"resolve"}; + QCOMPARE(runQbs(resolveParams), 0); + const bool useRPathLink = m_qbsStdout.contains("useRPathLink: true"); + const bool dontUseRPathLink = m_qbsStdout.contains("useRPathLink: false"); + QVERIFY2(useRPathLink || dontUseRPathLink, m_qbsStdout); + if (dontUseRPathLink) + QSKIP("Only applies to toolchains that support rPathLink"); + const QString output = QString::fromLocal8Bit(m_qbsStdout); + const QRegularExpression pattern(QRegularExpression::anchoredPattern(".*===(.*)===.*"), + QRegularExpression::DotMatchesEverythingOption); + const QRegularExpressionMatch match = pattern.match(output); + QVERIFY2(match.hasMatch(), qPrintable(output)); + QCOMPARE(pattern.captureCount(), 1); + const QString linkFlag = match.captured(1); + + QbsRunParameters buildParams; + buildParams.arguments = QStringList({"--command-echo-mode", "command-line"}); + QCOMPARE(runQbs(buildParams), 0); + // private DynamicLibraryA is a dependency for 2 other libs but should only appear once + const auto libDir = QFileInfo(relativeProductBuildDir("DynamicLibraryA")).absoluteFilePath(); + QCOMPARE(m_qbsStdout.count((linkFlag + libDir).toUtf8()), 1); +} + void TestBlackbox::ruleConditions() { QDir::setCurrent(testDataDir + "/ruleConditions"); @@ -2444,11 +2826,60 @@ void TestBlackbox::ruleWithNonRequiredInputs() output = outFile.readAll(); QCOMPARE(output, QByteArray("(a.inp,b.inp,c.inp,)")); QCOMPARE(runQbs(), 0); - QVERIFY2(!m_qbsStdout.contains("Generating"), m_qbsStdout.constData()); + QVERIFY2(!m_qbsStdout.contains("generating"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("a.inp"); QCOMPARE(runQbs(), 0); - QVERIFY2(m_qbsStdout.contains("Generating"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("generating"), m_qbsStdout.constData()); +} + +void TestBlackbox::runMultiplexed() +{ + QDir::setCurrent(testDataDir + "/run-multiplexed"); + QCOMPARE(runQbs({"resolve"}), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); + + QbsRunParameters params("run"); + params.expectFailure = true; + QVERIFY(runQbs(params) != 0); + params.arguments = QStringList{"-p", "app"}; + QVERIFY(runQbs(params) != 0); + params.expectFailure = false; + params.arguments.last() = "app {\"buildVariant\":\"debug\"}"; + QCOMPARE(runQbs(params), 0); + params.arguments.last() = "app {\"buildVariant\":\"release\"}"; + QCOMPARE(runQbs(params), 0); +} + +void TestBlackbox::sanitizer_data() +{ + QTest::addColumn<QString>("sanitizer"); + QTest::newRow("none") << QString(); + QTest::newRow("address") << QStringLiteral("address"); + QTest::newRow("undefined") << QStringLiteral("undefined"); + QTest::newRow("thread") << QStringLiteral("thread"); +} + +void TestBlackbox::sanitizer() +{ + QFETCH(QString, sanitizer); + QDir::setCurrent(testDataDir + "/sanitizer"); + rmDirR(relativeBuildDir()); + QbsRunParameters params("build", {"--command-echo-mode", "command-line"}); + if (!sanitizer.isEmpty()) { + params.arguments.append( + {QStringLiteral("products.sanitizer.sanitizer:\"") + sanitizer + "\""}); + } + QCOMPARE(runQbs(params), 0); + if (m_qbsStdout.contains(QByteArrayLiteral("Compiler does not support sanitizer"))) + QSKIP("Compiler does not support the specified sanitizer"); + if (!sanitizer.isEmpty()) { + QVERIFY2(m_qbsStdout.contains(QByteArrayLiteral("fsanitize=") + sanitizer.toLatin1()), + qPrintable(m_qbsStdout)); + } else { + QVERIFY2(!m_qbsStdout.contains(QByteArrayLiteral("fsanitize=")), qPrintable(m_qbsStdout)); + } } void TestBlackbox::scannerItem() @@ -2469,6 +2900,47 @@ void TestBlackbox::scannerItem() QVERIFY2(m_qbsStdout.contains("handling file2.in"), m_qbsStdout.constData()); } +void TestBlackbox::scanResultInOtherProduct() +{ + QDir::setCurrent(testDataDir + "/scan-result-in-other-product"); + QCOMPARE(runQbs(QStringList("-vv")), 0); + QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("generating text file"), m_qbsStdout.constData()); + QVERIFY2(!m_qbsStderr.contains("The file dependency might get lost during change tracking"), + m_qbsStderr.constData()); + WAIT_FOR_NEW_TIMESTAMP(); + REPLACE_IN_FILE("other/other.qbs", "blubb", "blubb2"); + QCOMPARE(runQbs(), 0); + QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("generating text file"), m_qbsStdout.constData()); + WAIT_FOR_NEW_TIMESTAMP(); + touch("lib/lib.h"); + QCOMPARE(runQbs(), 0); + QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); + QVERIFY2(!m_qbsStdout.contains("generating text file"), m_qbsStdout.constData()); +} + +void TestBlackbox::scanResultInNonDependency() +{ + QDir::setCurrent(testDataDir + "/scan-result-in-non-dependency"); + QCOMPARE(runQbs(QStringList("-vv")), 0); + QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("generating text file"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStderr.contains("The file dependency might get lost during change tracking"), + m_qbsStderr.constData()); + WAIT_FOR_NEW_TIMESTAMP(); + REPLACE_IN_FILE("other/other.qbs", "blubb", "blubb2"); + QCOMPARE(runQbs(), 0); + QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("generating text file"), m_qbsStdout.constData()); + WAIT_FOR_NEW_TIMESTAMP(); + touch("lib/lib.h"); + QCOMPARE(runQbs(), 0); + QEXPECT_FAIL("", "QBS-1532", Continue); + QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); + QVERIFY2(!m_qbsStdout.contains("generating text file"), m_qbsStdout.constData()); +} + void TestBlackbox::setupBuildEnvironment() { QDir::setCurrent(testDataDir + "/setup-build-environment"); @@ -2486,6 +2958,8 @@ void TestBlackbox::setupRunEnvironment() { QDir::setCurrent(testDataDir + "/setup-run-environment"); QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); QbsRunParameters failParams("run", QStringList({"--setup-run-env-config", "ignore-lib-dependencies"})); failParams.expectFailure = true; @@ -2760,9 +3234,11 @@ void TestBlackbox::pathProbe_data() QTest::newRow("mult-files-mult-variants") << QString("mult-files-mult-variants.qbs") << true; QTest::newRow("single-file-suffixes") << QString("single-file-suffixes.qbs") << true; QTest::newRow("mult-files-suffixes") << QString("mult-files-suffixes.qbs") << true; + QTest::newRow("mult-files-common-suffixes") << QString("mult-files-common-suffixes.qbs") << true; QTest::newRow("mult-files-mult-suffixes") << QString("mult-files-mult-suffixes.qbs") << true; QTest::newRow("name-filter") << QString("name-filter.qbs") << true; QTest::newRow("candidate-filter") << QString("candidate-filter.qbs") << true; + QTest::newRow("environment-paths") << QString("environment-paths.qbs") << true; } void TestBlackbox::pathProbe() @@ -2774,23 +3250,41 @@ void TestBlackbox::pathProbe() QbsRunParameters buildParams("build", QStringList{"-f", projectFile}); buildParams.expectFailure = !successExpected; + buildParams.environment.insert("SEARCH_PATH", "usr/bin"); QCOMPARE(runQbs(buildParams) == 0, successExpected); + if (!successExpected) + QVERIFY2(m_qbsStderr.contains("Probe failed to find files"), m_qbsStderr); +} + +void TestBlackbox::pathListInProbe() +{ + QDir::setCurrent(testDataDir + "/path-list-in-probe"); + QCOMPARE(runQbs(), 0); } void TestBlackbox::pchChangeTracking() { QDir::setCurrent(testDataDir + "/pch-change-tracking"); - QCOMPARE(runQbs(), 0); + bool success = runQbs() == 0; + if (!success && m_qbsStderr.contains("mingw32_gt_pch_use_address")) + QSKIP("https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91440"); + QVERIFY(success); QVERIFY(m_qbsStdout.contains("precompiling pch.h (cpp)")); WAIT_FOR_NEW_TIMESTAMP(); touch("header1.h"); - QCOMPARE(runQbs(), 0); + success = runQbs() == 0; + if (!success && m_qbsStderr.contains("mingw32_gt_pch_use_address")) + QSKIP("https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91440"); + QVERIFY(success); QVERIFY(m_qbsStdout.contains("precompiling pch.h (cpp)")); QVERIFY(m_qbsStdout.contains("compiling header2.cpp")); QVERIFY(m_qbsStdout.contains("compiling main.cpp")); WAIT_FOR_NEW_TIMESTAMP(); touch("header2.h"); - QCOMPARE(runQbs(), 0); + success = runQbs() == 0; + if (!success && m_qbsStderr.contains("mingw32_gt_pch_use_address")) + QSKIP("https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91440"); + QVERIFY(success); QVERIFY2(!m_qbsStdout.contains("precompiling pch.h (cpp)"), m_qbsStdout.constData()); } @@ -2920,13 +3414,19 @@ void TestBlackbox::pluginDependency() void TestBlackbox::precompiledAndPrefixHeaders() { QDir::setCurrent(testDataDir + "/precompiled-and-prefix-headers"); - QCOMPARE(runQbs(), 0); + const bool success = runQbs() == 0; + if (!success && m_qbsStderr.contains("mingw32_gt_pch_use_address")) + QSKIP("https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91440"); + QVERIFY(success); } void TestBlackbox::precompiledHeaderAndRedefine() { QDir::setCurrent(testDataDir + "/precompiled-headers-and-redefine"); - QCOMPARE(runQbs(), 0); + const bool success = runQbs() == 0; + if (!success && m_qbsStderr.contains("mingw32_gt_pch_use_address")) + QSKIP("https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91440"); + QVERIFY(success); } void TestBlackbox::preventFloatingPointValues() @@ -3031,6 +3531,9 @@ void TestBlackbox::probeProperties() 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()); + QVERIFY2(m_qbsStdout.contains("probe3.fileName=tool"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("probe3.path=" + dir + "/bin"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("probe3.filePath=" + dir + "/bin/tool"), m_qbsStdout.constData()); } void TestBlackbox::probesAndShadowProducts() @@ -3053,7 +3556,7 @@ void TestBlackbox::probeInExportedModule() << QStringLiteral("probe-in-exported-module.qbs"))), 0); QVERIFY2(m_qbsStdout.contains("found: true"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("prop: yes"), m_qbsStdout.constData()); - QVERIFY2(m_qbsStdout.contains("listProp: my,myother"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("listProp: myother,my"), m_qbsStdout.constData()); } void TestBlackbox::probesAndArrayProperties() @@ -3075,13 +3578,6 @@ void TestBlackbox::productProperties() QVERIFY(regularFileExists(relativeExecutableFilePath("blubb_user"))); } -void TestBlackbox::propertyAssignmentOnNonPresentModule() -{ - QDir::setCurrent(testDataDir + "/property-assignment-on-non-present-module"); - QCOMPARE(runQbs(), 0); - QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); -} - void TestBlackbox::propertyAssignmentInFailedModule() { QDir::setCurrent(testDataDir + "/property-assignment-in-failed-module"); @@ -3091,7 +3587,7 @@ void TestBlackbox::propertyAssignmentInFailedModule() QVERIFY(runQbs(failParams) != 0); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("modules.m.doFail:true"))), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); - QEXPECT_FAIL(0, "circular dependency between module merging and validation", Continue); + failParams.expectFailure = false; QCOMPARE(runQbs(failParams), 0); } @@ -3109,9 +3605,9 @@ void TestBlackbox::propertyChanges() QVERIFY(m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(m_qbsStdout.contains("linking product 1.debug")); QVERIFY(m_qbsStdout.contains("generated.txt")); - QVERIFY(m_qbsStdout.contains("Making output from input")); + QVERIFY(m_qbsStdout.contains("making output from input")); QVERIFY(m_qbsStdout.contains("default value")); - QVERIFY(m_qbsStdout.contains("Making output from other output")); + QVERIFY(m_qbsStdout.contains("making output from other output")); QFile generatedFile(relativeProductBuildDir("generated text file") + "/generated.txt"); QVERIFY(generatedFile.open(QIODevice::ReadOnly)); QCOMPARE(generatedFile.readAll(), QByteArray("prefix 1contents 1suffix 1")); @@ -3125,8 +3621,8 @@ void TestBlackbox::propertyChanges() QVERIFY(!m_qbsStdout.contains("compiling lib.cpp.cpp")); QVERIFY(!m_qbsStdout.contains("linking")); QVERIFY(!m_qbsStdout.contains("generated.txt")); - QVERIFY(!m_qbsStdout.contains("Making output from input")); - QVERIFY(!m_qbsStdout.contains("Making output from other output")); + QVERIFY(!m_qbsStdout.contains("making output from input")); + QVERIFY(!m_qbsStdout.contains("making output from other output")); // Incremental build with no changes, but updated project file timestamp. WAIT_FOR_NEW_TIMESTAMP(); @@ -3138,8 +3634,8 @@ void TestBlackbox::propertyChanges() QVERIFY(!m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(!m_qbsStdout.contains("linking")); QVERIFY(!m_qbsStdout.contains("generated.txt")); - QVERIFY(!m_qbsStdout.contains("Making output from input")); - QVERIFY(!m_qbsStdout.contains("Making output from other output")); + QVERIFY(!m_qbsStdout.contains("making output from input")); + QVERIFY(!m_qbsStdout.contains("making output from other output")); // Incremental build, input property changed for first product WAIT_FOR_NEW_TIMESTAMP(); @@ -3151,8 +3647,8 @@ void TestBlackbox::propertyChanges() QVERIFY(!m_qbsStdout.contains("linking product 3")); QVERIFY(!m_qbsStdout.contains("linking library")); QVERIFY(!m_qbsStdout.contains("generated.txt")); - QVERIFY(!m_qbsStdout.contains("Making output from input")); - QVERIFY(!m_qbsStdout.contains("Making output from other output")); + QVERIFY(!m_qbsStdout.contains("making output from input")); + QVERIFY(!m_qbsStdout.contains("making output from other output")); // Incremental build, input property changed via project for second product. WAIT_FOR_NEW_TIMESTAMP(); @@ -3162,8 +3658,8 @@ void TestBlackbox::propertyChanges() QVERIFY(m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("linking product 3")); QVERIFY(!m_qbsStdout.contains("generated.txt")); - QVERIFY(!m_qbsStdout.contains("Making output from input")); - QVERIFY(!m_qbsStdout.contains("Making output from other output")); + QVERIFY(!m_qbsStdout.contains("making output from input")); + QVERIFY(!m_qbsStdout.contains("making output from other output")); // Incremental build, input property changed via command line for second product. params.command = "resolve"; @@ -3181,8 +3677,8 @@ void TestBlackbox::propertyChanges() QVERIFY(m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("linking product 3")); QVERIFY(!m_qbsStdout.contains("generated.txt")); - QVERIFY(!m_qbsStdout.contains("Making output from input")); - QVERIFY(!m_qbsStdout.contains("Making output from other output")); + QVERIFY(!m_qbsStdout.contains("making output from input")); + QVERIFY(!m_qbsStdout.contains("making output from other output")); // Incremental build, input property changed via environment for third product. params.environment.insert("QBS_BLACKBOX_DEFINE", "newvalue"); @@ -3197,8 +3693,8 @@ void TestBlackbox::propertyChanges() QVERIFY(!m_qbsStdout.contains("linking product 2")); QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("generated.txt")); - QVERIFY(!m_qbsStdout.contains("Making output from input")); - QVERIFY(!m_qbsStdout.contains("Making output from other output")); + QVERIFY(!m_qbsStdout.contains("making output from input")); + QVERIFY(!m_qbsStdout.contains("making output from other output")); params.environment.insert("QBS_BLACKBOX_DEFINE", "newvalue"); QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); @@ -3213,8 +3709,8 @@ void TestBlackbox::propertyChanges() QVERIFY(!m_qbsStdout.contains("linking product 2")); QVERIFY(m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("generated.txt")); - QVERIFY(!m_qbsStdout.contains("Making output from input")); - QVERIFY(!m_qbsStdout.contains("Making output from other output")); + QVERIFY(!m_qbsStdout.contains("making output from input")); + QVERIFY(!m_qbsStdout.contains("making output from other output")); // Incremental build, module property changed via command line. params.arguments << "qbs.enableDebugCode:false"; @@ -3234,8 +3730,8 @@ void TestBlackbox::propertyChanges() QVERIFY(m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("generated.txt")); - QVERIFY(!m_qbsStdout.contains("Making output from input")); - QVERIFY(!m_qbsStdout.contains("Making output from other output")); + QVERIFY(!m_qbsStdout.contains("making output from input")); + QVERIFY(!m_qbsStdout.contains("making output from other output")); // Incremental build, non-essential dependency removed. WAIT_FOR_NEW_TIMESTAMP(); @@ -3247,8 +3743,8 @@ void TestBlackbox::propertyChanges() QVERIFY(!m_qbsStdout.contains("linking product 3")); QVERIFY(!m_qbsStdout.contains("linking library")); QVERIFY(!m_qbsStdout.contains("generated.txt")); - QVERIFY(!m_qbsStdout.contains("Making output from input")); - QVERIFY(!m_qbsStdout.contains("Making output from other output")); + QVERIFY(!m_qbsStdout.contains("making output from input")); + QVERIFY(!m_qbsStdout.contains("making output from other output")); // Incremental build, prepare script of a transformer changed. WAIT_FOR_NEW_TIMESTAMP(); @@ -3259,8 +3755,8 @@ void TestBlackbox::propertyChanges() QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(m_qbsStdout.contains("generated.txt")); - QVERIFY(!m_qbsStdout.contains("Making output from input")); - QVERIFY(!m_qbsStdout.contains("Making output from other output")); + QVERIFY(!m_qbsStdout.contains("making output from input")); + QVERIFY(!m_qbsStdout.contains("making output from other output")); QVERIFY(generatedFile.open(QIODevice::ReadOnly)); QCOMPARE(generatedFile.readAll(), QByteArray("prefix 1contents 2suffix 1")); generatedFile.close(); @@ -3274,8 +3770,8 @@ void TestBlackbox::propertyChanges() QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(m_qbsStdout.contains("generated.txt")); - QVERIFY(!m_qbsStdout.contains("Making output from input")); - QVERIFY(!m_qbsStdout.contains("Making output from other output")); + QVERIFY(!m_qbsStdout.contains("making output from input")); + QVERIFY(!m_qbsStdout.contains("making output from other output")); QVERIFY(generatedFile.open(QIODevice::ReadOnly)); QCOMPARE(generatedFile.readAll(), QByteArray("prefix 2contents 2suffix 1")); generatedFile.close(); @@ -3289,8 +3785,8 @@ void TestBlackbox::propertyChanges() QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(m_qbsStdout.contains("generated.txt")); - QVERIFY(!m_qbsStdout.contains("Making output from input")); - QVERIFY(!m_qbsStdout.contains("Making output from other output")); + QVERIFY(!m_qbsStdout.contains("making output from input")); + QVERIFY(!m_qbsStdout.contains("making output from other output")); QVERIFY(generatedFile.open(QIODevice::ReadOnly)); QCOMPARE(generatedFile.readAll(), QByteArray("prefix 2contents 2suffix 2")); generatedFile.close(); @@ -3304,8 +3800,8 @@ void TestBlackbox::propertyChanges() QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(!m_qbsStdout.contains("generated.txt")); - QVERIFY(m_qbsStdout.contains("Making output from input")); - QVERIFY(m_qbsStdout.contains("Making output from other output")); + QVERIFY(m_qbsStdout.contains("making output from input")); + QVERIFY(m_qbsStdout.contains("making output from other output")); QVERIFY(m_qbsStdout.contains("new value")); // Incremental build, prepare script of a rule in a module changed. @@ -3318,22 +3814,31 @@ void TestBlackbox::propertyChanges() QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(!m_qbsStdout.contains("generated.txt")); - QVERIFY(m_qbsStdout.contains("Making output from input")); - QVERIFY(m_qbsStdout.contains("Making output from other output")); + QVERIFY(m_qbsStdout.contains("making output from input")); + QVERIFY(m_qbsStdout.contains("making output from other output")); +} + +void TestBlackbox::propertyEvaluationContext() +{ + const QString testDir = testDataDir + "/property-evaluation-context"; + QDir::setCurrent(testDir); + QCOMPARE(runQbs(), 0); + QCOMPARE(m_qbsStdout.count("base.productInBase evaluated in: myapp"), 1); + QCOMPARE(m_qbsStdout.count("base.productInTop evaluated in: myapp"), 1); + QCOMPARE(m_qbsStdout.count("top.productInExport evaluated in: mylib"), 1); + QCOMPARE(m_qbsStdout.count("top.productInTop evaluated in: myapp"), 1); } void TestBlackbox::qtBug51237() { - const QString profileName = "profile-qtBug51237"; - const QString propertyName = "mymodule.theProperty"; - { - const SettingsPtr s = settings(); - Profile profile(profileName, s.get()); - profile.setValue(propertyName, QStringList()); - } + const SettingsPtr s = settings(); + qbs::Internal::TemporaryProfile profile("qbs_autotests_qtBug51237", s.get()); + profile.p.setValue("mymodule.theProperty", QStringList()); + s->sync(); + QDir::setCurrent(testDataDir + "/QTBUG-51237"); QbsRunParameters params; - params.profile = profileName; + params.profile = profile.p.name(); QCOMPARE(runQbs(params), 0); } @@ -3406,6 +3911,42 @@ void TestBlackbox::dynamicRuleOutputs() QVERIFY(!QFile::exists(sourceFile2)); } +void TestBlackbox::emptyProfile() +{ + QDir::setCurrent(testDataDir + "/empty-profile"); + + const SettingsPtr s = settings(); + const qbs::Profile buildProfile(profileName(), s.get()); + bool isMsvc = false; + auto toolchainType = buildProfile.value(QStringLiteral("qbs.toolchainType")).toString(); + QbsRunParameters params; + params.profile = "none"; + + if (toolchainType.isEmpty()) { + const auto toolchain = buildProfile.value(QStringLiteral("qbs.toolchain")).toStringList(); + if (!toolchain.isEmpty()) + toolchainType = toolchain.first(); + } + if (!toolchainType.isEmpty()) { + params.arguments = QStringList{QStringLiteral("qbs.toolchainType:") + toolchainType}; + isMsvc = toolchainType == "msvc" || toolchainType == "clang-cl"; + } + + if (!isMsvc) { + const auto tcPath = + QDir::toNativeSeparators( + buildProfile.value(QStringLiteral("cpp.toolchainInstallPath")).toString()); + auto paths = params.environment.value(QStringLiteral("PATH")) + .split(HostOsInfo::pathListSeparator(), Qt::SkipEmptyParts); + if (!tcPath.isEmpty() && !paths.contains(tcPath)) { + paths.prepend(tcPath); + params.environment.insert( + QStringLiteral("PATH"), paths.join(HostOsInfo::pathListSeparator())); + } + } + QCOMPARE(runQbs(params), 0); +} + void TestBlackbox::erroneousFiles_data() { QTest::addColumn<QString>("errorMessage"); @@ -3433,7 +3974,7 @@ void TestBlackbox::erroneousFiles() params.expectFailure = true; QVERIFY(runQbs(params) != 0); QString err = QString::fromLocal8Bit(m_qbsStderr); - if (!err.contains(QRegExp(errorMessage))) { + if (!err.contains(QRegularExpression(errorMessage))) { qDebug().noquote() << "Output: " << err; qDebug().noquote() << "Expected: " << errorMessage; QFAIL("Unexpected error message."); @@ -3496,13 +4037,16 @@ void TestBlackbox::errorInfo() void TestBlackbox::escapedLinkerFlags() { - const SettingsPtr s = settings(); - const Profile buildProfile(profileName(), s.get()); - const QStringList toolchain = buildProfile.value("qbs.toolchain").toStringList(); - if (!toolchain.contains("gcc") || targetOs() == HostOsInfo::HostOsMacos) - QSKIP("escaped linker flags test only applies with gcc and GNU ld"); QDir::setCurrent(testDataDir + "/escaped-linker-flags"); - QbsRunParameters params(QStringList("products.app.escapeLinkerFlags:false")); + QbsRunParameters params("resolve", QStringList("products.app.escapeLinkerFlags:false")); + QCOMPARE(runQbs(params), 0); + const bool isGcc = m_qbsStdout.contains("is gcc: true"); + const bool isNotGcc = m_qbsStdout.contains("is gcc: false"); + if (isNotGcc) + QSKIP("escaped linker flags test only applies on plain unix with gcc and GNU ld"); + QVERIFY(isGcc); + + params.command = "build"; QCOMPARE(runQbs(params), 0); params.command = "resolve"; params.arguments = QStringList() << "products.app.escapeLinkerFlags:true"; @@ -3559,26 +4103,24 @@ void TestBlackbox::exportedPropertyInDisabledProduct_data() void TestBlackbox::systemRunPaths() { - const SettingsPtr s = settings(); - const Profile buildProfile(profileName(), s.get()); - switch (targetOs()) { - case HostOsInfo::HostOsLinux: - case HostOsInfo::HostOsMacos: - case HostOsInfo::HostOsOtherUnix: - break; - default: - QSKIP("only applies on Unix"); - } - const QString lddFilePath = findExecutable(QStringList() << "ldd"); if (lddFilePath.isEmpty()) QSKIP("ldd not found"); + QDir::setCurrent(testDataDir + "/system-run-paths"); QFETCH(bool, setRunPaths); rmDirR(relativeBuildDir()); - QbsRunParameters params; + QbsRunParameters params("resolve"); params.arguments << QString("project.setRunPaths:") + (setRunPaths ? "true" : "false"); QCOMPARE(runQbs(params), 0); + const bool isUnix = m_qbsStdout.contains("is unix: true"); + const bool isNotUnix = m_qbsStdout.contains("is unix: false"); + if (isNotUnix) + QSKIP("only applies on Unix"); + QVERIFY(isUnix); + + params.command = "build"; + QCOMPARE(runQbs(params), 0); QProcess ldd; ldd.start(lddFilePath, QStringList() << relativeExecutableFilePath("app")); QVERIFY2(ldd.waitForStarted(), qPrintable(ldd.errorString())); @@ -3615,7 +4157,7 @@ void TestBlackbox::exportRule() params.expectFailure = false; QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); - QVERIFY2(m_qbsStdout.contains("Creating C++ source file"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("creating C++ source file"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("compiling myapp.cpp"), m_qbsStdout.constData()); } @@ -3629,12 +4171,88 @@ void TestBlackbox::exportToOutsideSearchPath() m_qbsStderr.constData()); } +void TestBlackbox::exportsCMake() +{ + QFETCH(QStringList, arguments); + + QDir::setCurrent(testDataDir + "/exports-cmake"); + rmDirR(relativeBuildDir()); + QbsRunParameters findCMakeParams("resolve", {"-f", "find-cmake.qbs"}); + QCOMPARE(runQbs(findCMakeParams), 0); + const QString output = QString::fromLocal8Bit(m_qbsStdout); + const QRegularExpression pattern( + QRegularExpression::anchoredPattern(".*---(.*)---.*"), + QRegularExpression::DotMatchesEverythingOption); + const QRegularExpressionMatch match = pattern.match(output); + QVERIFY2(match.hasMatch(), qPrintable(output)); + QCOMPARE(pattern.captureCount(), 1); + const QString jsonString = match.captured(1); + const QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonString.toUtf8()); + const QJsonObject jsonData = jsonDoc.object(); + + rmDirR(relativeBuildDir()); + const QStringList exporterArgs{"-f", "exports-cmake.qbs"}; + QbsRunParameters exporterRunParams("build", exporterArgs); + exporterRunParams.arguments << arguments; + QCOMPARE(runQbs(exporterRunParams), 0); + + if (!jsonData.value(u"cmakeFound").toBool()) { + QSKIP("cmake is not installed"); + return; + } + + if (jsonData.value(u"crossCompiling").toBool()) { + QSKIP("test is not applicable with cross-compile toolchains"); + return; + } + + const auto cmakeFilePath = jsonData.value(u"cmakeFilePath").toString(); + QVERIFY(!cmakeFilePath.isEmpty()); + + const auto generator = jsonData.value(u"generator").toString(); + if (generator.isEmpty()) { + QSKIP("cannot detect cmake generator"); + return; + } + + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + const auto buildEnv = jsonData.value(u"buildEnv").toObject(); + for (auto it = buildEnv.begin(), end = buildEnv.end(); it != end; ++it) { + env.insert(it.key(), it.value().toString()); + } + + const auto installPrefix = jsonData.value(u"installPrefix").toString(); + const auto cmakePrefixPath = QFileInfo(relativeBuildDir()).absoluteFilePath() + "/install-root/" + + installPrefix + "/lib/cmake"; + const auto sourceDirectory = testDataDir + "/exports-cmake/cmake"; + QProcess configure; + configure.setProcessEnvironment(env); + configure.setWorkingDirectory(sourceDirectory); + configure.start( + cmakeFilePath, {".", "-DCMAKE_PREFIX_PATH=" + cmakePrefixPath, "-G" + generator}); + QVERIFY(waitForProcessSuccess(configure, 120000)); + + QProcess build; + build.setProcessEnvironment(env); + build.setWorkingDirectory(sourceDirectory); + build.start(cmakeFilePath, QStringList{"--build", "."}); + QVERIFY(waitForProcessSuccess(build)); +} + +void TestBlackbox::exportsCMake_data() +{ + QTest::addColumn<QStringList>("arguments"); + QTest::newRow("dynamic lib") << QStringList("project.isStatic: false"); + QTest::newRow("static lib") << QStringList("project.isStatic: true"); + QTest::newRow("framework") << QStringList("project.isBundle: true"); +} + void TestBlackbox::exportsPkgconfig() { QDir::setCurrent(testDataDir + "/exports-pkgconfig"); QCOMPARE(runQbs(), 0); - QVERIFY2(m_qbsStdout.contains("Creating TheFirstLib.pc"), m_qbsStdout.constData()); - QVERIFY2(m_qbsStdout.contains("Creating TheSecondLib.pc"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("creating TheFirstLib.pc"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("creating TheSecondLib.pc"), m_qbsStdout.constData()); QFile sourcePcFile(HostOsInfo::isWindowsHost() ? "TheFirstLib_windows.pc" : "TheFirstLib.pc"); QString generatedPcFilePath = relativeProductBuildDir("TheFirstLib") + "/TheFirstLib.pc"; QFile generatedPcFile(generatedPcFilePath); @@ -3649,14 +4267,17 @@ void TestBlackbox::exportsPkgconfig() touch("firstlib.cpp"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("linking"), m_qbsStdout.constData()); - QVERIFY2(!m_qbsStdout.contains("Creating TheFirstLib.pc"), m_qbsStdout.constData()); - QVERIFY2(!m_qbsStdout.contains("Creating TheSecondLib.pc"), m_qbsStdout.constData()); + QVERIFY2(!m_qbsStdout.contains("creating TheFirstLib.pc"), m_qbsStdout.constData()); + QVERIFY2(!m_qbsStdout.contains("creating TheSecondLib.pc"), m_qbsStdout.constData()); } void TestBlackbox::exportsQbs() { QDir::setCurrent(testDataDir + "/exports-qbs"); + QCOMPARE(runQbs({"resolve", {"-f", "exports-qbs.qbs"}}), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); // First we build exportable products and use them (as products) inside // the original project. QCOMPARE(runQbs(QStringList{"-f", "exports-qbs.qbs", "--command-echo-mode", "command-line"}), @@ -3679,11 +4300,12 @@ void TestBlackbox::exportsQbs() // Trying to build with an unsupported build variant must fail. paramsExternalBuild.arguments = QStringList{"-f", "consumer.qbs", - "modules.qbs.buildVariant:unknown"}; + "modules.qbs.buildVariant:profiling"}; paramsExternalBuild.buildDirectory = QDir::currentPath() + "/external-consumer-profile"; paramsExternalBuild.expectFailure = true; QVERIFY(runQbs(paramsExternalBuild) != 0); - QVERIFY2(m_qbsStderr.contains("MyLib could not be loaded"), m_qbsStderr.constData()); + QVERIFY2(m_qbsStderr.contains("Dependency 'MyLib' not found for product 'consumer'"), + m_qbsStderr.constData()); // Removing the condition from the generated module leaves us with two conflicting // candidates. @@ -3697,19 +4319,19 @@ void TestBlackbox::exportsQbs() // Change tracking for accesses to product.exports (negative). QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList{"-f", "exports-qbs.qbs"})), 0); QCOMPARE(runQbs(), 0); - QVERIFY2(m_qbsStdout.contains("Creating MyTool.qbs"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("creating MyTool.qbs"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("exports-qbs.qbs"); QCOMPARE(runQbs(QStringList({"-p", "MyTool"})), 0); - QVERIFY2(!m_qbsStdout.contains("Creating MyTool.qbs"), m_qbsStdout.constData()); + QVERIFY2(!m_qbsStdout.contains("creating MyTool.qbs"), m_qbsStdout.constData()); // Rebuilding the target binary should not cause recreating the module file. WAIT_FOR_NEW_TIMESTAMP(); touch("mylib.cpp"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.count("linking") >= 2, m_qbsStdout.constData()); - QVERIFY2(!m_qbsStdout.contains("Creating MyLib"), m_qbsStdout.constData()); - QVERIFY2(!m_qbsStdout.contains("Creating MyTool.qbs"), m_qbsStdout.constData()); + QVERIFY2(!m_qbsStdout.contains("creating MyLib"), m_qbsStdout.constData()); + QVERIFY2(!m_qbsStdout.contains("creating MyTool.qbs"), m_qbsStdout.constData()); // Changing a setting that influences the name of a target artifact should cause // recreating the module file. @@ -3718,14 +4340,14 @@ void TestBlackbox::exportsQbs() QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.count("linking") >= 2, m_qbsStdout.constData()); - QVERIFY2(m_qbsStdout.count("Creating MyLib") == 2, m_qbsStdout.constData()); - QVERIFY2(!m_qbsStdout.contains("Creating MyTool.qbs"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.count("creating MyLib") == 2, m_qbsStdout.constData()); + QVERIFY2(!m_qbsStdout.contains("creating MyTool.qbs"), m_qbsStdout.constData()); // Change tracking for accesses to product.exports (positive). WAIT_FOR_NEW_TIMESTAMP(); - REPLACE_IN_FILE("tool.qbs", "product.toolTags", "[]"); + REPLACE_IN_FILE("tool.qbs", "exportingProduct.toolTags", "[]"); QCOMPARE(runQbs(QStringList({"-p", "MyTool"})), 0); - QVERIFY2(m_qbsStdout.contains("Creating MyTool.qbs"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("creating MyTool.qbs"), m_qbsStdout.constData()); } void TestBlackbox::externalLibs() @@ -3787,6 +4409,77 @@ void TestBlackbox::fileTagsFilterMerging() QVERIFY2(QFile::exists(otherOutput), qPrintable(otherOutput)); } +void TestBlackbox::flatbuf() +{ + QFETCH(QString, projectFile); + + QDir::setCurrent(testDataDir + "/flatbuf"); + + rmDirR(relativeBuildDir()); + if (!prepareAndRunConan()) + QSKIP("conan is not prepared, check messages above"); + + QbsRunParameters resolveParams( + "resolve", QStringList{"-f", projectFile, "moduleProviders.conan.installDirectory:build"}); + QCOMPARE(runQbs(resolveParams), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); + const bool withFlatbuffers = m_qbsStdout.contains("has flatbuffers: true"); + const bool withoutFlatbuffers = m_qbsStdout.contains("has flatbuffers: false"); + QVERIFY2(withFlatbuffers || withoutFlatbuffers, m_qbsStdout.constData()); + if (withoutFlatbuffers) + QSKIP("flatbuf module not present"); + QbsRunParameters runParams("run"); + QCOMPARE(runQbs(runParams), 0); +} + +void TestBlackbox::flatbuf_data() +{ + QTest::addColumn<QString>("projectFile"); + + // QTest::newRow("c") << QString("flat_c.qbs"); + QTest::newRow("cpp") << QString("flat_cpp.qbs"); + QTest::newRow("relative import") << QString("flat_relative_import.qbs"); + QTest::newRow("absolute import") << QString("flat_absolute_import.qbs"); + QTest::newRow("filename suffix") << QString("flat_filename_suffix.qbs"); + QTest::newRow("filename extension") << QString("flat_filename_extension.qbs"); + QTest::newRow("keep prefix") << QString("flat_keep_prefix.qbs"); +} + +void TestBlackbox::freedesktop() +{ + if (!HostOsInfo::isAnyUnixHost()) + QSKIP("only applies on Unix"); + if (HostOsInfo::isMacosHost()) + QSKIP("Does not apply on macOS"); + QDir::setCurrent(testDataDir + "/freedesktop"); + QCOMPARE(runQbs(), 0); + + // Check desktop file + QString desktopFilePath = + defaultInstallRoot + "/usr/local/share/applications/myapp.desktop"; + QVERIFY(QFile::exists(desktopFilePath)); + QFile desktopFile(desktopFilePath); + QVERIFY2(desktopFile.open(QIODevice::ReadOnly), qPrintable(desktopFile.errorString())); + QByteArrayList lines = desktopFile.readAll().split('\n'); + // Automatically filled line: + QVERIFY(lines.contains("Exec=main")); + // Name specified in `freedesktop.name` property + QVERIFY(lines.contains("Name=My App")); + // Overridden line: + QVERIFY(lines.contains("Icon=myapp.png")); + // Untouched line: + QVERIFY(lines.contains("Terminal=false")); + + // Check AppStream file + QVERIFY(QFile::exists(defaultInstallRoot + + "/usr/local/share/metainfo/myapp.appdata.xml")); + + // Check icon file + QVERIFY(QFile::exists(defaultInstallRoot + + "/usr/local/share/icons/hicolor/scalable/apps/myapp.png")); +} + void TestBlackbox::installedTransformerOutput() { QDir::setCurrent(testDataDir + "/installed-transformer-output"); @@ -3800,8 +4493,16 @@ void TestBlackbox::installLocations_data() QTest::addColumn<QString>("binDir"); QTest::addColumn<QString>("dllDir"); QTest::addColumn<QString>("libDir"); - QTest::newRow("explicit values") << QString("bindir") << QString("dlldir") << QString("libdir"); - QTest::newRow("default values") << QString() << QString() << QString(); + QTest::addColumn<QString>("pluginDir"); + QTest::addColumn<QString>("dsymDir"); + QTest::newRow("explicit values") + << QString("bindir") + << QString("dlldir") + << QString("libdir") + << QString("pluginDir") + << QString("dsymDir"); + QTest::newRow("default values") + << QString() << QString() << QString() << QString() << QString(); } void TestBlackbox::installLocations() @@ -3810,6 +4511,8 @@ void TestBlackbox::installLocations() QFETCH(QString, binDir); QFETCH(QString, dllDir); QFETCH(QString, libDir); + QFETCH(QString, pluginDir); + QFETCH(QString, dsymDir); QbsRunParameters params("resolve"); if (!binDir.isEmpty()) params.arguments.push_back("products.theapp.installDir:" + binDir); @@ -3817,35 +4520,98 @@ void TestBlackbox::installLocations() params.arguments.push_back("products.thelib.installDir:" + dllDir); if (!libDir.isEmpty()) params.arguments.push_back("products.thelib.importLibInstallDir:" + libDir); + if (!pluginDir.isEmpty()) + params.arguments.push_back("products.theplugin.installDir:" + pluginDir); + if (!dsymDir.isEmpty()) { + params.arguments.push_back("products.theapp.debugInformationInstallDir:" + dsymDir); + params.arguments.push_back("products.thelib.debugInformationInstallDir:" + dsymDir); + params.arguments.push_back("products.theplugin.debugInformationInstallDir:" + dsymDir); + } QCOMPARE(runQbs(params), 0); const bool isWindows = m_qbsStdout.contains("is windows"); + const bool isDarwin = m_qbsStdout.contains("is darwin"); const bool isMac = m_qbsStdout.contains("is mac"); const bool isUnix = m_qbsStdout.contains("is unix"); - QVERIFY(isWindows || isMac || isUnix); + const bool isMingw = m_qbsStdout.contains("is mingw"); + QVERIFY(isWindows || isDarwin || isUnix); QCOMPARE(runQbs(QbsRunParameters(QStringList("--clean-install-root"))), 0); - const QString dllFileName = isWindows ? "thelib.dll" : isMac ? "thelib" : "libthelib.so"; - const QString appFileName = isWindows ? "theapp.exe" : "theapp"; - if (binDir.isEmpty()) - binDir = isMac ? "/Applications" : "/bin"; - if (dllDir.isEmpty()) - dllDir = isMac ? "/Library/Frameworks" : isWindows ? "/bin" : "/lib"; - if (libDir.isEmpty()) - libDir = "/lib"; - if (isMac) { - binDir += "/theapp.app/Contents/MacOS"; - dllDir += "/thelib.framework"; - } + + struct BinaryInfo + { + QString fileName; + QString installDir; + QString subDir; + + QString absolutePath(const QString &prefix) const + { + return QDir::cleanPath(prefix + '/' + installDir + '/' + subDir + '/' + fileName); + } + }; + + const BinaryInfo dll = { + isWindows ? "thelib.dll" : isDarwin ? "thelib" : "libthelib.so", + dllDir.isEmpty() + ? (isDarwin ? "/Library/Frameworks" : (isWindows ? "/bin" : "/lib")) + : dllDir, + isDarwin ? "thelib.framework" : "" + }; + const BinaryInfo dllDsym = { + isWindows + ? (!isMingw ? "thelib.pdb" : "thelib.dll.debug") + : isDarwin ? "thelib.framework.dSYM" : "libthelib.so.debug", + dsymDir.isEmpty() ? dll.installDir : dsymDir, + {} + }; + const BinaryInfo plugin = { + isWindows ? "theplugin.dll" : isDarwin ? "theplugin" : "libtheplugin.so", + pluginDir.isEmpty() ? dll.installDir : pluginDir, + isDarwin ? (isMac ? "theplugin.bundle/Contents/MacOS" : "theplugin.bundle") : "" + }; + const BinaryInfo pluginDsym = { + isWindows + ? (!isMingw ? "theplugin.pdb" : "theplugin.dll.debug") + : isDarwin ? "theplugin.bundle.dSYM" : "libtheplugin.so.debug", + dsymDir.isEmpty() ? plugin.installDir : dsymDir, + {} + }; + const BinaryInfo app = { + isWindows ? "theapp.exe" : "theapp", + binDir.isEmpty() ? (isDarwin ? "/Applications" : "/bin") : binDir, + isDarwin ? (isMac ? "theapp.app/Contents/MacOS" : "theapp.app") : "" + }; + const BinaryInfo appDsym = { + isWindows + ? (!isMingw ? "theapp.pdb" : "theapp.exe.debug") + : isDarwin ? "theapp.app.dSYM" : "theapp.debug", + dsymDir.isEmpty() ? app.installDir : dsymDir, + {} + }; + const QString installRoot = QDir::currentPath() + "/default/install-root"; const QString installPrefix = isWindows ? QString() : "/usr/local"; const QString fullInstallPrefix = installRoot + '/' + installPrefix + '/'; - const QString appFilePath = fullInstallPrefix + binDir + '/' + appFileName; + const QString appFilePath = app.absolutePath(fullInstallPrefix); QVERIFY2(QFile::exists(appFilePath), qPrintable(appFilePath)); - const QString dllFilePath = fullInstallPrefix + dllDir + '/' + dllFileName; + const QString dllFilePath = dll.absolutePath(fullInstallPrefix); QVERIFY2(QFile::exists(dllFilePath), qPrintable(dllFilePath)); if (isWindows) { - const QString libFilePath = fullInstallPrefix + libDir + "/thelib.lib"; + const BinaryInfo lib = { + "thelib.lib", + libDir.isEmpty() ? "/lib" : libDir, + "" + }; + const QString libFilePath = lib.absolutePath(fullInstallPrefix); QVERIFY2(QFile::exists(libFilePath), qPrintable(libFilePath)); } + const QString pluginFilePath = plugin.absolutePath(fullInstallPrefix); + QVERIFY2(QFile::exists(pluginFilePath), qPrintable(pluginFilePath)); + + const QString appDsymFilePath = appDsym.absolutePath(fullInstallPrefix); + QVERIFY2(QFileInfo(appDsymFilePath).exists(), qPrintable(appDsymFilePath)); + const QString dllDsymFilePath = dllDsym.absolutePath(fullInstallPrefix); + QVERIFY2(QFileInfo(dllDsymFilePath).exists(), qPrintable(dllDsymFilePath)); + const QString pluginDsymFilePath = pluginDsym.absolutePath(fullInstallPrefix); + QVERIFY2(QFile::exists(pluginDsymFilePath), qPrintable(pluginDsymFilePath)); } void TestBlackbox::inputsFromDependencies() @@ -3887,7 +4653,7 @@ void TestBlackbox::installPackage() cleanOutputLines.push_back(trimmedLine); } QCOMPARE(cleanOutputLines.size(), 3); - for (const QByteArray &line : qAsConst(cleanOutputLines)) { + for (const QByteArray &line : std::as_const(cleanOutputLines)) { QVERIFY2(line.contains("public_tool") || line.contains("mylib") || line.contains("lib.h"), line.constData()); } @@ -3915,6 +4681,9 @@ void TestBlackbox::installable() void TestBlackbox::installableAsAuxiliaryInput() { QDir::setCurrent(testDataDir + "/installable-as-auxiliary-input"); + QCOMPARE(runQbs({"resolve"}), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); QCOMPARE(runQbs(QbsRunParameters("run")), 0); QVERIFY2(m_qbsStdout.contains("f-impl"), m_qbsStdout.constData()); } @@ -3931,6 +4700,33 @@ void TestBlackbox::installTree() QVERIFY(QFile::exists(installRoot + "content/subdir2/baz.txt")); } +void TestBlackbox::invalidArtifactPath_data() +{ + QTest::addColumn<QString>("baseDir"); + QTest::addColumn<bool>("isValid"); + + QTest::newRow("inside, normal case") << "subdir" << true; + QTest::newRow("inside, build dir 1") << "project.buildDirectory" << true; + QTest::newRow("inside, build dir 2") << "subdir/.." << true; + QTest::newRow("outside, absolute") << "/tmp" << false; + QTest::newRow("outside, relative 1") << "../../" << false; + QTest::newRow("outside, relative 2") << "subdir/../../.." << false; +} + +void TestBlackbox::invalidArtifactPath() +{ + QFETCH(QString, baseDir); + QFETCH(bool, isValid); + + rmDirR(relativeBuildDir()); + QDir::setCurrent(testDataDir + "/invalid-artifact-path"); + QbsRunParameters params(QStringList("project.artifactDir:" + baseDir)); + params.expectFailure = !isValid; + QCOMPARE(runQbs(params) == 0, isValid); + if (!isValid) + QVERIFY2(m_qbsStderr.contains("outside of build directory"), m_qbsStderr.constData()); +} + void TestBlackbox::invalidCommandProperty_data() { QTest::addColumn<QString>("errorType"); @@ -3961,7 +4757,7 @@ void TestBlackbox::invalidLibraryNames() QbsRunParameters params(QStringList("project.valueIndex:" + index)); params.expectFailure = !success; QCOMPARE(runQbs(params) == 0, success); - for (const QString &diag : qAsConst(diagnostics)) + for (const QString &diag : std::as_const(diagnostics)) QVERIFY2(m_qbsStderr.contains(diag.toLocal8Bit()), m_qbsStderr.constData()); } @@ -4022,8 +4818,8 @@ void TestBlackbox::cli() QCOMPARE(status, 0); const SettingsPtr s = settings(); - Profile p("qbs_autotests-cli", s.get()); - const QStringList toolchain = p.value("qbs.toolchain").toStringList(); + qbs::Profile p("qbs_autotests-cli", s.get()); + const QStringList toolchain = profileToolchain(p); if (!p.exists() || !(toolchain.contains("dotnet") || toolchain.contains("mono"))) QSKIP("No suitable Common Language Infrastructure test profile"); @@ -4114,7 +4910,7 @@ void TestBlackbox::jsExtensionsFileInfo() QVERIFY(output.exists()); QVERIFY(output.open(QIODevice::ReadOnly)); const QList<QByteArray> lines = output.readAll().trimmed().split('\n'); - QCOMPARE(lines.size(), 26); + QCOMPARE(lines.size(), 28); int i = 0; QCOMPARE(lines.at(i++).trimmed().constData(), "blubb"); QCOMPARE(lines.at(i++).trimmed().constData(), qUtf8Printable( @@ -4143,11 +4939,52 @@ void TestBlackbox::jsExtensionsFileInfo() QCOMPARE(lines.at(i++).trimmed().constData(), "../blubb.tar.gz"); QCOMPARE(lines.at(i++).trimmed().constData(), "\\tmp\\blubb.tar.gz"); QCOMPARE(lines.at(i++).trimmed().constData(), "c:\\tmp\\blubb.tar.gz"); + QCOMPARE(lines.at(i++).trimmed().constData(), qUtf8Printable(HostOsInfo::pathListSeparator())); + QCOMPARE(lines.at(i++).trimmed().constData(), qUtf8Printable(HostOsInfo::pathSeparator())); +} + +void TestBlackbox::jsExtensionsHost() +{ + QDir::setCurrent(testDataDir + "//jsextensions-host"); + QbsRunParameters params(QStringList { "-f", "host.qbs" }); + QCOMPARE(runQbs(params), 0); + QFile output("output.txt"); + QVERIFY(output.exists()); + QVERIFY(output.open(QIODevice::ReadOnly)); + const QList<QByteArray> lines = output.readAll().trimmed().split('\n'); + QCOMPARE(lines.size(), 10); + int i = 0; + QCOMPARE(lines.at(i++).trimmed().constData(), "architecture: " + + HostOsInfo::hostOSArchitecture()); + QStringList list; + for (const auto &s : HostOsInfo::canonicalOSIdentifiers(HostOsInfo::hostOSIdentifier())) + list.push_back(s); + QCOMPARE(lines.at(i++).trimmed().constData(), "os: " + list.join(',')); + QCOMPARE(lines.at(i++).trimmed().constData(), "platform: " + HostOsInfo::hostOSIdentifier()); + QCOMPARE(lines.at(i++).trimmed().constData(), "osVersion: " + + HostOsInfo::hostOsVersion().toString()); + QCOMPARE(lines.at(i++).trimmed().constData(), "osBuildVersion: " + + (HostOsInfo::hostOsBuildVersion().isNull() ? "undefined" : + HostOsInfo::hostOsBuildVersion())); + QCOMPARE(lines.at(i++).trimmed().constData(), "osVersionParts: " + + HostOsInfo::hostOsVersion().toString(',')); + QCOMPARE(lines.at(i++).trimmed().constData(), "osVersionMajor: " + QString::number( + HostOsInfo::hostOsVersion().majorVersion())); + QCOMPARE(lines.at(i++).trimmed().constData(), "osVersionMinor: " + QString::number( + HostOsInfo::hostOsVersion().minorVersion())); + QCOMPARE(lines.at(i++).trimmed().constData(), "osVersionPatch: " + QString::number( + HostOsInfo::hostOsVersion().patchLevel())); + QString nullDevice = HostOsInfo::isWindowsHost() ? QStringLiteral("NUL") : + QStringLiteral("/dev/null"); + QCOMPARE(lines.at(i++).trimmed().constData(), "nullDevice: " + nullDevice); } void TestBlackbox::jsExtensionsProcess() { QDir::setCurrent(testDataDir + "/jsextensions-process"); + QCOMPARE(runQbs({"resolve", {"-f", "process.qbs"}}), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); QbsRunParameters params(QStringList() << "-f" << "process.qbs"); QCOMPARE(runQbs(params), 0); QFile output("output.txt"); @@ -4249,6 +5086,20 @@ void TestBlackbox::jsExtensionsBinaryFile() QCOMPARE(data.at(5), char(0x05)); QCOMPARE(data.at(6), char(0x06)); QCOMPARE(data.at(7), char(0xFF)); + QFile destination2("destination2.dat"); + QVERIFY(destination2.exists()); + QVERIFY(destination2.open(QIODevice::ReadOnly)); + QCOMPARE(destination2.readAll(), data); +} + +void TestBlackbox::lastModuleCandidateBroken() +{ + QDir::setCurrent(testDataDir + "/last-module-candidate-broken"); + QbsRunParameters params; + params.expectFailure = true; + QVERIFY(runQbs(params) != 0); + QVERIFY2(m_qbsStderr.contains("Dependency 'Foo' not found for product " + "'last-module-candidate-broken'"), m_qbsStderr); } void TestBlackbox::ld() @@ -4264,6 +5115,9 @@ void TestBlackbox::symbolLinkMode() QDir::setCurrent(testDataDir + "/symbolLinkMode"); + QCOMPARE(runQbs({"resolve"}), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); QbsRunParameters params; params.command = "run"; const QStringList commonArgs{"-p", "driver", "--setup-run-env-config", @@ -4351,6 +5205,7 @@ void TestBlackbox::linkerVariant_data() QTest::newRow("default") << QString(); QTest::newRow("bfd") << QString("bfd"); QTest::newRow("gold") << QString("gold"); + QTest::newRow("mold") << QString("mold"); } void TestBlackbox::linkerVariant() @@ -4378,6 +5233,9 @@ void TestBlackbox::lexyacc() if (!lexYaccExist()) QSKIP("lex or yacc not present"); QDir::setCurrent(testDataDir + "/lexyacc/one-grammar"); + QCOMPARE(runQbs({"resolve"}), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); QCOMPARE(runQbs(), 0); const QString parserBinary = relativeExecutableFilePath("one-grammar"); QProcess p; @@ -4393,7 +5251,7 @@ void TestBlackbox::lexyacc() env.insert("PATH", dir); p.setProcessEnvironment(env); } - p.start(parserBinary); + p.start(parserBinary, QStringList()); QVERIFY2(p.waitForStarted(), qPrintable(p.errorString())); p.write("a && b || c && !d"); p.closeWriteChannel(); @@ -4481,22 +5339,20 @@ void TestBlackbox::lexyaccOutputs_data() void TestBlackbox::linkerLibraryDuplicates() { - const SettingsPtr s = settings(); - Profile buildProfile(profileName(), s.get()); - QStringList toolchain = buildProfile.value("qbs.toolchain").toStringList(); - if (!toolchain.contains("gcc")) - QSKIP("linkerLibraryDuplicates test only applies to GCC toolchain"); - QDir::setCurrent(testDataDir + "/linker-library-duplicates"); rmDirR(relativeBuildDir()); - QFETCH(QString, removeDuplicateLibraries); QStringList runParams; - if (!removeDuplicateLibraries.isEmpty()) { + if (!removeDuplicateLibraries.isEmpty()) runParams.append(removeDuplicateLibraries); - } QCOMPARE(runQbs(QbsRunParameters("resolve", runParams)), 0); + const bool isGcc = m_qbsStdout.contains("is gcc: true"); + const bool isNotGcc = m_qbsStdout.contains("is gcc: false"); + if (isNotGcc) + QSKIP("linkerLibraryDuplicates test only applies to GCC toolchain"); + QVERIFY(isGcc); + QCOMPARE(runQbs(QStringList { "--command-echo-mode", "command-line" }), 0); const QByteArrayList output = m_qbsStdout.split('\n'); QByteArray linkLine; @@ -4561,25 +5417,27 @@ void TestBlackbox::linkerLibraryDuplicates_data() void TestBlackbox::linkerScripts() { - const SettingsPtr s = settings(); - Profile buildProfile(profileName(), s.get()); - QStringList toolchain = buildProfile.value("qbs.toolchain").toStringList(); - if (!toolchain.contains("gcc") || targetOs() != HostOsInfo::HostOsLinux) - QSKIP("linker script test only applies to Linux "); - - QbsRunParameters runParams(QStringList() -// << "--log-level" << "debug" - << ("qbs.installRoot:" + QDir::currentPath())); const QString sourceDir = QDir::cleanPath(testDataDir + "/linkerscripts"); + QbsRunParameters runParams("resolve", {"qbs.installRoot:" + QDir::currentPath()}); runParams.buildDirectory = sourceDir + "/build"; runParams.workingDir = sourceDir; QCOMPARE(runQbs(runParams), 0); + const bool isGcc = m_qbsStdout.contains("is Linux gcc: true"); + const bool isNotGcc = m_qbsStdout.contains("is Linux gcc: false"); + if (isNotGcc) + QSKIP("linker script test only applies to Linux"); + QVERIFY(isGcc); + + runParams.command = "build"; + QCOMPARE(runQbs(runParams), 0); const QString output = QString::fromLocal8Bit(m_qbsStderr); - QRegExp pattern(".*---(.*)---.*"); - QVERIFY2(pattern.exactMatch(output), qPrintable(output)); + const QRegularExpression pattern(QRegularExpression::anchoredPattern(".*---(.*)---.*"), + QRegularExpression::DotMatchesEverythingOption); + const QRegularExpressionMatch match = pattern.match(output); + QVERIFY2(match.hasMatch(), qPrintable(output)); QCOMPARE(pattern.captureCount(), 1); - const QString nmPath = pattern.capturedTexts().at(1); + const QString nmPath = match.captured(1); if (!QFile::exists(nmPath)) QSKIP("Cannot check for symbol presence: No nm found."); @@ -4652,6 +5510,26 @@ void TestBlackbox::linkerScripts() "TEST_SYMBOL_FROM_RECURSIVE_MODIFIED"})); } +void TestBlackbox::linkerModuleDefinition() +{ + QDir::setCurrent(testDataDir + "/linker-module-definition"); + QCOMPARE(runQbs({"build"}), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); + QCOMPARE(runQbs({"run"}), 0); + const auto verifyOutput = [this](const QByteArrayList &symbols) { + for (const QByteArray &symbol : symbols) { + if (!m_qbsStdout.contains(symbol)) { + qDebug() << "Expected symbol" << symbol + << "not found in" << m_qbsStdout; + return false; + } + } + return true; + }; + QVERIFY(verifyOutput({"foo", "bar"})); +} + void TestBlackbox::listProducts() { QDir::setCurrent(testDataDir + "/list-products"); @@ -4680,7 +5558,7 @@ void TestBlackbox::listPropertyOrder() const QbsRunParameters params(QStringList() << "-q"); QCOMPARE(runQbs(params), 0); const QByteArray firstOutput = m_qbsStderr; - QVERIFY(firstOutput.contains("listProp = [\"higher1\",\"higher2\",\"higher3\"]")); + QVERIFY(firstOutput.contains("listProp = [\"product\",\"higher3\",\"higher2\",\"higher1\",\"lower\"]")); for (int i = 0; i < 25; ++i) { rmDirR(relativeBuildDir()); QCOMPARE(runQbs(params), 0); @@ -4696,16 +5574,6 @@ void TestBlackbox::require() QCOMPARE(runQbs(), 0); } -void TestBlackbox::requireDeprecated() -{ - QDir::setCurrent(testDataDir + "/require-deprecated"); - QCOMPARE(runQbs(), 0); - QVERIFY2(m_qbsStderr.contains("loadExtension() function is deprecated"), - m_qbsStderr.constData()); - QVERIFY2(m_qbsStderr.contains("loadFile() function is deprecated"), - m_qbsStderr.constData()); -} - void TestBlackbox::rescueTransformerData() { QDir::setCurrent(testDataDir + "/rescue-transformer-data"); @@ -4767,6 +5635,9 @@ void TestBlackbox::multipleConfigurations() void TestBlackbox::multiplexedTool() { QDir::setCurrent(testDataDir + "/multiplexed-tool"); + QCOMPARE(runQbs(QStringLiteral("resolve")), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); QCOMPARE(runQbs(), 0); QCOMPARE(m_qbsStdout.count("creating tool.out"), 4); } @@ -4922,6 +5793,8 @@ void TestBlackbox::propertyPrecedence() // Case 1: [cmdline=0,prod=0,export=0,nonleaf=0,profile=0] QCOMPARE(runQbs(params), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); + QVERIFY2(m_qbsStdout.contains("scalar prop: leaf\n") && m_qbsStdout.contains("list prop: [\"leaf\"]\n"), m_qbsStdout.constData()); @@ -4930,6 +5803,8 @@ void TestBlackbox::propertyPrecedence() // Case 2: [cmdline=0,prod=0,export=0,nonleaf=0,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); + QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: profile\n") && m_qbsStdout.contains("list prop: [\"profile\"]\n"), @@ -4941,6 +5816,7 @@ void TestBlackbox::propertyPrecedence() switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, true); QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: nonleaf\n") && m_qbsStdout.contains("list prop: [\"nonleaf\",\"leaf\"]\n"), @@ -4949,6 +5825,7 @@ void TestBlackbox::propertyPrecedence() // Case 4: [cmdline=0,prod=0,export=0,nonleaf=1,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: nonleaf\n") && m_qbsStdout.contains("list prop: [\"nonleaf\",\"profile\"]\n"), @@ -4961,6 +5838,7 @@ void TestBlackbox::propertyPrecedence() switchFileContents(nonleafFile, false); switchFileContents(depFile, true); QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: export\n") && m_qbsStdout.contains("list prop: [\"export\",\"leaf\"]\n"), @@ -4969,16 +5847,18 @@ void TestBlackbox::propertyPrecedence() // Case 6: [cmdline=0,prod=0,export=1,nonleaf=0,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: export\n") && m_qbsStdout.contains("list prop: [\"export\",\"profile\"]\n"), m_qbsStdout.constData()); + // Case 7: [cmdline=0,prod=0,export=1,nonleaf=1,profile=0] switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, true); QCOMPARE(runQbs(resolveParams), 0); - QCOMPARE(runQbs(params), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: export\n") && m_qbsStdout.contains("list prop: [\"export\",\"nonleaf\",\"leaf\"]\n"), m_qbsStdout.constData()); @@ -4986,6 +5866,7 @@ void TestBlackbox::propertyPrecedence() // Case 8: [cmdline=0,prod=0,export=1,nonleaf=1,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: export\n") && m_qbsStdout.contains("list prop: [\"export\",\"nonleaf\",\"profile\"]\n"), @@ -4999,6 +5880,7 @@ void TestBlackbox::propertyPrecedence() switchFileContents(depFile, false); switchFileContents(productFile, true); QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"leaf\"]\n"), @@ -5007,6 +5889,7 @@ void TestBlackbox::propertyPrecedence() // Case 10: [cmdline=0,prod=1,export=0,nonleaf=0,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"profile\"]\n"), @@ -5016,6 +5899,7 @@ void TestBlackbox::propertyPrecedence() switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, true); QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"nonleaf\",\"leaf\"]\n"), @@ -5024,6 +5908,7 @@ void TestBlackbox::propertyPrecedence() // Case 12: [cmdline=0,prod=1,export=0,nonleaf=1,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"nonleaf\",\"profile\"]\n"), @@ -5034,6 +5919,7 @@ void TestBlackbox::propertyPrecedence() switchFileContents(nonleafFile, false); switchFileContents(depFile, true); QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"export\",\"leaf\"]\n"), @@ -5042,6 +5928,7 @@ void TestBlackbox::propertyPrecedence() // Case 14: [cmdline=0,prod=1,export=1,nonleaf=0,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"export\",\"profile\"]\n"), @@ -5051,6 +5938,7 @@ void TestBlackbox::propertyPrecedence() switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, true); QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"export\",\"nonleaf\",\"leaf\"]\n"), @@ -5059,6 +5947,7 @@ void TestBlackbox::propertyPrecedence() // Case 16: [cmdline=0,prod=1,export=1,nonleaf=1,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"export\",\"nonleaf\",\"profile\"]\n"), @@ -5072,6 +5961,7 @@ void TestBlackbox::propertyPrecedence() switchFileContents(productFile, false); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5081,6 +5971,7 @@ void TestBlackbox::propertyPrecedence() switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5091,6 +5982,7 @@ void TestBlackbox::propertyPrecedence() switchFileContents(nonleafFile, true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5100,6 +5992,7 @@ void TestBlackbox::propertyPrecedence() switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5111,6 +6004,7 @@ void TestBlackbox::propertyPrecedence() switchFileContents(depFile, true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5120,6 +6014,7 @@ void TestBlackbox::propertyPrecedence() switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5130,6 +6025,7 @@ void TestBlackbox::propertyPrecedence() switchFileContents(nonleafFile, true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5139,6 +6035,7 @@ void TestBlackbox::propertyPrecedence() switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5151,6 +6048,7 @@ void TestBlackbox::propertyPrecedence() switchFileContents(productFile, true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5160,6 +6058,7 @@ void TestBlackbox::propertyPrecedence() switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5170,6 +6069,7 @@ void TestBlackbox::propertyPrecedence() switchFileContents(nonleafFile, true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5179,6 +6079,7 @@ void TestBlackbox::propertyPrecedence() switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5190,6 +6091,7 @@ void TestBlackbox::propertyPrecedence() switchFileContents(depFile, true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5199,6 +6101,7 @@ void TestBlackbox::propertyPrecedence() switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5209,6 +6112,7 @@ void TestBlackbox::propertyPrecedence() switchFileContents(nonleafFile, true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5218,6 +6122,7 @@ void TestBlackbox::propertyPrecedence() switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5247,10 +6152,19 @@ void TestBlackbox::productDependenciesByType() QVERIFY(apps.empty()); } +void TestBlackbox::productInExportedModule() +{ + QDir::setCurrent(testDataDir + "/product-in-exported-module"); + QCOMPARE(runQbs(), 0); + QVERIFY2(m_qbsStdout.contains("product: importing"), m_qbsStdout.constData()); +} + void TestBlackbox::properQuoting() { QDir::setCurrent(testDataDir + "/proper quoting"); QCOMPARE(runQbs(), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); QbsRunParameters params(QStringLiteral("run"), QStringList() << "-q" << "-p" << "Hello World"); params.expectFailure = true; // Because the exit code is non-zero. QCOMPARE(runQbs(params), 156); @@ -5272,15 +6186,27 @@ void TestBlackbox::protobuf_data() { QTest::addColumn<QString>("projectFile"); QTest::addColumn<QStringList>("properties"); + QTest::addColumn<bool>("hasModules"); QTest::addColumn<bool>("successExpected"); - QTest::newRow("cpp") << QString("addressbook_cpp.qbs") << QStringList() << true; - QTest::newRow("objc") << QString("addressbook_objc.qbs") << QStringList() << true; - QTest::newRow("import") << QString("import.qbs") << QStringList() << true; + QTest::newRow("cpp-pkgconfig") + << QString("addressbook_cpp.qbs") + << QStringList({"project.qbsModuleProviders:qbspkgconfig"}) << true << true; + QTest::newRow("cpp-conan") << QString("addressbook_cpp.qbs") + << QStringList( + {"project.qbsModuleProviders:conan", + "qbs.buildVariant:release", + "moduleProviders.conan.installDirectory:build"}) + << true << true; + QTest::newRow("objc") << QString("addressbook_objc.qbs") << QStringList() << false << true; + QTest::newRow("nanopb") << QString("addressbook_nanopb.qbs") << QStringList() << false << true; + QTest::newRow("import") << QString("import.qbs") << QStringList() << true << true; QTest::newRow("missing import dir") << QString("needs-import-dir.qbs") - << QStringList() << false; + << QStringList() << true << false; QTest::newRow("provided import dir") << QString("needs-import-dir.qbs") - << QStringList("products.app.theImportDir:subdir") << true; + << QStringList("products.app.theImportDir:subdir") << true << true; + QTest::newRow("create proto library") + << QString("create-proto-library.qbs") << QStringList() << true << true; } void TestBlackbox::protobuf() @@ -5288,20 +6214,55 @@ void TestBlackbox::protobuf() QDir::setCurrent(testDataDir + "/protobuf"); QFETCH(QString, projectFile); QFETCH(QStringList, properties); + QFETCH(bool, hasModules); QFETCH(bool, successExpected); rmDirR(relativeBuildDir()); + + if (QTest::currentDataTag() == QLatin1String("cpp-conan")) { + if (!prepareAndRunConan()) + QSKIP("conan is not prepared, check messages above"); + } + QbsRunParameters resolveParams("resolve", QStringList{"-f", projectFile} << properties); QCOMPARE(runQbs(resolveParams), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); const bool withProtobuf = m_qbsStdout.contains("has protobuf: true"); const bool withoutProtobuf = m_qbsStdout.contains("has protobuf: false"); QVERIFY2(withProtobuf || withoutProtobuf, m_qbsStdout.constData()); if (withoutProtobuf) QSKIP("protobuf module not present"); + const bool hasMods = m_qbsStdout.contains("has modules: true"); + const bool dontHaveMods = m_qbsStdout.contains("has modules: false"); + QVERIFY2(hasMods == !dontHaveMods, m_qbsStdout.constData()); + QCOMPARE(hasMods, hasModules); QbsRunParameters runParams("run"); runParams.expectFailure = !successExpected; QCOMPARE(runQbs(runParams) == 0, successExpected); } +void TestBlackbox::protobufLibraryInstall() +{ + QDir::setCurrent(testDataDir + "/protobuf-library-install"); + rmDirR(relativeBuildDir()); + QbsRunParameters resolveParams("resolve", QStringList{"qbs.installPrefix:/usr/local"}); + QCOMPARE(runQbs(resolveParams), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); + const bool withProtobuf = m_qbsStdout.contains("has protobuf: true"); + const bool withoutProtobuf = m_qbsStdout.contains("has protobuf: false"); + QVERIFY2(withProtobuf || withoutProtobuf, m_qbsStdout.constData()); + if (withoutProtobuf) + QSKIP("protobuf module not present"); + QbsRunParameters buildParams("build"); + buildParams.expectFailure = false; + QCOMPARE(runQbs(buildParams), 0); + + const QString installRootInclude = relativeBuildDir() + "/install-root/usr/local/include"; + QVERIFY(QFileInfo::exists(installRootInclude + "/hello.pb.h") && + QFileInfo::exists(installRootInclude + "/hello/world.pb.h")); +} + void TestBlackbox::pseudoMultiplexing() { // This is "pseudo-multiplexing" on all platforms that initialize qbs.architectures @@ -5411,7 +6372,158 @@ void TestBlackbox::qbsConfig() if (!canWriteToSystemSettings) { QVERIFY2(m_qbsStderr.contains("You do not have permission to write to that location."), m_qbsStderr.constData()); + } else { + // cleanup system settings + params.arguments = QStringList{"--system", "--unset", "key.subkey.scalar"}; + QCOMPARE(runQbs(params) == 0, canWriteToSystemSettings); + } +} + +void TestBlackbox::qbsConfigAddProfile() +{ + QbsRunParameters params("config"); + QTemporaryDir settingsDir1; + QTemporaryDir settingsDir2; + QVERIFY(settingsDir1.isValid()); + QVERIFY(settingsDir2.isValid()); + const QStringList settingsDir1Args = QStringList{"--settings-dir", settingsDir1.path()}; + const QStringList settingsDir2Args = QStringList{"--settings-dir", settingsDir2.path()}; + + QFETCH(QStringList, args); + QFETCH(QString, errorMsg); + + // Step 1: Run --add-profile. + params.arguments = settingsDir1Args; + params.arguments << "--add-profile"; + params.arguments << args; + params.expectFailure = !errorMsg.isEmpty(); + QCOMPARE(runQbs(params) == 0, !params.expectFailure); + if (params.expectFailure) { + QVERIFY(QString::fromLocal8Bit(m_qbsStderr).contains(errorMsg)); + return; } + params.expectFailure = false; + params.arguments = settingsDir1Args; + params.arguments << "--list"; + QCOMPARE(runQbs(params), 0); + const QByteArray output1 = m_qbsStdout; + + // Step 2: Set properties manually. + for (int i = 1; i < args.size(); i += 2) { + params.arguments = settingsDir2Args; + params.arguments << ("profiles." + args.first() + '.' + args.at(i)) << args.at(i + 1); + QCOMPARE(runQbs(params), 0); + } + params.arguments = settingsDir2Args; + params.arguments << "--list"; + QCOMPARE(runQbs(params), 0); + const QByteArray output2 = m_qbsStdout; + + // Step3: Compare results. + QCOMPARE(output1, output2); +} + +void TestBlackbox::qbsConfigAddProfile_data() +{ + QTest::addColumn<QStringList>("args"); + QTest::addColumn<QString>("errorMsg"); + QTest::newRow("no arguments") << QStringList() << QString("Profile name missing"); + QTest::newRow("empty name") << QStringList{"", "p", "v"} + << QString("Profile name must not be empty"); + QTest::newRow("no properties") << QStringList("p") + << QString("Profile properties must be provided"); + QTest::newRow("one property") << QStringList{"p", "p", "v"} << QString(); + QTest::newRow("two properties") << QStringList{"p", "p1", "v1", "p2", "v2"} << QString(); + QTest::newRow("missing value") << QStringList{"p", "p"} + << QString("Profile properties must be key/value pairs"); + QTest::newRow("missing values") << QStringList{"p", "p1", "v1", "p2"} + << QString("Profile properties must be key/value pairs"); +} + +void TestBlackbox::qbsConfigImport() +{ + QFETCH(QString, format); + + QDir::setCurrent(testDataDir + "/qbs-config-import-export"); + + QbsRunParameters params("config"); + QTemporaryDir settingsDir; + QVERIFY(settingsDir.isValid()); + const QStringList settingsDirArgs = QStringList{"--settings-dir", settingsDir.path()}; + params.arguments = settingsDirArgs; + params.arguments << "--import" << "config." + format; + + QCOMPARE(runQbs(params), 0); + + params.arguments = settingsDirArgs; + params.arguments << "--list"; + QCOMPARE(runQbs(params), 0); + const QByteArray output = m_qbsStdout; + const auto lines = output.split('\n'); + QCOMPARE(lines.count(), 5); + QCOMPARE(lines[0], "group.key1: \"value1\""); + QCOMPARE(lines[1], "group.key2: \"value2\""); + QCOMPARE(lines[2], "key: \"value\""); + QCOMPARE(lines[3], "listKey: [\"valueOne\", \"valueTwo\"]"); + QCOMPARE(lines[4], ""); +} + +void TestBlackbox::qbsConfigImport_data() +{ + QTest::addColumn<QString>("format"); + + QTest::newRow("text") << QStringLiteral("txt"); + QTest::newRow("json") << QStringLiteral("json"); +} + +void TestBlackbox::qbsConfigExport() +{ + QFETCH(QString, format); + + QDir::setCurrent(testDataDir + "/qbs-config-import-export"); + + QbsRunParameters params("config"); + QTemporaryDir settingsDir; + const QString fileName = "config." + format; + const QString filePath = settingsDir.path() + "/" + fileName; + QVERIFY(settingsDir.isValid()); + const QStringList commonArgs = QStringList{"--settings-dir", settingsDir.path(), "--user"}; + + std::pair<QString, QString> values[] = { + {"key", "value"}, + {"listKey", "[\"valueOne\",\"valueTwo\"]"}, + {"group.key1", "value1"}, + {"group.key2", "value2"} + }; + + for (const auto &value: values) { + params.arguments = commonArgs; + params.arguments << value.first << value.second; + QCOMPARE(runQbs(params), 0); + } + + params.arguments = commonArgs; + params.arguments << "--export" << filePath; + + QCOMPARE(runQbs(params), 0); + + QVERIFY(QFileInfo(filePath).canonicalPath() != QFileInfo(fileName).canonicalPath()); + + QFile exported(filePath); + QFile expected(fileName); + + QVERIFY(exported.open(QIODevice::ReadOnly | QIODevice::Text)); + QVERIFY(expected.open(QIODevice::ReadOnly | QIODevice::Text)); + + QCOMPARE(exported.readAll(), expected.readAll()); +} + +void TestBlackbox::qbsConfigExport_data() +{ + QTest::addColumn<QString>("format"); + + QTest::newRow("text") << QStringLiteral("txt"); + QTest::newRow("json") << QStringLiteral("json"); } static QJsonObject getNextSessionPacket(QProcess &session, QByteArray &data) @@ -5450,6 +6562,137 @@ static QJsonObject getNextSessionPacket(QProcess &session, QByteArray &data) return QJsonDocument::fromJson(QByteArray::fromBase64(msg)).object(); } +static void sendSessionPacket(QProcess &sessionProc, const QJsonObject &message) +{ + const QByteArray data = QJsonDocument(message).toJson().toBase64(); + sessionProc.write("qbsmsg:"); + sessionProc.write(QByteArray::number(data.length())); + sessionProc.write("\n"); + sessionProc.write(data); +} + +void TestBlackbox::qbsLanguageServer_data() +{ + QTest::addColumn<QString>("request"); + QTest::addColumn<QString>("location"); + QTest::addColumn<QString>("insertLocation"); + QTest::addColumn<QString>("insertString"); + QTest::addColumn<QString>("expectedReply"); + + QTest::addRow("follow to module") << "--goto-def" + << (testDataDir + "/lsp/lsp.qbs:4:9") + << QString() << QString() + << (testDataDir + "/lsp/modules/m/m.qbs:1:1"); + QTest::addRow("follow to submodules") + << "--goto-def" + << (testDataDir + "/lsp/lsp.qbs:5:35") + << QString() << QString() + << ((testDataDir + "/lsp/modules/Prefix/m1/m1.qbs:1:1\n") + + (testDataDir + "/lsp/modules/Prefix/m2/m2.qbs:1:1\n") + + (testDataDir + "/lsp/modules/Prefix/m3/m3.qbs:1:1")); + QTest::addRow("follow to product") + << "--goto-def" << (testDataDir + "/lsp/lsp.qbs:9:19") << QString() << QString() + << (testDataDir + "/lsp/lsp.qbs:2:5"); + QTest::addRow("follow to module, non-invalidating insert") + << "--goto-def" << (testDataDir + "/lsp/lsp.qbs:4:9") << "5:9" + << QString("property bool dummy\n") << (testDataDir + "/lsp/modules/m/m.qbs:1:1"); + QTest::addRow("follow to module, invalidating insert") + << "--goto-def" << (testDataDir + "/lsp/lsp.qbs:4:9") << QString() + << QString("property bool dummy\n") << QString(); + QTest::addRow("completion: LHS, module prefix") + << "--completion" << (testDataDir + "/lsp/lsp.qbs:7:1") << QString() << QString("P") + << QString("Prefix.m1\nPrefix.m2\nPrefix.m3"); + QTest::addRow("completion: LHS, module name") + << "--completion" << (testDataDir + "/lsp/lsp.qbs:7:1") << QString() << QString("Prefix.m") + << QString("m1\nm2\nm3"); + QTest::addRow("completion: LHS, module property right after dot") + << "--completion" << (testDataDir + "/lsp/lsp.qbs:7:1") << QString() + << QString("Prefix.m1.") << QString("p1 bool\np2 string\nx bool"); + QTest::addRow("completion: LHS, module property with identifier prefix") + << "--completion" << (testDataDir + "/lsp/lsp.qbs:7:1") << QString() + << QString("Prefix.m1.p") << QString("p1 bool\np2 string"); + QTest::addRow("completion: simple RHS, module property") + << "--completion" << (testDataDir + "/lsp/lsp.qbs:7:1") << QString() + << QString("property bool dummy: Prefix.m1.p") << QString("p1 bool\np2 string"); + QTest::addRow("completion: complex RHS, module property") + << "--completion" << (testDataDir + "/lsp/lsp.qbs:7:1") << QString() + << QString("property bool dummy: { return Prefix.m1.p") << QString("p1 bool\np2 string"); +} + +void TestBlackbox::qbsLanguageServer() +{ + QFETCH(QString, request); + QFETCH(QString, location); + QFETCH(QString, insertLocation); + QFETCH(QString, insertString); + QFETCH(QString, expectedReply); + + QDir::setCurrent(testDataDir + "/lsp"); + QProcess sessionProc; + sessionProc.start(qbsExecutableFilePath, QStringList("session")); + + QVERIFY(sessionProc.waitForStarted()); + + QByteArray incomingData; + + // Wait for and verify hello packet. + QJsonObject receivedMessage = getNextSessionPacket(sessionProc, incomingData); + const QString socketPath = receivedMessage.value("lsp-socket").toString(); + QVERIFY(!socketPath.isEmpty()); + + // Resolve project. + QJsonObject resolveMessage; + resolveMessage.insert("type", "resolve-project"); + resolveMessage.insert("top-level-profile", profileName()); + resolveMessage.insert("project-file-path", QDir::currentPath() + "/lsp.qbs"); + resolveMessage.insert("build-root", QDir::currentPath()); + resolveMessage.insert("settings-directory", settings()->baseDirectory()); + sendSessionPacket(sessionProc, resolveMessage); + bool receivedReply = false; + while (!receivedReply) { + receivedMessage = getNextSessionPacket(sessionProc, incomingData); + QVERIFY(!receivedMessage.isEmpty()); + const QString msgType = receivedMessage.value("type").toString(); + if (msgType == "project-resolved") { + receivedReply = true; + const QJsonObject error = receivedMessage.value("error").toObject(); + if (!error.isEmpty()) + qDebug() << error; + QVERIFY(error.isEmpty()); + } + } + QVERIFY(receivedReply); + + // Employ client app to send request. + QProcess lspClient; + const QFileInfo qbsFileInfo(qbsExecutableFilePath); + const QString clientFilePath = HostOsInfo::appendExecutableSuffix( + qbsFileInfo.absolutePath() + "/qbs_lspclient"); + QStringList args{"--socket", socketPath, request, location}; + if (!insertString.isEmpty()) + args << "--insert-code" << insertString; + if (!insertLocation.isEmpty()) + args << "--insert-location" << insertLocation; + lspClient.start(clientFilePath, args); + QVERIFY2(lspClient.waitForStarted(), qPrintable(lspClient.errorString())); + QVERIFY2(lspClient.waitForFinished(), qPrintable(lspClient.errorString())); + QString errMsg; + if (lspClient.exitStatus() != QProcess::NormalExit) + errMsg = lspClient.errorString(); + if (errMsg.isEmpty()) + errMsg = QString::fromLocal8Bit(lspClient.readAllStandardError()); + QVERIFY2(lspClient.exitCode() == 0, qPrintable(errMsg)); + QVERIFY2(errMsg.isEmpty(), qPrintable(errMsg)); + QString output = QString::fromUtf8(lspClient.readAllStandardOutput().trimmed()); + output.replace("\r\n", "\n"); + QCOMPARE(output, expectedReply); + + QJsonObject quitRequest; + quitRequest.insert("type", "quit"); + sendSessionPacket(sessionProc, quitRequest); + QVERIFY(sessionProc.waitForFinished(3000)); +} + void TestBlackbox::qbsSession() { QDir::setCurrent(testDataDir + "/qbs-session"); @@ -5466,11 +6709,7 @@ void TestBlackbox::qbsSession() QVERIFY(sessionProc.waitForStarted()); const auto sendPacket = [&sessionProc](const QJsonObject &message) { - const QByteArray data = QJsonDocument(message).toJson().toBase64(); - sessionProc.write("qbsmsg:"); - sessionProc.write(QByteArray::number(data.length())); - sessionProc.write("\n"); - sessionProc.write(data); + sendSessionPacket(sessionProc, message); }; static const auto envToJson = [](const QProcessEnvironment &env) { @@ -5494,8 +6733,8 @@ void TestBlackbox::qbsSession() // Wait for and verify hello packet. QJsonObject receivedMessage = getNextSessionPacket(sessionProc, incomingData); QCOMPARE(receivedMessage.value("type"), "hello"); - QCOMPARE(receivedMessage.value("api-level").toInt(), 1); - QCOMPARE(receivedMessage.value("api-compat-level").toInt(), 1); + QCOMPARE(receivedMessage.value("api-level").toInt(), 5); + QCOMPARE(receivedMessage.value("api-compat-level").toInt(), 2); // Resolve & verify structure QJsonObject resolveMessage; @@ -5508,8 +6747,9 @@ void TestBlackbox::qbsSession() QJsonObject overriddenValues; overriddenValues.insert("products.theLib.cpp.cxxLanguageVersion", "c++17"); resolveMessage.insert("overridden-properties", overriddenValues); - resolveMessage.insert("environment", envToJson(QProcessEnvironment::systemEnvironment())); + resolveMessage.insert("environment", envToJson(QbsRunParameters::defaultEnvironment())); resolveMessage.insert("data-mode", "only-if-changed"); + resolveMessage.insert("max-job-count", 2); resolveMessage.insert("log-time", true); resolveMessage.insert("module-properties", QJsonArray::fromStringList({"cpp.cxxLanguageVersion"})); @@ -5553,7 +6793,7 @@ void TestBlackbox::qbsSession() const QJsonObject group = v.toObject(); const QJsonArray sourceArtifacts = group.value("source-artifacts").toArray(); - const auto findArtifact = [&sourceArtifacts](const QString fileName) { + const auto findArtifact = [&sourceArtifacts](const QString &fileName) { for (const QJsonValue &v : sourceArtifacts) { const QJsonObject artifact = v.toObject(); if (QFileInfo(artifact.value("file-path").toString()).fileName() @@ -5815,7 +7055,7 @@ void TestBlackbox::qbsSession() QCOMPARE(receivedMessage.value("type").toString(), QString("files-added")); error = receivedMessage.value("error").toObject(); if (!error.isEmpty()) { - for (const auto &item: error[QStringLiteral("items")].toArray()) { + for (const auto item: error[QStringLiteral("items")].toArray()) { const auto description = QStringLiteral("Project file updates are not enabled"); if (item.toObject()[QStringLiteral("description")].toString().contains(description)) QSKIP("File updates are disabled"); @@ -5823,34 +7063,51 @@ void TestBlackbox::qbsSession() qDebug() << error; } QVERIFY(error.isEmpty()); - QJsonObject projectData = receivedMessage.value("project-data").toObject(); - QJsonArray products = projectData.value("products").toArray(); - bool file1 = false; - bool file2 = false; - for (const QJsonValue &v : products) { - const QJsonObject product = v.toObject(); - const QString productName = product.value("full-display-name").toString(); - const QJsonArray groups = product.value("groups").toArray(); - for (const QJsonValue &v : groups) { - const QJsonObject group = v.toObject(); - const QString groupName = group.value("name").toString(); - const QJsonArray sourceArtifacts = group.value("source-artifacts").toArray(); - for (const QJsonValue &v : sourceArtifacts) { - const QString filePath = v.toObject().value("file-path").toString(); - if (filePath.endsWith("file1.cpp")) { - QCOMPARE(productName, QString("theLib")); - QCOMPARE(groupName, QString("sources")); - file1 = true; - } else if (filePath.endsWith("file2.cpp")) { - QCOMPARE(productName, QString("theLib")); - QCOMPARE(groupName, QString("sources")); - file2 = true; + + receivedReply = false; + sendPacket(resolveMessage); + while (!receivedReply) { + receivedMessage = getNextSessionPacket(sessionProc, incomingData); + QVERIFY(!receivedMessage.isEmpty()); + const QString msgType = receivedMessage.value("type").toString(); + if (msgType == "project-resolved") { + receivedReply = true; + const QJsonObject error = receivedMessage.value("error").toObject(); + if (!error.isEmpty()) + qDebug() << error; + QVERIFY(error.isEmpty()); + const QJsonObject projectData = receivedMessage.value("project-data").toObject(); + QJsonArray products = projectData.value("products").toArray(); + bool file1 = false; + bool file2 = false; + for (const QJsonValue v : products) { + const QJsonObject product = v.toObject(); + const QString productName = product.value("full-display-name").toString(); + const QJsonArray groups = product.value("groups").toArray(); + for (const QJsonValue &v : groups) { + const QJsonObject group = v.toObject(); + const QString groupName = group.value("name").toString(); + const QJsonArray sourceArtifacts = group.value("source-artifacts").toArray(); + for (const QJsonValue &v : sourceArtifacts) { + const QString filePath = v.toObject().value("file-path").toString(); + if (filePath.endsWith("file1.cpp")) { + QCOMPARE(productName, QString("theLib")); + QCOMPARE(groupName, QString("sources")); + file1 = true; + } else if (filePath.endsWith("file2.cpp")) { + QCOMPARE(productName, QString("theLib")); + QCOMPARE(groupName, QString("sources")); + file2 = true; + } + } } } + QVERIFY(file1); + QVERIFY(file2); } } - QVERIFY(file1); - QVERIFY(file2); + QVERIFY(receivedReply); + receivedReply = false; receivedProcessResult = false; bool compiledFile1 = false; @@ -5909,32 +7166,48 @@ void TestBlackbox::qbsSession() if (!error.isEmpty()) qDebug() << error; QVERIFY(error.isEmpty()); - projectData = receivedMessage.value("project-data").toObject(); - products = projectData.value("products").toArray(); - file1 = false; - file2 = false; - for (const QJsonValue &v : products) { - const QJsonObject product = v.toObject(); - const QString productName = product.value("full-display-name").toString(); - const QJsonArray groups = product.value("groups").toArray(); - for (const QJsonValue &v : groups) { - const QJsonObject group = v.toObject(); - const QString groupName = group.value("name").toString(); - const QJsonArray sourceArtifacts = group.value("source-artifacts").toArray(); - for (const QJsonValue &v : sourceArtifacts) { - const QString filePath = v.toObject().value("file-path").toString(); - if (filePath.endsWith("file1.cpp")) { - file1 = true; - } else if (filePath.endsWith("file2.cpp")) { - QCOMPARE(productName, QString("theLib")); - QCOMPARE(groupName, QString("sources")); - file2 = true; + receivedReply = false; + sendPacket(resolveMessage); + while (!receivedReply) { + receivedMessage = getNextSessionPacket(sessionProc, incomingData); + QVERIFY(!receivedMessage.isEmpty()); + const QString msgType = receivedMessage.value("type").toString(); + if (msgType == "project-resolved") { + receivedReply = true; + const QJsonObject error = receivedMessage.value("error").toObject(); + if (!error.isEmpty()) + qDebug() << error; + QVERIFY(error.isEmpty()); + const QJsonObject projectData = receivedMessage.value("project-data").toObject(); + QJsonArray products = projectData.value("products").toArray(); + bool file1 = false; + bool file2 = false; + for (const QJsonValue v : products) { + const QJsonObject product = v.toObject(); + const QString productName = product.value("full-display-name").toString(); + const QJsonArray groups = product.value("groups").toArray(); + for (const QJsonValue &v : groups) { + const QJsonObject group = v.toObject(); + const QString groupName = group.value("name").toString(); + const QJsonArray sourceArtifacts = group.value("source-artifacts").toArray(); + for (const QJsonValue &v : sourceArtifacts) { + const QString filePath = v.toObject().value("file-path").toString(); + if (filePath.endsWith("file1.cpp")) { + file1 = true; + } else if (filePath.endsWith("file2.cpp")) { + QCOMPARE(productName, QString("theLib")); + QCOMPARE(groupName, QString("sources")); + file2 = true; + } + } } } + QVERIFY(!file1); + QVERIFY(file2); } } - QVERIFY(!file1); - QVERIFY(file2); + QVERIFY(receivedReply); + receivedReply = false; receivedProcessResult = false; compiledFile1 = false; @@ -6388,6 +7661,9 @@ void TestBlackbox::assembly() void TestBlackbox::autotestWithDependencies() { QDir::setCurrent(testDataDir + "/autotest-with-dependencies"); + QCOMPARE(runQbs({"resolve"}), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); QCOMPARE(runQbs(QStringList({"-p", "autotest-runner"})), 0); QVERIFY2(m_qbsStdout.contains("i am the test app") && m_qbsStdout.contains("i am the helper"), m_qbsStdout.constData()); @@ -6397,14 +7673,19 @@ void TestBlackbox::autotestTimeout() { QFETCH(QStringList, resolveParams); QFETCH(bool, expectFailure); + QFETCH(QString, errorDetails); QDir::setCurrent(testDataDir + "/autotest-timeout"); QbsRunParameters resolveParameters("resolve", resolveParams); QCOMPARE(runQbs(resolveParameters), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); QbsRunParameters buildParameters(QStringList({"-p", "autotest-runner"})); buildParameters.expectFailure = expectFailure; if (expectFailure) { QVERIFY(runQbs(buildParameters) != 0); - QVERIFY(m_qbsStderr.contains("cancelled") && m_qbsStderr.contains("timeout")); + QVERIFY( + m_qbsStderr.contains("cancelled") && m_qbsStderr.contains("timeout") + && m_qbsStderr.contains(errorDetails.toLocal8Bit())); } else QVERIFY(runQbs(buildParameters) == 0); @@ -6414,11 +7695,12 @@ void TestBlackbox::autotestTimeout_data() { QTest::addColumn<QStringList>("resolveParams"); QTest::addColumn<bool>("expectFailure"); - QTest::newRow("no timeout") << QStringList() << false; - QTest::newRow("timeout on test") << QStringList({"products.testApp.autotest.timeout:2"}) - << true; - QTest::newRow("timeout on runner") << QStringList({"products.autotest-runner.timeout:2"}) - << true; + QTest::addColumn<QString>("errorDetails"); + QTest::newRow("no timeout") << QStringList() << false << QString(); + QTest::newRow("timeout on test") + << QStringList({"products.testApp.autotest.timeout:2"}) << true << QString("testApp"); + QTest::newRow("timeout on runner") + << QStringList({"products.autotest-runner.timeout:2"}) << true << QString("testApp"); } void TestBlackbox::autotests_data() @@ -6444,6 +7726,8 @@ void TestBlackbox::autotests() if (!evilPropertySpec.isEmpty()) resolveParams.arguments << evilPropertySpec; QCOMPARE(runQbs(resolveParams), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); QbsRunParameters testParams(QStringList{"-p", "autotest-runner"}); if (!evilPropertySpec.isEmpty()) testParams.expectFailure = true; @@ -6452,9 +7736,9 @@ void TestBlackbox::autotests() QVERIFY2(m_qbsStderr.contains(expectedErrorMessage), m_qbsStderr.constData()); return; } - QVERIFY2(m_qbsStdout.contains("Running test test1") - && m_qbsStdout.contains("Running test test2") - && m_qbsStdout.contains("Running test test3"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("running test test1") + && m_qbsStdout.contains("running test test2") + && m_qbsStdout.contains("running test test3"), m_qbsStdout.constData()); QCOMPARE(m_qbsStdout.count("PASS"), 2); QCOMPARE(m_qbsStderr.count("FAIL"), 1); } @@ -6543,9 +7827,9 @@ static bool haveMakeNsis() << QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS"); QStringList paths = QProcessEnvironment::systemEnvironment().value("PATH") - .split(HostOsInfo::pathListSeparator(), QString::SkipEmptyParts); + .split(HostOsInfo::pathListSeparator(), Qt::SkipEmptyParts); - for (const QString &key : qAsConst(regKeys)) { + for (const QString &key : std::as_const(regKeys)) { QSettings settings(key, QSettings::NativeFormat); QString str = settings.value(QStringLiteral(".")).toString(); if (!str.isEmpty()) @@ -6553,7 +7837,7 @@ static bool haveMakeNsis() } bool haveMakeNsis = false; - for (const QString &path : qAsConst(paths)) { + for (const QString &path : std::as_const(paths)) { if (regularFileExists(QDir::fromNativeSeparators(path) + HostOsInfo::appendExecutableSuffix(QStringLiteral("/makensis")))) { haveMakeNsis = true; @@ -6678,12 +7962,16 @@ void TestBlackbox::enableRtti() void TestBlackbox::envMerging() { QDir::setCurrent(testDataDir + "/env-merging"); - QbsRunParameters params; + QbsRunParameters params("resolve"); QString pathVal = params.environment.value("PATH"); pathVal.prepend(HostOsInfo::pathListSeparator()).prepend("/opt/blackbox/bin"); const QString keyName = HostOsInfo::isWindowsHost() ? "pATh" : "PATH"; params.environment.insert(keyName, pathVal); QCOMPARE(runQbs(params), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); + params.command = "build"; + QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains(QByteArray("PATH=/opt/tool/bin") + HostOsInfo::pathListSeparator().toLatin1()) && m_qbsStdout.contains(HostOsInfo::pathListSeparator().toLatin1() @@ -6774,98 +8062,10 @@ void TestBlackbox::generator_data() QTest::newRow("no update") << QString() << QStringList(); } -static bool haveWiX(const Profile &profile) -{ - if (profile.value("wix.toolchainInstallPath").isValid() && - profile.value("wix.toolchainInstallRoot").isValid()) { - return true; - } - - QStringList regKeys; - regKeys << QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows Installer XML\\") - << QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Installer XML\\"); - - QStringList paths = QProcessEnvironment::systemEnvironment().value("PATH") - .split(HostOsInfo::pathListSeparator(), QString::SkipEmptyParts); - - for (const QString &key : qAsConst(regKeys)) { - const QStringList versions = QSettings(key, QSettings::NativeFormat).childGroups(); - for (const QString &version : versions) { - QSettings settings(key + version, QSettings::NativeFormat); - QString str = settings.value(QStringLiteral("InstallRoot")).toString(); - if (!str.isEmpty()) - paths.prepend(str); - } - } - - for (const QString &path : qAsConst(paths)) { - if (regularFileExists(QDir::fromNativeSeparators(path) + - HostOsInfo::appendExecutableSuffix(QStringLiteral("/candle"))) && - regularFileExists(QDir::fromNativeSeparators(path) + - HostOsInfo::appendExecutableSuffix(QStringLiteral("/light")))) { - return true; - } - } - - return false; -} - -void TestBlackbox::wix() -{ - const SettingsPtr s = settings(); - Profile profile(profileName(), s.get()); - - if (!haveWiX(profile)) { - QSKIP("WiX is not installed"); - return; - } - - QByteArray arch = profile.value("qbs.architecture").toString().toLatin1(); - if (arch.isEmpty()) - arch = QByteArrayLiteral("x86"); - - QDir::setCurrent(testDataDir + "/wix"); - QCOMPARE(runQbs(), 0); - QVERIFY2(m_qbsStdout.contains("compiling QbsSetup.wxs"), m_qbsStdout); - QVERIFY2(m_qbsStdout.contains("linking qbs.msi"), m_qbsStdout); - QVERIFY(regularFileExists(relativeProductBuildDir("QbsSetup") + "/qbs.msi")); - - if (HostOsInfo::isWindowsHost()) { - QVERIFY2(m_qbsStdout.contains("compiling QbsBootstrapper.wxs"), m_qbsStdout); - QVERIFY2(m_qbsStdout.contains("linking qbs-setup-" + arch + ".exe"), m_qbsStdout); - QVERIFY(regularFileExists(relativeProductBuildDir("QbsBootstrapper") - + "/qbs-setup-" + arch + ".exe")); - } -} - -void TestBlackbox::wixDependencies() -{ - const SettingsPtr s = settings(); - Profile profile(profileName(), s.get()); - - if (!haveWiX(profile)) { - QSKIP("WiX is not installed"); - return; - } - - QByteArray arch = profile.value("qbs.architecture").toString().toLatin1(); - if (arch.isEmpty()) - arch = QByteArrayLiteral("x86"); - - QDir::setCurrent(testDataDir + "/wixDependencies"); - QbsRunParameters params; - if (!HostOsInfo::isWindowsHost()) - params.arguments << "qbs.targetOS:windows"; - QCOMPARE(runQbs(params), 0); - QVERIFY2(m_qbsStdout.contains("compiling QbsSetup.wxs"), m_qbsStdout); - QVERIFY2(m_qbsStdout.contains("linking qbs.msi"), m_qbsStdout); - QVERIFY(regularFileExists(relativeBuildDir() + "/qbs.msi")); -} - void TestBlackbox::nodejs() { const SettingsPtr s = settings(); - Profile p(profileName(), s.get()); + qbs::Profile p(profileName(), s.get()); int status; findNodejs(&status); @@ -6884,6 +8084,13 @@ void TestBlackbox::nodejs() QSKIP("nodejs.packageManagerFilePath not set and automatic detection failed"); } + if (p.value("nodejs.interpreterFilePath").toString().isEmpty() + && status != 0 && m_qbsStderr.contains("interpreterPath")) { + QSKIP("nodejs.interpreterFilePath not set and automatic detection failed"); + } + + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); QCOMPARE(status, 0); QbsRunParameters params; @@ -6895,8 +8102,11 @@ void TestBlackbox::nodejs() void TestBlackbox::typescript() { + if (qEnvironmentVariableIsSet("GITHUB_ACTIONS")) + QSKIP("Skip this test when running on GitHub"); + const SettingsPtr s = settings(); - Profile p(profileName(), s.get()); + qbs::Profile p(profileName(), s.get()); int status; findTypeScript(&status); @@ -6930,6 +8140,12 @@ void TestBlackbox::typescript() QVERIFY(regularFileExists(relativeProductBuildDir("animals") + "/main.js")); } +void TestBlackbox::undefinedTargetPlatform() +{ + QDir::setCurrent(testDataDir + "/undefined-target-platform"); + QCOMPARE(runQbs(), 0); +} + void TestBlackbox::importInPropertiesCondition() { QDir::setCurrent(testDataDir + "/import-in-properties-condition"); @@ -6959,77 +8175,15 @@ void TestBlackbox::importsConflict() void TestBlackbox::includeLookup() { QDir::setCurrent(testDataDir + "/includeLookup"); + QCOMPARE(runQbs({"resolve"}), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); QbsRunParameters params; params.command = "run"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("definition.."), m_qbsStdout.constData()); } -static bool haveInnoSetup(const Profile &profile) -{ - if (profile.value("innosetup.toolchainInstallPath").isValid()) - return true; - - QStringList regKeys; - regKeys << QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Inno Setup 5_is1") - << QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Inno Setup 5_is1"); - - QStringList paths = QProcessEnvironment::systemEnvironment().value("PATH") - .split(HostOsInfo::pathListSeparator(), QString::SkipEmptyParts); - - for (const QString &key : qAsConst(regKeys)) { - QSettings settings(key, QSettings::NativeFormat); - QString str = settings.value(QStringLiteral("InstallLocation")).toString(); - if (!str.isEmpty()) - paths.prepend(str); - } - - for (const QString &path : qAsConst(paths)) { - if (regularFileExists(QDir::fromNativeSeparators(path) + - HostOsInfo::appendExecutableSuffix(QStringLiteral("/ISCC")))) - return true; - } - - return false; -} - -void TestBlackbox::innoSetup() -{ - const SettingsPtr s = settings(); - Profile profile(profileName(), s.get()); - - if (!haveInnoSetup(profile)) { - QSKIP("Inno Setup is not installed"); - return; - } - - QDir::setCurrent(testDataDir + "/innosetup"); - QCOMPARE(runQbs(), 0); - QVERIFY(m_qbsStdout.contains("compiling test.iss")); - QVERIFY(m_qbsStdout.contains("compiling Example1.iss")); - QVERIFY(regularFileExists(relativeProductBuildDir("QbsSetup") + "/qbs.setup.test.exe")); - QVERIFY(regularFileExists(relativeProductBuildDir("Example1") + "/Example1.exe")); -} - -void TestBlackbox::innoSetupDependencies() -{ - const SettingsPtr s = settings(); - Profile profile(profileName(), s.get()); - - if (!haveInnoSetup(profile)) { - QSKIP("Inno Setup is not installed"); - return; - } - - QDir::setCurrent(testDataDir + "/innosetupDependencies"); - QbsRunParameters params; - if (!HostOsInfo::isWindowsHost()) - params.arguments << "qbs.targetOS:windows"; - QCOMPARE(runQbs(params), 0); - QVERIFY(m_qbsStdout.contains("compiling test.iss")); - QVERIFY(regularFileExists(relativeBuildDir() + "/qbs.setup.test.exe")); -} - void TestBlackbox::inputTagsChangeTracking_data() { QTest::addColumn<QString>("generateInput"); @@ -7091,7 +8245,7 @@ void TestBlackbox::wildCardsAndRules() { QDir::setCurrent(testDataDir + "/wildcards-and-rules"); QCOMPARE(runQbs(), 0); - QVERIFY(m_qbsStdout.contains("Creating output artifact")); + QVERIFY(m_qbsStdout.contains("creating output artifact")); QFile output(relativeProductBuildDir("wildcards-and-rules") + "/test.mytype"); QVERIFY2(output.open(QIODevice::ReadOnly), qPrintable(output.errorString())); QCOMPARE(output.readAll().count('\n'), 1); @@ -7103,7 +8257,7 @@ void TestBlackbox::wildCardsAndRules() QbsRunParameters params; params.expectFailure = true; QCOMPARE(runQbs(params), 0); - QVERIFY(m_qbsStdout.contains("Creating output artifact")); + QVERIFY(m_qbsStdout.contains("creating output artifact")); QVERIFY2(output.open(QIODevice::ReadOnly), qPrintable(output.errorString())); QCOMPARE(output.readAll().count('\n'), 2); output.close(); @@ -7112,17 +8266,49 @@ void TestBlackbox::wildCardsAndRules() WAIT_FOR_NEW_TIMESTAMP(); touch("dep.dep"); QCOMPARE(runQbs(), 0); - QVERIFY(m_qbsStdout.contains("Creating output artifact")); + QVERIFY(m_qbsStdout.contains("creating output artifact")); // Add nothing. QCOMPARE(runQbs(), 0); - QVERIFY(!m_qbsStdout.contains("Creating output artifact")); + QVERIFY(!m_qbsStdout.contains("creating output artifact")); +} + +void TestBlackbox::wildCardsAndChangeTracking_data() +{ + QTest::addColumn<QString>("dirToModify"); + QTest::addColumn<bool>("expectReResolve"); + + QTest::newRow("root path") << QString(".") << false; + QTest::newRow("dir with recursive match") << QString("recursive1") << false; + QTest::newRow("non-recursive base dir") << QString("nonrecursive") << true; + QTest::newRow("empty base dir with file patterns") << QString("nonrecursive/empty") << true; +} + +void TestBlackbox::wildCardsAndChangeTracking() +{ + QFETCH(QString, dirToModify); + QFETCH(bool, expectReResolve); + + const QString srcDir = testDataDir + "/wildcards-and-change-tracking"; + QDir::setCurrent(srcDir); + rmDirR("default"); + QDir::current().mkdir("nonrecursive/empty"); + + QCOMPARE(runQbs({"resolve"}), 0); + QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); + WAIT_FOR_NEW_TIMESTAMP(); + touch(dirToModify + "/blubb.txt"); + QCOMPARE(runQbs({"resolve"}), 0); + QCOMPARE(m_qbsStdout.contains("Resolving"), expectReResolve); } void TestBlackbox::loadableModule() { QDir::setCurrent(testDataDir + QLatin1String("/loadablemodule")); + QCOMPARE(runQbs({"resolve"}), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); QbsRunParameters params; params.command = "run"; QCOMPARE(runQbs(params), 0); @@ -7136,6 +8322,10 @@ void TestBlackbox::localDeployment() QVERIFY(main.open(QIODevice::ReadOnly)); QByteArray content = main.readAll(); content.replace('\r', ""); + QCOMPARE(runQbs({"resolve"}), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); + QbsRunParameters params; params.command = "run"; QCOMPARE(runQbs(params), 0); @@ -7149,6 +8339,8 @@ void TestBlackbox::makefileGenerator() QCOMPARE(runQbs(params), 0); if (HostOsInfo::isWindowsHost()) return; + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); QProcess make; make.setWorkingDirectory(QDir::currentPath() + '/' + relativeBuildDir()); const QString customInstallRoot = QDir::currentPath() + "/my-install-root"; @@ -7157,7 +8349,7 @@ void TestBlackbox::makefileGenerator() QVERIFY(QFile::exists(relativeExecutableFilePath("the app"))); QVERIFY(!QFile::exists(relativeBuildGraphFilePath())); QProcess app; - app.start('"' + customInstallRoot + "/usr/local/bin/the app\""); + app.start(customInstallRoot + "/usr/local/bin/the app", QStringList()); QVERIFY(waitForProcessSuccess(app)); const QByteArray appStdout = app.readAllStandardOutput(); QVERIFY2(appStdout.contains("Hello, World!"), appStdout.constData()); @@ -7171,14 +8363,18 @@ void TestBlackbox::maximumCLanguageVersion() QDir::setCurrent(testDataDir + "/maximum-c-language-version"); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("products.app.enableNewestModule:true"))), 0); - if (m_qbsStdout.contains("is msvc")) - QSKIP("MSVC has no support for setting the C language version."); + const bool isMsvc = m_qbsStdout.contains("is msvc: true"); + if (isMsvc && m_qbsStdout.contains("is old msvc: true")) + QSKIP("MSVC supports setting the C language version only from version 16.8, and Clang from version 13."); QCOMPARE(runQbs(QStringList({"--command-echo-mode", "command-line", "-n"})), 0); QVERIFY2(m_qbsStdout.contains("c11") || m_qbsStdout.contains("c1x"), m_qbsStdout.constData()); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("products.app.enableNewestModule:false"))), 0); QCOMPARE(runQbs(QStringList({"--command-echo-mode", "command-line", "-n"})), 0); - QVERIFY2(m_qbsStdout.contains("c99"), m_qbsStdout.constData()); + if (isMsvc) + QVERIFY2(!m_qbsStdout.contains("c11"), m_qbsStdout.constData()); + else + QVERIFY2(m_qbsStdout.contains("c99"), m_qbsStdout.constData()); } void TestBlackbox::maximumCxxLanguageVersion() @@ -7187,7 +8383,7 @@ void TestBlackbox::maximumCxxLanguageVersion() QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("products.app.enableNewestModule:true"))), 0); QCOMPARE(runQbs(QStringList({"--command-echo-mode", "command-line", "-n"})), 0); - QVERIFY2(m_qbsStdout.contains("c++17") || m_qbsStdout.contains("c++1z") + QVERIFY2(m_qbsStdout.contains("c++23") || m_qbsStdout.contains("c++2b") || m_qbsStdout.contains("c++latest"), m_qbsStdout.constData()); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("products.app.enableNewestModule:false"))), 0); @@ -7196,107 +8392,6 @@ void TestBlackbox::maximumCxxLanguageVersion() m_qbsStdout.constData()); } -void TestBlackbox::moduleProviders() -{ - QDir::setCurrent(testDataDir + "/module-providers"); - - // Resolving in dry-run mode must not leave any data behind. - QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("-n"))), 0); - QCOMPARE(m_qbsStdout.count("Running setup script for mygenerator"), 2); - QVERIFY(!QFile::exists(relativeBuildDir())); - - // Initial build. - QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app1"})), 0); - QVERIFY(QFile::exists(relativeBuildDir())); - QCOMPARE(m_qbsStdout.count("Running setup script for mygenerator"), 2); - QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); - QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app2"})), 0); - QVERIFY2(m_qbsStdout.contains("The letters are Z and Y"), m_qbsStdout.constData()); - - // Rebuild with overridden module provider config. The output for product 2 must change, - // but no setup script must be re-run, because both config values have already been - // handled in the first run. - const QStringList resolveArgs("moduleProviders.mygenerator.chooseLettersFrom:beginning"); - QCOMPARE(runQbs(QbsRunParameters("resolve", resolveArgs)), 0); - QVERIFY2(!m_qbsStdout.contains("Running setup script"), m_qbsStdout.constData()); - QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app1"})), 0); - QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); - QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app2"})), 0); - QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); - - // Forcing Probe execution triggers a re-run of the setup script. But only once, - // because the module provider config is the same now. - QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList(resolveArgs) - << "--force-probe-execution")), 0); - QCOMPARE(m_qbsStdout.count("Running setup script for mygenerator"), 1); - QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app1"})), 0); - QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); - QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app2"})), 0); - QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); - - // Now re-run without the module provider config override. Again, the setup script must - // run once, for the config value that was not present in the last run. - QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); - QCOMPARE(m_qbsStdout.count("Running setup script for mygenerator"), 1); - QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app1"})), 0); - QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); - QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app2"})), 0); - QVERIFY2(m_qbsStdout.contains("The letters are Z and Y"), m_qbsStdout.constData()); -} - -void TestBlackbox::fallbackModuleProvider_data() -{ - QTest::addColumn<bool>("fallbacksEnabledGlobally"); - QTest::addColumn<bool>("fallbacksEnabledInProduct"); - QTest::addColumn<QStringList>("pkgConfigLibDirs"); - QTest::addColumn<bool>("successExpected"); - QTest::newRow("without custom lib dir, fallbacks disabled globally and in product") - << false << false << QStringList() << false; - QTest::newRow("without custom lib dir, fallbacks disabled globally, enabled in product") - << false << true << QStringList() << false; - QTest::newRow("without custom lib dir, fallbacks enabled globally, disabled in product") - << true << false << QStringList() << false; - QTest::newRow("without custom lib dir, fallbacks enabled globally and in product") - << true << true << QStringList() << false; - QTest::newRow("with custom lib dir, fallbacks disabled globally and in product") - << false << false << QStringList(testDataDir + "/fallback-module-provider/libdir") - << false; - QTest::newRow("with custom lib dir, fallbacks disabled globally, enabled in product") - << false << true << QStringList(testDataDir + "/fallback-module-provider/libdir") - << false; - QTest::newRow("with custom lib dir, fallbacks enabled globally, disabled in product") - << true << false << QStringList(testDataDir + "/fallback-module-provider/libdir") - << false; - QTest::newRow("with custom lib dir, fallbacks enabled globally and in product") - << true << true << QStringList(testDataDir + "/fallback-module-provider/libdir") - << true; -} - -void TestBlackbox::fallbackModuleProvider() -{ - QFETCH(bool, fallbacksEnabledInProduct); - QFETCH(bool, fallbacksEnabledGlobally); - QFETCH(QStringList, pkgConfigLibDirs); - QFETCH(bool, successExpected); - QDir::setCurrent(testDataDir + "/fallback-module-provider"); - static const auto b2s = [](bool b) { return QString(b ? "true" : "false"); }; - QbsRunParameters resolveParams("resolve", - QStringList{"modules.pkgconfig.libDirs:" + pkgConfigLibDirs.join(','), - "products.p.fallbacksEnabled:" + b2s(fallbacksEnabledInProduct), - "--force-probe-execution"}); - if (!fallbacksEnabledGlobally) - resolveParams.arguments << "--no-fallback-module-provider"; - QCOMPARE(runQbs(resolveParams), 0); - const bool pkgConfigPresent = m_qbsStdout.contains("pkg-config present: true"); - const bool pkgConfigNotPresent = m_qbsStdout.contains("pkg-config present: false"); - QVERIFY(pkgConfigPresent != pkgConfigNotPresent); - if (pkgConfigNotPresent) - successExpected = false; - QbsRunParameters buildParams; - buildParams.expectFailure = !successExpected; - QCOMPARE(runQbs(buildParams) == 0, successExpected); -} - void TestBlackbox::minimumSystemVersion() { rmDirR(relativeBuildDir()); @@ -7304,6 +8399,10 @@ void TestBlackbox::minimumSystemVersion() QFETCH(QString, file); QFETCH(QString, output); QbsRunParameters params({ "-f", file + ".qbs" }); + params.command = "resolve"; + QCOMPARE(runQbs(params), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); params.command = "run"; QCOMPARE(runQbs(params), 0); if (m_qbsStdout.contains("Unsupported compiler")) @@ -7385,7 +8484,7 @@ void TestBlackbox::minimumSystemVersion_data() return "__MAC_OS_X_VERSION_MIN_REQUIRED=1070\nversion 10.7\n"; if (HostOsInfo::isWindowsHost()) - return "WINVER=1536\n6.00 operating system version\n6.00 subsystem version\n"; + return "WINVER=1538\n6.02 operating system version\n6.02 subsystem version\n"; return ""; }(); @@ -7413,7 +8512,7 @@ void TestBlackbox::missingBuildGraph() QbsRunParameters params; params.expectFailure = true; params.arguments << QLatin1String("config:") + actualConfigName; - for (const QString &command : qAsConst(commands)) { + for (const QString &command : std::as_const(commands)) { params.command = command; QVERIFY2(runQbs(params) != 0, qPrintable(command)); const QString expectedErrorMessage = QString("Build graph not found for " @@ -7523,6 +8622,12 @@ void TestBlackbox::movedFileDependency() QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); } +void TestBlackbox::msvcAsmLinkerFlags() +{ + QDir::setCurrent(testDataDir + "/msvc-asm-flags"); + QCOMPARE(runQbs(), 0); +} + void TestBlackbox::badInterpreter() { if (!HostOsInfo::isAnyUnixHost()) @@ -7531,16 +8636,19 @@ void TestBlackbox::badInterpreter() QDir::setCurrent(testDataDir + QLatin1String("/badInterpreter")); QCOMPARE(runQbs(), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); + QbsRunParameters params("run"); params.expectFailure = true; - const QRegExp reNoSuchFileOrDir("bad interpreter:.* No such file or directory"); - const QRegExp rePermissionDenied("bad interpreter:.* Permission denied"); + const QRegularExpression reNoSuchFileOrDir("bad interpreter:.* No such file or directory"); + const QRegularExpression rePermissionDenied("bad interpreter:.* Permission denied"); params.arguments = QStringList() << "-p" << "script-interp-missing"; QCOMPARE(runQbs(params), 1); QString strerr = QString::fromLocal8Bit(m_qbsStderr); - QVERIFY(strerr.contains(reNoSuchFileOrDir)); + QVERIFY2(strerr.contains(reNoSuchFileOrDir), m_qbsStderr); params.arguments = QStringList() << "-p" << "script-interp-noexec"; QCOMPARE(runQbs(params), 1); @@ -7609,6 +8717,16 @@ void TestBlackbox::qbsVersion() QVERIFY(runQbs(params) != 0); } +void TestBlackbox::transitiveInvalidDependencies() +{ + QDir::setCurrent(testDataDir + "/transitive-invalid-dependencies"); + QbsRunParameters params; + QCOMPARE(runQbs(params), 0); + QVERIFY2(m_qbsStdout.contains("b.present = false"), m_qbsStdout); + QVERIFY2(m_qbsStdout.contains("c.present = true"), m_qbsStdout); + QVERIFY2(m_qbsStdout.contains("d.present = false"), m_qbsStdout); +} + void TestBlackbox::transitiveOptionalDependencies() { QDir::setCurrent(testDataDir + "/transitive-optional-dependencies"); @@ -7619,19 +8737,23 @@ void TestBlackbox::transitiveOptionalDependencies() void TestBlackbox::groupsInModules() { QDir::setCurrent(testDataDir + "/groups-in-modules"); + QCOMPARE(runQbs({"resolve"}), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); QbsRunParameters params; QCOMPARE(runQbs(params), 0); - QVERIFY(m_qbsStdout.contains("compile rock.coal => rock.diamond")); - QVERIFY(m_qbsStdout.contains("compile chunk.coal => chunk.diamond")); + QVERIFY(m_qbsStdout.contains("compiling rock.coal to rock.diamond")); + QVERIFY(m_qbsStdout.contains("compiling chunk.coal to chunk.diamond")); QVERIFY(m_qbsStdout.contains("compiling helper2.c")); QVERIFY(!m_qbsStdout.contains("compiling helper3.c")); QVERIFY(m_qbsStdout.contains("compiling helper4.c")); QVERIFY(m_qbsStdout.contains("compiling helper5.c")); QVERIFY(!m_qbsStdout.contains("compiling helper6.c")); + QVERIFY(m_qbsStdout.contains("compiling helper7.c")); QCOMPARE(runQbs(params), 0); - QVERIFY(!m_qbsStdout.contains("compile rock.coal => rock.diamond")); - QVERIFY(!m_qbsStdout.contains("compile chunk.coal => chunk.diamond")); + QVERIFY(!m_qbsStdout.contains("compiling rock.coal to rock.diamond")); + QVERIFY(!m_qbsStdout.contains("compiling chunk.coal to chunk.diamond")); WAIT_FOR_NEW_TIMESTAMP(); touch("modules/helper/diamondc.c"); @@ -7639,8 +8761,8 @@ void TestBlackbox::groupsInModules() waitForFileUnlock(); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling diamondc.c")); - QVERIFY(m_qbsStdout.contains("compile rock.coal => rock.diamond")); - QVERIFY(m_qbsStdout.contains("compile chunk.coal => chunk.diamond")); + QVERIFY(m_qbsStdout.contains("compiling rock.coal to rock.diamond")); + QVERIFY(m_qbsStdout.contains("compiling chunk.coal to chunk.diamond")); QVERIFY(regularFileExists(relativeProductBuildDir("groups-in-modules") + "/rock.diamond")); QFile output(relativeProductBuildDir("groups-in-modules") + "/rock.diamond"); QVERIFY(output.open(QIODevice::ReadOnly)); @@ -7650,15 +8772,36 @@ void TestBlackbox::groupsInModules() void TestBlackbox::grpc_data() { QTest::addColumn<QString>("projectFile"); - QTest::newRow("cpp") << QString("grpc_cpp.qbs"); + QTest::addColumn<QStringList>("arguments"); + QTest::addColumn<bool>("hasModules"); + + QStringList pkgConfigArgs({"project.qbsModuleProviders:qbspkgconfig"}); + // on macOS, openSSL is hidden from pkg-config by default + if (qbs::Internal::HostOsInfo::isMacosHost()) { + pkgConfigArgs + << "moduleProviders.qbspkgconfig.extraPaths:/usr/local/opt/openssl@1.1/lib/pkgconfig"; + } + QTest::newRow("cpp-pkgconfig") << QString("grpc_cpp.qbs") << pkgConfigArgs << true; + QStringList conanArgs( + {"project.qbsModuleProviders:conan", "moduleProviders.conan.installDirectory:build"}); + QTest::newRow("cpp-conan") << QString("grpc_cpp.qbs") << conanArgs << true; } void TestBlackbox::grpc() { QDir::setCurrent(testDataDir + "/grpc"); QFETCH(QString, projectFile); + QFETCH(QStringList, arguments); + QFETCH(bool, hasModules); + rmDirR(relativeBuildDir()); + if (QTest::currentDataTag() == QLatin1String("cpp-conan")) { + if (!prepareAndRunConan()) + QSKIP("conan is not prepared, check messages above"); + } + QbsRunParameters resolveParams("resolve", QStringList{"-f", projectFile}); + resolveParams.arguments << arguments; QCOMPARE(runQbs(resolveParams), 0); const bool withGrpc = m_qbsStdout.contains("has grpc: true"); const bool withoutGrpc = m_qbsStdout.contains("has grpc: false"); @@ -7666,10 +8809,33 @@ void TestBlackbox::grpc() if (withoutGrpc) QSKIP("grpc module not present"); + const bool hasMods = m_qbsStdout.contains("has modules: true"); + const bool dontHaveMods = m_qbsStdout.contains("has modules: false"); + QVERIFY2(hasMods == !dontHaveMods, m_qbsStdout.constData()); + QCOMPARE(hasMods, hasModules); + + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); + QbsRunParameters runParams; QCOMPARE(runQbs(runParams), 0); } +void TestBlackbox::hostOsProperties() +{ + QDir::setCurrent(testDataDir + "/host-os-properties"); + QCOMPARE(runQbs(QStringLiteral("resolve")), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); + QCOMPARE(runQbs(QStringLiteral("run")), 0); + QVERIFY2(m_qbsStdout.contains( + ("HOST_ARCHITECTURE = " + HostOsInfo::hostOSArchitecture().toUtf8()).data()), + m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains( + ("HOST_PLATFORM = " + HostOsInfo::hostOSIdentifier().toUtf8()).data()), + m_qbsStdout.constData()); +} + void TestBlackbox::ico() { QDir::setCurrent(testDataDir + "/ico"); @@ -7747,8 +8913,8 @@ void TestBlackbox::ico() QCOMPARE(b.at(12), '\0'); QCOMPARE(b.at(26), '\0'); QCOMPARE(b.at(28), '\0'); - QWARN("this version of icoutil does not support setting the hotspot " - "for cursor files with multiple images"); + qWarning() << "this version of icoutil does not support setting the hotspot " + "for cursor files with multiple images"; } else { QCOMPARE(b.at(10), '\x8'); QCOMPARE(b.at(12), '\x9'); diff --git a/tests/auto/blackbox/tst_blackbox.h b/tests/auto/blackbox/tst_blackbox.h index 4e2755724..3f817b481 100644 --- a/tests/auto/blackbox/tst_blackbox.h +++ b/tests/auto/blackbox/tst_blackbox.h @@ -40,6 +40,8 @@ public: TestBlackbox(); private slots: + void allowedValues(); + void allowedValues_data(); void addFileTagToGeneratedArtifact(); void alwaysRun(); void alwaysRun_data(); @@ -58,8 +60,14 @@ private slots: void bomSources(); void buildDataOfDisabledProduct(); void buildDirectories(); + void buildDirPlaceholders_data(); + void buildDirPlaceholders(); void buildEnvChange(); void buildGraphVersions(); + void buildVariantDefaults_data(); + void buildVariantDefaults(); + void capnproto(); + void capnproto_data(); void changedFiles_data(); void changedFiles(); void changedInputsFromDependencies(); @@ -76,26 +84,33 @@ private slots: void combinedSources(); void commandFile(); void compilerDefinesByLanguage(); - void concurrentExecutor(); void conditionalExport(); void conditionalFileTagger(); void configure(); void conflictingArtifacts(); void cxxLanguageVersion(); void cxxLanguageVersion_data(); + void conanfileProbe_data(); + void conanfileProbe(); + void conflictingPropertyValues_data(); + void conflictingPropertyValues(); void cpuFeatures(); + void dateProperty(); void dependenciesProperty(); - void dependencyProfileMismatch(); + void dependencyScanningLoop(); void deprecatedProperty(); + void deprecatedProperty_data(); void disappearedProfile(); void discardUnusedData(); void discardUnusedData_data(); + void dotDotPcFile(); void driverLinkerFlags(); void driverLinkerFlags_data(); void dynamicLibraryInModule(); void dynamicMultiplexRule(); void dynamicProject(); void dynamicRuleOutputs(); + void emptyProfile(); void enableExceptions(); void enableExceptions_data(); void enableRtti(); @@ -113,11 +128,16 @@ private slots: void exportedPropertyInDisabledProduct_data(); void exportRule(); void exportToOutsideSearchPath(); + void exportsCMake(); + void exportsCMake_data(); void exportsPkgconfig(); void exportsQbs(); void externalLibs(); void fileDependencies(); void fileTagsFilterMerging(); + void flatbuf(); + void flatbuf_data(); + void freedesktop(); void generatedArtifactAsInputToDynamicRule(); void generateLinkerMapFile(); void generator(); @@ -125,6 +145,7 @@ private slots: void groupsInModules(); void grpc_data(); void grpc(); + void hostOsProperties(); void ico(); void importAssignment(); void importChangeTracking(); @@ -133,8 +154,6 @@ private slots: void importingProduct(); void importsConflict(); void includeLookup(); - void innoSetup(); - void innoSetupDependencies(); void inputTagsChangeTracking_data(); void inputTagsChangeTracking(); void inputsFromDependencies(); @@ -150,6 +169,8 @@ private slots: void installPackage(); void installRootFromProjectFile(); void installTree(); + void invalidArtifactPath_data(); + void invalidArtifactPath(); void invalidCommandProperty_data(); void invalidCommandProperty(); void invalidExtensionInstantiation(); @@ -159,11 +180,13 @@ private slots: void invalidLibraryNames_data(); void jsExtensionsFile(); void jsExtensionsFileInfo(); + void jsExtensionsHost(); void jsExtensionsProcess(); void jsExtensionsPropertyList(); void jsExtensionsTemporaryDir(); void jsExtensionsTextFile(); void jsExtensionsBinaryFile(); + void lastModuleCandidateBroken(); void ld(); void linkerMode(); void linkerVariant_data(); @@ -174,6 +197,7 @@ private slots: void linkerLibraryDuplicates(); void linkerLibraryDuplicates_data(); void linkerScripts(); + void linkerModuleDefinition(); void listProducts(); void listPropertiesWithOuter(); void listPropertyOrder(); @@ -182,9 +206,6 @@ private slots: void makefileGenerator(); void maximumCLanguageVersion(); void maximumCxxLanguageVersion(); - void moduleProviders(); - void fallbackModuleProvider_data(); - void fallbackModuleProvider(); void minimumSystemVersion(); void minimumSystemVersion_data(); void missingBuildGraph(); @@ -194,6 +215,7 @@ private slots: void missingOverridePrefix(); void moduleConditions(); void movedFileDependency(); + void msvcAsmLinkerFlags(); void multipleChanges(); void multipleConfigurations(); void multiplexedTool(); @@ -216,6 +238,7 @@ private slots: void overrideProjectProperties(); void pathProbe_data(); void pathProbe(); + void pathListInProbe(); void pchChangeTracking(); void perGroupDefineInExportItem(); void pkgConfigProbe(); @@ -232,17 +255,27 @@ private slots: void probesAndArrayProperties(); void probesInNestedModules(); void productDependenciesByType(); + void productInExportedModule(); void productProperties(); - void propertyAssignmentOnNonPresentModule(); void propertyAssignmentInFailedModule(); void propertyChanges(); + void propertyEvaluationContext(); void propertyPrecedence(); void properQuoting(); void propertiesInExportItems(); void protobuf_data(); void protobuf(); + void protobufLibraryInstall(); void pseudoMultiplexing(); void qbsConfig(); + void qbsConfigAddProfile(); + void qbsConfigAddProfile_data(); + void qbsConfigImport(); + void qbsConfigImport_data(); + void qbsConfigExport(); + void qbsConfigExport_data(); + void qbsLanguageServer_data(); + void qbsLanguageServer(); void qbsSession(); void qbsVersion(); void qtBug51237(); @@ -256,16 +289,21 @@ private slots: void reproducibleBuild(); void reproducibleBuild_data(); void require(); - void requireDeprecated(); void rescueTransformerData(); void responseFiles(); void retaggedOutputArtifact(); + void rpathlinkDeduplication(); void ruleConditions(); void ruleConnectionWithExcludedInputs(); void ruleCycle(); void ruleWithNoInputs(); void ruleWithNonRequiredInputs(); + void runMultiplexed(); + void sanitizer_data(); + void sanitizer(); void scannerItem(); + void scanResultInOtherProduct(); + void scanResultInNonDependency(); void setupBuildEnvironment(); void setupRunEnvironment(); void smartRelinking(); @@ -285,6 +323,7 @@ private slots: void suspiciousCalls(); void suspiciousCalls_data(); void systemIncludePaths(); + void distributionIncludePaths(); void systemRunPaths(); void systemRunPaths_data(); void tar(); @@ -299,8 +338,10 @@ private slots: void trackRemoveFile(); void trackRemoveFileTag(); void trackRemoveProduct(); + void transitiveInvalidDependencies(); void transitiveOptionalDependencies(); void typescript(); + void undefinedTargetPlatform(); void usingsAsSoleInputsNonMultiplexed(); void variantSuffix(); void variantSuffix_data(); @@ -312,9 +353,9 @@ private slots: void wholeArchive(); void wholeArchive_data(); void wildCardsAndRules(); + void wildCardsAndChangeTracking_data(); + void wildCardsAndChangeTracking(); void wildcardRenaming(); - void wix(); - void wixDependencies(); void zip(); void zip_data(); void zipInvalid(); @@ -324,6 +365,7 @@ private: QMap<QString, QString> findNodejs(int *status); QMap<QString, QString> findTypeScript(int *status); QString findArchiver(const QString &fileName, int *status = nullptr); + bool prepareAndRunConan(); static bool lexYaccExist(); static qbs::Version bisonVersion(); }; diff --git a/tests/auto/blackbox/tst_blackboxandroid.cpp b/tests/auto/blackbox/tst_blackboxandroid.cpp index e312c4493..a74d9415d 100644 --- a/tests/auto/blackbox/tst_blackboxandroid.cpp +++ b/tests/auto/blackbox/tst_blackboxandroid.cpp @@ -58,6 +58,7 @@ QMap<QString, QString> TestBlackboxAndroid::findAndroid(int *status, const QStri return { {"sdk", QDir::fromNativeSeparators(tools["sdk"].toString())}, {"sdk-build-tools-dx", QDir::fromNativeSeparators(tools["sdk-build-tools-dx"].toString())}, + {"sdk-build-tools-d8", QDir::fromNativeSeparators(tools["sdk-build-tools-d8"].toString())}, {"ndk", QDir::fromNativeSeparators(tools["ndk"].toString())}, {"ndk-samples", QDir::fromNativeSeparators(tools["ndk-samples"].toString())}, {"jar", QDir::fromNativeSeparators(tools["jar"].toString())}, @@ -80,11 +81,19 @@ void TestBlackboxAndroid::android() QFETCH(QStringList, productNames); QFETCH(QList<QByteArrayList>, expectedFilesLists); QFETCH(QStringList, customProperties); + QFETCH(bool, enableAapt2); + QFETCH(bool, generateAab); + QFETCH(bool, isIncrementalBuild); + QFETCH(bool, enableD8); + + // skip tests on github except when run in docker - this var is not propagated into the image + if (qEnvironmentVariableIsSet("GITHUB_ACTIONS")) + QSKIP("Skip Android tests when running on GitHub"); const SettingsPtr s = settings(); - Profile p(theProfileName(projectDir == "qml-app"), s.get()); + Profile p(theProfileName(projectDir == "qml-app" || projectDir == "qt-app"), s.get()); if (!p.exists()) - p = Profile("none", s.get()); + QSKIP("Qt is not installed"); int status; const auto androidPaths = findAndroid(&status, p.name()); QCOMPARE(status, 0); @@ -103,33 +112,39 @@ void TestBlackboxAndroid::android() && ndkSamplesDirs.contains(projectDir)) QSKIP("NDK samples directory not present"); + const QString buildSubDir = enableAapt2 ? (generateAab ? "aab" : "aapt2") : "aapt"; QDir::setCurrent(testDataDir + "/" + projectDir); + if (!isIncrementalBuild) + rmDirR(relativeBuildDir(buildSubDir)); static const QStringList configNames { "debug", "release" }; for (const QString &configName : configNames) { auto currentExpectedFilesLists = expectedFilesLists; const QString configArgument = "config:" + configName; QbsRunParameters resolveParams("resolve"); + resolveParams.buildDirectory = buildSubDir; resolveParams.arguments << configArgument << customProperties; resolveParams.profile = p.name(); QCOMPARE(runQbs(resolveParams), 0); QbsRunParameters buildParams(QStringList{"--command-echo-mode", "command-line", configArgument}); + buildParams.buildDirectory = buildSubDir; buildParams.profile = p.name(); QCOMPARE(runQbs(buildParams), 0); - for (const QString &productName : qAsConst(productNames)) { + for (const QString &productName : std::as_const(productNames)) { const QByteArray tag(QTest::currentDataTag()); - const bool isIncrementalBuild = tag.startsWith("qml app") && tag != "qml app"; - QCOMPARE(m_qbsStdout.count("Generating BuildConfig.java"), + QCOMPARE(m_qbsStdout.count("generating BuildConfig.java"), isIncrementalBuild ? 0 : productNames.size()); - QVERIFY(m_qbsStdout.contains(productName.toLocal8Bit() + ".apk")); - const QString apkFilePath = relativeProductBuildDir(productName, configName) - + '/' + productName + ".apk"; - QVERIFY2(regularFileExists(apkFilePath), qPrintable(apkFilePath)); + const QString packageName = productName + (generateAab ? ".aab" : ".apk"); + QVERIFY(m_qbsStdout.contains(packageName.toLocal8Bit())); + const QString packageFilePath = buildSubDir + "/" + relativeProductBuildDir(productName, + configName) + + '/' + packageName; + QVERIFY2(regularFileExists(packageFilePath), qPrintable(packageFilePath)); const QString jarFilePath = androidPaths["jar"]; QVERIFY(!jarFilePath.isEmpty()); QProcess jar; - jar.start(jarFilePath, QStringList() << "-tf" << apkFilePath); + jar.start(jarFilePath, QStringList() << "-tf" << packageFilePath); QVERIFY2(jar.waitForStarted(), qPrintable(jar.errorString())); QVERIFY2(jar.waitForFinished(), qPrintable(jar.errorString())); QVERIFY2(jar.exitCode() == 0, qPrintable(jar.readAllStandardError().constData())); @@ -159,8 +174,8 @@ void TestBlackboxAndroid::android() return f.contains("qmltooling"); }; if (none_of(actualFiles, isFileSharedObject) - || std::all_of(actualFiles.cbegin(), actualFiles.cend(), isQmlToolingLib)) { - QWARN(msg); + || qbs::Internal::all_of(actualFiles, isQmlToolingLib)) { + qWarning() << msg; } else { QFAIL(msg); } @@ -168,11 +183,12 @@ void TestBlackboxAndroid::android() } if (projectDir == "multiple-libs-per-apk") { - const auto dxPath = androidPaths["sdk-build-tools-dx"]; - QVERIFY(!dxPath.isEmpty()); + const auto dexCompilerPath = enableD8 ? androidPaths["sdk-build-tools-d8"] + : androidPaths["sdk-build-tools-dx"]; + QVERIFY(!dexCompilerPath.isEmpty()); const auto lines = m_qbsStdout.split('\n'); const auto it = std::find_if(lines.cbegin(), lines.cend(), [&](const QByteArray &line) { - return !line.isEmpty() && line.startsWith(dxPath.toUtf8()); + return !line.isEmpty() && line.startsWith(dexCompilerPath.toUtf8()); }); QVERIFY2(it != lines.cend(), qPrintable(m_qbsStdout.constData())); const auto line = *it; @@ -204,71 +220,102 @@ void TestBlackboxAndroid::android_data() const auto cxxLibPath = [&p, &pQt](const QByteArray &oldcxxLib, bool forQt) { const bool usesClang = (forQt ? pQt : p).value(QStringLiteral("qbs.toolchainType")) .toString() == "clang"; - return QByteArray("lib/${ARCH}/") + (usesClang ? "libc++_shared.so" : oldcxxLib); + const QByteArray path = "lib/${ARCH}/"; + return path + (usesClang ? QByteArrayLiteral("libc++_shared.so") : oldcxxLib); }; - const QByteArrayList archsForQt = { pQt.value("qbs.architecture").toString().toUtf8() }; - QByteArrayList ndkArchsForQt = archsForQt; - if (ndkArchsForQt.first() == "armv7a") - ndkArchsForQt.first() = "armeabi-v7a"; - else if (ndkArchsForQt.first() == "armv5te") - ndkArchsForQt.first() = "armeabi"; - else if (ndkArchsForQt.first() == "arm64") - ndkArchsForQt.first() = "arm64-v8a"; + qbs::Version version(5, 13); + QStringList qmakeFilePaths = pQt.value(QStringLiteral("moduleProviders.Qt.qmakeFilePaths")). + toStringList(); + if (qmakeFilePaths.size() >= 1) + version = TestBlackboxBase::qmakeVersion(qmakeFilePaths[0]); + bool singleArchQt = (version < qbs::Version(5, 14)); + QByteArray qtVersionMajor((version >= qbs::Version(6, 0)) ? "6" : "5"); + QByteArrayList archsForQt; + if (singleArchQt) { + archsForQt = { pQt.value("qbs.architecture").toString().toUtf8() }; + if (archsStringList.empty()) + archsStringList << QStringLiteral("armv7a"); // must match default in common.qbs + } else { + QStringList archsForQtStringList = pQt.value(QStringLiteral("qbs.architectures")) + .toStringList(); + if (archsForQtStringList.empty()) + archsForQtStringList << pQt.value("qbs.architecture").toString(); + std::transform(archsForQtStringList.begin(), + archsForQtStringList.end(), + std::back_inserter(archsForQt), + [] (const QString &s) { + return s.toUtf8(); + }); + } + + QByteArrayList ndkArchsForQt; + std::transform(archsForQt.begin(), archsForQt.end(), std::back_inserter(ndkArchsForQt), + [] (const QString &s) { + return s.toUtf8().replace("armv7a", "armeabi-v7a") + .replace("armv5te", "armeabi") + .replace("arm64", "arm64-v8a"); + }); - auto expandArchs = [] (const QByteArrayList &archs, const QByteArrayList &lst) { + auto expandArchs = [] (const QByteArrayList &archs, const QByteArrayList &lst, bool aabPackage) { const QByteArray &archPlaceHolder = "${ARCH}"; QByteArrayList result; + QByteArray base( aabPackage ? "base/" : ""); for (const QByteArray &entry : lst) { if (entry.contains(archPlaceHolder)) { - for (const QByteArray &arch : qAsConst(archs)) - result << QByteArray(entry).replace(archPlaceHolder, arch); + for (const QByteArray &arch : std::as_const(archs)) + result << (base + QByteArray(entry).replace(archPlaceHolder, arch)); } else { - result << entry; + result << (base + entry); } } return result; }; - const QByteArrayList commonFiles = expandArchs(archs, { - "AndroidManifest.xml", "META-INF/ANDROIDD.RSA", "META-INF/ANDROIDD.SF", - "META-INF/MANIFEST.MF", "classes.dex" - }); + auto commonFiles = [](bool generateAab, bool codeSign = true, + QString keyAlias="androiddebugkey") { + QByteArrayList files; + if (generateAab) + files << "base/manifest/AndroidManifest.xml" << "base/dex/classes.dex" + << "BundleConfig.pb"; + else + files << "AndroidManifest.xml" << "classes.dex"; + if (codeSign) + files << QByteArray("META-INF/" + keyAlias.toUpper().left(8).toUtf8() + ".RSA") + << QByteArray("META-INF/" + keyAlias.toUpper().left(8).toUtf8() + ".SF") + << "META-INF/MANIFEST.MF"; + return files; + }; QTest::addColumn<QString>("projectDir"); QTest::addColumn<QStringList>("productNames"); QTest::addColumn<QList<QByteArrayList>>("expectedFilesLists"); QTest::addColumn<QStringList>("customProperties"); - QTest::newRow("teapot") - << "teapot" << QStringList("TeapotNativeActivity") - << (QList<QByteArrayList>() << commonFiles + expandArchs(archs, { - "resources.arsc", - "assets/Shaders/ShaderPlain.fsh", - "assets/Shaders/VS_ShaderPlain.vsh", - "lib/${ARCH}/libgdbserver.so", - cxxLibPath("libgnustl_shared.so", false), - "lib/${ARCH}/libTeapotNativeActivity.so", - "res/layout/widgets.xml"})) - << QStringList(); - QTest::newRow("minimal-native") - << "minimal-native" << QStringList("minimalnative") - << (QList<QByteArrayList>() << commonFiles + expandArchs({archs.first()}, { - "lib/${ARCH}/libminimalnative.so", - cxxLibPath("libstlport_shared.so", false), - "lib/${ARCH}/libdependency.so"})) - << QStringList{"products.minimalnative.multiplexByQbsProperties:[]", - "modules.qbs.architecture:" + archsStringList.first()}; - QTest::newRow("qml app") - << "qml-app" << QStringList("qmlapp") - << (QList<QByteArrayList>() << commonFiles + expandArchs(ndkArchsForQt, { - "resources.arsc", - "assets/--Added-by-androiddeployqt--/qml/QtQuick.2/plugins.qmltypes", - "assets/--Added-by-androiddeployqt--/qml/QtQuick.2/qmldir", - "assets/--Added-by-androiddeployqt--/qml/QtQuick/Window.2/plugins.qmltypes", - "assets/--Added-by-androiddeployqt--/qml/QtQuick/Window.2/qmldir", - "assets/--Added-by-androiddeployqt--/qt_cache_pregenerated_file_list", - "lib/${ARCH}/libgdbserver.so", + QTest::addColumn<bool>("enableAapt2"); + QTest::addColumn<bool>("generateAab"); + QTest::addColumn<bool>("isIncrementalBuild"); + QTest::addColumn<bool>("enableD8"); + + const auto aaptVersion = [](bool enableAapt2) { + return QString("modules.Android.sdk.aaptName:") + (enableAapt2 ? "aapt2" : "aapt"); + }; + bool enableAapt2 = false; + const auto packageType = [](bool generateAab) { + return QString("modules.Android.sdk.packageType:") + (generateAab ? "aab" : "apk"); + }; + bool generateAab = false; + bool isIncrementalBuild = false; + + const auto dexCompilerVersion = [](bool enableD8) { + return QString("modules.Android.sdk.dexCompilerName:") + (enableD8 ? "d8" : "dx"); + }; + bool enableD8 = true; + auto qtAppExpectedFiles = [&](bool generateAab, bool enableAapt2, bool codeSign = true, + QString keyAlias="androiddebugkey") { + QByteArrayList expectedFile; + if (singleArchQt) { + expectedFile << commonFiles(generateAab, codeSign, keyAlias) + expandArchs(ndkArchsForQt, { cxxLibPath("libgnustl_shared.so", true), - "lib/${ARCH}/libplugins_bearer_libqandroidbearer.so", + "assets/--Added-by-androiddeployqt--/qt_cache_pregenerated_file_list", "lib/${ARCH}/libplugins_imageformats_libqgif.so", "lib/${ARCH}/libplugins_imageformats_libqicns.so", "lib/${ARCH}/libplugins_imageformats_libqico.so", @@ -278,139 +325,791 @@ void TestBlackboxAndroid::android_data() "lib/${ARCH}/libplugins_imageformats_libqwbmp.so", "lib/${ARCH}/libplugins_imageformats_libqwebp.so", "lib/${ARCH}/libplugins_platforms_android_libqtforandroid.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_debugger.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_inspector.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_local.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_messages.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_native.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_nativedebugger.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_profiler.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_preview.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_quickprofiler.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_server.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_tcp.so", - "lib/${ARCH}/libqml_QtQuick.2_libqtquick2plugin.so", - "lib/${ARCH}/libqml_QtQuick_Window.2_libwindowplugin.so", + "lib/${ARCH}/libplugins_styles_libqandroidstyle.so", "lib/${ARCH}/libQt5Core.so", "lib/${ARCH}/libQt5Gui.so", - "lib/${ARCH}/libQt5Network.so", - "lib/${ARCH}/libQt5Qml.so", - "lib/${ARCH}/libQt5QuickParticles.so", - "lib/${ARCH}/libQt5Quick.so", - "lib/${ARCH}/libqmlapp.so", - "res/layout/splash.xml"})) - << QStringList{"modules.Android.sdk.automaticSources:false", - "modules.qbs.architecture:" + archsForQt.first()}; - QTest::newRow("qml app using Ministro") - << "qml-app" << QStringList("qmlapp") - << (QList<QByteArrayList>() << commonFiles + expandArchs(ndkArchsForQt, { - "resources.arsc", - "assets/--Added-by-androiddeployqt--/qt_cache_pregenerated_file_list", - "lib/${ARCH}/libgdbserver.so", + "lib/${ARCH}/libQt5Widgets.so", + "lib/${ARCH}/libqt-app.so"}, generateAab); + } else { + expectedFile << commonFiles(generateAab, codeSign, keyAlias) + expandArchs(ndkArchsForQt, { cxxLibPath("libgnustl_shared.so", true), - "lib/${ARCH}/libqmlapp.so", - "res/layout/splash.xml"})) - << QStringList{"modules.Qt.android_support.useMinistro:true", - "modules.Android.sdk.automaticSources:false"}; + "lib/${ARCH}/libplugins_imageformats_qgif_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qico_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qjpeg_${ARCH}.so", + "lib/${ARCH}/libplugins_platforms_qtforandroid_${ARCH}.so", + "lib/${ARCH}/libQt" + qtVersionMajor + "Core_${ARCH}.so", + "lib/${ARCH}/libQt" + qtVersionMajor + "Gui_${ARCH}.so", + "lib/${ARCH}/libQt" + qtVersionMajor + "Widgets_${ARCH}.so", + "lib/${ARCH}/libqt-app_${ARCH}.so"}, generateAab); + } + if (generateAab) + expectedFile << "base/resources.pb" << "base/native.pb"; + else + expectedFile << "resources.arsc"; + if (version >= qbs::Version(5, 14)) + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libplugins_styles_qandroidstyle_${ARCH}.so"}, generateAab); + if (version < qbs::Version(6, 0) && version >= qbs::Version(5, 14)) + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libplugins_imageformats_qicns_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qtga_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qtiff_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qwbmp_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qwebp_${ARCH}.so"}, generateAab); + if (version >= qbs::Version(6, 5)) + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libQt6Svg_${ARCH}.so", + "lib/${ARCH}/libplugins_iconengines_qsvgicon_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qsvg_${ARCH}.so"}, generateAab); + if (!enableAapt2 && version < qbs::Version(6, 0)) + expectedFile << "res/layout/splash.xml"; + return expectedFile; + }; + auto codeSignProperties = [&](bool codeSign, QString keyStorePath, QString keystorePassword, + QString keyPassword, QString keyAlias) { + if (!codeSign) + return QStringList{"modules.codesign.enableCodeSigning:false"}; + return QStringList{ + "modules.codesign.enableCodeSigning:true", + "modules.codesign.keystorePath:" + keyStorePath, + "modules.codesign.keystorePassword:" + keystorePassword, + "modules.codesign.keyPassword:" + keyPassword, + "modules.codesign.keyAlias:" + keyAlias, + }; + }; + bool codeSign = true; + QString keyStorePath(testDataDir + "/qt-app/test.keystore"); + QString keystorePassword("qbsKeystoreTest"); + QString keyPassword("qbsKeyTest"); + QString keyAlias("qbsTest"); + QTest::newRow("qt app") + << "qt-app" << QStringList("qt-app") + << (QList<QByteArrayList>() << (QByteArrayList() << qtAppExpectedFiles(generateAab, + enableAapt2, + codeSign, + keyAlias))) + << (QStringList() << codeSignProperties(codeSign, keyStorePath, keystorePassword, + keyPassword, keyAlias) + << aaptVersion(enableAapt2) + << packageType(generateAab)) + << enableAapt2 << generateAab << isIncrementalBuild << enableD8;; + codeSign = false; + QTest::newRow("qt app no signing") + << "qt-app" << QStringList("qt-app") + << (QList<QByteArrayList>() << (QByteArrayList() << qtAppExpectedFiles(generateAab, + enableAapt2, + codeSign, + keyAlias))) + << (QStringList() << codeSignProperties(codeSign, keyStorePath, keystorePassword, + keyPassword, keyAlias) + << aaptVersion(enableAapt2) + << packageType(generateAab)) + << enableAapt2 << generateAab << isIncrementalBuild << enableD8; + enableAapt2 = true; + codeSign = true; + QTest::newRow("qt app aapt2") + << "qt-app" << QStringList("qt-app") + << (QList<QByteArrayList>() << (QByteArrayList() << qtAppExpectedFiles(generateAab, + enableAapt2, + codeSign, + keyAlias))) + << (QStringList() << codeSignProperties(codeSign, keyStorePath, keystorePassword, + keyPassword, keyAlias) + << aaptVersion(enableAapt2) + << packageType(generateAab)) + << enableAapt2 << generateAab << isIncrementalBuild << enableD8; + generateAab = true; + QTest::newRow("qt app aab") + << "qt-app" << QStringList("qt-app") + << (QList<QByteArrayList>() << (QByteArrayList() << qtAppExpectedFiles(generateAab, + enableAapt2, + codeSign, + keyAlias))) + << (QStringList() << codeSignProperties(codeSign, keyStorePath, keystorePassword, + keyPassword, keyAlias) + << aaptVersion(enableAapt2) + << packageType(generateAab)) + << enableAapt2 << generateAab << isIncrementalBuild << enableD8; + codeSign = false; + QTest::newRow("qt app aab no signing") + << "qt-app" << QStringList("qt-app") + << (QList<QByteArrayList>() << (QByteArrayList() << qtAppExpectedFiles(generateAab, + enableAapt2, + codeSign, + keyAlias))) + << (QStringList() << codeSignProperties(codeSign, keyStorePath, keystorePassword, + keyPassword, keyAlias) + << aaptVersion(enableAapt2) + << packageType(generateAab)) + << enableAapt2 << generateAab << isIncrementalBuild << enableD8; + + const QByteArrayList ndkArchsForQtSave = ndkArchsForQt; + ndkArchsForQt = {ndkArchsForQt.first()}; + QTest::newRow("qt app (single arch)") + << "qt-app" << QStringList("qt-app") + << (QList<QByteArrayList>() << (QByteArrayList() << qtAppExpectedFiles(generateAab, + enableAapt2))) + << QStringList{aaptVersion(enableAapt2), packageType(generateAab), + "modules.qbs.architectures:" + archsForQt.first()} + << enableAapt2 << generateAab << isIncrementalBuild << enableD8; + ndkArchsForQt = ndkArchsForQtSave; + + auto teaPotAppExpectedFiles = [&](const QByteArrayList &archs, bool generateAab) { + QByteArrayList expectedFile; + expectedFile << commonFiles(generateAab) + expandArchs(archs, { + "assets/Shaders/ShaderPlain.fsh", + "assets/Shaders/VS_ShaderPlain.vsh", + cxxLibPath("libgnustl_shared.so", false), + "lib/${ARCH}/libTeapotNativeActivity.so", + "res/layout/widgets.xml", + "res/mipmap-hdpi-v4/ic_launcher.png", + "res/mipmap-mdpi-v4/ic_launcher.png", + "res/mipmap-xhdpi-v4/ic_launcher.png", + "res/mipmap-xxhdpi-v4/ic_launcher.png"}, generateAab); + if (generateAab) + expectedFile << "base/resources.pb" << "base/assets.pb" << "base/native.pb"; + else + expectedFile << "resources.arsc"; + return expectedFile; + }; + generateAab = false; + enableAapt2 = false; + QTest::newRow("teapot") + << "teapot" << QStringList("TeapotNativeActivity") + << (QList<QByteArrayList>() << teaPotAppExpectedFiles(archs, generateAab)) + << QStringList{aaptVersion(enableAapt2), packageType(generateAab)} + << enableAapt2 << generateAab << isIncrementalBuild << enableD8; + enableAapt2 = true; + QTest::newRow("teapot aapt2") + << "teapot" << QStringList("TeapotNativeActivity") + << (QList<QByteArrayList>() << teaPotAppExpectedFiles(archs, generateAab)) + << QStringList{aaptVersion(enableAapt2), packageType(generateAab)} + << enableAapt2 << generateAab << isIncrementalBuild << enableD8; + generateAab = true; + QTest::newRow("teapot aapt2 aab") + << "teapot" << QStringList("TeapotNativeActivity") + << (QList<QByteArrayList>() << teaPotAppExpectedFiles(archs, generateAab)) + << QStringList{aaptVersion(enableAapt2), packageType(generateAab)} + << enableAapt2 << generateAab << isIncrementalBuild << enableD8; + enableAapt2 = false; + generateAab = false; + QTest::newRow("minimal-native") + << "minimal-native" << QStringList("minimalnative") + << (QList<QByteArrayList>() << commonFiles(generateAab) + expandArchs({archs.first()}, { + "lib/${ARCH}/libminimalnative.so", + cxxLibPath("libstlport_shared.so", false), + "lib/${ARCH}/libdependency.so"}, generateAab)) + << QStringList{"products.minimalnative.multiplexByQbsProperties:[]", + "modules.qbs.architecture:" + archsStringList.first(), + aaptVersion(enableAapt2)} + << enableAapt2 << generateAab << isIncrementalBuild << enableD8; + enableAapt2 = true; + QTest::newRow("minimal-native aapt2") + << "minimal-native" << QStringList("minimalnative") + << (QList<QByteArrayList>() << commonFiles(generateAab) + + (QByteArrayList() << "resources.arsc") + expandArchs({archs.first()}, { + "lib/${ARCH}/libminimalnative.so", + cxxLibPath("libstlport_shared.so", false), + "lib/${ARCH}/libdependency.so"}, generateAab)) + << QStringList{"products.minimalnative.multiplexByQbsProperties:[]", + "modules.qbs.architecture:" + archsStringList.first(), + aaptVersion(enableAapt2), packageType(generateAab)} + << enableAapt2 << generateAab << isIncrementalBuild << enableD8; + generateAab = true; + QTest::newRow("minimal-native aapt2 aab") + << "minimal-native" << QStringList("minimalnative") + << (QList<QByteArrayList>() << commonFiles(generateAab) + + (QByteArrayList() << "base/resources.pb" << "base/native.pb") + + expandArchs({archs.first()}, { + "lib/${ARCH}/libminimalnative.so", + cxxLibPath("libstlport_shared.so", false), + "lib/${ARCH}/libdependency.so"}, generateAab)) + << QStringList{"products.minimalnative.multiplexByQbsProperties:[]", + "modules.qbs.architecture:" + archsStringList.first(), + aaptVersion(enableAapt2), packageType(generateAab)} + << enableAapt2 << generateAab << isIncrementalBuild << enableD8; + auto qmlAppExpectedFiles = [&](bool generateAab, bool enableAapt2) { + QByteArrayList expectedFile; + if (singleArchQt) { + expectedFile << commonFiles(generateAab) + expandArchs(ndkArchsForQt, { + "assets/--Added-by-androiddeployqt--/qml/QtQuick.2/plugins.qmltypes", + "assets/--Added-by-androiddeployqt--/qml/QtQuick.2/qmldir", + "assets/--Added-by-androiddeployqt--/qml/QtQuick/Window.2/plugins.qmltypes", + "assets/--Added-by-androiddeployqt--/qml/QtQuick/Window.2/qmldir", + "assets/--Added-by-androiddeployqt--/qt_cache_pregenerated_file_list", + cxxLibPath("libgnustl_shared.so", true), + "lib/${ARCH}/libplugins_bearer_libqandroidbearer.so", + "lib/${ARCH}/libplugins_imageformats_libqgif.so", + "lib/${ARCH}/libplugins_imageformats_libqicns.so", + "lib/${ARCH}/libplugins_imageformats_libqico.so", + "lib/${ARCH}/libplugins_imageformats_libqjpeg.so", + "lib/${ARCH}/libplugins_imageformats_libqtga.so", + "lib/${ARCH}/libplugins_imageformats_libqtiff.so", + "lib/${ARCH}/libplugins_imageformats_libqwbmp.so", + "lib/${ARCH}/libplugins_imageformats_libqwebp.so", + "lib/${ARCH}/libplugins_platforms_android_libqtforandroid.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_debugger.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_inspector.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_local.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_messages.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_native.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_nativedebugger.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_profiler.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_preview.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_quickprofiler.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_server.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_tcp.so", + "lib/${ARCH}/libqml_QtQuick.2_libqtquick2plugin.so", + "lib/${ARCH}/libqml_QtQuick_Window.2_libwindowplugin.so", + "lib/${ARCH}/libQt5Core.so", + "lib/${ARCH}/libQt5Gui.so", + "lib/${ARCH}/libQt5Network.so", + "lib/${ARCH}/libQt5Qml.so", + "lib/${ARCH}/libQt5QuickParticles.so", + "lib/${ARCH}/libQt5Quick.so", + "lib/${ARCH}/libqmlapp.so"}, generateAab); + } else { + expectedFile << commonFiles(generateAab) + expandArchs(ndkArchsForQt, { + "assets/android_rcc_bundle.rcc", + cxxLibPath("libgnustl_shared.so", true), + "lib/${ARCH}/libplugins_imageformats_qgif_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qico_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qjpeg_${ARCH}.so", + "lib/${ARCH}/libplugins_platforms_qtforandroid_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_debugger_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_inspector_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_local_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_messages_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_native_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_nativedebugger_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_profiler_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_preview_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_quickprofiler_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_server_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_tcp_${ARCH}.so", + "lib/${ARCH}/libQt" + qtVersionMajor + "Core_${ARCH}.so", + "lib/${ARCH}/libQt" + qtVersionMajor + "Gui_${ARCH}.so", + "lib/${ARCH}/libQt" + qtVersionMajor + "Network_${ARCH}.so", + "lib/${ARCH}/libQt" + qtVersionMajor + "Qml_${ARCH}.so", + "lib/${ARCH}/libQt" + qtVersionMajor + "Quick_${ARCH}.so", + "lib/${ARCH}/libQt" + qtVersionMajor + "QmlModels_${ARCH}.so", + "lib/${ARCH}/libQt" + qtVersionMajor + "QmlWorkerScript_${ARCH}.so", + "lib/${ARCH}/libqmlapp_${ARCH}.so"}, generateAab); + if (version < qbs::Version(5, 15)) + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libQt5QuickParticles_${ARCH}.so"}, generateAab); + if (version >= qbs::Version(5, 15) && version < qbs::Version(6, 0)) + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libqml_QtQml_StateMachine_qtqmlstatemachine_${ARCH}.so", + "lib/${ARCH}/libqml_QtQml_WorkerScript.2_workerscriptplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQml_Models.2_modelsplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQml_qmlplugin_${ARCH}.so"}, generateAab); + if (version >= qbs::Version(5, 14) && version < qbs::Version(6, 0)) + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libqml_QtQuick.2_qtquick2plugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Window.2_windowplugin_${ARCH}.so"}, + generateAab); + if (version < qbs::Version(6, 0)) + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libplugins_bearer_qandroidbearer_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qicns_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qtga_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qtiff_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qwbmp_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qwebp_${ARCH}.so"}, generateAab); + if (version >= qbs::Version(6, 5)) + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libQt6Svg_${ARCH}.so", + "lib/${ARCH}/libplugins_iconengines_qsvgicon_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qsvg_${ARCH}.so"}, generateAab); + if (version >= qbs::Version(6, 0)) { + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libQt6OpenGL_${ARCH}.so", + "lib/${ARCH}/libqml_QtQml_Models_modelsplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQml_WorkerScript_workerscriptplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_qtquick2plugin_${ARCH}.so"}, generateAab); + if (version >= qbs::Version(6, 5)) + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libqml_QtQml_Base_qmlplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQml_qmlmetaplugin_${ARCH}.so"}, generateAab); + else + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libqml_QtQml_qmlplugin_${ARCH}.so"}, generateAab); + } + if (version >= qbs::Version(6, 2)) + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libplugins_networkinformation_qandroidnetworkinformation_${ARCH}.so", + "lib/${ARCH}/libplugins_tls_qcertonlybackend_${ARCH}.so", + "lib/${ARCH}/libplugins_tls_qopensslbackend_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Window_quickwindowplugin_${ARCH}.so", + }, generateAab); + + if (version >= qbs::Version(6, 0) && version < qbs::Version(6, 3)) { + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libQt6QuickControls2Impl_${ARCH}.so", + "lib/${ARCH}/libQt6QuickControls2_${ARCH}.so", + "lib/${ARCH}/libQt6QuickParticles_${ARCH}.so", + "lib/${ARCH}/libQt6QuickShapes_${ARCH}.so", + "lib/${ARCH}/libQt6QuickTemplates2_${ARCH}.so", + "lib/${ARCH}/libQt6Sql_${ARCH}.so", + "lib/${ARCH}/libplugins_sqldrivers_qsqlite_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Controls_Basic_impl_qtquickcontrols2basicstyleimplplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Controls_Basic_qtquickcontrols2basicstyleplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Controls_Fusion_impl_qtquickcontrols2fusionstyleimplplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Controls_Fusion_qtquickcontrols2fusionstyleplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Controls_Imagine_impl_qtquickcontrols2imaginestyleimplplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Controls_Imagine_qtquickcontrols2imaginestyleplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Controls_Material_impl_qtquickcontrols2materialstyleimplplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Controls_Material_qtquickcontrols2materialstyleplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Controls_Universal_impl_qtquickcontrols2universalstyleimplplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Controls_Universal_qtquickcontrols2universalstyleplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Controls_impl_qtquickcontrols2implplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Controls_qtquickcontrols2plugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_LocalStorage_qmllocalstorageplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_NativeStyle_qtquickcontrols2nativestyleplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Particles_particlesplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Shapes_qmlshapesplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Templates_qtquicktemplates2plugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Timeline_qtquicktimelineplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Layouts_qquicklayoutsplugin_${ARCH}.so"}, generateAab); + if (version >= qbs::Version(6, 2)) + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libqml_QtQuick_tooling_quicktoolingplugin_${ARCH}.so", + "lib/${ARCH}/libQt6QmlLocalStorage_${ARCH}.so", + "lib/${ARCH}/libQt6QmlXmlListModel_${ARCH}.so", + "lib/${ARCH}/libQt6QuickDialogs2QuickImpl_${ARCH}.so", + "lib/${ARCH}/libQt6QuickDialogs2Utils_${ARCH}.so", + "lib/${ARCH}/libQt6QuickDialogs2_${ARCH}.so", + "lib/${ARCH}/libQt6QuickLayouts_${ARCH}.so", + "lib/${ARCH}/libQt6QuickTimeline_${ARCH}.so", + "lib/${ARCH}/libqml_QtQml_XmlListModel_qmlxmllistmodelplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Dialogs_qtquickdialogsplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Dialogs_quickimpl_qtquickdialogs2quickimplplugin_${ARCH}.so"}, + generateAab); + else + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libqml_QtQuick_Window_quickwindow_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_tooling_quicktooling_${ARCH}.so"}, generateAab); + } + } + if (generateAab) + expectedFile << "base/resources.pb" << "base/assets.pb" << "base/native.pb"; + else + expectedFile << "resources.arsc"; + if (!enableAapt2 && version < qbs::Version(6, 0)) + expectedFile << "res/layout/splash.xml"; + return expectedFile; + }; + auto qmlAppCustomMetaDataExpectedFiles = [&](bool generateAab, bool enableAapt2) { + QByteArrayList expectedFile; + if (singleArchQt) { + expectedFile << commonFiles(generateAab) + expandArchs(ndkArchsForQt, { + "assets/--Added-by-androiddeployqt--/qml/QtQuick.2/plugins.qmltypes", + "assets/--Added-by-androiddeployqt--/qml/QtQuick.2/qmldir", + "assets/--Added-by-androiddeployqt--/qml/QtQuick/Window.2/plugins.qmltypes", + "assets/--Added-by-androiddeployqt--/qml/QtQuick/Window.2/qmldir", + "assets/--Added-by-androiddeployqt--/qt_cache_pregenerated_file_list", + "assets/dummyasset.txt", + cxxLibPath("libgnustl_shared.so", true), + "lib/${ARCH}/libplugins_bearer_libqandroidbearer.so", + "lib/${ARCH}/libplugins_imageformats_libqgif.so", + "lib/${ARCH}/libplugins_imageformats_libqicns.so", + "lib/${ARCH}/libplugins_imageformats_libqico.so", + "lib/${ARCH}/libplugins_imageformats_libqjpeg.so", + "lib/${ARCH}/libplugins_imageformats_libqtga.so", + "lib/${ARCH}/libplugins_imageformats_libqtiff.so", + "lib/${ARCH}/libplugins_imageformats_libqwbmp.so", + "lib/${ARCH}/libplugins_imageformats_libqwebp.so", + "lib/${ARCH}/libplugins_platforms_android_libqtforandroid.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_debugger.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_inspector.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_local.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_messages.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_native.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_nativedebugger.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_profiler.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_preview.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_quickprofiler.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_server.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_tcp.so", + "lib/${ARCH}/libqml_QtQuick.2_libqtquick2plugin.so", + "lib/${ARCH}/libqml_QtQuick_Window.2_libwindowplugin.so", + "lib/${ARCH}/libQt5Core.so", + "lib/${ARCH}/libQt5Gui.so", + "lib/${ARCH}/libQt5Network.so", + "lib/${ARCH}/libQt5Qml.so", + "lib/${ARCH}/libQt5QuickParticles.so", + "lib/${ARCH}/libQt5Quick.so", + "lib/${ARCH}/libqmlapp.so"}, generateAab); + } else { + expectedFile << commonFiles(generateAab) + expandArchs(ndkArchsForQt, { + "assets/android_rcc_bundle.rcc", + "assets/dummyasset.txt", + cxxLibPath("libgnustl_shared.so", true), + "lib/${ARCH}/libplugins_imageformats_qgif_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qico_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qjpeg_${ARCH}.so", + "lib/${ARCH}/libplugins_platforms_qtforandroid_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_debugger_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_inspector_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_local_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_messages_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_native_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_nativedebugger_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_profiler_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_preview_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_quickprofiler_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_server_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_tcp_${ARCH}.so", + "lib/${ARCH}/libQt" + qtVersionMajor + "Core_${ARCH}.so", + "lib/${ARCH}/libQt" + qtVersionMajor + "Gui_${ARCH}.so", + "lib/${ARCH}/libQt" + qtVersionMajor + "Network_${ARCH}.so", + "lib/${ARCH}/libQt" + qtVersionMajor + "Qml_${ARCH}.so", + "lib/${ARCH}/libQt" + qtVersionMajor + "Quick_${ARCH}.so", + "lib/${ARCH}/libQt" + qtVersionMajor + "QmlModels_${ARCH}.so", + "lib/${ARCH}/libQt" + qtVersionMajor + "QmlWorkerScript_${ARCH}.so", + "lib/${ARCH}/libqmlapp_${ARCH}.so"}, generateAab); + if (version < qbs::Version(5, 15)) + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libQt5QuickParticles_${ARCH}.so"}, generateAab); + if (version >= qbs::Version(5, 15) && version < qbs::Version(6, 0)) + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libqml_QtQml_StateMachine_qtqmlstatemachine_${ARCH}.so", + "lib/${ARCH}/libqml_QtQml_WorkerScript.2_workerscriptplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQml_Models.2_modelsplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQml_qmlplugin_${ARCH}.so"}, generateAab); + if (version >= qbs::Version(5, 14) && version < qbs::Version(6, 0)) + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libqml_QtQuick.2_qtquick2plugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Window.2_windowplugin_${ARCH}.so"}, + generateAab); + if (version < qbs::Version(6, 0)) + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libplugins_bearer_qandroidbearer_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qicns_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qtga_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qtiff_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qwbmp_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qwebp_${ARCH}.so"}, generateAab); + if (version >= qbs::Version(6, 5)) + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libQt6Svg_${ARCH}.so", + "lib/${ARCH}/libplugins_iconengines_qsvgicon_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qsvg_${ARCH}.so"}, generateAab); + if (version >= qbs::Version(6, 0)) { + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libQt6OpenGL_${ARCH}.so", + "lib/${ARCH}/libqml_QtQml_Models_modelsplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQml_WorkerScript_workerscriptplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_qtquick2plugin_${ARCH}.so"}, generateAab); + if (version >= qbs::Version(6, 5)) + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libqml_QtQml_Base_qmlplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQml_qmlmetaplugin_${ARCH}.so"}, generateAab); + else + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libqml_QtQml_qmlplugin_${ARCH}.so"}, generateAab); + } + if (version >= qbs::Version(6, 2)) + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libplugins_networkinformation_qandroidnetworkinformation_${ARCH}.so", + "lib/${ARCH}/libplugins_tls_qcertonlybackend_${ARCH}.so", + "lib/${ARCH}/libplugins_tls_qopensslbackend_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Window_quickwindowplugin_${ARCH}.so", + }, generateAab); + if (version >= qbs::Version(6, 0) && version < qbs::Version(6, 3)) { + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libQt6QuickControls2Impl_${ARCH}.so", + "lib/${ARCH}/libQt6QuickControls2_${ARCH}.so", + "lib/${ARCH}/libQt6QuickParticles_${ARCH}.so", + "lib/${ARCH}/libQt6QuickShapes_${ARCH}.so", + "lib/${ARCH}/libQt6QuickTemplates2_${ARCH}.so", + "lib/${ARCH}/libQt6Sql_${ARCH}.so", + "lib/${ARCH}/libplugins_sqldrivers_qsqlite_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Controls_Basic_impl_qtquickcontrols2basicstyleimplplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Controls_Basic_qtquickcontrols2basicstyleplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Controls_Fusion_impl_qtquickcontrols2fusionstyleimplplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Controls_Fusion_qtquickcontrols2fusionstyleplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Controls_Imagine_impl_qtquickcontrols2imaginestyleimplplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Controls_Imagine_qtquickcontrols2imaginestyleplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Controls_Material_impl_qtquickcontrols2materialstyleimplplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Controls_Material_qtquickcontrols2materialstyleplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Controls_Universal_impl_qtquickcontrols2universalstyleimplplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Controls_Universal_qtquickcontrols2universalstyleplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Controls_impl_qtquickcontrols2implplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Controls_qtquickcontrols2plugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_LocalStorage_qmllocalstorageplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_NativeStyle_qtquickcontrols2nativestyleplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Particles_particlesplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Shapes_qmlshapesplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Templates_qtquicktemplates2plugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Timeline_qtquicktimelineplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Layouts_qquicklayoutsplugin_${ARCH}.so"}, generateAab); + if (version >= qbs::Version(6, 2)) + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libqml_QtQuick_tooling_quicktoolingplugin_${ARCH}.so", + "lib/${ARCH}/libQt6QmlLocalStorage_${ARCH}.so", + "lib/${ARCH}/libQt6QmlXmlListModel_${ARCH}.so", + "lib/${ARCH}/libQt6QuickDialogs2QuickImpl_${ARCH}.so", + "lib/${ARCH}/libQt6QuickDialogs2Utils_${ARCH}.so", + "lib/${ARCH}/libQt6QuickDialogs2_${ARCH}.so", + "lib/${ARCH}/libQt6QuickLayouts_${ARCH}.so", + "lib/${ARCH}/libQt6QuickTimeline_${ARCH}.so", + "lib/${ARCH}/libqml_QtQml_XmlListModel_qmlxmllistmodelplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Dialogs_qtquickdialogsplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Dialogs_quickimpl_qtquickdialogs2quickimplplugin_${ARCH}.so"}, + generateAab); + else + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libqml_QtQuick_Window_quickwindow_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_tooling_quicktooling_${ARCH}.so"}, generateAab); + } + } + if (generateAab) + expectedFile << "base/resources.pb" << "base/assets.pb" << "base/native.pb"; + else + expectedFile << "resources.arsc"; + if (!enableAapt2 && version < qbs::Version(6, 0)) + expectedFile << "res/layout/splash.xml"; + return expectedFile; + }; + QStringList qmlAppCustomProperties; + if (singleArchQt) { + qmlAppCustomProperties = QStringList{"modules.Android.sdk.automaticSources:false", + "modules.qbs.architecture:" + archsForQt.first()}; + } else { + qmlAppCustomProperties = QStringList{"modules.Android.sdk.automaticSources:false"}; + } + // aapt tool for the resources works with a directory option pointing to the parent directory + // of the resources (res). + // The Qt.android_support module adds res/values/libs.xml (from Qt install dir). So the res from + // Qt install res directory is added to aapt. This results in adding res/layout/splash.xml to + // the package eventhough the file is not needed. + // On the other hand aapt2 requires giving all the resources files. + // Also when enabling aapt2 the resources.arsc is always created, eventhough no resources are + // declared. + enableAapt2 = false; + generateAab = false; + QTest::newRow("qml app") + << "qml-app" << QStringList("qmlapp") + << (QList<QByteArrayList>() << qmlAppExpectedFiles(generateAab, enableAapt2)) + << (QStringList() << qmlAppCustomProperties << aaptVersion(enableAapt2) + << packageType(generateAab)) + << enableAapt2 << generateAab << isIncrementalBuild << enableD8; + enableAapt2 = true; + QTest::newRow("qml app aapt2") + << "qml-app" << QStringList("qmlapp") + << (QList<QByteArrayList>() << qmlAppExpectedFiles(generateAab, enableAapt2)) + << (QStringList() << qmlAppCustomProperties << aaptVersion(enableAapt2) + << packageType(generateAab)) + << enableAapt2 << generateAab << isIncrementalBuild << enableD8; + generateAab = true; + QTest::newRow("qml app aab") + << "qml-app" << QStringList("qmlapp") + << (QList<QByteArrayList>() << qmlAppExpectedFiles(generateAab, enableAapt2)) + << (QStringList() << qmlAppCustomProperties << aaptVersion(enableAapt2) + << packageType(generateAab)) + << enableAapt2 << generateAab << isIncrementalBuild << enableD8; + enableAapt2 = false; + generateAab = false; QTest::newRow("qml app with custom metadata") << "qml-app" << QStringList("qmlapp") - << (QList<QByteArrayList>() << commonFiles + expandArchs(ndkArchsForQt, { - "resources.arsc", - "assets/--Added-by-androiddeployqt--/qml/QtQuick.2/plugins.qmltypes", - "assets/--Added-by-androiddeployqt--/qml/QtQuick.2/qmldir", - "assets/--Added-by-androiddeployqt--/qml/QtQuick/Window.2/plugins.qmltypes", - "assets/--Added-by-androiddeployqt--/qml/QtQuick/Window.2/qmldir", - "assets/--Added-by-androiddeployqt--/qt_cache_pregenerated_file_list", - "assets/dummyasset.txt", - "lib/${ARCH}/libgdbserver.so", - cxxLibPath("libgnustl_shared.so", true), - "lib/${ARCH}/libplugins_bearer_libqandroidbearer.so", - "lib/${ARCH}/libplugins_imageformats_libqgif.so", - "lib/${ARCH}/libplugins_imageformats_libqicns.so", - "lib/${ARCH}/libplugins_imageformats_libqico.so", - "lib/${ARCH}/libplugins_imageformats_libqjpeg.so", - "lib/${ARCH}/libplugins_imageformats_libqtga.so", - "lib/${ARCH}/libplugins_imageformats_libqtiff.so", - "lib/${ARCH}/libplugins_imageformats_libqwbmp.so", - "lib/${ARCH}/libplugins_imageformats_libqwebp.so", - "lib/${ARCH}/libplugins_platforms_android_libqtforandroid.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_debugger.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_inspector.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_local.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_messages.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_native.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_nativedebugger.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_profiler.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_preview.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_quickprofiler.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_server.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_tcp.so", - "lib/${ARCH}/libqml_QtQuick.2_libqtquick2plugin.so", - "lib/${ARCH}/libqml_QtQuick_Window.2_libwindowplugin.so", - "lib/${ARCH}/libQt5Core.so", - "lib/${ARCH}/libQt5Gui.so", - "lib/${ARCH}/libQt5Network.so", - "lib/${ARCH}/libQt5Qml.so", - "lib/${ARCH}/libQt5QuickParticles.so", - "lib/${ARCH}/libQt5Quick.so", - "lib/${ARCH}/libqmlapp.so", - "res/layout/splash.xml"})) - << QStringList("modules.Android.sdk.automaticSources:true"); + << (QList<QByteArrayList>() << (QByteArrayList() + << qmlAppCustomMetaDataExpectedFiles(generateAab, + enableAapt2))) + << QStringList{"modules.Android.sdk.automaticSources:true", + aaptVersion(enableAapt2), packageType(generateAab)} + << enableAapt2 << generateAab << isIncrementalBuild << enableD8; + enableAapt2 = true; + QTest::newRow("qml app with custom metadata aapt2") + << "qml-app" << QStringList("qmlapp") + << (QList<QByteArrayList>() << (QByteArrayList() + << qmlAppCustomMetaDataExpectedFiles(generateAab, + enableAapt2))) + << QStringList{"modules.Android.sdk.automaticSources:true", aaptVersion(enableAapt2), + packageType(generateAab)} + << enableAapt2 << generateAab << isIncrementalBuild << enableD8; + generateAab = true; + if (!singleArchQt) { + QTest::newRow("qml app with custom metadata aab") + << "qml-app" << QStringList("qmlapp") + << (QList<QByteArrayList>() << (QByteArrayList() + << qmlAppCustomMetaDataExpectedFiles(generateAab, + enableAapt2))) + << QStringList{"modules.Android.sdk.automaticSources:true", aaptVersion(enableAapt2), + packageType(generateAab)} + << enableAapt2 << generateAab << isIncrementalBuild << enableD8; + } + isIncrementalBuild = false; + enableAapt2 = false; + generateAab = false; + auto noNativeExpectedFiles = [&](bool generateAab) { + QByteArrayList expectedFile; + expectedFile << commonFiles(generateAab) + expandArchs(archs, { + "res/drawable-hdpi-v4/ic_action_play_disabled.png", + "res/drawable-hdpi-v4/ic_action_play.png", + "res/drawable-hdpi-v4/ic_launcher.png", + "res/drawable-hdpi-v4/tile.9.png", + "res/drawable-mdpi-v4/ic_action_play_disabled.png", + "res/drawable-mdpi-v4/ic_action_play.png", + "res/drawable-mdpi-v4/ic_launcher.png", + "res/drawable/selector_play.xml", + "res/drawable-xhdpi-v4/ic_action_play_disabled.png", + "res/drawable-xhdpi-v4/ic_action_play.png", + "res/drawable-xhdpi-v4/ic_launcher.png", + "res/drawable-xxhdpi-v4/ic_launcher.png", + "res/layout/sample_main.xml", + "res/menu/action_menu.xml", + "res/raw/vid_bigbuckbunny.mp4"}, generateAab); + if (generateAab) + expectedFile << "base/resources.pb"; + else + expectedFile << "resources.arsc"; + return expectedFile; + }; + QTest::newRow("no native") << "no-native" << QStringList("com.example.android.basicmediadecoder") - << (QList<QByteArrayList>() << commonFiles + expandArchs(archs, { - "resources.arsc", - "res/drawable-hdpi-v4/ic_action_play_disabled.png", - "res/drawable-hdpi-v4/ic_action_play.png", - "res/drawable-hdpi-v4/ic_launcher.png", - "res/drawable-hdpi-v4/tile.9.png", - "res/drawable-mdpi-v4/ic_action_play_disabled.png", - "res/drawable-mdpi-v4/ic_action_play.png", - "res/drawable-mdpi-v4/ic_launcher.png", - "res/drawable/selector_play.xml", - "res/drawable-xhdpi-v4/ic_action_play_disabled.png", - "res/drawable-xhdpi-v4/ic_action_play.png", - "res/drawable-xhdpi-v4/ic_launcher.png", - "res/drawable-xxhdpi-v4/ic_launcher.png", - "res/layout/sample_main.xml", - "res/menu/action_menu.xml", - "res/menu-v11/action_menu.xml", - "res/raw/vid_bigbuckbunny.mp4"})) - << QStringList(); + << (QList<QByteArrayList>() << noNativeExpectedFiles(generateAab)) + << QStringList{aaptVersion(enableAapt2), packageType(generateAab)} + << enableAapt2 << generateAab << isIncrementalBuild << enableD8; + enableAapt2 = true; + QTest::newRow("no native aapt2") + << "no-native" + << QStringList("com.example.android.basicmediadecoder") + << (QList<QByteArrayList>() << noNativeExpectedFiles(generateAab)) + << QStringList{aaptVersion(enableAapt2), packageType(generateAab)} + << enableAapt2 << generateAab << isIncrementalBuild << enableD8; + generateAab = true; + QTest::newRow("no native aab") + << "no-native" + << QStringList("com.example.android.basicmediadecoder") + << (QList<QByteArrayList>() << noNativeExpectedFiles(generateAab)) + << QStringList{aaptVersion(enableAapt2), packageType(generateAab)} + << enableAapt2 << generateAab << isIncrementalBuild << enableD8; + enableAapt2 = false; + generateAab = false; QTest::newRow("aidl") << "aidl" << QStringList("io.qbs.aidltest") - << QList<QByteArrayList>{commonFiles} << QStringList(); + << (QList<QByteArrayList>() << (QByteArrayList() + << commonFiles(generateAab))) + << QStringList{aaptVersion(enableAapt2), packageType(generateAab)} + << enableAapt2 << generateAab << isIncrementalBuild << enableD8; + enableAapt2 = true; + QTest::newRow("aidl aapt2") << "aidl" << QStringList("io.qbs.aidltest") + << (QList<QByteArrayList>() << (QByteArrayList() + << commonFiles(generateAab) + << "resources.arsc")) + << QStringList{aaptVersion(enableAapt2), packageType(generateAab)} + << enableAapt2 << generateAab << isIncrementalBuild << enableD8; + generateAab = true; + QTest::newRow("aidl aab") << "aidl" << QStringList("io.qbs.aidltest") + << (QList<QByteArrayList>() << (QByteArrayList() + << commonFiles(generateAab) + << "base/resources.pb")) + << QStringList{aaptVersion(enableAapt2), packageType(generateAab)} + << enableAapt2 << generateAab << isIncrementalBuild << enableD8; + enableAapt2 = false; + generateAab = false; + enableD8 = false; QTest::newRow("multiple libs") << "multiple-libs-per-apk" << QStringList("twolibs") - << (QList<QByteArrayList>() << commonFiles + expandArchs(archs, { + << (QList<QByteArrayList>() << commonFiles(generateAab) + expandArchs(archs, { + "resources.arsc", + "lib/${ARCH}/liblib1.so", + "lib/${ARCH}/liblib2.so", + cxxLibPath("libstlport_shared.so", false)}, generateAab)) + << QStringList{aaptVersion(enableAapt2), packageType(generateAab), + dexCompilerVersion(enableD8)} + << enableAapt2 << generateAab << isIncrementalBuild << enableD8; + enableD8 = true; + QTest::newRow("multiple libs with d8") + << "multiple-libs-per-apk" + << QStringList("twolibs") + << (QList<QByteArrayList>() << commonFiles(generateAab) + expandArchs(archs, { + "resources.arsc", + "lib/${ARCH}/liblib1.so", + "lib/${ARCH}/liblib2.so", + cxxLibPath("libstlport_shared.so", false)}, generateAab)) + << QStringList{aaptVersion(enableAapt2), packageType(generateAab), + dexCompilerVersion(enableD8)} + << enableAapt2 << generateAab << isIncrementalBuild << enableD8; + enableD8 = false; + enableAapt2 = true; + QTest::newRow("multiple libs aapt2") + << "multiple-libs-per-apk" + << QStringList("twolibs") + << (QList<QByteArrayList>() << commonFiles(generateAab) + expandArchs(archs, { "resources.arsc", - "lib/${ARCH}/libgdbserver.so", "lib/${ARCH}/liblib1.so", "lib/${ARCH}/liblib2.so", - cxxLibPath("libstlport_shared.so", false)})) - << QStringList(); - QByteArrayList expectedFiles1 = (commonFiles - + expandArchs(QByteArrayList{"armeabi-v7a", "x86"}, { - "resources.arsc", - "lib/${ARCH}/libgdbserver.so", - "lib/${ARCH}/libp1lib1.so", - cxxLibPath("libstlport_shared.so", false)}) - + expandArchs(QByteArrayList{archs}, { - "resources.arsc", - "lib/${ARCH}/libgdbserver.so", - "lib/${ARCH}/libp1lib2.so", - cxxLibPath("libstlport_shared.so", false)})).toSet().toList(); - QByteArrayList expectedFiles2 = commonFiles + expandArchs(archs, { - "lib/${ARCH}/libgdbserver.so", - "lib/${ARCH}/libp2lib1.so", - "lib/${ARCH}/libp2lib2.so", - cxxLibPath("libstlport_shared.so", false)}); + cxxLibPath("libstlport_shared.so", false)}, generateAab)) + << QStringList{aaptVersion(enableAapt2), packageType(generateAab), + dexCompilerVersion(enableD8)} + << enableAapt2 << generateAab << isIncrementalBuild << enableD8; + generateAab = true; + QTest::newRow("multiple libs aab") + << "multiple-libs-per-apk" + << QStringList("twolibs") + << (QList<QByteArrayList>() << commonFiles(generateAab) + expandArchs(archs, { + "resources.pb", "native.pb", + "lib/${ARCH}/liblib1.so", + "lib/${ARCH}/liblib2.so", + cxxLibPath("libstlport_shared.so", false)}, generateAab)) + << QStringList{aaptVersion(enableAapt2), packageType(generateAab), + dexCompilerVersion(enableD8)} + << enableAapt2 << generateAab << isIncrementalBuild << enableD8; + + enableAapt2 = false; + generateAab = false; + auto expectedFiles1 = [&](bool generateAab) { + QByteArrayList expectedFile = qbs::toList(qbs::toSet(commonFiles(generateAab) + + expandArchs(QByteArrayList{"armeabi-v7a", "x86"}, { + "lib/${ARCH}/libp1lib1.so", + cxxLibPath("libstlport_shared.so", false)}, generateAab) + + expandArchs(QByteArrayList{archs}, { + "lib/${ARCH}/libp1lib2.so", + cxxLibPath("libstlport_shared.so", false)}, generateAab))); + if (generateAab) + expectedFile << "base/resources.pb" << "base/native.pb"; + else + expectedFile << "resources.arsc"; + return expectedFile; + }; + auto expectedFiles2 = [&](bool generateAab) { + QByteArrayList expectedFile = commonFiles(generateAab) + expandArchs(archs, { + "lib/${ARCH}/libp2lib1.so", + "lib/${ARCH}/libp2lib2.so", + cxxLibPath("libstlport_shared.so", false)}, generateAab); + return expectedFile; + }; QTest::newRow("multiple apks") << "multiple-apks-per-project" << (QStringList() << "twolibs1" << "twolibs2") - << QList<QByteArrayList>{expectedFiles1, expectedFiles2} - << QStringList(); + << QList<QByteArrayList>{expectedFiles1(generateAab), expectedFiles2(generateAab)} + << QStringList{aaptVersion(enableAapt2), packageType(generateAab), + dexCompilerVersion(enableD8)} + << enableAapt2 << generateAab << isIncrementalBuild << enableD8; + enableAapt2 = true; + QTest::newRow("multiple apks aapt2") + << "multiple-apks-per-project" + << (QStringList() << "twolibs1" << "twolibs2") + << (QList<QByteArrayList>() << expectedFiles1(generateAab) + << (QByteArrayList() << expectedFiles2(generateAab) << "resources.arsc")) + << QStringList{aaptVersion(enableAapt2), packageType(generateAab), + dexCompilerVersion(enableD8)} + << enableAapt2 << generateAab << isIncrementalBuild << enableD8; + generateAab = true; + QTest::newRow("multiple apks aab") + << "multiple-apks-per-project" + << (QStringList() << "twolibs1" << "twolibs2") + << (QList<QByteArrayList>() << expectedFiles1(generateAab) + << (QByteArrayList() << expectedFiles2(generateAab) << "base/resources.pb" + << "base/native.pb")) + << QStringList{aaptVersion(enableAapt2), packageType(generateAab), + dexCompilerVersion(enableD8)} + << enableAapt2 << generateAab << isIncrementalBuild << enableD8; } QTEST_MAIN(TestBlackboxAndroid) diff --git a/tests/auto/blackbox/tst_blackboxapple.cpp b/tests/auto/blackbox/tst_blackboxapple.cpp index 96cd70b58..30e20a1c9 100644 --- a/tests/auto/blackbox/tst_blackboxapple.cpp +++ b/tests/auto/blackbox/tst_blackboxapple.cpp @@ -31,7 +31,9 @@ #include "../shared.h" #include <tools/hostosinfo.h> #include <tools/profile.h> +#include <tools/qttools.h> +#include <QtCore/qdiriterator.h> #include <QtCore/qjsondocument.h> #include <QtCore/qjsonobject.h> #include <QtXml/qdom.h> @@ -60,6 +62,117 @@ static QString getEmbeddedBinaryPlist(const QString &file) return QString::fromUtf8(p.readAllStandardOutput()).trimmed(); } +static QVariantMap readInfoPlistFile(const QString &infoPlistPath) +{ + if (!QFile::exists(infoPlistPath)) { + qWarning() << infoPlistPath << "doesn't exist"; + return {}; + } + + QProcess plutil; + plutil.start("plutil", { + QStringLiteral("-convert"), + QStringLiteral("json"), + infoPlistPath + }); + if (!plutil.waitForStarted()) { + qWarning() << plutil.errorString(); + return {}; + } + if (!plutil.waitForFinished()) { + qWarning() << plutil.errorString(); + return {}; + } + if (plutil.exitCode() != 0) { + qWarning() << plutil.readAllStandardError().constData(); + return {}; + } + + QFile infoPlist(infoPlistPath); + if (!infoPlist.open(QIODevice::ReadOnly)) { + qWarning() << infoPlist.errorString(); + return {}; + } + QJsonParseError error; + const auto json = QJsonDocument::fromJson(infoPlist.readAll(), &error); + if (error.error != QJsonParseError::NoError) { + qWarning() << error.errorString(); + return {}; + } + return json.object().toVariantMap(); +} + +static QString getInfoPlistPath(const QString &bundlePath) +{ + QFileInfo contents(bundlePath + "/Contents"); + if (contents.exists() && contents.isDir()) + return contents.filePath() + "/Info.plist"; // macOS bundle + return bundlePath + "/Info.plist"; +} + +static bool testVariantListType(const QVariant &variant, QMetaType::Type type) +{ + if (variant.userType() != QMetaType::QVariantList) + return false; + for (const auto &value : variant.toList()) { + if (value.userType() != type) + return false; + } + return true; +} + +static QString findFatLibrary(const QString &dir, const QString &libraryName) +{ + QDirIterator it(dir, {}, QDir::AllEntries, QDirIterator::Subdirectories); + while (it.hasNext()) { + it.next(); + if (it.fileInfo().fileName() == libraryName) { + QProcess lipo; + lipo.start("lipo", { QStringLiteral("-info"), it.filePath() }); + if (!lipo.waitForStarted() || !lipo.waitForFinished() || lipo.exitCode() != 0) + return {}; + auto output = lipo.readAllStandardOutput(); + if (output.contains(QByteArrayLiteral("Architectures in the fat file"))) + return QDir::cleanPath(it.filePath()); + } + } + + return {}; +} + +enum class CodeSignResult { Failed = 0, Signed, Unsigned }; +using CodeSignData = QMap<QByteArray, QByteArray>; +static std::pair<CodeSignResult, CodeSignData> parseCodeSignOutput(const QByteArray &output) +{ + CodeSignData data; + if (output.contains("code object is not signed at all")) + return {CodeSignResult::Unsigned, data}; + const auto lines = output.split('\n'); + for (const auto &line: lines) { + if (line.isEmpty() + || line.startsWith("CodeDirectory") + || line.startsWith("Sealed Resources") + || line.startsWith("Internal requirements")) { + continue; + } + const int index = line.indexOf('='); + if (index == -1) + return {CodeSignResult::Failed, {}}; + data[line.mid(0, index)] = line.mid(index + 1); + } + return {CodeSignResult::Signed, data}; +} + +static std::pair<CodeSignResult, CodeSignData> getCodeSignInfo(const QString &path) +{ + QProcess codesign; + codesign.start("codesign", { QStringLiteral("-dv"), path }); + if (!codesign.waitForStarted() || !codesign.waitForFinished()) + return {CodeSignResult::Failed, {}}; + const auto output = codesign.readAllStandardError(); + return parseCodeSignOutput(output); +} + TestBlackboxApple::TestBlackboxApple() : TestBlackboxBase (SRCDIR "/testdata-apple", "blackbox-apple") { @@ -78,106 +191,190 @@ void TestBlackboxApple::initTestCase() void TestBlackboxApple::appleMultiConfig() { const auto xcodeVersion = findXcodeVersion(); - const bool supportsX86 = xcodeVersion < qbs::Version(10); - + if (!xcodeVersion) + QSKIP("requires Xcode profile"); QDir::setCurrent(testDataDir + "/apple-multiconfig"); QCOMPARE(runQbs(QbsRunParameters(QStringList{ "qbs.installPrefix:''", - QString("project.enableX86:") + (supportsX86 ? "true" : "false")})), 0); - - QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp.app/Contents/MacOS/singleapp").isExecutable()); - QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp.app/Contents/Info.plist").isRegularFile()); - QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp.app/Contents/PkgInfo").isRegularFile()); - - QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp_agg.app/Contents/MacOS/singleapp_agg").isExecutable()); - QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp_agg.app/Contents/Info.plist").isRegularFile()); - QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp_agg.app/Contents/PkgInfo").isRegularFile()); - - QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/singlelib").isFileSymLink()); - QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/Resources").isDirSymLink()); - QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/Versions").isRegularDir()); - QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/Versions/A").isRegularDir()); - QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/Versions/A/singlelib").isRegularFile()); - QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/Versions/A/Resources").isRegularDir()); - QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/Versions/A/Resources/Info.plist").isRegularFile()); - QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/Versions/Current").isDirSymLink()); - - QVERIFY(QFileInfo2(defaultInstallRoot + "/multiapp.app/Contents/MacOS/multiapp").isExecutable()); - QVERIFY(QFileInfo2(defaultInstallRoot + "/multiapp.app/Contents/Info.plist").isRegularFile()); - QVERIFY(QFileInfo2(defaultInstallRoot + "/multiapp.app/Contents/PkgInfo").isRegularFile()); - - QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiapp.app/Contents/MacOS/fatmultiapp").isExecutable()); - QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiapp.app/Contents/Info.plist").isRegularFile()); - QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiapp.app/Contents/PkgInfo").isRegularFile()); - - QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiappmultivariant.app/Contents/MacOS/" - "fatmultiappmultivariant").isFileSymLink()); - QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiappmultivariant.app/Contents/MacOS/" - "fatmultiappmultivariant_debug").isExecutable()); - QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiappmultivariant.app/Contents/MacOS/" - "fatmultiappmultivariant_profile").isExecutable()); - QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiappmultivariant.app/Contents/Info.plist") - .isRegularFile()); - QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiappmultivariant.app/Contents/PkgInfo") - .isRegularFile()); - - QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/multilib").isFileSymLink()); - QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Resources").isDirSymLink()); - QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions").isRegularDir()); - QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions/A").isRegularDir()); - QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions/A/multilib").isRegularFile()); - QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions/A/multilib_debug").isRegularFile()); - QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions/A/multilib_profile").isRegularFile()); - QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions/A/Resources").isRegularDir()); - QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions/A/Resources/Info.plist").isRegularFile()); - QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions/Current").isDirSymLink()); - - for (const QString &variant : { "release", "debug", "profile" }) { - for (const QString &arch : { "x86_64" }) { - QProcess process; - process.setProgram("/usr/bin/arch"); - process.setArguments({ - "-arch", arch, - "-e", "DYLD_IMAGE_SUFFIX=_" + variant, - defaultInstallRoot + "/multiapp.app/Contents/MacOS/multiapp" - }); - process.start(); - process.waitForFinished(); - QCOMPARE(process.exitCode(), 0); - const auto processStdout = process.readAllStandardOutput(); - QVERIFY2(processStdout.contains("Hello from " + variant.toUtf8() + " " + arch.toUtf8()), - processStdout.constData()); + QStringLiteral("project.xcodeVersion:") + xcodeVersion->toString()})), 0); + + if (m_qbsStdout.contains("isShallow: false")) { + QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp.app/Contents/MacOS/singleapp").isExecutable()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp.app/Contents/Info.plist").isRegularFile()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp.app/Contents/PkgInfo").isRegularFile()); + + QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp_agg.app/Contents/MacOS/singleapp_agg").isExecutable()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp_agg.app/Contents/Info.plist").isRegularFile()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp_agg.app/Contents/PkgInfo").isRegularFile()); + + QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/singlelib").isFileSymLink()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/Resources").isDirSymLink()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/Versions").isRegularDir()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/Versions/A").isRegularDir()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/Versions/A/singlelib").isRegularFile()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/Versions/A/Resources").isRegularDir()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/Versions/A/Resources/Info.plist").isRegularFile()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/Versions/Current").isDirSymLink()); + + QVERIFY(QFileInfo2(defaultInstallRoot + "/multiapp.app/Contents/MacOS/multiapp").isExecutable()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/multiapp.app/Contents/Info.plist").isRegularFile()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/multiapp.app/Contents/PkgInfo").isRegularFile()); + + QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiapp.app/Contents/MacOS/fatmultiapp").isExecutable()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiapp.app/Contents/Info.plist").isRegularFile()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiapp.app/Contents/PkgInfo").isRegularFile()); + + QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiappmultivariant.app/Contents/MacOS/" + "fatmultiappmultivariant").isFileSymLink()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiappmultivariant.app/Contents/MacOS/" + "fatmultiappmultivariant_debug").isExecutable()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiappmultivariant.app/Contents/MacOS/" + "fatmultiappmultivariant_profiling").isExecutable()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiappmultivariant.app/Contents/Info.plist") + .isRegularFile()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiappmultivariant.app/Contents/PkgInfo") + .isRegularFile()); + + QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/multilib").isFileSymLink()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Resources").isDirSymLink()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions").isRegularDir()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions/A").isRegularDir()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions/A/multilib").isRegularFile()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions/A/multilib_debug").isRegularFile()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions/A/multilib_profiling").isRegularFile()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions/A/Resources").isRegularDir()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions/A/Resources/Info.plist").isRegularFile()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions/Current").isDirSymLink()); + + for (const QString variant : { "release", "debug", "profiling" }) { + for (const QString arch : { "x86_64" }) { + QProcess process; + process.setProgram("/usr/bin/arch"); + process.setArguments({ + "-arch", arch, + "-e", "DYLD_IMAGE_SUFFIX=_" + variant, + defaultInstallRoot + "/multiapp.app/Contents/MacOS/multiapp" + }); + process.start(); + process.waitForFinished(); + QCOMPARE(process.exitCode(), 0); + const auto processStdout = process.readAllStandardOutput(); + QVERIFY2(processStdout.contains("Hello from " + variant.toUtf8() + " " + arch.toUtf8()), + processStdout.constData()); + } } + } else if (m_qbsStdout.contains("isShallow: true")) { + QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp.app/singleapp").isExecutable()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp.app/Info.plist").isRegularFile()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp.app/PkgInfo").isRegularFile()); + + QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp_agg.app/singleapp_agg").isExecutable()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp_agg.app/Info.plist").isRegularFile()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp_agg.app/PkgInfo").isRegularFile()); + + QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/singlelib").isExecutable()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/Info.plist").isRegularFile()); + + QVERIFY(QFileInfo2(defaultInstallRoot + "/multiapp.app/multiapp").isExecutable()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/multiapp.app/Info.plist").isRegularFile()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/multiapp.app/PkgInfo").isRegularFile()); + + QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiapp.app/fatmultiapp").isExecutable()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiapp.app/Info.plist").isRegularFile()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiapp.app/PkgInfo").isRegularFile()); + + QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiappmultivariant.app/" + "fatmultiappmultivariant").isFileSymLink()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiappmultivariant.app/" + "fatmultiappmultivariant_debug").isExecutable()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiappmultivariant.app/" + "fatmultiappmultivariant_profiling").isExecutable()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiappmultivariant.app/Info.plist") + .isRegularFile()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiappmultivariant.app/PkgInfo") + .isRegularFile()); + + QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/multilib").isRegularFile()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/multilib_debug").isRegularFile()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/multilib_profiling").isRegularFile()); + QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Info.plist").isRegularFile()); + } else { + QVERIFY2(false, qPrintable(m_qbsStdout)); } } void TestBlackboxApple::aggregateDependencyLinking() { - if (HostOsInfo::hostOsVersion() > qbs::Version(10, 13, 4)) - QSKIP("32-bit arch build is no longer supported on macOS versions higher than 10.13.4."); + const auto xcodeVersion = findXcodeVersion(); + + if (!xcodeVersion) + QSKIP("requires Xcode profile"); + + // XCode 11 produces warning about deprecation of 32-bit apps, but still works + const bool hasX86Mac = xcodeVersion < qbs::Version(12); + const bool hasArmMac = xcodeVersion >= qbs::Version(12, 2); QDir::setCurrent(testDataDir + "/aggregateDependencyLinking"); - QCOMPARE(runQbs(QStringList{"-p", "multi_arch_lib"}), 0); + QbsRunParameters params{QStringList{"-p", "multi_arch_lib"}}; + params.arguments << QStringLiteral("products.multi_arch_lib.hasX86Mac:%1").arg(hasX86Mac); + params.arguments << QStringLiteral("products.multi_arch_lib.hasArmMac:%1").arg(hasArmMac); + QCOMPARE(runQbs(params), 0); + if (m_qbsStdout.contains("Cannot build fat binaries")) + QSKIP("Building fat binaries is not supported for this profile"); QCOMPARE(runQbs(QStringList{"-p", "just_app", "--command-echo-mode", "command-line"}), 0); int linkedInLibrariesCount = - QString::fromUtf8(m_qbsStdout).count(QStringLiteral("multi_arch_lib.a")); + QString::fromUtf8(m_qbsStdout).count(QStringLiteral("libmulti_arch_lib.a")); QCOMPARE(linkedInLibrariesCount, 1); + const auto fatLibPath = findFatLibrary(testDataDir, QStringLiteral("libmulti_arch_lib.a")); + QVERIFY(!fatLibPath.isEmpty()); + QVERIFY2(QString::fromUtf8(m_qbsStdout).contains(fatLibPath), m_qbsStdout); +} + +void TestBlackboxApple::appiconset() +{ + QDir::setCurrent(testDataDir + QLatin1String("/ib/appiconset")); + + QbsRunParameters params; + params.arguments = QStringList() << "-f" << "appiconset.qbs"; + QCOMPARE(runQbs(params), 0); + + const auto infoPlistPath = getInfoPlistPath( + relativeProductBuildDir("appiconset") + "/appiconset.app"); + QVERIFY(QFile::exists(infoPlistPath)); + const auto content = readInfoPlistFile(infoPlistPath); + QVERIFY(!content.isEmpty()); + + if (m_qbsStdout.contains("bundle.isShallow: false")) { + QCOMPARE(content.value(QStringLiteral("CFBundleIconFile")), QStringLiteral("AppIcon")); + QCOMPARE(content.value(QStringLiteral("CFBundleIconName")), QStringLiteral("AppIcon")); + QVERIFY(regularFileExists(relativeProductBuildDir("appiconset") + + "/appiconset.app/Contents/Resources/AppIcon.icns")); + } else if (m_qbsStdout.contains("bundle.isShallow: true")) { + const auto icons = content.value(QStringLiteral("CFBundleIcons")).toMap(); + QVERIFY2(!icons.isEmpty(), "Info.plist doesn't contain CFBundleIcons key"); + const auto primaryIcon = icons.value(QStringLiteral("CFBundlePrimaryIcon")).toMap(); + QVERIFY2(!primaryIcon.isEmpty(), "Info.plist doesn't contain CFBundlePrimaryIcon key"); + QCOMPARE(primaryIcon.value(QStringLiteral("CFBundleIconName")), QStringLiteral("AppIcon")); + } else { + QVERIFY2(false, "Cannot determine bundle type"); + } } void TestBlackboxApple::assetCatalog() { QFETCH(bool, flatten); - const auto xcodeVersion = findXcodeVersion(); QDir::setCurrent(testDataDir + QLatin1String("/ib/assetcatalog")); rmDirR(relativeBuildDir()); + if (!findXcode()) + QSKIP("requires Xcode profile"); + QbsRunParameters params; - const auto v = HostOsInfo::hostOsVersion(); const QString flattens = "modules.ib.flatten:" + QString(flatten ? "true" : "false"); - const QString macosTarget = "modules.cpp.minimumMacosVersion:'" + v.toString() + "'"; + const QString macosTarget = "modules.cpp.minimumMacosVersion:'10.15'"; // Make sure a dry run does not write anything params.arguments = QStringList() << "-f" << "assetcatalogempty.qbs" << "--dry-run" @@ -185,44 +382,20 @@ void TestBlackboxApple::assetCatalog() QCOMPARE(runQbs(params), 0); QVERIFY(!directoryExists(relativeBuildDir())); + if (m_qbsStdout.contains("Skip this test")) + QSKIP("Skip this test"); + params.arguments = QStringList() << "-f" << "assetcatalogempty.qbs" << flattens << macosTarget; QCOMPARE(runQbs(params), 0); // empty asset catalogs must still produce output - if (xcodeVersion >= qbs::Version(5)) - QVERIFY((bool)m_qbsStdout.contains("compiling empty.xcassets")); - - // should additionally produce raw assets since deployment target will be < 10.9 - // older versions of ibtool generated either raw assets OR .car files; - // newer versions always generate the .car file regardless of the deployment target - if (v < qbs::Version(10, 9)) { - QVERIFY(regularFileExists(relativeProductBuildDir("assetcatalogempty") - + "/assetcatalogempty.app/Contents/Resources/other.png")); - QVERIFY(regularFileExists(relativeProductBuildDir("assetcatalogempty") - + "/assetcatalogempty.app/Contents/Resources/other@2x.png")); - } - - rmDirR(relativeBuildDir()); - params.arguments.push_back("modules.cpp.minimumMacosVersion:'10.10'"); // force CAR generation - QCOMPARE(runQbs(params), 0); + QVERIFY((bool)m_qbsStdout.contains("compiling empty.xcassets")); // empty asset catalogs must still produce output - if (xcodeVersion >= qbs::Version(5)) { - QVERIFY((bool)m_qbsStdout.contains("compiling empty.xcassets")); - // No matter what, we need a 10.9 host to build CAR files - if (HostOsInfo::hostOsVersion() >= qbs::Version(10, 9)) { - QVERIFY(regularFileExists(relativeProductBuildDir("assetcatalogempty") - + "/assetcatalogempty.app/Contents/Resources/Assets.car")); - } else { - QVERIFY(regularFileExists(relativeProductBuildDir("assetcatalogempty") - + "/assetcatalogempty.app/Contents/Resources/empty.icns")); - QVERIFY(regularFileExists(relativeProductBuildDir("assetcatalogempty") - + "/assetcatalogempty.app/Contents/Resources/other.png")); - QVERIFY(regularFileExists(relativeProductBuildDir("assetcatalogempty") - + "/assetcatalogempty.app/Contents/Resources/other@2x.png")); - } - } + QVERIFY((bool)m_qbsStdout.contains("compiling empty.xcassets")); + QVERIFY(regularFileExists(relativeProductBuildDir("assetcatalogempty") + + "/assetcatalogempty.app/Contents/Resources/Assets.car")); // this asset catalog happens to have an embedded icon set, // but this should NOT be built since it is not in the files list @@ -301,19 +474,10 @@ void TestBlackboxApple::bundleStructure() { QFETCH(QString, productName); QFETCH(QString, productTypeIdentifier); - QFETCH(bool, isShallow); QDir::setCurrent(testDataDir + "/bundle-structure"); QbsRunParameters params(QStringList{"qbs.installPrefix:''"}); params.arguments << "project.buildableProducts:" + productName; - if (isShallow) { - // Coerce shallow bundles - don't set bundle.isShallow directly because we want to test the - // automatic detection - const auto xcode5 = findXcodeVersion() >= qbs::Version(5); - params.arguments - << "modules.qbs.targetPlatform:ios" - << (xcode5 ? "qbs.architectures:arm64" : "qbs.architectures:armv7a"); - } if (productName == "ABadApple" || productName == "ABadThirdParty") params.expectFailure = true; @@ -330,7 +494,10 @@ void TestBlackboxApple::bundleStructure() QCOMPARE(status, 0); - if (!isShallow) { + if (m_qbsStdout.contains("bundle.isShallow: false")) { + // Test shallow bundles detection - bundles are not shallow only on macOS, so also check + // the qbs.targetOS property + QVERIFY2(m_qbsStdout.contains("qbs.targetOS: macos"), m_qbsStdout); if (productName == "A") { QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app/Contents").isRegularDir()); @@ -424,7 +591,9 @@ void TestBlackboxApple::bundleStructure() QVERIFY(QFileInfo2(defaultInstallRoot + "/G/ContentInfo.plist").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/G/Contents/resource.txt").isRegularFile()); } - } else { + } else if (m_qbsStdout.contains("bundle.isShallow: true")) { + QVERIFY2(m_qbsStdout.contains("qbs.targetOS:"), m_qbsStdout); + QVERIFY2(!m_qbsStdout.contains("qbs.targetOS: macos"), m_qbsStdout); if (productName == "A") { QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app/A").isRegularFile()); @@ -502,6 +671,8 @@ void TestBlackboxApple::bundleStructure() QVERIFY(QFileInfo2(defaultInstallRoot + "/G/ContentInfo.plist").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/G/Contents/resource.txt").isRegularFile()); } + } else { + QVERIFY2(false, qPrintable(m_qbsStdout)); } } @@ -511,21 +682,127 @@ void TestBlackboxApple::bundleStructure_data() 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; - }; + QTest::newRow("A") << "A" << "com.apple.product-type.application"; + QTest::newRow("ABadApple") << "ABadApple" << "com.apple.product-type.will.never.exist.ever.guaranteed"; + QTest::newRow("ABadThirdParty") << "ABadThirdParty" << "org.special.third.party.non.existent.product.type"; + QTest::newRow("B") << "B" << "com.apple.product-type.framework"; + QTest::newRow("C") << "C" << "com.apple.product-type.framework.static"; + QTest::newRow("D") << "D" << "com.apple.product-type.bundle"; + QTest::newRow("E") << "E" << "com.apple.product-type.app-extension"; + QTest::newRow("F") << "F" << "com.apple.product-type.xpc-service"; + QTest::newRow("G") << "G" << "com.apple.product-type.in-app-purchase-content"; +} + +void TestBlackboxApple::byteArrayInfoPlist() +{ + QDir::setCurrent(testDataDir + "/byteArrayInfoPlist"); + + QCOMPARE(runQbs(), 0); + + const auto infoPlistPath = getInfoPlistPath( + relativeProductBuildDir("byteArrayInfoPlist") + "/byteArrayInfoPlist.app"); + QVERIFY(QFile::exists(infoPlistPath)); + const auto outFilePath = + relativeProductBuildDir("byteArrayInfoPlist") + "/bytearrayInfoPlist-Info.plist.out"; + QFile file(outFilePath); + QVERIFY(file.exists()); + QVERIFY(file.open(QIODevice::ReadOnly)); + QCOMPARE(file.readAll(), "The data value"); +} + +void TestBlackboxApple::codesign() +{ + QFETCH(int, expectedCount); + QFETCH(bool, isBundle); + QFETCH(bool, enableSigning); + QFETCH(bool, multiArch); + QFETCH(bool, multiVariant); + + const auto xcodeVersion = findXcodeVersion(); + + if (!xcodeVersion) + QSKIP("requires Xcode profile"); + + QDir::setCurrent(testDataDir + "/codesign"); + QbsRunParameters params(QStringList{"qbs.installPrefix:''"}); + // the test can't use xcode module to determine version itself + params.arguments << QStringLiteral("project.xcodeVersion:") + xcodeVersion->toString(); + params.arguments << QStringLiteral("project.isBundle:%1").arg(isBundle ? "true" : "false"); + params.arguments << QStringLiteral("project.enableSigning:%1") + .arg(enableSigning ? "true" : "false"); + params.arguments << QStringLiteral("project.multiArch:%1").arg(multiArch ? "true" : "false"); + params.arguments << QStringLiteral("project.multiVariant:%1") + .arg(multiVariant ? "true" : "false"); + + rmDirR(relativeBuildDir()); + QCOMPARE(runQbs(params), 0); + + const int codeSignCount = + QString::fromUtf8(m_qbsStdout).count(QStringLiteral("codesign")); + QCOMPARE(codeSignCount, expectedCount); + + const auto appName = isBundle ? QStringLiteral("A.app") : QStringLiteral("A"); + const auto appPath = defaultInstallRoot + "/" + appName; + QVERIFY(QFileInfo(appPath).exists()); + auto codeSignInfo = getCodeSignInfo(appPath); + QVERIFY(codeSignInfo.first != CodeSignResult::Failed); + QCOMPARE(codeSignInfo.first == CodeSignResult::Signed, enableSigning); + QCOMPARE(codeSignInfo.second.isEmpty(), !enableSigning); + if (!codeSignInfo.second.isEmpty()) { + QVERIFY(codeSignInfo.second.contains(QByteArrayLiteral("Executable"))); + QVERIFY(codeSignInfo.second.contains(QByteArrayLiteral("Identifier"))); + QCOMPARE(codeSignInfo.second.value(QByteArrayLiteral("Signature")), "adhoc"); + } + + const auto libName = + isBundle ? QStringLiteral("B.framework") : QStringLiteral("libB.1.0.0.dylib"); + const auto libPath = defaultInstallRoot + "/" + libName; + QVERIFY(QFileInfo(libPath).exists()); + codeSignInfo = getCodeSignInfo(libPath); + QVERIFY(codeSignInfo.first != CodeSignResult::Failed); + QCOMPARE(codeSignInfo.first == CodeSignResult::Signed, enableSigning); + QCOMPARE(codeSignInfo.second.isEmpty(), !enableSigning); + if (!codeSignInfo.second.isEmpty()) { + QVERIFY(codeSignInfo.second.contains(QByteArrayLiteral("Executable"))); + QVERIFY(codeSignInfo.second.contains(QByteArrayLiteral("Identifier"))); + QCOMPARE(codeSignInfo.second.value(QByteArrayLiteral("Signature")), "adhoc"); + } + + const auto pluginPath = defaultInstallRoot + "/" + QStringLiteral("C.bundle"); + QVERIFY(QFileInfo(pluginPath).exists()); + QVERIFY(QFileInfo(pluginPath).isDir() == isBundle); + codeSignInfo = getCodeSignInfo(pluginPath); + QVERIFY(codeSignInfo.first != CodeSignResult::Failed); + QCOMPARE(codeSignInfo.first == CodeSignResult::Signed, enableSigning); + QCOMPARE(codeSignInfo.second.isEmpty(), !enableSigning); + if (!codeSignInfo.second.isEmpty()) { + QVERIFY(codeSignInfo.second.contains(QByteArrayLiteral("Executable"))); + QVERIFY(codeSignInfo.second.contains(QByteArrayLiteral("Identifier"))); + QCOMPARE(codeSignInfo.second.value(QByteArrayLiteral("Signature")), "adhoc"); + } +} - addRows(true); - addRows(false); +void TestBlackboxApple::codesign_data() +{ + QTest::addColumn<int>("expectedCount"); + QTest::addColumn<bool>("isBundle"); + QTest::addColumn<bool>("enableSigning"); + QTest::addColumn<bool>("multiArch"); + QTest::addColumn<bool>("multiVariant"); + + QTest::newRow("standalone, unsigned") << 0 << false << false << false << false; + QTest::newRow("bundle, unsigned") << 0 << true << false << false << false; + QTest::newRow("standalone, signed") << 3 << false << true << false << false; + QTest::newRow("bundle, signed") << 3 << true << true << false << false; + // here we only sign the resulting lipo artifact + QTest::newRow("standalone, signed, multiarch") << 3 << false << true << true << false; + QTest::newRow("bundle, signed, multiarch") << 3 << true << true << true << false; + // here we sign all artifacts + QTest::newRow("standalone, signed, multivariant") << 15 << false << true << false << true; + QTest::newRow("bundle, signed, multivariant") << 15 << true << true << false << true; + QTest::newRow("standalone, signed, multiarch, multivariant") + << 15 << false << true << true << true; + QTest::newRow("bundle, signed, multiarch, multivariant") << 15 << true << true << true << true; } void TestBlackboxApple::deploymentTarget() @@ -538,6 +815,9 @@ void TestBlackboxApple::deploymentTarget() QDir::setCurrent(testDataDir + "/deploymentTarget"); + if (!findXcode()) + QSKIP("requires Xcode profile"); + QbsRunParameters params; params.arguments = QStringList() << "--command-echo-mode" @@ -591,52 +871,54 @@ void TestBlackboxApple::deploymentTarget_data() } QTest::newRow("macos x86_64") << "macosx" << macos << "x86_64" << "-triple x86_64-apple-macosx10.6" - << "-macosx_version_min 10.6"; + << "10.6"; if (xcodeVersion >= qbs::Version(6)) QTest::newRow("macos x86_64h") << "macosx" << macos << "x86_64h" << "-triple x86_64h-apple-macosx10.12" - << "-macosx_version_min 10.12"; + << "10.12"; QTest::newRow("ios armv7a") << "iphoneos" << ios << "armv7a" << "-triple thumbv7-apple-ios6.0" - << "-iphoneos_version_min 6.0"; + << "6.0"; QTest::newRow("ios armv7s") << "iphoneos" <<ios << "armv7s" << "-triple thumbv7s-apple-ios7.0" - << "-iphoneos_version_min 7.0"; + << "7.0"; if (xcodeVersion >= qbs::Version(5)) QTest::newRow("ios arm64") << "iphoneos" <<ios << "arm64" << "-triple arm64-apple-ios7.0" - << "-iphoneos_version_min 7.0"; + << "7.0"; QTest::newRow("ios-simulator x86") << "iphonesimulator" << ios_sim << "x86" << "-triple i386-apple-ios6.0" - << "-ios_simulator_version_min 6.0"; + << "6.0"; if (xcodeVersion >= qbs::Version(5)) QTest::newRow("ios-simulator x86_64") << "iphonesimulator" << ios_sim << "x86_64" << "-triple x86_64-apple-ios7.0" - << "-ios_simulator_version_min 7.0"; + << "7.0"; if (xcodeVersion >= qbs::Version(7)) { if (xcodeVersion >= qbs::Version(7, 1)) { QTest::newRow("tvos arm64") << "appletvos" << tvos << "arm64" << "-triple arm64-apple-tvos9.0" - << "-tvos_version_min 9.0"; + << "9.0"; QTest::newRow("tvos-simulator x86_64") << "appletvsimulator" << tvos_sim << "x86_64" << "-triple x86_64-apple-tvos9.0" - << "-tvos_simulator_version_min 9.0"; + << "9.0"; } QTest::newRow("watchos armv7k") << "watchos" << watchos << "armv7k" << "-triple thumbv7k-apple-watchos2.0" - << "-watchos_version_min 2.0"; + << "2.0"; QTest::newRow("watchos-simulator x86") << "watchsimulator" << watchos_sim << "x86" << "-triple i386-apple-watchos2.0" - << "-watchos_simulator_version_min 2.0"; + << "2.0"; } } void TestBlackboxApple::dmg() { + if (qEnvironmentVariableIsSet("GITHUB_ACTIONS")) + QSKIP("Skip this test when running on GitHub"); QDir::setCurrent(testDataDir + "/apple-dmg"); QCOMPARE(runQbs(), 0); } @@ -669,16 +951,29 @@ void TestBlackboxApple::frameworkStructure() QbsRunParameters params; QCOMPARE(runQbs(params), 0); - QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Versions/A/Widget")); - QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Versions/A/Headers/Widget.h")); - QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Versions/A/PrivateHeaders/WidgetPrivate.h")); - QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Versions/A/Resources/BaseResource")); - QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Versions/A/Resources/en.lproj/EnglishResource")); - QVERIFY(directoryExists(relativeProductBuildDir("Widget") + "/Widget.framework/Versions/Current")); - QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Widget")); - QVERIFY(directoryExists(relativeProductBuildDir("Widget") + "/Widget.framework/Headers")); - QVERIFY(directoryExists(relativeProductBuildDir("Widget") + "/Widget.framework/PrivateHeaders")); - QVERIFY(directoryExists(relativeProductBuildDir("Widget") + "/Widget.framework/Resources")); + if (m_qbsStdout.contains("isShallow: false")) { + QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Versions/A/Widget")); + QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Versions/A/Headers/Widget.h")); + QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Versions/A/PrivateHeaders/WidgetPrivate.h")); + QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Versions/A/Resources/BaseResource")); + QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Versions/A/Resources/en.lproj/EnglishResource")); + QVERIFY(directoryExists(relativeProductBuildDir("Widget") + "/Widget.framework/Versions/Current")); + QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Widget")); + QVERIFY(directoryExists(relativeProductBuildDir("Widget") + "/Widget.framework/Headers")); + QVERIFY(directoryExists(relativeProductBuildDir("Widget") + "/Widget.framework/PrivateHeaders")); + QVERIFY(directoryExists(relativeProductBuildDir("Widget") + "/Widget.framework/Resources")); + } else if (m_qbsStdout.contains("isShallow: true")) { + QVERIFY(directoryExists(relativeProductBuildDir("Widget") + "/Widget.framework/Headers")); + QVERIFY(directoryExists(relativeProductBuildDir("Widget") + "/Widget.framework/PrivateHeaders")); + QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Widget")); + QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Headers/Widget.h")); + QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/PrivateHeaders/WidgetPrivate.h")); + QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/BaseResource")); + QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/en.lproj/EnglishResource")); + QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Widget")); + } else { + QVERIFY2(false, qPrintable(m_qbsStdout)); + } params.command = "resolve"; params.arguments = QStringList() << "project.includeHeaders:false"; @@ -708,7 +1003,15 @@ void TestBlackboxApple::iconsetApp() params.arguments = QStringList() << "-f" << "iconsetapp.qbs"; QCOMPARE(runQbs(params), 0); - QVERIFY(regularFileExists(relativeProductBuildDir("iconsetapp") + "/iconsetapp.app/Contents/Resources/white.icns")); + if (m_qbsStdout.contains("isShallow: false")) { + QVERIFY(regularFileExists(relativeProductBuildDir("iconsetapp") + + "/iconsetapp.app/Contents/Resources/white.icns")); + } else if (m_qbsStdout.contains("isShallow: true")) { + QVERIFY(regularFileExists(relativeProductBuildDir("iconsetapp") + + "/iconsetapp.app/white.icns")); + } else { + QVERIFY2(false, qPrintable(m_qbsStdout)); + } } void TestBlackboxApple::infoPlist() @@ -719,40 +1022,74 @@ void TestBlackboxApple::infoPlist() params.arguments = QStringList() << "-f" << "infoplist.qbs"; QCOMPARE(runQbs(params), 0); - auto infoplistPath = relativeProductBuildDir("infoplist") - + "/infoplist.app/Contents/Info.plist"; - if (!QFile::exists(infoplistPath)) - infoplistPath = relativeProductBuildDir("infoplist") + "/infoplist.app/Info.plist"; - QVERIFY(QFile::exists(infoplistPath)); - QProcess plutil; - plutil.start("plutil", { - QStringLiteral("-convert"), - QStringLiteral("json"), - infoplistPath - }); - QVERIFY2(plutil.waitForStarted(), qPrintable(plutil.errorString())); - QVERIFY2(plutil.waitForFinished(), qPrintable(plutil.errorString())); - QVERIFY2(plutil.exitCode() == 0, qPrintable(plutil.readAllStandardError().constData())); + const auto infoPlistPath = getInfoPlistPath( + relativeProductBuildDir("infoplist") + "/infoplist.app"); + QVERIFY(QFile::exists(infoPlistPath)); + const auto content = readInfoPlistFile(infoPlistPath); + QVERIFY(!content.isEmpty()); - QFile infoplist(infoplistPath); - QVERIFY(infoplist.open(QIODevice::ReadOnly)); - QJsonParseError error; - const auto json = QJsonDocument::fromJson(infoplist.readAll(), &error); - QCOMPARE(error.error, QJsonParseError::NoError); - QVERIFY(json.isObject()); // common values - QCOMPARE(json.object().value(QStringLiteral("CFBundleIdentifier")), + QCOMPARE(content.value(QStringLiteral("CFBundleIdentifier")), QStringLiteral("org.example.infoplist")); - QCOMPARE(json.object().value(QStringLiteral("CFBundleName")), QStringLiteral("infoplist")); - QCOMPARE(json.object().value(QStringLiteral("CFBundleExecutable")), + QCOMPARE(content.value(QStringLiteral("CFBundleName")), QStringLiteral("infoplist")); + QCOMPARE(content.value(QStringLiteral("CFBundleExecutable")), QStringLiteral("infoplist")); - if (!json.object().contains(QStringLiteral("SDKROOT"))) { // macOS-specific values - QCOMPARE(json.object().value("LSMinimumSystemVersion"), QStringLiteral("10.7")); - QVERIFY(json.object().contains("NSPrincipalClass")); + if (!content.contains(QStringLiteral("SDKROOT"))) { // macOS-specific values + QCOMPARE(content.value("LSMinimumSystemVersion"), QStringLiteral("10.7")); + QCOMPARE(content.value("NSPrincipalClass"), QStringLiteral("NSApplication")); + QCOMPARE(content.value(QStringLiteral("NSSupportsAutomaticGraphicsSwitching")), true); + } else { + // QBS-1447: UIDeviceFamily was set to a string instead of an array + const auto family = content.value(QStringLiteral("UIDeviceFamily")); + if (family.isValid()) { + // Prior to Qt 5.15, int gets converted to a double when exporting plist as JSON + QVERIFY(testVariantListType(family, QMetaType::LongLong) + || testVariantListType(family, QMetaType::Double)); + } + const auto caps = content.value(QStringLiteral("UIRequiredDeviceCapabilities")); + if (caps.isValid()) + QVERIFY(testVariantListType(caps, QMetaType::QString)); + const auto orientations = content.value(QStringLiteral("UIRequiredDeviceCapabilities")); + if (orientations.isValid()) + QVERIFY(testVariantListType(orientations, QMetaType::QString)); } } +void TestBlackboxApple::infoPlistVariables() +{ + QDir::setCurrent(testDataDir + "/infoPlistVariables"); + + QbsRunParameters params; + params.arguments = QStringList() << "-f" << "infoPlistVariables.qbs"; + QCOMPARE(runQbs(params), 0); + + const auto infoPlistPath = getInfoPlistPath( + relativeProductBuildDir("infoPlistVariables") + "/infoPlistVariables.app"); + QVERIFY(QFile::exists(infoPlistPath)); + const auto content = readInfoPlistFile(infoPlistPath); + QVERIFY(!content.isEmpty()); + + QCOMPARE(content.value(QStringLiteral("Curly")), + QStringLiteral("infoPlistVariables")); + QCOMPARE(content.value(QStringLiteral("Braces")), + QStringLiteral("infoPlistVariables")); + QCOMPARE(content.value(QStringLiteral("At")), + QStringLiteral("infoPlistVariables")); + QCOMPARE(content.value(QStringLiteral("CurlyMult")), + QStringLiteral("infoPlistVariables_infoPlistVariables")); + QCOMPARE(content.value(QStringLiteral("BracesMult")), + QStringLiteral("infoPlistVariables_infoPlistVariables")); + QCOMPARE(content.value(QStringLiteral("AtMult")), + QStringLiteral("infoPlistVariables_infoPlistVariables")); + QCOMPARE(content.value(QStringLiteral("CurlyNested")), + QStringLiteral("infoPlistVariables")); + QCOMPARE(content.value(QStringLiteral("BracesNested")), + QStringLiteral("infoPlistVariables")); + QCOMPARE(content.value(QStringLiteral("WithDefault")), + QStringLiteral("DEFAULT")); +} + void TestBlackboxApple::objcArc() { QDir::setCurrent(testDataDir + QLatin1String("/objc-arc")); @@ -760,8 +1097,36 @@ void TestBlackboxApple::objcArc() QCOMPARE(runQbs(), 0); } +void TestBlackboxApple::overrideInfoPlist() +{ + QDir::setCurrent(testDataDir + "/overrideInfoPlist"); + + QCOMPARE(runQbs(), 0); + + const auto infoPlistPath = getInfoPlistPath( + relativeProductBuildDir("overrideInfoPlist") + "/overrideInfoPlist.app"); + QVERIFY(QFile::exists(infoPlistPath)); + const auto content = readInfoPlistFile(infoPlistPath); + QVERIFY(!content.isEmpty()); + + // test we do not override custom values by default + QCOMPARE(content.value(QStringLiteral("DefaultValue")), + QStringLiteral("The default value")); + // test we can override custom values + QCOMPARE(content.value(QStringLiteral("OverriddenValue")), + QStringLiteral("The overridden value")); + // test we do not override special values set by Qbs by default + QCOMPARE(content.value(QStringLiteral("CFBundleExecutable")), + QStringLiteral("overrideInfoPlist")); + // test we can override special values set by Qbs + QCOMPARE(content.value(QStringLiteral("CFBundleName")), QStringLiteral("My Bundle")); +} + void TestBlackboxApple::xcode() { + if (!findXcode()) + QSKIP("requires Xcode profile"); + QProcess xcodeSelect; xcodeSelect.start("xcode-select", QStringList() << "--print-path"); QVERIFY2(xcodeSelect.waitForStarted(), qPrintable(xcodeSelect.errorString())); @@ -775,8 +1140,10 @@ void TestBlackboxApple::xcode() xcodebuildShowSdks.start("xcrun", QStringList() << "xcodebuild" << "-showsdks"); QVERIFY2(xcodebuildShowSdks.waitForStarted(), qPrintable(xcodebuildShowSdks.errorString())); QVERIFY2(xcodebuildShowSdks.waitForFinished(), qPrintable(xcodebuildShowSdks.errorString())); - QVERIFY2(xcodebuildShowSdks.exitCode() == 0, qPrintable(xcodebuildShowSdks.readAllStandardError().constData())); - const auto lines = QString::fromLocal8Bit(xcodebuildShowSdks.readAllStandardOutput().trimmed()).split('\n', QString::SkipEmptyParts); + QVERIFY2(xcodebuildShowSdks.exitCode() == 0, + qPrintable(xcodebuildShowSdks.readAllStandardError().constData())); + const auto lines = QString::fromLocal8Bit(xcodebuildShowSdks.readAllStandardOutput().trimmed()) + .split('\n', Qt::SkipEmptyParts); for (const QString &line : lines) { static const std::regex regexp("^.+\\s+\\-sdk\\s+([a-z]+)([0-9]+\\.[0-9]+)$"); const auto ln = line.toStdString(); @@ -812,11 +1179,10 @@ void TestBlackboxApple::xcode() QTEST_MAIN(TestBlackboxApple) -QVariantMap TestBlackboxApple::findXcode(int *status) +std::optional<QVariantMap> TestBlackboxApple::findXcode(int *status) { QTemporaryDir temp; QbsRunParameters params = QStringList({"-f", testDataDir + "/find/find-xcode.qbs"}); - params.profile = "none"; params.buildDirectory = temp.path(); const int res = runQbs(params); if (status) @@ -825,10 +1191,16 @@ QVariantMap TestBlackboxApple::findXcode(int *status) + "/xcode.json"); if (!file.open(QIODevice::ReadOnly)) return {}; - return QJsonDocument::fromJson(file.readAll()).toVariant().toMap(); + auto result = QJsonDocument::fromJson(file.readAll()).toVariant().toMap(); + if (!result["present"].toBool()) + return {}; + return result; } -qbs::Version TestBlackboxApple::findXcodeVersion() +std::optional<qbs::Version> TestBlackboxApple::findXcodeVersion() { - return qbs::Version::fromString(findXcode().value("version").toString()); + const auto xcode = findXcode(); + if (!xcode) + return {}; + return qbs::Version::fromString(xcode->value("version").toString()); } diff --git a/tests/auto/blackbox/tst_blackboxapple.h b/tests/auto/blackbox/tst_blackboxapple.h index 76711ddf5..a51414917 100644 --- a/tests/auto/blackbox/tst_blackboxapple.h +++ b/tests/auto/blackbox/tst_blackboxapple.h @@ -31,6 +31,8 @@ #include "tst_blackboxbase.h" +#include <optional> + namespace qbs { class Version; } // namespace qbs @@ -48,12 +50,16 @@ public slots: private slots: void appleMultiConfig(); void aggregateDependencyLinking(); + void appiconset(); void assetCatalog(); void assetCatalog_data(); void assetCatalogsEmpty(); void assetCatalogsMultiple(); void bundleStructure(); void bundleStructure_data(); + void byteArrayInfoPlist(); + void codesign(); + void codesign_data(); void deploymentTarget(); void deploymentTarget_data(); void dmg(); @@ -62,12 +68,14 @@ private slots: void iconset(); void iconsetApp(); void infoPlist(); + void infoPlistVariables(); void objcArc(); + void overrideInfoPlist(); void xcode(); private: - QVariantMap findXcode(int *status = nullptr); - qbs::Version findXcodeVersion(); + std::optional<QVariantMap> findXcode(int *status = nullptr); + std::optional<qbs::Version> findXcodeVersion(); }; #endif // TST_BLACKBOXAPPLE_H diff --git a/tests/auto/blackbox/tst_blackboxbaremetal.cpp b/tests/auto/blackbox/tst_blackboxbaremetal.cpp new file mode 100644 index 000000000..ec6ffcdc6 --- /dev/null +++ b/tests/auto/blackbox/tst_blackboxbaremetal.cpp @@ -0,0 +1,311 @@ +/**************************************************************************** +** +** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "tst_blackboxbaremetal.h" + +#include "../shared.h" + +#include <QtCore/qdir.h> +#include <QtCore/qregularexpression.h> + +static bool extractToolset(const QByteArray &output, + QByteArray &toolchain, QByteArray &architecture) +{ + const QRegularExpression re("%%([\\w\\-]+)%%, %%(\\w+)%%"); + QRegularExpressionMatchIterator it = re.globalMatch(output); + if (!it.hasNext()) + return false; + const QRegularExpressionMatch match = it.next(); + toolchain = match.captured(1).toLocal8Bit(); + architecture = match.captured(2).toLocal8Bit(); + return true; +} + +static bool extractCompilerIncludePaths(const QByteArray &output, QStringList &compilerIncludePaths) +{ + const QRegularExpression re("%%([^%%]+)%%"); + QRegularExpressionMatchIterator it = re.globalMatch(output); + if (!it.hasNext()) + return false; + const QRegularExpressionMatch match = it.next(); + compilerIncludePaths = match.captured(1).split(","); + return true; +} + +static bool extractQuitedValue(const QByteArray &output, QString &pattern) +{ + const QRegularExpression re("%%(.+)%%"); + const QRegularExpressionMatch match = re.match(output); + if (!match.hasMatch()) + return false; + pattern = match.captured(1); + return true; +} + +static QByteArray unsupportedToolsetMessage(const QByteArray &output) +{ + QByteArray toolchain; + QByteArray architecture; + extractToolset(output, toolchain, architecture); + return "Unsupported toolchain '" + toolchain + + "' for architecture '" + architecture + "'"; +} + +static QByteArray brokenProbeMessage(const QByteArray &output) +{ + QByteArray toolchain; + QByteArray architecture; + extractToolset(output, toolchain, architecture); + return "Broken probe for toolchain '" + toolchain + + "' for architecture '" + architecture + "'"; +} + +TestBlackboxBareMetal::TestBlackboxBareMetal() + : TestBlackboxBase (SRCDIR "/testdata-baremetal", "blackbox-baremetal") +{ +} + +void TestBlackboxBareMetal::targetPlatform() +{ + QDir::setCurrent(testDataDir + "/target-platform"); + QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("-n"))), 0); + if (m_qbsStdout.contains("unsupported toolset:")) + QSKIP(unsupportedToolsetMessage(m_qbsStdout)); + const bool hasNoPlatform = m_qbsStdout.contains("has no platform: true"); + QCOMPARE(hasNoPlatform, true); + const bool hasNoOS = m_qbsStdout.contains("has no os: true"); + QCOMPARE(hasNoOS, true); +} + +void TestBlackboxBareMetal::application_data() +{ + QTest::addColumn<QString>("testPath"); + QTest::newRow("one-object-application") << "/one-object-application"; + QTest::newRow("two-object-application") << "/two-object-application"; + QTest::newRow("one-object-asm-application") << "/one-object-asm-application"; +} + +void TestBlackboxBareMetal::application() +{ + QFETCH(QString, testPath); + QDir::setCurrent(testDataDir + testPath); + QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("-n"))), 0); + if (m_qbsStdout.contains("unsupported toolset:")) + QSKIP(unsupportedToolsetMessage(m_qbsStdout)); + QCOMPARE(runQbs(QbsRunParameters("build")), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); + QCOMPARE(runQbs(QbsRunParameters("run")), 0); +} + +void TestBlackboxBareMetal::staticLibraryDependencies() +{ + QDir::setCurrent(testDataDir + "/static-library-dependencies"); + QCOMPARE(runQbs(QStringList{"-p", "lib-a,lib-b,lib-c,lib-d,lib-e"}), 0); + QCOMPARE(runQbs(QStringList{"--command-echo-mode", "command-line"}), 0); + const QByteArray output = m_qbsStdout + '\n' + m_qbsStderr; + QVERIFY(output.contains("lib-a")); + QVERIFY(output.contains("lib-b")); + QVERIFY(output.contains("lib-c")); + QVERIFY(output.contains("lib-d")); + QVERIFY(output.contains("lib-e")); +} + +void TestBlackboxBareMetal::externalStaticLibraries() +{ + QDir::setCurrent(testDataDir + "/external-static-libraries"); + QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("-n"))), 0); + if (m_qbsStdout.contains("unsupported toolset:")) + QSKIP(unsupportedToolsetMessage(m_qbsStdout)); + QCOMPARE(runQbs(), 0); +} + +void TestBlackboxBareMetal::sharedLibraries() +{ + QDir::setCurrent(testDataDir + "/shared-libraries"); + QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("-n"))), 0); + if (m_qbsStdout.contains("unsupported toolset:")) + QSKIP(unsupportedToolsetMessage(m_qbsStdout)); + QCOMPARE(runQbs(QbsRunParameters("build")), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); + QCOMPARE(runQbs(QbsRunParameters("run")), 0); + QVERIFY2(m_qbsStdout.contains("Hello from app"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("Hello from lib"), m_qbsStdout.constData()); +} + +void TestBlackboxBareMetal::userIncludePaths() +{ + QDir::setCurrent(testDataDir + "/user-include-paths"); + QCOMPARE(runQbs(), 0); +} + +void TestBlackboxBareMetal::systemIncludePaths() +{ + QDir::setCurrent(testDataDir + "/system-include-paths"); + QCOMPARE(runQbs(), 0); +} + +void TestBlackboxBareMetal::distributionIncludePaths() +{ + QDir::setCurrent(testDataDir + "/distribution-include-paths"); + QCOMPARE(runQbs(), 0); +} + +void TestBlackboxBareMetal::compilerIncludePaths() +{ + QDir::setCurrent(testDataDir + "/compiler-include-paths"); + QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("-n"))), 0); + if (!m_qbsStdout.contains("compilerIncludePaths:")) + QFAIL("No compiler include paths exists"); + + QStringList includePaths; + QVERIFY(extractCompilerIncludePaths(m_qbsStdout, includePaths)); + QVERIFY(includePaths.count() > 0); + for (const auto &includePath : includePaths) { + const QDir dir(includePath); + QVERIFY(dir.exists()); + } +} + +void TestBlackboxBareMetal::preincludeHeaders() +{ + QDir::setCurrent(testDataDir + "/preinclude-headers"); + QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("-n"))), 0); + if (m_qbsStdout.contains("unsupported toolset:")) + QSKIP(unsupportedToolsetMessage(m_qbsStdout)); + QCOMPARE(runQbs(), 0); +} + +void TestBlackboxBareMetal::defines() +{ + QDir::setCurrent(testDataDir + "/defines"); + QCOMPARE(runQbs(), 0); +} + +void TestBlackboxBareMetal::compilerListingFiles_data() +{ + QTest::addColumn<bool>("generateListing"); + QTest::addColumn<QString>("customListingSuffix"); + QTest::newRow("do-not-generate-compiler-listing") << false << ""; + QTest::newRow("generate-default-compiler-listing") << true << ""; + QTest::newRow("generate-custom-compiler-listing") << true << ".lll"; +} + +void TestBlackboxBareMetal::compilerListingFiles() +{ + QFETCH(bool, generateListing); + QFETCH(QString, customListingSuffix); + QDir::setCurrent(testDataDir + "/compiler-listing"); + + rmDirR(relativeBuildDir()); + QStringList args = {QStringLiteral("modules.cpp.generateCompilerListingFiles:%1") + .arg(generateListing ? "true" : "false")}; + if (!customListingSuffix.isEmpty()) + args << QStringLiteral("modules.cpp.compilerListingSuffix:%1").arg(customListingSuffix); + + QCOMPARE(runQbs(QbsRunParameters("resolve", args)), 0); + if (m_qbsStdout.contains("unsupported toolset:")) + QSKIP(unsupportedToolsetMessage(m_qbsStdout)); + if (!m_qbsStdout.contains("compiler listing suffix:")) + QFAIL("No current compiler listing suffix pattern exists"); + + QString compilerListingSuffix; + if (!extractQuitedValue(m_qbsStdout, compilerListingSuffix)) + QFAIL("Unable to extract current compiler listing suffix"); + + if (!customListingSuffix.isEmpty()) + QCOMPARE(compilerListingSuffix, customListingSuffix); + + QCOMPARE(runQbs(QbsRunParameters(args)), 0); + const QString productBuildDir = relativeProductBuildDir("compiler-listing"); + const QString hash = inputDirHash("."); + const QString mainListing = productBuildDir + "/" + hash + + "/main.c" + compilerListingSuffix; + QCOMPARE(regularFileExists(mainListing), generateListing); + const QString funListing = productBuildDir + "/" + hash + + "/fun.c" + compilerListingSuffix; + QCOMPARE(regularFileExists(funListing), generateListing); +} + +void TestBlackboxBareMetal::linkerMapFile_data() +{ + QTest::addColumn<bool>("generateMap"); + QTest::addColumn<QString>("customMapSuffix"); + QTest::newRow("do-not-generate-linker-map") << false << ""; + QTest::newRow("generate-default-linker-map") << true << ""; + QTest::newRow("generate-custom-linker-map") << true << ".mmm"; +} + +void TestBlackboxBareMetal::linkerMapFile() +{ + QFETCH(bool, generateMap); + QFETCH(QString, customMapSuffix); + QDir::setCurrent(testDataDir + "/linker-map"); + + rmDirR(relativeBuildDir()); + QStringList args = {QStringLiteral("modules.cpp.generateLinkerMapFile:%1") + .arg(generateMap ? "true" : "false")}; + if (!customMapSuffix.isEmpty()) + args << QStringLiteral("modules.cpp.linkerMapSuffix:%1").arg(customMapSuffix); + + QCOMPARE(runQbs(QbsRunParameters("resolve", args)), 0); + if (!m_qbsStdout.contains("linker map suffix:")) + QFAIL("No current linker map suffix pattern exists"); + + QString linkerMapSuffix; + if (!extractQuitedValue(m_qbsStdout, linkerMapSuffix)) + QFAIL("Unable to extract current linker map suffix"); + + if (!customMapSuffix.isEmpty()) + QCOMPARE(linkerMapSuffix, customMapSuffix); + + QCOMPARE(runQbs(QbsRunParameters(args)), 0); + const QString productBuildDir = relativeProductBuildDir("linker-map"); + const QString linkerMap = productBuildDir + "/linker-map" + linkerMapSuffix; + QCOMPARE(regularFileExists(linkerMap), generateMap); +} + +void TestBlackboxBareMetal::compilerDefinesByLanguage() +{ + QDir::setCurrent(testDataDir + "/compiler-defines-by-language"); + QbsRunParameters params(QStringList{ "-f", "compiler-defines-by-language.qbs" }); + QCOMPARE(runQbs(params), 0); +} + +void TestBlackboxBareMetal::toolchainProbe() +{ + QDir::setCurrent(testDataDir + "/toolchain-probe"); + QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("-n"))), 0); + if (m_qbsStdout.contains("broken probe:")) + QFAIL(brokenProbeMessage(m_qbsStdout)); +} + +QTEST_MAIN(TestBlackboxBareMetal) diff --git a/tests/auto/blackbox/tst_blackboxbaremetal.h b/tests/auto/blackbox/tst_blackboxbaremetal.h new file mode 100644 index 000000000..9c45fa63c --- /dev/null +++ b/tests/auto/blackbox/tst_blackboxbaremetal.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef TST_BLACKBOXBAREMETAL_H +#define TST_BLACKBOXBAREMETAL_H + +#include "tst_blackboxbase.h" + +class TestBlackboxBareMetal : public TestBlackboxBase +{ + Q_OBJECT + +public: + TestBlackboxBareMetal(); + +private slots: + void targetPlatform(); + + void application_data(); + void application(); + + void staticLibraryDependencies(); + void externalStaticLibraries(); + + void sharedLibraries(); + + void userIncludePaths(); + void systemIncludePaths(); + void distributionIncludePaths(); + void compilerIncludePaths(); + + void preincludeHeaders(); + + void defines(); + + void compilerListingFiles_data(); + void compilerListingFiles(); + + void linkerMapFile_data(); + void linkerMapFile(); + + void compilerDefinesByLanguage(); + + void toolchainProbe(); + +private: + +}; + +#endif // TST_BLACKBOXBAREMETAL_H diff --git a/tests/auto/blackbox/tst_blackboxbase.cpp b/tests/auto/blackbox/tst_blackboxbase.cpp index 61b0271f6..317a6b663 100644 --- a/tests/auto/blackbox/tst_blackboxbase.cpp +++ b/tests/auto/blackbox/tst_blackboxbase.cpp @@ -64,7 +64,7 @@ static bool supportsSettingsDirOption(const QString &command) { TestBlackboxBase::TestBlackboxBase(const QString &testDataSrcDir, const QString &testName) : testDataDir(testWorkDir(testName)), - testSourceDir(QDir::cleanPath(testDataSrcDir)), + testSourceDir(testDataSourceDir(testDataSrcDir)), qbsExecutableFilePath(initQbsExecutableFilePath()), defaultInstallRoot(relativeBuildDir() + QLatin1Char('/') + InstallOptions::defaultInstallRoot()) { @@ -96,14 +96,18 @@ int TestBlackboxBase::runQbs(const QbsRunParameters ¶ms) process.setWorkingDirectory(params.workingDir); process.setProcessEnvironment(params.environment); process.start(qbsExecutableFilePath, args); + int exitCode = 0; if (!process.waitForStarted() || !process.waitForFinished(testTimeoutInMsecs()) || process.exitStatus() != QProcess::NormalExit) { - m_qbsStderr = process.readAllStandardError(); if (!params.expectCrash) { QTest::qFail("qbs did not run correctly", __FILE__, __LINE__); qDebug("%s", qPrintable(process.errorString())); } - return -1; + exitCode = -1; + } else if (m_qbsStdout.contains("Memory leak:")) { + exitCode = 27; + } else { + exitCode = process.exitCode(); } m_qbsStderr = process.readAllStandardError(); @@ -111,14 +115,14 @@ int TestBlackboxBase::runQbs(const QbsRunParameters ¶ms) sanitizeOutput(&m_qbsStderr); sanitizeOutput(&m_qbsStdout); const bool shouldLog = (process.exitStatus() != QProcess::NormalExit - || process.exitCode() != 0) && !params.expectFailure; + || exitCode != 0) && !params.expectFailure; if (!m_qbsStderr.isEmpty() && (shouldLog || qEnvironmentVariableIsSet("QBS_AUTOTEST_ALWAYS_LOG_STDERR"))) qDebug("%s", m_qbsStderr.constData()); if (!m_qbsStdout.isEmpty() && (shouldLog || qEnvironmentVariableIsSet("QBS_AUTOTEST_ALWAYS_LOG_STDOUT"))) qDebug("%s", m_qbsStdout.constData()); - return process.exitCode(); + return exitCode; } /*! @@ -194,10 +198,30 @@ void TestBlackboxBase::initTestCase() QVERIFY(copyDllExportHeader(testSourceDir, testDataDir)); } +void TestBlackboxBase::validateTestProfile() +{ + const SettingsPtr s = settings(); + if (profileName() != "none" && !s->profiles().contains(profileName())) + QFAIL(QByteArray("The build profile '" + profileName().toLocal8Bit() + + "' could not be found. Please set it up on your machine.")); + if (!m_needsQt) + return; + const QStringList qmakeFilePaths = Profile(profileName(), s.get()) + .value("moduleProviders.Qt.qmakeFilePaths").toStringList(); + if (!qmakeFilePaths.empty()) + return; + if (!findExecutable(QStringList{"qmake"}).isEmpty()) + return; + QSKIP(QByteArray("The build profile '" + profileName().toLocal8Bit() + + "' is not a valid Qt profile and Qt was not found " + "in the global search paths.")); + +} + QString TestBlackboxBase::findExecutable(const QStringList &fileNames) { const QStringList path = QString::fromLocal8Bit(qgetenv("PATH")) - .split(HostOsInfo::pathListSeparator(), QString::SkipEmptyParts); + .split(HostOsInfo::pathListSeparator(), Qt::SkipEmptyParts); for (const QString &fileName : fileNames) { QFileInfo fi(fileName); @@ -232,3 +256,34 @@ QMap<QString, QString> TestBlackboxBase::findJdkTools(int *status) {"jar", QDir::fromNativeSeparators(tools["jar"].toString())} }; } + +qbs::Version TestBlackboxBase::qmakeVersion(const QString &qmakeFilePath) +{ + QStringList arguments; + arguments << "-query" << "QT_VERSION"; + QProcess qmakeProcess; + qmakeProcess.start(qmakeFilePath, arguments); + if (!qmakeProcess.waitForStarted() || !qmakeProcess.waitForFinished() + || qmakeProcess.exitStatus() != QProcess::NormalExit) { + qDebug() << "qmake '" << qmakeFilePath << "' could not be run."; + return qbs::Version(); + } + QByteArray result = qmakeProcess.readAll().simplified(); + qbs::Version version = qbs::Version::fromString(result); + if (!version.isValid()) + qDebug() << "qmake '" << qmakeFilePath << "' version is not valid."; + return version; +} + +bool waitForProcessSuccess(QProcess &p, int msecs) +{ + if (!p.waitForStarted(msecs) || !p.waitForFinished(msecs)) { + qDebug() << p.errorString(); + return false; + } + if (p.exitCode() != 0) { + qDebug() << p.readAllStandardError(); + return false; + } + return true; +} diff --git a/tests/auto/blackbox/tst_blackboxbase.h b/tests/auto/blackbox/tst_blackboxbase.h index 251f3752d..5733cacd7 100644 --- a/tests/auto/blackbox/tst_blackboxbase.h +++ b/tests/auto/blackbox/tst_blackboxbase.h @@ -42,14 +42,14 @@ public: init(); } - QbsRunParameters(const QString &cmd, const QStringList &args = QStringList()) - : command(cmd), arguments(args) + QbsRunParameters(QString cmd, QStringList args = QStringList()) + : command(std::move(cmd)), arguments(std::move(args)) { init(); } - QbsRunParameters(const QStringList &args) - : arguments(args) + QbsRunParameters(QStringList args) + : arguments(std::move(args)) { init(); } @@ -60,7 +60,14 @@ public: expectCrash = false; profile = profileName(); settingsDir = settings()->baseDirectory(); - environment = QProcessEnvironment::systemEnvironment(); + environment = defaultEnvironment(); + } + + static QProcessEnvironment defaultEnvironment() + { + auto result = QProcessEnvironment::systemEnvironment(); + result.insert(QStringLiteral("QBS_AUTOTEST_CODE_SIGNING_REQUIRED"), QStringLiteral("0")); + return result; } QString command; @@ -83,15 +90,19 @@ public: public slots: virtual void initTestCase(); + static QString findExecutable(const QStringList &fileNames); + protected: - virtual void validateTestProfile() { } + virtual void validateTestProfile(); + + void setNeedsQt() { m_needsQt = true; } int runQbs(const QbsRunParameters ¶ms = QbsRunParameters()); void rmDirR(const QString &dir); static QByteArray unifiedLineEndings(const QByteArray &ba); static void sanitizeOutput(QByteArray *ba); static void ccp(const QString &sourceDirPath, const QString &targetDirPath); - static QString findExecutable(const QStringList &fileNames); QMap<QString, QString> findJdkTools(int *status); + static qbs::Version qmakeVersion(const QString &qmakeFilePath); const QString testDataDir; const QString testSourceDir; @@ -100,6 +111,9 @@ protected: QByteArray m_qbsStderr; QByteArray m_qbsStdout; + int m_needsQt = false; }; +bool waitForProcessSuccess(QProcess &p, int msecs = 30000); + #endif // TST_BLACKBOXBASE_H diff --git a/tests/auto/blackbox/tst_blackboxexamples.cpp b/tests/auto/blackbox/tst_blackboxexamples.cpp new file mode 100644 index 000000000..13ccb7796 --- /dev/null +++ b/tests/auto/blackbox/tst_blackboxexamples.cpp @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2020 Ivan Komissarov (abbapoh@gmail.com) +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "tst_blackboxexamples.h" + +#include <QtCore/qdir.h> +#include <QtCore/qdiriterator.h> + +QStringList TestBlackboxExamples::collectExamples(const QString &dirPath) +{ + QStringList result; + QDir dir(dirPath); + const auto subDirs = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name); + for (const auto &subDir : subDirs) { + const auto path = dir.filePath(subDir); + if (!QFileInfo::exists(path + "/" + subDir + ".qbs")) + continue; + result.append(QDir(testDataDir).relativeFilePath(path)); + } + return result; +} + +TestBlackboxExamples::TestBlackboxExamples() + : TestBlackboxBase(SRCDIR "/../../../examples/", "blackbox-examples") +{ + setNeedsQt(); +} + +void TestBlackboxExamples::baremetal_data() +{ + QTest::addColumn<QString>("example"); + + QDir baremetal(testDataDir + "/baremetal/"); + const auto subDirs = baremetal.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name); + for (const auto &subDir : subDirs) { + const auto examples = collectExamples(baremetal.filePath(subDir)); + for (const auto &example: examples) { + const auto relativePath = baremetal.relativeFilePath(example); + QTest::newRow(relativePath.toUtf8().data()) << relativePath; + } + } +} + +void TestBlackboxExamples::baremetal() +{ + QFETCH(QString, example); + + QVERIFY(QDir::setCurrent(testDataDir + "/" + example)); + QCOMPARE(runQbs(), 0); +} + +void TestBlackboxExamples::examples_data() +{ + QTest::addColumn<QString>("example"); + + auto examples = collectExamples(testDataDir); + examples.append(collectExamples(testDataDir + "/protobuf")); + examples.append(collectExamples(testDataDir + "/flatbuffers")); + std::sort(examples.begin(), examples.end()); + + for (const auto &example: examples) { + if (example == u"baremetal") + continue; + QTest::newRow(example.toUtf8().data()) << example; + } +} + +void TestBlackboxExamples::examples() +{ + QFETCH(QString, example); + + QVERIFY(QDir::setCurrent(testDataDir + "/" + example)); + QbsRunParameters params( + {QStringLiteral("-f"), QFileInfo(example).fileName() + QStringLiteral(".qbs")}); + QCOMPARE(runQbs(params), 0); +} + +QTEST_MAIN(TestBlackboxExamples) diff --git a/tests/auto/blackbox/tst_blackboxexamples.h b/tests/auto/blackbox/tst_blackboxexamples.h new file mode 100644 index 000000000..bea8be768 --- /dev/null +++ b/tests/auto/blackbox/tst_blackboxexamples.h @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2020 Ivan Komissarov (abbapoh@gmail.com) +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef TST_BLACKBOXEXAMPLES_H +#define TST_BLACKBOXEXAMPLES_H + +#include "tst_blackboxbase.h" + +class TestBlackboxExamples : public TestBlackboxBase +{ + Q_OBJECT + +private: + QStringList collectExamples(const QString &dirPath); + +public: + TestBlackboxExamples(); + +private slots: + void baremetal_data(); + void baremetal(); + void examples_data(); + void examples(); +}; + +#endif // TST_BLACKBOXEXAMPLES_H diff --git a/tests/auto/blackbox/tst_blackboxjava.cpp b/tests/auto/blackbox/tst_blackboxjava.cpp index f7feb0612..4ddd6cdda 100644 --- a/tests/auto/blackbox/tst_blackboxjava.cpp +++ b/tests/auto/blackbox/tst_blackboxjava.cpp @@ -39,7 +39,9 @@ using qbs::Internal::HostOsInfo; using qbs::Profile; -TestBlackboxJava::TestBlackboxJava() : TestBlackboxBase (SRCDIR "/testdata-java", "blackbox-java") +TestBlackboxJava::TestBlackboxJava() + : TestBlackboxBase (SRCDIR "/testdata-java", "blackbox-java"), + m_blacklistedJdks(qgetenv("QBS_AUTOTEST_JDK_BLACKLIST")) { } @@ -73,6 +75,9 @@ void TestBlackboxJava::java() QSKIP("java.jdkPath not set and automatic detection failed"); } + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Skip test in cross-compiled build"); + QCOMPARE(status, 0); const QStringList classFiles = @@ -93,7 +98,7 @@ void TestBlackboxJava::java() // Now check whether we correctly predicted the class file output paths. QCOMPARE(runQbs(QbsRunParameters("clean")), 0); - for (const QString &classFile : qAsConst(classFiles1)) { + for (const QString &classFile : std::as_const(classFiles1)) { QVERIFY2(!regularFileExists(classFile), qPrintable(classFile)); } @@ -119,7 +124,7 @@ void TestBlackboxJava::java() if (process.waitForStarted()) { QVERIFY2(process.waitForFinished(), qPrintable(process.errorString())); const QByteArray stdOut = process.readAllStandardOutput(); - QVERIFY2(stdOut.contains("Class-Path: car_jar.jar random_stuff.jar"), stdOut.constData()); + QVERIFY2(stdOut.contains("Class-Path: random_stuff.jar car_jar.jar"), stdOut.constData()); QVERIFY2(stdOut.contains("Main-Class: Vehicles"), stdOut.constData()); QVERIFY2(stdOut.contains("Some-Property: Some-Value"), stdOut.constData()); QVERIFY2(stdOut.contains("Additional-Property: Additional-Value"), stdOut.constData()); @@ -145,8 +150,11 @@ void TestBlackboxJava::javaDependencyTracking() QDir::setCurrent(testDataDir + "/java"); QbsRunParameters rp; rp.arguments.push_back("--check-outputs"); - if (!jdkPath.isEmpty()) + if (!jdkPath.isEmpty()) { + if (m_blacklistedJdks.contains(jdkPath)) + QSKIP("skipping blacklisted JDK"); rp.arguments << ("modules.java.jdkPath:" + jdkPath); + } if (!javaVersion.isEmpty()) rp.arguments << ("modules.java.languageVersion:'" + javaVersion + "'"); rmDirR(relativeBuildDir()); @@ -167,7 +175,7 @@ void TestBlackboxJava::javaDependencyTracking_data() auto getSpecificJdkVersion = [](const QString &jdkVersion) -> QString { if (HostOsInfo::isMacosHost()) { QProcess java_home; - java_home.start("/usr/libexec/java_home", QStringList() << "--version" << jdkVersion); + java_home.start("/usr/libexec/java_home", {"--version", jdkVersion, "--failfast"}); java_home.waitForFinished(); if (java_home.exitStatus() == QProcess::NormalExit && java_home.exitCode() == 0) return QString::fromLocal8Bit(java_home.readAllStandardOutput().trimmed()); @@ -184,6 +192,7 @@ void TestBlackboxJava::javaDependencyTracking_data() "/usr/lib/jvm/java-" + minorVersion + "-openjdk" + dpkgArch("-"), // Debian "/usr/lib/jvm/java-" + minorVersion + "-openjdk", // Arch "/usr/lib/jvm/jre-1." + minorVersion + ".0-openjdk", // Fedora + "/usr/lib64/jvm/java-1." + minorVersion + ".0-openjdk", // OpenSuSE }; for (const QString &searchPath : searchPaths) { if (QFile::exists(searchPath + "/bin/javac")) @@ -194,7 +203,7 @@ void TestBlackboxJava::javaDependencyTracking_data() return {}; }; - static const auto knownJdkVersions = QStringList() << "1.6" << "1.7" << "1.8" << "1.9" + static const auto knownJdkVersions = QStringList() << "1.7" << "1.8" << "1.9" << QString(); // default JDK; QStringList seenJdkVersions; for (const auto &jdkVersion : knownJdkVersions) { diff --git a/tests/auto/blackbox/tst_blackboxjava.h b/tests/auto/blackbox/tst_blackboxjava.h index 68d8a7f80..e770306df 100644 --- a/tests/auto/blackbox/tst_blackboxjava.h +++ b/tests/auto/blackbox/tst_blackboxjava.h @@ -43,6 +43,9 @@ private slots: void javaDependencyTracking(); void javaDependencyTracking_data(); void javaDependencyTrackingInnerClass(); + +private: + const QStringList m_blacklistedJdks; }; #endif // TST_BLACKBOX_H diff --git a/tests/auto/blackbox/tst_blackboxjoblimits.cpp b/tests/auto/blackbox/tst_blackboxjoblimits.cpp index 89b5f638e..acaf69a5b 100644 --- a/tests/auto/blackbox/tst_blackboxjoblimits.cpp +++ b/tests/auto/blackbox/tst_blackboxjoblimits.cpp @@ -39,6 +39,7 @@ public: TestBlackboxJobLimits(); private slots: + void initTestCase(); void jobLimits_data(); void jobLimits(); }; @@ -48,6 +49,16 @@ TestBlackboxJobLimits::TestBlackboxJobLimits() { } +void TestBlackboxJobLimits::initTestCase() +{ + TestBlackboxBase::initTestCase(); + + QDir::setCurrent(testDataDir + "/job-limits-init"); + QCOMPARE(runQbs({"resolve"}), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Skip test in cross-compiled build"); +} + void TestBlackboxJobLimits::jobLimits_data() { QTest::addColumn<int>("projectJobCount"); @@ -143,6 +154,7 @@ void TestBlackboxJobLimits::jobLimits() SettingsPtr theSettings = settings(); qbs::Internal::TemporaryProfile profile("jobLimitsProfile", theSettings.get()); profile.p.setValue("preferences.jobLimit.singleton", prefsJobCount); + profile.p.setValue("baseProfile", profileName()); theSettings->sync(); QbsRunParameters resolveParams("resolve"); resolveParams.profile = profile.p.name(); @@ -150,6 +162,7 @@ void TestBlackboxJobLimits::jobLimits() << ("project.productJobCount:" + QString::number(productJobCount)) << ("project.moduleJobCount:" + QString::number(moduleJobCount)); QCOMPARE(runQbs(resolveParams), 0); + QbsRunParameters buildParams; buildParams.expectFailure = !expectSuccess; if (cliJobCount != -1) @@ -165,7 +178,7 @@ void TestBlackboxJobLimits::jobLimits() else QVERIFY2(m_qbsStderr.contains("exclusive"), m_qbsStderr.constData()); if (exitCode == 0) - QCOMPARE(m_qbsStdout.count("Running tool"), 5); + QCOMPARE(m_qbsStdout.count("running tool"), 5); } QTEST_MAIN(TestBlackboxJobLimits) diff --git a/tests/auto/blackbox/tst_blackboxproviders.cpp b/tests/auto/blackbox/tst_blackboxproviders.cpp new file mode 100644 index 000000000..cf6594229 --- /dev/null +++ b/tests/auto/blackbox/tst_blackboxproviders.cpp @@ -0,0 +1,443 @@ +/**************************************************************************** +** +** Copyright (C) 2023 Ivan Komissarov (abbapoh@gmail.com) +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "tst_blackboxproviders.h" + +#include "../shared.h" + +// #include <tools/hostosinfo.h> +// #include <tools/profile.h> +// #include <tools/qttools.h> + +// #include <QtCore/qdir.h> +// #include <QtCore/qregularexpression.h> + +// using qbs::Internal::HostOsInfo; +// using qbs::Profile; + +#define WAIT_FOR_NEW_TIMESTAMP() waitForNewTimestamp(testDataDir) + +TestBlackboxProviders::TestBlackboxProviders() + : TestBlackboxBase(SRCDIR "/testdata-providers", "blackbox-providers") +{ +} + +void TestBlackboxProviders::allowedValues() +{ + QFETCH(QStringList, arguments); + QFETCH(bool, expectFailure); + + QDir::setCurrent(testDataDir + "/allowed-values"); + rmDirR(relativeBuildDir()); + QbsRunParameters params; + params.arguments = arguments; + params.expectFailure = expectFailure; + + QVERIFY2(runQbs(params) == int(expectFailure), m_qbsStderr); +} + +void TestBlackboxProviders::allowedValues_data() +{ + QTest::addColumn<QStringList>("arguments"); + QTest::addColumn<bool>("expectFailure"); + + QTest::newRow("invalid js value") << QStringList{} << true; + QTest::newRow("invalid variant value") + << QStringList{"moduleProviders.provider.aProperty:three"} << true; + QTest::newRow("valid variant value") + << QStringList{"moduleProviders.provider.aProperty:one"} << false; +} + +void TestBlackboxProviders::brokenProvider() +{ + QDir::setCurrent(testDataDir + "/broken-provider"); + QbsRunParameters params; + params.expectFailure = true; + QVERIFY(runQbs(params) != 0); + + QVERIFY(m_qbsStderr.contains("Error executing provider for module 'qbsothermodule'")); + QVERIFY(m_qbsStderr.contains("Error executing provider for module 'qbsmetatestmodule'")); + QCOMPARE(m_qbsStderr.count("This provider is broken"), 2); +} + +void TestBlackboxProviders::conanProvider() +{ + QFETCH(bool, generateConanFiles); + QFETCH(bool, successExpected); + + const auto executable = findExecutable({"conan"}); + if (executable.isEmpty()) + QSKIP("conan is not installed or not available in PATH."); + + const auto generator = QDir::homePath() + "/.conan2/extensions/generators/qbsdeps.py"; + if (!QFileInfo(generator).exists()) { + QSKIP( + "qbsdeps.py is not installed, call 'conan config install src/conan/ from qbs source'."); + } + + const auto profilePath = QDir::homePath() + "/.conan2/profiles/qbs-test"; + if (!QFileInfo(profilePath).exists()) + QSKIP("conan profile is not installed, run './scripts/setup-conan-profiles.sh'."); + + // install testlibdep first + QProcess conan; + QDir::setCurrent(testDataDir + "/conan-provider/testlibdep"); + conan.start(executable, {"create", ".", "--profile:all=qbs-test"}); + QVERIFY(waitForProcessSuccess(conan)); + + // install testlib second + QDir::setCurrent(testDataDir + "/conan-provider/testlib"); + conan.start(executable, {"create", ".", "--profile:all=qbs-test"}); + QVERIFY(waitForProcessSuccess(conan)); + + // install header lib third + QDir::setCurrent(testDataDir + "/conan-provider/testlibheader"); + conan.start(executable, {"create", ".", "--profile:all=qbs-test"}); + QVERIFY(waitForProcessSuccess(conan)); + + // now build an app using those libs + QDir::setCurrent(testDataDir + "/conan-provider"); + + rmDirR(relativeBuildDir()); + rmDirR("build"); + + if (generateConanFiles) { + QStringList arguments{ + "install", ".", "-g=QbsDeps", "--profile:all=qbs-test", "--output-folder=build"}; + QProcess conan; + conan.start(executable, arguments); + QVERIFY(waitForProcessSuccess(conan)); + } + + QbsRunParameters buildParams( + "build", + {"--force-probe-execution", + "moduleProviders.conan.installDirectory:" + QDir::currentPath() + "/build"}); + buildParams.expectFailure = !successExpected; + QCOMPARE(runQbs(buildParams) == 0, successExpected); +} + +void TestBlackboxProviders::conanProvider_data() +{ + QTest::addColumn<bool>("generateConanFiles"); + QTest::addColumn<bool>("successExpected"); + + QTest::addRow("no conan files generated") << false << false; + QTest::addRow("conan files generated") << true << true; +} + +void TestBlackboxProviders::moduleProviders() +{ + QDir::setCurrent(testDataDir + "/module-providers"); + + // Resolving in dry-run mode must not leave any data behind. + QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("-n"))), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); + QCOMPARE(m_qbsStdout.count("Running setup script for mygenerator"), 2); + QVERIFY(!QFile::exists(relativeBuildDir())); + + // Initial build. + QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app1"})), 0); + QVERIFY(QFile::exists(relativeBuildDir())); + QCOMPARE(m_qbsStdout.count("Running setup script for mygenerator"), 2); + QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("The MY_DEFINE is app1"), m_qbsStdout.constData()); + QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app2"})), 0); + QVERIFY2(m_qbsStdout.contains("The letters are Z and Y"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("The MY_DEFINE is app2"), m_qbsStdout.constData()); + + // Rebuild with overridden module provider config. The output for product 2 must change, + // but no setup script must be re-run, because both config values have already been + // handled in the first run. + const QStringList resolveArgs("moduleProviders.mygenerator.chooseLettersFrom:beginning"); + QCOMPARE(runQbs(QbsRunParameters("resolve", resolveArgs)), 0); + QVERIFY2(!m_qbsStdout.contains("Running setup script"), m_qbsStdout.constData()); + QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app1"})), 0); + QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); + QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app2"})), 0); + QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); + + // Forcing Probe execution triggers a re-run of the setup script. But only once, + // because the module provider config is the same now. + QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList(resolveArgs) + << "--force-probe-execution")), 0); + QCOMPARE(m_qbsStdout.count("Running setup script for mygenerator"), 1); + QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app1"})), 0); + QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); + QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app2"})), 0); + QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); + + // Now re-run without the module provider config override. Again, the setup script must + // run once, for the config value that was not present in the last run. + QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); + QCOMPARE(m_qbsStdout.count("Running setup script for mygenerator"), 1); + QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app1"})), 0); + QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); + QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app2"})), 0); + QVERIFY2(m_qbsStdout.contains("The letters are Z and Y"), m_qbsStdout.constData()); +} + +// Checks regression - when loading 2 modules from the same provider, the second module should +// come from provider cache +void TestBlackboxProviders::moduleProvidersCache() +{ + QDir::setCurrent(testDataDir + "/module-providers-cache"); + + QbsRunParameters params("resolve", {"-v"}); + QCOMPARE(runQbs(params), 0); + const auto qbsmetatestmoduleMessage = "Re-checking for module \"qbsmetatestmodule\" with " + "newly added search paths from module provider"; + const auto qbsothermoduleMessage = "Re-checking for module \"qbsothermodule\" with " + "newly added search paths from module provider"; + QCOMPARE(m_qbsStderr.count(qbsmetatestmoduleMessage), 1); + QCOMPARE(m_qbsStderr.count(qbsothermoduleMessage), 1); + QCOMPARE(m_qbsStderr.count("Re-using provider \"provider_a\" from cache"), 1); + + // We didn't change providers, so both modules should come from cache. + params.arguments << "project.dummyProp:value"; + QCOMPARE(runQbs(params), 0); + QCOMPARE(m_qbsStderr.count(qbsmetatestmoduleMessage), 1); + QCOMPARE(m_qbsStderr.count(qbsothermoduleMessage), 1); + QCOMPARE(m_qbsStderr.count("Re-using provider \"provider_a\" from cache"), 2); +} + +void TestBlackboxProviders::nonEagerModuleProvider() +{ + QDir::setCurrent(testDataDir + "/non-eager-provider"); + + QbsRunParameters params("resolve"); + QCOMPARE(runQbs(params), 0); + QVERIFY2(m_qbsStdout.contains(("Running setup script for qbsmetatestmodule")), m_qbsStdout); + QVERIFY2(m_qbsStdout.contains(("Running setup script for qbsothermodule")), m_qbsStdout); + QVERIFY2(!m_qbsStdout.contains(("Running setup script for nonexistentmodule")), m_qbsStdout); + + QVERIFY2(m_qbsStdout.contains(("p1.qbsmetatestmodule.prop: from_provider_a")), + m_qbsStdout); + QVERIFY2(m_qbsStdout.contains(("p1.qbsothermodule.prop: from_provider_a")), + m_qbsStdout); +} + +void TestBlackboxProviders::probeInModuleProvider() +{ + QDir::setCurrent(testDataDir + "/probe-in-module-provider"); + + QbsRunParameters params; + params.command = "build"; + params.arguments << "--force-probe-execution"; + QCOMPARE(runQbs(params), 0); + QVERIFY2(m_qbsStdout.contains("Running probe"), m_qbsStdout); + QVERIFY2(m_qbsStdout.contains("p.qbsmetatestmodule.boolProp: true"), m_qbsStdout); + WAIT_FOR_NEW_TIMESTAMP(); + touch("probe-in-module-provider.qbs"); + QCOMPARE(runQbs(), 0); + QVERIFY2(m_qbsStdout.contains("p.qbsmetatestmodule.boolProp: true"), m_qbsStdout); + QVERIFY2(m_qbsStdout.contains("p.qbsmetatestmodule.prop: \"value\""), m_qbsStdout); + QVERIFY2(!m_qbsStdout.contains("Running probe"), m_qbsStdout); +} + +// Tests whether it is possible to set providers properties in a Product or from command-line +void TestBlackboxProviders::providersProperties() +{ + QDir::setCurrent(testDataDir + "/providers-properties"); + + QbsRunParameters params("build"); + params.arguments = QStringList("moduleProviders.provider_b.someProp: \"first,second\""); + QCOMPARE(runQbs(params), 0); + QVERIFY2(m_qbsStdout.contains("p.qbsmetatestmodule.listProp: [\"someValue\"]"), m_qbsStdout); + QVERIFY2(m_qbsStdout.contains( + "p.qbsothermodule.listProp: [\"first\",\"second\"]"), m_qbsStdout); +} + +// checks that we can set qbs module properties in providers and provider cache works corectly +void TestBlackboxProviders::qbsModulePropertiesInProviders() +{ + QDir::setCurrent(testDataDir + "/qbs-module-properties-in-providers"); + + QbsRunParameters params("resolve"); + + QCOMPARE(runQbs(params), 0); + + // We have 2 products in 2 configurations, but second product should use the cached value + // so we should have only 2 copies of the module, not 4. + QCOMPARE(m_qbsStdout.count("Running setup script for qbsmetatestmodule"), 2); + + // Check that products get correct values from modules + QVERIFY2(m_qbsStdout.contains(("product1.qbsmetatestmodule.prop: /sysroot1")), m_qbsStdout); + QVERIFY2(m_qbsStdout.contains(("product1.qbsmetatestmodule.prop: /sysroot2")), m_qbsStdout); + + QVERIFY2(m_qbsStdout.contains(("product2.qbsmetatestmodule.prop: /sysroot1")), m_qbsStdout); + QVERIFY2(m_qbsStdout.contains(("product2.qbsmetatestmodule.prop: /sysroot2")), m_qbsStdout); +} + +void TestBlackboxProviders::qbsModuleProviders_data() +{ + QTest::addColumn<QStringList>("arguments"); + QTest::addColumn<QString>("firstProp"); + QTest::addColumn<QString>("secondProp"); + + QTest::newRow("default") << QStringList() << "from_provider_a" << "undefined"; + QTest::newRow("override") + << QStringList("projects.project.qbsModuleProviders:provider_b") + << "from_provider_b" + << "from_provider_b"; + QTest::newRow("override list a") + << QStringList("projects.project.qbsModuleProviders:provider_a,provider_b") + << "from_provider_a" + << "from_provider_b"; + QTest::newRow("override list b") + << QStringList("projects.project.qbsModuleProviders:provider_b,provider_a") + << "from_provider_b" + << "from_provider_b"; +} + +// Tests whether it is possible to set qbsModuleProviders in Product and Project items +// and that the order of providers results in correct priority +void TestBlackboxProviders::qbsModuleProviders() +{ + QFETCH(QStringList, arguments); + QFETCH(QString, firstProp); + QFETCH(QString, secondProp); + + QDir::setCurrent(testDataDir + "/qbs-module-providers"); + + QbsRunParameters params("resolve"); + params.arguments = arguments; + QCOMPARE(runQbs(params), 0); + QVERIFY2(m_qbsStdout.contains(("p1.qbsmetatestmodule.prop: " + firstProp).toUtf8()), + m_qbsStdout); + QVERIFY2(m_qbsStdout.contains(("p1.qbsothermodule.prop: " + secondProp).toUtf8()), + m_qbsStdout); + QVERIFY2(m_qbsStdout.contains(("p2.qbsmetatestmodule.prop: " + firstProp).toUtf8()), + m_qbsStdout); + QVERIFY2(m_qbsStdout.contains(("p2.qbsothermodule.prop: " + secondProp).toUtf8()), + m_qbsStdout); +} + +void TestBlackboxProviders::qbsModuleProvidersCliOverride_data() +{ + QTest::addColumn<QStringList>("arguments"); + QTest::addColumn<QString>("propertyValue"); + + QTest::newRow("default") << QStringList() << "undefined"; + QTest::newRow("project-wide") + << QStringList("project.qbsModuleProviders:provider_a") + << "from_provider_a"; + QTest::newRow("concrete project") + << QStringList("projects.innerProject.qbsModuleProviders:provider_a") + << "from_provider_a"; + QTest::newRow("concrete product") + << QStringList("products.product.qbsModuleProviders:provider_a") + << "from_provider_a"; + QTest::newRow("concrete project override project-wide") + << QStringList({ + "project.qbsModuleProviders:provider_a", + "projects.innerProject.qbsModuleProviders:provider_b"}) + << "from_provider_b"; + QTest::newRow("concrete product override project-wide") + << QStringList({ + "project.qbsModuleProviders:provider_a", + "products.product.qbsModuleProviders:provider_b"}) + << "from_provider_b"; +} + +// Tests possible use-cases how to override providers from command-line +void TestBlackboxProviders::qbsModuleProvidersCliOverride() +{ + QFETCH(QStringList, arguments); + QFETCH(QString, propertyValue); + + QDir::setCurrent(testDataDir + "/qbs-module-providers-cli-override"); + + QbsRunParameters params("resolve"); + params.arguments = arguments; + QCOMPARE(runQbs(params), 0); + QVERIFY2(m_qbsStdout.contains(("qbsmetatestmodule.prop: " + propertyValue).toUtf8()), + m_qbsStdout); +} + +void TestBlackboxProviders::qbsModuleProvidersCompatibility_data() +{ + QTest::addColumn<QStringList>("arguments"); + QTest::addColumn<QString>("propertyValue"); + + QTest::newRow("default") << QStringList() << "from_scoped_provider"; + QTest::newRow("scoped by name") << QStringList("project.qbsModuleProviders:qbsmetatestmodule") << "from_scoped_provider"; + QTest::newRow("named") << QStringList("project.qbsModuleProviders:named_provider") << "from_named_provider"; +} + +// Tests whether scoped providers can be used as named, i.e. new provider machinery +// is compatible with the old one +void TestBlackboxProviders::qbsModuleProvidersCompatibility() +{ + QFETCH(QStringList, arguments); + QFETCH(QString, propertyValue); + + QDir::setCurrent(testDataDir + "/qbs-module-providers-compatibility"); + + QbsRunParameters params("resolve"); + params.arguments = arguments; + QCOMPARE(runQbs(params), 0); + QVERIFY2(m_qbsStdout.contains(("qbsmetatestmodule.prop: " + propertyValue).toUtf8()), + m_qbsStdout); +} + +void TestBlackboxProviders::qbspkgconfigModuleProvider() +{ + QDir::setCurrent(testDataDir + "/qbspkgconfig-module-provider/libs"); + rmDirR(relativeBuildDir()); + + const auto commonParams = QbsRunParameters(QStringLiteral("install"), { + QStringLiteral("--install-root"), + QStringLiteral("install-root") + }); + auto dynamicParams = commonParams; + dynamicParams.arguments << "config:library" << "projects.libs.isBundle:false"; + QCOMPARE(runQbs(dynamicParams), 0); + + QDir::setCurrent(testDataDir + "/qbspkgconfig-module-provider"); + rmDirR(relativeBuildDir()); + + const auto sysroot = testDataDir + "/qbspkgconfig-module-provider/libs/install-root"; + + QbsRunParameters params; + params.arguments << "moduleProviders.qbspkgconfig.sysroot:" + sysroot; + QCOMPARE(runQbs(params), 0); +} + +void TestBlackboxProviders::removalVersion() +{ + QDir::setCurrent(testDataDir + "/removal-version"); + QCOMPARE(runQbs(), 0); + QVERIFY(m_qbsStderr.contains( + "Property 'deprecated' was scheduled for removal in version 2.2.0, but is still present")); +} + +QTEST_MAIN(TestBlackboxProviders) diff --git a/tests/auto/blackbox/tst_blackboxproviders.h b/tests/auto/blackbox/tst_blackboxproviders.h new file mode 100644 index 000000000..088cea6a3 --- /dev/null +++ b/tests/auto/blackbox/tst_blackboxproviders.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2023 Ivan Komissarov (abbapoh@gmail.com) +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef TST_BLACKBOXPROVIDERS_H +#define TST_BLACKBOXPROVIDERS_H + +#include "tst_blackboxbase.h" + +class TestBlackboxProviders : public TestBlackboxBase +{ + Q_OBJECT + +public: + TestBlackboxProviders(); + +private slots: + void allowedValues(); + void allowedValues_data(); + void brokenProvider(); + void conanProvider(); + void conanProvider_data(); + void moduleProviders(); + void moduleProvidersCache(); + void nonEagerModuleProvider(); + void probeInModuleProvider(); + void providersProperties(); + void qbsModulePropertiesInProviders(); + void qbsModuleProviders_data(); + void qbsModuleProviders(); + void qbsModuleProvidersCliOverride(); + void qbsModuleProvidersCliOverride_data(); + void qbsModuleProvidersCompatibility(); + void qbsModuleProvidersCompatibility_data(); + void qbspkgconfigModuleProvider(); + void removalVersion(); +}; + +#endif // TST_BLACKBOXPROVIDERS_H diff --git a/tests/auto/blackbox/tst_blackboxqt.cpp b/tests/auto/blackbox/tst_blackboxqt.cpp index 474fb95f3..b083a97e8 100644 --- a/tests/auto/blackbox/tst_blackboxqt.cpp +++ b/tests/auto/blackbox/tst_blackboxqt.cpp @@ -38,27 +38,10 @@ #define WAIT_FOR_NEW_TIMESTAMP() waitForNewTimestamp(testDataDir) using qbs::Internal::HostOsInfo; -using qbs::Profile; TestBlackboxQt::TestBlackboxQt() : TestBlackboxBase (SRCDIR "/testdata-qt", "blackbox-qt") { -} - -void TestBlackboxQt::validateTestProfile() -{ - const SettingsPtr s = settings(); - if (profileName() != "none" && !s->profiles().contains(profileName())) - QFAIL(QByteArray("The build profile '" + profileName().toLocal8Bit() + - "' could not be found. Please set it up on your machine.")); - const QStringList qmakeFilePaths = Profile(profileName(), s.get()) - .value("moduleProviders.Qt.qmakeFilePaths").toStringList(); - if (!qmakeFilePaths.empty()) - return; - if (!findExecutable(QStringList{"qmake"}).isEmpty()) - return; - QSKIP(QByteArray("The build profile '" + profileName().toLocal8Bit() + - "' is not a valid Qt profile and Qt was not found " - "in the global search paths.")); + setNeedsQt(); } void TestBlackboxQt::addQObjectMacroToGeneratedCppFile() @@ -75,6 +58,9 @@ void TestBlackboxQt::addQObjectMacroToGeneratedCppFile() void TestBlackboxQt::autoQrc() { QDir::setCurrent(testDataDir + "/auto-qrc"); + QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app"})), 0); QVERIFY2(m_qbsStdout.simplified().contains("resource data: resource1 resource2"), m_qbsStdout.constData()); @@ -83,7 +69,9 @@ void TestBlackboxQt::autoQrc() void TestBlackboxQt::cachedQml() { QDir::setCurrent(testDataDir + "/cached-qml"); - QCOMPARE(runQbs(), 0); + if ((runQbs() != 0) && m_qbsStderr.contains("Dependency 'Qt.qml' not found for product 'app'")) + QSKIP("Qt version too old"); + QString dataDir = relativeBuildDir() + "/install-root/data"; QVERIFY2(m_qbsStdout.contains("qmlcachegen must work: true") || m_qbsStdout.contains("qmlcachegen must work: false"), @@ -118,7 +106,7 @@ void TestBlackboxQt::combinedMoc() void TestBlackboxQt::createProject() { QDir::setCurrent(testDataDir + "/create-project"); - QVERIFY(QFile::copy(SRCDIR "/../../../examples/helloworld-qt/main.cpp", + QVERIFY(QFile::copy(testSourceDir + "/../../../../examples/helloworld-qt/main.cpp", QDir::currentPath() + "/main.cpp")); QbsRunParameters createParams("create-project"); createParams.profile.clear(); @@ -145,6 +133,11 @@ void TestBlackboxQt::dbusInterfaces() void TestBlackboxQt::forcedMoc() { QDir::setCurrent(testDataDir + "/forced-moc"); + QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); + if (m_qbsStdout.contains("using qt4")) + QSKIP("Qt version too old"); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); QCOMPARE(runQbs(QbsRunParameters("run")), 0); QVERIFY2(m_qbsStderr.contains("Hello from slot"), m_qbsStderr.constData()); } @@ -153,6 +146,8 @@ void TestBlackboxQt::includedMocCpp() { QDir::setCurrent(testDataDir + "/included-moc-cpp"); QCOMPARE(runQbs(), 0); + if (m_qbsStdout.contains("using qt4")) + QSKIP("Qt version too old"); QVERIFY2(!m_qbsStdout.contains("compiling moc_myobject.cpp"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("myobject.cpp", "#include <moc_myobject.cpp", "// #include <moc_myobject.cpp"); @@ -204,12 +199,48 @@ void TestBlackboxQt::lrelease() QVERIFY(!regularFileExists(relativeProductBuildDir("lrelease-test") + "/hu.qm")); } +void TestBlackboxQt::metaTypes_data() +{ + QTest::addColumn<bool>("generate"); + QTest::addColumn<QString>("installDir"); + QTest::newRow("don't generate") << false << QString(); + QTest::newRow("don't generate with install info") << false << QString("blubb"); + QTest::newRow("generate only") << true << QString(); + QTest::newRow("generate and install") << true << QString("blubb"); +} + +void TestBlackboxQt::metaTypes() +{ + QDir::setCurrent(testDataDir + "/metatypes"); + QFETCH(bool, generate); + QFETCH(QString, installDir); + const QStringList args{"modules.Qt.core.generateMetaTypesFile:" + + QString(generate ? "true" : "false"), + "modules.Qt.core.metaTypesInstallDir:" + installDir, + "-v", "--force-probe-execution"}; + QCOMPARE(runQbs(QbsRunParameters("resolve", args)), 0); + const bool canGenerate = m_qbsStdout.contains("can generate"); + const bool cannotGenerate = m_qbsStdout.contains("cannot generate"); + QVERIFY(canGenerate != cannotGenerate); + const bool expectFiles = generate && canGenerate; + const bool expectInstalledFiles = expectFiles && !installDir.isEmpty(); + QCOMPARE(runQbs(QStringList("--clean-install-root")), 0); + const QString productDir = relativeProductBuildDir("mylib"); + const QString outputDir = productDir + "/qt.headers"; + QVERIFY(!regularFileExists(outputDir + "/moc_unmocableclass.cpp.json")); + QCOMPARE(regularFileExists(outputDir + "/moc_mocableclass1.cpp.json"), expectFiles); + QCOMPARE(regularFileExists(outputDir + "/mocableclass2.moc.json"), expectFiles); + QCOMPARE(regularFileExists(productDir + "/mylib_metatypes.json"), expectFiles); + QCOMPARE(regularFileExists(relativeBuildDir() + "/install-root/some-prefix/" + installDir + + "/mylib_metatypes.json"), expectInstalledFiles); +} + void TestBlackboxQt::mixedBuildVariants() { QDir::setCurrent(testDataDir + "/mixed-build-variants"); const SettingsPtr s = settings(); - Profile profile(profileName(), s.get()); - if (profile.value("qbs.toolchain").toStringList().contains("msvc")) { + qbs::Profile profile(profileName(), s.get()); + if (profileToolchain(profile).contains("msvc")) { QbsRunParameters params; params.arguments << "qbs.buildVariant:debug"; params.expectFailure = true; @@ -240,6 +271,12 @@ void TestBlackboxQt::mocFlags() QVERIFY(runQbs(params) != 0); } +void TestBlackboxQt::mocCompilerDefines() +{ + QDir::setCurrent(testDataDir + "/moc-compiler-defines"); + QCOMPARE(runQbs(), 0); +} + void TestBlackboxQt::mocSameFileName() { QDir::setCurrent(testDataDir + "/moc-same-file-name"); @@ -247,19 +284,141 @@ void TestBlackboxQt::mocSameFileName() QCOMPARE(m_qbsStdout.count("compiling moc_someclass.cpp"), 2); } +void TestBlackboxQt::noRelinkOnQDebug() +{ + QFETCH(QString, checkMode); + QFETCH(bool, expectRelink); + + QVERIFY(QDir::setCurrent(testDataDir + "/no-relink-on-qdebug")); + rmDirR("default"); + + // Target check. + QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); + QVERIFY2(m_qbsStdout.contains("is GCC: "), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("is MinGW: "), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("is Darwin: "), m_qbsStdout.constData()); + const bool isGCCLike = m_qbsStdout.contains("is GCC: true"); + const bool isMingw = m_qbsStdout.contains("is MinGW: true"); + const bool isDarwin = m_qbsStdout.contains("is Darwin: true"); + if (!isGCCLike) + expectRelink = false; + else if (isMingw || isDarwin) + expectRelink = true; + + // Initial build. + QbsRunParameters params("resolve"); + if (isGCCLike && !checkMode.isEmpty()) + params.arguments << ("modules.cpp.exportedSymbolsCheckMode:" + checkMode); + QCOMPARE(runQbs(params), 0); + QCOMPARE(runQbs(), 0); + QCOMPARE(m_qbsStdout.count("linking"), 2); + + // Inserting the qDebug() statement will pull in weak symbols. + WAIT_FOR_NEW_TIMESTAMP(); + REPLACE_IN_FILE("lib.cpp", "// qDebug", "qDebug"); + QCOMPARE(runQbs(), 0); + QCOMPARE(m_qbsStdout.count("linking"), expectRelink ? 2 : 1); + + // Also check the opposite case. + WAIT_FOR_NEW_TIMESTAMP(); + REPLACE_IN_FILE("lib.cpp", "qDebug", "// qDebug"); + QCOMPARE(runQbs(), 0); + QCOMPARE(m_qbsStdout.count("linking"), expectRelink ? 2 : 1); +} + +void TestBlackboxQt::noRelinkOnQDebug_data() +{ + QTest::addColumn<QString>("checkMode"); + QTest::addColumn<bool>("expectRelink"); + QTest::newRow("default") << QString() << false; + QTest::newRow("relaxed") << QString("ignore-undefined") << false; + QTest::newRow("strict") << QString("strict") << true; +} + void TestBlackboxQt::pkgconfig() { QDir::setCurrent(testDataDir + "/pkgconfig"); + QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); QbsRunParameters params; params.command = "run"; QCOMPARE(runQbs(params), 0); - if (m_qbsStdout.contains("Skip this test")) + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) QSKIP("pkgconfig or Qt not found"); } +void TestBlackboxQt::pkgconfigQt() +{ + QFETCH(QStringList, arguments); + QFETCH(bool, success); + + QDir::setCurrent(testDataDir + "/pkgconfig-qt"); + rmDirR(relativeBuildDir()); + + QbsRunParameters dumpParams("resolve", {"-f", "dump-libpath.qbs"}); + QCOMPARE(runQbs(dumpParams), 0); + auto lines = QString::fromUtf8(m_qbsStdout).split('\n'); + const QString needle = "libPath="; + qbs::Internal::removeIf( + lines, [&needle](const auto &line) { return !line.startsWith(needle); }); + QCOMPARE(lines.size(), 1); + const auto libPath = lines[0].mid(needle.size()); + auto prefix = QFileInfo(libPath).path(); + if (prefix.endsWith("/lib") && !prefix.startsWith("/lib")) + prefix = QFileInfo(prefix).path(); + const auto pkgConfigPath = libPath + "/pkgconfig/"; + if (!QFileInfo(pkgConfigPath).exists()) + QSKIP("No *.pc files found"); + + rmDirR(relativeBuildDir()); + QbsRunParameters params("build", {"-f", "pkgconfig-qt.qbs"}); + // need to override prefix for the downloaded Qt + params.environment.insert("PKG_CONFIG_QT5CORE_PREFIX", prefix); + params.environment.insert("PKG_CONFIG_QT6CORE_PREFIX", prefix); + params.arguments << "moduleProviders.qbspkgconfig.extraPaths:" + pkgConfigPath; + params.arguments << arguments; + + QCOMPARE(runQbs(params) == 0, success); + + if (!success) + QVERIFY(m_qbsStderr.contains("Dependency 'Qt.core' not found for product 'p'")); +} + +void TestBlackboxQt::pkgconfigQt_data() +{ + QTest::addColumn<QStringList>("arguments"); + QTest::addColumn<bool>("success"); + QTest::newRow("pkgconfig") << QStringList() << true; + QTest::newRow("dummy") + << QStringList({"products.p.qbsModuleProviders:dummyProvider"}) << false; + QTest::newRow("cross-compiling") + << QStringList({"moduleProviders.qbspkgconfig.sysroot:/some/fake/sysroot"}) << false; +} + +void TestBlackboxQt::pkgconfigNoQt() +{ + QDir::setCurrent(testDataDir + "/pkgconfig-qt"); + rmDirR(relativeBuildDir()); + QbsRunParameters params("build", {"-f", "pkgconfig-qt.qbs"}); + params.arguments << "moduleProviders.qbspkgconfig.libDirs:nonexistent"; + params.expectFailure = true; + + QCOMPARE(runQbs(params) == 0, false); + QVERIFY2(m_qbsStderr.contains("Dependency 'Qt.core' not found for product 'p'"), m_qbsStderr); + // QBS-1777: basic check for JS exceptions in case of missing Qt + QVERIFY2(!m_qbsStderr.contains("Error executing provider for module 'Qt.core'"), m_qbsStderr); +} + void TestBlackboxQt::pluginMetaData() { QDir::setCurrent(testDataDir + "/plugin-meta-data"); + QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); + if (m_qbsStdout.contains("using qt4")) + QSKIP("Qt version too old"); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); + QVERIFY2(runQbs(QbsRunParameters("run", QStringList{"-p", "app"})) == 0, m_qbsStderr.constData()); QVERIFY2(m_qbsStderr.contains("all ok!"), m_qbsStderr.constData()); @@ -286,7 +445,11 @@ void TestBlackboxQt::pluginSupport() resolveParams.arguments << "modules.m1.useDummy:true"; resolveParams.expectFailure = true; } - QCOMPARE(runQbs(resolveParams) == 0, !invalidPlugin); + bool resolveResult = runQbs(resolveParams) == 0; + if (m_qbsStdout.contains("using qt4")) + QSKIP("Qt version too old"); + QCOMPARE(resolveResult, !invalidPlugin); + if (invalidPlugin) { QVERIFY2(m_qbsStderr.contains("Plugin 'dummy' of type 'imageformats' was requested, " "but is not available"), m_qbsStderr.constData()); @@ -320,22 +483,36 @@ void TestBlackboxQt::pluginSupport() } } +void TestBlackboxQt::qdoc() +{ + QDir::setCurrent(testDataDir + "/qdoc"); + QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); + if (m_qbsStdout.contains("Qt is too old")) + QSKIP("Skip test since qdoc3 does not work properly"); + QCOMPARE(runQbs(), 0); + QVERIFY(QFileInfo(relativeProductBuildDir("QDoc Test") + "/qdoctest.qch").exists()); +} + void TestBlackboxQt::qmlDebugging() { QDir::setCurrent(testDataDir + "/qml-debugging"); QCOMPARE(runQbs(), 0); - const SettingsPtr s = settings(); - Profile profile(profileName(), s.get()); - if (!profile.value("qbs.toolchain").toStringList().contains("gcc")) - return; + + const bool isGcc = m_qbsStdout.contains("is gcc: true"); + const bool isNotGcc = m_qbsStdout.contains("is gcc: false"); + if (isNotGcc) + QSKIP("The remainder of this test only applies to gcc"); + QVERIFY(isGcc); + QProcess nm; nm.start("nm", QStringList(relativeExecutableFilePath("debuggable-app"))); - if (nm.waitForStarted()) { // Let's ignore hosts without nm. - QVERIFY2(nm.waitForFinished(), qPrintable(nm.errorString())); - QVERIFY2(nm.exitCode() == 0, nm.readAllStandardError().constData()); - const QByteArray output = nm.readAllStandardOutput(); - QVERIFY2(output.toLower().contains("debugginghelper"), output.constData()); - } + if (!nm.waitForStarted()) + QSKIP("The remainder of this test requires nm"); + + QVERIFY2(nm.waitForFinished(), qPrintable(nm.errorString())); + QVERIFY2(nm.exitCode() == 0, nm.readAllStandardError().constData()); + const QByteArray output = nm.readAllStandardOutput(); + QVERIFY2(output.toLower().contains("debugginghelper"), output.constData()); } void TestBlackboxQt::qobjectInObjectiveCpp() @@ -347,6 +524,42 @@ void TestBlackboxQt::qobjectInObjectiveCpp() QCOMPARE(runQbs(), 0); } +void TestBlackboxQt::qmlTypeRegistrar_data() +{ + QTest::addColumn<QString>("importName"); + QTest::addColumn<QString>("installDir"); + QTest::newRow("don't generate") << QString() << QString(); + QTest::newRow("don't generate with install info") << QString() << QString("blubb"); + QTest::newRow("generate only") << QString("People") << QString(); + QTest::newRow("generate and install") << QString("People") << QString("blubb"); +} + +void TestBlackboxQt::qmlTypeRegistrar() +{ + QDir::setCurrent(testDataDir + "/qmltyperegistrar"); + QFETCH(QString, importName); + QFETCH(QString, installDir); + rmDirR(relativeBuildDir()); + const QStringList args{"modules.Qt.qml.importName:" + importName, + "modules.Qt.qml.typesInstallDir:" + installDir}; + if ((runQbs(QbsRunParameters("resolve", args)) != 0) && + m_qbsStderr.contains("Dependency 'Qt.qml' not found for product 'myapp'")) + QSKIP("Qt version too old"); + const bool hasRegistrar = m_qbsStdout.contains("has registrar"); + const bool doesNotHaveRegistrar = m_qbsStdout.contains("does not have registrar"); + QVERIFY(hasRegistrar != doesNotHaveRegistrar); + if (doesNotHaveRegistrar) + QSKIP("Qt version too old"); + QCOMPARE(runQbs(), 0); + const bool enabled = !importName.isEmpty(); + QCOMPARE(m_qbsStdout.contains("running qmltyperegistrar"), enabled); + QCOMPARE(m_qbsStdout.contains("compiling myapp_qmltyperegistrations.cpp"), enabled); + const QString buildDir = relativeProductBuildDir("myapp"); + QCOMPARE(regularFileExists(buildDir + "/myapp.qmltypes"), enabled); + QCOMPARE(regularFileExists(relativeBuildDir() + "/install-root/" + installDir + + "/myapp.qmltypes"), enabled && !installDir.isEmpty()); +} + void TestBlackboxQt::qtKeywords() { QDir::setCurrent(testDataDir + "/qt-keywords"); @@ -364,7 +577,9 @@ void TestBlackboxQt::qtKeywords() void TestBlackboxQt::quickCompiler() { QDir::setCurrent(testDataDir + "/quick-compiler"); - QCOMPARE(runQbs(), 0); + if ((runQbs() != 0) && + m_qbsStderr.contains("'Qt.quick' has version 4.8.7, but it needs to be at least 5.0.0.")) + QSKIP("Qt version too old"); const bool hasCompiler = m_qbsStdout.contains("compiler available"); const bool doesNotHaveCompiler = m_qbsStdout.contains("compiler not available"); QVERIFY2(hasCompiler || doesNotHaveCompiler, m_qbsStdout.constData()); @@ -390,6 +605,9 @@ void TestBlackboxQt::quickCompiler() void TestBlackboxQt::qtScxml() { QDir::setCurrent(testDataDir + "/qtscxml"); + QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); QCOMPARE(runQbs(), 0); if (m_qbsStdout.contains("QtScxml not present")) QSKIP("QtScxml module not present"); @@ -423,10 +641,10 @@ void TestBlackboxQt::staticQtPluginLinking() QDir::setCurrent(testDataDir + "/static-qt-plugin-linking"); QCOMPARE(runQbs(QStringList("products.p.type:application")), 0); const bool isStaticQt = m_qbsStdout.contains("Qt is static"); - QVERIFY2(m_qbsStdout.contains("Creating static import") == isStaticQt, m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("creating static import") == isStaticQt, m_qbsStdout.constData()); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("products.p.type:staticlibrary"))), 0); QCOMPARE(runQbs(), 0); - QVERIFY2(!m_qbsStdout.contains("Creating static import"), m_qbsStdout.constData()); + QVERIFY2(!m_qbsStdout.contains("creating static import"), m_qbsStdout.constData()); } void TestBlackboxQt::trackAddMocInclude() @@ -469,6 +687,11 @@ void TestBlackboxQt::track_qobject_change() void TestBlackboxQt::track_qrc() { QDir::setCurrent(testDataDir + "/qrc"); + QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); + if (m_qbsStdout.contains("using qt4")) + QSKIP("Qt version too old"); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); QCOMPARE(runQbs(QbsRunParameters("run")), 0); QVERIFY2(m_qbsStdout.contains("rcc"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("compiling test.cpp"), m_qbsStdout.constData()); diff --git a/tests/auto/blackbox/tst_blackboxqt.h b/tests/auto/blackbox/tst_blackboxqt.h index 180f9e0c0..da395b7d4 100644 --- a/tests/auto/blackbox/tst_blackboxqt.h +++ b/tests/auto/blackbox/tst_blackboxqt.h @@ -38,9 +38,6 @@ class TestBlackboxQt : public TestBlackboxBase public: TestBlackboxQt(); -protected: - void validateTestProfile() override; - private slots: void addQObjectMacroToGeneratedCppFile(); void autoQrc(); @@ -53,16 +50,27 @@ private slots: void includedMocCpp(); void linkerVariant(); void lrelease(); + void metaTypes_data(); + void metaTypes(); void mixedBuildVariants(); void mocAndCppCombining(); void mocFlags(); + void mocCompilerDefines(); void mocSameFileName(); + void noRelinkOnQDebug(); + void noRelinkOnQDebug_data(); void pkgconfig(); + void pkgconfigQt(); + void pkgconfigQt_data(); + void pkgconfigNoQt(); void pluginMetaData(); void pluginSupport_data(); void pluginSupport(); + void qdoc(); void qmlDebugging(); void qobjectInObjectiveCpp(); + void qmlTypeRegistrar_data(); + void qmlTypeRegistrar(); void qtKeywords(); void quickCompiler(); void qtScxml(); diff --git a/tests/auto/blackbox/tst_blackboxtutorial.cpp b/tests/auto/blackbox/tst_blackboxtutorial.cpp new file mode 100644 index 000000000..49de448a1 --- /dev/null +++ b/tests/auto/blackbox/tst_blackboxtutorial.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com) +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "tst_blackboxtutorial.h" + +#include <QtCore/qdir.h> +#include <QtCore/qdiriterator.h> + +static QStringList collectProjects(const QString &dirPath) +{ + QStringList result; + QDir dir(dirPath); + const auto subDirs = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name); + for (const auto &subDir : subDirs) { + const auto path = dir.filePath(subDir); + if (!QFileInfo::exists(path + "/myproject.qbs")) + continue; + result.append(dir.relativeFilePath(path)); + } + return result; +} + +TestBlackboxTutorial::TestBlackboxTutorial() + : TestBlackboxBase(SRCDIR "/../../../tutorial/", "blackbox-tutorial") +{} + +void TestBlackboxTutorial::tutorial_data() +{ + QTest::addColumn<QString>("project"); + + const auto projects = collectProjects(testDataDir); + for (const auto &project : projects) { + QTest::newRow(project.toUtf8().data()) << project; + } +} + +void TestBlackboxTutorial::tutorial() +{ + QFETCH(QString, project); + + QVERIFY(QDir::setCurrent(testDataDir + "/" + project)); + QCOMPARE(runQbs(), 0); +} + +QTEST_MAIN(TestBlackboxTutorial) diff --git a/tests/auto/blackbox/tst_blackboxtutorial.h b/tests/auto/blackbox/tst_blackboxtutorial.h new file mode 100644 index 000000000..2e84d6a96 --- /dev/null +++ b/tests/auto/blackbox/tst_blackboxtutorial.h @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com) +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef TST_BLACKBOXTUTORIAL_H +#define TST_BLACKBOXTUTORIAL_H + +#include "tst_blackboxbase.h" + +class TestBlackboxTutorial : public TestBlackboxBase +{ + Q_OBJECT + +public: + TestBlackboxTutorial(); + +private slots: + void tutorial_data(); + void tutorial(); +}; + +#endif // TST_BLACKBOXTUTORIAL_H diff --git a/tests/auto/blackbox/tst_blackboxwindows.cpp b/tests/auto/blackbox/tst_blackboxwindows.cpp new file mode 100644 index 000000000..57bd7f947 --- /dev/null +++ b/tests/auto/blackbox/tst_blackboxwindows.cpp @@ -0,0 +1,307 @@ +/**************************************************************************** +** +** Copyright (C) 2021 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "tst_blackboxwindows.h" + +#include "../shared.h" + +#include <tools/hostosinfo.h> +#include <tools/profile.h> +#include <tools/qttools.h> + +#include <QtCore/qdir.h> +#include <QtCore/qregularexpression.h> + +using qbs::Internal::HostOsInfo; +using qbs::Profile; + +struct SigntoolInfo +{ + enum class CodeSignResult { Failed = 0, Signed, Unsigned }; + CodeSignResult result = CodeSignResult::Failed; + bool timestamped = false; + QString hashAlgorithm; + QString subjectName; +}; + +Q_DECLARE_METATYPE(SigntoolInfo::CodeSignResult) + +static SigntoolInfo extractSigntoolInfo(const QString &signtoolPath, const QString &appPath) +{ + QProcess signtool; + signtool.start(signtoolPath, { QStringLiteral("verify"), QStringLiteral("/v"), appPath }); + if (!signtool.waitForStarted() || !signtool.waitForFinished()) + return {}; + const auto output = signtool.readAllStandardError(); + SigntoolInfo signtoolInfo; + if (output.contains("No signature found")) { + signtoolInfo.result = SigntoolInfo::CodeSignResult::Unsigned; + } else { + signtoolInfo.result = SigntoolInfo::CodeSignResult::Signed; + const auto output = signtool.readAllStandardOutput(); + const auto lines = output.split('\n'); + for (const auto &line: lines) { + { + const QRegularExpression re("^Hash of file \\((.+)\\):.+$"); + const QRegularExpressionMatch match = re.match(line); + if (match.hasMatch()) { + signtoolInfo.hashAlgorithm = match.captured(1).toLocal8Bit(); + continue; + } + } + { + const QRegularExpression re("Issued to: (.+)"); + const QRegularExpressionMatch match = re.match(line); + if (match.hasMatch()) { + signtoolInfo.subjectName = match.captured(1).toLocal8Bit().trimmed(); + continue; + } + } + if (line.startsWith("The signature is timestamped:")) { + signtoolInfo.timestamped = true; + break; + } else if (line.startsWith("File is not timestamped.")) { + break; + } + } + } + return signtoolInfo; +} + +static QString extractSigntoolPath(const QByteArray &output) +{ + const QRegularExpression re("%%(.+)%%"); + QRegularExpressionMatchIterator it = re.globalMatch(output); + if (!it.hasNext()) + return {}; + const QRegularExpressionMatch match = it.next(); + return match.captured(1).toUtf8(); +} + +TestBlackboxWindows::TestBlackboxWindows() + : TestBlackboxBase (SRCDIR "/testdata-windows", "blackbox-windows") +{ +} + +void TestBlackboxWindows::initTestCase() +{ + if (!HostOsInfo::isWindowsHost()) { + QSKIP("only applies on Windows"); + return; + } + + TestBlackboxBase::initTestCase(); +} + +void TestBlackboxWindows::innoSetup() +{ + const SettingsPtr s = settings(); + Profile profile(profileName(), s.get()); + + QDir::setCurrent(testDataDir + "/innosetup"); + + QCOMPARE(runQbs({"resolve"}), 0); + const bool withInnosetup = m_qbsStdout.contains("has innosetup: true"); + const bool withoutInnosetup = m_qbsStdout.contains("has innosetup: false"); + QVERIFY2(withInnosetup || withoutInnosetup, m_qbsStdout.constData()); + if (withoutInnosetup) + QSKIP("innosetup module not present"); + + QCOMPARE(runQbs(), 0); + QVERIFY(m_qbsStdout.contains("compiling test.iss")); + QVERIFY(m_qbsStdout.contains("compiling Example1.iss")); + QVERIFY(regularFileExists(relativeProductBuildDir("QbsSetup") + "/qbs.setup.test.exe")); + QVERIFY(regularFileExists(relativeProductBuildDir("Example1") + "/Example1.exe")); +} + +void TestBlackboxWindows::innoSetupDependencies() +{ + const SettingsPtr s = settings(); + Profile profile(profileName(), s.get()); + + QDir::setCurrent(testDataDir + "/innosetupDependencies"); + + QCOMPARE(runQbs({"resolve"}), 0); + const bool withInnosetup = m_qbsStdout.contains("has innosetup: true"); + const bool withoutInnosetup = m_qbsStdout.contains("has innosetup: false"); + QVERIFY2(withInnosetup || withoutInnosetup, m_qbsStdout.constData()); + if (withoutInnosetup) + QSKIP("innosetup module not present"); + + QbsRunParameters params; + QCOMPARE(runQbs(params), 0); + QVERIFY(m_qbsStdout.contains("compiling test.iss")); + QVERIFY(regularFileExists(relativeBuildDir() + "/qbs.setup.test.exe")); +} + +void TestBlackboxWindows::standaloneCodesign() +{ + QFETCH(SigntoolInfo::CodeSignResult, result); + QFETCH(QString, hashAlgorithm); + QFETCH(QString, subjectName); + QFETCH(QString, signingTimestamp); + + QDir::setCurrent(testDataDir + "/codesign"); + QbsRunParameters params(QStringList{"qbs.installPrefix:''"}); + params.arguments << QStringLiteral("project.enableSigning:%1").arg( + (result == SigntoolInfo::CodeSignResult::Signed) ? "true" : "false") + << QStringLiteral("project.hashAlgorithm:%1").arg(hashAlgorithm) + << QStringLiteral("project.subjectName:%1").arg(subjectName) + << QStringLiteral("project.signingTimestamp:%1").arg(signingTimestamp); + + rmDirR(relativeBuildDir()); + QCOMPARE(runQbs(params), 0); + + if (!m_qbsStdout.contains("signtool path:")) + QSKIP("No current signtool path pattern exists"); + + const auto signtoolPath = extractSigntoolPath(m_qbsStdout); + QVERIFY(QFileInfo(signtoolPath).exists()); + + const QStringList outputBinaries = {"A.exe", "B.dll"}; + for (const auto &outputBinary : outputBinaries) { + const auto outputBinaryPath = defaultInstallRoot + "/" + outputBinary; + QVERIFY(QFileInfo(outputBinaryPath).exists()); + + const SigntoolInfo signtoolInfo = extractSigntoolInfo(signtoolPath, outputBinaryPath); + QVERIFY(signtoolInfo.result != SigntoolInfo::CodeSignResult::Failed); + QCOMPARE(signtoolInfo.result, result); + QCOMPARE(signtoolInfo.hashAlgorithm, hashAlgorithm); + QCOMPARE(signtoolInfo.subjectName, subjectName); + QCOMPARE(signtoolInfo.timestamped, !signingTimestamp.isEmpty()); + } +} + +void TestBlackboxWindows::standaloneCodesign_data() +{ + QTest::addColumn<SigntoolInfo::CodeSignResult>("result"); + QTest::addColumn<QString>("hashAlgorithm"); + QTest::addColumn<QString>("subjectName"); + QTest::addColumn<QString>("signingTimestamp"); + + QTest::newRow("standalone, unsigned") + << SigntoolInfo::CodeSignResult::Unsigned << "" << "" << ""; + QTest::newRow("standalone, signed, sha1, qbs@community.test, no timestamp") + << SigntoolInfo::CodeSignResult::Signed << "sha1" << "qbs@community.test" << ""; + QTest::newRow("standalone, signed, sha256, qbs@community.test, RFC3061 timestamp") + << SigntoolInfo::CodeSignResult::Signed << "sha256" << "qbs@community.test" + << "http://timestamp.digicert.com"; +} + + +static bool haveWiX(const Profile &profile) +{ + if (profile.value("wix.toolchainInstallPath").isValid() && + profile.value("wix.toolchainInstallRoot").isValid()) { + return true; + } + + QStringList regKeys; + regKeys << QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows Installer XML\\") + << QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Installer XML\\"); + + QStringList paths = QProcessEnvironment::systemEnvironment().value("PATH") + .split(HostOsInfo::pathListSeparator(), Qt::SkipEmptyParts); + + for (const QString &key : std::as_const(regKeys)) { + const QStringList versions = QSettings(key, QSettings::NativeFormat).childGroups(); + for (const QString &version : versions) { + QSettings settings(key + version, QSettings::NativeFormat); + QString str = settings.value(QStringLiteral("InstallRoot")).toString(); + if (!str.isEmpty()) + paths.prepend(str); + } + } + + for (const QString &path : std::as_const(paths)) { + if (regularFileExists(QDir::fromNativeSeparators(path) + + HostOsInfo::appendExecutableSuffix(QStringLiteral("/candle"))) && + regularFileExists(QDir::fromNativeSeparators(path) + + HostOsInfo::appendExecutableSuffix(QStringLiteral("/light")))) { + return true; + } + } + + return false; +} + +void TestBlackboxWindows::wix() +{ + const SettingsPtr s = settings(); + Profile profile(profileName(), s.get()); + + if (!haveWiX(profile)) { + QSKIP("WiX is not installed"); + return; + } + + QByteArray arch = profile.value("qbs.architecture").toString().toLatin1(); + if (arch.isEmpty()) + arch = QByteArrayLiteral("x86"); + + QDir::setCurrent(testDataDir + "/wix"); + QCOMPARE(runQbs(), 0); + QVERIFY2(m_qbsStdout.contains("compiling QbsSetup.wxs"), m_qbsStdout); + QVERIFY2(m_qbsStdout.contains("linking qbs.msi"), m_qbsStdout); + QVERIFY(regularFileExists(relativeProductBuildDir("QbsSetup") + "/qbs.msi")); + + if (HostOsInfo::isWindowsHost()) { + QVERIFY2(m_qbsStdout.contains("compiling QbsBootstrapper.wxs"), m_qbsStdout); + QVERIFY2(m_qbsStdout.contains("linking qbs-setup-" + arch + ".exe"), m_qbsStdout); + QVERIFY(regularFileExists(relativeProductBuildDir("QbsBootstrapper") + + "/qbs-setup-" + arch + ".exe")); + } +} + +void TestBlackboxWindows::wixDependencies() +{ + const SettingsPtr s = settings(); + Profile profile(profileName(), s.get()); + + if (!haveWiX(profile)) { + QSKIP("WiX is not installed"); + return; + } + + QByteArray arch = profile.value("qbs.architecture").toString().toLatin1(); + if (arch.isEmpty()) + arch = QByteArrayLiteral("x86"); + + QDir::setCurrent(testDataDir + "/wixDependencies"); + QbsRunParameters params; + if (!HostOsInfo::isWindowsHost()) + params.arguments << "qbs.targetOS:windows"; + QCOMPARE(runQbs(params), 0); + QVERIFY2(m_qbsStdout.contains("compiling QbsSetup.wxs"), m_qbsStdout); + QVERIFY2(m_qbsStdout.contains("linking qbs.msi"), m_qbsStdout); + QVERIFY(regularFileExists(relativeBuildDir() + "/qbs.msi")); +} + +QTEST_MAIN(TestBlackboxWindows) diff --git a/tests/auto/blackbox/tst_blackboxwindows.h b/tests/auto/blackbox/tst_blackboxwindows.h new file mode 100644 index 000000000..ad8d60ca3 --- /dev/null +++ b/tests/auto/blackbox/tst_blackboxwindows.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2021 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef TST_BLACKBOXWINDOWS_H +#define TST_BLACKBOXWINDOWS_H + +#include "tst_blackboxbase.h" + +class TestBlackboxWindows : public TestBlackboxBase +{ + Q_OBJECT + +public: + TestBlackboxWindows(); + +public slots: + void initTestCase() override; + +private slots: + void innoSetup(); + void innoSetupDependencies(); + void standaloneCodesign(); + void standaloneCodesign_data(); + void wix(); + void wixDependencies(); +}; + +#endif // TST_BLACKBOXWINDOWS_H diff --git a/tests/auto/blackbox/tst_clangdb.cpp b/tests/auto/blackbox/tst_clangdb.cpp index 3a6dd2d92..c4216ac13 100644 --- a/tests/auto/blackbox/tst_clangdb.cpp +++ b/tests/auto/blackbox/tst_clangdb.cpp @@ -36,7 +36,7 @@ #include <QtCore/qdir.h> #include <QtCore/qfile.h> -#include <QtCore/qregexp.h> +#include <QtCore/qregularexpression.h> #include <QtCore/qjsonarray.h> #include <QtCore/qjsondocument.h> @@ -202,17 +202,19 @@ void TestClangDb::checkClangDetectsSourceCodeProblems() // clang-check.exe does not understand MSVC command-line syntax const SettingsPtr s = settings(); qbs::Profile profile(profileName(), s.get()); - if (profile.value("qbs.toolchain").toStringList().contains("msvc")) { + if (profileToolchain(profile).contains("msvc")) { arguments << "-extra-arg-before=--driver-mode=cl"; - } else if (profile.value("qbs.toolchain").toStringList().contains("mingw")) { + } else if (profileToolchain(profile).contains("mingw")) { arguments << "-extra-arg-before=--driver-mode=g++"; } arguments << "-analyze" << "-p" << relativeBuildDir() << sourceFilePath; QVERIFY(runProcess(executable, arguments, stdErr, stdOut) == 0); const QString output = QString::fromLocal8Bit(stdErr); - QVERIFY(output.contains(QRegExp(QStringLiteral("warning.*undefined"), Qt::CaseInsensitive))); - QVERIFY(output.contains(QRegExp(QStringLiteral("warning.*never read"), Qt::CaseInsensitive))); + QVERIFY(output.contains(QRegularExpression(QStringLiteral("warning.*undefined"), + QRegularExpression::CaseInsensitiveOption))); + QVERIFY(output.contains(QRegularExpression(QStringLiteral("warning.*never read"), + QRegularExpression::CaseInsensitiveOption))); } QTEST_MAIN(TestClangDb) |