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
compilerlibs: avoid unnecessary read to +compiler-libs/topdirs.cmi #11382
Conversation
The Toploop module perform some pre-initialisation as soon as the module is linked. This pre-initialisation only affects modules linked by ocamlmktop when building custom toplevels. Indeed user-provided module are linked by ocamlmktop before the toplevel is initialised and started. This commit removes the read of topdirs.cmi from this preinitialisation stage. This may broke ocamlmktop users that install printers, but this is required to be able to write client of the toplevel compiler library that don't read +compiler-libs/topdirs.cmi. In particular, the expect_test tool from the compiler testsuite belongs to this category.
Doing something magic on printer installation also sounds like a hack to me. A naive idea would be as follows:
I think that we do something similar with |
The binary |
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.
The new approach looks nice, thanks! See inline comment.
extra_quote ^ ocamlc ^ | ||
" -I +compiler-libs -I +ocamlmktop " ^ | ||
"-linkall ocamlcommon.cma ocamlbytecomp.cma ocamltoplevel.cma " ^ | ||
"ocamlmktop_init.cmo " ^ args ^ " topstart.cmo" ^ |
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.
Out of curiosity: why are topstart
and ocamlmktop_init
handled so differently in the build system and in the installation layout? I would assume that we could use the same approach for both modules, making the overall system simpler.
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.
The Topstart
module is used by the toplevel itself, it makes sense to distribute as part of the compiler library. Since ocamlmktop
is the only user of the new Ocamlmktop_init
module, I feel that it is better to distribute it as a part of a small "ocamlmktop runtime library".
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.
You could have a topinit
module to complement topstart
, and then build ocaml
exactly as the result of ocamlmktop
called with no user-provided module at all.
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 agree with @gasche - given that topdirs.cmi
has to be special-cased by OS packagers now (i.e. +compiler-libs/topdirs.cmi
must always be installed, even in layouts which install the compiler-libs separately) it doesn't seem too bad to put this module there too?
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 would rather not increase the use of purely effectful module triggered by linking in the toplevel. It seem better to let Topmain
responsible for the initialization of the paths and the directives.
The ocamlmktop_init
module is a backward-compatibility pre-initialization step that is only required by ocamlmktop and I would rather contain it to ocamlmktop
.
I don't think this will affect utop, but have you compiled utop with it? |
I have not compiled |
My approval still stands. My gut feeling is that the approach could be further simplified by pulling down the thread of the initialization logic (see our discussion inline), but @Octachron has looked more deeply than I have and seems unconvinced -- or maybe he had enough exciting realizations about how the toplevel work and is eager to move to something else for a bit. In any case, the current PR is an improvement over the ugly hack that is currently in the codebase, so it deserves to be merged in any case. |
@Octachron may want to cleanup the commit history. I think this PR could deserve a Changes entry, it makes an observable change to the installation layout etc. |
This initialization module is linked before any of the user-provided modules and reads "+compiler-libs/topdirs.cmi". This step is required before installing any custom printers. Custom repl build before OCaml 5 are unaware of this requirement and thus ocamlmktop needs to initialize this part of the toplevel environment itself to preserve backward compatibility.
Speaking of observable change in the installation layout, the Makefile change is not quite right for bytecode only installation. I will fix that shortly. |
compilerlibs: avoid unnecessary read to +compiler-libs/topdirs.cmi (cherry picked from commit 3140fb4)
This PR proposes to modifiy the pre-initialization of the toplevel in order to not force clients of compiler-libs.toplevel to read +compiler-libs/topdirs.cmi. (This is the non-hackish alternative to #11318.)
Currently, the
ocaml
toplevel is initialized in two phases:Topeval.init
)The first pre-initialization is done to ensure that the toplevel is at least partially initialized when building custom toplevel with ocamlmktop. A good illustration of such use case would to build a custom toplevel with a custom int printer
which is automatically loaded in another module
and the custom toplevel is then build with
ocamlmktop printer.cmo loader.cmo -o mytop
When #11199 moved topdirs.cmi to +compiler-libs, it kept compatibility with this use case by loading
+compiler-libs/topdirs.cmi
in the pre-initialization phase. However, this means that nearly all programs linked withocamltoplevel.cma
will try to read this file as soon as they loadToploop
without any control on this behavior. This unavoidable cmi read created some stability in our testsuite (see #11318) but at a higher-level is seem strange to enforce such read to all users for the sake of an edge case.This PR proposes thus to:
+compiler-libs/topdirs.cmi
during the pre-initialization of the toplevel+compiler-libs/topdirs.cmi
if we are trying to install a printer and ifTopdirs
is not in the toplevel environment.A possible alternative would be to go further in the direction of the second commit and makes the directive for installing printer fully responsible of loading
topdirs.cmi
(with some caching of the type of printers to avoid reading the cmi at every printer installation). The major difference with this PR approach is that theTopdirs
module would no longer be always accessible from the toplevel.