请您分享您对libxml2
,libpng
,libfreetype
等库的交叉编译的智慧,这些库有一个配置脚本和一个Makefile for android和其他主机,如linux, Windows和Mac Os X使用 gradle ?
目前我没有一个完整的工作示例,但是希望找到类似以下的解决方案:
https://github.com/couchbase/couchbase-lite-java-native/blob/master/crosscompile-build.gradle
//
// To cross compile to ARM replace the default build.gradle with this file.
// Before running the build install these additional linux packages
//
// gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf
//
apply plugin: 'c'
apply plugin: 'java'
apply plugin: 'maven'
version = System.getenv("MAVEN_UPLOAD_VERSION")
model {
platforms {
osx_x86 {
architecture "x86"
operatingSystem "osx"
}
osx_x86_64 {
architecture "x86_64"
operatingSystem "osx"
}
linux_x86 {
architecture "x86"
operatingSystem "linux"
}
linux_x86_64 {
architecture "x86_64"
operatingSystem "linux"
}
linux_amd64 {
architecture "amd64"
operatingSystem "linux"
}
linux_arm {
architecture "arm"
operatingSystem "linux"
}
windows_x86 {
architecture "x86"
operatingSystem "windows"
}
windows_x86_64 {
architecture "x86_64"
operatingSystem "windows"
}
windows_amd64 {
architecture "amd64"
operatingSystem "windows"
}
}
toolChains {
visualCpp(VisualCpp)
gcc(Gcc)
gccArm(Gcc) {
getCppCompiler().setExecutable 'arm-linux-gnueabihf-g++'
getCCompiler().setExecutable 'arm-linux-gnueabihf-gcc'
getAssembler().setExecutable 'arm-linux-gnueabihf-as'
getLinker().setExecutable 'arm-linux-gnueabihf-gcc'
getStaticLibArchiver().setExecutable 'arm-linux-gnueabihf-ar'
addPlatformConfiguration(new ArmSupport())
}
clang(Clang)
}
}
class ArmSupport implements TargetPlatformConfiguration {
boolean supportsPlatform(Platform element) {
return element.getArchitecture().name == "arm"
}
List<String> getCppCompilerArgs() {
[]
}
List<String> getObjectiveCppCompilerArgs() {
[]
}
List<String> getObjectiveCCompilerArgs() {
[]
}
List<String> getCCompilerArgs() {
[]
}
List<String> getAssemblerArgs() {
[]
}
List<String> getLinkerArgs() {
[]
}
List<String> getStaticLibraryArchiverArgs() {
[]
}
}
sources {
native_library {
c {
source {
srcDir "src/main/c"
}
exportedHeaders {
srcDir "src/main/include"
}
}
}
}
libraries {
native_library {
baseName "CouchbaseLiteJavaNative"
}
all {
binaries.withType(SharedLibraryBinary) { binary ->
if (targetPlatform.operatingSystem.macOsX) {
cCompiler.args '-I', "/System/Library/Frameworks/JavaVM.framework/Headers"
linker.args '-framework', "JavaVM"
} else if (targetPlatform.operatingSystem.linux) {
cCompiler.args '-I', "${org.gradle.internal.jvm.Jvm.current().javaHome}/include"
cCompiler.args '-I', "${org.gradle.internal.jvm.Jvm.current().javaHome}/include/linux"
} else if (targetPlatform.operatingSystem.windows) {
cCompiler.args "-I${org.gradle.internal.jvm.Jvm.current().javaHome}/include"
cCompiler.args "-I${org.gradle.internal.jvm.Jvm.current().javaHome}/include/win32"
linker.args "--add-stdcall-alias"
}
}
}
}
binaries.withType(SharedLibraryBinary) { binary ->
if (!buildable) {
return
}
def builderTask = binary.tasks.builder
jar.into("native/${targetPlatform.operatingSystem.name}/${targetPlatform.architecture.name}") {
from builderTask.outputFile
}
jar.dependsOn builderTask
}
task createMavenDirectory(type: Exec) {
ext {
uploadUser = System.getenv("MAVEN_UPLOAD_USERNAME") + ":" + System.getenv("MAVEN_UPLOAD_PASSWORD")
mkcolPath = System.getenv("MAVEN_UPLOAD_REPO_URL") + "com/couchbase/lite/java-native/" + version + "/"
}
commandLine "curl", "--user", uploadUser, "-X", "MKCOL", mkcolPath
}
// this hack is only needed for apache mod_dav based Maven repo's like file.couchbase.com. otherwise, skip it
createMavenDirectory.onlyIf { System.getenv("MAVEN_UPLOAD_REPO_URL").contains("files") }
// first create the directory, then do the upload
task uploadArchivesWrapper(dependsOn: createMavenDirectory) << {
uploadArchives.execute()
}
// this will upload, but will not first create a directory (which is needed on some servers)
uploadArchives {
repositories {
mavenDeployer {
repository(url: System.getenv("MAVEN_UPLOAD_REPO_URL")) {
authentication(userName: System.getenv("MAVEN_UPLOAD_USERNAME"), password: System.getenv("MAVEN_UPLOAD_PASSWORD"))
}
pom.version = version
pom.groupId = 'com.couchbase.lite'
pom.artifactId = 'java-native'
pom.project {
licenses {
license {
name 'Couchbase Community Edition License Agreement'
url 'http://www.couchbase.com/agreement/community'
distribution 'repo'
}
}
}
}
}
}
task sourcesJar(type: Jar, dependsOn: classes) {
classifier = 'sources'
from sourceSets.main.java.srcDirs
}
artifacts {
archives sourcesJar
}
最好使用 Android NDK 提供的工具链,而不是指定 gnueabi 并静态链接所有内容。
我已经扩展了构建文件,但是我得到了UP-TO DATE
所有任务:
设置是:
libxml2-2.9.2
build.gradle
apply plugin: 'c'
import com.ulabs.gradle.AutoConfigureTask
import com.ulabs.gradle.MakefileTask
import com.ulabs.gradle.ConfigureTask
gradle.allprojects {
ext.getLibXmlLibsPath = {
def distDir = new File(project(":libxml2").projectDir, "buildLibxml2")
return distDir.toString()
}
ext.getLibXmlHeaderPath = {
def hDir = new File(project(":libxml2").projectDir, "include")
return hDir.toString()
}
}
project(':libxml2') {
model {
toolChains {
visualCpp(VisualCpp)
gcc(Gcc)
clang(Clang)
}
platforms {
x86 {
architecture "x86"
}
x64 {
architecture "x86_64"
}
itanium {
architecture "ia-64"
}
}
components {
xml2(NativeLibrarySpec) {
sources {
c {
exportedHeaders {
srcDir "include"
include "libxml/*.h"
}
exportedHeaders {
srcDir "include"
include "win32config.h", "wsockcompat.h"
}
exportedHeaders {
srcDir "."
include "libxml.h"
}
}
}
}
}
repositories {
libs(PrebuiltLibraries) {
libxml2 {
headers.srcDir getLibXmlHeaderPath()
binaries.withType(StaticLibraryBinary) {
def baseDir = getLibXmlLibsPath()
staticLibraryFile = file("${baseDir}/libxml2.a")
}
binaries.withType(SharedLibraryBinary) {
def os = targetPlatform.operatingSystem
def baseDir = getLibXmlLibsPath()
if (os.windows) {
sharedLibraryFile = file("${baseDir}/libxml2.dll")
if (file("${baseDir}/util.lib").exists()) {
sharedLibraryLinkFile = file("${baseDir}/libxml2.lib")
}
} else if (os.macOsX) {
sharedLibraryFile = file("${baseDir}/libxml2.dylib")
} else {
sharedLibraryFile = file("${baseDir}/libxml2.so")
}
}
}
}
}
}
task autoConfigTask(type: AutoConfigureTask) << {
extraArgs ""
}
task configureTask(type: ConfigureTask, dependsOn: autoConfigTask) << {
extraArgs "--without-python", "--without-zlib"
}
task makeFileTask(type: MakefileTask, dependsOn: configureTask) << {
println "Running makefile Task ${project}"
}
task make(dependsOn : makeFileTask) << {
def distDir = new File(getLibXmlLibsPath())
delete distDir.toString()
distDir.mkdirs()
def binDir = projectDir.toString() + "/.libs"
FileTree tree = fileTree(binDir.toString()) {
include 'libxml2*'
exclude '*.la*'
}
tree.each {File file ->
copy {
from file.toString()
into distDir.toString()
}
}
}
}
build.dependsOn(make)
assemble.dependsOn(make)
buildSrc/src/main/groovy/com/ulabs/gradle/*.groovy
包含:
package com.ulabs.gradle
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Optional
import org.gradle.api.Project
import org.gradle.api.tasks.incremental.IncrementalTaskInputs
class AutoConfigureTask extends DefaultTask {
@Input
@Optional
def extraArgs
@TaskAction
def execConfigure(IncrementalTaskInputs inputs) {
println "Launching AutoConfigureTask from: " + project.projectDir
if(!new File(project.projectDir, 'configure.ac').exists() &&
!new File(project.projectDir, 'configure.in').exists()) {
throw new FileNotFoundException(
'autoconfigure task should have either configure.in or configure.ac ')
}
boolean outDated = false
inputs.outOfDate { change ->
outDated = true
}
if(outDated) {
project.exec {
executable "autoreconf"
args "-ivf", hasProperty("extraArgs") ? extraArgs : ""
}
}
}
}
package com.ulabs.gradle
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Optional
import org.gradle.api.Project
import org.gradle.api.tasks.incremental.IncrementalTaskInputs
class ConfigureTask extends DefaultTask {
@Input
@Optional
def extraArgs
@TaskAction
def execConfigure(IncrementalTaskInputs inputs) {
if(!new File(project.projectDir, 'configure').exists()) {
throw new FileNotFoundException(
'configure task should have a configure script')
}
boolean outDated = false
inputs.outOfDate { change ->
outDated = true
}
if(outDated) {
project.exec {
executable "./configure"
args hasProperty("extraArgs") ? extraArgs : ""
}
}
}
}
package com.ulabs.gradle
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Optional
import org.gradle.api.Project
import org.gradle.api.tasks.incremental.IncrementalTaskInputs
class MakefileTask extends DefaultTask {
@Input
@Optional
def extraArgs
@Input
@Optional
def env
@TaskAction
def execConfigure(IncrementalTaskInputs inputs) {
if(!new File(project.projectDir, 'configure').exists()) {
throw new FileNotFoundException(
'makefile task should have a Makefile script')
}
boolean outDated = false
inputs.outOfDate { change ->
outDated = true
}
if(outDated) {
project.exec {
executable "make"
args hasProperty("extraArgs") ? extraArgs : "-f Makefile"
}
}
}
}
这很可能与任务的输入或任务的混乱配置/运行时阶段有关,但我尝试了很多选项,但似乎都没有。
所以最后我想:
./configure
,autotools
或make
除非参数更改(extraArgs
或env
)libxml2
能像一个项目,可以与其他人联系,并能够匹配依赖的平台/架构,与链接api,共享或静态答案 0 :(得分:1)
因此,调用库本身附带的构建系统似乎更好。
以下是执行此操作的脚本:
task autoReconfigure(type : Exec) {
executable "autoreconf"
args "-vif"
workingDir "."
}
task configureTask(type : Exec, dependsOn : autoReconfigure) {
executable "./configure"
args "--without-zlib"
workingDir "."
}
task makeFileTask(type : Exec, dependsOn : configureTask) {
executable "make"
args "-f", "Makefile"
workingDir "."
}
build.dependsOn(makeFileTask)
assemble.dependsOn(makeFileTask)
我将尝试添加对不同工具链/平台的支持