2020-08-22 22:30:12 -04:00
|
|
|
#include <cstdio>
|
2022-06-22 23:37:46 -04:00
|
|
|
#include <regex>
|
|
|
|
|
2021-01-06 12:16:39 -05:00
|
|
|
#include "common/log/log.h"
|
2023-01-07 11:24:02 -05:00
|
|
|
#include "common/repl/nrepl/ReplServer.h"
|
2024-06-03 00:14:52 -04:00
|
|
|
#include "common/repl/repl_wrapper.h"
|
2022-06-22 23:37:46 -04:00
|
|
|
#include "common/util/FileUtil.h"
|
repl: Add a few new quality of life improvements (#2030)
- You can define a `startup.gc` in your user folder, each line will be
executed on startup (deprecates the usefulness of some cli flags)
- You can define a `repl-config.json` file to override REPL settings.
Long-term this is a better approach than a bunch of CLI flags as well
- Via this, you can override the amount of time the repl will attempt to
listen for the target
- At the same time, I think i may have found why on Windows it can
sometimes take forever to timeout when the game dies, will dig into this
later
- Added some keybinds for common operations, shown here
https://user-images.githubusercontent.com/13153231/202890278-1ff2bb06-dddf-4bde-9178-aa0883799167.mp4
> builds the game, connects to it, attaches a debugger and continues,
launches it, gets the backtrace, stops the target -- all with only
keybinds.
If you want these keybinds to work inside VSCode's integrated terminal,
you need to add the following to your settings file
```json
"terminal.integrated.commandsToSkipShell": [
"-workbench.action.quickOpen",
"-workbench.action.quickOpenView"
]
```
2022-11-20 14:28:41 -05:00
|
|
|
#include "common/util/diff.h"
|
2023-01-07 11:24:02 -05:00
|
|
|
#include "common/util/string_util.h"
|
2023-08-08 12:59:37 -04:00
|
|
|
#include "common/util/term_util.h"
|
2023-03-09 23:13:01 -05:00
|
|
|
#include "common/util/unicode_util.h"
|
2023-04-22 14:13:57 -04:00
|
|
|
#include "common/versions/versions.h"
|
2022-06-22 23:37:46 -04:00
|
|
|
|
|
|
|
#include "goalc/compiler/Compiler.h"
|
2020-10-29 19:03:44 -04:00
|
|
|
|
2024-03-05 22:11:52 -05:00
|
|
|
#include "fmt/color.h"
|
|
|
|
#include "fmt/core.h"
|
2022-05-06 18:19:37 -04:00
|
|
|
#include "third-party/CLI11.hpp"
|
2021-03-03 00:05:13 -05:00
|
|
|
|
2023-08-08 12:59:37 -04:00
|
|
|
void setup_logging(const bool disable_ansi_colors) {
|
2022-06-21 21:26:11 -04:00
|
|
|
lg::set_file_level(lg::level::info);
|
|
|
|
lg::set_stdout_level(lg::level::info);
|
|
|
|
lg::set_flush_level(lg::level::info);
|
2023-08-08 12:59:37 -04:00
|
|
|
if (disable_ansi_colors) {
|
|
|
|
lg::disable_ansi_colors();
|
|
|
|
}
|
2024-06-03 00:14:52 -04:00
|
|
|
lg::set_file("compiler");
|
2021-01-06 12:16:39 -05:00
|
|
|
lg::initialize();
|
2020-10-29 19:03:44 -04:00
|
|
|
}
|
2020-08-22 22:30:12 -04:00
|
|
|
|
|
|
|
int main(int argc, char** argv) {
|
2023-03-09 23:13:01 -05:00
|
|
|
ArgumentGuard u8_guard(argc, argv);
|
|
|
|
|
2022-05-06 18:19:37 -04:00
|
|
|
bool auto_find_user = false;
|
|
|
|
std::string cmd = "";
|
|
|
|
std::string username = "#f";
|
2022-07-06 21:18:08 -04:00
|
|
|
std::string game = "jak1";
|
2023-06-07 20:04:16 -04:00
|
|
|
int nrepl_port = -1;
|
2022-09-24 12:06:26 -04:00
|
|
|
fs::path project_path_override;
|
Parameterize the iso_data folder for goalc (#3692)
I hope this is everything I needed, and nothing I didn't.
## What's Changed
This update adds a command-line parameter to goalc, `--iso-path`.
Providing a path to a directory like
`D:\Files\Repositories\ArchipelaGOAL\iso_data\jak1` will inform the
compiler to use that directory instead.
## Why is this useful?
When combined with `--proj-path`, the compiler can be pointed to a
completely different project folder, given the `(mi)` command, and
immediately begin building from that directory, with everything it
needs. This eliminates the need to copy `iso_data` to multiple `data`
directories.
If a subsequent change to the Launcher is made, each mod could be passed
an --iso-path pointing to a single shared folder, allowing mods to each
run their own REPL _without_ requiring a copy of `iso_data` in a
subfolder.
## Independent testing required!
My local repositories are a little suspect, with a mod, a fork of
mod-base, and a fork of jak-project, all on the same drive. My
decompiler_out and iso_data folders are in the mod repo, not mod-base
nor jak-project. So what I did was make the change in the mod-base fork,
point `--proj-path and --iso-path` to the mod folders, and then ran
`(mi)`. The output showed a build starting with no errors.
Then I had to create this PR, which my fork of mod-base is unable to do,
so I created a patch file, forked jak-project, then applied the patch
there.
All this is to say that it would be preferable if someone could apply
this code to their own installation and see if it works. Even I wouldn't
take my own word for this.
---------
Co-authored-by: Tyler Wilding <xtvaser@gmail.com>
2024-10-18 00:03:14 -04:00
|
|
|
fs::path iso_path_override;
|
2022-05-06 18:19:37 -04:00
|
|
|
|
repl: Add a few new quality of life improvements (#2030)
- You can define a `startup.gc` in your user folder, each line will be
executed on startup (deprecates the usefulness of some cli flags)
- You can define a `repl-config.json` file to override REPL settings.
Long-term this is a better approach than a bunch of CLI flags as well
- Via this, you can override the amount of time the repl will attempt to
listen for the target
- At the same time, I think i may have found why on Windows it can
sometimes take forever to timeout when the game dies, will dig into this
later
- Added some keybinds for common operations, shown here
https://user-images.githubusercontent.com/13153231/202890278-1ff2bb06-dddf-4bde-9178-aa0883799167.mp4
> builds the game, connects to it, attaches a debugger and continues,
launches it, gets the backtrace, stops the target -- all with only
keybinds.
If you want these keybinds to work inside VSCode's integrated terminal,
you need to add the following to your settings file
```json
"terminal.integrated.commandsToSkipShell": [
"-workbench.action.quickOpen",
"-workbench.action.quickOpenView"
]
```
2022-11-20 14:28:41 -05:00
|
|
|
// TODO - a lot of these flags could be deprecated and moved into `repl-config.json`
|
2022-05-06 18:19:37 -04:00
|
|
|
CLI::App app{"OpenGOAL Compiler / REPL"};
|
2023-01-07 11:24:02 -05:00
|
|
|
app.add_option("-c,--cmd", cmd, "Specify a command to run, no REPL is launched in this mode");
|
2022-05-06 18:19:37 -04:00
|
|
|
app.add_option("-u,--user", username,
|
|
|
|
"Specify the username to use for your user profile in 'goal_src/user/'");
|
2024-06-03 00:14:52 -04:00
|
|
|
app.add_option("-p,--port", nrepl_port, "Specify the nREPL port. Defaults to 8181");
|
2022-05-06 18:19:37 -04:00
|
|
|
app.add_flag("--user-auto", auto_find_user,
|
2023-01-07 11:24:02 -05:00
|
|
|
"Attempt to automatically deduce the user, overrides '--user'");
|
2022-07-06 21:18:08 -04:00
|
|
|
app.add_option("-g,--game", game, "The game name: 'jak1' or 'jak2'");
|
2022-09-24 12:06:26 -04:00
|
|
|
app.add_option("--proj-path", project_path_override,
|
|
|
|
"Specify the location of the 'data/' folder");
|
Parameterize the iso_data folder for goalc (#3692)
I hope this is everything I needed, and nothing I didn't.
## What's Changed
This update adds a command-line parameter to goalc, `--iso-path`.
Providing a path to a directory like
`D:\Files\Repositories\ArchipelaGOAL\iso_data\jak1` will inform the
compiler to use that directory instead.
## Why is this useful?
When combined with `--proj-path`, the compiler can be pointed to a
completely different project folder, given the `(mi)` command, and
immediately begin building from that directory, with everything it
needs. This eliminates the need to copy `iso_data` to multiple `data`
directories.
If a subsequent change to the Launcher is made, each mod could be passed
an --iso-path pointing to a single shared folder, allowing mods to each
run their own REPL _without_ requiring a copy of `iso_data` in a
subfolder.
## Independent testing required!
My local repositories are a little suspect, with a mod, a fork of
mod-base, and a fork of jak-project, all on the same drive. My
decompiler_out and iso_data folders are in the mod repo, not mod-base
nor jak-project. So what I did was make the change in the mod-base fork,
point `--proj-path and --iso-path` to the mod folders, and then ran
`(mi)`. The output showed a build starting with no errors.
Then I had to create this PR, which my fork of mod-base is unable to do,
so I created a patch file, forked jak-project, then applied the patch
there.
All this is to say that it would be preferable if someone could apply
this code to their own installation and see if it works. Even I wouldn't
take my own word for this.
---------
Co-authored-by: Tyler Wilding <xtvaser@gmail.com>
2024-10-18 00:03:14 -04:00
|
|
|
app.add_option("--iso-path", iso_path_override, "Specify the location of the 'iso_data/' folder");
|
2023-08-08 12:59:37 -04:00
|
|
|
define_common_cli_arguments(app);
|
2022-05-06 18:19:37 -04:00
|
|
|
app.validate_positionals();
|
|
|
|
CLI11_PARSE(app, argc, argv);
|
|
|
|
|
2022-09-24 12:06:26 -04:00
|
|
|
GameVersion game_version = game_name_to_version(game);
|
|
|
|
|
|
|
|
if (!project_path_override.empty()) {
|
|
|
|
if (!fs::exists(project_path_override)) {
|
|
|
|
lg::error("Error: project path override '{}' does not exist", project_path_override.string());
|
|
|
|
return 1;
|
|
|
|
}
|
2024-06-03 00:14:52 -04:00
|
|
|
if (!file_util::setup_project_path(project_path_override, true)) {
|
2022-09-24 12:06:26 -04:00
|
|
|
lg::error("Could not setup project path!");
|
|
|
|
return 1;
|
|
|
|
}
|
2024-06-03 00:14:52 -04:00
|
|
|
} else if (!file_util::setup_project_path(std::nullopt, true)) {
|
2022-05-06 18:19:37 -04:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2023-03-01 17:52:33 -05:00
|
|
|
try {
|
2023-08-08 12:59:37 -04:00
|
|
|
setup_logging(_cli_flag_disable_ansi);
|
2023-03-01 17:52:33 -05:00
|
|
|
} catch (const std::exception& e) {
|
|
|
|
lg::error("Failed to setup logging: {}", e.what());
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2023-01-07 11:24:02 -05:00
|
|
|
// Figure out the username
|
2022-05-06 18:19:37 -04:00
|
|
|
if (auto_find_user) {
|
2023-01-07 11:24:02 -05:00
|
|
|
username = REPL::find_repl_username();
|
2020-10-29 19:03:44 -04:00
|
|
|
}
|
2023-01-07 11:24:02 -05:00
|
|
|
// Load the user's startup file
|
2023-01-30 20:45:03 -05:00
|
|
|
auto startup_file = REPL::load_user_startup_file(username, game_version);
|
2023-01-07 11:24:02 -05:00
|
|
|
// Load the user's REPL config
|
2024-06-03 00:14:52 -04:00
|
|
|
auto repl_config = REPL::load_repl_config(username, game_version, nrepl_port);
|
2022-05-06 18:19:37 -04:00
|
|
|
|
Parameterize the iso_data folder for goalc (#3692)
I hope this is everything I needed, and nothing I didn't.
## What's Changed
This update adds a command-line parameter to goalc, `--iso-path`.
Providing a path to a directory like
`D:\Files\Repositories\ArchipelaGOAL\iso_data\jak1` will inform the
compiler to use that directory instead.
## Why is this useful?
When combined with `--proj-path`, the compiler can be pointed to a
completely different project folder, given the `(mi)` command, and
immediately begin building from that directory, with everything it
needs. This eliminates the need to copy `iso_data` to multiple `data`
directories.
If a subsequent change to the Launcher is made, each mod could be passed
an --iso-path pointing to a single shared folder, allowing mods to each
run their own REPL _without_ requiring a copy of `iso_data` in a
subfolder.
## Independent testing required!
My local repositories are a little suspect, with a mod, a fork of
mod-base, and a fork of jak-project, all on the same drive. My
decompiler_out and iso_data folders are in the mod repo, not mod-base
nor jak-project. So what I did was make the change in the mod-base fork,
point `--proj-path and --iso-path` to the mod folders, and then ran
`(mi)`. The output showed a build starting with no errors.
Then I had to create this PR, which my fork of mod-base is unable to do,
so I created a patch file, forked jak-project, then applied the patch
there.
All this is to say that it would be preferable if someone could apply
this code to their own installation and see if it works. Even I wouldn't
take my own word for this.
---------
Co-authored-by: Tyler Wilding <xtvaser@gmail.com>
2024-10-18 00:03:14 -04:00
|
|
|
// Check for a custom ISO path before we instantiate the compiler.
|
|
|
|
if (!iso_path_override.empty()) {
|
|
|
|
if (!fs::exists(iso_path_override)) {
|
|
|
|
lg::error("Error: iso path override '{}' does not exist", iso_path_override.string());
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
file_util::set_iso_data_dir(iso_path_override);
|
|
|
|
repl_config.iso_path = iso_path_override.string();
|
|
|
|
}
|
|
|
|
|
2023-01-07 11:24:02 -05:00
|
|
|
// Init Compiler
|
|
|
|
std::unique_ptr<Compiler> compiler;
|
|
|
|
std::mutex compiler_mutex;
|
|
|
|
// if a command is provided on the command line, no REPL just run the compiler on it
|
|
|
|
try {
|
|
|
|
if (!cmd.empty()) {
|
|
|
|
compiler = std::make_unique<Compiler>(game_version);
|
|
|
|
compiler->run_front_end_on_string(cmd);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} catch (std::exception& e) {
|
|
|
|
lg::error("Compiler Fatal Error: {}", e.what());
|
2023-02-20 19:49:37 -05:00
|
|
|
return 1;
|
2023-01-07 11:24:02 -05:00
|
|
|
}
|
2020-08-22 22:30:12 -04:00
|
|
|
|
2023-01-07 11:24:02 -05:00
|
|
|
// Otherwise, start the REPL normally
|
2022-11-30 22:36:09 -05:00
|
|
|
ReplStatus status = ReplStatus::OK;
|
2023-01-07 11:24:02 -05:00
|
|
|
std::function<void()> repl_startup_func = [&]() {
|
|
|
|
// Run automatic forms if applicable
|
|
|
|
std::lock_guard<std::mutex> lock(compiler_mutex);
|
|
|
|
for (const auto& cmd : startup_file.run_before_listen) {
|
|
|
|
status = compiler->handle_repl_string(cmd);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Initialize nREPL server socket
|
2022-05-06 18:19:37 -04:00
|
|
|
std::function<bool()> shutdown_callback = [&]() { return status == ReplStatus::WANT_EXIT; };
|
2024-06-03 00:14:52 -04:00
|
|
|
ReplServer repl_server(shutdown_callback, repl_config.get_nrepl_port());
|
|
|
|
bool nrepl_server_ok = repl_server.init_server(true);
|
2022-05-06 18:19:37 -04:00
|
|
|
std::thread nrepl_thread;
|
2021-05-24 19:52:19 -04:00
|
|
|
// the compiler may throw an exception if it fails to load its standard library.
|
|
|
|
try {
|
2023-01-07 11:24:02 -05:00
|
|
|
compiler = std::make_unique<Compiler>(
|
2023-04-11 17:57:20 -04:00
|
|
|
game_version, std::make_optional(repl_config), username,
|
2024-06-03 00:14:52 -04:00
|
|
|
std::make_unique<REPL::Wrapper>(username, repl_config, startup_file, nrepl_server_ok));
|
2023-01-07 11:24:02 -05:00
|
|
|
// Start nREPL Server if it spun up successfully
|
2024-06-03 00:14:52 -04:00
|
|
|
if (nrepl_server_ok) {
|
2022-05-06 18:19:37 -04:00
|
|
|
nrepl_thread = std::thread([&]() {
|
|
|
|
while (!shutdown_callback()) {
|
|
|
|
auto resp = repl_server.get_msg();
|
|
|
|
if (resp) {
|
|
|
|
std::lock_guard<std::mutex> lock(compiler_mutex);
|
|
|
|
status = compiler->handle_repl_string(resp.value());
|
|
|
|
// Print out the prompt, just for better UX
|
|
|
|
compiler->print_to_repl(compiler->get_prompt());
|
|
|
|
}
|
|
|
|
std::this_thread::sleep_for(std::chrono::microseconds(50000));
|
2021-05-24 19:52:19 -04:00
|
|
|
}
|
2022-05-06 18:19:37 -04:00
|
|
|
});
|
|
|
|
}
|
2023-01-07 11:24:02 -05:00
|
|
|
repl_startup_func();
|
repl: Add a few new quality of life improvements (#2030)
- You can define a `startup.gc` in your user folder, each line will be
executed on startup (deprecates the usefulness of some cli flags)
- You can define a `repl-config.json` file to override REPL settings.
Long-term this is a better approach than a bunch of CLI flags as well
- Via this, you can override the amount of time the repl will attempt to
listen for the target
- At the same time, I think i may have found why on Windows it can
sometimes take forever to timeout when the game dies, will dig into this
later
- Added some keybinds for common operations, shown here
https://user-images.githubusercontent.com/13153231/202890278-1ff2bb06-dddf-4bde-9178-aa0883799167.mp4
> builds the game, connects to it, attaches a debugger and continues,
launches it, gets the backtrace, stops the target -- all with only
keybinds.
If you want these keybinds to work inside VSCode's integrated terminal,
you need to add the following to your settings file
```json
"terminal.integrated.commandsToSkipShell": [
"-workbench.action.quickOpen",
"-workbench.action.quickOpenView"
]
```
2022-11-20 14:28:41 -05:00
|
|
|
|
2022-05-06 18:19:37 -04:00
|
|
|
// Poll Terminal
|
|
|
|
while (status != ReplStatus::WANT_EXIT) {
|
|
|
|
if (status == ReplStatus::WANT_RELOAD) {
|
2022-10-01 11:58:36 -04:00
|
|
|
lg::info("Reloading compiler...");
|
2022-05-06 18:19:37 -04:00
|
|
|
std::lock_guard<std::mutex> lock(compiler_mutex);
|
|
|
|
if (compiler) {
|
|
|
|
compiler->save_repl_history();
|
|
|
|
}
|
2023-01-07 11:24:02 -05:00
|
|
|
compiler = std::make_unique<Compiler>(
|
2023-04-11 17:57:20 -04:00
|
|
|
game_version, std::make_optional(repl_config), username,
|
2024-06-03 00:14:52 -04:00
|
|
|
std::make_unique<REPL::Wrapper>(username, repl_config, startup_file, nrepl_server_ok));
|
2022-05-06 18:19:37 -04:00
|
|
|
status = ReplStatus::OK;
|
|
|
|
}
|
2023-01-07 11:24:02 -05:00
|
|
|
// process user input
|
2022-05-06 18:19:37 -04:00
|
|
|
std::string input_from_stdin = compiler->get_repl_input();
|
|
|
|
if (!input_from_stdin.empty()) {
|
|
|
|
// lock, while we compile
|
|
|
|
std::lock_guard<std::mutex> lock(compiler_mutex);
|
|
|
|
status = compiler->handle_repl_string(input_from_stdin);
|
2021-03-03 20:52:25 -05:00
|
|
|
}
|
|
|
|
}
|
2021-05-24 19:52:19 -04:00
|
|
|
} catch (std::exception& e) {
|
2022-10-01 11:58:36 -04:00
|
|
|
lg::error("Compiler Fatal Error: {}", e.what());
|
2022-05-19 17:08:01 -04:00
|
|
|
status = ReplStatus::WANT_EXIT;
|
2020-11-24 20:48:38 -05:00
|
|
|
}
|
2020-08-22 22:30:12 -04:00
|
|
|
|
2023-01-07 11:24:02 -05:00
|
|
|
// TODO - investigate why there is such a delay when exitting
|
|
|
|
|
2022-05-06 18:19:37 -04:00
|
|
|
// Cleanup
|
2024-06-03 00:14:52 -04:00
|
|
|
if (nrepl_server_ok) {
|
2022-05-06 18:19:37 -04:00
|
|
|
repl_server.shutdown_server();
|
|
|
|
nrepl_thread.join();
|
|
|
|
}
|
2020-08-22 22:30:12 -04:00
|
|
|
return 0;
|
|
|
|
}
|