polishing up pcommandbatch on my flight home

This commit is contained in:
Eric 2023-08-18 19:23:09 -07:00
parent 66d644108d
commit 7643ebce10
No known key found for this signature in database
GPG Key ID: 89C93F0F8D6D5A98
11 changed files with 510 additions and 359 deletions

32
.efrocachemap generated
View File

@ -4076,18 +4076,18 @@
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "7b5a0ecb206e6e99bc226b450947f574", "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "7b5a0ecb206e6e99bc226b450947f574",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "3ec06df77ccbd6692f70627590839015", "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "3ec06df77ccbd6692f70627590839015",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "6d0aaabc7b99cc3ede5e929243978996", "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "6d0aaabc7b99cc3ede5e929243978996",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "6d1fe60a2a3ec603957cbc7423eae8bc", "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "da63fc9c35a40a5dd00b635a25f8c6f3",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "3ccba6e3f58feaa072e586a931e4fd66", "build/prefab/full/mac_arm64_gui/release/ballisticakit": "3ccba6e3f58feaa072e586a931e4fd66",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "83d14fc9336afa5dc41ec366b137203e", "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "731a2915a6171ef062731c955ce08e88",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "98a5504c530c7e7332c7a36e74768cda", "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "98a5504c530c7e7332c7a36e74768cda",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "d0cfd400a198391887c9254f80acef48", "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "fc296240aea46b34c2cbc025469c0b35",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "2de6690d43b4e0ca1f025db203e61105", "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "2de6690d43b4e0ca1f025db203e61105",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "a6f8edb46a3651a609575d07b0df2c7f", "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "907aa9778e4d5de273c8ab0371693973",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "f5931ba9f402cb06ae3fac1435fe373b", "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "f5931ba9f402cb06ae3fac1435fe373b",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "df37f9ec11f003f192b3f58c071393f0", "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "80044ca1925fda3eff45413fd95dfcd5",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "f7b674637dc6e633b37118bd19eb3f6a", "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "2ce86b7c958c9e7c020aa45bac5c6add",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "04900388d6ee576fe6ca7004f03754c5", "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "179578c9032fce4a42c525b1cc5f076f",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "48c7804a59abb43e7e7c7c54fce11dc0", "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "09fa90d666a704c13090e77f840dbd9f",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "85ba4e81a1f7ae2cff4b1355eb49904f", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "85ba4e81a1f7ae2cff4b1355eb49904f",
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "498921f7eb2afd327d4b900cb70e31f9", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "498921f7eb2afd327d4b900cb70e31f9",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "85ba4e81a1f7ae2cff4b1355eb49904f", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "85ba4e81a1f7ae2cff4b1355eb49904f",
@ -4104,14 +4104,14 @@
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "0ab638b6602610bdaf432e3cc2464080", "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "0ab638b6602610bdaf432e3cc2464080",
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "92394eb19387c363471ce134ac9e6a1b", "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "92394eb19387c363471ce134ac9e6a1b",
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "0ab638b6602610bdaf432e3cc2464080", "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "0ab638b6602610bdaf432e3cc2464080",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "1d8634f8423145911a8db28caffa7022", "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "829a4527bff626c891712fc68ecd0b2f",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "12191e80087d08e5def19f9bbdc84b9e", "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "192469453f6c0e5fb54ed2286c44319f",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "4abf18c2871cf29ba5c2ed466cd60ce7", "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "5f3e5de6cc2b29d2183d4ba725a03dc4",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "d267014b78a59c519af3c9c4769372c3", "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "d0d0e606a7b5e8ee5f463ae2589f8054",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "78f112cec4040a2c478793ee93936c8d", "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "6e6e70046ff50d7080395f9b00fcb73f",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "9b5b639759109353e848a67eb092ba8d", "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "77b5b5d744c23471a640f85e611f8ab0",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "83ea8101969c9c030c97f9e529da6ae8", "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "d84545b72fd39dbc4cad3956141e725f",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "54c7978cfc2a1870a8b23aa18b913ebc", "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "646f9d970cdb97c002ac5deded02f934",
"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": "f8cd3af311ac63147882590123b78318", "src/assets/ba_data/python/babase/_mgen/enums.py": "f8cd3af311ac63147882590123b78318",
"src/ballistica/base/mgen/pyembed/binding_base.inc": "eeddad968b176000e31c65be6206a2bc", "src/ballistica/base/mgen/pyembed/binding_base.inc": "eeddad968b176000e31c65be6206a2bc",

View File

@ -515,6 +515,8 @@
<w>clearsign</w> <w>clearsign</w>
<w>clientid</w> <w>clientid</w>
<w>clientlist</w> <w>clientlist</w>
<w>clientprint</w>
<w>clientprints</w>
<w>clienttobasn</w> <w>clienttobasn</w>
<w>clionbin</w> <w>clionbin</w>
<w>clioncode</w> <w>clioncode</w>
@ -532,6 +534,7 @@
<w>clrhdr</w> <w>clrhdr</w>
<w>clrnames</w> <w>clrnames</w>
<w>clrred</w> <w>clrred</w>
<w>clrtp</w>
<w>cmakelist</w> <w>cmakelist</w>
<w>cmakelists</w> <w>cmakelists</w>
<w>cmakemodular</w> <w>cmakemodular</w>

277
Makefile
View File

