This commit is contained in:
Eric 2024-04-24 18:16:38 -07:00
parent b09bdbb45f
commit 3fb10b7394
No known key found for this signature in database
GPG Key ID: 89C93F0F8D6D5A98
11 changed files with 152 additions and 48 deletions

56
.efrocachemap generated
View File

@ -4056,26 +4056,26 @@
"build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1",
"build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae",
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "7c8972ca3658d967ba43011362b087aa", "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "6c7508f088e0b061b0d443a51e6a852b",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "27be65844fce312e8c8e13e9d187798d", "build/prefab/full/linux_arm64_gui/release/ballisticakit": "f6598ab7468acdec2ccc730d21e56fb0",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "e746d122dd08a3f92e4ec28cda6c1fdc", "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "532877b098f19696d19b1997a09f826d",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "e0bdc0e743747562e7bcc2404343ded1", "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "63c466b9d41dbb548473bb98c2091fd2",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "5d7250aeef4af4159e64c03e40607c92", "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "61b5b25750bb5ab345013cb985f86551",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "106939b64bd0c1a7084e31d94e4482e8", "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "5d7052354d7d68337e1ee853f6b9a757",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "08c321f9fbd4299b51710ef2cf332f14", "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "20f068094c73beaa8c231ed058f32a28",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "5d8949348cb0f8fa18d756132cb24b21", "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "848c1e4376474504f0d03fbecb2bf933",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "815364e6a7f8b5e7f9531cc9bc7840b5", "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "a699fb523ed5b9959014ceab98fe1c2b",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "483f8f40534fde1ce6c76e446e1bd249", "build/prefab/full/mac_arm64_gui/release/ballisticakit": "456f860358d90f3dfaddffc5bd5d5eaa",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "76f4a382be4ff02bd511349f185f9c94", "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "b53a1d296d46fd782210dc3fe41b3306",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "8bf5d5375b20828572a7488d283ffebb", "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "63689cb81be98b9731b47757ff1768ed",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "452ee2b082927abfc5e995e7d6d005e2", "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "f7a100bdb8431973c969b9817ce3239a",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "93260f68603774826cf48e4556d0fd36", "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "db2eca1c74a8eaf6169ab638223a15ed",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "89bef7d763799ca4a9b86f3819e9af7c", "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "1a44aae131f2208742d7c04d905ea2ea",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "7775b58359a970118938b7629613ae28", "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "7c7c4c3a64a3c82d6e89b7846f6f4ad4",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "af85416a3e610a12c54bf1a151a78750", "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "9ac60da735da0e07d82cabbb0a23e3d2",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "86a5ecaa46411e8226d6b0a2b1311297", "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "3756377852b3e9ad4bbf079dee7a9e73",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "135935d46ebc78492f05cd23331685c1", "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "89c9207961bc55ea4ccaf2a9c64d4e1d",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "5a3d820dbf01c0243c574b0594965994", "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "517249ffc950c28968a94e97dd6a4205",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "d838781c9192c6d1db86bd540478aadf", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "d838781c9192c6d1db86bd540478aadf",
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "b9f7438c554cdadedd0d71aabb3a1d86", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "b9f7438c554cdadedd0d71aabb3a1d86",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "d838781c9192c6d1db86bd540478aadf", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "d838781c9192c6d1db86bd540478aadf",
@ -4092,14 +4092,14 @@
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "5471a38a2f6cc967b6518b7976d48cae", "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "5471a38a2f6cc967b6518b7976d48cae",
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "807b53c6ca38c392a7477f250d3a85e5", "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "807b53c6ca38c392a7477f250d3a85e5",
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "5471a38a2f6cc967b6518b7976d48cae", "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "5471a38a2f6cc967b6518b7976d48cae",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "08d57b27324c81c15b548378297d8bee", "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "eda0b395775cdedf080e0d80aa7fbe7c",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "ddaa4e0263a93bf07ad0b32e88473b95", "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "d8d746575d21eb26b56319f2d23b142d",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "0655da25b5d61c49dc768c3bcf871a86", "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "6b6078e47e9993a9b2d9e08dd24adf22",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "019338079c4c8e486bddb1fcde266d30", "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "ed7c7cd11e33fd5c9fa1bf7015cfc431",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "72c8127f2d20fb08381e9427da4277b0", "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "a69b5ba73dac421de34352f480dca39a",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "e020ac5ad52e12a74f562c4133d843ea", "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "48fc85dbf186820241733d2d447f299f",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "1142e87548995e74ea749eac87a8fc66", "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "957d5f95c29d018025fc4517acb2216d",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "b687a3dcf04060a3c4635e5c5e883b5b", "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "d65f649dc8b6a1dbd0686ea95294605e",
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
"src/assets/ba_data/python/babase/_mgen/enums.py": "b611c090513a21e2fe90e56582724e9d", "src/assets/ba_data/python/babase/_mgen/enums.py": "b611c090513a21e2fe90e56582724e9d",
"src/ballistica/base/mgen/pyembed/binding_base.inc": "72bfed2cce8ff19741989dec28302f3f", "src/ballistica/base/mgen/pyembed/binding_base.inc": "72bfed2cce8ff19741989dec28302f3f",

