Modules can bundle AARs and native libraries however there will be a conflict if you have multiple modules bundling the same libraries.

Internally at my workplace we handle this by wrapping the native library (either native C++ or AAR/xcframework) around a plugin whose sole purpose is to provide the library, which multiple modules can use the <dependency> directive to import the plugin. This ensures that a single
copy of the library is present for the application.

Some examples:
https://github.com/totalpaveinc/cordova-plugin-libcxx
https://github.com/totalpaveinc/cordova-plugin-libsqlite (depends on libcxx)
https://github.com/totalpaveinc/cordova-plugin-sqlite (depends on libsqlite)

Where sqlite is a cordova plugin API into libsqlite, which contains the native SQLite C library, with additional C++ addons, making it depend on libcxx for android. We have another internal/private plugin that also depends on libsqlite and libcxx and it's cordova plugin declares the dependency so that the library wrappers
are present at the application level.

I believe this is only an issue if you bundle the libraries yourself as well. If you use Gradle to manage dependency artifacts, I believe those are all resolved at build time, assuming that you don't have two modules requiring on incompatible versions. (e.g. Plugin A wants X:1.0.0 where Plugin B wants X:2.0.0).

If you know of any specific libraries that **has** to be bundled at the application level, would be interesting to know, but in those cases I think the existing <lib-file> directive
could be used to support that kind of use case.

On 2023-03-30 11:57 a.m., julio cesar sanchez wrote:
I had similar thoughts in the past, but never had time to implement it
myself.

For reference, Joe already tried to convert the Android part of
InAppBrowser plugin into a library project back in 2018

https://github.com/apache/cordova-plugin-inappbrowser/pull/242

Modules have some problems too, like not being able to bundle aar
libraries, and some native SDKs can’t be used in modules.



El jueves, 30 de marzo de 2023, Norman Breau <nor...@nbsolutions.ca>
escribió:

Hi all,

I just wanted to announce that I've been experimenting with a different
way of authoring Cordova plugins.
I don't really have anything to show right now, but looking to get some
abstract high-level feedback based on the idea.

This is more or less a preliminary start of a discussion so that I can get
some early feedback. The plan is to come back some time later with
a more official specification document and usable PoCs for both Android &
iOS platforms.

Privately I've been experimenting with a more closer "native" method which
I feel like solves several issues
with the way that cordova plugins are traditionally authored.

First I'll explain briefly the pains of authoring cordova plugins, and
then I'll explain a high level idea that will likely solve the problems.

Currently the plugins are authored by having a set of arbitrary source
files as defined by the <source-file> / <header-file> directives,
which also declares where these files should be copied to into the cordova
native app project. Additionally, if the plugin requires
changing resource files or adding additional configurations, they must
make use of several directives which may include:

- config-file
- edit-config
- resource-file
- lib-file
- framework
- source-file / header-file
- asset


Most of these works well enough, but shouldn't be necessary to begin with.
Others, are very finicky or are barely usable due to bugs or other caveats
(e.g. config-file and edit-config)

The second issue with the way that Cordova plugins are traditionally
authored (based on the Official Apache plugins) is that they
aren't unit testable. They can only really be tested as part of a real
cordova project, which we currently do via cordova-paramedic.
This is because there is a disconnect between the plugin sources and an
actual native project.

So I've been experimenting with authoring cordova plugins using a native
project that gets imported a cordova project. Right now
my experimentation has been exclusively with the Android platform, so I'll
be using more Android-specific examples.

But my experimentation has me building a cordova plugin that instead of
containing loose java source files, they contain an actual
Gradle project that builds an Android Library. This means that the Cordova
Plugin has it's own:

- Source files
- AndroidManifest
- resources
- Gradle configs & dependency management

With these tools at the plugin's author disposal... it should eliminate,
or mostly eliminate the need of the aforementioned directives:

- edit-config

Is no longer required to edit AndroidManifest.xml, but may still be
required to edit config.xml (but is there really a need to?). Instead
native libraries have their own AndroidManifest.xml which will get merged
with the App's manifest.

- lib-file

A native library can bundle their own lib-files.

- resource-file

A native library can bundle their own resource files.

- framework

A native library has it's own gradle file to manage frameworks/dependencies

- source-file / header-file

A native library has it's own file structure for their source files,
whether java or native C++ modules.

- config-file*

While won't be needed to edit AndroidManifest.xml for the same reason as
edit-config, which was a common use case...
It will still be required for setting up cordova Feature tags/declarations
which gets placed into `config.xml`.

- asset*

Untested, I'm not sure if assets will get merged in a way that is usable
by the app. So this directive may still be relevant.

Additionally, the js-module directive will still be relevant as the native
project has no concept of setting up the webview JS modules.

*To be clear*, I'm not suggesting that the current plugin.xml directives
to be deprecated or removed. They are still going
to be required to support any cordova plugin authored in a traditional
method. However, with the module method, most of these directives won't be
necessary to use.
In fact, I think the module method could continue to use any one of the
existing directives if they choose to, but in all likeliness, there won't
be a need to. In
practice we may want to discourage people to use the "legacy" directives
so that support could be considered to be dropped in the future.

I foresee a new directive being created to declare the "module" directory,
which is the root folder of a native project, which would simply be copied
in full to a directory inside the app project.
For example, the module format really needs 4 main actions to be done in a
cordova android project. I'll pretend that cordova-plugin-file is authored
in a module format containing a gradle project.

Cordova will need to:

1. Copy the cordova-plugin-file gradle project into a subdirectory (e.g.
/platforms/android/cdvModules/cordova-plugin-file)
2. settings.gradle needs a line to include the gradle project into it's
build system (e.g. include ":cdvModules:cordova-plugin-file")
3. The "app" module needs to depend on cordova-plugin-file (e.g:
implementation project(":cdvModules:cordova-plugin-file"))
4. Configure the JS-modules / config.xml "Feature" tags just like it
always did before.

Apache Cordova will still not be distributing prebuilt libraries (e.g.
plugins are not AAR or xcframeworks) but rather the complete module that
can be copied into a project as a module.
The module itself will contain all the build scripts and source code. I
believe this still satisfies Apache's Release policy requiring source
packages with no compiled code[1]. Of course,
third-party plugin authors can still utilize this method of authoring
plugins and still include closed sources or libraries if they choose so.

Lastly, now that the plugin has a native project housed, it will also be
much easier to unit test the native side. However there is one caveat where
e2e tests cannot be done as that will still require a real cordova project,
so cordova-paramedic will still have to be used for e2e testing.

I do have a working example of this system I described for Android but I
still have lots of testing to do myself. Still, I feel very confident that
this is major improvements to how plugins are authored, which hopefully
will encourage well written and well tested plugins, as well as reducing
the need for plugin authors to manipulate the app's resource files, which
can often result in conflicts.

Moving forward I'd be continuing to experiment with both the Android & iOS
platforms, preparing proof of concept repositories as well as a
specification document for a lower level detailed
of what implementation may look like, which can then be further
reviewed/commented.

Looking forward for any comments, questions, or concerns.

Cheers,
Norman

References:
[1] https://www.apache.org/legal/release-policy.html#source-packages


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@cordova.apache.org
For additional commands, e-mail: dev-h...@cordova.apache.org

Reply via email to