Merge branch 'efroemling:master' into master

This commit is contained in:
Loup 2024-04-28 11:01:02 +05:30 committed by GitHub
commit 43dfac5044
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
43 changed files with 678 additions and 612 deletions

110
.efrocachemap generated
View File

@ -945,29 +945,11 @@
"build/assets/ba_data/meshes/zoeTorso.bob": "26a1007e98902178d8c62fd7069d5da5", "build/assets/ba_data/meshes/zoeTorso.bob": "26a1007e98902178d8c62fd7069d5da5",
"build/assets/ba_data/meshes/zoeUpperArm.bob": "a8a881010ac1ee9ec5ca872d5c5e853a", "build/assets/ba_data/meshes/zoeUpperArm.bob": "a8a881010ac1ee9ec5ca872d5c5e853a",
"build/assets/ba_data/meshes/zoeUpperLeg.bob": "95b2502f74c70f934927f67cd505c3ad", "build/assets/ba_data/meshes/zoeUpperLeg.bob": "95b2502f74c70f934927f67cd505c3ad",
"build/assets/ba_data/python-site-packages/_yaml/__init__.py": "b09d1968d73a04d6cf20e4e79657a6e7",
"build/assets/ba_data/python-site-packages/certifi/__init__.py": "98360d9e66de68a618eed6098a65405b", "build/assets/ba_data/python-site-packages/certifi/__init__.py": "98360d9e66de68a618eed6098a65405b",
"build/assets/ba_data/python-site-packages/certifi/__main__.py": "ef02e73f8581609df189a9f61aca365b", "build/assets/ba_data/python-site-packages/certifi/__main__.py": "ef02e73f8581609df189a9f61aca365b",
"build/assets/ba_data/python-site-packages/certifi/cacert.pem": "4e587dca9ab75057ffef6658ed385ff2", "build/assets/ba_data/python-site-packages/certifi/cacert.pem": "4e587dca9ab75057ffef6658ed385ff2",
"build/assets/ba_data/python-site-packages/certifi/core.py": "c1b8c102093ea26587619677c7ec6016", "build/assets/ba_data/python-site-packages/certifi/core.py": "c1b8c102093ea26587619677c7ec6016",
"build/assets/ba_data/python-site-packages/typing_extensions.py": "f1af94a03caf6fc79be0aedc8ab03090", "build/assets/ba_data/python-site-packages/typing_extensions.py": "f1af94a03caf6fc79be0aedc8ab03090",
"build/assets/ba_data/python-site-packages/yaml/__init__.py": "2b747e5772c203377222afc888ac6b71",
"build/assets/ba_data/python-site-packages/yaml/composer.py": "cef871e1f5f99ba2a7c44941b70afb06",
"build/assets/ba_data/python-site-packages/yaml/constructor.py": "8a15e361e34b79491c81553bb3534062",
"build/assets/ba_data/python-site-packages/yaml/cyaml.py": "9b11cba12e6f1cf2efe1725a20d7e1e5",
"build/assets/ba_data/python-site-packages/yaml/dumper.py": "b2cb6b4883f3504bb0255bfce6c3b09f",
"build/assets/ba_data/python-site-packages/yaml/emitter.py": "4c9bec47c3d0398c452f43a4344b2e71",
"build/assets/ba_data/python-site-packages/yaml/error.py": "e419d0e3ccb94a42881b565d285b6c9a",
"build/assets/ba_data/python-site-packages/yaml/events.py": "3e36b40c15962a78747acde2d434518d",
"build/assets/ba_data/python-site-packages/yaml/loader.py": "46f0fc4e2aef0b002bf56c87340a2650",
"build/assets/ba_data/python-site-packages/yaml/nodes.py": "43e867bb7f3cd06e0108837d9fd2a892",
"build/assets/ba_data/python-site-packages/yaml/parser.py": "d5225a0995e6802f440f7bc0bce34905",
"build/assets/ba_data/python-site-packages/yaml/reader.py": "a73be6f8420c9d02c8fe88c06c4b4dab",
"build/assets/ba_data/python-site-packages/yaml/representer.py": "8af292de41185af996c8f35ca1a96663",
"build/assets/ba_data/python-site-packages/yaml/resolver.py": "79802aa2c45560625a19e0eab318e45e",
"build/assets/ba_data/python-site-packages/yaml/scanner.py": "09239836ea50e81db330635e71460baa",
"build/assets/ba_data/python-site-packages/yaml/serializer.py": "baf67e938b13a5a3625d50d8b56180d7",
"build/assets/ba_data/python-site-packages/yaml/tokens.py": "9530e25e7cc2dfa36cff6fddc1578d9a",
"build/assets/ba_data/textures/achievementBoxer.dds": "5b5c461e67f3a92105b56fe264a7dd28", "build/assets/ba_data/textures/achievementBoxer.dds": "5b5c461e67f3a92105b56fe264a7dd28",
"build/assets/ba_data/textures/achievementBoxer.ktx": "1055e009423ea1d0bc3b172f9d7328bb", "build/assets/ba_data/textures/achievementBoxer.ktx": "1055e009423ea1d0bc3b172f9d7328bb",
"build/assets/ba_data/textures/achievementBoxer.pvr": "48f212189a6d83d29be410613b4f0005", "build/assets/ba_data/textures/achievementBoxer.pvr": "48f212189a6d83d29be410613b4f0005",
@ -2595,8 +2577,8 @@
"build/assets/pylib-android/_pylong.py": "e057ab3c9eea264704dff2af204884f8", "build/assets/pylib-android/_pylong.py": "e057ab3c9eea264704dff2af204884f8",
"build/assets/pylib-android/_sitebuiltins.py": "8b5e3f6e73917962fa014ad2c4a55e61", "build/assets/pylib-android/_sitebuiltins.py": "8b5e3f6e73917962fa014ad2c4a55e61",
"build/assets/pylib-android/_strptime.py": "8c65b46a50f13ca2389b19b32b7f2996", "build/assets/pylib-android/_strptime.py": "8c65b46a50f13ca2389b19b32b7f2996",
"build/assets/pylib-android/_sysconfigdata__linux_.py": "90ccf964f2bb27f565a4e9d1f2298701", "build/assets/pylib-android/_sysconfigdata__linux_.py": "e112c946a141bcf18e0656a14a52ca71",
"build/assets/pylib-android/_sysconfigdata_d_linux_.py": "5b0f120dabd3236bbf39e7630d6f97c4", "build/assets/pylib-android/_sysconfigdata_d_linux_.py": "063295bed5c2c6f30d323abb2cf82fd9",
"build/assets/pylib-android/_threading_local.py": "4a9688e3987d7d692db46feb9214945e", "build/assets/pylib-android/_threading_local.py": "4a9688e3987d7d692db46feb9214945e",
"build/assets/pylib-android/_weakrefset.py": "e4fa8532ace46dfbc35149c41ea497f7", "build/assets/pylib-android/_weakrefset.py": "e4fa8532ace46dfbc35149c41ea497f7",
"build/assets/pylib-android/abc.py": "a0daa1ed187eee8690c1e8438b97da90", "build/assets/pylib-android/abc.py": "a0daa1ed187eee8690c1e8438b97da90",
@ -4056,50 +4038,50 @@
"build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1",
"build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae",
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "9d6c7dcd7bf389dcbe29cfc7937d9a56", "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "d74d998608b2be90551db0c1d96fe9bb",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "4f40db9f40f1c16799254b2c94696942", "build/prefab/full/linux_arm64_gui/release/ballisticakit": "a98a74989bea6f6020df62a1e9df0f79",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "2d224e9438975458e1952af0c2b0d533", "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "36f14bbd6ae38e97ff423d9d767e31c2",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "ad311de40204ae2c96af8b7159fc4b28", "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "28a717bce15f9fdf6fb99483beacc19a",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "403fe6bd30d80cf4ecefd47dba093f09", "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "fcca800df7adf35b34463e01077db1b6",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "d9b98710fe088d506543a50294c5a3a4", "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "5a595984e6e663e4ead1b17fc84146e5",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "29c87115ee8771a4a0bc17317a4a127a", "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "3631577e0dfa072c0e9bb603a6b5edf0",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "27a27244b971b48dc545b40a3011ef1a", "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "e78b348e2b6709ef974630745d61f886",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "5c7540dc387ae395dd73eeb0eaea28ba", "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "f51357176081a05cab1f31141d3e3edc",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "81bd15d634824d149e50774b3233a31e", "build/prefab/full/mac_arm64_gui/release/ballisticakit": "f51d29b9ed8fecb4262c925a03f7f9cb",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "37b5d59fb91dca52f1adec53e31b084f", "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "f10ecde53794acf04f1ff748fe44a317",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "af1a00445c5801b194f02ccd9398004d", "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "ae2d6b9b5648d03461564c4816d3152c",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "75f400ca9e44557aa1c68aeb87b411f7", "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "7545271b4990e75a372e05a6d732d244",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "aa7f3acd8b8a5161fc74897b6f24d307", "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "bd8ccf40c3e6bdcf3cf5697b7078c5b0",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "40c465bbefbb7a76abe944a237606965", "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "8abba03f2364a3a5a76547f442cfc878",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "a4ab928602e225bf6cab87fe66418420", "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "94a53e1f34519b22b3f37e53bc9f2aa9",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "386448718b4cc1df3b4ddb4792a3a38c", "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "6fb53a4580ba643e3e9e89f75a780fba",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "59eec91d53ef39b46c69d6955f7920c8", "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "ec871cfb272bee1848c5a7be5149f8b1",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "57e8c777723b873c7e90ad5d7655de15", "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "a9df11c9d43cb96ab6a3ee642658bc2c",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "67899fad5203c451e5e3411bd887100b", "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "159fd444515da2af0cac7818f2ba1a54",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "11668f7191dc8d4e2b03db15ff2a4241", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "e40234644df79316d71808a731ba14f0",
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "b190199ce8b8fe122993d14fb7e8e813", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "8563857336ffcf40abfeac81fc3955eb",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "11668f7191dc8d4e2b03db15ff2a4241", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "e40234644df79316d71808a731ba14f0",
"build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "b190199ce8b8fe122993d14fb7e8e813", "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "8563857336ffcf40abfeac81fc3955eb",
"build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "d33507e6163f7afb54334dc6141d074b", "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "07033318a9b2b299128906c61342f391",
"build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "15d57b7d0c2fae7695e008650a37b7f7", "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "403c3f754e7d900b044a9f06658fffde",
"build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "d33507e6163f7afb54334dc6141d074b", "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "07033318a9b2b299128906c61342f391",
"build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "15d57b7d0c2fae7695e008650a37b7f7", "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "403c3f754e7d900b044a9f06658fffde",
"build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "6d5af317e8e9fc6d4eabeab31623e109", "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "5cbf318e235fc9218abd1df4bca567c4",
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "19e9dab275cd13cc3030de1b0f1f08c9", "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "4989c44cc8c9854a9a1dc6bf1b633796",
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "6d5af317e8e9fc6d4eabeab31623e109", "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "5cbf318e235fc9218abd1df4bca567c4",
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "19e9dab275cd13cc3030de1b0f1f08c9", "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "4989c44cc8c9854a9a1dc6bf1b633796",
"build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "3769b38b590a8a5623749771900e60fe", "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "c40665a3e7f727e0fb7350e21bfd64aa",
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "4fab22abc481a97e884cce9d67b35c6b", "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "9768548c6dfdff65fb25661540025ffe",
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "7c536b056d78148a302c975bf9238118", "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "1a0cc7e78dc66dec6ee85a8a0d68aefd",
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "4fab22abc481a97e884cce9d67b35c6b", "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "9768548c6dfdff65fb25661540025ffe",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "8072b0140655621c07fd97cab9e9ca2d", "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "8f9d11a98898066b9c492a62cb539843",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "758e51a2b6f52436796c607371221bbc", "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "994f00aa1718157f2c3ecf252218afb7",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "240aea32d29d4cc6260c5be61faad5c7", "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "4fbd801cc96d084a1c399f44de40c6e7",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "30ea6e77aa5e33949bba018acbbe0b93", "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "3c696fd17f85168472bb298eeeb23b58",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "8dfb5b9a723189015c9b3eaf73816f90", "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "cf6d352320bdaa081c8a8de122eac7ec",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "2b82beecc22a653fc8881e76b1c9adcb", "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "a02405ac7586f175ca2daf69d1965446",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "29893062fd160d20b621ead316232961", "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "b8b98848ba5e0da6dee7336a6cd5284c",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "ed2ce864584e0ed9d6427bf4b1c5743c", "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "883cc779e54b299245d4e01ea061f2e8",
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
"src/assets/ba_data/python/babase/_mgen/enums.py": "b611c090513a21e2fe90e56582724e9d", "src/assets/ba_data/python/babase/_mgen/enums.py": "b611c090513a21e2fe90e56582724e9d",
"src/ballistica/base/mgen/pyembed/binding_base.inc": "72bfed2cce8ff19741989dec28302f3f", "src/ballistica/base/mgen/pyembed/binding_base.inc": "72bfed2cce8ff19741989dec28302f3f",

View File

@ -14,8 +14,8 @@ jobs:
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: '3.12' python-version: '3.12'
- name: Install pip requirements - name: Setup project environment
run: make prereqs run: make env
- name: Make the build - name: Make the build
run: make prefab-gui-debug-build run: make prefab-gui-debug-build
- name: Upload the build - name: Upload the build
@ -31,8 +31,8 @@ jobs:
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: '3.12' python-version: '3.12'
- name: Install pip requirements - name: Setup project environment
run: make prereqs run: make env
- name: Make the build - name: Make the build
run: make prefab-server-debug-build run: make prefab-server-debug-build
- name: Upload the build - name: Upload the build
@ -48,8 +48,8 @@ jobs:
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: '3.12' python-version: '3.12'
- name: Install pip requirements - name: Setup project environment
run: make prereqs run: make env
- name: Make the build - name: Make the build
run: make prefab-linux-arm64-gui-debug-build run: make prefab-linux-arm64-gui-debug-build
- name: Upload the build - name: Upload the build
@ -65,8 +65,8 @@ jobs:
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: '3.12' python-version: '3.12'
- name: Install pip requirements - name: Setup project environment
run: make prereqs run: make env
- name: Make the build - name: Make the build
run: make prefab-linux-arm64-server-debug-build run: make prefab-linux-arm64-server-debug-build
- name: Upload the build - name: Upload the build
@ -82,8 +82,8 @@ jobs:
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: '3.12' python-version: '3.12'
- name: Install pip requirements - name: Setup project environment
run: make prereqs run: make env
- name: Make the build - name: Make the build
run: make prefab-mac-x86-64-gui-debug-build run: make prefab-mac-x86-64-gui-debug-build
- name: Upload the build - name: Upload the build
@ -99,8 +99,8 @@ jobs:
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: '3.12' python-version: '3.12'
- name: Install pip requirements - name: Setup project environment
run: make prereqs run: make env
- name: Make the build - name: Make the build
run: make prefab-mac-x86-64-server-debug-build run: make prefab-mac-x86-64-server-debug-build
- name: Upload the build - name: Upload the build
@ -116,8 +116,8 @@ jobs:
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: '3.12' python-version: '3.12'
- name: Install pip requirements - name: Setup project environment
run: make prereqs run: make env
- name: Make the build - name: Make the build
run: make prefab-mac-arm64-gui-debug-build run: make prefab-mac-arm64-gui-debug-build
- name: Upload the build - name: Upload the build
@ -133,8 +133,8 @@ jobs:
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: '3.12' python-version: '3.12'
- name: Install pip requirements - name: Setup project environment
run: make prereqs run: make env
- name: Make the build - name: Make the build
run: make prefab-mac-arm64-server-debug-build run: make prefab-mac-arm64-server-debug-build
- name: Upload the build - name: Upload the build
@ -150,8 +150,8 @@ jobs:
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: '3.12' python-version: '3.12'
- name: Install pip requirements - name: Setup project environment
run: make prereqs run: make env
- name: Make the build - name: Make the build
run: make prefab-windows-x86-gui-debug-build run: make prefab-windows-x86-gui-debug-build
- name: Upload the build - name: Upload the build
@ -167,8 +167,8 @@ jobs:
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: '3.12' python-version: '3.12'
- name: Install pip requirements - name: Setup project environment
run: make prereqs run: make env
- name: Make the build - name: Make the build
run: make prefab-windows-x86-server-debug-build run: make prefab-windows-x86-server-debug-build
- name: Upload the build - name: Upload the build
@ -184,8 +184,8 @@ jobs:
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: '3.12' python-version: '3.12'
- name: Install pip requirements - name: Setup project environment
run: make prereqs run: make env
- name: Make the build - name: Make the build
run: make docs-sphinx run: make docs-sphinx
- name: Upload the build - name: Upload the build

