BigKarel / maven-android-plugin

Automatically exported from code.google.com/p/maven-android-plugin
0 stars 0 forks source link

scope=provided APKLIB dependencies are not automatically included on APK compile classpath #435

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
If I have apklib dependency which has optional dependency on Google Play 
Service (it detect at runtime if it is available and use it only if exists) So 
Google Play Services is declared like provided in this apklib. But when I use 
this library in my project, android-maven-plugin skip provided dependency and 
compile will fail. It is necessary to declare provided dependency to Google 
Play Service again in main project, also when I don't want to use it. I think 
that also provided dependencies from all apklibs project should be on classpath 
during compile of main project (because apklibs are distributed like source 
code). Only when I add Google Play Service as compile time dependency in the 
main project, it should override provided dependency in apklibs itself and 
include Google Play Service to the apk. 

Tested on version 3.7.0.  But I think that this was not changed in 3.8.x 
version.

Original issue reported on code.google.com by tomas.pr...@gmail.com on 8 Dec 2013 at 10:00

GoogleCodeExporter commented 9 years ago
Test against 3.8.3-SNAPSHOT

If the failure stills occurs then provide a project or link to a project that 
clearly highlights the failure.

Original comment by william....@xandar.com.au on 17 Feb 2014 at 11:11

GoogleCodeExporter commented 9 years ago
Ok I will test it as soon as possible. Was made some changes in this area?

Original comment by tomas.pr...@gmail.com on 17 Feb 2014 at 12:01

GoogleCodeExporter commented 9 years ago
Lots of changes

Original comment by william....@xandar.com.au on 17 Feb 2014 at 12:49

GoogleCodeExporter commented 9 years ago
Tomas, have you tested against 3.8.3-SNAPSHOT or 3.9.0-rc.1?

Original comment by william....@xandar.com.au on 27 Feb 2014 at 10:30

GoogleCodeExporter commented 9 years ago
Sorry. Not yet, I was too busy, but today at night (CET) I will look on.

Original comment by tomas.pr...@gmail.com on 27 Feb 2014 at 1:31

GoogleCodeExporter commented 9 years ago
I started with testing. But problem is that I'm not able to build my project, 
because it fail on another error.

Problems is that android-maven plugin duplicate one dependency twice time for 
run aapt.exe.
Here is commandline line:

Caused by: com.jayway.maven.plugins.android.ExecutionException: 
ANDROID-040-001: Could not execute: Command = cmd.exe /X /C 
"d:\_PJazyky\_Android\SDK\build-tools\19.0.0\aapt.exe package --non-constant
-id -m -J ...target\generated-sources\r --custom-package 
eu.inmite.android.lib.about -M ...target\unpacked-lib
s\eial_android-about\AndroidManifest.xml -S 
...target\unpacked-libs\eial_android-about\res -S ...target\unpack
ed-libs\cga_support-v7-appcompat\res -S 
...target\unpacked-libs\eial_android-framework-main\res -S ...target\u
npacked-libs\cga_support-v7-appcompat\res -S 
...target\unpacked-libs\eial_android-styled-dialogs\res --auto-add-overlay -I 
d:\_PJazyky\_Android\SDK\platfor
ms\android-19\android.jar --output-text-symbols 
...target\unpacked-libs\eial_android-about", Result = 1
        at com.jayway.maven.plugins.android.CommandExecutor$Factory$DefaultCommandExecutor.executeCommand(CommandExecutor.java:252)
        at com.jayway.maven.plugins.android.phase01generatesources.GenerateSourcesMojo.generateRForApkLibDependency(GenerateSourcesMojo.java:766)

Check "cga_support-v7-appcompat"

appcompat is declared directly in the project pom.xml and also some APKLIB 
dependency use it.
The some project it is possible to build by 3.7.0

Original comment by tomas.pr...@gmail.com on 27 Feb 2014 at 6:59

GoogleCodeExporter commented 9 years ago
I found this in the build debug log:

[DEBUG] apklib dependencies = 
[com.google.android:support-v7-appcompat:apklib:19:compile, 
eu.inmite.android.lib:android-framework-main:apklib:1.0.0:compile, 
com.google.android:support-v7-appcompat:apklib:19:provided, 
eu.inmite.android.lib:android-styled-dialogs:apklib:1.1.2:compile]

