More spring-cleaning on build setup

This commit is contained in:
Eric Froemling 2020-04-20 00:13:26 -07:00
parent ec898e3971
commit 5114280d0a
7 changed files with 199 additions and 161 deletions

View File

@ -1096,6 +1096,7 @@
<w>msbuild</w>
<w>mshell</w>
<w>msvccompiler</w>
<w>mtarget</w>
<w>mtime</w>
<w>mtrans</w>
<w>mtvos</w>

View File

@ -8,6 +8,7 @@
<inspection_tool class="ProblematicWhitespace" enabled="true" level="WARNING" enabled_by_default="true">
<scope name="NonPython" level="WARNING" enabled="false" />
</inspection_tool>
<inspection_tool class="PyArgumentListInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyBroadExceptionInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PyMethodMayBeStaticInspection" enabled="true" level="INFORMATION" enabled_by_default="true" />
<inspection_tool class="PyPep8Inspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">

View File

@ -275,8 +275,6 @@ class SoundtrackEditWindow(ba.Window):
ba.widget(edit=prev_type_button, down_widget=btn)
prev_type_button = btn
ba.textwidget(parent=row, size=(10, 32), text='') # spacing
# (looks like a PyCharm false positive)
# noinspection PyArgumentList
btn = ba.buttonwidget(
parent=row,
size=(50, 32),

View File

@ -363,7 +363,6 @@ class BaseEnumValue(TypedValue[T]):
else:
# At this point we assume its an enum value
try:
# noinspection PyArgumentList
self._enumtype(data)
except ValueError:
if error:
@ -377,7 +376,6 @@ class BaseEnumValue(TypedValue[T]):
def filter_output(self, data: Any) -> Any:
if self._allow_none and data is None:
return None
# noinspection PyArgumentList
return self._enumtype(data)

View File

@ -1,5 +1,5 @@
<!-- THIS FILE IS AUTO GENERATED; DO NOT EDIT BY HAND -->
<h4><em>last updated on 2020-04-15 for Ballistica version 1.5.0 build 20001</em></h4>
<h4><em>last updated on 2020-04-20 for Ballistica version 1.5.0 build 20001</em></h4>
<p>This page documents the Python classes and functions in the 'ba' module,
which are the ones most relevant to modding in Ballistica. If you come across something you feel should be included here or could be better explained, please <a href="mailto:support@froemling.net">let me know</a>. Happy modding!</p>
<hr>

View File

@ -29,12 +29,25 @@ from pathlib import Path
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from typing import List
from typing import List, Sequence
CLRBLU = '\033[94m' # Blue.
CLRHDR = '\033[95m' # Header.
CLREND = '\033[0m' # End.
# Python modules we require for this project.
# (module name, required version, pip package (if it differs from module name))
REQUIRED_PYTHON_MODULES = [
('pylint', [2, 4, 4], None),
('mypy', [0, 770], None),
('yapf', [0, 29, 0], None),
('typing_extensions', None, None),
('pytz', None, None),
('yaml', None, 'PyYAML'),
('requests', None, None),
('pytest', None, None),
]
# Parts of full-tests suite we only run on particular days.
# (This runs in listed order so should be randomized by hand to avoid
# clustering similar tests too much)
@ -68,6 +81,14 @@ class SourceCategory(Enum):
WIN = 'win_src'
class PrefabTarget(Enum):
"""Types of prefab builds able to be run."""
DEBUG = 'debug'
DEBUG_BUILD = 'debug-build'
RELEASE = 'release'
RELEASE_BUILD = 'release-build'
def _checkpaths(inpaths: List[str], category: SourceCategory,
target: str) -> bool:
# pylint: disable=too-many-branches
@ -170,16 +191,12 @@ def lazy_build(target: str, category: SourceCategory, command: str) -> None:
Path(target).touch()
def archive_old_builds() -> None:
def archive_old_builds(ssh_server: str, builds_dir: str,
ssh_args: List[str]) -> None:
"""Stuff our old public builds into the 'old' dir.
(called after we push newer ones)
"""
if len(sys.argv) < 3:
raise Exception('invalid arguments')
ssh_server = sys.argv[2]
builds_dir = sys.argv[3]
ssh_args = sys.argv[4:]
def ssh_run(cmd: str) -> str:
val: str = subprocess.check_output(['ssh'] + ssh_args +
@ -407,3 +424,140 @@ def gen_fulltest_buildfile_linux() -> None:
with open('_fulltest_buildfile_linux', 'w') as outfile:
outfile.write('\n'.join(lines))
def make_prefab(target: PrefabTarget) -> None:
"""Run prefab builds for the current platform."""
from efrotools import run
import platform
system = platform.system()
machine = platform.machine()
if system == 'Darwin':
# Currently there's just x86_64 on mac; will need to revisit when arm
# cpus happen.
base = 'mac'
elif system == 'Linux':
# If it looks like we're in Windows Subsystem for Linux,
# go with the Windows version.
if 'microsoft' in platform.uname()[3].lower():
base = 'windows'
else:
# We currently only support x86_64 linux.
if machine == 'x86_64':
base = 'linux'
else:
raise RuntimeError(
f'make_prefab: unsupported linux machine type:'
f' {machine}.')
else:
raise RuntimeError(f'make_prefab: unrecognized platform:'
f' {platform.system()}.')
if target is PrefabTarget.DEBUG:
mtarget = f'prefab-{base}-debug'
elif target is PrefabTarget.DEBUG_BUILD:
mtarget = f'prefab-{base}-debug-build'
elif target is PrefabTarget.RELEASE:
mtarget = f'prefab-{base}-release'
elif target is PrefabTarget.RELEASE_BUILD:
mtarget = f'prefab-{base}-release-build'
else:
raise RuntimeError(f'Invalid target: {target}')
run(f'make {target}')
def _vstr(nums: Sequence[int]) -> str:
return '.'.join(str(i) for i in nums)
def checkenv() -> None:
"""Check for tools necessary to build and run the app."""
from efrotools import PYTHON_BIN
print('Checking environment...', flush=True)
# Make sure they've got curl.
if subprocess.run(['which', 'curl'], check=False,
capture_output=True).returncode != 0:
raise RuntimeError(f'curl is required; please install it.')
# Make sure they've got our target python version.
if subprocess.run(['which', PYTHON_BIN], check=False,
capture_output=True).returncode != 0:
raise RuntimeError(f'{PYTHON_BIN} is required; please install it.')
# Make sure they've got pip for that python version.
if subprocess.run(f"{PYTHON_BIN} -m pip --version",
shell=True,
check=False,
capture_output=True).returncode != 0:
raise RuntimeError(
'pip (for {PYTHON_BIN}) is required; please install it.')
# Check for some required python modules.
for modname, minver, packagename in REQUIRED_PYTHON_MODULES:
if packagename is None:
packagename = modname
if minver is not None:
results = subprocess.run(f'{PYTHON_BIN} -m {modname} --version',
shell=True,
check=False,
capture_output=True)
else:
results = subprocess.run(f'{PYTHON_BIN} -c "import {modname}"',
shell=True,
check=False,
capture_output=True)
if results.returncode != 0:
raise RuntimeError(
f'{packagename} (for {PYTHON_BIN}) is required.\n'
f'To install it, try: "{PYTHON_BIN}'
f' -m pip install {packagename}"')
if minver is not None:
ver_line = results.stdout.decode().splitlines()[0]
assert modname in ver_line
vnums = [int(x) for x in ver_line.split()[-1].split('.')]
assert len(vnums) == len(minver)
if vnums < minver:
raise RuntimeError(
f'{packagename} ver. {_vstr(minver)} or newer required;'
f' found {_vstr(vnums)}')
print('Environment ok.', flush=True)
def get_pip_reqs() -> List[str]:
"""Return the pip requirements needed to build/run stuff."""
out: List[str] = []
for module in REQUIRED_PYTHON_MODULES:
name = module[0] if module[2] is None else module[2]
assert isinstance(name, str)
out.append(name)
return out
def update_makebob() -> None:
"""Build fresh make_bob binaries for all relevant platforms."""
print('Building mac_x86_64...', flush=True)
env = dict(os.environ)
env['CMAKE_BUILD_TYPE'] = 'Release'
subprocess.run(['make', 'cmake-build'], check=True, env=env)
subprocess.run(
[
'cp', '-v', 'ballisticacore-cmake/build/release/make_bob',
'tools/make_bob/mac_x86_64/'
],
check=True,
)
print('Building linux_x86_64...', flush=True)
subprocess.run(['make', 'linux-build'], check=True, env=env)
subprocess.run(
[
'cp', '-v', 'build/linux-release/make_bob',
'tools/make_bob/linux_x86_64/'
],
check=True,
)
print('All builds complete!', flush=True)

View File

@ -32,7 +32,6 @@ to functionality contained in efrotools or other standalone tool modules.
from __future__ import annotations
import os
import subprocess
import sys
from typing import TYPE_CHECKING
@ -47,20 +46,7 @@ from efrotools.snippets import ( # pylint: disable=unused-import
makefile_target_list, spelling, spelling_all, compile_python_files, pytest)
if TYPE_CHECKING:
from typing import Optional, List, Sequence
# Python modules we require for this project.
# (module name, required version, pip package (if it differs from module name))
REQUIRED_PYTHON_MODULES = [
('pylint', [2, 4, 4], None),
('mypy', [0, 770], None),
('yapf', [0, 29, 0], None),
('typing_extensions', None, None),
('pytz', None, None),
('yaml', None, 'PyYAML'),
('requests', None, None),
('pytest', None, None),
]
from typing import Optional
def archive_old_builds() -> None:
@ -69,7 +55,12 @@ def archive_old_builds() -> None:
(called after we push newer ones)
"""
import batools.build
batools.build.archive_old_builds()
if len(sys.argv) < 3:
raise Exception('invalid arguments')
ssh_server = sys.argv[2]
builds_dir = sys.argv[3]
ssh_args = sys.argv[4:]
batools.build.archive_old_builds(ssh_server, builds_dir, ssh_args)
def gen_fulltest_buildfile_android() -> None:
@ -153,6 +144,7 @@ def check_clean_safety() -> None:
def get_master_asset_src_dir() -> None:
"""Print master-asset-source dir for this repo."""
import subprocess
# Ok, for now lets simply use our hard-coded master-src
# path if we're on master in and not otherwise. Should
@ -177,6 +169,7 @@ def androidaddr() -> None:
command line args: archive_dir architecture addr
"""
import subprocess
if len(sys.argv) != 5:
print('ERROR: expected 4 args; got ' + str(len(sys.argv) - 1) + '.\n' +
'Usage: "tools/snippets android_addr'
@ -417,6 +410,7 @@ def efrocache_get() -> None:
def get_modern_make() -> None:
"""Print name of a modern make command."""
import platform
import subprocess
# Mac gnu make is outdated (due to newer versions using GPL3 I believe).
# so let's return 'gmake' there which will point to homebrew make which
@ -436,6 +430,7 @@ def get_modern_make() -> None:
def warm_start_asset_build() -> None:
"""Prep asset builds to run faster."""
import subprocess
from pathlib import Path
from efrotools import get_config
public: bool = get_config(PROJROOT)['public']
@ -452,10 +447,6 @@ def warm_start_asset_build() -> None:
check=True)
def _vstr(nums: Sequence[int]) -> str:
return '.'.join(str(i) for i in nums)
def update_docs_md() -> None:
"""Updates docs markdown files if necessary."""
# pylint: disable=too-many-locals
@ -511,168 +502,63 @@ def update_docs_md() -> None:
print(f'{docs_path} is up to date.')
def _get_pip_reqs() -> List[str]:
out: List[str] = []
for module in REQUIRED_PYTHON_MODULES:
name = module[0] if module[2] is None else module[2]
assert isinstance(name, str)
out.append(name)
return out
def list_pip_reqs() -> None:
"""List Python Pip packages needed for this project."""
print(' '.join(_get_pip_reqs()))
from batools.build import get_pip_reqs
print(' '.join(get_pip_reqs()))
def install_pip_reqs() -> None:
"""Install Python Pip packages needed for this project."""
import subprocess
from efrotools import PYTHON_BIN
from batools.build import get_pip_reqs
subprocess.run([PYTHON_BIN, '-m', 'pip', 'install', '--upgrade'] +
_get_pip_reqs(),
get_pip_reqs(),
check=True)
print(f'All pip requirements installed!')
def checkenv() -> None:
"""Check for tools necessary to build and run the app."""
from efrotools import PYTHON_BIN
print('Checking environment...', flush=True)
# Make sure they've got curl.
if subprocess.run(['which', 'curl'], check=False,
capture_output=True).returncode != 0:
raise CleanError(f'curl is required; please install it.')
# Make sure they've got our target python version.
if subprocess.run(['which', PYTHON_BIN], check=False,
capture_output=True).returncode != 0:
raise CleanError(f'{PYTHON_BIN} is required; please install it.')
# Make sure they've got pip for that python version.
if subprocess.run(f"{PYTHON_BIN} -m pip --version",
shell=True,
check=False,
capture_output=True).returncode != 0:
raise CleanError(
'pip (for {PYTHON_BIN}) is required; please install it.')
# Check for some required python modules.
for modname, minver, packagename in REQUIRED_PYTHON_MODULES:
if packagename is None:
packagename = modname
if minver is not None:
results = subprocess.run(f'{PYTHON_BIN} -m {modname} --version',
shell=True,
check=False,
capture_output=True)
else:
results = subprocess.run(f'{PYTHON_BIN} -c "import {modname}"',
shell=True,
check=False,
capture_output=True)
if results.returncode != 0:
raise CleanError(f'{packagename} (for {PYTHON_BIN}) is required.\n'
f'To install it, try: "{PYTHON_BIN}'
f' -m pip install {packagename}"')
if minver is not None:
ver_line = results.stdout.decode().splitlines()[0]
assert modname in ver_line
vnums = [int(x) for x in ver_line.split()[-1].split('.')]
assert len(vnums) == len(minver)
if vnums < minver:
raise CleanError(
f'{packagename} ver. {_vstr(minver)} or newer required;'
f' found {_vstr(vnums)}')
print('Environment ok.', flush=True)
import batools.build
try:
batools.build.checkenv()
except RuntimeError as exc:
raise CleanError(exc)
def make_prefab() -> None:
"""Run prefab builds for the current platform."""
from efrotools import run
import platform
system = platform.system()
machine = platform.machine()
if system == 'Darwin':
# Currently there's just x86_64 on mac; will need to revisit when arm
# cpus happen.
base = 'mac'
elif system == 'Linux':
# If it looks like we're in Windows Subsystem for Linux,
# go with the Windows version.
if 'microsoft' in platform.uname()[3].lower():
base = 'windows'
else:
# We currently only support x86_64 linux.
if machine == 'x86_64':
base = 'linux'
else:
raise RuntimeError(
f'make_prefab: unsupported linux machine type:'
f' {machine}.')
else:
raise RuntimeError(f'make_prefab: unrecognized platform:'
f' {platform.system()}.')
import batools.build
if len(sys.argv) != 3:
raise RuntimeError('Expected one argument')
arg = sys.argv[2]
if arg == 'debug':
target = f'prefab-{base}-debug'
elif arg == 'debug-build':
target = f'prefab-{base}-debug-build'
elif arg == 'release':
target = f'prefab-{base}-release'
elif arg == 'release-build':
target = f'prefab-{base}-release-build'
else:
raise RuntimeError(f'Invalid target: {arg}')
run(f'make {target}')
target = batools.build.PrefabTarget(sys.argv[2])
batools.build.make_prefab(target)
def update_makebob() -> None:
"""Build fresh make_bob binaries for all relevant platforms."""
print('Building mac_x86_64...', flush=True)
env = dict(os.environ)
env['CMAKE_BUILD_TYPE'] = 'Release'
subprocess.run(['make', 'cmake-build'], check=True, env=env)
subprocess.run(
[
'cp', '-v', 'ballisticacore-cmake/build/release/make_bob',
'tools/make_bob/mac_x86_64/'
],
check=True,
)
print('Building linux_x86_64...', flush=True)
subprocess.run(['make', 'linux-build'], check=True, env=env)
subprocess.run(
[
'cp', '-v', 'build/linux-release/make_bob',
'tools/make_bob/linux_x86_64/'
],
check=True,
)
print('All builds complete!', flush=True)
import batools.build
batools.build.update_makebob()
def lazybuild() -> None:
"""Testing."""
from batools.build import lazy_build, SourceCategory
"""Run a build command only if an input has changed."""
import subprocess
import batools.build
if len(sys.argv) < 5:
raise CleanError('Expected at least 3 args')
try:
category = SourceCategory(sys.argv[2])
category = batools.build.SourceCategory(sys.argv[2])
except ValueError as exc:
raise CleanError(exc)
target = sys.argv[3]
cmd = ' '.join(sys.argv[4:])
lazy_build(target, category, cmd)
command = ' '.join(sys.argv[4:])
try:
batools.build.lazy_build(target, category, command)
except subprocess.CalledProcessError as exc:
raise CleanError(exc)
if __name__ == '__main__':