View File

@ -1,4 +1,4 @@
### 1.7.34 (build 21810, api 8, 2024-04-23) ### 1.7.34 (build 21812, api 8, 2024-04-24)
- Bumped Python version from 3.11 to 3.12 for all builds and project tools. One - Bumped Python version from 3.11 to 3.12 for all builds and project tools. One
of the things this means is that we can use `typing.override` instead of the of the things this means is that we can use `typing.override` instead of the
`typing_extensions` version so the annoying requirement of installing `typing_extensions` version so the annoying requirement of installing
@ -38,9 +38,12 @@
counts keep increasing in the future, the time expense of spinning up a new counts keep increasing in the future, the time expense of spinning up a new
Python process per pcommand decreases, making pcommandbatch less of a win. Python process per pcommand decreases, making pcommandbatch less of a win.
Please holler if you have any thoughts on this. Please holler if you have any thoughts on this.
- Renamed the `prereqs` Makefile target to `env`. This is easier to type and - Renamed the `prereqs` Makefile target to `env`. This is more concise and feels
feels more accurate now that the target sets up things like the Python virtual more accurate now that the target sets up things such as the Python virtual
environment and generally gets the project environment ready to use. environment and generally gets the project environment ready to use.
- (build 21810) Fixed an issue where AppSubsystems could get inited multiple
times (due to functools.cached_property no longer being thread-safe in Python
3.12).
### 1.7.33 (build 21795, api 8, 2024-03-24) ### 1.7.33 (build 21795, api 8, 2024-03-24)
- Stress test input-devices are now a bit smarter; they won't press any buttons - Stress test input-devices are now a bit smarter; they won't press any buttons

View File