@ -26,7 +26,7 @@
# List targets in this Makefile and basic descriptions for them. # List targets in this Makefile and basic descriptions for them.
help: help:
@tools/pcommand makefile_target_list Makefile @$(PCOMMAND) makefile_target_list Makefile
# Set env-var BA_ENABLE_COMPILE_COMMANDS_DB=1 to enable creating/updating a # Set env-var BA_ENABLE_COMPILE_COMMANDS_DB=1 to enable creating/updating a
# cmake compile-commands database for use with irony for emacs (and possibly # cmake compile-commands database for use with irony for emacs (and possibly
@ -35,13 +35,14 @@ ifeq ($(BA_ENABLE_COMPILE_COMMANDS_DB),1)
PREREQ_COMPILE_COMMANDS_DB = .cache/compile_commands_db/compile_commands.json PREREQ_COMPILE_COMMANDS_DB = .cache/compile_commands_db/compile_commands.json
endif endif
PCOMMAND = tools/pcommand
# Support for running pcommands in 'batch' mode in which a simple local server # Support for running pcommands in 'batch' mode in which a simple local server
# handles command requests from a lightweight client binary. This largely # handles command requests from a lightweight client binary. This largely
# takes Python's startup time out of the equation, which can add up when # takes Python's startup time out of the equation, which can add up when
# running lots of small pcommands in cases such as asset builds. # running lots of small pcommands in cases such as asset builds.
PCOMMANDBATCHBIN := .cache/pcommandbatch/pcommandbatch PCOMMANDBATCHBIN = .cache/pcommandbatch/pcommandbatch
ifeq ($(BA_PCOMMANDBATCH_DISABLE),1) ifeq ($(BA_PCOMMANDBATCH_DISABLE),1)
PCOMMANDBATCH = tools/pcommand PCOMMANDBATCH = $(PCOMMAND)
else else
PCOMMANDBATCH = $(PCOMMANDBATCHBIN) PCOMMANDBATCH = $(PCOMMANDBATCHBIN)
endif endif
@ -71,52 +72,52 @@ prereqs-clean:
# Build all assets for all platforms. # Build all assets for all platforms.
assets: prereqs meta assets: prereqs meta
@tools/pcommand lazybuild assets_src $(LAZYBUILDDIR)/$@ \ @$(PCOMMAND) lazybuild assets_src $(LAZYBUILDDIR)/$@ \
cd src/assets \&\& $(MAKE) -j$(CPUS) cd src/assets \&\& $(MAKE) -j$(CPUS)
# Build assets required for cmake builds (linux, mac). # Build assets required for cmake builds (linux, mac).
assets-cmake: prereqs meta assets-cmake: prereqs meta
@tools/pcommand lazybuild assets_src $(LAZYBUILDDIR)/$@ \ @$(PCOMMAND) lazybuild assets_src $(LAZYBUILDDIR)/$@ \
cd src/assets \&\& $(MAKE) -j$(CPUS) cmake cd src/assets \&\& $(MAKE) -j$(CPUS) cmake
# Build only script assets for cmake builds (linux, mac). # Build only script assets for cmake builds (linux, mac).
assets-cmake-scripts: prereqs meta assets-cmake-scripts: prereqs meta
@tools/pcommand lazybuild assets_src $(LAZYBUILDDIR)/$@ \ @$(PCOMMAND) lazybuild assets_src $(LAZYBUILDDIR)/$@ \
cd src/assets \&\& $(MAKE) -j$(CPUS) scripts-cmake cd src/assets \&\& $(MAKE) -j$(CPUS) scripts-cmake
# Build assets required for server builds. # Build assets required for server builds.
assets-server: prereqs meta assets-server: prereqs meta
@tools/pcommand lazybuild assets_src $(LAZYBUILDDIR)/$@ \ @$(PCOMMAND) lazybuild assets_src $(LAZYBUILDDIR)/$@ \
cd src/assets \&\& $(MAKE) -j$(CPUS) server cd src/assets \&\& $(MAKE) -j$(CPUS) server
# Build assets required for WINDOWS_PLATFORM windows builds. # Build assets required for WINDOWS_PLATFORM windows builds.
assets-windows: prereqs meta assets-windows: prereqs meta
@tools/pcommand lazybuild assets_src $(LAZYBUILDDIR)/$@ \ @$(PCOMMAND) lazybuild assets_src $(LAZYBUILDDIR)/$@ \
cd src/assets \&\& $(MAKE) -j$(CPUS) win-$(WINDOWS_PLATFORM) cd src/assets \&\& $(MAKE) -j$(CPUS) win-$(WINDOWS_PLATFORM)
# Build assets required for Win32 windows builds. # Build assets required for Win32 windows builds.
assets-windows-Win32: prereqs meta assets-windows-Win32: prereqs meta
@tools/pcommand lazybuild assets_src $(LAZYBUILDDIR)/$@ \ @$(PCOMMAND) lazybuild assets_src $(LAZYBUILDDIR)/$@ \
cd src/assets \&\& $(MAKE) -j$(CPUS) win-Win32 cd src/assets \&\& $(MAKE) -j$(CPUS) win-Win32
# Build assets required for x64 windows builds. # Build assets required for x64 windows builds.
assets-windows-x64: prereqs meta assets-windows-x64: prereqs meta
@tools/pcommand lazybuild assets_src $(LAZYBUILDDIR)/$@ \ @$(PCOMMAND) lazybuild assets_src $(LAZYBUILDDIR)/$@ \
cd src/assets \&\& $(MAKE) -j$(CPUS) win-x64 cd src/assets \&\& $(MAKE) -j$(CPUS) win-x64
# Build assets required for mac xcode builds # Build assets required for mac xcode builds
assets-mac: prereqs meta assets-mac: prereqs meta
@tools/pcommand lazybuild assets_src $(LAZYBUILDDIR)/$@ \ @$(PCOMMAND) lazybuild assets_src $(LAZYBUILDDIR)/$@ \
cd src/assets \&\& $(MAKE) -j$(CPUS) mac cd src/assets \&\& $(MAKE) -j$(CPUS) mac
# Build assets required for ios. # Build assets required for ios.
assets-ios: prereqs meta assets-ios: prereqs meta
@tools/pcommand lazybuild assets_src $(LAZYBUILDDIR)/$@ \ @$(PCOMMAND) lazybuild assets_src $(LAZYBUILDDIR)/$@ \
cd src/assets \&\& $(MAKE) -j$(CPUS) ios cd src/assets \&\& $(MAKE) -j$(CPUS) ios
# Build assets required for android. # Build assets required for android.
assets-android: prereqs meta assets-android: prereqs meta
@tools/pcommand lazybuild assets_src $(LAZYBUILDDIR)/$@ \ @$(PCOMMAND) lazybuild assets_src $(LAZYBUILDDIR)/$@ \
cd src/assets \&\& $(MAKE) -j$(CPUS) android cd src/assets \&\& $(MAKE) -j$(CPUS) android
# Clean all assets. # Clean all assets.
@ -126,7 +127,7 @@ assets-clean:
# Build resources. # Build resources.
resources: prereqs meta resources: prereqs meta
@tools/pcommand lazybuild resources_src $(LAZYBUILDDIR)/$@ \ @$(PCOMMAND) lazybuild resources_src $(LAZYBUILDDIR)/$@ \
cd src/resources \&\& $(MAKE) -j$(CPUS) cd src/resources \&\& $(MAKE) -j$(CPUS)
# Clean resources. # Clean resources.
@ -138,7 +139,7 @@ resources-clean:
# Meta builds can affect sources used by asset builds, resource builds, and # Meta builds can affect sources used by asset builds, resource builds, and
# compiles, so it should be listed as a dependency of any of those. # compiles, so it should be listed as a dependency of any of those.
meta: prereqs meta: prereqs
@tools/pcommand lazybuild meta_src $(LAZYBUILDDIR)/$@ \ @$(PCOMMAND) lazybuild meta_src $(LAZYBUILDDIR)/$@ \
cd src/meta \&\& $(MAKE) -j$(CPUS) cd src/meta \&\& $(MAKE) -j$(CPUS)
# Clean our generated sources. # Clean our generated sources.
@ -164,8 +165,8 @@ clean-list:
# it should not be built in parallel with other targets. # it should not be built in parallel with other targets.
# See py_check_prereqs target for more info. # See py_check_prereqs target for more info.
dummymodules: prereqs meta dummymodules: prereqs meta
@tools/pcommand lazybuild dummymodules_src $(LAZYBUILDDIR)/$@ \ @$(PCOMMAND) lazybuild dummymodules_src $(LAZYBUILDDIR)/$@ \
rm -rf build/dummymodules \&\& ./tools/pcommand gen_dummy_modules rm -rf build/dummymodules \&\& $(PCOMMAND) gen_dummy_modules
dummymodules-clean: dummymodules-clean:
rm -f $(LAZYBUILDDIR)/dummymodules rm -f $(LAZYBUILDDIR)/dummymodules
@ -179,10 +180,10 @@ docs:
$(MAKE) docs-pdoc $(MAKE) docs-pdoc
docs-pdoc: docs-pdoc:
@tools/pcommand gen_docs_pdoc @$(PCOMMAND) gen_docs_pdoc
pcommandbatch_speed_test: prereqs pcommandbatch_speed_test: prereqs
@tools/pcommand pcommandbatch_speed_test $(PCOMMANDBATCH) @$(PCOMMAND) pcommandbatch_speed_test $(PCOMMANDBATCH)
# Tell make which of these targets don't represent files. # Tell make which of these targets don't represent files.
.PHONY: help prereqs prereqs-pre-update prereqs-clean assets assets-cmake \ .PHONY: help prereqs prereqs-pre-update prereqs-clean assets assets-cmake \
@ -202,35 +203,35 @@ pcommandbatch_speed_test: prereqs
# Assemble & run a gui debug build for this platform. # Assemble & run a gui debug build for this platform.
prefab-gui-debug: prefab-gui-debug-build prefab-gui-debug: prefab-gui-debug-build
$($(shell tools/pcommand prefab_run_var gui-debug)) $($(shell $(PCOMMANDBATCH) prefab_run_var gui-debug))
# Assemble & run a gui release build for this platform. # Assemble & run a gui release build for this platform.
prefab-gui-release: prefab-gui-release-build prefab-gui-release: prefab-gui-release-build
$($(shell tools/pcommand prefab_run_var gui-release)) $($(shell $(PCOMMANDBATCH) prefab_run_var gui-release))
# Assemble a debug build for this platform. # Assemble a debug build for this platform.
prefab-gui-debug-build: prefab-gui-debug-build:
@tools/pcommand make_prefab gui-debug @$(PCOMMAND) make_prefab gui-debug
# Assemble a release build for this platform. # Assemble a release build for this platform.
prefab-gui-release-build: prefab-gui-release-build:
@tools/pcommand make_prefab gui-release @$(PCOMMAND) make_prefab gui-release
# Assemble & run a server debug build for this platform. # Assemble & run a server debug build for this platform.
prefab-server-debug: prefab-server-debug-build prefab-server-debug: prefab-server-debug-build
$($(shell tools/pcommand prefab_run_var server-debug)) $($(shell $(PCOMMANDBATCH) prefab_run_var server-debug))
# Assemble & run a server release build for this platform. # Assemble & run a server release build for this platform.
prefab-server-release: prefab-server-release-build prefab-server-release: prefab-server-release-build
$($(shell tools/pcommand prefab_run_var server-release)) $($(shell $(PCOMMANDBATCH) prefab_run_var server-release))
# Assemble a server debug build for this platform. # Assemble a server debug build for this platform.
prefab-server-debug-build: prefab-server-debug-build:
@tools/pcommand make_prefab server-debug @$(PCOMMAND) make_prefab server-debug
# Assemble a server release build for this platform. # Assemble a server release build for this platform.
prefab-server-release-build: prefab-server-release-build:
@tools/pcommand make_prefab server-release @$(PCOMMAND) make_prefab server-release
# Clean all prefab builds. # Clean all prefab builds.
prefab-clean: prefab-clean:
@ -250,11 +251,11 @@ RUN_PREFAB_MAC_ARM64_GUI_DEBUG = cd build/prefab/full/mac_arm64_gui/debug \
&& ./ballisticakit && ./ballisticakit
prefab-mac-x86-64-gui-debug: prefab-mac-x86-64-gui-debug-build prefab-mac-x86-64-gui-debug: prefab-mac-x86-64-gui-debug-build
@tools/pcommand ensure_prefab_platform mac_x86_64 @$(PCOMMAND) ensure_prefab_platform mac_x86_64
@$(RUN_PREFAB_MAC_X86_64_GUI_DEBUG) @$(RUN_PREFAB_MAC_X86_64_GUI_DEBUG)
prefab-mac-arm64-gui-debug: prefab-mac-arm64-gui-debug-build prefab-mac-arm64-gui-debug: prefab-mac-arm64-gui-debug-build
@tools/pcommand ensure_prefab_platform mac_arm64 @$(PCOMMAND) ensure_prefab_platform mac_arm64
@$(RUN_PREFAB_MAC_ARM64_GUI_DEBUG) @$(RUN_PREFAB_MAC_ARM64_GUI_DEBUG)
prefab-mac-x86-64-gui-debug-build: prereqs assets-cmake \ prefab-mac-x86-64-gui-debug-build: prereqs assets-cmake \
@ -280,11 +281,11 @@ RUN_PREFAB_MAC_ARM64_GUI_RELEASE = cd build/prefab/full/mac_arm64_gui/release \
&& ./ballisticakit && ./ballisticakit
prefab-mac-x86-64-gui-release: prefab-mac-x86-64-gui-release-build prefab-mac-x86-64-gui-release: prefab-mac-x86-64-gui-release-build
@tools/pcommand ensure_prefab_platform mac_x86_64 @$(PCOMMAND) ensure_prefab_platform mac_x86_64
@$(RUN_PREFAB_MAC_X86_64_GUI_RELEASE) @$(RUN_PREFAB_MAC_X86_64_GUI_RELEASE)
prefab-mac-arm64-gui-release: prefab-mac-arm64-gui_release-build prefab-mac-arm64-gui-release: prefab-mac-arm64-gui_release-build
@tools/pcommand ensure_prefab_platform mac_arm64 @$(PCOMMAND) ensure_prefab_platform mac_arm64
@$(RUN_PREFAB_MAC_ARM64_GUI_RELEASE) @$(RUN_PREFAB_MAC_ARM64_GUI_RELEASE)
prefab-mac-x86-64-gui-release-build: prereqs assets-cmake \ prefab-mac-x86-64-gui-release-build: prereqs assets-cmake \
@ -310,11 +311,11 @@ RUN_PREFAB_MAC_ARM64_SERVER_DEBUG = cd \
build/prefab/full/mac_arm64_server/debug && ./ballisticakit_server build/prefab/full/mac_arm64_server/debug && ./ballisticakit_server
prefab-mac-x86-64-server-debug: prefab-mac-x86-64-server-debug-build prefab-mac-x86-64-server-debug: prefab-mac-x86-64-server-debug-build
@tools/pcommand ensure_prefab_platform mac_x86_64 @$(PCOMMAND) ensure_prefab_platform mac_x86_64
@$(RUN_PREFAB_MAC_X86_64_SERVER_DEBUG) @$(RUN_PREFAB_MAC_X86_64_SERVER_DEBUG)
prefab-mac-arm64-server-debug: prefab-mac-arm64-server-debug-build prefab-mac-arm64-server-debug: prefab-mac-arm64-server-debug-build
@tools/pcommand ensure_prefab_platform mac_arm64 @$(PCOMMAND) ensure_prefab_platform mac_arm64
@$(RUN_PREFAB_MAC_ARM64_SERVER_DEBUG) @$(RUN_PREFAB_MAC_ARM64_SERVER_DEBUG)
prefab-mac-x86-64-server-debug-build: prereqs assets-server \ prefab-mac-x86-64-server-debug-build: prereqs assets-server \
@ -340,11 +341,11 @@ RUN_PREFAB_MAC_ARM64_SERVER_RELEASE = cd \
build/prefab/full/mac_arm64_server/release && ./ballisticakit_server build/prefab/full/mac_arm64_server/release && ./ballisticakit_server
prefab-mac-x86-64-server-release: prefab-mac-x86-64-server-release-build prefab-mac-x86-64-server-release: prefab-mac-x86-64-server-release-build
@tools/pcommand ensure_prefab_platform mac_x86_64 @$(PCOMMAND) ensure_prefab_platform mac_x86_64
@$(RUN_PREFAB_MAC_X86_64_SERVER_RELEASE) @$(RUN_PREFAB_MAC_X86_64_SERVER_RELEASE)
prefab-mac-arm64-server-release: prefab-mac-arm64-server-release-build prefab-mac-arm64-server-release: prefab-mac-arm64-server-release-build
@tools/pcommand ensure_prefab_platform mac_arm64 @$(PCOMMAND) ensure_prefab_platform mac_arm64
@$(RUN_PREFAB_MAC_ARM64_SERVER_RELEASE) @$(RUN_PREFAB_MAC_ARM64_SERVER_RELEASE)
prefab-mac-x86-64-server-release-build: prereqs assets-server \ prefab-mac-x86-64-server-release-build: prereqs assets-server \
@ -372,11 +373,11 @@ RUN_PREFAB_LINUX_ARM64_GUI_DEBUG = cd \
build/prefab/full/linux_arm64_gui/debug && ./ballisticakit build/prefab/full/linux_arm64_gui/debug && ./ballisticakit
prefab-linux-x86-64-gui-debug: prefab-linux-x86-64-gui-debug-build prefab-linux-x86-64-gui-debug: prefab-linux-x86-64-gui-debug-build
@tools/pcommand ensure_prefab_platform linux_x86_64 @$(PCOMMAND) ensure_prefab_platform linux_x86_64
@$(RUN_PREFAB_LINUX_X86_64_GUI_DEBUG) @$(RUN_PREFAB_LINUX_X86_64_GUI_DEBUG)
prefab-linux-arm64-gui-debug: prefab-linux-arm64-gui-debug-build prefab-linux-arm64-gui-debug: prefab-linux-arm64-gui-debug-build
@tools/pcommand ensure_prefab_platform linux_arm64 @$(PCOMMAND) ensure_prefab_platform linux_arm64
@$(RUN_PREFAB_LINUX_ARM64_GUI_DEBUG) @$(RUN_PREFAB_LINUX_ARM64_GUI_DEBUG)
prefab-linux-x86-64-gui-debug-build: prereqs assets-cmake \ prefab-linux-x86-64-gui-debug-build: prereqs assets-cmake \
@ -402,11 +403,11 @@ RUN_PREFAB_LINUX_ARM64_GUI_RELEASE = cd \
build/prefab/full/linux_arm64_gui/release && ./ballisticakit build/prefab/full/linux_arm64_gui/release && ./ballisticakit
prefab-linux-x86-64-gui-release: prefab-linux-x86-64-gui-release-build prefab-linux-x86-64-gui-release: prefab-linux-x86-64-gui-release-build
@tools/pcommand ensure_prefab_platform linux_x86_64 @$(PCOMMAND) ensure_prefab_platform linux_x86_64
@$(RUN_PREFAB_LINUX_X86_64_GUI_RELEASE) @$(RUN_PREFAB_LINUX_X86_64_GUI_RELEASE)
prefab-linux-arm64-gui-release: prefab-linux-arm64-gui-release-build prefab-linux-arm64-gui-release: prefab-linux-arm64-gui-release-build
@tools/pcommand ensure_prefab_platform linux_arm64 @$(PCOMMAND) ensure_prefab_platform linux_arm64
@$(RUN_PREFAB_LINUX_ARM64_GUI_RELEASE) @$(RUN_PREFAB_LINUX_ARM64_GUI_RELEASE)
prefab-linux-x86-64-gui-release-build: prereqs assets-cmake \ prefab-linux-x86-64-gui-release-build: prereqs assets-cmake \
@ -432,11 +433,11 @@ RUN_PREFAB_LINUX_ARM64_SERVER_DEBUG = cd \
build/prefab/full/linux_arm64_server/debug && ./ballisticakit_server build/prefab/full/linux_arm64_server/debug && ./ballisticakit_server
prefab-linux-x86-64-server-debug: prefab-linux-x86-64-server-debug-build prefab-linux-x86-64-server-debug: prefab-linux-x86-64-server-debug-build
@tools/pcommand ensure_prefab_platform linux_x86_64 @$(PCOMMAND) ensure_prefab_platform linux_x86_64
@$(RUN_PREFAB_LINUX_X86_64_SERVER_DEBUG) @$(RUN_PREFAB_LINUX_X86_64_SERVER_DEBUG)
prefab-linux-arm64-server-debug: prefab-linux-arm64-server-debug-build prefab-linux-arm64-server-debug: prefab-linux-arm64-server-debug-build
@tools/pcommand ensure_prefab_platform linux_arm64 @$(PCOMMAND) ensure_prefab_platform linux_arm64
@$(RUN_PREFAB_LINUX_ARM64_SERVER_DEBUG) @$(RUN_PREFAB_LINUX_ARM64_SERVER_DEBUG)
prefab-linux-x86-64-server-debug-build: prereqs assets-server \ prefab-linux-x86-64-server-debug-build: prereqs assets-server \
@ -464,11 +465,11 @@ RUN_PREFAB_LINUX_ARM64_SERVER_RELEASE = cd \
build/prefab/full/linux_arm64_server/release && ./ballisticakit_server build/prefab/full/linux_arm64_server/release && ./ballisticakit_server
prefab-linux-x86-64-server-release: prefab-linux-x86-64-server-release-build prefab-linux-x86-64-server-release: prefab-linux-x86-64-server-release-build
@tools/pcommand ensure_prefab_platform linux_x86_64 @$(PCOMMAND) ensure_prefab_platform linux_x86_64
@$(RUN_PREFAB_LINUX_X86_64_SERVER_RELEASE) @$(RUN_PREFAB_LINUX_X86_64_SERVER_RELEASE)
prefab-linux-arm64-server-release: prefab-linux-arm64-server-release-build prefab-linux-arm64-server-release: prefab-linux-arm64-server-release-build
@tools/pcommand ensure_prefab_platform linux_arm64 @$(PCOMMAND) ensure_prefab_platform linux_arm64
@$(RUN_PREFAB_LINUX_ARM64_SERVER_RELEASE) @$(RUN_PREFAB_LINUX_ARM64_SERVER_RELEASE)
prefab-linux-x86-64-server-release-build: prereqs assets-server \ prefab-linux-x86-64-server-release-build: prereqs assets-server \
@ -493,7 +494,7 @@ RUN_PREFAB_WINDOWS_X86_GUI_DEBUG = cd build/prefab/full/windows_x86_gui/debug \
&& ./BallisticaKit.exe && ./BallisticaKit.exe
prefab-windows-x86-gui-debug: prefab-windows-x86-gui-debug-build prefab-windows-x86-gui-debug: prefab-windows-x86-gui-debug-build
@tools/pcommand ensure_prefab_platform windows_x86 @$(PCOMMAND) ensure_prefab_platform windows_x86
@$(RUN_PREFAB_WINDOWS_X86_GUI_DEBUG) @$(RUN_PREFAB_WINDOWS_X86_GUI_DEBUG)
prefab-windows-x86-gui-debug-build: prereqs assets-windows-$(WINPLAT_X86) \ prefab-windows-x86-gui-debug-build: prereqs assets-windows-$(WINPLAT_X86) \
@ -516,7 +517,7 @@ RUN_PREFAB_WINDOWS_X86_GUI_RELEASE = cd \
build/prefab/full/windows_x86_gui/release && ./BallisticaKit.exe build/prefab/full/windows_x86_gui/release && ./BallisticaKit.exe
prefab-windows-x86-gui-release: prefab-windows-x86-gui-release-build prefab-windows-x86-gui-release: prefab-windows-x86-gui-release-build
@tools/pcommand ensure_prefab_platform windows_x86 @$(PCOMMAND) ensure_prefab_platform windows_x86
@$(RUN_PREFAB_WINDOWS_X86_GUI_RELEASE) @$(RUN_PREFAB_WINDOWS_X86_GUI_RELEASE)
prefab-windows-x86-gui-release-build: prereqs \ prefab-windows-x86-gui-release-build: prereqs \
@ -541,7 +542,7 @@ RUN_PREFAB_WINDOWS_X86_SERVER_DEBUG = cd \
&& dist/python_d.exe ballisticakit_server.py && dist/python_d.exe ballisticakit_server.py
prefab-windows-x86-server-debug: prefab-windows-x86-server-debug-build prefab-windows-x86-server-debug: prefab-windows-x86-server-debug-build
@tools/pcommand ensure_prefab_platform windows_x86 @$(PCOMMAND) ensure_prefab_platform windows_x86
@$(RUN_PREFAB_WINDOWS_X86_SERVER_DEBUG) @$(RUN_PREFAB_WINDOWS_X86_SERVER_DEBUG)
prefab-windows-x86-server-debug-build: prereqs \ prefab-windows-x86-server-debug-build: prereqs \
@ -566,7 +567,7 @@ RUN_PREFAB_WINDOWS_X86_SERVER_RELEASE = cd \
&& dist/python.exe -O ballisticakit_server.py && dist/python.exe -O ballisticakit_server.py
prefab-windows-x86-server-release: prefab-windows-x86-server-release-build prefab-windows-x86-server-release: prefab-windows-x86-server-release-build
@tools/pcommand ensure_prefab_platform windows_x86 @$(PCOMMAND) ensure_prefab_platform windows_x86
@$(RUN_PREFAB_WINDOWS_X86_SERVER_RELEASE) @$(RUN_PREFAB_WINDOWS_X86_SERVER_RELEASE)
prefab-windows-x86-server-release-build: prereqs \ prefab-windows-x86-server-release-build: prereqs \
@ -622,43 +623,43 @@ SPINOFF_TEST_TARGET ?= core
# Run a given spinoff test. # Run a given spinoff test.
spinoff-test: spinoff-test:
tools/pcommand spinoff_test $(SPINOFF_TEST_TARGET) $(SPINOFF_TEST_EXTRA_ARGS) $(PCOMMAND) spinoff_test $(SPINOFF_TEST_TARGET) $(SPINOFF_TEST_EXTRA_ARGS)
# Build and check core feature set alone. # Build and check core feature set alone.
spinoff-test-core: spinoff-test-core:
tools/pcommand spinoff_test core $(SPINOFF_TEST_EXTRA_ARGS) $(PCOMMAND) spinoff_test core $(SPINOFF_TEST_EXTRA_ARGS)
# Build and check base feature set alone. # Build and check base feature set alone.
spinoff-test-base: spinoff-test-base:
tools/pcommand spinoff_test base $(SPINOFF_TEST_EXTRA_ARGS) $(PCOMMAND) spinoff_test base $(SPINOFF_TEST_EXTRA_ARGS)
# Build and check plus feature set alone. # Build and check plus feature set alone.
spinoff-test-plus: spinoff-test-plus:
tools/pcommand spinoff_test plus $(SPINOFF_TEST_EXTRA_ARGS) $(PCOMMAND) spinoff_test plus $(SPINOFF_TEST_EXTRA_ARGS)
# Build and check classic feature set alone. # Build and check classic feature set alone.
spinoff-test-classic: spinoff-test-classic:
tools/pcommand spinoff_test classic $(SPINOFF_TEST_EXTRA_ARGS) $(PCOMMAND) spinoff_test classic $(SPINOFF_TEST_EXTRA_ARGS)
# Build and check template_fs feature set alone. # Build and check template_fs feature set alone.
spinoff-test-template_fs: spinoff-test-template_fs:
tools/pcommand spinoff_test template_fs $(SPINOFF_TEST_EXTRA_ARGS) $(PCOMMAND) spinoff_test template_fs $(SPINOFF_TEST_EXTRA_ARGS)
# Build and check ui_v1 feature set alone. # Build and check ui_v1 feature set alone.
spinoff-test-ui_v1: spinoff-test-ui_v1:
tools/pcommand spinoff_test ui_v1 $(SPINOFF_TEST_EXTRA_ARGS) $(PCOMMAND) spinoff_test ui_v1 $(SPINOFF_TEST_EXTRA_ARGS)
# Build and check ui_v1_lib feature set alone. # Build and check ui_v1_lib feature set alone.
spinoff-test-ui_v1_lib: spinoff-test-ui_v1_lib:
tools/pcommand spinoff_test ui_v1_lib $(SPINOFF_TEST_EXTRA_ARGS) $(PCOMMAND) spinoff_test ui_v1_lib $(SPINOFF_TEST_EXTRA_ARGS)
# Build and check scene_v1 feature set alone. # Build and check scene_v1 feature set alone.
spinoff-test-scene_v1: spinoff-test-scene_v1:
tools/pcommand spinoff_test scene_v1 $(SPINOFF_TEST_EXTRA_ARGS) $(PCOMMAND) spinoff_test scene_v1 $(SPINOFF_TEST_EXTRA_ARGS)
# Build and check scene_v1_lib feature set alone. # Build and check scene_v1_lib feature set alone.
spinoff-test-scene_v1_lib: spinoff-test-scene_v1_lib:
tools/pcommand spinoff_test scene_v1_lib $(SPINOFF_TEST_EXTRA_ARGS) $(PCOMMAND) spinoff_test scene_v1_lib $(SPINOFF_TEST_EXTRA_ARGS)
# Blow away all spinoff-test builds. # Blow away all spinoff-test builds.
spinoff-test-clean: spinoff-test-clean:
@ -666,25 +667,25 @@ spinoff-test-clean:
# Grab the current parent project and sync it into ourself. # Grab the current parent project and sync it into ourself.
spinoff-update: spinoff-update:
@tools/pcommand spinoff_check_submodule_parent @$(PCOMMAND) spinoff_check_submodule_parent
$(MAKE) update $(MAKE) update
@tools/pcommand echo BLU Pulling current parent project... @$(PCOMMANDBATCH) echo BLU Pulling current parent project...
git submodule update git submodule update
@tools/pcommand echo BLU Syncing parent into current project... @$(PCOMMANDBATCH) echo BLU Syncing parent into current project...
tools/spinoff update tools/spinoff update
@$(MAKE) update-check # Make sure spinoff didn't break anything. @$(MAKE) update-check # Make sure spinoff didn't break anything.
@tools/pcommand echo GRN Spinoff update successful! @$(PCOMMANDBATCH) echo GRN Spinoff update successful!
# Upgrade to latest parent project and sync it into ourself. # Upgrade to latest parent project and sync it into ourself.
spinoff-upgrade: spinoff-upgrade:
@tools/pcommand spinoff_check_submodule_parent @$(PCOMMAND) spinoff_check_submodule_parent
$(MAKE) update $(MAKE) update
@tools/pcommand echo BLU Pulling latest parent project... @$(PCOMMANDBATCH) echo BLU Pulling latest parent project...
cd submodules/ballistica && git checkout master && git pull cd submodules/ballistica && git checkout master && git pull
@tools/pcommand echo BLU Syncing parent into current project... @$(PCOMMANDBATCH) echo BLU Syncing parent into current project...
tools/spinoff update tools/spinoff update
@$(MAKE) update-check # Make sure spinoff didn't break anything. @$(MAKE) update-check # Make sure spinoff didn't break anything.
@tools/pcommand echo GRN Spinoff upgrade successful! @$(PCOMMANDBATCH) echo GRN Spinoff upgrade successful!
# Tell make which of these targets don't represent files. # Tell make which of these targets don't represent files.
.PHONY: spinoff-test-core spinoff-test-base spinoff-test-plus \ .PHONY: spinoff-test-core spinoff-test-base spinoff-test-plus \
@ -700,16 +701,16 @@ spinoff-upgrade:
# Update any project files that need it (does NOT build projects). # Update any project files that need it (does NOT build projects).
update: prereqs-pre-update update: prereqs-pre-update
@tools/pcommand update_project @$(PCOMMAND) update_project
# Though not technically necessary, let's keep things like tool-configs # Though not technically necessary, let's keep things like tool-configs
# immediately updated so our editors/etc. better reflect the current state. # immediately updated so our editors/etc. better reflect the current state.
@$(MAKE) -j$(CPUS) prereqs @$(MAKE) -j$(CPUS) prereqs
@tools/pcommand echo GRN Update-Project: SUCCESS! @$(PCOMMANDBATCH) echo GRN Update-Project: SUCCESS!
# Don't update but fail if anything needs it. # Don't update but fail if anything needs it.
update-check: prereqs-pre-update update-check: prereqs-pre-update
@tools/pcommand update_project --check @$(PCOMMAND) update_project --check
@tools/pcommand echo GRN Check-Project: Everything up to date. @$(PCOMMANDBATCH) echo GRN Check-Project: Everything up to date.
# Tell make which of these targets don't represent files. # Tell make which of these targets don't represent files.
.PHONY: update update-check .PHONY: update update-check
@ -724,32 +725,32 @@ update-check: prereqs-pre-update
# Run formatting on all files in the project considered 'dirty'. # Run formatting on all files in the project considered 'dirty'.
format: format:
@$(MAKE) -j$(CPUS) format-code format-scripts format-makefile @$(MAKE) -j$(CPUS) format-code format-scripts format-makefile
@tools/pcommand echo BLD Formatting complete for $(notdir $(CURDIR))! @$(PCOMMANDBATCH) echo BLD Formatting complete for $(notdir $(CURDIR))!
# Same but always formats; ignores dirty state. # Same but always formats; ignores dirty state.
format-full: format-full:
@$(MAKE) -j$(CPUS) format-code-full format-scripts-full format-makefile @$(MAKE) -j$(CPUS) format-code-full format-scripts-full format-makefile
@tools/pcommand echo BLD Formatting complete for $(notdir $(CURDIR))! @$(PCOMMANDBATCH) echo BLD Formatting complete for $(notdir $(CURDIR))!
# Run formatting for compiled code sources (.cc, .h, etc.). # Run formatting for compiled code sources (.cc, .h, etc.).
format-code: prereqs format-code: prereqs
@tools/pcommand formatcode @$(PCOMMAND) formatcode
# Same but always formats; ignores dirty state. # Same but always formats; ignores dirty state.
format-code-full: prereqs format-code-full: prereqs
@tools/pcommand formatcode -full @$(PCOMMAND) formatcode -full
# Runs formatting for scripts (.py, etc). # Runs formatting for scripts (.py, etc).
format-scripts: prereqs format-scripts: prereqs
@tools/pcommand formatscripts @$(PCOMMAND) formatscripts
# Same but always formats; ignores dirty state. # Same but always formats; ignores dirty state.
format-scripts-full: prereqs format-scripts-full: prereqs
@tools/pcommand formatscripts -full @$(PCOMMAND) formatscripts -full
# Runs formatting on the project Makefile. # Runs formatting on the project Makefile.
format-makefile: prereqs format-makefile: prereqs
@tools/pcommand formatmakefile @$(PCOMMAND) formatmakefile
.PHONY: format format-full format-code format-code-full format-scripts \ .PHONY: format format-full format-code format-code-full format-scripts \
format-scripts-full format-scripts-full
@ -764,67 +765,67 @@ format-makefile: prereqs
# Run all project checks. (static analysis) # Run all project checks. (static analysis)
check: py_check_prereqs check: py_check_prereqs
@$(DMAKE) -j$(CPUS) update-check cpplint pylint mypy @$(DMAKE) -j$(CPUS) update-check cpplint pylint mypy
@tools/pcommand echo SGRN BLD ALL CHECKS PASSED! @$(PCOMMANDBATCH) echo SGRN BLD ALL CHECKS PASSED!
# Same as check but no caching (all files are checked). # Same as check but no caching (all files are checked).
check-full: py_check_prereqs check-full: py_check_prereqs
@$(DMAKE) -j$(CPUS) update-check cpplint-full pylint-full mypy-full @$(DMAKE) -j$(CPUS) update-check cpplint-full pylint-full mypy-full
@tools/pcommand echo SGRN BLD ALL CHECKS PASSED! @$(PCOMMANDBATCH) echo SGRN BLD ALL CHECKS PASSED!
# Same as 'check' plus optional/slow extra checks. # Same as 'check' plus optional/slow extra checks.
check2: py_check_prereqs check2: py_check_prereqs
@$(DMAKE) -j$(CPUS) update-check cpplint pylint mypy pycharm @$(DMAKE) -j$(CPUS) update-check cpplint pylint mypy pycharm
@tools/pcommand echo SGRN BLD ALL CHECKS PASSED! @$(PCOMMANDBATCH) echo SGRN BLD ALL CHECKS PASSED!
# Same as check2 but no caching (all files are checked). # Same as check2 but no caching (all files are checked).
check2-full: py_check_prereqs check2-full: py_check_prereqs
@$(DMAKE) -j$(CPUS) update-check cpplint-full pylint-full mypy-full \ @$(DMAKE) -j$(CPUS) update-check cpplint-full pylint-full mypy-full \
pycharm-full pycharm-full
@tools/pcommand echo SGRN BLD ALL CHECKS PASSED! @$(PCOMMANDBATCH) echo SGRN BLD ALL CHECKS PASSED!
# Run Cpplint checks on all C/C++ code. # Run Cpplint checks on all C/C++ code.
cpplint: prereqs meta cpplint: prereqs meta
@tools/pcommand cpplint @$(PCOMMAND) cpplint
# Run Cpplint checks without caching (all files are checked). # Run Cpplint checks without caching (all files are checked).
cpplint-full: prereqs meta cpplint-full: prereqs meta
@tools/pcommand cpplint -full @$(PCOMMAND) cpplint -full
# Run Pylint checks on all Python Code. # Run Pylint checks on all Python Code.
pylint: py_check_prereqs pylint: py_check_prereqs
@tools/pcommand pylint @$(PCOMMAND) pylint
# Run Pylint checks without caching (all files are checked). # Run Pylint checks without caching (all files are checked).
pylint-full: py_check_prereqs pylint-full: py_check_prereqs
@tools/pcommand pylint -full @$(PCOMMAND) pylint -full
# Run Mypy checks on all Python code. # Run Mypy checks on all Python code.
mypy: py_check_prereqs mypy: py_check_prereqs
@tools/pcommand mypy @$(PCOMMAND) mypy
# Run Mypy checks without caching (all files are checked). # Run Mypy checks without caching (all files are checked).
mypy-full: py_check_prereqs mypy-full: py_check_prereqs
@tools/pcommand mypy -full @$(PCOMMAND) mypy -full
# Run Mypy checks on all Python code using daemon mode. # Run Mypy checks on all Python code using daemon mode.
dmypy: py_check_prereqs dmypy: py_check_prereqs
@tools/pcommand dmypy @$(PCOMMAND) dmypy
# Stop the mypy daemon # Stop the mypy daemon
dmypy-stop: py_check_prereqs dmypy-stop: py_check_prereqs
@tools/pcommand dmypy -stop @$(PCOMMAND) dmypy -stop
# Run Pyright checks on all Python code. # Run Pyright checks on all Python code.
pyright: py_check_prereqs pyright: py_check_prereqs
@tools/pcommand pyright @$(PCOMMAND) pyright
# Run PyCharm checks on all Python code. # Run PyCharm checks on all Python code.
pycharm: py_check_prereqs pycharm: py_check_prereqs
@tools/pcommand pycharm @$(PCOMMAND) pycharm
# Run PyCharm checks without caching (all files are checked). # Run PyCharm checks without caching (all files are checked).
pycharm-full: py_check_prereqs pycharm-full: py_check_prereqs
@tools/pcommand pycharm -full @$(PCOMMAND) pycharm -full
# Build prerequisites needed for python checks. # Build prerequisites needed for python checks.
# #
@ -862,14 +863,14 @@ TEST_TARGET ?= tests
# Run all tests. (live execution verification) # Run all tests. (live execution verification)
test: py_check_prereqs test: py_check_prereqs
@tools/pcommand echo BLU Running all tests... @$(PCOMMANDBATCH) echo BLU Running all tests...
@tools/pcommand tests_warm_start @$(PCOMMAND) tests_warm_start
@tools/pcommand pytest -v $(TEST_TARGET) @$(PCOMMAND) pytest -v $(TEST_TARGET)
test-verbose: py_check_prereqs test-verbose: py_check_prereqs
@tools/pcommand echo BLU Running all tests... @$(PCOMMANDBATCH) echo BLU Running all tests...
@tools/pcommand tests_warm_start @$(PCOMMAND) tests_warm_start
@tools/pcommand pytest -o log_cli=true -o log_cli_level=debug \ @$(PCOMMAND) pytest -o log_cli=true -o log_cli_level=debug \
-s -vv $(TEST_TARGET) -s -vv $(TEST_TARGET)
# Run tests with any caching disabled. # Run tests with any caching disabled.
@ -877,17 +878,17 @@ test-full: test
# Shortcut to test efro.message only. # Shortcut to test efro.message only.
test-message: test-message:
@tools/pcommand pytest -o log_cli=true -o log_cli_level=debug -s -vv \ @$(PCOMMAND) pytest -o log_cli=true -o log_cli_level=debug -s -vv \
tests/test_efro/test_message.py tests/test_efro/test_message.py
# Shortcut to test efro.dataclassio only. # Shortcut to test efro.dataclassio only.
test-dataclassio: test-dataclassio:
@tools/pcommand pytest -o log_cli=true -o log_cli_level=debug -s -vv \ @$(PCOMMAND) pytest -o log_cli=true -o log_cli_level=debug -s -vv \
tests/test_efro/test_dataclassio.py tests/test_efro/test_dataclassio.py
# Shortcut to test efro.rpc only. # Shortcut to test efro.rpc only.
test-rpc: test-rpc:
@tools/pcommand pytest -o log_cli=true -o log_cli_level=debug -s -vv \ @$(PCOMMAND) pytest -o log_cli=true -o log_cli_level=debug -s -vv \
tests/test_efro/test_rpc.py tests/test_efro/test_rpc.py
# Tell make which of these targets don't represent files. # Tell make which of these targets don't represent files.
@ -905,28 +906,28 @@ preflight:
@$(MAKE) format @$(MAKE) format
@$(MAKE) update @$(MAKE) update
@$(MAKE) -j$(CPUS) cpplint pylint mypy test @$(MAKE) -j$(CPUS) cpplint pylint mypy test
@tools/pcommand echo SGRN BLD PREFLIGHT SUCCESSFUL! @$(PCOMMANDBATCH) echo SGRN BLD PREFLIGHT SUCCESSFUL!
# Same as 'preflight' without caching (all files are visited). # Same as 'preflight' without caching (all files are visited).
preflight-full: preflight-full:
@$(MAKE) format-full @$(MAKE) format-full
@$(MAKE) update @$(MAKE) update
@$(MAKE) -j$(CPUS) cpplint-full pylint-full mypy-full test-full @$(MAKE) -j$(CPUS) cpplint-full pylint-full mypy-full test-full
@tools/pcommand echo SGRN BLD PREFLIGHT SUCCESSFUL! @$(PCOMMANDBATCH) echo SGRN BLD PREFLIGHT SUCCESSFUL!
# Same as 'preflight' plus optional/slow extra checks. # Same as 'preflight' plus optional/slow extra checks.
preflight2: preflight2:
@$(MAKE) format @$(MAKE) format
@$(MAKE) update @$(MAKE) update
@$(MAKE) -j$(CPUS) cpplint pylint mypy pycharm test @$(MAKE) -j$(CPUS) cpplint pylint mypy pycharm test
@tools/pcommand echo SGRN BLD PREFLIGHT SUCCESSFUL! @$(PCOMMANDBATCH) echo SGRN BLD PREFLIGHT SUCCESSFUL!
# Same as 'preflight2' but without caching (all files visited). # Same as 'preflight2' but without caching (all files visited).
preflight2-full: preflight2-full:
@$(MAKE) format-full @$(MAKE) format-full
@$(MAKE) update @$(MAKE) update
@$(MAKE) -j$(CPUS) cpplint-full pylint-full mypy-full pycharm-full test-full @$(MAKE) -j$(CPUS) cpplint-full pylint-full mypy-full pycharm-full test-full
@tools/pcommand echo SGRN BLD PREFLIGHT SUCCESSFUL! @$(PCOMMANDBATCH) echo SGRN BLD PREFLIGHT SUCCESSFUL!
# Tell make which of these targets don't represent files. # Tell make which of these targets don't represent files.
.PHONY: preflight preflight-full preflight2 preflight2-full .PHONY: preflight preflight-full preflight2 preflight2-full
@ -956,20 +957,20 @@ windows-staging: assets-windows resources meta
# Build and run a debug windows build (from WSL). # Build and run a debug windows build (from WSL).
windows-debug: windows-debug-build windows-debug: windows-debug-build
@tools/pcommand ensure_prefab_platform windows_x86 @$(PCOMMAND) ensure_prefab_platform windows_x86
build/windows/Debug_Win32/BallisticaKitGeneric.exe build/windows/Debug_Win32/BallisticaKitGeneric.exe
# Build and run a release windows build (from WSL). # Build and run a release windows build (from WSL).
windows-release: windows-release-build windows-release: windows-release-build
@tools/pcommand ensure_prefab_platform windows_x86 @$(PCOMMAND) ensure_prefab_platform windows_x86
build/windows/Release_Win32/BallisticaKitGeneric.exe build/windows/Release_Win32/BallisticaKitGeneric.exe
# Build a debug windows build (from WSL). # Build a debug windows build (from WSL).
windows-debug-build: \ windows-debug-build: \
build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib \ build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib \
build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb
@tools/pcommand ensure_prefab_platform windows_x86 @$(PCOMMAND) ensure_prefab_platform windows_x86
@tools/pcommand wsl_build_check_win_drive @$(PCOMMAND) wsl_build_check_win_drive
WINDOWS_CONFIGURATION=Debug WINDOWS_PLATFORM=Win32 $(MAKE) windows-staging WINDOWS_CONFIGURATION=Debug WINDOWS_PLATFORM=Win32 $(MAKE) windows-staging
WINDOWS_PROJECT=Generic WINDOWS_CONFIGURATION=Debug WINDOWS_PLATFORM=Win32 \ WINDOWS_PROJECT=Generic WINDOWS_CONFIGURATION=Debug WINDOWS_PLATFORM=Win32 \
$(MAKE) _windows-wsl-build $(MAKE) _windows-wsl-build
@ -978,8 +979,8 @@ windows-debug-build: \
windows-debug-rebuild: \ windows-debug-rebuild: \
build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib \ build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib \
build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb
@tools/pcommand ensure_prefab_platform windows_x86 @$(PCOMMAND) ensure_prefab_platform windows_x86
@tools/pcommand wsl_build_check_win_drive @$(PCOMMAND) wsl_build_check_win_drive
WINDOWS_CONFIGURATION=Debug WINDOWS_PLATFORM=Win32 $(MAKE) windows-staging WINDOWS_CONFIGURATION=Debug WINDOWS_PLATFORM=Win32 $(MAKE) windows-staging
WINDOWS_PROJECT=Generic WINDOWS_CONFIGURATION=Debug WINDOWS_PLATFORM=Win32 \ WINDOWS_PROJECT=Generic WINDOWS_CONFIGURATION=Debug WINDOWS_PLATFORM=Win32 \
$(MAKE) _windows-wsl-rebuild $(MAKE) _windows-wsl-rebuild
@ -988,8 +989,8 @@ windows-debug-rebuild: \
windows-release-build: \ windows-release-build: \
build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib \ build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib \
build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb
@tools/pcommand ensure_prefab_platform windows_x86 @$(PCOMMAND) ensure_prefab_platform windows_x86
@tools/pcommand wsl_build_check_win_drive @$(PCOMMAND) wsl_build_check_win_drive
WINDOWS_CONFIGURATION=Release WINDOWS_PLATFORM=Win32 $(MAKE) windows-staging WINDOWS_CONFIGURATION=Release WINDOWS_PLATFORM=Win32 $(MAKE) windows-staging
WINDOWS_PROJECT=Generic WINDOWS_CONFIGURATION=Release WINDOWS_PLATFORM=Win32 \ WINDOWS_PROJECT=Generic WINDOWS_CONFIGURATION=Release WINDOWS_PLATFORM=Win32 \
$(MAKE) _windows-wsl-build $(MAKE) _windows-wsl-build
@ -998,8 +999,8 @@ windows-release-build: \
windows-release-rebuild: \ windows-release-rebuild: \
build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib \ build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib \
build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb
@tools/pcommand ensure_prefab_platform windows_x86 @$(PCOMMAND) ensure_prefab_platform windows_x86
@tools/pcommand wsl_build_check_win_drive @$(PCOMMAND) wsl_build_check_win_drive
WINDOWS_CONFIGURATION=Release WINDOWS_PLATFORM=Win32 $(MAKE) windows-staging WINDOWS_CONFIGURATION=Release WINDOWS_PLATFORM=Win32 $(MAKE) windows-staging
WINDOWS_PROJECT=Generic WINDOWS_CONFIGURATION=Release WINDOWS_PLATFORM=Win32 \ WINDOWS_PROJECT=Generic WINDOWS_CONFIGURATION=Release WINDOWS_PLATFORM=Win32 \
$(MAKE) _windows-wsl-rebuild $(MAKE) _windows-wsl-rebuild
@ -1050,10 +1051,10 @@ cmake-lldb: cmake-build
cmake-build: assets-cmake resources cmake-binary cmake-build: assets-cmake resources cmake-binary
@$(STAGE_BUILD) -cmake -$(CM_BT_LC) -builddir build/cmake/$(CM_BT_LC) \ @$(STAGE_BUILD) -cmake -$(CM_BT_LC) -builddir build/cmake/$(CM_BT_LC) \
build/cmake/$(CM_BT_LC)/staged build/cmake/$(CM_BT_LC)/staged
@tools/pcommand echo BLD Build complete: BLU build/cmake/$(CM_BT_LC)/staged @$(PCOMMANDBATCH) echo BLD Build complete: BLU build/cmake/$(CM_BT_LC)/staged
cmake-binary: meta cmake-binary: meta
@tools/pcommand cmake_prep_dir build/cmake/$(CM_BT_LC) @$(PCOMMAND) cmake_prep_dir build/cmake/$(CM_BT_LC)
@cd build/cmake/$(CM_BT_LC) && test -f Makefile \ @cd build/cmake/$(CM_BT_LC) && test -f Makefile \
|| cmake -DCMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) \ || cmake -DCMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) \
$(shell pwd)/ballisticakit-cmake $(shell pwd)/ballisticakit-cmake
@ -1071,11 +1072,11 @@ cmake-server-build: assets-server meta cmake-server-binary
@$(STAGE_BUILD) -cmakeserver -$(CM_BT_LC) \ @$(STAGE_BUILD) -cmakeserver -$(CM_BT_LC) \
-builddir build/cmake/server-$(CM_BT_LC) \ -builddir build/cmake/server-$(CM_BT_LC) \
build/cmake/server-$(CM_BT_LC)/staged build/cmake/server-$(CM_BT_LC)/staged
@tools/pcommand echo BLD \ @$(PCOMMANDBATCH) echo BLD \
Server build complete: BLU build/cmake/server-$(CM_BT_LC)/staged Server build complete: BLU build/cmake/server-$(CM_BT_LC)/staged
cmake-server-binary: meta cmake-server-binary: meta
@tools/pcommand cmake_prep_dir build/cmake/server-$(CM_BT_LC) @$(PCOMMAND) cmake_prep_dir build/cmake/server-$(CM_BT_LC)
@cd build/cmake/server-$(CM_BT_LC) && test -f Makefile \ @cd build/cmake/server-$(CM_BT_LC) && test -f Makefile \
|| cmake -DCMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) -DHEADLESS=true \ || cmake -DCMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) -DHEADLESS=true \
$(shell pwd)/ballisticakit-cmake $(shell pwd)/ballisticakit-cmake
@ -1090,14 +1091,14 @@ cmake-modular-build: assets-cmake meta cmake-modular-binary
@$(STAGE_BUILD) -cmakemodular -$(CM_BT_LC) \ @$(STAGE_BUILD) -cmakemodular -$(CM_BT_LC) \
-builddir build/cmake/modular-$(CM_BT_LC) \ -builddir build/cmake/modular-$(CM_BT_LC) \
build/cmake/modular-$(CM_BT_LC)/staged build/cmake/modular-$(CM_BT_LC)/staged
@tools/pcommand echo BLD \ @$(PCOMMANDBATCH) echo BLD \
Modular build complete: BLU build/cmake/modular-$(CM_BT_LC)/staged Modular build complete: BLU build/cmake/modular-$(CM_BT_LC)/staged
cmake-modular: cmake-modular-build cmake-modular: cmake-modular-build
cd build/cmake/modular-$(CM_BT_LC)/staged && ./ballisticakit cd build/cmake/modular-$(CM_BT_LC)/staged && ./ballisticakit
cmake-modular-binary: meta cmake-modular-binary: meta
@tools/pcommand cmake_prep_dir build/cmake/modular-$(CM_BT_LC) @$(PCOMMAND) cmake_prep_dir build/cmake/modular-$(CM_BT_LC)
@cd build/cmake/modular-$(CM_BT_LC) && test -f Makefile \ @cd build/cmake/modular-$(CM_BT_LC) && test -f Makefile \
|| cmake -DCMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) \ || cmake -DCMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) \
$(shell pwd)/ballisticakit-cmake $(shell pwd)/ballisticakit-cmake
@ -1115,11 +1116,11 @@ cmake-modular-server-build: assets-server meta cmake-modular-server-binary
@$(STAGE_BUILD) -cmakemodularserver -$(CM_BT_LC) \ @$(STAGE_BUILD) -cmakemodularserver -$(CM_BT_LC) \
-builddir build/cmake/modular-server-$(CM_BT_LC) \ -builddir build/cmake/modular-server-$(CM_BT_LC) \
build/cmake/modular-server-$(CM_BT_LC)/staged build/cmake/modular-server-$(CM_BT_LC)/staged
@tools/pcommand echo BLD \ @$(PCOMMANDBATCH) echo BLD \
Server build complete: BLU build/cmake/modular-server-$(CM_BT_LC)/staged Server build complete: BLU build/cmake/modular-server-$(CM_BT_LC)/staged
cmake-modular-server-binary: meta cmake-modular-server-binary: meta
@tools/pcommand cmake_prep_dir build/cmake/modular-server-$(CM_BT_LC) @$(PCOMMAND) cmake_prep_dir build/cmake/modular-server-$(CM_BT_LC)
@cd build/cmake/modular-server-$(CM_BT_LC) && test -f Makefile \ @cd build/cmake/modular-server-$(CM_BT_LC) && test -f Makefile \
|| cmake -DCMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) -DHEADLESS=true \ || cmake -DCMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) -DHEADLESS=true \
$(shell pwd)/ballisticakit-cmake $(shell pwd)/ballisticakit-cmake
@ -1163,11 +1164,11 @@ 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))
VERSION = $(shell tools/pcommand version version) VERSION = $(shell $(PCOMMAND) version version)
BUILD_NUMBER = $(shell tools/pcommand version build) BUILD_NUMBER = $(shell $(PCOMMAND) version build)
BUILD_DIR = $(PROJ_DIR)/build BUILD_DIR = $(PROJ_DIR)/build
LAZYBUILDDIR = .cache/lazybuild LAZYBUILDDIR = .cache/lazybuild
STAGE_BUILD = $(PROJ_DIR)/tools/pcommand stage_build 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
@ -1176,16 +1177,16 @@ ROOT_CLEAN_IGNORES = --exclude=config/localconfig.json \
--exclude=.spinoffdata \ --exclude=.spinoffdata \
--exclude=/build --exclude=/build
CHECK_CLEAN_SAFETY = tools/pcommand check_clean_safety CHECK_CLEAN_SAFETY = $(PCOMMAND) check_clean_safety
# Some tool configs that need filtering (mainly injecting projroot path). # Some tool configs that need filtering (mainly injecting projroot path).
TOOL_CFG_INST = tools/pcommand tool_config_install TOOL_CFG_INST = $(PCOMMAND) tool_config_install
# Anything that affects tool-config generation. # Anything that affects tool-config generation.
TOOL_CFG_SRC = tools/efrotools/toolconfig.py config/projectconfig.json TOOL_CFG_SRC = tools/efrotools/toolconfig.py config/projectconfig.json
# Anything that should trigger an environment-check when changed. # Anything that should trigger an environment-check when changed.
ENV_SRC = tools/pcommand tools/batools/build.py ENV_SRC = $(PCOMMAND) tools/batools/build.py
.clang-format: config/toolconfigsrc/clang-format $(TOOL_CFG_SRC) .clang-format: config/toolconfigsrc/clang-format $(TOOL_CFG_SRC)
@$(TOOL_CFG_INST) $< $@ @$(TOOL_CFG_INST) $< $@
@ -1219,12 +1220,12 @@ SKIP_ENV_CHECKS ?= 0
.cache/checkenv: $(ENV_SRC) .cache/checkenv: $(ENV_SRC)
@if [ $(SKIP_ENV_CHECKS) -ne 1 ]; then \ @if [ $(SKIP_ENV_CHECKS) -ne 1 ]; then \
tools/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
@tools/pcommand build_pcommandbatch $^ $@ @$(PCOMMAND) build_pcommandbatch $^ $@
# CMake build-type lowercase # CMake build-type lowercase
CM_BT_LC = $(shell echo $(CMAKE_BUILD_TYPE) | tr A-Z a-z) CM_BT_LC = $(shell echo $(CMAKE_BUILD_TYPE) | tr A-Z a-z)
@ -1253,7 +1254,7 @@ ballisticakit-cmake/.clang-format: .clang-format
# whenever CMakeLists changes. # whenever CMakeLists changes.
.cache/compile_commands_db/compile_commands.json: \ .cache/compile_commands_db/compile_commands.json: \
ballisticakit-cmake/CMakeLists.txt ballisticakit-cmake/CMakeLists.txt
@tools/pcommand echo BLU Updating compile commands db... @$(PCOMMANDBATCH) echo BLU Updating compile commands db...
@mkdir -p .cache/compile_commands_db @mkdir -p .cache/compile_commands_db
@cd .cache/compile_commands_db \ @cd .cache/compile_commands_db \
&& cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Debug \ && cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Debug \
@ -1262,29 +1263,29 @@ ballisticakit-cmake/.clang-format: .clang-format
&& rm -rf .cache/compile_commands_db \ && rm -rf .cache/compile_commands_db \
&& mkdir .cache/compile_commands_db \ && mkdir .cache/compile_commands_db \
&& mv compile_commands.json .cache/compile_commands_db && mv compile_commands.json .cache/compile_commands_db
@tools/pcommand echo BLU Created compile commands db at $@ @$(PCOMMANDBATCH) echo BLU Created compile commands db at $@
_windows-wsl-build: _windows-wsl-build:
@tools/pcommand wsl_build_check_win_drive @$(PCOMMAND) wsl_build_check_win_drive
$(WIN_MSBUILD_EXE_B) \ $(WIN_MSBUILD_EXE_B) \
$(shell tools/pcommand wsl_path_to_win --escape \ $(shell $(PCOMMAND) wsl_path_to_win --escape \
ballisticakit-windows/$(WINPRJ)/BallisticaKit$(WINPRJ).vcxproj) \ ballisticakit-windows/$(WINPRJ)/BallisticaKit$(WINPRJ).vcxproj) \
-target:Build \ -target:Build \
-property:Configuration=$(WINCFG) \ -property:Configuration=$(WINCFG) \
-property:Platform=$(WINPLT) \ -property:Platform=$(WINPLT) \
$(VISUAL_STUDIO_VERSION) $(VISUAL_STUDIO_VERSION)
@tools/pcommand echo BLU BLD Built build/windows/BallisticaKit$(WINPRJ).exe. @$(PCOMMAND) echo BLU BLD Built build/windows/BallisticaKit$(WINPRJ).exe.
_windows-wsl-rebuild: _windows-wsl-rebuild:
@tools/pcommand wsl_build_check_win_drive @$(PCOMMAND) wsl_build_check_win_drive
$(WIN_MSBUILD_EXE_B) \ $(WIN_MSBUILD_EXE_B) \
$(shell tools/pcommand wsl_path_to_win --escape \ $(shell $(PCOMMAND) wsl_path_to_win --escape \
ballisticakit-windows/$(WINPRJ)/BallisticaKit$(WINPRJ).vcxproj) \ ballisticakit-windows/$(WINPRJ)/BallisticaKit$(WINPRJ).vcxproj) \
-target:Rebuild \ -target:Rebuild \
-property:Configuration=$(WINCFG) \ -property:Configuration=$(WINCFG) \
-property:Platform=$(WINPLT) \ -property:Platform=$(WINPLT) \
$(VISUAL_STUDIO_VERSION) $(VISUAL_STUDIO_VERSION)
@tools/pcommand echo BLU BLD Built build/windows/BallisticaKit$(WINPRJ).exe. @$(PCOMMAND) echo BLU BLD Built build/windows/BallisticaKit$(WINPRJ).exe.
# Tell make which of these targets don't represent files. # Tell make which of these targets don't represent files.
.PHONY: _windows-wsl-build _windows-wsl-rebuild .PHONY: _windows-wsl-build _windows-wsl-rebuild

