Skip to content

Commit

Permalink
Publish an AAR for Android developers.
Browse files Browse the repository at this point in the history
This extends the existing Android workflow to collect the validation
layer libraries into an AAR that is published to the repository's GitHub
Packages Repository. This way, Android Gradle users can point their
build at this repository and add a new dependency to their
build.gradle.kts file rather than needing to download and manage the
artifacts manually.

Fixes KhronosGroup#8167
  • Loading branch information
DanAlbert committed Jul 18, 2024
1 parent 31118fe commit fc6422f
Show file tree
Hide file tree
Showing 3 changed files with 191 additions and 21 deletions.
123 changes: 103 additions & 20 deletions .github/workflows/sdk_android_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ name: SDK Android Build
# artifacts to the release when a Vulkan SDK tag is pushed. The
# Vulkan SDK does not include binaries for Android, so we publish
# them here to provide Android binaries built from the same source
# used to build the Vulkan SDK.
# used to build the Vulkan SDK. The artifacts will also be bundled into an AAR
# (the library counterpart the APK application format) and uploaded to GitHub
# Packages so app developers can include the validation layers in their
# application the same way they would any Java dependencies.
#
# The tag needs to be pushed by name, as `git push --tags` to push all
# tags does not appear to trigger the action.
Expand Down Expand Up @@ -48,7 +51,23 @@ on:
tags:
- vulkan-sdk-*

env:
MIN_SDK_VERSION: 26
ARTIFACT_ID: vulkan-validation-layers

jobs:
sdk-version:
name: Get SDK version
runs-on: ubuntu-22.04
outputs:
sdk_version: ${{ steps.get_sdk_version.outputs.sdk_version}}
steps:
- name: Get sdk version string
id: get_sdk_version
run: |
sdk_version=`echo "${{ github.ref }}" | cut -d "-" -f 3`
echo "sdk_version=$sdk_version" >> $GITHUB_OUTPUT
android:
name: Android SDK Release
runs-on: ubuntu-22.04
Expand All @@ -63,36 +82,105 @@ jobs:
with:
python-version: '3.10'
- name: CMake Build
run: python scripts/android.py --config Release --app-abi ${{ matrix.abi }} --app-stl c++_static
run: python scripts/android.py --config Release --app-abi ${{ matrix.abi }} --app-stl c++_static --min-sdk-version $MIN_SDK_VERSION
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: vvl-android-${{ matrix.abi }}
path: ./build-android/libs/lib/

aar:
name: Create AAR
runs-on: ubuntu-22.04
needs: [android, sdk-version]
steps:
- name: Clone repository
uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: Download artifacts
uses: actions/download-artifact@v4
with:
path: ./libs
merge-multiple: true
pattern: vvl-android-*
- name: Assemble AAR
# GROUP_ID must be configured as a repoistory variable in Settings ->
# Actions -> Variables.
run: |
python scripts/aar.py \
--group-id ${{ vars.GROUP_ID }} \
--artifact-id ${{ env.ARTIFACT_ID }} \
--min-sdk-version $MIN_SDK_VERSION \
-o vulkan-validation-layers-${{ needs.sdk-version.outputs.sdk_version }}.aar \
libs
- name: Upload AAR
uses: actions/upload-artifact@v4
with:
name: vulkan-validation-layers-aar
path: vulkan-validation-layers-${{ needs.sdk-version.outputs.sdk_version }}.aar
if-no-files-found: error

maven:
name: Push AAR to GitHub Packages
runs-on: ubuntu-22.04
needs: [aar, sdk-version]
steps:
- name: Set up Java
uses: actions/setup-java@v4
with:
# Neither are really important. We need the mvn tool, but we aren't
# going to use it to build anything.
distribution: "temurin"
java-version: "21"
- name: Download artifacts
uses: actions/download-artifact@v4
with:
path: aar
name: vulkan-validation-layers-aar
- name: Publish
# Useful docs for this section:
# https://maven.apache.org/guides/mini/guide-3rd-party-jars-remote.html
# https://docs.github.com/en/actions/publishing-packages/publishing-java-packages-with-maven
run: |
mvn --batch-mode deploy:deploy-file \
-DgroupId=${{ vars.GROUP_ID }} \
-DartifactId=$ARTIFACT_ID \
-Dversion=${{ needs.sdk-version.outputs.sdk_version }} \
-Dpackaging=aar \
-DrepositoryId=github \
-Durl=https://maven.pkg.github.com/${{ github.repository }} \
-Dfile=aar/vulkan-validation-layers-${{ needs.sdk-version.outputs.sdk_version }}.aar
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

