Re: Building native libraries for both armeabi and armeabi-v7a

860 views
Skip to first unread message

Patrik Åkerfeldt

unread,
Nov 8, 2012, 5:21:18 AM11/8/12
to maven-androi...@googlegroups.com
Okay, I think I'm able to build for different architecture using maven profiles. When I depend on these shared objects from another project, is there a way to include/copy the libraries into the libs/ folder in order to make it possible to run the application directly from Eclipse/ADT (run as Android Application)?

/på

Den onsdagen den 7:e november 2012 kl. 14:27:58 UTC+1 skrev Patrik Åkerfeldt:
I'm successfully build a native library for the armeabi platform using the android-maven-plugin. However, my Application.mk specifies that I want to build to both armeabi and armeabi-v7a:

APP_ABI := armeabi armeabi-v7a

When I build manually using ndk-build these two libraries are created in [project]/libs. Why is it that the maven plugin only builds for the armeabi architecture? I'm guessing I'm doing something wrong.

/på

Patrik Åkerfeldt

unread,
Nov 9, 2012, 4:23:56 AM11/9/12
to maven-androi...@googlegroups.com
So, back to compile issues again. For some reason, it doesn't seem to respect my configuration settings in the pom.xml. I have a profile that looks like this:

<profile>
<id>armeabi</id>
<properties>
<packaging.type>so</packaging.type>
</properties>
<build>
<plugins>
<plugin>
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
<artifactId>android-maven-plugin</artifactId>
<version>3.4.0</version>
<executions>
<execution>
<goals>
<goal>ndk-build</goal>
</goals>
<configuration>
<clearNativeArtifacts>false</clearNativeArtifacts>
<attachNativeArtifacts>true</attachNativeArtifacts>
<ndkFinalLibraryName>my_library</ndkFinalLibraryName>
<target>my_library</target>                     
</configuration>
</execution>
</executions>
<extensions>true</extensions>
</plugin>
</plugins>
</build>
</profile>

If I just build it now with mvn -X -e install -Parmeabi it fails because it is passing the artifact name as target to ndk-build. Even though I've set the target to another name. So I add the target as parameter to command line as well, like:  mvn -X -e -Dandroid.nativeTarget="my_library" install -Parmeabi
Now it fails saying: [ERROR] Error during build: No native compiled library found, did the native compile complete successfully?
So I add final library name as well, like so: 
mvn -X -e -Dandroid.nativeTarget="my_library" -Dandroid.ndk.build.build.final-library.name=my_library install -Parmeabi
And now it builds just fine.

I'm very confused. Am I doing something wrong or does this look like a bug?

/på

Johan Lindquist

unread,
Nov 10, 2012, 7:15:18 AM11/10/12
to maven-androi...@googlegroups.com
Hi Patrik,

I am a little late chiming into this thread - the plugin does not
currently support multiple architectures (e.g. it will not try to find
the libs for both armeabi and armeabi-v7a) and I admit that it should
have been developed to cover this from the beginning but alas, this is
how it turned out.

As for your error, I know we bail because we find more than 1 library
in the output folder - it is tough to determine which one we should be
using for an artifact (all of this is legacies from supporting only 1
architecture). What you could try is to use the same pom.xml as you
have now but specify only armeabi in your Application.mk. Also, if you
have a list of the files in the libs folder after the build, that would
help.

Also, I believe you dont need the attachNativeArtifacts configuration,
since your project is of packaging type 'so'.

Cheers,

Johan
> --

--
you too?

Johan Lindquist

unread,
Nov 11, 2012, 9:14:26 AM11/11/12
to maven-androi...@googlegroups.com
Hi again,

I have tested this again with the trunk code and the
mixed-java-native-code sample. I added the APP_ABI := armeabi
armeabi-v7a to the Application.mk (which I also had to add), and indeed
only the armeabi got included in the APK.

However, I've got the feeling the plugin is not dealing with a couple
of things correctly (anymore?) - I know I added the 'target' to the
command line to force a certain build but this seems to not be required
anymore. Simply leaving out the target (as passed to the ndk-build
command), the two libraries get built and also included in the APK but
only the armeabi gets attached to the build.

So, current issues as I see it:

1) Target is passed no matter (should not be required)
2) Libraries are "taken" from the obj directory by the plugin - this
should probably be the libs directory since that is where the final
libraries are placed when using the ndk-build command without a target.
Would also mean the plugin would not need to manually strip the
libraries either - could be taken as is from the libs folder
3) Not all architectures get attached to the build as they should be

A couple of issues with multiple architectures - the classifier seems
to the natural place to indicate the architecture but this will make it
tough to have an .so (for example) that is built with different
capabilities (i.e using defines to include/exclude features -
unfortunately common in native land). Both architectures and
capabilities in this case would have to be signalled using classifiers
and it would get messy trying to coordinate this imho. It is almost
like we should lobby the Maven team for a new tag in the dependency -
architecture. :) Thoughts?

