Explicitly compile the primitives object before linking bytecode executables#12896
Merged
Conversation
lthls
approved these changes
Jan 16, 2024
Contributor
lthls
left a comment
There was a problem hiding this comment.
Looks good to me.
I think it's clearly better to not rely on the linker to compile C files.
I believe that we can also remove Ccomp.linker_is_flexlink now.
| let flag = | ||
| [Printf.sprintf "-fdebug-prefix-map=%s=camlprim.c" prim_name] | ||
| in | ||
| if Ccomp.linker_is_flexlink then |
Contributor
There was a problem hiding this comment.
I believe this was the only use of Ccomp.linker_is_flexlink
Member
Author
There was a problem hiding this comment.
Yes, indeed it is! Another victory - no longer needing a function to work out if the C compiler pretending to be a linker is in fact a linker pretending to be a C compiler 🤯
Co-authored-by: David Allsopp <david.allsopp@metastack.com>
Introduces a few convenient blank lines to improve the readability of camlprim.c and the C file generated for `-output-obj`.
In bytecode, when compiling a custom runtime (when using any of -custom, -output-obj, -output-complete-obj or -output-complete-exe), the camlprim.c file is passed directly to the linker. When this was originally done, the cost was a single typedef for the value type, but now this process involves considerable code duplication both for the -fdebug-prefix-map implementation and for the full definition of the value type. The primitives file is now explicitly compiled, which means it gets treated in the same way as a C file passed to ocamlc and in particular can `#include <caml/mlvalues.h>` to remove the definitions otherwise duplicated with <caml/config.h>. Using `Ccomp.compile_file` also allows the duplicate machinery for `-fdebug-prefix-map` to be deleted from Bytelink.
Instead of the `guarded_primitives` mechanism in bytelink.ml, don't declare the primitives `caml_get_public_method` and `caml_set_oo_id` in mlvalues.h when `CAML_INTERNALS_NO_PRIM_DECLARES` is defined so that it can be included as-is in `camlprim.c` (where those primitives are declared at a very generic type instead of their real type) without needing `#define`/`#undef` wrappers.
Since we no longer pass C files to the "linker"!
d119e81 to
5521385
Compare
Member
Author
|
Thanks @lthls! |
dra27
added a commit
to dra27/ocaml
that referenced
this pull request
Feb 1, 2024
Explicitly compile the primitives object before linking bytecode executables (cherry picked from commit b3b892e)
dra27
added a commit
to dra27/ocaml
that referenced
this pull request
Feb 1, 2024
Explicitly compile the primitives object before linking bytecode executables (cherry picked from commit b3b892e)
dra27
added a commit
to dra27/ocaml
that referenced
this pull request
Feb 13, 2024
Explicitly compile the primitives object before linking bytecode executables (cherry picked from commit b3b892e)
shym
added a commit
to shym/ocaml
that referenced
this pull request
Jul 10, 2024
The `runtime` directory must be `-I`ncluded only since ocaml#12896 and only in ocamltest. When building an OCaml cross compiler, two OCaml compilers are really involved, where the non-cross compiler is used to build the cross one. Most cross-compiler projects do that by overriding variables such as `CAMLOPT` to point to the non-cross compiler during the build of the cross compilers. In these use cases, adding the explicit `-I runtime` makes them generate the cross compilers linking in the cross runtime (which naturally fails) instead of the build/host runtime that the non-cross compiler would use without `-I runtime`. To re-enable those use cases, this patch moves the addition only on `ocamltest/%` targets.
shym
added a commit
to shym/ocaml
that referenced
this pull request
Jul 16, 2024
The `runtime` directory must be `-I`ncluded only since ocaml#12896 and only in ocamltest. When building an OCaml cross compiler, two OCaml compilers are really involved, where the non-cross compiler is used to build the cross one. Most cross-compiler projects do that by overriding variables such as `CAMLOPT` to point to the non-cross compiler during the build of the cross compilers. In these use cases, adding the explicit `-I runtime` makes them generate the cross compilers linking in the cross runtime (which naturally fails) instead of the build/host runtime that the non-cross compiler would use without `-I runtime`. To re-enable those use cases, this patch moves the addition only on `ocamltest/%` targets.
shym
added a commit
to shym/ocaml
that referenced
this pull request
Jul 17, 2024
The `runtime` directory must be `-I`ncluded only since ocaml#12896 and only in ocamltest. When building an OCaml cross compiler, two OCaml compilers are really involved, where the non-cross compiler is used to build the cross one. Most cross-compiler projects do that by overriding variables such as `CAMLOPT` to point to the non-cross compiler during the build of the cross compilers. In these use cases, adding the explicit `-I runtime` makes them generate the cross compilers linking in the cross runtime (which naturally fails) instead of the build/host runtime that the non-cross compiler would use without `-I runtime`. To re-enable those use cases, this patch moves the addition only on `ocamltest/%` targets.
shym
added a commit
to shym/ocaml
that referenced
this pull request
Jul 19, 2024
The `runtime` directory must be `-I`ncluded only since ocaml#12896 and only in ocamltest. When building an OCaml cross compiler, two OCaml compilers are really involved, where the non-cross compiler is used to build the cross one. Most cross-compiler projects do that by overriding variables such as `CAMLOPT` to point to the non-cross compiler during the build of the cross compilers. In these use cases, adding the explicit `-I runtime` makes them generate the cross compilers linking in the cross runtime (which naturally fails) instead of the build/host runtime that the non-cross compiler would use without `-I runtime`. To re-enable those use cases, this patch moves the addition only on `ocamltest/%` targets.
shym
added a commit
to shym/ocaml
that referenced
this pull request
Jul 19, 2024
The `runtime` directory must be `-I`ncluded only since ocaml#12896 and only in ocamltest. When building an OCaml cross compiler, two OCaml compilers are really involved, where the non-cross compiler is used to build the cross one. Most cross-compiler projects do that by overriding variables such as `CAMLOPT` to point to the non-cross compiler during the build of the cross compilers. In these use cases, adding the explicit `-I runtime` makes them generate the cross compilers linking in the cross runtime (which naturally fails) instead of the build/host runtime that the non-cross compiler would use without `-I runtime`. To re-enable those use cases, this patch moves the addition only on `ocamltest/%` targets.
shym
added a commit
to shym/ocaml
that referenced
this pull request
Aug 20, 2024
The `runtime` directory must be `-I`ncluded only since ocaml#12896 and only in ocamltest. When building an OCaml cross compiler, two OCaml compilers are really involved, where the non-cross compiler is used to build the cross one. Most cross-compiler projects do that by overriding variables such as `CAMLOPT` to point to the non-cross compiler during the build of the cross compilers. In these use cases, adding the explicit `-I runtime` makes them generate the cross compilers linking in the cross runtime (which naturally fails) instead of the build/host runtime that the non-cross compiler would use without `-I runtime`. To re-enable those use cases, this patch moves the addition only on `ocamltest/%` targets.
shym
added a commit
to shym/ocaml
that referenced
this pull request
Aug 20, 2024
The `runtime` directory must be `-I`ncluded only since ocaml#12896 and only in ocamltest. When building an OCaml cross compiler, two OCaml compilers are really involved, where the non-cross compiler is used to build the cross one. Most cross-compiler projects do that by overriding variables such as `CAMLOPT` to point to the non-cross compiler during the build of the cross compilers. In these use cases, adding the explicit `-I runtime` makes them generate the cross compilers linking in the cross runtime (which naturally fails) instead of the build/host runtime that the non-cross compiler would use without `-I runtime`. To re-enable those use cases, this patch moves the addition only on `ocamltest/%` targets.
shym
added a commit
to shym/ocaml
that referenced
this pull request
Sep 25, 2024
The `runtime` directory must be `-I`ncluded only since ocaml#12896 and only in ocamltest. When building an OCaml cross compiler, two OCaml compilers are really involved, where the non-cross compiler is used to build the cross one. Most cross-compiler projects do that by overriding variables such as `CAMLOPT` to point to the non-cross compiler during the build of the cross compilers. In these use cases, adding the explicit `-I runtime` makes them generate the cross compilers linking in the cross runtime (which naturally fails) instead of the build/host runtime that the non-cross compiler would use without `-I runtime`. To re-enable those use cases, this patch moves the addition only on `ocamltest/%` targets.
shym
added a commit
to shym/ocaml
that referenced
this pull request
Sep 30, 2024
The `runtime` directory must be `-I`ncluded only since ocaml#12896 and only in ocamltest. When building an OCaml cross compiler, two OCaml compilers are really involved, where the non-cross compiler is used to build the cross one. Most cross-compiler projects do that by overriding variables such as `CAMLOPT` to point to the non-cross compiler during the build of the cross compilers. In these use cases, adding the explicit `-I runtime` makes them generate the cross compilers linking in the cross runtime (which naturally fails) instead of the build/host runtime that the non-cross compiler would use without `-I runtime`. To re-enable those use cases, this patch moves the addition only on `ocamltest/%` targets.
shym
added a commit
to shym/ocaml
that referenced
this pull request
Oct 2, 2024
The `runtime` directory must be `-I`ncluded only since ocaml#12896 and only in ocamltest. When building an OCaml cross compiler, two OCaml compilers are really involved, where the non-cross compiler is used to build the cross one. Most cross-compiler projects do that by overriding variables such as `CAMLOPT` to point to the non-cross compiler during the build of the cross compilers. In these use cases, adding the explicit `-I runtime` makes them generate the cross compilers linking in the cross runtime (which naturally fails) instead of the build/host runtime that the non-cross compiler would use without `-I runtime`. To re-enable those use cases, this patch moves the addition only on `ocamltest/%` targets.
shym
added a commit
to shym/ocaml
that referenced
this pull request
Oct 2, 2024
The `runtime` directory must be `-I`ncluded only since ocaml#12896 and only in ocamltest. When building an OCaml cross compiler, two OCaml compilers are really involved, where the non-cross compiler is used to build the cross one. Most cross-compiler projects do that by overriding variables such as `CAMLOPT` to point to the non-cross compiler during the build of the cross compilers. In these use cases, adding the explicit `-I runtime` makes them generate the cross compilers linking in the cross runtime (which naturally fails) instead of the build/host runtime that the non-cross compiler would use without `-I runtime`. To re-enable those use cases, this patch moves the addition only on `ocamltest/%` targets.
shym
added a commit
to shym/ocaml
that referenced
this pull request
Oct 3, 2024
The `runtime` directory must be `-I`ncluded only since ocaml#12896 and only in ocamltest. When building an OCaml cross compiler, two OCaml compilers are really involved, where the non-cross compiler is used to build the cross one. Most cross-compiler projects do that by overriding variables such as `CAMLOPT` to point to the non-cross compiler during the build of the cross compilers. In these use cases, adding the explicit `-I runtime` makes them generate the cross compilers linking in the cross runtime (which naturally fails) instead of the build/host runtime that the non-cross compiler would use without `-I runtime`. To re-enable those use cases, this patch moves the addition only on `ocamltest/%` targets.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR forms a small part of the "Relocatable OCaml" series of patches, but is opened at the moment because it is a solution to a problem affecting the restoration of the MSVC port of OCaml. The PR is virtually impossible to review as a whole - please see after the background for advice on reviewing commit-by-commit.
Background
When compiling a custom bytecode runtime, a C file is generated containing the combined primitives table of the runtime (
camlprim.c). Presently, this is passed directly toCcomp.call_linkerand is written in a way which avoids using any of the C headers. This has resulted in increasing amounts of code duplication - thetypedefforintnat(already incaml/config.h) has to be inferred and the linker command line inBytelinkhas to handle-fdebug-prefix-map, duplicating logic already inCcompto handle this. The duplication gets worse with the relocatable compiler patches.The MSVC port of OCaml at present requires
-experimental:c11atomics -std:c11to be added in order to enable the experimental C11 atomics support which we rely on. While this doesn't affect the compilation ofcamlprim.cin-custommode (because of the duplicatedtypedef), it renders the C file for-output-obj, which does include header files uncompilable. The issue affecting MSVC is thatCcomp.call_linkerquite rightly does not passConfig.ocamlc_cflagsto the compiler.Changes
This PR alters
ocamlc's link process so that primitives file is explicitly compiled usingCcomp.compile_file. That eliminates the duplicated debug prefix map code and also allowscaml/mlvalues.hto be used to get all the required definitions.Ccomp.compile_fileobviously does passConfig.ocamlc_cflags, which fixes the problem for the MSVC port.For the build system, this means when building with
-customthat we must ensure thatruntimedirectory has been included with-Iso that the headers are available (the build system does not use-output-objor any of the other modes which already require access to the headers, which is why this has not been necessary before).Although the statistics for the PR may therefore hide it, the overall effect is to reduce code/logic duplication 🙂
Reviewing
Given that this PR alters some of the C files generated by the bytecode linker, the opportunity is being taken to modernise some of this code a little bit. Since #5146, various C files put
\nat the beginning of lines which, while fixing the issue introduced in OCaml 3.12 by the unescaped newline warning, leaves the intent of the code somewhat obscured. Now that #12514 is merged, we can instead take advantage of OCaml 4.02's quoted strings, making both the C code being emitted, and the formatting of the lines, somewhat less obscure. I was partly motivated to put this change in having misread\nmarkings and initially generated syntactically invalid code while testing this.The first commit is intended to result in no changes to the C files generated, which means that the very noisy diff can be tested more easily with:
The second commit then applies a few very minor changes to the C files - the C++ guard is consistently moved to the start of the file, and a few extra blank lines are added
Difference in generated C file
The third commit is then the main part of the change - when looking at the diff in
Bytelink.build_custom_runtime, especially for the deleted code, it is worth havingCcomp.compile_fileside-by-side (i.e. by inspection one should be able to confirm that the C file is then being compiled in a similar way to how it was being linked before).The final commit, proposes an alternate mechanism for dealing with the
caml_get_public_methodandcaml_set_oo_idprimitives inmlvalues.hto the one which was added in #12509. It is an optional addition, but motivated by the fact that theguarded_primitivesmechanism now appears in two places in bytelink.ml.