feat(relinker): support explicit CLI help
This commit is contained in:
parent
bc40a6b5a0
commit
1fc31ba358
|
|
@ -198,6 +198,8 @@ if(BUILD_TESTING)
|
|||
|
||||
find_package(Python3 QUIET COMPONENTS Interpreter)
|
||||
if(Python3_Interpreter_FOUND)
|
||||
add_test(NAME cli_help COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/cli/tests/test_help.py $<TARGET_FILE:relinker>)
|
||||
add_test(NAME elf_offsets COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/relinker/tests/test_elf_offsets.py $<TARGET_FILE:relinker>)
|
||||
add_test(NAME dynamic_segment COMMAND ${Python3_EXECUTABLE}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
namespace Cli {
|
||||
|
||||
struct Args {
|
||||
bool showHelp = false;
|
||||
bool skipSyscallCheck = false;
|
||||
bool skipSceModule = false;
|
||||
bool toIntel = false;
|
||||
|
|
@ -27,6 +28,8 @@ struct Args {
|
|||
|
||||
Args ParseArgs(int argc, char* argv[]);
|
||||
|
||||
const char* Usage();
|
||||
|
||||
int Autorun(const std::string& absPath, bool toWindows);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,13 +5,20 @@
|
|||
|
||||
namespace Cli {
|
||||
|
||||
const char* Usage() {
|
||||
return "Usage: relinker [--help] [--windows | --macos] [--windows-diagnostics] [--windows-gui] [--skip-syscall-check] [--skip-sce-module] [--exclude-sce-module <file>]... [--to-intel] [unused-filter=0|1|2] [--registry] [--rpath <path>] [--lazy-binding] [--autorun] <input.elf> <output.elf>\n"
|
||||
"Example: relinker input.elf output.elf";
|
||||
}
|
||||
|
||||
Args ParseArgs(int argc, char* argv[]) {
|
||||
Args args;
|
||||
bool unusedFilterSpecified = false;
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
const std::string arg = argv[i];
|
||||
if (arg == "--skip-syscall-check") {
|
||||
if (arg == "--help") {
|
||||
args.showHelp = true;
|
||||
} else if (arg == "--skip-syscall-check") {
|
||||
args.skipSyscallCheck = true;
|
||||
} else if (arg == "--skip-sce-module") {
|
||||
args.skipSceModule = true;
|
||||
|
|
@ -67,11 +74,9 @@ Args ParseArgs(int argc, char* argv[]) {
|
|||
if (args.windowsGui && !args.toWindows)
|
||||
throw std::runtime_error("--windows-gui requires --windows");
|
||||
|
||||
if (args.inputPath.empty() || args.outputPath.empty())
|
||||
throw std::runtime_error(
|
||||
"Usage: relinker [--windows | --macos] [--windows-diagnostics] [--windows-gui] [--skip-syscall-check] [--skip-sce-module] [--exclude-sce-module <file>]... [--to-intel] [unused-filter=0|1|2] [--registry] [--rpath <path>] [--lazy-binding] [--autorun] <input.elf> <output.elf>\n"
|
||||
"Example: relinker input.elf output.elf"
|
||||
);
|
||||
if (!args.showHelp && (args.inputPath.empty() || args.outputPath.empty()))
|
||||
throw std::runtime_error(Usage());
|
||||
|
||||
|
||||
return args;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
from pathlib import Path
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
|
||||
def main():
|
||||
relinker = Path(sys.argv[1]).resolve()
|
||||
with tempfile.TemporaryDirectory(prefix="anyps5-help-") as directory:
|
||||
work = Path(directory)
|
||||
source = work / "missing.elf"
|
||||
output = work / "existing.exe"
|
||||
output.write_bytes(b"preserve this output")
|
||||
|
||||
def run(*args):
|
||||
return subprocess.run([str(relinker), *args], cwd=work,
|
||||
capture_output=True, text=True, timeout=10)
|
||||
|
||||
for args in [("--help",), ("--help", "--registry", "--autorun", str(source), str(output)),
|
||||
(str(source), str(output), "--help")]:
|
||||
result = run(*args)
|
||||
assert result.returncode == 0, result.stderr
|
||||
assert result.stdout.startswith("Usage: relinker "), result.stdout
|
||||
assert "--help" in result.stdout and "Example:" in result.stdout
|
||||
assert result.stderr == "", result.stderr
|
||||
assert output.read_bytes() == b"preserve this output"
|
||||
assert sorted(path.name for path in work.iterdir()) == [output.name]
|
||||
|
||||
result = run()
|
||||
assert result.returncode == 1 and "Usage: relinker" in result.stderr
|
||||
for args in [("--help", "--unknown"), ("--unknown", "--help")]:
|
||||
result = run(*args)
|
||||
assert result.returncode == 1 and "unknown option" in result.stderr
|
||||
result = run("--help", "--windows-gui")
|
||||
assert result.returncode == 1 and "requires --windows" in result.stderr
|
||||
for flag in ["--rpath", "--exclude-sce-module"]:
|
||||
result = run(flag, "--help", str(source), str(output))
|
||||
assert result.returncode == 2 and "Cannot open file" in result.stderr
|
||||
assert result.stdout == "", result.stdout
|
||||
assert output.read_bytes() == b"preserve this output"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -37,6 +37,11 @@ int main(const int argc, char* argv[]) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (args.showHelp) {
|
||||
std::cout << Cli::Usage() << '\n';
|
||||
return 0;
|
||||
}
|
||||
|
||||
try {
|
||||
auto extension = std::filesystem::path(args.outputPath).extension().string();
|
||||
for (auto& character : extension) if (character >= 'A' && character <= 'Z') character = static_cast<char>(character + ('a' - 'A'));
|
||||
|
|
|
|||
Loading…
Reference in New Issue