Skip to content

[GR-73086] additional libc backend#12865

Open
ahgamut wants to merge 13 commits intooracle:masterfrom
elide-dev:cosmo
Open

[GR-73086] additional libc backend#12865
ahgamut wants to merge 13 commits intooracle:masterfrom
elide-dev:cosmo

Conversation

@ahgamut
Copy link

@ahgamut ahgamut commented Jan 26, 2026

This patch adds support to build native-image binaries with Cosmopolitan Libc. More specifically:

  • CosmoLibC added as a subclass of LibCBase
  • --libc=cosmo added to SubstrateOptions
  • POSIX headers and related C directives duplicated with modifications
  • stub functions added to libchelper
  • added BooleanSupplier classes to check for libc usage
  • implementation of -fpatchable-function-entry flag (as in gcc/clang) to support debugging

This enables building binaries with native-image that can be converted to Actually Portable Executables.

  1. build the cosmocc compiler suite with this patch of Cosmopolitan Libc
  2. run make static-libs-image using this patch of labs JDK
  3. build native-image as usual with this patch on the host system
  4. use the built native-image with --libc=cosmo and provide necessary flags to build binaries

Example build recipes for Github Actions are given here.

@oracle-contributor-agreement
Copy link

Thank you for your pull request and welcome to our community! To contribute, please sign the Oracle Contributor Agreement (OCA).
The following contributors of this PR have not signed the OCA:

To sign the OCA, please create an Oracle account and sign the OCA in Oracle's Contributor Agreement Application.

When signing the OCA, please provide your GitHub username. After signing the OCA and getting an OCA approval from Oracle, this PR will be automatically updated.

If you are an Oracle employee, please make sure that you are a member of the main Oracle GitHub organization, and your membership in this organization is public.

@oracle-contributor-agreement oracle-contributor-agreement bot added the OCA Required At least one contributor does not have an approved Oracle Contributor Agreement. label Jan 26, 2026
@sgammon
Copy link

sgammon commented Jan 26, 2026

relates to #8350

@oracle-contributor-agreement
Copy link

Thank you for signing the OCA.

@oracle-contributor-agreement oracle-contributor-agreement bot added OCA Verified All contributors have signed the Oracle Contributor Agreement. and removed OCA Required At least one contributor does not have an approved Oracle Contributor Agreement. labels Jan 27, 2026
@oubidar-Abderrahim oubidar-Abderrahim self-assigned this Jan 30, 2026
@oubidar-Abderrahim
Copy link
Member

oubidar-Abderrahim commented Jan 30, 2026

Thank you for your contribution @ahgamut
@wirthi could you please assign/review this PR?

@wirthi wirthi requested a review from olpaw January 30, 2026 10:05
@wirthi wirthi changed the title additional libc backend [GR-73086] additional libc backend Jan 30, 2026
@olpaw
Copy link
Member

olpaw commented Feb 2, 2026

@sgammon thank you for this very interesting PR. We’re currently investigating whether merging it is feasible and practical. As far as I can tell, adding Cosmopolitan support in NI depends on changes in other projects that we don’t control. Is Justine Tunney willing to integrate your Cosmo changes as-is? From what I see, these are largely stub implementations of C library functionality that Cosmo is currently missing, but that LabsJDK (and the NI build) depends on at build time. Ideally, there would be an official Cosmopolitan release that includes your changes, which we could then build on.

Regarding the LabsJDK changes, I have another concern: they further increase our delta to OpenJDK and therefore increase our maintenance effort. Would you be willing to minimize these changes as much as possible and help resolve any merge conflicts that might arise in the future?

Also, could you elaborate on the need for the AArch64-specific register changes that Cosmo seems to require? Where can I read more about the rationale behind those changes?

Finally, if we integrate Cosmo support, we’ll likely need a setup to safeguard against regressions—e.g., a GitHub Actions–based CI job would be appreciated.

@olpaw olpaw self-assigned this Feb 2, 2026
@ahgamut
Copy link
Author

ahgamut commented Feb 2, 2026

Is Justine Tunney willing to integrate your Cosmo changes as-is?

At the moment, the Cosmo changes are just headers and stubs for well known functions, so I would hope yes. I've submitted a PR here: jart/cosmopolitan#1474

Regarding the LabsJDK changes, I have another concern: they further increase our delta to OpenJDK and therefore increase our maintenance effort. Would you be willing to minimize these changes as much as possible?

The labs JDK changes as far as I remember are mostly just ifdefs to account for Cosmopolitan Libc. The only major change is with respect to the r28 register on aarch64, which brings us to

Also, could you elaborate on the need for the AArch64-specific register changes that Cosmo seems to require? Where can I read more about the rationale behind those changes?

