Add support for GN to gradle config and remove cmake

This commit is contained in:
Attila Uygun 2023-08-29 12:54:06 +02:00
parent 9ff2e51ff1
commit a07d32e44a
5 changed files with 325 additions and 203 deletions

View File

@ -8,28 +8,49 @@ based on this engine. Full game code and assets are included in this repository.
## Pre-requisites:
**GN build system** is required for all platforms except Android:\
GN build system is required for all platforms:\
https://gn.googlesource.com/gn/
## Building from the command-line:
### All platforms except Android:
Setup:
#### Setup:
Generate build files for Ninja in release and debug modes.
```text
gn gen out/release
gn gen --args="is_debug=true" out/debug
gn gen --args='is_debug=true' out/debug
```
Building and running:
#### Building and running:
Build all games in release mode and run "hello_world".
```text
ninja -C out/debug
./out/debug/hello_world
ninja -C out/release
./out/release/hello_world
```
Build only "demo" in debug mode and run.
```text
ninja -C out/debug demo
./out/debug/demo
```
### Android:
Build the default game ("hello_world") in debug mode for all ABIs and install.
GN will be run by Gradle so no setup is required. Both Linux and Windows are
supported as host platforms. The Gradle project can also be
opened in Android Studio.
```text
cd build/android
./gradlew :app:installDebug
```
Build in release mode. The generated APK must be signed before installing.
```text
./gradlew :app:assembleRelease
```
Build configuration can be changed via project properties. The following command
will build "demo" in debug mode for x86_64 ABI and install. "targetArchs"
property can be set to any combination of Arm7, Arm8, X86_64, X86. Location of
gn and ninja executables can also be specified via "gn" and "ninja" properties.
```text
./gradlew :app:installDebug -PtargetArchs="X86_64" -PtargetGame="demo"
```
### Generate Visual Studio solution:
```text
gn.exe gen --args="is_debug=true" --ide=vs2022 out\vs
@ -53,7 +74,7 @@ devenv out\vs\all.sln
## Hello World example:
Shows a smoothly rotating "Hello Wolrd!".
Shows a smoothly rotating "Hello World!".
```cpp
class HelloWorld final : public eng::Game {
public:

View File

@ -1,173 +0,0 @@
cmake_minimum_required(VERSION 3.22.1)
# common_config
add_library(common_config INTERFACE)
target_compile_options(common_config INTERFACE
$<$<COMPILE_LANGUAGE:CXX>:-std=c++20>
#$<$<NOT:$<CONFIG:DEBUG>>:-Ofast>
-Wall
-Werror
-Wno-unused-but-set-variable
-Wno-deprecated-enum-enum-conversion
-Wno-unsequenced
-Wno-nullability-completeness
-Wno-unused-variable
)
target_compile_definitions(common_config INTERFACE
VK_USE_PLATFORM_ANDROID_KHR
VMA_STATIC_VULKAN_FUNCTIONS=1
$<$<CONFIG:DEBUG>:_DEBUG>
)
target_include_directories(common_config INTERFACE
../../../src
../../../src/third_party/glslang
../../../src/third_party/vulkan/include
)
# oboe
set (OBOE_DIR ../../../src/third_party/oboe)
add_subdirectory(${OBOE_DIR} ./oboe-bin)
# cpufeatures
add_library(cpufeatures STATIC ${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c)
target_include_directories(cpufeatures PUBLIC ${ANDROID_NDK}/sources/android/cpufeatures)
# native_app_glue
add_library(native_app_glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c)
target_include_directories(native_app_glue PUBLIC ${ANDROID_NDK}/sources/android/native_app_glue)
set_property(TARGET native_app_glue PROPERTY POSITION_INDEPENDENT_CODE ON)
# Export ANativeActivity_onCreate(),
# Refer to: https://github.com/android-ndk/ndk/issues/381.
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate")
# kaliber
project(kaliber)
add_library(kaliber SHARED
../../../src/base/collusion_test.cc
../../../src/base/log.cc
../../../src/base/mem.cc
../../../src/base/task_runner.cc
../../../src/base/thread_pool.cc
../../../src/demo/credits.cc
../../../src/demo/demo.cc
../../../src/demo/enemy.cc
../../../src/demo/hud.cc
../../../src/demo/menu.cc
../../../src/demo/player.cc
../../../src/demo/sky_quad.cc
../../../src/engine/animatable.cc
../../../src/engine/animator.cc
../../../src/engine/asset/font.cc
../../../src/engine/asset/image.cc
../../../src/engine/asset/mesh.cc
../../../src/engine/asset/shader_source.cc
../../../src/engine/asset/sound.cc
../../../src/engine/audio/audio_bus.cc
../../../src/engine/audio/audio_mixer.cc
../../../src/engine/audio/audio_sink_oboe.cc
../../../src/engine/audio/mixer_input.cc
../../../src/engine/audio/sinc_resampler.cc
../../../src/engine/drawable.cc
../../../src/engine/engine.cc
../../../src/engine/image_quad.cc
../../../src/engine/persistent_data.cc
../../../src/engine/platform/asset_file_android.cc
../../../src/engine/platform/asset_file.cc
../../../src/engine/platform/platform_android.cc
../../../src/engine/renderer/geometry.cc
../../../src/engine/renderer/opengl/renderer_opengl_android.cc
../../../src/engine/renderer/opengl/renderer_opengl.cc
../../../src/engine/renderer/renderer_types.cc
../../../src/engine/renderer/shader.cc
../../../src/engine/renderer/texture.cc
../../../src/engine/renderer/vulkan/renderer_vulkan_android.cc
../../../src/engine/renderer/vulkan/renderer_vulkan.cc
../../../src/engine/renderer/vulkan/vulkan_context_android.cc
../../../src/engine/renderer/vulkan/vulkan_context.cc
../../../src/engine/solid_quad.cc
../../../src/engine/sound_player.cc
../../../src/third_party/android/gl3stub.c
../../../src/third_party/android/GLContext.cpp
../../../src/third_party/glslang/glslang/GenericCodeGen/CodeGen.cpp
../../../src/third_party/glslang/glslang/GenericCodeGen/Link.cpp
../../../src/third_party/glslang/glslang/MachineIndependent/attribute.cpp
../../../src/third_party/glslang/glslang/MachineIndependent/Constant.cpp
../../../src/third_party/glslang/glslang/MachineIndependent/glslang_tab.cpp
../../../src/third_party/glslang/glslang/MachineIndependent/InfoSink.cpp
../../../src/third_party/glslang/glslang/MachineIndependent/Initialize.cpp
../../../src/third_party/glslang/glslang/MachineIndependent/Intermediate.cpp
../../../src/third_party/glslang/glslang/MachineIndependent/intermOut.cpp
../../../src/third_party/glslang/glslang/MachineIndependent/IntermTraverse.cpp
../../../src/third_party/glslang/glslang/MachineIndependent/iomapper.cpp
../../../src/third_party/glslang/glslang/MachineIndependent/limits.cpp
../../../src/third_party/glslang/glslang/MachineIndependent/linkValidate.cpp
../../../src/third_party/glslang/glslang/MachineIndependent/parseConst.cpp
../../../src/third_party/glslang/glslang/MachineIndependent/ParseContextBase.cpp
../../../src/third_party/glslang/glslang/MachineIndependent/ParseHelper.cpp
../../../src/third_party/glslang/glslang/MachineIndependent/PoolAlloc.cpp
../../../src/third_party/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp
../../../src/third_party/glslang/glslang/MachineIndependent/preprocessor/PpAtom.cpp
../../../src/third_party/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp
../../../src/third_party/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp
../../../src/third_party/glslang/glslang/MachineIndependent/preprocessor/PpTokens.cpp
../../../src/third_party/glslang/glslang/MachineIndependent/propagateNoContraction.cpp
../../../src/third_party/glslang/glslang/MachineIndependent/reflection.cpp
../../../src/third_party/glslang/glslang/MachineIndependent/RemoveTree.cpp
../../../src/third_party/glslang/glslang/MachineIndependent/Scan.cpp
../../../src/third_party/glslang/glslang/MachineIndependent/ShaderLang.cpp
../../../src/third_party/glslang/glslang/MachineIndependent/SpirvIntrinsics.cpp
../../../src/third_party/glslang/glslang/MachineIndependent/SymbolTable.cpp
../../../src/third_party/glslang/glslang/MachineIndependent/Versions.cpp
../../../src/third_party/glslang/glslang/OSDependent/Unix/ossource.cpp
../../../src/third_party/glslang/OGLCompilersDLL/InitializeDll.cpp
../../../src/third_party/glslang/SPIRV/disassemble.cpp
../../../src/third_party/glslang/SPIRV/doc.cpp
../../../src/third_party/glslang/SPIRV/GlslangToSpv.cpp
../../../src/third_party/glslang/SPIRV/InReadableOrder.cpp
../../../src/third_party/glslang/SPIRV/Logger.cpp
../../../src/third_party/glslang/SPIRV/SpvBuilder.cpp
../../../src/third_party/glslang/SPIRV/SpvPostProcess.cpp
../../../src/third_party/glslang/SPIRV/SPVRemapper.cpp
../../../src/third_party/glslang/SPIRV/SpvTools.cpp
../../../src/third_party/jsoncpp/jsoncpp.cpp
../../../src/third_party/minimp3/minimp3.cc
../../../src/third_party/minizip/ioapi.c
../../../src/third_party/minizip/unzip.c
../../../src/third_party/spirv-reflect/spirv_reflect.c
../../../src/third_party/stb/stb_image.cc
../../../src/third_party/texture_compressor/dxt_encoder_internals.cc
../../../src/third_party/texture_compressor/dxt_encoder.cc
../../../src/third_party/texture_compressor/texture_compressor_etc1.cc
../../../src/third_party/texture_compressor/texture_compressor.cc
../../../src/third_party/vma/vk_mem_alloc.cpp
../../../src/third_party/volk/volk.c
)
if (ANDROID_ABI STREQUAL armeabi-v7a)
target_sources(kaliber PRIVATE ../../../src/third_party/texture_compressor/dxt_encoder_neon.cc)
target_sources(kaliber PRIVATE ../../../src/third_party/texture_compressor/texture_compressor_etc1_neon.cc)
set_source_files_properties(../../../src/third_party/texture_compressor/dxt_encoder_neon.cc PROPERTIES COMPILE_FLAGS -mfpu=neon)
set_source_files_properties(../../../src/third_party/texture_compressor/texture_compressor_etc1_neon.cc PROPERTIES COMPILE_FLAGS -mfpu=neon)
endif()
if (ANDROID_ABI STREQUAL arm64-v8a)
target_sources(kaliber PRIVATE ../../../src/third_party/texture_compressor/dxt_encoder_neon.cc)
target_sources(kaliber PRIVATE ../../../src/third_party/texture_compressor/texture_compressor_etc1_neon.cc)
endif()
target_link_libraries(kaliber PRIVATE
common_config
android
native_app_glue
oboe
cpufeatures
EGL
GLESv2
log
z
)

View File

@ -1,20 +1,103 @@
@CacheableTask
abstract class WriteFileTask extends DefaultTask {
@Input
abstract Property<String> getContent()
@OutputFile
abstract RegularFileProperty getTarget()
@TaskAction
void run() {
def file = target.get().asFile
file.parentFile.mkdirs()
def text = content.get()
if (!file.exists() || text != file.text)
file.text = text
}
}
class Utils implements Plugin<Project> {
final def BUILD_TYPES = ['Debug', 'Release'].asImmutable()
final def BUILD_TYPES_REG_EXP = BUILD_TYPES.join('|')
final def ABI_CODES = ["Arm7": "armeabi-v7a",
"Arm8": "arm64-v8a",
"X86_64": "x86_64",
"X86": "x86"].asImmutable()
final def CPU_CODES = ["Arm7": "arm",
"Arm8": "arm64",
"X86_64": "x64",
"X86": "x86"].asImmutable()
def project
@Inject
Utils(Project project) {
this.project = project
}
void apply(Project project) {
project.extensions.create('utils', Utils)
}
void addTask(String prefix, Closure taskClosure) {
forEachBuildVariant { String arch, String buildType ->
def taskName = "${prefix}${arch}${buildType}"
taskClosure(taskName, buildType, arch)
}
}
void forEachBuildVariant(Closure callback) {
project.rootProject.ext.targetArchs.each { arch ->
BUILD_TYPES.each { buildType ->
callback(arch, buildType)
}
}
}
}
def generateGnArgsContent(String buildType, String arch) {
def content = 'target_os="android"\n'
content += 'target_cpu="' + utils.CPU_CODES[arch] + '"\n'
content += "is_debug=${buildType != 'Release'}\n"
content += 'ndk="' + android.ndkDirectory + '"\n'
content += "ndk_api=${rootProject.ext.minSdk}\n"
return content
}
def getOutDir(String buildType) {
return "${project.buildDir}/gn_out/${buildType.toLowerCase()}"
}
def getAssetsDir(String buildType) {
return "${project.buildDir}/gn_out/${buildType.toLowerCase()}/assets"
}
def getJniLibsDir(String buildType) {
return "${project.buildDir}/gn_out/jniLibs/${buildType.toLowerCase()}"
}
apply plugin: 'com.android.application'
apply plugin: Utils
rootProject.ext.targetArchs.each { arch ->
assert utils.ABI_CODES.containsKey(arch)
assert utils.CPU_CODES.containsKey(arch)
}
android {
compileSdk 33
ndkVersion '25.2.9519653'
compileSdk rootProject.ext.compileSdk
ndkVersion rootProject.ext.ndkVersion
defaultConfig {
applicationId = 'com.woom.game'
minSdk 24
targetSdk 33
externalNativeBuild {
cmake {
arguments '-DANDROID_STL=c++_static'
}
}
applicationId rootProject.ext.applicationId
minSdk rootProject.ext.minSdk
targetSdk rootProject.ext.targetSdk
ndk {
abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64'
abiFilters = []
rootProject.ext.targetArchs.each { arch ->
abiFilters.add(utils.ABI_CODES[arch])
}
}
}
buildTypes {
@ -22,24 +105,24 @@ android {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
ndk {
debugSymbolLevel 'FULL'
}
}
}
externalNativeBuild {
cmake {
version '3.22.1'
path 'CMakeLists.txt'
}
}
sourceSets {
main {
java.srcDirs += ['../../../src/engine/platform/java/com/kaliber/base']
assets.srcDirs = ['../../../assets']
utils.BUILD_TYPES.each { buildType ->
"${buildType.toLowerCase()}" {
assets.srcDirs = [getAssetsDir(buildType)]
}
}
namespace 'com.woom.game'
}
utils.BUILD_TYPES.each { buildType ->
"${buildType.toLowerCase()}" {
jniLibs.srcDirs = [getJniLibsDir(buildType)]
}
}
}
namespace rootProject.ext.applicationId
}
dependencies {
@ -48,3 +131,79 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'com.google.android.gms:play-services-ads:22.0.0'
}
utils.addTask('generateGnArgsFor') { String taskName, String buildType, String arch ->
task(taskName, type: WriteFileTask) {
content = generateGnArgsContent(buildType, arch)
target = project.layout.file(provider { new File("${getOutDir(buildType)}/${utils.ABI_CODES[arch]}", 'args.gn') })
}
}
utils.addTask('runGnFor') { String taskName, String buildType, String arch ->
task(taskName, type: Exec) {
dependsOn "generateGnArgsFor${arch}${buildType}"
executable rootProject.ext.gn
args '--fail-on-unused-args', 'gen', "${getOutDir(buildType)}/${utils.ABI_CODES[arch]}"
inputs.file(new File("${getOutDir(buildType)}/${utils.ABI_CODES[arch]}", 'args.gn'))
outputs.file(new File("${getOutDir(buildType)}/${utils.ABI_CODES[arch]}", 'build.ninja'))
}
}
utils.addTask('runNinjaFor') { String taskName, String buildType, String arch ->
task(taskName, type: Exec) {
dependsOn "runGnFor${arch}${buildType}"
executable rootProject.ext.ninja
args '-C', "${getOutDir(buildType)}/${utils.ABI_CODES[arch]}", rootProject.ext.targetGame
inputs.file(new File("${getOutDir(buildType)}/${utils.ABI_CODES[arch]}", 'build.ninja'))
outputs.file(new File("${getOutDir(buildType)}/${utils.ABI_CODES[arch]}", "lib${rootProject.ext.targetGame}.so"))
}
}
utils.addTask('copyAssetsFor') { String taskName, String buildType, String arch ->
task(taskName, type: Copy) {
dependsOn "runNinjaFor${arch}${buildType}"
from "${getOutDir(buildType)}/${utils.ABI_CODES[arch]}/assets"
into getAssetsDir(buildType)
}
}
utils.addTask('copyJniLibsFor') { String taskName, String buildType, String arch ->
task(taskName, type: Copy) {
dependsOn "runNinjaFor${arch}${buildType}"
from("${getOutDir(buildType)}/${utils.ABI_CODES[arch]}") {
include "lib${rootProject.ext.targetGame}.so"
rename "lib${rootProject.ext.targetGame}.so", "libkaliber.so"
}
into "${getJniLibsDir(buildType)}/${utils.ABI_CODES[arch]}"
}
}
tasks.configureEach { task ->
def match = task.name =~ /^merge(${utils.BUILD_TYPES_REG_EXP})JniLibFolders$/
if (match) {
rootProject.ext.targetArchs.each { arch ->
task.dependsOn "copyJniLibsFor${arch}${match.group(1)}"
return
}
}
match = task.name =~ /^merge(${utils.BUILD_TYPES_REG_EXP})Assets$/
if (match) {
rootProject.ext.targetArchs.each { arch ->
task.dependsOn "copyAssetsFor${arch}${match.group(1)}"
return
}
}
match = task.name =~ /^lintVitalAnalyze(${utils.BUILD_TYPES_REG_EXP})$/
if (match) {
rootProject.ext.targetArchs.each { arch ->
task.dependsOn "copyAssetsFor${arch}${match.group(1)}"
return
}
}
}

View File

@ -19,3 +19,29 @@ allprojects {
task clean(type: Delete) {
delete rootProject.buildDir
}
ext {
if (!project.hasProperty('targetGame')) {
targetGame = "hello_world"
}
if (!project.hasProperty('targetArchs')) {
targetArchs = ['Arm7', 'Arm8', 'X86_64', 'X86']
} else {
targetArchs = project.getProperty('targetArchs').split(',')
}
applicationId = 'com.woom.game'
ndkVersion = '25.2.9519653'
minSdk = 24
compileSdk = 33
targetSdk = 33
if (!project.hasProperty('gn')) {
gn = "gn"
}
if (!project.hasProperty('ninja')) {
ninja = "ninja"
}
}

89
build/android/gradlew.bat vendored Normal file
View File

@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega