diff --git a/.efrocachemap b/.efrocachemap
index 571dca2e..e76d1774 100644
--- a/.efrocachemap
+++ b/.efrocachemap
@@ -4135,16 +4135,16 @@
"assets/build/windows/x64/vc_redist.x64.exe": "https://files.ballistica.net/cache/ba1/ea/19/8b8787d81abcdce158ba608cd24f",
"assets/build/windows/x64/vcruntime140_1d.dll": "https://files.ballistica.net/cache/ba1/11/d8/ff6344b429b00c24d9a1930d4338",
"assets/build/windows/x64/vcruntime140d.dll": "https://files.ballistica.net/cache/ba1/20/33/0825e11e6518f87ece3009309933",
- "build/prefab/linux-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/29/9c/24a918c046b06f010d9948458a09",
- "build/prefab/linux-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/2e/1c/2285cc92d83ce3a32b26c020cb71",
- "build/prefab/linux/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/24/b6/9410d8cf8be5aaf2ffad07964950",
- "build/prefab/linux/release/ballisticacore": "https://files.ballistica.net/cache/ba1/48/c4/2bdd6802858b92c348df702c9dcd",
- "build/prefab/mac-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/b4/ca/0a1426dabc53a9f90a6beb011423",
- "build/prefab/mac-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/f8/ef/4186b927c2675c3e4dfa19ba180d",
- "build/prefab/mac/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/29/59/60175945534d87709dfc29d1b180",
- "build/prefab/mac/release/ballisticacore": "https://files.ballistica.net/cache/ba1/5c/b8/16b868c1bbd8b1be2ebaf4da4d31",
- "build/prefab/windows-server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/30/6c/33b6b194062212beeae3043515a3",
- "build/prefab/windows-server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/4b/24/c54be077112185f6a3d2c67641ea",
- "build/prefab/windows/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/ee/6e/a9d59e81b549b992673d20f84f11",
- "build/prefab/windows/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/5b/73/97159eb1d7dfb4018c5a1241f164"
+ "build/prefab/linux-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/fc/3d/ab2ccd1f76fec48d1d1f8cc07aa4",
+ "build/prefab/linux-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/e2/e1/672e2ccaceadf3b0867bf3b887a4",
+ "build/prefab/linux/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/5f/9d/90533da6e9d91dc6b932a2aa7f43",
+ "build/prefab/linux/release/ballisticacore": "https://files.ballistica.net/cache/ba1/30/ea/6af215aa0cab66e46c7041a7b091",
+ "build/prefab/mac-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/55/66/b8bc31f6818606e282eda887939f",
+ "build/prefab/mac-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/52/e7/2419b41d3524735dc709338c4290",
+ "build/prefab/mac/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/11/b5/5ee7f3ba18e2683d56b8a020b39f",
+ "build/prefab/mac/release/ballisticacore": "https://files.ballistica.net/cache/ba1/24/5f/6953fd0f2b47e943ea734bc14911",
+ "build/prefab/windows-server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/1b/fb/739c5d5dc13218efdeaaa020c9f9",
+ "build/prefab/windows-server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/01/15/75f7b94e3608435a4609a3992dbc",
+ "build/prefab/windows/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/9f/9d/cf77bfbd79aed7178d9674b3af14",
+ "build/prefab/windows/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/c9/b2/6863b197eac679f85a5414525aa9"
}
\ No newline at end of file
diff --git a/.idea/dictionaries/ericf.xml b/.idea/dictionaries/ericf.xml
index 74ab5b89..a631cdc7 100644
--- a/.idea/dictionaries/ericf.xml
+++ b/.idea/dictionaries/ericf.xml
@@ -1196,6 +1196,7 @@
modder
modders
modename
+ modestr
modpack
modtimes
moduledir
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2696a3d2..20550909 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+### 1.5.6 (20072)
+- Mouse wheel now works in manual camera mode on more platforms.
+- Lots of internal event-handling cleanup/reorganization in preparation for Android 1.5 update.
+- Server scripts now run in opt mode in release builds so they can use bundled .opt-1.pyc files.
+- More misc bug fixes and tidying.
+
### 1.5.5 (20069)
- Cleaned up Windows version packaging.
- More misc bug fixes.
diff --git a/Makefile b/Makefile
index 47257e12..79ede417 100644
--- a/Makefile
+++ b/Makefile
@@ -188,14 +188,15 @@ prefab-mac-server-debug-build: prereqs assets-cmake \
@${STAGE_ASSETS} -cmakeserver build/prefab/mac-server/debug/dist
build/prefab/mac-server/debug/ballisticacore_server: \
- assets/src/server/ballisticacore_server.py
- @cp $< $@
+ assets/src/server/ballisticacore_server.py tools/batools/snippets.py
+ @tools/snippets stage_server_file debug $< $@
build/prefab/mac-server/debug/config_template.yaml: \
assets/src/server/config_template.yaml \
tools/batools/build.py \
+ tools/batools/snippets.py \
tools/bacommon/servermanager.py
- @tools/snippets filter_server_config $< $@
+ @tools/snippets stage_server_file debug $< $@
build/prefab/mac-server/debug/README.txt: \
assets/src/server/README.txt
@@ -219,14 +220,15 @@ prefab-mac-server-release-build: prereqs assets-cmake \
@${STAGE_ASSETS} -cmakeserver build/prefab/mac-server/release/dist
build/prefab/mac-server/release/ballisticacore_server: \
- assets/src/server/ballisticacore_server.py
- @cp $< $@
+ assets/src/server/ballisticacore_server.py tools/batools/snippets.py
+ @tools/snippets stage_server_file release $< $@
build/prefab/mac-server/release/config_template.yaml: \
assets/src/server/config_template.yaml \
tools/batools/build.py \
+ tools/batools/snippets.py \
tools/bacommon/servermanager.py
- @tools/snippets filter_server_config $< $@
+ @tools/snippets stage_server_file release $< $@
build/prefab/mac-server/release/README.txt: \
assets/src/server/README.txt
@@ -276,14 +278,15 @@ prefab-linux-server-debug-build: prereqs assets-cmake \
@${STAGE_ASSETS} -cmakeserver build/prefab/linux-server/debug/dist
build/prefab/linux-server/debug/ballisticacore_server: \
- assets/src/server/ballisticacore_server.py
- @cp $< $@
+ assets/src/server/ballisticacore_server.py tools/batools/snippets.py
+ @tools/snippets stage_server_file debug $< $@
build/prefab/linux-server/debug/config_template.yaml: \
assets/src/server/config_template.yaml \
tools/batools/build.py \
+ tools/batools/snippets.py \
tools/bacommon/servermanager.py
- @tools/snippets filter_server_config $< $@
+ @tools/snippets stage_server_file debug $< $@
build/prefab/linux-server/debug/README.txt: \
assets/src/server/README.txt
@@ -307,14 +310,15 @@ prefab-linux-server-release-build: prereqs assets-cmake \
@${STAGE_ASSETS} -cmakeserver build/prefab/linux-server/release/dist
build/prefab/linux-server/release/ballisticacore_server: \
- assets/src/server/ballisticacore_server.py
- @cp $< $@
+ assets/src/server/ballisticacore_server.py tools/batools/snippets.py
+ @tools/snippets stage_server_file release $< $@
build/prefab/linux-server/release/config_template.yaml: \
assets/src/server/config_template.yaml \
tools/batools/build.py \
+ tools/batools/snippets.py \
tools/bacommon/servermanager.py
- @tools/snippets filter_server_config $< $@
+ @tools/snippets stage_server_file release $< $@
build/prefab/linux-server/release/README.txt: \
assets/src/server/README.txt
@@ -376,25 +380,26 @@ build/prefab/windows-server/debug/dist/ballisticacore_headless.exe: .efrocachema
@tools/snippets efrocache_get $@
build/prefab/windows-server/debug/ballisticacore_server.py: \
- assets/src/server/ballisticacore_server.py
- @cp $< $@
+ assets/src/server/ballisticacore_server.py tools/batools/snippets.py
+ @tools/snippets stage_server_file debug $< $@
build/prefab/windows-server/debug/launch_ballisticacore_server.bat: \
- assets/src/server/launch_ballisticacore_server.bat
- @cp $< $@
+ assets/src/server/launch_ballisticacore_server.bat tools/batools/snippets.py
+ @tools/snippets stage_server_file debug $< $@
build/prefab/windows-server/debug/config_template.yaml: \
assets/src/server/config_template.yaml \
tools/batools/build.py \
+ tools/batools/snippets.py \
tools/bacommon/servermanager.py
- @tools/snippets filter_server_config $< $@
+ @tools/snippets stage_server_file debug $< $@
build/prefab/windows-server/debug/README.txt: \
assets/src/server/README.txt
@cp $< $@
RUN_PREFAB_WINDOWS_SERVER_RELEASE = cd build/prefab/windows-server/release \
- && dist/python.exe ballisticacore_server.py
+ && dist/python.exe -O ballisticacore_server.py
prefab-windows-server-release: prefab-windows-server-release-build
@tools/snippets ensure_prefab_platform windows
@@ -414,18 +419,19 @@ build/prefab/windows-server/release/dist/ballisticacore_headless.exe: .efrocache
@tools/snippets efrocache_get $@
build/prefab/windows-server/release/ballisticacore_server.py: \
- assets/src/server/ballisticacore_server.py
- @cp $< $@
+ assets/src/server/ballisticacore_server.py tools/batools/snippets.py
+ @tools/snippets stage_server_file release $< $@
build/prefab/windows-server/release/launch_ballisticacore_server.bat: \
- assets/src/server/launch_ballisticacore_server.bat
- @cp $< $@
+ assets/src/server/launch_ballisticacore_server.bat tools/batools/snippets.py
+ @tools/snippets stage_server_file release $< $@
build/prefab/windows-server/release/config_template.yaml: \
assets/src/server/config_template.yaml \
tools/batools/build.py \
+ tools/batools/snippets.py \
tools/bacommon/servermanager.py
- @tools/snippets filter_server_config $< $@
+ @tools/snippets stage_server_file release $< $@
build/prefab/windows-server/release/README.txt: \
assets/src/server/README.txt
diff --git a/assets/src/server/ballisticacore_server.py b/assets/src/server/ballisticacore_server.py
index 969d5884..a0de2d87 100755
--- a/assets/src/server/ballisticacore_server.py
+++ b/assets/src/server/ballisticacore_server.py
@@ -51,7 +51,7 @@ if TYPE_CHECKING:
# Not sure how much versioning we'll do with this, but this will get
# printed at startup in case we need it.
-VERSION_STR = '1.0.1'
+VERSION_STR = '1.0.2'
class ServerManagerApp:
@@ -106,9 +106,13 @@ class ServerManagerApp:
# Print basic usage info in interactive mode.
if sys.stdin.isatty():
+ if __debug__:
+ modestr = '(debug mode)'
+ else:
+ modestr = '(opt mode)'
print(f'{Clr.CYN}{Clr.BLD}BallisticaCore server'
f' manager {VERSION_STR}'
- f' starting up...{Clr.RST}\n'
+ f' starting up {modestr}...{Clr.RST}\n'
f'{Clr.CYN}Use the "mgr" object to make'
f' live server adjustments.\n'
f'Type "help(mgr)" for more information.{Clr.RST}')
diff --git a/assets/src/server/launch_ballisticacore_server.bat b/assets/src/server/launch_ballisticacore_server.bat
index a5315816..547324d6 100644
--- a/assets/src/server/launch_ballisticacore_server.bat
+++ b/assets/src/server/launch_ballisticacore_server.bat
@@ -1,4 +1,3 @@
:: Simply run the ballisticacore_server.py script with the bundled
-:: python interpreter. Run in opt-mode so we pick up all the
-:: bundled .opt-1.pyc files too.
-dist\\python.exe -O ballisticacore_server.py
+:: Python interpreter.
+dist\\python.exe ballisticacore_server.py
diff --git a/tools/batools/snippets.py b/tools/batools/snippets.py
new file mode 100644
index 00000000..7324cc21
--- /dev/null
+++ b/tools/batools/snippets.py
@@ -0,0 +1,618 @@
+# Copyright (c) 2011-2020 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.
+# -----------------------------------------------------------------------------
+"""Standard snippets that can be pulled into project snippets scripts.
+
+A snippet is a mini-program that directly takes input from stdin and does
+some focused task. This module consists of ballistica-specific ones.
+"""
+from __future__ import annotations
+
+# Note: import as little as possible here at the module level to
+# keep launch times fast for small snippets.
+import sys
+from typing import TYPE_CHECKING
+
+from efrotools.snippets import PROJROOT
+
+if TYPE_CHECKING:
+ from typing import Optional
+
+
+def stage_server_file() -> None:
+ """Stage files for the server environment with some filtering."""
+ import os
+ import subprocess
+ import batools.build
+ from efro.error import CleanError
+ from efrotools import replace_one
+ if len(sys.argv) != 5:
+ raise CleanError('Expected 3 args (mode, infile, outfile).')
+ mode, infilename, outfilename = sys.argv[2], sys.argv[3], sys.argv[4]
+ if mode not in ('debug', 'release'):
+ raise CleanError(f"Invalid mode '{mode}'; expected debug or release.")
+
+ print(f'Building server file: {os.path.basename(outfilename)}')
+
+ basename = os.path.basename(infilename)
+ if basename == 'config_template.yaml':
+ # Inject all available config values into the config file.
+ batools.build.filter_server_config(str(PROJROOT), infilename,
+ outfilename)
+ elif basename == 'ballisticacore_server.py':
+ # Run Python in opt mode for release builds.
+ with open(infilename) as infile:
+ lines = infile.read().splitlines()
+ if mode == 'release':
+ lines[0] = replace_one(lines[0], '#!/usr/bin/env python3.7',
+ '#!/usr/bin/env python3.7 -O')
+ with open(outfilename, 'w') as outfile:
+ outfile.write('\n'.join(lines) + '\n')
+ subprocess.run(['chmod', '+x', outfilename], check=True)
+ elif basename == 'launch_ballisticacore_server.bat':
+ # Run Python in opt mode for release builds.
+ with open(infilename) as infile:
+ lines = infile.read().splitlines()
+ if mode == 'release':
+ lines[1] = replace_one(
+ lines[1], ':: Python interpreter.',
+ ':: Python interpreter.'
+ ' (in opt mode so we use bundled .opt-1.pyc files)')
+ lines[2] = replace_one(
+ lines[2], 'dist\\\\python.exe ballisticacore_server.py',
+ 'dist\\\\python.exe -O ballisticacore_server.py')
+ with open(outfilename, 'w') as outfile:
+ outfile.write('\n'.join(lines) + '\n')
+ else:
+ raise CleanError(f"Unknown server file for staging: '{basename}'.")
+
+
+def py_examine() -> None:
+ """Run a python examination at a given point in a given file."""
+ import os
+ from pathlib import Path
+ import efrotools
+ if len(sys.argv) != 7:
+ print('ERROR: expected 7 args')
+ sys.exit(255)
+ filename = Path(sys.argv[2])
+ line = int(sys.argv[3])
+ column = int(sys.argv[4])
+ selection: Optional[str] = (None if sys.argv[5] == '' else sys.argv[5])
+ operation = sys.argv[6]
+
+ # This stuff assumes it is being run from project root.
+ os.chdir(PROJROOT)
+
+ # Set up pypaths so our main distro stuff works.
+ scriptsdir = os.path.abspath(
+ os.path.join(os.path.dirname(sys.argv[0]),
+ '../assets/src/ba_data/python'))
+ toolsdir = os.path.abspath(
+ os.path.join(os.path.dirname(sys.argv[0]), '../tools'))
+ if scriptsdir not in sys.path:
+ sys.path.append(scriptsdir)
+ if toolsdir not in sys.path:
+ sys.path.append(toolsdir)
+ efrotools.py_examine(PROJROOT, filename, line, column, selection,
+ operation)
+
+
+def clean_orphaned_assets() -> None:
+ """Remove asset files that are no longer part of the build."""
+ import os
+ import json
+ import efrotools
+
+ # Operate from dist root..
+ os.chdir(PROJROOT)
+
+ # Our manifest is split into 2 files (public and private)
+ with open('assets/.asset_manifest_public.json') as infile:
+ manifest = set(json.loads(infile.read()))
+ with open('assets/.asset_manifest_private.json') as infile:
+ manifest.update(set(json.loads(infile.read())))
+ for root, _dirs, fnames in os.walk('assets/build'):
+ for fname in fnames:
+ fpath = os.path.join(root, fname)
+ fpathrel = fpath[13:] # paths are relative to assets/build
+ if fpathrel not in manifest:
+ print(f'Removing orphaned asset file: {fpath}')
+ os.unlink(fpath)
+
+ # Lastly, clear empty dirs.
+ efrotools.run('find assets/build -depth -empty -type d -delete')
+
+
+def fix_mac_ssh() -> None:
+ """Turn off mac ssh password access.
+
+ (This totally doesn't belong in this project btw..)
+ """
+ configpath = '/etc/ssh/sshd_config'
+ with open(configpath) as infile:
+ lines = infile.readlines()
+ index = lines.index('#PasswordAuthentication yes\n')
+ lines[index] = 'PasswordAuthentication no\n'
+ index = lines.index('#ChallengeResponseAuthentication yes\n')
+ lines[index] = 'ChallengeResponseAuthentication no\n'
+ index = lines.index('UsePAM yes\n')
+ lines[index] = 'UsePAM no\n'
+ with open(configpath, 'w') as outfile:
+ outfile.write(''.join(lines))
+ print('SSH config updated successfully!')
+
+
+def check_mac_ssh() -> None:
+ """Make sure ssh password access is turned off.
+
+ (This totally doesn't belong here, but I use it it to remind myself to
+ fix mac ssh after system updates which blow away ssh customizations).
+ """
+ with open('/etc/ssh/sshd_config') as infile:
+ lines = infile.read().splitlines()
+ if ('UsePAM yes' in lines or '#PasswordAuthentication yes' in lines
+ or '#ChallengeResponseAuthentication yes' in lines):
+ print('ERROR: ssh config is allowing password access.\n'
+ 'To fix: sudo tools/snippets fix_mac_ssh')
+ sys.exit(255)
+ print('password ssh auth seems disabled; hooray!')
+
+
+def resize_image() -> None:
+ """Resize an image and save it to a new location.
+
+ args: xres, yres, src, dst
+ """
+ import os
+ import efrotools
+ if len(sys.argv) != 6:
+ raise Exception('expected 5 args')
+ width = int(sys.argv[2])
+ height = int(sys.argv[3])
+ src = sys.argv[4]
+ dst = sys.argv[5]
+ if not dst.endswith('.png'):
+ raise RuntimeError(f'dst must be a png; got "{dst}"')
+ if not src.endswith('.png'):
+ raise RuntimeError(f'src must be a png; got "{src}"')
+ print('Creating: ' + os.path.basename(dst), file=sys.stderr)
+ efrotools.run(f'convert "{src}" -resize {width}x{height} "{dst}"')
+
+
+def check_clean_safety() -> None:
+ """Ensure all files are are added to git or in gitignore.
+
+ Use to avoid losing work if we accidentally do a clean without
+ adding something.
+ """
+ import os
+ from efrotools.snippets import check_clean_safety as std_snippet
+
+ # First do standard checks.
+ std_snippet()
+
+ # Then also make sure there are no untracked changes to core files
+ # (since we may be blowing core away here).
+ spinoff_bin = os.path.join(str(PROJROOT), 'tools', 'spinoff')
+ if os.path.exists(spinoff_bin):
+ status = os.system(spinoff_bin + ' cleancheck')
+ if status != 0:
+ sys.exit(255)
+
+
+def archive_old_builds() -> None:
+ """Stuff our old public builds into the 'old' dir.
+
+ (called after we push newer ones)
+ """
+ import batools.build
+ 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 lazy_increment_build() -> None:
+ """Increment build number only if C++ sources have changed.
+
+ This is convenient to place in automatic commit/push scripts.
+ It could make sense to auto update build number when scripts/assets
+ change too, but a build number change requires rebuilding all binaries
+ so I'll leave that as an explicit choice to save work.
+ """
+ import os
+ import subprocess
+ from efro.terminal import Clr
+ from efro.error import CleanError
+ from efrotools import get_files_hash
+ from efrotools.code import get_code_filenames
+ if sys.argv[2:] not in [[], ['--update-hash-only']]:
+ raise CleanError('Invalid arguments')
+ update_hash_only = '--update-hash-only' in sys.argv
+ codefiles = get_code_filenames(PROJROOT)
+ codehash = get_files_hash(codefiles)
+ hashfilename = '.cache/lazy_increment_build'
+ try:
+ with open(hashfilename) as infile:
+ lasthash = infile.read()
+ except FileNotFoundError:
+ lasthash = ''
+ if codehash != lasthash:
+ print(f'{Clr.SMAG}Source(s) changed; incrementing build...{Clr.RST}')
+
+ if not update_hash_only:
+ # Just go ahead and bless; this will increment the build as needed.
+ # subprocess.run(['make', 'bless'], check=True)
+ subprocess.run(['tools/version_utils', 'incrementbuild'],
+ check=True)
+
+ # We probably just changed code, so we need to re-calc the hash.
+ codehash = get_files_hash(codefiles)
+ os.makedirs(os.path.dirname(hashfilename), exist_ok=True)
+ with open(hashfilename, 'w') as outfile:
+ outfile.write(codehash)
+
+
+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
+ # probably make this configurable.
+ output = subprocess.check_output(
+ ['git', 'status', '--branch', '--porcelain']).decode()
+
+ # Also compare repo name to split version of itself to
+ # see if we're outside of core (filtering will cause mismatch if so).
+ if ('origin/master' in output.splitlines()[0]
+ and 'ballistica' + 'core' == 'ballisticacore'):
+
+ # We seem to be in master in core repo; lets do it.
+ print('/Users/ericf/Dropbox/ballisticacore_master_assets')
+ else:
+ # Still need to supply dummy path for makefile if not..
+ print('/__DUMMY_MASTER_SRC_DISABLED_PATH__')
+
+
+def androidaddr() -> None:
+ """Return the source file location for an android program-counter.
+
+ command line args: archive_dir architecture addr
+ """
+ import batools.android
+ from efro.error import CleanError
+ if len(sys.argv) != 5:
+ raise CleanError(f'ERROR: expected 3 args; got {len(sys.argv) - 2}\n'
+ f'Usage: "tools/snippets android_addr'
+ f' "')
+ archive_dir = sys.argv[2]
+ arch = sys.argv[3]
+ addr = sys.argv[4]
+ batools.android.androidaddr(archive_dir=archive_dir, arch=arch, addr=addr)
+
+
+def push_ipa() -> None:
+ """Construct and push ios IPA for testing."""
+ from pathlib import Path
+ import efrotools.ios
+ root = Path(sys.argv[0], '../..').resolve()
+ if len(sys.argv) != 3:
+ raise Exception('expected 1 arg (debug or release)')
+ modename = sys.argv[2]
+ efrotools.ios.push_ipa(root, modename)
+
+
+def printcolors() -> None:
+ """Print all colors available in efro.terminals.TerminalColor."""
+ from efro.error import CleanError
+ from efro.terminal import TerminalColor, Clr
+
+ if Clr.RED == '':
+ raise CleanError('Efro color terminal output is disabled.')
+
+ clrnames = {getattr(Clr, s): s for s in dir(Clr) if s.isupper()}
+
+ # Print everything in Clr (since that's what users should be using
+ # but do it in the order of TerminalColor (since Clr is just a class
+ # so is unordered)
+ for value in TerminalColor:
+ if value is TerminalColor.RESET:
+ continue
+ shortname = f'Clr.{clrnames[value.value]}'
+ longname = f'({value.name})'
+ print(f'{shortname:<12} {longname:<20} {value.value}'
+ f'The quick brown fox jumps over the lazy dog.'
+ f'{TerminalColor.RESET.value}')
+
+
+def gen_fulltest_buildfile_android() -> None:
+ """Generate fulltest command list for jenkins.
+
+ (so we see nice pretty split-up build trees)
+ """
+ import batools.build
+ batools.build.gen_fulltest_buildfile_android()
+
+
+def gen_fulltest_buildfile_windows() -> None:
+ """Generate fulltest command list for jenkins.
+
+ (so we see nice pretty split-up build trees)
+ """
+ import batools.build
+ batools.build.gen_fulltest_buildfile_windows()
+
+
+def gen_fulltest_buildfile_apple() -> None:
+ """Generate fulltest command list for jenkins.
+
+ (so we see nice pretty split-up build trees)
+ """
+ import batools.build
+ batools.build.gen_fulltest_buildfile_apple()
+
+
+def gen_fulltest_buildfile_linux() -> None:
+ """Generate fulltest command list for jenkins.
+
+ (so we see nice pretty split-up build trees)
+ """
+ import batools.build
+ batools.build.gen_fulltest_buildfile_linux()
+
+
+def python_build_apple() -> None:
+ """Build an embeddable python for mac/ios/tvos."""
+ _python_build_apple(debug=False)
+
+
+def python_build_apple_debug() -> None:
+ """Build embeddable python for mac/ios/tvos (dbg ver)."""
+ _python_build_apple(debug=True)
+
+
+def _python_build_apple(debug: bool) -> None:
+ """Build an embeddable python for macOS/iOS/tvOS."""
+ import os
+ from efrotools import pybuild
+ os.chdir(PROJROOT)
+ archs = ('mac', 'ios', 'tvos')
+ if len(sys.argv) != 3:
+ print('ERROR: expected one arg: ' + ', '.join(archs))
+ sys.exit(255)
+ arch = sys.argv[2]
+ if arch not in archs:
+ print('ERROR: invalid arch. valid values are: ' + ', '.join(archs))
+ sys.exit(255)
+ pybuild.build_apple(arch, debug=debug)
+
+
+def python_build_android() -> None:
+ """Build an embeddable Python lib for Android."""
+ _python_build_android(debug=False)
+
+
+def python_build_android_debug() -> None:
+ """Build embeddable Android Python lib (debug ver)."""
+ _python_build_android(debug=True)
+
+
+def _python_build_android(debug: bool) -> None:
+ import os
+ from efrotools import pybuild
+ os.chdir(PROJROOT)
+ archs = ('arm', 'arm64', 'x86', 'x86_64')
+ if len(sys.argv) != 3:
+ print('ERROR: expected one arg: ' + ', '.join(archs))
+ sys.exit(255)
+ arch = sys.argv[2]
+ if arch not in archs:
+ print('ERROR: invalid arch. valid values are: ' + ', '.join(archs))
+ sys.exit(255)
+ pybuild.build_android(str(PROJROOT), arch, debug=debug)
+
+
+def python_android_patch() -> None:
+ """Patches Python to prep for building for Android."""
+ import os
+ from efrotools import pybuild
+ os.chdir(sys.argv[2])
+ pybuild.android_patch()
+
+
+def python_gather() -> None:
+ """Gather build python components into the project.
+
+ This assumes all embeddable py builds have been run successfully.
+ """
+ import os
+ from efrotools import pybuild
+ os.chdir(PROJROOT)
+ pybuild.gather()
+
+
+def capitalize() -> None:
+ """Print args capitalized."""
+ print(' '.join(w.capitalize() for w in sys.argv[2:]))
+
+
+def efrocache_update() -> None:
+ """Build & push files to efrocache for public access."""
+ from efrotools.efrocache import update_cache
+ makefile_dirs = ['', 'assets']
+ update_cache(makefile_dirs)
+
+
+def efrocache_get() -> None:
+ """Get a file from efrocache."""
+ from efrotools.efrocache import get_target
+ if len(sys.argv) != 3:
+ raise RuntimeError('Expected exactly 1 arg')
+ get_target(sys.argv[2])
+
+
+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
+ # should be up to date.
+ if platform.system() == 'Darwin':
+ if subprocess.run(['which', 'gmake'], check=False,
+ capture_output=True).returncode != 0:
+ print(
+ 'WARNING: this requires gmake (mac system make is too old).'
+ " Install it with 'brew install make'",
+ file=sys.stderr,
+ flush=True)
+ print('gmake')
+ else:
+ print('make')
+
+
+def warm_start_asset_build() -> None:
+ """Prep asset builds to run faster."""
+ import os
+ import subprocess
+ from pathlib import Path
+ from efrotools import getconfig
+ public: bool = getconfig(PROJROOT)['public']
+
+ if public:
+ from efrotools.efrocache import warm_start_cache
+ os.chdir(PROJROOT)
+ warm_start_cache()
+ else:
+ # For internal builds we don't use efrocache but we do use an
+ # internal build cache. Download an initial cache/etc. if need be.
+ subprocess.run(
+ [str(Path(PROJROOT, 'tools/convert_util')), '--init-asset-cache'],
+ check=True)
+
+
+def update_docs_md() -> None:
+ """Updates docs markdown files if necessary."""
+ import batools.build
+ batools.build.update_docs_md(check='--check' in sys.argv)
+
+
+def list_pip_reqs() -> None:
+ """List Python Pip packages needed for this project."""
+ 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 efro.terminal import Clr
+ from batools.build import get_pip_reqs
+ subprocess.run([PYTHON_BIN, '-m', 'pip', 'install', '--upgrade'] +
+ get_pip_reqs(),
+ check=True)
+ print(f'{Clr.GRN}All pip requirements installed!{Clr.RST}')
+
+
+def checkenv() -> None:
+ """Check for tools necessary to build and run the app."""
+ import batools.build
+ from efro.error import CleanError
+ try:
+ batools.build.checkenv()
+ except RuntimeError as exc:
+ raise CleanError(exc)
+
+
+def ensure_prefab_platform() -> None:
+ """Ensure we are running on a particular prefab platform."""
+ import batools.build
+ from efro.error import CleanError
+ if len(sys.argv) != 3:
+ raise CleanError('Expected 1 platform name arg.')
+ needed = sys.argv[2]
+ current = batools.build.get_current_prefab_platform()
+ if current != needed:
+ raise CleanError(
+ f'Incorrect platform: we are {current}, this requires {needed}.')
+
+
+def prefab_run_var() -> None:
+ """Print a var for running a prefab run for the current platform.
+
+ We use this mechanism instead of just having a command recursively run
+ a make target so that ctrl-c can be handled cleanly and directly by the
+ command getting run instead of generating extra errors in the recursive
+ processes.
+ """
+ import batools.build
+ if len(sys.argv) != 3:
+ raise RuntimeError('Expected 1 arg.')
+ base = sys.argv[2].replace('-', '_').upper()
+ platform = batools.build.get_current_prefab_platform().upper()
+ print(f'RUN_PREFAB_{platform}_{base}', end='')
+
+
+def make_prefab() -> None:
+ """Run prefab builds for the current platform."""
+ import subprocess
+ import batools.build
+ if len(sys.argv) != 3:
+ raise RuntimeError('Expected one argument')
+ target = batools.build.PrefabTarget(sys.argv[2])
+ platform = batools.build.get_current_prefab_platform()
+ try:
+ subprocess.run(['make', f'prefab-{platform}-{target.value}-build'],
+ check=True)
+ except (Exception, KeyboardInterrupt) as exc:
+ if str(exc):
+ print(f'make_prefab failed with error: {exc}')
+ sys.exit(-1)
+
+
+def update_makebob() -> None:
+ """Build fresh make_bob binaries for all relevant platforms."""
+ import batools.build
+ batools.build.update_makebob()
+
+
+def lazybuild() -> None:
+ """Run a build command only if an input has changed."""
+ import subprocess
+ import batools.build
+ from efro.error import CleanError
+ if len(sys.argv) < 5:
+ raise CleanError('Expected at least 3 args')
+ try:
+ category = batools.build.SourceCategory(sys.argv[2])
+ except ValueError as exc:
+ raise CleanError(exc)
+ target = sys.argv[3]
+ command = ' '.join(sys.argv[4:])
+ try:
+ batools.build.lazybuild(target, category, command)
+ except subprocess.CalledProcessError as exc:
+ raise CleanError(exc)
diff --git a/tools/snippets b/tools/snippets
index 25bb7722..7a5d17eb 100755
--- a/tools/snippets
+++ b/tools/snippets
@@ -32,10 +32,10 @@ from __future__ import annotations
# Note: import as little as possible here at the module level to
# keep launch times fast for small snippets.
-import sys
from typing import TYPE_CHECKING
-# Pull in some standard snippets we want to expose.
+# Pull in the snippets we want to expose. Its more efficient to define them in
+# modules rather than inline here because we'll be able to load them via pyc.
# pylint: disable=unused-import
from efrotools.snippets import (
PROJROOT, snippets_main, formatcode, formatscripts, formatmakefile,
@@ -43,554 +43,22 @@ from efrotools.snippets import (
sync, sync_all, scriptfiles, pycharm, clioncode, androidstudiocode,
makefile_target_list, spelling, spelling_all, pytest, echo,
compile_python_files)
+from batools.snippets import (
+ stage_server_file, py_examine, fix_mac_ssh, check_mac_ssh, resize_image,
+ check_clean_safety, clean_orphaned_assets, archive_old_builds,
+ lazy_increment_build, get_master_asset_src_dir, androidaddr, push_ipa,
+ printcolors, gen_fulltest_buildfile_android,
+ gen_fulltest_buildfile_windows, gen_fulltest_buildfile_apple,
+ gen_fulltest_buildfile_linux, python_build_apple, python_build_apple_debug,
+ python_build_android, python_build_android_debug, python_android_patch,
+ python_gather, capitalize, efrocache_update, efrocache_get,
+ get_modern_make, warm_start_asset_build, update_docs_md, list_pip_reqs,
+ install_pip_reqs, checkenv, ensure_prefab_platform, prefab_run_var,
+ make_prefab, update_makebob, lazybuild)
# pylint: enable=unused-import
if TYPE_CHECKING:
- from typing import Optional
-
-
-def archive_old_builds() -> None:
- """Stuff our old public builds into the 'old' dir.
-
- (called after we push newer ones)
- """
- import batools.build
- 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:
- """Generate fulltest command list for jenkins.
-
- (so we see nice pretty split-up build trees)
- """
- import batools.build
- batools.build.gen_fulltest_buildfile_android()
-
-
-def gen_fulltest_buildfile_windows() -> None:
- """Generate fulltest command list for jenkins.
-
- (so we see nice pretty split-up build trees)
- """
- import batools.build
- batools.build.gen_fulltest_buildfile_windows()
-
-
-def gen_fulltest_buildfile_apple() -> None:
- """Generate fulltest command list for jenkins.
-
- (so we see nice pretty split-up build trees)
- """
- import batools.build
- batools.build.gen_fulltest_buildfile_apple()
-
-
-def gen_fulltest_buildfile_linux() -> None:
- """Generate fulltest command list for jenkins.
-
- (so we see nice pretty split-up build trees)
- """
- import batools.build
- batools.build.gen_fulltest_buildfile_linux()
-
-
-def resize_image() -> None:
- """Resize an image and save it to a new location.
-
- args: xres, yres, src, dst
- """
- import os
- import efrotools
- if len(sys.argv) != 6:
- raise Exception('expected 5 args')
- width = int(sys.argv[2])
- height = int(sys.argv[3])
- src = sys.argv[4]
- dst = sys.argv[5]
- if not dst.endswith('.png'):
- raise RuntimeError(f'dst must be a png; got "{dst}"')
- if not src.endswith('.png'):
- raise RuntimeError(f'src must be a png; got "{src}"')
- print('Creating: ' + os.path.basename(dst), file=sys.stderr)
- efrotools.run(f'convert "{src}" -resize {width}x{height} "{dst}"')
-
-
-def check_clean_safety() -> None:
- """Ensure all files are are added to git or in gitignore.
-
- Use to avoid losing work if we accidentally do a clean without
- adding something.
- """
- import os
- from efrotools.snippets import check_clean_safety as std_snippet
-
- # First do standard checks.
- std_snippet()
-
- # Then also make sure there are no untracked changes to core files
- # (since we may be blowing core away here).
- spinoff_bin = os.path.join(str(PROJROOT), 'tools', 'spinoff')
- if os.path.exists(spinoff_bin):
- status = os.system(spinoff_bin + ' cleancheck')
- if status != 0:
- sys.exit(255)
-
-
-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
- # probably make this configurable.
- output = subprocess.check_output(
- ['git', 'status', '--branch', '--porcelain']).decode()
-
- # Also compare repo name to split version of itself to
- # see if we're outside of core (filtering will cause mismatch if so).
- if ('origin/master' in output.splitlines()[0]
- and 'ballistica' + 'core' == 'ballisticacore'):
-
- # We seem to be in master in core repo; lets do it.
- print('/Users/ericf/Dropbox/ballisticacore_master_assets')
- else:
- # Still need to supply dummy path for makefile if not..
- print('/__DUMMY_MASTER_SRC_DISABLED_PATH__')
-
-
-def androidaddr() -> None:
- """Return the source file location for an android program-counter.
-
- command line args: archive_dir architecture addr
- """
- import batools.android
- from efro.error import CleanError
- if len(sys.argv) != 5:
- raise CleanError(f'ERROR: expected 3 args; got {len(sys.argv) - 2}\n'
- f'Usage: "tools/snippets android_addr'
- f' "')
- archive_dir = sys.argv[2]
- arch = sys.argv[3]
- addr = sys.argv[4]
- batools.android.androidaddr(archive_dir=archive_dir, arch=arch, addr=addr)
-
-
-def python_build_apple() -> None:
- """Build an embeddable python for mac/ios/tvos."""
- _python_build_apple(debug=False)
-
-
-def python_build_apple_debug() -> None:
- """Build embeddable python for mac/ios/tvos (dbg ver)."""
- _python_build_apple(debug=True)
-
-
-def _python_build_apple(debug: bool) -> None:
- """Build an embeddable python for macOS/iOS/tvOS."""
- import os
- from efrotools import pybuild
- os.chdir(PROJROOT)
- archs = ('mac', 'ios', 'tvos')
- if len(sys.argv) != 3:
- print('ERROR: expected one arg: ' + ', '.join(archs))
- sys.exit(255)
- arch = sys.argv[2]
- if arch not in archs:
- print('ERROR: invalid arch. valid values are: ' + ', '.join(archs))
- sys.exit(255)
- pybuild.build_apple(arch, debug=debug)
-
-
-def python_build_android() -> None:
- """Build an embeddable Python lib for Android."""
- _python_build_android(debug=False)
-
-
-def python_build_android_debug() -> None:
- """Build embeddable Android Python lib (debug ver)."""
- _python_build_android(debug=True)
-
-
-def _python_build_android(debug: bool) -> None:
- import os
- from efrotools import pybuild
- os.chdir(PROJROOT)
- archs = ('arm', 'arm64', 'x86', 'x86_64')
- if len(sys.argv) != 3:
- print('ERROR: expected one arg: ' + ', '.join(archs))
- sys.exit(255)
- arch = sys.argv[2]
- if arch not in archs:
- print('ERROR: invalid arch. valid values are: ' + ', '.join(archs))
- sys.exit(255)
- pybuild.build_android(str(PROJROOT), arch, debug=debug)
-
-
-def python_android_patch() -> None:
- """Patches Python to prep for building for Android."""
- import os
- from efrotools import pybuild
- os.chdir(sys.argv[2])
- pybuild.android_patch()
-
-
-def python_gather() -> None:
- """Gather build python components into the project.
-
- This assumes all embeddable py builds have been run successfully.
- """
- import os
- from efrotools import pybuild
- os.chdir(PROJROOT)
- pybuild.gather()
-
-
-def clean_orphaned_assets() -> None:
- """Remove asset files that are no longer part of the build."""
- import os
- import json
- import efrotools
-
- # Operate from dist root..
- os.chdir(PROJROOT)
-
- # Our manifest is split into 2 files (public and private)
- with open('assets/.asset_manifest_public.json') as infile:
- manifest = set(json.loads(infile.read()))
- with open('assets/.asset_manifest_private.json') as infile:
- manifest.update(set(json.loads(infile.read())))
- for root, _dirs, fnames in os.walk('assets/build'):
- for fname in fnames:
- fpath = os.path.join(root, fname)
- fpathrel = fpath[13:] # paths are relative to assets/build
- if fpathrel not in manifest:
- print(f'Removing orphaned asset file: {fpath}')
- os.unlink(fpath)
-
- # Lastly, clear empty dirs.
- efrotools.run('find assets/build -depth -empty -type d -delete')
-
-
-def py_examine() -> None:
- """Run a python examination at a given point in a given file."""
- import os
- from pathlib import Path
- import efrotools
- if len(sys.argv) != 7:
- print('ERROR: expected 7 args')
- sys.exit(255)
- filename = Path(sys.argv[2])
- line = int(sys.argv[3])
- column = int(sys.argv[4])
- selection: Optional[str] = (None if sys.argv[5] == '' else sys.argv[5])
- operation = sys.argv[6]
-
- # This stuff assumes it is being run from project root.
- os.chdir(PROJROOT)
-
- # Set up pypaths so our main distro stuff works.
- scriptsdir = os.path.abspath(
- os.path.join(os.path.dirname(sys.argv[0]),
- '../assets/src/ba_data/python'))
- toolsdir = os.path.abspath(
- os.path.join(os.path.dirname(sys.argv[0]), '../tools'))
- if scriptsdir not in sys.path:
- sys.path.append(scriptsdir)
- if toolsdir not in sys.path:
- sys.path.append(toolsdir)
- efrotools.py_examine(PROJROOT, filename, line, column, selection,
- operation)
-
-
-def push_ipa() -> None:
- """Construct and push ios IPA for testing."""
- from pathlib import Path
- import efrotools.ios
- root = Path(sys.argv[0], '../..').resolve()
- if len(sys.argv) != 3:
- raise Exception('expected 1 arg (debug or release)')
- modename = sys.argv[2]
- efrotools.ios.push_ipa(root, modename)
-
-
-def fix_mac_ssh() -> None:
- """Turn off mac ssh password access.
-
- (This totally doesn't belong in this project btw..)
- """
- configpath = '/etc/ssh/sshd_config'
- with open(configpath) as infile:
- lines = infile.readlines()
- index = lines.index('#PasswordAuthentication yes\n')
- lines[index] = 'PasswordAuthentication no\n'
- index = lines.index('#ChallengeResponseAuthentication yes\n')
- lines[index] = 'ChallengeResponseAuthentication no\n'
- index = lines.index('UsePAM yes\n')
- lines[index] = 'UsePAM no\n'
- with open(configpath, 'w') as outfile:
- outfile.write(''.join(lines))
- print('SSH config updated successfully!')
-
-
-def check_mac_ssh() -> None:
- """Make sure ssh password access is turned off.
-
- (This totally doesn't belong here, but I use it it to remind myself to
- fix mac ssh after system updates which blow away ssh customizations).
- """
- with open('/etc/ssh/sshd_config') as infile:
- lines = infile.read().splitlines()
- if ('UsePAM yes' in lines or '#PasswordAuthentication yes' in lines
- or '#ChallengeResponseAuthentication yes' in lines):
- print('ERROR: ssh config is allowing password access.\n'
- 'To fix: sudo tools/snippets fix_mac_ssh')
- sys.exit(255)
- print('password ssh auth seems disabled; hooray!')
-
-
-def capitalize() -> None:
- """Print args capitalized."""
- print(' '.join(w.capitalize() for w in sys.argv[2:]))
-
-
-def efrocache_update() -> None:
- """Build & push files to efrocache for public access."""
- from efrotools.efrocache import update_cache
- makefile_dirs = ['', 'assets']
- update_cache(makefile_dirs)
-
-
-def efrocache_get() -> None:
- """Get a file from efrocache."""
- from efrotools.efrocache import get_target
- if len(sys.argv) != 3:
- raise RuntimeError('Expected exactly 1 arg')
- get_target(sys.argv[2])
-
-
-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
- # should be up to date.
- if platform.system() == 'Darwin':
- if subprocess.run(['which', 'gmake'], check=False,
- capture_output=True).returncode != 0:
- print(
- 'WARNING: this requires gmake (mac system make is too old).'
- " Install it with 'brew install make'",
- file=sys.stderr,
- flush=True)
- print('gmake')
- else:
- print('make')
-
-
-def warm_start_asset_build() -> None:
- """Prep asset builds to run faster."""
- import os
- import subprocess
- from pathlib import Path
- from efrotools import getconfig
- public: bool = getconfig(PROJROOT)['public']
-
- if public:
- from efrotools.efrocache import warm_start_cache
- os.chdir(PROJROOT)
- warm_start_cache()
- else:
- # For internal builds we don't use efrocache but we do use an
- # internal build cache. Download an initial cache/etc. if need be.
- subprocess.run(
- [str(Path(PROJROOT, 'tools/convert_util')), '--init-asset-cache'],
- check=True)
-
-
-def update_docs_md() -> None:
- """Updates docs markdown files if necessary."""
- import batools.build
- batools.build.update_docs_md(check='--check' in sys.argv)
-
-
-def list_pip_reqs() -> None:
- """List Python Pip packages needed for this project."""
- 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 efro.terminal import Clr
- from batools.build import get_pip_reqs
- subprocess.run([PYTHON_BIN, '-m', 'pip', 'install', '--upgrade'] +
- get_pip_reqs(),
- check=True)
- print(f'{Clr.GRN}All pip requirements installed!{Clr.RST}')
-
-
-def checkenv() -> None:
- """Check for tools necessary to build and run the app."""
- import batools.build
- from efro.error import CleanError
- try:
- batools.build.checkenv()
- except RuntimeError as exc:
- raise CleanError(exc)
-
-
-def ensure_prefab_platform() -> None:
- """Ensure we are running on a particular prefab platform."""
- import batools.build
- from efro.error import CleanError
- if len(sys.argv) != 3:
- raise CleanError('Expected 1 platform name arg.')
- needed = sys.argv[2]
- current = batools.build.get_current_prefab_platform()
- if current != needed:
- raise CleanError(
- f'Incorrect platform: we are {current}, this requires {needed}.')
-
-
-def prefab_run_var() -> None:
- """Print a var for running a prefab run for the current platform.
-
- We use this mechanism instead of just having a command recursively run
- a make target so that ctrl-c can be handled cleanly and directly by the
- command getting run instead of generating extra errors in the recursive
- processes.
- """
- import batools.build
- if len(sys.argv) != 3:
- raise RuntimeError('Expected 1 arg.')
- base = sys.argv[2].replace('-', '_').upper()
- platform = batools.build.get_current_prefab_platform().upper()
- print(f'RUN_PREFAB_{platform}_{base}', end='')
-
-
-def make_prefab() -> None:
- """Run prefab builds for the current platform."""
- import subprocess
- import batools.build
- if len(sys.argv) != 3:
- raise RuntimeError('Expected one argument')
- target = batools.build.PrefabTarget(sys.argv[2])
- platform = batools.build.get_current_prefab_platform()
- try:
- subprocess.run(['make', f'prefab-{platform}-{target.value}-build'],
- check=True)
- except (Exception, KeyboardInterrupt) as exc:
- if str(exc):
- print(f'make_prefab failed with error: {exc}')
- sys.exit(-1)
-
-
-def update_makebob() -> None:
- """Build fresh make_bob binaries for all relevant platforms."""
- import batools.build
- batools.build.update_makebob()
-
-
-def lazybuild() -> None:
- """Run a build command only if an input has changed."""
- import subprocess
- import batools.build
- from efro.error import CleanError
- if len(sys.argv) < 5:
- raise CleanError('Expected at least 3 args')
- try:
- category = batools.build.SourceCategory(sys.argv[2])
- except ValueError as exc:
- raise CleanError(exc)
- target = sys.argv[3]
- command = ' '.join(sys.argv[4:])
- try:
- batools.build.lazybuild(target, category, command)
- except subprocess.CalledProcessError as exc:
- raise CleanError(exc)
-
-
-def filter_server_config() -> None:
- """Add commented-out config options to a server config."""
- import batools.build
- from efro.error import CleanError
- if len(sys.argv) != 4:
- raise CleanError('Expected 2 args (infile and outfile).')
- batools.build.filter_server_config(str(PROJROOT), sys.argv[2], sys.argv[3])
-
-
-def printcolors() -> None:
- """Print all colors available in efro.terminals.TerminalColor."""
- from efro.error import CleanError
- from efro.terminal import TerminalColor, Clr
-
- if Clr.RED == '':
- raise CleanError('Efro color terminal output is disabled.')
-
- clrnames = {getattr(Clr, s): s for s in dir(Clr) if s.isupper()}
-
- # Print everything in Clr (since that's what users should be using
- # but do it in the order of TerminalColor (since Clr is just a class
- # so is unordered)
- for value in TerminalColor:
- if value is TerminalColor.RESET:
- continue
- shortname = f'Clr.{clrnames[value.value]}'
- longname = f'({value.name})'
- print(f'{shortname:<12} {longname:<20} {value.value}'
- f'The quick brown fox jumps over the lazy dog.'
- f'{TerminalColor.RESET.value}')
-
-
-def lazy_increment_build() -> None:
- """Increment build number only if C++ sources have changed.
-
- This is convenient to place in automatic commit/push scripts.
- It could make sense to auto update build number when scripts/assets
- change too, but a build number change requires rebuilding all binaries
- so I'll leave that as an explicit choice to save work.
- """
- import os
- import subprocess
- from efro.terminal import Clr
- from efro.error import CleanError
- from efrotools import get_files_hash
- from efrotools.code import get_code_filenames
- if sys.argv[2:] not in [[], ['--update-hash-only']]:
- raise CleanError('Invalid arguments')
- update_hash_only = '--update-hash-only' in sys.argv
- codefiles = get_code_filenames(PROJROOT)
- codehash = get_files_hash(codefiles)
- hashfilename = '.cache/lazy_increment_build'
- try:
- with open(hashfilename) as infile:
- lasthash = infile.read()
- except FileNotFoundError:
- lasthash = ''
- if codehash != lasthash:
- print(f'{Clr.SMAG}Source(s) changed; incrementing build...{Clr.RST}')
-
- if not update_hash_only:
- # Just go ahead and bless; this will increment the build as needed.
- # subprocess.run(['make', 'bless'], check=True)
- subprocess.run(['tools/version_utils', 'incrementbuild'],
- check=True)
-
- # We probably just changed code, so we need to re-calc the hash.
- codehash = get_files_hash(codefiles)
- os.makedirs(os.path.dirname(hashfilename), exist_ok=True)
- with open(hashfilename, 'w') as outfile:
- outfile.write(codehash)
-
+ pass
if __name__ == '__main__':
snippets_main(globals())