-
Notifications
You must be signed in to change notification settings - Fork 471
Reliably determine @rescript/runtime path #7637
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
rescript
@rescript/darwin-arm64
@rescript/darwin-x64
@rescript/linux-arm64
@rescript/linux-x64
@rescript/runtime
@rescript/win32-x64
commit: |
BTW this approach should also make it easier to move the runtime to |
@zth This probably needs to be taken into account in the editor extension, too?
So maybe the variable should actually be |
a18e180
to
2daa984
Compare
@cknitt this means that you have to supply that env variable always to be able to run bsc standalone...? |
Yes. I mean we could fall back to the previous algorithm if the variable is not set, but we need to be aware that there are cases where this algorithm will not work. We could also use a command line argument instead of an env var if that's your concern - just more work to implement to get it passed through for both rewatch and bsb. |
Would like to have a fallback for this. I frequently run bsc. |
Note that that would only be an issue when directly running the platform-specific When running bsc via |
b7afc8e
to
56bb638
Compare
That includes running |
Would it be possible to make it an optional bsc arg (that uses the old algorithm if not supplied) and bake resolving that into the "compiler args" command? Rewatch could call a node script to get the path. Maybe in the future we could check if this resolution is needed at all by checking what package manager is used. Bsc is already used standalone in a few places, and I envision it being used even more standalone in the future (Svelte integration, one off scripts, code blocks in docs etc). The overhead of calling a node process for each invocation is non-negligible, and the orchestration for figuring out how to call it shouldn't be too difficult (that's why compiler args is so nice). |
Yes, we could make it an optional bsc arg. There actually already exists an optional arg If the flag is not set, the default could be the simple implementation we had earlier that just assumed npm's I would avoid rewatch calling node though, I'd prefer node/bun/whatever calling rewatch via the wrapper script, with the wrapper script passing the correct location of the runtime as implemented in this PR. rewatch can then directly call bsc.exe with the |
d64d7ed
to
0ccec74
Compare
Now using a |
@cknitt don't know the details here, but a thought - would "compiler args" contain everything needed for the runtime path? So that one can always call that and get everything needed to call Maybe something obvious, but thought I'd ask. |
Yes, compiler args will also contain the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still a little on the fence.
|
||
const delegate_args = process.argv.slice(2); | ||
if (!delegate_args.includes("-runtime-path")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So this happens when we run bunx bsc
directly. It makes me wonder if we could just reuse this and pass it to Rewatch via an environment variable.
I'm not against oxc_resolver
per se, but doesn't this create two different mechanisms for resolving the -runtime-path
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Passing the runtime path to rewatch via an env var or command line flag was my original intention, but then I thought it was better if rewatch can remain self-contained here so that you can just invoke the binary directly and it does the resolution itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, my experience with calling rewatch directly is that I need to set RESCRIPT_BSC_EXE
, so it seems a bit weird that we do this for the runtime but not the compiler.
@@ -249,26 +250,41 @@ pub fn get_bsc() -> PathBuf { | |||
.to_stripped_verbatim_path() | |||
} | |||
|
|||
pub fn get_rescript_legacy(project_context: &ProjectContext) -> PathBuf { | |||
pub fn get_runtime_path(project_context: &ProjectContext) -> anyhow::Result<PathBuf> { | |||
let resolver = Resolver::new(ResolveOptions::default()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the resolver expensive to make?
If this helper called multiple times, it might make sense to have this outside the function and scoped to the lifetime of the process.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know, but it is only called once in initialize_build
if I am not mistaken.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, we should be mindful of it if we end up using it again for other parts.
There is a part of hoping it can be used in helpers::try_package_path
as well (used by packages::read_dependency
and config::flatten_ppx_flags
).
In there, we are trying some logical things, yet perhaps we can offload it as well to oxc.
@@ -97,6 +97,7 @@ pub struct BuildState { | |||
pub module_names: AHashSet<String>, | |||
pub deleted_modules: AHashSet<String>, | |||
pub bsc_path: PathBuf, | |||
pub runtime_path: Option<PathBuf>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not 100% sold that this should be part of the BuildState
.
Computing it in compile::compile
is probably fine.
The fact that is is optional is a bit of a smell to make.
Clean doesn't use this.
rewatch/src/build.rs
Outdated
@@ -89,6 +89,9 @@ pub fn get_compiler_args(rescript_file_path: &Path) -> Result<String> { | |||
interface_filename.push('i'); | |||
PathBuf::from(&interface_filename).exists() | |||
}; | |||
|
|||
let runtime_path = helpers::get_runtime_path(&project_context).ok(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this not fail? Isn't this destined to throw a more cryptic error in bsc
if it wasn't found?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, it falls back to the default (simple) implementation in bsc then, but it can still continue.
When building @rescript/runtime
itself, the resolution will fail for example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(.ok
means "toOption", weird naming...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be good to add that somewhere in the code as well, when it is fine to be None
.
|
||
rescript_legacy_path.unwrap_or_else(|_| panic!("Could not find rescript-legacy.exe")) | ||
// Resolve <project> -> rescript |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you elaborate in a code comment why you are resolving rescript
package first? This seems like an unnecessary extra step. Why not search for @rescript/runtime
from the get go?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tried that, but didn't work, probably because there is no direct dependency on the runtime package. Or maybe I was doing something wrong. I can have another look.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No — that may just be how resolve_oxc
and https://nodejs.org/api/esm.html#resolution-algorithm
work. That’s fine, but we should document it.
There’s a tendency to assume oxc_resolver
can solve everything; I’m all for leaning on it when it helps, but we need to understand and document what it can and cannot do.
Let’s leave clear "whys" for future contributors so they understand our decisions and don’t keep getting challenged.
1b65720
to
944d91b
Compare
(updated description after moving the runtime to
@rescript/runtime
and deciding to use a command line arg instead of an env var)To determine the path of the runtime module
@rescript/runtime
in a reliable way that works with all package managers / package directory layouts, we need to use the JS module resolution algorithm.In rewatch, we can use https://github.com/oxc-project/oxc-resolver.
For the legacy build system, we can just use
require.resolve
.This should fix all issues with pnpm not finding the runtime module.