diff --git a/CMakeLists.txt b/CMakeLists.txt index 76c47083..3a8257ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,11 +96,62 @@ if(PLATFORM_NAME STREQUAL "Windows64") endif() list(APPEND MINECRAFT_SHARED_DEFINES ${PLATFORM_DEFINES}) +# handle fxc shader compilation on non-windows platforms +if(CMAKE_HOST_UNIX AND CMAKE_CROSSCOMPILING AND PLATFORM_NAME STREQUAL "Windows64") + set(_LCE_FXC_CANDIDATES + "${CMAKE_SOURCE_DIR}/Minecraft.Client/Windows64/Shaders/fxc.exe" + "${CMAKE_SOURCE_DIR}/Minecraft.Client/Windows64/4JLibs/impls/Windows_Libs/Render/shaders/fxc.exe" + ) + + unset(LCE_FXC_EXE) + foreach(_LCE_FXC_CANDIDATE IN LISTS _LCE_FXC_CANDIDATES) + if(EXISTS "${_LCE_FXC_CANDIDATE}") + set(LCE_FXC_EXE "${_LCE_FXC_CANDIDATE}") + break() + endif() + endforeach() + + if(LCE_FXC_EXE) + find_program(LCE_WINE_PROGRAM NAMES wine) + if(NOT LCE_WINE_PROGRAM) + message(FATAL_ERROR "Found fxc.exe at '${LCE_FXC_EXE}', but could not find wine in the system PATH.") + endif() + + set(_LCE_FXC_WRAPPER_DIR "${CMAKE_BINARY_DIR}/tools") + set(_LCE_FXC_WRAPPER "${_LCE_FXC_WRAPPER_DIR}/fxc") + file(MAKE_DIRECTORY "${_LCE_FXC_WRAPPER_DIR}") + configure_file( + "${CMAKE_SOURCE_DIR}/cmake/FxcWineWrapper.sh.in" + "${_LCE_FXC_WRAPPER}" + @ONLY + ) + file(CHMOD "${_LCE_FXC_WRAPPER}" + PERMISSIONS + OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE + WORLD_READ WORLD_EXECUTE + ) + + set(FXC_COMPILER "${_LCE_FXC_WRAPPER}" CACHE FILEPATH "Path to FXC compiler" FORCE) + message(STATUS "Translating FXC through Wine: ${LCE_WINE_PROGRAM} ${LCE_FXC_EXE}") + endif() +endif() + # --- # Sources # --- add_subdirectory("Minecraft.Client/${PLATFORM_NAME}/4JLibs") +if(CMAKE_CROSSCOMPILING AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + # clang apparently doesnt like whatever __m128 is so we gotta define it manually + if(TARGET 4JLibs.${PLATFORM_NAME}.Render) + target_compile_definitions(4JLibs.${PLATFORM_NAME}.Render PRIVATE + _XM_NO_INTRINSICS_ + m128_f32=vector4_f32 + ) + endif() +endif() + add_subdirectory(Minecraft.World) add_subdirectory(Minecraft.Client) if(PLATFORM_NAME STREQUAL "Windows64") # Server is only supported on Windows for now diff --git a/Minecraft.Client/Windows64/Shaders/fxc.exe b/Minecraft.Client/Windows64/Shaders/fxc.exe new file mode 100755 index 00000000..9d5e3e73 Binary files /dev/null and b/Minecraft.Client/Windows64/Shaders/fxc.exe differ diff --git a/build-linux.sh b/build-linux.sh index 7669646b..d5357932 100755 --- a/build-linux.sh +++ b/build-linux.sh @@ -17,7 +17,7 @@ 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) + local deps=(clang-cl lld-link llvm-rc llvm-ml llvm-lib llvm-mt cmake ninja xwin rsync wine) for dep in "${deps[@]}"; do command -v "$dep" &>/dev/null || missing+=("$dep") done diff --git a/cmake/FxcWineWrapper.sh.in b/cmake/FxcWineWrapper.sh.in new file mode 100644 index 00000000..6a744fd0 --- /dev/null +++ b/cmake/FxcWineWrapper.sh.in @@ -0,0 +1,68 @@ +#!/usr/bin/env bash +set -euo pipefail + +map_to_windows_path() { + local v="$1" + if [[ "$v" == /*/* ]]; then + winepath -w "$v" 2>/dev/null || printf '%s' "$v" + else + printf '%s' "$v" + fi +} + +args=() +out_header="" +expect_out_header=0 +for arg in "$@"; do + if [[ "$expect_out_header" -eq 1 ]]; then + out_header="$arg" + expect_out_header=0 + elif [[ "$arg" == "/Fh" ]]; then + expect_out_header=1 + fi + + args+=("$(map_to_windows_path "$arg")") +done + +"@LCE_WINE_PROGRAM@" "@LCE_FXC_EXE@" "${args[@]}" +status=$? + +if [[ "$status" -eq 0 && -n "$out_header" && -f "$out_header" ]]; then + tmp="${out_header}.tmp.$$" + # normalize CRLF and #endif arguments + LC_ALL=C awk ' + BEGIN { + has_if0 = 0 + has_endif = 0 + inserted = 0 + } + { + sub(/\r$/, "") + + if (index($0, "#if 0") == 1) { + has_if0 = 1 + } + + if (index($0, "#endif") > 0) { + print "#endif" + has_endif = 1 + next + } + + if (has_if0 && !has_endif && !inserted && index($0, "const BYTE ") == 1) { + print "#endif" + inserted = 1 + has_endif = 1 + } + + print $0 + } + END { + if (has_if0 && !has_endif) { + print "#endif" + } + } + ' "$out_header" > "$tmp" && mv "$tmp" "$out_header" +fi + +exit "$status"