on aarch64, native-image uses r28 to note the current isolate/thread. However, Cosmopolitan Libc currently uses r28 to remember thread-local storage, so there was a clash. I just chose to use r25 because it is also callee-saved.

Finally, if we integrate Cosmo support, we’ll likely need a setup to safeguard against regressions—e.g., a GitHub Actions–based CI job would be appreciated.

We have example CI actions here. I think in terms of CI we'd just need an action that creates static-libs for cosmo libc, like labs JDK currently provides for musl, and then a simplified version of this build script.

@olpaw
Copy link
Member

olpaw commented Feb 2, 2026

However, Cosmopolitan Libc currently uses r28 to remember thread-local storage, so there was a clash. I just chose to use r25 because it is also callee-saved.

Sounds like we could possibly make this the default for all aarch64 images (not just cosmo). @lewurm do you agree?

@lewurm
Copy link
Member

lewurm commented Feb 2, 2026

However, Cosmopolitan Libc currently uses r28 to remember thread-local storage, so there was a clash. I just chose to use r25 because it is also callee-saved.

Sounds like we could possibly make this the default for all aarch64 images (not just cosmo). @lewurm do you agree?

We have a tendency to choose the same register assignment as HotSpot to ease sharing of e.g. LIR instructions. After a quick look I don't see an unclean usages of the thread registers however, so it should be fine (and if not, it's certainly fixable).

The labs JDK changes as far as I remember are mostly just ifdefs to account for Cosmopolitan Libc. The only major change is with respect to the r28 register on aarch64, which brings us to

I'm confused about that (context elide-dev/labs-openjdk@7042bab ): Do you need to change it so that you can build libjvm with the cosmo toolchain? We still need a working labsjdk build, so I'm afraid to make that actually work on any AArch64 platform that will require some more work (we can discuss this on a labs JDK PR however; can you create one?).

@olpaw
Copy link
Member

olpaw commented Feb 9, 2026

Thanks for graalvm/labs-openjdk#28

I left my comments: graalvm/labs-openjdk#28 (comment)

@olpaw
Copy link
Member

olpaw commented Feb 25, 2026

@ahgamut regarding

  1. build the cosmocc compiler suite with this patch of Cosmopolitan Libc

I was able to do that. But how to proceed from here?

I see that now the o folder got created and a lot of tests ran. But how do I use the result of this step to complete the next step:

  1. run make static-libs-image using this patch of labs JDK

I need more detailed instructions than what you provide in top comment #12865 (comment).

  • Please provide precise instructions for all the steps you mentioned above.

@olpaw
Copy link
Member

olpaw commented Feb 25, 2026

At the moment, the Cosmo changes are just headers and stubs for well known functions, so I would hope yes. I've submitted a PR here: jart/cosmopolitan#1474

Sent a ping on the Cosmo PR jart/cosmopolitan#1474 (comment)

@olpaw
Copy link
Member

olpaw commented Feb 25, 2026

  1. run make static-libs-image using this patch of labs JDK

Using

export CC=/path/to/cosmo-repo/tool/cosmocc/bin/x86_64-unknown-cosmo-cc
export CXX=/path/to/cosmo-repo/tool/cosmocc/bin/x86_64-unknown-cosmo-c++

and

bash configure --without-{alsa,cups,fontconfig,x} --with-freetype=bundled

gives me

...
checking for jni library path... default
configure: Using default toolchain gcc (GNU Compiler Collection)
configure: Will use user supplied compiler CC=/home/pwoegere/OLabs/issues/GR-73086/cosmopolitan/tool/cosmocc/bin/x86_64-unknown-cosmo-cc
checking resolved symbolic links for CC... /home/pwoegere/OLabs/issues/GR-73086/cosmopolitan/tool/cosmocc/bin/cosmocross
configure: Using gcc C compiler version 14.1.0 [x86_64-unknown-cosmo-cc (GCC) 14.1.0]
checking whether the C compiler works... no
configure: error: in '/home/pwoegere/OLabs/issues/GR-73086/labs-openjdk':
configure: error: C compiler cannot create executables
See 'config.log' for more details
configure exiting with result code 77

In other words, how does this work in detail? See #12865 (comment)

Copy link
Member

@olpaw olpaw left a comment

Choose a reason for hiding this comment

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

See comments

ahgamut added 3 commits March 2, 2026 02:58
set options when cosmo is provided
- use r25 as the thread register for aarch64
- cosmo has -ffixed-x18 and -ffixed-x28 on aarch64
- (remember to patch jdkvm.ci in labs JDK ot use r25)
- disable vaddr calculations and call fixupobj
we create equivalent files for a whole bunch of headers in
com.oracle.svm.core.posix within a subpackage cosmo. basically every
feature that involves checking for linux/posix is copied into cosmo, and
a BooleanSupplier ensures the Cosmo versions are chosen only when
--libc=cosmo is provided.