@ -1197,11 +1197,15 @@ DMAKE = $(MAKE) MAKEFLAGS= MKFLAGS= MAKELEVEL=
# if using this on other platforms. # if using this on other platforms.
CPUS = $(shell getconf _NPROCESSORS_ONLN || echo 8) CPUS = $(shell getconf _NPROCESSORS_ONLN || echo 8)
PROJ_DIR = $(abspath $(CURDIR)) PROJ_DIR = $(abspath $(CURDIR))
# IMPORTANT: Make sure anything using these values has built env first (so
# that pcommand exists).
VERSION = $(shell $(PCOMMAND) version version) VERSION = $(shell $(PCOMMAND) version version)
BUILD_NUMBER = $(shell $(PCOMMAND) version build) BUILD_NUMBER = $(shell $(PCOMMAND) version build)
STAGE_BUILD = $(PROJ_DIR)/$(PCOMMAND) stage_build
BUILD_DIR = $(PROJ_DIR)/build BUILD_DIR = $(PROJ_DIR)/build
LAZYBUILDDIR = .cache/lazybuild LAZYBUILDDIR = .cache/lazybuild
STAGE_BUILD = $(PROJ_DIR)/$(PCOMMAND) stage_build
# Things to ignore when doing root level cleans. Note that we exclude build # Things to ignore when doing root level cleans. Note that we exclude build
# and just blow that away manually; it might contain git repos or other things # and just blow that away manually; it might contain git repos or other things
@ -1288,8 +1292,9 @@ tools/efrotools/pyver.py
$(PCOMMAND) checkenv && mkdir -p .cache && touch .cache/checkenv; \ $(PCOMMAND) checkenv && mkdir -p .cache && touch .cache/checkenv; \
fi fi
$(PCOMMANDBATCHBIN): src/tools/pcommandbatch/pcommandbatch.c \ $(PCOMMANDBATCHBIN): src/tools/pcommandbatch/pcommandbatch.c \
src/tools/pcommandbatch/cJSON.c src/tools/pcommandbatch/cJSON.c
@$(MAKE) tools/pcommand
@$(PCOMMAND) build_pcommandbatch $^ $@ @$(PCOMMAND) build_pcommandbatch $^ $@
# CMake build-type lowercase # CMake build-type lowercase

View File

@ -1,8 +1,9 @@
ansiwrap==0.8.4 ansiwrap==0.8.4
cpplint==1.6.1 cpplint==1.6.1
dmgbuild==1.6.1
filelock==3.13.4 filelock==3.13.4
furo==2024.1.29 furo==2024.1.29
mypy==1.9.0 mypy==1.10.0
pbxproj==4.1.0 pbxproj==4.1.0
pdoc==14.4.0 pdoc==14.4.0
pur==7.3.1 pur==7.3.1

View File

@ -12,9 +12,6 @@ ignore_missing_imports = True
[mypy-pylint.*] [mypy-pylint.*]
ignore_missing_imports = True ignore_missing_imports = True
[mypy-ansiwrap.*]
ignore_missing_imports = True
[mypy-xml.*] [mypy-xml.*]
ignore_missing_imports = True ignore_missing_imports = True

View File

