Skip to content
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

Use Github actions to compile and push all supported precompiled libraries #102

Merged

Conversation

pietrygamat
Copy link
Collaborator

@pietrygamat pietrygamat commented Aug 3, 2021

Current project setup treats native libraries as part of the source, and enforces commiting the artifacts alongside the source. Naturally this may lead to hard to detect errors resulting from commiting libraries built on wrongly configured environment, unintended differences in provided functionalities between platforms or even introduction of malware by malicious "hypocrite committer".
The proposed solution to this problem is to only allow transparent, reproducible Github Action to build and commit the libraries. This way anyone can review the script and the logs resulting from the operation.

There are currently 12 native library variants, and to my knowledge, no cross-compiling options that would match them all from a single machine (compilation targetting MacOS and Solaris is not possible from any other OS), so the solution is to set up several runs on different machines, each compiling relevant version.

In this pipeline the following happens:

  • Github collaborator triggers the build (manually, from selected branch)
  • A new dedicated branch is created on selected branch HEAD
  • 8 linux, 2 macOs and 1 solaris VM checkout the code at this revision
  • Each VM builds project using maven 3.8.1 and jdk-11
  • Each VM commits generated artifact to the dedicated branch. The commit message indicates the revision used to build the library. This should result in a branch with 11 automatically generated commits.

Now it is up to the maintainer to either merge the branch, or simply delete it if further testing reveals any problems. Not merging to the master too often should prevent the repository from swellling in size too much. As the action is also part of the fork repositories, each developer can execute it on their own repo - no sharing of CI access is required.

Word about Solaris:

I was unable to find any information on how to configure cross compilation targeting Solaris on Linux, but it seems there is a way to run VirtualBox VM right inside the Github Actions. The process is terribly slow (takes about 30 minutes to set up VM, download dependencies and run the job - compared to 30 seconds it takes on other platforms), and not 100% reliable (issues), but it does work with result like this.

Goals:

  • Manual trigger in place
  • Manual merge to master after review
  • Build for linux_32, 64, arm, arm64, ppc on ubuntu-14.04
  • Build for Windows 32, 64, arm64 on ubuntu-20.04 and mingw
  • Build for MacOS 64 using Catalina + SDK 10.9
  • Build for MacOS M1 using Catalina + SDK 11.0
  • Build for Solaris 32, 64 using Solaris VM

Non-Goals:

  • As this is geared towards versioned releases, so the goal is to cover the baseline: not attempting to build on all supported configurations (only jdk11, only ubuntu 20.04, only MacOs Catalina, only Solaris 11, no Windows).
  • Hopefully all works for all supported platforms (e.g. solaris 10+, jre 6-16) but no testing for compatibility is done.

@pietrygamat pietrygamat force-pushed the precompile-natives-pipeline branch 2 times, most recently from 13e9c3c to c88ec29 Compare August 4, 2021 11:33
@tresf
Copy link

tresf commented Aug 4, 2021

no cross-compiling options [...] targeting MacOS

I haven't had a chance to try this, but I wanted to add an FYI that this is finally possible using darling. At time of writing this, precompiled binaries for Debian systems are available. The process of getting the rest of the tools setup may take a while in CI (e.g. Xcode xip, Command Line tools) and (for performance reasons) likely require a caching between builds.

no cross-compiling options [...] targeting Solaris

We may choose to deprecate support for Solaris by only providing outdated binaries until the API changes. If we do this, I'd recommend we bump to version 3.0.0 to signify a cut-off to any users. Studies show it as < 0.1% of "known" servers, it probably won't be missed.

@tresf
Copy link

tresf commented Aug 5, 2021

Non-Goals (only jdk11, only ubuntu 20.04, only MacOs Catalina, only Solaris 11, no Windows).

Linux Binaries

  • We should build using oldest Ubuntu for highest ABI compatibility (e.g. Ubuntu 14.04, if a CI still offers it, if not, 16.04, etc) as documented here.
  • Ubuntu 20.04 will produce binaries which may not function on older, supported OSs. Note, the supported ABI may differ between Ubuntu and Fedora (as an example), which is why the oldest possible Ubuntu version for CI/manual builds always yields the highest level of compatibility.