View File

@ -332,9 +332,12 @@
<w>clearsign</w> <w>clearsign</w>
<w>clientid</w> <w>clientid</w>
<w>clientinfo</w> <w>clientinfo</w>
<w>clientprint</w>
<w>clientprints</w>
<w>clienttobasn</w> <w>clienttobasn</w>
<w>clipcount</w> <w>clipcount</w>
<w>cloudtoba</w> <w>cloudtoba</w>
<w>clrtp</w>
<w>cmakelist</w> <w>cmakelist</w>
<w>cmakemodular</w> <w>cmakemodular</w>
<w>cmakemodularserver</w> <w>cmakemodularserver</w>

View File

@ -13,6 +13,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/_types/_ssize_t.h>
#include <sys/param.h> #include <sys/param.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -40,6 +41,16 @@ int establish_connection_(const struct Context_* ctx);
int calc_paths_(struct Context_* ctx); int calc_paths_(struct Context_* ctx);
int send_command_(struct Context_* ctx, int argc, char** argv); int send_command_(struct Context_* ctx, int argc, char** argv);
int handle_response_(const struct Context_* ctx); int handle_response_(const struct Context_* ctx);
// Read all data from a socket and return as a malloc'ed null-terminated
// string.
char* read_string_from_socket_(const struct Context_* ctx);
// Tear down context (closing socket, etc.) before closing app.
void tear_down_context_(struct Context_* ctx);
// If a valid state file is present at the provided path and not older than
// server_idle_seconds, return said port as an int. Otherwise return -1;
int get_running_server_port_(const struct Context_* ctx, int get_running_server_port_(const struct Context_* ctx,
const char* state_file_path_full); const char* state_file_path_full);
@ -49,6 +60,7 @@ int main(int argc, char** argv) {
ctx.server_idle_seconds = 5; ctx.server_idle_seconds = 5;
ctx.pid = getpid(); ctx.pid = getpid();
ctx.sockfd = -1;
// Verbose mode enables more printing here. Debug mode enables that plus // Verbose mode enables more printing here. Debug mode enables that plus
// extra stuff. The extra stuff is mostly the server side though. // extra stuff. The extra stuff is mostly the server side though.
@ -67,36 +79,43 @@ int main(int argc, char** argv) {
// Figure our which file path we'll use to get server state. // Figure our which file path we'll use to get server state.
if (calc_paths_(&ctx) != 0) { if (calc_paths_(&ctx) != 0) {
tear_down_context_(&ctx);
return 1; return 1;
} }
// Establish communication with said server (spinning it up if needed). // Establish communication with said server (spinning it up if needed).
ctx.sockfd = establish_connection_(&ctx); ctx.sockfd = establish_connection_(&ctx);
if (ctx.sockfd == -1) { if (ctx.sockfd == -1) {
tear_down_context_(&ctx);
return 1; return 1;
} }
if (send_command_(&ctx, argc, argv) != 0) { if (send_command_(&ctx, argc, argv) != 0) {
tear_down_context_(&ctx);
return 1; return 1;
} }
int result_val = handle_response_(&ctx); int result_val = handle_response_(&ctx);
if (result_val != 0) { if (result_val != 0) {
tear_down_context_(&ctx);
return 1; return 1;
} }
if (close(ctx.sockfd) != 0) { tear_down_context_(&ctx);
fprintf(
stderr,
"Error: pcommandbatch client %s_%d (pid %d): error on socket close.\n",
ctx.instance_prefix, ctx.instance_num, ctx.pid);
return 1;
}
return result_val; return result_val;
} }
// If a valid state file is present at the provided path and not older than void tear_down_context_(struct Context_* ctx) {
// server_idle_seconds, return said port as an int. Otherwise return -1; if (ctx->sockfd != -1) {
if (close(ctx->sockfd) != 0) {
fprintf(stderr,
"Error: pcommandbatch client %s_%d (pid %d): error %d closing "
"socket.\n",
ctx->instance_prefix, ctx->instance_num, ctx->pid, errno);
}
}
}
int get_running_server_port_(const struct Context_* ctx, int get_running_server_port_(const struct Context_* ctx,
const char* state_file_path_full) { const char* state_file_path_full) {
struct stat file_stat; struct stat file_stat;
@ -120,12 +139,12 @@ int get_running_server_port_(const struct Context_* ctx,
int age_seconds = current_time - file_stat.st_mtime; int age_seconds = current_time - file_stat.st_mtime;
if (ctx->verbose) { if (ctx->verbose) {
if (age_seconds <= ctx->server_idle_seconds) { if (age_seconds <= ctx->server_idle_seconds) {
fprintf( fprintf(stderr,
stderr, "pcommandbatch client %s_%d (pid %d) found state file with age "
"pcommandbatch client %s_%d (pid %d) found state file with age %d at " "%d at "
"time %ld.\n", "time %ld.\n",
ctx->instance_prefix, ctx->instance_num, ctx->pid, age_seconds, ctx->instance_prefix, ctx->instance_num, ctx->pid, age_seconds,
time(NULL)); time(NULL));
} }
} }
@ -153,6 +172,7 @@ int get_running_server_port_(const struct Context_* ctx,
ctx->instance_prefix, ctx->instance_num, ctx->pid); ctx->instance_prefix, ctx->instance_num, ctx->pid);
return -1; return -1;
} }
// If results included output, print it. // If results included output, print it.
cJSON* port_obj = cJSON_GetObjectItem(state_dict, "p"); cJSON* port_obj = cJSON_GetObjectItem(state_dict, "p");
if (!port_obj || !cJSON_IsNumber(port_obj)) { if (!port_obj || !cJSON_IsNumber(port_obj)) {
@ -166,8 +186,6 @@ int get_running_server_port_(const struct Context_* ctx,
int port = cJSON_GetNumberValue(port_obj); int port = cJSON_GetNumberValue(port_obj);
cJSON_Delete(state_dict); cJSON_Delete(state_dict);
return port; return port;
// return val;
} }
int path_exists_(const char* path) { int path_exists_(const char* path) {
@ -221,9 +239,9 @@ int establish_connection_(const struct Context_* ctx) {
snprintf(buf, sizeof(buf), snprintf(buf, sizeof(buf),
"%s run_pcommandbatch_server --timeout %d --project-dir %s" "%s run_pcommandbatch_server --timeout %d --project-dir %s"
" --state-dir %s --instance %s_%d %s", " --state-dir %s --instance %s_%d %s",
ctx->pcommandpath, ctx->server_idle_seconds, ctx->project_dir_path, ctx->pcommandpath, ctx->server_idle_seconds,
ctx->state_dir_path, ctx->instance_prefix, ctx->instance_num, ctx->project_dir_path, ctx->state_dir_path, ctx->instance_prefix,
endbuf); ctx->instance_num, endbuf);
system(buf); system(buf);
// Spin and wait up to a few seconds for the file to appear. // Spin and wait up to a few seconds for the file to appear.
@ -260,12 +278,12 @@ int establish_connection_(const struct Context_* ctx) {
// Ok we got a port; now try to connect to it. // Ok we got a port; now try to connect to it.
if (port != -1) { if (port != -1) {
if (ctx->verbose) { if (ctx->verbose) {
fprintf( fprintf(stderr,
stderr, "pcommandbatch client %s_%d (pid %d) will use server on port "
"pcommandbatch client %s_%d (pid %d) will use server on port %d at " "%d at "
"time %ld.\n", "time %ld.\n",
ctx->instance_prefix, ctx->instance_num, ctx->pid, port, ctx->instance_prefix, ctx->instance_num, ctx->pid, port,
time(NULL)); time(NULL));
} }
struct sockaddr_in serv_addr; struct sockaddr_in serv_addr;
@ -288,11 +306,11 @@ int establish_connection_(const struct Context_* ctx) {
} }
} else { } else {
// Currently not retrying on other errors. // Currently not retrying on other errors.
fprintf( fprintf(stderr,
stderr, "Error: pcommandbatch client %s_%d (pid %d): connect failed "
"Error: pcommandbatch client %s_%d (pid %d): connect failed (errno " "(errno "
"%d).\n", "%d).\n",
ctx->instance_prefix, ctx->instance_num, ctx->pid, errno); ctx->instance_prefix, ctx->instance_num, ctx->pid, errno);
close(sockfd); close(sockfd);
return -1; return -1;
} }
@ -346,11 +364,11 @@ int calc_paths_(struct Context_* ctx) {
ctx->instance_prefix, ctx->pid); ctx->instance_prefix, ctx->pid);
return -1; return -1;
} }
fprintf( fprintf(stderr,
stderr, "Error: pcommandbatch client %s (pid %d): pcommandbatch from cwd "
"Error: pcommandbatch client %s (pid %d): pcommandbatch from cwd '%s' " "'%s' "
"is not supported.\n", "is not supported.\n",
ctx->instance_prefix, ctx->pid, cwdbuf); ctx->instance_prefix, ctx->pid, cwdbuf);
return -1; return -1;
} }
assert(ctx->pcommandpath != NULL); assert(ctx->pcommandpath != NULL);
@ -358,10 +376,11 @@ int calc_paths_(struct Context_* ctx) {
// Spread requests for each location out randomly across a few instances. // Spread requests for each location out randomly across a few instances.
// This greatly increases scalability though is probably wasteful when // This greatly increases scalability though is probably wasteful when
// running just a few commands. Maybe there's some way to smartly scale // running just a few commands since we likely spin up a new server for
// this. The best setup might be to have a single 'controller' server // each. Maybe there's some way to smartly scale this. The best setup
// instance that spins up worker instances as needed. Though such a fancy // might be to have a single 'controller' server instance that spins up
// setup might be overkill. // worker instances as needed. Though such a fancy setup might be
// overkill.
ctx->instance_num = rand() % 6; ctx->instance_num = rand() % 6;
// I was wondering if using pid would lead to a more even distribution, // I was wondering if using pid would lead to a more even distribution,
@ -396,10 +415,10 @@ int send_command_(struct Context_* ctx, int argc, char** argv) {
// Issue a write shutdown so they get EOF on the other end. // Issue a write shutdown so they get EOF on the other end.
if (shutdown(ctx->sockfd, SHUT_WR) < 0) { if (shutdown(ctx->sockfd, SHUT_WR) < 0) {
fprintf( fprintf(stderr,
stderr, "Error: pcommandbatch client %s_%d (pid %d): write shutdown "
"Error: pcommandbatch client %s_%d (pid %d): write shutdown failed.\n", "failed.\n",
ctx->instance_prefix, ctx->instance_num, ctx->pid); ctx->instance_prefix, ctx->instance_num, ctx->pid);
return -1; return -1;
} }
@ -411,26 +430,18 @@ int send_command_(struct Context_* ctx, int argc, char** argv) {
} }
int handle_response_(const struct Context_* ctx) { int handle_response_(const struct Context_* ctx) {
// Read the response. Currently expecting short-ish responses only; will char* inbuf = read_string_from_socket_(ctx);
// have to revisit this if/when they get long. if (!inbuf) {
char inbuf[512];
ssize_t result = read(ctx->sockfd, inbuf, sizeof(inbuf) - 1);
if (result < 0 || result == sizeof(inbuf) - 1) {
fprintf(stderr, fprintf(stderr,
"Error: pcommandbatch client %s_%d (pid %d): failed to read result " "Error: pcommandbatch client %s_%d (pid %d): failed to read result "
"(errno %d).\n", "(errno %d).\n",
ctx->instance_prefix, ctx->instance_num, ctx->pid, errno); ctx->instance_prefix, ctx->instance_num, ctx->pid, errno);
close(ctx->sockfd);
return -1; return -1;
} }
if (ctx->verbose) {
fprintf(stderr,
"pcommandbatch client %s_%d (pid %d) read %zd byte response.\n",
ctx->instance_prefix, ctx->instance_num, ctx->pid, result);
}
inbuf[result] = 0; // null terminate result str.
cJSON* result_dict = cJSON_Parse(inbuf); cJSON* result_dict = cJSON_Parse(inbuf);
free(inbuf);
if (!result_dict) { if (!result_dict) {
fprintf( fprintf(
stderr, stderr,
@ -440,7 +451,7 @@ int handle_response_(const struct Context_* ctx) {
return -1; return -1;
} }
// If results included output, print it. // If results included stdout output, print it.
cJSON* result_output = cJSON_GetObjectItem(result_dict, "o"); cJSON* result_output = cJSON_GetObjectItem(result_dict, "o");
if (!result_output || !cJSON_IsString(result_output)) { if (!result_output || !cJSON_IsString(result_output)) {
fprintf( fprintf(
@ -448,6 +459,7 @@ int handle_response_(const struct Context_* ctx) {
"Error: pcommandbatch client %s_%d (pid %d): failed to parse result " "Error: pcommandbatch client %s_%d (pid %d): failed to parse result "
"output value.\n", "output value.\n",
ctx->instance_prefix, ctx->instance_num, ctx->pid); ctx->instance_prefix, ctx->instance_num, ctx->pid);
cJSON_Delete(result_dict);
return -1; return -1;
} }
char* output_str = cJSON_GetStringValue(result_output); char* output_str = cJSON_GetStringValue(result_output);
@ -456,6 +468,23 @@ int handle_response_(const struct Context_* ctx) {
printf("%s", output_str); printf("%s", output_str);
} }
// If results included stderr output, print it.
result_output = cJSON_GetObjectItem(result_dict, "e");
if (!result_output || !cJSON_IsString(result_output)) {
fprintf(
stderr,
"Error: pcommandbatch client %s_%d (pid %d): failed to parse result "
"output value.\n",
ctx->instance_prefix, ctx->instance_num, ctx->pid);
cJSON_Delete(result_dict);
return -1;
}
output_str = cJSON_GetStringValue(result_output);
assert(output_str);
if (output_str[0] != 0) {
fprintf(stderr, "%s", output_str);
}
cJSON* result_code = cJSON_GetObjectItem(result_dict, "r"); cJSON* result_code = cJSON_GetObjectItem(result_dict, "r");
if (!result_code || !cJSON_IsNumber(result_code)) { if (!result_code || !cJSON_IsNumber(result_code)) {
fprintf( fprintf(
@ -463,6 +492,7 @@ int handle_response_(const struct Context_* ctx) {
"Error: pcommandbatch client %s_%d (pid %d): failed to parse result " "Error: pcommandbatch client %s_%d (pid %d): failed to parse result "
"code value.\n", "code value.\n",
ctx->instance_prefix, ctx->instance_num, ctx->pid); ctx->instance_prefix, ctx->instance_num, ctx->pid);
cJSON_Delete(result_dict);
return -1; return -1;
} }
int result_val = cJSON_GetNumberValue(result_code); int result_val = cJSON_GetNumberValue(result_code);
@ -474,3 +504,57 @@ int handle_response_(const struct Context_* ctx) {
return result_val; return result_val;
} }
char* read_string_from_socket_(const struct Context_* ctx) {
const size_t initial_buffer_size = 1024 * 10;
char* buffer = NULL;
size_t buffer_size = 0;
size_t data_received = 0;
// Allocate initial memory for the buffer
buffer = malloc(initial_buffer_size);
if (!buffer) {
perror("Failed to allocate memory for buffer");
return NULL;
}
buffer_size = initial_buffer_size;
while (1) {
// Read data from the socket.
ssize_t bytes_read = recv(ctx->sockfd, buffer + data_received,
buffer_size - data_received - 1, 0);
if (bytes_read == -1) {
perror("Error reading socket data");
free(buffer);
return NULL;
} else if (bytes_read == 0) {
// Connection closed.
break;
}
data_received += bytes_read;
// Check if buffer is full (reserving space for term char); resize if
// necessary.
if (data_received + 1 >= buffer_size) {
buffer_size *= 2;
char* rbuffer = (char*)realloc(buffer, buffer_size);
if (rbuffer) {
buffer = rbuffer;
} else {
perror("Failed to resize buffer");
free(buffer);
return NULL;
}
}
}
assert(data_received + 1 < buffer_size);
if (ctx->verbose) {
fprintf(stderr,
"pcommandbatch client %s_%d (pid %d) read %zu byte response.\n",
ctx->instance_prefix, ctx->instance_num, ctx->pid, data_received);
}
buffer[data_received] = 0; // Null terminator.
return buffer;
}

View File

@ -456,9 +456,9 @@ def capitalize() -> None:
def upper() -> None: def upper() -> None:
"""Print args uppercased.""" """Print args uppercased."""
pcommand.disallow_in_batch() pcommand.clientprint(
' '.join(w.upper() for w in pcommand.get_args()), end=''
print(' '.join(w.upper() for w in sys.argv[2:]), end='') )
def efrocache_update() -> None: def efrocache_update() -> None:
@ -481,7 +481,7 @@ def efrocache_get() -> None:
output = get_target(args[0], batch=pcommand.is_batch(), clr=pcommand.clr()) output = get_target(args[0], batch=pcommand.is_batch(), clr=pcommand.clr())
if pcommand.is_batch(): if pcommand.is_batch():
pcommand.set_output(output) pcommand.clientprint(output)
def get_modern_make() -> None: def get_modern_make() -> None:
@ -618,13 +618,12 @@ def prefab_run_var() -> None:
"""Print the current platform prefab run target var.""" """Print the current platform prefab run target var."""
import batools.build import batools.build
pcommand.disallow_in_batch() args = pcommand.get_args()
if len(args) != 1:
if len(sys.argv) != 3:
raise RuntimeError('Expected 1 arg.') raise RuntimeError('Expected 1 arg.')
base = sys.argv[2].replace('-', '_').upper() base = args[0].replace('-', '_').upper()
platform = batools.build.get_current_prefab_platform().upper() platform = batools.build.get_current_prefab_platform().upper()
print(f'RUN_PREFAB_{platform}_{base}', end='') pcommand.clientprint(f'RUN_PREFAB_{platform}_{base}', end='')
def prefab_binary_path() -> None: def prefab_binary_path() -> None:
@ -679,16 +678,19 @@ def lazybuild() -> None:
import batools.build import batools.build
from efro.error import CleanError from efro.error import CleanError
# This command is not a good candidate for batch since it can be
# long running and prints various stuff throughout the process.
pcommand.disallow_in_batch() pcommand.disallow_in_batch()
args = pcommand.get_args()
if len(sys.argv) < 5: if len(args) < 3:
raise CleanError('Expected at least 3 args') raise CleanError('Expected at least 3 args')
try: try:
category = batools.build.LazyBuildCategory(sys.argv[2]) category = batools.build.LazyBuildCategory(args[0])
except ValueError as exc: except ValueError as exc:
raise CleanError(exc) from exc raise CleanError(exc) from exc
target = sys.argv[3] target = args[1]
command = ' '.join(sys.argv[4:]) command = ' '.join(args[2:])
try: try:
batools.build.lazybuild(target, category, command) batools.build.lazybuild(target, category, command)
except subprocess.CalledProcessError as exc: except subprocess.CalledProcessError as exc:

View File

@ -7,7 +7,9 @@ from typing import TYPE_CHECKING
import errno import errno
if TYPE_CHECKING: if TYPE_CHECKING:
pass from typing import Any
from efro.terminal import ClrBase
class CleanError(Exception): class CleanError(Exception):
@ -25,18 +27,29 @@ class CleanError(Exception):
more descriptive exception types. more descriptive exception types.
""" """
def pretty_print(self, flush: bool = True, prefix: str = 'Error') -> None: def pretty_print(
self,
flush: bool = True,
prefix: str = 'Error',
file: Any = None,
clr: type[ClrBase] | None = None,
) -> None:
"""Print the error to stdout, using red colored output if available. """Print the error to stdout, using red colored output if available.
If the error has an empty message, prints nothing (not even a newline). If the error has an empty message, prints nothing (not even a newline).
""" """
from efro.terminal import Clr from efro.terminal import Clr
if clr is None:
clr = Clr
if prefix: if prefix:
prefix = f'{prefix}: ' prefix = f'{prefix}: '
errstr = str(self) errstr = str(self)
if errstr: if errstr:
print(f'{Clr.SRED}{prefix}{errstr}{Clr.RST}', flush=flush) print(
f'{clr.SRED}{prefix}{errstr}{clr.RST}', flush=flush, file=file
)
class CommunicationError(Exception): class CommunicationError(Exception):

View File

@ -15,6 +15,7 @@ from pathlib import Path
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
import io
import threading import threading
from typing import Any from typing import Any
@ -28,7 +29,7 @@ PROJROOT = Path(__file__).resolve().parents[2]
# the name of the pcommand; only the arguments *to* the command. # the name of the pcommand; only the arguments *to* the command.
_g_thread_local_storage: threading.local | None = None _g_thread_local_storage: threading.local | None = None
# Discovered functions for the currently running pcommand instance. # Discovered functions for the current project.
_g_funcs: dict | None = None _g_funcs: dict | None = None
# Are we running as a server? # Are we running as a server?
@ -43,6 +44,9 @@ def pcommand_main(globs: dict[str, Any]) -> None:
""" """
import types import types
from efro.terminal import Clr
from efro.error import CleanError
global _g_funcs # pylint: disable=global-statement global _g_funcs # pylint: disable=global-statement
assert _g_funcs is None assert _g_funcs is None
@ -57,8 +61,14 @@ def pcommand_main(globs: dict[str, Any]) -> None:
) )
) )
# Call the one based on sys args. try:
sys.exit(_run_pcommand(sys.argv)) _run_pcommand(sys.argv)
except KeyboardInterrupt as exc:
print(f'{Clr.RED}{exc}{Clr.RST}')
sys.exit(1)
except CleanError as exc:
exc.pretty_print()
sys.exit(1)
def get_args() -> list[str]: def get_args() -> list[str]:
@ -79,104 +89,99 @@ def get_args() -> list[str]:
def clr() -> type[ClrBase]: def clr() -> type[ClrBase]:
"""Like efro.terminal.Clr but works correctly under pcommandbatch.""" """Like efro.terminal.Clr but for use with pcommand.clientprint().
This properly colorizes or doesn't colorize based on whether the
*client* where output will be displayed is running on a terminal.
Regular print() output should still use efro.terminal.Clr for this
purpose.
"""
import efro.terminal import efro.terminal
# Note: currently just using the 'isatty' value from the client.
# ideally should expand the client-side logic to exactly match what
# efro.terminal.Clr does locally.
if _g_batch_server_mode: if _g_batch_server_mode:
assert _g_thread_local_storage is not None assert _g_thread_local_storage is not None
isatty = _g_thread_local_storage.isatty clrtp: type[ClrBase] = _g_thread_local_storage.clr
assert isinstance(isatty, bool) assert issubclass(clrtp, efro.terminal.ClrBase)
return efro.terminal.ClrAlways if isatty else efro.terminal.ClrNever return clrtp
return efro.terminal.Clr return efro.terminal.Clr
def set_output(output: str, newline: bool = True) -> None: def clientprint(
"""Set an output string for the current pcommand. *args: Any, stderr: bool = False, end: str | None = None
) -> None:
"""Print to client stdout.
This will be printed to stdout on the client even in batch mode. Note that, in batch mode, the results of all clientprints will show
up only after the command completes. In regular mode, clientprint()
simply passes through to regular print().
""" """
if newline: if _g_batch_server_mode:
output = f'{output}\n' assert _g_thread_local_storage is not None
print(
if not _g_batch_server_mode: *args,
print(output, end='') file=_g_thread_local_storage.stderr
return if stderr
else _g_thread_local_storage.stdout,
# Ok, we're in batch mode. Stuff this into thread-local storage to end=end,
# be returned once we're done. )
assert _g_thread_local_storage is not None else:
if hasattr(_g_thread_local_storage, 'output'): print(*args, end=end)
raise RuntimeError('Output is already set for this pcommand.')
_g_thread_local_storage.output = output
def _run_pcommand(sysargv: list[str]) -> int: def _run_pcommand(sysargv: list[str]) -> None:
"""Do the thing.""" """Run a pcommand given raw sys args."""
from efro.error import CleanError from efro.error import CleanError
from efro.terminal import Clr
assert _g_funcs is not None assert _g_funcs is not None
retval = 0 clrtp = clr()
error = False
show_help = False show_help = False
if len(sysargv) < 2: if len(sysargv) < 2:
print(f'{Clr.RED}ERROR: command expected.{Clr.RST}') clientprint(f'{clrtp.SRED}Error: Command expected.{clrtp.RST}')
show_help = True show_help = True
retval = 1 error = True
else: else:
if sysargv[1] == 'help': if sysargv[1] == 'help':
if len(sysargv) == 2: if len(sysargv) == 2:
show_help = True show_help = True
elif sysargv[2] not in _g_funcs: elif sysargv[2] not in _g_funcs:
print('Invalid help command.') raise CleanError('Invalid help command.')
retval = 1
else: else:
docs = _trim_docstring( docs = _trim_docstring(
getattr(_g_funcs[sysargv[2]], '__doc__', '<no docs>') getattr(_g_funcs[sysargv[2]], '__doc__', '<no docs>')
) )
print( clientprint(
f'\n{Clr.MAG}{Clr.BLD}pcommand {sysargv[2]}:{Clr.RST}\n' f'\n{clrtp.MAG}{clrtp.BLD}'
f'{Clr.MAG}{docs}{Clr.RST}\n' f'pcommand {sysargv[2]}:{clrtp.RST}\n'
f'{clrtp.MAG}{docs}{clrtp.RST}\n'
) )
elif sysargv[1] in _g_funcs: elif sysargv[1] in _g_funcs:
try: _g_funcs[sysargv[1]]()
_g_funcs[sysargv[1]]()
except KeyboardInterrupt as exc:
print(f'{Clr.RED}{exc}{Clr.RST}')
retval = 1
except CleanError as exc:
exc.pretty_print()
retval = 1
else: else:
print( raise CleanError(f"Unknown pcommand '{sysargv[1]}'.")
f'{Clr.RED}Unknown pcommand: "{sysargv[1]}"{Clr.RST}',
file=sys.stderr,
)
retval = 1
if show_help: if show_help:
print( clientprint(
f'The {Clr.MAG}{Clr.BLD}pcommand{Clr.RST} script encapsulates' f'The {clrtp.MAG}{clrtp.BLD}pcommand{clrtp.RST} script encapsulates'
f' a collection of project-related commands.' f' a collection of project-related commands.'
) )
print( clientprint(
f"Run {Clr.MAG}{Clr.BLD}'pcommand [COMMAND] ...'" f"Run {clrtp.MAG}{clrtp.BLD}'pcommand [COMMAND] ...'"
f'{Clr.RST} to run a command.' f'{clrtp.RST} to run a command.'
) )
print( clientprint(
f"Run {Clr.MAG}{Clr.BLD}'pcommand help [COMMAND]'" f"Run {clrtp.MAG}{clrtp.BLD}'pcommand help [COMMAND]'"
f'{Clr.RST} for full documentation for a command.' f'{clrtp.RST} for full documentation for a command.'
) )
print('Available commands:') clientprint('Available commands:')
for func, obj in sorted(_g_funcs.items()): for func, obj in sorted(_g_funcs.items()):
doc = getattr(obj, '__doc__', '').splitlines()[0].strip() doc = getattr(obj, '__doc__', '').splitlines()[0].strip()
print(f'{Clr.MAG}{func}{Clr.BLU} - {doc}{Clr.RST}') clientprint(f'{clrtp.MAG}{func}{clrtp.BLU} - {doc}{clrtp.RST}')
return retval if error:
raise CleanError()
def enter_batch_server_mode() -> None: def enter_batch_server_mode() -> None:
@ -204,32 +209,49 @@ def is_batch() -> bool:
return _g_batch_server_mode return _g_batch_server_mode
def run_client_pcommand(args: list[str], isatty: bool) -> tuple[int, str]: def run_client_pcommand(
"""Call a pcommand function when running as a batch server.""" args: list[str], clrtp: type[ClrBase], logpath: str
) -> tuple[int, str, str]:
"""Call a pcommand function as a server.
Returns a result code and stdout output.
"""
import io
import traceback
from efro.error import CleanError
assert _g_batch_server_mode assert _g_batch_server_mode
assert _g_thread_local_storage is not None assert _g_thread_local_storage is not None
# Clear any output from previous commands on this thread. with io.StringIO() as stdout, io.StringIO() as stderr:
if hasattr(_g_thread_local_storage, 'output'): # Stuff some state into thread-local storage for the handler thread
delattr(_g_thread_local_storage, 'output') # to access.
_g_thread_local_storage.stdout = stdout
_g_thread_local_storage.stderr = stderr
_g_thread_local_storage.argv = args
_g_thread_local_storage.clr = clrtp
# Stuff args into our thread-local storage so the user can get at try:
# them. _run_pcommand(args)
_g_thread_local_storage.argv = args resultcode = 0
_g_thread_local_storage.isatty = isatty except KeyboardInterrupt as exc:
clientprint(f'{clrtp.RED}{exc}{clrtp.RST}')
resultcode = 1
except CleanError as exc:
exc.pretty_print(file=stderr, clr=clrtp)
resultcode = 1
except Exception:
traceback.print_exc(file=stderr)
print(
f'More error output may be available at {logpath}', file=stderr
)
resultcode = 1
# Run the command. This may return an explicit code or may throw an stdout_str = stdout.getvalue()
# exception. stderr_str = stderr.getvalue()
resultcode: int = _run_pcommand(args)
# Handle error result-codes consistently with exceptions. return resultcode, stdout_str, stderr_str
if resultcode != 0:
raise RuntimeError(f'client pcommand returned error code {resultcode}.')
output = getattr(_g_thread_local_storage, 'output', '')
assert isinstance(output, str)
return (resultcode, output)
def disallow_in_batch() -> None: def disallow_in_batch() -> None:

View File

@ -11,42 +11,48 @@ a minimal set of modules. This can add up for large builds where
hundreds or thousands of pcommands are being run. hundreds or thousands of pcommands are being run.
To help fight that problem, pcommandbatch introduces a way to run To help fight that problem, pcommandbatch introduces a way to run
pcommands by submitting requests to a temporary local server daemon. pcommands by submitting requests to temporary local server daemons.
This allows individual pcommand calls to go through a very lightweight This allows individual pcommand calls to go through a very lightweight
client binary that simply forwards the command to a running server. client binary that simply forwards the command to a running server.
This cuts minimal client runtime down to nearly zero. Building and This cuts minimal client runtime down greatly. Building and managing
managing the server and client are handled automatically, and systems the server and client are handled automatically, and systems which are
which are unable to compile a client binary can fall back to using unable to compile a client binary can fall back to using vanilla
vanilla pcommand in those cases. pcommand in those cases.
A few considerations must be made when writing pcommands that work A few considerations must be made when using pcommands with batch mode.
in batch mode. By default, all existing pcommands have been fitted with By default, all existing pcommands have been fitted with a
a disallow_in_batch() call which triggers an error under batch mode. disallow_in_batch() call which triggers an error under batch mode.
These calls should be removed if/when each call is updated to work These calls should be removed if/when each call is updated to work
cleanly in batch mode. Requirements for batch-friendly pcommands follow: cleanly in batch mode. Requirements for batch-friendly pcommands follow:
- Batch mode runs parallel pcommands in different background threads. - Batch mode runs parallel pcommands in different background threads
Commands must be ok with that. and may run thousands of commands throughout the duration of the
server process. Batch-friendly pcommands must behave reasonably in
such an environment.
- Batch-enabled pcommands must not look at sys.argv. They should instead - Batch-enabled pcommands must not call os.chdir() or sys.exit() or
use pcommand.get_args(). Be aware that this value does not include
the first two values from sys.argv (executable path and pcommand name)
so is generally cleaner to use anyway. Also be aware that args are
thread-local, so only call get_args() from the thread your pcommand
was called in.
- Batch-enabled pcommands should not call os.chdir() or sys.exit() or
anything else having global effects. This should be self-explanatory anything else having global effects. This should be self-explanatory
considering the shared server model in use. considering the shared server model in use.
- Standard print and log calls will wind up in the pcommandbatch server - Batch-enabled pcommands should not look at sys.argv. They should
log and will not be seen by the user or capturable by the calling instead use pcommand.get_args(). Be aware that this value does not
process. By default, only a return code is passed back to the client, include the first two values from sys.argv (executable path and
where an error messages instructs the user to refer to the log or run pcommand name) so is generally cleaner to use anyway. Also be aware
again with batch mode disabled. Commands that should print some output that args are thread-local, so only call get_args() from the thread
even in batch mode can use pcommand.set_output() to do so. Note that your pcommand was called in.
this is currently limited to small bits of output (but that can be
changed). - Batch-enabled pcommands should not use efro.terminal.Clr for coloring
terminal output; instead they should use pcommand.clr() which properly
takes into account whether the *client* is running on a tty/etc.
- Standard print and log calls (as well as those of child processes)
will wind up in the pcommandbatch server log and will not be seen by
the user or capturable by the calling process. For batch-friendly
printing, use pcommand.clientprint(). Note that, in batch mode, all
output will be printed on the client after the command completes and
stderr and stdout will be printed separately instead of intermingled.
If a pcommand is long-running and prints at multiple times while doing
its thing, it is probably not a good fit for batch-mode.
""" """
from __future__ import annotations from __future__ import annotations
@ -302,6 +308,7 @@ class Server:
self, reader: asyncio.StreamReader, writer: asyncio.StreamWriter self, reader: asyncio.StreamReader, writer: asyncio.StreamWriter
) -> None: ) -> None:
"""Handle a client.""" """Handle a client."""
import efro.terminal
from efrotools.pcommand import run_client_pcommand from efrotools.pcommand import run_client_pcommand
request_id = self._next_request_id request_id = self._next_request_id
@ -309,6 +316,9 @@ class Server:
self._client_count_since_last_check += 1 self._client_count_since_last_check += 1
self._running_client_count += 1 self._running_client_count += 1
try: try:
logpath = self._worker_log_file_path.removeprefix(
f'{self._project_dir}/'
)
reqdata: dict = json.loads((await reader.read()).decode()) reqdata: dict = json.loads((await reader.read()).decode())
assert isinstance(reqdata, dict) assert isinstance(reqdata, dict)
argv: list[str] = reqdata['a'] argv: list[str] = reqdata['a']
@ -324,17 +334,26 @@ class Server:
file=sys.stderr, file=sys.stderr,
) )
# Note: currently just using the 'isatty' value from the
# client. ideally should expand the client-side logic to
# exactly match what efro.terminal.Clr does locally.
clr: type[efro.terminal.ClrBase] = (
efro.terminal.ClrAlways if isatty else efro.terminal.ClrNever
)
try: try:
if self._server_error is not None: if self._server_error is not None:
resultcode = 1 resultcode = 1
output = self._server_error stdout_output = ''
stderr_output = self._server_error
else: else:
( (
resultcode, resultcode,
output, stdout_output,
stderr_output,
) = await asyncio.get_running_loop().run_in_executor( ) = await asyncio.get_running_loop().run_in_executor(
None, None,
lambda: run_client_pcommand(argv, isatty), lambda: run_client_pcommand(argv, clr, logpath),
) )
if VERBOSE: if VERBOSE:
print( print(
@ -352,18 +371,17 @@ class Server:
file=sys.stderr, file=sys.stderr,
) )
traceback.print_exc() traceback.print_exc()
stdout_output = ''
stderr_output = (
f"internal pcommandbatch error; see log at '{logpath}'."
)
resultcode = 1 resultcode = 1
logpath = self._worker_log_file_path.removeprefix(
f'{self._project_dir}/'
)
output = (
f'Error: pcommandbatch command failed: {argv}.'
f" For more info, see '{logpath}', or rerun with"
' env var BA_PCOMMANDBATCH_DISABLE=1 to see'
' all output here.\n'
)
writer.write(json.dumps({'r': resultcode, 'o': output}).encode()) writer.write(
json.dumps(
{'r': resultcode, 'o': stdout_output, 'e': stderr_output}
).encode()
)
writer.close() writer.close()
await writer.wait_closed() await writer.wait_closed()