It looks like appcompat:apklib:19 is handled twice time, because it is defined 
and provided in one of my apklib and as compile in my second apklib.

Original comment by tomas.pr...@gmail.com on 27 Feb 2014 at 7:30

GoogleCodeExporter commented 9 years ago
I tried to remove on of my APKLIB dependency and now I'm possible to build 
project.

Now back to original problem.

I have defined 

<dependency>
  <groupId>com.flurry</groupId>
  <artifactId>flurry-android</artifactId>
  <scope>provided</scope>
</dependency>

in my core apklib dependency, where flurry is used, but it is optional feature.

If I use this core apklib dependency in my apk project it fail during 
compilation because android-maven-plugin don't add flurry on the class path 
during compilation, it ignore provided dependencies defined in apklib. If will 
not be able to reproduce it, I will try to make demo project.

Original comment by tomas.pr...@gmail.com on 27 Feb 2014 at 7:35

GoogleCodeExporter commented 9 years ago
Tomas, can you make the project (or cut down version that shows the error) 
available?
Was this with 3.9.0-rc.1?

Original comment by william....@xandar.com.au on 27 Feb 2014 at 7:56

GoogleCodeExporter commented 9 years ago
I tested it with latest snapshot from trunk, so one commit ahead of RC.
Do you want test project for booth problems? I mean the problem with 
duplication path on -S parameter is possible to fix directly, only be avoid to 
duplication. I go to sleep now, but I will continue tomorrow.

Original comment by tomas.pr...@gmail.com on 27 Feb 2014 at 9:05

GoogleCodeExporter commented 9 years ago
Yes for both problems.
You shouldn't need to manually exclude a dependency from an apklib to
ensure it is not being added to apt twice.

Original comment by william....@xandar.com.au on 27 Feb 2014 at 9:35

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
I extracted test case based on my project, but I'm not able reproduce -S 
parameter duplication for appt, so it reproduce only problem with ignoring 
provided dependencies from APKLIB, which is original topic of this bug report

Here is project
https://dl.dropboxusercontent.com/u/998569/perm/android-maven-plugin-provided.zi
p

All android related dependencies is create by maven-android-sdk-deployer, i 
only use com.google.android instead of android groupId to be compatible with 
older version which are already in the central repo. I provided my base pom.xml 
with my configuration.

Then example contain one company POM parent project and two APKLIB project 
that. All must be installed by mvn install.

Project B contain dependency on Square Picasso library, but it is optional 
feature and it is marked as provided.

Main project "4-project" than contain booth APKLIB libraries and dependency. 
Class with Picasso is not used so it can stay provided, but if you try to build 
project by mvn package it fail.

I will continue to figure how to reproduce problem with duplication -S argument 
in my original project.

Original comment by tomas.pr...@gmail.com on 1 Mar 2014 at 11:07

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
I found also reason of second problem.

Here is updated demo project which is testcase booth problem
https://dl.dropboxusercontent.com/u/998569/perm/android-maven-plugin-provided-v2
.zip

It is happen. If you use apklib, that has another apklib as dependency.
"4-project" folder contain also out.txt with debug log

Original comment by tomas.pr...@gmail.com on 1 Mar 2014 at 6:40

GoogleCodeExporter commented 9 years ago

Original comment by william....@xandar.com.au on 10 Mar 2014 at 11:49

GoogleCodeExporter commented 9 years ago
Do you have all necessary informations to reproduce the bug?
Can I help in some way to solve this problem?

Original comment by tomas.pr...@gmail.com on 25 Apr 2014 at 7:01

GoogleCodeExporter commented 9 years ago
Tomas, I cannot follow the instructions in the readme of 
android-maven-plugin-provide-v2.zip

The 0-maven-android-sdk-deployer project is missing the platforms and add-ons 
modules.

Everything else fails with missing deps after that.

Instead of posting it to dropbox. Why don't you post it to  github. Then we can 
all iterate over the problem.

Original comment by william....@xandar.com.au on 26 Apr 2014 at 12:36

