This page documents Cosmopolitan Libc, a free and open source C library for cross-platform compilation. The content demonstrates human rights principles through unrestricted access to educational resources and scientific tools, enabling global participation in technical advancement, though it does not explicitly address human rights. Key engagement appears in Articles 26 (education) and 27 (scientific progress).
I'm a huge fan of the ideas behind this library. Using the stable ABI of "magic numbers" is brilliant. Would love to see this solution gain more usage!
It appears to build a "naked" thompson shell script without a shebang line that works as a PE file for Windows/DOS, and uses `exec` to feed a binary to the shell via a pipe.
Sorry for being naive, but how can it be possible that nobody had thought of this approach and this approach would have actually worked? What have been preventing people from coming up with something like this?
> For an example of how that works, consider the following common fact about C which that's often overlooked. External function calls such as the following:
memcpy(foo, bar, n);
Are roughly equivalent to the following assembly, which leads compilers to assume that most cpu state is clobbered:
I think most modern C and C++ compilers know that memcpy is special and optimize accordingly. I believe some C++ compilers recognize when you are using memcpy just to do bit casting to different representations and avoid doing a memory copy at all.
Doesn’t the “strlcpy” example near the bottom of the page overwrite the buffer by one byte when the source string is as long or longer than the buffer?
Imagine I have a three byte buffer, n is 3 and I copy in “foo”. The result of the MIN is going to be three. And d[3] is the fourth byte of my three byte buffer.
This is very clever. I wonder if it could be adopted for Python C extensions (where possible) to make it easier to distribute cross-platform binary distributions. Of course it wouldn’t be suitable for gui toolkits, but I imagine that the majority of Python C-extensions could be handled.
This approach of using inline asm wrappers around functions which specify exactly the clobbered registers is neat, but...
I don't think the approach of making a call from inline asm is safe. In particular, it clobbers the redzone [1], which the compiler may have used and expect to be intact after the call.
In general, at least some compilers (e.g., gcc) assume there are no calls in an inline asm block.
In case it helps anyone else, this is a compact libc for an x86_64 binary format that can bootstrap and make syscalls on several kernels but relies on static linking (it doesn’t use any platform’s shared libc).
> Please note this is intended for people who don't care about desktop GUIs, and just want stdio and sockets [...]
Not to diminish the achievement at all, but a significant limitation to be noted (and not a very surprising limitation).
I also wonder about things like the sizeof(long). On 64-bit linux, this is 8, but on windows, it's 4. Well, "on windows"... maybe this throws all the APIs that make such assumptions, uh, out the window, (puts on sunglasses).
This is an interesting, and potentially compelling argument that WebAssembly binaries and runtime actually aren’t the future of compile-once-run-anywhere systems software: these support syscalls, sockets, and stdin/stdout —- all of which requires platform-specific glue code to achieve using WebAssembly and standard libc (or JS).
I have Wine installed on my Linux system, which uses "binfmt_misc" to automatically run Windows-looking executable files through Wine. This causes an issue with Cosmopolitan, since it uses an output format that triggers binfmt_misc. I had to run this to disable binfmt_misc on my system:
Cute trick, but probably fragile. It basically requires either writing functions like memcpy in assembly by hand or parsing the compiler-generated assembly post-codegen to determine the actual set of register clobbers. Otherwise it is bound to be broken as soon as the register allocator decides to clobber a different set of registers when generating the function.
Also, this effectively makes the body of the function a part of its public ABI, which makes it morally equivalent to inlining; it requires users of the function to be recompiled each time the body (and in consequence the clobber set) is changed. But since this seems to be static-linking-only library, this seems not that much of a problem in this case.
Still, I’m expecting improvements to whole-program LTO and inter-procedural optimisations to render this hack obsolete.
This project sounds amazing and very interesting! I have one question: how does it work on bare metal? I tried to look for an explanation in the documentation but I couldn't find anything. The specific questions I have are:
1) How does this interact with a boot loader like GRUB? Or does it come with its own boot loader? But in this case, shouldn't this go in a specific location on the boot disk?
2) How does it handle io in bare metal mode? Specifically: sockets.
This is what I've been working on with RISC-V, and you have no idea how much resistance I get when I try to fix the problems relating to calling conventions, inline assembly and system calls.
I don't want to have to explain what I'm doing from the beginning every time I have a complex question about how to make a function call from inline assembly. It has really turned me off from stackoverflow as a whole. Sorry for the rant.
I think your project is awesome, and really shows that we can improve the base upon which everything rests.
> So what Cosmopolitan does for memcpy() and many other frequently-called core library leaf functions, is defining a simple macro wrapper, which tells the compiler the correct subset of the abi that's actually needed
By not marking all memory as clobbered for a call to memcpy, couldn't the memcpy overwrite a local variable, in which case reads post memcpy could miss the updated value?
> The above two compiles used the same gcc flags
Why does the before have frame pointers and post does not?
I think it's been pondered a bunch, but the legwork required to build the headers for each system so that you can execute the same binaries on every platform was tough.
I can think of two reasons: It's arguably a hack and it's not needed.
While this is awesome, it can easily break (zsh already seems to do so) and, as the author states, it is not meant for GUI apps or programs relying deeply on OS APIs, which includes a lot of apps.
Additionaly, it does not solve an important problem. Doing a build for each supported OS is not that hard and easily automated. The actual problem is to be able to reuse code and this is solved for the most part.
Even if you are trying to avoid the standard library, visual studio will insert memcpy into a loop that is just copying memory, then the linker will error out when it can't find it.
Not an answer, but Splunk currently has a large deployment of a C++ application that supports a large variety of platforms. At least as of a few years ago, they deployed C++ indexing and querying nodes on customer machines. They've spent a great deal of time to accommodate the peculiarities of enterprise customers, old compilers, etc. One might imagine that a "build once run anywhere" platform would benefit them, but they've found a business model where they were able to work around the peculiarities and still be profitable.
So while there's probably some interesting historical reasons that explain why there's no "JVM for C++", Splunk is a good example of a modern technical / business model where conquering platform fragmentation was feasible.
Author here. Here's the best explanation I've thought of so far:
> If it's this easy, why has no one done this before? The best answer I can tell is it requires an minor ABI change, where C preprocessor macros relating to system interfaces need to be symbolic. This is barely an issue, except in cases like switch(errno){case EINVAL:...}. https://justine.lol/ape.html
It also took an act of willpower. This is a novel approach to building software that says the conventional wisdom is wrong. When I first stumbled upon the idea, I couldn't believe it was even possible, until I actually did it. Now I'm glad that I did. Actually Portable Executable has been so useful for my work. I used to work on the TensorFlow team, so I've seen the worst c/c++ build toil imaginable, and looking back at those experiences I just can't believe how I managed to get by for so long without having portable build-once binaries without interpreters.
A downside of this approach is the binary can't be executed with the exec system call because the kernel doesn't recognize scripts without a shebang. It can only be executed from within a shell.
Author here. The example and repository has been updated. Many eyes make all bugs shallow. I was hoping to do more testing before posting on Hacker News. Now that the cat's out of the bag, I'd like to explain what's being done to make sure bugs like that never happen.
Cosmopolitan implements a simplified version of the Address Sanitizer (ASAN) runtime. See https://github.com/jart/cosmopolitan/blob/master/libc/log/as... I've been systematically working towards using it to vet the entire codebase. It's helped to address more than a few memory issues so far. However more work needs to be done polishing the ASAN code so it can be bootstrapped for the purposes of having memory safety in the lowest level libraries like LIBC_STR, due to the way that the Makefile requires acyclicity between libraries.
This has been less of an issue, because bugs are normally very evident in functions like strcpy(). The BSD version is an exception though, since it was only used to port programs from the OpenBSD codebase which were used sparingly. But in either case, the real focus here is having continual incremental improvements over time, and I'm very committed to addressing any and all concerns.
Cosmopolitan also has extensive unit tests. This is something that C libraries have traditional done somewhat sparingly, if at all, since C library authors conventionally rely on an ecosystem of ported software that very quickly breaks if everything isn't perfect. If you build the Cosmopolitan repository, you'll notice there's 194 independent test executables in the o/test folder. That's one of the great things about Actually Portable Executable. It makes binaries so tiny that we can have lots of tests, completely isolated from each other!
Cosmopolitan doesn't use the "red zone" because these binaries boot on bare metal and operating system code can't assume a red zone. GCC supports this. Otherwise the Linux Kernel wouldn't work, since it's compiled the same way. So invoking call from inline asm is perfectly safe. The only real issue is that the called function can't assume the stack is 16-byte aligned. But that's fine, since Cosmo only using asm(call) to call functions written in assembly.
Cosmopolitan would actually be a great fit for Python extensions, since manylinux1 requires RHEL5 support and Cosmopolitan is probably the only modern C library that still supports it (glibc these days needs rhel8+). Maybe someone will figure out a way to compile a single-file library that's simultaneously a .dylib / .dll / .so just like how Actually Portable Executable does for programs.
Author here. WebAssembly has played an important role protecting CI on the Internet and it's cool that it enables us to run LLVM in the browser. I was very surprised when I learned that some people were using it offline outside of browsers, since doing so requires a JVM-like runtime such as wasmtime. Cosmopolitan proves that it's possible to just fix C instead, which might fix all the stuff that's built on top of C too. We can in fact have first-class portable native binaries, which will only require JIT compilation if they're launched on a non-x86 machine. This is probably how Java would have been designed, if Intel's instruction set hadn't been encumbered by patents at the time. That's changed. The x86-64 patents just expired this year. So I say why not use it as a canonical software encoding.
Yes! Cosmopolitan and APE are now permissively licensed under ISC terms. So they'd be a perfect fit for language authors. One of the biggest obstacles language authors encounter, is overcoming the obstacles posed by portability between operating system apis. Cosmopolitan takes care of that. You can just use the normal textbook unix apis and have it work on Windows/Linux/BSDs. Best of all, Cosmpolitan is tiny, embeddable, and unobtrusive. As in, these "fat binaries" are actually more like 16kb in size. So any language author who chooses to use it is going to have more time to focus on their vision, while reaching a broader audience from day one, with a sexy lightweight form.
Replace modern with clang, and awful with gcc.
I have no idea why gcc is still so fast overall, but its memcpy is horrible, as shown in the blog post. My own memcpy in my libc also beats the gcc/glibc one. The compilers are only good for short memcpy's.
For the rest the asm hinders modern compiler optimizations.
Author here. That's not an inherent limitation. See https://justine.lol/apelife/index.html for an example of a GUI + TUI that's built using Cosmopolitan. The reason why I said what you quoted, is I'm simply trying to calibrate expectations. I don't view desktop GUIs as a productive area of focus, because there's such a lack of consensus surrounding the APIs that requires, and web browsers do a great job.
As for sizeof(long) it's 64-bit with Cosmopolitan, which uses an LP64 data model. That hasn't impacted its ability to use the WIN32 API. See https://github.com/jart/cosmopolitan/tree/master/libc/nt where WIN32 API functions are declared using uint32_t, int64_t, etc. It works great. I compile my Windows apps on Linux and it feels wonderful to not have to touch MSVC. Cosmopolitan even takes care of the chore of translating your UTF-8 strings into UTF-16 when polyfilling functions like open() which delegates to CreateFile() on Windows.
sudo sh -c "echo ':APE:M::MZqFpD::/bin/sh:' >/proc/sys/fs/binfmt_misc/register"
That command should allow Actually Portable Executables to co-exist with WINE, which assumes the MZ prefix, since APE binaries always use the longer MZqFpD prefix.
Author here. Bare metal so far has been a "we built it because we could" kind of feature, so please be warned it's not as polished. Here's a quick tutorial.
Basically, ape/ape.S is a traditional BIOS bootloader. It also embeds a GRUB stub, which basically just switches back to the real mode BIOS bootloader entrypoint. So it should work with or without GRUB. The boot sector loads the rest of your executable of disk and prints "actually portable executable" to your display. It then configures standard i/o to use serial uart, sets up the page tables, enters long mode, and calls _start(). That's all I've got working so far. I would love to have e1000 and virtio though!
To try it out, here's how you build the included PC BIOS system emulator and boot an x86-64 ape executable that prints a spinning deathstar:
m=tiny; make -j12 MODE=$m o/$m/tool/build/blinkenlights.com o/$m/tool/viz/deathstar.com &&
o/$m/tool/build/blinkenlights.com -rt o/$m/tool/viz/deathstar.com
It's beautiful, isn't it? Making something simultaneously compatible with multiple formats. A far more interesting use of the PE/COM “MZ” header than simply printing “This program cannot be run in DOS mode”.
"We find that the mean slowdown of WebAssembly vs. native across SPEC benchmarks is 1.55× for Chrome and 1.45× for Firefox, with peak slowdowns of 2.5× in Chrome and 2.08× in Firefox."
These binaries wouldn't provide the isolation that wasm provides... Although it's looks like they're essentially unikernels, which means that they could potentially be run per-invocation by a hypervisor.
I can confirm we came up with this optimization inside tcmalloc, and our compiler experts nacked it as unsafe, even only calling tightly controlled code. A pity, as it is really beautiful to see the improved clobbering (and even, in some cases, hacked calling conventions.)
Editorial Channel
What the content says
+0.35
Article 27Cultural Participation
Medium Advocacy Practice
Editorial
+0.35
SETL
+0.13
Content describes scientific advancement (portable C compilation across multiple platforms) and advocates participation through open source distribution.
FW Ratio: 60%
Observable Facts
Page explicitly states the project is 'Free Libre & Open Source' and links to github.com/jart/cosmopolitan.
Technical content describes scientific advancement: enabling C as 'build-anywhere run-anywhere language' across multiple platforms and architectures.
GitHub link indicates source code is publicly available for study, modification, and redistribution without restrictions.
Inferences
Open source licensing directly enables participation in scientific advancement and its benefits as guaranteed in Article 27.
Free distribution of scientific tools removes barriers to entry for developers globally, supporting universal scientific participation.
+0.25
Article 26Education
Medium Framing Practice
Editorial
+0.25
SETL
+0.11
Content provides structured educational material including step-by-step tutorials, code examples, and learning resources.
FW Ratio: 60%
Observable Facts
Page includes 'Getting Started' section with step-by-step installation and compilation instructions.
Content contains a 'Hello World' tutorial demonstrating hands-on learning with practical examples.
Page provides links to README, documentation, example code files (greenbean.c, superconfigure), and further learning resources.
Inferences
Tutorial structure is explicitly designed to develop technical competence through guided, practical instruction.
Free and unrestricted access to learning materials removes economic barriers to education.
+0.15
Article 19Freedom of Expression
Medium Framing Practice
Editorial
+0.15
SETL
+0.09
Content openly shares technical information without restrictions, demonstrating freedom to seek, receive, and impart information via internet media.
FW Ratio: 60%
Observable Facts
Page is publicly accessible without login, payment requirement, or geographic restrictions.
Content provides detailed technical information including code examples and links to external repositories (GitHub).
Information is distributed through an internet-accessible domain with no apparent content filtering mechanisms.
Inferences
Open accessibility of information demonstrates practical commitment to freedom of expression and information sharing.
Public distribution of technical knowledge reduces barriers to seeking and receiving information as guaranteed in Article 19.
ND
PreamblePreamble
No reference to human dignity, equal rights, or justice frameworks.
ND
Article 1Freedom, Equality, Brotherhood
No discussion of inherent dignity or equal rights.
ND
Article 2Non-Discrimination
No discussion of discrimination or protected characteristics.
ND
Article 3Life, Liberty, Security
No discussion of life, liberty, or personal security.
ND
Article 4No Slavery
No discussion of slavery or servitude.
ND
Article 5No Torture
No discussion of torture or cruel treatment.
ND
Article 6Legal Personhood
No discussion of legal personhood or recognition.
ND
Article 7Equality Before Law
No discussion of equality before the law.
ND
Article 8Right to Remedy
No discussion of legal remedies or justice access.
ND
Article 9No Arbitrary Detention
No discussion of arrest or detention.
ND
Article 10Fair Hearing
No discussion of fair hearing or due process.
ND
Article 11Presumption of Innocence
No discussion of presumption of innocence.
ND
Article 12Privacy
No discussion of privacy or family protection.
ND
Article 13Freedom of Movement
No discussion of freedom of movement.
ND
Article 14Asylum
No discussion of asylum or refuge.
ND
Article 15Nationality
No discussion of nationality or state protection.
ND
Article 16Marriage & Family
No discussion of family, marriage, or parental rights.
ND
Article 17Property
No discussion of property rights or ownership protection.
ND
Article 18Freedom of Thought
No discussion of thought, conscience, or religion.
ND
Article 20Assembly & Association
No discussion of peaceful assembly or association.
ND
Article 21Political Participation
No discussion of democratic participation or government.
ND
Article 22Social Security
No discussion of social security or welfare.
ND
Article 23Work & Equal Pay
No explicit discussion of work or economic participation rights.
ND
Article 24Rest & Leisure
No discussion of rest, leisure, or work hours.
ND
Article 25Standard of Living
No discussion of adequate standard of living.
ND
Article 28Social & International Order
No discussion of social or international order.
ND
Article 29Duties to Community
No discussion of duties or community obligations.
ND
Article 30No Destruction of Rights
No discussion of preventing rights destruction.
Structural Channel
What the site does
+0.30
Article 27Cultural Participation
Medium Advocacy Practice
Structural
+0.30
Context Modifier
ND
SETL
+0.13
Project is licensed as 'Free Libre & Open Source' and published on GitHub, enabling anyone to study, modify, and contribute.
+0.20
Article 26Education
Medium Framing Practice
Structural
+0.20
Context Modifier
ND
SETL
+0.11
Educational resources are freely accessible without paywalls, registration barriers, or economic restrictions.
+0.10
Article 19Freedom of Expression
Medium Framing Practice
Structural
+0.10
Context Modifier
ND
SETL
+0.09
Website provides unrestricted public access to information with no paywalls, authentication, geofencing, or filtering.
ND
PreamblePreamble
No structural signals regarding universal human rights principles.
ND
Article 1Freedom, Equality, Brotherhood
No structural signals regarding equality of dignity.
ND
Article 2Non-Discrimination
No structural signals regarding non-discrimination.
ND
Article 3Life, Liberty, Security
No structural signals regarding personal security.
ND
Article 4No Slavery
No structural signals regarding slavery abolition.
ND
Article 5No Torture
No structural signals regarding torture prevention.
ND
Article 6Legal Personhood
No structural signals regarding personhood.
ND
Article 7Equality Before Law
No structural signals regarding legal equality.
ND
Article 8Right to Remedy
No structural signals regarding judicial remedies.
ND
Article 9No Arbitrary Detention
No structural signals regarding arbitrary detention.
ND
Article 10Fair Hearing
No structural signals regarding fair trial.
ND
Article 11Presumption of Innocence
No structural signals regarding criminal justice.
ND
Article 12Privacy
No structural signals regarding privacy.
ND
Article 13Freedom of Movement
No structural signals regarding movement.
ND
Article 14Asylum
No structural signals regarding asylum.
ND
Article 15Nationality
No structural signals regarding nationality.
ND
Article 16Marriage & Family
No structural signals regarding family.
ND
Article 17Property
No structural signals regarding property.
ND
Article 18Freedom of Thought
No structural signals regarding conscience.
ND
Article 20Assembly & Association
No structural signals regarding assembly.
ND
Article 21Political Participation
No structural signals regarding democratic process.
ND
Article 22Social Security
No structural signals regarding social protection.
ND
Article 23Work & Equal Pay
Open source model enables voluntary contribution but does not explicitly address labor rights.
ND
Article 24Rest & Leisure
No structural signals regarding rest or leisure.
ND
Article 25Standard of Living
No structural signals regarding living standards.
ND
Article 28Social & International Order
No structural signals regarding international order.
ND
Article 29Duties to Community
No structural signals regarding community duties.
ND
Article 30No Destruction of Rights
No structural signals regarding rights protection.
Supplementary Signals
How this content communicates, beyond directional lean. Learn more
build 08564a6+zer3 · deployed 2026-02-28 15:22 UTC · evaluated 2026-02-28 15:14:40 UTC
Support HN HRCB
Each evaluation uses real API credits. HN HRCB runs on donations — no ads, no paywalls.
If you find it useful, please consider helping keep it running.