mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-27 00:28:14 +00:00
Merge pull request #103 from boykopovar/feat/provide-release
Feat/provide release Added a release workflow for v* tags: build Windows and Linux, run tests, and publish only if both platforms are successful. The release contains PRX archives, relinker executables, and documentation from docs/user. The build cache is reused. - `prx-windows-v0.1.0.zip` - `prx-windows-v0.1.0.tar.gz` - `prx-linux-v0.1.0.zip` - `prx-linux-v0.1.0.tar.gz` - `relinker-v0.1.0.exe` - `relinker-v0.1.0` - `COMPATIBILITY.md` - `INPUT_MAPPING.md`
This commit is contained in:
11 files changed
+245
-54
No files matched your search
@@ -0,0 +1,111 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: ['v*']
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: release-${{ github.ref }}
|
||||
cancel-in-progress: false
|
||||
|
||||
env:
|
||||
RELEASE_TAG: ${{ github.ref_name }}
|
||||
CONFIGURE: >-
|
||||
-G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON
|
||||
-DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
WINLIBS_RELEASE: 15.2.0posix-14.0.0-ucrt-r7
|
||||
WINLIBS_ZIP: winlibs-x86_64-posix-seh-gcc-15.2.0-mingw-w64ucrt-14.0.0-r7.zip
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build and test (${{ matrix.platform }})
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
include:
|
||||
- platform: linux
|
||||
runner: ubuntu-latest
|
||||
timeout: 30
|
||||
- platform: windows
|
||||
runner: windows-latest
|
||||
timeout: 45
|
||||
runs-on: ${{ matrix.runner }}
|
||||
timeout-minutes: ${{ matrix.timeout }}
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
submodules: true
|
||||
- id: toolchain
|
||||
if: matrix.platform == 'windows'
|
||||
uses: actions/cache@v6
|
||||
with:
|
||||
path: C:\winlibs
|
||||
key: ${{ env.WINLIBS_ZIP }}
|
||||
- if: matrix.platform == 'windows' && steps.toolchain.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
curl -sSfL -o "$RUNNER_TEMP/winlibs.zip" "https://github.com/brechtsanders/winlibs_mingw/releases/download/$WINLIBS_RELEASE/$WINLIBS_ZIP"
|
||||
7z x "$RUNNER_TEMP/winlibs.zip" -oC:/winlibs
|
||||
- if: matrix.platform == 'windows'
|
||||
run: echo 'C:\winlibs\mingw64\bin' >> "$GITHUB_PATH"
|
||||
- uses: hendrikmuhs/[email protected]
|
||||
with:
|
||||
key: ${{ matrix.platform }}
|
||||
save: false
|
||||
- name: Configure Linux
|
||||
if: matrix.platform == 'linux'
|
||||
run: cmake -S . -B build $CONFIGURE
|
||||
- name: Configure Windows
|
||||
if: matrix.platform == 'windows'
|
||||
shell: cmd
|
||||
run: cmake -S . -B build %CONFIGURE%
|
||||
- name: Build project and tests
|
||||
run: cmake --build build
|
||||
- name: Run tests
|
||||
run: ctest --test-dir build --output-on-failure --timeout 120 --stop-on-failure --no-tests=error
|
||||
- name: Build patched libraries
|
||||
run: cmake --build build --target libs
|
||||
- name: Package release files
|
||||
run: python tools/package_release.py --platform "${{ matrix.platform }}" --build build --output dist --version "$RELEASE_TAG"
|
||||
- uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: release-${{ matrix.platform }}
|
||||
path: dist/*
|
||||
if-no-files-found: error
|
||||
compression-level: 0
|
||||
|
||||
publish:
|
||||
name: Publish release
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
permissions:
|
||||
contents: write
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
pattern: release-*
|
||||
merge-multiple: true
|
||||
path: dist
|
||||
- name: Check release files and collect documentation
|
||||
shell: bash
|
||||
run: |
|
||||
for file in "prx-windows-$RELEASE_TAG.zip" "prx-windows-$RELEASE_TAG.tar.gz" "prx-linux-$RELEASE_TAG.zip" "prx-linux-$RELEASE_TAG.tar.gz" "relinker-$RELEASE_TAG.exe" "relinker-$RELEASE_TAG"; do
|
||||
test -s "dist/$file"
|
||||
done
|
||||
python tools/package_release.py --docs docs/user --output dist
|
||||
chmod +x "dist/relinker-$RELEASE_TAG"
|
||||
- name: Create draft and upload files
|
||||
run: gh release create "$RELEASE_TAG" dist/* --verify-tag --draft --title "$RELEASE_TAG" --generate-notes
|
||||
- name: Publish complete release
|
||||
run: gh release edit "$RELEASE_TAG" --draft=false
|
||||
@@ -4,23 +4,23 @@ Tool for automatic executables porting to Linux and Windows.
|
||||
|
||||
Includes a [relinker](core/relinker) that converts executable to the target system's native format and implementations of [system prx libraries](core/libs/prx) suitable for dynamic linking. No emulation or separate runtime process.
|
||||
|
||||
|
||||
|
||||
## Status
|
||||
|
||||
[](https://boykopovar.github.io/AnyPS5/) [](https://boykopovar.github.io/AnyPS5/)
|
||||
|
||||
[](https://boykopovar.github.io/AnyPS5/)
|
||||
|
||||
<sub>* System libraries: percentage of the functions known to the project so far (declared in [core/libs/prx](core/libs/prx)), not of every PS5 system function. The total grows as more functions are declared.</sub>
|
||||
[List of verified games](docs/user/COMPATIBILITY.md)
|
||||
|
||||
Releases will be published after the first full successful launch of at least one game.
|
||||
Dreaming Sarah (2D platformer) runs at a stable 60 fps on a GTX 1050 Ti / i5-7500 3.4GHz.
|
||||
|
||||
## Status
|
||||
Unsupported or unexpected states strictly throw `std::runtime_error`. `what()` is printed to stderr and the process terminates.
|
||||
|
||||
Execution reaches `_start`, [stack unwinding](core/libs/prx/libc/src/exception/Unwind.cpp) and exception handling tables are built, reaches main. Unsupported or unexpected states strictly throw `std::runtime_error`. `what()` is printed to stderr and the process terminates.
|
||||
The [shader recompiler](core/shader/recompiler/Recompiler.cpp) successfully produces SPIR-V (validated via [Spirv-Tools](3rdparty/SPIRV-Tools) when built with `ANYPS5_ENABLE_SPIRV_TOOLS`).
|
||||
|
||||
The [shader recompiler](core/shader/recompiler/Recompiler.cpp) successfully produces SPIR-V, validated via [Spirv-Tools](3rdparty/SPIRV-Tools) when built with `ANYPS5_ENABLE_SPIRV_TOOLS`.
|
||||
|
||||
The real game reaches the logo, main menu, and [gameplay](https://gist.github.com/user-attachments/assets/81d28e9b-c237-4545-b2ca-720071129816) with audio.
|
||||
|
||||
[Technical debt of the project](docs/TechnicalDebt.md), [code style conventions](docs/CONVENTIONS.md)
|
||||
[Technical debt of the project](docs/dev/TechnicalDebt.md), [code style conventions](docs/dev/CONVENTIONS.md)
|
||||
|
||||
## Build
|
||||
|
||||
@@ -30,9 +30,13 @@ The relinker uses only the C++20 standard library and should build with any conf
|
||||
|
||||
The project targets maximum compiler portability. Support for additional compilers will be addressed after the first successful game launch.
|
||||
|
||||
## Compatibility
|
||||
|
||||
See the [game compatibility list](docs/user/COMPATIBILITY.md) for tested games and known issues.
|
||||
|
||||
## Input mapping
|
||||
|
||||
SDL-mapped game controllers are supported, including analog sticks and triggers. Keyboard and mouse controls can be configured with an `anyps5-input.ini` file. See [input mapping](docs/INPUT_MAPPING.md) for the supported devices and configuration format.
|
||||
SDL-mapped game controllers are supported, including analog sticks and triggers. Keyboard and mouse controls can be configured with an `anyps5-input.ini` file. See [input mapping](docs/user/INPUT_MAPPING.md) for the supported devices and configuration format.
|
||||
|
||||
## Disclaimer
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ Game `DT_NEEDED` expects exactly: `libcohtml.Prospero.prx`.
|
||||
Copy next to the relinked eboot (same directory):
|
||||
|
||||
- `build/core/libs/libs/libcohtml.Prospero.prx` (patched build output, 50 NIDs) — required.
|
||||
- `libgcc_s_seh-1.dll`, `libstdc++-6.dll`, `libwinpthread-1.dll` from `winlibs-gcc15/mingw64/bin` — required on Windows (see `docs/TechnicalDebt.md`).
|
||||
- `libgcc_s_seh-1.dll`, `libstdc++-6.dll`, `libwinpthread-1.dll` from `winlibs-gcc15/mingw64/bin` — required on Windows (see [technical debt](../../../../docs/dev/TechnicalDebt.md)).
|
||||
|
||||
Do NOT deploy:
|
||||
|
||||
|
||||
@@ -1635,7 +1635,7 @@ public:
|
||||
} else {
|
||||
// Compressed (Vorbis/MP3/FSB/AT9...) or unknown: audible
|
||||
// placeholder so the mixer path can be heard. Real decoders
|
||||
// (Vorbis/MP3/AT9) remain future work — see docs/TechnicalDebt.
|
||||
// (Vorbis/MP3/AT9) remain future work — see docs/dev/TechnicalDebt.
|
||||
FmodMakeSine(created->pcm, kFmodOutRate, 2, 440.0f, 1.0f);
|
||||
created->pcmRate = kFmodOutRate;
|
||||
created->pcmCh = 2;
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
# Project technical debt
|
||||
|
||||
### Build
|
||||
|
||||
- Building on Windows requires a specific version of mingw - MinGW-w64 GCC 15.2.0 (`winlibs-gcc15`, `x86_64-ucrt-posix-seh`)
|
||||
- Even compiled prx libraries on Windows require nearby (static linking of these dependencies causes conflicts):
|
||||
- libgcc_s_seh-1.dll
|
||||
- libstdc++-6.dll
|
||||
- libwinpthread-1.dll
|
||||
|
||||
### Silent stubs
|
||||
|
||||
Throughout the project, every function at every stage either **does exactly what it's supposed to or throws an exception**. Everywhere... except:
|
||||
- [libSceSaveDataDialog.native](../core/libs/prx/libSceSaveDataDialog.native/Export.cpp)
|
||||
- [libSceCommonDialog](../core/libs/prx/libSceCommonDialog/Export.cpp)
|
||||
- The shader recompiler [skips baryctric coordinates](../core/shader/recompiler/Recompiler.cpp) (is not even passed to SpirvTargetOptions at row 212).
|
||||
|
||||
### Unknown function info
|
||||
|
||||
- [zARR5aCmkoY](../core/libs/prx/libSceAgc/DcbFlow/src/Control.cpp) (libSceAgc) - unknown name, signature
|
||||
- [qj7QZpgr9Uw](../core/libs/prx/libSceAgc/DcbState/src/ContextState.cpp) (libSceAgc) - unknown name
|
||||
- [fd5Bp5tGTgo](../core/libs/prx/libSceAgc/Misc/src/ShaderFusion.cpp) (libSceAgc) - unknown name
|
||||
- [dolOmWH+huQ](../core/libs/prx/libSceAgc/Misc/src/ShaderFusion.cpp) (libSceAgc) - unknown name
|
||||
- [V++UgBtQhn0](../core/libs/prx/libSceAgc/Misc/src/PacketInfo.cpp) (libSceAgc) - unknown name
|
||||
- [gQkqkLttcpw](../core/libs/prx/libSceAgc/Acb/src/Control.cpp) (libSceAgc) - unknown name, signature
|
||||
- [sceKernelInternalMemoryGetModuleSegmentInfo](../core/libs/prx/libkernel/Module/src/Module.cpp) (libkernel) - unknown signature
|
||||
- [sceLibcInternalBacktraceForGame](../core/libs/prx/libc/src/HeapDiagnostics.cpp) (libSceLibcInternal, implemented in libc) - unknown signature
|
||||
- [sceLibcInternalHeapErrorReportForGame](../core/libs/prx/libc/src/HeapDiagnostics.cpp) (libSceLibcInternal, implemented in libc) - unknown signature
|
||||
- [__progname](../core/libs/prx/libkernel/System/src/Process.cpp) (libkernel) - unknown data export
|
||||
|
||||
### Functional
|
||||
|
||||
- [Shader recompilation](../core/shader/recompiler/Recompiler.cpp) currently occurs right before it was transferred to Vulkan with caching, but should be moved to the [relinker](../core/relinker/main.cpp) stage. For this purpose, [shader/recompiler](../core/shader/recompiler) was written completely independently from [libs/prx](../core/libs/prx).
|
||||
- The executable file that [relinker](../core/relinker/elfpatcher/src/windows/WindowsPeWriter.cpp) generates opens the console when launched, which is inconvenient for playability.
|
||||
- [Relinker](../core/relinker/elfpatcher/src) doesn't add an icon to the generated executable. This should be done without adding dependencies (only standard).
|
||||
- `--to-intel` does not lower the register form of INSERTQ (`F2 0F 79`) nor MONITORX/MWAITX/CLZERO/RDPRU/MCOMMIT; the [lowering](../core/relinker/codegen/src/x86/Sse4aLowering.cpp) fails the relink instead. SHA-NI is not substituted.
|
||||
- The length-changing path of the [instruction rewriter](../core/relinker/codegen/src/x86/X64InstructionRewriter.cpp) is not used by the [converter](../core/relinker/codegen/src/Amd64OnlyConverter.cpp): it does not adjust VEX/0F38/0F3A RIP-relative operands, data-to-code references (relocations, FDEs, jump tables) or segment sizes, so every substitution keeps the instruction length.
|
||||
- The Linux placement of the `--to-intel` stubs in the [ELF patcher](../core/relinker/elfpatcher/src/linux/LinuxElfPatcher.cpp) is covered only by a synthetic test.
|
||||
- The libc [SSE4a trap emulation](../core/libs/prx/libc/src/specifics/windows/Sse4aEmulation.hpp) on Windows is superseded by `--to-intel` and remains only until the relinked title has been verified without it.
|
||||
- `--to-intel` lowerings that need a stub section are rejected for `sce_module` guest modules: the [guest module builder](../core/relinker/relinker/src/guest/GuestModuleBuilder.cpp) does not pass stub sites to the [guest module writer](../core/relinker/elfpatcher/include/elfpatcher/general/GuestModuleWriter.hpp).
|
||||
- The game can expect its modified prx from the `sce_module`/`sce_modules` folder - this support is not implemented.
|
||||
File renamed without changes.
@@ -0,0 +1,41 @@
|
||||
# Project technical debt
|
||||
|
||||
### Build
|
||||
|
||||
- Building on Windows requires a specific version of mingw - MinGW-w64 GCC 15.2.0 (`winlibs-gcc15`, `x86_64-ucrt-posix-seh`)
|
||||
- Even compiled prx libraries on Windows require nearby (static linking of these dependencies causes conflicts):
|
||||
- libgcc_s_seh-1.dll
|
||||
- libstdc++-6.dll
|
||||
- libwinpthread-1.dll
|
||||
|
||||
### Silent stubs
|
||||
|
||||
Throughout the project, every function at every stage either **does exactly what it's supposed to or throws an exception**. Everywhere... except:
|
||||
- [libSceSaveDataDialog.native](../../core/libs/prx/libSceSaveDataDialog.native/Export.cpp)
|
||||
- [libSceCommonDialog](../../core/libs/prx/libSceCommonDialog/Export.cpp)
|
||||
- The shader recompiler [skips baryctric coordinates](../../core/shader/recompiler/Recompiler.cpp) (is not even passed to SpirvTargetOptions at row 212).
|
||||
|
||||
### Unknown function info
|
||||
|
||||
- [zARR5aCmkoY](../../core/libs/prx/libSceAgc/DcbFlow/src/Control.cpp) (libSceAgc) - unknown name, signature
|
||||
- [qj7QZpgr9Uw](../../core/libs/prx/libSceAgc/DcbState/src/ContextState.cpp) (libSceAgc) - unknown name
|
||||
- [fd5Bp5tGTgo](../../core/libs/prx/libSceAgc/Misc/src/ShaderFusion.cpp) (libSceAgc) - unknown name
|
||||
- [dolOmWH+huQ](../../core/libs/prx/libSceAgc/Misc/src/ShaderFusion.cpp) (libSceAgc) - unknown name
|
||||
- [V++UgBtQhn0](../../core/libs/prx/libSceAgc/Misc/src/PacketInfo.cpp) (libSceAgc) - unknown name
|
||||
- [gQkqkLttcpw](../../core/libs/prx/libSceAgc/Acb/src/Control.cpp) (libSceAgc) - unknown name, signature
|
||||
- [sceKernelInternalMemoryGetModuleSegmentInfo](../../core/libs/prx/libkernel/Module/src/Module.cpp) (libkernel) - unknown signature
|
||||
- [sceLibcInternalBacktraceForGame](../../core/libs/prx/libc/src/HeapDiagnostics.cpp) (libSceLibcInternal, implemented in libc) - unknown signature
|
||||
- [sceLibcInternalHeapErrorReportForGame](../../core/libs/prx/libc/src/HeapDiagnostics.cpp) (libSceLibcInternal, implemented in libc) - unknown signature
|
||||
- [__progname](../../core/libs/prx/libkernel/System/src/Process.cpp) (libkernel) - unknown data export
|
||||
|
||||
### Functional
|
||||
|
||||
- [Shader recompilation](../../core/shader/recompiler/Recompiler.cpp) currently occurs right before it was transferred to Vulkan with caching, but should be moved to the [relinker](../../core/relinker/main.cpp) stage. For this purpose, [shader/recompiler](../../core/shader/recompiler) was written completely independently from [libs/prx](../../core/libs/prx).
|
||||
- The executable file that [relinker](../../core/relinker/elfpatcher/src/windows/WindowsPeWriter.cpp) generates opens the console when launched, which is inconvenient for playability.
|
||||
- [Relinker](../../core/relinker/elfpatcher/src) doesn't add an icon to the generated executable. This should be done without adding dependencies (only standard).
|
||||
- `--to-intel` does not lower the register form of INSERTQ (`F2 0F 79`) nor MONITORX/MWAITX/CLZERO/RDPRU/MCOMMIT; the [lowering](../../core/relinker/codegen/src/x86/Sse4aLowering.cpp) fails the relink instead. SHA-NI is not substituted.
|
||||
- The length-changing path of the [instruction rewriter](../../core/relinker/codegen/src/x86/X64InstructionRewriter.cpp) is not used by the [converter](../../core/relinker/codegen/src/Amd64OnlyConverter.cpp): it does not adjust VEX/0F38/0F3A RIP-relative operands, data-to-code references (relocations, FDEs, jump tables) or segment sizes, so every substitution keeps the instruction length.
|
||||
- The Linux placement of the `--to-intel` stubs in the [ELF patcher](../../core/relinker/elfpatcher/src/linux/LinuxElfPatcher.cpp) is covered only by a synthetic test.
|
||||
- The libc [SSE4a trap emulation](../../core/libs/prx/libc/src/specifics/windows/Sse4aEmulation.hpp) on Windows is superseded by `--to-intel` and remains only until the relinked title has been verified without it.
|
||||
- `--to-intel` lowerings that need a stub section are rejected for `sce_module` guest modules: the [guest module builder](../../core/relinker/relinker/src/guest/GuestModuleBuilder.cpp) does not pass stub sites to the [guest module writer](../../core/relinker/elfpatcher/include/elfpatcher/general/GuestModuleWriter.hpp).
|
||||
- The game can expect its modified prx from the `sce_module`/`sce_modules` folder - this support is not implemented.
|
||||
@@ -0,0 +1,5 @@
|
||||
# Tested compatibility
|
||||
|
||||
| Game | ID | Windows | Linux | GTX 1050 Ti / i5-7500 3.4GHz | Intel(R) HD Graphic 620 / i5-7200 2.5GHz |
|
||||
|----------------|-----------|-------------------|-------|------------------------------|------------------------------------------|
|
||||
| Dreaming Sarah | PPSA02929 | In game, playable | ? | 60 FPS | 36 FPS |
|
||||
File renamed without changes.
@@ -0,0 +1,71 @@
|
||||
import argparse
|
||||
import re
|
||||
import shutil
|
||||
import tarfile
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def package(platform, build, output, version):
|
||||
if not re.fullmatch(r"v[0-9A-Za-z][0-9A-Za-z._-]*", version) or version.endswith("."):
|
||||
raise ValueError(f"Invalid release tag for asset filenames: {version}")
|
||||
libraries = sorted((build / "core/libs/libs").glob("*.prx"))
|
||||
expected = {f"{directory.name}.prx" for directory in Path("core/libs/prx").iterdir() if directory.is_dir()}
|
||||
expected.add("libcohtml.Prospero.prx")
|
||||
missing = expected - {library.name for library in libraries}
|
||||
if missing:
|
||||
raise RuntimeError(f"Missing patched libraries: {', '.join(sorted(missing))}")
|
||||
executable = "relinker.exe" if platform == "windows" else "relinker"
|
||||
files = list(libraries)
|
||||
if platform == "windows":
|
||||
runtime = Path("C:/winlibs/mingw64/bin")
|
||||
files.extend(runtime / name for name in ("libgcc_s_seh-1.dll", "libstdc++-6.dll", "libwinpthread-1.dll"))
|
||||
binary = build / "core/relinker" / executable
|
||||
for file in [*files, binary]:
|
||||
if not file.is_file() or file.stat().st_size == 0:
|
||||
raise RuntimeError(f"Missing or empty release file: {file}")
|
||||
output.mkdir(parents=True, exist_ok=True)
|
||||
with zipfile.ZipFile(output / f"prx-{platform}-{version}.zip", "w", compression=zipfile.ZIP_DEFLATED) as archive:
|
||||
for file in files:
|
||||
archive.write(file, arcname=file.name)
|
||||
with tarfile.open(output / f"prx-{platform}-{version}.tar.gz", "w:gz") as archive:
|
||||
for file in files:
|
||||
archive.add(file, arcname=file.name)
|
||||
asset = f"relinker-{version}.exe" if platform == "windows" else f"relinker-{version}"
|
||||
shutil.copy2(binary, output / asset)
|
||||
|
||||
|
||||
def collect_docs(source, output):
|
||||
documents = sorted(source.rglob("*.md"))
|
||||
if not documents:
|
||||
raise RuntimeError(f"No Markdown documents found in {source}")
|
||||
names = set()
|
||||
for document in documents:
|
||||
if document.name in names or (output / document.name).exists():
|
||||
raise RuntimeError(f"Duplicate release asset name: {document.name}")
|
||||
names.add(document.name)
|
||||
output.mkdir(parents=True, exist_ok=True)
|
||||
for document in documents:
|
||||
shutil.copy2(document, output / document.name)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--platform", choices=("linux", "windows"))
|
||||
parser.add_argument("--build", type=Path)
|
||||
parser.add_argument("--version")
|
||||
parser.add_argument("--docs", type=Path)
|
||||
parser.add_argument("--output", required=True, type=Path)
|
||||
args = parser.parse_args()
|
||||
if args.docs is not None:
|
||||
if args.platform is not None or args.build is not None or args.version is not None:
|
||||
parser.error("--docs cannot be combined with --platform, --build or --version")
|
||||
collect_docs(args.docs, args.output)
|
||||
else:
|
||||
if args.platform is None or args.build is None or args.version is None:
|
||||
parser.error("--platform, --build and --version are required when --docs is not specified")
|
||||
package(args.platform, args.build, args.output, args.version)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
+1
-1
@@ -26,7 +26,7 @@ OPCODE_ALIASES = {
|
||||
}
|
||||
REPORT_ROWS = 100
|
||||
PANEL_WIDTH, GAP, MAP_HEIGHT, HEADER = 495, 10, 280, 30
|
||||
DONE_COLOR, TODO_COLOR, BORDER, TEXT = "#2ea043", "#1f6feb", "#0d1117", "#ffffff"
|
||||
DONE_COLOR, TODO_COLOR, BORDER, TEXT = "#2ea043", "#6e7681", "#0d1117", "#ffffff"
|
||||
|
||||
|
||||
def body_end(text, start):
|
||||
|
||||
Reference in new issue
Block a user