Skip to content
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

Rework racket based runtime/compilation #4675

Merged
merged 188 commits into from
Mar 8, 2024
Merged

Conversation

dolio
Copy link
Contributor

@dolio dolio commented Feb 6, 2024

This PR includes the changes that get us about as far as we can easily go for our racket evaluation/compilation at the moment. It includes the following aspects.

  • I renamed the runner file/executable to ucr, so that it's more similar to ucm. It's not something that people should be calling directly, but runner is obviously not a very good name.
  • I changed the 'compilation' part of ucr to just generate a file. The reason for this is that somehow a math library we are using for the primops causes create-embedding-executable to fail. The easiest solution to this problem is to divide the compilation process into two steps: first generate the file using all the unison infrastructure, then compile that file. At first I was thinking about copying the math operations into the primops, but I realized that dividing the programs up is a better solution.
  • At the moment, compiling the generated file is just done via raco exe using a racket installation. The reason for this is that create-embedding-executable does not seem to work in a standalone executable. The API needs to find a copy of the racket executable to modify, and the procedure for that doesn't work in a standalone binary (confirmed with racket devs). Peeking at the code, it doesn't seem like this absolutely couldn't work, but making it work would require someone digging into the racket internals to make it happen. So for the time being, compiling requires a racket install.
  • I've included a short transcript that will download base, @unison/internal, and generate the racket modules alongside the checked-in modules. This is a step necessary in building ucr or getting things set up for compilation, so we'll probably use it when we get this stuff building in CI.

Even for compilation, where we still depend on a racket install, we no longer actually need to make people download @unison/internal themselves. We can run the library generation as part of a build, and just distribute the generated libraries to people. The runtime should be completely self-contained, though. Once ucr is built, ucm just needs to shell out to it to execute run.native. A racket install is only necessary to build ucr.

I think one tweak I have left is a better error message for compile.native if raco doesn't exist. Beyond that, I just need a little advice on how to get this hooked into CI to get everything distributed properly. I might need to make the native runtime calls a bit more configurable with respect to the location of ucr and such, too, but that shouldn't be a big deal.

dolio added 4 commits January 16, 2024 15:24
Switch compile.native to using the native Runtime

Tweak the call for compilation to use `racket runner.rkt`, since it
seems like _compiling_ runner.rkt precludes the use of
create-embedding-executable, at least until something further is figured
out.

runner and other racket infrastructure additions for producing the right
input for racket executable creation
There are, for the moment, multiple problems with producing executables.
One is that the API doesn't work when certain math libraries are
imported. The other is that the API doesn't work in a generated
executable.

So, I've turned the 'compile mode' of the standalone runtime program
just generate a module to be compiled. Then we can use an installed
`raco` to build that module into a standalone program. I don't think
there's any advantage currently to not using raco, since the best we can
do is write our own separate exe builder that still requires racket to
be installed.

In any case, the exe builder must apparently be a separate program so
that it doesn't need to import the offending math library.
@aryairani
Copy link
Contributor

  • I renamed the runner file/executable to ucr, so that it's more similar to ucm. It's not something that people should be calling directly, but runner is obviously not a very good name.

I'm thinking we could use a more descriptive name and stick it in libexec if nobody needs to call it.

  • I changed the 'compilation' part of ucr to just generate a file.

What did it do before?

  • I've included a short transcript that will download base, @unison/internal, and generate the racket modules alongside the checked-in modules. This is a step necessary in building ucr or getting things set up for compilation, so we'll probably use it when we get this stuff building in CI.

Even for compilation, where we still depend on a racket install, we no longer actually need to make people download @unison/internal themselves. We can run the library generation as part of a build, and just distribute the generated libraries to people. The runtime should be completely self-contained, though. Once ucr is built, ucm just needs to shell out to it to execute run.native. A racket install is only necessary to build ucr.

Can we just do all of this in CI? Build ucr there, and nobody needs to install racket outside of CI?

I think one tweak I have left is a better error message for compile.native if raco doesn't exist. Beyond that, I just need a little advice on how to get this hooked into CI to get everything distributed properly.

We can pair on the CI part if you want.

@dolio
Copy link
Contributor Author

dolio commented Feb 6, 2024

I'm thinking we could use a more descriptive name and stick it in libexec if nobody needs to call it.

Any suggestion on the name? I guess it could be something more like unison-runtime or something.

What did it do before?

It generated a file then threw errors. But the command line gave you the expectation that it would produce an executable.

Can we just do all of this in CI? Build ucr there, and nobody needs to install racket outside of CI?

You can do the equivalent of run. Or you can generate a racket source file, but that's useless without racket. If you want to build a standalone executable from some unison code, you need racket installed, because the API for generating executables doesn't work when you build it into a standalone executable.

ucrError (_ :: IOException) =
die
"I had trouble calling the unison runtime exectuable.\n\n\
\Please check that the `ucr` executable is properly\
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be great to link to a guide in these errors, as an end user I wouldn't know where to start on ensuring "ucr" is installed and google probably won't help.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'd like to make them better. I'm not exactly sure what the install process will be right now, though. Hopefully I can flesh these out after I work out some details with Arya.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm anticipating that either our installers will set it up correctly for them, or they're in big trouble and need to come ask for help, which will help us flesh out better error messages :-\

@ChrisPenner
Copy link
Contributor

Looks great! I'd second the idea of changing ucr to something like unison-runtime

dolio added 5 commits February 7, 2024 16:10
All the infrastructure was there already, just needed to enable it.

This should break the jit tests in CI until we can get the runner
building as a prior step, and coordinate the location the native runtime
looks for the build files.
@aryairani

This comment was marked as outdated.

Arya Irani added 8 commits February 11, 2024 21:02
recommend moving support scheme files to another repo
if they aren't deeply related to ucm; but maybe they are.
but bash tricks can maybe?
Copy link
Contributor

@aryairani aryairani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm gonna doublecheck CI again in the morning, but I think this is ready to merge even though we may do some additional tweaks later.

@aryairani
Copy link
Contributor

aryairani commented Mar 7, 2024

Okay, I think the tests in @aryairani/jit-tests should pass with this branch.

I also added compiler.generateSchemeBoot to @unison/internal in the new release 0.0.11 that this depends on. I think you were planning on doing something with that in the transcripts?

Thanks for the reminder, got it in 20a0e73.

@aryairani
Copy link
Contributor

aryairani commented Mar 8, 2024

The default runtime location is set in fixNativeRuntimePath, currently as $XDG_DATA/unisonlanguage/libexec/unison-runtime, and can be overridden by nativeRuntimePathFlag.

  • It should probably default to a system-wide location though, like $0/unison-runtime?

The default runtime location is set in fixNativeRuntimePath, as $0/runtime/unison-runtime[.exe], and can be overridden by nativeRuntimePathFlag.

@aryairani
Copy link
Contributor

A racket install is only necessary to build ucr.

The racket install is still needed to use compile.native, right?

@aryairani aryairani merged commit 27b29c1 into trunk Mar 8, 2024
12 checks passed
@aryairani aryairani deleted the topic/native-compiler branch March 8, 2024 22:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants