diff --git a/.clang-tidy b/.clang-tidy index 9534cad..78808f9 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -51,4 +51,6 @@ CheckOptions: readability-identifier-naming.NamespaceCase: lower_case readability-identifier-naming.ParameterCase: lower_case readability-identifier-naming.VariableCase: lower_case + + readability-identifier-length.IgnoredVariableNames: _ --- diff --git a/.cruft.json b/.cruft.json index 1fdb0f9..f7b7e7a 100644 --- a/.cruft.json +++ b/.cruft.json @@ -1,6 +1,6 @@ { "template": "git@github.com:bl-sdk/common_dotfiles.git", - "commit": "d03eee713ad436d20033d0598eb88f1529c56ca8", + "commit": "cee5c9dbf5b95f57bb636e5138171aa6a4964cf1", "checkout": null, "context": { "cookiecutter": { @@ -15,7 +15,8 @@ "__project_slug": "pyunrealsdk", "include_cpp": true, "include_py": true, - "_template": "git@github.com:bl-sdk/common_dotfiles.git" + "_template": "git@github.com:bl-sdk/common_dotfiles.git", + "_commit": "cee5c9dbf5b95f57bb636e5138171aa6a4964cf1" } }, "directory": null diff --git a/.devcontainer/.gitignore b/.devcontainer/.gitignore new file mode 100644 index 0000000..670808b --- /dev/null +++ b/.devcontainer/.gitignore @@ -0,0 +1,6 @@ +# Ignore any custom folders outside of our predefined ones, to let you create your own +# One use might be using your own container mapping the install path onto your actual game folder +*/ +!clang-cross +!llvm-mingw +!mingw diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..a9aeee4 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,65 @@ +FROM alpine:latest AS clang-cross +CMD ["/bin/bash"] +RUN <> $GITHUB_PATH - - - name: Setup MinGW - if: startswith(matrix.preset, 'mingw') - uses: egor-tensin/setup-mingw@v2 - with: - platform: ${{ fromJSON('["x86", "x64"]')[contains(matrix.preset, 'x64')] }} - - - name: Setup Clang - if: startswith(matrix.preset, 'clang-cross') - uses: egor-tensin/setup-clang@v1 - - - name: Restore win sdk cache - if: startswith(matrix.preset, 'clang-cross') - uses: actions/cache@v4 - id: cache-win-sdk - with: - path: ~/win-sdk - key: ${{ runner.os }}-win-sdk - - - name: Setup win sdk - if: startswith(matrix.preset, 'clang-cross') && steps.cache-win-sdk.outputs.cache-hit != 'true' - run: | - git clone https://github.com/mstorsjo/msvc-wine.git - msvc-wine/vsdownload.py --accept-license --dest ~/win-sdk Microsoft.VisualStudio.Workload.VCTools - msvc-wine/install.sh ~/win-sdk - rm -r msvc-wine - - - name: Checkout repository and submodules - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Configure CMake - working-directory: ${{ env.GITHUB_WORKSPACE }} - # The extra msvc wine arg won't do anything if we're not cross compiling - run: > - cmake . - --preset ${{ matrix.preset }} - -G Ninja - -DMSVC_WINE_ENV_SCRIPT=$(readlink -f ~)/win-sdk/bin/${{ fromJSON('["x86", "x64"]')[contains(matrix.preset, 'x64')] }}/msvcenv.sh - - - name: Build - working-directory: ${{ env.GITHUB_WORKSPACE }} - run: cmake --build out/build/${{ matrix.preset }} + - name: Checkout repository and submodules + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Build + uses: devcontainers/ci@v0.3 + with: + cacheFrom: ghcr.io/bl-sdk/${{ matrix.toolchain.container }}:latest + configFile: .devcontainer/${{ matrix.toolchain.container }}/devcontainer.json + push: never + # The git watcher cmake thinks something's unsafe? Doesn't happen to me locally. + runCmd: | + git config --global --add safe.directory `pwd` + git config --global --add safe.directory `pwd`/libs/unrealsdk + + cmake . --preset ${{ matrix.toolchain.preset }} -G Ninja + cmake --build out/build/${{ matrix.toolchain.preset }} # ============================================================================== diff --git a/.gitignore b/.gitignore index e3ebb96..bc2e1e9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .vs .vscode +.idea # C/C++ excludes .cache/clangd diff --git a/CMakePresets.json b/CMakePresets.json index 54de933..efe923b 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -40,6 +40,9 @@ "lhs": "${hostSystemName}", "rhs": "Windows" }, + "environment": { + "MSVC_WINE_ENV_SCRIPT": "/win-sdk/bin/x86/msvcenv.sh" + }, "toolchainFile": "common_cmake/clang-cross-x86.cmake" }, { @@ -50,6 +53,9 @@ "lhs": "${hostSystemName}", "rhs": "Windows" }, + "environment": { + "MSVC_WINE_ENV_SCRIPT": "/win-sdk/bin/x64/msvcenv.sh" + }, "toolchainFile": "common_cmake/clang-cross-x64.cmake" }, { diff --git a/Readme.md b/Readme.md index 52ebd13..09f9597 100644 --- a/Readme.md +++ b/Readme.md @@ -98,54 +98,54 @@ To use it: Note that the sdk disables the integration if it's unable to import debugpy on first use, meaning you may not get away with manipulating `sys.path`. Instead, consider using [`._pth` files](https://docs.python.org/3/library/sys_path_init.html). -# Installation -1. Download the relevant [release](https://github.com/bl-sdk/pyunrealsdk/releases). - - If you don't know which compiler's version to get, we recommend MSVC (so functions log messages - include namespaces). - -2. Install some game specific plugin loader. The released dlls are not set up to alias any system - dlls, you can't just call it `d3d9.dll` and assume your game will load fine. - - If you know a specific dll name is fine to use without aliasing, rename `pyunrealsdk.dll`. - -3. Extract all files to somewhere in your game's dll search path. Your plugin loader's plugins - folder may work, otherwise you can fall back to the same directory as the executable. - # Development -To build: +The sdk can be built with one of five different toolchains, each of which have a few different +configurations: + +- MSVC +- Clang (Windows) +- Clang (Cross Compile) * +- MinGW * +- LLVM MinGW * + +The toolchains with an asterix are all cross compiling toolchains. These all also have an associated +dev container, which is the recommended way of building them. The `clang-cross-*` presets in +particular hardcode a path assuming they're running in the container. + +The sdk is always built as a Windows dll. To allow the cross compiling toolchains to link against a +Windows copy of Python, rather than using CMake's normal `FindPython` helpers, when configuring we +download a copy from Python's site. When integrating the sdk into your own projects, exactly which +version can be specified using the `EXPLICIT_PYTHON_ARCH` and `EXPLICIT_PYTHON_VERSION` variables. +The CMake presets already have these set if building locally. + +To download the relevant python version, you need a copy of Python with requests on your path. When +cross compiling you also need `msiextract`, which is typically part of an `msitools` package. The +dev containers already have these set up. +```sh +pip install requests +python -c 'import requests' + +# Linux only +apt install msitools # Or equivalent +msiextract --version +``` + +Once you've got this all set up, to build the sdk: 1. Clone the repo (including submodules). ```sh git clone --recursive https://github.com/bl-sdk/pyunrealsdk.git ``` -2. Make sure you have Python with requests on your PATH. This doesn't need to be the same version - as what the SDK uses, it's just used by the script which downloads the correct one. - ```sh - pip install requests - python -c 'import requests' - ``` - - If not running on Windows, make sure `msiextract` is also on your PATH. This is typically part - of an `msitools` package. - ```sh - apt install msitools # Or equivalent - msiextract --version - ``` - - See the explicit python [readme](https://github.com/bl-sdk/common_cmake/blob/master/explicit_python/Readme.md) - for a few extra details. - -3. (OPTIONAL) Copy `postbuild.template`, and edit it to copy files to your game install directories. +2. (OPTIONAL) Copy `postbuild.template`, and edit it to copy files to your game install directories. -4. Choose a preset, and run CMake. Most IDEs will be able to do this for you, +3. Choose a preset, and run CMake. Most IDEs will be able to do this for you, ``` cmake . --preset msvc-ue4-x64-debug cmake --build out/build/msvc-ue4-x64-debug ``` -5. (OPTIONAL) Copy the python runtime files to the game's directory. At a minimum, you probably +4. (OPTIONAL) Copy the python runtime files to the game's directory. At a minimum, you probably want these: ``` python3.dll @@ -159,10 +159,10 @@ To build: cmake --build out/build/msvc-ue4-x64-debug --target install ``` - As an alternative to this and step 3, you could point the CMake install dir directly at your + As an alternative to this and step 2, you could point the CMake install dir directly at your game, so everything's automatically copied. This however will only work with one game at a time. -6. (OPTIONAL) If you're debugging a game on Steam, add a `steam_appid.txt` in the same folder as the +5. (OPTIONAL) If you're debugging a game on Steam, add a `steam_appid.txt` in the same folder as the executable, containing the game's Steam App Id. Normally, games compiled with Steamworks will call diff --git a/libs/unrealsdk b/libs/unrealsdk index bfe72ca..391854d 160000 --- a/libs/unrealsdk +++ b/libs/unrealsdk @@ -1 +1 @@ -Subproject commit bfe72ca0c27e100c16533834352a21d0d884afac +Subproject commit 391854d098531ab7c0fb41105752116e91cb3953 diff --git a/pyproject.toml b/pyproject.toml index ff5cd3d..84a6db9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,16 +10,9 @@ target-version = "py313" line-length = 100 [tool.ruff.lint] -# Last time rules scrutinised: ruff 0.6.9 / 2024-10-08 +# Last time rules scrutinised: ruff 0.11.0 / 2025-03-20 select = [ - "F", - "W", - "E", - "C90", - "I", - "N", - "D", - "UP", + "ERA", "YTT", "ANN", "ASYNC", @@ -31,34 +24,51 @@ select = [ "C4", "DTZ", "T10", + "FIX", "FA", + "INT", "ISC", "ICN", "LOG", "G", "PIE", + "T20", "PYI", "Q", "RSE", "RET", - "SLOT", "SIM", + "SLOT", "TID", - "TCH", - "INT", + "TD", + "TC", "ARG", "PTH", - "TD", - "FIX", - "ERA", - "PGH", - "PL", "FLY", + "I", + "C90", + "N", "PERF", + "E", + "W", + "D", + "F", + "PGH", + "PL", + "UP", "FURB", "RUF", ] ignore = [ + "ANN401", + "S101", + "S603", + "S607", + "PYI011", + "PYI021", + "PYI029", + "PYI044", + "TC006", "D100", "D101", "D104", @@ -76,16 +86,6 @@ ignore = [ "D410", "D411", "D413", - "ANN101", - "ANN102", - "ANN401", - "S101", - "S603", - "S607", - "PYI011", - "PYI021", - "PYI029", - "PYI044", "PGH003", "PLR0904", "PLR0911", @@ -100,4 +100,4 @@ ignore = [ ] [tool.ruff.lint.per-file-ignores] -"*.pyi" = ["D418", "A002", "A003"] +"*.pyi" = ["A002", "A003", "D418"] diff --git a/src/pyunrealsdk/unreal_bindings/wrapped_array_methods.cpp b/src/pyunrealsdk/unreal_bindings/wrapped_array_methods.cpp index dfa96aa..8c4eae5 100644 --- a/src/pyunrealsdk/unreal_bindings/wrapped_array_methods.cpp +++ b/src/pyunrealsdk/unreal_bindings/wrapped_array_methods.cpp @@ -105,7 +105,7 @@ size_t array_py_index(const WrappedArray& self, void array_py_insert(WrappedArray& self, py::ssize_t py_idx, const py::object& value) { auto size = self.size(); - if (static_cast(py_idx) == size) { + if (std::cmp_equal(py_idx, size)) { // We're just appending array_py_append(self, value); return; @@ -193,7 +193,7 @@ void array_py_emplace_struct(WrappedArray& self, auto size = self.size(); - if (static_cast(py_idx) >= size) { + if (std::cmp_greater_equal(py_idx, size)) { // We're just appending self.resize(size + 1); try {