View File

@ -503,7 +503,7 @@ def compile_mesh_file() -> None:
# Show project-relative paths when possible. # Show project-relative paths when possible.
relpath = os.path.abspath(dst).removeprefix(f'{pcommand.PROJROOT}/') relpath = os.path.abspath(dst).removeprefix(f'{pcommand.PROJROOT}/')
pcommand.set_output(f'Compiling mesh: {relpath}') pcommand.clientprint(f'Compiling mesh: {relpath}')
os.makedirs(os.path.dirname(dst), exist_ok=True) os.makedirs(os.path.dirname(dst), exist_ok=True)
subprocess.run([makebob, src, dst], check=True) subprocess.run([makebob, src, dst], check=True)
@ -525,7 +525,7 @@ def compile_collision_mesh_file() -> None:
# Show project-relative paths when possible. # Show project-relative paths when possible.
relpath = os.path.abspath(dst).removeprefix(f'{pcommand.PROJROOT}/') relpath = os.path.abspath(dst).removeprefix(f'{pcommand.PROJROOT}/')
pcommand.set_output(f'Compiling collision mesh: {relpath}') pcommand.clientprint(f'Compiling collision mesh: {relpath}')
os.makedirs(os.path.dirname(dst), exist_ok=True) os.makedirs(os.path.dirname(dst), exist_ok=True)
subprocess.run([makebob, src, dst], check=True) subprocess.run([makebob, src, dst], check=True)
@ -556,7 +556,7 @@ def compile_python_file() -> None:
# Show project-relative path when possible. # Show project-relative path when possible.
relpath = os.path.abspath(fname).removeprefix(f'{pcommand.PROJROOT}/') relpath = os.path.abspath(fname).removeprefix(f'{pcommand.PROJROOT}/')
pcommand.set_output(f'Compiling script: {relpath}') pcommand.clientprint(f'Compiling script: {relpath}')
py_compile.compile( py_compile.compile(
fname, fname,
@ -583,7 +583,7 @@ def _simple_file_copy(msg: str, make_unwritable: bool = False) -> None:
src, dst = args src, dst = args
relpath = os.path.abspath(dst).removeprefix(f'{pcommand.PROJROOT}/') relpath = os.path.abspath(dst).removeprefix(f'{pcommand.PROJROOT}/')
pcommand.set_output(f'{msg}: {relpath}') pcommand.clientprint(f'{msg}: {relpath}')
# If we're making built files unwritable, we need to blow # If we're making built files unwritable, we need to blow
# away exiting ones to allow this to succeed. # away exiting ones to allow this to succeed.
@ -723,23 +723,21 @@ def echo() -> None:
Prints a Clr.RST at the end so that can be omitted. Prints a Clr.RST at the end so that can be omitted.
""" """
from efro.terminal import Clr clr = pcommand.clr()
pcommand.disallow_in_batch() clrnames = {n for n in dir(clr) if n.isupper() and not n.startswith('_')}
clrnames = {n for n in dir(Clr) if n.isupper() and not n.startswith('_')}
first = True first = True
out: list[str] = [] out: list[str] = []
for arg in sys.argv[2:]: for arg in pcommand.get_args():
if arg in clrnames: if arg in clrnames:
out.append(getattr(Clr, arg)) out.append(getattr(clr, arg))
else: else:
if not first: if not first:
out.append(' ') out.append(' ')
first = False first = False
out.append(arg) out.append(arg)
out.append(Clr.RST) out.append(clr.RST)
print(''.join(out)) pcommand.clientprint(''.join(out))
def urandom_pretty() -> None: def urandom_pretty() -> None:

View File

@ -138,5 +138,12 @@ from batools.pcommands2 import (
# pylint: enable=unused-import # pylint: enable=unused-import
def foof() -> None:
"""test."""
from efro.error import CleanError
raise CleanError('foo')
if __name__ == '__main__': if __name__ == '__main__':
pcommand.pcommand_main(globals()) pcommand.pcommand_main(globals())