Platforms and targets
On this page
Most of Cone is the same wherever it runs, but not all of it: threads are not yet built for every operating system, a C struct crosses differently on each, and a usize is 64 bits here and 32 bits there. This page gathers where Cone code is known to run, and what differs, so you know which targets to expect a program or package to build for, and how code can choose by target. Here is a program asking where it was compiled for:
mod target;
import stdio use *;
fn main() {
// Each test is a constant of the compile, true or false for the whole build
let os = if isWindows() { "Windows"; }
elif isLinux() { "Linux"; }
elif isMacOS() { "macOS"; }
elif isWasm() { "WebAssembly"; }
else { "another target"; };
print <- "compiled for ", os, "\n";
print <- "a usize here is ", mem.sizeof[usize]() * 8usize, " bits\n";
}
On a 64-bit Windows machine it prints:
compiled for Windows a usize here is 64 bits
Cone's compiler, conec, compiles for a target, named by a target triple: the host's own, or the one --triple or --wasm names. Each entry below names the page it comes from, and that page is the authority: where the two disagree, the other page is right.
At a glance#
| Target | What the manual says |
|---|---|
| Windows (x86-64) | supported: the standard library, threads, actors, I/O and HTTP all run here |
| Linux (x86-64) | supported, the same |
| macOS | not supported yet for threads, locks, channels and actors; a C struct crosses by value as C does on x86-64 macOS |
| WebAssembly | a target (--wasm); a C struct does not yet cross by value; usize is 32 bits; barriers do nothing |
| SPIR-V (GPU) | Vulkan form only, for compute kernels; the OpenCL form is refused |
Windows and Linux#
These two, on x86-64, are where Cone runs in full. Each of these runs on both:
- Threads, locks, channels and actors. The thread and sync packages, and so the locks, the channels and the actors built on them, and the actors package. Source: Roll your own: threads, atomics and locks and Actors in depth.
- I/O. iocore (sockets, timers, files, cancel groups and the blocking pool), iobuf, aio, actorhttp and the HTTP and TLS packages over them. The loop is an I/O completion port and Winsock on Windows, epoll on Linux. Source: I/O from an actor, The I/O loop underneath, Time, HTTP.
- Files, paths, environment, processes. path reads the paths of the system the program is built for (Windows' drive letters, shares and both separators; or POSIX's one separator and root). fs and env are written over ISO C and the posix package, which is the C library's own POSIX functions on Linux, and maps the POSIX names onto the Windows C runtime on Windows. process is written directly over kernel32 on Windows, and over posix_spawn, pipes and poll on Linux. Where the two behave differently, it is said where the function is described. Source: Files, paths and processes.
- Time. time calls the operating system for one thing, Instant.now(): QueryPerformanceCounter on Windows, clock_gettime on Linux, chosen when the program is compiled. Source: Time.
- TLS. tls asks the operating system whether a server is who it says it is: on Windows its certificate verifier (crypt32), on Linux OpenSSL's own check against the system's roots. On Windows, Congo copies OpenSSL's two libraries beside any program that imports tls or httpclient; on Linux those programs link the system's OpenSSL 3 (libssl-dev on Ubuntu). Source: HTTP.
- C structs by value. On 64-bit Windows a struct crosses as one integer if it is 1, 2, 4 or 8 bytes, and otherwise by pointer; on x86-64 Linux (System V) a struct of up to 16 bytes is passed in registers. Source: Structs and bools by value.
- The standard library's packages. The library catalogue has a section, "Where they run", saying which packages run on Windows and on Linux, which call nothing of the system's, and which have been run on Linux so far. Source: The standard library.
- Linking. What differs by system in a package's link libraries goes in a section of the manifest's [link] table: [link.windows], [link.linux] and [link.macos]. Source: Packages and the build.
macOS#
The thread and sync packages, and so the locks, the channels and the actors built on them, and the actors package, run on Windows and Linux (x86-64), not yet on macOS (Roll your own: threads, atomics and locks, Actors in depth). A version of path, fs, env and process for macOS would change their insides, not what a program calls (Files, paths and processes). What the manual does say about macOS: a C-named function passes a struct by value as C does on x86-64 macOS, as on x86-64 Linux (Structs and bools by value); a target triple naming darwin or macos makes isMacOS() true; and [link.macos] is a link section.
WebAssembly#
A WebAssembly target is named with --wasm, or a WebAssembly triple. What differs there:
- No C struct by value yet. A struct crosses as C passes it on x86-64 (Windows, Linux and macOS) only, not yet on WebAssembly. A bool, and an 8- or 16-bit integer, cross as C's do on WebAssembly too. Source: Structs and bools by value.
- Pointer-sized numbers are 32 bits. usize and isize are 64 bits on some targets and 32 on others, such as WebAssembly, which is why neither may be reinterpreted as a fixed-width number type: convert the value instead. Source: Reinterpretation: as.
- Barriers do nothing. A GPU workgroup's barriers do nothing on WebAssembly. Source: Intrinsics, The GPU.
- No entry from the compiler. A WebAssembly or GPU module gets no entry (the runner of every module's initializer and finalizer) from the compiler. Source: Global state and initialisation.
- A failed check traps. WebAssembly links no runtime to report a panic, so a check the compiler inserts (an index out of bounds, say) is a trap instead. Source: Panics.
SPIR-V and the GPU#
Compiled for a GPU, the entry points of a module are written as SPIR-V's Vulkan form: conec --triple=spirv1.6-unknown-vulkan1.3 writes <name>.spv. SPIR-V's OpenCL form (--triple=spirv64-unknown-unknown) has kernels of another kind, and a compute entry point compiled for it is refused. Not implemented: any GPU target but SPIR-V's Vulkan form. A SPIR-V triple makes none of the OS tests below true. Source: The GPU (its status note and its first section, on compiling for a GPU).
Choosing by target in your own code#
The tests in the program above are core's constants of the compile, read from the target triple with no flag: isWindows() (a triple naming windows, such as x86_64-pc-windows-msvc), isLinux(), isMacOS() (one naming darwin or macos) and isWasm(). At most one holds, and none for a SPIR-V triple. An if on one of them has only the side the build takes generated, so a program links without the other platform's functions. This is a provisional mechanism, and its final design is open. The full description, with its caveats and with the -D constants a build can name on the command line, is under Constants of the build.
You can now say where a program will run, and make one program fit several targets. Last in this part comes what the compiler does on behalf of library code that needs to go deeper still: the intrinsics.