From 71edfc19ffa3699239311dd5e4de46a98dd2e20e Mon Sep 17 00:00:00 2001 From: neoapps-dev Date: Sat, 28 Mar 2026 22:34:13 +0300 Subject: [PATCH] feat: generic build script --- .gitea/workflows/nightly.yml | 44 ++++--- README.md | 7 ++ build-linux.sh | 217 +++++++++++++++++++++++++++++++++++ 3 files changed, 249 insertions(+), 19 deletions(-) create mode 100755 build-linux.sh diff --git a/.gitea/workflows/nightly.yml b/.gitea/workflows/nightly.yml index ce3b0d3f..c238d0f3 100644 --- a/.gitea/workflows/nightly.yml +++ b/.gitea/workflows/nightly.yml @@ -25,35 +25,41 @@ jobs: - name: Checkout uses: https://code.forgejo.org/actions/checkout@v4 - - name: Install Nix - uses: https://github.com/cachix/install-nix-action@v27 - with: - extra_nix_config: | - experimental-features = nix-command flakes - accept-flake-config = true + - name: Install dependencies + run: | + sudo apt-get update -qq + sudo apt-get install -y --no-install-recommends \ + cmake ninja-build rsync zip \ + clang lld llvm - - name: Cache Nix store + - name: Install xwin + run: | + cargo install xwin --locked + + - name: Cache Windows SDK uses: https://code.forgejo.org/actions/cache@v4 with: - path: | - ~/.cache/nix - /nix/store - /nix/var/nix/db - /nix/var/nix/gcroots - key: nix-${{ runner.os }}-${{ hashFiles('flake.lock') }} + path: ~/.cache/xwin + key: xwin-${{ runner.os }}-v1 restore-keys: | - nix-${{ runner.os }}- + xwin-${{ runner.os }}- - name: Build - run: nix build .#unwrapped --out-link result-unwrapped --max-jobs 1 --cores 1 + run: | + chmod +x build-linux.sh + INSTALL_PREFIX=$PWD/result ./build-linux.sh . Release - name: Package artifacts run: | mkdir -p staging - cd result-unwrapped/client + cd result/client zip -r ../../staging/LCEWindows64.zip . cp Minecraft.Client.exe ../../staging/ cd ../.. + cd result/server + zip -r ../../staging/LCEWindows64Server.zip . + cp Minecraft.Server.exe ../../staging/ + cd ../.. - name: Upload build artifacts uses: https://code.forgejo.org/actions/upload-artifact@v3 @@ -96,7 +102,7 @@ jobs: -H "$AUTH" -H "Content-Type: application/json" \ "$API/repos/$REPO/releases/$RELEASE_ID" \ -d '{ - "name": "Nightly Client Release", + "name": "Nightly Release", "prerelease": true, "body": "Requires at least Windows 7 and a DirectX 11 compatible GPU.\n\n# 🚨 First time here? 🚨\nDownload `LCEWindows64.zip` and extract it." }' @@ -107,7 +113,7 @@ jobs: "$API/repos/$REPO/releases" \ -d '{ "tag_name": "'"$TAG"'", - "name": "Nightly Client Release", + "name": "Nightly Release", "prerelease": true, "body": "Requires at least Windows 7 and a DirectX 11 compatible GPU.\n\n# 🚨 First time here? 🚨\nDownload `LCEWindows64.zip` and extract it." }') @@ -142,4 +148,4 @@ jobs: for ARTIFACT_ID in $(echo "$ARTIFACTS" | jq -r '.artifacts[].id // empty'); do curl -s -X DELETE -H "$AUTH" \ "$API/repos/$REPO/actions/artifacts/$ARTIFACT_ID" - done \ No newline at end of file + done diff --git a/README.md b/README.md index 0e74b2d9..eb94d2a3 100644 --- a/README.md +++ b/README.md @@ -30,3 +30,10 @@ Huge thanks to the following projects: 2. Clone the repository. 3. Open the project folder from Visual Studio. 4. Set the build configuration to **Windows64 - Debug** (Release is also ok but missing some debug features), then build and run. + +### GNU/Linux + +We provide both a generic build script and a Nix flake. + +- Nix: `nix run .#client` +- Generic: `./build-linux.sh` diff --git a/build-linux.sh b/build-linux.sh new file mode 100755 index 00000000..96762c81 --- /dev/null +++ b/build-linux.sh @@ -0,0 +1,217 @@ +#!/usr/bin/env bash +set -euo pipefail +VERSION="0.0.0" # man we're using nightly :sob: +SOURCE_DIR="${1:-.}" +BUILD_TYPE="${2:-Release}" +XWIN_CACHE="${XWIN_CACHE:-$HOME/.cache/xwin}" +INSTALL_DIR="${INSTALL_PREFIX:-$HOME/.local/share/evolved-lce}" +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +CYAN='\033[0;36m' +NC='\033[0m' +info() { echo -e "${CYAN}[info]${NC} $*"; } +success() { echo -e "${GREEN}[ok]${NC} $*"; } +warn() { echo -e "${YELLOW}[warn]${NC} $*"; } +die() { echo -e "${RED}[error]${NC} $*" >&2; exit 1; } +check_deps() { + local missing=() + local deps=(clang-cl lld-link llvm-rc llvm-ml llvm-lib llvm-mt cmake ninja xwin rsync) + for dep in "${deps[@]}"; do + command -v "$dep" &>/dev/null || missing+=("$dep") + done + + if [[ ${#missing[@]} -gt 0 ]]; then + die "Missing dependencies: ${missing[*]}\n\nInstall guide:\n clang-cl/lld/llvm -> clang + lld (your distro's llvm package)\n cmake/ninja -> cmake + ninja-build\n xwin -> cargo install xwin\n rsync -> rsync" + fi + + success "All dependencies found" +} + +fetch_winsdk() { + local splat_dir="$XWIN_CACHE/splat" + if [[ -d "$splat_dir" ]]; then + info "Using cached Windows SDK at $splat_dir" + return + fi + + info "Downloading Windows SDK and CRT via xwin..." + mkdir -p "$XWIN_CACHE" + xwin --accept-license splat --output "$splat_dir" + success "Windows SDK downloaded" +} + +patch_winsdk_symlinks() { + local splat_dir="$XWIN_CACHE/splat" + info "Patching case-sensitivity symlinks..." + ln -sf "$splat_dir/sdk/include/shared/sdkddkver.h" \ + "$splat_dir/sdk/include/shared/SDKDDKVer.h" 2>/dev/null || true + ln -sf "$splat_dir/sdk/lib/um/x86_64/xinput9_1_0.lib" \ + "$splat_dir/sdk/lib/um/x86_64/XInput9_1_0.lib" 2>/dev/null || true + ln -sf "$splat_dir/sdk/lib/um/x86_64/ws2_32.lib" \ + "$splat_dir/sdk/lib/um/x86_64/Ws2_32.lib" 2>/dev/null || true +} + +write_toolchain() { + local toolchain_file="$BUILD_DIR/clang-cl-toolchain.cmake" + cat > "$toolchain_file" <<'CMAKE' +set(CMAKE_SYSTEM_NAME Windows) +set(CMAKE_SYSTEM_PROCESSOR AMD64) +set(CMAKE_C_COMPILER clang-cl) +set(CMAKE_CXX_COMPILER clang-cl) +set(CMAKE_RC_COMPILER llvm-rc) +set(CMAKE_ASM_MASM_COMPILER llvm-ml) +set(CMAKE_AR llvm-lib) +set(CMAKE_LINKER lld-link) +set(CMAKE_CROSSCOMPILING TRUE) +set(CMAKE_C_LINK_EXECUTABLE " -out: ") +set(CMAKE_CXX_LINK_EXECUTABLE " -out: ") +add_compile_options(-fms-compatibility -fms-extensions) +add_compile_definitions(_WIN64 _AMD64_ WIN32_LEAN_AND_MEAN) +CMAKE + + echo "$toolchain_file" +} + +do_cmake_configure() { + local winsdk="$XWIN_CACHE/splat" + local toolchain + toolchain="$(write_toolchain)" + local c_flags="/MT -fms-compatibility -fms-extensions --target=x86_64-pc-windows-msvc \ +-imsvc $winsdk/crt/include \ +-imsvc $winsdk/sdk/include/ucrt \ +-imsvc $winsdk/sdk/include/um \ +-imsvc $winsdk/sdk/include/shared" + + local linker_flags="\ +-libpath:$winsdk/crt/lib/x86_64 \ +-libpath:$winsdk/sdk/lib/um/x86_64 \ +-libpath:$winsdk/sdk/lib/ucrt/x86_64" + + info "Configuring with CMake ($BUILD_TYPE)..." + cmake -S "$SOURCE_DIR" -B "$BUILD_DIR" \ + -G Ninja \ + -DCMAKE_BUILD_TYPE="$BUILD_TYPE" \ + -DCMAKE_TOOLCHAIN_FILE="$toolchain" \ + -DCMAKE_C_COMPILER=clang-cl \ + -DCMAKE_CXX_COMPILER=clang-cl \ + -DCMAKE_LINKER=lld-link \ + -DCMAKE_RC_COMPILER=llvm-rc \ + -DCMAKE_MT=llvm-mt \ + -DPLATFORM_DEFINES="_WINDOWS64" \ + -DPLATFORM_NAME="Windows64" \ + -DIGGY_LIBS="iggy_w64.lib;iggyperfmon_w64.lib;iggyexpruntime_w64.lib" \ + -DCMAKE_SYSTEM_NAME=Windows \ + -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded \ + -DCMAKE_C_FLAGS="$c_flags" \ + -DCMAKE_CXX_FLAGS="$c_flags" \ + -DCMAKE_ASM_MASM_FLAGS="-m64" \ + -DCMAKE_EXE_LINKER_FLAGS="$linker_flags" \ + -DCMAKE_RC_FLAGS="/I $winsdk/sdk/include/shared /I $winsdk/sdk/include/um /I $winsdk/sdk/include/ucrt" + + success "CMake configuration done" +} + +do_build() { + info "Building with $(nproc) cores..." + cmake --build "$BUILD_DIR" --config "$BUILD_TYPE" -j "$(nproc)" + success "Build complete" +} + +do_install() { + info "Installing to $INSTALL_DIR..." + mkdir -p "$INSTALL_DIR"/{client,server} + cp "$BUILD_DIR/Minecraft.Client/Minecraft.Client.exe" "$INSTALL_DIR/client/" + cp "$BUILD_DIR/Minecraft.Server/Minecraft.Server.exe" "$INSTALL_DIR/server/" + for asset in iggy_w64.dll Common music Windows64 Windows64Media; do + [[ -e "$BUILD_DIR/Minecraft.Client/$asset" ]] && \ + cp -r "$BUILD_DIR/Minecraft.Client/$asset" "$INSTALL_DIR/client/" || true + done + for asset in iggy_w64.dll Common Windows64; do + [[ -e "$BUILD_DIR/Minecraft.Server/$asset" ]] && \ + cp -r "$BUILD_DIR/Minecraft.Server/$asset" "$INSTALL_DIR/server/" || true + done + write_client_launcher + write_server_launcher + success "Installed to $INSTALL_DIR" + info "Run the client: $INSTALL_DIR/minecraft-lce-client" + info "Run the server: $INSTALL_DIR/minecraft-lce-server" +} + +write_client_launcher() { + cat > "$INSTALL_DIR/minecraft-lce-client" </dev/null || true +ln -sf "\$PERSIST_DIR/GameHDD" "\$WORK_DIR/Windows64/GameHDD" +cd "\$WORK_DIR" +exec wine "\$WORK_DIR/Minecraft.Client.exe" "\$@" +LAUNCHER + chmod +x "$INSTALL_DIR/minecraft-lce-client" +} + +write_server_launcher() { + cat > "$INSTALL_DIR/minecraft-lce-server" < "\$PERSIST_DIR/\$file" + fi + ln -sf "\$PERSIST_DIR/\$file" "\$WORK_DIR/\$file" +done +rm -rf "\$WORK_DIR/Windows64/GameHDD" 2>/dev/null || true +ln -sf "\$PERSIST_DIR/GameHDD" "\$WORK_DIR/Windows64/GameHDD" +cd "\$WORK_DIR" +if [[ -z "\${DISPLAY:-}" ]]; then + export DISPLAY=":99" + Xvfb "\$DISPLAY" -nolisten tcp -screen 0 64x64x16 & + XVFB_PID=\$! + trap 'kill \$XVFB_PID 2>/dev/null || true; rm -rf "\$WORK_DIR"' EXIT + sleep 1 +fi +exec wine "\$WORK_DIR/Minecraft.Server.exe" -port "\$SERVER_PORT" -bind "\$SERVER_BIND_IP" "\$@" +LAUNCHER + chmod +x "$INSTALL_DIR/minecraft-lce-server" +} + +BUILD_DIR="$SOURCE_DIR/build/windows64-clang" +mkdir -p "$BUILD_DIR" +info "LegacyEvolved LCE v$VERSION build script" +info "Source: $SOURCE_DIR | Type: $BUILD_TYPE" +echo "" +check_deps +fetch_winsdk +patch_winsdk_symlinks +do_cmake_configure +do_build +do_install