diff options
3 files changed, 78 insertions, 31 deletions
diff --git a/src/main/groovy/org/qtproject/qt/gradleplugin/QtBuildTask.groovy b/src/main/groovy/org/qtproject/qt/gradleplugin/QtBuildTask.groovy index 53a257e..882cc14 100644 --- a/src/main/groovy/org/qtproject/qt/gradleplugin/QtBuildTask.groovy +++ b/src/main/groovy/org/qtproject/qt/gradleplugin/QtBuildTask.groovy @@ -36,6 +36,8 @@ class QtBuildTask extends DefaultTask { private final String NDK_PATH_CMAKE_ARG = "ANDROID_NDK_ROOT" private final String SDK_PATH_CMAKE_ARG = "ANDROID_SDK_ROOT" private final String MAKE_PROGRAM_CMAKE_ARG = "CMAKE_MAKE_PROGRAM" + private final String BUILD_ALL_ABIS_ARG = "QT_ANDROID_BUILD_ALL_ABIS" + private final String ANDROID_ABIS_ARG = "QT_ANDROID_ABIS" private String pluginVersion = "NA" @@ -81,11 +83,8 @@ class QtBuildTask extends DefaultTask { include: ["${targetName}.aar"])) } - // Declared as @Internal so gradle will ignore this path when checking if the task is - // up-to-date or not. - @Internal - def getQtCMakeWrapperPath() { - def qtCMakeWrapperPath = "$qtKitDir/bin/qt-cmake" + def getQtCMakeWrapperPath(File qtAbiPath) { + def qtCMakeWrapperPath = "$qtAbiPath/bin/qt-cmake" if (isWindows()) qtCMakeWrapperPath += '.bat' return qtCMakeWrapperPath @@ -204,7 +203,7 @@ class QtBuildTask extends DefaultTask { // @TODO: QTTA-297 Instead of taking the first ABI found take one that, // matches with the running device/emulator. def listAndroidABIsAndSelectFirst() { - def firstMatch = new File(qtPath).listFiles().find { file -> + def firstMatch = new File(qtPath).listFiles().sort().find { file -> file.name ==~ Utils.androidAbiDirNameFormat() } @@ -213,8 +212,18 @@ class QtBuildTask extends DefaultTask { return new File(firstMatch.path) } - def resolveCoreJson() { - def qtCoreJsonPath = "$qtKitDir/modules/Core.json" + def findFirstMatchingAbiDirectory(ArrayList androidABIs) { + def firstMatch = new File(qtPath).listFiles().find { file -> + file.name in androidABIs + } + + if (!firstMatch) + Utils.logAndThrowException("No Qt for Android kit from $androidABIs found from: $qtPath") + return new File(firstMatch.path) + } + + def resolveCoreJson(File qtAbiPath) { + def qtCoreJsonPath = "$qtAbiPath/modules/Core.json" if (!new File(qtCoreJsonPath).exists()) Utils.logAndThrowException("No Core.json file found under $qtCoreJsonPath.") @@ -250,14 +259,41 @@ class QtBuildTask extends DefaultTask { } def configCommand() { - def buildMultiABI = !qtKitDir - if (!qtKitDir) - qtKitDir = listAndroidABIsAndSelectFirst() - def qtCoreJSon = resolveCoreJson() + def buildAllAbis = extractValueFromCMakeArgs(BUILD_ALL_ABIS_ARG) + def androidAbis = extractValueFromCMakeArgs(ANDROID_ABIS_ARG) + def qtAbiPath = "" + + // if qt.abiPath is set, build a single ABI build and ignore other ABI arguments + if (qtKitDir) { + qtAbiPath = new File(qtKitDir) + for (argument in [BUILD_ALL_ABIS_ARG, ANDROID_ABIS_ARG]) { + if (extraCMakeArguments.any { it.contains(argument) } ) { + System.err.println("Warning: Setting qt.abiPath means $argument will be ignored.") + extraCMakeArguments.removeAll { it.contains(argument) } + } + } + + } else if (Utils.parseCMakeBoolean(buildAllAbis) == true) { + qtAbiPath = listAndroidABIsAndSelectFirst() + + // if QT_ANDROID_ABIS is defined, build a multi-ABI build with those ABIs + } else if (androidAbis) { + androidAbis = androidAbis.replace("-", "_").split(";").collect{"android_$it".toString()} + qtAbiPath = findFirstMatchingAbiDirectory(androidAbis) + + } else if (Utils.parseCMakeBoolean(buildAllAbis) == false) { + Utils.logAndThrowException( + "Setting $BUILD_ALL_ABIS_ARG=$buildAllAbis without defining $ANDROID_ABIS_ARG " + + "or qt.abiPath would result in a single ABI build with the first one in alphabetical " + + "order. This is probably not what is wanted." + ) - def architecture = getCoreJsonArchitecture(qtCoreJSon) - def currentABI = Utils.abiFromArchitecture(architecture) + // the "standard" all-ABIs build + } else { + qtAbiPath = listAndroidABIsAndSelectFirst() + } + def qtCoreJSon = resolveCoreJson(qtAbiPath) def platform = getCoreJsonPlatform(qtCoreJSon) if (platform.toString().toLowerCase() != 'android') { Utils.logAndThrowException( @@ -265,7 +301,7 @@ class QtBuildTask extends DefaultTask { "The kit's path: $qtKitDir") } - def qtCMakeWrapperPath = getQtCMakeWrapperPath() + def qtCMakeWrapperPath = getQtCMakeWrapperPath(qtAbiPath) def cmd = [ qtCMakeWrapperPath, @@ -274,10 +310,11 @@ class QtBuildTask extends DefaultTask { '-G', 'Ninja', '-DQT_ANDROID_GENERATE_JAVA_QTQUICKVIEW_CONTENTS=ON', '-DQT_USE_TARGET_ANDROID_BUILD_DIR=ON', - "-DANDROID_ABI=$currentABI", - "-DQT_ANDROID_BUILD_ALL_ABIS=${buildMultiABI ? 'ON': 'OFF'}" ] + if (!buildAllAbis && !androidAbis && !qtKitDir) + cmd += "-DQT_ANDROID_BUILD_ALL_ABIS=ON" + def ninjaPathFromExtraCMakeArgs = extractValueFromCMakeArgs(MAKE_PROGRAM_CMAKE_ARG) if (!ninjaPathFromExtraCMakeArgs) resolveNinjaPath() diff --git a/src/main/groovy/org/qtproject/qt/gradleplugin/Utils.groovy b/src/main/groovy/org/qtproject/qt/gradleplugin/Utils.groovy index d1b2bdb..3eea60f 100644 --- a/src/main/groovy/org/qtproject/qt/gradleplugin/Utils.groovy +++ b/src/main/groovy/org/qtproject/qt/gradleplugin/Utils.groovy @@ -8,20 +8,8 @@ import org.gradle.api.Project @Singleton class Utils { - static String ANDROID_ABI_X86_64 = "x86_64" - static String ANDROID_ABI_X86 = "x86" - - static def abis = [ - 'arm64': 'arm64-v8a', 'arm': 'armeabi-v7a', - 'x86_64': ANDROID_ABI_X86_64, 'i386': ANDROID_ABI_X86 - ] - static String androidAbiDirNameFormat() { - return "android_(arm64_v8a|armv7|$ANDROID_ABI_X86_64|$ANDROID_ABI_X86)" - } - - static String abiFromArchitecture(String architecture) { - return abis.find { it.key == architecture }?.value + return "android_(arm64_v8a|armv7|x86_64|x86)" } static def getAndroidBuildTargetName(File buildDir) { @@ -51,4 +39,26 @@ class Utils { file = project.rootProject.file(path) return file } + + // CMake truthy values are 1, ON, TRUE, Y and non-zero numbers including floats + static parseCMakeBoolean(String value) { + if (value == "") { + return null + } + + try { + def returnValue = value.toFloat() + return returnValue != 0.0 + } + catch(java.lang.NumberFormatException ignored) { + // Not a number, proceed to string processing + } + + // toBoolean() returns true for "true", "y" or "1" (ignoring the case) + // we need to handle the rest + return value.toUpperCase() + .replace("ON", "TRUE") + .replace("YES", "TRUE") + .toBoolean() + } } diff --git a/src/test/groovy/org/qtproject/qt/gradleplugin/QtBuildTaskTest.groovy b/src/test/groovy/org/qtproject/qt/gradleplugin/QtBuildTaskTest.groovy index 8be3242..a96701a 100644 --- a/src/test/groovy/org/qtproject/qt/gradleplugin/QtBuildTaskTest.groovy +++ b/src/test/groovy/org/qtproject/qt/gradleplugin/QtBuildTaskTest.groovy @@ -134,7 +134,7 @@ class QtBuildTaskTest extends Specification { def mockQtCMakeFile = createQtCMakeFileMock(buildTask) when: "getQtCMakeWrapperPath is called" - def cmakeDir = buildTask.getQtCMakeWrapperPath() + def cmakeDir = buildTask.getQtCMakeWrapperPath(new File(buildTask.qtKitDir)) then: "qt-cmake file is found at the appropriate path" assert new File(cmakeDir).exists() |