GoogleCodeExporter commented 9 years ago
0-maven-android-sdk-deployer needs 
https://github.com/mosabua/maven-android-sdk-deployer to work properly, pom.xml 
is only my replacement of standard maven-android-sdk-deployer, it only use 
different groupId for artifacts compatible with maven central.

But I updated 
https://dl.dropboxusercontent.com/u/998569/perm/android-maven-plugin-provided-v2
.zip
It now contain full content of sdk deployer, you don't need any additional 
operation. I also updated readme and version of dependencies to latest version. 
I tested it with  clean local repository.

It also looks that problem with duplication -S argument was already fixed in 
the current 3.9.0 snapshot. So only missing problem is "All provided 
dependencies of apklib project are skipped if apklib is used"

Build of "4-project" fail because of missing library, which is defined as 
provided dependency for "library b"

Original comment by tomas.pr...@gmail.com on 26 Apr 2014 at 7:33

GoogleCodeExporter commented 9 years ago
Your project is not valid.

It makes no sense for the picasso library to be marked as provided in
android-lib-b.
If we changed the android-maven-plugin to allow the apk source to be
compiled then it would crash at runtime because the picasso library would
be missing.

That library needs to be defined as a compile time dependency at some point
in the build.

Original comment by william....@xandar.com.au on 26 Apr 2014 at 8:09

GoogleCodeExporter commented 9 years ago
Here is only example. But point of provided dependencies is allow to compile 
optional dependency, presence detection is made during code execution. For 
example Picaso library itself has provided dependency to the OkHttp library, it 
only allow to compile it Library itself then test if OkHttp is available and 
use it in runtime.

In our company we have apklib library which works like mini framework, it has 
optional dependency on Crittercism, Flurry and Google Analytics. It depends on 
app configuration which library will be used in run-time.

Android maven plugin simply should grab all provided dependencies from all 
apklibs and put the same provided dependency also during compile the project, 
because it also compile apklibs in the same step.

Original comment by tomas.pr...@gmail.com on 26 Apr 2014 at 8:24

GoogleCodeExporter commented 9 years ago
No. In Maven the point of provided dependencies is for libraries that will
already be made available at runtime through another means. Typically
because they are already provided by the container.

An optional dependency is very different from scope=provided.

In your scenario if a provided dependency is defined in the project then
there is zero ability for those classes to be used at runtime because they
are not being provided by any other means.

It sounds like what you need is all libraries provided with your APK and
app configuration decides which to load.

Original comment by william....@xandar.com.au on 26 Apr 2014 at 10:25

GoogleCodeExporter commented 9 years ago
Android works a little bit different, if some classes is missing, APK normally 
works until you use it. So I can have class which use Google Analytics and if I 
will don't use (call) it in the app, I don't need to include Google Analytics 
in the APK. APK should be as small as possible. Provided is best way how to do 
it.

Original comment by tomas.pr...@gmail.com on 26 Apr 2014 at 10:50

GoogleCodeExporter commented 9 years ago
No. It is the wrong way to do it. Android is no different to any other
application.

Provided means that you expect the library to be there at runtime.
In your case that will never be.

Original comment by william....@xandar.com.au on 26 Apr 2014 at 11:06

GoogleCodeExporter commented 9 years ago
Yes. Will be. "provided" dependency is part of apklib project, and when 
somebody use it can decide if it will need Google Analytics and will add it to 
the dependency of main apk project. It's the same way how almost any java 
library does. It's the same way how you can use Picasso library without OkHttp, 
but if you simply add OkHttp to the project dependency it will just work.

Original comment by tomas.pr...@gmail.com on 26 Apr 2014 at 11:42

GoogleCodeExporter commented 9 years ago
Exactly.

So, if and when you want to use library-b in an APK, you MUST include library-b 
as a listed dependency in your APK. This is the way that Maven works.

If you want people to use part of library-b (the part that does not rely on 
picasso) without including the picasso libraries then you have 2 options:
1) Convert your APKLIB to an AAR and use compile:optional scope for picassso
2) Split library-b into picasso and non-picasso related concerns so that your 
APK only ever includes exactly what it needs.

