diff options
-rw-r--r-- | CMakeLists.txt | 8 | ||||
-rw-r--r-- | README.md | 14 | ||||
-rwxr-xr-x | android_sample/AndroidManifest.xml | 45 | ||||
-rw-r--r-- | android_sample/CMakeLists.txt | 53 | ||||
-rw-r--r-- | android_sample/assets/amber/compute_ssbo.amber | 54 | ||||
-rw-r--r-- | android_sample/assets/amber/compute_ssbo.amber.vk_shader_0.spv | bin | 0 -> 1996 bytes | |||
-rw-r--r-- | android_sample/jni/amber_script.cc | 157 | ||||
-rw-r--r-- | android_sample/jni/amber_script.h | 75 | ||||
-rw-r--r-- | android_sample/jni/main.cc | 106 | ||||
-rwxr-xr-x | android_sample/res/values/strings.xml | 19 | ||||
-rw-r--r-- | src/CMakeLists.txt | 4 | ||||
-rw-r--r-- | src/vulkan/CMakeLists.txt | 4 | ||||
-rwxr-xr-x | tools/build-amber-sample.sh | 120 |
13 files changed, 653 insertions, 6 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 01a1360..f0bdb54 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,8 +77,10 @@ if (${AMBER_ENABLE_SPIRV_TOOLS}) include_directories("${PROJECT_SOURCE_DIR}/third_party/spirv-tools/include") endif() -include(src/dawn/find_dawn.cmake) -include(src/vulkan/find_vulkan.cmake) +if (NOT ANDROID) + include(src/dawn/find_dawn.cmake) + include(src/vulkan/find_vulkan.cmake) +endif() add_definitions(-DAMBER_ENGINE_VULKAN=$<BOOL:${Vulkan_FOUND}>) add_definitions(-DAMBER_ENGINE_DAWN=$<BOOL:${Dawn_FOUND}>) @@ -187,6 +189,6 @@ endfunction() add_subdirectory(third_party) add_subdirectory(src) -if (${AMBER_ENABLE_SAMPLES}) +if (${AMBER_ENABLE_SAMPLES} AND NOT ANDROID) add_subdirectory(samples) endif() @@ -42,6 +42,20 @@ cmake -GNinja ../.. ninja ``` +### Android + +* Android build needs Android SDK 28, Android NDK 16, Java 8. If you prefer + other versions of Android SDK, Android NDK, Java, then you can change + `ANDROID_PLATFORM` and `ANDROID_BUILD_TOOL_VERSION` in + `tools/build-amber-sample.sh`. +* Set up Android SDK path by running + `export ANDROID_SDK_HOME=path/to/Android/SDK` in your shell. +* Set up Android NDK path by running + `export ANDROID_NDK_HOME=path/to/Android/NDK` in your shell. +* Generate a KeyStore using `keytool` command and set up `KEY_STORE_PATH` + env variable for the KeyStore file path. +* Run `./tools/build-amber-sample.sh [build output directory path]`. + ### Optional Components Amber, by default, enables testing, SPIRV-Tools and Shaderc. Each of these can diff --git a/android_sample/AndroidManifest.xml b/android_sample/AndroidManifest.xml new file mode 100755 index 0000000..a6c1f9d --- /dev/null +++ b/android_sample/AndroidManifest.xml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright 2019 The Amber Authors. + +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 + + https://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. +--> +<!-- BEGIN_INCLUDE(manifest) --> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.google.amber"> + + <!-- This is the platform API where NativeActivity was introduced. --> + <uses-sdk /> + + <!-- This .apk has no Java code itself, so set hasCode to false. --> + <application android:label="@string/app_name" + android:hasCode="false" + android:theme="@android:style/Theme.NoTitleBar.Fullscreen"> + + <!-- Our activity is the built-in NativeActivity framework class. + This will take care of integrating with our NDK code. --> + <activity android:name="android.app.NativeActivity" + android:label="@string/app_name" + android:configChanges="orientation|keyboardHidden"> + <!-- Tell NativeActivity the name of or .so --> + <meta-data android:name="android.app.lib_name" + android:value="amber_android" /> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> + +</manifest> +<!-- END_INCLUDE(manifest) --> diff --git a/android_sample/CMakeLists.txt b/android_sample/CMakeLists.txt new file mode 100644 index 0000000..1853771 --- /dev/null +++ b/android_sample/CMakeLists.txt @@ -0,0 +1,53 @@ +# Copyright 2019 The Amber Authors. +# +# 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 +# +# https://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. + +cmake_minimum_required(VERSION 3.1) + +# build native_app_glue as a static lib +set(APP_GLUE_DIR ${ANDROID_NDK}/sources/android/native_app_glue) +include_directories(${APP_GLUE_DIR}) +add_library(app-glue STATIC + ${APP_GLUE_DIR}/android_native_app_glue.c) + +# build vulkan app +set(SRC_DIR jni) + +add_library(amber_android SHARED + ${SRC_DIR}/main.cc + ${SRC_DIR}/amber_script.cc) + +include_directories(${SRC_DIR}) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror \ + -DVK_USE_PLATFORM_ANDROID_KHR") +set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} \ + -u ANativeActivity_onCreate") + +# Begin: include Amber +set(AMBER_DIR ${CMAKE_SOURCE_DIR}/..) +set(AMBER_SKIP_TESTS TRUE) +set(AMBER_SKIP_SPIRV_TOOLS TRUE) +set(Vulkan_FOUND TRUE) +set(Dawn_FOUND FALSE) + +include_directories(${AMBER_DIR}/include) +message("Android Amber adds header path: ${AMBER_DIR}/include") +include_directories(${AMBER_DIR}) +message("Android Amber adds header path: ${AMBER_DIR}") + +add_subdirectory(${AMBER_DIR} amber_vulkan) +target_link_libraries(amber_android libamber vulkan) +# End: include Amber + +target_link_libraries(amber_android app-glue log android) diff --git a/android_sample/assets/amber/compute_ssbo.amber b/android_sample/assets/amber/compute_ssbo.amber new file mode 100644 index 0000000..5aa5942 --- /dev/null +++ b/android_sample/assets/amber/compute_ssbo.amber @@ -0,0 +1,54 @@ +# Copyright 2019 The Amber Authors. +# +# 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 +# +# https://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. + +[compute shader] +#version 430 + +layout(set = 0, binding = 0) buffer block0 { + float data_set0_binding0[3]; +}; + +layout(set = 1, binding = 2) buffer block1 { + float data_set1_binding2[3]; +}; + +layout(set = 2, binding = 1) buffer block2 { + float data_set2_binding1[3]; +}; + +layout(set = 2, binding = 3) buffer block3 { + float data_set2_binding3[3]; +}; + +void main() { + const uint index = gl_WorkGroupID.x; + data_set0_binding0[index] = data_set0_binding0[index] + 1.0f; + data_set1_binding2[index] = data_set2_binding1[index] - + data_set1_binding2[index]; + data_set2_binding1[index] = 10.0f * data_set2_binding3[index] + + data_set2_binding1[index]; + data_set2_binding3[index] = 30.0f * data_set2_binding3[index]; +} + +[test] +ssbo 0:0 subdata vec3 0 1.0 2.0 3.0 +ssbo 1:2 subdata vec3 0 4.0 5.0 6.0 +ssbo 2:1 subdata vec3 0 21.0 22.0 23.0 +ssbo 2:3 subdata vec3 0 0.7 0.8 0.9 +compute 3 1 1 + +probe ssbo vec3 0:0 0 ~= 2.0 3.0 4.0 +probe ssbo vec3 1:2 0 ~= 17.0 17.0 17.0 +probe ssbo vec3 2:1 0 ~= 28.0 30.0 32.0 +probe ssbo vec3 2:3 0 ~= 21.0 24.0 27.0 diff --git a/android_sample/assets/amber/compute_ssbo.amber.vk_shader_0.spv b/android_sample/assets/amber/compute_ssbo.amber.vk_shader_0.spv Binary files differnew file mode 100644 index 0000000..535357f --- /dev/null +++ b/android_sample/assets/amber/compute_ssbo.amber.vk_shader_0.spv diff --git a/android_sample/jni/amber_script.cc b/android_sample/jni/amber_script.cc new file mode 100644 index 0000000..2d00716 --- /dev/null +++ b/android_sample/jni/amber_script.cc @@ -0,0 +1,157 @@ +// Copyright 2019 The Amber Authors. +// +// 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. + +#include "amber_script.h" + +#include "src/make_unique.h" + +namespace amber { +namespace android { +namespace { + +const char kAmberDir[] = "amber/"; +const char kAmberScriptExtension[] = ".amber"; +const char kShaderNameSignature[] = ".vk_shader_"; +const char kShaderExtension[] = ".spv"; + +bool IsEndedWith(const std::string& path, const std::string& end) { + const size_t path_size = path.size(); + const size_t end_size = end.size(); + if (path_size < end_size) + return false; + + return path.compare(path_size - end_size, end_size, end) == 0; +} + +bool IsStartedWith(const std::string& path, const std::string& start) { + const size_t path_size = path.size(); + const size_t start_size = start.size(); + if (path_size < start_size) + return false; + + return path.compare(0, start_size, start) == 0; +} + +std::string GetShaderID(const std::string& shader_name) { + size_t spv_extension_pos = shader_name.find_last_of('.'); + if (spv_extension_pos == std::string::npos) + return std::string(); + + size_t shader_id_pos = + shader_name.find_last_of('.', spv_extension_pos - 1UL) + 1UL; + if (shader_id_pos == std::string::npos) + return std::string(); + + if (shader_id_pos >= spv_extension_pos || shader_name.size() <= shader_id_pos) + return std::string(); + + return shader_name.substr(shader_id_pos, spv_extension_pos - shader_id_pos); +} + +} // namespace + +AmberScriptLoader::AmberScriptLoader(android_app* app) : app_context_(app) {} + +AmberScriptLoader::~AmberScriptLoader() = default; + +Result AmberScriptLoader::LoadAllScriptsFromAsset() { + auto shader_names = FindAllScriptsAndReturnShaderNames(); + if (script_info_.empty()) + return Result("No Amber script found"); + + for (auto& info : script_info_) { + info.script_content = ReadScript(info.asset_name); + if (info.script_content.empty()) + return Result(info.asset_name + ":\n\tEmpty Amber script"); + } + + for (auto& info : script_info_) { + for (const auto& shader : shader_names) { + if (!IsStartedWith(shader, info.asset_name + kShaderNameSignature)) + continue; + + auto shader_content = ReadSpvShader(shader); + if (shader_content.empty()) + return Result(shader + ":\n\tEmpty shader"); + + auto id = GetShaderID(shader); + if (id.empty()) + return Result(shader + ":\n\tFail to get shader ID"); + + info.shader_map[id] = shader_content; + } + } + + return {}; +} + +std::vector<std::string> +AmberScriptLoader::FindAllScriptsAndReturnShaderNames() { + std::vector<std::string> shaders; + + AAssetDir* asset = + AAssetManager_openDir(app_context_->activity->assetManager, kAmberDir); + for (const char* file_name = AAssetDir_getNextFileName(asset); file_name; + file_name = AAssetDir_getNextFileName(asset)) { + std::string file_name_in_string(file_name); + if (IsEndedWith(file_name_in_string, kAmberScriptExtension)) { + script_info_.emplace_back(); + script_info_.back().asset_name = file_name_in_string; + } + + if (IsEndedWith(file_name_in_string, kShaderExtension)) + shaders.push_back(file_name_in_string); + } + AAssetDir_close(asset); + + return shaders; +} + +std::vector<uint8_t> AmberScriptLoader::ReadContent( + const std::string& asset_name) { + auto asset_path = kAmberDir + asset_name; + AAsset* asset = AAssetManager_open(app_context_->activity->assetManager, + asset_path.c_str(), AASSET_MODE_BUFFER); + if (!asset) + return std::vector<uint8_t>(); + + size_t size_in_bytes = AAsset_getLength(asset); + + // Allocate a memory chunk whose size in bytes is |size_in_bytes|. + std::vector<uint8_t> content(size_in_bytes); + + AAsset_read(asset, content.data(), size_in_bytes); + AAsset_close(asset); + + return content; +} + +std::string AmberScriptLoader::ReadScript(const std::string& script_name) { + auto content = ReadContent(script_name); + return std::string(reinterpret_cast<char*>(content.data())); +} + +std::vector<uint32_t> AmberScriptLoader::ReadSpvShader( + const std::string& shader_name) { + auto content = ReadContent(shader_name); + if (content.size() % sizeof(uint32_t) != 0) + return std::vector<uint32_t>(); + + return std::vector<uint32_t>( + reinterpret_cast<uint32_t*>(content.data()), + reinterpret_cast<uint32_t*>(content.data() + content.size())); +} + +} // namespace android +} // namespace amber diff --git a/android_sample/jni/amber_script.h b/android_sample/jni/amber_script.h new file mode 100644 index 0000000..495555b --- /dev/null +++ b/android_sample/jni/amber_script.h @@ -0,0 +1,75 @@ +// Copyright 2019 The Amber Authors. +// +// 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. + +#ifndef ANDROID_AMBER_SCRIPT_H_ +#define ANDROID_AMBER_SCRIPT_H_ + +#include <android_native_app_glue.h> +#include <memory> +#include <string> +#include <vector> + +#include "amber/amber.h" +#include "amber/result.h" + +namespace amber { +namespace android { + +struct AmberScriptInfo { + std::string asset_name; // Script asset name. Note it is not a + // path and just the name of script file. + std::string script_content; // Script itself from the script file. + amber::ShaderMap shader_map; +}; + +// A class to load scripts for Amber under assets/amber/ into +// |script_info_|. We assume that file extension of those scripts +// is ".amber" and all files with the extension are scripts for +// Amber. +class AmberScriptLoader { + public: + explicit AmberScriptLoader(android_app* app); + ~AmberScriptLoader(); + + Result LoadAllScriptsFromAsset(); + const std::vector<AmberScriptInfo>& GetScripts() const { + return script_info_; + } + + private: + // Find all files with ".amber" extension and set |asset_name| of + // |script_info_| as their names. In addition, return all shader + // file names that have ".spv" extensions. + std::vector<std::string> FindAllScriptsAndReturnShaderNames(); + + // Return content of script named |script_name| under + // assets/amber/ as a std::string. + std::string ReadScript(const std::string& script_name); + + // Return SPIRV binary of script named |shader_name| under + // assets/amber/ as a std::vector<uint32_t>. + std::vector<uint32_t> ReadSpvShader(const std::string& shader_name); + + // Return content of asset named |asset_name| under assets/amber/ + // as a std::vector<uint8_t>. + std::vector<uint8_t> ReadContent(const std::string& asset_name); + + android_app* app_context_ = nullptr; + std::vector<AmberScriptInfo> script_info_; +}; + +} // namespace android +} // namespace amber + +#endif // ANDROID_AMBER_SCRIPT_H_ diff --git a/android_sample/jni/main.cc b/android_sample/jni/main.cc new file mode 100644 index 0000000..77d3157 --- /dev/null +++ b/android_sample/jni/main.cc @@ -0,0 +1,106 @@ +// Copyright 2019 The Amber Authors. +// +// 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. + +#include <android/log.h> +#include <android_native_app_glue.h> + +#include "amber/amber.h" +#include "amber/recipe.h" +#include "amber/result.h" +#include "amber_script.h" + +namespace { + +// TODO(jaebaek): Change this as a method rather than macro. +// Android log function wrappers +const char* kTAG = "Amber"; +#define LOGE(...) \ + ((void)__android_log_print(ANDROID_LOG_ERROR, kTAG, __VA_ARGS__)) + +void amber_sample_main(android_app* app) { + amber::android::AmberScriptLoader loader(app); + + amber::Result r = loader.LoadAllScriptsFromAsset(); + if (!r.IsSuccess()) { + LOGE("%s", r.Error().c_str()); + return; + } + + const auto& script_info = loader.GetScripts(); + + std::vector<std::string> failures; + for (const auto& info : script_info) { + LOGE("\ncase %s: run...", info.asset_name.c_str()); + + amber::Amber am; + amber::Recipe recipe; + amber::Result r = am.Parse(info.script_content, &recipe); + if (!r.IsSuccess()) { + LOGE("\ncase %s: fail\n\t%s", info.asset_name.c_str(), r.Error().c_str()); + failures.push_back(info.asset_name); + continue; + } + + amber::Options amber_options; + r = am.ExecuteWithShaderData(&recipe, amber_options, info.shader_map); + if (!r.IsSuccess()) { + LOGE("\ncase %s: fail\n\t%s", info.asset_name.c_str(), r.Error().c_str()); + failures.push_back(info.asset_name); + continue; + } + + LOGE("\ncase %s: pass", info.asset_name.c_str()); + } + + if (!failures.empty()) { + LOGE("\nSummary of Failures:"); + for (const auto& failure : failures) + LOGE("%s", failure.c_str()); + } + LOGE("\nsummary: %u pass, %u fail", + static_cast<uint32_t>(script_info.size() - failures.size()), + static_cast<uint32_t>(failures.size())); +} + +// Process the next main command. +void handle_cmd(android_app* app, int32_t cmd) { + switch (cmd) { + case APP_CMD_INIT_WINDOW: + amber_sample_main(app); + break; + case APP_CMD_TERM_WINDOW: + break; + default: + break; + } +} + +} // namespace + +void android_main(struct android_app* app) { + // Set the callback to process system events + app->onAppCmd = handle_cmd; + + // Used to poll the events in the main loop + int events; + android_poll_source* source; + + // Main loop + while (app->destroyRequested == 0) { + if (ALooper_pollAll(1, nullptr, &events, (void**)&source) >= 0) { + if (source != NULL) + source->process(app, source); + } + } +} diff --git a/android_sample/res/values/strings.xml b/android_sample/res/values/strings.xml new file mode 100755 index 0000000..c34222d --- /dev/null +++ b/android_sample/res/values/strings.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright 2019 The Amber Authors. + +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 + + https://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. +--> +<resources> + <string name="app_name">AmberSample</string> +</resources> diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 67184d9..ad4aa2f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -100,8 +100,8 @@ if (${AMBER_ENABLE_TESTS}) add_executable(amber_unittests ${TEST_SRCS}) if (NOT MSVC) - target_compile_options(amber_unittests PRIVATE - -Wno-global-constructors) + target_compile_options(amber_unittests PRIVATE + -Wno-global-constructors) endif() target_include_directories(amber_unittests PRIVATE diff --git a/src/vulkan/CMakeLists.txt b/src/vulkan/CMakeLists.txt index aa8bc74..164cf0a 100644 --- a/src/vulkan/CMakeLists.txt +++ b/src/vulkan/CMakeLists.txt @@ -36,7 +36,9 @@ amber_default_compile_options(libamberenginevulkan) set_target_properties(libamberenginevulkan PROPERTIES OUTPUT_NAME "amberenginevulkan" ) -target_link_libraries(libamberenginevulkan ${VULKAN_LIB}) +if (NOT ANDROID) + target_link_libraries(libamberenginevulkan ${VULKAN_LIB}) +endif() if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") # vulkan/vulkan.h defines VK_NULL_HANDLE as 0u and that also serves as a null pointer. diff --git a/tools/build-amber-sample.sh b/tools/build-amber-sample.sh new file mode 100755 index 0000000..7d9fb0a --- /dev/null +++ b/tools/build-amber-sample.sh @@ -0,0 +1,120 @@ +#!/bin/bash + +# Copyright 2019 The Amber Authors. +# +# 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 +# +# https://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. + +set -x + +if [[ $1 == "" ]]; then + echo "Usage: $0 [build directory]" + exit 1 +fi + +BUILD_DIR=$(readlink -f $1) +if [[ $(ls $BUILD_DIR 2> /dev/null) == "" ]]; then + mkdir -p $BUILD_DIR +fi + +if [[ $ANDROID_SDK_HOME == "" ]]; then + echo "Error: ANDROID_SDK_HOME missing, please set env variable e.g.," + echo " $ export ANDROID_SDK_HOME=path/to/Android/SDK" + exit 1 +fi + +if [[ $ANDROID_NDK_HOME == "" ]]; then + echo "Error: ANDROID_NDK_HOME missing, please set env variable e.g.," + echo " $ export ANDROID_NDK_HOME=path/to/Android/NDK" + exit 1 +fi + +if [[ $(command -v javac) == "" ]]; then + echo "Error: Install Java. Recommended version is Java 8." + exit 1 +fi + +if [[ $KEY_STORE_PATH == "" ]]; then + echo "Error: KEY_STORE_PATH missing, please set env variable." + exit 1 +fi + +ANDROID_SOURCE_DIR=$(dirname $(readlink -f $0))/../android_sample + +APK_NAME=AmberSample.apk +ANDROID_PLATFORM=android-28 +ANDROID_BUILD_TOOL_VERSION=28.0.0 +ABI=arm64-v8a +BUILD_TYPE=Release + +AAPT=$ANDROID_SDK_HOME/build-tools/$ANDROID_BUILD_TOOL_VERSION/aapt +AAPT_ADD="$AAPT add" +AAPT_PACK="$AAPT package -f -I + $ANDROID_SDK_HOME/platforms/$ANDROID_PLATFORM/android.jar" + +DX="$ANDROID_SDK_HOME/build-tools/$ANDROID_BUILD_TOOL_VERSION/dx --dex" + +JAVAC="javac -classpath + $ANDROID_SDK_HOME/platforms/$ANDROID_PLATFORM/android.jar + -sourcepath $BUILD_DIR/gen -d $BUILD_DIR" + +mkdir -p $BUILD_DIR/gen $BUILD_DIR/output/lib/$ABI $BUILD_DIR/$BUILD_TYPE + +pushd $BUILD_DIR/$BUILD_TYPE +cmake \ + -DANDROID_ABI=$ABI \ + -DANDROID_PLATFORM=$ANDROID_PLATFORM \ + -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=$BUILD_DIR/output/lib/$ABI \ + -DCMAKE_BUILD_TYPE=$BUILD_TYPE \ + -DANDROID_NDK=$ANDROID_NDK_HOME \ + -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake \ + -DCMAKE_MAKE_PROGRAM=$(which ninja) \ + -GNinja \ + -DANDROID_TOOLCHAIN=clang \ + -DANDROID_STL=c++_static \ + $ANDROID_SOURCE_DIR +ninja +popd + +ANDROID_VULKAN=$ANDROID_NDK_HOME/sources/third_party/vulkan +for f in $(find $ANDROID_VULKAN/src/build-android/jniLibs/$ABI/ -name '*.so') +do + LINK=$BUILD_DIR/output/lib/$ABI/$(basename $f) + if [[ $(ls $LINK 2> /dev/null) == "" ]]; then + ln -s $f $LINK + fi +done + +$AAPT_PACK --non-constant-id -m \ + -M $ANDROID_SOURCE_DIR/AndroidManifest.xml \ + -S $ANDROID_SOURCE_DIR/res \ + -J $BUILD_DIR/gen/ \ + --generate-dependencies + +$AAPT_PACK -m \ + -M $ANDROID_SOURCE_DIR/AndroidManifest.xml \ + -A $ANDROID_SOURCE_DIR/assets \ + -S $ANDROID_SOURCE_DIR/res \ + -J "$BUILD_DIR/gen" \ + -F "$BUILD_DIR/$APK_NAME" \ + --shared-lib $BUILD_DIR/output + +$JAVAC $BUILD_DIR/gen/com/google/amber/*.java +$DX --output="$BUILD_DIR/classes.dex" $BUILD_DIR + +cd $BUILD_DIR +$AAPT_ADD $APK_NAME classes.dex + +$ANDROID_SDK_HOME/build-tools/$ANDROID_BUILD_TOOL_VERSION/apksigner sign \ +--min-sdk-version 28 --ks $KEY_STORE_PATH $APK_NAME + +echo "Successfully built $BUILD_DIR/$APK_NAME" |