mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-02-01 20:33:46 +08:00
adding mac debug binary
This commit is contained in:
parent
45a61c09a5
commit
7777902e9a
21
Makefile
21
Makefile
@ -35,6 +35,27 @@ all: help
|
|||||||
.PHONY: all
|
.PHONY: all
|
||||||
|
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# #
|
||||||
|
# Prefab #
|
||||||
|
# #
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
# Prebuilt binaries for various platforms.
|
||||||
|
|
||||||
|
prefab-mac: prefab-mac-build
|
||||||
|
@cd build/prefab-mac/debug && ./ballisticacore
|
||||||
|
|
||||||
|
prefab-mac-build: assets-cmake build/prefab-mac/debug/ballisticacore
|
||||||
|
@${STAGE_ASSETS} -cmake build/prefab-mac/debug
|
||||||
|
|
||||||
|
build/prefab-mac/debug/ballisticacore: .efrocachemap
|
||||||
|
@tools/snippets efrocache_get $@
|
||||||
|
|
||||||
|
# Tell make which of these targets don't represent files.
|
||||||
|
.PHONY: prefab-mac prefab-mac-build
|
||||||
|
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# #
|
# #
|
||||||
# General #
|
# General #
|
||||||
|
|||||||
@ -164,11 +164,11 @@ def update_cache(makefile_dirs: List[str]) -> None:
|
|||||||
cdp = f'cd {path} && ' if path else ''
|
cdp = f'cd {path} && ' if path else ''
|
||||||
mfpath = os.path.join(path, 'Makefile')
|
mfpath = os.path.join(path, 'Makefile')
|
||||||
print(f'Building cache targets for {mfpath}...')
|
print(f'Building cache targets for {mfpath}...')
|
||||||
subprocess.run(f'{cdp}make -j{cpus} efrocache_build',
|
subprocess.run(f'{cdp}make -j{cpus} efrocache-build',
|
||||||
shell=True,
|
shell=True,
|
||||||
check=True)
|
check=True)
|
||||||
|
|
||||||
rawpaths = subprocess.run(f'{cdp}make efrocache_list',
|
rawpaths = subprocess.run(f'{cdp}make efrocache-list',
|
||||||
shell=True,
|
shell=True,
|
||||||
check=True,
|
check=True,
|
||||||
capture_output=True).stdout.decode().split()
|
capture_output=True).stdout.decode().split()
|
||||||
|
|||||||
353
tools/stage_assets
Executable file
353
tools/stage_assets
Executable file
@ -0,0 +1,353 @@
|
|||||||
|
#!/usr/bin/env python3.7
|
||||||
|
# Copyright (c) 2011-2019 Eric Froemling
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in
|
||||||
|
# all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
"""Stage assets for a build."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import hashlib
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from functools import partial
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
from efrotools.pybuild import PYTHON_VERSION_MAJOR
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
# Suffix for the pyc files we include in stagings.
|
||||||
|
# We're using deterministic opt pyc files; see PEP 552.
|
||||||
|
# Note: this means anyone wanting to modify .py files in a build
|
||||||
|
# will need to wipe out the existing .pyc files first or the changes
|
||||||
|
# will be ignored.
|
||||||
|
OPT_PYC_SUFFIX = ('cpython-' + PYTHON_VERSION_MAJOR.replace('.', '') +
|
||||||
|
'.opt-1.pyc')
|
||||||
|
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
"""Encapsulates command options."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
# We always calc src relative to this script.
|
||||||
|
self.src = os.path.abspath(
|
||||||
|
os.path.dirname(sys.argv[0]) + '/../assets/build')
|
||||||
|
self.dst: Optional[str] = None
|
||||||
|
self.win_extras_src: Optional[str] = None
|
||||||
|
self.include_audio = True
|
||||||
|
self.include_models = True
|
||||||
|
self.include_collide_models = True
|
||||||
|
self.include_scripts = True
|
||||||
|
self.include_python = True
|
||||||
|
self.include_textures = True
|
||||||
|
self.include_fonts = True
|
||||||
|
self.include_json = True
|
||||||
|
self.include_pylib = False
|
||||||
|
self.pylib_src_name: Optional[str] = None
|
||||||
|
self.include_payload_file = False
|
||||||
|
self.tex_suffix: Optional[str] = None
|
||||||
|
self.is_payload_full = False
|
||||||
|
|
||||||
|
def _parse_android_args(self) -> None:
|
||||||
|
# On Android we get nitpicky with what
|
||||||
|
# we want to copy in since we can speed up
|
||||||
|
# iterations by installing stripped down
|
||||||
|
# apks.
|
||||||
|
self.dst = 'assets/ballistica_files'
|
||||||
|
self.pylib_src_name = 'pylib-android'
|
||||||
|
self.include_payload_file = True
|
||||||
|
self.tex_suffix = '.ktx'
|
||||||
|
self.include_audio = False
|
||||||
|
self.include_models = False
|
||||||
|
self.include_collide_models = False
|
||||||
|
self.include_scripts = False
|
||||||
|
self.include_python = False
|
||||||
|
self.include_textures = False
|
||||||
|
self.include_fonts = False
|
||||||
|
self.include_json = False
|
||||||
|
self.include_pylib = False
|
||||||
|
for arg in sys.argv[1:]:
|
||||||
|
if arg == '-full':
|
||||||
|
self.include_audio = True
|
||||||
|
self.include_models = True
|
||||||
|
self.include_collide_models = True
|
||||||
|
self.include_scripts = True
|
||||||
|
self.include_python = True
|
||||||
|
self.include_textures = True
|
||||||
|
self.include_fonts = True
|
||||||
|
self.include_json = True
|
||||||
|
self.is_payload_full = True
|
||||||
|
self.include_pylib = True
|
||||||
|
elif arg == '-none':
|
||||||
|
pass
|
||||||
|
elif arg == '-models':
|
||||||
|
self.include_models = True
|
||||||
|
self.include_collide_models = True
|
||||||
|
elif arg == '-python':
|
||||||
|
self.include_python = True
|
||||||
|
self.include_pylib = True
|
||||||
|
elif arg == '-textures':
|
||||||
|
self.include_textures = True
|
||||||
|
elif arg == '-fonts':
|
||||||
|
self.include_fonts = True
|
||||||
|
elif arg == '-scripts':
|
||||||
|
self.include_scripts = True
|
||||||
|
elif arg == '-audio':
|
||||||
|
self.include_audio = True
|
||||||
|
|
||||||
|
def parse_args(self) -> None:
|
||||||
|
"""Parse args and apply to the cfg."""
|
||||||
|
if '-android' in sys.argv:
|
||||||
|
self._parse_android_args()
|
||||||
|
elif '-cmake' in sys.argv:
|
||||||
|
self.dst = sys.argv[2]
|
||||||
|
self.tex_suffix = '.dds'
|
||||||
|
elif '-win-Win32' in sys.argv:
|
||||||
|
self.dst = sys.argv[2]
|
||||||
|
self.tex_suffix = '.dds'
|
||||||
|
self.win_extras_src = os.path.abspath(
|
||||||
|
os.path.dirname(sys.argv[0]) +
|
||||||
|
'/../ballisticacore-windows/Extras/Win32')
|
||||||
|
elif '-win-x64' in sys.argv:
|
||||||
|
self.dst = sys.argv[2]
|
||||||
|
self.tex_suffix = '.dds'
|
||||||
|
self.win_extras_src = os.path.abspath(
|
||||||
|
os.path.dirname(sys.argv[0]) +
|
||||||
|
'/../ballisticacore-windows/Extras/x64')
|
||||||
|
elif '-win-server-Win32' in sys.argv:
|
||||||
|
self.dst = sys.argv[2]
|
||||||
|
self.win_extras_src = os.path.abspath(
|
||||||
|
os.path.dirname(sys.argv[0]) +
|
||||||
|
'/../ballisticacore-windows/Extras/Win32')
|
||||||
|
self.include_textures = False
|
||||||
|
self.include_audio = False
|
||||||
|
self.include_models = False
|
||||||
|
elif '-win-server-x64' in sys.argv:
|
||||||
|
self.dst = sys.argv[2]
|
||||||
|
self.win_extras_src = os.path.abspath(
|
||||||
|
os.path.dirname(sys.argv[0]) +
|
||||||
|
'/../ballisticacore-windows/Extras/x64')
|
||||||
|
self.include_textures = False
|
||||||
|
self.include_audio = False
|
||||||
|
self.include_models = False
|
||||||
|
elif '-cmake-server' in sys.argv:
|
||||||
|
self.dst = sys.argv[2]
|
||||||
|
self.include_textures = False
|
||||||
|
self.include_audio = False
|
||||||
|
self.include_models = False
|
||||||
|
|
||||||
|
elif '-xcode-mac' in sys.argv:
|
||||||
|
self.src = os.environ['SOURCE_ROOT'] + '/assets/build'
|
||||||
|
self.dst = (os.environ['TARGET_BUILD_DIR'] + '/' +
|
||||||
|
os.environ['UNLOCALIZED_RESOURCES_FOLDER_PATH'])
|
||||||
|
self.include_pylib = True
|
||||||
|
self.pylib_src_name = 'pylib-apple'
|
||||||
|
self.tex_suffix = '.dds'
|
||||||
|
elif '-xcode-ios' in sys.argv:
|
||||||
|
self.src = os.environ['SOURCE_ROOT'] + '/assets/build'
|
||||||
|
self.dst = (os.environ['TARGET_BUILD_DIR'] + '/' +
|
||||||
|
os.environ['UNLOCALIZED_RESOURCES_FOLDER_PATH'])
|
||||||
|
self.include_pylib = True
|
||||||
|
self.pylib_src_name = 'pylib-apple'
|
||||||
|
self.tex_suffix = '.pvr'
|
||||||
|
else:
|
||||||
|
raise Exception('no valid platform set')
|
||||||
|
|
||||||
|
|
||||||
|
def md5sum(filename: str) -> str:
|
||||||
|
"""Generate an md5sum given a filename."""
|
||||||
|
md5 = hashlib.md5()
|
||||||
|
with open(filename, mode='rb') as infile:
|
||||||
|
for buf in iter(partial(infile.read, 128), b''):
|
||||||
|
md5.update(buf)
|
||||||
|
return md5.hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def _run(cmd: str, echo: bool = False) -> None:
|
||||||
|
"""Run an os command; raise Exception on non-zero return value."""
|
||||||
|
if echo:
|
||||||
|
print(cmd)
|
||||||
|
result = os.system(cmd)
|
||||||
|
if result != 0:
|
||||||
|
raise Exception("error running cmd: '" + cmd + "'")
|
||||||
|
|
||||||
|
|
||||||
|
def _write_payload_file(assets_root: str, full: bool) -> None:
|
||||||
|
if not assets_root.endswith('/'):
|
||||||
|
assets_root = assets_root + '/'
|
||||||
|
|
||||||
|
# Now construct a payload file if we have any files.
|
||||||
|
file_list = []
|
||||||
|
payload_str = ''
|
||||||
|
for root, _subdirs, fnames in os.walk(assets_root):
|
||||||
|
for fname in fnames:
|
||||||
|
if fname.startswith('.'):
|
||||||
|
continue
|
||||||
|
if fname == 'payload_info':
|
||||||
|
continue
|
||||||
|
fpath = os.path.join(root, fname)
|
||||||
|
fpathshort = fpath.replace(assets_root, '')
|
||||||
|
if ' ' in fpathshort:
|
||||||
|
raise Exception("invalid filename found (contains spaces): '" +
|
||||||
|
fpathshort + "'")
|
||||||
|
payload_str += fpathshort + ' ' + md5sum(fpath) + '\n'
|
||||||
|
file_list.append(fpathshort)
|
||||||
|
|
||||||
|
if file_list:
|
||||||
|
# Write the file count, whether this is a 'full' payload, and finally
|
||||||
|
# the file list.
|
||||||
|
payload_str = (str(len(file_list)) + '\n' + ('1' if full else '0') +
|
||||||
|
'\n' + payload_str)
|
||||||
|
payload_path = assets_root + '/payload_info'
|
||||||
|
with open(payload_path, 'w') as outfile:
|
||||||
|
outfile.write(payload_str)
|
||||||
|
else:
|
||||||
|
# Hmm; do we need to build an empty payload in this case?
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def _sync_windows_extras(cfg: Config) -> str:
|
||||||
|
assert cfg.win_extras_src is not None
|
||||||
|
if not os.path.isdir(cfg.win_extras_src):
|
||||||
|
raise Exception('win extras src dir not found: ' + cfg.win_extras_src)
|
||||||
|
|
||||||
|
# Ok, lets do full syncs on each subdir we find so we
|
||||||
|
# properly delete anything in dst that disappeared from src.
|
||||||
|
# Lastly we'll sync over the remaining top level files.
|
||||||
|
# It'll technically be possible to orphaned top level
|
||||||
|
# files in dst, but we should be pulling those into dists
|
||||||
|
# individually by name anyway so it should be safe.
|
||||||
|
for dirname in ('DLLs', 'Lib'):
|
||||||
|
# We also need to be more particular about which pyc files we pull
|
||||||
|
# over. The Python stuff in Extras is also used by some scripts
|
||||||
|
# so there may be arbitrary non-opt pycs hanging around.
|
||||||
|
assert cfg.dst is not None
|
||||||
|
_run(f'mkdir -p "{cfg.dst}/{dirname}"')
|
||||||
|
cmd = ("rsync --recursive --update --delete --delete-excluded "
|
||||||
|
" --prune-empty-dirs"
|
||||||
|
" --include '*.ico' --include '*.cat'"
|
||||||
|
" --include '*.dll' --include '*.pyd'"
|
||||||
|
" --include '*.py' --include '*." + OPT_PYC_SUFFIX + "'"
|
||||||
|
" --include '*/' --exclude '*' \"" +
|
||||||
|
os.path.join(cfg.win_extras_src, dirname) + "/\" "
|
||||||
|
"\"" + cfg.dst + "/" + dirname + "/\"")
|
||||||
|
_run(cmd)
|
||||||
|
|
||||||
|
# Now sync the top level individual files.
|
||||||
|
cmd = ("rsync --update " + cfg.win_extras_src + "/{*.dll,*.exe}"
|
||||||
|
" \"" + cfg.dst + "/\"")
|
||||||
|
_run(cmd)
|
||||||
|
|
||||||
|
# We may want to add some site-packages on top; say where they should go.
|
||||||
|
return 'Lib'
|
||||||
|
|
||||||
|
|
||||||
|
def _sync_pylib(cfg: Config) -> str:
|
||||||
|
assert cfg.pylib_src_name is not None
|
||||||
|
assert cfg.dst is not None
|
||||||
|
_run(f'mkdir -p "{cfg.dst}/pylib"')
|
||||||
|
cmd = (f"rsync --recursive --update --delete --delete-excluded "
|
||||||
|
f" --prune-empty-dirs"
|
||||||
|
f" --include '*.py' --include '*.{OPT_PYC_SUFFIX}'"
|
||||||
|
f" --include '*/' --exclude '*'"
|
||||||
|
f" \"{cfg.src}/{cfg.pylib_src_name}/\" "
|
||||||
|
f"\"{cfg.dst}/pylib/\"")
|
||||||
|
_run(cmd)
|
||||||
|
|
||||||
|
# We may want to add some site-packages on top; say where they should go.
|
||||||
|
return 'pylib'
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
"""Stage assets for a build."""
|
||||||
|
|
||||||
|
cfg = Config()
|
||||||
|
cfg.parse_args()
|
||||||
|
|
||||||
|
# Ok, now for every top level dir in src, come up with a nice single
|
||||||
|
# command to sync the needed subset of it to dst.
|
||||||
|
|
||||||
|
# We can now use simple speedy timestamp based updates since
|
||||||
|
# we no longer have to try to preserve timestamps to get .pyc files
|
||||||
|
# to behave (hooray!)
|
||||||
|
|
||||||
|
site_packages_target: Optional[str] = None
|
||||||
|
|
||||||
|
# Do our stripped down pylib dir for platforms that use that.
|
||||||
|
if cfg.include_pylib:
|
||||||
|
site_packages_target = _sync_pylib(cfg)
|
||||||
|
|
||||||
|
# On windows we need to pull in some dlls and this and that
|
||||||
|
# (we also include a non-stripped-down set of python libs).
|
||||||
|
if cfg.win_extras_src is not None:
|
||||||
|
site_packages_target = _sync_windows_extras(cfg)
|
||||||
|
|
||||||
|
# Lastly, drop our site-packages into the python sys dir if desired.
|
||||||
|
# Ideally we should have a separate directory for these, but
|
||||||
|
# there's so few of them that this is simpler at the moment..
|
||||||
|
if site_packages_target is not None:
|
||||||
|
cmd = (f"rsync --recursive "
|
||||||
|
f" --include '*.py' --include '*.{OPT_PYC_SUFFIX}'"
|
||||||
|
f" --include '*/' --exclude '*'"
|
||||||
|
f" \"{cfg.src}/pylib-site-packages/\" "
|
||||||
|
f"\"{cfg.dst}/{site_packages_target}/\"")
|
||||||
|
_run(cmd)
|
||||||
|
|
||||||
|
# Now standard common game data.
|
||||||
|
assert cfg.dst is not None
|
||||||
|
_run('mkdir -p "' + cfg.dst + '/data"')
|
||||||
|
cmd = ("rsync --recursive --update --delete --delete-excluded"
|
||||||
|
" --prune-empty-dirs")
|
||||||
|
|
||||||
|
if cfg.include_scripts:
|
||||||
|
cmd += " --include '*.py' --include '*." + OPT_PYC_SUFFIX + "'"
|
||||||
|
|
||||||
|
if cfg.include_textures:
|
||||||
|
assert cfg.tex_suffix is not None
|
||||||
|
cmd += " --include '*" + cfg.tex_suffix + "'"
|
||||||
|
|
||||||
|
if cfg.include_audio:
|
||||||
|
cmd += " --include '*.ogg'"
|
||||||
|
|
||||||
|
if cfg.include_fonts:
|
||||||
|
cmd += " --include '*.fdata'"
|
||||||
|
|
||||||
|
if cfg.include_json:
|
||||||
|
cmd += " --include '*.json'"
|
||||||
|
|
||||||
|
if cfg.include_models:
|
||||||
|
cmd += " --include '*.bob'"
|
||||||
|
|
||||||
|
if cfg.include_collide_models:
|
||||||
|
cmd += " --include '*.cob'"
|
||||||
|
|
||||||
|
cmd += (" --include='*/' --exclude='*' \"" + cfg.src + "/data/\" \"" +
|
||||||
|
cfg.dst + "/data/\"")
|
||||||
|
_run(cmd)
|
||||||
|
|
||||||
|
# On Android we need to build a payload file so it knows
|
||||||
|
# what to pull out of the apk.
|
||||||
|
if cfg.include_payload_file:
|
||||||
|
_write_payload_file(cfg.dst, cfg.is_payload_full)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
@ -196,7 +196,8 @@ class App:
|
|||||||
print(f'{CLRRED} Found "{line}"{CLREND}')
|
print(f'{CLRRED} Found "{line}"{CLREND}')
|
||||||
print(CLRRED +
|
print(CLRRED +
|
||||||
f'All {len(auto_changes)} errors are auto-fixable;'
|
f'All {len(auto_changes)} errors are auto-fixable;'
|
||||||
' pass --fix to apply corrections.' + CLREND)
|
' run tools/update_project --fix to apply corrections.' +
|
||||||
|
CLREND)
|
||||||
sys.exit(255)
|
sys.exit(255)
|
||||||
else:
|
else:
|
||||||
for i, change in enumerate(auto_changes):
|
for i, change in enumerate(auto_changes):
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user