premake-core icon indicating copy to clipboard operation
premake-core copied to clipboard

Add premake-androidndk module link to the website

Open Triang3l opened this issue 2 years ago • 6 comments

What does this PR do?

Adds a link to the new generator for the ndk-build system used in the Android NDK, for building C, C++, GNU Assembler, Yasm and RenderScript code for Android, with support for per-architecture settings.

How does this PR change Premake's behavior?

As this is a third-party module, the core functionality of Premake is not changed — only the community section on the website is modified.

This module exposes a more comprehensive set of features provided by ndk-build compared to other NDK modules, such as Meoo/premake-androidmk (ndk-build, listed on the website), IsCoolEntertainment/premake-ndk (ndk-build, not listed), polymonster/premake-android-studio (CMake, listed). I haven't done comparisons to the generator of Visual Studio projects for the Android NDK as it appears that Visual Studio has a different approach to target architecture selection, though this module serves a different goal — generation of files for Google's original cross-platform tools.

The most important addition — why this module was created in the first place (as our project contains a large amount of architecture-specific code, being an emulator) — is support for architecture filters, while also preserving the intended way of running ndk-build (one invocation builds for all needed architectures), so it's easy to use the generated scripts with Gradle via its externalNativeBuild.ndkBuild functionality, with only a few additions to the arguments provided to ndk-build. It's done by allowing users to specify multiple platforms (or build configurations) to build the workspace for, each with its own architecture (though universal-architecture configurations, including mixing of architecture specializations and architecture-agnostic fallbacks, are also supported). The configuration–platform pair that will actually be used for building each project, out of all build configurations and platforms selected by the user, will be chosen based on the TARGET_ARCH_ABI state variable set by ndk-build at build time. This is in contrast to other NDK modules for Premake, which restrict one build system invocation to just one set of project settings (similar to the behavior of most build systems that Premake generates scripts for), making it inconvenient to integrate generated scripts into Gradle projects if per-architecture settings are needed.

The new module also tries to provide broad support for all source file languages accepted by ndk-build — C, C++, the GNU Assembler, Yasm and RenderScript, passing applicable settings to the compilers of each. As Premake itself doesn't expose separate settings like buildoptions and defines (among many others) for different languages, this module relies on files:**.extension filters for letting the user pick which language each setting is designed for. Unfortunately, ndk-build doesn't allow per-file settings (except for .arm and .neon suffixes, exposed directly or as properly file-filtered armisa and vectorextensions by this module), but it does provide certain per-language variables, so this specific kind of files filtering is still possible to some extent.

On the linkage side, a few additional features for convenience and for consistency with other build systems (like Visual Studio) are also available. System libraries required by static libraries (via links or, as a fallback, for example, for cases of name collisions, linkoptions) are automatically exported to shared libraries that depend on them. This is also done for -u (--undefined) in linkoptions, so a static library project can, for instance, list the Java native function implementations it contains, so they will not be removed from shared libraries as unused by the linker (the more brute-force option, whole archive linkage, is also provided via two new settings — either wholelib in the static library or wholelibs in the shared library can be used for this purpose). The -flto type can also be overridden via buildoptions and linkoptions, and it will be exported from static libraries if it's specified in their linkoptions.

Prebuilt libraries, external Android.mk files, and executables (such as for Runtime.exec or Termux) are also supported. The way external Android.mk files are exposed is different than in Meoo/premake-androidmk and, possibly unlike there, is limited to only one ndk-build module per Android.mk, as ndk-build modules correspond to Premake projects here so they can have their own linkoptions, links and some other settings.

A lot of attention is paid to escaping and input validation — as ndk-build performs various string operations internally and passes values to shell commands, the handling of each non-alphanumeric character in all ndk-build variables accepting file names or paths was checked. Different kinds of escaping are performed at both Premake time and dynamically at build time (so escaping is also done for the result of GNU make $ variable expansion and function calls).

Anything else we should know?