View File

@ -22,7 +22,7 @@ jobs:
with: with:
python-version: '3.12' python-version: '3.12'
- name: Install dependencies - name: Install dependencies
run: make prereqs run: make env
- name: Run checks - name: Run checks
run: BA_PCOMMANDBATCH_BUILD_REQUIRE=1 make check run: BA_PCOMMANDBATCH_BUILD_REQUIRE=1 make check
@ -36,7 +36,7 @@ jobs:
with: with:
python-version: '3.12' python-version: '3.12'
- name: Install dependencies - name: Install dependencies
run: make prereqs run: make env
- name: Assemble monolithic server build - name: Assemble monolithic server build
run: make cmake-server-build run: make cmake-server-build
- name: Run tests - name: Run tests
@ -54,7 +54,7 @@ jobs:
with: with:
python-version: '3.12' python-version: '3.12'
- name: Install dependencies - name: Install dependencies
run: make prereqs run: make env
- name: Build spinoff project with only core featureset - name: Build spinoff project with only core featureset
run: make spinoff-test-core run: make spinoff-test-core
- name: Build spinoff project with core and base featuresets - name: Build spinoff project with core and base featuresets
@ -72,7 +72,7 @@ jobs:
with: with:
python-version: '3.12' python-version: '3.12'
- name: Install dependencies - name: Install dependencies
run: make prereqs run: make env
- name: Create poo feature-set - name: Create poo feature-set
run: tools/spinoff fset-copy template_fs poo run: tools/spinoff fset-copy template_fs poo
- name: Add new feature-set to project - name: Add new feature-set to project

View File

@ -15,8 +15,8 @@ jobs:
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: '3.12' python-version: '3.12'
- name: Install pip requirements - name: Setup project environment
run: make prereqs run: make env
- name: Build documentation - name: Build documentation
run: make docs-sphinx run: make docs-sphinx
- name: Upload the build - name: Upload the build

1
.gitignore vendored
View File

@ -33,6 +33,7 @@ _fulltest_buildfile_*
ballistica_files/ ballistica_files/
tools/pcommand tools/pcommand
tools/cloudshell tools/cloudshell
tools/bacloud
**/.#* **/.#*
# Environment files # Environment files

View File

@ -679,7 +679,6 @@
<w>cval</w> <w>cval</w>
<w>cwdg</w> <w>cwdg</w>
<w>cxxabi</w> <w>cxxabi</w>
<w>cyaml</w>
<w>cycledelay</w> <w>cycledelay</w>
<w>cygwinccompiler</w> <w>cygwinccompiler</w>
<w>dandroid</w> <w>dandroid</w>
@ -2019,7 +2018,6 @@
<w>objset</w> <w>objset</w>
<w>objsizes</w> <w>objsizes</w>
<w>objt</w> <w>objt</w>
<w>objtoyaml</w>
<w>objtype</w> <w>objtype</w>
<w>objtypes</w> <w>objtypes</w>
<w>obval</w> <w>obval</w>

View File

@ -1,9 +1,12 @@
### 1.7.34 (build 21804, api 8, 2024-04-23) ### 1.7.35 (build 21824, api 8, 2024-04-26)
### 1.7.34 (build 21823, api 8, 2024-04-26)
- Bumped Python version from 3.11 to 3.12 for all builds and project tools. One - Bumped Python version from 3.11 to 3.12 for all builds and project tools. One
of the things this means is that we can use `typing.override` instead of the of the things this means is that we can use `typing.override` instead of the
`typing_extensions` version so the annoying requirement of installing `typing_extensions.override` version so the annoying requirement of installing
`typing_extensions` first thing when setting up the repo introduced a few `typing_extensions` first thing when setting up the repo introduced a few
versions back is finally no longer a thing. versions back is finally no longer a thing. I'll try to be careful to avoid
falling back into that situation in the future.
- The project now maintains its own Python virtual environment in `.venv` where - The project now maintains its own Python virtual environment in `.venv` where
it automatically installs whatever Python packages it needs instead of asking it automatically installs whatever Python packages it needs instead of asking
the user to do so in their own environment. This should greatly simplify the user to do so in their own environment. This should greatly simplify
@ -29,6 +32,30 @@
- `_bascenev1.protocol_version()` now properly throws an exception if called - `_bascenev1.protocol_version()` now properly throws an exception if called
while scene-v1 is not active. while scene-v1 is not active.
- The `efro.dataclassio` system now supports `datetime.timedelta` values. - The `efro.dataclassio` system now supports `datetime.timedelta` values.
- Usage of `pcommandbatch` is now disabled by default. To enable it, set the env
var `BA_PCOMMANDBATCH_ENABLE=1`. This is primarily due to rare sporadic
failures I have observed or have been informed of, possibly involving socket
exhaustion or other hard-to-debug OS conditions. For now I am still
considering `pcommandbatch` supported and may continue to use it myself, but
its speed gains may not be worth its added complexity indefinitely. As core
counts keep increasing in the future, the time expense of spinning up a new
Python process per pcommand decreases, making pcommandbatch less of a win.
Please holler if you have any thoughts on this.
- Renamed the `prereqs` Makefile target to `env`. This is more concise and feels
more accurate now that the target sets up things such as the Python virtual
environment and generally gets the project environment ready to use.
- (build 21810) Fixed an issue where AppSubsystems could get inited multiple
times (due to functools.cached_property no longer being thread-safe in Python
3.12).
- The server config file is now in `toml` format instead of `yaml`. Python has
built in support for reading `toml` as of 3.11 which means we don't have to
bundle extra packages, and `toml` has more of a clean minimal design that
works well for config files. Also I plan to use it for AssetPackage
configuration stuff so this keeps things consistent.
- The server config can now be set to a `.json` file as an alternative to the
default `.toml`. This can be handy when procedurally generating server
configs. If no `--config` path is explicitly passed, it will look for
`config.json` and `config.toml` in the same dir as the script in that order.
### 1.7.33 (build 21795, api 8, 2024-03-24) ### 1.7.33 (build 21795, api 8, 2024-03-24)
- Stress test input-devices are now a bit smarter; they won't press any buttons - Stress test input-devices are now a bit smarter; they won't press any buttons

287
Makefile
View File