there might be issues where a class is subclassed from core.posix.foo
rather than core.posix.cosmo.foo.
ahgamut added 10 commits March 2, 2026 03:01
perhaps equivalent translation can be within cosmo
questionable casting for mcontext_t and sa_flags
the IsWindows() checks are rather annoying to deal with outside, plus
there were segfaults occurring due to memory corruption, so we moved
some of the functions needed by VirtualMemoryProvider inside for closer
examination.

and use the ImageHeapProvider without mremap for now
the option: available as a string in SubstrateOptions, with a pair of
concealed options. the individual integers can probably be part of
GraalOptions, but the value checking happens in SubstrateOptions. we
might also need to check wherever we are using these things.

at compile time: All NOPs are added before emitting LIR to a
CompilationResult. The before/after is handled by adding an offset to
the function entry when the object file is laid out (this might cause an
issue around trampolines), and during patchMethods when fixing
rip-relative calls.

at runtime: the offset due to the nops is subtracted via
ImageCodeInfo.nopsBeforeEntry when the image info is loaded, so that
runtime relativeIP checks work out ok. the subtraction is done with
CodeInfoAccess, but not UntetheredCodeInfoAccess, which may cause issues
later.
itimerspec/sigevent are stubbed anyway, so we can add them back in a
later commit once the implementations have been tested in detail.
@ahgamut
Copy link
Author

ahgamut commented Mar 2, 2026

Updated the commits to avoid merge conflicts.

When opening this PR, I provided a repo containing all scripts and Github Actions used to build example binaries (the Envmap example, and the google-java-format JAR) via this patch.

Both example binaries appear to run without error even after the latest rebase here and here. I will re-run the actions in a while to confirm.

@ahgamut
Copy link
Author

ahgamut commented Mar 2, 2026

@olpaw I have described more details of the build steps below.


  1. build the cosmocc compiler suite with this patch of Cosmopolitan Libc

this comment mentions cosmocc can be built using the above branch.

However, I found building the labs JDK required some additional headers and static libraries (at least libz, libpng, libjpeg, and libfreetype) that are not provided alongside cosmocc by default. I build these libraries using my superconfigure repo, which provides scaffolding for autotools-style builds.

Similar to the build script attempted here, it may be possible to build the static libs without having to rely on the superconfigure repo, by using the bundled option. I have not tested that build process yet.

Relevant scripts: patch-cosmo-repo.bash, build-cosmocc.bash, and build-deps-labs.bash.

  1. run make static-libs-image using this patch of labs JDK

After collecting cosmocc and headers/libraries for (libz, libjpeg, libpng, freetype), I attempt to build the static-libs-image target with the labs JDK, using the patch under discussion at graalvm/labs-openjdk#28. The goal is to have static libs similar to what is currently provided for musl in the labs JDK Releases page.

I provide some additional arguments at the configuration stage (notably --disable-precompiled-headers and --enable-dtrace=no) to simpify the build. After calling make static-libs-image I just collect the relevant archives from the build (along with libz.a from earlier) for use when building with native-image.

Relevant scripts: build-labs-jdk.bash.

Note

A detail I failed to mention earlier that is provided in the repo: static libraries within native-image (liblibchelper.a, the libjvm.a stub, and libsvm_container.a) also need to be built with cosmopolitan libc. I assume it is possible to build these via a specific target in the mx tool (as is done for glibc and musl), but for now I just use the --alt-cc option with mx.

Relevant scripts: build-graal-helpers.bash

  1. build native-image as usual with this patch on the host system

If I understand correctly, this step currently does not require cosmocc or any of the previous build artifacts. When writing the patch I used mx --env ni-ce build on my host system so I could have the diagnostic agent for testing.

Relevant scripts: build-native-image.bash.

  1. use the built native-image with --libc=cosmo and provide necessary flags to build binaries

Once native-image has been built with this patch, and cosmocc along with the other build artifacts have been collected, we can use all of them together to build native-image binaries with Cosmopolitan Libc.

For now, the liblibchelper.a, the libjvm.a stub, and libsvm_container.a built using cosmocc from earlier need to be copied to a specific folder, namely lib/svm/clibraries/linux-$ARCH/cosmo before running a build. Once those files are in the correct spot, we can build static binaries via native-image --libc=cosmo and required flags.

Relevant scripts: build-envmap-example.bash, build-google-java-format.bash.

@olpaw
Copy link
Member

olpaw commented Mar 9, 2026

Thanks for the updates. I will look into it in the next days (hopefully).

@olpaw
Copy link
Member

olpaw commented Mar 23, 2026

Thanks for the info in #12865 (comment). I'm now able to successfully build the static libs with cosmocc. Next step, using these artifacts for review and test this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

OCA Verified All contributors have signed the Oracle Contributor Agreement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants