From 9ff2e51ff10cbbdb1fe90a5c968e6dcceffecc2c Mon Sep 17 00:00:00 2001 From: Attila Uygun Date: Thu, 17 Aug 2023 18:05:42 +0200 Subject: [PATCH] Add support for Android build to GN config --- BUILD.gn | 2 +- assets/BUILD.gn | 1 - build/BUILD.gn | 50 ++++++++++++++++- build/BUILDCONFIG.gn | 48 +++++++++++++++- build/toolchain/{msvc => }/copy.py | 42 +++++++------- build/toolchain/gcc/BUILD.gn | 56 +++++++++++-------- build/toolchain/msvc/BUILD.gn | 2 +- build/utils.gni | 11 ++++ src/demo/BUILD.gn | 5 +- src/engine/BUILD.gn | 20 +++++++ src/hello_world/BUILD.gn | 5 +- src/third_party/BUILD.gn | 89 +++++++++++++++++++++++++++++- 12 files changed, 272 insertions(+), 59 deletions(-) rename build/toolchain/{msvc => }/copy.py (94%) create mode 100644 build/utils.gni diff --git a/BUILD.gn b/BUILD.gn index edaf7e1..5ef5a75 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1,4 +1,4 @@ -group("kaliber") { +group("all") { deps = [ "//src/demo", "//src/hello_world", diff --git a/assets/BUILD.gn b/assets/BUILD.gn index aee3ea6..9fccc17 100644 --- a/assets/BUILD.gn +++ b/assets/BUILD.gn @@ -6,7 +6,6 @@ copy("assets") { "Boss_ok_lvl2.png", "Boss_ok_lvl3.png", "Boss_ok.png", - "BUILD.gn", "chromatic_aberration.glsl_fragment", "chromatic_aberration.glsl_vertex", "enemy_anims_01_frames_ok.png", diff --git a/build/BUILD.gn b/build/BUILD.gn index 54be4d1..e3f7849 100644 --- a/build/BUILD.gn +++ b/build/BUILD.gn @@ -54,9 +54,9 @@ config("default") { # ] if (is_linux) { - # cflags += [ - # "-fPIC", # Emit position-independent code suitable for dynamic linking. - # ] + cflags += [ + "-fPIC", # Emit position-independent code suitable for dynamic linking. + ] libs = [ "pthread", # Use the POSIX thread library. ] @@ -74,6 +74,12 @@ config("default") { "-target", "arm64-apple-macos11", ] + } else if (is_android) { + cflags += [ + "--sysroot=$ndk/toolchains/llvm/prebuilt/$ndk_host/sysroot", + "-fPIC", # Emit position-independent code suitable for dynamic linking. + ] + ldflags = [ "-static-libstdc++" ] } } @@ -82,6 +88,13 @@ config("default") { # "//", "//src", ] + if (is_android) { + include_dirs += [ + "$ndk/sources/android", + "$ndk/sources/android/native_app_glue", + "$ndk/sources/android/cpufeatures", + ] + } } config("debug") { @@ -191,9 +204,11 @@ config("warnings") { "/wd4191", # 'type cast': unsafe conversion "/wd4244", # conversion, possible loss of data. 'int' to 'float' "/wd4245", # tmp:conversion from 'int' to 'const unsigned int' + # "/wd4267", # conversion, possible loss of data. "/wd4305", # truncation from 'double' to 'float'. "/wd4365", # conversion, signed/unsigned mismatch. + # "/wd5219", # conversion, possible loss of data. 'int' to 'float' "/wd4722", # destructor never returns, potential memory leak "/wd4702", # unreachable code @@ -260,6 +275,7 @@ config("warnings") { # Disable the following warnings: "-Wno-unused-parameter", + "-Wno-sign-compare", ] } } @@ -291,6 +307,34 @@ config("executable") { } } +config("shared_library") { + if (is_android) { + ldflags = [ + "-Wl,--build-id=sha1", + "-Wl,--no-rosegment", + "-Wl,--fatal-warnings", + "-Wl,--no-undefined", + "-Qunused-arguments", + "-u ANativeActivity_onCreate", + ] + } else if (is_linux) { + ldflags = [ + "-Wl,-rpath,\$ORIGIN", # Add directory to runtime library search path. + ] + } else if (is_mac) { + ldflags = [ "-Wl,-rpath,@loader_path/." ] + } else if (is_win) { + ldflags = [ + "/DYNAMICBASE", # Use address space layout randomization. + "/INCREMENTAL:NO", # Incremental linking interferes with both ninja and + # release optimizations. + + # Leave the target architecture to environment settings. + # "/MACHINE:X64", + ] + } +} + # TODO: This needs some more investigation. # Is it possible to avoid setting it and rely on defaults? # Some tools will be console apps while games will be gui apps. diff --git a/build/BUILDCONFIG.gn b/build/BUILDCONFIG.gn index 438e41d..1618af7 100644 --- a/build/BUILDCONFIG.gn +++ b/build/BUILDCONFIG.gn @@ -1,5 +1,14 @@ declare_args() { is_debug = false + + # Note that this uses the 'cc' and 'c++' links that should map to GCC on linux + # systems and clang on macs. + ar = "ar" + cc = "cc" + cxx = "c++" + + ndk = "" + ndk_api = 24 } # Platform detection @@ -21,9 +30,6 @@ is_desktop = is_mac || is_linux || is_win is_mobile = is_android || is_ios is_unix = is_android || is_linux -# Optional build components -have_vulkan = false - if (target_cpu == "") { if (is_mobile) { target_cpu = "arm64" @@ -38,6 +44,42 @@ if (current_cpu == "") { current_cpu = target_cpu } +if (is_android) { + assert(ndk != "", "NDK path argument is empty") + + ndk_host = "" + ndk_target = "" + + if (host_os == "linux") { + ndk_host = "linux-x86_64" + } else if (host_os == "mac") { + ndk_host = "darwin-x86_64" + } else if (host_os == "win") { + ndk_host = "windows-x86_64" + } + + if (target_cpu == "arm64") { + ndk_target = "aarch64-linux-android" + } else if (target_cpu == "arm") { + ndk_target = "armv7a-linux-androideabi" + } else if (target_cpu == "x64") { + ndk_target = "x86_64-linux-android" + } else if (target_cpu == "x86") { + ndk_target = "i686-linux-android" + } + + _prefix = "$ndk/toolchains/llvm/prebuilt/$ndk_host/bin" + if (host_os == "win") { + ar = "$_prefix/llvm-ar.exe" + cc = "$_prefix/clang.exe --target=$ndk_target$ndk_api -fno-addrsig" + cxx = "$_prefix/clang++.exe --target=$ndk_target$ndk_api -fno-addrsig" + } else { + ar = "$_prefix/llvm-ar" + cc = "$_prefix/$ndk_target$ndk_api-clang" + cxx = "$_prefix/$ndk_target$ndk_api-clang++" + } +} + # Set defaults _default_config = [ "//build:default", diff --git a/build/toolchain/msvc/copy.py b/build/toolchain/copy.py similarity index 94% rename from build/toolchain/msvc/copy.py rename to build/toolchain/copy.py index fbf79f1..baabed9 100644 --- a/build/toolchain/msvc/copy.py +++ b/build/toolchain/copy.py @@ -1,21 +1,21 @@ -#!/usr/bin/env python - -import os -import shutil -import sys - -src, dst = sys.argv[1:] - -if os.path.exists(dst): - if os.path.isdir(dst): - shutil.rmtree(dst) - else: - os.remove(dst) - -if os.path.isdir(src): - shutil.copytree(src, dst) -else: - shutil.copy2(src, dst) - - # https://github.com/ninja-build/ninja/issues/1554 - os.utime(dst, None) +#!/usr/bin/env python + +import os +import shutil +import sys + +src, dst = sys.argv[1:] + +if os.path.exists(dst): + if os.path.isdir(dst): + shutil.rmtree(dst) + else: + os.remove(dst) + +if os.path.isdir(src): + shutil.copytree(src, dst) +else: + shutil.copy2(src, dst) + + # https://github.com/ninja-build/ninja/issues/1554 + os.utime(dst, None) diff --git a/build/toolchain/gcc/BUILD.gn b/build/toolchain/gcc/BUILD.gn index 6c323e4..fbf0a60 100644 --- a/build/toolchain/gcc/BUILD.gn +++ b/build/toolchain/gcc/BUILD.gn @@ -1,16 +1,10 @@ -# Note that this uses the 'cc' and 'c++' environment variables or links that -# should map to GCC on linux systems and clang on macs. - -# This also means that you can install clang or another compiler and it should -# automatically use that instead. - toolchain("gcc") { lib_switch = "-l" lib_dir_switch = "-L" tool("asm") { depfile = "{{output}}.d" - command = "cc -MD -MF $depfile {{defines}} {{include_dirs}} {{asmflags}} -c {{source}} -o {{output}}" + command = "$cc -MD -MF $depfile {{defines}} {{include_dirs}} {{asmflags}} -c {{source}} -o {{output}}" depsformat = "gcc" outputs = [ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" ] @@ -19,7 +13,7 @@ toolchain("gcc") { tool("cc") { depfile = "{{output}}.d" - command = "cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}" + command = "$cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}" depsformat = "gcc" outputs = [ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" ] @@ -28,7 +22,7 @@ toolchain("gcc") { tool("cxx") { depfile = "{{output}}.d" - command = "c++ -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -c {{source}} -o {{output}}" + command = "$cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -c {{source}} -o {{output}}" depsformat = "gcc" outputs = [ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" ] @@ -37,7 +31,7 @@ toolchain("gcc") { tool("objc") { depfile = "{{output}}.d" - command = "cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{framework_dirs}} {{cflags}} {{cflags_c}} {{cflags_objc}} -c {{source}} -o {{output}}" + command = "$cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{framework_dirs}} {{cflags}} {{cflags_c}} {{cflags_objc}} -c {{source}} -o {{output}}" depsformat = "gcc" outputs = [ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" ] @@ -46,7 +40,7 @@ toolchain("gcc") { tool("objcxx") { depfile = "{{output}}.d" - command = "c++ -MMD -MF $depfile {{defines}} {{include_dirs}} {{framework_dirs}} {{cflags}} {{cflags_cc}} {{cflags_objcc}} -c {{source}} -o {{output}}" + command = "$cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{framework_dirs}} {{cflags}} {{cflags_cc}} {{cflags_objcc}} -c {{source}} -o {{output}}" depsformat = "gcc" outputs = [ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" ] @@ -62,7 +56,7 @@ toolchain("gcc") { command = "libtool -static -o {{output}} -no_warning_for_no_symbols {{inputs}}" } else { - command = "rm -f {{output}} && ar rcs {{output}} {{inputs}}" + command = "rm -f {{output}} && $ar rcs {{output}} {{inputs}}" } outputs = [ "{{target_out_dir}}/{{target_output_name}}{{output_extension}}" ] @@ -82,7 +76,7 @@ toolchain("gcc") { os_specific_option = "-Wl,-soname=$soname" rspfile_content = "-Wl,--whole-archive {{inputs}} {{solibs}} -Wl,--no-whole-archive {{libs}}" } - command = "c++ -shared {{ldflags}} {{frameworks}} -o $sofile $os_specific_option @$rspfile" + command = "$cxx -shared {{ldflags}} {{frameworks}} -o $sofile $os_specific_option @$rspfile" default_output_extension = ".so" default_output_dir = "{{root_out_dir}}" outputs = [ sofile ] @@ -97,22 +91,40 @@ toolchain("gcc") { rspfile = "$outfile.rsp" rspfile_content = "{{inputs}}" if (is_apple) { - command = "c++ {{ldflags}} {{solibs}} {{libs}} {{frameworks}} -o $outfile @$rspfile" + command = "$cxx {{ldflags}} {{solibs}} {{libs}} {{frameworks}} -o $outfile @$rspfile" } else { - command = "c++ {{ldflags}} -o $outfile -Wl,--start-group @$rspfile {{solibs}} -Wl,--end-group {{libs}}" + command = "$cxx {{ldflags}} -o $outfile -Wl,--start-group @$rspfile {{solibs}} -Wl,--end-group {{libs}}" } default_output_dir = "{{root_out_dir}}" outputs = [ outfile ] description = "link $outfile" } - tool("stamp") { - command = "touch {{output}}" - description = "stamp {{output}}" - } + if (host_os == "win") { + tool("stamp") { + command = "cmd.exe /c echo > {{output}}" + description = "stamp {{output}}" + } - tool("copy") { - command = "cp -af {{source}} {{output}}" - description = "copy {{source}} {{output}}" + tool("copy") { + # Note: The build in copy command can't handle forward slashes as path separators. + # Use a python script as a work around. + # command = "cmd.exe /c copy /Y {{source}} {{output}}" + + copy_cmd = rebase_path("../copy.py") + command = "python \"$copy_cmd\" {{source}} {{output}}" + + description = "copy {{source}} {{output}}" + } + } else { + tool("stamp") { + command = "touch {{output}}" + description = "stamp {{output}}" + } + + tool("copy") { + command = "cp -af {{source}} {{output}}" + description = "copy {{source}} {{output}}" + } } } diff --git a/build/toolchain/msvc/BUILD.gn b/build/toolchain/msvc/BUILD.gn index 8c4a07f..929c8d1 100644 --- a/build/toolchain/msvc/BUILD.gn +++ b/build/toolchain/msvc/BUILD.gn @@ -82,7 +82,7 @@ toolchain("msvc") { # Use a python script as a work around. # command = "cmd.exe /c copy /Y {{source}} {{output}}" - copy_cmd = rebase_path("copy.py") + copy_cmd = rebase_path("../copy.py") command = "python \"$copy_cmd\" {{source}} {{output}}" description = "copy {{source}} {{output}}" diff --git a/build/utils.gni b/build/utils.gni new file mode 100644 index 0000000..ce93dda --- /dev/null +++ b/build/utils.gni @@ -0,0 +1,11 @@ +# Build a shared library for Android. Build an executable for other platforms. +template("game_tmpl") { + if (target_os == "android") { + _target_type = "shared_library" + } else { + _target_type = "executable" + } + target(_target_type, target_name) { + forward_variables_from(invoker, "*") + } +} diff --git a/src/demo/BUILD.gn b/src/demo/BUILD.gn index c399e49..391b13e 100644 --- a/src/demo/BUILD.gn +++ b/src/demo/BUILD.gn @@ -1,4 +1,6 @@ -executable("demo") { +import("//build/utils.gni") + +game_tmpl("demo") { sources = [ "credits.cc", "credits.h", @@ -16,7 +18,6 @@ executable("demo") { "sky_quad.cc", "sky_quad.h", ] - deps = [ "//assets", "//src/base", diff --git a/src/engine/BUILD.gn b/src/engine/BUILD.gn index 21efc8e..357f1eb 100644 --- a/src/engine/BUILD.gn +++ b/src/engine/BUILD.gn @@ -98,6 +98,26 @@ source_set("engine") { ] } + if (target_os == "android") { + sources += [ + "audio/audio_sink_oboe.cc", + "audio/audio_sink_oboe.h", + "platform/asset_file_android.cc", + "platform/platform_android.cc", + "renderer/opengl/renderer_opengl_android.cc", + "renderer/vulkan/renderer_vulkan_android.cc", + "renderer/vulkan/vulkan_context_android.cc", + ] + + libs += [ + "android", + "EGL", + "GLESv2", + "log", + "z", + ] + } + deps = [ "//assets/engine", "//src/base", diff --git a/src/hello_world/BUILD.gn b/src/hello_world/BUILD.gn index 29e1bea..bb0c99d 100644 --- a/src/hello_world/BUILD.gn +++ b/src/hello_world/BUILD.gn @@ -1,6 +1,7 @@ -executable("hello_world") { - sources = [ "hello_world.cc" ] +import("//build/utils.gni") +game_tmpl("hello_world") { + sources = [ "hello_world.cc" ] deps = [ "//src/base", "//src/engine", diff --git a/src/third_party/BUILD.gn b/src/third_party/BUILD.gn index 2ccd775..99b8c77 100644 --- a/src/third_party/BUILD.gn +++ b/src/third_party/BUILD.gn @@ -6,10 +6,11 @@ config("third_party_config") { if (target_os == "linux") { defines = [ "VK_USE_PLATFORM_XLIB_KHR" ] - } - - if (target_os == "win") { + } else if (target_os == "win") { defines = [ "VK_USE_PLATFORM_WIN32_KHR" ] + } else if (target_os == "android") { + defines = [ "VK_USE_PLATFORM_ANDROID_KHR" ] + include_dirs += [ "oboe/include" ] } } @@ -111,6 +112,88 @@ source_set("third_party") { ] } + if (target_os == "android") { + sources += [ + "$ndk/sources/android/cpufeatures/cpu-features.c", + "$ndk/sources/android/native_app_glue/android_native_app_glue.c", + "android/GLContext.cpp", + "android/gl3stub.c", + "glslang/glslang/OSDependent/Unix/ossource.cpp", + "minizip/ioapi.c", + "minizip/unzip.c", + "oboe/src/aaudio/AAudioLoader.cpp", + "oboe/src/aaudio/AudioStreamAAudio.cpp", + "oboe/src/common/AudioSourceCaller.cpp", + "oboe/src/common/AudioStream.cpp", + "oboe/src/common/AudioStreamBuilder.cpp", + "oboe/src/common/DataConversionFlowGraph.cpp", + "oboe/src/common/FilterAudioStream.cpp", + "oboe/src/common/FixedBlockAdapter.cpp", + "oboe/src/common/FixedBlockReader.cpp", + "oboe/src/common/FixedBlockWriter.cpp", + "oboe/src/common/LatencyTuner.cpp", + "oboe/src/common/OboeExtensions.cpp", + "oboe/src/common/QuirksManager.cpp", + "oboe/src/common/SourceFloatCaller.cpp", + "oboe/src/common/SourceI16Caller.cpp", + "oboe/src/common/SourceI24Caller.cpp", + "oboe/src/common/SourceI32Caller.cpp", + "oboe/src/common/StabilizedCallback.cpp", + "oboe/src/common/Trace.cpp", + "oboe/src/common/Utilities.cpp", + "oboe/src/common/Version.cpp", + "oboe/src/fifo/FifoBuffer.cpp", + "oboe/src/fifo/FifoController.cpp", + "oboe/src/fifo/FifoControllerBase.cpp", + "oboe/src/fifo/FifoControllerIndirect.cpp", + "oboe/src/flowgraph/ChannelCountConverter.cpp", + "oboe/src/flowgraph/ClipToRange.cpp", + "oboe/src/flowgraph/FlowGraphNode.cpp", + "oboe/src/flowgraph/ManyToMultiConverter.cpp", + "oboe/src/flowgraph/MonoBlend.cpp", + "oboe/src/flowgraph/MonoToMultiConverter.cpp", + "oboe/src/flowgraph/MultiToManyConverter.cpp", + "oboe/src/flowgraph/MultiToMonoConverter.cpp", + "oboe/src/flowgraph/RampLinear.cpp", + "oboe/src/flowgraph/SampleRateConverter.cpp", + "oboe/src/flowgraph/SinkFloat.cpp", + "oboe/src/flowgraph/SinkI16.cpp", + "oboe/src/flowgraph/SinkI24.cpp", + "oboe/src/flowgraph/SinkI32.cpp", + "oboe/src/flowgraph/SourceFloat.cpp", + "oboe/src/flowgraph/SourceI16.cpp", + "oboe/src/flowgraph/SourceI24.cpp", + "oboe/src/flowgraph/SourceI32.cpp", + "oboe/src/flowgraph/resampler/IntegerRatio.cpp", + "oboe/src/flowgraph/resampler/LinearResampler.cpp", + "oboe/src/flowgraph/resampler/MultiChannelResampler.cpp", + "oboe/src/flowgraph/resampler/PolyphaseResampler.cpp", + "oboe/src/flowgraph/resampler/PolyphaseResamplerMono.cpp", + "oboe/src/flowgraph/resampler/PolyphaseResamplerStereo.cpp", + "oboe/src/flowgraph/resampler/SincResampler.cpp", + "oboe/src/flowgraph/resampler/SincResamplerStereo.cpp", + "oboe/src/opensles/AudioInputStreamOpenSLES.cpp", + "oboe/src/opensles/AudioOutputStreamOpenSLES.cpp", + "oboe/src/opensles/AudioStreamBuffered.cpp", + "oboe/src/opensles/AudioStreamOpenSLES.cpp", + "oboe/src/opensles/EngineOpenSLES.cpp", + "oboe/src/opensles/OpenSLESUtilities.cpp", + "oboe/src/opensles/OutputMixerOpenSLES.cpp", + ] + if (target_cpu == "arm" || target_cpu == "arm64") { + sources += [ + "texture_compressor/dxt_encoder_neon.cc", + "texture_compressor/texture_compressor_etc1_neon.cc", + ] + } + cflags += [ + "-Wno-nullability-completeness", + "-Wno-deprecated-enum-enum-conversion", + ] + include_dirs = [ "oboe/src" ] + libs = [ "OpenSLES" ] + } + configs -= [ "//build:warnings" ] deps = []