Compare commits
No commits in common. "main" and "v2.0.2-mp1" have entirely different histories.
main
...
v2.0.2-mp1
8 changed files with 42 additions and 213 deletions
|
|
@ -50,37 +50,12 @@ Per-platform notes:
|
||||||
| Platform | Build machine | Command |
|
| Platform | Build machine | Command |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| Linux | any Linux with the toolchain (README: Ubuntu 24.04 + Clang 20) | `./tools/release/release.sh` |
|
| Linux | any Linux with the toolchain (README: Ubuntu 24.04 + Clang 20) | `./tools/release/release.sh` |
|
||||||
| Windows | a **Windows** machine (Visual Studio MSVC + Windows SDK, D3D12) | `tools\release\windows-build.cmd` (see below) |
|
| Windows | a **Windows** machine (MSVC/clang-cl + Windows SDK, D3D12) | run the same script on Windows (`--os windows`) |
|
||||||
| macOS | an **Apple Silicon/Intel Mac** (Homebrew LLVM + MoltenVK, per README) | `./tools/release/release.sh` |
|
| macOS | an **Apple Silicon/Intel Mac** (Homebrew LLVM + MoltenVK, per README) | run the same script on macOS |
|
||||||
|
|
||||||
Cross-compiling Windows/macOS from a Linux box is not practical for this
|
Cross-compiling Windows/macOS from a Linux box is not practical for this
|
||||||
stack (D3D12 needs the Windows SDK, Cocoa/MoltenVK need a Mac), so each
|
stack (D3D12 on Windows, Cocoa/MoltenVK on macOS need their native SDKs), so
|
||||||
platform's release is built on that platform.
|
each platform's release is built on that platform.
|
||||||
|
|
||||||
### Windows build
|
|
||||||
|
|
||||||
On a Windows box, the known build issues (multiple Windows SDKs, Git Bash
|
|
||||||
`%LIB%` mangling, missing submodules) are handled by the launcher:
|
|
||||||
|
|
||||||
```bat
|
|
||||||
tools\release\windows-build.cmd --tag v2.0.2-mp1 --upload
|
|
||||||
```
|
|
||||||
|
|
||||||
It loads the MSVC environment (`vcvarsall.bat x64 <SDK>`), sets
|
|
||||||
`MSYS2_ARG_CONV_EXCL=*` so Git Bash doesn't corrupt `%LIB%`, initializes the
|
|
||||||
submodules (including the self-heal), and runs `release.sh`. Config via env:
|
|
||||||
|
|
||||||
- `VCVARSALL` — path to `vcvarsall.bat` (default: VS 18 Community x64).
|
|
||||||
- `WINSDK` — Windows SDK version (default `10.0.26100.0`; try `10.0.22621.0`
|
|
||||||
if yours differs — a broken SDK default is what causes `kernel32.lib`
|
|
||||||
`LNK1104`).
|
|
||||||
- `GITBASH` — path to Git for Windows `bash.exe`.
|
|
||||||
|
|
||||||
`release.sh` now auto-detects the Title Update package (repo root or
|
|
||||||
`game/`), falls back to PowerShell `Compress-Archive` when `zip` is missing,
|
|
||||||
and no longer requires `python3` for the upload JSON parsing. The Windows
|
|
||||||
build also needs the game dump (`game/default.xex` + `EAWebkit.xex`) and the
|
|
||||||
TU package present on that box (build-time only, never shipped).
|
|
||||||
|
|
||||||
## Option B — automated via Forgejo Actions (optional)
|
## Option B — automated via Forgejo Actions (optional)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@
|
||||||
|
|
||||||
#include "skate3_native_ghost_net.h"
|
#include "skate3_native_ghost_net.h"
|
||||||
#include "skate3_native_ghost_relay.h"
|
#include "skate3_native_ghost_relay.h"
|
||||||
#include "skate3_native_entity.h"
|
|
||||||
#include "skate3_native_guest_read.h"
|
#include "skate3_native_guest_read.h"
|
||||||
#include "skate3_native_palette.h"
|
#include "skate3_native_palette.h"
|
||||||
|
|
||||||
|
|
@ -739,15 +738,8 @@ void GhostNetworkLoop() {
|
||||||
RoomSet(room_buf, room_len, room_str.c_str());
|
RoomSet(room_buf, room_len, room_str.c_str());
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(g_mu);
|
std::lock_guard<std::mutex> lock(g_mu);
|
||||||
// A non-empty room cvar is the user's explicit choice: sync it into
|
std::memcpy(g_room, room_buf, kGhostMaxRoomLen);
|
||||||
// the active room. An EMPTY cvar means "server auto-assigns" - keep
|
g_room_len = room_len;
|
||||||
// the code the relay handed back on HELLO. Overwriting the assigned
|
|
||||||
// code with the empty cvar every 25 ms is what made the room code
|
|
||||||
// flicker in and out of the multiplayer menu.
|
|
||||||
if (room_len != 0) {
|
|
||||||
std::memcpy(g_room, room_buf, kGhostMaxRoomLen);
|
|
||||||
g_room_len = room_len;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sock == GHOST_INVALID_SOCKET) {
|
if (sock == GHOST_INVALID_SOCKET) {
|
||||||
|
|
@ -902,7 +894,24 @@ void GhostNetworkLoop() {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// ---- capture (per built frame; see OnFrameSceneBuilt) ----------------------
|
// ---- capture (sim thread; hook in skate3_native_render.cpp) ------------------
|
||||||
|
void OnLocalSkaterTick(uint8_t* base) {
|
||||||
|
if (!Enabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const uint32_t entity = skate3::native_palette::CurrentPackOwner();
|
||||||
|
if (entity == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
float world[16];
|
||||||
|
if (!ReadEntityWorld(base, entity, world)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::lock_guard<std::mutex> lock(g_mu);
|
||||||
|
std::memcpy(g_local_world, world, sizeof(g_local_world));
|
||||||
|
g_local_valid = true;
|
||||||
|
g_local_time = NowSec();
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// Identity rows for a bone (column-vector affine [R|t]): the safe padding
|
// Identity rows for a bone (column-vector affine [R|t]): the safe padding
|
||||||
|
|
@ -972,33 +981,6 @@ void OnFrameSceneBuilt(uint8_t* base,
|
||||||
g_local_pose_count = rows;
|
g_local_pose_count = rows;
|
||||||
g_local_pose_valid = true;
|
g_local_pose_valid = true;
|
||||||
g_local_pose_time = NowSec();
|
g_local_pose_time = NowSec();
|
||||||
|
|
||||||
// Local player's world transform for the self-check cube / the wire
|
|
||||||
// pos/rot. Resolve the body item's OWNING ENTITY (ctx -> entity store)
|
|
||||||
// and read its world matrix - the reliable player signal. The previous
|
|
||||||
// UBT-hook capture could pick an NPC skater (UpdateBoneTransforms fires
|
|
||||||
// for them too), which put the cube on a nearby NPC.
|
|
||||||
float world[16];
|
|
||||||
bool have_world = false;
|
|
||||||
if (body->ctx != 0) {
|
|
||||||
skate3::native_entity::CtxInfo info;
|
|
||||||
if (skate3::native_entity::LookupCtx(body->ctx, &info) && info.entity != 0 &&
|
|
||||||
ReadEntityWorld(base, info.entity, world)) {
|
|
||||||
have_world = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!have_world) {
|
|
||||||
// Fallback: the body item's root bone translation (the player's pelvis
|
|
||||||
// world position); identity rotation is fine for a debug cube.
|
|
||||||
std::memset(world, 0, sizeof(world));
|
|
||||||
world[0] = world[5] = world[10] = world[15] = 1.0f;
|
|
||||||
world[12] = body->bones[3];
|
|
||||||
world[13] = body->bones[7];
|
|
||||||
world[14] = body->bones[11];
|
|
||||||
}
|
|
||||||
std::memcpy(g_local_world, world, sizeof(g_local_world));
|
|
||||||
g_local_valid = true;
|
|
||||||
g_local_time = NowSec();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnsureNetworkThread() {
|
void EnsureNetworkThread() {
|
||||||
|
|
|
||||||
|
|
@ -31,12 +31,13 @@ struct FrameScene;
|
||||||
|
|
||||||
namespace skate3::native_ghost {
|
namespace skate3::native_ghost {
|
||||||
|
|
||||||
|
// ---- host-side capture (called from skate3_native_render.cpp) -------------
|
||||||
|
void OnLocalSkaterTick(uint8_t* base);
|
||||||
|
|
||||||
// ---- host-side pose capture (called from BuildFrameScene pre-publish) -----
|
// ---- host-side pose capture (called from BuildFrameScene pre-publish) -----
|
||||||
// Snapshot the local player's skater skeleton (the highest-bone-count
|
// Snapshot the local player's skater skeleton (the highest-bone-count
|
||||||
// skinned non-ropa character item near the camera) as the pose this client
|
// skinned non-ropa character item near the camera) as the pose this client
|
||||||
// broadcasts, plus the local player's world transform (resolved from that
|
// broadcasts. Called every built frame; gated internally on the enable cvar.
|
||||||
// item's owning entity). Called every built frame; gated internally on the
|
|
||||||
// enable cvar.
|
|
||||||
void OnFrameSceneBuilt(uint8_t* base, const skate3::native_scene::FrameScene& scene);
|
void OnFrameSceneBuilt(uint8_t* base, const skate3::native_scene::FrameScene& scene);
|
||||||
|
|
||||||
// ---- network thread lifecycle -------------------------------------------------
|
// ---- network thread lifecycle -------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -45,19 +45,7 @@ void GhostDialog::Toggle() {
|
||||||
|
|
||||||
void GhostDialog::SyncBuffersFromCvars() {
|
void GhostDialog::SyncBuffersFromCvars() {
|
||||||
const std::string room = REXCVAR_GET(skate3_ghost_room);
|
const std::string room = REXCVAR_GET(skate3_ghost_room);
|
||||||
if (!room.empty()) {
|
std::snprintf(room_input_, sizeof(room_input_), "%s", room.c_str());
|
||||||
std::snprintf(room_input_, sizeof(room_input_), "%s", room.c_str());
|
|
||||||
} else {
|
|
||||||
// Auto-assigned room: the active code comes from the connection, not the
|
|
||||||
// (empty) cvar - surface it in the input so the user can see/copy it.
|
|
||||||
skate3::native_ghost::Status st;
|
|
||||||
if (skate3::native_ghost::GetStatus(&st) && st.room_len > 0) {
|
|
||||||
std::snprintf(room_input_, sizeof(room_input_), "%.*s",
|
|
||||||
int(st.room_len), st.room);
|
|
||||||
} else {
|
|
||||||
room_input_[0] = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const std::string server = REXCVAR_GET(skate3_ghost_server);
|
const std::string server = REXCVAR_GET(skate3_ghost_server);
|
||||||
std::snprintf(server_input_, sizeof(server_input_), "%s", server.c_str());
|
std::snprintf(server_input_, sizeof(server_input_), "%s", server.c_str());
|
||||||
const std::string name = REXCVAR_GET(skate3_ghost_name);
|
const std::string name = REXCVAR_GET(skate3_ghost_name);
|
||||||
|
|
@ -104,21 +92,8 @@ void GhostDialog::OnDraw(ImGuiIO& io) {
|
||||||
ImGui::SetKeyboardFocusHere(-1);
|
ImGui::SetKeyboardFocusHere(-1);
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
// Copy the ACTIVE room (the one this player is actually in), which for an
|
|
||||||
// auto-assigned room lives in the connection state, not the cvar.
|
|
||||||
if (ImGui::Button("Copy")) {
|
if (ImGui::Button("Copy")) {
|
||||||
skate3::native_ghost::Status st;
|
ImGui::SetClipboardText(REXCVAR_GET(skate3_ghost_room).c_str());
|
||||||
if (skate3::native_ghost::GetStatus(&st) && st.room_len > 0) {
|
|
||||||
char buf[skate3::native_ghost::kGhostMaxRoomLen + 1] = {};
|
|
||||||
std::memcpy(buf, st.room, st.room_len);
|
|
||||||
ImGui::SetClipboardText(buf);
|
|
||||||
copy_feedback_ = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (copy_feedback_) {
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::TextDisabled("copied");
|
|
||||||
copy_feedback_ = false;
|
|
||||||
}
|
}
|
||||||
ImGui::TextDisabled("Empty = the server assigns one; share it with friends.");
|
ImGui::TextDisabled("Empty = the server assigns one; share it with friends.");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ class GhostDialog final : public rex::ui::ImGuiDialog {
|
||||||
|
|
||||||
bool visible_ = false;
|
bool visible_ = false;
|
||||||
bool synced_ = false;
|
bool synced_ = false;
|
||||||
bool copy_feedback_ = false;
|
|
||||||
char room_input_[16] = {};
|
char room_input_[16] = {};
|
||||||
char server_input_[128] = {};
|
char server_input_[128] = {};
|
||||||
char name_input_[skate3::native_ghost::kGhostMaxNameLen + 1] = {};
|
char name_input_[skate3::native_ghost::kGhostMaxNameLen + 1] = {};
|
||||||
|
|
|
||||||
|
|
@ -473,6 +473,9 @@ extern "C" REX_FUNC(sub_827A52C8) {
|
||||||
__imp__sub_827A52C8(ctx, base);
|
__imp__sub_827A52C8(ctx, base);
|
||||||
if (skate3::native_render::Enabled()) {
|
if (skate3::native_render::Enabled()) {
|
||||||
skate3::native_palette::OnBoneTransforms(base, parts, count);
|
skate3::native_palette::OnBoneTransforms(base, parts, count);
|
||||||
|
// Ghost multiplayer: capture the local player's world transform (the
|
||||||
|
// pack-owner entity at this point is the player's SkaterPresEntity).
|
||||||
|
skate3::native_ghost::OnLocalSkaterTick(base);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -78,46 +78,14 @@ if [ ! -f "$GAME_ROOT/default.xex" ]; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ---- helpers (Windows Git Bash lacks zip/python; provide fallbacks) ---------
|
|
||||||
json_id() { # read JSON on stdin, print the value of "id"
|
|
||||||
if command -v python3 >/dev/null 2>&1; then
|
|
||||||
python3 -c "import sys,json
|
|
||||||
try: print(json.load(sys.stdin).get('id',''))
|
|
||||||
except Exception: print('')"
|
|
||||||
elif command -v python >/dev/null 2>&1; then
|
|
||||||
python -c "import sys,json
|
|
||||||
try: print(json.load(sys.stdin).get('id',''))
|
|
||||||
except Exception: print('')"
|
|
||||||
else
|
|
||||||
grep -o '"id":[0-9]*' | head -1 | cut -d: -f2
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
make_zip() { # make_zip <zipname> <dir>
|
|
||||||
if command -v zip >/dev/null 2>&1; then
|
|
||||||
(cd "$(dirname "$2")" && zip -r "$(basename "$1")" "$(basename "$2")")
|
|
||||||
elif command -v 7z >/dev/null 2>&1; then
|
|
||||||
7z a -tzip "$1" "$2" >/dev/null
|
|
||||||
elif command -v powershell >/dev/null 2>&1; then
|
|
||||||
powershell -NoProfile -Command "Compress-Archive -Path '$2' -DestinationPath '$1' -Force"
|
|
||||||
else
|
|
||||||
echo "ERROR: no zip tool found (install zip, 7z, or use PowerShell)"; exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# ---- build ------------------------------------------------------------------
|
|
||||||
TU_ARGS=""
|
TU_ARGS=""
|
||||||
if [ -n "$TU" ]; then
|
if [ -n "$TU" ]; then
|
||||||
if [ ! -f "$TU" ]; then echo "ERROR: title update package not found: $TU"; exit 1; fi
|
if [ ! -f "$TU" ]; then echo "ERROR: title update package not found: $TU"; exit 1; fi
|
||||||
TU_ARGS="-DSKATE3_TITLE_UPDATE_PACKAGE=$TU"
|
TU_ARGS="-DSKATE3_TITLE_UPDATE_PACKAGE=$TU"
|
||||||
elif [ -n "$(ls "$REPO"/TU_12K2276_* "$GAME_ROOT"/TU_12K2276_* 2>/dev/null | head -1)" ]; then
|
|
||||||
TU="$(ls "$REPO"/TU_12K2276_* "$GAME_ROOT"/TU_12K2276_* 2>/dev/null | head -1)"
|
|
||||||
echo "==> Using title update package: $TU"
|
|
||||||
TU_ARGS="-DSKATE3_TITLE_UPDATE_PACKAGE=$TU"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "==> Release $TAG ($EXT) preset=$PRESET game=$GAME_ROOT"
|
echo "==> Release $TAG ($EXT) preset=$PRESET game=$GAME_ROOT"
|
||||||
echo "==> Configure"
|
echo "==> Configure (extra args: ${CMAKE_ARGS:-none})"
|
||||||
cmake --preset "$PRESET" -DSKATE3_GAME_DATA_ROOT="$GAME_ROOT" $TU_ARGS $CMAKE_ARGS
|
cmake --preset "$PRESET" -DSKATE3_GAME_DATA_ROOT="$GAME_ROOT" $TU_ARGS $CMAKE_ARGS
|
||||||
echo "==> Generate recompiled code"
|
echo "==> Generate recompiled code"
|
||||||
cmake --build --preset "$PRESET" --target generate-all --parallel
|
cmake --build --preset "$PRESET" --target generate-all --parallel
|
||||||
|
|
@ -148,7 +116,7 @@ if [ -f "$OUT/game/default.xexp" ]; then
|
||||||
fi
|
fi
|
||||||
cp README.md "$STAGE/"
|
cp README.md "$STAGE/"
|
||||||
rm -f "$NAME.zip"
|
rm -f "$NAME.zip"
|
||||||
make_zip "$NAME.zip" "$STAGE"
|
zip -r "$NAME.zip" "$STAGE"
|
||||||
rm -rf "$STAGE"
|
rm -rf "$STAGE"
|
||||||
echo "==> Packaged: $NAME.zip ($(du -h "$NAME.zip" | cut -f1))"
|
echo "==> Packaged: $NAME.zip ($(du -h "$NAME.zip" | cut -f1))"
|
||||||
sha256sum "$NAME.zip"
|
sha256sum "$NAME.zip"
|
||||||
|
|
@ -164,11 +132,15 @@ if [ "$UPLOAD" = 1 ]; then
|
||||||
RELEASE_ID="$(curl -s -X POST "$INSTANCE/api/v1/repos/$REPO_FULL/releases" \
|
RELEASE_ID="$(curl -s -X POST "$INSTANCE/api/v1/repos/$REPO_FULL/releases" \
|
||||||
-H "$AUTH" -H "Content-Type: application/json" \
|
-H "$AUTH" -H "Content-Type: application/json" \
|
||||||
-d "{\"tag_name\":\"$TAG\",\"name\":\"Skate 3 Recomp $TAG\",\"target_commitish\":\"main\"}" \
|
-d "{\"tag_name\":\"$TAG\",\"name\":\"Skate 3 Recomp $TAG\",\"target_commitish\":\"main\"}" \
|
||||||
| json_id)"
|
| python3 -c "import sys,json
|
||||||
|
try: print(json.load(sys.stdin).get('id',''))
|
||||||
|
except Exception: print('')")"
|
||||||
|
|
||||||
if [ -z "$RELEASE_ID" ]; then
|
if [ -z "$RELEASE_ID" ]; then
|
||||||
RELEASE_ID="$(curl -s "$INSTANCE/api/v1/repos/$REPO_FULL/releases/tags/$TAG" -H "$AUTH" \
|
RELEASE_ID="$(curl -s "$INSTANCE/api/v1/repos/$REPO_FULL/releases/tags/$TAG" -H "$AUTH" \
|
||||||
| json_id)"
|
| python3 -c "import sys,json
|
||||||
|
try: print(json.load(sys.stdin).get('id',''))
|
||||||
|
except Exception: print('')")"
|
||||||
fi
|
fi
|
||||||
if [ -z "$RELEASE_ID" ]; then
|
if [ -z "$RELEASE_ID" ]; then
|
||||||
echo "ERROR: could not create/find release '$TAG'"; exit 1
|
echo "ERROR: could not create/find release '$TAG'"; exit 1
|
||||||
|
|
@ -176,14 +148,9 @@ if [ "$UPLOAD" = 1 ]; then
|
||||||
|
|
||||||
curl -s -X POST "$INSTANCE/api/v1/repos/$REPO_FULL/releases/$RELEASE_ID/assets" \
|
curl -s -X POST "$INSTANCE/api/v1/repos/$REPO_FULL/releases/$RELEASE_ID/assets" \
|
||||||
-H "$AUTH" -F "attachment=@$NAME.zip" -F "name=$NAME.zip" \
|
-H "$AUTH" -F "attachment=@$NAME.zip" -F "name=$NAME.zip" \
|
||||||
| if command -v python3 >/dev/null 2>&1 || command -v python >/dev/null 2>&1; then
|
| python3 -c "import sys,json
|
||||||
PY=python3; command -v python3 >/dev/null 2>&1 || PY=python
|
|
||||||
"$PY" -c "import sys,json
|
|
||||||
try:
|
try:
|
||||||
a=json.load(sys.stdin); print('Uploaded asset', a.get('name'), a.get('size'), 'bytes')
|
a=json.load(sys.stdin); print('Uploaded asset', a.get('name'), a.get('size'), 'bytes')
|
||||||
except Exception as e: print('upload response parse failed:', e)"
|
except Exception as e: print('upload response parse failed:', e)"
|
||||||
else
|
|
||||||
echo "Upload request sent (no python to parse the response)"
|
|
||||||
fi
|
|
||||||
echo "==> Done: https://git.mithraic.cloud/$REPO_FULL/releases/tag/$TAG"
|
echo "==> Done: https://git.mithraic.cloud/$REPO_FULL/releases/tag/$TAG"
|
||||||
fi
|
fi
|
||||||
|
|
@ -1,73 +0,0 @@
|
||||||
@echo off
|
|
||||||
rem One-click Windows release build for skate3recomp-multiplayer.
|
|
||||||
rem
|
|
||||||
rem Fixes the known Windows build issues documented in /mnt/archive/Issues.txt
|
|
||||||
rem (and mirrored in docs/releases.md):
|
|
||||||
rem 1. stable Windows SDK so kernel32.lib resolves (vcvarsall with an SDK
|
|
||||||
rem version instead of the broken default),
|
|
||||||
rem 2. Git Bash %LIB% mangling (MSYS2_ARG_CONV_EXCL=*),
|
|
||||||
rem 3. missing rexglue submodules (git submodule update --init + self-heal).
|
|
||||||
rem
|
|
||||||
rem Usage (from a normal cmd.exe / PowerShell prompt):
|
|
||||||
rem tools\release\windows-build.cmd [--tag vX.Y.Z] [--upload]
|
|
||||||
rem
|
|
||||||
rem Config via environment variables:
|
|
||||||
rem VCVARSALL path to vcvarsall.bat (default: VS 18 Community x64)
|
|
||||||
rem WINSDK Windows SDK version (default 10.0.26100.0; try 10.0.22621.0
|
|
||||||
rem if yours is different)
|
|
||||||
rem GITBASH path to Git for Windows bash.exe
|
|
||||||
setlocal
|
|
||||||
|
|
||||||
if "%VCVARSALL%"=="" set "VCVARSALL=%ProgramFiles%\Microsoft Visual Studio\18\Community\VC\Auxiliary\Build\vcvarsall.bat"
|
|
||||||
if "%WINSDK%"=="" set "WINSDK=10.0.26100.0"
|
|
||||||
if "%GITBASH%"=="" set "GITBASH=%ProgramFiles%\Git\bin\bash.exe"
|
|
||||||
|
|
||||||
if not exist "%VCVARSALL%" (
|
|
||||||
echo [ERROR] vcvarsall.bat not found: %VCVARSALL%
|
|
||||||
echo Set VCVARSALL to your Visual Studio install, e.g.
|
|
||||||
echo "%%ProgramFiles%%\Microsoft Visual Studio\17\Community\VC\Auxiliary\Build\vcvarsall.bat"
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
if not exist "%GITBASH%" (
|
|
||||||
echo [ERROR] Git Bash not found: %GITBASH%
|
|
||||||
echo Install Git for Windows or set GITBASH.
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
echo [1/3] Loading MSVC environment (x64, SDK %WINSDK%)
|
|
||||||
call "%VCVARSALL%" x64 %WINSDK%
|
|
||||||
if errorlevel 1 (
|
|
||||||
echo [ERROR] vcvarsall failed. Try a different WINSDK, e.g.
|
|
||||||
echo set WINSDK=10.0.22621.0
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
rem Prevent Git Bash from converting/corrupting the MSVC environment.
|
|
||||||
rem MSYS2_ARG_CONV_EXCL protects command-line ARGUMENTS; the actual
|
|
||||||
rem kernel32.lib LNK1104 is caused by MSYS rewriting the %LIB% ENVIRONMENT
|
|
||||||
rem variable (backslashes + semicolons), which requires MSYS2_ENV_CONV_EXCL.
|
|
||||||
set "MSYS2_ARG_CONV_EXCL=*"
|
|
||||||
set "MSYS2_ENV_CONV_EXCL=*"
|
|
||||||
|
|
||||||
if "%LIB%"=="" (
|
|
||||||
echo [WARN] LIB is empty after vcvarsall - try a different WINSDK
|
|
||||||
echo e.g. set WINSDK=10.0.22621.0
|
|
||||||
)
|
|
||||||
echo LIB=%LIB%
|
|
||||||
|
|
||||||
rem Convert the repo path to forward slashes for Git Bash (%~dp0 is
|
|
||||||
rem tools\release\ with a trailing backslash; ..\.. reaches the repo root).
|
|
||||||
set "REPO=%~dp0..\.."
|
|
||||||
set "REPO=%REPO:\=/%"
|
|
||||||
|
|
||||||
echo [2/3] Initializing submodules (rexglue SDK + nested)
|
|
||||||
"%GITBASH%" --login -c "cd '%REPO%' && git submodule update --init --jobs 4 && bash tools/ci/init-submodules.sh"
|
|
||||||
if errorlevel 1 (
|
|
||||||
echo [ERROR] submodule init failed.
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
echo [3/3] Building release
|
|
||||||
"%GITBASH%" --login -c "cd '%REPO%' && bash tools/release/release.sh %*"
|
|
||||||
exit /b %errorlevel%
|
|
||||||
endlocal
|
|
||||||
Loading…
Add table
Reference in a new issue