Compare commits

...

8 Commits

5 changed files with 118 additions and 39 deletions

View File

@@ -5,13 +5,13 @@ cmake_minimum_required(VERSION 3.6)
project(XASH_ANDROID) project(XASH_ANDROID)
# armeabi-v7a requires cpufeatures library # armeabi-v7a requires cpufeatures library
include(AndroidNdkModules) if(ANDROID)
android_ndk_import_module_cpufeatures() include_directories(${ANDROID_NDK}/sources/android/cpufeatures)
add_library(cpufeatures ${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c)
target_link_libraries(cpufeatures dl)
endif()
find_package(PythonInterp 2.7 REQUIRED) include(FindPython)
get_filename_component(C_COMPILER_ID ${CMAKE_C_COMPILER} NAME_WE)
get_filename_component(CXX_COMPILER_ID ${CMAKE_CXX_COMPILER} NAME_WE)
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
set(BUILD_TYPE "debug") set(BUILD_TYPE "debug")
@@ -20,30 +20,20 @@ else()
list(APPEND WAF_EXTRA_ARGS --enable-poly-opt --enable-lto) list(APPEND WAF_EXTRA_ARGS --enable-poly-opt --enable-lto)
endif() endif()
if(CMAKE_SIZEOF_VOID_P MATCHES "8") if(ANDROID_ABI STREQUAL "x86")
set(64BIT ON CACHE BOOL "" FORCE) # HACKHACK: I don't know why but engine gets built as 64-bit binary here
list(APPEND WAF_EXTRA_ARGS -8) # only required for x86 when testing this cmakelist under linux list(APPEND WAF_EXTRA_ARGS -4)
endif() endif()
set(CMAKE_VERBOSE_MAKEFILE ON) set(CMAKE_VERBOSE_MAKEFILE ON)
set(WAF_CC "${CMAKE_C_COMPILER} --target=${CMAKE_C_COMPILER_TARGET}")
set(WAF_CXX "${CMAKE_CXX_COMPILER} --target=${CMAKE_CXX_COMPILER_TARGET}")
# not cleanest way to get upper directory # not cleanest way to get upper directory
set(ENGINE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../") set(ENGINE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../")
execute_process( set(WAF_CC "${CMAKE_C_COMPILER} --target=${CMAKE_C_COMPILER_TARGET}")
COMMAND ${CMAKE_COMMAND} -E env set(WAF_CXX "${CMAKE_CXX_COMPILER} --target=${CMAKE_CXX_COMPILER_TARGET}")
CC=${WAF_CC} CXX=${WAF_CXX} set(WAF ${Python_EXECUTABLE} ${ENGINE_SOURCE_DIR}waf -t ${ENGINE_SOURCE_DIR} -o ${CMAKE_CURRENT_BINARY_DIR}/xash3d-fwgs)
AR=${CMAKE_AR} STRIP=${CMAKE_STRIP}
${PYTHON_EXECUTABLE} waf configure -T ${BUILD_TYPE} -o "${CMAKE_CURRENT_BINARY_DIR}/xash3d-fwgs" ${WAF_EXTRA_ARGS} cmake
--check-c-compiler=${C_COMPILER_ID} --check-cxx-compiler=${CXX_COMPILER_ID}
-s "${ENGINE_SOURCE_DIR}/SDL" --skip-sdl2-sanity-check --enable-bundled-deps
WORKING_DIRECTORY "${ENGINE_SOURCE_DIR}"
)
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/hlsdk-portable" hlsdk-portable)
# try to build minimal SDL. Enable features as we're gonna use them # try to build minimal SDL. Enable features as we're gonna use them
set(SDL_RENDER OFF) set(SDL_RENDER OFF)
@@ -56,5 +46,50 @@ set(SDL_VULKAN OFF)
set(SDL_OFFSCREEN OFF) set(SDL_OFFSCREEN OFF)
set(SDL_STATIC OFF) set(SDL_STATIC OFF)
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/SDL" SDL) add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/SDL" SDL)
add_subdirectory("${ENGINE_SOURCE_DIR}/" xash3d-fwgs)
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/mainui" mainui) include(ExternalProject)
# gradle passes backslashes to cmake, how does this even work for everybody else?
string(REPLACE "\\" "/" CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
ExternalProject_Add(
Xash3DFWGS
SOURCE_DIR ${ENGINE_SOURCE_DIR}
INSTALL_DIR ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
BUILD_IN_SOURCE TRUE
DEPENDS SDL2
BUILD_ALWAYS TRUE
LOG_CONFIGURE TRUE
LOG_BUILD TRUE
LOG_INSTALL TRUE
LOG_OUTPUT_ON_FAILURE TRUE
LOG_MERGED_STDOUTERR TRUE
# USES_TERMINAL_CONFIGURE TRUE
# USES_TERMINAL_BUILD TRUE
# USES_TERMINAL_INSTALL TRUE
# NOTE: setting up WAFLOCK is important to avoid possible race conditions
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env
ANDROID_NDK=${ANDROID_NDK}
BUILD_CMAKE_LIBRARY_OUTPUT_DIRECTORY=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
WAFLOCK=.lock-waf_android_${ANDROID_ABI}_build
${WAF} configure -T ${BUILD_TYPE} --android=${ANDROID_ABI},,${CMAKE_SYSTEM_VERSION}
-s "${ENGINE_SOURCE_DIR}/3rdparty/SDL" --enable-bundled-deps
BUILD_COMMAND ${CMAKE_COMMAND} -E env
WAFLOCK=.lock-waf_android_${ANDROID_ABI}_build
${WAF} build -v
INSTALL_COMMAND ${CMAKE_COMMAND} -E env
WAFLOCK=.lock-waf_android_${ANDROID_ABI}_build
${WAF} install --destdir=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
)
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/hlsdk-portable" hlsdk-portable)
# a1ba: without this, xash3d target will be ignored as nothing depends on it
add_dependencies(client Xash3DFWGS)
add_dependencies(server Xash3DFWGS)

View File

@@ -9,7 +9,7 @@ plugins {
android { android {
namespace = "su.xash.engine" namespace = "su.xash.engine"
ndkVersion = "27.2.12479018" ndkVersion = "28.0.13004108"
defaultConfig { defaultConfig {
applicationId = "su.xash" applicationId = "su.xash"

View File

@@ -20,4 +20,7 @@ kotlin.code.style=official
# Enables namespacing of each library's R class so that its R class includes only the # Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies, # resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library # thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true android.nonTransitiveRClass=true
# Enable verbose output for CMake
android.native.buildOutput=verbose

View File

@@ -48,6 +48,12 @@ def sdl2_configure_path(conf, path, libname):
conf.env[FRAMEWORKPATH] = [my_dirname(path)] conf.env[FRAMEWORKPATH] = [my_dirname(path)]
conf.env[FRAMEWORK] = [libname] conf.env[FRAMEWORK] = [libname]
conf.end_msg('yes: {0}, {1}, {2}'.format(conf.env[FRAMEWORK], conf.env[FRAMEWORKPATH], conf.env[INCLUDES])) conf.end_msg('yes: {0}, {1}, {2}'.format(conf.env[FRAMEWORK], conf.env[FRAMEWORKPATH], conf.env[INCLUDES]))
elif conf.env.DEST_OS == 'android':
# Special setup for waf called from CMake, through ExternalProject_Add
conf.env[INCLUDES] = [os.path.abspath(os.path.join(path, 'include'))]
conf.env[LIBPATH] = [os.environ['BUILD_CMAKE_LIBRARY_OUTPUT_DIRECTORY']]
conf.env[LIB] = [libname]
conf.end_msg('yes: {0}, {1}, {2}'.format(conf.env[LIB], conf.env[LIBPATH], conf.env[INCLUDES]))
else: else:
conf.env[INCLUDES] = [ conf.env[INCLUDES] = [
os.path.abspath(os.path.join(path, 'include')), os.path.abspath(os.path.join(path, 'include')),

View File

@@ -20,12 +20,20 @@ import os
import sys import sys
ANDROID_NDK_ENVVARS = ['ANDROID_NDK_HOME', 'ANDROID_NDK'] ANDROID_NDK_ENVVARS = ['ANDROID_NDK_HOME', 'ANDROID_NDK']
ANDROID_NDK_SUPPORTED = [10, 19, 20, 23, 25] ANDROID_NDK_SUPPORTED = [10, 19, 20, 23, 25, 27, 28]
ANDROID_NDK_HARDFP_MAX = 11 # latest version that supports hardfp ANDROID_NDK_HARDFP_MAX = 11 # latest version that supports hardfp
ANDROID_NDK_GCC_MAX = 17 # latest NDK that ships with GCC ANDROID_NDK_GCC_MAX = 17 # latest NDK that ships with GCC
ANDROID_NDK_UNIFIED_SYSROOT_MIN = 15 ANDROID_NDK_UNIFIED_SYSROOT_MIN = 15
ANDROID_NDK_SYSROOT_FLAG_MAX = 19 # latest NDK that need --sysroot flag ANDROID_NDK_SYSROOT_FLAG_MAX = 19 # latest NDK that need --sysroot flag
ANDROID_NDK_API_MIN = { 10: 3, 19: 16, 20: 16, 23: 16, 25: 19 } # minimal API level ndk revision supports ANDROID_NDK_API_MIN = {
10: 3,
19: 16,
20: 16,
23: 16,
25: 19,
27: 19,
28: 19,
} # minimal API level ndk revision supports
ANDROID_STPCPY_API_MIN = 21 # stpcpy() introduced in SDK 21 ANDROID_STPCPY_API_MIN = 21 # stpcpy() introduced in SDK 21
ANDROID_64BIT_API_MIN = 21 # minimal API level that supports 64-bit targets ANDROID_64BIT_API_MIN = 21 # minimal API level that supports 64-bit targets
@@ -50,6 +58,7 @@ class Android:
self.api = api self.api = api
self.toolchain = toolchain self.toolchain = toolchain
self.arch = arch self.arch = arch
self.exe = '.exe' if sys.platform.startswith('win32') or sys.platform.startswith('cygwin') else ''
for i in ANDROID_NDK_ENVVARS: for i in ANDROID_NDK_ENVVARS:
self.ndk_home = os.getenv(i) self.ndk_home = os.getenv(i)
@@ -196,10 +205,10 @@ class Android:
def gen_toolchain_path(self): def gen_toolchain_path(self):
if self.is_clang(): if self.is_clang():
triplet = '%s%d-' % (self.ndk_triplet(llvm_toolchain = True), self.api) base = ''
else: else:
triplet = self.ndk_triplet() + '-' base = self.ndk_triplet() + '-'
return os.path.join(self.gen_gcc_toolchain_path(), 'bin', triplet) return os.path.join(self.gen_gcc_toolchain_path(), 'bin', base)
def gen_binutils_path(self): def gen_binutils_path(self):
if self.ndk_rev >= 23: if self.ndk_rev >= 23:
@@ -215,7 +224,11 @@ class Android:
s = environ['CC'] s = environ['CC']
return '%s --target=%s%d' % (s, self.ndk_triplet(), self.api) return '%s --target=%s%d' % (s, self.ndk_triplet(), self.api)
return self.gen_toolchain_path() + ('clang' if self.is_clang() else 'gcc')
if self.is_clang():
return '%s --target=%s%d' % (self.gen_toolchain_path() + 'clang' + self.exe, self.ndk_triplet(), self.api)
return self.gen_toolchain_path() + 'gcc'
def cxx(self): def cxx(self):
if self.is_host(): if self.is_host():
@@ -226,19 +239,33 @@ class Android:
s = environ['CXX'] s = environ['CXX']
return '%s --target=%s%d' % (s, self.ndk_triplet(), self.api) return '%s --target=%s%d' % (s, self.ndk_triplet(), self.api)
return self.gen_toolchain_path() + ('clang++' if self.is_clang() else 'g++')
if self.is_clang():
return '%s --target=%s%d' % (self.gen_toolchain_path() + 'clang++' + self.exe, self.ndk_triplet(), self.api)
return self.gen_toolchain_path() + 'g++'
def strip(self): def strip(self):
if self.is_host(): if self.is_host():
environ = getattr(self.ctx, 'environ', os.environ) environ = getattr(self.ctx, 'environ', os.environ)
if 'STRIP' in environ: if 'STRIP' in environ:
return environ['STRIP'] return environ['STRIP']
return 'llvm-strip' return 'llvm-strip'
if self.ndk_rev >= 23: if self.ndk_rev >= 23:
return os.path.join(self.gen_binutils_path(), 'llvm-strip') return os.path.join(self.gen_binutils_path(), 'llvm-strip' + self.exe)
return os.path.join(self.gen_binutils_path(), 'strip') return os.path.join(self.gen_binutils_path(), 'strip' + self.exe)
def ar(self):
if self.is_host():
environ = getattr(self.ctx, 'environ', os.environ)
if 'AR' in environ:
return environ['AR']
return 'llvm-ar'
if self.ndk_rev >= 23:
return os.path.join(self.gen_binutils_path(), 'llvm-ar' + self.exe)
return os.path.join(self.gen_binutils_path(), 'ar' + self.exe)
def system_stl(self): def system_stl(self):
# TODO: proper STL support # TODO: proper STL support
@@ -336,7 +363,7 @@ class Android:
ldflags += ['-lgcc'] ldflags += ['-lgcc']
if self.is_clang() or self.is_host(): if self.is_clang() or self.is_host():
ldflags += ['-stdlib=libstdc++'] ldflags += ['-stdlib=libstdc++', '-lc++abi']
else: ldflags += ['-no-canonical-prefixes'] else: ldflags += ['-no-canonical-prefixes']
if self.is_arm(): if self.is_arm():
@@ -521,25 +548,33 @@ def configure(conf):
valid_archs = ['x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'armeabi-v7a-hard', 'aarch64'] valid_archs = ['x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'armeabi-v7a-hard', 'aarch64']
if values[0] == 'arm64-v8a':
values[0] = 'aarch64'
if values[0] not in valid_archs: if values[0] not in valid_archs:
conf.fatal('Unknown arch: %s. Supported: %r' % (values[0], ', '.join(valid_archs))) conf.fatal('Unknown arch: %s. Supported: %r' % (values[0], ', '.join(valid_archs)))
conf.android = android = Android(conf, values[0], values[1], int(values[2])) conf.android = android = Android(conf, values[0], values[1], int(values[2]))
conf.environ['CC'] = android.cc() conf.environ['CC'] = android.cc()
conf.environ['CXX'] = android.cxx() conf.environ['CXX'] = android.cxx()
conf.environ['STRIP'] = android.strip() conf.environ['STRIP'] = android.strip()
conf.environ['AR'] = android.ar()
conf.env.CFLAGS += android.cflags() conf.env.CFLAGS += android.cflags()
conf.env.CXXFLAGS += android.cflags(True) conf.env.CXXFLAGS += android.cflags(True)
conf.env.LINKFLAGS += android.linkflags() conf.env.LINKFLAGS += android.linkflags()
conf.env.LDFLAGS += android.ldflags() conf.env.LDFLAGS += android.ldflags()
from waflib.Tools.compiler_c import c_compiler
from waflib.Tools.compiler_cxx import cxx_compiler
c_compiler['win32'] = ['clang' if android.is_clang() or android.is_host() else 'gcc']
cxx_compiler['win32'] = ['clang++' if android.is_clang() or android.is_host() else 'gxx']
conf.env.HAVE_M = True conf.env.HAVE_M = True
if android.is_hardfp(): if android.is_hardfp():
conf.env.LIB_M = ['m_hard'] conf.env.LIB_M = ['m_hard']
else: conf.env.LIB_M = ['m'] else: conf.env.LIB_M = ['m']
conf.env.PREFIX = '/lib/%s' % android.apk_arch()
conf.msg('Selected Android NDK', '%s, version: %d' % (android.ndk_home, android.ndk_rev)) conf.msg('Selected Android NDK', '%s, version: %d' % (android.ndk_home, android.ndk_rev))
# no need to print C/C++ compiler, as it would be printed by compiler_c/cxx # no need to print C/C++ compiler, as it would be printed by compiler_c/cxx
conf.msg('... C/C++ flags', ' '.join(android.cflags()).replace(android.ndk_home, '$NDK/')) conf.msg('... C/C++ flags', ' '.join(android.cflags()).replace(android.ndk_home, '$NDK/'))