release:
name: Create Release for Tag
permissions: write-all
runs-on: ubuntu-22.04
needs: android
needs: [android, sdk-version]
steps:
- name: Get sdk version string
id: get_sdk_version
run: |
sdk_version=`echo "${{ github.ref }}" | cut -d "-" -f 3`
echo "sdk_version=$sdk_version" >> $GITHUB_OUTPUT
- name: Create release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Android binaries for ${{ steps.get_sdk_version.outputs.sdk_version }} SDK release
release_name: Android binaries for ${{ needs.sdk-version.outputs.sdk_version }} SDK release
body: |
These Android Validation Layer binaries were built with ndk version 25.2.9519653
The validation binaries can only be used with a device that supports Android API version 26 or higher.
The validation binaries can only be used with a device that supports Android API version ${{ env.MIN_SDK_VERSION }} or higher.
If you're using Android Gradle to build your app, it will be easier
to use the validation layers direcetly from the GitHub Package
Repository: ${{ github.repositoryUrl }}/packages/. See
https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-gradle-registry#using-a-published-package
for instructions on using packages from this repository. To include
the validation layers only in your debug APK (recommended), use
`debugImplementation` rather than `implementation` as the docs say.
draft: false
prerelease: false
- name: Get release URL
Expand All @@ -107,7 +195,7 @@ jobs:
publish:
runs-on: ubuntu-22.04
permissions: write-all
needs: release
needs: [release, sdk-version]
strategy:
fail-fast: false
matrix:
Expand All @@ -123,20 +211,15 @@ jobs:
suffix: "zip"
type: "application/zip"
steps:
- name: Get sdk version string
id: get_sdk_version
run: |
sdk_version=`echo "${{ github.ref }}" | cut -d "-" -f 3`
echo "sdk_version=$sdk_version" >> $GITHUB_OUTPUT
- name: Download artifacts
uses: actions/download-artifact@v4
with:
path: ./android-binaries-${{ steps.get_sdk_version.outputs.sdk_version }}
path: ./android-binaries-${{ needs.sdk-version.outputs.sdk_version }}
merge-multiple: true
pattern: ${{ matrix.config.artifact }}-*
- name: Make release artifacts
run: |
${{ matrix.config.command }} android-binaries-${{ steps.get_sdk_version.outputs.sdk_version }}.${{ matrix.config.suffix }} android-binaries-${{ steps.get_sdk_version.outputs.sdk_version }}
${{ matrix.config.command }} android-binaries-${{ needs.sdk-version.outputs.sdk_version }}.${{ matrix.config.suffix }} android-binaries-${{ needs.sdk-version.outputs.sdk_version }}
- name: Download release URL
uses: actions/download-artifact@v4
with:
Expand All @@ -153,6 +236,6 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.set_upload_url.outputs.upload_url }}
asset_name: android-binaries-${{ steps.get_sdk_version.outputs.sdk_version }}.${{ matrix.config.suffix }}
asset_path: ./android-binaries-${{ steps.get_sdk_version.outputs.sdk_version }}.${{ matrix.config.suffix }}
asset_name: android-binaries-${{ needs.sdk-version.outputs.sdk_version }}.${{ matrix.config.suffix }}
asset_path: ./android-binaries-${{ needs.sdk-version.outputs.sdk_version }}.${{ matrix.config.suffix }}
asset_content_type: ${{ matrix.config.type }}
85 changes: 85 additions & 0 deletions scripts/aar.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#!/usr/bin/env python3
#
# Copyright (c) 2024 LunarG, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from pathlib import Path
from zipfile import ZipFile
import argparse
import textwrap


def generate_aar(
output_path: Path,
library_dir: Path,
group_id: str,
artifact_id: str,
min_sdk_version: int,
) -> None:
"""Creates an AAR from the CMake binaries."""
with ZipFile(output_path, mode="w") as zip_file:
zip_file.writestr(
"AndroidManifest.xml",
textwrap.dedent(
f"""\
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="{group_id}.{artifact_id}" >
<uses-sdk android:minSdkVersion="{min_sdk_version}" />
</manifest>
"""
),
)

for abi_dir in library_dir.iterdir():
libs = list(abi_dir.glob("*.so"))
if not libs:
raise RuntimeError(f"No libraries found matching {abi_dir}/*.so")
for lib in libs:
zip_file.write(lib, arcname=f"jni/{abi_dir.name}/{lib.name}")


def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument(
"--group-id", help="The group ID of the AAR that will be published"
)
parser.add_argument(
"--artifact-id", help="The artifact ID of the AAR that will be published"
)
parser.add_argument(
"--min-sdk-version",
type=int,
default=26,
help="The minSdkVersion of the built artifacts",
)
parser.add_argument("-o", "--output", type=Path, help="Output file name")
parser.add_argument(
"library_directory",
type=Path,
help="Directory containing the built libraries, separated into ABI-named subdirectories",
)
args = parser.parse_args()

generate_aar(
args.output,
args.library_directory,
args.group_id,
args.artifact_id,
args.min_sdk_version,
)


if __name__ == "__main__":
main()
4 changes: 3 additions & 1 deletion scripts/android.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ def main():
parser = argparse.ArgumentParser()
parser.add_argument('--config', type=str, choices=configs, default=configs[0])
parser.add_argument('--app-abi', dest='android_abi', type=str, default="arm64-v8a")
parser.add_argument('--min-sdk-version', type=int, default=26, help='The minSdkVersion of the built artifacts')
parser.add_argument('--app-stl', dest='android_stl', type=str, choices=["c++_static", "c++_shared"], default="c++_static")
parser.add_argument('--apk', action='store_true', help='Generate an APK as a post build step.')
parser.add_argument('--clean', action='store_true', help='Cleans CMake build artifacts')
Expand All @@ -91,6 +92,7 @@ def main():
cmake_config = args.config
android_abis = args.android_abi.split(" ")
android_stl = args.android_stl
min_sdk_version = args.min_sdk_version
create_apk = args.apk
clean = args.clean

Expand Down Expand Up @@ -159,7 +161,7 @@ def main():
cmake_cmd += f' -D BUILD_TESTS={create_apk}'
cmake_cmd += f' -D CMAKE_ANDROID_STL_TYPE={android_stl}'

cmake_cmd += ' -D ANDROID_PLATFORM=26'
cmake_cmd += f' -D ANDROID_PLATFORM={min_sdk_version}'
cmake_cmd += ' -D ANDROID_USE_LEGACY_TOOLCHAIN_FILE=NO'

common_ci.RunShellCmd(cmake_cmd)
Expand Down

0 comments on commit fc6422f

Please sign in to comment.