New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[TIMOB-25353] Android: Allow Titanium modules to process module dependencies #9481
Conversation
Generated by 🚫 dangerJS |
After discussion with @jquick-axway it's probably best this exists as an external module. |
@garymathews if implemented as an external module will this still remove the conflicts that module developers have? Is there anyway we can have a standard which we (module developers) build against? |
@benbahrenburg, the idea is to wrap the Google Play Services main JAR in its own module and to have other modules which depend on it (ex: ti.map) remove the Google Play Services JAR file from their "lib" directory. It'll be our responsibility to keep the Google Play Services module up-to-date. So, this will only resolve dependency conflicts if other modules "play ball", remove their Google Play Services JAR, and instead document that they require this new module as a dependency. For example, if an app developer wanted to use the "ti.map" module, the developer would have to add the "ti.map" module and the Google Play Services module in order for it to work. However, doing so with an existing module would be a breaking change, so, we'll look into providing a sensible warning message when attempting to a build while a module dependency is missing. May involve having adding a new feature to "timodule.xml" to reference another module as a dependency. As an added benefit to making Google Play Services its own module, we'll likely expose the APIs needed to ensure that it's installed and enabled on the device as documented by Google below. My impression is that most modules are not doing this right now, which is why we're holding on to an old version of this library. So, exposing these APIs is needed since the Google Play Services library doesn't contain implementation for most of its functionality and instead does inter-process communications with the Google Play app to request it to perform the needed operations.
What do you think? |
532a4f2
to
0a46faa
Compare
@jquick-axway sounds like a good plan. I had tried to keep the different versions of Play straight using this repo https://github.com/benbahrenburg/Ti-Google-Play-Services but it never really worked out. Having one place that everyone could get the latest version to compile against I think would be a welcome addition. |
@janvennemann Updated PR |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me.
@janvennemann, do you have any feedback you want to give?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a few minor notes regarding code style. Apart from that it looks good to me. Nice feature!
android/cli/commands/_buildModule.js
Outdated
|
||
// process module dependencies | ||
this.modules = this.timodule && !Array.isArray(this.timodule.modules) ? [] : this.timodule.modules.filter(function(m) { | ||
if (!m.platform || /^android$/.test(m.platform)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider using a negative check and return early here so you won't have to wrap everything in the if block.
android/cli/commands/_buildModule.js
Outdated
if (!m.platform || /^android$/.test(m.platform)) { | ||
var localPath = path.join(this.modulesDir, m.id), | ||
globalPath = path.join(this.globalModulesDir, m.id), | ||
getModulePath = function(modulePath) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If possible do not define functions inside loop-like function like forEach
, map
or filter
and don't use bind as this is expensive. Move it out and pass the module object into it so you can still edit it. Not really an issue here considering the number of modules a project probably has but this will also make the code more readable.
android/cli/commands/_buildModule.js
Outdated
}.bind(this); | ||
|
||
if ((fs.existsSync(localPath) && getModulePath(localPath)) || | ||
(fs.existsSync(globalPath) && getModulePath(globalPath))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like to move longer if checks like this into a simple function with a fitting name so it's easier to understand what it does.
@garymathews, what about when a modules defines dependencies but they are not present? As i understand it, currently this will just be silently ignored. Maybe we should print a nice error message instead of just continuing the build, knowing that it will probably fail later on anyway. |
When the build can't find a module in "tiapp.xml", we see the following error messages logged:
If we can't replicate the above for dependency modules as well, then that would be great. (Unless it's doing this already. I haven't tested this code change yet.) Also, does the build simply log all of the |
f01d899
to
8fb0db6
Compare
@janvennemann Updated PR |
5c29168
to
cc7ff30
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@garymathews Can you fix the typo in LIBRARY_ORIGIN_PORJECT
while you're at it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approved! appc-aar-tools is also updated to 1.1.4
We should probably also make changes to the app build so that it is aware of module dependencies and can print an appropriate error message if a dependency is missing.
@janvennemann Like this? |
@garymathews Yes, but i mean in the app build. Let's say you use a module that has another dependency then you would also require both modules during the app build, right? |
3f90de5
to
2a66415
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@garymathews, can you please check the linting errors reported by Jenkins? Thanks!
113fec4
to
e007bf6
Compare
e007bf6
to
bebc657
Compare
bebc657
to
d876555
Compare
android/cli/commands/_build.js
Outdated
this.cli.tiapp.modules.push({ | ||
id: dependency.id, | ||
version: dependency.version, | ||
platform: ['android'], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do dependencies always have to be explicitly the same platform and native, or could it be commonjs too?
Do we need to specify the apiversion here to be the same as the requirer/SDK, or is that handled by validateTiModules?
Also, If they specify a version for the dependency, I assume it has to be an exact match, we have no concept of semver here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- commonjs modules aren't supported as module dependencies
- I tried my best to re-use our current module handling code, so all of the existing module checks will take place.
apiversion
needs to match the SDK - It will be the same as our current module version handling code (I believe it's exact match only?)
android/cli/commands/_build.js
Outdated
@@ -1657,6 +1667,10 @@ process.exit(1); | |||
} | |||
logger.error(msg); | |||
process.exit(1); | |||
*/ | |||
|
|||
// re-validate modules |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a possible infinite loop here? I see before you'd just give up and report missing dependencies, but now we basically implicitly add them for you and re-try.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- It looks like that, but our existing checks will prevent that (if the module is missing/invalid) from happening and return before reaching this code again
FR Passed. We can now use modules using google Studio Ver: 4.10.0.201709271713 |
@garymathews @jquick-axway is there anything that module developers should be doing to embrace this? For example, how would I add this as a dependency to my module projects. Or is this simply asking the module developers to take the same version of playservices and use it in this modules? |
@benbahrenburg Here's the PR that makes use of ti.playservices as a dependency of ti.map: tidev/ti.map#216 I think the goal here is to have ti.playservices be a dependency of any native modules requiring it, and then they'll grab the latest ti.playservices module by default (or if you specify an exact version in your tiapp.xml it'll use that). That way we can avoid having all these modules embed differing versions. |
@benbahrenburg, we plan on writing up a blog post about this sometime this month to inform 3rd party module developers. For a more specific example, have a look at our "ti.map" module's "timodule.xml" file (link below) and note the new So, when a developer includes your module in their project, our build system will double check that their "tiapp.xml" file also references your module's module dependency too. If it doesn't, then the developer will get a build error stating that they need to also include said module dependency into their project. You can see an example of what a "tiapp.xml" file will look like with the "ti.map" module and the new Google Play Service module "ti.playservices" at the top of this pull request. The plan is to always bundle the new "ti.playservices" dependency module with Titanium so that developer's won't have to download/install it themselves. |
@jquick-axway Just to note: I asked Gary to modify the behavior of handling module dependencies so that we will attempt to automatically/implicitly add the dependency as if the user had done so in their tiapp.xml (but if they specify it in the tiapp.xml that works too). This was to avoid causing a breaking change to ti.map usage for existing apps (suddenly they'd stop working and the user would have to explicitly add ti.playservices to the app to get it working again). |
appc-aar-tools#16 NEEDS TO BE MERGED FIRST!In an attempt to minimise conflicting Google Play Services library versions I have implemented the ability for Titanium Android native modules to have dependencies on other Titanium Android native modules.
This is to allow dependency on the
ti.playservices
module for modules such asti.map
andti.admob
for Google Play Services.This will prevent the need to update each modules Play Services library and negate the need for module developers to include their own Play Services library which could conflict with existing modules.
TEST CASE
ti.playservices
andti.map
into yourtiapp.xml
JIRA Ticket