@ -9,7 +9,8 @@ import logging
from enum import Enum from enum import Enum
from typing import TYPE_CHECKING, TypeVar, override from typing import TYPE_CHECKING, TypeVar, override
from concurrent.futures import ThreadPoolExecutor from concurrent.futures import ThreadPoolExecutor
from functools import cached_property from threading import RLock
from efro.call import tpartial from efro.call import tpartial
@ -45,6 +46,8 @@ if TYPE_CHECKING:
T = TypeVar('T') T = TypeVar('T')
Tsub = TypeVar('Tsub', bound='AppSubsystem')
class App: class App:
"""A class for high level app functionality and state. """A class for high level app functionality and state.
@ -219,6 +222,13 @@ class App:
] ]
self._pool_thread_count = 0 self._pool_thread_count = 0
# We hold a lock while lazy-loading our subsystem properties so
# we don't spin up any subsystem more than once, but the lock is
# recursive so that the subsystems can instantiate other
# subsystems.
self._subsystem_property_lock = RLock()
self._subsystem_property_data: dict[str, AppSubsystem | bool] = {}
def postinit(self) -> None: def postinit(self) -> None:
"""Called after we've been inited and assigned to babase.app. """Called after we've been inited and assigned to babase.app.
@ -331,12 +341,63 @@ class App:
def mode_selector(self, selector: babase.AppModeSelector) -> None: def mode_selector(self, selector: babase.AppModeSelector) -> None:
self._mode_selector = selector self._mode_selector = selector
def _get_subsystem_property(
self, ssname: str, create_call: Callable[[], AppSubsystem | None]
) -> AppSubsystem | None:
# Quick-out: if a subsystem object is present, just return it;
# no locking necessary.
val = self._subsystem_property_data.get(ssname)
if val is not None:
if val is False:
# False means subsystem is confirmed as not present.
return None
if val is not True:
# A subsystem has been set. Return it.
return val
# Anything else (no val present or val True) requires locking.
with self._subsystem_property_lock:
val = self._subsystem_property_data.get(ssname)
if val is not None:
if val is False:
# False means confirmed as not present.
return None
if val is True:
# True means this property is already being loaded;
# not good.
raise RuntimeError(
f'Recursive subsystem load detected for {ssname}'
)
# Must be an instantiated subsystem. Noice.
return val
# Ok, there's nothing here for it. Instantiate and set it
# while we hold the lock. Set a placeholder value of True
# first so we know if something tries to recursively
# instantiate us while we're instantiating.
self._subsystem_property_data[ssname] = True
# Do our one attempt to create the singleton.
val = create_call()
self._subsystem_property_data[ssname] = (
False if val is None else val
)
return val
# __FEATURESET_APP_SUBSYSTEM_PROPERTIES_BEGIN__ # __FEATURESET_APP_SUBSYSTEM_PROPERTIES_BEGIN__
# This section generated by batools.appmodule; do not edit. # This section generated by batools.appmodule; do not edit.
@cached_property @property
def classic(self) -> ClassicSubsystem | None: def classic(self) -> ClassicSubsystem | None:
"""Our classic subsystem (if available).""" """Our classic subsystem (if available)."""
return self._get_subsystem_property(
'classic', self._create_classic_subsystem
) # type: ignore
@staticmethod
def _create_classic_subsystem() -> ClassicSubsystem | None:
# pylint: disable=cyclic-import # pylint: disable=cyclic-import
try: try:
@ -349,9 +410,15 @@ class App:
logging.exception('Error importing baclassic.') logging.exception('Error importing baclassic.')
return None return None
@cached_property @property
def plus(self) -> PlusSubsystem | None: def plus(self) -> PlusSubsystem | None:
"""Our plus subsystem (if available).""" """Our plus subsystem (if available)."""
return self._get_subsystem_property(
'plus', self._create_plus_subsystem
) # type: ignore
@staticmethod
def _create_plus_subsystem() -> PlusSubsystem | None:
# pylint: disable=cyclic-import # pylint: disable=cyclic-import
try: try:
@ -364,9 +431,15 @@ class App:
logging.exception('Error importing baplus.') logging.exception('Error importing baplus.')
return None return None
@cached_property @property
def ui_v1(self) -> UIV1Subsystem: def ui_v1(self) -> UIV1Subsystem:
"""Our ui_v1 subsystem (always available).""" """Our ui_v1 subsystem (always available)."""
return self._get_subsystem_property(
'ui_v1', self._create_ui_v1_subsystem
) # type: ignore
@staticmethod
def _create_ui_v1_subsystem() -> UIV1Subsystem:
# pylint: disable=cyclic-import # pylint: disable=cyclic-import
from bauiv1 import UIV1Subsystem from bauiv1 import UIV1Subsystem

View File

@ -52,7 +52,7 @@ if TYPE_CHECKING:
# Build number and version of the ballistica binary we expect to be # Build number and version of the ballistica binary we expect to be
# using. # using.
TARGET_BALLISTICA_BUILD = 21810 TARGET_BALLISTICA_BUILD = 21812
TARGET_BALLISTICA_VERSION = '1.7.34' TARGET_BALLISTICA_VERSION = '1.7.34'

View File