Original comment by william....@xandar.com.au on 27 Apr 2014 at 1:53

GoogleCodeExporter commented 9 years ago
To do what you want would require us to modify the classpath for APKLIB 
dependencies to include any provided and compile:optional AOPKLIB dependencies 
in the APK project.

These are normally excluded by Maven during compilation because it deals with 
compilation resources.

If you want to modify the classpath then it needs to be done before the project 
is resolved. Look at the ClasspathModifierLifecycleParticipant.

Original comment by william....@xandar.com.au on 27 Apr 2014 at 1:58

GoogleCodeExporter commented 9 years ago
Decided to chime in here, as we are facing exactly the same problem as Tomas 
explained.

To simplify the things up, we have an Android Library project, set up to be 
built by Maven, which "compiles" into an APKLIB. This library project includes 
a third-party library that is not actually used by end-user facing Android 
application we are developing. But the third-party library has to be there in 
APKLIB pom.xml for historical and backward-compatibility reasons.

In the library project, there are also some proprietary Java source code which 
explicitly references (imports) some of classes & interfaces found in the 
third-party library. Naturally, APKLIB project compiles and builds just fine.

Then, we have an Android application (packaged into APK) that includes the 
aforementioned APKLIB as a simple Maven dependency. On this step, javac fails 
with compile-time error as it cannot locate the third-party library, which is 
declared with "provided" scope in APKLIB, but obviously skipped or ignored by 
maven-android-plugin.

The only solution I see right now is to convert APKLIB module into an AAR, 
which should solve our problems (Android dex tool does not complain about 
referenced but missing classes). But then, AAR is not supported [yet] by 
Eclipse ... 

Original comment by leonid.m...@creative-mobile.com on 9 May 2014 at 10:07

GoogleCodeExporter commented 9 years ago
@leonid there is a simple solution to your use case. Add the provided 
dependency as a provided dependency in your APK. That way your app compiles 
fine, you don't include a library into your APK that you believe you don't use 
and you have explicitly acknowledged that the library is required but you are 
not providing it.

I think it would be simple to change android-maven-plugin to automatically add 
provided deps of an APKLIB to the APK  build. But it would be a dangerous thing 
to do and IMHO wrong.

If we did auto include provided APKLIB deps in an APK build it would mean that 
your APK would build fine but could crash at runtime because it attempts to 
execute code that it is not there. Provided scope is used to denote artifacts 
that you need to build against but which are provided at runtime by the 
container (or other mechanism).

Original comment by william....@xandar.com.au on 9 May 2014 at 9:17

GoogleCodeExporter commented 9 years ago
Just to further clarify, if you were to pick up an APKLIB from elsewhere that 
defined a scope=provided dependency would you rather that
A) It compiled and then crashed at some point at runtime?
B) It couldn't compile, told you why and let you make the call on whether you 
need to include the missing dep as scope=compile or can safely run with 
scope=provided

Maybe we should add a warning during the build about any APKLIB deps that have 
a scope=provided dependency.

Original comment by william....@xandar.com.au on 9 May 2014 at 9:29

GoogleCodeExporter commented 9 years ago
Thank you for a quick response, @william. I tend to agree that in most 
real-life use cases the best approach to tackle our problem would be to 
explicitly add the same external dependency (with scope=provided) to APK 
project as well, and this is what we actually did to "workaround" the issue.

However, if we would be looking at an APKLIB which is NOT managed by our team, 
and comes from the outside, hence its dependencies are managed and updated by 
someone else, then trying to figure which of APKLIB "provided" dependencies 
have to be also present in our APK project is an extra work, prone to mistakes.

As a summary, and after thinking through both use cases (A and B), I believe 
displaying an explicit build-time warning would be the best we can do today. A 
warning, not an error.

Original comment by leonid.m...@creative-mobile.com on 12 May 2014 at 7:20

GoogleCodeExporter commented 9 years ago
We are no longer using the issue tracking system on Google Code. Please refile 
this issue on https://github.com/jayway/maven-android-plugin/issues if you 
still have this problem with the latest release of the Android Maven Plugin

Original comment by mosa...@gmail.com on 19 May 2014 at 4:20