diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..c7def876 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,8 @@ +build/ +cmake-build-*/ +out/ +.cache/ +result +bin/Cemu_* +bin/*.pdb +bin/*.ilk diff --git a/BUILD.md b/BUILD.md index 6e1a2be9..2a452f96 100644 --- a/BUILD.md +++ b/BUILD.md @@ -15,6 +15,8 @@ - [Troubleshooting Steps](#troubleshooting-steps) - [Compiling Errors](#compiling-errors) - [Building Errors](#building-errors) +- [Nix](#nix) +- [Docker](#docker) - [macOS](#macos) - [Installing brew](#installing-brew) - [Installing Tool Dependencies](#installing-tool-dependencies) @@ -131,6 +133,32 @@ This section refers to running `cmake -S...` (truncated). If you are getting a different error than any of the errors listed above, you may either open an issue in this repo or try using [GCC](#gcc). Make sure your standard library and compilers are updated since Cemu uses a lot of modern features! +## Nix + +The repository includes a flake that provides a reproducible Linux build and development shell. It uses Nixpkgs for the native dependencies and does not invoke vcpkg. + +From the CemuExtend directory: + +``` +nix develop +cmake -S . -B build/nix -G Ninja -DCMAKE_BUILD_TYPE=Debug -DENABLE_VCPKG=OFF -DALLOW_PORTABLE=OFF +cmake --build build/nix --parallel +``` + +The development build is written to `bin/Cemu_debug`. To build the packaged Nix output instead, run `nix build .#cemu-extend`; the executable is available as `result/bin/cemu`. + +## Docker + +The Dockerfile uses CemuExtend's vcpkg manifest and initializes all git submodules inside the image. Build from the CemuExtend directory: + +``` +git submodule update --init --recursive +docker build -t cemu-extend:build . +docker run --rm -it cemu-extend:build +``` + +The default image performs a Release build. Use `--build-arg BUILD_TYPE=Debug` for a Debug build. The compiled executable is at `/workspace/CemuExtend/bin/Cemu_release` (or `Cemu_debug`) inside the container. To create only the dependency-enabled development image without compiling, use `docker build --target dev -t cemu-extend:dev .`. + ##### Building Errors diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..67236269 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,97 @@ +# syntax=docker/dockerfile:1 + +FROM ubuntu:24.04 AS cemu-extend-base + +ARG DEBIAN_FRONTEND=noninteractive + +ENV LANG=C.UTF-8 \ + LC_ALL=C.UTF-8 \ + VCPKG_FORCE_SYSTEM_BINARIES=1 \ + VCPKG_DEFAULT_BINARY_CACHE=/root/.cache/vcpkg/archives + +RUN apt-get update \ + && apt-get install --no-install-recommends -y \ + build-essential \ + ca-certificates \ + clang \ + cmake \ + curl \ + file \ + freeglut3-dev \ + git \ + libasound2-dev \ + libbluetooth-dev \ + libdbus-1-dev \ + libdrm-dev \ + libegl1-mesa-dev \ + libgcrypt20-dev \ + libgbm-dev \ + libgl1-mesa-dev \ + libglu1-mesa-dev \ + libgtk-3-dev \ + libpulse-dev \ + libsecret-1-dev \ + libssl-dev \ + libsystemd-dev \ + libtool \ + libudev-dev \ + libusb-1.0-0-dev \ + libwayland-dev \ + libx11-dev \ + libx11-xcb-dev \ + libxcursor-dev \ + libxext-dev \ + libxfixes-dev \ + libxi-dev \ + libxinerama-dev \ + libxkbcommon-dev \ + libxrandr-dev \ + libxrender-dev \ + libxtst-dev \ + nasm \ + ninja-build \ + pkg-config \ + python3 \ + unzip \ + wayland-protocols \ + zip \ + && rm -rf /var/lib/apt/lists/* + +RUN mkdir -p "$VCPKG_DEFAULT_BINARY_CACHE" + +RUN apt-get update \ + && apt-get install --no-install-recommends -y \ + autoconf \ + autoconf-archive \ + automake \ + libglm-dev \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /workspace/CemuExtend +COPY . . + +# CemuExtend keeps most third-party sources in git submodules. Initializing +# them here also makes a checkout with empty submodule directories usable as a +# Docker build context. +RUN test -e .git \ + && git submodule update --init --recursive \ + && bash ./dependencies/vcpkg/bootstrap-vcpkg.sh -disableMetrics + +FROM cemu-extend-base AS dev + +CMD ["bash"] + +FROM dev AS build + +ARG BUILD_TYPE=Release + +RUN --mount=type=cache,target=/root/.cache/vcpkg/archives \ + cmake -S . -B build/docker \ + -G Ninja \ + -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \ + -DENABLE_VCPKG=ON \ + -DALLOW_PORTABLE=OFF \ + -DVCPKG_INSTALL_OPTIONS=--clean-after-build \ + && cmake --build build/docker --parallel + +CMD ["bash"] diff --git a/flake.lock b/flake.lock new file mode 100644 index 00000000..07f6bef8 --- /dev/null +++ b/flake.lock @@ -0,0 +1,45 @@ +{ + "nodes": { + "imgui-src": { + "flake": false, + "locked": { + "lastModified": 1728049365, + "narHash": "sha256-J4gz4rnydu8JlzqNC/OIoVoRcgeFd6B1Qboxu5drOKY=", + "owner": "ocornut", + "repo": "imgui", + "rev": "cb16568fca5297512ff6a8f3b877f461c4323fbe", + "type": "github" + }, + "original": { + "owner": "ocornut", + "ref": "v1.91.3", + "repo": "imgui", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1783856661, + "narHash": "sha256-ZGP04e+Q6WyQJGA9ZvI5CL6+heGQldbAG9U1T9NGvmU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "569d578509928497eddc3fdbf94a799027050be4", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-26.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "imgui-src": "imgui-src", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 00000000..8835ec9b --- /dev/null +++ b/flake.nix @@ -0,0 +1,204 @@ +{ + description = "CemuExtend Nix build environment"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05"; + + # Cemu expects the complete Dear ImGui source tree, not only installed + # headers. Keep it as an explicit input so the flake also works when the + # git submodules in a checkout have not been initialized yet. + imgui-src = { + url = "github:ocornut/imgui/v1.91.3"; + flake = false; + }; + }; + + outputs = + inputs@{ + self, + nixpkgs, + imgui-src, + ... + }: + let + system = "x86_64-linux"; + pkgs = import nixpkgs { inherit system; }; + lib = pkgs.lib; + + # Keep the Nix source small and reproducible. Dependencies that are + # supplied by Nixpkgs are deliberately omitted and linked in + # preConfigure below where Cemu expects a vendored source tree. + source = lib.fileset.toSource { + root = ./.; + fileset = lib.fileset.unions [ + ./CMakeLists.txt + ./bin/gameProfiles/default + ./bin/resources + ./cmake + ./dependencies/DirectX_2010 + ./dependencies/gamemode + ./dependencies/ih264d + ./dist + ./src + ]; + }; + + # glslang's CMake package refers to SPIRV-Tools-opt before it is + # otherwise loaded. This is the same initialization used by the + # cemu_pinkd reference flake. + devCmakeInit = pkgs.writeText "cemu-extend-nix-init.cmake" '' + if(NOT TARGET SPIRV-Tools-opt) + find_package(SPIRV-Tools-opt REQUIRED) + endif() + ''; + + cemu = pkgs.stdenv.mkDerivation { + pname = "cemu-extend"; + version = "2.0-${self.shortRev or "dirty"}"; + src = source; + + nativeBuildInputs = with pkgs; [ + addDriverRunpath + cmake + nasm + ninja + pkg-config + wayland-scanner + wrapGAppsHook3 + wxwidgets_3_3 + ]; + + buildInputs = with pkgs; [ + bluez + boost + cubeb + curl + fmt_12 + glm + glslang + gtk3 + hidapi + libGL + libGLU + libpng + libusb1 + libxrender + libzip + openssl + pugixml + rapidjson + sdl3 + spirv-tools + vulkan-headers + vulkan-loader + wayland + wayland-protocols + wxwidgets_3_3 + libx11 + libxrender + zarchive + zlib + zstd + ]; + + cmakeFlags = [ + (lib.cmakeBool "ALLOW_PORTABLE" false) + (lib.cmakeBool "ENABLE_FERAL_GAMEMODE" true) + (lib.cmakeBool "ENABLE_VCPKG" false) + (lib.cmakeFeature "CMAKE_PROJECT_INCLUDE" (toString devCmakeInit)) + (lib.cmakeFeature "EMULATOR_VERSION_MAJOR" "2") + (lib.cmakeFeature "EMULATOR_VERSION_MINOR" "0") + ]; + + postPatch = '' + # The Nixpkgs wxWidgets package exposes wx-config rather than the + # vcpkg wxWidgets::wxWidgets target. The module already creates a + # complete wx::base interface target in this case, so provide the + # compatibility alias expected by CemuExtend. + substituteInPlace cmake/FindwxWidgets.cmake \ + --replace-fail \ + ' find_package_handle_standard_args(wxWidgets' \ + ' if (NOT TARGET wxWidgets::wxWidgets AND TARGET wx::base) + add_library(wxWidgets::wxWidgets ALIAS wx::base) + endif() + + find_package_handle_standard_args(wxWidgets' + ''; + + preConfigure = '' + rm -rf dependencies/imgui dependencies/Vulkan-Headers + ln -s ${imgui-src} dependencies/imgui + ln -s ${pkgs.vulkan-headers} dependencies/Vulkan-Headers + + substituteInPlace dependencies/gamemode/lib/gamemode_client.h \ + --replace-fail "libgamemode.so.0" \ + "${pkgs.gamemode.lib}/lib/libgamemode.so.0" + ''; + + installPhase = '' + runHook preInstall + + install -Dm755 ../bin/Cemu_release $out/bin/Cemu + ln -s Cemu $out/bin/cemu + + install -d $out/share/Cemu + cp -r ../bin/resources ../bin/gameProfiles $out/share/Cemu/ + + install -d $out/share/applications + substitute ../dist/linux/info.cemu.Cemu.desktop \ + $out/share/applications/info.cemu.Cemu.desktop \ + --replace-fail "Exec=Cemu" "Exec=$out/bin/cemu" + + install -Dm644 ../dist/linux/info.cemu.Cemu.metainfo.xml \ + $out/share/metainfo/info.cemu.Cemu.metainfo.xml + install -Dm644 ../src/resource/logo_icon.png \ + $out/share/icons/hicolor/128x128/apps/info.cemu.Cemu.png + + runHook postInstall + ''; + + preFixup = '' + gappsWrapperArgs+=( + --prefix LD_LIBRARY_PATH : "${lib.makeLibraryPath [ pkgs.vulkan-loader ]}" + ) + ''; + + strictDeps = true; + enableParallelBuilding = true; + + meta = { + description = "CemuExtend Wii U emulator build for NixOS"; + homepage = "https://github.com/fooly9858/CemuExtend"; + license = lib.licenses.mpl20; + mainProgram = "cemu"; + platforms = [ system ]; + }; + }; + in + { + packages.${system} = { + default = cemu; + cemu-extend = cemu; + }; + + apps.${system}.default = { + type = "app"; + program = lib.getExe cemu; + meta.description = "Run CemuExtend"; + }; + + devShells.${system}.default = pkgs.mkShell { + inputsFrom = [ cemu ]; + packages = [ pkgs.git ]; + CMAKE_PROJECT_INCLUDE = devCmakeInit; + + shellHook = '' + echo "CemuExtend Nix development shell" + echo "Configure with: cmake -S . -B build/nix -G Ninja -DCMAKE_BUILD_TYPE=Debug -DENABLE_VCPKG=OFF -DALLOW_PORTABLE=OFF" + ''; + }; + + checks.${system}.default = cemu; + formatter.${system} = pkgs.nixfmt; + }; +} diff --git a/src/imgui/imgui_extension.cpp b/src/imgui/imgui_extension.cpp index eb0e31ef..a3217b00 100644 --- a/src/imgui/imgui_extension.cpp +++ b/src/imgui/imgui_extension.cpp @@ -133,8 +133,6 @@ void ImGui_UpdateWindowInformation(bool mainWindow) io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; #if BOOST_OS_WINDOWS io.ImeWindowHandle = mainWindow ? windowInfo.window_main.surface : windowInfo.window_pad.surface; -#else - io.ImeWindowHandle = nullptr; #endif io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);