For 3) it would be possible to parse the Application.mk to figure out
what architectures are being built - an easier option would be to simply
trawel the libs folder for libraries matching the 'lib<artifactid>.so'
or 'lib<artifactid>.a' and attach them depending on their parent folder
(armeabi/armeabi-v7a/etc).

Will think about this but any suggestions are outmost welcome.

Cheers,

Johan

Johan Lindquist

unread,
Nov 11, 2012, 12:53:18 PM11/11/12
to maven-androi...@googlegroups.com
One option for still using the classifier would be that the plugin
append _<architecture> to the classifier automatically but that could
quickly get messy.

Cheers,

Johan

Patrik Åkerfeldt

unread,
Nov 11, 2012, 1:15:23 PM11/11/12
to maven-androi...@googlegroups.com
As it seems to me, the plugin always compiles armeabi + the architecture specified with ndkArchitecture. So if I specify armeabi-v7a it compiles (and copies) both armeabi and armeabi-v7a. And they seem to be compiled with two completely separate executions of the ndk mojo, from reading the log output. I'm too unfamiliar with maven mojos to do any deeper debugging at the moment.

In the best of worlds, I would like the plugin to build the native library just as if I would run ndk-build in a shell and then taking the resulting shared objects. For me it doesn't matter if I had to specify all the resulting .so names in the pom configuration for it to find them. But maybe this is to big of a change to the plugin at the moment?

My use case is this. We're building an SDK to be used by other developers. This SDK contains a jar file + a number of native libraries. At the moment these only include armeabi and armeabi-v7a. The build is defined by an Application.mk and a number of makefiles. I would like to deploy all the artifacts to a Nexus server. If these three artifacts could be built using one jenkins job only that would be great.

Thanks,


2012/11/11 Johan Lindquist <jo...@kawoo.co.uk>
--



Johan Lindquist

unread,
Nov 11, 2012, 2:00:10 PM11/11/12
to maven-androi...@googlegroups.com
It definately does not make sense for the plugin to compile it in two
executions - one single invoke of the ndk-build always was the aim -
could you bump up the debug and share the log? Or is this a result of
you adding an additional execution to your pom?

And the current approach, with the artifact being the result of
lib<artifactid>.so would still work, as long as the plugin also looks
into the other architecture directories.

Will have to think a bit about the classifiers still though, since
there are other use cases to be considered.

Johan
>>>>> -Dandroid.ndk.build.build.final-library.name [2]=my_library
> --
>
>
>
> Links:
> ------
> [1] http://Dandroid.ndk.build.build.final-library.name

--
you too?

Patrik Åkerfeldt

unread,
Nov 12, 2012, 3:09:14 AM11/12/12
to maven-androi...@googlegroups.com

Here's the output from running:
mvn -X -e -Dandroid.nativeTarget="acme_sdk_android" -Dandroid.ndk.build.build.final-library.name=acme_sdk_android -Dandroid.ndk.path=/Users/pakerfeldt/Dev/android-ndk-r8b install -Parmeabi-v7a 2>&1 >output.txt


2012/11/11 Johan Lindquist <jo...@kawoo.co.uk>

--
you too?

--



output.txt
pom1.xml

Johan Lindquist

unread,
Nov 12, 2012, 6:45:39 AM11/12/12
to maven-androi...@googlegroups.com
Hi,

Thanks for the log - I believe the dual execution is coming from the
fact that your profile declares the <extensions/> tag - this makes the
plugin execute the lifecycle as normal and in addition, it will execute
your activated profile - but this is just a guess. Perhaps try to
remove the <extensions/> and check what happens?

In any case, the plugin should be changed to handle multiple
architectures per execution (as you mention, a single ndk-build
invocation creates all the artifacts we need). Will just have to think
a bit about the classifier.

Cheers,

Johan

On 2012-11-12 03:09, Patrik Åkerfeldt wrote:
> Here's the output from running:
> mvn -X -e -Dandroid.nativeTarget="acme_sdk_android"
> -Dandroid.ndk.build.build.final-library.name [1]=acme_sdk_android
>>>>>>> -Dandroid.ndk.build.build.final-library.name [2] [2]=my_library
>>> [1] http://Dandroid.ndk.build.build.final-library.name [1]

Patrik Åkerfeldt

unread,
Nov 13, 2012, 5:57:04 AM11/13/12
to maven-androi...@googlegroups.com
If I remove the extensions I get " Unknown packaging: so @ line 7, column 13"

Thanks,


2012/11/12 Johan Lindquist <jo...@kawoo.co.uk>

--
you too?

--



Reply all
Reply to author
Forward
0 new messages