Windows Binaries

  • We can and should build for Windows (x86, x86_64, aarch64) as documented here.
    • Windows aarch64 (ARM64) does require Ubuntu 20.04 due to clang (llvm-mingw wrapper) dependencies as documented here,
    • Windows x86, x86_64 can probably use newer Ubuntu + mingw without compat regressions as documented here.
    • If desired, x86 and x86_64 unit tests can be added using Wine if available. This would also require a paired Windows version of Java/openjdk available to Wine.
    • If aarch64/ARM64 testing is desired, Wine may be available for aarch64/ARM64 binaries. More information here. This would also require a paired Windows version of Java/openjdk available to Wine. Microsoft offers a native version of Java for ARM64 here.
    • If needed or desired, we may be able to use Windows to compile Windows resources, the build system supports MSVC on Windows, but mingw is generally preferred due to its simplicity and wide range of compatibility (e.g. tested back to Windows XP).

MacOS Binaries

  • MacOS can use Catalina, but *should use 10.9 SDK as documented here (you may find SDK published in some places without need for an Apple developer account) but this is very common so CI services may offer this by configuration.
    • We now have instructions for MacOS M1/aarch64 which requires newer 11.0 SDK as documented here (you may find SDK published in some places without need for an Apple developer account)

      * @GMKennedy and I will be confirming this 10.9 SDK is adequate for Apple notarization requirements prior to merging Release 2.9.3 #104.

@pietrygamat
Copy link
Collaborator Author

pietrygamat commented Aug 5, 2021

We should build using oldest Ubuntu for highest ABI compatibility

Github actions allows ubuntu-18.04 and ubuntu-20.04. Perhaps running docker image of ubuntu 14 is an option under ubuntu latest runner?

MacOS can use Catalina, but *should use 10.9 SDK

I am not sure I grasp the distinction between MacOS, Xcode and SDK version. Would you care to confirm that what is needed is listed here?

@tresf
Copy link

tresf commented Aug 5, 2021

We should build using oldest Ubuntu for highest ABI compatibility

Github actions allows ubuntu-18.04 and ubuntu-20.04. Perhaps running docker image of ubuntu 14 is an option under ubuntu latest runner?

... or we choose a non-Ubuntu machine with older ABI, such as Centos, Redhat, etc. I'm not sure if these are options, but 18.04 is too new. For example, Ubuntu 16.04 is supported until 2023. If Linux offers a way to use older ABI that would also work (and possible better for our tutorials, older OSs can be hard to get packages and updates for)

MacOS can use Catalina, but *should use 10.9 SDK

I am not sure I grasp the distinction between MacOS, Xcode and SDK version. Would you care to confirm that what is needed is listed here?

Unfortunately it is not listed in the link you provided. We use SDK 10.9 which comes with XCode 6.2, which is old. @GMKennedy and I tested our future 2.9.3 release on MacOS 10.8 last night and it worked with this SDK. Unfortunately, the GitHub actions do not list this SDK, so you will need to download this SDK manually. There are GitHub mirrors which offer this, the package is much smaller than the entire XCode installation and should be relatively fast to setup and do not require an apple developer subscription. Once extracted, the SDK path can be configured through an environmental variable so that you do not need to execute CMake manually or modify the script scripts like the tutorial states.

@pietrygamat pietrygamat force-pushed the precompile-natives-pipeline branch 2 times, most recently from fff6063 to 426fd3a Compare August 6, 2021 18:05
@pietrygamat
Copy link
Collaborator Author

pietrygamat commented Aug 6, 2021

For Linux/Windows targets I'd with the docker route. This IMO is a good way to provide really portable script that could also go to the wiki, because docker is available for windows and MacOS too.

  docker run --rm --workdir=/jssc --volume $PWD:/jssc ${{ matrix.image }} bash -c \
          ' apt-get update && apt-get install --yes mvn openjdk-11-jdk-headless ${{ matrix.packages }} && \
          /mvn/bin/mvn -B clean install -P ${{ matrix.profile }} '

Clean docker images for Ubuntu:14.03 with predictable preinstaleld software are easily available.

@tresf
Copy link

tresf commented Aug 6, 2021

For Linux/Windows targets I'd with the docker route. This IMO is a good way to provide really portable script that could also go to the wiki, because docker is available for windows and MacOS too.

  docker run --rm --workdir=/jssc --volume $PWD:/jssc ${{ matrix.image }} bash -c \
          ' apt-get update && apt-get install --yes mvn openjdk-11-jdk-headless ${{ matrix.packages }} && \
          /mvn/bin/mvn -B clean install -P ${{ matrix.profile }} '

Clean docker images for Ubuntu:14.03 with predictable preinstaleld software are easily available.

I think this is good for manually publishing a release, but I do not think it is a good baseline for people interested in developing, as the complexity of troubleshooting becomes a game of debug "inception", e.g. Docker -> Ubuntu -> Maven -> Ant -> Cmake -> Clang, etc.