@ -39,7 +39,7 @@ auto main(int argc, char** argv) -> int {
namespace ballistica { namespace ballistica {
// These are set automatically via script; don't modify them here. // These are set automatically via script; don't modify them here.
const int kEngineBuildNumber = 21810; const int kEngineBuildNumber = 21812;
const char* kEngineVersion = "1.7.34"; const char* kEngineVersion = "1.7.34";
const int kEngineApiVersion = 8; const int kEngineApiVersion = 8;

View File

@ -94,12 +94,28 @@ def generate_app_module(
# so we need to be consistent. # so we need to be consistent.
if fset.allow_as_soft_requirement: if fset.allow_as_soft_requirement:
contents += ( contents += (
# f'\n'
# f'_{fset.name}_init_lock = Lock()\n'
f'\n' f'\n'
f'@cached_property\n' # f'@cached_property\n'
f'@property\n'
f'def {fset.name}(self) -> {classname} | None:\n' f'def {fset.name}(self) -> {classname} | None:\n'
f' """Our {fset.name} subsystem (if available)."""\n' f' """Our {fset.name} subsystem (if available)."""\n'
f' return self._get_subsystem_property(\n'
f" '{fset.name}', "
f'self._create_{fset.name}_subsystem\n'
f' ) # type: ignore\n'
f'\n'
f'@staticmethod\n'
f'def _create_{fset.name}_subsystem()'
f' -> {classname} | None:\n'
f' # pylint: disable=cyclic-import\n' f' # pylint: disable=cyclic-import\n'
f'\n' f'\n'
# f' # cached_property is not thread safe as of'
# f' Python 3.12, so we\n'
# f' # need to wrangle that ourself'
# f' to avoid multiple instantiations.\n'
# f'\n'
f' try:\n' f' try:\n'
f' from {modname} import {classname}\n' f' from {modname} import {classname}\n'
f'\n' f'\n'
@ -114,10 +130,19 @@ def generate_app_module(
else: else:
contents += ( contents += (
f'\n' f'\n'
f'@cached_property\n' # f'@cached_property\n'
'@property\n'
f'def {fset.name}(self) -> {classname}:\n' f'def {fset.name}(self) -> {classname}:\n'
f' """Our {fset.name} subsystem' f' """Our {fset.name} subsystem'
' (always available)."""\n' ' (always available)."""\n'
f' return self._get_subsystem_property(\n'
f" '{fset.name}', "
f'self._create_{fset.name}_subsystem\n'
f' ) # type: ignore\n'
f'\n'
f'@staticmethod\n'
f'def _create_{fset.name}_subsystem()'
f' -> {classname}:\n'
f' # pylint: disable=cyclic-import\n' f' # pylint: disable=cyclic-import\n'
f'\n' f'\n'
f' from {modname} import {classname}\n' f' from {modname} import {classname}\n'

View File

@ -78,7 +78,8 @@ def pcommand_main(globs: dict[str, Any]) -> None:
): ):
raise RuntimeError( raise RuntimeError(
'Unexpected Python environment;' 'Unexpected Python environment;'
' we expect to be running using .venv/bin/pythonX.Y' f' we expect to be running under something like'
f" .venv/bin/pythonX.Y; found '{abs_exe_path}'."
) )
cur_paths_str = os.environ.get('PATH') cur_paths_str = os.environ.get('PATH')

View File

@ -271,8 +271,7 @@ def build_apple(arch: str, debug: bool = False) -> None:
'\t# Apply target Python patches\n' '\t# Apply target Python patches\n'
f'\tcd $$(PYTHON_SRCDIR-$({tword})) && ' f'\tcd $$(PYTHON_SRCDIR-$({tword})) && '
'patch -p1 < $(PROJECT_DIR)/patch/Python/Python.patch\n' 'patch -p1 < $(PROJECT_DIR)/patch/Python/Python.patch\n'
f'\t/opt/homebrew/opt/python@3.12/bin/python3.12' f'\t../../tools/pcommand python_apple_patch'
' ../../tools/pcommand python_apple_patch'
f' $$(PYTHON_SRCDIR-$({tword}))\n' f' $$(PYTHON_SRCDIR-$({tword}))\n'
), ),
count=1, count=1,