Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
attach/gradle/native-build.gradle
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
424 lines (370 sloc)
13.8 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def dummyFiles = [ '**/*/impl/Dummy**' ] | |
def iosFiles = [ '**/*/impl/IOS**', '**/**ios.json', '**/ios' ] | |
def androidFiles = [ '**/*/impl/Android**', '**/**android.json', '**/dalvik' ] | |
def desktopFiles = [ '**/impl/Desktop**', '**/**darwin.json', '**/**linux.json', '**/**windows.json' ] | |
def projectClasses = "$project.buildDir/classes/java/main" | |
def projectResources = "$project.buildDir/resources/main" | |
def projectIOSResources = "$project.projectDir/src/ios/resources/" | |
def projectAndroidResources = "$project.projectDir/src/android/resources/" | |
def projectDesktopResources = "$project.projectDir/src/desktop/resources/" | |
def sdkPath(String platform) { | |
return "/Applications/Xcode.app/Contents/Developer/Platforms/${platform}.platform/Developer/SDKs/${platform}${IOS_VERSION}.sdk"; | |
} | |
def AndroidPlatform = 31 | |
task androidBuild { | |
group = "native" | |
dependsOn build | |
doLast { | |
def serviceName = getServiceName(project.name) | |
File aar = aarBuild ("$project.buildDir", "$project.projectDir", serviceName, 'android') | |
if (aar == null) { | |
println "Error creating $aar" | |
} | |
nativeBuildLib("$project.buildDir", "$project.projectDir", serviceName, 'android') | |
} | |
} | |
task androidJar (type: Jar, dependsOn: androidBuild) { | |
group = "native" | |
from projectClasses, projectResources, projectAndroidResources | |
exclude dummyFiles | |
exclude iosFiles | |
exclude desktopFiles | |
archiveClassifier.set('android') | |
afterEvaluate { | |
into("native") { | |
from ("$project.buildDir/native/android") { | |
include 'lib*.a' | |
} | |
} | |
} | |
} | |
task iosBuild { | |
enabled = System.getProperty('os.name').toLowerCase().contains("mac") | |
group = "native" | |
dependsOn build | |
doLast { | |
def serviceName = getServiceName(project.name) | |
nativeBuildLib("$project.buildDir", "$project.projectDir", serviceName, 'ios') | |
} | |
} | |
task iosJar (type: Jar, dependsOn: iosBuild) { | |
enabled = System.getProperty('os.name').toLowerCase().contains("mac") | |
group = "native" | |
from projectClasses, projectResources, projectIOSResources | |
exclude dummyFiles | |
exclude desktopFiles | |
exclude androidFiles | |
archiveClassifier.set('ios') | |
afterEvaluate { | |
def serviceName = getServiceName(project.name) | |
into("native") { | |
from "$project.buildDir/native/ios/lib${serviceName}.a" | |
} | |
} | |
} | |
task desktopBuild { | |
enabled = project.name != "util" | |
group = "native" | |
dependsOn build | |
doLast { | |
def serviceName = getServiceName(project.name) | |
nativeBuildLib("$project.buildDir", "$project.projectDir", serviceName, 'desktop') | |
} | |
} | |
task desktopJar (type: Jar, dependsOn: desktopBuild) { | |
enabled = project.name != "util" | |
group = "native" | |
from projectClasses, projectResources, projectDesktopResources | |
exclude dummyFiles | |
exclude iosFiles | |
exclude androidFiles | |
archiveClassifier.set('desktop') | |
afterEvaluate { | |
def serviceName = getServiceName(project.name) | |
into("native") { | |
from "$project.buildDir/native/desktop/lib${serviceName}.a" | |
} | |
} | |
} | |
task nativeBuild { | |
dependsOn androidBuild, iosBuild, desktopBuild | |
group = "native" | |
description = "Runs native build for android, ios and desktop" | |
} | |
ext.aarBuild = { buildDir, projectDir, name, os -> | |
def JAVAHOME = System.getenv("JAVA_HOME") | |
def sdk = System.getenv("ANDROID_SDK") | |
if (sdk == null) { | |
throw new GradleException("Error: ANDROID_SDK can't be null") | |
} | |
def androidJar = sdk + "/platforms/android-${AndroidPlatform}/android.jar" | |
if (!file(androidJar).exists()) { | |
throw new GradleException("Error: path for ${androidJar} doesn't exist") | |
} | |
// copy android_project | |
File androidDir = file("$projectDir/../../gradle/android_project") | |
def tempDir = file("${buildDir}/aar") | |
mkdir tempDir | |
project.copy { | |
from androidDir | |
exclude "**/gradlew" | |
into tempDir | |
} | |
project.copy { | |
from file("$androidDir/gradlew").getAbsolutePath() | |
into tempDir | |
fileMode 0744 | |
} | |
// copy service dalvik sources | |
File sourcesDir = file("$projectDir/src/main/native/$os/dalvik") | |
project.copy { | |
from sourcesDir | |
into file("$tempDir/library/src/main/java/com/gluonhq/helloandroid") | |
} | |
if (name != "Util") { | |
def util = file("$projectDir/../util/build/tmp/util_classes.jar") | |
if (!util.exists()) { | |
// compile util | |
File sourcesUtilDir = file("$projectDir/../util/src/main/native/$os/dalvik") | |
def javaSources = [sourcesUtilDir.listFiles()].flatten() | |
def javac = "$JAVAHOME/bin/javac" | |
def javacArgs = ["-d", file("$tempDir/classes").getAbsolutePath(), | |
"-source", "1.7", "-target", "1.7", | |
"-bootclasspath", androidJar, | |
javaSources].flatten() | |
exec { | |
executable javac | |
args javacArgs | |
} | |
// create jar | |
def jar = "$JAVAHOME/bin/jar" | |
file(util.getParent()).mkdirs() | |
def jarArgs = ["cf", util.getAbsolutePath(), "-C", | |
file("$tempDir/classes").getAbsolutePath(), "."].flatten() | |
exec { | |
executable jar | |
args jarArgs | |
} | |
} | |
// copy util jar | |
project.copy { | |
from util | |
into file("$tempDir/libs") | |
} | |
} | |
// use build | |
File build = file("$projectDir/src/main/resources/META-INF/substrate/dalvik/build.gradle") | |
if (build != null && build.exists()) { | |
file("$tempDir/library/build.gradle").delete() | |
project.copy { | |
from build | |
into file("$tempDir/library/") | |
} | |
} | |
// use manifest | |
File manifest = file("$projectDir/src/main/resources/META-INF/substrate/dalvik/AndroidManifest.xml") | |
if (manifest != null && manifest.exists()) { | |
file("$tempDir/library/src/main/AndroidManifest.xml").delete() | |
project.copy { | |
from manifest | |
into file("$tempDir/library/src/main/") | |
} | |
} | |
// use res | |
File res = file("$projectDir/src/main/resources/META-INF/substrate/dalvik/res/xml/file_provider_paths.xml") | |
if (res != null && res.exists()) { | |
project.copy { | |
from res | |
into file("$tempDir/library/src/main/res/xml/") | |
} | |
} | |
// use dalvik assets | |
File assetsDir = file("$projectDir/src/main/resources/META-INF/substrate/dalvik/assets") | |
project.copy { | |
from assetsDir | |
into file("$tempDir/library/src/main/assets") | |
} | |
// prepare output | |
def dalvikOutput = "${buildDir}/resources/main/META-INF/substrate/dalvik/" | |
project.delete(files(dalvikOutput)) | |
// build aar | |
file("$tempDir/gradlew") | |
def aarArgs = ["-p", file("$tempDir/library").getAbsolutePath(), "assembleDebug"].flatten() | |
exec { | |
environment ANDROID_HOME: sdk, JAVA_HOME: JAVAHOME | |
executable file("$tempDir/gradlew").getAbsolutePath() | |
args aarArgs | |
} | |
// copy aar, dependencies | |
project.copy { | |
from file("$tempDir/library/build/outputs/aar/library-debug.aar") | |
from file("$projectDir/src/main/resources/META-INF/substrate/dalvik/android-dependencies.txt") | |
into dalvikOutput | |
rename { fileName -> fileName.replace('library-debug', "$name") } | |
} | |
println("build for ${name}.aar finished") | |
File a = new File("$dalvikOutput/${name}.aar") | |
if (a.exists()) { | |
a | |
} | |
} | |
ext.nativeBuildLib = { buildDir, projectDir, name, os -> | |
println("native build for $name started") | |
File shareDir = file("$projectDir/src/main/native/share") | |
if (!shareDir.exists()) { | |
// TODO | |
//println("No share lib dir found for $name") | |
//return | |
} | |
def sharedSources = shareDir.listFiles() | |
def osSources = [] | |
File osDir = file("$projectDir/src/main/native/$os") | |
if (osDir.exists()) { | |
osSources = osDir.listFiles() | |
} else { | |
println("No native lib dir found for $name at $osDir") | |
return | |
} | |
def JAVAHOME = System.getenv("JAVA_HOME") | |
def includeFlags = [ | |
"-I$JAVAHOME/include", | |
"-I$projectDir/../../gradle/include", | |
] | |
def osIncludeFlags = "" | |
if (os == "ios") { | |
osIncludeFlags = "-I$JAVAHOME/include/darwin" | |
def linkerOutputs = [] | |
def lipoOutput = "$buildDir/native/ios/lib${name}.a" | |
def buildSystems = ["iPhoneOS+arm64", "iPhoneSimulator+x86_64"] | |
buildSystems.each { buildSystem -> | |
def (platform, arch) = buildSystem.tokenize("+") | |
if (!file(sdkPath(platform)).exists()) { | |
println "Skipping native-build on iOS: path for ${platform} doesn't exist" | |
return | |
} | |
osSources = "$projectDir/src/main/native/$os/${name}.m" | |
def compileOutput = "$buildDir/native/ios/$arch" | |
new File(compileOutput).mkdirs() | |
def compileOutputs = ["$buildDir/native/ios/$arch/${name}.o"] | |
def linkerOutput = "$buildDir/native/ios/$arch/lib${name}.a" | |
def clangArgs = [ | |
"-xobjective-c", | |
"-mios-version-min=11.0", | |
includeFlags, | |
osIncludeFlags, | |
"-c", | |
"-fPIC", | |
"-arch", arch, | |
"-isysroot", | |
sdkPath(platform), | |
osSources].flatten() | |
exec { | |
executable "clang" | |
args clangArgs | |
workingDir compileOutput | |
} | |
def linkerArgs = [ | |
"-static", | |
"-framework", "Foundation", | |
"-framework", "CoreGraphics", | |
"-framework", "CoreBluetooth", | |
"-framework", "CoreLocation", | |
"-framework", "CoreMotion", | |
"-framework", "CoreText", | |
"-framework", "UIKit", | |
"-framework", "QuartzCore", | |
"-framework", "OpenGLES", | |
"-framework", "StoreKit", | |
"-framework", "UserNotifications", | |
"-arch_only", arch, | |
"-syslibroot", sdkPath(platform), | |
"-L${sdkPath(platform)}/usr/lib", | |
"-o", linkerOutput, | |
compileOutputs | |
].flatten() | |
exec { | |
executable "libtool" | |
args linkerArgs | |
workingDir compileOutput | |
} | |
linkerOutputs.add(linkerOutput) | |
} | |
// execute lipo to combine all linker output in one archive | |
def lipoArgs = ["-create", linkerOutputs, "-o", lipoOutput].flatten() | |
exec { | |
executable "lipo" | |
args lipoArgs | |
} | |
println("native build for $name finished") | |
File n = new File(lipoOutput) | |
if (n.exists()) { | |
n | |
} | |
} else if (os == "android") { | |
def ndk = System.getenv("ANDROID_NDK") | |
if (ndk == null) { | |
throw new GradleException("Error: ANDROID_NDK can't be null") | |
} | |
def host = System.getProperty('os.name').toLowerCase().contains("mac") ? | |
"darwin" : "linux" | |
def arch = "arm64-v8a" | |
def compileOutput = "$buildDir/native/$os/$arch" | |
File outputDir = file(compileOutput) | |
outputDir.mkdirs() | |
def platform="aarch64-linux-android21" | |
def toolchainHome = "$ndk/toolchains/llvm" | |
def compilerHome = "$toolchainHome/prebuilt/${host}-x86_64" | |
def compiler = file("$compilerHome/bin/clang").getAbsolutePath() | |
def linker = file("$compilerHome/bin/llvm-ar").getAbsolutePath() | |
osIncludeFlags = ["-I$JAVAHOME/include/$host", | |
"-I$projectDir/../../gradle/include/android", | |
"-I$projectDir/../util/src/main/native/$os/c"].flatten() | |
File nativeSourcesDir = file("$projectDir/src/main/native/$os/c/") | |
osSources = [nativeSourcesDir.listFiles().findAll {it.name.endsWith(".c")}].flatten() | |
def compilerArgs = ["-target", platform, "-Werror", "-c", "-fPIC", | |
includeFlags, osIncludeFlags, osSources].flatten() | |
exec { | |
executable compiler | |
args compilerArgs | |
workingDir compileOutput | |
} | |
def linkerObj = [outputDir.listFiles().findAll {it.name.endsWith(".o")}].flatten() | |
def linkerOutput = "$buildDir/native/$os/lib${name.toLowerCase()}.a" | |
def linkerArgs = ["rcs", linkerOutput, linkerObj].flatten() | |
exec { | |
executable linker | |
args linkerArgs | |
} | |
println("native build for $name finished") | |
File a = new File(linkerOutput) | |
if (a.exists()) { | |
a | |
} | |
} else { | |
// TODO | |
def compileOutput = "$buildDir/native/$os" | |
new File(compileOutput).mkdirs() | |
def compiler = "gcc" | |
def cargs = [ | |
"-c", includeFlags, osIncludeFlags, sharedSources, osSources | |
].flatten() | |
exec { | |
executable "/usr/bin/gcc" | |
args cargs | |
workingDir compileOutput | |
} | |
// TODO | |
File n = new File("$buildDir/native/${os}") | |
if (n.exists()) { | |
fileTree("$buildDir/native/${os}").filter { it.isFile() }.files | |
.first() | |
} | |
} | |
} | |
private String getServiceName(projectName) { | |
if (projectName.contains("-")) { // in-app-billing -> InAppBilling | |
def values = projectName.tokenize("-") | |
return values.inject("") { name, pn -> name + pn.capitalize() } | |
} | |
return projectName.capitalize() | |
} |