Docker instructions do help keep the CIs in good shape, and many people prefer them to VMs these days, but I just don't want to minimize the difficulties it can potentially create. :).

@tresf
Copy link

tresf commented Aug 6, 2021

But yes, let's please add anything that's helpful to the wiki. I'm happy to test any commands on other platforms if needed. Note: At time of writing this the newer M1 macs would pose some limitations for example, Ubuntu 20.04 running in a container or VM on ARM64 (M1) can build windows_32, windows_64, linux_ppc, linux_arm, linux_arm64, but NOT linux_32, linux_64 or windows_arm64 due to missing cross-compilers.

This has less to do with Docker and more to do with the toolchain availability, but these things can be less obvious when executing a small script versus setting up the environment from scratch.

@pietrygamat pietrygamat force-pushed the precompile-natives-pipeline branch from 426fd3a to 29f3b60 Compare August 6, 2021 22:22
@pietrygamat
Copy link
Collaborator Author

I have updated the pipeline. Current version builds the libraries in the following way:

  • Anything targetting linux is built on ubuntu-14.04 via docker (ubuntu 20.04 x64 host)
  • Anything targetting windows is built on ubuntu-20.04 via docker (ubuntu 20.04 x64 host)
  • Anything targetting MacOS is built with MacOS 10.15 on xcode 12.2 using SDKs 11.0 and 10.9
  • Anything targeting solaris is built with Solaris 11 VM hosted on virtual box on MacOs 10.15.

The following modifications vs the wikis were required:

  • on ubuntu 14.03 the required apt package is make3, as ant build explicitly rejects make apparently it's version 2.x in this release
  • on ubuntu 20.03 added required apt package file which is not part of base image
  • on macos targetting SDK 10.8, the SKD 10.9 needs to be downloaded during execution.
  • on Solaris, the project is built with mvn, not make and using jdk11.
  • Solaris that is available for this CI is in version 11, not 10.

It would be great if someone with access to non-x64 pc would verify if the artifacts commited to branch precompile-natives-pipeline-precompiled-natives of my fork https://github.com/pietrygamat/jssc are all working as expected. They are all generated by this build, so please also review the logs and the scripts themselves.

@tresf
Copy link

tresf commented Aug 6, 2021

  • on ubuntu 14.03 the required apt package is make3, as ant build explicitly rejects make apparently it's version 2.x in this release

I believe you mean cmake3? This is intentional for the build tutorial as it will apply to more developers and is a divergence between publishing (which we have no Ubuntu tutorial for) and developing (which we do have a tutorial for). Sorry about the confusion. The publishing tutorial should be updated with this information but the section has not been written yet. 😄

  • on ubuntu 20.03 added required apt package file which is not part of base image

Added to tutorial.

  • on macos targetting SDK 10.8, the SKD 10.9 needs to be downloaded during execution.

I'm not sure I understand, I believe this is already part of our tutorial.

  • on Solaris, the project is built with mvn, not make and using jdk11.

Maven is not available for Solaris 10. We can archive that tutorial if we plan to drop support for Solaris 10.

  • Solaris that is available for this CI is in version 11, not 10.

Understood.

@pietrygamat pietrygamat force-pushed the precompile-natives-pipeline branch from 29f3b60 to 72fddc7 Compare August 7, 2021 22:05
@pietrygamat pietrygamat mentioned this pull request Sep 11, 2021
@pietrygamat pietrygamat force-pushed the precompile-natives-pipeline branch from 72fddc7 to 20dfefe Compare September 11, 2021 17:17
CMakeLists.txt Outdated Show resolved Hide resolved
pom.xml Show resolved Hide resolved
@pietrygamat pietrygamat force-pushed the precompile-natives-pipeline branch 2 times, most recently from b6d5c3a to 854e3ad Compare September 11, 2021 17:37
@tresf
Copy link

tresf commented Sep 11, 2021

Thanks you for the version improvements. I've left some feedback on the cmake stuff, with a request to restore the old functionality as a fallback for cmake standalone builds where this version information would otherwise be unavailable.

@pietrygamat pietrygamat force-pushed the precompile-natives-pipeline branch from 854e3ad to 0f9f4da Compare September 11, 2021 20:13
@pietrygamat pietrygamat force-pushed the precompile-natives-pipeline branch from 0f9f4da to ae95f9c Compare September 20, 2021 19:39
@pietrygamat pietrygamat merged commit ae95f9c into java-native:master Sep 20, 2021
@pietrygamat pietrygamat deleted the precompile-natives-pipeline branch September 20, 2021 19:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants