mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-02-04 22:43:17 +08:00
work on cmake-modular builds
This commit is contained in:
parent
15d9d1c7ce
commit
aeb893294d
104
.efrocachemap
generated
104
.efrocachemap
generated
@ -421,11 +421,11 @@
|
|||||||
"build/assets/ba_data/audio/zoeOw.ogg": "https://files.ballistica.net/cache/ba1/74/be/fe45a8417e95b6a2233c51992a26",
|
"build/assets/ba_data/audio/zoeOw.ogg": "https://files.ballistica.net/cache/ba1/74/be/fe45a8417e95b6a2233c51992a26",
|
||||||
"build/assets/ba_data/audio/zoePickup01.ogg": "https://files.ballistica.net/cache/ba1/48/ab/8cddfcde36a750856f3f81dd20c8",
|
"build/assets/ba_data/audio/zoePickup01.ogg": "https://files.ballistica.net/cache/ba1/48/ab/8cddfcde36a750856f3f81dd20c8",
|
||||||
"build/assets/ba_data/audio/zoeScream01.ogg": "https://files.ballistica.net/cache/ba1/2b/46/8aedfa8741090247f04eb9e6df55",
|
"build/assets/ba_data/audio/zoeScream01.ogg": "https://files.ballistica.net/cache/ba1/2b/46/8aedfa8741090247f04eb9e6df55",
|
||||||
"build/assets/ba_data/data/langdata.json": "https://files.ballistica.net/cache/ba1/a1/f9/645b8c7e1e99dd11446bc77005da",
|
"build/assets/ba_data/data/langdata.json": "https://files.ballistica.net/cache/ba1/b8/5e/c8766634397fb77ae3a407c05d63",
|
||||||
"build/assets/ba_data/data/languages/arabic.json": "https://files.ballistica.net/cache/ba1/83/87/06fc7255ebf8a895ad37d2dfa13d",
|
"build/assets/ba_data/data/languages/arabic.json": "https://files.ballistica.net/cache/ba1/6f/38/958616d8cb85916aa8b2bcd84f63",
|
||||||
"build/assets/ba_data/data/languages/belarussian.json": "https://files.ballistica.net/cache/ba1/57/68/d03a19b9035cfae7cdc5377d889a",
|
"build/assets/ba_data/data/languages/belarussian.json": "https://files.ballistica.net/cache/ba1/57/68/d03a19b9035cfae7cdc5377d889a",
|
||||||
"build/assets/ba_data/data/languages/chinese.json": "https://files.ballistica.net/cache/ba1/b6/00/924583b899165757f412eef0dd01",
|
"build/assets/ba_data/data/languages/chinese.json": "https://files.ballistica.net/cache/ba1/b6/00/924583b899165757f412eef0dd01",
|
||||||
"build/assets/ba_data/data/languages/chinesetraditional.json": "https://files.ballistica.net/cache/ba1/50/4c/4fb39f065b1a2f0320026a2e1b92",
|
"build/assets/ba_data/data/languages/chinesetraditional.json": "https://files.ballistica.net/cache/ba1/3f/e9/60a8f0ca529aa57b4f9cb7385abc",
|
||||||
"build/assets/ba_data/data/languages/croatian.json": "https://files.ballistica.net/cache/ba1/76/65/32c67af5bd0144c2d63cab0516fa",
|
"build/assets/ba_data/data/languages/croatian.json": "https://files.ballistica.net/cache/ba1/76/65/32c67af5bd0144c2d63cab0516fa",
|
||||||
"build/assets/ba_data/data/languages/czech.json": "https://files.ballistica.net/cache/ba1/f3/ce/219840946cb8f9aa6d3e25927ab3",
|
"build/assets/ba_data/data/languages/czech.json": "https://files.ballistica.net/cache/ba1/f3/ce/219840946cb8f9aa6d3e25927ab3",
|
||||||
"build/assets/ba_data/data/languages/danish.json": "https://files.ballistica.net/cache/ba1/3f/d6/9080783d5c9dcc0af737f02b6f1e",
|
"build/assets/ba_data/data/languages/danish.json": "https://files.ballistica.net/cache/ba1/3f/d6/9080783d5c9dcc0af737f02b6f1e",
|
||||||
@ -438,7 +438,7 @@
|
|||||||
"build/assets/ba_data/data/languages/gibberish.json": "https://files.ballistica.net/cache/ba1/23/6f/8547ba09722b7c7f5b8333986984",
|
"build/assets/ba_data/data/languages/gibberish.json": "https://files.ballistica.net/cache/ba1/23/6f/8547ba09722b7c7f5b8333986984",
|
||||||
"build/assets/ba_data/data/languages/greek.json": "https://files.ballistica.net/cache/ba1/a6/5d/78f912e9a89f98de004405167a6a",
|
"build/assets/ba_data/data/languages/greek.json": "https://files.ballistica.net/cache/ba1/a6/5d/78f912e9a89f98de004405167a6a",
|
||||||
"build/assets/ba_data/data/languages/hindi.json": "https://files.ballistica.net/cache/ba1/88/ee/0cda537bab9ac827def5e236fe1a",
|
"build/assets/ba_data/data/languages/hindi.json": "https://files.ballistica.net/cache/ba1/88/ee/0cda537bab9ac827def5e236fe1a",
|
||||||
"build/assets/ba_data/data/languages/hungarian.json": "https://files.ballistica.net/cache/ba1/00/ba/cf1b8bb9f7914f64647d4665b0a8",
|
"build/assets/ba_data/data/languages/hungarian.json": "https://files.ballistica.net/cache/ba1/a9/b5/10de2f3928d8c1f4887e0975743f",
|
||||||
"build/assets/ba_data/data/languages/indonesian.json": "https://files.ballistica.net/cache/ba1/58/3b/ae1ecc04375cee089a82359110b7",
|
"build/assets/ba_data/data/languages/indonesian.json": "https://files.ballistica.net/cache/ba1/58/3b/ae1ecc04375cee089a82359110b7",
|
||||||
"build/assets/ba_data/data/languages/italian.json": "https://files.ballistica.net/cache/ba1/67/44/40ada7b8e76adceb2129d7668df6",
|
"build/assets/ba_data/data/languages/italian.json": "https://files.ballistica.net/cache/ba1/67/44/40ada7b8e76adceb2129d7668df6",
|
||||||
"build/assets/ba_data/data/languages/korean.json": "https://files.ballistica.net/cache/ba1/bd/c1/3f8632adda5517059323d928f192",
|
"build/assets/ba_data/data/languages/korean.json": "https://files.ballistica.net/cache/ba1/bd/c1/3f8632adda5517059323d928f192",
|
||||||
@ -450,13 +450,13 @@
|
|||||||
"build/assets/ba_data/data/languages/russian.json": "https://files.ballistica.net/cache/ba1/aa/99/f9f597787fe4e09c8ab53fe2e081",
|
"build/assets/ba_data/data/languages/russian.json": "https://files.ballistica.net/cache/ba1/aa/99/f9f597787fe4e09c8ab53fe2e081",
|
||||||
"build/assets/ba_data/data/languages/serbian.json": "https://files.ballistica.net/cache/ba1/d7/45/2dd72ac0e51680cb39b5ebaa1c69",
|
"build/assets/ba_data/data/languages/serbian.json": "https://files.ballistica.net/cache/ba1/d7/45/2dd72ac0e51680cb39b5ebaa1c69",
|
||||||
"build/assets/ba_data/data/languages/slovak.json": "https://files.ballistica.net/cache/ba1/27/96/2d53dc3f7dd4e877cd40faafeeef",
|
"build/assets/ba_data/data/languages/slovak.json": "https://files.ballistica.net/cache/ba1/27/96/2d53dc3f7dd4e877cd40faafeeef",
|
||||||
"build/assets/ba_data/data/languages/spanish.json": "https://files.ballistica.net/cache/ba1/bd/5e/80c74f96bb50d270396d437d6750",
|
"build/assets/ba_data/data/languages/spanish.json": "https://files.ballistica.net/cache/ba1/45/dd/ce6d9dd446293f5e0ae541f36943",
|
||||||
"build/assets/ba_data/data/languages/swedish.json": "https://files.ballistica.net/cache/ba1/77/d6/71f10613291ebf9c71da66f18a18",
|
"build/assets/ba_data/data/languages/swedish.json": "https://files.ballistica.net/cache/ba1/77/d6/71f10613291ebf9c71da66f18a18",
|
||||||
"build/assets/ba_data/data/languages/tamil.json": "https://files.ballistica.net/cache/ba1/c7/fc/5ed7bd686839ec1a867763248cf9",
|
"build/assets/ba_data/data/languages/tamil.json": "https://files.ballistica.net/cache/ba1/c7/fc/5ed7bd686839ec1a867763248cf9",
|
||||||
"build/assets/ba_data/data/languages/thai.json": "https://files.ballistica.net/cache/ba1/33/f6/3753c9af9a5b238d229a0bf23fbc",
|
"build/assets/ba_data/data/languages/thai.json": "https://files.ballistica.net/cache/ba1/33/f6/3753c9af9a5b238d229a0bf23fbc",
|
||||||
"build/assets/ba_data/data/languages/turkish.json": "https://files.ballistica.net/cache/ba1/0a/97/f1f948f6587ea7d40b639aba67ce",
|
"build/assets/ba_data/data/languages/turkish.json": "https://files.ballistica.net/cache/ba1/0a/97/f1f948f6587ea7d40b639aba67ce",
|
||||||
"build/assets/ba_data/data/languages/ukrainian.json": "https://files.ballistica.net/cache/ba1/97/4a/399422e3061fdd82f66591283397",
|
"build/assets/ba_data/data/languages/ukrainian.json": "https://files.ballistica.net/cache/ba1/97/4a/399422e3061fdd82f66591283397",
|
||||||
"build/assets/ba_data/data/languages/venetian.json": "https://files.ballistica.net/cache/ba1/e4/74/5c85bc56487bb715712c8b90a1eb",
|
"build/assets/ba_data/data/languages/venetian.json": "https://files.ballistica.net/cache/ba1/b0/e3/d73ccf96c5fa490a54f090ee77a5",
|
||||||
"build/assets/ba_data/data/languages/vietnamese.json": "https://files.ballistica.net/cache/ba1/92/1c/d1e50f60fe3e101f246e172750ba",
|
"build/assets/ba_data/data/languages/vietnamese.json": "https://files.ballistica.net/cache/ba1/92/1c/d1e50f60fe3e101f246e172750ba",
|
||||||
"build/assets/ba_data/data/maps/big_g.json": "https://files.ballistica.net/cache/ba1/1d/d3/01d490643088a435ce75df971054",
|
"build/assets/ba_data/data/maps/big_g.json": "https://files.ballistica.net/cache/ba1/1d/d3/01d490643088a435ce75df971054",
|
||||||
"build/assets/ba_data/data/maps/bridgit.json": "https://files.ballistica.net/cache/ba1/6a/ea/74805f4880cc11237c5734a24422",
|
"build/assets/ba_data/data/maps/bridgit.json": "https://files.ballistica.net/cache/ba1/6a/ea/74805f4880cc11237c5734a24422",
|
||||||
@ -951,7 +951,7 @@
|
|||||||
"build/assets/ba_data/python-site-packages/certifi/cacert.pem": "https://files.ballistica.net/cache/ba1/6a/c2/9a6bccca11cd2ed7e16e27dfccec",
|
"build/assets/ba_data/python-site-packages/certifi/cacert.pem": "https://files.ballistica.net/cache/ba1/6a/c2/9a6bccca11cd2ed7e16e27dfccec",
|
||||||
"build/assets/ba_data/python-site-packages/certifi/core.py": "https://files.ballistica.net/cache/ba1/1b/50/5388f1475fabd1b60031f985271c",
|
"build/assets/ba_data/python-site-packages/certifi/core.py": "https://files.ballistica.net/cache/ba1/1b/50/5388f1475fabd1b60031f985271c",
|
||||||
"build/assets/ba_data/python-site-packages/typing_extensions.py": "https://files.ballistica.net/cache/ba1/08/4d/93bb609d798a3930dfb5e25eba59",
|
"build/assets/ba_data/python-site-packages/typing_extensions.py": "https://files.ballistica.net/cache/ba1/08/4d/93bb609d798a3930dfb5e25eba59",
|
||||||
"build/assets/ba_data/python-site-packages/yaml/__init__.py": "https://files.ballistica.net/cache/ba1/55/7c/37ea8dbd4fa4d6dac97f399b6fdd",
|
"build/assets/ba_data/python-site-packages/yaml/__init__.py": "https://files.ballistica.net/cache/ba1/2b/74/7e5772c203377222afc888ac6b71",
|
||||||
"build/assets/ba_data/python-site-packages/yaml/composer.py": "https://files.ballistica.net/cache/ba1/ce/f8/71e1f5f99ba2a7c44941b70afb06",
|
"build/assets/ba_data/python-site-packages/yaml/composer.py": "https://files.ballistica.net/cache/ba1/ce/f8/71e1f5f99ba2a7c44941b70afb06",
|
||||||
"build/assets/ba_data/python-site-packages/yaml/constructor.py": "https://files.ballistica.net/cache/ba1/8a/15/e361e34b79491c81553bb3534062",
|
"build/assets/ba_data/python-site-packages/yaml/constructor.py": "https://files.ballistica.net/cache/ba1/8a/15/e361e34b79491c81553bb3534062",
|
||||||
"build/assets/ba_data/python-site-packages/yaml/cyaml.py": "https://files.ballistica.net/cache/ba1/9b/11/cba12e6f1cf2efe1725a20d7e1e5",
|
"build/assets/ba_data/python-site-packages/yaml/cyaml.py": "https://files.ballistica.net/cache/ba1/9b/11/cba12e6f1cf2efe1725a20d7e1e5",
|
||||||
@ -4068,50 +4068,50 @@
|
|||||||
"build/assets/windows/Win32/ucrtbased.dll": "https://files.ballistica.net/cache/ba1/2d/ef/5335207d41b21b9823f6805997f1",
|
"build/assets/windows/Win32/ucrtbased.dll": "https://files.ballistica.net/cache/ba1/2d/ef/5335207d41b21b9823f6805997f1",
|
||||||
"build/assets/windows/Win32/vc_redist.x86.exe": "https://files.ballistica.net/cache/ba1/b0/8a/55e2e77623fe657bea24f223a3ae",
|
"build/assets/windows/Win32/vc_redist.x86.exe": "https://files.ballistica.net/cache/ba1/b0/8a/55e2e77623fe657bea24f223a3ae",
|
||||||
"build/assets/windows/Win32/vcruntime140d.dll": "https://files.ballistica.net/cache/ba1/86/5b/2af4d1e26a1a8073c89acb06e599",
|
"build/assets/windows/Win32/vcruntime140d.dll": "https://files.ballistica.net/cache/ba1/86/5b/2af4d1e26a1a8073c89acb06e599",
|
||||||
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/a8/5e/e644cd4120304fba4d4dbd9762e2",
|
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/31/48/05c88daed3cf3e90f5a051ec6a0c",
|
||||||
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/92/73/0a1325df721b51d0c9f2e0f6f075",
|
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/72/f9/d85a330987d81ffc895fc8ec922c",
|
||||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/24/f8/b372c8e02345a5540bd976069de8",
|
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/1a/92/6d465e12a3460498d978f31abf15",
|
||||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/81/5d/8368c53554a9b997f0a1d38c0ced",
|
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/0c/0e/1b219bc8d0b6d7ccf57bdd721860",
|
||||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/cb/90/6f74ab7d83e5ff9db887f391664a",
|
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/4a/7f/1068c0311d88aa8145e487f0e30b",
|
||||||
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/cd/51/6639bbf611e918b21c1676b25764",
|
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/1d/0d/fd0d55be1b0e69de4c4667d34644",
|
||||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/d1/4b/5f2cb963955fd973bd7498c57519",
|
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/3f/d0/cec6952032a5ddc8c1a63b1e1ba3",
|
||||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/9b/9f/1e1d79b604749c2033e7fad06394",
|
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/a7/6e/b40ca2ec7dde8c0e9edb0db376c1",
|
||||||
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/97/f6/2f0e7dba9be2437f43dc4af5e449",
|
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/fe/88/123692ae9ffbc97aaddbd51c0f30",
|
||||||
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/2e/22/297bedb0cbfb169fb9ba607bff1b",
|
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/16/31/b64154143f4e903388b9013b41c7",
|
||||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/c6/3e/6b09e07290a01483186b2ca44f8b",
|
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/c0/f9/aea06ce01cffb7931aca46285316",
|
||||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/9e/c9/89f8f396ba8597453d81542f6ff6",
|
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/d0/a0/a9a8c9fe3addcc0a9f7a014acef1",
|
||||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/0b/d8/4b6df9ec36d59a5560615c763bbf",
|
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/66/e3/d827e9edb1363d55a85636fc5f58",
|
||||||
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/2d/5e/f6e1619a73c21c886425d878b96a",
|
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/b4/05/e5a12646d900aeeaa7e974dabda2",
|
||||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/b6/4b/c7e9a14a16d69b20313f7007662c",
|
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/94/16/24b8715c0f5c2eb6699ff20e594d",
|
||||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/2c/00/fe4d13eb53c0d825da2750b30cec",
|
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/83/6d/d914432abe2d071890a6b3e2d6f1",
|
||||||
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/69/19/13f59849fe2a31eac8a350db2e12",
|
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/10/b7/04b0835c36649b8bcd70abf2f3d7",
|
||||||
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/01/ab/f243ffaa211fd9463cc7ede10f29",
|
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/0a/13/807d5e92e146b5e9bfc679dbd44b",
|
||||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/87/d3/88a28894dc15e511f3ba56f44267",
|
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/3f/1e/2970e115041bc1828b3b2b8ef4db",
|
||||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/b5/1e/bb7075104c420ca1c0663d24768c",
|
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/9f/28/bf466437892861a399375c864a0d",
|
||||||
"build/prefab/lib/linux_arm64_gui/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/84/aa/534f35b6499762739646ea173382",
|
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "https://files.ballistica.net/cache/ba1/4e/69/3d3715ffb88e61962dff80e52fa0",
|
||||||
"build/prefab/lib/linux_arm64_gui/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/25/2f/3bd787d6debb2c4073fd6c2e8098",
|
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "https://files.ballistica.net/cache/ba1/df/78/f138dbf92a93dcd647831fb8fde4",
|
||||||
"build/prefab/lib/linux_arm64_server/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/84/aa/534f35b6499762739646ea173382",
|
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "https://files.ballistica.net/cache/ba1/4e/69/3d3715ffb88e61962dff80e52fa0",
|
||||||
"build/prefab/lib/linux_arm64_server/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/25/2f/3bd787d6debb2c4073fd6c2e8098",
|
"build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "https://files.ballistica.net/cache/ba1/df/78/f138dbf92a93dcd647831fb8fde4",
|
||||||
"build/prefab/lib/linux_x86_64_gui/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/b8/01/153180116f1ab302aa8e6fd9ca9c",
|
"build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "https://files.ballistica.net/cache/ba1/4d/45/84cd8d36933f680c4c5ea6ed56e3",
|
||||||
"build/prefab/lib/linux_x86_64_gui/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/93/1c/1aba110dcf69d8651b428f2927ed",
|
"build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "https://files.ballistica.net/cache/ba1/31/e8/ebc78517b4f6c3dba799d96b6770",
|
||||||
"build/prefab/lib/linux_x86_64_server/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/b8/01/153180116f1ab302aa8e6fd9ca9c",
|
"build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "https://files.ballistica.net/cache/ba1/4d/45/84cd8d36933f680c4c5ea6ed56e3",
|
||||||
"build/prefab/lib/linux_x86_64_server/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/93/1c/1aba110dcf69d8651b428f2927ed",
|
"build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "https://files.ballistica.net/cache/ba1/31/e8/ebc78517b4f6c3dba799d96b6770",
|
||||||
"build/prefab/lib/mac_arm64_gui/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/4b/1a/21983185f7bdd78842b572535dad",
|
"build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "https://files.ballistica.net/cache/ba1/16/31/fa50eca4cccba5819aba7598cdd2",
|
||||||
"build/prefab/lib/mac_arm64_gui/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/3c/1d/d7864d7822c64ee06cee0dde659e",
|
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "https://files.ballistica.net/cache/ba1/80/f5/1e75ca051bcc9cf5622443368820",
|
||||||
"build/prefab/lib/mac_arm64_server/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/4b/1a/21983185f7bdd78842b572535dad",
|
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "https://files.ballistica.net/cache/ba1/16/31/fa50eca4cccba5819aba7598cdd2",
|
||||||
"build/prefab/lib/mac_arm64_server/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/3c/1d/d7864d7822c64ee06cee0dde659e",
|
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "https://files.ballistica.net/cache/ba1/80/f5/1e75ca051bcc9cf5622443368820",
|
||||||
"build/prefab/lib/mac_x86_64_gui/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/65/ab/524fe2f6a339b6480173c2c1624a",
|
"build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "https://files.ballistica.net/cache/ba1/34/26/fe4dacd23b76a39c024e220a6851",
|
||||||
"build/prefab/lib/mac_x86_64_gui/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/47/61/eca0961c54b2eae2cf65fac7848d",
|
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "https://files.ballistica.net/cache/ba1/84/7d/952ba7e47c98635853b6b3e046fa",
|
||||||
"build/prefab/lib/mac_x86_64_server/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/06/5c/90c3a49e16a004e2db71909af919",
|
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "https://files.ballistica.net/cache/ba1/ad/de/141e3f5ea646f9d359a7edc40524",
|
||||||
"build/prefab/lib/mac_x86_64_server/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/47/61/eca0961c54b2eae2cf65fac7848d",
|
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "https://files.ballistica.net/cache/ba1/84/7d/952ba7e47c98635853b6b3e046fa",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/d3/34/d2fa72d15a085424bad4157a6f2e",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/0d/e3/9a30e693bc57d27a093019988e2d",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/56/5f/6cde7712eebd76bcd9081b1d063a",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/b3/df/933a84818c7a7f7059c5d2aef159",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/8e/bb/cde5d48031a147358f49372348fc",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/76/46/7e4792528fdc5ee7b432b8239567",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/82/e5/7d8d72481b84b81a3ec2b85cddf1",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/03/54/742e4cae6ce81180e6977ccf3cd1",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/74/11/5059d262beb03fda192c967760ea",
|
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/35/1b/cd6f88e5a7dda82848362d3ee41e",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/bf/57/94af76a5f7f51c10e9725730469e",
|
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/8f/b4/32805c7732aa03bc4417aed0f61b",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/fc/56/19374bffec117190ae9c132cff68",
|
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/7a/10/3c2abaa7fa0280fe5111209a9fd5",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/c6/c9/b6828fe5295e6d5df08fad9ebf3f",
|
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/60/88/4d71bc815388e9d867d8ffa95c61",
|
||||||
"src/assets/ba_data/python/babase/_mgen/__init__.py": "https://files.ballistica.net/cache/ba1/f8/85/fed7f2ed98ff2ba271f9dbe3391c",
|
"src/assets/ba_data/python/babase/_mgen/__init__.py": "https://files.ballistica.net/cache/ba1/f8/85/fed7f2ed98ff2ba271f9dbe3391c",
|
||||||
"src/assets/ba_data/python/babase/_mgen/enums.py": "https://files.ballistica.net/cache/ba1/f8/cd/3af311ac63147882590123b78318",
|
"src/assets/ba_data/python/babase/_mgen/enums.py": "https://files.ballistica.net/cache/ba1/f8/cd/3af311ac63147882590123b78318",
|
||||||
"src/ballistica/base/mgen/pyembed/binding_base.inc": "https://files.ballistica.net/cache/ba1/3e/7a/203e2a5d2b5bb42cfe3fd2fe16c2",
|
"src/ballistica/base/mgen/pyembed/binding_base.inc": "https://files.ballistica.net/cache/ba1/3e/7a/203e2a5d2b5bb42cfe3fd2fe16c2",
|
||||||
@ -4119,7 +4119,7 @@
|
|||||||
"src/ballistica/classic/mgen/pyembed/binding_classic.inc": "https://files.ballistica.net/cache/ba1/3c/eb/412513963f0818ab39c58bf292e3",
|
"src/ballistica/classic/mgen/pyembed/binding_classic.inc": "https://files.ballistica.net/cache/ba1/3c/eb/412513963f0818ab39c58bf292e3",
|
||||||
"src/ballistica/core/mgen/pyembed/binding_core.inc": "https://files.ballistica.net/cache/ba1/9d/0a/3c9636138e35284923e0c8311c69",
|
"src/ballistica/core/mgen/pyembed/binding_core.inc": "https://files.ballistica.net/cache/ba1/9d/0a/3c9636138e35284923e0c8311c69",
|
||||||
"src/ballistica/core/mgen/pyembed/env.inc": "https://files.ballistica.net/cache/ba1/8b/e4/6e5818f360d10b7b0224a9e91d07",
|
"src/ballistica/core/mgen/pyembed/env.inc": "https://files.ballistica.net/cache/ba1/8b/e4/6e5818f360d10b7b0224a9e91d07",
|
||||||
"src/ballistica/core/mgen/python_modules_monolithic.h": "https://files.ballistica.net/cache/ba1/c4/8c/4f5294e83eb1ff22edffebf2bf8b",
|
"src/ballistica/core/mgen/python_modules_monolithic.h": "https://files.ballistica.net/cache/ba1/fb/96/7ed1c7db0c77d8deb4f00a7103c5",
|
||||||
"src/ballistica/scene_v1/mgen/pyembed/binding_scene_v1.inc": "https://files.ballistica.net/cache/ba1/d8/0f/970053099b3044204bfe29ddefce",
|
"src/ballistica/scene_v1/mgen/pyembed/binding_scene_v1.inc": "https://files.ballistica.net/cache/ba1/d8/0f/970053099b3044204bfe29ddefce",
|
||||||
"src/ballistica/template_fs/mgen/pyembed/binding_template_fs.inc": "https://files.ballistica.net/cache/ba1/44/a4/5492db057bf7f7158c3b0fa11f0f",
|
"src/ballistica/template_fs/mgen/pyembed/binding_template_fs.inc": "https://files.ballistica.net/cache/ba1/44/a4/5492db057bf7f7158c3b0fa11f0f",
|
||||||
"src/ballistica/ui_v1/mgen/pyembed/binding_ui_v1.inc": "https://files.ballistica.net/cache/ba1/6e/98/2bd0dda68e8b821f5b5cc18ce1d5"
|
"src/ballistica/ui_v1/mgen/pyembed/binding_ui_v1.inc": "https://files.ballistica.net/cache/ba1/6e/98/2bd0dda68e8b821f5b5cc18ce1d5"
|
||||||
|
|||||||
30
.idea/dictionaries/ericf.xml
generated
30
.idea/dictionaries/ericf.xml
generated
@ -233,6 +233,8 @@
|
|||||||
<w>ballistica's</w>
|
<w>ballistica's</w>
|
||||||
<w>ballisticakit</w>
|
<w>ballisticakit</w>
|
||||||
<w>ballisticakitcb</w>
|
<w>ballisticakitcb</w>
|
||||||
|
<w>ballisticakitso</w>
|
||||||
|
<w>ballisticaplus</w>
|
||||||
<w>bamaster</w>
|
<w>bamaster</w>
|
||||||
<w>bamasteraddr</w>
|
<w>bamasteraddr</w>
|
||||||
<w>bamasterlegacy</w>
|
<w>bamasterlegacy</w>
|
||||||
@ -318,6 +320,7 @@
|
|||||||
<w>bmas</w>
|
<w>bmas</w>
|
||||||
<w>bmasl</w>
|
<w>bmasl</w>
|
||||||
<w>bmcjphh</w>
|
<w>bmcjphh</w>
|
||||||
|
<w>bmodfeaturesets</w>
|
||||||
<w>bname</w>
|
<w>bname</w>
|
||||||
<w>bndl</w>
|
<w>bndl</w>
|
||||||
<w>boffs</w>
|
<w>boffs</w>
|
||||||
@ -522,6 +525,7 @@
|
|||||||
<w>clrred</w>
|
<w>clrred</w>
|
||||||
<w>cmakelist</w>
|
<w>cmakelist</w>
|
||||||
<w>cmakelists</w>
|
<w>cmakelists</w>
|
||||||
|
<w>cmakemodular</w>
|
||||||
<w>cmakeserver</w>
|
<w>cmakeserver</w>
|
||||||
<w>cmath</w>
|
<w>cmath</w>
|
||||||
<w>cmathmodule</w>
|
<w>cmathmodule</w>
|
||||||
@ -729,6 +733,7 @@
|
|||||||
<w>dingsound</w>
|
<w>dingsound</w>
|
||||||
<w>dingsoundhigh</w>
|
<w>dingsoundhigh</w>
|
||||||
<w>dinl</w>
|
<w>dinl</w>
|
||||||
|
<w>dir's</w>
|
||||||
<w>dirfilter</w>
|
<w>dirfilter</w>
|
||||||
<w>dirmanifest</w>
|
<w>dirmanifest</w>
|
||||||
<w>dirname</w>
|
<w>dirname</w>
|
||||||
@ -832,6 +837,7 @@
|
|||||||
<w>dusing</w>
|
<w>dusing</w>
|
||||||
<w>dval</w>
|
<w>dval</w>
|
||||||
<w>dxml</w>
|
<w>dxml</w>
|
||||||
|
<w>dylibdir</w>
|
||||||
<w>dynload</w>
|
<w>dynload</w>
|
||||||
<w>eachother</w>
|
<w>eachother</w>
|
||||||
<w>eaddrnotavail</w>
|
<w>eaddrnotavail</w>
|
||||||
@ -894,6 +900,7 @@
|
|||||||
<w>enumvalue</w>
|
<w>enumvalue</w>
|
||||||
<w>enval</w>
|
<w>enval</w>
|
||||||
<w>envcfg</w>
|
<w>envcfg</w>
|
||||||
|
<w>envglobals</w>
|
||||||
<w>envhash</w>
|
<w>envhash</w>
|
||||||
<w>envname</w>
|
<w>envname</w>
|
||||||
<w>envs</w>
|
<w>envs</w>
|
||||||
@ -930,6 +937,7 @@
|
|||||||
<w>excludetypes</w>
|
<w>excludetypes</w>
|
||||||
<w>excstr</w>
|
<w>excstr</w>
|
||||||
<w>exec'ed</w>
|
<w>exec'ed</w>
|
||||||
|
<w>exec'ing</w>
|
||||||
<w>execcode</w>
|
<w>execcode</w>
|
||||||
<w>execed</w>
|
<w>execed</w>
|
||||||
<w>execing</w>
|
<w>execing</w>
|
||||||
@ -982,6 +990,7 @@
|
|||||||
<w>fdata</w>
|
<w>fdata</w>
|
||||||
<w>fdataraw</w>
|
<w>fdataraw</w>
|
||||||
<w>fdcount</w>
|
<w>fdcount</w>
|
||||||
|
<w>fdcwd</w>
|
||||||
<w>fdesc</w>
|
<w>fdesc</w>
|
||||||
<w>fdict</w>
|
<w>fdict</w>
|
||||||
<w>fdirs</w>
|
<w>fdirs</w>
|
||||||
@ -1103,6 +1112,8 @@
|
|||||||
<w>fsconfigpath</w>
|
<w>fsconfigpath</w>
|
||||||
<w>fsdf</w>
|
<w>fsdf</w>
|
||||||
<w>fset</w>
|
<w>fset</w>
|
||||||
|
<w>fsetmfilenames</w>
|
||||||
|
<w>fsetmfilenamevals</w>
|
||||||
<w>fsetname</w>
|
<w>fsetname</w>
|
||||||
<w>fsets</w>
|
<w>fsets</w>
|
||||||
<w>fsettings</w>
|
<w>fsettings</w>
|
||||||
@ -1130,6 +1141,7 @@
|
|||||||
<w>fullpath</w>
|
<w>fullpath</w>
|
||||||
<w>fullprice</w>
|
<w>fullprice</w>
|
||||||
<w>fullscreen</w>
|
<w>fullscreen</w>
|
||||||
|
<w>fullstr</w>
|
||||||
<w>fulltest</w>
|
<w>fulltest</w>
|
||||||
<w>funcname</w>
|
<w>funcname</w>
|
||||||
<w>funcnames</w>
|
<w>funcnames</w>
|
||||||
@ -1403,6 +1415,7 @@
|
|||||||
<w>initializers</w>
|
<w>initializers</w>
|
||||||
<w>initialplayerinfos</w>
|
<w>initialplayerinfos</w>
|
||||||
<w>initing</w>
|
<w>initing</w>
|
||||||
|
<w>initname</w>
|
||||||
<w>inits</w>
|
<w>inits</w>
|
||||||
<w>inittab</w>
|
<w>inittab</w>
|
||||||
<w>inmobi</w>
|
<w>inmobi</w>
|
||||||
@ -1419,6 +1432,7 @@
|
|||||||
<w>insta</w>
|
<w>insta</w>
|
||||||
<w>installdir</w>
|
<w>installdir</w>
|
||||||
<w>instancer</w>
|
<w>instancer</w>
|
||||||
|
<w>instpath</w>
|
||||||
<w>interfacetype</w>
|
<w>interfacetype</w>
|
||||||
<w>internalmodule</w>
|
<w>internalmodule</w>
|
||||||
<w>internalsrc</w>
|
<w>internalsrc</w>
|
||||||
@ -1551,6 +1565,7 @@
|
|||||||
<w>lfval</w>
|
<w>lfval</w>
|
||||||
<w>libballistica</w>
|
<w>libballistica</w>
|
||||||
<w>libballisticakit</w>
|
<w>libballisticakit</w>
|
||||||
|
<w>libballisticaplus</w>
|
||||||
<w>libbz</w>
|
<w>libbz</w>
|
||||||
<w>libbzip</w>
|
<w>libbzip</w>
|
||||||
<w>libcrypto</w>
|
<w>libcrypto</w>
|
||||||
@ -1721,6 +1736,7 @@
|
|||||||
<w>maxw</w>
|
<w>maxw</w>
|
||||||
<w>maxwait</w>
|
<w>maxwait</w>
|
||||||
<w>maxwidth</w>
|
<w>maxwidth</w>
|
||||||
|
<w>mbstowcs</w>
|
||||||
<w>mbytecount</w>
|
<w>mbytecount</w>
|
||||||
<w>mdiv</w>
|
<w>mdiv</w>
|
||||||
<w>mdocs</w>
|
<w>mdocs</w>
|
||||||
@ -1741,6 +1757,7 @@
|
|||||||
<w>metaprogramming</w>
|
<w>metaprogramming</w>
|
||||||
<w>metascan</w>
|
<w>metascan</w>
|
||||||
<w>meteorshower</w>
|
<w>meteorshower</w>
|
||||||
|
<w>mfilename</w>
|
||||||
<w>mfpath</w>
|
<w>mfpath</w>
|
||||||
<w>mhash</w>
|
<w>mhash</w>
|
||||||
<w>mhbegin</w>
|
<w>mhbegin</w>
|
||||||
@ -1984,6 +2001,7 @@
|
|||||||
<w>olde</w>
|
<w>olde</w>
|
||||||
<w>oldlady</w>
|
<w>oldlady</w>
|
||||||
<w>oldpath</w>
|
<w>oldpath</w>
|
||||||
|
<w>oldpaths</w>
|
||||||
<w>oldtoken</w>
|
<w>oldtoken</w>
|
||||||
<w>olduuid</w>
|
<w>olduuid</w>
|
||||||
<w>olduuids</w>
|
<w>olduuids</w>
|
||||||
@ -2003,7 +2021,9 @@
|
|||||||
<w>opposingbody</w>
|
<w>opposingbody</w>
|
||||||
<w>opposingnode</w>
|
<w>opposingnode</w>
|
||||||
<w>opstr</w>
|
<w>opstr</w>
|
||||||
|
<w>optnm</w>
|
||||||
<w>optparse</w>
|
<w>optparse</w>
|
||||||
|
<w>optstuff</w>
|
||||||
<w>orchestrahitsound</w>
|
<w>orchestrahitsound</w>
|
||||||
<w>origwrapper</w>
|
<w>origwrapper</w>
|
||||||
<w>ortho</w>
|
<w>ortho</w>
|
||||||
@ -2019,6 +2039,7 @@
|
|||||||
<w>ourhash</w>
|
<w>ourhash</w>
|
||||||
<w>ourname</w>
|
<w>ourname</w>
|
||||||
<w>ourpackage</w>
|
<w>ourpackage</w>
|
||||||
|
<w>ourpaths</w>
|
||||||
<w>ourself</w>
|
<w>ourself</w>
|
||||||
<w>outdata</w>
|
<w>outdata</w>
|
||||||
<w>outdelay</w>
|
<w>outdelay</w>
|
||||||
@ -2065,6 +2086,7 @@
|
|||||||
<w>pathbar</w>
|
<w>pathbar</w>
|
||||||
<w>pathcapture</w>
|
<w>pathcapture</w>
|
||||||
<w>pathdst</w>
|
<w>pathdst</w>
|
||||||
|
<w>pathlen</w>
|
||||||
<w>pathlib</w>
|
<w>pathlib</w>
|
||||||
<w>pathlist</w>
|
<w>pathlist</w>
|
||||||
<w>pathnames</w>
|
<w>pathnames</w>
|
||||||
@ -2357,8 +2379,10 @@
|
|||||||
<w>pythondontwritebytecode</w>
|
<w>pythondontwritebytecode</w>
|
||||||
<w>pythonenumsmodule</w>
|
<w>pythonenumsmodule</w>
|
||||||
<w>pythonhashseed</w>
|
<w>pythonhashseed</w>
|
||||||
|
<w>pythonoptimize</w>
|
||||||
<w>pythonpath</w>
|
<w>pythonpath</w>
|
||||||
<w>pythonpaths</w>
|
<w>pythonpaths</w>
|
||||||
|
<w>pythonutf</w>
|
||||||
<w>pythonw</w>
|
<w>pythonw</w>
|
||||||
<w>pytree</w>
|
<w>pytree</w>
|
||||||
<w>pytz</w>
|
<w>pytz</w>
|
||||||
@ -2390,6 +2414,8 @@
|
|||||||
<w>readexactly</w>
|
<w>readexactly</w>
|
||||||
<w>readline</w>
|
<w>readline</w>
|
||||||
<w>readlines</w>
|
<w>readlines</w>
|
||||||
|
<w>readlink</w>
|
||||||
|
<w>readlinkat</w>
|
||||||
<w>realpath</w>
|
<w>realpath</w>
|
||||||
<w>realsies</w>
|
<w>realsies</w>
|
||||||
<w>recache</w>
|
<w>recache</w>
|
||||||
@ -2708,10 +2734,12 @@
|
|||||||
<w>sred</w>
|
<w>sred</w>
|
||||||
<w>sriyakaal</w>
|
<w>sriyakaal</w>
|
||||||
<w>sshd</w>
|
<w>sshd</w>
|
||||||
|
<w>ssize</w>
|
||||||
<w>sslcontext</w>
|
<w>sslcontext</w>
|
||||||
<w>sslproto</w>
|
<w>sslproto</w>
|
||||||
<w>ssval</w>
|
<w>ssval</w>
|
||||||
<w>stackstr</w>
|
<w>stackstr</w>
|
||||||
|
<w>stager</w>
|
||||||
<w>standin</w>
|
<w>standin</w>
|
||||||
<w>starscale</w>
|
<w>starscale</w>
|
||||||
<w>startercache</w>
|
<w>startercache</w>
|
||||||
@ -2820,6 +2848,7 @@
|
|||||||
<w>syncitem</w>
|
<w>syncitem</w>
|
||||||
<w>syncitems</w>
|
<w>syncitems</w>
|
||||||
<w>synclist</w>
|
<w>synclist</w>
|
||||||
|
<w>syscall</w>
|
||||||
<w>sysconfigdata</w>
|
<w>sysconfigdata</w>
|
||||||
<w>sysctl</w>
|
<w>sysctl</w>
|
||||||
<w>syslogmodule</w>
|
<w>syslogmodule</w>
|
||||||
@ -3186,6 +3215,7 @@
|
|||||||
<w>winapi</w>
|
<w>winapi</w>
|
||||||
<w>winbeast</w>
|
<w>winbeast</w>
|
||||||
<w>wincfg</w>
|
<w>wincfg</w>
|
||||||
|
<w>wincfglc</w>
|
||||||
<w>wincount</w>
|
<w>wincount</w>
|
||||||
<w>winempty</w>
|
<w>winempty</w>
|
||||||
<w>winnergroup</w>
|
<w>winnergroup</w>
|
||||||
|
|||||||
36
CHANGELOG.md
36
CHANGELOG.md
@ -1,4 +1,38 @@
|
|||||||
### 1.7.23 (build 21171, api 8, 2023-07-16)
|
### 1.7.24 (build 21183, api 8, 2023-07-21)
|
||||||
|
|
||||||
|
- Due to the cleanup done in 1.7.20, it is now possible to build and run
|
||||||
|
Ballistica as a 'pure' Python app consisting of binary Python modules loaded
|
||||||
|
by a standard Python interpreter. This new build style is referred to as
|
||||||
|
'modular'. The traditional form of the app, where we bootstrap Python
|
||||||
|
ourselves inside a standalone binary, is called 'monolithic'. To build and run
|
||||||
|
Ballistica in modular form, you can do `make cmake-modular`. This should make
|
||||||
|
it easier to use certain things like Python debuggers with Ballistica. While I
|
||||||
|
expect most builds of the game to remain monolithic, this may become the
|
||||||
|
default for certain situations such as server builds or possibly Linux builds
|
||||||
|
if it seems beneficial. We'll see. Modular mode should work on Linux and Mac
|
||||||
|
currently; other platforms remain monolithic-only for now.
|
||||||
|
- Changed path wrangling a bit in baenv.py. All ballistica Python paths
|
||||||
|
(including python-site-packages) are now placed before any other existing
|
||||||
|
Python paths. This should provide a more consistent environment and means
|
||||||
|
Ballistica will always use its own version of things like yaml or certifi or
|
||||||
|
typing_extensions instead of one the user has installed via pip. Holler if you
|
||||||
|
run into any problems because of this and we can make an option to use the old
|
||||||
|
behavior where Ballistica's app and site paths get placed at the end.
|
||||||
|
- It is now possible to manually run the app loop even on monolithic builds;
|
||||||
|
just do `PYTHONPATH=ba_data/python ./ballisticacore -c "import baenv;
|
||||||
|
baenv.configure(); import babase; babase.app.run()"`. This is basically the
|
||||||
|
same thing modular builds are doing except that they use a regular Python
|
||||||
|
interpreter instead of the ballisticakit binary.
|
||||||
|
- Cleaned up the `tools/pcommand stage_assets` command. It now always expects a
|
||||||
|
separate `-debug` or `-release` arg. So old commands such as `tools/pcommand
|
||||||
|
stage_assets -win-Win32-Debug .` now look like `tools/pcommand stage_assets
|
||||||
|
-win-Win32 -debug .`. Please holler if you run into any broken asset-staging
|
||||||
|
calls in the Makefile/etc.
|
||||||
|
- `FeatureSet.has_native_python_module` has been renamed to
|
||||||
|
`FeatureSet.has_python_binary_module` for better consistency with related
|
||||||
|
functionality.
|
||||||
|
|
||||||
|
### 1.7.23 (build 21178, api 8, 2023-07-19)
|
||||||
|
|
||||||
- Network security improvements. (Thanks Dliwk!)
|
- Network security improvements. (Thanks Dliwk!)
|
||||||
- You can now double click a chat message to copy it. (Thanks Vishal332008!)
|
- You can now double click a chat message to copy it. (Thanks Vishal332008!)
|
||||||
|
|||||||
75
Makefile
75
Makefile
@ -243,16 +243,16 @@ prefab-mac-arm64-gui-debug: prefab-mac-arm64-gui-debug-build
|
|||||||
|
|
||||||
prefab-mac-x86-64-gui-debug-build: prereqs assets-cmake \
|
prefab-mac-x86-64-gui-debug-build: prereqs assets-cmake \
|
||||||
build/prefab/full/mac_x86_64_gui/debug/ballisticakit
|
build/prefab/full/mac_x86_64_gui/debug/ballisticakit
|
||||||
@$(STAGE_ASSETS) -cmake build/prefab/full/mac_x86_64_gui/debug
|
@$(STAGE_ASSETS) -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: prereqs assets-cmake \
|
||||||
build/prefab/full/mac_arm64_gui/debug/ballisticakit
|
build/prefab/full/mac_arm64_gui/debug/ballisticakit
|
||||||
@$(STAGE_ASSETS) -cmake build/prefab/full/mac_arm64_gui/debug
|
@$(STAGE_ASSETS) -cmake -debug build/prefab/full/mac_arm64_gui/debug
|
||||||
|
|
||||||
build/prefab/full/mac_%_gui/debug/ballisticakit: .efrocachemap
|
build/prefab/full/mac_%_gui/debug/ballisticakit: .efrocachemap
|
||||||
@tools/pcommand efrocache_get $@
|
@tools/pcommand efrocache_get $@
|
||||||
|
|
||||||
build/prefab/lib/mac_%_gui/debug/libballistica_plus.a: .efrocachemap
|
build/prefab/lib/mac_%_gui/debug/libballisticaplus.a: .efrocachemap
|
||||||
@tools/pcommand efrocache_get $@
|
@tools/pcommand efrocache_get $@
|
||||||
|
|
||||||
# Mac gui release:
|
# Mac gui release:
|
||||||
@ -273,16 +273,16 @@ prefab-mac-arm64-gui-release: prefab-mac-arm64-gui_release-build
|
|||||||
|
|
||||||
prefab-mac-x86-64-gui-release-build: prereqs assets-cmake \
|
prefab-mac-x86-64-gui-release-build: prereqs assets-cmake \
|
||||||
build/prefab/full/mac_x86_64_gui/release/ballisticakit
|
build/prefab/full/mac_x86_64_gui/release/ballisticakit
|
||||||
@$(STAGE_ASSETS) -cmake build/prefab/full/mac_x86_64_gui/release
|
@$(STAGE_ASSETS) -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: prereqs assets-cmake \
|
||||||
build/prefab/full/mac_arm64_gui/release/ballisticakit
|
build/prefab/full/mac_arm64_gui/release/ballisticakit
|
||||||
@$(STAGE_ASSETS) -cmake build/prefab/full/mac_arm64_gui/release
|
@$(STAGE_ASSETS) -cmake -release build/prefab/full/mac_arm64_gui/release
|
||||||
|
|
||||||
build/prefab/full/mac_%_gui/release/ballisticakit: .efrocachemap
|
build/prefab/full/mac_%_gui/release/ballisticakit: .efrocachemap
|
||||||
@tools/pcommand efrocache_get $@
|
@tools/pcommand efrocache_get $@
|
||||||
|
|
||||||
build/prefab/lib/mac_%_gui/release/libballistica_plus.a: .efrocachemap
|
build/prefab/lib/mac_%_gui/release/libballisticaplus.a: .efrocachemap
|
||||||
@tools/pcommand efrocache_get $@
|
@tools/pcommand efrocache_get $@
|
||||||
|
|
||||||
# Mac server debug:
|
# Mac server debug:
|
||||||
@ -312,7 +312,7 @@ prefab-mac-arm64-server-debug-build: prereqs assets-server \
|
|||||||
build/prefab/full/mac_%_server/debug/dist/ballisticakit_headless: .efrocachemap
|
build/prefab/full/mac_%_server/debug/dist/ballisticakit_headless: .efrocachemap
|
||||||
@tools/pcommand efrocache_get $@
|
@tools/pcommand efrocache_get $@
|
||||||
|
|
||||||
build/prefab/lib/mac_%_server/debug/libballistica_plus.a: .efrocachemap
|
build/prefab/lib/mac_%_server/debug/libballisticaplus.a: .efrocachemap
|
||||||
@tools/pcommand efrocache_get $@
|
@tools/pcommand efrocache_get $@
|
||||||
|
|
||||||
# Mac server release:
|
# Mac server release:
|
||||||
@ -344,7 +344,7 @@ prefab-mac-arm64-server-release-build: prereqs assets-server \
|
|||||||
build/prefab/full/mac_%_server/release/dist/ballisticakit_headless: .efrocachemap
|
build/prefab/full/mac_%_server/release/dist/ballisticakit_headless: .efrocachemap
|
||||||
@tools/pcommand efrocache_get $@
|
@tools/pcommand efrocache_get $@
|
||||||
|
|
||||||
build/prefab/lib/mac_%_server/release/libballistica_plus.a: .efrocachemap
|
build/prefab/lib/mac_%_server/release/libballisticaplus.a: .efrocachemap
|
||||||
@tools/pcommand efrocache_get $@
|
@tools/pcommand efrocache_get $@
|
||||||
|
|
||||||
# Linux gui debug:
|
# Linux gui debug:
|
||||||
@ -365,16 +365,16 @@ prefab-linux-arm64-gui-debug: prefab-linux-arm64-gui-debug-build
|
|||||||
|
|
||||||
prefab-linux-x86-64-gui-debug-build: prereqs assets-cmake \
|
prefab-linux-x86-64-gui-debug-build: prereqs assets-cmake \
|
||||||
build/prefab/full/linux_x86_64_gui/debug/ballisticakit
|
build/prefab/full/linux_x86_64_gui/debug/ballisticakit
|
||||||
@$(STAGE_ASSETS) -cmake build/prefab/full/linux_x86_64_gui/debug
|
@$(STAGE_ASSETS) -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: prereqs assets-cmake \
|
||||||
build/prefab/full/linux_arm64_gui/debug/ballisticakit
|
build/prefab/full/linux_arm64_gui/debug/ballisticakit
|
||||||
@$(STAGE_ASSETS) -cmake build/prefab/full/linux_arm64_gui/debug
|
@$(STAGE_ASSETS) -cmake -debug build/prefab/full/linux_arm64_gui/debug
|
||||||
|
|
||||||
build/prefab/full/linux_%_gui/debug/ballisticakit: .efrocachemap
|
build/prefab/full/linux_%_gui/debug/ballisticakit: .efrocachemap
|
||||||
@tools/pcommand efrocache_get $@
|
@tools/pcommand efrocache_get $@
|
||||||
|
|
||||||
build/prefab/lib/linux_%_gui/debug/libballistica_plus.a: .efrocachemap
|
build/prefab/lib/linux_%_gui/debug/libballisticaplus.a: .efrocachemap
|
||||||
@tools/pcommand efrocache_get $@
|
@tools/pcommand efrocache_get $@
|
||||||
|
|
||||||
# Linux gui release:
|
# Linux gui release:
|
||||||
@ -395,16 +395,16 @@ prefab-linux-arm64-gui-release: prefab-linux-arm64-gui-release-build
|
|||||||
|
|
||||||
prefab-linux-x86-64-gui-release-build: prereqs assets-cmake \
|
prefab-linux-x86-64-gui-release-build: prereqs assets-cmake \
|
||||||
build/prefab/full/linux_x86_64_gui/release/ballisticakit
|
build/prefab/full/linux_x86_64_gui/release/ballisticakit
|
||||||
@$(STAGE_ASSETS) -cmake build/prefab/full/linux_x86_64_gui/release
|
@$(STAGE_ASSETS) -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: prereqs assets-cmake \
|
||||||
build/prefab/full/linux_arm64_gui/release/ballisticakit
|
build/prefab/full/linux_arm64_gui/release/ballisticakit
|
||||||
@$(STAGE_ASSETS) -cmake build/prefab/full/linux_arm64_gui/release
|
@$(STAGE_ASSETS) -cmake -release build/prefab/full/linux_arm64_gui/release
|
||||||
|
|
||||||
build/prefab/full/linux_%_gui/release/ballisticakit: .efrocachemap
|
build/prefab/full/linux_%_gui/release/ballisticakit: .efrocachemap
|
||||||
@tools/pcommand efrocache_get $@
|
@tools/pcommand efrocache_get $@
|
||||||
|
|
||||||
build/prefab/lib/linux_%_gui/release/libballistica_plus.a: .efrocachemap
|
build/prefab/lib/linux_%_gui/release/libballisticaplus.a: .efrocachemap
|
||||||
@tools/pcommand efrocache_get $@
|
@tools/pcommand efrocache_get $@
|
||||||
|
|
||||||
# Linux server debug:
|
# Linux server debug:
|
||||||
@ -436,7 +436,7 @@ prefab-linux-arm64-server-debug-build: prereqs assets-server \
|
|||||||
build/prefab/full/linux_%_server/debug/dist/ballisticakit_headless: .efrocachemap
|
build/prefab/full/linux_%_server/debug/dist/ballisticakit_headless: .efrocachemap
|
||||||
@tools/pcommand efrocache_get $@
|
@tools/pcommand efrocache_get $@
|
||||||
|
|
||||||
build/prefab/lib/linux_%_server/debug/libballistica_plus.a: .efrocachemap
|
build/prefab/lib/linux_%_server/debug/libballisticaplus.a: .efrocachemap
|
||||||
@tools/pcommand efrocache_get $@
|
@tools/pcommand efrocache_get $@
|
||||||
|
|
||||||
# Linux server release:
|
# Linux server release:
|
||||||
@ -468,7 +468,7 @@ prefab-linux-arm64-server-release-build: prereqs assets-server \
|
|||||||
build/prefab/full/linux_%_server/release/dist/ballisticakit_headless: .efrocachemap
|
build/prefab/full/linux_%_server/release/dist/ballisticakit_headless: .efrocachemap
|
||||||
@tools/pcommand efrocache_get $@
|
@tools/pcommand efrocache_get $@
|
||||||
|
|
||||||
build/prefab/lib/linux_%_server/release/libballistica_plus.a: .efrocachemap
|
build/prefab/lib/linux_%_server/release/libballisticaplus.a: .efrocachemap
|
||||||
@tools/pcommand efrocache_get $@
|
@tools/pcommand efrocache_get $@
|
||||||
|
|
||||||
# Windows gui debug:
|
# Windows gui debug:
|
||||||
@ -482,7 +482,7 @@ prefab-windows-x86-gui-debug: prefab-windows-x86-gui-debug-build
|
|||||||
|
|
||||||
prefab-windows-x86-gui-debug-build: prereqs assets-windows-$(WINPLAT_X86) \
|
prefab-windows-x86-gui-debug-build: prereqs assets-windows-$(WINPLAT_X86) \
|
||||||
build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe
|
build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe
|
||||||
@$(STAGE_ASSETS) -win-$(WINPLAT_X86)-Debug \
|
@$(STAGE_ASSETS) -win-$(WINPLAT_X86) -debug \
|
||||||
build/prefab/full/windows_x86_gui/debug
|
build/prefab/full/windows_x86_gui/debug
|
||||||
|
|
||||||
build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe: .efrocachemap
|
build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe: .efrocachemap
|
||||||
@ -506,7 +506,7 @@ prefab-windows-x86-gui-release: prefab-windows-x86-gui-release-build
|
|||||||
prefab-windows-x86-gui-release-build: prereqs \
|
prefab-windows-x86-gui-release-build: prereqs \
|
||||||
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_ASSETS) -win-$(WINPLAT_X86)-Release \
|
@$(STAGE_ASSETS) -win-$(WINPLAT_X86) -release \
|
||||||
build/prefab/full/windows_x86_gui/release
|
build/prefab/full/windows_x86_gui/release
|
||||||
|
|
||||||
build/prefab/full/windows_x86_gui/release/BallisticaKit.exe: .efrocachemap
|
build/prefab/full/windows_x86_gui/release/BallisticaKit.exe: .efrocachemap
|
||||||
@ -531,7 +531,7 @@ prefab-windows-x86-server-debug: prefab-windows-x86-server-debug-build
|
|||||||
prefab-windows-x86-server-debug-build: prereqs \
|
prefab-windows-x86-server-debug-build: prereqs \
|
||||||
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_ASSETS) -winserver-$(WINPLAT_X86)-Debug \
|
@$(STAGE_ASSETS) -winserver-$(WINPLAT_X86) -debug \
|
||||||
build/prefab/full/windows_x86_server/debug
|
build/prefab/full/windows_x86_server/debug
|
||||||
|
|
||||||
build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe: .efrocachemap
|
build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe: .efrocachemap
|
||||||
@ -556,7 +556,7 @@ prefab-windows-x86-server-release: prefab-windows-x86-server-release-build
|
|||||||
prefab-windows-x86-server-release-build: prereqs \
|
prefab-windows-x86-server-release-build: prereqs \
|
||||||
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_ASSETS) -winserver-$(WINPLAT_X86)-Release \
|
@$(STAGE_ASSETS) -winserver-$(WINPLAT_X86) -release \
|
||||||
build/prefab/full/windows_x86_server/release
|
build/prefab/full/windows_x86_server/release
|
||||||
|
|
||||||
build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe: .efrocachemap
|
build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe: .efrocachemap
|
||||||
@ -931,7 +931,7 @@ WINDOWS_CONFIGURATION ?= Debug
|
|||||||
|
|
||||||
# Stage assets and other files so a built binary will run.
|
# Stage assets and other files so a built binary will run.
|
||||||
windows-staging: assets-windows resources meta
|
windows-staging: assets-windows resources meta
|
||||||
$(STAGE_ASSETS) -win-$(WINPLT)-$(WINCFG) \
|
$(STAGE_ASSETS) -win-$(WINPLT) -$(WINCFGLC) \
|
||||||
build/windows/$(WINCFG)_$(WINPLT)
|
build/windows/$(WINCFG)_$(WINPLT)
|
||||||
|
|
||||||
# Build and run a debug windows build (from WSL).
|
# Build and run a debug windows build (from WSL).
|
||||||
@ -1026,7 +1026,7 @@ cmake-lldb: cmake-build
|
|||||||
|
|
||||||
# Build but don't run it.
|
# Build but don't run it.
|
||||||
cmake-build: assets-cmake resources cmake-binary
|
cmake-build: assets-cmake resources cmake-binary
|
||||||
@$(STAGE_ASSETS) -cmake build/cmake/$(CM_BT_LC)
|
@$(STAGE_ASSETS) -cmake -$(CM_BT_LC) build/cmake/$(CM_BT_LC)
|
||||||
@tools/pcommand echo BLD Build complete: BLU build/cmake/$(CM_BT_LC)
|
@tools/pcommand echo BLD Build complete: BLU build/cmake/$(CM_BT_LC)
|
||||||
|
|
||||||
cmake-binary: meta
|
cmake-binary: meta
|
||||||
@ -1046,25 +1046,43 @@ cmake-server: cmake-server-build
|
|||||||
cmake-server-build: assets-server meta cmake-server-binary
|
cmake-server-build: assets-server meta cmake-server-binary
|
||||||
@$(STAGE_ASSETS) -cmakeserver -$(CM_BT_LC) build/cmake/server-$(CM_BT_LC)
|
@$(STAGE_ASSETS) -cmakeserver -$(CM_BT_LC) build/cmake/server-$(CM_BT_LC)
|
||||||
@tools/pcommand echo BLD \
|
@tools/pcommand echo BLD \
|
||||||
Server build complete: BLU build/cmake/server-$(CM_BT_LC)
|
Server build complete: BLU build/cmake/server-$(CM_BT_LC)
|
||||||
|
|
||||||
# Build just the headless binary.
|
|
||||||
# Note: We currently symlink FOO_headless. In packaged builds we rename it.
|
|
||||||
cmake-server-binary: meta
|
cmake-server-binary: meta
|
||||||
@tools/pcommand cmake_prep_dir build/cmake/server-$(CM_BT_LC)/dist
|
@tools/pcommand cmake_prep_dir build/cmake/server-$(CM_BT_LC)/dist
|
||||||
@cd build/cmake/server-$(CM_BT_LC)/dist && test -f Makefile \
|
@cd build/cmake/server-$(CM_BT_LC)/dist && test -f Makefile \
|
||||||
|| cmake -DCMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) -DHEADLESS=true \
|
|| cmake -DCMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) -DHEADLESS=true \
|
||||||
$(shell pwd)/ballisticakit-cmake
|
$(shell pwd)/ballisticakit-cmake
|
||||||
@tools/pcommand update_cmake_prefab_lib server $(CM_BT_LC) build/cmake/server-$(CM_BT_LC)/dist
|
@tools/pcommand update_cmake_prefab_lib server $(CM_BT_LC) build/cmake/server-$(CM_BT_LC)/dist
|
||||||
@cd build/cmake/server-$(CM_BT_LC)/dist && $(MAKE) -j$(CPUS)
|
@cd build/cmake/server-$(CM_BT_LC)/dist && $(MAKE) -j$(CPUS) \
|
||||||
|
ballisticakit
|
||||||
|
|
||||||
cmake-server-clean:
|
cmake-server-clean:
|
||||||
rm -rf build/cmake/server-$(CM_BT_LC)
|
rm -rf build/cmake/server-$(CM_BT_LC)
|
||||||
|
|
||||||
|
cmake-modular-build: assets-cmake meta cmake-modular-binary
|
||||||
|
@$(STAGE_ASSETS) -cmakemodular -$(CM_BT_LC) \
|
||||||
|
build/cmake/modular-$(CM_BT_LC)/staged
|
||||||
|
@tools/pcommand echo BLD \
|
||||||
|
Modular build complete: BLU build/cmake/modular-$(CM_BT_LC)/staged
|
||||||
|
|
||||||
|
cmake-modular: cmake-modular-build
|
||||||
|
@cd build/cmake/modular-$(CM_BT_LC)/staged && ./ballisticakit
|
||||||
|
|
||||||
|
cmake-modular-binary: meta
|
||||||
|
@tools/pcommand cmake_prep_dir build/cmake/modular-$(CM_BT_LC)
|
||||||
|
@cd build/cmake/modular-$(CM_BT_LC) && test -f Makefile \
|
||||||
|
|| cmake -DCMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) \
|
||||||
|
$(shell pwd)/ballisticakit-cmake
|
||||||
|
@cd build/cmake/modular-$(CM_BT_LC) && $(MAKE) -j$(CPUS) ballisticakitso
|
||||||
|
|
||||||
|
cmake-modular-clean:
|
||||||
|
rm -rf build/cmake/modular-$(CM_BT_LC)
|
||||||
|
|
||||||
# Stage assets for building/running within CLion.
|
# Stage assets for building/running within CLion.
|
||||||
clion-staging: assets-cmake resources meta
|
clion-staging: assets-cmake resources meta
|
||||||
$(STAGE_ASSETS) -cmake build/clion_debug
|
$(STAGE_ASSETS) -cmake -debug build/clion_debug
|
||||||
$(STAGE_ASSETS) -cmake build/clion_release
|
$(STAGE_ASSETS) -cmake -release build/clion_release
|
||||||
|
|
||||||
# Tell make which of these targets don't represent files.
|
# Tell make which of these targets don't represent files.
|
||||||
.PHONY: cmake cmake-build cmake-clean cmake-server cmake-server-build \
|
.PHONY: cmake cmake-build cmake-clean cmake-server cmake-server-build \
|
||||||
@ -1162,6 +1180,7 @@ WIN_MSBUILD_EXE_B = "$(_WMSBE_1B)$(_WMSBE_2B)"
|
|||||||
WINPRJ = $(WINDOWS_PROJECT)
|
WINPRJ = $(WINDOWS_PROJECT)
|
||||||
WINPLT = $(WINDOWS_PLATFORM)
|
WINPLT = $(WINDOWS_PLATFORM)
|
||||||
WINCFG = $(WINDOWS_CONFIGURATION)
|
WINCFG = $(WINDOWS_CONFIGURATION)
|
||||||
|
WINCFGLC = $(shell echo $(WINDOWS_CONFIGURATION) | tr A-Z a-z)
|
||||||
|
|
||||||
# When using CLion, our cmake dir is root. Expose .clang-format there too.
|
# When using CLion, our cmake dir is root. Expose .clang-format there too.
|
||||||
ballisticakit-cmake/.clang-format: .clang-format
|
ballisticakit-cmake/.clang-format: .clang-format
|
||||||
|
|||||||
29
ballisticakit-cmake/.idea/dictionaries/ericf.xml
generated
29
ballisticakit-cmake/.idea/dictionaries/ericf.xml
generated
@ -137,6 +137,8 @@
|
|||||||
<w>ballistica</w>
|
<w>ballistica</w>
|
||||||
<w>ballistica's</w>
|
<w>ballistica's</w>
|
||||||
<w>ballisticakit</w>
|
<w>ballisticakit</w>
|
||||||
|
<w>ballisticakitso</w>
|
||||||
|
<w>ballisticaplus</w>
|
||||||
<w>bamasteraddr</w>
|
<w>bamasteraddr</w>
|
||||||
<w>bamasterlegacy</w>
|
<w>bamasterlegacy</w>
|
||||||
<w>bameta</w>
|
<w>bameta</w>
|
||||||
@ -206,6 +208,7 @@
|
|||||||
<w>bmas</w>
|
<w>bmas</w>
|
||||||
<w>bmasl</w>
|
<w>bmasl</w>
|
||||||
<w>bmcjphh</w>
|
<w>bmcjphh</w>
|
||||||
|
<w>bmodfeaturesets</w>
|
||||||
<w>bname</w>
|
<w>bname</w>
|
||||||
<w>bodyid</w>
|
<w>bodyid</w>
|
||||||
<w>bodypart</w>
|
<w>bodypart</w>
|
||||||
@ -324,6 +327,7 @@
|
|||||||
<w>clipcount</w>
|
<w>clipcount</w>
|
||||||
<w>cloudtoba</w>
|
<w>cloudtoba</w>
|
||||||
<w>cmakelist</w>
|
<w>cmakelist</w>
|
||||||
|
<w>cmakemodular</w>
|
||||||
<w>cmath</w>
|
<w>cmath</w>
|
||||||
<w>cmds</w>
|
<w>cmds</w>
|
||||||
<w>cmdspath</w>
|
<w>cmdspath</w>
|
||||||
@ -454,6 +458,7 @@
|
|||||||
<w>diesound</w>
|
<w>diesound</w>
|
||||||
<w>diffbit</w>
|
<w>diffbit</w>
|
||||||
<w>dinl</w>
|
<w>dinl</w>
|
||||||
|
<w>dir's</w>
|
||||||
<w>dirfilter</w>
|
<w>dirfilter</w>
|
||||||
<w>dirslash</w>
|
<w>dirslash</w>
|
||||||
<w>displaytime</w>
|
<w>displaytime</w>
|
||||||
@ -507,6 +512,7 @@
|
|||||||
<w>dusing</w>
|
<w>dusing</w>
|
||||||
<w>dval</w>
|
<w>dval</w>
|
||||||
<w>dxgi</w>
|
<w>dxgi</w>
|
||||||
|
<w>dylibdir</w>
|
||||||
<w>dynamicdata</w>
|
<w>dynamicdata</w>
|
||||||
<w>echidna</w>
|
<w>echidna</w>
|
||||||
<w>echofile</w>
|
<w>echofile</w>
|
||||||
@ -539,6 +545,7 @@
|
|||||||
<w>enumvalue</w>
|
<w>enumvalue</w>
|
||||||
<w>enval</w>
|
<w>enval</w>
|
||||||
<w>envcfg</w>
|
<w>envcfg</w>
|
||||||
|
<w>envglobals</w>
|
||||||
<w>envs</w>
|
<w>envs</w>
|
||||||
<w>envval</w>
|
<w>envval</w>
|
||||||
<w>ericf</w>
|
<w>ericf</w>
|
||||||
@ -558,6 +565,7 @@
|
|||||||
<w>exargs</w>
|
<w>exargs</w>
|
||||||
<w>exctype</w>
|
<w>exctype</w>
|
||||||
<w>exec'ed</w>
|
<w>exec'ed</w>
|
||||||
|
<w>exec'ing</w>
|
||||||
<w>execed</w>
|
<w>execed</w>
|
||||||
<w>execinfo</w>
|
<w>execinfo</w>
|
||||||
<w>execing</w>
|
<w>execing</w>
|
||||||
@ -592,6 +600,7 @@
|
|||||||
<w>fdata</w>
|
<w>fdata</w>
|
||||||
<w>fdataraw</w>
|
<w>fdataraw</w>
|
||||||
<w>fdcount</w>
|
<w>fdcount</w>
|
||||||
|
<w>fdcwd</w>
|
||||||
<w>fdirs</w>
|
<w>fdirs</w>
|
||||||
<w>fdirx</w>
|
<w>fdirx</w>
|
||||||
<w>fdiry</w>
|
<w>fdiry</w>
|
||||||
@ -660,6 +669,8 @@
|
|||||||
<w>fsarg</w>
|
<w>fsarg</w>
|
||||||
<w>fsconfigpath</w>
|
<w>fsconfigpath</w>
|
||||||
<w>fset</w>
|
<w>fset</w>
|
||||||
|
<w>fsetmfilenames</w>
|
||||||
|
<w>fsetmfilenamevals</w>
|
||||||
<w>fsetname</w>
|
<w>fsetname</w>
|
||||||
<w>fsets</w>
|
<w>fsets</w>
|
||||||
<w>fsmetapackagename</w>
|
<w>fsmetapackagename</w>
|
||||||
@ -673,6 +684,7 @@
|
|||||||
<w>ftos</w>
|
<w>ftos</w>
|
||||||
<w>ftou</w>
|
<w>ftou</w>
|
||||||
<w>fullpath</w>
|
<w>fullpath</w>
|
||||||
|
<w>fullstr</w>
|
||||||
<w>funcname</w>
|
<w>funcname</w>
|
||||||
<w>funcp</w>
|
<w>funcp</w>
|
||||||
<w>fval</w>
|
<w>fval</w>
|
||||||
@ -826,10 +838,12 @@
|
|||||||
<w>inides</w>
|
<w>inides</w>
|
||||||
<w>initguid</w>
|
<w>initguid</w>
|
||||||
<w>initing</w>
|
<w>initing</w>
|
||||||
|
<w>initname</w>
|
||||||
<w>inittab</w>
|
<w>inittab</w>
|
||||||
<w>inputdevice</w>
|
<w>inputdevice</w>
|
||||||
<w>inputter</w>
|
<w>inputter</w>
|
||||||
<w>insta</w>
|
<w>insta</w>
|
||||||
|
<w>instpath</w>
|
||||||
<w>intercollide</w>
|
<w>intercollide</w>
|
||||||
<w>internalformat</w>
|
<w>internalformat</w>
|
||||||
<w>internalmodule</w>
|
<w>internalmodule</w>
|
||||||
@ -914,6 +928,7 @@
|
|||||||
<w>lgui</w>
|
<w>lgui</w>
|
||||||
<w>lhalf</w>
|
<w>lhalf</w>
|
||||||
<w>libballistica</w>
|
<w>libballistica</w>
|
||||||
|
<w>libballisticaplus</w>
|
||||||
<w>libbz</w>
|
<w>libbz</w>
|
||||||
<w>libbzip</w>
|
<w>libbzip</w>
|
||||||
<w>libfile</w>
|
<w>libfile</w>
|
||||||
@ -998,6 +1013,7 @@
|
|||||||
<w>maxtries</w>
|
<w>maxtries</w>
|
||||||
<w>maxwait</w>
|
<w>maxwait</w>
|
||||||
<w>maxwidth</w>
|
<w>maxwidth</w>
|
||||||
|
<w>mbstowcs</w>
|
||||||
<w>mdpath</w>
|
<w>mdpath</w>
|
||||||
<w>mediump</w>
|
<w>mediump</w>
|
||||||
<w>memalign</w>
|
<w>memalign</w>
|
||||||
@ -1014,6 +1030,7 @@
|
|||||||
<w>metallink</w>
|
<w>metallink</w>
|
||||||
<w>metamakefile</w>
|
<w>metamakefile</w>
|
||||||
<w>meth</w>
|
<w>meth</w>
|
||||||
|
<w>mfilename</w>
|
||||||
<w>mhbegin</w>
|
<w>mhbegin</w>
|
||||||
<w>mhend</w>
|
<w>mhend</w>
|
||||||
<w>microsecs</w>
|
<w>microsecs</w>
|
||||||
@ -1164,6 +1181,7 @@
|
|||||||
<w>olde</w>
|
<w>olde</w>
|
||||||
<w>oldname</w>
|
<w>oldname</w>
|
||||||
<w>oldpath</w>
|
<w>oldpath</w>
|
||||||
|
<w>oldpaths</w>
|
||||||
<w>oldtoken</w>
|
<w>oldtoken</w>
|
||||||
<w>olduuid</w>
|
<w>olduuid</w>
|
||||||
<w>olduuids</w>
|
<w>olduuids</w>
|
||||||
@ -1192,6 +1210,8 @@
|
|||||||
<w>opposingbody</w>
|
<w>opposingbody</w>
|
||||||
<w>opposingnode</w>
|
<w>opposingnode</w>
|
||||||
<w>optin</w>
|
<w>optin</w>
|
||||||
|
<w>optnm</w>
|
||||||
|
<w>optstuff</w>
|
||||||
<w>ortho</w>
|
<w>ortho</w>
|
||||||
<w>osis</w>
|
<w>osis</w>
|
||||||
<w>ossaudiodev</w>
|
<w>ossaudiodev</w>
|
||||||
@ -1201,6 +1221,7 @@
|
|||||||
<w>ourcode</w>
|
<w>ourcode</w>
|
||||||
<w>ourname</w>
|
<w>ourname</w>
|
||||||
<w>ourpackage</w>
|
<w>ourpackage</w>
|
||||||
|
<w>ourpaths</w>
|
||||||
<w>ourself</w>
|
<w>ourself</w>
|
||||||
<w>ourstanding</w>
|
<w>ourstanding</w>
|
||||||
<w>outdict</w>
|
<w>outdict</w>
|
||||||
@ -1223,6 +1244,7 @@
|
|||||||
<w>pathbar</w>
|
<w>pathbar</w>
|
||||||
<w>pathcapture</w>
|
<w>pathcapture</w>
|
||||||
<w>pathdst</w>
|
<w>pathdst</w>
|
||||||
|
<w>pathlen</w>
|
||||||
<w>pathlist</w>
|
<w>pathlist</w>
|
||||||
<w>pathparts</w>
|
<w>pathparts</w>
|
||||||
<w>pathsegs</w>
|
<w>pathsegs</w>
|
||||||
@ -1362,6 +1384,8 @@
|
|||||||
<w>pysitedir</w>
|
<w>pysitedir</w>
|
||||||
<w>pythondevmode</w>
|
<w>pythondevmode</w>
|
||||||
<w>pythonenumsmodule</w>
|
<w>pythonenumsmodule</w>
|
||||||
|
<w>pythonoptimize</w>
|
||||||
|
<w>pythonutf</w>
|
||||||
<w>pytype</w>
|
<w>pytype</w>
|
||||||
<w>qerr</w>
|
<w>qerr</w>
|
||||||
<w>qrcode</w>
|
<w>qrcode</w>
|
||||||
@ -1386,6 +1410,8 @@
|
|||||||
<w>rdynamic</w>
|
<w>rdynamic</w>
|
||||||
<w>reaaaly</w>
|
<w>reaaaly</w>
|
||||||
<w>readexactly</w>
|
<w>readexactly</w>
|
||||||
|
<w>readlink</w>
|
||||||
|
<w>readlinkat</w>
|
||||||
<w>readset</w>
|
<w>readset</w>
|
||||||
<w>realloc</w>
|
<w>realloc</w>
|
||||||
<w>reallocations</w>
|
<w>reallocations</w>
|
||||||
@ -1579,6 +1605,7 @@
|
|||||||
<w>sssssssi</w>
|
<w>sssssssi</w>
|
||||||
<w>ssssssssssss</w>
|
<w>ssssssssssss</w>
|
||||||
<w>ssval</w>
|
<w>ssval</w>
|
||||||
|
<w>stager</w>
|
||||||
<w>standin</w>
|
<w>standin</w>
|
||||||
<w>startedptr</w>
|
<w>startedptr</w>
|
||||||
<w>startms</w>
|
<w>startms</w>
|
||||||
@ -1635,6 +1662,7 @@
|
|||||||
<w>swiftgeneratepch</w>
|
<w>swiftgeneratepch</w>
|
||||||
<w>swiftmergegeneratedheaders</w>
|
<w>swiftmergegeneratedheaders</w>
|
||||||
<w>symbolification</w>
|
<w>symbolification</w>
|
||||||
|
<w>syscall</w>
|
||||||
<w>syscalls</w>
|
<w>syscalls</w>
|
||||||
<w>sysresponse</w>
|
<w>sysresponse</w>
|
||||||
<w>tabdefs</w>
|
<w>tabdefs</w>
|
||||||
@ -1839,6 +1867,7 @@
|
|||||||
<w>wiimote</w>
|
<w>wiimote</w>
|
||||||
<w>wiimotes</w>
|
<w>wiimotes</w>
|
||||||
<w>winapi</w>
|
<w>winapi</w>
|
||||||
|
<w>wincfglc</w>
|
||||||
<w>windowshade</w>
|
<w>windowshade</w>
|
||||||
<w>winmm</w>
|
<w>winmm</w>
|
||||||
<w>winsock</w>
|
<w>winsock</w>
|
||||||
|
|||||||
@ -177,6 +177,12 @@ add_library(ode
|
|||||||
)
|
)
|
||||||
target_include_directories(ode PRIVATE ${ODE_SRC_ROOT})
|
target_include_directories(ode PRIVATE ${ODE_SRC_ROOT})
|
||||||
|
|
||||||
|
# Necessary on GCC to allow linking in to our .so version.
|
||||||
|
# (but disabling semantic-interposition should lessen the associated speed hit).
|
||||||
|
if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
|
||||||
|
target_compile_options(ode PRIVATE -fPIC -fno-semantic-interposition)
|
||||||
|
endif ()
|
||||||
|
|
||||||
# NOTE: There used to be an issue with optimized GCC builds where mesh
|
# NOTE: There used to be an issue with optimized GCC builds where mesh
|
||||||
# collisions would fail randomly, leading to characters falling through
|
# collisions would fail randomly, leading to characters falling through
|
||||||
# floors somewhat regularly. For this reason I was limiting optimization to
|
# floors somewhat regularly. For this reason I was limiting optimization to
|
||||||
@ -194,8 +200,7 @@ target_include_directories(ode PRIVATE ${ODE_SRC_ROOT})
|
|||||||
# endif()
|
# endif()
|
||||||
# endif ()
|
# endif ()
|
||||||
|
|
||||||
# BallisticaKit binary.
|
set(BALLISTICA_SOURCES
|
||||||
add_executable(ballisticakit
|
|
||||||
${BA_SRC_ROOT}/external/qr_code_generator/QrCode.cpp
|
${BA_SRC_ROOT}/external/qr_code_generator/QrCode.cpp
|
||||||
# AUTOGENERATED_PUBLIC_BEGIN (this section is managed by the "update_project" tool)
|
# AUTOGENERATED_PUBLIC_BEGIN (this section is managed by the "update_project" tool)
|
||||||
${BA_SRC_ROOT}/ballistica/base/app/app.cc
|
${BA_SRC_ROOT}/ballistica/base/app/app.cc
|
||||||
@ -742,28 +747,65 @@ add_executable(ballisticakit
|
|||||||
${BA_SRC_ROOT}/ballistica/ui_v1/widget/widget.cc
|
${BA_SRC_ROOT}/ballistica/ui_v1/widget/widget.cc
|
||||||
${BA_SRC_ROOT}/ballistica/ui_v1/widget/widget.h
|
${BA_SRC_ROOT}/ballistica/ui_v1/widget/widget.h
|
||||||
# AUTOGENERATED_PUBLIC_END
|
# AUTOGENERATED_PUBLIC_END
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# BallisticaKit monolithic binary.
|
||||||
|
add_executable(ballisticakit ${BALLISTICA_SOURCES})
|
||||||
|
|
||||||
# Gets -rdynamic added when linking gcc builds which exports all symbols
|
# Gets -rdynamic added when linking gcc builds which exports all symbols
|
||||||
# which gives us more meaningful stack traces using backtrace_symbols().
|
# which gives us more meaningful stack traces using backtrace_symbols().
|
||||||
set_target_properties(ballisticakit PROPERTIES ENABLE_EXPORTS 1)
|
set_target_properties(ballisticakit PROPERTIES ENABLE_EXPORTS 1)
|
||||||
|
|
||||||
if (HEADLESS)
|
if (HEADLESS)
|
||||||
set_target_properties(ballisticakit PROPERTIES OUTPUT_NAME "ballisticakit_headless")
|
set_target_properties(ballisticakit
|
||||||
|
PROPERTIES OUTPUT_NAME "ballisticakit_headless")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
target_include_directories(ballisticakit PRIVATE
|
target_include_directories(ballisticakit PRIVATE
|
||||||
${Python_INCLUDE_DIRS}
|
${Python_INCLUDE_DIRS}
|
||||||
${BA_SRC_ROOT}/external/open_dynamics_engine-ef
|
${BA_SRC_ROOT}/external/open_dynamics_engine-ef
|
||||||
${EXTRA_INCLUDE_DIRS}
|
${EXTRA_INCLUDE_DIRS})
|
||||||
)
|
|
||||||
|
|
||||||
target_link_libraries(ballisticakit PRIVATE
|
target_link_libraries(ballisticakit PRIVATE
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/prefablib/libballistica_plus.a ode pthread ${Python_LIBRARIES}
|
${CMAKE_CURRENT_BINARY_DIR}/prefablib/libballisticaplus.a ode pthread ${Python_LIBRARIES}
|
||||||
${SDL2_LIBRARIES} ${EXTRA_LIBRARIES} dl)
|
${SDL2_LIBRARIES} ${EXTRA_LIBRARIES} dl)
|
||||||
|
|
||||||
# Hack for building on rpi (might be due to my manually built Python 3.8)
|
# Hack for building on rpi; need to update my pi so I can remove this.
|
||||||
# Hopefully can remove later...
|
|
||||||
if(EXISTS "/home/pi")
|
if(EXISTS "/home/pi")
|
||||||
target_link_libraries(ballisticakit PRIVATE dl util stdc++fs)
|
target_link_libraries(ballisticakit PRIVATE dl util stdc++fs)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
# BallisticaKit modular shared library
|
||||||
|
# (for use with vanilla Python interpreters).
|
||||||
|
add_library(ballisticakitso SHARED ${BALLISTICA_SOURCES})
|
||||||
|
|
||||||
|
# This is a 'modular' build.
|
||||||
|
target_compile_definitions(ballisticakitso PRIVATE BA_MONOLITHIC_BUILD=0)
|
||||||
|
|
||||||
|
# Gets -rdynamic added when linking gcc builds which exports all symbols
|
||||||
|
# which gives us more meaningful stack traces using backtrace_symbols().
|
||||||
|
set_target_properties(ballisticakitso PROPERTIES ENABLE_EXPORTS 1)
|
||||||
|
|
||||||
|
set_target_properties(ballisticakitso
|
||||||
|
PROPERTIES PREFIX "")
|
||||||
|
set_target_properties(ballisticakitso
|
||||||
|
PROPERTIES SUFFIX ".so")
|
||||||
|
|
||||||
|
if (HEADLESS)
|
||||||
|
set_target_properties(ballisticakitso
|
||||||
|
PROPERTIES OUTPUT_NAME "ballisticakit_headless")
|
||||||
|
else ()
|
||||||
|
set_target_properties(ballisticakitso
|
||||||
|
PROPERTIES OUTPUT_NAME "ballisticakit")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
target_include_directories(ballisticakitso PRIVATE
|
||||||
|
${Python_INCLUDE_DIRS}
|
||||||
|
${BA_SRC_ROOT}/external/open_dynamics_engine-ef
|
||||||
|
${EXTRA_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
target_link_libraries(ballisticakitso PRIVATE
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/prefablib/libballisticaplus.a ode pthread ${Python_LIBRARIES}
|
||||||
|
${SDL2_LIBRARIES} ${EXTRA_LIBRARIES} dl)
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,7 @@ fset = FeatureSet.get_active()
|
|||||||
|
|
||||||
fset.requirements = set()
|
fset.requirements = set()
|
||||||
|
|
||||||
fset.has_native_python_module = False
|
fset.has_python_binary_module = False
|
||||||
|
|
||||||
# Bits of code we're using that don't conform to our feature-set based
|
# Bits of code we're using that don't conform to our feature-set based
|
||||||
# namespace scheme.
|
# namespace scheme.
|
||||||
|
|||||||
@ -12,6 +12,6 @@ from batools.featureset import FeatureSet
|
|||||||
# Grab the FeatureSet we should apply to.
|
# Grab the FeatureSet we should apply to.
|
||||||
fset = FeatureSet.get_active()
|
fset = FeatureSet.get_active()
|
||||||
|
|
||||||
fset.has_native_python_module = False
|
fset.has_python_binary_module = False
|
||||||
|
|
||||||
fset.requirements = {'core', 'base', 'scene_v1'}
|
fset.requirements = {'core', 'base', 'scene_v1'}
|
||||||
|
|||||||
@ -12,6 +12,6 @@ from batools.featureset import FeatureSet
|
|||||||
# Grab the FeatureSet we should apply to.
|
# Grab the FeatureSet we should apply to.
|
||||||
fset = FeatureSet.get_active()
|
fset = FeatureSet.get_active()
|
||||||
|
|
||||||
fset.has_native_python_module = False
|
fset.has_python_binary_module = False
|
||||||
|
|
||||||
fset.requirements = {'core', 'base', 'ui_v1', 'classic'}
|
fset.requirements = {'core', 'base', 'ui_v1', 'classic'}
|
||||||
|
|||||||
@ -54,8 +54,10 @@ def on_native_module_import() -> None:
|
|||||||
# make noise if that's not the case.
|
# make noise if that's not the case.
|
||||||
if debug_build != sys.flags.dev_mode:
|
if debug_build != sys.flags.dev_mode:
|
||||||
logging.warning(
|
logging.warning(
|
||||||
'Mismatch in ballistica debug_build %s'
|
'Ballistica was built with debug-mode %s'
|
||||||
' and sys.flags.dev_mode %s; this may cause problems.',
|
' but Python is running with dev-mode %s;'
|
||||||
|
' this mismatch may cause problems.'
|
||||||
|
' See https://docs.python.org/3/library/devmode.html',
|
||||||
debug_build,
|
debug_build,
|
||||||
sys.flags.dev_mode,
|
sys.flags.dev_mode,
|
||||||
)
|
)
|
||||||
@ -75,11 +77,11 @@ def setup_env_for_app_run() -> None:
|
|||||||
assert baenv.config_exists()
|
assert baenv.config_exists()
|
||||||
|
|
||||||
# If we were unable to set paths earlier, complain now.
|
# If we were unable to set paths earlier, complain now.
|
||||||
if baenv.g_paths_set_failed:
|
if baenv.did_paths_set_fail():
|
||||||
logging.warning(
|
logging.warning(
|
||||||
'Ballistica Python paths have not been set. This may cause'
|
'Ballistica Python paths have not been set. This may cause'
|
||||||
' problems. To ensure paths are set, run baenv.configure()'
|
' problems. To ensure paths are set, run baenv.configure()'
|
||||||
' before importing any ballistica modules.'
|
' BEFORE importing any Ballistica modules.'
|
||||||
)
|
)
|
||||||
|
|
||||||
# Set up interrupt-signal handling.
|
# Set up interrupt-signal handling.
|
||||||
@ -144,9 +146,10 @@ def on_app_launching() -> None:
|
|||||||
assert _babase.in_logic_thread()
|
assert _babase.in_logic_thread()
|
||||||
|
|
||||||
# Let the user know if the app python dir is a custom one.
|
# Let the user know if the app python dir is a custom one.
|
||||||
if baenv.g_user_system_scripts_dir is not None:
|
user_sys_scripts_dir = baenv.get_user_system_scripts_dir()
|
||||||
|
if user_sys_scripts_dir is not None:
|
||||||
_babase.screenmessage(
|
_babase.screenmessage(
|
||||||
f"Using user system scripts: '{baenv.g_user_system_scripts_dir}'",
|
f"Using user system scripts: '{user_sys_scripts_dir}'",
|
||||||
color=(0.6, 0.6, 1.0),
|
color=(0.6, 0.6, 1.0),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -267,6 +267,9 @@ class StoreSubsystem:
|
|||||||
'icons.mikirog': {
|
'icons.mikirog': {
|
||||||
'icon': babase.charstr(babase.SpecialChar.MIKIROG)
|
'icon': babase.charstr(babase.SpecialChar.MIKIROG)
|
||||||
},
|
},
|
||||||
|
'icons.explodinary': {
|
||||||
|
'icon': babase.charstr(babase.SpecialChar.EXPLODINARY_LOGO)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
return babase.app.classic.store_items
|
return babase.app.classic.store_items
|
||||||
|
|
||||||
|
|||||||
@ -4,9 +4,11 @@
|
|||||||
|
|
||||||
This module is used to set up and/or check the global Python environment
|
This module is used to set up and/or check the global Python environment
|
||||||
before running a ballistica app. This includes things such as paths,
|
before running a ballistica app. This includes things such as paths,
|
||||||
logging, debug-modes, garbage-collection settings, and signal handling.
|
logging, and app-dirs. Because these things are global in nature, this
|
||||||
Because these things are global in nature, this should be done before
|
should be done before any ballistica modules are imported.
|
||||||
any ballistica modules are imported.
|
|
||||||
|
This module can also be exec'ed directly to set up a default environment
|
||||||
|
and then run the app.
|
||||||
|
|
||||||
Ballistica can be used without explicitly configuring the environment in
|
Ballistica can be used without explicitly configuring the environment in
|
||||||
order to integrate it in arbitrary Python environments, but this may
|
order to integrate it in arbitrary Python environments, but this may
|
||||||
@ -20,25 +22,42 @@ import logging
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
import __main__
|
||||||
|
|
||||||
from efro.log import setup_logging, LogLevel
|
from efro.log import setup_logging, LogLevel
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from efro.log import LogHandler
|
from efro.log import LogHandler
|
||||||
|
|
||||||
|
# IMPORTANT - It is likely (and in some cases expected) that this
|
||||||
|
# module's code will be exec'ed multiple times. This is because it is
|
||||||
|
# the job of this module to set up paths for an engine run, and that may
|
||||||
|
# involve modifying sys.path in such a way that this module resolves to
|
||||||
|
# a different path afterwards (for example from
|
||||||
|
# /abs/path/to/ba_data/scripts/babase.py to ba_data/scripts/babase.py).
|
||||||
|
# This can result in the next import of baenv loading us from our 'new'
|
||||||
|
# location, which may or may not actually be the same file on disk as
|
||||||
|
# the old. Either way, however, multiple execs will happen in some form.
|
||||||
|
#
|
||||||
|
# So we need to do a few things to handle that situation gracefully.
|
||||||
|
#
|
||||||
|
# - First, we need to store any mutable global state in the __main__
|
||||||
|
# module; not in ourself. This way, alternate versions of ourself will
|
||||||
|
# still know if we already ran configure/etc.
|
||||||
|
#
|
||||||
|
# - Second, we should avoid the use of isinstance and similar calls for
|
||||||
|
# our types. An EnvConfig we create would technically be a different
|
||||||
|
# type than that created by an alternate baenv.
|
||||||
|
|
||||||
# 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 = 21171
|
TARGET_BALLISTICA_BUILD = 21183
|
||||||
TARGET_BALLISTICA_VERSION = '1.7.23'
|
TARGET_BALLISTICA_VERSION = '1.7.24'
|
||||||
|
|
||||||
_g_env_config: EnvConfig | None = None
|
|
||||||
g_paths_set_failed = False # pylint: disable=invalid-name
|
|
||||||
g_user_system_scripts_dir: str | None = None
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class EnvConfig:
|
class EnvConfig:
|
||||||
"""Final settings put together by the configure call."""
|
"""Environment put together by the configure call."""
|
||||||
|
|
||||||
config_dir: str
|
config_dir: str
|
||||||
data_dir: str
|
data_dir: str
|
||||||
@ -49,17 +68,56 @@ class EnvConfig:
|
|||||||
log_handler: LogHandler | None
|
log_handler: LogHandler | None
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class EnvGlobals:
|
||||||
|
"""Our globals we store in the main module."""
|
||||||
|
|
||||||
|
config: EnvConfig | None = None
|
||||||
|
config_called: bool = False
|
||||||
|
paths_set_failed: bool = False
|
||||||
|
user_system_scripts_dir: str | None = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get(cls) -> EnvGlobals:
|
||||||
|
"""Create/return our singleton."""
|
||||||
|
name = '_baenv_globals'
|
||||||
|
envglobals: EnvGlobals | None = getattr(__main__, name, None)
|
||||||
|
if envglobals is None:
|
||||||
|
envglobals = EnvGlobals()
|
||||||
|
setattr(__main__, name, envglobals)
|
||||||
|
return envglobals
|
||||||
|
|
||||||
|
|
||||||
def config_exists() -> bool:
|
def config_exists() -> bool:
|
||||||
"""Has a config been created?"""
|
"""Has a config been created?"""
|
||||||
return _g_env_config is not None
|
|
||||||
|
return EnvGlobals.get().config is not None
|
||||||
|
|
||||||
|
|
||||||
|
def did_paths_set_fail() -> bool:
|
||||||
|
"""Did we try to set paths and failed?"""
|
||||||
|
return EnvGlobals.get().paths_set_failed
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_system_scripts_dir() -> str | None:
|
||||||
|
"""If there's a custom user system scripts dir in play, return it."""
|
||||||
|
return EnvGlobals.get().user_system_scripts_dir
|
||||||
|
|
||||||
|
|
||||||
def get_config() -> EnvConfig:
|
def get_config() -> EnvConfig:
|
||||||
"""Return the active env-config. Creates default if none exists."""
|
"""Return the active config, creating a default if none exists."""
|
||||||
if _g_env_config is None:
|
envglobals = EnvGlobals.get()
|
||||||
|
|
||||||
|
if not envglobals.config_called:
|
||||||
configure()
|
configure()
|
||||||
assert _g_env_config is not None
|
|
||||||
return _g_env_config
|
config = envglobals.config
|
||||||
|
if config is None:
|
||||||
|
raise RuntimeError(
|
||||||
|
'baenv.configure() has been called but no config exists;'
|
||||||
|
' perhaps it errored?'
|
||||||
|
)
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
def configure(
|
def configure(
|
||||||
@ -72,22 +130,91 @@ def configure(
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Set up the Python environment for running a ballistica app.
|
"""Set up the Python environment for running a ballistica app.
|
||||||
|
|
||||||
This includes things such as Python paths and log redirection. For
|
This includes things such as Python path wrangling and app directory
|
||||||
that reason, this should be called before any other ballistica
|
creation. This should be called before any other ballistica modules
|
||||||
modules are imported, since it may make changes to sys.path,
|
are imported since it may make changes to sys.path which can affect
|
||||||
affecting where those modules get loaded from.
|
where those modules get loaded from.
|
||||||
"""
|
"""
|
||||||
# pylint: disable=too-many-branches
|
|
||||||
# pylint: disable=too-many-locals
|
|
||||||
|
|
||||||
global _g_env_config # pylint: disable=global-statement
|
envglobals = EnvGlobals.get()
|
||||||
if _g_env_config is not None:
|
|
||||||
raise RuntimeError('An EnvConfig has already been created.')
|
|
||||||
|
|
||||||
# The very first thing we do is set up our logging system and feed
|
if envglobals.config_called:
|
||||||
# Python's stdout/stderr into it. Then we can at least debug problems
|
raise RuntimeError(
|
||||||
# on systems where native stdout/stderr is not easily accessible
|
'baenv.configure() has already been called;'
|
||||||
# such as Android.
|
' it can only be called once.'
|
||||||
|
)
|
||||||
|
envglobals.config_called = True
|
||||||
|
|
||||||
|
# The very first thing we do is set up our logging system and pipe
|
||||||
|
# Python's stdout/stderr into it. Then we can at least debug
|
||||||
|
# problems on systems where native stdout/stderr is not easily
|
||||||
|
# accessible such as Android.
|
||||||
|
log_handler = _setup_logging()
|
||||||
|
|
||||||
|
# We want to always be run in UTF-8 mode; complain if we're not.
|
||||||
|
if sys.flags.utf8_mode != 1:
|
||||||
|
logging.warning(
|
||||||
|
"Python's UTF-8 mode is not set. Running ballistica without"
|
||||||
|
' it may lead to errors.'
|
||||||
|
)
|
||||||
|
|
||||||
|
# Attempt to set up Python paths and our own data paths so that
|
||||||
|
# engine modules, mods, etc. are pulled from predictable places.
|
||||||
|
(
|
||||||
|
user_python_dir,
|
||||||
|
app_python_dir,
|
||||||
|
site_python_dir,
|
||||||
|
data_dir,
|
||||||
|
config_dir,
|
||||||
|
standard_app_python_dir,
|
||||||
|
) = _setup_paths(
|
||||||
|
user_python_dir,
|
||||||
|
app_python_dir,
|
||||||
|
site_python_dir,
|
||||||
|
data_dir,
|
||||||
|
config_dir,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Attempt to create dirs that we'll write stuff to.
|
||||||
|
_setup_dirs(config_dir, user_python_dir)
|
||||||
|
|
||||||
|
# Get ssl working if needed so we can use https and all that.
|
||||||
|
_setup_certs(contains_python_dist)
|
||||||
|
|
||||||
|
# This is now the active config.
|
||||||
|
envglobals.config = EnvConfig(
|
||||||
|
config_dir=config_dir,
|
||||||
|
data_dir=data_dir,
|
||||||
|
user_python_dir=user_python_dir,
|
||||||
|
app_python_dir=app_python_dir,
|
||||||
|
standard_app_python_dir=standard_app_python_dir,
|
||||||
|
site_python_dir=site_python_dir,
|
||||||
|
log_handler=log_handler,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _calc_data_dir(data_dir: str | None) -> str:
|
||||||
|
if data_dir is None:
|
||||||
|
# To calc default data_dir, we assume this module was imported
|
||||||
|
# from that dir's ba_data/python subdir.
|
||||||
|
assert Path(__file__).parts[-3:-1] == ('ba_data', 'python')
|
||||||
|
data_dir_path = Path(__file__).parents[2]
|
||||||
|
|
||||||
|
# Prefer tidy relative paths like '.' if possible so that things
|
||||||
|
# like stack traces are easier to read.
|
||||||
|
|
||||||
|
# NOTE: Perhaps we should have an option to disable this
|
||||||
|
# behavior for cases where the user might be doing chdir stuff.
|
||||||
|
cwd_path = Path.cwd()
|
||||||
|
data_dir = str(
|
||||||
|
data_dir_path.relative_to(cwd_path)
|
||||||
|
if data_dir_path.is_relative_to(cwd_path)
|
||||||
|
else data_dir_path
|
||||||
|
)
|
||||||
|
return data_dir
|
||||||
|
|
||||||
|
|
||||||
|
def _setup_logging() -> LogHandler:
|
||||||
log_handler = setup_logging(
|
log_handler = setup_logging(
|
||||||
log_path=None,
|
log_path=None,
|
||||||
level=LogLevel.DEBUG,
|
level=LogLevel.DEBUG,
|
||||||
@ -95,41 +222,46 @@ def configure(
|
|||||||
log_stdout_stderr=True,
|
log_stdout_stderr=True,
|
||||||
cache_size_limit=1024 * 1024,
|
cache_size_limit=1024 * 1024,
|
||||||
)
|
)
|
||||||
|
return log_handler
|
||||||
|
|
||||||
# Sanity check: we should always be run in UTF-8 mode.
|
|
||||||
if sys.flags.utf8_mode != 1:
|
|
||||||
logging.warning(
|
|
||||||
"Python's UTF-8 mode is not set. Running ballistica without"
|
|
||||||
' it may lead to errors.'
|
|
||||||
)
|
|
||||||
|
|
||||||
# Now do paths. We want to set stuff up so that engine modules,
|
def _setup_certs(contains_python_dist: bool) -> None:
|
||||||
# mods, etc. are pulled from predictable places.
|
# In situations where we're bringing our own Python let's also
|
||||||
cwd_path = Path.cwd()
|
# provide our own root certs so ssl works. We can consider
|
||||||
|
# overriding this in particular embedded cases if we can verify that
|
||||||
|
# system certs are working. We also allow forcing this via an env
|
||||||
|
# var if the user desires.
|
||||||
|
if (
|
||||||
|
contains_python_dist
|
||||||
|
or os.environ.get('BA_USE_BUNDLED_ROOT_CERTS') == '1'
|
||||||
|
):
|
||||||
|
import certifi
|
||||||
|
|
||||||
# A few paths we can ALWAYS calculate since they don't affect Python
|
# Let both OpenSSL and requests (if present) know to use this.
|
||||||
# imports:
|
os.environ['SSL_CERT_FILE'] = os.environ[
|
||||||
|
'REQUESTS_CA_BUNDLE'
|
||||||
|
] = certifi.where()
|
||||||
|
|
||||||
# Default data_dir assumes this module was imported from its
|
|
||||||
# ba_data/python subdir.
|
def _setup_paths(
|
||||||
if data_dir is None:
|
user_python_dir: str | None,
|
||||||
assert Path(__file__).parts[-3:-1] == ('ba_data', 'python')
|
app_python_dir: str | None,
|
||||||
data_dir_path = Path(__file__).parents[2]
|
site_python_dir: str | None,
|
||||||
# Prefer tidy relative paths like '.' if possible.
|
data_dir: str | None,
|
||||||
data_dir = str(
|
config_dir: str | None,
|
||||||
data_dir_path.relative_to(cwd_path)
|
) -> tuple[str | None, str | None, str | None, str, str, str]:
|
||||||
if data_dir_path.is_relative_to(cwd_path)
|
# First a few paths we can ALWAYS calculate since they don't affect
|
||||||
else data_dir_path
|
# Python imports:
|
||||||
)
|
|
||||||
|
envglobals = EnvGlobals.get()
|
||||||
|
|
||||||
|
data_dir = _calc_data_dir(data_dir)
|
||||||
|
|
||||||
# Default config-dir is simply ~/.ballisticakit
|
# Default config-dir is simply ~/.ballisticakit
|
||||||
if config_dir is None:
|
if config_dir is None:
|
||||||
config_dir = str(Path(Path.home(), '.ballisticakit'))
|
config_dir = str(Path(Path.home(), '.ballisticakit'))
|
||||||
|
|
||||||
# Ok now Python paths.
|
# Standard app-python-dir is simply ba_data/python under data-dir.
|
||||||
|
|
||||||
# By default, app-python-dir is simply ba_data/python under
|
|
||||||
# data-dir.
|
|
||||||
standard_app_python_dir = str(Path(data_dir, 'ba_data', 'python'))
|
standard_app_python_dir = str(Path(data_dir, 'ba_data', 'python'))
|
||||||
|
|
||||||
# If _babase has already been imported, there's not much we can do
|
# If _babase has already been imported, there's not much we can do
|
||||||
@ -137,12 +269,11 @@ def configure(
|
|||||||
if '_babase' in sys.modules:
|
if '_babase' in sys.modules:
|
||||||
app_python_dir = user_python_dir = site_python_dir = None
|
app_python_dir = user_python_dir = site_python_dir = None
|
||||||
|
|
||||||
# We don't actually complain yet here; we simply take note
|
# We don't actually complain yet here; we simply take note that
|
||||||
# that we weren't able to set paths. Then we complain if/when
|
# we weren't able to set paths. Then we complain if/when the app
|
||||||
# the app is started. This way, non-app uses of babase won't be
|
# is started. This way, non-app uses of babase won't be filled
|
||||||
# filled with unnecessary warnings.
|
# with unnecessary warnings.
|
||||||
global g_paths_set_failed # pylint: disable=global-statement
|
envglobals.paths_set_failed = True
|
||||||
g_paths_set_failed = True
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Ok; _babase hasn't been imported yet so we can muck with
|
# Ok; _babase hasn't been imported yet so we can muck with
|
||||||
@ -163,35 +294,58 @@ def configure(
|
|||||||
|
|
||||||
# Wherever our user_python_dir is, if we find a sys/FOO dir
|
# Wherever our user_python_dir is, if we find a sys/FOO dir
|
||||||
# under it where FOO matches our version, use that as our
|
# under it where FOO matches our version, use that as our
|
||||||
# app_python_dir.
|
# app_python_dir. This allows modding built-in stuff on
|
||||||
check_dir = os.path.join(
|
# platforms where there is no write access to said built-in
|
||||||
user_python_dir, 'sys', TARGET_BALLISTICA_VERSION
|
# stuff.
|
||||||
)
|
check_dir = Path(user_python_dir, 'sys', TARGET_BALLISTICA_VERSION)
|
||||||
if os.path.isdir(check_dir):
|
if check_dir.is_dir():
|
||||||
global g_user_system_scripts_dir # pylint: disable=global-statement
|
envglobals.user_system_scripts_dir = app_python_dir = str(check_dir)
|
||||||
g_user_system_scripts_dir = check_dir
|
|
||||||
app_python_dir = check_dir
|
|
||||||
|
|
||||||
# Ok, now apply these to sys.path.
|
# Ok, now apply these to sys.path.
|
||||||
|
|
||||||
# First off, strip out any instances of the path containing this
|
# First off, strip out any instances of the path containing this
|
||||||
# module. We will probably be re-adding the same path in a
|
# module. We will *probably* be re-adding the same path in a
|
||||||
# moment but its technically possible that we won't be (if
|
# moment so this keeps things cleaner. Though hmm should we
|
||||||
# app_python_dir is overridden to somewhere else, etc.)
|
# leave it in there in cases where we *don't* re-add the same
|
||||||
|
# path?...
|
||||||
our_parent_path = Path(__file__).parent.resolve()
|
our_parent_path = Path(__file__).parent.resolve()
|
||||||
paths: list[str] = [
|
oldpaths: list[str] = [
|
||||||
p for p in sys.path if Path(p).resolve() != our_parent_path
|
p for p in sys.path if Path(p).resolve() != our_parent_path
|
||||||
]
|
]
|
||||||
# Let's lookup mods first (so users can do whatever they want).
|
|
||||||
# and then our bundled scripts last (don't want bundled
|
|
||||||
# site-package stuff overwriting system versions)
|
|
||||||
paths.insert(0, user_python_dir)
|
|
||||||
paths.append(app_python_dir)
|
|
||||||
paths.append(site_python_dir)
|
|
||||||
sys.path = paths
|
|
||||||
|
|
||||||
# Attempt to create the dirs that we'll write stuff to. Not the end
|
# Let's place mods first (so users can override whatever they
|
||||||
# of the world if we fail though.
|
# want) followed by our app scripts and lastly our bundled site
|
||||||
|
# stuff.
|
||||||
|
|
||||||
|
# One could make the argument that at least our bundled app &
|
||||||
|
# site stuff should be placed at the end so actual local site
|
||||||
|
# stuff could override it. That could be a good thing or a bad
|
||||||
|
# thing. Maybe we could add an option for that, but for now I'm
|
||||||
|
# prioritizing our stuff to give as consistent an environment as
|
||||||
|
# possible.
|
||||||
|
ourpaths = [user_python_dir, app_python_dir, site_python_dir]
|
||||||
|
|
||||||
|
# Special case: our modular builds will have a 'python-dylib'
|
||||||
|
# dir alongside the 'python' scripts dir which contains our
|
||||||
|
# binary Python modules. If we see that, add it to the path also.
|
||||||
|
# Not sure if we'd ever have a need to customize this path.
|
||||||
|
dylibdir = f'{app_python_dir}-dylib'
|
||||||
|
if os.path.exists(dylibdir):
|
||||||
|
ourpaths.append(dylibdir)
|
||||||
|
|
||||||
|
sys.path = ourpaths + oldpaths
|
||||||
|
|
||||||
|
return (
|
||||||
|
user_python_dir,
|
||||||
|
app_python_dir,
|
||||||
|
site_python_dir,
|
||||||
|
data_dir,
|
||||||
|
config_dir,
|
||||||
|
standard_app_python_dir,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _setup_dirs(config_dir: str | None, user_python_dir: str | None) -> None:
|
||||||
create_dirs: list[tuple[str, str | None]] = [
|
create_dirs: list[tuple[str, str | None]] = [
|
||||||
('config', config_dir),
|
('config', config_dir),
|
||||||
('user_python', user_python_dir),
|
('user_python', user_python_dir),
|
||||||
@ -201,32 +355,22 @@ def configure(
|
|||||||
try:
|
try:
|
||||||
os.makedirs(cdir, exist_ok=True)
|
os.makedirs(cdir, exist_ok=True)
|
||||||
except Exception:
|
except Exception:
|
||||||
|
# Not the end of the world if we can't make these dirs.
|
||||||
logging.warning(
|
logging.warning(
|
||||||
"Unable to create %s dir at '%s'.", cdirname, cdir
|
"Unable to create %s dir at '%s'.", cdirname, cdir
|
||||||
)
|
)
|
||||||
|
|
||||||
_g_env_config = EnvConfig(
|
|
||||||
config_dir=config_dir,
|
|
||||||
data_dir=data_dir,
|
|
||||||
user_python_dir=user_python_dir,
|
|
||||||
app_python_dir=app_python_dir,
|
|
||||||
standard_app_python_dir=standard_app_python_dir,
|
|
||||||
site_python_dir=site_python_dir,
|
|
||||||
log_handler=log_handler,
|
|
||||||
)
|
|
||||||
|
|
||||||
# In embedded situations (when we're providing our own Python) let's
|
def _main() -> None:
|
||||||
# also provide our own root certs so ssl works. We can consider
|
# Run a default configure BEFORE importing babase.
|
||||||
# overriding this in particular embedded cases if we can verify that
|
# (may affect where babase comes from).
|
||||||
# system certs are working. (We also allow forcing this via an env
|
configure()
|
||||||
# var if the user desires)
|
|
||||||
if (
|
|
||||||
contains_python_dist
|
|
||||||
or os.environ.get('BA_USE_BUNDLED_ROOT_CERTS') == '1'
|
|
||||||
):
|
|
||||||
import certifi
|
|
||||||
|
|
||||||
# Let both OpenSSL and requests (if present) know to use this.
|
import babase
|
||||||
os.environ['SSL_CERT_FILE'] = os.environ[
|
|
||||||
'REQUESTS_CA_BUNDLE'
|
babase.app.run()
|
||||||
] = certifi.where()
|
|
||||||
|
|
||||||
|
# Allow exec'ing this module directly to do a standard app run.
|
||||||
|
if __name__ == '__main__':
|
||||||
|
_main()
|
||||||
|
|||||||
@ -177,6 +177,11 @@ void BaseFeatureSet::StartApp() {
|
|||||||
|
|
||||||
LogVersionInfo();
|
LogVersionInfo();
|
||||||
|
|
||||||
|
// The logic thread (or maybe other things) need to run Python as
|
||||||
|
// we're bringing them up, so let it go for the duration of this call.
|
||||||
|
// We'll explicitly grab it if/when we need it.
|
||||||
|
Python::ScopedInterpreterLockRelease gil_release;
|
||||||
|
|
||||||
// Read in ba.app.config for anyone who wants to start looking at it
|
// Read in ba.app.config for anyone who wants to start looking at it
|
||||||
// (though we don't explicitly ask anyone to apply it until later).
|
// (though we don't explicitly ask anyone to apply it until later).
|
||||||
python->ReadConfig();
|
python->ReadConfig();
|
||||||
@ -280,6 +285,10 @@ void BaseFeatureSet::RunAppToCompletion() {
|
|||||||
StartApp();
|
StartApp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Let go of the GIL while we're running. The logic thread or other things
|
||||||
|
// will grab it when needed.
|
||||||
|
Python::ScopedInterpreterLockRelease gil_release;
|
||||||
|
|
||||||
// On our event-loop-managing platforms we now simply sit in our event
|
// On our event-loop-managing platforms we now simply sit in our event
|
||||||
// loop until the app is quit.
|
// loop until the app is quit.
|
||||||
g_core->main_event_loop()->RunEventLoop(false);
|
g_core->main_event_loop()->RunEventLoop(false);
|
||||||
@ -494,8 +503,13 @@ void BaseFeatureSet::DoV1CloudLog(const std::string& msg) {
|
|||||||
// We may attempt to import stuff and that should *never* happen before
|
// We may attempt to import stuff and that should *never* happen before
|
||||||
// base is fully imported.
|
// base is fully imported.
|
||||||
if (!IsBaseCompletelyImported()) {
|
if (!IsBaseCompletelyImported()) {
|
||||||
printf(
|
static bool warned = false;
|
||||||
"WARNING: V1CloudLog called before babase fully imported; ignoring.\n");
|
if (!warned) {
|
||||||
|
warned = true;
|
||||||
|
printf(
|
||||||
|
"WARNING: V1CloudLog called before babase fully imported; "
|
||||||
|
"ignoring.\n");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -523,7 +537,11 @@ void BaseFeatureSet::DoV1CloudLog(const std::string& msg) {
|
|||||||
|
|
||||||
// Need plus for direct sends.
|
// Need plus for direct sends.
|
||||||
if (!HavePlus()) {
|
if (!HavePlus()) {
|
||||||
printf("WARNING: V1CloudLog direct-sends not available; ignoring.\n");
|
static bool did_warn = false;
|
||||||
|
if (!did_warn) {
|
||||||
|
did_warn = true;
|
||||||
|
printf("WARNING: V1CloudLog direct-sends not available; ignoring.\n");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -49,8 +49,6 @@ static PyMethodDef PyAppNameDef = {
|
|||||||
static auto PyRunApp(PyObject* self) -> PyObject* {
|
static auto PyRunApp(PyObject* self) -> PyObject* {
|
||||||
BA_PYTHON_TRY;
|
BA_PYTHON_TRY;
|
||||||
|
|
||||||
FatalError("NOT WORKING YET; COME BACK SOON.");
|
|
||||||
|
|
||||||
assert(g_base);
|
assert(g_base);
|
||||||
g_base->RunAppToCompletion();
|
g_base->RunAppToCompletion();
|
||||||
|
|
||||||
|
|||||||
@ -97,7 +97,7 @@ void CoreFeatureSet::PostInit() {
|
|||||||
// FIXME: MOVE THIS TO A RUN_APP_TO_COMPLETION() SORT OF PLACE.
|
// FIXME: MOVE THIS TO A RUN_APP_TO_COMPLETION() SORT OF PLACE.
|
||||||
// For now it does the right thing here since all we have is monolithic
|
// For now it does the right thing here since all we have is monolithic
|
||||||
// builds but this will need to account for more situations later.
|
// builds but this will need to account for more situations later.
|
||||||
python->ReleaseMainThreadGIL();
|
// python->ReleaseMainThreadGIL();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CoreFeatureSet::CalcBuildSrcDir() -> std::string {
|
auto CoreFeatureSet::CalcBuildSrcDir() -> std::string {
|
||||||
|
|||||||
@ -202,14 +202,6 @@ void CorePython::ImportPythonObjs() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CorePython::ReleaseMainThreadGIL() {
|
|
||||||
assert(g_core->InMainThread());
|
|
||||||
// After we bootstrap Python here in the main thread we release the GIL.
|
|
||||||
// We'll explicitly reacquire it anytime we need it (mainly in the logic
|
|
||||||
// thread once that comes up later).
|
|
||||||
PyEval_SaveThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CorePython::SoftImportBase() {
|
void CorePython::SoftImportBase() {
|
||||||
auto gil{Python::ScopedInterpreterLock()};
|
auto gil{Python::ScopedInterpreterLock()};
|
||||||
auto result = PythonRef::StolenSoft(PyImport_ImportModule("_babase"));
|
auto result = PythonRef::StolenSoft(PyImport_ImportModule("_babase"));
|
||||||
@ -345,29 +337,4 @@ void CorePython::LoggingCall(LogLevel loglevel, const std::string& msg) {
|
|||||||
objs().Get(logcallobj).Call(args);
|
objs().Get(logcallobj).Call(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CorePython::AcquireGIL() {
|
|
||||||
assert(g_base_soft && g_base_soft->InLogicThread());
|
|
||||||
auto debug_timing{g_core->core_config().debug_timing};
|
|
||||||
millisecs_t startms{debug_timing ? CorePlatform::GetCurrentMillisecs() : 0};
|
|
||||||
|
|
||||||
if (logic_thread_state_) {
|
|
||||||
PyEval_RestoreThread(logic_thread_state_);
|
|
||||||
logic_thread_state_ = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (debug_timing) {
|
|
||||||
auto duration{CorePlatform::GetCurrentMillisecs() - startms};
|
|
||||||
if (duration > (1000 / 120)) {
|
|
||||||
Log(LogLevel::kInfo,
|
|
||||||
"GIL acquire took too long (" + std::to_string(duration) + " ms).");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CorePython::ReleaseGIL() {
|
|
||||||
assert(g_base_soft && g_base_soft->InLogicThread());
|
|
||||||
assert(logic_thread_state_ == nullptr);
|
|
||||||
logic_thread_state_ = PyEval_SaveThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ballistica::core
|
} // namespace ballistica::core
|
||||||
|
|||||||
@ -52,11 +52,8 @@ class CorePython {
|
|||||||
/// logging is available, logs locally using Logging::DisplayLog()
|
/// logging is available, logs locally using Logging::DisplayLog()
|
||||||
/// (with an added warning).
|
/// (with an added warning).
|
||||||
void LoggingCall(LogLevel loglevel, const std::string& msg);
|
void LoggingCall(LogLevel loglevel, const std::string& msg);
|
||||||
void AcquireGIL();
|
|
||||||
void ReleaseGIL();
|
|
||||||
void ImportPythonObjs();
|
void ImportPythonObjs();
|
||||||
void VerifyPythonEnvironment();
|
void VerifyPythonEnvironment();
|
||||||
void ReleaseMainThreadGIL();
|
|
||||||
void SoftImportBase();
|
void SoftImportBase();
|
||||||
|
|
||||||
const auto& objs() { return objs_; }
|
const auto& objs() { return objs_; }
|
||||||
@ -64,8 +61,6 @@ class CorePython {
|
|||||||
private:
|
private:
|
||||||
PythonObjectSet<ObjID> objs_;
|
PythonObjectSet<ObjID> objs_;
|
||||||
|
|
||||||
PyThreadState* logic_thread_state_{};
|
|
||||||
|
|
||||||
// Log calls we make before we're set up to ship logs through Python
|
// Log calls we make before we're set up to ship logs through Python
|
||||||
// go here. They all get shipped at once as soon as it is possible.
|
// go here. They all get shipped at once as soon as it is possible.
|
||||||
bool python_logging_calls_enabled_{};
|
bool python_logging_calls_enabled_{};
|
||||||
|
|||||||
@ -2,5 +2,5 @@
|
|||||||
|
|
||||||
Bits of the engine related to accounts and cloud functionality. In prefab builds
|
Bits of the engine related to accounts and cloud functionality. In prefab builds
|
||||||
the compiled code for this feature set is contained in the pre-compiled static
|
the compiled code for this feature set is contained in the pre-compiled static
|
||||||
ballistica_plus library. The plus feature set can also be removed from
|
ballisticaplus library. The plus feature set can also be removed from
|
||||||
spinoff projects if desired to remove the need for that library.
|
spinoff projects if desired to remove the need for that library.
|
||||||
|
|||||||
@ -385,16 +385,18 @@ void ConnectionToClient::HandleMessagePacket(
|
|||||||
|
|
||||||
case BA_MESSAGE_CLIENT_INFO: {
|
case BA_MESSAGE_CLIENT_INFO: {
|
||||||
if (buffer.size() > 1) {
|
if (buffer.size() > 1) {
|
||||||
|
// Make a null-terminated copy of the string data.
|
||||||
std::vector<char> str_buffer(buffer.size());
|
std::vector<char> str_buffer(buffer.size());
|
||||||
memcpy(&(str_buffer[0]), &(buffer[1]), buffer.size() - 1);
|
memcpy(str_buffer.data(), buffer.data() + 1, buffer.size() - 1);
|
||||||
str_buffer[str_buffer.size() - 1] = 0;
|
str_buffer[str_buffer.size() - 1] = 0;
|
||||||
cJSON* info = cJSON_Parse(reinterpret_cast<const char*>(&(buffer[1])));
|
|
||||||
|
cJSON* info = cJSON_Parse(str_buffer.data());
|
||||||
if (info) {
|
if (info) {
|
||||||
cJSON* b = cJSON_GetObjectItem(info, "b");
|
cJSON* b = cJSON_GetObjectItem(info, "b");
|
||||||
if (b) {
|
if (b) {
|
||||||
build_number_ = b->valueint;
|
build_number_ = b->valueint;
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError, "no buildnumber in clientinfo msg");
|
Log(LogLevel::kError, "No buildnumber in clientinfo msg.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grab their token (we use this to ask the
|
// Grab their token (we use this to ask the
|
||||||
@ -403,7 +405,7 @@ void ConnectionToClient::HandleMessagePacket(
|
|||||||
if (t) {
|
if (t) {
|
||||||
token_ = t->valuestring;
|
token_ = t->valuestring;
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError, "no token in clientinfo msg");
|
Log(LogLevel::kError, "No token in clientinfo msg.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Newer clients also pass a peer-hash, which
|
// Newer clients also pass a peer-hash, which
|
||||||
@ -423,9 +425,9 @@ void ConnectionToClient::HandleMessagePacket(
|
|||||||
cJSON_Delete(info);
|
cJSON_Delete(info);
|
||||||
} else {
|
} else {
|
||||||
Log(LogLevel::kError,
|
Log(LogLevel::kError,
|
||||||
"got invalid json in clientinfo message: '"
|
"Got invalid json in clientinfo message: '"
|
||||||
+ std::string(reinterpret_cast<const char*>(&(buffer[1])))
|
+ std::string(reinterpret_cast<const char*>(&(buffer[1])))
|
||||||
+ "'");
|
+ "'.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
got_client_info_ = true;
|
got_client_info_ = true;
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// If desired, define main() in the global namespace.
|
// If desired, define main() in the global namespace.
|
||||||
#if BA_DEFINE_MAIN
|
#if BA_MONOLITHIC_BUILD && BA_DEFINE_MAIN
|
||||||
auto main(int argc, char** argv) -> int {
|
auto main(int argc, char** argv) -> int {
|
||||||
auto core_config =
|
auto core_config =
|
||||||
ballistica::core::CoreConfig::FromCommandLineAndEnv(argc, argv);
|
ballistica::core::CoreConfig::FromCommandLineAndEnv(argc, argv);
|
||||||
@ -39,8 +39,10 @@ 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 = 21171;
|
const int kEngineBuildNumber = 21183;
|
||||||
const char* kEngineVersion = "1.7.23";
|
const char* kEngineVersion = "1.7.24";
|
||||||
|
|
||||||
|
#if BA_MONOLITHIC_BUILD
|
||||||
|
|
||||||
auto MonolithicMain(const core::CoreConfig& core_config) -> int {
|
auto MonolithicMain(const core::CoreConfig& core_config) -> int {
|
||||||
// This code is meant to be run standalone so won't inherit any
|
// This code is meant to be run standalone so won't inherit any
|
||||||
@ -171,6 +173,8 @@ auto MonolithicMain(const core::CoreConfig& core_config) -> int {
|
|||||||
return -1; // Didn't even get core; something clearly wrong.
|
return -1; // Didn't even get core; something clearly wrong.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // BA_MONOLITHIC_BUILD
|
||||||
|
|
||||||
void FatalError(const std::string& message) {
|
void FatalError(const std::string& message) {
|
||||||
// Let the user and/or master-server know we're dying.
|
// Let the user and/or master-server know we're dying.
|
||||||
FatalError::ReportFatalError(message, false);
|
FatalError::ReportFatalError(message, false);
|
||||||
|
|||||||
@ -104,8 +104,10 @@ class CoreConfig;
|
|||||||
// enough that avoiding the extra class includes seems like an overall
|
// enough that avoiding the extra class includes seems like an overall
|
||||||
// compile-time/convenience win.
|
// compile-time/convenience win.
|
||||||
|
|
||||||
|
#if BA_MONOLITHIC_BUILD
|
||||||
/// Entry point for standard monolithic builds. Handles all initing and running.
|
/// Entry point for standard monolithic builds. Handles all initing and running.
|
||||||
auto MonolithicMain(const core::CoreConfig& config) -> int;
|
auto MonolithicMain(const core::CoreConfig& config) -> int;
|
||||||
|
#endif // BA_MONOLITHIC_BUILD
|
||||||
|
|
||||||
// Print a momentary message on the screen.
|
// Print a momentary message on the screen.
|
||||||
void ScreenMessage(const std::string& msg);
|
void ScreenMessage(const std::string& msg);
|
||||||
|
|||||||
@ -64,7 +64,9 @@
|
|||||||
// Allow stdin commands too.
|
// Allow stdin commands too.
|
||||||
#define BA_ENABLE_STDIO_CONSOLE 1
|
#define BA_ENABLE_STDIO_CONSOLE 1
|
||||||
|
|
||||||
|
#ifndef BA_DEFINE_MAIN
|
||||||
#define BA_DEFINE_MAIN 1
|
#define BA_DEFINE_MAIN 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !BA_DEBUG_BUILD
|
#if !BA_DEBUG_BUILD
|
||||||
|
|
||||||
|
|||||||
@ -23,8 +23,10 @@ namespace ballistica {
|
|||||||
// can override any of these before this is included.
|
// can override any of these before this is included.
|
||||||
|
|
||||||
// Monolithic builds consist of a single binary that inits and manages
|
// Monolithic builds consist of a single binary that inits and manages
|
||||||
// Python itself, as opposed to modular builds which are made up of
|
// Python itself, as opposed to modular builds which are made up of Python
|
||||||
// Python binary modules which are run under a standard Python runtime.
|
// binary modules which are run under a standard Python runtime. This will
|
||||||
|
// be 0 for both modular (.so) builds of the engine as well as for static
|
||||||
|
// libraries such as baplus intended to be linked to either version.
|
||||||
#ifndef BA_MONOLITHIC_BUILD
|
#ifndef BA_MONOLITHIC_BUILD
|
||||||
#define BA_MONOLITHIC_BUILD 1
|
#define BA_MONOLITHIC_BUILD 1
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
#include "ballistica/core/support/base_soft.h"
|
#include "ballistica/core/support/base_soft.h"
|
||||||
#include "ballistica/shared/foundation/fatal_error.h"
|
#include "ballistica/shared/foundation/fatal_error.h"
|
||||||
#include "ballistica/shared/python/python.h"
|
#include "ballistica/shared/python/python.h"
|
||||||
|
#include "ballistica/shared/python/python_sys.h"
|
||||||
|
|
||||||
namespace ballistica {
|
namespace ballistica {
|
||||||
|
|
||||||
@ -224,7 +225,7 @@ void EventLoop::WaitForNextEvent(bool single_cycle) {
|
|||||||
|
|
||||||
// While we're waiting, allow other python threads to run.
|
// While we're waiting, allow other python threads to run.
|
||||||
if (acquires_python_gil_) {
|
if (acquires_python_gil_) {
|
||||||
g_core->python->ReleaseGIL();
|
ReleaseGIL();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we've got active timers, wait for messages with a timeout so we can
|
// If we've got active timers, wait for messages with a timeout so we can
|
||||||
@ -257,7 +258,7 @@ void EventLoop::WaitForNextEvent(bool single_cycle) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (acquires_python_gil_) {
|
if (acquires_python_gil_) {
|
||||||
g_core->python->AcquireGIL();
|
AcquireGIL();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -451,7 +452,7 @@ void EventLoop::SetAcquiresPythonGIL() {
|
|||||||
assert(!acquires_python_gil_); // This should be called exactly once.
|
assert(!acquires_python_gil_); // This should be called exactly once.
|
||||||
assert(ThreadIsCurrent());
|
assert(ThreadIsCurrent());
|
||||||
acquires_python_gil_ = true;
|
acquires_python_gil_ = true;
|
||||||
g_core->python->AcquireGIL();
|
AcquireGIL();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Explicitly kill the main thread.
|
// Explicitly kill the main thread.
|
||||||
@ -784,4 +785,30 @@ auto EventLoop::CheckPushRunnableSafety() -> bool {
|
|||||||
return thread_messages_.size() < kThreadMessageSafetyThreshold;
|
return thread_messages_.size() < kThreadMessageSafetyThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EventLoop::AcquireGIL() {
|
||||||
|
assert(g_base_soft && g_base_soft->InLogicThread());
|
||||||
|
auto debug_timing{g_core->core_config().debug_timing};
|
||||||
|
millisecs_t startms{debug_timing ? core::CorePlatform::GetCurrentMillisecs()
|
||||||
|
: 0};
|
||||||
|
|
||||||
|
if (py_thread_state_) {
|
||||||
|
PyEval_RestoreThread(py_thread_state_);
|
||||||
|
py_thread_state_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug_timing) {
|
||||||
|
auto duration{core::CorePlatform::GetCurrentMillisecs() - startms};
|
||||||
|
if (duration > (1000 / 120)) {
|
||||||
|
Log(LogLevel::kInfo,
|
||||||
|
"GIL acquire took too long (" + std::to_string(duration) + " ms).");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventLoop::ReleaseGIL() {
|
||||||
|
assert(g_base_soft && g_base_soft->InLogicThread());
|
||||||
|
assert(py_thread_state_ == nullptr);
|
||||||
|
py_thread_state_ = PyEval_SaveThread();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ballistica
|
} // namespace ballistica
|
||||||
|
|||||||
@ -164,6 +164,9 @@ class EventLoop {
|
|||||||
void RunPauseCallbacks();
|
void RunPauseCallbacks();
|
||||||
void RunResumeCallbacks();
|
void RunResumeCallbacks();
|
||||||
|
|
||||||
|
void AcquireGIL();
|
||||||
|
void ReleaseGIL();
|
||||||
|
|
||||||
bool bootstrapped_{};
|
bool bootstrapped_{};
|
||||||
std::list<std::pair<Runnable*, bool*>> runnables_;
|
std::list<std::pair<Runnable*, bool*>> runnables_;
|
||||||
std::list<Runnable*> pause_callbacks_;
|
std::list<Runnable*> pause_callbacks_;
|
||||||
@ -174,6 +177,7 @@ class EventLoop {
|
|||||||
std::condition_variable client_listener_cv_;
|
std::condition_variable client_listener_cv_;
|
||||||
std::mutex client_listener_mutex_;
|
std::mutex client_listener_mutex_;
|
||||||
std::list<std::vector<char>> data_to_client_;
|
std::list<std::vector<char>> data_to_client_;
|
||||||
|
PyThreadState* py_thread_state_{};
|
||||||
TimerList timers_;
|
TimerList timers_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -377,21 +377,16 @@ void Python::MarkReachedEndOfModule(PyObject* module) {
|
|||||||
class Python::ScopedInterpreterLock::Impl {
|
class Python::ScopedInterpreterLock::Impl {
|
||||||
public:
|
public:
|
||||||
Impl() {
|
Impl() {
|
||||||
if (need_lock_) {
|
// Grab the python GIL.
|
||||||
// Grab the python GIL.
|
gil_state_ = PyGILState_Ensure();
|
||||||
gstate_ = PyGILState_Ensure();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
~Impl() {
|
~Impl() {
|
||||||
if (need_lock_) {
|
// Release the python GIL.
|
||||||
// Release the python GIL.
|
PyGILState_Release(gil_state_);
|
||||||
PyGILState_Release(gstate_);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool need_lock_{true};
|
PyGILState_STATE gil_state_{PyGILState_UNLOCKED};
|
||||||
PyGILState_STATE gstate_{PyGILState_UNLOCKED};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Python::ScopedInterpreterLock::ScopedInterpreterLock()
|
Python::ScopedInterpreterLock::ScopedInterpreterLock()
|
||||||
@ -401,6 +396,31 @@ Python::ScopedInterpreterLock::ScopedInterpreterLock()
|
|||||||
|
|
||||||
Python::ScopedInterpreterLock::~ScopedInterpreterLock() { delete impl_; }
|
Python::ScopedInterpreterLock::~ScopedInterpreterLock() { delete impl_; }
|
||||||
|
|
||||||
|
class Python::ScopedInterpreterLockRelease::Impl {
|
||||||
|
public:
|
||||||
|
Impl() {
|
||||||
|
assert(HaveGIL());
|
||||||
|
// Release the GIL.
|
||||||
|
thread_state_ = PyEval_SaveThread();
|
||||||
|
}
|
||||||
|
~Impl() {
|
||||||
|
// Restore the GIL.
|
||||||
|
PyEval_RestoreThread(thread_state_);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
PyThreadState* thread_state_{};
|
||||||
|
};
|
||||||
|
|
||||||
|
Python::ScopedInterpreterLockRelease::ScopedInterpreterLockRelease()
|
||||||
|
: impl_{new Python::ScopedInterpreterLockRelease::Impl()}
|
||||||
|
// impl_{std::make_unique<Python::ScopedInterpreterLock::Impl>()}
|
||||||
|
{}
|
||||||
|
|
||||||
|
Python::ScopedInterpreterLockRelease::~ScopedInterpreterLockRelease() {
|
||||||
|
delete impl_;
|
||||||
|
}
|
||||||
|
|
||||||
// (some stuff borrowed from python's source code - used in our overriding of
|
// (some stuff borrowed from python's source code - used in our overriding of
|
||||||
// objects' dir() results)
|
// objects' dir() results)
|
||||||
|
|
||||||
|
|||||||
@ -39,9 +39,9 @@ class Python {
|
|||||||
BA_DISALLOW_CLASS_COPIES(ScopedCallLabel);
|
BA_DISALLOW_CLASS_COPIES(ScopedCallLabel);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Use this to protect Python code that may be run in cases where we don't
|
/// Use this to protect Python code that may be run in cases where we
|
||||||
/// hold the Global Interpreter Lock (GIL) (basically anything outside of the
|
/// don't hold the Global Interpreter Lock (GIL). (Basically anything
|
||||||
/// logic thread).
|
/// outside of the logic thread).
|
||||||
class ScopedInterpreterLock {
|
class ScopedInterpreterLock {
|
||||||
public:
|
public:
|
||||||
ScopedInterpreterLock();
|
ScopedInterpreterLock();
|
||||||
@ -55,7 +55,20 @@ class Python {
|
|||||||
Impl* impl_{};
|
Impl* impl_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
// static auto Create() -> Python*;
|
/// Use this for cases where we *do* hold the GIL but want to release
|
||||||
|
/// it for some operation.
|
||||||
|
class ScopedInterpreterLockRelease {
|
||||||
|
public:
|
||||||
|
ScopedInterpreterLockRelease();
|
||||||
|
~ScopedInterpreterLockRelease();
|
||||||
|
|
||||||
|
private:
|
||||||
|
class Impl;
|
||||||
|
// Note: should use unique_ptr for this, but build fails on raspberry pi
|
||||||
|
// (gcc 8.3.0). Works on Ubuntu 9.3 so should try again later.
|
||||||
|
// std::unique_ptr<Impl> impl_{};
|
||||||
|
Impl* impl_{};
|
||||||
|
};
|
||||||
|
|
||||||
/// Return whether the current thread holds the global-interpreter-lock.
|
/// Return whether the current thread holds the global-interpreter-lock.
|
||||||
/// We must always hold the GIL while running python code.
|
/// We must always hold the GIL while running python code.
|
||||||
|
|||||||
6
src/external/readlinktest.c
vendored
Normal file
6
src/external/readlinktest.c
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
printf("HELLO WORLD!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@ -16,26 +16,38 @@ from efrotools import PYVER
|
|||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Suffix for the pyc files we include in stagings.
|
# Suffix for the pyc files we include in stagings. We're using
|
||||||
# We're using deterministic opt pyc files; see PEP 552.
|
# deterministic opt pyc files; see PEP 552.
|
||||||
# Note: this means anyone wanting to modify .py files in a build
|
#
|
||||||
# will need to wipe out the existing .pyc files first or the changes
|
# Note: this means anyone
|
||||||
# will be ignored.
|
# wanting to modify .py files in a build will need to wipe out the
|
||||||
|
# existing .pyc files first or the changes will be ignored.
|
||||||
OPT_PYC_SUFFIX = 'cpython-' + PYVER.replace('.', '') + '.opt-1.pyc'
|
OPT_PYC_SUFFIX = 'cpython-' + PYVER.replace('.', '') + '.opt-1.pyc'
|
||||||
|
|
||||||
|
|
||||||
class Config:
|
def stage_assets(projroot: str, args: list[str] | None = None) -> None:
|
||||||
"""Encapsulates command options."""
|
"""Stage assets for a build."""
|
||||||
|
|
||||||
|
if args is None:
|
||||||
|
args = sys.argv
|
||||||
|
|
||||||
|
AssetStager(projroot).run(args)
|
||||||
|
|
||||||
|
|
||||||
|
class AssetStager:
|
||||||
|
"""Context for a run of the tool."""
|
||||||
|
|
||||||
def __init__(self, projroot: str) -> None:
|
def __init__(self, projroot: str) -> None:
|
||||||
self.projroot = projroot
|
self.projroot = projroot
|
||||||
# We always calc src relative to this script.
|
# We always calc src relative to this script.
|
||||||
self.src = self.projroot + '/build/assets'
|
self.src = f'{self.projroot}/build/assets'
|
||||||
self.dst: str | None = None
|
self.dst: str | None = None
|
||||||
self.serverdst: str | None = None
|
self.serverdst: str | None = None
|
||||||
self.win_extras_src: str | None = None
|
self.win_extras_src: str | None = None
|
||||||
self.win_platform: str | None = None
|
self.win_platform: str | None = None
|
||||||
self.win_type: str | None = None
|
self.win_type: str | None = None
|
||||||
|
self.include_python_dylib = False
|
||||||
|
self.include_shell_launcher = False
|
||||||
self.include_audio = True
|
self.include_audio = True
|
||||||
self.include_meshes = True
|
self.include_meshes = True
|
||||||
self.include_collision_meshes = True
|
self.include_collision_meshes = True
|
||||||
@ -51,11 +63,105 @@ class Config:
|
|||||||
self.is_payload_full = False
|
self.is_payload_full = False
|
||||||
self.debug: bool | None = None
|
self.debug: bool | None = None
|
||||||
|
|
||||||
|
def run(self, args: list[str]) -> None:
|
||||||
|
"""Do the thing."""
|
||||||
|
self._parse_args(args)
|
||||||
|
|
||||||
|
# Ok, now for every top level dir in src, come up with a nice single
|
||||||
|
# command to sync the needed subset of it to dst.
|
||||||
|
|
||||||
|
# We can now use simple speedy timestamp based updates since we no
|
||||||
|
# longer have to try to preserve timestamps to get .pyc files to
|
||||||
|
# behave (hooray!)
|
||||||
|
|
||||||
|
# Do our stripped down pylib dir for platforms that use that.
|
||||||
|
if self.include_pylib:
|
||||||
|
self._sync_pylib()
|
||||||
|
else:
|
||||||
|
if self.dst is not None and os.path.isdir(f'{self.dst}/pylib'):
|
||||||
|
subprocess.run(['rm', '-rf', f'{self.dst}/pylib'], check=True)
|
||||||
|
|
||||||
|
# Sync our server files if we're doing that.
|
||||||
|
if self.serverdst is not None:
|
||||||
|
self._sync_server_files()
|
||||||
|
|
||||||
|
# On windows we need to pull in some dlls and this and that (we also
|
||||||
|
# include a non-stripped-down set of Python libs).
|
||||||
|
if self.win_extras_src is not None:
|
||||||
|
self._sync_windows_extras()
|
||||||
|
|
||||||
|
# Standard stuff in ba_data.
|
||||||
|
self._sync_ba_data()
|
||||||
|
|
||||||
|
# On Android we need to build a payload file so it knows what to
|
||||||
|
# pull out of the apk.
|
||||||
|
if self.include_payload_file:
|
||||||
|
assert self.dst is not None
|
||||||
|
_write_payload_file(self.dst, self.is_payload_full)
|
||||||
|
|
||||||
|
def _parse_args(self, args: list[str]) -> None:
|
||||||
|
"""Parse args and apply to ourself."""
|
||||||
|
if len(args) < 1:
|
||||||
|
raise RuntimeError('Expected at least one argument.')
|
||||||
|
platform_arg = args[0]
|
||||||
|
|
||||||
|
# Require either -debug or -release in args.
|
||||||
|
if '-debug' in args:
|
||||||
|
self.debug = True
|
||||||
|
assert '-release' not in args
|
||||||
|
elif '-release' in args:
|
||||||
|
self.debug = False
|
||||||
|
else:
|
||||||
|
raise RuntimeError(
|
||||||
|
"Expected either '-debug' or '-release' in args."
|
||||||
|
)
|
||||||
|
|
||||||
|
if platform_arg == '-android':
|
||||||
|
self._parse_android_args(args)
|
||||||
|
elif platform_arg.startswith('-win'):
|
||||||
|
self._parse_win_args(platform_arg, args)
|
||||||
|
elif platform_arg == '-cmake':
|
||||||
|
self.dst = args[-1]
|
||||||
|
self.tex_suffix = '.dds'
|
||||||
|
elif platform_arg == '-cmakemodular':
|
||||||
|
self.dst = args[-1]
|
||||||
|
self.tex_suffix = '.dds'
|
||||||
|
self.include_python_dylib = True
|
||||||
|
self.include_shell_launcher = True
|
||||||
|
elif platform_arg == '-cmakeserver':
|
||||||
|
self.dst = os.path.join(args[-1], 'dist')
|
||||||
|
self.serverdst = args[-1]
|
||||||
|
self.include_textures = False
|
||||||
|
self.include_audio = False
|
||||||
|
self.include_meshes = False
|
||||||
|
|
||||||
|
elif platform_arg == '-xcode-mac':
|
||||||
|
self.src = os.environ['SOURCE_ROOT'] + '/build/assets'
|
||||||
|
self.dst = (
|
||||||
|
os.environ['TARGET_BUILD_DIR']
|
||||||
|
+ '/'
|
||||||
|
+ os.environ['UNLOCALIZED_RESOURCES_FOLDER_PATH']
|
||||||
|
)
|
||||||
|
self.include_pylib = True
|
||||||
|
self.pylib_src_name = 'pylib-apple'
|
||||||
|
self.tex_suffix = '.dds'
|
||||||
|
elif platform_arg == '-xcode-ios':
|
||||||
|
self.src = os.environ['SOURCE_ROOT'] + '/build/assets'
|
||||||
|
self.dst = (
|
||||||
|
os.environ['TARGET_BUILD_DIR']
|
||||||
|
+ '/'
|
||||||
|
+ os.environ['UNLOCALIZED_RESOURCES_FOLDER_PATH']
|
||||||
|
)
|
||||||
|
self.include_pylib = True
|
||||||
|
self.pylib_src_name = 'pylib-apple'
|
||||||
|
self.tex_suffix = '.pvr'
|
||||||
|
else:
|
||||||
|
raise RuntimeError('No valid platform arg provided.')
|
||||||
|
|
||||||
def _parse_android_args(self, args: list[str]) -> None:
|
def _parse_android_args(self, args: list[str]) -> None:
|
||||||
# On Android we get nitpicky with what
|
# On Android we get nitpicky with exactly what we want to copy
|
||||||
# we want to copy in since we can speed up
|
# in since we can speed up iterations by installing stripped
|
||||||
# iterations by installing stripped down
|
# down apks.
|
||||||
# apks.
|
|
||||||
self.dst = 'assets/ballistica_files'
|
self.dst = 'assets/ballistica_files'
|
||||||
self.pylib_src_name = 'pylib-android'
|
self.pylib_src_name = 'pylib-android'
|
||||||
self.include_payload_file = True
|
self.include_payload_file = True
|
||||||
@ -98,9 +204,9 @@ class Config:
|
|||||||
elif arg == '-audio':
|
elif arg == '-audio':
|
||||||
self.include_audio = True
|
self.include_audio = True
|
||||||
|
|
||||||
def _parse_win_platform(self, platform: str, args: list[str]) -> None:
|
def _parse_win_args(self, platform: str, args: list[str]) -> None:
|
||||||
"""Parse sub-args in the windows platform string."""
|
"""Parse sub-args in the windows platform string."""
|
||||||
winempty, wintype, winplt, wincfg = platform.split('-')
|
winempty, wintype, winplt = platform.split('-')
|
||||||
self.win_platform = winplt
|
self.win_platform = winplt
|
||||||
self.win_type = wintype
|
self.win_type = wintype
|
||||||
assert winempty == ''
|
assert winempty == ''
|
||||||
@ -115,78 +221,375 @@ class Config:
|
|||||||
self.include_audio = False
|
self.include_audio = False
|
||||||
self.include_meshes = False
|
self.include_meshes = False
|
||||||
else:
|
else:
|
||||||
raise RuntimeError(f'Invalid wintype: "{wintype}"')
|
raise RuntimeError(f"Invalid wintype: '{wintype}'.")
|
||||||
|
|
||||||
if winplt == 'Win32':
|
if winplt == 'Win32':
|
||||||
self.win_extras_src = self.projroot + '/build/assets/windows/Win32'
|
self.win_extras_src = f'{self.projroot}/build/assets/windows/Win32'
|
||||||
elif winplt == 'x64':
|
elif winplt == 'x64':
|
||||||
self.win_extras_src = self.projroot + '/build/assets/windows/x64'
|
self.win_extras_src = f'{self.projroot}/build/assets/windows/x64'
|
||||||
else:
|
else:
|
||||||
raise RuntimeError(f'Invalid winplt: "{winplt}"')
|
raise RuntimeError(f"Invalid winplt: '{winplt}'.")
|
||||||
|
|
||||||
if wincfg == 'Debug':
|
def _sync_windows_extras(self) -> None:
|
||||||
self.debug = True
|
# pylint: disable=too-many-branches
|
||||||
elif wincfg == 'Release':
|
assert self.win_extras_src is not None
|
||||||
self.debug = False
|
assert self.win_platform is not None
|
||||||
|
assert self.win_type is not None
|
||||||
|
if not os.path.isdir(self.win_extras_src):
|
||||||
|
raise RuntimeError(
|
||||||
|
f"Win extras src dir not found: '{self.win_extras_src}'."
|
||||||
|
)
|
||||||
|
|
||||||
|
# Ok, lets do full syncs on each subdir we find so we properly
|
||||||
|
# delete anything in dst that disappeared from src. Lastly we'll
|
||||||
|
# sync over the remaining top level files. Note: technically it'll
|
||||||
|
# be possible to leave orphaned top level files in dst, so when
|
||||||
|
# building packages/etc. we should always start from scratch.
|
||||||
|
assert self.dst is not None
|
||||||
|
assert self.debug is not None
|
||||||
|
pyd_rules: list[str]
|
||||||
|
if self.debug:
|
||||||
|
pyd_rules = ['--include', '*_d.pyd']
|
||||||
else:
|
else:
|
||||||
raise RuntimeError(f'Invalid wincfg: "{wincfg}"')
|
pyd_rules = ['--exclude', '*_d.pyd', '--include', '*.pyd']
|
||||||
|
|
||||||
def parse_args(self, args: list[str]) -> None:
|
for dirname in ('DLLs', 'Lib'):
|
||||||
"""Parse args and apply to the cfg."""
|
# EWW: seems Windows Python currently sets its path to ./lib but
|
||||||
if len(args) < 1:
|
# it comes with Lib. Windows is normally case-insensitive but
|
||||||
raise RuntimeError('Expected a platform argument.')
|
# this messes it up when running under WSL. Let's install it as
|
||||||
platform = args[0]
|
# lib for now.
|
||||||
if platform == '-android':
|
dstdirname = 'lib' if dirname == 'Lib' else dirname
|
||||||
self._parse_android_args(args)
|
os.makedirs(f'{self.dst}/{dstdirname}', exist_ok=True)
|
||||||
elif platform.startswith('-win'):
|
cmd: list[str] = (
|
||||||
self._parse_win_platform(platform, args)
|
[
|
||||||
elif platform == '-cmake':
|
'rsync',
|
||||||
self.dst = args[1]
|
'--recursive',
|
||||||
self.tex_suffix = '.dds'
|
'--times',
|
||||||
elif '-cmakeserver' in args:
|
'--delete',
|
||||||
self.dst = os.path.join(args[-1], 'dist')
|
'--delete-excluded',
|
||||||
self.serverdst = args[-1]
|
'--prune-empty-dirs',
|
||||||
self.include_textures = False
|
'--include',
|
||||||
self.include_audio = False
|
'*.ico',
|
||||||
self.include_meshes = False
|
'--include',
|
||||||
|
'*.cat',
|
||||||
|
'--include',
|
||||||
|
'*.dll',
|
||||||
|
]
|
||||||
|
+ pyd_rules
|
||||||
|
+ [
|
||||||
|
'--include',
|
||||||
|
'*.py',
|
||||||
|
'--include',
|
||||||
|
f'*.{OPT_PYC_SUFFIX}',
|
||||||
|
'--include',
|
||||||
|
'*/',
|
||||||
|
'--exclude',
|
||||||
|
'*',
|
||||||
|
f'{os.path.join(self.win_extras_src, dirname)}/',
|
||||||
|
f'{self.dst}/{dstdirname}/',
|
||||||
|
]
|
||||||
|
)
|
||||||
|
subprocess.run(cmd, check=True)
|
||||||
|
|
||||||
# Require either -debug or -release in args.
|
# Now sync the top level individual files that we want. We could
|
||||||
# FIXME: should require this for all platforms for consistency.
|
# technically copy everything over but this keeps staging dirs a bit
|
||||||
if '-debug' in args:
|
# tidier.
|
||||||
self.debug = True
|
dbgsfx = '_d' if self.debug else ''
|
||||||
assert '-release' not in args
|
|
||||||
elif '-release' in args:
|
# Note: Needs updating when Python version changes (currently 3.11).
|
||||||
self.debug = False
|
toplevelfiles: list[str] = [f'python311{dbgsfx}.dll']
|
||||||
|
|
||||||
|
if self.win_type == 'win':
|
||||||
|
toplevelfiles += [
|
||||||
|
'libvorbis.dll',
|
||||||
|
'libvorbisfile.dll',
|
||||||
|
'ogg.dll',
|
||||||
|
'OpenAL32.dll',
|
||||||
|
'SDL2.dll',
|
||||||
|
]
|
||||||
|
elif self.win_type == 'winserver':
|
||||||
|
toplevelfiles += [f'python{dbgsfx}.exe']
|
||||||
|
|
||||||
|
# Include debug dlls so folks without msvc can run them.
|
||||||
|
if self.debug:
|
||||||
|
if self.win_platform == 'x64':
|
||||||
|
toplevelfiles += [
|
||||||
|
'msvcp140d.dll',
|
||||||
|
'vcruntime140d.dll',
|
||||||
|
'vcruntime140_1d.dll',
|
||||||
|
'ucrtbased.dll',
|
||||||
|
]
|
||||||
else:
|
else:
|
||||||
raise RuntimeError(
|
toplevelfiles += [
|
||||||
"Expected either '-debug' or '-release' in args."
|
'msvcp140d.dll',
|
||||||
)
|
'vcruntime140d.dll',
|
||||||
elif '-xcode-mac' in args:
|
'ucrtbased.dll',
|
||||||
self.src = os.environ['SOURCE_ROOT'] + '/build/assets'
|
]
|
||||||
self.dst = (
|
|
||||||
os.environ['TARGET_BUILD_DIR']
|
# Include the runtime redistributables in release builds.
|
||||||
+ '/'
|
if not self.debug:
|
||||||
+ os.environ['UNLOCALIZED_RESOURCES_FOLDER_PATH']
|
if self.win_platform == 'x64':
|
||||||
)
|
toplevelfiles.append('vc_redist.x64.exe')
|
||||||
self.include_pylib = True
|
elif self.win_platform == 'Win32':
|
||||||
self.pylib_src_name = 'pylib-apple'
|
toplevelfiles.append('vc_redist.x86.exe')
|
||||||
self.tex_suffix = '.dds'
|
else:
|
||||||
elif '-xcode-ios' in args:
|
raise RuntimeError(f'Invalid win_platform {self.win_platform}')
|
||||||
self.src = os.environ['SOURCE_ROOT'] + '/build/assets'
|
|
||||||
self.dst = (
|
cmd2 = (
|
||||||
os.environ['TARGET_BUILD_DIR']
|
['rsync', '--times']
|
||||||
+ '/'
|
+ [os.path.join(self.win_extras_src, f) for f in toplevelfiles]
|
||||||
+ os.environ['UNLOCALIZED_RESOURCES_FOLDER_PATH']
|
+ [f'{self.dst}/']
|
||||||
)
|
)
|
||||||
self.include_pylib = True
|
subprocess.run(cmd2, check=True)
|
||||||
self.pylib_src_name = 'pylib-apple'
|
|
||||||
self.tex_suffix = '.pvr'
|
# If we're running under WSL we won't be able to launch these .exe
|
||||||
|
# files unless they're marked executable, so do that here. Update:
|
||||||
|
# gonna try simply setting this flag on the source side.
|
||||||
|
# _run(f'chmod +x {self.dst}/*.exe')
|
||||||
|
|
||||||
|
def _sync_pylib(self) -> None:
|
||||||
|
assert self.pylib_src_name is not None
|
||||||
|
assert self.dst is not None
|
||||||
|
os.makedirs(f'{self.dst}/pylib', exist_ok=True)
|
||||||
|
cmd: list[str] = [
|
||||||
|
'rsync',
|
||||||
|
'--recursive',
|
||||||
|
'--times',
|
||||||
|
'--delete',
|
||||||
|
'--delete-excluded',
|
||||||
|
'--prune-empty-dirs',
|
||||||
|
'--include',
|
||||||
|
'*.py',
|
||||||
|
'--include',
|
||||||
|
f'*.{OPT_PYC_SUFFIX}',
|
||||||
|
'--include',
|
||||||
|
'*/',
|
||||||
|
'--exclude',
|
||||||
|
'*',
|
||||||
|
f'{self.src}/{self.pylib_src_name}/',
|
||||||
|
f'{self.dst}/pylib/',
|
||||||
|
]
|
||||||
|
subprocess.run(cmd, check=True)
|
||||||
|
|
||||||
|
def _sync_ba_data(self) -> None:
|
||||||
|
assert self.dst is not None
|
||||||
|
os.makedirs(f'{self.dst}/ba_data', exist_ok=True)
|
||||||
|
cmd: list[str] = [
|
||||||
|
'rsync',
|
||||||
|
'--recursive',
|
||||||
|
'--times',
|
||||||
|
'--delete',
|
||||||
|
'--prune-empty-dirs',
|
||||||
|
]
|
||||||
|
|
||||||
|
# Normally we use --delete-excluded so that we can do sparse
|
||||||
|
# syncs for quick iteration on android apks/etc. However for our
|
||||||
|
# modular builds we need to avoid that flag because we do a
|
||||||
|
# second pass after to sync in our python-dylib stuff and with
|
||||||
|
# that flag it all gets blown on the first pass.
|
||||||
|
if not self.include_python_dylib:
|
||||||
|
cmd.append('--delete-excluded')
|
||||||
else:
|
else:
|
||||||
raise RuntimeError('No valid platform arg provided.')
|
# Shouldn't be trying to do sparse stuff.
|
||||||
|
assert (
|
||||||
|
self.include_textures
|
||||||
|
and self.include_audio
|
||||||
|
and self.include_fonts
|
||||||
|
and self.include_json
|
||||||
|
and self.include_meshes
|
||||||
|
and self.include_collision_meshes
|
||||||
|
)
|
||||||
|
# Keep rsync from trying to prune this as an 'empty' dir.
|
||||||
|
cmd += ['--exclude', '/python-dylib']
|
||||||
|
|
||||||
|
if self.include_scripts:
|
||||||
|
cmd += [
|
||||||
|
'--include',
|
||||||
|
'*.py',
|
||||||
|
'--include',
|
||||||
|
'*.pem',
|
||||||
|
'--include',
|
||||||
|
f'*.{OPT_PYC_SUFFIX}',
|
||||||
|
]
|
||||||
|
|
||||||
|
if self.include_textures:
|
||||||
|
assert self.tex_suffix is not None
|
||||||
|
cmd += ['--include', f'*{self.tex_suffix}']
|
||||||
|
|
||||||
|
if self.include_audio:
|
||||||
|
cmd += ['--include', '*.ogg']
|
||||||
|
|
||||||
|
if self.include_fonts:
|
||||||
|
cmd += ['--include', '*.fdata']
|
||||||
|
|
||||||
|
if self.include_json:
|
||||||
|
cmd += ['--include', '*.json']
|
||||||
|
|
||||||
|
if self.include_meshes:
|
||||||
|
cmd += ['--include', '*.bob']
|
||||||
|
|
||||||
|
if self.include_collision_meshes:
|
||||||
|
cmd += ['--include', '*.cob']
|
||||||
|
|
||||||
|
# By default we want to include all dirs and exclude all files.
|
||||||
|
cmd += [
|
||||||
|
'--include',
|
||||||
|
'*/',
|
||||||
|
'--exclude',
|
||||||
|
'*',
|
||||||
|
f'{self.src}/ba_data/',
|
||||||
|
f'{self.dst}/ba_data/',
|
||||||
|
]
|
||||||
|
subprocess.run(cmd, check=True)
|
||||||
|
|
||||||
|
if self.include_python_dylib:
|
||||||
|
self._sync_python_dylib()
|
||||||
|
|
||||||
|
if self.include_shell_launcher:
|
||||||
|
self._sync_shell_launcher()
|
||||||
|
|
||||||
|
def _sync_shell_launcher(self) -> None:
|
||||||
|
path = f'{self.dst}/ballisticakit'
|
||||||
|
|
||||||
|
# For now this is so simple we just do an ad-hoc write each time;
|
||||||
|
# not worth setting up files and syncs.
|
||||||
|
if self.debug:
|
||||||
|
optstuff = 'export PYTHONDEVMODE=1\nexport PYTHONOPTIMIZE=0\n'
|
||||||
|
else:
|
||||||
|
optstuff = 'export PYTHONDEVMODE=0\nexport PYTHONOPTIMIZE=1\n'
|
||||||
|
|
||||||
|
optnm = 'DEBUG' if self.debug else 'RELEASE'
|
||||||
|
with open(path, 'w', encoding='utf-8') as outfile:
|
||||||
|
outfile.write(
|
||||||
|
'#!/bin/sh\n'
|
||||||
|
'\n'
|
||||||
|
'# We should error if anything here errors.\n'
|
||||||
|
'set -e\n'
|
||||||
|
'\n'
|
||||||
|
'# We want Python to use UTF-8 everywhere for consistency.\n'
|
||||||
|
'# (This will be the default in the future; see PEP 686).\n'
|
||||||
|
f'export PYTHONUTF8=1\n'
|
||||||
|
'\n'
|
||||||
|
f'# This is a Ballistica {optnm} build; set Python to match.\n'
|
||||||
|
f'{optstuff}'
|
||||||
|
'\n'
|
||||||
|
'# Run the app, forwarding along all arguments.\n'
|
||||||
|
'# Basically this does:\n'
|
||||||
|
'# import baenv; baenv.configure();'
|
||||||
|
' import babase; babase.app.run().\n'
|
||||||
|
'python3.11 ba_data/python/baenv.py $@\n'
|
||||||
|
)
|
||||||
|
subprocess.run(['chmod', '+x', path], check=True)
|
||||||
|
|
||||||
|
def _sync_python_dylib(self) -> None:
|
||||||
|
# pylint: disable=too-many-locals
|
||||||
|
from batools.featureset import FeatureSet
|
||||||
|
|
||||||
|
# Note: we're technically not *syncing* quite so much as
|
||||||
|
# *constructing* here.
|
||||||
|
|
||||||
|
dylib_staging_dir = f'{self.dst}/ba_data/python-dylib'
|
||||||
|
|
||||||
|
# Name of our single shared library containing all our stuff.
|
||||||
|
soname = 'ballisticakit.so'
|
||||||
|
|
||||||
|
# All featuresets in the project with binary modules.
|
||||||
|
bmodfeaturesets = {
|
||||||
|
f.name: f
|
||||||
|
for f in FeatureSet.get_all_for_project(self.projroot)
|
||||||
|
if f.has_python_binary_module
|
||||||
|
}
|
||||||
|
|
||||||
|
# Map of featureset names (foo) to module filenames (_foo.so).
|
||||||
|
fsetmfilenames = {
|
||||||
|
f.name: f'{f.name_python_binary_module}.so'
|
||||||
|
for f in bmodfeaturesets.values()
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set of all module filenames (_foo.so, etc.) we should have.
|
||||||
|
fsetmfilenamevals = set(fsetmfilenames.values())
|
||||||
|
|
||||||
|
if not os.path.exists(dylib_staging_dir):
|
||||||
|
os.makedirs(dylib_staging_dir, exist_ok=True)
|
||||||
|
|
||||||
|
# Create a symlink to our original built so. NOTE: Anyone
|
||||||
|
# building final app packages/etc. should replace this with the
|
||||||
|
# actual file. This is just for development.
|
||||||
|
|
||||||
|
# FIXME - currently assuming our built .so lives one dir above
|
||||||
|
# our staging dir; should not be making that assumption.
|
||||||
|
built_so_path = f'{self.dst}/../{soname}'
|
||||||
|
staged_so_path = f'{dylib_staging_dir}/{soname}'
|
||||||
|
|
||||||
|
if not os.path.islink(staged_so_path):
|
||||||
|
relpath = os.path.relpath(built_so_path, dylib_staging_dir)
|
||||||
|
subprocess.run(['ln', '-sf', relpath, staged_so_path], check=True)
|
||||||
|
|
||||||
|
# Ok, now we want to create symlinks for each of our featureset
|
||||||
|
# Python modules. All of our stuff lives in the same .so and we
|
||||||
|
# can use symlinks to help Python find them all there. See the
|
||||||
|
# following:
|
||||||
|
# https://peps.python.org/pep-0489/#multiple-modules-in-one-library
|
||||||
|
for fsetname, featureset in bmodfeaturesets.items():
|
||||||
|
if featureset.has_python_binary_module:
|
||||||
|
mfilename = fsetmfilenames[fsetname]
|
||||||
|
instpath = f'{dylib_staging_dir}/{mfilename}'
|
||||||
|
if not os.path.islink(instpath):
|
||||||
|
subprocess.run(['ln', '-sf', soname, instpath], check=True)
|
||||||
|
|
||||||
|
# Lastly, blow away anything in that dir that's not something we
|
||||||
|
# just made (clears out featuresets that get renamed or
|
||||||
|
# disabled, etc).
|
||||||
|
fnames = os.listdir(dylib_staging_dir)
|
||||||
|
for fname in fnames:
|
||||||
|
if not fname in fsetmfilenamevals and fname != soname:
|
||||||
|
fpath = f'{dylib_staging_dir}/{fname}'
|
||||||
|
print(f"Pruning orphaned dylib path: '{fpath}'.")
|
||||||
|
subprocess.run(['rm', '-rf', fpath], check=True)
|
||||||
|
|
||||||
|
def _sync_server_files(self) -> None:
|
||||||
|
assert self.serverdst is not None
|
||||||
|
assert self.debug is not None
|
||||||
|
modeval = 'debug' if self.debug else 'release'
|
||||||
|
|
||||||
|
# NOTE: staging these directly from src; not build.
|
||||||
|
_stage_server_file(
|
||||||
|
projroot=self.projroot,
|
||||||
|
mode=modeval,
|
||||||
|
infilename=f'{self.projroot}/src/assets/server_package/'
|
||||||
|
'ballisticakit_server.py',
|
||||||
|
outfilename=os.path.join(
|
||||||
|
self.serverdst,
|
||||||
|
'ballisticakit_server.py'
|
||||||
|
if self.win_type is not None
|
||||||
|
else 'ballisticakit_server',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
_stage_server_file(
|
||||||
|
projroot=self.projroot,
|
||||||
|
mode=modeval,
|
||||||
|
infilename=f'{self.projroot}/src/assets/server_package/README.txt',
|
||||||
|
outfilename=os.path.join(self.serverdst, 'README.txt'),
|
||||||
|
)
|
||||||
|
_stage_server_file(
|
||||||
|
projroot=self.projroot,
|
||||||
|
mode=modeval,
|
||||||
|
infilename=f'{self.projroot}/src/assets/server_package/'
|
||||||
|
'config_template.yaml',
|
||||||
|
outfilename=os.path.join(self.serverdst, 'config_template.yaml'),
|
||||||
|
)
|
||||||
|
if self.win_type is not None:
|
||||||
|
fname = 'launch_ballisticakit_server.bat'
|
||||||
|
_stage_server_file(
|
||||||
|
projroot=self.projroot,
|
||||||
|
mode=modeval,
|
||||||
|
infilename=f'{self.projroot}/src/assets/server_package/{fname}',
|
||||||
|
outfilename=os.path.join(self.serverdst, fname),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def md5sum(filename: str) -> str:
|
def _filehash(filename: str) -> str:
|
||||||
"""Generate an md5sum given a filename."""
|
"""Generate a hash for a file."""
|
||||||
md5 = hashlib.md5()
|
md5 = hashlib.md5()
|
||||||
with open(filename, mode='rb') as infile:
|
with open(filename, mode='rb') as infile:
|
||||||
for buf in iter(partial(infile.read, 1024), b''):
|
for buf in iter(partial(infile.read, 1024), b''):
|
||||||
@ -194,18 +597,9 @@ def md5sum(filename: str) -> str:
|
|||||||
return md5.hexdigest()
|
return md5.hexdigest()
|
||||||
|
|
||||||
|
|
||||||
def _run(cmd: str, echo: bool = False) -> None:
|
|
||||||
"""Run an os command; raise Exception on non-zero return value."""
|
|
||||||
if echo:
|
|
||||||
print(cmd)
|
|
||||||
result = os.system(cmd)
|
|
||||||
if result != 0:
|
|
||||||
raise RuntimeError(f"Error running cmd: '{cmd}'.")
|
|
||||||
|
|
||||||
|
|
||||||
def _write_payload_file(assets_root: str, full: bool) -> None:
|
def _write_payload_file(assets_root: str, full: bool) -> None:
|
||||||
if not assets_root.endswith('/'):
|
if not assets_root.endswith('/'):
|
||||||
assets_root = assets_root + '/'
|
assets_root = f'{assets_root}/'
|
||||||
|
|
||||||
# Now construct a payload file if we have any files.
|
# Now construct a payload file if we have any files.
|
||||||
file_list = []
|
file_list = []
|
||||||
@ -222,226 +616,24 @@ def _write_payload_file(assets_root: str, full: bool) -> None:
|
|||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
f"Invalid filename (contains spaces): '{fpathshort}'"
|
f"Invalid filename (contains spaces): '{fpathshort}'"
|
||||||
)
|
)
|
||||||
payload_str += fpathshort + ' ' + md5sum(fpath) + '\n'
|
payload_str += f'{fpathshort} {_filehash(fpath)}\n'
|
||||||
file_list.append(fpathshort)
|
file_list.append(fpathshort)
|
||||||
|
|
||||||
payload_path = assets_root + '/payload_info'
|
payload_path = f'{assets_root}/payload_info'
|
||||||
if file_list:
|
if file_list:
|
||||||
# Write the file count, whether this is a 'full' payload, and finally
|
# Write the file count, whether this is a 'full' payload, and
|
||||||
# the file list.
|
# finally the file list.
|
||||||
payload_str = (
|
fullstr = '1' if full else '0'
|
||||||
str(len(file_list))
|
payload_str = f'{len(file_list)}\n{fullstr}\n{payload_str}'
|
||||||
+ '\n'
|
|
||||||
+ ('1' if full else '0')
|
|
||||||
+ '\n'
|
|
||||||
+ payload_str
|
|
||||||
)
|
|
||||||
with open(payload_path, 'w', encoding='utf-8') as outfile:
|
with open(payload_path, 'w', encoding='utf-8') as outfile:
|
||||||
outfile.write(payload_str)
|
outfile.write(payload_str)
|
||||||
else:
|
else:
|
||||||
# Remove the payload file; this will cause the game to completely
|
# Remove the payload file; this will cause the game to
|
||||||
# skip the payload processing step.
|
# completely skip the payload processing step.
|
||||||
if os.path.exists(payload_path):
|
if os.path.exists(payload_path):
|
||||||
os.unlink(payload_path)
|
os.unlink(payload_path)
|
||||||
|
|
||||||
|
|
||||||
def _sync_windows_extras(cfg: Config) -> None:
|
|
||||||
# pylint: disable=too-many-branches
|
|
||||||
assert cfg.win_extras_src is not None
|
|
||||||
assert cfg.win_platform is not None
|
|
||||||
assert cfg.win_type is not None
|
|
||||||
if not os.path.isdir(cfg.win_extras_src):
|
|
||||||
raise RuntimeError(
|
|
||||||
"Win extras src dir not found: '{cfg.win_extras_src}'."
|
|
||||||
)
|
|
||||||
|
|
||||||
# Ok, lets do full syncs on each subdir we find so we
|
|
||||||
# properly delete anything in dst that disappeared from src.
|
|
||||||
# Lastly we'll sync over the remaining top level files.
|
|
||||||
# Note: technically it'll be possible to leave orphaned top level
|
|
||||||
# files in dst, so when building packages/etc. we should always start
|
|
||||||
# from scratch.
|
|
||||||
assert cfg.dst is not None
|
|
||||||
assert cfg.debug is not None
|
|
||||||
if cfg.debug:
|
|
||||||
pyd_rules = "--include '*_d.pyd'"
|
|
||||||
else:
|
|
||||||
pyd_rules = "--exclude '*_d.pyd' --include '*.pyd'"
|
|
||||||
|
|
||||||
for dirname in ('DLLs', 'Lib'):
|
|
||||||
# EWW: seems windows python currently sets its path to ./lib but it
|
|
||||||
# comes with Lib. Windows is normally case-insensitive but this messes
|
|
||||||
# it up when running under WSL. Let's install it as lib for now.
|
|
||||||
dstdirname = 'lib' if dirname == 'Lib' else dirname
|
|
||||||
_run(f'mkdir -p "{cfg.dst}/{dstdirname}"')
|
|
||||||
cmd = (
|
|
||||||
'rsync --recursive --update --delete --delete-excluded '
|
|
||||||
' --prune-empty-dirs'
|
|
||||||
" --include '*.ico' --include '*.cat'"
|
|
||||||
f" --include '*.dll' {pyd_rules}"
|
|
||||||
" --include '*.py' --include '*." + OPT_PYC_SUFFIX + "'"
|
|
||||||
" --include '*/' --exclude '*' \""
|
|
||||||
+ os.path.join(cfg.win_extras_src, dirname)
|
|
||||||
+ '/" '
|
|
||||||
'"' + cfg.dst + '/' + dstdirname + '/"'
|
|
||||||
)
|
|
||||||
_run(cmd)
|
|
||||||
|
|
||||||
# Now sync the top level individual files that we want.
|
|
||||||
# We could technically copy everything over but this keeps staging
|
|
||||||
# dirs a bit tidier.
|
|
||||||
dbgsfx = '_d' if cfg.debug else ''
|
|
||||||
# Note: Below needs updating when Python version changes (currently 3.11)
|
|
||||||
toplevelfiles: list[str] = [f'python311{dbgsfx}.dll']
|
|
||||||
|
|
||||||
if cfg.win_type == 'win':
|
|
||||||
toplevelfiles += [
|
|
||||||
'libvorbis.dll',
|
|
||||||
'libvorbisfile.dll',
|
|
||||||
'ogg.dll',
|
|
||||||
'OpenAL32.dll',
|
|
||||||
'SDL2.dll',
|
|
||||||
]
|
|
||||||
elif cfg.win_type == 'winserver':
|
|
||||||
toplevelfiles += [f'python{dbgsfx}.exe']
|
|
||||||
|
|
||||||
# Include debug dlls so folks without msvc can run them.
|
|
||||||
if cfg.debug:
|
|
||||||
if cfg.win_platform == 'x64':
|
|
||||||
toplevelfiles += [
|
|
||||||
'msvcp140d.dll',
|
|
||||||
'vcruntime140d.dll',
|
|
||||||
'vcruntime140_1d.dll',
|
|
||||||
'ucrtbased.dll',
|
|
||||||
]
|
|
||||||
else:
|
|
||||||
toplevelfiles += [
|
|
||||||
'msvcp140d.dll',
|
|
||||||
'vcruntime140d.dll',
|
|
||||||
'ucrtbased.dll',
|
|
||||||
]
|
|
||||||
|
|
||||||
# Include the runtime redistributables in release builds.
|
|
||||||
if not cfg.debug:
|
|
||||||
if cfg.win_platform == 'x64':
|
|
||||||
toplevelfiles.append('vc_redist.x64.exe')
|
|
||||||
elif cfg.win_platform == 'Win32':
|
|
||||||
toplevelfiles.append('vc_redist.x86.exe')
|
|
||||||
else:
|
|
||||||
raise RuntimeError(f'Invalid win_platform {cfg.win_platform}')
|
|
||||||
|
|
||||||
cmd2 = (
|
|
||||||
['rsync', '--update']
|
|
||||||
+ [os.path.join(cfg.win_extras_src, f) for f in toplevelfiles]
|
|
||||||
+ [cfg.dst + '/']
|
|
||||||
)
|
|
||||||
subprocess.run(cmd2, check=True)
|
|
||||||
|
|
||||||
# If we're running under WSL we won't be able to launch these .exe files
|
|
||||||
# unless they're marked executable, so do that here.
|
|
||||||
# Update: gonna try simply setting this flag on the source side.
|
|
||||||
# _run(f'chmod +x {cfg.dst}/*.exe')
|
|
||||||
|
|
||||||
|
|
||||||
def _sync_pylib(cfg: Config) -> None:
|
|
||||||
assert cfg.pylib_src_name is not None
|
|
||||||
assert cfg.dst is not None
|
|
||||||
_run(f'mkdir -p "{cfg.dst}/pylib"')
|
|
||||||
cmd = (
|
|
||||||
f'rsync --recursive --update --delete --delete-excluded '
|
|
||||||
f' --prune-empty-dirs'
|
|
||||||
f" --include '*.py' --include '*.{OPT_PYC_SUFFIX}'"
|
|
||||||
f" --include '*/' --exclude '*'"
|
|
||||||
f' "{cfg.src}/{cfg.pylib_src_name}/" '
|
|
||||||
f'"{cfg.dst}/pylib/"'
|
|
||||||
)
|
|
||||||
_run(cmd)
|
|
||||||
|
|
||||||
|
|
||||||
def _sync_standard_game_data(cfg: Config) -> None:
|
|
||||||
assert cfg.dst is not None
|
|
||||||
_run('mkdir -p "' + cfg.dst + '/ba_data"')
|
|
||||||
cmd = (
|
|
||||||
'rsync --recursive --update --delete --delete-excluded'
|
|
||||||
' --prune-empty-dirs'
|
|
||||||
)
|
|
||||||
|
|
||||||
if cfg.include_scripts:
|
|
||||||
cmd += (
|
|
||||||
f" --include '*.py' --include '*.pem'"
|
|
||||||
f" --include '*.{OPT_PYC_SUFFIX}'"
|
|
||||||
)
|
|
||||||
|
|
||||||
if cfg.include_textures:
|
|
||||||
assert cfg.tex_suffix is not None
|
|
||||||
cmd += " --include '*" + cfg.tex_suffix + "'"
|
|
||||||
|
|
||||||
if cfg.include_audio:
|
|
||||||
cmd += " --include '*.ogg'"
|
|
||||||
|
|
||||||
if cfg.include_fonts:
|
|
||||||
cmd += " --include '*.fdata'"
|
|
||||||
|
|
||||||
if cfg.include_json:
|
|
||||||
cmd += " --include '*.json'"
|
|
||||||
|
|
||||||
if cfg.include_meshes:
|
|
||||||
cmd += " --include '*.bob'"
|
|
||||||
|
|
||||||
if cfg.include_collision_meshes:
|
|
||||||
cmd += " --include '*.cob'"
|
|
||||||
|
|
||||||
cmd += (
|
|
||||||
" --include='*/' --exclude='*' \""
|
|
||||||
+ cfg.src
|
|
||||||
+ '/ba_data/" "'
|
|
||||||
+ cfg.dst
|
|
||||||
+ '/ba_data/"'
|
|
||||||
)
|
|
||||||
_run(cmd)
|
|
||||||
|
|
||||||
|
|
||||||
def _sync_server_files(cfg: Config) -> None:
|
|
||||||
assert cfg.serverdst is not None
|
|
||||||
assert cfg.debug is not None
|
|
||||||
modeval = 'debug' if cfg.debug else 'release'
|
|
||||||
|
|
||||||
# NOTE: staging these directly from src; not build.
|
|
||||||
stage_server_file(
|
|
||||||
projroot=cfg.projroot,
|
|
||||||
mode=modeval,
|
|
||||||
infilename=f'{cfg.projroot}/src/assets/server_package/'
|
|
||||||
'ballisticakit_server.py',
|
|
||||||
outfilename=os.path.join(
|
|
||||||
cfg.serverdst,
|
|
||||||
'ballisticakit_server.py'
|
|
||||||
if cfg.win_type is not None
|
|
||||||
else 'ballisticakit_server',
|
|
||||||
),
|
|
||||||
)
|
|
||||||
stage_server_file(
|
|
||||||
projroot=cfg.projroot,
|
|
||||||
mode=modeval,
|
|
||||||
infilename=f'{cfg.projroot}/src/assets/server_package/README.txt',
|
|
||||||
outfilename=os.path.join(cfg.serverdst, 'README.txt'),
|
|
||||||
)
|
|
||||||
stage_server_file(
|
|
||||||
projroot=cfg.projroot,
|
|
||||||
mode=modeval,
|
|
||||||
infilename=f'{cfg.projroot}/src/assets/server_package/'
|
|
||||||
'config_template.yaml',
|
|
||||||
outfilename=os.path.join(cfg.serverdst, 'config_template.yaml'),
|
|
||||||
)
|
|
||||||
if cfg.win_type is not None:
|
|
||||||
fname = 'launch_ballisticakit_server.bat'
|
|
||||||
stage_server_file(
|
|
||||||
projroot=cfg.projroot,
|
|
||||||
mode=modeval,
|
|
||||||
infilename=f'{cfg.projroot}/src/assets/server_package/{fname}',
|
|
||||||
outfilename=os.path.join(cfg.serverdst, fname),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _write_if_changed(
|
def _write_if_changed(
|
||||||
path: str, contents: str, make_executable: bool = False
|
path: str, contents: str, make_executable: bool = False
|
||||||
) -> None:
|
) -> None:
|
||||||
@ -459,7 +651,7 @@ def _write_if_changed(
|
|||||||
subprocess.run(['chmod', '+x', path], check=True)
|
subprocess.run(['chmod', '+x', path], check=True)
|
||||||
|
|
||||||
|
|
||||||
def stage_server_file(
|
def _stage_server_file(
|
||||||
projroot: str, mode: str, infilename: str, outfilename: str
|
projroot: str, mode: str, infilename: str, outfilename: str
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Stage files for the server environment with some filtering."""
|
"""Stage files for the server environment with some filtering."""
|
||||||
@ -528,45 +720,3 @@ def stage_server_file(
|
|||||||
_write_if_changed(outfilename, '\n'.join(lines) + '\n')
|
_write_if_changed(outfilename, '\n'.join(lines) + '\n')
|
||||||
else:
|
else:
|
||||||
raise RuntimeError(f"Unknown server file for staging: '{basename}'.")
|
raise RuntimeError(f"Unknown server file for staging: '{basename}'.")
|
||||||
|
|
||||||
|
|
||||||
def main(projroot: str, args: list[str] | None = None) -> None:
|
|
||||||
"""Stage assets for a build."""
|
|
||||||
|
|
||||||
if args is None:
|
|
||||||
args = sys.argv
|
|
||||||
|
|
||||||
cfg = Config(projroot)
|
|
||||||
cfg.parse_args(args)
|
|
||||||
|
|
||||||
# Ok, now for every top level dir in src, come up with a nice single
|
|
||||||
# command to sync the needed subset of it to dst.
|
|
||||||
|
|
||||||
# We can now use simple speedy timestamp based updates since
|
|
||||||
# we no longer have to try to preserve timestamps to get .pyc files
|
|
||||||
# to behave (hooray!)
|
|
||||||
|
|
||||||
# Do our stripped down pylib dir for platforms that use that.
|
|
||||||
if cfg.include_pylib:
|
|
||||||
_sync_pylib(cfg)
|
|
||||||
else:
|
|
||||||
if cfg.dst is not None and os.path.isdir(cfg.dst + '/pylib'):
|
|
||||||
subprocess.run(['rm', '-rf', cfg.dst + '/pylib'], check=True)
|
|
||||||
|
|
||||||
# Sync our server files if we're doing that.
|
|
||||||
if cfg.serverdst is not None:
|
|
||||||
_sync_server_files(cfg)
|
|
||||||
|
|
||||||
# On windows we need to pull in some dlls and this and that
|
|
||||||
# (we also include a non-stripped-down set of python libs).
|
|
||||||
if cfg.win_extras_src is not None:
|
|
||||||
_sync_windows_extras(cfg)
|
|
||||||
|
|
||||||
# Standard stuff in ba_data
|
|
||||||
_sync_standard_game_data(cfg)
|
|
||||||
|
|
||||||
# On Android we need to build a payload file so it knows
|
|
||||||
# what to pull out of the apk.
|
|
||||||
if cfg.include_payload_file:
|
|
||||||
assert cfg.dst is not None
|
|
||||||
_write_payload_file(cfg.dst, cfg.is_payload_full)
|
|
||||||
|
|||||||
@ -937,7 +937,7 @@ def generate_dummy_modules(projroot: str) -> None:
|
|||||||
|
|
||||||
# Generate a dummy module for each featureset that has a binary module.
|
# Generate a dummy module for each featureset that has a binary module.
|
||||||
featuresets = FeatureSet.get_all_for_project(project_root=projroot)
|
featuresets = FeatureSet.get_all_for_project(project_root=projroot)
|
||||||
featuresets = [f for f in featuresets if f.has_native_python_module]
|
featuresets = [f for f in featuresets if f.has_python_binary_module]
|
||||||
mnames: list[str] = [fs.name_python_binary_module for fs in featuresets]
|
mnames: list[str] = [fs.name_python_binary_module for fs in featuresets]
|
||||||
|
|
||||||
builddir = 'build/dummymodules'
|
builddir = 'build/dummymodules'
|
||||||
|
|||||||
@ -54,7 +54,7 @@ class FeatureSet:
|
|||||||
# its C++ code. The build process will try to create dummy
|
# its C++ code. The build process will try to create dummy
|
||||||
# modules for all native modules, so to avoid errors you must
|
# modules for all native modules, so to avoid errors you must
|
||||||
# tell it if you don't have one.
|
# tell it if you don't have one.
|
||||||
self.has_native_python_module = True
|
self.has_python_binary_module = True
|
||||||
|
|
||||||
# If True, for feature-set 'foo_bar', the build system will
|
# If True, for feature-set 'foo_bar', the build system will
|
||||||
# define a 'babase.app.foo_bar' attr which points to a lazy
|
# define a 'babase.app.foo_bar' attr which points to a lazy
|
||||||
|
|||||||
@ -806,11 +806,13 @@ def efro_gradle() -> None:
|
|||||||
|
|
||||||
def stage_assets() -> None:
|
def stage_assets() -> None:
|
||||||
"""Stage assets for a build."""
|
"""Stage assets for a build."""
|
||||||
from batools.assetstaging import main
|
import batools.assetstaging
|
||||||
from efro.error import CleanError
|
from efro.error import CleanError
|
||||||
|
|
||||||
try:
|
try:
|
||||||
main(projroot=str(PROJROOT), args=sys.argv[2:])
|
batools.assetstaging.stage_assets(
|
||||||
|
projroot=str(PROJROOT), args=sys.argv[2:]
|
||||||
|
)
|
||||||
except CleanError as exc:
|
except CleanError as exc:
|
||||||
exc.pretty_print()
|
exc.pretty_print()
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|||||||
@ -25,16 +25,48 @@ def gen_monolithic_register_modules() -> None:
|
|||||||
featuresets = FeatureSet.get_all_for_project(str(PROJROOT))
|
featuresets = FeatureSet.get_all_for_project(str(PROJROOT))
|
||||||
|
|
||||||
# Filter out ones without native modules.
|
# Filter out ones without native modules.
|
||||||
featuresets = [f for f in featuresets if f.has_native_python_module]
|
featuresets = [f for f in featuresets if f.has_python_binary_module]
|
||||||
|
|
||||||
pymodulenames = sorted(f.name_python_binary_module for f in featuresets)
|
pymodulenames = sorted(f.name_python_binary_module for f in featuresets)
|
||||||
|
|
||||||
|
def initname(mname: str) -> str:
|
||||||
|
# plus is a special case since we need to define that symbol
|
||||||
|
# ourself.
|
||||||
|
return f'DoPyInit_{mname}' if mname == '_baplus' else f'PyInit_{mname}'
|
||||||
|
|
||||||
extern_def_code = '\n'.join(
|
extern_def_code = '\n'.join(
|
||||||
f'auto PyInit_{n}() -> PyObject*;' for n in pymodulenames
|
f'auto {initname(n)}() -> PyObject*;' for n in pymodulenames
|
||||||
)
|
)
|
||||||
|
|
||||||
py_register_code = '\n'.join(
|
py_register_code = '\n'.join(
|
||||||
f'PyImport_AppendInittab("{n}", &PyInit_{n});' for n in pymodulenames
|
f'PyImport_AppendInittab("{n}", &{initname(n)});' for n in pymodulenames
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if '_baplus' in pymodulenames:
|
||||||
|
init_plus_code = (
|
||||||
|
'\n'
|
||||||
|
'// Slight hack: because we are currently building baplus as a'
|
||||||
|
' static module\n'
|
||||||
|
'// and linking it in, symbols exported there (namely'
|
||||||
|
' PyInit__baplus) do not\n'
|
||||||
|
'// seem to be available through us when we are compiled as'
|
||||||
|
' a dynamic\n'
|
||||||
|
'// library. This leads to Python being unable to load baplus.'
|
||||||
|
' While I\'m sure\n'
|
||||||
|
'// there is some way to get those symbols exported, I\'m worried'
|
||||||
|
' it might be\n'
|
||||||
|
'// a messy platform-specific affair. So instead we\'re just'
|
||||||
|
' defining that\n'
|
||||||
|
'// function here when baplus is present and forwarding it through'
|
||||||
|
' to the\n'
|
||||||
|
'// static library version.\n'
|
||||||
|
'extern "C" auto PyInit__baplus() -> PyObject* {\n'
|
||||||
|
' return DoPyInit__baplus();\n'
|
||||||
|
'}\n'
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
init_plus_code = ''
|
||||||
|
|
||||||
base_code = """
|
base_code = """
|
||||||
// Released under the MIT License. See LICENSE for details.
|
// Released under the MIT License. See LICENSE for details.
|
||||||
|
|
||||||
@ -43,13 +75,12 @@ def gen_monolithic_register_modules() -> None:
|
|||||||
|
|
||||||
// THIS CODE IS AUTOGENERATED BY META BUILD; DO NOT EDIT BY HAND.
|
// THIS CODE IS AUTOGENERATED BY META BUILD; DO NOT EDIT BY HAND.
|
||||||
|
|
||||||
|
#include "ballistica/shared/ballistica.h"
|
||||||
#include "ballistica/shared/python/python_sys.h"
|
#include "ballistica/shared/python/python_sys.h"
|
||||||
|
|
||||||
#if BA_MONOLITHIC_BUILD
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
${EXTERN_DEF_CODE}
|
${EXTERN_DEF_CODE}
|
||||||
}
|
}
|
||||||
#endif // BA_MONOLITHIC_BUILD
|
|
||||||
|
|
||||||
namespace ballistica {
|
namespace ballistica {
|
||||||
|
|
||||||
@ -58,15 +89,15 @@ def gen_monolithic_register_modules() -> None:
|
|||||||
/// binary modules get located as .so files on disk as per regular
|
/// binary modules get located as .so files on disk as per regular
|
||||||
/// Python behavior.
|
/// Python behavior.
|
||||||
void MonolithicRegisterPythonModules() {
|
void MonolithicRegisterPythonModules() {
|
||||||
#if BA_MONOLITHIC_BUILD
|
if (g_buildconfig.monolithic_build()) {
|
||||||
${PY_REGISTER_CODE}
|
${PY_REGISTER_CODE}
|
||||||
#else
|
} else {
|
||||||
FatalError(
|
FatalError(
|
||||||
"MonolithicRegisterPythonModules should not be called"
|
"MonolithicRegisterPythonModules should not be called"
|
||||||
" in modular builds.");
|
" in modular builds.");
|
||||||
#endif // BA_MONOLITHIC_BUILD
|
}
|
||||||
}
|
}
|
||||||
|
${PY_INIT_PLUS}
|
||||||
} // namespace ballistica
|
} // namespace ballistica
|
||||||
|
|
||||||
#endif // BALLISTICA_CORE_MGEN_PYTHON_MODULES_MONOLITHIC_H_
|
#endif // BALLISTICA_CORE_MGEN_PYTHON_MODULES_MONOLITHIC_H_
|
||||||
@ -74,7 +105,10 @@ def gen_monolithic_register_modules() -> None:
|
|||||||
out = (
|
out = (
|
||||||
textwrap.dedent(base_code)
|
textwrap.dedent(base_code)
|
||||||
.replace('${EXTERN_DEF_CODE}', extern_def_code)
|
.replace('${EXTERN_DEF_CODE}', extern_def_code)
|
||||||
.replace('${PY_REGISTER_CODE}', textwrap.indent(py_register_code, ' '))
|
.replace(
|
||||||
|
'${PY_REGISTER_CODE}', textwrap.indent(py_register_code, ' ')
|
||||||
|
)
|
||||||
|
.replace('${PY_INIT_PLUS}', init_plus_code)
|
||||||
.strip()
|
.strip()
|
||||||
+ '\n'
|
+ '\n'
|
||||||
)
|
)
|
||||||
@ -84,19 +118,6 @@ def gen_monolithic_register_modules() -> None:
|
|||||||
outfile.write(out)
|
outfile.write(out)
|
||||||
|
|
||||||
|
|
||||||
def stage_server_file() -> None:
|
|
||||||
"""Stage files for the server environment with some filtering."""
|
|
||||||
from efro.error import CleanError
|
|
||||||
import batools.assetstaging
|
|
||||||
|
|
||||||
if len(sys.argv) != 5:
|
|
||||||
raise CleanError('Expected 3 args (mode, infile, outfile).')
|
|
||||||
mode, infilename, outfilename = sys.argv[2], sys.argv[3], sys.argv[4]
|
|
||||||
batools.assetstaging.stage_server_file(
|
|
||||||
str(PROJROOT), mode, infilename, outfilename
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def py_examine() -> None:
|
def py_examine() -> None:
|
||||||
"""Run a python examination at a given point in a given file."""
|
"""Run a python examination at a given point in a given file."""
|
||||||
import os
|
import os
|
||||||
@ -244,7 +265,7 @@ def update_cmake_prefab_lib() -> None:
|
|||||||
)
|
)
|
||||||
suffix = '_server' if buildtype == 'server' else '_gui'
|
suffix = '_server' if buildtype == 'server' else '_gui'
|
||||||
target = (
|
target = (
|
||||||
f'build/prefab/lib/{platform}{suffix}/{mode}/' f'libballistica_plus.a'
|
f'build/prefab/lib/{platform}{suffix}/{mode}/' f'libballisticaplus.a'
|
||||||
)
|
)
|
||||||
|
|
||||||
# Build the target and then copy it to dst if it doesn't exist there yet
|
# Build the target and then copy it to dst if it doesn't exist there yet
|
||||||
@ -252,7 +273,7 @@ def update_cmake_prefab_lib() -> None:
|
|||||||
subprocess.run(['make', target], check=True)
|
subprocess.run(['make', target], check=True)
|
||||||
|
|
||||||
libdir = os.path.join(builddir, 'prefablib')
|
libdir = os.path.join(builddir, 'prefablib')
|
||||||
libpath = os.path.join(libdir, 'libballistica_plus.a')
|
libpath = os.path.join(libdir, 'libballisticaplus.a')
|
||||||
|
|
||||||
update = True
|
update = True
|
||||||
time1 = os.path.getmtime(target)
|
time1 = os.path.getmtime(target)
|
||||||
|
|||||||
@ -788,7 +788,7 @@ class SpinoffContext:
|
|||||||
# Strip precompiled plus library out of the cmake file.
|
# Strip precompiled plus library out of the cmake file.
|
||||||
text = replace_exact(
|
text = replace_exact(
|
||||||
text,
|
text,
|
||||||
'${CMAKE_CURRENT_BINARY_DIR}/prefablib/libballistica_plus.a'
|
'${CMAKE_CURRENT_BINARY_DIR}/prefablib/libballisticaplus.a'
|
||||||
' ode ',
|
' ode ',
|
||||||
'ode ',
|
'ode ',
|
||||||
label=src_path,
|
label=src_path,
|
||||||
|
|||||||
@ -714,42 +714,77 @@ def _patch_py_wreadlink_test() -> None:
|
|||||||
fname = 'Python/fileutils.c'
|
fname = 'Python/fileutils.c'
|
||||||
txt = readfile(fname)
|
txt = readfile(fname)
|
||||||
|
|
||||||
|
# Final fix for this problem.
|
||||||
|
# It seems that readlink() might be broken in android at the moment,
|
||||||
|
# returning an int while claiming it to be a ssize_t value. This makes
|
||||||
|
# the error case (-1) actually come out as 4294967295. When cast back
|
||||||
|
# to an int it is -1, so that's what we do. This should be fine to do
|
||||||
|
# even on a fixed version.
|
||||||
txt = replace_exact(
|
txt = replace_exact(
|
||||||
txt,
|
txt,
|
||||||
' res = readlink(cpath, cbuf, cbuf_len);\n',
|
' res = readlink(cpath, cbuf, cbuf_len);\n',
|
||||||
(
|
' res = (int)readlink(cpath, cbuf, cbuf_len);\n',
|
||||||
' res = readlink(cpath, cbuf, cbuf_len);\n'
|
|
||||||
' const wchar_t *path2 = path;\n'
|
|
||||||
' int path2len = 0;\n'
|
|
||||||
' while (*path2) {\n'
|
|
||||||
' path2++;\n'
|
|
||||||
' path2len++;\n'
|
|
||||||
' }\n'
|
|
||||||
' char dlog1[512];\n'
|
|
||||||
' if (res >= 0) {\n'
|
|
||||||
' snprintf(dlog1, sizeof(dlog1), "ValsA1 pathlen=%d slen=%d'
|
|
||||||
' path=\'%s\'", path2len, strlen(cpath), cpath);\n'
|
|
||||||
' } else {\n'
|
|
||||||
' snprintf(dlog1, sizeof(dlog1), "ValsA2 pathlen=%d",'
|
|
||||||
' path2len);\n'
|
|
||||||
' }\n'
|
|
||||||
' Py_BallisticaLowLevelDebugLog(dlog1);\n'
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
txt = replace_exact(
|
# Verbose problem exploration:
|
||||||
txt,
|
# txt = replace_exact(
|
||||||
" cbuf[res] = '\\0'; /* buf will be null terminated */",
|
# txt,
|
||||||
(
|
# '#include <stdlib.h> // mbstowcs()\n',
|
||||||
' char dlog[512];\n'
|
# '#include <stdlib.h> // mbstowcs()\n'
|
||||||
' snprintf(dlog, sizeof(dlog), "ValsB res=%d resx=%X'
|
# '#include <sys/syscall.h>\n',
|
||||||
' eq1=%d eq2=%d",'
|
# )
|
||||||
' (int)res, res, (int)(res == -1),'
|
|
||||||
' (int)((size_t)res == cbuf_len));\n'
|
# txt = replace_exact(txt, ' Py_ssize_t res;\n', '')
|
||||||
' Py_BallisticaLowLevelDebugLog(dlog);\n'
|
|
||||||
" cbuf[res] = '\\0'; /* buf will be null terminated */"
|
# txt = replace_exact(
|
||||||
),
|
# txt,
|
||||||
)
|
# ' res = readlink(cpath, cbuf, cbuf_len);\n',
|
||||||
|
# (
|
||||||
|
# ' Py_ssize_t res = readlink(cpath, cbuf, cbuf_len);\n'
|
||||||
|
# ' Py_ssize_t res2 = readlink(cpath, cbuf, cbuf_len);\n'
|
||||||
|
# ' ssize_t res3 = readlink(cpath, cbuf, cbuf_len);\n'
|
||||||
|
# ' ssize_t res4 = readlinkat(AT_FDCWD, cpath,
|
||||||
|
# cbuf, cbuf_len);\n'
|
||||||
|
# ' int res5 = syscall(SYS_readlinkat, AT_FDCWD, cpath,'
|
||||||
|
# ' cbuf, cbuf_len);\n'
|
||||||
|
# ' ssize_t res6 = syscall(SYS_readlinkat, AT_FDCWD, cpath,'
|
||||||
|
# ' cbuf, cbuf_len);\n'
|
||||||
|
# ' char dlog[512];\n'
|
||||||
|
# ' snprintf(dlog, sizeof(dlog),'
|
||||||
|
# ' "res=%zd res2=%zd res3=%zd res4=%zd res5=%d res6=%zd"\n'
|
||||||
|
# ' " (res == -1)=%d (res2 == -1)=%d (res3 == -1)=%d'
|
||||||
|
# ' (res4 == -1)=%d (res5 == -1)=%d (res6 == -1)=%d",\n'
|
||||||
|
# ' res, res2, res3, res4, res5, res6,\n'
|
||||||
|
# ' (res == -1), (res2 == -1), (res3 == -1),'
|
||||||
|
# ' (res4 == -1), (res5 == -1), (res6 == -1));\n'
|
||||||
|
# ' Py_BallisticaLowLevelDebugLog(dlog);\n'
|
||||||
|
# '\n'
|
||||||
|
# ' char dlog1[512];\n'
|
||||||
|
# ' ssize_t st1;\n'
|
||||||
|
# ' Py_ssize_t st2;\n'
|
||||||
|
# ' snprintf(dlog1, sizeof(dlog1),
|
||||||
|
# "ValsA1 sz1=%zu sz2=%zu res=%zd'
|
||||||
|
# ' res_hex=%lX res_cmp=%d res_cmp_2=%d pathlen=%d slen=%d'
|
||||||
|
# ' path=\'%s\'", sizeof(st1), sizeof(st2), res,'
|
||||||
|
# ' res, (int)(res == -1), (int)((int)res == -1),'
|
||||||
|
# ' (int)wcslen(path), (int)strlen(cpath), cpath);\n'
|
||||||
|
# ' Py_BallisticaLowLevelDebugLog(dlog1);\n'
|
||||||
|
# ),
|
||||||
|
# )
|
||||||
|
|
||||||
|
# txt = replace_exact(
|
||||||
|
# txt,
|
||||||
|
# " cbuf[res] = '\\0'; /* buf will be null terminated */",
|
||||||
|
# (
|
||||||
|
# ' char dlog[512];\n'
|
||||||
|
# ' snprintf(dlog, sizeof(dlog), "ValsB res=%d resx=%lX'
|
||||||
|
# ' eq1=%d eq2=%d",'
|
||||||
|
# ' (int)res, res, (int)(res == -1),'
|
||||||
|
# ' (int)((size_t)res == cbuf_len));\n'
|
||||||
|
# ' Py_BallisticaLowLevelDebugLog(dlog);\n'
|
||||||
|
# " cbuf[res] = '\\0'; /* buf will be null terminated */"
|
||||||
|
# ),
|
||||||
|
# )
|
||||||
writefile(fname, txt)
|
writefile(fname, txt)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -114,7 +114,6 @@ from batools.pcommand import (
|
|||||||
from batools.pcommand2 import (
|
from batools.pcommand2 import (
|
||||||
gen_python_init_module,
|
gen_python_init_module,
|
||||||
gen_monolithic_register_modules,
|
gen_monolithic_register_modules,
|
||||||
stage_server_file,
|
|
||||||
py_examine,
|
py_examine,
|
||||||
clean_orphaned_assets,
|
clean_orphaned_assets,
|
||||||
win_ci_install_prereqs,
|
win_ci_install_prereqs,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user