diff --git a/zig/README.md b/zig/README.md new file mode 100644 index 0000000..070eed1 --- /dev/null +++ b/zig/README.md @@ -0,0 +1,213 @@ +--- +title: Zig +homepage: https://ziglang.org/ +tagline: | + zig: write and cross-compile maintainable robust, optimal, and reusable software. +--- + +To update or switch versions, run `webi zig@stable` (or `@v0.9`, `@beta`, etc). + +### Files + +These are the files / directories that are created and/or modified with this +install: + +```txt +~/.config/envman/PATH.env +~/.local/opt/zig +``` + +## Cheat Sheet + +> `zig` is two things: +> +> 1. A drop-in cross-compiling toolchain for C and C++ (and Rust and CGo for +> that matter). +> +> 2. A general purpose systems programming language, like C, but intentional, +> and with benefit of hindsight. +> +> (and also a nod to +> [Zero Wing]()) + +Philosophy: + +- [The Road to Zig 1.0](https://www.youtube.com/watch?v=Gv2I7qTux7g) +- [The Zen of Zig](https://ziglang.org/documentation/master/#Zen) + +### The Zen of Zig + +- Communicate intent precisely. +- Edge cases matter. +- Favor reading code over writing code. +- Only one obvious way to do things. +- Runtime crashes are better than bugs. +- Compile errors are better than runtime crashes. +- Incremental improvements. +- Avoid local maximums. +- Reduce the amount one must remember. +- Focus on code rather than style. +- Resource allocation may fail; resource deallocation must succeed. +- Memory is a resource. +- Together we serve the users. + +### How to compile C/C++ with Zig + +You can use +[Zig as a drop-in C compiler](https://andrewkelley.me/post/zig-cc-powerful-drop-in-replacement-gcc-clang.html). + +```bash +zig cc -o ./hello main.c +zig c++ -o ./hello++ main.cpp +``` + +And you can cross-compile effortlessly: + +```bash +zig cc -o ./hello.exe main.c -target x86_64-windows-gnu +zig c++ -o ./hello.exe main.cpp -target x86_64-windows-gnu +``` + +### How to create and compile Zig programs + +1. Create a new project directory: + ```bash + mkdir -p ./zig-hello/ + pushd ./zig-hello/ + ``` +2. Initialize the project with a new `build.zig` + ```bash + zig init-exe + ``` +3. Build `hello.exe` for Windows from MacOS or Linux + ```bash + zig build-exe src/main.zig --name hello -target x86_64-windows-gnu + zig build-exe src/main.zig --name hello -target x86_64-linux-musl + zig build-exe src/main.zig --name hello-arm -target aarch64-linux-musl + zig build-exe src/main.zig --name hello-macos -target x86_64-macos-gnu + zig build-exe src/main.zig --name hello-m1 -target aarch64-macos-gnu + ``` + +### How to list and use Zig's cross-compile targets + +```bash +zig targets | jq -r '.libc[]' +``` + +Here's a few of the common targets: + +```txt +aarch64-linux-musl +aarch64-windows-gnu +aarch64-macos-gnu +thumb-linux-musleabihf +wasm32-wasi-musl +x86_64-linux-musl +x86_64-windows-gnu +x86_64-macos-gnu +``` + +### How to cross-compile Rust with Zig + +1. Create a `zig-cc-{ARCH-OS}` and `zig-cpp-{ARCH-OS}` wrappers: + + ```bash + cat << EOF >> ~/.local/bin/zig-cc-x86_64-windows-gnu + #!/bin/sh + set -e + set -u + "\${HOME}/.local/opt/zig/zig" cc -target x86_64-windows-gnu \$@ + EOF + + chmod a+x ~/.local/bin/zig-cc + ``` + + ```bash + cat << EOF >> ~/.local/bin/zig-cpp-x86_64-windows-gnu + #!/bin/sh + set -e + set -u + "\${HOME}/.local/opt/zig/zig" c++ -target x86_64-windows-gnu \$@ + EOF + + chmod a+x ~/.local/bin/zig-cpp + ``` + +2. Set the `CC`, `CPP` and `ZIGTARGET` ENVs. For example: + ```bash + #export ZIGTARGET="x86_64-windows-gnu" + export CC="zig-cc-x86_64-windows-gnu" + export CPP="zig-cpp-x86_64-windows-gnu" + ``` +3. Install the correpsonding Rust toolchains: + ```bash + rustup target install x86_64-apple-darwin + rustup target install x86_64-unknown-linux-musl + rustup target install aarch64-unknown-linux-musl + rustup target install x86_64-pc-windows-gnu + ``` +4. You may need to also specifically set the linker. For example, with Rust's + `~/.cargo/config.toml`: + + ```bash + [target.x86_64-apple-darwin] + linker = "zig-cc-x86_64-macos-gnu" + + [target.x86_64-unknown-linux-musl] + linker = "zig-cc-x86_64-unknown-linux-musl" + + [target.aarch64-unknown-linux-musl] + linker = "zig-cc-aarch64-unknown-linux-musl" + + [target.x86_64-pc-windows-gnu] + linker = "zig-cc-x86_64-windows-gnu" + ``` + +`~/.local/bin/zig-create-crossies`: + +```bash +#!/bin/bash +set -e +set -u + +my_targets="$(zig targets | jq -r '.libc[]' | sort -u)" + +for my_target in $my_targets; do + cat << EOF >> "${HOME}/.local/bin/zig-cc-${my_target}" +#!/bin/sh +set -e +set -u + +"\${HOME}/.local/opt/zig/zig" cc -target ${my_target} \$@ +EOF + + chmod a+x "${HOME}/.local/bin/zig-cc-${my_target}" +done + +for my_target in $my_targets; do + cat << EOF >> "${HOME}/.local/bin/zig-cpp-${my_target}" +#!/bin/sh +set -e +set -u + +"\${HOME}/.local/opt/zig/zig" c++ -target ${my_target} \$@ +EOF + + chmod a+x "${HOME}/.local/bin/zig-cpp-${my_target}" +done +``` + +See also: + +- + +### How to cross-compile CGo (Golang) with Zig + +See the section above about Rust. + +It's almost exactly the same. + +See also: + +- +- diff --git a/zig/install.ps1 b/zig/install.ps1 new file mode 100644 index 0000000..f26860d --- /dev/null +++ b/zig/install.ps1 @@ -0,0 +1,60 @@ +#!/usr/bin/env pwsh + +################### +# Install ziglang # +################### + +# Every package should define these variables +$pkg_cmd_name = "zig" + +$pkg_dst_cmd = "$Env:USERPROFILE\.local\opt\zig\zig.exe" +$pkg_dst_bin = "$Env:USERPROFILE\.local\opt\zig" +$pkg_dst_dir = "$Env:USERPROFILE\.local\opt\zig" +$pkg_dst = "$pkg_dst_dir" + +$pkg_src_cmd = "$Env:USERPROFILE\.local\opt\zig-v$Env:WEBI_VERSION\zig.exe" +$pkg_src_bin = "$Env:USERPROFILE\.local\opt\zig-v$Env:WEBI_VERSION" +$pkg_src_dir = "$Env:USERPROFILE\.local\opt\zig-v$Env:WEBI_VERSION" +$pkg_src = "$pkg_src_dir" + +New-Item "$Env:USERPROFILE\Downloads\webi" -ItemType Directory -Force | out-null +$pkg_download = "$Env:USERPROFILE\Downloads\webi\$Env:WEBI_PKG_FILE" + +# Fetch archive +IF (!(Test-Path -Path "$Env:USERPROFILE\Downloads\webi\$Env:WEBI_PKG_FILE")) +{ + echo "Downloading ziglang from $Env:WEBI_PKG_URL to $pkg_download" + & curl.exe -A "$Env:WEBI_UA" -fsSL "$Env:WEBI_PKG_URL" -o "$pkg_download.part" + & move "$pkg_download.part" "$pkg_download" +} + +IF (!(Test-Path -Path "$pkg_src_cmd")) +{ + echo "Installing ziglang" + + # TODO: create package-specific temp directory + # Enter tmp + pushd .local\tmp + + # Remove any leftover tmp cruft + Remove-Item -Path ".\zig-*" -Recurse -ErrorAction Ignore + + # Unpack archive file into this temporary directory + # Windows BSD-tar handles zip. Imagine that. + echo "Unpacking $pkg_download" + & tar xf "$pkg_download" + + # Settle unpacked archive into place + echo "Install Location: $pkg_src_cmd" + Move-Item -Path ".\zig-*" -Destination "$pkg_src" + + # Exit tmp + popd +} + +echo "Copying into '$pkg_dst' from '$pkg_src'" +Remove-Item -Path "$pkg_dst" -Recurse -ErrorAction Ignore | out-null +Copy-Item -Path "$pkg_src" -Destination "$pkg_dst" -Recurse + +# Add to Windows PATH +& "$Env:USERPROFILE\.local\bin\pathman.exe" add ~/.local/opt/zig diff --git a/zig/install.sh b/zig/install.sh new file mode 100644 index 0000000..ed6f9d7 --- /dev/null +++ b/zig/install.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +# shellcheck disable=SC2034 +# "'pkg_cmd_name' appears unused. Verify it or export it." + +function __init_ziglang() { + set -e + set -u + + ################### + # Install ziglang # + ################### + + # Every package should define these 6 variables + pkg_cmd_name="zig" + + pkg_dst_cmd="$HOME/.local/opt/zig/zig" + pkg_dst_dir="$HOME/.local/opt/zig" + pkg_dst="$pkg_dst_dir" + + pkg_src_cmd="$HOME/.local/opt/zig-v$WEBI_VERSION/zig" + pkg_src_dir="$HOME/.local/opt/zig-v$WEBI_VERSION" + pkg_src="$pkg_src_dir" + + # pkg_install must be defined by every package + pkg_install() { + # mv ./zig-* ~/.local/opt/zig-v0.9.1 + mv ./zig-* "${pkg_src}" + } + + # pkg_get_current_version is recommended, but not required + pkg_get_current_version() { + # 'zig version' has output in this format: + # 0.9.1 + # We're just doing a little future-proofing to keep it that way + zig version 2> /dev/null | + head -n 1 | + cut -d ' ' -f 1 + } + +} + +__init_ziglang diff --git a/zig/releases.js b/zig/releases.js new file mode 100644 index 0000000..a97ba38 --- /dev/null +++ b/zig/releases.js @@ -0,0 +1,81 @@ +'use strict'; + +module.exports = function (request) { + return request({ + url: 'https://ziglang.org/download/index.json', + json: true + }).then(function (resp) { + let versions = resp.body; + let releases = []; + + let refs = Object.keys(versions); + refs.forEach(function (ref) { + let pkgs = versions[ref]; + + // "platform" = arch + os combo + let platforms = Object.keys(pkgs); + platforms.forEach(function (platform) { + let pkg = pkgs[platform]; + + // don't grab 'date' or 'notes', which are (confusingly) + // at the same level as platform releases + let isNotPackage = !pkg || 'object' !== typeof pkg || !pkg.tarball; + if (isNotPackage) { + return; + } + + // Ex: aarch64-macos => ['aarch64', 'macos'] + let parts = platform.split('-'); + let arch = parts[0]; + let os = parts[1]; + if (parts.length > 2) { + console.warn( + `unexpected platform name with multiple '-': ${platform}` + ); + return; + } + + let p = { + version: ref, + date: pkgs.date, + channel: 'stable', + // linux, macos, windows + os: os, + // TODO map explicitly (rather than normalization auto-detect) + //arch: arch, + download: pkg.tarball, + hash: pkg.shasum, + size: pkg.size + // TODO docs + release notes? + //docs: 'https://ziglang.org/documentation/0.9.1/', + //stdDocs: 'https://ziglang.org/documentation/0.9.1/std/', + //notes: 'https://ziglang.org/download/0.9.1/release-notes.html' + }; + + // Mark branches or tags as beta (for now) + // Ex: 'master' + // Also mark prereleases (with build tags) as beta + // Ex: 0.10.0-dev.1606+97a53bb8a + let isNotStable = !/\./.test(ref) || /\+|-/.test(p.version); + if (isNotStable) { + p.channel = 'beta'; + } + + releases.push(p); + }); + }); + + return { + releases: releases + }; + }); +}; + +if (module === require.main) { + module.exports(require('@root/request')).then(function (all) { + all = require('../_webi/normalize.js')(all); + // just select the first 5 for demonstration + all.releases = all.releases.slice(0, 5); + console.info(JSON.stringify(all, null, 2)); + }); +} diff --git a/zig/zig-create-crossies.sh b/zig/zig-create-crossies.sh new file mode 100755 index 0000000..859bd2b --- /dev/null +++ b/zig/zig-create-crossies.sh @@ -0,0 +1,29 @@ +#!/bin/bash +set -e +set -u + +my_targets="$(zig targets | jq -r '.libc[]' | sort -u)" + +for my_target in $my_targets; do + cat << EOF >> "${HOME}/.local/bin/zig-cc-${my_target}" +#!/bin/sh +set -e +set -u + +"\${HOME}/.local/opt/zig/zig" cc -target ${my_target} \$@ +EOF + + chmod a+x "${HOME}/.local/bin/zig-cc-${my_target}" +done + +for my_target in $my_targets; do + cat << EOF >> "${HOME}/.local/bin/zig-cpp-${my_target}" +#!/bin/sh +set -e +set -u + +"\${HOME}/.local/opt/zig/zig" c++ -target ${my_target} \$@ +EOF + + chmod a+x "${HOME}/.local/bin/zig-cpp-${my_target}" +done diff --git a/ziglang/README.md b/ziglang/README.md new file mode 100644 index 0000000..7f955a6 --- /dev/null +++ b/ziglang/README.md @@ -0,0 +1,11 @@ +--- +title: ziglang (zig alias) +homepage: https://webinstall.dev/zig +tagline: | + Alias for https://webinstall.dev/zig +alias: zig +description: | + See https://webinstall.dev/zig +--- + +Alias for https://webinstall.dev/zig diff --git a/ziglang/install.ps1 b/ziglang/install.ps1 new file mode 100644 index 0000000..031e30f --- /dev/null +++ b/ziglang/install.ps1 @@ -0,0 +1,5 @@ +#!/bin/pwsh + +echo "'ziglang@$Env:WEBI_TAG' is an alias for 'zig@$Env:WEBI_VERSION'" +IF ($Env:WEBI_HOST -eq $null -or $Env:WEBI_HOST -eq "") { $Env:WEBI_HOST = "https://webinstall.dev" } +curl.exe -fsSL "$Env:WEBI_HOST/zig@$Env:WEBI_VERSION" | powershell diff --git a/ziglang/install.sh b/ziglang/install.sh new file mode 100644 index 0000000..7036df4 --- /dev/null +++ b/ziglang/install.sh @@ -0,0 +1,11 @@ +#!/bin/bash +set -e +set -u + +function __redirect_alias_zig() { + echo "'ziglang@${WEBI_TAG:-stable}' is an alias for 'zig@${WEBI_VERSION:-}'" + WEBI_HOST=${WEBI_HOST:-"https://webinstall.dev"} + curl -fsSL "$WEBI_HOST/zig@${WEBI_VERSION:-}" | bash +} + +__redirect_alias_zig