cosmopolitan experiments
Go to file
Connor Olding 652e29ad50 update perl 2022-09-23 17:08:10 -07:00
cosmo move dedupe to utilities and write a wrapper 2022-09-23 14:05:19 -07:00
cosmo-kuroko add cosmo-kuroko 2022-09-23 13:19:43 -07:00
cosmo-perl update perl 2022-09-23 17:08:10 -07:00
cosmo-yices update comments and todo 2022-09-23 15:39:25 -07:00
notwa-util move dedupe to utilities and write a wrapper 2022-09-23 14:05:19 -07:00
.gitignore ignore out directory 2022-09-23 13:45:26 -07:00
README.md better wording 2022-09-23 15:16:58 -07:00
TODO.md update todo 2022-09-23 15:57:36 -07:00
build-all update perl 2022-09-23 17:08:10 -07:00
install-cosmo add install-cosmo script 2022-09-23 14:46:24 -07:00

README.md

stargazing

this repository contains experiments in building third-party software against cosmopolitan libc. the provided scripts produce APEs (Actually Portable Executables) that run on Linux, Mac, Windows, FreeBSD, OpenBSD, and NetBSD. however, despite running on all platforms, not every feature is available on every platform. cosmopolitan already does a tremendous job at polyfilling missing features across platforms, but pre-existing software still takes a lot of patching before becoming fully functional.

building

on most Linux distros with podman properly installed and configured, it should suffice to run ./build-all in the root of the repository. binaries are output to the out/ directory upon success.

installing

no installation is necessary — everything in the out/ directory is self-contained. however, if you'd like to use create your own pseudo-release of cosmopolitan to build against, you can run install-cosmo to install an amalgamation to /opt/cosmopolitan/. this includes the amalgamation (in dist/), the gcc toolchain (in gcc/), some essential APEs (in bin/), and all the necessary headers.

notes

Docker

this project uses Dockerfiles to allow for mostly-reproducible builds. podman is used instead of docker, because the official docker software is commercial and obnoxious.

neither docker nor podman is required for executing the binaries. binaries are to be isolated and extracted from the resulting containers. those binaries can then be transferred across platforms, like any other APE.

in the future, it would be nice to use something like what Void Linux does for its packages, which would entirely sidestep the clunkiness of Dockerfiles and working with containers.

make no mistake, this project does not strive for reproducible builds in any way that nix does.

Host OS

this project must be built on a host running Linux. if you are not running Linux, use a VM of some sort. i personally use VirtualBox running Alpine Linux. i have not tried building with WSL2.

Code Style

this project encourages a heretical and horrifying style of code for its shell scripts. the intent is to chain &&s while facilitating trivial re-ordering of lines. for instance, a RUN command in a Dockerfile (which just executes a line of shell) might look like this:

RUN : \
 && echo hello \
 && note() \
    { : \
     && printf '\033[1m%s\033[m: %s\n' >&2 \
        noted "$*" \
     ;} \
# this is an inline comment! it should end with a semicolon, \
# because vim's syntax highlighting is bad. \
 && note '\\( o _ o )//' \
;

a good example of a script in this style is the acquire script.

gratuitous explanation

  • 4-space indentation is a must, since at least three characters are needed to contain the operators on the left of each line.

  • : is akin to the true command; it's used as a no-op that only sets the most recent exit code ($?) to 0.

  • \ continues the shell command to the next line; the proceeding newline is removed and ignored.

  • && is a short-circuiting operator that only evaluates its right-hand side when $? is 0. && is preferred over a simple semicolon because most programs use a non-zero exit code to indicate that an error occurred, whereas ; will continue executing code, even in the presence of an error. note: the diff command breaks the convention and uses both 0 and 1 as normal exit codes.

  • || is like && but only executes when $? is not 0. important: || has a lower precedence than &&! make sure to wrap your ||s in braces unless you want to capture everything before it. for example, an excerpt of a shell script might look like this:
    && { test -e myfile || touch myfile ;} \

  • leftmost &&s and ||s are always centered within their 4-space indent.

  • avoid using pipes (|) when possible, because only the exit code of the final command in any pipe is respected. instead, write intermediate data to /tmp when possible. remember to mount /tmp as a tmpfs at the start of the RUN command!

  • functions are declared (()) on their own line without any braces or other commands.

  • { : is used to begin a multi-line block, similar to how RUN : begins a shell command. sadly, the space between the brace and the colon is not optional.

  • ;} is used to finish a multi-line block. this is aligned with the preceeding && and || operators. thankfully, the space between ; and } is optional.

  • a final ; is used to finish off the line-continutation. this means that every line before it can end with a \, which simplifies editing. when podman gives you strange errors, double-check that you aren't forgetting a \ or the final semicolon.

  • redirections are usually specified before a final list of arguments. this makes skimming code easier when arguments extend across many lines.

  • TODO: explain if cmd \␤ ;then : \␤ && cmd \␤ ;fi.

  • TODO: explain for cmd \␤ ;do : \␤ && cmd \␤ ;done.

  • TODO: explain while cmd \␤ ;do : \␤ && cmd \␤ ;done.

  • TODO: explain tests?

  • TODO: explain the two different kinds of commends.