0c7605c9b6
* Update the minimum CMake version to 3.20 Sets the cmake_minimum_required calls to version 3.20 and updates the README.md to point at the general CMake download page instead of a stale link. * Remove unnecessary cmake minimum version It was using an old 3.0 version and can be removed. * Additional updates to CMake 3.20, build scripts Updates the version and remove logic to find a CMake in 3rdParty. * Removing backup path to ninja path in the build_ninja_windows.cmd The backup path for finding ninja was coming from the Perforce depot which isn't available for o3de builds. * Removing reference to 3rdParty Android SDK 29 from the build and run unit test script The Android SDK is not part of the new 3rdParty system and users are expected to install the Android SDK on their own in order to build the engine for Android. * Update the get_python scripts and README No longer try to append a CMake path to LY_3RDPARTY_PATH, but do still support LY_CMAKE_PATH because there are still uses of it. Remove mention of an LY_3RDPARTY_PATH-relative CMake path from the README.md. * Removing LY_NINJA_PATH from the build_ninja_windows.cmd Co-authored-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com>
411 lines
21 KiB
Python
Executable File
411 lines
21 KiB
Python
Executable File
#
|
|
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
|
# its licensors.
|
|
#
|
|
# For complete copyright and license terms please see the LICENSE at the root of this
|
|
# distribution (the "License"). All use of this software is governed by the License,
|
|
# or, if provided, by the license below or the license accompanying this file. Do not
|
|
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
#
|
|
|
|
import argparse
|
|
import logging
|
|
import os
|
|
import pathlib
|
|
import platform
|
|
import re
|
|
import sys
|
|
|
|
from distutils.version import LooseVersion
|
|
|
|
ROOT_DEV_PATH = os.path.realpath(os.path.join(os.path.dirname(__file__), '..', '..', '..', '..'))
|
|
if ROOT_DEV_PATH not in sys.path:
|
|
sys.path.append(ROOT_DEV_PATH)
|
|
|
|
from cmake.Tools import common
|
|
from cmake.Tools.Platform.Android import android_support
|
|
|
|
GRADLE_ARGUMENT_NAME = '--gradle-install-path'
|
|
GRADLE_MIN_VERSION = LooseVersion('6.5')
|
|
GRADLE_MAX_VERSION = LooseVersion('7.0.0')
|
|
GRADLE_VERSION_REGEX = re.compile(r"Gradle\s(\d+.\d+.?\d*)")
|
|
GRADLE_EXECUTABLE = 'gradle.bat' if platform.system() == 'Windows' else 'gradle'
|
|
|
|
|
|
def verify_gradle(override_gradle_path=None):
|
|
"""
|
|
Verify the installed gradle requirement.
|
|
"""
|
|
return common.verify_tool(override_tool_path=override_gradle_path,
|
|
tool_name='gradle',
|
|
tool_filename=GRADLE_EXECUTABLE,
|
|
argument_name=GRADLE_ARGUMENT_NAME,
|
|
tool_version_argument='-v',
|
|
tool_version_regex=GRADLE_VERSION_REGEX,
|
|
min_version=GRADLE_MIN_VERSION,
|
|
max_version=GRADLE_MAX_VERSION)
|
|
|
|
|
|
CMAKE_ARGUMENT_NAME = '--cmake-install-path'
|
|
CMAKE_MIN_VERSION = LooseVersion('3.20.0')
|
|
CMAKE_VERSION_REGEX = re.compile(r'cmake version (\d+.\d+.?\d*)')
|
|
CMAKE_EXECUTABLE = 'cmake'
|
|
|
|
|
|
def verify_cmake(override_cmake_path=None):
|
|
"""
|
|
Verify the installed cmake requirement.
|
|
"""
|
|
return common.verify_tool(override_tool_path=override_cmake_path,
|
|
tool_name='cmake',
|
|
tool_filename=CMAKE_EXECUTABLE,
|
|
argument_name=CMAKE_ARGUMENT_NAME,
|
|
tool_version_argument='--version',
|
|
tool_version_regex=CMAKE_VERSION_REGEX,
|
|
min_version=CMAKE_MIN_VERSION,
|
|
max_version=None)
|
|
|
|
|
|
NINJA_ARGUMENT_NAME = '--ninja-install-path'
|
|
NINJA_VERSION_REGEX = re.compile(r'(\d+.\d+.?\d*)')
|
|
NINJA_EXECUTABLE = 'ninja'
|
|
|
|
|
|
def verify_ninja(override_ninja_path=None):
|
|
"""
|
|
Verify the installed ninja requirement.
|
|
"""
|
|
return common.verify_tool(override_tool_path=override_ninja_path,
|
|
tool_name='ninja',
|
|
tool_filename='ninja',
|
|
argument_name=NINJA_ARGUMENT_NAME,
|
|
tool_version_argument='--version',
|
|
tool_version_regex=NINJA_VERSION_REGEX,
|
|
min_version=None,
|
|
max_version=None)
|
|
|
|
|
|
SIGNING_PROFILE_STORE_FILE_ARGUMENT_NAME = "--signconfig-store-file"
|
|
SIGNING_PROFILE_STORE_PASSWORD_ARGUMENT_NAME = "--signconfig-store-password"
|
|
SIGNING_PROFILE_KEY_ALIAS_ARGUMENT_NAME = "--signconfig-key-alias"
|
|
SIGNING_PROFILE_KEY_PASSWORD_ARGUMENT_NAME = "--signconfig-key-password"
|
|
|
|
|
|
def build_optional_signing_profile(store_file, store_password, key_alias, key_password):
|
|
# If none of the arguments are set, then return None and skip the signing config generation
|
|
if not any([store_file, store_password, key_alias, key_password]):
|
|
return
|
|
return android_support.AndroidSigningConfig(store_file=store_file,
|
|
store_password=store_password,
|
|
key_alias=key_alias,
|
|
key_password=key_password)
|
|
|
|
|
|
ANDROID_SDK_ARGUMENT_NAME = '--android-sdk-path'
|
|
ANDROID_SDK_PLATFORM_ARGUMENT_NAME = '--android-sdk-platform'
|
|
ANDROID_SDK_PREFERRED_TOOL_VER = '--android-sdk-build-tool-version'
|
|
|
|
ANDROID_NATIVE_API_LEVEL = '--android-native-api-level'
|
|
|
|
|
|
MIN_ANDROID_SDK_PLATFORM = 28 # The minimum platform/api level that is supported for the SDK Platform
|
|
MIN_NATIVE_API_LEVEL = 24 # The minimum Native API level that is supported for the NDK
|
|
|
|
|
|
ANDROID_NDK_PLATFORM_ARGUMENT_NAME = '--android-ndk-version'
|
|
|
|
ANDROID_GRADLE_PLUGIN_ARGUMENT_NAME = '--gradle-plugin-version'
|
|
ANDROID_GRADLE_MIN_PLUGIN_VERSION = LooseVersion("4.2.0")
|
|
|
|
# Constants for asset-related options for APK generation
|
|
INCLUDE_APK_ASSETS_ARGUMENT_NAME = "--include-apk-assets"
|
|
ASSET_MODE_ARGUMENT_NAME = "--asset-mode"
|
|
ASSET_MODE_PAK = 'PAK'
|
|
ASSET_MODE_LOOSE = 'LOOSE'
|
|
ASSET_MODE_VFS = 'VFS'
|
|
ALL_ASSET_MODES = [ASSET_MODE_PAK, ASSET_MODE_LOOSE, ASSET_MODE_VFS]
|
|
ASSET_TYPE_ARGUMENT_NAME = '--asset-type'
|
|
DEFAULT_ASSET_TYPE = 'android'
|
|
|
|
|
|
def wrap_parsed_args(parsed_args):
|
|
"""
|
|
Function to add a method to the parsed argument object to transform a long-form argument name to and get the
|
|
parsed values based on the input long form.
|
|
|
|
This will allow us to read an argument like '--foo-bar=Orange' by using the built in method rather than looking for
|
|
the argparsed transformed attrobite 'foo_bar'
|
|
|
|
:param parsed_args: The parsed args object to wrap
|
|
"""
|
|
|
|
def parse_argument_attr(argument):
|
|
argument_attr = argument[2:].replace('-', '_')
|
|
return getattr(parsed_args, argument_attr)
|
|
|
|
parsed_args.get_argument = parse_argument_attr
|
|
|
|
|
|
def main(args):
|
|
"""
|
|
Perform the main argument processing and execution of the project generator
|
|
:param args: The arguments to process
|
|
"""
|
|
|
|
parser = argparse.ArgumentParser(description="Prepare the android studio subfolder")
|
|
|
|
# Required Arguments
|
|
parser.add_argument('--engine-root',
|
|
help='The path to the engine root. Defaults to the current working directory.',
|
|
default=os.getcwd())
|
|
|
|
parser.add_argument('--build-dir',
|
|
help='The build dir path. It will be concatenated to the project-path using the rules of os.path.join',
|
|
type=pathlib.Path,
|
|
required=True)
|
|
|
|
parser.add_argument('--third-party-path',
|
|
help='The path to the 3rd Party root directory',
|
|
required=True)
|
|
|
|
parser.add_argument(ANDROID_SDK_ARGUMENT_NAME,
|
|
help='The path to the android SDK',
|
|
required=True)
|
|
|
|
parser.add_argument('-g', '--project-path',
|
|
help='The project path to generate an android project',
|
|
required=True)
|
|
|
|
parser.add_argument(ANDROID_SDK_PLATFORM_ARGUMENT_NAME,
|
|
help=f'The android SDK platform number version to use for the APK. (Minimum {MIN_ANDROID_SDK_PLATFORM})',
|
|
type=int,
|
|
default=-1)
|
|
|
|
parser.add_argument(ANDROID_NATIVE_API_LEVEL,
|
|
help=f'The android native API level to use for the APK. If not set, this will default to the android SDK platform. (Minimum {MIN_ANDROID_SDK_PLATFORM})',
|
|
type=int,
|
|
default=-1)
|
|
|
|
# Override arguments
|
|
parser.add_argument(ANDROID_SDK_PREFERRED_TOOL_VER,
|
|
help='The android SDK build tools version.',
|
|
required=False)
|
|
|
|
parser.add_argument(ANDROID_NDK_PLATFORM_ARGUMENT_NAME,
|
|
help='The android NDK version',
|
|
required=False)
|
|
|
|
parser.add_argument(GRADLE_ARGUMENT_NAME,
|
|
help=f'The path to installed gradle. The version of gradle must fall in between {str(GRADLE_MIN_VERSION)} and {str(GRADLE_MAX_VERSION)}.',
|
|
default=None,
|
|
required=False)
|
|
|
|
parser.add_argument(ANDROID_GRADLE_PLUGIN_ARGUMENT_NAME,
|
|
help=f'The version of the android gradle plugin to use. Defaults to the minimum version ({ANDROID_GRADLE_MIN_PLUGIN_VERSION})',
|
|
default=str(ANDROID_GRADLE_MIN_PLUGIN_VERSION))
|
|
|
|
parser.add_argument(CMAKE_ARGUMENT_NAME,
|
|
help=f'The path to cmake build tool if not installed on the system path. The version of cmake must be at least version {str(CMAKE_MIN_VERSION)}.',
|
|
default=None,
|
|
required=False)
|
|
|
|
parser.add_argument(NINJA_ARGUMENT_NAME,
|
|
help='The path to the ninja build tool if not installed on the system path.',
|
|
default=None,
|
|
required=False)
|
|
|
|
# Asset Options
|
|
parser.add_argument(INCLUDE_APK_ASSETS_ARGUMENT_NAME,
|
|
action='store_true',
|
|
help='Option to include the game assets when building the APK. If this option is set, you must have the android assets built.')
|
|
|
|
parser.add_argument(ASSET_MODE_ARGUMENT_NAME,
|
|
choices=ALL_ASSET_MODES,
|
|
default=ASSET_MODE_LOOSE,
|
|
help=f'Asset Mode (vfs|pak|loose) to use when including assets into the APK. (Defaults to {ASSET_MODE_LOOSE})')
|
|
|
|
parser.add_argument(ASSET_TYPE_ARGUMENT_NAME,
|
|
default=DEFAULT_ASSET_TYPE,
|
|
help=f'Asset Type to use when including assets into the APK. (Defaults to {DEFAULT_ASSET_TYPE})')
|
|
|
|
parser.add_argument('--debug',
|
|
action='store_true',
|
|
help='Enable debug logs.')
|
|
|
|
# Signing Config options
|
|
parser.add_argument(SIGNING_PROFILE_STORE_FILE_ARGUMENT_NAME,
|
|
default=None,
|
|
help='(Optional) If specified, create a signing profile based on this supplied android jks keystore file.')
|
|
|
|
parser.add_argument(SIGNING_PROFILE_STORE_PASSWORD_ARGUMENT_NAME,
|
|
default=None,
|
|
help='If an android jks keystore file is specified, this is the store password for the keystore.')
|
|
|
|
parser.add_argument(SIGNING_PROFILE_KEY_ALIAS_ARGUMENT_NAME,
|
|
default=None,
|
|
help='If an android jks keystore file is specified, this is the alias of the signing key in the keystore.')
|
|
|
|
parser.add_argument(SIGNING_PROFILE_KEY_PASSWORD_ARGUMENT_NAME,
|
|
default=None,
|
|
help='If an android jks keystore file is specified, this is the password of the signing key in the keystore.')
|
|
|
|
parser.add_argument('--unit-test',
|
|
action='store_true',
|
|
help='Generate a unit test APK instead of a game APK.')
|
|
|
|
parser.add_argument('--overwrite-existing',
|
|
action='store_true',
|
|
help='Option to overwrite existing scripts in the target build folder if they exist already.')
|
|
|
|
parsed_args = parser.parse_args(args)
|
|
wrap_parsed_args(parsed_args)
|
|
|
|
# Prepare the logging
|
|
logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.DEBUG if parsed_args.debug else logging.INFO)
|
|
|
|
# Verify the gradle requirements
|
|
gradle_version, override_gradle_path = verify_gradle(override_gradle_path=parsed_args.get_argument(GRADLE_ARGUMENT_NAME))
|
|
logging.info("Detected Gradle version %s", str(gradle_version))
|
|
|
|
# Verify the cmake requirements
|
|
cmake_version, override_cmake_path = verify_cmake(override_cmake_path=parsed_args.get_argument(CMAKE_ARGUMENT_NAME))
|
|
logging.info("Detected CMake version %s", str(cmake_version))
|
|
|
|
# Verify the ninja requirements
|
|
ninja_version, override_ninja_path = verify_ninja(override_ninja_path=parsed_args.get_argument(NINJA_ARGUMENT_NAME))
|
|
logging.info("Detected Ninja version %s", str(ninja_version))
|
|
|
|
# Get the android sdk platform version to use from the arguments, but also handle the deprecated argument name
|
|
android_sdk_platform_version = parsed_args.get_argument(ANDROID_SDK_PLATFORM_ARGUMENT_NAME)
|
|
|
|
# Get the gradle plugin details and validate against the current environment
|
|
android_gradle_plugin_version = parsed_args.get_argument(ANDROID_GRADLE_PLUGIN_ARGUMENT_NAME)
|
|
android_gradle_plugin = android_support.AndroidGradlePluginInfo(android_gradle_plugin_version)
|
|
logging.info(f"Generating Android Gradle Plugin version {android_gradle_plugin_version} based project")
|
|
|
|
if gradle_version < android_gradle_plugin.min_gradle_version:
|
|
raise common.LmbrCmdError(f"The current version of gradle ({gradle_version}) does not satisfy the minimum version "
|
|
f"({android_gradle_plugin.min_gradle_version}) needed for the android gradle plugin "
|
|
f"({android_gradle_plugin_version}). Please upgrade your gradle.")
|
|
if cmake_version < android_gradle_plugin.min_cmake_version:
|
|
raise common.LmbrCmdError(f"The current version of cmake ({cmake_version}) does not satisfy the minimum version "
|
|
f"({android_gradle_plugin.min_cmake_version}) needed for the android gradle plugin "
|
|
f"({android_gradle_plugin_version}). Please upgrade your cmake.")
|
|
if android_gradle_plugin.max_cmake_version and cmake_version > android_gradle_plugin.max_cmake_version:
|
|
raise common.LmbrCmdError(f"The current version of cmake ({cmake_version}) exceeds the maximum version "
|
|
f"({android_gradle_plugin.max_cmake_version}) of the android gradle plugin "
|
|
f"({android_gradle_plugin_version}).")
|
|
|
|
# Use the SDK Resolver to make sure the build tools and ndk
|
|
android_sdk = android_support.AndroidSDKResolver(android_sdk_path=parsed_args.get_argument(ANDROID_SDK_ARGUMENT_NAME))
|
|
|
|
# If no SDK platform is provided, check for any installed one
|
|
if android_sdk_platform_version < 0:
|
|
android_sdk_platform_version = MIN_ANDROID_SDK_PLATFORM
|
|
installed_android_sdk_platforms = android_sdk.is_package_installed('platforms;*')
|
|
if installed_android_sdk_platforms:
|
|
# If there are installed platforms, check the most recent one
|
|
latest_platform_version = -1
|
|
for installed_android_sdk_platform in installed_android_sdk_platforms:
|
|
platform_number_match = re.match(r'platforms;android-([0-9]*)', installed_android_sdk_platform.path)
|
|
if not platform_number_match:
|
|
continue
|
|
check_platform_version = int(platform_number_match.group(1))
|
|
if check_platform_version > latest_platform_version:
|
|
latest_platform_version = check_platform_version
|
|
if latest_platform_version >= MIN_ANDROID_SDK_PLATFORM:
|
|
android_sdk_platform_version = latest_platform_version
|
|
else:
|
|
if android_sdk_platform_version < MIN_ANDROID_SDK_PLATFORM:
|
|
raise common.LmbrCmdError(f"Invalid argument for {ANDROID_SDK_PLATFORM_ARGUMENT_NAME} ({android_sdk_platform_version}). Must be greater than the minimum value supported {MIN_ANDROID_SDK_PLATFORM}.")
|
|
|
|
# Get the android native api level from the arguments. Default to the sdk platform version if not provided
|
|
android_native_api_level = parsed_args.get_argument(ANDROID_NATIVE_API_LEVEL)
|
|
if android_native_api_level < 0:
|
|
android_native_api_level = android_sdk_platform_version
|
|
else:
|
|
if android_native_api_level < MIN_NATIVE_API_LEVEL:
|
|
raise common.LmbrCmdError(f"Invalid argument for {ANDROID_NATIVE_API_LEVEL} ({android_native_api_level}). Must be greater than the minimum value supported {MIN_NATIVE_API_LEVEL}.")
|
|
|
|
# Check and make sure that the requested sdk platform exists, download if necessary
|
|
platform_package_name = f"platforms;android-{android_sdk_platform_version}"
|
|
android_sdk.install_package(package_install_path=platform_package_name,
|
|
package_description=f'Android SDK Platform {android_sdk_platform_version}')
|
|
|
|
# Make sure we have the extra android packages "market_apk_expansion" and "market_licensing" which is needed by the APK
|
|
android_sdk.install_package(package_install_path='extras;google;market_apk_expansion',
|
|
package_description='Google APK Expansion Library')
|
|
|
|
android_sdk.install_package(package_install_path='extras;google;market_licensing',
|
|
package_description='Google Play Licensing Library')
|
|
|
|
# Install either the requested SDK build tools or the default one for the android gradle plugin version
|
|
build_tools_version = parsed_args.get_argument(ANDROID_SDK_PREFERRED_TOOL_VER) or android_gradle_plugin.default_sdk_build_tools_version
|
|
build_tools_package_name = f'build-tools;{build_tools_version}'
|
|
build_tools_package = android_sdk.install_package(package_install_path=build_tools_package_name,
|
|
package_description='Android SDK Build Tools')
|
|
|
|
# Install either the requested NDK version or the default one for the android gradle plugin version
|
|
android_ndk_version = parsed_args.get_argument(ANDROID_NDK_PLATFORM_ARGUMENT_NAME) or android_gradle_plugin.default_ndk_version
|
|
android_ndk_package_name = f'ndk;{android_ndk_version}'
|
|
android_ndk_package = android_sdk.install_package(package_install_path=android_ndk_package_name,
|
|
package_description='Android NDK')
|
|
|
|
# Verify the engine root path and project path
|
|
verified_project_path, verified_engine_root = common.verify_project_and_engine_root(project_root=parsed_args.project_path,
|
|
engine_root=parsed_args.engine_root)
|
|
is_test_project = parsed_args.unit_test
|
|
|
|
# Verify the 3rd Party Root Path
|
|
third_party_path = pathlib.Path(parsed_args.third_party_path)
|
|
if not third_party_path.is_dir():
|
|
raise common.LmbrCmdError(f"Invalid --third-party-path '{parsed_args.third_party_path}'.",
|
|
common.ERROR_CODE_INVALID_PARAMETER)
|
|
third_party_path = third_party_path.parent
|
|
|
|
build_dir = parsed_args.build_dir
|
|
|
|
signing_config = build_optional_signing_profile(store_file=parsed_args.get_argument(SIGNING_PROFILE_STORE_FILE_ARGUMENT_NAME),
|
|
store_password=parsed_args.get_argument(SIGNING_PROFILE_STORE_PASSWORD_ARGUMENT_NAME),
|
|
key_alias=parsed_args.get_argument(SIGNING_PROFILE_KEY_ALIAS_ARGUMENT_NAME),
|
|
key_password=parsed_args.get_argument(SIGNING_PROFILE_KEY_PASSWORD_ARGUMENT_NAME))
|
|
|
|
logging.debug("Engine Root : %s", str(verified_engine_root.resolve()))
|
|
logging.debug("Build Path : %s", str(build_dir.resolve()))
|
|
|
|
# Prepare the generator and execute
|
|
generator = android_support.AndroidProjectGenerator(engine_root=verified_engine_root,
|
|
build_dir=build_dir,
|
|
android_sdk_path=android_sdk.android_sdk_path,
|
|
build_tool=build_tools_package,
|
|
android_sdk_platform=android_sdk_platform_version,
|
|
android_native_api_level=android_native_api_level,
|
|
android_ndk=android_ndk_package,
|
|
project_path=verified_project_path,
|
|
third_party_path=third_party_path,
|
|
cmake_version=cmake_version,
|
|
override_cmake_path=override_cmake_path,
|
|
override_gradle_path=override_gradle_path,
|
|
gradle_version=gradle_version,
|
|
gradle_plugin_version=android_gradle_plugin_version,
|
|
override_ninja_path=override_ninja_path,
|
|
include_assets_in_apk=parsed_args.get_argument(INCLUDE_APK_ASSETS_ARGUMENT_NAME),
|
|
asset_mode=parsed_args.get_argument(ASSET_MODE_ARGUMENT_NAME),
|
|
asset_type=parsed_args.get_argument(ASSET_TYPE_ARGUMENT_NAME),
|
|
signing_config=signing_config,
|
|
is_test_project=is_test_project,
|
|
overwrite_existing=parsed_args.overwrite_existing)
|
|
generator.execute()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
try:
|
|
main(sys.argv[1:])
|
|
exit(0)
|
|
|
|
except common.LmbrCmdError as err:
|
|
print(str(err), file=sys.stderr)
|
|
exit(err.code)
|