Android .aar usually only contain *.jar, *.so and asset related resources.
How to include *.so related header files inside .aar?
Try to use AndroidNativeBundle plugin.
Edit your root build.gradle file, add classpath 'io.github.howardpang:androidNativeBundle:1.1.1' to the file
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.0'
//Add androidNativeBundle dependency
classpath "io.github.howardpang:androidNativeBundle:1.1.1"
}
}
Apply plugin to your lib, add following line to your lib build.gradle
plugins {
id 'com.android.library'
id 'com.ydq.android.gradle.native-aar.export'
}
Specify header path that you want to export, add following code segment to your lib build.gradle;
nativeBundleExport {
headerDir = "${project.projectDir}/native/export/header/path"
}
Related
I have a QBS Project which is a collection of subprojects, including static libraries, shared libraries, and a Qt GUI applications. The Qt GUI application has been giving me issue in that the linking stage fails, throwing several "/usr/bin/ld: cannot find {library}: File format not recognized" errors for libraries that are built earlier in the project chain. It does not do this for all libraries though, including libraries with near identical .qbs files as those which do throw this error.
Oddly enough, if I build the application on it's own, that is to say I run qbs from within the application's project directory rather than at the top level, it builds fine (assuming the dependent libraries all exist within their install directories). The main difference I see is that when building the full project, the cpp.libraryPaths for the application are ignored for all products in the project and the application attempts to link against the lib files produced in the build directory, while when building the application on it's own the cpp.libraryPaths are used as intended, and the files in the install directory are linked against successfully.
I have no idea why the lib files in the install directory can be linked against while files in the build directory throw errors. What could be causing the linking to fail in the first place? Additionally, how can I fix my project configuration so that I can build everything by calling qbs at the top level. Am I perhaps going about this in the wrong manner?
Here is the command I use to start the build:
qbs qbs.installRoot:. release
And a visual representation of the issue:
Poject <-- calling qbs here throws errors at linking application
|- LibraryOne
|- LibraryTwo
|- Application <-- calling qbs here works if libraries already built
And here is a very simplified reproduction of the relevent qbs files
-- SubOne.qbs and SubTwo --
// These are identical excluding the files
StaticLibrary {
name: // "One" or "Two"
files: [/*Files...*/]
Depends {
name: "Qt"
submodules: [/*core, etc...*/]
}
Depends { name: "cpp" }
// cpp depends and properties
Group {
fileTagsFilter: product.type
qbs.installDir: "lib"
qbs.install: true
}
}
-- App.qbs --
QtGuiApplication {
name: "App"
files: [/*Files...*/]
Depends { name: "One" } // I comment out these depends when building the Application on it's own
Depends { name: "Two" }
Depends { name: "cpp" }
cpp.includePaths: ["../One/include","..Two/include"]
cpp.libraryPaths: ["../lib"] // <-- Ignored during full project build
cpp.staticLibraries: ["One","Two"]
Group {
fileTagsFilter: product.type
qbs.installDir: "bin"
qbs.install: true
}
}
Never run qbs from a subdirectory. You should always run it on the top-level project file. In your root directory you should have a file like this:
// project.qbs
import qbs
Project {
// order doesn't matter here
references: [
"LibraryOne/SubOne.qbs",
"LibraryTwo/SubTwo.qbs",
"Application/App.qbs"
]
}
Secondly, you should not set the cpp.libraryPaths and cpp.staticLibraries in your application, as the Depends items which you have in your application, will already handle this (never comment them out).
Your cpp.includePaths properties should also not be set in the application, instead they should go into an Export item in each of your respective static libraries, like so:
StaticLibrary {
...
Export {
Depends { name: "cpp" }
cpp.includePaths: [product.sourceDirectory + "/include"]
}
...
}
Then run qbs -f project.qbs and everything should be built correctly.
I have a third party precompiled library (.lib+.dll) that I use in my Qt application.
In a regular (qmake) QtCreator project I have the following lines in my .pro file:
LIBS += -L$$PWD/lib/release -ltag
INCLUDEPATH += include/taglib
There is also an option in Projects tab -> Run -> "Add build library search path to PATH" which is by default ON. It ensures that LIBS path gets added to system PATH, so the dll can be found.
However, I can't find an equivalent in QBS. I have the following qbs file, which then gets included and added via Depends in my CppApplication file:
DynamicLibrary {
name: "taglib"
files: "lib/release/tag.dll"
Export {
Depends { name: "cpp" }
cpp.includePaths: [".","include/taglib"]
cpp.libraryPaths: ["lib/release"]
cpp.dynamicLibraries: "tag"
}
Group {
name: "taglib"
fileTagsFilter: ["dynamicLibrary"]
qbs.install: true
}
}
The linker passes but the application can't find the DLL at runtime and crashes.
Is it possible to add cpp.libraryPaths to system PATH at runtime?
Another option would be to copy the DLL file to build directory, but I can't figure out how to do that for precompiled libraries in QBS.
EDIT: I tried to use cpp.systemRunPaths which is documented here but it doesn't work.
I figured out how to copy prebuilt .dll files to build dir.
What was missing was FileTagger property since it seems QBS doesn't consider .dll files dynamic libraries.
FileTagger {
patterns: ["*.dll"]
fileTags: ["dynamicLibrary"]
}
The question still stands on how to add cpp.libraryPaths to system PATH on runtime. I found the following method in core.qbs:
setupRunEnvironment: {
var env;
if (qbs.targetOS.contains('windows')) {
env = new ModUtils.EnvironmentVariable("PATH", qbs.pathListSeparator, true);
env.append(binPath);
env.set();
}
...
}
I have no idea how to modify or invoke that method in my QBS files.
alan, your're on the right way. Just place
setupRunEnvironment: {
var env;
if (qbs.targetOS.contains('windows')) {
env = new ModUtils.EnvironmentVariable("PATH", qbs.pathListSeparator, true);
env.append(binPath);
env.set();
}
}
in the DynamicLibrary {} block, below the last Group {}. Change binPath to point to the folder with your shared libraries. This works at least with Windows.
Maybe you need to move Depends { name: "cpp" } out of the Export block.
I'd like to build my Gluon Project as a SINGLE executable jar file.
Currently there is a startup script included with a bin folder and so on.
Is it possible to build a single jar? Or can I include an own gradle task that accomplishes this?
The current tasks like installApp or distZip will not bundle the jars in one.
If you want to create a 'fat-jar', you can add this plugin to your build.gradle script:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.javafxports:jfxmobile-plugin:1.0.8'
classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.3'
}
}
apply plugin: 'org.javafxports.jfxmobile'
apply plugin: 'com.github.johnrengelman.shadow'
And then run gradlew shadowJar. It will create under libs an executable jar.
Note: if you are using desktopCompile or desktopRuntime dependencies, those won't be included so you need to change those to compile or runtime.
Since I had to build the jar with javapackager I used this plugin: javafx-gradle-plugin
I am relatively new to Gradle so adding the dependencies is just a temporary solution but it works
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.javafxports:jfxmobile-plugin:1.0.8'
classpath group: 'de.dynamicfiles.projects.gradle.plugins', name: 'javafx-gradle-plugin', version: '8.4.1'
}
}
jfx {
verbose = true
mainClass = "package.path.to.main.class.MainClass"
jfxAppOutputDir = "build/jfx/app" //configurable
jfxMainAppJarName = "ProjectName.jar"
deployDir = "src/main/deploy" //for signing
//many more options, go to link to learn about them
}
jfxJar.doFirst {
//TODO add all desktop dependencies
println("adding desktop dependency")
project.dependencies.add("runtime", "com.gluonhq:charm-desktop:2.1.0")
}
I have a multi-module gradle project with the following basic structure:
root
core
c-interface
m-interface
The c-interface and m-interface both depend on the core project:
compile project(':root:core')
c-interface and m-interface use the WAR plugin, but core does not and is just a jar.
In the core project, I am pulling in some file system dependencies with the following. One of these dependencies I cannot have packaged in the WARs generated by c-interface and m-interface. Previously I had this dependency in a nexus maven repository so I could exclude it by group,name,version in a providedRuntime configuration in c-interface and m-interface.
I cannot figure out how to do the same for the file dependency. The gradle dependencies task does not list file dependencies so I don't know what I would put in a providedRuntime.
I read http://issues.gradle.org/browse/GRADLE-471 but trying to use the idea there doesn't seem to remove the archive from my packages. Here is what I am currently defining (in core's build.gradle):
compile fileTree(dir: 'dependencies/compile/archive', include: '*.jar', exclude: 'management.jar')
compile(files('dependencies/compile/archive/management.jar')){ notPackaged = true } // Excludes it from all publications
Update
providedCompile without war plugin looked like a possibility. I set this up in the core build.gradle and it compiled fine, but c-interface and m-interface also needed the dependency at compile time. Including the file as providedCompile (or even a sanity check with compile) in c-interface and m-interface did not fix compile time errors related to missing the management.jar dependency. My speculation is because it was already scoped as providedCompile in core that the new declarations are ignored in c-interface and m-interface.
core/build.gradle:
configurations { providedCompile }
dependencies {
providedCompile files('dependencies/compile/archive/management.jar')
}
sourceSets.main.compileClasspath += configurations.providedCompile
sourceSets.test.compileClasspath += configurations.providedCompile
sourceSets.test.runtimeClasspath += configurations.providedCompile
c-interface/build.gradle:
providedCompile files('dependencies/compile/archive/management.jar')
There probably is a cleaner and simpler solution but you could then specify a custom configuration:
configurations {
compileOnly
}
and then specify all dependencies:
dependencies {
compile fileTree(dir: 'dependencies/compile/archive', include: '*.jar', exclude: 'management.jar')
compileOnly files('dependencies/compile/archive/management.jar')
}
Finally add the compileOnly configuration to classpaths of all source sets
sourceSets.all {
compileClasspath += configurations.compileOnly
}
This way management.jar should be on the classpath for compilation but won't be packaged.
EDIT
Only now I fully understand your problem. The following worked for me on a test project.
In core project gradle file:
repositories {
flatDir {
dirs 'dependencies/compile/archive'
}
}
dependencies {
compile fileTree(dir: 'dependencies/compile/archive', include: '*.jar', exclude: 'management.jar')
compile ':management:'
}
In project that depends on core:
repositories {
flatDir {
dirs new File(project(':core').projectDir, 'dependencies/compile/archive')
}
}
dependencies {
compile(project(':core')) {
exclude module: 'management'
}
compileOnly ':management':
}
sourceSets.all {
compileClasspath += configurations.compileOnly
}
How do I create a hadoop jar that includes all dependencies in the lib folder using Gradle? Basically, similar to what fatjar does.
Figured it out! Hadoop looks for libraries inside the "lib" folder of the final jar. So, add the following to the "jar" task.
jar {
doFirst {
into('lib') {
from configurations.runtime
}
}
}