diff --git a/.github/workflows/cachix-install-nix-action.yml b/.github/workflows/cachix-install-nix-action.yml new file mode 100644 index 000000000..daa6d5cdc --- /dev/null +++ b/.github/workflows/cachix-install-nix-action.yml @@ -0,0 +1,34 @@ +name: Nix Flake actions + +on: + pull_request: + push: + +jobs: + nix-matrix: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} + steps: + - uses: actions/checkout@v4 + - uses: cachix/install-nix-action@v30 + - id: set-matrix + name: Generate Nix Matrix + run: | + set -Eeu + matrix="$(nix eval --json '.#githubActions.matrix')" + echo "matrix=$matrix" >> "$GITHUB_OUTPUT" + + nix-build: + name: ${{ matrix.name }} (${{ matrix.system }}) + needs: nix-matrix + runs-on: ${{ matrix.os }} + strategy: + matrix: ${{fromJSON(needs.nix-matrix.outputs.matrix)}} + steps: + - uses: actions/checkout@v4 + - uses: n1hility/cancel-previous-runs@v2 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - uses: cachix/install-nix-action@v30 + - run: nix build -L '.#${{ matrix.attr }}' diff --git a/Makefile b/Makefile index 553b99a24..be1a87291 100644 --- a/Makefile +++ b/Makefile @@ -5,10 +5,12 @@ CROSS ?= none UNAME_S := $(shell uname -s) UNAME_M := $(shell uname -m) -rwildcard=$(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2)) +rwildcard = $(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2)) CC_IS_CLANG := $(shell $(CC) --version | grep -q clang && echo true || echo false) -PACKAGES := capstone freetype2 glfw3 libavcodec libavformat libavutil libswresample libuv zlib libcurl +PACKAGES := capstone freetype2 glfw3 libavcodec libavformat libavutil libswresample libcurl libuv zlib +OPTIONAL_PACKAGES := md4c fmt libllhttp libluv liburiparser +OPTIONAL_LIBRARIES := multipart ucl LOCALES := el es_ES fr ja pt_BR uk zh_CN @@ -19,12 +21,11 @@ HAS_SUBMODULES = true endif CXXFLAGS += -std=c++2b -CPPFLAGS += `pkg-config --cflags $(PACKAGES)` CPPFLAGS += -I. CPPFLAGS += -Isrc CPPFLAGS += -Ithird_party CPPFLAGS += -Ithird_party/ELFIO -CPPFLAGS += -Ithird_party/fmt/include/ +CPPFLAGS_pkg_fmt += -Ithird_party/fmt/include/ CPPFLAGS += -Ithird_party/gl3w CPPFLAGS += -Ithird_party/googletest/googletest/include CPPFLAGS += -Ithird_party/imgui @@ -32,16 +33,16 @@ CPPFLAGS += -Ithird_party/imgui/backends CPPFLAGS += -Ithird_party/imgui/examples CPPFLAGS += -Ithird_party/imgui/misc/cpp CPPFLAGS += -Ithird_party/libelfin -CPPFLAGS += -Ithird_party/llhttp +CPPFLAGS_pkg_libllhttp += -Ithird_party/llhttp CPPFLAGS += -Ithird_party/luajit/src -CPPFLAGS += -Ithird_party/luv/src -CPPFLAGS += -Ithird_party/luv/deps/lua-compat-5.3/c-api +CPPFLAGS_pkg_libluv += -Ithird_party/luv/src +CPPFLAGS_pkg_libluv += -Ithird_party/luv/deps/lua-compat-5.3/c-api CPPFLAGS += -Ithird_party/magic_enum/include/magic_enum -CPPFLAGS += -Ithird_party/md4c/src -CPPFLAGS += -Ithird_party/multipart-parser-c +CPPFLAGS_pkg_md4c += -Ithird_party/md4c/src +CPPFLAGS_lib_multipart += -Ithird_party/multipart-parser-c CPPFLAGS += -Ithird_party/tracy/public -CPPFLAGS += -Ithird_party/ucl -Ithird_party/ucl/include -CPPFLAGS += -Ithird_party/uriparser/include +CPPFLAGS_lib_ucl += -Ithird_party/ucl -Ithird_party/ucl/include +CPPFLAGS_pkg_liburiparser += -Ithird_party/uriparser/include CPPFLAGS += -Ithird_party/zep/extensions CPPFLAGS += -Ithird_party/zep/include CPPFLAGS += -Ithird_party/xbyak/xbyak @@ -75,7 +76,6 @@ ifeq ($(UNAME_S),Darwin) endif LUAJIT_LDFLAGS := $(LDFLAGS) -LDFLAGS += `pkg-config --libs $(PACKAGES)` ifeq ($(UNAME_S),Darwin) LDFLAGS += -lc++ -framework GLUT -framework OpenGL -framework CoreFoundation -framework Cocoa @@ -108,8 +108,8 @@ endif LD := $(CXX) -SRCS := $(call rwildcard,src/,*.cc) -SRCS += third_party/fmt/src/os.cc third_party/fmt/src/format.cc +SRCS += $(call rwildcard,src/,*.cc) +SRCS_pkg_fmt += third_party/fmt/src/os.cc third_party/fmt/src/format.cc IMGUI_SRCS += $(wildcard third_party/imgui/*.cpp) VIXL_SRCS := $(call rwildcard, third_party/vixl/src,*.cc) SRCS += $(IMGUI_SRCS) @@ -129,16 +129,16 @@ SRCS += third_party/imgui/misc/freetype/imgui_freetype.cpp SRCS += third_party/imgui_lua_bindings/imgui_lua_bindings.cpp SRCS += third_party/imgui_md/imgui_md.cpp SRCS += third_party/imgui_memory_editor/imgui_memory_editor.cpp -SRCS += $(wildcard third_party/llhttp/*.c) +SRCS_pkg_libllhttp += $(wildcard third_party/llhttp/*.c) SRCS += $(wildcard third_party/lpeg/*.c) SRCS += third_party/lua-protobuf/pb.c SRCS += third_party/luafilesystem/src/lfs.c -SRCS += third_party/luv/src/luv.c -SRCS += third_party/md4c/src/md4c.c -SRCS += third_party/multipart-parser-c/multipart_parser.c +SRCS_pkg_libluv += third_party/luv/src/luv.c +SRCS_pkg_md4c += third_party/md4c/src/md4c.c +SRCS_lib_multipart += third_party/multipart-parser-c/multipart_parser.c SRCS += third_party/nanovg/src/nanovg.c -SRCS += third_party/tracy/public/TracyClient.cpp -SRCS += third_party/ucl/src/n2e_99.c third_party/ucl/src/alloc.c +SRCS_ReleaseWithTracy += third_party/tracy/public/TracyClient.cpp +SRCS_lib_ucl += third_party/ucl/src/n2e_99.c third_party/ucl/src/alloc.c SRCS += $(wildcard third_party/uriparser/src/*.c) SRCS += third_party/zep/extensions/repl/mode_repl.cpp SRCS += $(wildcard third_party/zep/src/*.cpp) @@ -176,6 +176,37 @@ TOOLS = exe2elf exe2iso modconv ps1-packer psyq-obj-parser ############################################################################## +SRCS += $(SRCS_$(BUILD)) + +define CHECK_PKG +ifeq ($(shell pkg-config --exists $(1) && echo true || echo false),true) +PACKAGES += $(1) +else +CPPFLAGS += $(CPPFLAGS_pkg_$(1)) +LDFLAGS += $(LDFLAGS_pkg_$(1)) +SRCS += $(SRCS_pkg_$(1)) +endif +endef + +define CHECK_LIB +ifeq ($(shell echo "int main(){}" | gcc -x c - -l$(1) -Wl,--no-as-needed -Wl,--unresolved-symbols=ignore-all -Wl,--no-undefined -o /dev/null >& /dev/null && echo true || echo false),true) +LDFLAGS += -l$(1) +else +CPPFLAGS += $(CPPFLAGS_lib_$(1)) +LDFLAGS += $(LDFLAGS_lib_$(1)) +SRCS += $(SRCS_lib_$(1)) +endif +endef + +$(foreach pkg,$(OPTIONAL_PACKAGES),$(eval $(call CHECK_PKG,$(pkg)))) +$(foreach lib,$(OPTIONAL_LIBRARIES),$(eval $(call CHECK_LIB,$(lib)))) + +CPPFLAGS_PKGCONFIG := $(shell pkg-config --cflags $(PACKAGES)) +LDFLAGS_PKGCONFIG := $(shell pkg-config --libs $(PACKAGES)) + +CPPFLAGS += $(CPPFLAGS_PKGCONFIG) +LDFLAGS += $(LDFLAGS_PKGCONFIG) + OBJECTS += $(patsubst %.c,%.o,$(filter %.c,$(SRCS))) OBJECTS += $(patsubst %.cc,%.o,$(filter %.cc,$(SRCS))) OBJECTS += $(patsubst %.cpp,%.o,$(filter %.cpp,$(SRCS))) diff --git a/flake.lock b/flake.lock new file mode 100644 index 000000000..a416a730e --- /dev/null +++ b/flake.lock @@ -0,0 +1,48 @@ +{ + "nodes": { + "nix-github-actions": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1737420293, + "narHash": "sha256-F1G5ifvqTpJq7fdkT34e/Jy9VCyzd5XfJ9TO8fHhJWE=", + "owner": "nix-community", + "repo": "nix-github-actions", + "rev": "f4158fa080ef4503c8f4c820967d946c2af31ec9", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-github-actions", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1739020877, + "narHash": "sha256-mIvECo/NNdJJ/bXjNqIh8yeoSjVLAuDuTUzAo7dzs8Y=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "a79cfe0ebd24952b580b1cf08cd906354996d547", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nix-github-actions": "nix-github-actions", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 000000000..ff3079aeb --- /dev/null +++ b/flake.nix @@ -0,0 +1,41 @@ +{ + description = "PlayStation 1 emulator and debugger"; + + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + nix-github-actions.url = "github:nix-community/nix-github-actions"; + nix-github-actions.inputs.nixpkgs.follows = "nixpkgs"; + }; + + outputs = { + self, + nixpkgs, + nix-github-actions + }: + let + lib = nixpkgs.lib; + # githubSystems = builtins.attrNames nix-github-actions.lib.githubPlatforms; + # forAllSystems = lib.genAttrs lib.systems.flakeExposed; + # forGithubSystems = lib.genAttrs githubSystems; + # TODO: githubSystems should be supportedSystems intersects lib.githubPlatforms + # Some of the dependencies don't build on clang. Will fix later + supportedSystems = [ "x86_64-linux" "aarch64-linux" ]; + forAllSystems = lib.genAttrs supportedSystems; + forGithubSystems = lib.genAttrs supportedSystems; + in { + packages = forAllSystems (system: + let pkgs = import nixpkgs { inherit system; }; + in { + pcsx-redux = pkgs.callPackage ./pcsx-redux.nix { + src = self; + platforms = lib.systems.flakeExposed; + }; + # FIXME: default gets duplicated in githubActions + # default = self.packages.${system}.pcsx-redux; + }); + + githubActions = nix-github-actions.lib.mkGithubMatrix { + checks = forGithubSystems (system: self.packages.${system}); + }; + }; +} diff --git a/pcsx-redux.nix b/pcsx-redux.nix new file mode 100644 index 000000000..cea4fb521 --- /dev/null +++ b/pcsx-redux.nix @@ -0,0 +1,187 @@ +{ + stdenv, + lib, + fetchFromGitHub, + libuv, + zlib, + curl, + ffmpeg, + glfw3, + capstone, + freetype, + libX11, + pkg-config, + imagemagick, + luajitPackages, + multipart-parser-c, + fmt, + magic-enum, + miniaudio, + gtest, + tl-expected, + elfio, + tracy, + md4c, + stb, + uriparser, + ucl, + llhttp, + + src, + debugBuild ? false, + platforms, +}: +let + zep = fetchFromGitHub { + owner = "grumpycoders"; + repo = "zep"; + rev = "86ea3c7019f45ccd4a13503bf7d98a396e8f0193"; + hash = "sha256-6NmUlOHkRQvCgbATcNxnFrfA2ZWROPYN8Vpd10k6Z2g="; + }; + nanosvg = fetchFromGitHub { + owner = "grumpycoders"; + repo = "nanosvg"; + rev = "f0a3e1034dd22e2e87e5db22401e44998383124e"; + hash = "sha256-af11kAga6Ru2rPgrfcYswXNy9etvH3J9FX2T0I0++ew="; + }; + nanovg = fetchFromGitHub { + owner = "grumpycoders"; + repo = "nanovg"; + rev = "7c021819bbd4843a1a3091fe47346d3fcb2a3e1a"; + hash = "sha256-gZHbNuDkLXlLlXZZpLBHcbwzTfeBBkLY7xl4L5yr2lY="; + }; + vixl = fetchFromGitHub { + owner = "grumpycoders"; + repo = "vixl"; + rev = "53ad192b26ddf6edd228a24ae1cffc363b442c01"; + hash = "sha256-p9Z2lFzhqnHnFWfqT6BIJBVw2ZpkVIxykhG3jUHXA84="; + }; + imgui-md = fetchFromGitHub { + owner = "mekhontsev"; + repo = "imgui_md"; + rev = "8ca75c5f7663f314821e3d0b2c51011792bee68f"; + hash = "sha256-uxhY81DWLRRCceYn9khk3rwzT+2f9PNMIMT9OrkPfFc="; + }; + xbyak = fetchFromGitHub { + owner = "herumi"; + repo = "xbyak"; + rev = "2fb843c3287918038c8f76276a590c25cc7ec5ee"; + hash = "sha256-XZce+kEZ7dipI19WY43ycOjzM2dZyANMEN5+GhoNYUk="; + }; + luafs = fetchFromGitHub { + owner = "lunarmodules"; + repo = "luafilesystem"; + rev = "912e06714fc276c15b4d5d1b42bd2b11edb8deff"; + hash = "sha256-BShByo2NhVrOHDPze/JXfeFWq36PFrI2HVugR2MDB0A="; + }; + luajit = fetchFromGitHub { + owner = "grumpycoders"; + repo = "luajit"; + rev = "66fadd16a51955cfbd770de62806cfbdd7c6c818"; + hash = "sha256-nFlDr79GC8MsL6ausAsEPJwL8OJrFydB37tpD5mS1C8="; + }; + imgui = fetchFromGitHub { + owner = "ocornut"; + repo = "imgui"; + rev = "368123ab06b2b573d585e52f84cd782c5c006697"; + hash = "sha256-6VOs7a31bEfAG75SQAY2X90h/f/HvqZmN615WXYkUOA="; + }; + sdl-db = fetchFromGitHub { + owner = "mdqinc"; + repo = "SDL_GameControllerDB"; + rev = "b1e342774cbb35467dfdd3634d4f0181a76cbc89"; + hash = "sha256-LYvO+chDVo6D++fuFbxqSRltGW3y82SESmtFj39TdSA="; + }; +in stdenv.mkDerivation { + pname = "pcsx-redux"; + version = "0.99test"; + inherit src; + + postUnpack = '' + rm -rf source/third_party/miniaudio + rm -rf source/third_party/zep + rm -rf source/third_party/nanosvg + rm -rf source/third_party/nanovg + rm -rf source/third_party/imgui + rm -rf source/third_party/imgui_md + rm -rf source/third_party/xbyak + rm -rf source/third_party/luafilesystem + rm -rf source/third_party/SDL_GameControllerDB + rm -rf source/third_party/tracy + rm -rf source/third_party/luajit + + cp -r ${miniaudio.out} source/third_party/miniaudio + cp -r ${zep.out} source/third_party/zep + cp -r ${nanosvg.out} source/third_party/nanosvg + cp -r ${nanovg.out} source/third_party/nanovg + cp -r ${imgui.out} source/third_party/imgui + cp -r ${imgui-md.out} source/third_party/imgui_md + cp -r ${xbyak.out} source/third_party/xbyak + cp -r ${luafs.out} source/third_party/luafilesystem + cp -r ${sdl-db.out} source/third_party/SDL_GameControllerDB + cp -r ${tracy.src} source/third_party/tracy + cp -r ${luajit.out} source/third_party/luajit + + chmod -R +w source/third_party/miniaudio + chmod -R +w source/third_party/zep + chmod -R +w source/third_party/nanosvg + chmod -R +w source/third_party/nanovg + chmod -R +w source/third_party/imgui + chmod -R +w source/third_party/imgui_md + chmod -R +w source/third_party/luafilesystem + chmod -R +w source/third_party/SDL_GameControllerDB + chmod -R +w source/third_party/tracy + chmod -R +w source/third_party/luajit + '' + + lib.optionalString stdenv.hostPlatform.isAarch '' + cp -r ${vixl.out} source/third_party/vixl + chmod -R +w source/third_party/vixl + ''; + + nativeBuildInputs = [ + pkg-config + imagemagick + ]; + + buildInputs = [ + stb + ucl + md4c + luajitPackages.libluv + multipart-parser-c + fmt + magic-enum + gtest + tl-expected + elfio + libuv + tracy + curl.dev + zlib + ffmpeg.dev + glfw3 + capstone + freetype.dev + uriparser + libX11 + llhttp + ]; + + makeFlags = [ + "DESTDIR=$(out)" + ]; + + # TODO: learn how to use separate debug info + dontStrip = debugBuild; + enableDebugging = debugBuild; + + enableParallelBuilding = true; + NIX_BUILD_CORES = 2; + + meta = { + homepage = "https://pcsx-redux.consoledev.net"; + description = "PlayStation 1 emulator and debugger"; + mainProgram = "pcsx-redux"; + inherit platforms; + }; +}