While this module is generally more flexible at building native code, it still doesn't completely supersede the other generators mentioned previously. One example covered above is different constraints in the usage of external Android.mk files. Deprecated architectures, such as ARMv5, are not supported as well (as they would need not only the architecture value, but also settings for things like floating-point operation implementation and calling convention for floating-point numbers). Gradle, Java/Kotlin are completely out of scope of the project, as that's a completely different world than what is covered by Premake.

The module is also intentionally incompatible with the settings added by the Visual Studio Android module in the Premake core. There are many things that it does inconsistently with Premake itself, that will likely be unexpected or inconvenient to users. The detailed list of reasons for diverging is written in the bottom of the README.md of the new module, but some of the examples are duplicate (and lowercase) architecture names which are not aliases, thumbmode also being lowercase and using "disabled" instead of the usual "Default" (and also duplicated as flags "Thumb"), androidapilevel introduced while systemversion exists. If the new module is added to the core, I think the Visual Studio module needs to be adjusted (to use the new armisa = "Default" / "A32" / "T32" instead of thumbmode = "disabled" / "arm" / "thumb", the cppstl setting added by this module which corresponds directly to the NDK STL names instead of stl with arbitrary and unexpected renaming) rather than this module.

Currently, the module doesn't include unit tests. There are many edge cases that need to be validated, including various combinations of platform-specific and platform-agnostic, architecture-specific and architecture-agnostic configurations, linkage (including transitivity of certain settings), input validation. However, this is unfortunately also the reason why it's a massive task, but it's among what I want to do in the future, though it's low-priority as it doesn't directly effect my main project that uses this module.

Did you check all the boxes?

(This section is not entirely applicable as this is a third-party module rather than core functionality.)

  • [x] Focus on a single fix or feature; remove any unrelated formatting or code changes
  • [ ] Add unit tests showing fix or feature works; all tests pass
  • [ ] Mention any related issues (put closes #XXXX in comment to auto-close issue when PR is merged)
  • [ ] Follow our coding conventions
  • [x] Minimize the number of commits
  • [ ] Align documentation to your changes

You can now support Premake on our OpenCollective. Your contributions help us spend more time responding to requests like these!

Triang3l avatar Oct 30 '21 16:10 Triang3l

Considering there are 4 community modules (2 already listed on the website — though I'm not sure if we should add the old premake-ndk without a request from its author) targeting the Android NDK, each with their own features (multi-ABI builds and language filters here, whole app project generation in other ones, possibly broader (in a different way) external Android.mk inclusion functionality in another), would user experience of the visitors of the page be better if all NDK modules were grouped, with their key advantages, as well as the exact target build systems (ndk-build, CMake, Gradle, Ant), listed? The way I added this module to the list in this pull request is just the one that involves least changes, as anything further would be something to discuss, I think.

Triang3l avatar Oct 30 '21 16:10 Triang3l

Considering there are 4 community modules (2 already listed on the website…each with their own features…would user experience of the visitors of the page be better if all NDK modules were grouped, with their key advantages, as well as the exact target build systems (ndk-build, CMake, Gradle, Ant), listed?

If you're able to contribute that knowledge, that would be awesome! All for it.

starkos avatar Nov 03 '21 10:11 starkos

@Triang3l Do you want to split out the Android/NDK group as part of this PR, or should we go ahead and merge this one now?

starkos avatar Nov 03 '21 11:11 starkos

@starkos Yes, I'll split it out here after browsing their code a bit more. Should I add https://github.com/IsCoolEntertainment/premake-ndk as well?

Triang3l avatar Nov 03 '21 17:11 Triang3l

@Triang3l Where do we stand one this one? Are you still up for breaking out a section for Android, or should we go ahead and merge this as is?

starkos avatar Nov 21 '21 20:11 starkos

@starkos I think a subitem should be more user-friendly. I'm somewhat stuck regarding how features of the modules should be listed, however (while I think it's important to do so to make sure people won't be asking “why 4 of the same?” and maybe even get disappointed if they don't find the needed functionality in just one or two of them), considering that such a list may become outdated if something is changed in their code, though at least 2 of the modules there have not been updated for a long time, but I'll send a pull request within the next week with the proposed format.

Triang3l avatar Nov 21 '21 21:11 Triang3l