@ -25,7 +25,7 @@
################################################################################ ################################################################################
# List targets in this Makefile and basic descriptions for them. # List targets in this Makefile and basic descriptions for them.
help: prereqs help: env
@$(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
@ -40,82 +40,83 @@ endif
# which. # which.
PCOMMAND = tools/pcommand PCOMMAND = tools/pcommand
PCOMMANDBATCHBIN = .cache/pcommandbatch/pcommandbatch PCOMMANDBATCHBIN = .cache/pcommandbatch/pcommandbatch
ifeq ($(BA_PCOMMANDBATCH_DISABLE),1) ifeq ($(BA_PCOMMANDBATCH_ENABLE),0)
PCOMMANDBATCH = $(PCOMMAND)
else
PCOMMANDBATCH = $(PCOMMANDBATCHBIN) PCOMMANDBATCH = $(PCOMMANDBATCHBIN)
else
PCOMMANDBATCH = $(PCOMMAND)
endif endif
# Prereq targets that should be safe to run anytime; even if project-files # Prereq targets that should be safe to run anytime; even if project-files
# are out of date. # are out of date.
PREREQS_SAFE = .cache/checkenv $(PCOMMANDBATCHBIN) .dir-locals.el .mypy.ini \ ENV_REQS_SAFE = .cache/checkenv $(PCOMMANDBATCHBIN) .dir-locals.el .mypy.ini \
.pyrightconfig.json .pylintrc .clang-format \ .pyrightconfig.json .pylintrc .clang-format \
ballisticakit-cmake/.clang-format .editorconfig tools/cloudshell ballisticakit-cmake/.clang-format .editorconfig tools/cloudshell \
tools/bacloud
# Prereq targets that may break if the project needs updating should go here. # Prereq targets that may break if the project needs updating should go here.
# An example is compile-command-databases; these might try to run cmake and # An example is compile-command-databases; these might try to run cmake and
# fail if the CMakeList files don't match what's on disk. If such a target was # fail if the CMakeList files don't match what's on disk. If such a target was
# included in PREREQS_SAFE it would try to build *before* project updates # included in ENV_REQS_SAFE it would try to build *before* project updates
# which would leave us stuck in a broken state. # which would leave us stuck in a broken state.
PREREQS_POST_UPDATE_ONLY = $(PREREQ_COMPILE_COMMANDS_DB) ENV_REQS_POST_UPDATE_ONLY = $(PREREQ_COMPILE_COMMANDS_DB)
# Target that should be built before building almost any other target. This # Target that should be built before building almost any other target. This
# installs tool config files, sets up the Python virtual environment, etc. # installs tool config files, sets up the Python virtual environment, etc.
prereqs: $(PREREQS_SAFE) $(PREREQS_POST_UPDATE_ONLY) env: $(ENV_REQS_SAFE) $(ENV_REQS_POST_UPDATE_ONLY)
# Set of prereqs safe to run if the project state is dirty. # Set of prereqs safe to run if the project state is dirty.
prereqs-pre-update: $(PREREQS_SAFE) env-pre-update: $(ENV_REQS_SAFE)
prereqs-clean: env-clean:
rm -rf $(PREREQS_SAFE) $(PREREQS_POST_UPDATE_ONLY) rm -rf $(ENV_REQS_SAFE) $(ENV_REQS_POST_UPDATE_ONLY)
# Build all assets for all platforms. # Build all assets for all platforms.
assets: prereqs meta assets: env meta
@$(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: env meta
@$(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: env meta
@$(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: env meta
@$(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: env meta
@$(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: env meta
@$(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: env meta
@$(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: env meta
@$(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: env meta
@$(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: env meta
@$(PCOMMAND) lazybuild assets_src $(LAZYBUILDDIR)/$@ \ @$(PCOMMAND) lazybuild assets_src $(LAZYBUILDDIR)/$@ \
cd src/assets \&\& $(MAKE) -j$(CPUS) android cd src/assets \&\& $(MAKE) -j$(CPUS) android
@ -125,7 +126,7 @@ assets-clean:
cd src/assets && $(MAKE) clean cd src/assets && $(MAKE) clean
# Build resources. # Build resources.
resources: prereqs meta resources: env meta
@$(PCOMMAND) lazybuild resources_src $(LAZYBUILDDIR)/$@ \ @$(PCOMMAND) lazybuild resources_src $(LAZYBUILDDIR)/$@ \
cd src/resources \&\& $(MAKE) -j$(CPUS) cd src/resources \&\& $(MAKE) -j$(CPUS)
@ -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: env
@$(PCOMMAND) lazybuild meta_src $(LAZYBUILDDIR)/$@ \ @$(PCOMMAND) lazybuild meta_src $(LAZYBUILDDIR)/$@ \
cd src/meta \&\& $(MAKE) -j$(CPUS) cd src/meta \&\& $(MAKE) -j$(CPUS)
@ -149,13 +150,13 @@ meta-clean:
# Remove ALL files and directories that aren't managed by git (except for a # Remove ALL files and directories that aren't managed by git (except for a
# few things such as localconfig.json). # few things such as localconfig.json).
clean: prereqs clean: env
$(CHECK_CLEAN_SAFETY) $(CHECK_CLEAN_SAFETY)
rm -rf build # Kill this ourself; can confuse git if contains other repos. rm -rf build # Kill this ourself; can confuse git if contains other repos.
git clean -dfx $(ROOT_CLEAN_IGNORES) git clean -dfx $(ROOT_CLEAN_IGNORES)
# Show what clean would delete without actually deleting it. # Show what clean would delete without actually deleting it.
clean-list: prereqs clean-list: env
$(CHECK_CLEAN_SAFETY) $(CHECK_CLEAN_SAFETY)
@echo Would remove build # Handle this part ourself; can confuse git. @echo Would remove build # Handle this part ourself; can confuse git.
git clean -dnx $(ROOT_CLEAN_IGNORES) git clean -dnx $(ROOT_CLEAN_IGNORES)
@ -163,22 +164,22 @@ clean-list: prereqs
# Build/update dummy python modules. # Build/update dummy python modules.
# #
# IMPORTANT - building this target can kick off full builds/cleans and so it # IMPORTANT - building this target can kick off full builds/cleans and so it
# should not be built in parallel with other targets. See py_check_prereqs # should not be built in parallel with other targets. See py_check_prepass
# target for more info. # target for more info.
dummymodules: prereqs meta dummymodules: env meta
@$(PCOMMAND) lazybuild dummymodules_src $(LAZYBUILDDIR)/$@ \ @$(PCOMMAND) lazybuild dummymodules_src $(LAZYBUILDDIR)/$@ \
rm -rf build/dummymodules \&\& $(PCOMMAND) gen_dummy_modules rm -rf build/dummymodules \&\& $(PCOMMAND) gen_dummy_modules
dummymodules-clean: prereqs dummymodules-clean: env
rm -f $(LAZYBUILDDIR)/dummymodules rm -f $(LAZYBUILDDIR)/dummymodules
rm -rf build/dummymodules rm -rf build/dummymodules
# Build the project's Python virtual environment. This should happen # Build the project's Python virtual environment. This should happen
# automatically as a dependency of the prereqs target. # automatically as a dependency of the env target.
venv: .venv/efro_venv_complete venv: .venv/.efro_venv_complete
# Update pip requirements to latest versions. # Update pip requirements to latest versions.
venv-upgrade: prereqs venv-upgrade: env
$(PCOMMAND) requirements_upgrade config/requirements.txt $(PCOMMAND) requirements_upgrade config/requirements.txt
venv-clean: venv-clean:
@ -188,13 +189,13 @@ venv-clean:
# #
# IMPORTANT: Docs generation targets may themselves run builds, so they should # IMPORTANT: Docs generation targets may themselves run builds, so they should
# be run alone serially and never in parallel alongside other builds. # be run alone serially and never in parallel alongside other builds.
docs: prereqs docs: env
$(MAKE) docs-pdoc $(MAKE) docs-pdoc
docs-pdoc: prereqs docs-pdoc: env
@$(PCOMMAND) gen_docs_pdoc @$(PCOMMAND) gen_docs_pdoc
docs-sphinx: prereqs docs-sphinx: env
$(MAKE) dummymodules $(MAKE) dummymodules
@$(PCOMMAND) gen_docs_sphinx @$(PCOMMAND) gen_docs_sphinx
@ -202,11 +203,11 @@ docs-sphinx-clean:
rm -rf .cache/sphinx rm -rf .cache/sphinx
rm -rf build/sphinx rm -rf build/sphinx
pcommandbatch_speed_test: prereqs pcommandbatch_speed_test: env
@$(PCOMMAND) pcommandbatch_speed_test $(PCOMMANDBATCH) @$(PCOMMAND) pcommandbatch_speed_test $(PCOMMANDBATCHBIN)
# 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 env env-pre-update env-clean assets assets-cmake \
assets-cmake-scripts assets-windows assets-windows-Win32 \ assets-cmake-scripts assets-windows assets-windows-Win32 \
assets-windows-x64 assets-mac assets-ios assets-android assets-clean \ assets-windows-x64 assets-mac assets-ios assets-android assets-clean \
resources resources-clean meta meta-clean clean clean-list \ resources resources-clean meta meta-clean clean clean-list \
@ -235,11 +236,11 @@ prefab-gui-release: prefab-gui-release-build
$($(shell $(WSLU) $(PCOMMAND) prefab_run_var gui-release)) $($(shell $(WSLU) $(PCOMMAND) prefab_run_var gui-release))
# Assemble a debug build for this platform. # Assemble a debug build for this platform.
prefab-gui-debug-build: prereqs prefab-gui-debug-build: env
$(WSLU) $(PCOMMAND) make_prefab gui-debug $(WSLU) $(PCOMMAND) make_prefab gui-debug
# Assemble a release build for this platform. # Assemble a release build for this platform.
prefab-gui-release-build: prereqs prefab-gui-release-build: env
$(WSLU) $(PCOMMAND) make_prefab gui-release $(WSLU) $(PCOMMAND) make_prefab gui-release
# Assemble & run a server debug build for this platform. # Assemble & run a server debug build for this platform.
@ -251,11 +252,11 @@ prefab-server-release: prefab-server-release-build
$($(shell $(WSLU) $(PCOMMAND) prefab_run_var server-release)) $($(shell $(WSLU) $(PCOMMAND) 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: prereqs prefab-server-debug-build: env
$(WSLU) $(PCOMMAND) make_prefab server-debug $(WSLU) $(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: prereqs prefab-server-release-build: env
$(WSLU) $(PCOMMAND) make_prefab server-release $(WSLU) $(PCOMMAND) make_prefab server-release
# Clean all prefab builds. # Clean all prefab builds.
@ -283,11 +284,11 @@ prefab-mac-arm64-gui-debug: prefab-mac-arm64-gui-debug-build
@$(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: env assets-cmake \
build/prefab/full/mac_x86_64_gui/debug/ballisticakit build/prefab/full/mac_x86_64_gui/debug/ballisticakit
@$(STAGE_BUILD) -cmake -debug build/prefab/full/mac_x86_64_gui/debug @$(STAGE_BUILD) -cmake -debug build/prefab/full/mac_x86_64_gui/debug
prefab-mac-arm64-gui-debug-build: prereqs assets-cmake \ prefab-mac-arm64-gui-debug-build: env assets-cmake \
build/prefab/full/mac_arm64_gui/debug/ballisticakit build/prefab/full/mac_arm64_gui/debug/ballisticakit
@$(STAGE_BUILD) -cmake -debug build/prefab/full/mac_arm64_gui/debug @$(STAGE_BUILD) -cmake -debug build/prefab/full/mac_arm64_gui/debug
@ -313,11 +314,11 @@ prefab-mac-arm64-gui-release: prefab-mac-arm64-gui_release-build
@$(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: env assets-cmake \
build/prefab/full/mac_x86_64_gui/release/ballisticakit build/prefab/full/mac_x86_64_gui/release/ballisticakit
@$(STAGE_BUILD) -cmake -release build/prefab/full/mac_x86_64_gui/release @$(STAGE_BUILD) -cmake -release build/prefab/full/mac_x86_64_gui/release
prefab-mac-arm64-gui-release-build: prereqs assets-cmake \ prefab-mac-arm64-gui-release-build: env assets-cmake \
build/prefab/full/mac_arm64_gui/release/ballisticakit build/prefab/full/mac_arm64_gui/release/ballisticakit
@$(STAGE_BUILD) -cmake -release build/prefab/full/mac_arm64_gui/release @$(STAGE_BUILD) -cmake -release build/prefab/full/mac_arm64_gui/release
@ -343,11 +344,11 @@ prefab-mac-arm64-server-debug: prefab-mac-arm64-server-debug-build
@$(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: env assets-server \
build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless
@$(STAGE_BUILD) -cmakeserver -debug build/prefab/full/mac_x86_64_server/debug @$(STAGE_BUILD) -cmakeserver -debug build/prefab/full/mac_x86_64_server/debug
prefab-mac-arm64-server-debug-build: prereqs assets-server \ prefab-mac-arm64-server-debug-build: env assets-server \
build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless
@$(STAGE_BUILD) -cmakeserver -debug build/prefab/full/mac_arm64_server/debug @$(STAGE_BUILD) -cmakeserver -debug build/prefab/full/mac_arm64_server/debug
@ -373,12 +374,12 @@ prefab-mac-arm64-server-release: prefab-mac-arm64-server-release-build
@$(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: env assets-server \
build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless
@$(STAGE_BUILD) -cmakeserver -release \ @$(STAGE_BUILD) -cmakeserver -release \
build/prefab/full/mac_x86_64_server/release build/prefab/full/mac_x86_64_server/release
prefab-mac-arm64-server-release-build: prereqs assets-server \ prefab-mac-arm64-server-release-build: env assets-server \
build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless
@$(STAGE_BUILD) -cmakeserver -release \ @$(STAGE_BUILD) -cmakeserver -release \
build/prefab/full/mac_arm64_server/release build/prefab/full/mac_arm64_server/release
@ -405,11 +406,11 @@ prefab-linux-arm64-gui-debug: prefab-linux-arm64-gui-debug-build
@$(WSLL) $(PCOMMAND) ensure_prefab_platform linux_arm64 @$(WSLL) $(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: env assets-cmake \
build/prefab/full/linux_x86_64_gui/debug/ballisticakit build/prefab/full/linux_x86_64_gui/debug/ballisticakit
@$(STAGE_BUILD) -cmake -debug build/prefab/full/linux_x86_64_gui/debug @$(STAGE_BUILD) -cmake -debug build/prefab/full/linux_x86_64_gui/debug
prefab-linux-arm64-gui-debug-build: prereqs assets-cmake \ prefab-linux-arm64-gui-debug-build: env assets-cmake \
build/prefab/full/linux_arm64_gui/debug/ballisticakit build/prefab/full/linux_arm64_gui/debug/ballisticakit
@$(STAGE_BUILD) -cmake -debug build/prefab/full/linux_arm64_gui/debug @$(STAGE_BUILD) -cmake -debug build/prefab/full/linux_arm64_gui/debug
@ -435,11 +436,11 @@ prefab-linux-arm64-gui-release: prefab-linux-arm64-gui-release-build
@$(WSLL) $(PCOMMAND) ensure_prefab_platform linux_arm64 @$(WSLL) $(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: env assets-cmake \
build/prefab/full/linux_x86_64_gui/release/ballisticakit build/prefab/full/linux_x86_64_gui/release/ballisticakit
@$(STAGE_BUILD) -cmake -release build/prefab/full/linux_x86_64_gui/release @$(STAGE_BUILD) -cmake -release build/prefab/full/linux_x86_64_gui/release
prefab-linux-arm64-gui-release-build: prereqs assets-cmake \ prefab-linux-arm64-gui-release-build: env assets-cmake \
build/prefab/full/linux_arm64_gui/release/ballisticakit build/prefab/full/linux_arm64_gui/release/ballisticakit
@$(STAGE_BUILD) -cmake -release build/prefab/full/linux_arm64_gui/release @$(STAGE_BUILD) -cmake -release build/prefab/full/linux_arm64_gui/release
@ -465,12 +466,12 @@ prefab-linux-arm64-server-debug: prefab-linux-arm64-server-debug-build
@$(WSLL) $(PCOMMAND) ensure_prefab_platform linux_arm64 @$(WSLL) $(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: env assets-server \
build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless
@$(STAGE_BUILD) -cmakeserver -debug \ @$(STAGE_BUILD) -cmakeserver -debug \
build/prefab/full/linux_x86_64_server/debug build/prefab/full/linux_x86_64_server/debug
prefab-linux-arm64-server-debug-build: prereqs assets-server \ prefab-linux-arm64-server-debug-build: env assets-server \
build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless
@$(STAGE_BUILD) -cmakeserver -debug \ @$(STAGE_BUILD) -cmakeserver -debug \
build/prefab/full/linux_arm64_server/debug build/prefab/full/linux_arm64_server/debug
@ -497,12 +498,12 @@ prefab-linux-arm64-server-release: prefab-linux-arm64-server-release-build
@$(WSLL) $(PCOMMAND) ensure_prefab_platform linux_arm64 @$(WSLL) $(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: env assets-server \
build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless
@$(STAGE_BUILD) -cmakeserver -release \ @$(STAGE_BUILD) -cmakeserver -release \
build/prefab/full/linux_x86_64_server/release build/prefab/full/linux_x86_64_server/release
prefab-linux-arm64-server-release-build: prereqs assets-server \ prefab-linux-arm64-server-release-build: env assets-server \
build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless
@$(STAGE_BUILD) -cmakeserver -release \ @$(STAGE_BUILD) -cmakeserver -release \
build/prefab/full/linux_arm64_server/release build/prefab/full/linux_arm64_server/release
@ -522,7 +523,7 @@ prefab-windows-x86-gui-debug: prefab-windows-x86-gui-debug-build
@$(WSLW) $(PCOMMAND) ensure_prefab_platform windows_x86 @$(WSLW) $(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: env assets-windows-$(WINPLAT_X86) \
build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe
@$(STAGE_BUILD) -win-$(WINPLAT_X86) -debug \ @$(STAGE_BUILD) -win-$(WINPLAT_X86) -debug \
build/prefab/full/windows_x86_gui/debug build/prefab/full/windows_x86_gui/debug
@ -545,7 +546,7 @@ prefab-windows-x86-gui-release: prefab-windows-x86-gui-release-build
@$(WSLW) $(PCOMMAND) ensure_prefab_platform windows_x86 @$(WSLW) $(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: env \
assets-windows-$(WINPLAT_X86) \ assets-windows-$(WINPLAT_X86) \
build/prefab/full/windows_x86_gui/release/BallisticaKit.exe build/prefab/full/windows_x86_gui/release/BallisticaKit.exe
@$(STAGE_BUILD) -win-$(WINPLAT_X86) -release \ @$(STAGE_BUILD) -win-$(WINPLAT_X86) -release \
@ -570,7 +571,7 @@ prefab-windows-x86-server-debug: prefab-windows-x86-server-debug-build
@$(WSLW) $(PCOMMAND) ensure_prefab_platform windows_x86 @$(WSLW) $(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: env \
assets-windows-$(WINPLAT_X86) \ assets-windows-$(WINPLAT_X86) \
build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe
@$(STAGE_BUILD) -winserver-$(WINPLAT_X86) -debug \ @$(STAGE_BUILD) -winserver-$(WINPLAT_X86) -debug \
@ -595,7 +596,7 @@ prefab-windows-x86-server-release: prefab-windows-x86-server-release-build
@$(WSLW) $(PCOMMAND) ensure_prefab_platform windows_x86 @$(WSLW) $(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: env \
assets-windows-$(WINPLAT_X86) \ assets-windows-$(WINPLAT_X86) \
build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe
@$(STAGE_BUILD) -winserver-$(WINPLAT_X86) -release \ @$(STAGE_BUILD) -winserver-$(WINPLAT_X86) -release \
@ -651,51 +652,51 @@ build/prefab/lib/windows/Release_%/BallisticaKitHeadlessPlus.pdb: .efrocachemap
SPINOFF_TEST_TARGET ?= core SPINOFF_TEST_TARGET ?= core
# Run a given spinoff test. # Run a given spinoff test.
spinoff-test: prereqs spinoff-test: env
$(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: prereqs spinoff-test-core: env
$(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: prereqs spinoff-test-base: env
$(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: prereqs spinoff-test-plus: env
$(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: prereqs spinoff-test-classic: env
$(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: prereqs spinoff-test-template_fs: env
$(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: prereqs spinoff-test-ui_v1: env
$(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: prereqs spinoff-test-ui_v1_lib: env
$(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: prereqs spinoff-test-scene_v1: env
$(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: prereqs spinoff-test-scene_v1_lib: env
$(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: prereqs spinoff-test-clean: env
rm -rf build/spinofftest rm -rf build/spinofftest
# Grab the current parent project and sync it into ourself. # Grab the current parent project and sync it into ourself.
spinoff-update: prereqs spinoff-update: env
@$(PCOMMAND) spinoff_check_submodule_parent @$(PCOMMAND) spinoff_check_submodule_parent
$(MAKE) update $(MAKE) update
@$(PCOMMANDBATCH) echo BLU Pulling current parent project... @$(PCOMMANDBATCH) echo BLU Pulling current parent project...
@ -706,7 +707,7 @@ spinoff-update: prereqs
@$(PCOMMANDBATCH) 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: prereqs spinoff-upgrade: env
@$(PCOMMAND) spinoff_check_submodule_parent @$(PCOMMAND) spinoff_check_submodule_parent
$(MAKE) update $(MAKE) update
@$(PCOMMANDBATCH) echo BLU Pulling latest parent project... @$(PCOMMANDBATCH) echo BLU Pulling latest parent project...
@ -729,15 +730,15 @@ spinoff-upgrade: prereqs
################################################################################ ################################################################################
# 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: env-pre-update
@$(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) env
@$(PCOMMANDBATCH) 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: env-pre-update
@$(PCOMMAND) update_project --check @$(PCOMMAND) update_project --check
@$(PCOMMANDBATCH) echo GRN Check-Project: Everything up to date. @$(PCOMMANDBATCH) echo GRN Check-Project: Everything up to date.
@ -752,33 +753,33 @@ 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: prereqs format: env
@$(MAKE) -j$(CPUS) format-code format-scripts format-makefile @$(MAKE) -j$(CPUS) format-code format-scripts format-makefile
@$(PCOMMANDBATCH) 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: prereqs format-full: env
@$(MAKE) -j$(CPUS) format-code-full format-scripts-full format-makefile @$(MAKE) -j$(CPUS) format-code-full format-scripts-full format-makefile
@$(PCOMMANDBATCH) 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: env
@$(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: env
@$(PCOMMAND) formatcode -full @$(PCOMMAND) formatcode -full
# Runs formatting for scripts (.py, etc). # Runs formatting for scripts (.py, etc).
format-scripts: prereqs format-scripts: env
@$(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: env
@$(PCOMMAND) formatscripts -full @$(PCOMMAND) formatscripts -full
# Runs formatting on the project Makefile. # Runs formatting on the project Makefile.
format-makefile: prereqs format-makefile: env
@$(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 \
@ -792,67 +793,67 @@ format-makefile: prereqs
################################################################################ ################################################################################
# Run all project checks. (static analysis) # Run all project checks. (static analysis)
check: py_check_prereqs check: py_check_prepass
@$(DMAKE) -j$(CPUS) update-check cpplint pylint mypy @$(DMAKE) -j$(CPUS) update-check cpplint pylint mypy
@$(PCOMMANDBATCH) 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_prepass
@$(DMAKE) -j$(CPUS) update-check cpplint-full pylint-full mypy-full @$(DMAKE) -j$(CPUS) update-check cpplint-full pylint-full mypy-full
@$(PCOMMANDBATCH) 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_prepass
@$(DMAKE) -j$(CPUS) update-check cpplint pylint mypy @$(DMAKE) -j$(CPUS) update-check cpplint pylint mypy
@$(PCOMMANDBATCH) 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_prepass
@$(DMAKE) -j$(CPUS) update-check cpplint-full pylint-full mypy-full @$(DMAKE) -j$(CPUS) update-check cpplint-full pylint-full mypy-full
@$(PCOMMANDBATCH) 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: env meta
@$(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: env meta
@$(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_prepass
@$(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_prepass
@$(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_prepass
@$(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_prepass
@$(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_prepass
@$(PCOMMAND) dmypy @$(PCOMMAND) dmypy
# Stop the mypy daemon # Stop the mypy daemon
dmypy-stop: py_check_prereqs dmypy-stop: py_check_prepass
@$(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_prepass
@$(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_prepass
@$(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_prepass
@$(PCOMMAND) pycharm -full @$(PCOMMAND) pycharm -full
# Build prerequisites needed for python checks. # Build prerequisites needed for python checks.
@ -867,12 +868,12 @@ pycharm-full: py_check_prereqs
# others (such as by the 'check-full' target) the parent target should # others (such as by the 'check-full' target) the parent target should
# explicitly built this beforehand to ensure it does not happen during the # explicitly built this beforehand to ensure it does not happen during the
# parallel part. # parallel part.
py_check_prereqs: dummymodules py_check_prepass: dummymodules
# Tell make which of these targets don't represent files. # Tell make which of these targets don't represent files.
.PHONY: check check-full check2 check2-full cpplint cpplint-full pylint \ .PHONY: check check-full check2 check2-full cpplint cpplint-full pylint \
pylint-full mypy mypy-full dmypy dmypy-stop pycharm pycharm-full \ pylint-full mypy mypy-full dmypy dmypy-stop pycharm pycharm-full \
py_check_prereqs py_check_prepass
################################################################################ ################################################################################
@ -890,12 +891,12 @@ py_check_prereqs: dummymodules
TEST_TARGET ?= tests TEST_TARGET ?= tests
# Run all tests. (live execution verification) # Run all tests. (live execution verification)
test: py_check_prereqs test: py_check_prepass
@$(PCOMMANDBATCH) echo BLU Running all tests... @$(PCOMMANDBATCH) echo BLU Running all tests...
@$(PCOMMAND) tests_warm_start @$(PCOMMAND) tests_warm_start
@$(PCOMMAND) pytest -v $(TEST_TARGET) @$(PCOMMAND) pytest -v $(TEST_TARGET)
test-verbose: py_check_prereqs test-verbose: py_check_prepass
@$(PCOMMANDBATCH) echo BLU Running all tests... @$(PCOMMANDBATCH) echo BLU Running all tests...
@$(PCOMMAND) tests_warm_start @$(PCOMMAND) tests_warm_start
@$(PCOMMAND) pytest -o log_cli=true -o log_cli_level=debug \ @$(PCOMMAND) pytest -o log_cli=true -o log_cli_level=debug \
@ -933,7 +934,7 @@ test-rpc:
preflight: preflight:
@$(MAKE) format @$(MAKE) format
@$(MAKE) update @$(MAKE) update
@$(MAKE) -j$(CPUS) py_check_prereqs # Needs to be done explicitly first. @$(MAKE) -j$(CPUS) py_check_prepass # Needs to be done explicitly first.
@$(MAKE) -j$(CPUS) cpplint pylint mypy test @$(MAKE) -j$(CPUS) cpplint pylint mypy test
@$(PCOMMANDBATCH) echo SGRN BLD PREFLIGHT SUCCESSFUL! @$(PCOMMANDBATCH) echo SGRN BLD PREFLIGHT SUCCESSFUL!
@ -941,7 +942,7 @@ preflight:
preflight-full: preflight-full:
@$(MAKE) format-full @$(MAKE) format-full
@$(MAKE) update @$(MAKE) update
@$(MAKE) -j$(CPUS) py_check_prereqs # Needs to be done explicitly first. @$(MAKE) -j$(CPUS) py_check_prepass # Needs to be done explicitly first.
@$(MAKE) -j$(CPUS) cpplint-full pylint-full mypy-full test-full @$(MAKE) -j$(CPUS) cpplint-full pylint-full mypy-full test-full
@$(PCOMMANDBATCH) echo SGRN BLD PREFLIGHT SUCCESSFUL! @$(PCOMMANDBATCH) echo SGRN BLD PREFLIGHT SUCCESSFUL!
@ -949,7 +950,7 @@ preflight-full:
preflight2: preflight2:
@$(MAKE) format @$(MAKE) format
@$(MAKE) update @$(MAKE) update
@$(MAKE) -j$(CPUS) py_check_prereqs # Needs to be done explicitly first. @$(MAKE) -j$(CPUS) py_check_prepass # Needs to be done explicitly first.
@$(MAKE) -j$(CPUS) cpplint pylint mypy test @$(MAKE) -j$(CPUS) cpplint pylint mypy test
@$(PCOMMANDBATCH) echo SGRN BLD PREFLIGHT SUCCESSFUL! @$(PCOMMANDBATCH) echo SGRN BLD PREFLIGHT SUCCESSFUL!
@ -957,7 +958,7 @@ preflight2:
preflight2-full: preflight2-full:
@$(MAKE) format-full @$(MAKE) format-full
@$(MAKE) update @$(MAKE) update
@$(MAKE) -j$(CPUS) py_check_prereqs # Needs to be done explicitly first. @$(MAKE) -j$(CPUS) py_check_prepass # Needs to be done explicitly first.
@$(MAKE) -j$(CPUS) cpplint-full pylint-full mypy-full test-full @$(MAKE) -j$(CPUS) cpplint-full pylint-full mypy-full test-full
@$(PCOMMANDBATCH) echo SGRN BLD PREFLIGHT SUCCESSFUL! @$(PCOMMANDBATCH) echo SGRN BLD PREFLIGHT SUCCESSFUL!
@ -997,7 +998,7 @@ windows-release: windows-release-build
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: prereqs \ windows-debug-build: env \
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
@$(WSLW) $(PCOMMAND) ensure_prefab_platform windows_x86 @$(WSLW) $(PCOMMAND) ensure_prefab_platform windows_x86
@ -1007,7 +1008,7 @@ windows-debug-build: prereqs \
$(MAKE) _windows-wsl-build $(MAKE) _windows-wsl-build
# Rebuild a debug windows build (from WSL). # Rebuild a debug windows build (from WSL).
windows-debug-rebuild: prereqs \ windows-debug-rebuild: env \
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
@$(WSLW) $(PCOMMAND) ensure_prefab_platform windows_x86 @$(WSLW) $(PCOMMAND) ensure_prefab_platform windows_x86
@ -1017,7 +1018,7 @@ windows-debug-rebuild: prereqs \
$(MAKE) _windows-wsl-rebuild $(MAKE) _windows-wsl-rebuild
# Build a release windows build (from WSL). # Build a release windows build (from WSL).
windows-release-build: prereqs \ windows-release-build: env \
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
@$(WSLW) $(PCOMMAND) ensure_prefab_platform windows_x86 @$(WSLW) $(PCOMMAND) ensure_prefab_platform windows_x86
@ -1027,7 +1028,7 @@ windows-release-build: prereqs \
$(MAKE) _windows-wsl-build $(MAKE) _windows-wsl-build
# Rebuild a release windows build (from WSL). # Rebuild a release windows build (from WSL).
windows-release-rebuild: prereqs \ windows-release-rebuild: env \
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
@$(WSLW) $(PCOMMAND) ensure_prefab_platform windows_x86 @$(WSLW) $(PCOMMAND) ensure_prefab_platform windows_x86
@ -1037,13 +1038,13 @@ windows-release-rebuild: prereqs \
$(MAKE) _windows-wsl-rebuild $(MAKE) _windows-wsl-rebuild
# Remove all non-git-managed files in windows subdir. # Remove all non-git-managed files in windows subdir.
windows-clean: prereqs windows-clean: env
@$(CHECK_CLEAN_SAFETY) @$(CHECK_CLEAN_SAFETY)
git clean -dfx ballisticakit-windows git clean -dfx ballisticakit-windows
rm -rf build/windows $(LAZYBUILDDIR) rm -rf build/windows $(LAZYBUILDDIR)
# Show what would be cleaned. # Show what would be cleaned.
windows-clean-list: prereqs windows-clean-list: env
@$(CHECK_CLEAN_SAFETY) @$(CHECK_CLEAN_SAFETY)
git clean -dnx ballisticakit-windows git clean -dnx ballisticakit-windows
echo would also remove build/windows $(LAZYBUILDDIR) echo would also remove build/windows $(LAZYBUILDDIR)
@ -1196,11 +1197,15 @@ DMAKE = $(MAKE) MAKEFLAGS= MKFLAGS= MAKELEVEL=
# if using this on other platforms. # if using this on other platforms.
CPUS = $(shell getconf _NPROCESSORS_ONLN || echo 8) CPUS = $(shell getconf _NPROCESSORS_ONLN || echo 8)
PROJ_DIR = $(abspath $(CURDIR)) PROJ_DIR = $(abspath $(CURDIR))
# IMPORTANT: Make sure anything using these values has built env first (so
# that pcommand exists).
VERSION = $(shell $(PCOMMAND) version version) VERSION = $(shell $(PCOMMAND) version version)
BUILD_NUMBER = $(shell $(PCOMMAND) version build) BUILD_NUMBER = $(shell $(PCOMMAND) version build)
STAGE_BUILD = $(PROJ_DIR)/$(PCOMMAND) stage_build
BUILD_DIR = $(PROJ_DIR)/build BUILD_DIR = $(PROJ_DIR)/build
LAZYBUILDDIR = .cache/lazybuild LAZYBUILDDIR = .cache/lazybuild
STAGE_BUILD = $(PROJ_DIR)/$(PCOMMAND) stage_build
# Things to ignore when doing root level cleans. Note that we exclude build # Things to ignore when doing root level cleans. Note that we exclude build
# and just blow that away manually; it might contain git repos or other things # and just blow that away manually; it might contain git repos or other things
@ -1216,25 +1221,32 @@ 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 \
.venv/efro_venv_complete tools/pcommand .venv/.efro_venv_complete tools/pcommand
# Anything that should trigger an environment-check when changed. # Anything that should trigger an environment-check when changed.
ENV_SRC = tools/batools/build.py .venv/efro_venv_complete tools/pcommand ENV_SRC = tools/batools/build.py .venv/.efro_venv_complete tools/pcommand
# Generate a pcommand script hard-coded to use our virtual environment. # Generate a pcommand script hard-coded to use our virtual environment.
# This is a prereq dependency so should not itself depend on prereqs. # This is a prereq dependency so should not itself depend on env.
tools/pcommand: tools/efrotools/genwrapper.py tools/efrotools/pyver.py tools/pcommand: tools/efrotools/genwrapper.py tools/efrotools/pyver.py
@echo Generating tools/pcommand... @echo Generating tools/pcommand...
@PYTHONPATH=tools python3 -m \ @PYTHONPATH=tools python3 -m \
efrotools.genwrapper pcommand batools.pcommandmain tools/pcommand efrotools.genwrapper pcommand batools.pcommandmain tools/pcommand
# Generate a cloudshell script hard-coded to use our virtual environment. # Generate a cloudshell script hard-coded to use our virtual environment.
# This is a prereq dependency so should not itself depend on prereqs. # This is a prereq dependency so should not itself depend on env.
tools/cloudshell: tools/efrotools/genwrapper.py tools/efrotools/pyver.py tools/cloudshell: tools/efrotools/genwrapper.py tools/efrotools/pyver.py
@echo Generating tools/cloudshell... @echo Generating tools/cloudshell...
@PYTHONPATH=tools python3 -m \ @PYTHONPATH=tools python3 -m \
efrotools.genwrapper cloudshell efrotoolsinternal.cloudshell tools/cloudshell efrotools.genwrapper cloudshell efrotoolsinternal.cloudshell tools/cloudshell
# Generate a bacloud script hard-coded to use our virtual environment.
# This is a prereq dependency so should not itself depend on env.
tools/bacloud: tools/efrotools/genwrapper.py tools/efrotools/pyver.py
@echo Generating tools/bacloud...
@PYTHONPATH=tools python3 -m \
efrotools.genwrapper bacloud batools.bacloud tools/bacloud
.clang-format: config/toolconfigsrc/clang-format $(TOOL_CFG_SRC) .clang-format: config/toolconfigsrc/clang-format $(TOOL_CFG_SRC)
@$(TOOL_CFG_INST) $< $@ @$(TOOL_CFG_INST) $< $@
@ -1253,7 +1265,7 @@ tools/cloudshell: tools/efrotools/genwrapper.py tools/efrotools/pyver.py
.mypy.ini: config/toolconfigsrc/mypy.ini $(TOOL_CFG_SRC) .mypy.ini: config/toolconfigsrc/mypy.ini $(TOOL_CFG_SRC)
@$(TOOL_CFG_INST) $< $@ @$(TOOL_CFG_INST) $< $@
.pyrightconfig.json: config/toolconfigsrc/pyrightconfig.yaml $(TOOL_CFG_SRC) .pyrightconfig.json: config/toolconfigsrc/pyrightconfig.toml $(TOOL_CFG_SRC)
@$(TOOL_CFG_INST) $< $@ @$(TOOL_CFG_INST) $< $@
# Set this to 1 to skip environment checks. # Set this to 1 to skip environment checks.
@ -1261,19 +1273,31 @@ SKIP_ENV_CHECKS ?= 0
VENV_PYTHON ?= python3.12 VENV_PYTHON ?= python3.12
# Rebuild our virtual environment whenever reqs or Python version changes. # Increment this to force all downstream venvs to fully rebuild. Useful after
# This is a prereq dependency so should not itself depend on prereqs. Note # removing requirements since upgrading in place will never uninstall stuff.
# that we rely on pcommand but can't use it in here until the end when the VENV_STATE = 1
# venv is up.
.venv/efro_venv_complete: tools/pcommand config/requirements.txt \ # Rebuild our virtual environment whenever reqs, Python version, or explicit
# state number changes. This is a dependency of env so it should not itself
# depend on env. Note that we list pcommand as a requirement but can't use it
# in here until the end when the venv is up. Also note that we try to update
# venvs in place when possible, but when Python version or venv-state changes
# we blow it away and start over to be safe.
.venv/.efro_venv_complete: tools/pcommand config/requirements.txt \
tools/efrotools/pyver.py tools/efrotools/pyver.py
@echo Creating Project\'s Python Virtual Environment... @[ -f .venv/bin/$(VENV_PYTHON) ] \
@rm -rf .venv && [ -f .venv/.efro_venv_state_$(VENV_STATE) ] \
&& echo Updating existing $(VENV_PYTHON) virtual environment in \'.venv\'... \
|| (echo Creating new $(VENV_PYTHON) virtual environment in \'.venv\'... \
&& rm -rf .venv)
$(VENV_PYTHON) -m venv .venv $(VENV_PYTHON) -m venv .venv
.venv/bin/pip install --upgrade pip .venv/bin/pip install --upgrade pip
.venv/bin/pip install -r config/requirements.txt .venv/bin/pip install -r config/requirements.txt
touch .venv/efro_venv_complete # Done last to avoid partly-built venvs. touch .venv/.efro_venv_state_$(VENV_STATE) \
@$(PCOMMAND) echo GRN Python Virtual Environment Created. .venv/.efro_venv_complete # Done last to enforce fully-built venvs.
@$(PCOMMAND) echo \
GRN Project virtual environment for BLD $(VENV_PYTHON) RST GRN \
at BLD .venv RST GRN is ready to use.
.cache/checkenv: $(ENV_SRC) .cache/checkenv: $(ENV_SRC)
@if [ $(SKIP_ENV_CHECKS) -ne 1 ]; then \ @if [ $(SKIP_ENV_CHECKS) -ne 1 ]; then \
@ -1282,6 +1306,7 @@ tools/efrotools/pyver.py
$(PCOMMANDBATCHBIN): src/tools/pcommandbatch/pcommandbatch.c \ $(PCOMMANDBATCHBIN): src/tools/pcommandbatch/pcommandbatch.c \
src/tools/pcommandbatch/cJSON.c src/tools/pcommandbatch/cJSON.c
@$(MAKE) tools/pcommand
@$(PCOMMAND) build_pcommandbatch $^ $@ @$(PCOMMAND) build_pcommandbatch $^ $@
# CMake build-type lowercase # CMake build-type lowercase
@ -1329,7 +1354,7 @@ ballisticakit-cmake/.clang-format: .clang-format
&& mv compile_commands.json .cache/compile_commands_db && mv compile_commands.json .cache/compile_commands_db
@$(PCOMMANDBATCH) echo BLU Created compile commands db at $@ @$(PCOMMANDBATCH) echo BLU Created compile commands db at $@
_windows-wsl-build: prereqs _windows-wsl-build: env
@$(PCOMMAND) wsl_build_check_win_drive @$(PCOMMAND) wsl_build_check_win_drive
$(WIN_MSBUILD_EXE_B) \ $(WIN_MSBUILD_EXE_B) \
$(shell $(PCOMMAND) wsl_path_to_win --escape \ $(shell $(PCOMMAND) wsl_path_to_win --escape \
@ -1340,7 +1365,7 @@ _windows-wsl-build: prereqs
$(VISUAL_STUDIO_VERSION) $(VISUAL_STUDIO_VERSION)
@$(PCOMMAND) echo BLU BLD Built build/windows/BallisticaKit$(WINPRJ).exe. @$(PCOMMAND) echo BLU BLD Built build/windows/BallisticaKit$(WINPRJ).exe.
_windows-wsl-rebuild: prereqs _windows-wsl-rebuild: env
@$(PCOMMAND) wsl_build_check_win_drive @$(PCOMMAND) wsl_build_check_win_drive
$(WIN_MSBUILD_EXE_B) \ $(WIN_MSBUILD_EXE_B) \
$(shell $(PCOMMAND) wsl_path_to_win --escape \ $(shell $(PCOMMAND) wsl_path_to_win --escape \

View File

@ -1205,7 +1205,6 @@
<w>objpath</w> <w>objpath</w>
<w>objset</w> <w>objset</w>
<w>objsizes</w> <w>objsizes</w>
<w>objtoyaml</w>
<w>objtypes</w> <w>objtypes</w>
<w>obstack</w> <w>obstack</w>
<w>obvs</w> <w>obvs</w>

View File

@ -31,8 +31,6 @@
"astroid", "astroid",
"pylint.lint", "pylint.lint",
"pytest", "pytest",
"pytz",
"yaml",
"requests", "requests",
"typing_extensions", "typing_extensions",
"cpplint", "cpplint",
@ -47,7 +45,8 @@
"openstep_parser", "openstep_parser",
"daemon", "daemon",
"jinja2", "jinja2",
"jinja2.Environment" "jinja2.Environment",
"tomlkit"
], ],
"python_paths": [ "python_paths": [
"src/assets/ba_data/python", "src/assets/ba_data/python",

View File

@ -1,8 +1,8 @@
ansiwrap==0.8.4
cpplint==1.6.1 cpplint==1.6.1
dmgbuild==1.6.1
filelock==3.13.4 filelock==3.13.4
furo==2024.1.29 furo==2024.1.29
mypy==1.9.0 mypy==1.10.0
pbxproj==4.1.0 pbxproj==4.1.0
pdoc==14.4.0 pdoc==14.4.0
pur==7.3.1 pur==7.3.1
@ -12,13 +12,10 @@ pytest==8.1.1
python-daemon==3.0.1 python-daemon==3.0.1
python-lsp-black==2.0.0 python-lsp-black==2.0.0
python-lsp-server==1.11.0 python-lsp-server==1.11.0
pytz==2024.1
PyYAML==6.0.1
requests==2.31.0 requests==2.31.0
Sphinx==7.3.7 Sphinx==7.3.7
tomlkit==0.12.4
types-certifi==2021.10.8.3 types-certifi==2021.10.8.3
types-filelock==3.2.7 types-filelock==3.2.7
types-pytz==2024.1.0.20240417
types-PyYAML==6.0.12.20240311
types-requests==2.31.0.20240406 types-requests==2.31.0.20240406
typing_extensions==4.11.0 typing_extensions==4.11.0

View File

@ -198,7 +198,7 @@ ctx.filter_file_names = {
'LICENSE', 'LICENSE',
'cloudtool', 'cloudtool',
'bacloud', 'bacloud',
'config_template.yaml', 'config_template.toml',
'.efrocachemap', '.efrocachemap',
} }

View File

@ -1,6 +1,6 @@
# Ballistica Tool Config Source # Ballistica Tool Config Source
These configs can be installed via 'make prereqs' in the project root. These configs can be installed via 'make env' in the project root.
(this should automatically happen as part of other targets such as 'make check') (this should automatically happen as part of other targets such as 'make check')
Some of these are filtered to include an abs path to the project root or other Some of these are filtered to include an abs path to the project root or other

View File

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

View File

@ -0,0 +1,16 @@
# Pyright's actual config is a json file but we're using toml here so we
# can include lovely comments (yaml is a superset of json) and then we
# bake it down into a json file.
# For now I'm listing explicit things here. Once we get everything
# passing we can autogenerate the include list like we do for other
# checkers.
include = [ 'tools' ]
# Ideally we should get to 'strict' for everying if we want to consider
# leaning on this as much as we do mypy.
typeCheckingMode = 'basic'
reportMissingTypeStubs = true
stubPath = 'src/stubs'
pythonPlatform = 'Linux'

View File

@ -1,19 +0,0 @@
# Pyright's actual config is a json file but we're using yaml here so we can
# include lovely comments (yaml is a superset of json) and then we bake it down
# into a json file.
{
# For now I'm listing explicit things here. Once we get everything passing we
# can autogenerate the include list like we do for other checkers.
"include": [
"tools"
],
# Ideally we should get to 'strict' for everying if we want to consider
# leaning on this as much as we do mypy. But
"typeCheckingMode": "basic",
"reportMissingTypeStubs": true,
"stubPath": "src/stubs",
"pythonPlatform": "Linux"
}

View File

@ -945,8 +945,6 @@
"ba_data/meshes/zoeUpperArm.bob", "ba_data/meshes/zoeUpperArm.bob",
"ba_data/meshes/zoeUpperLeg.bob", "ba_data/meshes/zoeUpperLeg.bob",
"ba_data/python-site-packages/__pycache__/typing_extensions.cpython-312.opt-1.pyc", "ba_data/python-site-packages/__pycache__/typing_extensions.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/_yaml/__init__.py",
"ba_data/python-site-packages/_yaml/__pycache__/__init__.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/certifi/__init__.py", "ba_data/python-site-packages/certifi/__init__.py",
"ba_data/python-site-packages/certifi/__main__.py", "ba_data/python-site-packages/certifi/__main__.py",
"ba_data/python-site-packages/certifi/__pycache__/__init__.cpython-312.opt-1.pyc", "ba_data/python-site-packages/certifi/__pycache__/__init__.cpython-312.opt-1.pyc",
@ -955,40 +953,6 @@
"ba_data/python-site-packages/certifi/cacert.pem", "ba_data/python-site-packages/certifi/cacert.pem",
"ba_data/python-site-packages/certifi/core.py", "ba_data/python-site-packages/certifi/core.py",
"ba_data/python-site-packages/typing_extensions.py", "ba_data/python-site-packages/typing_extensions.py",
"ba_data/python-site-packages/yaml/__init__.py",
"ba_data/python-site-packages/yaml/__pycache__/__init__.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/composer.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/constructor.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/cyaml.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/dumper.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/emitter.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/error.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/events.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/loader.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/nodes.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/parser.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/reader.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/representer.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/resolver.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/scanner.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/serializer.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/tokens.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/composer.py",
"ba_data/python-site-packages/yaml/constructor.py",
"ba_data/python-site-packages/yaml/cyaml.py",
"ba_data/python-site-packages/yaml/dumper.py",
"ba_data/python-site-packages/yaml/emitter.py",
"ba_data/python-site-packages/yaml/error.py",
"ba_data/python-site-packages/yaml/events.py",
"ba_data/python-site-packages/yaml/loader.py",
"ba_data/python-site-packages/yaml/nodes.py",
"ba_data/python-site-packages/yaml/parser.py",
"ba_data/python-site-packages/yaml/reader.py",
"ba_data/python-site-packages/yaml/representer.py",
"ba_data/python-site-packages/yaml/resolver.py",
"ba_data/python-site-packages/yaml/scanner.py",
"ba_data/python-site-packages/yaml/serializer.py",
"ba_data/python-site-packages/yaml/tokens.py",
"ba_data/textures/achievementBoxer.dds", "ba_data/textures/achievementBoxer.dds",
"ba_data/textures/achievementBoxer.ktx", "ba_data/textures/achievementBoxer.ktx",
"ba_data/textures/achievementBoxer.pvr", "ba_data/textures/achievementBoxer.pvr",

View File

@ -28,12 +28,12 @@ PCOMMAND = $(TOOLS_DIR)/pcommand
# pcommand. See tools/efrotools/pcommandbatch.py for more info on when to use # pcommand. See tools/efrotools/pcommandbatch.py for more info on when to use
# which. # which.
PCOMMANDBATCHBIN = $(PROJ_DIR)/.cache/pcommandbatch/pcommandbatch PCOMMANDBATCHBIN = $(PROJ_DIR)/.cache/pcommandbatch/pcommandbatch
ifeq ($(BA_PCOMMANDBATCH_DISABLE),1) ifeq ($(BA_PCOMMANDBATCH_ENABLE),0)
PCOMMANDBATCH = $(TOOLS_DIR)/pcommand
PCOMMANDBATCHFROMROOT = tools/pcommand
else
PCOMMANDBATCH = $(PCOMMANDBATCHBIN) PCOMMANDBATCH = $(PCOMMANDBATCHBIN)
PCOMMANDBATCHFROMROOT = .cache/pcommandbatch/pcommandbatch PCOMMANDBATCHFROMROOT = .cache/pcommandbatch/pcommandbatch
else
PCOMMANDBATCH = $(TOOLS_DIR)/pcommand
PCOMMANDBATCHFROMROOT = tools/pcommand
endif endif
# High level targets: generally these are what should be used here. # High level targets: generally these are what should be used here.
@ -2691,53 +2691,17 @@ $(foreach element,$(SCRIPT_TARGETS_PYC_PRIVATE_ANDROID),\
$(eval $(call make-opt-pyc-target,$(element)))) $(eval $(call make-opt-pyc-target,$(element))))
SCRIPT_TARGETS_PY_PRIVATE_COMMON = \ SCRIPT_TARGETS_PY_PRIVATE_COMMON = \
$(BUILD_DIR)/ba_data/python-site-packages/_yaml/__init__.py \
$(BUILD_DIR)/ba_data/python-site-packages/certifi/__init__.py \ $(BUILD_DIR)/ba_data/python-site-packages/certifi/__init__.py \
$(BUILD_DIR)/ba_data/python-site-packages/certifi/__main__.py \ $(BUILD_DIR)/ba_data/python-site-packages/certifi/__main__.py \
$(BUILD_DIR)/ba_data/python-site-packages/certifi/core.py \ $(BUILD_DIR)/ba_data/python-site-packages/certifi/core.py \
$(BUILD_DIR)/ba_data/python-site-packages/typing_extensions.py \ $(BUILD_DIR)/ba_data/python-site-packages/typing_extensions.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__init__.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/composer.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/constructor.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/cyaml.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/dumper.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/emitter.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/error.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/events.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/loader.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/nodes.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/parser.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/reader.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/representer.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/resolver.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/scanner.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/serializer.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/tokens.py \
$(BUILD_DIR)/sphinx/static/conf.py $(BUILD_DIR)/sphinx/static/conf.py
SCRIPT_TARGETS_PYC_PRIVATE_COMMON = \ SCRIPT_TARGETS_PYC_PRIVATE_COMMON = \
$(BUILD_DIR)/ba_data/python-site-packages/_yaml/__pycache__/__init__.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/certifi/__pycache__/__init__.cpython-312.opt-1.pyc \ $(BUILD_DIR)/ba_data/python-site-packages/certifi/__pycache__/__init__.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/certifi/__pycache__/__main__.cpython-312.opt-1.pyc \ $(BUILD_DIR)/ba_data/python-site-packages/certifi/__pycache__/__main__.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/certifi/__pycache__/core.cpython-312.opt-1.pyc \ $(BUILD_DIR)/ba_data/python-site-packages/certifi/__pycache__/core.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/__pycache__/typing_extensions.cpython-312.opt-1.pyc \ $(BUILD_DIR)/ba_data/python-site-packages/__pycache__/typing_extensions.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/__init__.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/composer.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/constructor.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/cyaml.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/dumper.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/emitter.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/error.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/events.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/loader.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/nodes.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/parser.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/reader.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/representer.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/resolver.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/scanner.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/serializer.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/tokens.cpython-312.opt-1.pyc \
$(BUILD_DIR)/sphinx/static/__pycache__/conf.cpython-312.opt-1.pyc $(BUILD_DIR)/sphinx/static/__pycache__/conf.cpython-312.opt-1.pyc
# Rule to copy src asset scripts to dst. # Rule to copy src asset scripts to dst.

View File

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

View File

@ -7,6 +7,8 @@ from __future__ import annotations
import logging import logging
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from efro.util import utc_now
import babase import babase
import bascenev1 import bascenev1
@ -522,10 +524,10 @@ class StoreSubsystem:
if item in sales_raw: if item in sales_raw:
if not plus.get_purchased(item): if not plus.get_purchased(item):
to_end = ( to_end = (
datetime.datetime.utcfromtimestamp( datetime.datetime.fromtimestamp(
sales_raw[item]['e'] sales_raw[item]['e'], datetime.UTC
) )
- datetime.datetime.utcnow() - utc_now()
).total_seconds() ).total_seconds()
if to_end > 0: if to_end > 0:
sale_times.append(int(to_end * 1000)) sale_times.append(int(to_end * 1000))

View File

@ -52,8 +52,8 @@ if TYPE_CHECKING:
# Build number and version of the ballistica binary we expect to be # Build number and version of the ballistica binary we expect to be
# using. # using.
TARGET_BALLISTICA_BUILD = 21804 TARGET_BALLISTICA_BUILD = 21824
TARGET_BALLISTICA_VERSION = '1.7.34' TARGET_BALLISTICA_VERSION = '1.7.35'
@dataclass @dataclass

View File

@ -6,6 +6,8 @@ from __future__ import annotations
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from efro.util import utc_now
import bauiv1 as bui import bauiv1 as bui
if TYPE_CHECKING: if TYPE_CHECKING:
@ -541,24 +543,24 @@ class GetCurrencyWindow(bui.Window):
plus = bui.app.plus plus = bui.app.plus
assert plus is not None assert plus is not None
# if we somehow get signed out, just die.. # If we somehow get signed out, just die.
if plus.get_v1_account_state() != 'signed_in': if plus.get_v1_account_state() != 'signed_in':
self._back() self._back()
return return
self._ticket_count = plus.get_v1_account_ticket_count() self._ticket_count = plus.get_v1_account_ticket_count()
# update our incentivized ad button depending on whether ads are # Update our incentivized ad button depending on whether ads are
# available # available.
if self._ad_button is not None: if self._ad_button is not None:
next_reward_ad_time = plus.get_v1_account_misc_read_val_2( next_reward_ad_time = plus.get_v1_account_misc_read_val_2(
'nextRewardAdTime', None 'nextRewardAdTime', None
) )
if next_reward_ad_time is not None: if next_reward_ad_time is not None:
next_reward_ad_time = datetime.datetime.utcfromtimestamp( next_reward_ad_time = datetime.datetime.fromtimestamp(
next_reward_ad_time next_reward_ad_time, datetime.UTC
) )
now = datetime.datetime.utcnow() now = utc_now()
if plus.have_incentivized_ad() and ( if plus.have_incentivized_ad() and (
next_reward_ad_time is None or next_reward_ad_time <= now next_reward_ad_time is None or next_reward_ad_time <= now
): ):
@ -586,8 +588,8 @@ class GetCurrencyWindow(bui.Window):
sval = '' sval = ''
bui.textwidget(edit=self._ad_time_text, text=sval) bui.textwidget(edit=self._ad_time_text, text=sval)
# if this is our first update, assign immediately; otherwise kick # If this is our first update, assign immediately; otherwise kick
# off a smooth transition if the value has changed # off a smooth transition if the value has changed.
if self._smooth_ticket_count is None: if self._smooth_ticket_count is None:
self._smooth_ticket_count = float(self._ticket_count) self._smooth_ticket_count = float(self._ticket_count)
self._smooth_update() # will set the text widget self._smooth_update() # will set the text widget
@ -614,8 +616,8 @@ class GetCurrencyWindow(bui.Window):
plus = bui.app.plus plus = bui.app.plus
assert plus is not None assert plus is not None
# if we're on a platform without purchases, inform the user they # If we're on a platform without purchases, inform the user they
# can link their accounts and buy stuff elsewhere # can link their accounts and buy stuff elsewhere.
app = bui.app app = bui.app
assert app.classic is not None assert app.classic is not None
if ( if (
@ -652,8 +654,10 @@ class GetCurrencyWindow(bui.Window):
return return
appinvite.handle_app_invites_press() appinvite.handle_app_invites_press()
return return
# here we ping the server to ask if it's valid for us to
# purchase this.. (better to fail now than after we've paid locally) # Here we ping the server to ask if it's valid for us to
# purchase this.. (better to fail now than after we've paid
# locally).
app = bui.app app = bui.app
assert app.classic is not None assert app.classic is not None
bui.app.classic.master_server_v1_get( bui.app.classic.master_server_v1_get(
@ -694,7 +698,7 @@ class GetCurrencyWindow(bui.Window):
color=(1, 0, 0), color=(1, 0, 0),
) )
# actually start the purchase locally.. # Actually start the purchase locally.
def _do_purchase(self, item: str) -> None: def _do_purchase(self, item: str) -> None:
plus = bui.app.plus plus = bui.app.plus
assert plus is not None assert plus is not None
@ -702,15 +706,15 @@ class GetCurrencyWindow(bui.Window):
if item == 'ad': if item == 'ad':
import datetime import datetime
# if ads are disabled until some time, error.. # If ads are disabled until some time, error.
next_reward_ad_time = plus.get_v1_account_misc_read_val_2( next_reward_ad_time = plus.get_v1_account_misc_read_val_2(
'nextRewardAdTime', None 'nextRewardAdTime', None
) )
if next_reward_ad_time is not None: if next_reward_ad_time is not None:
next_reward_ad_time = datetime.datetime.utcfromtimestamp( next_reward_ad_time = datetime.datetime.fromtimestamp(
next_reward_ad_time next_reward_ad_time, datetime.UTC
) )
now = datetime.datetime.utcnow() now = utc_now()
if ( if (
next_reward_ad_time is not None and next_reward_ad_time > now next_reward_ad_time is not None and next_reward_ad_time > now
) or self._ad_button_greyed: ) or self._ad_button_greyed:
@ -730,7 +734,7 @@ class GetCurrencyWindow(bui.Window):
def _back(self) -> None: def _back(self) -> None:
from bauiv1lib.store import browser from bauiv1lib.store import browser
# no-op if our underlying widget is dead or on its way out. # No-op if our underlying widget is dead or on its way out.
if not self._root_widget or self._root_widget.transitioning_out: if not self._root_widget or self._root_widget.transitioning_out:
return return

View File

@ -15,6 +15,7 @@ from enum import Enum
from threading import Thread from threading import Thread
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from efro.util import utc_now
from efro.error import CommunicationError from efro.error import CommunicationError
import bacommon.cloud import bacommon.cloud
import bauiv1 as bui import bauiv1 as bui
@ -681,8 +682,10 @@ class StoreBrowserWindow(bui.Window):
# Look at the current set of sales; filter any with time remaining. # Look at the current set of sales; filter any with time remaining.
for sale_item, sale_info in list(sales_raw.items()): for sale_item, sale_info in list(sales_raw.items()):
to_end = ( to_end = (
datetime.datetime.utcfromtimestamp(sale_info['e']) datetime.datetime.fromtimestamp(
- datetime.datetime.utcnow() sale_info['e'], datetime.UTC
)
- utc_now()
).total_seconds() ).total_seconds()
if to_end > 0: if to_end > 0:
sales[sale_item] = { sales[sale_item] = {

View File

@ -6,6 +6,8 @@ from __future__ import annotations
import logging import logging
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from efro.util import utc_now
import bauiv1 as bui import bauiv1 as bui
if TYPE_CHECKING: if TYPE_CHECKING:
@ -278,8 +280,10 @@ class StoreButton:
for sale_item, sale_info in list(sales_raw.items()): for sale_item, sale_info in list(sales_raw.items()):
if not plus.get_purchased(sale_item): if not plus.get_purchased(sale_item):
to_end = ( to_end = (
datetime.datetime.utcfromtimestamp(sale_info['e']) datetime.datetime.fromtimestamp(
- datetime.datetime.utcnow() sale_info['e'], datetime.UTC
)
- utc_now()
).total_seconds() ).total_seconds()
if to_end > 0: if to_end > 0:
sale_times.append(to_end) sale_times.append(to_end)

View File

@ -2,8 +2,8 @@ To run this, simply cd into this directory and run ./ballisticakit_server
(on mac or linux) or launch_ballisticakit_server.bat (on windows). (on mac or linux) or launch_ballisticakit_server.bat (on windows).
You'll need to open a UDP port (43210 by default) so that the world can You'll need to open a UDP port (43210 by default) so that the world can
communicate with your server. communicate with your server.
You can configure your server by editing the config.yaml file. You can configure your server by editing the config.toml file.
(if you only see config_template.yaml, you can copy/rename that to config.yaml) (if you only see config_template.toml, you can copy/rename that to config.toml)
Platform-Specific Notes: Platform-Specific Notes:

View File

@ -1,15 +1,17 @@
#!/usr/bin/env python3.12 #!/usr/bin/env python3.12
# Released under the MIT License. See LICENSE for details. # Released under the MIT License. See LICENSE for details.
# #
# pylint: disable=too-many-lines
"""BallisticaKit server manager.""" """BallisticaKit server manager."""
from __future__ import annotations from __future__ import annotations
import json
import os import os
import signal
import subprocess
import sys import sys
import time import time
import json
import signal
import tomllib
import subprocess
from pathlib import Path from pathlib import Path
from threading import Lock, Thread, current_thread from threading import Lock, Thread, current_thread
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
@ -39,6 +41,12 @@ VERSION_STR = '1.3.2'
# #
# - Updated to use Python 3.12. # - Updated to use Python 3.12.
# #
# - Server config file is now in toml format instead of yaml.
#
# - Server config can now be set to a .json file OR a .toml file.
# By default it will look for 'config.json' and then 'config.toml'
# in the same dir as this script.
#
# 1.3.1 # 1.3.1
# #
# - Windows binary is now named 'BallisticaKitHeadless.exe'. # - Windows binary is now named 'BallisticaKitHeadless.exe'.
@ -101,8 +109,7 @@ class ServerManagerApp:
IMMEDIATE_SHUTDOWN_TIME_LIMIT = 5.0 IMMEDIATE_SHUTDOWN_TIME_LIMIT = 5.0
def __init__(self) -> None: def __init__(self) -> None:
self._config_path = 'config.yaml' self._user_provided_config_path: str | None = None
self._user_provided_config_path = False
self._config = ServerConfig() self._config = ServerConfig()
self._ba_root_path = os.path.abspath('dist/ba_root') self._ba_root_path = os.path.abspath('dist/ba_root')
self._interactive = sys.stdin.isatty() self._interactive = sys.stdin.isatty()
@ -125,13 +132,14 @@ class ServerManagerApp:
self._subprocess_sent_unclean_exit = False self._subprocess_sent_unclean_exit = False
self._subprocess_thread: Thread | None = None self._subprocess_thread: Thread | None = None
self._subprocess_exited_cleanly: bool | None = None self._subprocess_exited_cleanly: bool | None = None
self._did_multi_config_warning = False
# This may override the above defaults. # This may override the above defaults.
self._parse_command_line_args() self._parse_command_line_args()
# Do an initial config-load. If the config is invalid at this # Do an initial config-load. If the config is invalid at this
# point we can cleanly die (we're more lenient later on # point we can cleanly die; we're more resilient later on reload
# reloads). # attempts.
self.load_config(strict=True, print_confirmation=False) self.load_config(strict=True, print_confirmation=False)
@property @property
@ -407,8 +415,7 @@ class ServerManagerApp:
raise CleanError(f"Supplied path does not exist: '{path}'.") raise CleanError(f"Supplied path does not exist: '{path}'.")
# We need an abs path because we may be in a different # We need an abs path because we may be in a different
# cwd currently than we will be during the run. # cwd currently than we will be during the run.
self._config_path = os.path.abspath(path) self._user_provided_config_path = os.path.abspath(path)
self._user_provided_config_path = True
i += 2 i += 2
elif arg == '--root': elif arg == '--root':
if i + 1 >= argc: if i + 1 >= argc:
@ -476,11 +483,9 @@ class ServerManagerApp:
+ cls._par( + cls._par(
'Set the config file read by the server script. The config' 'Set the config file read by the server script. The config'
' file contains most options for what kind of game to host.' ' file contains most options for what kind of game to host.'
' It should be in yaml format. Note that yaml is backwards' ' It should be in toml or json format. If not specified,'
' compatible with json so you can just write json if you' ' the script will look for a file named \'config.toml\' or'
' want to. If not specified, the script will look for a' ' \'config.json\' in the same directory as the script.'
' file named \'config.yaml\' in the same directory as the'
' script.'
) )
+ '\n' + '\n'
f'{Clr.BLD}--root [path]{Clr.RST}\n' f'{Clr.BLD}--root [path]{Clr.RST}\n'
@ -570,21 +575,51 @@ class ServerManagerApp:
return return
time.sleep(1) time.sleep(1)
def _get_config_path(self) -> str:
if self._user_provided_config_path is not None:
return self._user_provided_config_path
# Otherwise look for config.toml or config.json in the same dir
# as our script. Need to work in abs paths since we may chdir when
# we start running.
toml_path = os.path.abspath(
os.path.join(os.path.dirname(__file__), 'config.toml')
)
toml_exists = os.path.exists(toml_path)
json_path = os.path.abspath(
os.path.join(os.path.dirname(__file__), 'config.json')
)
json_exists = os.path.exists(json_path)
# Warn if both configs are present.
if toml_exists and json_exists and not self._did_multi_config_warning:
self._did_multi_config_warning = True
print(
f'{Clr.YLW}Both config.toml and config.json'
f' found; will use json.{Clr.RST}',
flush=True,
)
if json_exists:
return json_path
return toml_path
def _load_config_from_file(self, print_confirmation: bool) -> ServerConfig: def _load_config_from_file(self, print_confirmation: bool) -> ServerConfig:
out: ServerConfig | None = None out: ServerConfig | None = None
if not os.path.exists(self._config_path): config_path = self._get_config_path()
if not os.path.exists(config_path):
# Special case: # Special case:
# #
# If the user didn't specify a particular config file, allow # If the user didn't provide a config path AND the default
# gracefully falling back to defaults if the default one is # config path does not exist, fall back to defaults.
# missing.
if not self._user_provided_config_path: if not self._user_provided_config_path:
if print_confirmation: if print_confirmation:
print( print(
f'{Clr.YLW}Default config file not found' f'{Clr.YLW}Default config file not found'
f' (\'{self._config_path}\'); using default' f' (\'{config_path}\'); using default'
f' settings.{Clr.RST}', f' config.{Clr.RST}',
flush=True, flush=True,
) )
self._config_mtime = None self._config_mtime = None
@ -592,25 +627,25 @@ class ServerManagerApp:
return ServerConfig() return ServerConfig()
# Don't be so lenient if the user pointed us at one though. # Don't be so lenient if the user pointed us at one though.
raise RuntimeError(f"Config file not found: '{self._config_path}'.") raise RuntimeError(f"Config file not found: '{config_path}'.")
import yaml with open(config_path, encoding='utf-8') as infile:
if config_path.endswith('.toml'):
user_config_raw = tomllib.loads(infile.read())
elif config_path.endswith('.json'):
user_config_raw = json.loads(infile.read())
else:
raise CleanError(
f"Invalid config file path '{config_path}';"
f" path must end with '.toml' or '.json'."
)
with open(self._config_path, encoding='utf-8') as infile:
user_config_raw = yaml.safe_load(infile.read())
# An empty config file will yield None, and that's ok.
if user_config_raw is not None:
out = dataclass_from_dict(ServerConfig, user_config_raw) out = dataclass_from_dict(ServerConfig, user_config_raw)
# Update our known mod-time since we know it exists. # Update our known mod-time since we know it exists.
self._config_mtime = Path(self._config_path).stat().st_mtime self._config_mtime = Path(config_path).stat().st_mtime
self._last_config_mtime_check_time = time.time() self._last_config_mtime_check_time = time.time()
# Go with defaults if we weren't able to load anything.
if out is None:
out = ServerConfig()
if print_confirmation: if print_confirmation:
print( print(
f'{Clr.CYN}Valid server config file loaded.{Clr.RST}', f'{Clr.CYN}Valid server config file loaded.{Clr.RST}',
@ -885,8 +920,9 @@ class ServerManagerApp:
): ):
self._last_config_mtime_check_time = now self._last_config_mtime_check_time = now
mtime: float | None mtime: float | None
if os.path.isfile(self._config_path): config_path = self._get_config_path()
mtime = Path(self._config_path).stat().st_mtime if os.path.isfile(config_path):
mtime = Path(config_path).stat().st_mtime
else: else:
mtime = None mtime = None
if mtime != self._config_mtime: if mtime != self._config_mtime:

View File

@ -1,5 +1,5 @@
# To configure your server, create a config.yaml file in the same directory # To configure your server, create a config.toml file in the same directory
# as the ballisticakit_server script. The config_template.yaml file can be # as the ballisticakit_server script. The config_template.toml file can be
# copied or renamed as a convenient starting point. # copied or renamed as a convenient starting point.
# Uncomment any of these values to override defaults. # Uncomment any of these values to override defaults.

View File

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

View File

@ -20,7 +20,7 @@ from typing import (
) )
import pytest import pytest
from efro.util import utc_now from efro.util import utc_now, utc_now_naive
from efro.dataclassio import ( from efro.dataclassio import (
dataclass_validate, dataclass_validate,
dataclass_from_dict, dataclass_from_dict,
@ -69,8 +69,6 @@ class _NestedClass:
dval: dict[int, str] = field(default_factory=dict) dval: dict[int, str] = field(default_factory=dict)
# We use utc_now() for a test which is deprecated.
@pytest.mark.filterwarnings('ignore::DeprecationWarning')
def test_assign() -> None: def test_assign() -> None:
"""Testing various assignments.""" """Testing various assignments."""
@ -292,8 +290,8 @@ def test_assign() -> None:
with pytest.raises(ValueError): with pytest.raises(ValueError):
dataclass_to_dict(_TestClass(datetimeval=datetime.datetime.now())) dataclass_to_dict(_TestClass(datetimeval=datetime.datetime.now()))
with pytest.raises(ValueError): with pytest.raises(ValueError):
# This doesn't actually set timezone on the datetime obj. # This doesn't have a timezone on the datetime obj.
dataclass_to_dict(_TestClass(datetimeval=datetime.datetime.utcnow())) dataclass_to_dict(_TestClass(datetimeval=utc_now_naive()))
def test_coerce() -> None: def test_coerce() -> None:

View File

@ -1,23 +0,0 @@
#!/usr/bin/env python3.12
# Released under the MIT License. See LICENSE for details.
#
"""A tool for interacting with ballistica's cloud services.
This facilitates workflows such as creating asset-packages, etc.
"""
from __future__ import annotations
import sys
from batools.bacloud import App
from efro.error import CleanError
try:
App().run()
except KeyboardInterrupt:
# Let's do a clean fail on keyboard interrupt.
# Can make this optional if a backtrace is ever useful.
sys.exit(1)
except CleanError as clean_exc:
clean_exc.pretty_print()
sys.exit(1)

View File

@ -69,11 +69,10 @@ def generate_app_module(
contents = '' contents = ''
for fsetname in sorted(all_fset_names): for fsetname in sorted(all_fset_names):
# for _fsname, fset in sorted(fsets.items()):
if fsetname in missing_soft_fset_names: if fsetname in missing_soft_fset_names:
contents += ( contents += (
f'\n' f'\n'
f'@cached_property\n' f'@property\n'
f'def {fsetname}(self) -> Any | None:\n' f'def {fsetname}(self) -> Any | None:\n'
f' """Our {fsetname} subsystem (not available' f' """Our {fsetname} subsystem (not available'
f' in this project)."""\n' f' in this project)."""\n'
@ -95,11 +94,18 @@ def generate_app_module(
if fset.allow_as_soft_requirement: if fset.allow_as_soft_requirement:
contents += ( contents += (
f'\n' f'\n'
f'@cached_property\n' f'@property\n'
f'def {fset.name}(self) -> {classname} | None:\n' f'def {fset.name}(self) -> {classname} | None:\n'
f' """Our {fset.name} subsystem (if available)."""\n' f' """Our {fset.name} subsystem (if available)."""\n'
f' # pylint: disable=cyclic-import\n' f' return self._get_subsystem_property(\n'
f" '{fset.name}', "
f'self._create_{fset.name}_subsystem\n'
f' ) # type: ignore\n'
f'\n' f'\n'
f'@staticmethod\n'
f'def _create_{fset.name}_subsystem()'
f' -> {classname} | None:\n'
f' # pylint: disable=cyclic-import\n'
f' try:\n' f' try:\n'
f' from {modname} import {classname}\n' f' from {modname} import {classname}\n'
f'\n' f'\n'
@ -114,10 +120,18 @@ def generate_app_module(
else: else:
contents += ( contents += (
f'\n' f'\n'
f'@cached_property\n' '@property\n'
f'def {fset.name}(self) -> {classname}:\n' f'def {fset.name}(self) -> {classname}:\n'
f' """Our {fset.name} subsystem' f' """Our {fset.name} subsystem'
' (always available)."""\n' ' (always available)."""\n'
f' return self._get_subsystem_property(\n'
f" '{fset.name}', "
f'self._create_{fset.name}_subsystem\n'
f' ) # type: ignore\n'
f'\n'
f'@staticmethod\n'
f'def _create_{fset.name}_subsystem()'
f' -> {classname}:\n'
f' # pylint: disable=cyclic-import\n' f' # pylint: disable=cyclic-import\n'
f'\n' f'\n'
f' from {modname} import {classname}\n' f' from {modname} import {classname}\n'

View File

@ -50,13 +50,31 @@ class StateData:
def get_tz_offset_seconds() -> float: def get_tz_offset_seconds() -> float:
"""Return the offset between utc and local time in seconds.""" """Return the offset between utc and local time in seconds."""
tval = time.time() tval = time.time()
# Compare naive current and utc times to get our offset from utc.
utc_offset = ( utc_offset = (
datetime.datetime.fromtimestamp(tval) datetime.datetime.fromtimestamp(tval)
- datetime.datetime.utcfromtimestamp(tval) - datetime.datetime.fromtimestamp(tval, datetime.UTC).replace(
tzinfo=None
)
).total_seconds() ).total_seconds()
return utc_offset return utc_offset
def run_bacloud_main() -> None:
"""Do the thing."""
try:
App().run()
except KeyboardInterrupt:
# Let's do a clean fail on keyboard interrupt.
# Can make this optional if a backtrace is ever useful.
sys.exit(1)
except CleanError as clean_exc:
clean_exc.pretty_print()
sys.exit(1)
class App: class App:
"""Context for a run of the tool.""" """Context for a run of the tool."""
@ -76,17 +94,17 @@ class App:
): ):
raise CleanError('Unable to locate project directory.') raise CleanError('Unable to locate project directory.')
# Also run project prereqs checks so we can hopefully inform the user # Also run project env checks so we can hopefully inform the user
# of missing Python modules/etc. instead of just failing cryptically. # of missing Python modules/etc. instead of just failing cryptically.
try: try:
subprocess.run( subprocess.run(
['make', '--quiet', 'prereqs'], ['make', '--quiet', 'env'],
check=True, check=True,
cwd=self._project_root, cwd=self._project_root,
) )
except subprocess.CalledProcessError as exc: except subprocess.CalledProcessError as exc:
raise CleanError( raise CleanError(
'"make prereqs" check failed. ' '"make env" check failed. '
'Install missing requirements and try again.' 'Install missing requirements and try again.'
) from exc ) from exc

View File

@ -446,92 +446,85 @@ def _get_server_config_raw_contents(projroot: str) -> str:
return textwrap.dedent('\n'.join(lines[firstline : lastline + 1])) return textwrap.dedent('\n'.join(lines[firstline : lastline + 1]))
def _get_server_config_template_yaml(projroot: str) -> str: def _get_server_config_template_toml(projroot: str) -> str:
# pylint: disable=too-many-branches from tomlkit import document, dumps
# pylint: disable=too-many-statements from bacommon.servermanager import ServerConfig
import yaml
cfg = ServerConfig()
# Override some defaults with values we want to display commented
# out instead.
cfg.playlist_code = 12345
cfg.stats_url = 'https://mystatssite.com/showstats?player=${ACCOUNT}'
cfg.clean_exit_minutes = 60
cfg.unclean_exit_minutes = 90
cfg.idle_exit_minutes = 20
cfg.admins = ['pb-yOuRAccOuNtIdHErE', 'pb-aNdMayBeAnotherHeRE']
cfg.protocol_version = 35
cfg.session_max_players_override = 8
cfg.playlist_inline = []
cfg.team_names = ('Red', 'Blue')
cfg.team_colors = ((0.1, 0.25, 1.0), (1.0, 0.25, 0.2))
lines_in = _get_server_config_raw_contents(projroot).splitlines() lines_in = _get_server_config_raw_contents(projroot).splitlines()
# Convert to double quotes only (we'll convert back at the end).
assert all(('"' not in l) for l in lines_in)
lines_in = [l.replace("'", '"') for l in lines_in]
lines_out: list[str] = [] lines_out: list[str] = []
ignore_vars = {'stress_test_players'} ignore_vars = {'stress_test_players'}
for line in lines_in: for line in lines_in:
if any(line.startswith(f'{var}:') for var in ignore_vars):
continue
if line.startswith(' '):
# Ignore indented lines (our few multi-line special cases).
continue
if line.startswith(']') or line.startswith(')'): # Replace attr declarations with commented out toml values.
# Ignore closing lines (our few multi-line special cases). if line != '' and not line.startswith('#') and ':' in line:
before_colon, _after_colon = line.split(':', 1)
vname = before_colon.strip()
if vname in ignore_vars:
continue continue
vval: Any = getattr(cfg, vname)
if line.startswith('team_names:'): doc = document()
lines_out += [ # Toml doesn't support None/null
'#team_names:', if vval is None:
'#- Blue', raise RuntimeError(
'#- Red', f"ServerManager value '{vname}' has value None."
] f' This is not allowed in toml;'
continue f' please provide a dummy value.'
)
assert vval is not None
doc[vname] = vval
lines_out += ['#' + l for l in dumps(doc).strip().splitlines()]
if line.startswith('team_colors:'): # Preserve blank lines, but only one in a row.
lines_out += [ elif line == '':
'#team_colors:', if not lines_out or lines_out[-1] != '':
'#- [0.1, 0.25, 1.0]', lines_out.append(line)
'#- [1.0, 0.25, 0.2]',
]
continue
if line.startswith('playlist_inline:'): # Preserve comment lines.
lines_out += ['#playlist_inline: []'] elif line.startswith('#'):
continue # Convert comments referring to python bools to toml bools.
if line != '' and not line.startswith('#'):
before_equal_sign, vval_raw = line.split('=', 1)
before_equal_sign = before_equal_sign.strip()
vval_raw = vval_raw.strip()
vname = before_equal_sign.split()[0]
assert vname.endswith(':'), f"'{vname}' does not end with ':'"
vname = vname[:-1]
vval: Any
if vval_raw == 'field(default_factory=list)':
vval = []
else:
vval = eval(vval_raw) # pylint: disable=eval-used
# Filter/override a few things.
if vname == 'playlist_code':
# User wouldn't want to pass the default of None here.
vval = 12345
elif vname == 'clean_exit_minutes':
vval = 60
elif vname == 'unclean_exit_minutes':
vval = 90
elif vname == 'idle_exit_minutes':
vval = 20
elif vname == 'stats_url':
vval = 'https://mystatssite.com/showstats?player=${ACCOUNT}'
elif vname == 'admins':
vval = ['pb-yOuRAccOuNtIdHErE', 'pb-aNdMayBeAnotherHeRE']
elif vname == 'protocol_version':
vval = 35
lines_out += [
'#' + l for l in yaml.dump({vname: vval}).strip().splitlines()
]
else:
# Convert comments referring to python bools to yaml bools.
line = line.replace('True', 'true').replace('False', 'false') line = line.replace('True', 'true').replace('False', 'false')
if '(internal)' not in line: if '(internal)' not in line:
lines_out.append(line) lines_out.append(line)
return '\n'.join(lines_out)
out = '\n'.join(lines_out)
# Convert back to single quotes only.
assert "'" not in out
out = out.replace('"', "'")
return out
def filter_server_config(projroot: str, infilepath: str) -> str: def filter_server_config_toml(projroot: str, infilepath: str) -> str:
"""Add commented-out config options to a server config.""" """Add commented-out config options to a server config."""
with open(infilepath, encoding='utf-8') as infile: with open(infilepath, encoding='utf-8') as infile:
cfg = infile.read() cfg = infile.read()
return cfg.replace( return cfg.replace(
'# __CONFIG_TEMPLATE_VALUES__', '# __CONFIG_TEMPLATE_VALUES__',
_get_server_config_template_yaml(projroot), _get_server_config_template_toml(projroot),
) )

View File

@ -1050,7 +1050,8 @@ class SpinoffContext:
# The proper way might be to ask the parent repo for its full list of # The proper way might be to ask the parent repo for its full list of
# script files but that would add more expense. # script files but that would add more expense.
if ( if (
src_path.endswith('.py') or src_path in {'tools/cloudshell'} src_path.endswith('.py')
# or src_path in {'tools/cloudshell'}
) and out != text: ) and out != text:
self._ensure_parent_repo_tool_configs_exist() self._ensure_parent_repo_tool_configs_exist()
out = format_python_str(projroot=self._src_root, code=out) out = format_python_str(projroot=self._src_root, code=out)
@ -1071,7 +1072,7 @@ class SpinoffContext:
# Interestingly, seems we need to use shell command cd here # Interestingly, seems we need to use shell command cd here
# instead of just passing cwd arg. # instead of just passing cwd arg.
subprocess.run( subprocess.run(
f'cd {self._src_root} && make prereqs', f'cd {self._src_root} && make env',
shell=True, shell=True,
check=True, check=True,
capture_output=True, capture_output=True,

View File

@ -669,8 +669,8 @@ class AssetStager:
projroot=self.projroot, projroot=self.projroot,
mode=modeval, mode=modeval,
infilename=f'{self.projroot}/src/assets/server_package/' infilename=f'{self.projroot}/src/assets/server_package/'
'config_template.yaml', 'config_template.toml',
outfilename=os.path.join(self.serverdst, 'config_template.yaml'), outfilename=os.path.join(self.serverdst, 'config_template.toml'),
) )
if self.win_type is not None: if self.win_type is not None:
fname = 'launch_ballisticakit_server.bat' fname = 'launch_ballisticakit_server.bat'
@ -763,11 +763,11 @@ def _stage_server_file(
os.makedirs(os.path.dirname(outfilename), exist_ok=True) os.makedirs(os.path.dirname(outfilename), exist_ok=True)
basename = os.path.basename(infilename) basename = os.path.basename(infilename)
if basename == 'config_template.yaml': if basename == 'config_template.toml':
# Inject all available config values into the config file. # Inject all available config values into the config file.
_write_if_changed( _write_if_changed(
outfilename, outfilename,
batools.build.filter_server_config(str(projroot), infilename), batools.build.filter_server_config_toml(str(projroot), infilename),
) )
elif basename == 'ballisticakit_server.py': elif basename == 'ballisticakit_server.py':

View File

@ -12,16 +12,6 @@ import functools
from enum import Enum from enum import Enum
from typing import TYPE_CHECKING, cast, TypeVar, Generic from typing import TYPE_CHECKING, cast, TypeVar, Generic
_pytz_utc: Any
# We don't *require* pytz, but we want to support it for tzinfos if available.
try:
import pytz
_pytz_utc = pytz.utc
except ModuleNotFoundError:
_pytz_utc = None # pylint: disable=invalid-name
if TYPE_CHECKING: if TYPE_CHECKING:
import asyncio import asyncio
from efro.call import Call as Call # 'as Call' so we re-export. from efro.call import Call as Call # 'as Call' so we re-export.
@ -112,29 +102,35 @@ def enum_by_value(cls: type[EnumT], value: Any) -> EnumT:
def check_utc(value: datetime.datetime) -> None: def check_utc(value: datetime.datetime) -> None:
"""Ensure a datetime value is timezone-aware utc.""" """Ensure a datetime value is timezone-aware utc."""
if value.tzinfo is not datetime.timezone.utc and ( if value.tzinfo is not datetime.UTC:
_pytz_utc is None or value.tzinfo is not _pytz_utc
):
raise ValueError( raise ValueError(
'datetime value does not have timezone set as' 'datetime value does not have timezone set as datetime.UTC'
' datetime.timezone.utc'
) )
def utc_now() -> datetime.datetime: def utc_now() -> datetime.datetime:
"""Get offset-aware current utc time. """Get timezone-aware current utc time.
This should be used for all datetimes getting sent over the network, Just a shortcut for datetime.datetime.now(datetime.UTC).
used with the entity system, etc. Avoid datetime.datetime.utcnow() which is deprecated and gives naive
(datetime.utcnow() gives a utc time value, but it is not timezone-aware times.
which makes it less safe to use)
""" """
return datetime.datetime.now(datetime.timezone.utc) return datetime.datetime.now(datetime.UTC)
def utc_now_naive() -> datetime.datetime:
"""Get naive utc time.
This can be used to replace datetime.utcnow(), which is now deprecated.
Most all code should migrate to use timezone-aware times instead of
this.
"""
return datetime.datetime.now(datetime.UTC).replace(tzinfo=None)
def utc_today() -> datetime.datetime: def utc_today() -> datetime.datetime:
"""Get offset-aware midnight in the utc time zone.""" """Get offset-aware midnight in the utc time zone."""
now = datetime.datetime.now(datetime.timezone.utc) now = datetime.datetime.now(datetime.UTC)
return datetime.datetime( return datetime.datetime(
year=now.year, month=now.month, day=now.day, tzinfo=now.tzinfo year=now.year, month=now.month, day=now.day, tzinfo=now.tzinfo
) )
@ -142,7 +138,7 @@ def utc_today() -> datetime.datetime:
def utc_this_hour() -> datetime.datetime: def utc_this_hour() -> datetime.datetime:
"""Get offset-aware beginning of the current hour in the utc time zone.""" """Get offset-aware beginning of the current hour in the utc time zone."""
now = datetime.datetime.now(datetime.timezone.utc) now = datetime.datetime.now(datetime.UTC)
return datetime.datetime( return datetime.datetime(
year=now.year, year=now.year,
month=now.month, month=now.month,
@ -154,7 +150,7 @@ def utc_this_hour() -> datetime.datetime:
def utc_this_minute() -> datetime.datetime: def utc_this_minute() -> datetime.datetime:
"""Get offset-aware beginning of current minute in the utc time zone.""" """Get offset-aware beginning of current minute in the utc time zone."""
now = datetime.datetime.now(datetime.timezone.utc) now = datetime.datetime.now(datetime.UTC)
return datetime.datetime( return datetime.datetime(
year=now.year, year=now.year,
month=now.month, month=now.month,

View File

@ -34,41 +34,31 @@ def format_cpp_str(
Note that some cpp formatting keys off the filename, so a fake one can Note that some cpp formatting keys off the filename, so a fake one can
be optionally provided. be optionally provided.
""" """
# Note: previously was explicitly passing the config path from
# toolconfigsrc so we didn't require running from the project root
# dir, but this doesn't work on older clang-format versions. So now
# just parsing and passing the values itself which should do the
# same thing. Once most people have newer clang-format we can go
# back to just passing the path.
use_built_config = True
cfconfig = os.path.join(projroot, '.clang-format') cfconfig = os.path.join(projroot, '.clang-format')
if not os.path.isfile(cfconfig): if not os.path.isfile(cfconfig):
raise CleanError( raise CleanError(
f".clang-format file not found in '{projroot}';" f".clang-format file not found in '{projroot}';"
" do 'make prereqs' to generate it." " do 'make env' to generate it."
) )
with tempfile.TemporaryDirectory() as tempdir: with tempfile.TemporaryDirectory() as tempdir:
filename = os.path.join(tempdir, filename) tfilename = os.path.join(tempdir, filename)
with open(filename, 'w', encoding='utf-8') as outfile: with open(tfilename, 'w', encoding='utf-8') as outfile:
outfile.write(text) outfile.write(text)
if use_built_config:
import yaml
import json
# clang-format uses yaml but seems passing our raw yaml # Note: clang-format allows '--style=file:<path>' in version 14
# config contents doesn't work; converting to json seems to # or newer, but older versions are still common, so the easiest
# work though. # way to work everywhere is to just copy our config file into
with open(cfconfig, encoding='utf-8') as infile: # the temp dir.
cfconfigdata = json.dumps(yaml.safe_load(infile.read())) with open(cfconfig, 'rb') as infileb:
style_arg = f'--style={cfconfigdata}' with open(os.path.join(tempdir, '.clang-format'), 'wb') as outfileb:
else: outfileb.write(infileb.read())
style_arg = f'--style=file:{cfconfig}'
subprocess.run(['clang-format', style_arg, '-i', filename], check=True) subprocess.run(
with open(filename, encoding='utf-8') as infile: ['clang-format', '--style=file', '-i', tfilename], check=True
)
with open(tfilename, encoding='utf-8') as infile:
return infile.read() return infile.read()
@ -91,7 +81,7 @@ def format_project_cpp_files(projroot: Path, full: bool) -> None:
if not os.path.isfile(cfconfig): if not os.path.isfile(cfconfig):
raise CleanError( raise CleanError(
f".clang-format file not found in '{os.getcwd()}';" f".clang-format file not found in '{os.getcwd()}';"
" do 'make prereqs' to generate it." " do 'make env' to generate it."
) )
# Exclude generated files or else we could mess up dependencies # Exclude generated files or else we could mess up dependencies
@ -105,8 +95,6 @@ def format_project_cpp_files(projroot: Path, full: bool) -> None:
def format_file(filename: str) -> dict[str, Any]: def format_file(filename: str) -> dict[str, Any]:
start_time = time.monotonic() start_time = time.monotonic()
# Note: seems os.system does not unlock the gil;
# make sure to use subprocess.
result = subprocess.call(['clang-format', '-i', filename]) result = subprocess.call(['clang-format', '-i', filename])
if result != 0: if result != 0:
raise RuntimeError(f'Formatting failed for {filename}') raise RuntimeError(f'Formatting failed for {filename}')

View File

@ -47,7 +47,7 @@ if __name__ == '__main__':
f'# {legalnotice}\n' f'# {legalnotice}\n'
f'# This file is autogenerated; do not edit.\n' f'# This file is autogenerated; do not edit.\n'
f'#\n' f'#\n'
f'"""Simple wrapper so {toolname} uses our internal virtual' f'"""Simple wrapper so {toolname} uses the project virtual'
f' environment."""\n' f' environment."""\n'
f'from {toolmodule} import run_{toolname}_main\n' f'from {toolmodule} import run_{toolname}_main\n'
f'\n' f'\n'

View File

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

View File

@ -74,7 +74,7 @@ def requirements_upgrade() -> None:
subprocess.run([sys.executable, '-m', 'pur', '-r', fname], check=True) subprocess.run([sys.executable, '-m', 'pur', '-r', fname], check=True)
# Sort lines. # Sort lines.
with open(reqpath, encoding='utf-8') as infile: with open(fname, encoding='utf-8') as infile:
reqs2 = infile.read().strip() reqs2 = infile.read().strip()
reqs_new = ( reqs_new = (
'\n'.join(sorted(reqs2.splitlines(), key=lambda l: l.lower())) '\n'.join(sorted(reqs2.splitlines(), key=lambda l: l.lower()))

View File

@ -271,8 +271,7 @@ def build_apple(arch: str, debug: bool = False) -> None:
'\t# Apply target Python patches\n' '\t# Apply target Python patches\n'
f'\tcd $$(PYTHON_SRCDIR-$({tword})) && ' f'\tcd $$(PYTHON_SRCDIR-$({tword})) && '
'patch -p1 < $(PROJECT_DIR)/patch/Python/Python.patch\n' 'patch -p1 < $(PROJECT_DIR)/patch/Python/Python.patch\n'
f'\t/opt/homebrew/opt/python@3.12/bin/python3.12' f'\t../../tools/pcommand python_apple_patch'
' ../../tools/pcommand python_apple_patch'
f' $$(PYTHON_SRCDIR-$({tword}))\n' f' $$(PYTHON_SRCDIR-$({tword}))\n'
), ),
count=1, count=1,
@ -1291,22 +1290,6 @@ def gather(do_android: bool, do_apple: bool) -> None:
], ],
libs=_apple_libs('tvos_simulator'), libs=_apple_libs('tvos_simulator'),
), ),
BuildDef(
name='android_arm',
group=groups['android'],
config_headers={
CompileArch.ANDROID_ARM: bases['android_arm']
+ f'/usr/include/{alibname}/pyconfig.h'
},
sys_config_scripts=[
bases['android_arm']
+ f'/usr/lib/python{PY_VER_ANDROID}/'
# f'_sysconfigdata_{debug_d}_linux_arm-linux-androideabi.py'
f'_sysconfigdata_{debug_d}_linux_.py'
],
libs=_android_libs('android_arm'),
libinst='android_armeabi-v7a',
),
BuildDef( BuildDef(
name='android_arm64', name='android_arm64',
group=groups['android'], group=groups['android'],
@ -1324,20 +1307,20 @@ def gather(do_android: bool, do_apple: bool) -> None:
libinst='android_arm64-v8a', libinst='android_arm64-v8a',
), ),
BuildDef( BuildDef(
name='android_x86', name='android_arm',
group=groups['android'], group=groups['android'],
config_headers={ config_headers={
CompileArch.ANDROID_X86: bases['android_x86'] CompileArch.ANDROID_ARM: bases['android_arm']
+ f'/usr/include/{alibname}/pyconfig.h' + f'/usr/include/{alibname}/pyconfig.h'
}, },
sys_config_scripts=[ sys_config_scripts=[
bases['android_x86'] + f'/usr/lib/python{PY_VER_ANDROID}/' bases['android_arm']
f'_sysconfigdata_{debug_d}' + f'/usr/lib/python{PY_VER_ANDROID}/'
# f'_linux_i686-linux-android.py' # f'_sysconfigdata_{debug_d}_linux_arm-linux-androideabi.py'
f'_linux_.py' f'_sysconfigdata_{debug_d}_linux_.py'
], ],
libs=_android_libs('android_x86'), libs=_android_libs('android_arm'),
libinst='android_x86', libinst='android_armeabi-v7a',
), ),
BuildDef( BuildDef(
name='android_x86_64', name='android_x86_64',
@ -1356,6 +1339,22 @@ def gather(do_android: bool, do_apple: bool) -> None:
libs=_android_libs('android_x86_64'), libs=_android_libs('android_x86_64'),
libinst='android_x86_64', libinst='android_x86_64',
), ),
BuildDef(
name='android_x86',
group=groups['android'],
config_headers={
CompileArch.ANDROID_X86: bases['android_x86']
+ f'/usr/include/{alibname}/pyconfig.h'
},
sys_config_scripts=[
bases['android_x86'] + f'/usr/lib/python{PY_VER_ANDROID}/'
f'_sysconfigdata_{debug_d}'
# f'_linux_i686-linux-android.py'
f'_linux_.py'
],
libs=_android_libs('android_x86'),
libinst='android_x86',
),
] ]
# if do_apple: # if do_apple:
@ -1561,9 +1560,20 @@ def gather(do_android: bool, do_apple: bool) -> None:
scriptdst = os.path.join( scriptdst = os.path.join(
pylib_dst, os.path.basename(script) pylib_dst, os.path.basename(script)
) )
# Note to self: Python 3.12 seemed to change
# something where the sys_config_scripts for
# each of the architectures has the same name
# whereas it did not before. We could patch this
# by hand to split them out again, but for now
# just going to hope it gets fixed in 3.13 (when
# Android Python becomes an officially supported
# target; yay!). Hopefully nobody is using stuff
# from sysconfig anyway. But if they are, I
# rearranged the order so x86 is the actual one
# which will hopefully make errors obvious.
if os.path.exists(scriptdst): if os.path.exists(scriptdst):
print( print(
'WARNING TEMPORARILY ALLOWING' 'WARNING: TEMPORARILY ALLOWING'
' REPEAT SYS CONFIG SCRIPTS' ' REPEAT SYS CONFIG SCRIPTS'
) )
# raise RuntimeError( # raise RuntimeError(

View File

@ -23,15 +23,15 @@ def install_tool_config(projroot: Path, src: Path, dst: Path) -> None:
"""Install a config.""" """Install a config."""
print(f'Creating tool config: {Clr.BLD}{dst}{Clr.RST}') print(f'Creating tool config: {Clr.BLD}{dst}{Clr.RST}')
# Special case: if we've got a src .yaml and a dst .json, convert. # Special case: if we've got a src .toml and a dst .json, convert.
# This can be handy to add annotations/etc. in the src which isn't # This can be handy to add annotations/etc. in the src which isn't
# possible with json. # possible with json.
if src.suffix == '.yaml' and dst.suffix == '.json': if src.suffix == '.toml' and dst.suffix == '.json':
import yaml import tomllib
import json import json
with src.open(encoding='utf-8') as infile: with src.open(encoding='utf-8') as infile:
contents = yaml.safe_load(infile.read()) contents = tomllib.loads(infile.read())
cfg = json.dumps(contents, indent=2, sort_keys=True) cfg = json.dumps(contents, indent=2, sort_keys=True)
# In normal cases we just push the source file straight through. # In normal cases we just push the source file straight through.

View File

@ -46,7 +46,7 @@ if __name__ == '__main__':
env['BA_SPINOFF_DST_ROOT'] = dst_proj_root env['BA_SPINOFF_DST_ROOT'] = dst_proj_root
# Make sure the src project is properly bootstrapped. # Make sure the src project is properly bootstrapped.
subprocess.run(['make', 'prereqs'], check=True, cwd=src_proj_root) subprocess.run(['make', 'env'], check=True, cwd=src_proj_root)
# Finally, run for realz (from src proj dir). # Finally, run for realz (from src proj dir).
result = subprocess.run(cmd, check=False, env=env, cwd=src_proj_root) result = subprocess.run(cmd, check=False, env=env, cwd=src_proj_root)