axmol/core/platform/android/libaxmol/axutils.gradle

348 lines
12 KiB
Groovy
Raw Normal View History

import java.nio.file.Files
import java.nio.file.Paths
2022-01-28 18:25:50 +08:00
import java.util.regex.Pattern
import java.util.stream.Stream
class VersionComparator implements Comparator<String> {
static private final List<String> SNAPSHOT_SUFFIXES = ["-SNAPSHOT", ".BUILD-SNAPSHOT"].asImmutable()
int compare(String o1, String o2) {
int result = 0
if (o1 == '*') {
result = 1
}
else if (o2 == '*') {
result = -1
}
else {
def nums1
try {
def tokens = deSnapshot(o1).split(/\./)
tokens = tokens.findAll { String it -> it.trim() ==~ /\d+/ }
nums1 = tokens*.toInteger()
}
catch (NumberFormatException e) {
throw new Exception("Cannot compare versions, left side [$o1] is invalid: ${e.message}")
}
def nums2
try {
def tokens = deSnapshot(o2).split(/\./)
tokens = tokens.findAll { String it -> it.trim() ==~ /\d+/ }
nums2 = tokens*.toInteger()
}
catch (NumberFormatException e) {
throw new Exception("Cannot compare versions, right side [$o2] is invalid: ${e.message}")
}
boolean bigRight = nums2.size() > nums1.size()
boolean bigLeft = nums1.size() > nums2.size()
for (int i in 0..<nums1.size()) {
if (nums2.size() > i) {
result = nums1[i].compareTo(nums2[i])
if (result != 0) {
break
}
if (i == (nums1.size()-1) && bigRight) {
if (nums2[i+1] != 0)
result = -1; break
}
}
else if (bigLeft) {
if (nums1[i] != 0)
result = 1; break
}
}
}
if (result == 0) {
// Versions are equal, but one may be a snapshot.
// A snapshot version is considered less than a non snapshot version
def o1IsSnapshot = isSnapshot(o1)
def o2IsSnapshot = isSnapshot(o2)
if (o1IsSnapshot && !o2IsSnapshot) {
result = -1
} else if (!o1IsSnapshot && o2IsSnapshot) {
result = 1
}
}
result
}
boolean equals(obj) { false }
/**
* Removes any suffixes that indicate that the version is a kind of snapshot
*/
protected String deSnapshot(String version) {
String suffix = SNAPSHOT_SUFFIXES.find { String it -> version?.endsWith(it) }
if (suffix) {
return version[0..-(suffix.size() + 1)]
} else {
return version
}
}
protected boolean isSnapshot(String version) {
SNAPSHOT_SUFFIXES.any { String it -> version?.endsWith(it) }
}
}
2022-08-08 18:02:17 +08:00
class axutils {
2022-08-07 09:26:56 +08:00
static String[] findNativeBuildTools(project, ndkVer = "23.2.8568313+", cmakeVer = "3.22.1+") {
// Detecting sdkRoot
def sdkRoot = null
Properties projProps = new Properties()
try {
projProps.load(project.rootProject.file("local.properties").newDataInputStream())
sdkRoot = projProps.getProperty("sdk.dir")
}
catch(Exception ex) {
ex.printStackTrace()
}
if (sdkRoot == null || !new File(sdkRoot).isDirectory()) {
sdkRoot = Paths.get("${System.env.ANDROID_SDK_ROOT}").toAbsolutePath().toString()
if (!new File(sdkRoot).isDirectory()) {
throw new Exception('android sdk not specified properly in local.properties or system env ANDROID_SDK_ROOT')
}
}
def rets = new String[3] // ndkVer,ndkPath,cmakeVer
findNDK(sdkRoot, ndkVer, rets)
findCMake(sdkRoot, cmakeVer, rets)
return rets
}
/**
* Find suitable ndk for current project
* @param project The current android project
* @param ndkVer The required ndk version for current project
* @param rets
* @return
*/
private static void findNDK(sdkRoot, ndkVer, rets) {
2022-07-12 21:51:44 +08:00
def allowNewerNdk = null
if (ndkVer.endsWith('+')) {
allowNewerNdk = true
ndkVer = ndkVer.substring(0, ndkVer.length() - 1)
}
2022-08-07 09:26:56 +08:00
def verList = []
File dir = new File("${sdkRoot}${File.separator}ndk")
if (dir.isDirectory()) {
for (ndkDir in dir.listFiles()) {
2022-08-07 09:26:56 +08:00
verList.add(ndkDir.getName())
}
}
2022-08-07 09:26:56 +08:00
verList.sort {a,b ->
2022-08-08 18:02:17 +08:00
return axutils.compareVersion(b, a)
2022-08-07 09:26:56 +08:00
}
def ndkDirs = []
// Collect ndkDirs for search
for(ver in verList){
2022-09-02 10:36:25 +08:00
if (ver.startsWith('.')) continue
2022-08-07 09:26:56 +08:00
ndkDirs.add("${sdkRoot}${File.separator}ndk${File.separator}${ver}")
}
/* Find suitable ndk in dirs */
rets[0] = ndkVer
for (ndkDir in ndkDirs) {
2022-07-12 21:51:44 +08:00
if (findNDKInDir(ndkVer, allowNewerNdk, ndkDir, rets)) {
return
}
}
println("No installed ndk found, the gradle will install ndk: $ndkVer automatically")
rets[1] = null
}
2022-01-28 18:25:50 +08:00
/**
* Find suitable cmake for current project
* @param project The current android project
* @param cmakeVer The required cmake version of project
* @param rets
* @return
*/
private static void findCMake(sdkRoot, String cmakeVer, rets) {
2022-01-28 18:25:50 +08:00
def allowNewerCMake = false
if(cmakeVer.endsWith('+')) {
allowNewerCMake = true
cmakeVer = cmakeVer.substring(0, cmakeVer.length() - 1)
}
def cmakeBinDirs = []
def cmakeBinDir = null
2022-01-28 18:25:50 +08:00
def verList = []
2022-08-02 17:55:00 +08:00
// Scan installed cmake in $sdk_root/cmake
2022-08-07 09:26:56 +08:00
File sdkCMakeDir = new File("${sdkRoot}${File.separator}cmake")
if (sdkCMakeDir.isDirectory()) {
for (cmakeDir in sdkCMakeDir.listFiles()) {
verList.add(cmakeDir.getName())
2022-08-02 17:55:00 +08:00
}
}
2022-08-02 17:55:00 +08:00
// Sort cmake verList
verList.sort {a,b ->
2022-08-08 18:02:17 +08:00
return axutils.compareVersion(b, a)
}
2022-08-02 17:55:00 +08:00
// Collect cmakeBinDirs for search
2022-08-07 09:26:56 +08:00
for(ver in verList){
2022-09-02 10:36:25 +08:00
if (ver.startsWith('.')) continue
2022-08-07 09:26:56 +08:00
cmakeBinDir = sdkRoot + File.separator + "cmake" + File.separator + ver + File.separator + "bin"
if(new File(cmakeBinDir).isDirectory()) {
cmakeBinDirs.add(cmakeBinDir)
2022-01-28 18:25:50 +08:00
}
}
cmakeBinDir = getCMakeBinFromPath()
if(cmakeBinDir != null) {
cmakeBinDirs.add(cmakeBinDir)
}
// find in cmakeBinDirs
def foundCMakeVer = null
for(item in cmakeBinDirs) {
foundCMakeVer = findCMakeFromBinDir(cmakeVer, item, allowNewerCMake)
if(foundCMakeVer != null) {
break
}
}
if(foundCMakeVer == null) {
2022-01-28 19:31:42 +08:00
println("No suitable cmake found, required $cmakeVer, the gradle will install it")
foundCMakeVer = cmakeVer
2022-01-28 18:25:50 +08:00
}
rets[2] = foundCMakeVer
2022-01-28 18:25:50 +08:00
}
private static int compareVersion(String ver1, String ver2) {
return new VersionComparator().compare(ver1, ver2)
}
2022-07-12 21:51:44 +08:00
private static String findNDKInDir(ndkVer, allowNewerNdk, ndkDir, rets) {
def found = null
def properties = new Properties()
2022-08-07 09:26:56 +08:00
File propertiesFile = new File("$ndkDir${File.separator}source.properties")
propertiesFile.withInputStream {
properties.load(it)
def foundNdkVer = properties['Pkg.Revision']
2022-08-08 18:02:17 +08:00
def ret = axutils.compareVersion(foundNdkVer, ndkVer)
if(ret == 0) {
println("Using found ndk (revision=$foundNdkVer,path=$ndkDir)")
found = true
}
else if(ret > 0){
if(allowNewerNdk) {
println("Using found newer ndk (revision=$foundNdkVer,path=$ndkDir), (minimum required is: ${ndkVer})")
ndkVer = foundNdkVer
found = true
}
else {
//throw new GradleException("The ndk ${ndkVer} is required, but $foundNdkVer found!")
}
}
else {
//throw new GradleException("The ndk ${ndkVer}+ is required, but $foundNdkVer found!")
}
}
if (found) {
rets[0] = ndkVer
rets[1] = ndkDir
return true
}
return null
}
private static String findCMakeFromBinDir(String cmakeVer, String cmakeBin, boolean allowNewerCMake) {
2022-01-28 18:25:50 +08:00
def foundCMakeVer = null
2022-01-28 19:31:42 +08:00
2022-01-28 19:59:27 +08:00
String ninjaPath = cmakeBin + File.separator + getNinjaProgramName()
2022-01-28 18:25:50 +08:00
if(!new File(ninjaPath).isFile()) {
2022-08-02 17:55:00 +08:00
println("The required ninja program is not present in cmake bin dir: '$cmakeBin'")
2022-01-28 19:51:42 +08:00
return null
2022-01-28 18:25:50 +08:00
}
try {
def programPath = cmakeBin + File.separator + getCMakeProgramName()
2022-01-28 19:31:42 +08:00
Process proc = isWindows() ? Runtime.getRuntime().exec("\"$programPath\" --version") : Runtime.getRuntime().exec("$programPath --version")
2022-01-28 18:25:50 +08:00
proc.waitFor()
int exitVal = proc.exitValue()
if (exitVal == 0) {
InputStream stdIn = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(stdIn)
BufferedReader br = new BufferedReader(isr)
String verLine = br.readLine()
2022-01-28 18:25:50 +08:00
def verInfo = verLine.split("\\s")
if (verInfo.length >= 3) {
def foundVer = verInfo[2]
def minusIdx = foundVer.indexOf('-')
def canonVer = minusIdx == -1 ? foundVer : foundVer.substring(0, minusIdx)
2022-08-08 18:02:17 +08:00
def ret = axutils.compareVersion(canonVer, cmakeVer)
2022-01-28 18:25:50 +08:00
if (ret == 0) {
println("Using found cmake version: $canonVer")
foundCMakeVer = canonVer
}
else if(ret > 0) {
if(allowNewerCMake) {
println("Using found newer cmake (version=$canonVer,path=$programPath), (minimum required is: ${cmakeVer})")
foundCMakeVer = canonVer
}
else {
println("The cmake ${cmakeVer} is required, but $canonVer found!")
}
}
}
}
}
catch(Exception ex) {
2022-01-28 19:31:42 +08:00
println("Execute cmake failed: " + ex.message)
2022-01-28 18:25:50 +08:00
}
return foundCMakeVer
}
2022-01-28 19:59:27 +08:00
private static String getCMakeBinFromPath() {
String cmakeExecName = getCMakeProgramName()
2022-01-28 19:59:27 +08:00
def foundBinPath = null
Stream.of(System.getenv("PATH").split(Pattern.quote(File.pathSeparator)))
.map(Paths::get)
.anyMatch(path -> {
def programPath = path.resolve(cmakeExecName)
2022-01-28 19:59:27 +08:00
boolean fileExist = Files.exists(path.resolve(cmakeExecName))
if(fileExist) {
foundBinPath = path.toAbsolutePath().toString()
}
return fileExist
})
2022-01-28 19:59:27 +08:00
return foundBinPath
}
private static String getCMakeProgramName() {
2022-01-28 19:59:27 +08:00
return isWindows() ? "cmake.exe" : "cmake"
}
private static String getNinjaProgramName() {
2022-01-28 19:59:27 +08:00
return isWindows() ? "ninja.exe" : "ninja"
}
private static boolean isWindows() {
return System.getProperty("os.name").toLowerCase().contains("windows")
2022-01-28 19:59:27 +08:00
}
}
2022-08-08 18:02:17 +08:00
ext.axutils = axutils