╭─────────────╮╭────────────╮ │scroll to top││next lines →│ ╰─────────────╯╰────────────╯ ╭ main.zig ─────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
339 }, 340 .@"test" => { 341 dev.check(.test_command); 342 return buildOutputType(gpa, arena, io, args, .zig_test, environ_map); 343 }, 344 .@"test-obj" => { 345 dev.check(.test_command); 346 return buildOutputType(gpa, arena, io, args, .zig_test_obj, environ_map); 347 }, 348 .run => { 349 dev.check(.run_command); 350 return buildOutputType(gpa, arena, io, args, .run, environ_map); 351 }, 352 .dlltool, .ranlib, .lib, .ar => { 353 dev.check(.ar_command); 354 return process.exit(try llvmArMain(arena, args)); 355 }, 356 .build, .fetch, .init, .libc, .@"cache-cat" => { 357 return jitCmd(gpa, arena, io, cmd_args, environ_map, .{ 358 .cmd_name = "maker", 359 .root_src_path = "Maker.zig", 360 .prepend_cmd = cmd, 361 .prepend_zig_lib_dir_path = true, 362 .prepend_global_cache_path = true, 363 .prepend_zig_exe_path = true, 364 .prepend_seed = true, 365 .release_mode = .safe, 366 }); 367 }, 368 .clang, .@"-cc1", .@"-cc1as" => { 369 dev.check(.clang_command); 370 return process.exit(try clangMain(arena, args)); 371 }, 372 .@"ld.lld", .@"lld-link", .@"wasm-ld" => { 373 dev.check(.lld_linker); 374 return process.exit(try lldMain(arena, args, true)); 375 }, 376 .cc => { 377 dev.check(.cc_command); 378 return buildOutputType(gpa, arena, io, args, .cc, environ_map); 379 }, 380 .@"c++" => { 381 dev.check(.cc_command); 382 return buildOutputType(gpa, arena, io, args, .cpp, environ_map); 383 }, 384 .@"translate-c" => { 385 dev.check(.translate_c_command); 386 return buildOutputType(gpa, arena, io, args, .translate_c, environ_map); 387 }, 388 .rc => { 389 const use_server = cmd_args.len > 0 and std.mem.eql(u8, cmd_args[0], "--zig-integration"); 390 return jitCmd(gpa, arena, io, cmd_args, environ_map, .{ 391 .cmd_name = "resinator", 392 .root_src_path = "resinator/main.zig", 393 .depend_on_aro = true, 394 .prepend_zig_lib_dir_path = true, 395 .server = use_server, 396 }); 397 }, 398 .fmt => { 399 dev.check(.fmt_command); 400 return @import("fmt.zig").run(gpa, arena, io, cmd_args); 401 }, 402 .objcopy => { 403 return jitCmd(gpa, arena, io, cmd_args, environ_map, .{ 404 .cmd_name = "objcopy", 405 .root_src_path = "objcopy.zig", 406 }); 407 }, 408 .objdump => { 409 return jitCmd(gpa, arena, io, cmd_args, environ_map, .{ 410 .cmd_name = "objdump", 411 .root_src_path = "objdump.zig", 412 }); 413 }, 414 .std => { 415 return jitCmd(gpa, arena, io, cmd_args, environ_map, .{ 416 .cmd_name = "std", 417 .root_src_path = "std-docs.zig", 418 .prepend_zig_lib_dir_path = true, 419 .prepend_zig_exe_path = true, 420 .prepend_global_cache_path = true, 421 }); 422 }, 423 .targets => { 424 dev.check(.targets_command); 425 const self_exe_path = switch (native_os) { 426 .wasi => {}, 427 else => process.executablePathAlloc(io, arena) catch |err| fatal("unable to find zig self exe path: {t}", .{err}), 428 }; 429 var dirs: std.zig.Directories = .init(arena, io, .{ 430 .override_zig_lib = EnvVar.ZIG_LIB_DIR.get(environ_map), 431 .override_global_cache = EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map), 432 .build_root = null, 433 .local_cache_strat = .global, 434 .preopens = preopens, 435 .self_exe_path = self_exe_path, 436 .environ_map = environ_map, 437 .cwd = try std.zig.getResolvedCwd(io, arena), 438 }); 439 defer dirs.deinit(io); 440 const host = std.zig.resolveTargetQueryOrFatal(io, .{}); 441 var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer); 442 try @import("print_targets.zig").cmdTargets( 443 arena, 444 io, 445 &dirs, 446 cmd_args, 447 &stdout_writer.interface, 448 &host, 449 ); 450 return stdout_writer.interface.flush(); 451 }, 452 .version => { 453 dev.check(.version_command); 454 try Io.File.stdout().writeStreamingAll(io, build_options.version ++ "\n"); 455 return; 456 }, 457 .env => { 458 dev.check(.env_command); 459 const self_exe_path = switch (native_os) { 460 .wasi => args[0], 461 else => process.executablePathAlloc(io, arena) catch |err| fatal("unable to find zig self exe path: {t}", .{err}), 462 }; 463 var dirs: std.zig.Directories = .init(arena, io, .{ 464 .override_zig_lib = EnvVar.ZIG_LIB_DIR.get(environ_map), 465 .override_global_cache = EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map), 466 .build_root = null, 467 .local_cache_strat = .global, 468 .preopens = preopens, 469 .self_exe_path = if (native_os != .wasi) self_exe_path, 470 .environ_map = environ_map, 471 .cwd = try std.zig.getResolvedCwd(io, arena), 472 }); 473 defer dirs.deinit(io); 474 const host = std.zig.resolveTargetQueryOrFatal(io, .{}); 475 var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer); 476 try @import("print_env.zig").cmdEnv( 477 arena, 478 &stdout_writer.interface, 479 &host, 480 environ_map, 481 &dirs, 482 self_exe_path, 483 ); 484 return stdout_writer.interface.flush(); 485 }, 486 .reduce => { 487 return jitCmd(gpa, arena, io, cmd_args, environ_map, .{ 488 .cmd_name = "reduce", 489 .root_src_path = "reduce.zig", 490 }); 491 }, 492 .zen => { 493 dev.check(.zen_command); 494 return Io.File.stdout().writeStreamingAll(io, info_zen); 495 }, 496 .help, .@"-h", .@"--help" => { 497 dev.check(.help_command); 498 return Io.File.stdout().writeStreamingAll(io, usage); 499 }, 500 .@"ast-check" => { 501 dev.check(.ast_check_command); 502 return cmdAstCheck(arena, io, cmd_args, environ_map); 503 }, 504 .changelist => { 505 dev.check(.changelist_command); 506 return cmdChangelist(arena, io, cmd_args, environ_map); 507 }, 508 .@"dump-zir" => { 509 dev.check(.dump_zir_command); 510 return cmdDumpZir(arena, io, cmd_args); 511 }, 512 } 513 } 514 515 const compile_usage = 516 \\Usage: zig build-exe [options] [files] 517 \\ zig build-lib [options] [files] 518 \\ zig build-obj [options] [files] 519 \\ zig test [options] [files] 520 \\ zig run [options] [files] [-- [args]] 521 \\ zig translate-c [options] [file] 522 \\ 523 \\Supported file types: 524 \\ .zig Zig source code 525 \\ .o ELF object file 526 \\ .o Mach-O (macOS) object file 527 \\ .o WebAssembly object file 528 \\ .obj COFF (Windows) object file 529 \\ .lib COFF (Windows) static library 530 \\ .a ELF static library 531 \\ .a Mach-O (macOS) static library 532 \\ .a WebAssembly static library 533 \\ .so ELF shared object (dynamic link) 534 \\ .dll Windows Dynamic Link Library 535 \\ .dylib Mach-O (macOS) dynamic library 536 \\ .tbd (macOS) text-based dylib definition 537 \\ .s Target-specific assembly source code 538 \\ .S Assembly with C preprocessor (requires LLVM extensions) 539 \\ .c C source code (requires LLVM extensions) 540 \\ .cxx .cc .C .cpp .c++ C++ source code (requires LLVM extensions) 541 \\ .m Objective-C source code (requires LLVM extensions) 542 \\ .mm Objective-C++ source code (requires LLVM extensions) 543 \\ .bc LLVM IR Module (requires LLVM extensions) 544 \\ 545 \\General Options: 546 \\ -h, --help Print this help and exit 547 \\ --color [auto|off|on] Enable or disable colored error messages 548 \\ -j<N> Limit concurrent jobs (default is to use all CPU cores) 549 \\ -fincremental Enable incremental compilation 550 \\ -fno-incremental Disable incremental compilation 551 \\ -femit-bin[=path] (default) Output machine code 552 \\ -fno-emit-bin Do not output machine code 553 \\ -femit-asm[=path] Output .s (assembly code) 554 \\ -fno-emit-asm (default) Do not output .s (assembly code) 555 \\ -femit-llvm-ir[=path] Produce a .ll file with optimized LLVM IR (requires LLVM extensions) 556 \\ -fno-emit-llvm-ir (default) Do not produce a .ll file with optimized LLVM IR 557 \\ -femit-llvm-bc[=path] Produce an optimized LLVM module as a .bc file (requires LLVM extensions) 558 \\ -fno-emit-llvm-bc (default) Do not produce an optimized LLVM module as a .bc file 559 \\ -femit-h[=path] Generate a C header file (.h) 560 \\ -fno-emit-h (default) Do not generate a C header file (.h) 561 \\ -femit-docs[=path] Create a docs/ dir with html documentation 562 \\ -fno-emit-docs (default) Do not produce docs/ dir with html documentation 563 \\ -femit-implib[=path] (default) Produce an import .lib when building a Windows DLL 564 \\ -fno-emit-implib Do not produce an import .lib when building a Windows DLL 565 \\ --show-builtin Output the source of @import("builtin") then exit 566 \\ --cache-dir [path] Override the local cache directory 567 \\ --global-cache-dir [path] Override the global cache directory 568 \\ --zig-lib-dir [path] Override path to Zig installation lib directory 569 \\ --build-root [path] Override path to project source files 570 \\ 571 \\Global Compile Options: 572 \\ --name [name] Compilation unit name (not a file path) 573 \\ -M[name][=src] Create a module based on the current per-module settings. 574 \\ The first module is the main module. 575 \\ "std" can be configured by omitting src 576 \\ After a -M argument, per-module settings are reset. 577 \\ --libc [file] Provide a file which specifies libc paths 578 \\ -x [language] Treat subsequent input files as having type <language> 579 \\ --error-limit [num] Set the maximum amount of distinct error values 580 \\ -fllvm Force using LLVM as the codegen backend 581 \\ -fno-llvm Prevent using LLVM as the codegen backend 582 \\ -flibllvm Force using the LLVM API in the codegen backend 583 \\ -fno-libllvm Prevent using the LLVM API in the codegen backend 584 \\ -fclang Force using Clang as the C/C++ compilation backend 585 \\ -fno-clang Prevent using Clang as the C/C++ compilation backend 586 \\ -fPIE Force-enable Position Independent Executable 587 \\ -fno-PIE Force-disable Position Independent Executable 588 \\ -flto Force-enable Link Time Optimization (requires LLVM extensions) 589 \\ -fno-lto Force-disable Link Time Optimization 590 \\ -fdll-export-fns Mark exported functions as DLL exports (Windows) 591 \\ -fno-dll-export-fns Force-disable marking exported functions as DLL exports 592 \\ -freference-trace[=num] Show num lines of reference trace per compile error 593 \\ -fno-reference-trace Disable reference trace 594 \\ -ffunction-sections Places each function in a separate section 595 \\ -fno-function-sections All functions go into same section 596 \\ -fdata-sections Places each data in a separate section 597 \\ -fno-data-sections All data go into same section 598 \\ -fpatchable-function-entry=[num] Add num NOPs of padding in function prologues 599 \\ -mexec-model=[value] (WASI) Execution model 600 \\ -municode (Windows) Use wmain/wWinMain as entry point 601 \\ --time-report Send timing diagnostics to '--listen' clients 602 \\ 603 \\Per-Module Compile Options: 604 \\ --dep [[import=]name] Add an entry to the next module's import table 605 \\ -target [name] <arch><sub>-<os>-<abi> see the targets command 606 \\ -O [mode] Choose what to optimize for 607 \\ debug (default) Prioritize bug detection, accurate debug info, compilation speed 608 \\ fast Prioritize runtime performance. Safety checks off. 609 \\ safe Enable both safety checks and machine code optimizations 610 \\ small Prioritize small binary size. Safety checks off. 611 \\ -ofmt=[fmt] Override target object format 612 \\ elf Executable and Linking Format 613 \\ c C source code 614 \\ wasm WebAssembly 615 \\ coff Common Object File Format (Windows) 616 \\ macho macOS relocatables 617 \\ spirv Standard, Portable Intermediate Representation V (SPIR-V) 618 \\ plan9 Plan 9 from Bell Labs object format 619 \\ hex (planned feature) Intel IHEX 620 \\ raw (planned feature) Dump machine code directly 621 \\ -mcpu [cpu] Specify target CPU and feature set 622 \\ -mcmodel=[model] Limit range of code and data virtual addresses 623 \\ default 624 \\ extreme 625 \\ kernel 626 \\ large 627 \\ medany 628 \\ medium 629 \\ medlow 630 \\ medmid 631 \\ normal 632 \\ small 633 \\ tiny 634 \\ -mred-zone Force-enable the "red-zone" 635 \\ -mno-red-zone Force-disable the "red-zone" 636 \\ -fomit-frame-pointer Omit the stack frame pointer 637 \\ -fno-omit-frame-pointer Store the stack frame pointer 638 \\ -fPIC Force-enable Position Independent Code 639 \\ -fno-PIC Force-disable Position Independent Code 640 \\ -fstack-check Enable stack probing in unsafe builds 641 \\ -fno-stack-check Disable stack probing in safe builds 642 \\ -fstack-protector Enable stack protection in unsafe builds 643 \\ -fno-stack-protector Disable stack protection in safe builds 644 \\ -fvalgrind Include valgrind client requests in release builds 645 \\ -fno-valgrind Omit valgrind client requests in debug builds 646 \\ -fsanitize-c[=mode] Enable C undefined behavior detection in unsafe builds 647 \\ trap Insert trap instructions on undefined behavior 648 \\ full (Default) Insert runtime calls on undefined behavior 649 \\ -fno-sanitize-c Disable C undefined behavior detection in safe builds 650 \\ -fsanitize-thread Enable Thread Sanitizer 651 \\ -fno-sanitize-thread Disable Thread Sanitizer 652 \\ -ffuzz Enable fuzz testing instrumentation 653 \\ -fno-fuzz Disable fuzz testing instrumentation 654 \\ -fbuiltin Enable implicit builtin knowledge of functions 655 \\ -fno-builtin Disable implicit builtin knowledge of functions 656 \\ -funwind-tables Always produce unwind table entries for all functions 657 \\ -fasync-unwind-tables Always produce asynchronous unwind table entries for all functions 658 \\ -fno-unwind-tables Never produce unwind table entries 659 \\ -ferror-tracing Enable error tracing in release builds 660 \\ -fno-error-tracing Disable error tracing in debug builds 661 \\ -fsingle-threaded Code assumes there is only one thread 662 \\ -fno-single-threaded Code may not assume there is only one thread 663 \\ -fstrip Omit debug symbols 664 \\ -fno-strip Keep debug symbols 665 \\ -idirafter [dir] Add directory to AFTER include search path 666 \\ -isystem [dir] Add directory to SYSTEM include search path 667 \\ -I[dir] Add directory to include search path 668 \\ --embed-dir=[dir] Add directory to embed search path 669 \\ -D[macro]=[value] Define C [macro] to [value] (1 if [value] omitted) 670 \\ -cflags [flags] -- Set extra flags for the next positional C source files 671 \\ -rcflags [flags] -- Set extra flags for the next positional .rc source files 672 \\ -rcincludes=[type] Set the type of includes to use when compiling .rc source files 673 \\ any (default) Use msvc if available, fall back to gnu 674 \\ msvc Use msvc include paths (must be present on the system) 675 \\ gnu Use mingw include paths (distributed with Zig) 676 \\ none Do not use any autodetected include paths 677 \\ 678 \\Global Link Options: 679 \\ -T[script], --script [script] Use a custom linker script 680 \\ --version-script [path] Provide a version .map file 681 \\ --undefined-version Allow version scripts to refer to undefined symbols 682 \\ --no-undefined-version (default) Disallow version scripts from referring to undefined symbols 683 \\ --enable-new-dtags Use the new behavior for dynamic tags (RUNPATH) 684 \\ --disable-new-dtags Use the old behavior for dynamic tags (RPATH) 685 \\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so) 686 \\ --no-dynamic-linker Do not set any dynamic interpreter path 687 \\ --sysroot [path] Set the system root directory (usually /) 688 \\ --version [ver] Dynamic library semver 689 \\ -fentry Enable entry point with default symbol name 690 \\ -fentry=[name] Override the entry point symbol name 691 \\ -fno-entry Do not output any entry point 692 \\ --force_undefined [name] Specify the symbol must be defined for the link to succeed 693 \\ -fsoname[=name] Override the default SONAME value 694 \\ -fno-soname Disable emitting a SONAME 695 \\ -flld Force using LLD as the linker 696 \\ -fno-lld Prevent using LLD as the linker 697 \\ -fcompiler-rt Always include compiler-rt symbols in output 698 \\ -fno-compiler-rt Prevent including compiler-rt symbols in output 699 \\ -fubsan-rt Always include ubsan-rt symbols in the output 700 \\ -fno-ubsan-rt Prevent including ubsan-rt symbols in the output 701 \\ -rdynamic Add all symbols to the dynamic symbol table 702 \\ -feach-lib-rpath Ensure adding rpath for each used dynamic library 703 \\ -fno-each-lib-rpath Prevent adding rpath for each used dynamic library 704 \\ -fallow-shlib-undefined Allows undefined symbols in shared libraries 705 \\ -fno-allow-shlib-undefined Disallows undefined symbols in shared libraries 706 \\ -fallow-so-scripts Allows .so files to be GNU ld scripts 707 \\ -fno-allow-so-scripts (default) .so files must be ELF files 708 \\ --build-id[=style] At a minor link-time expense, embeds a build ID in binaries 709 \\ fast 8-byte non-cryptographic hash (COFF, ELF, WASM) 710 \\ sha1, tree 20-byte cryptographic hash (ELF, WASM) 711 \\ md5 16-byte cryptographic hash (ELF) 712 \\ uuid 16-byte random UUID (ELF, WASM) 713 \\ 0x[hexstring] Constant ID, maximum 32 bytes (ELF, WASM) 714 \\ none (default) No build ID 715 \\ --eh-frame-hdr Enable C++ exception handling by passing --eh-frame-hdr to linker 716 \\ --no-eh-frame-hdr Disable C++ exception handling by passing --no-eh-frame-hdr to linker 717 \\ --emit-relocs Enable output of relocation sections for post build tools 718 \\ -z [arg] Set linker extension flags 719 \\ nodelete Indicate that the object cannot be deleted from a process 720 \\ notext Permit read-only relocations in read-only segments 721 \\ defs Force a fatal error if any undefined symbols remain 722 \\ undefs Reverse of -z defs 723 \\ origin Indicate that the object must have its origin processed 724 \\ nocopyreloc Disable the creation of copy relocations 725 \\ now (default) Force all relocations to be processed on load 726 \\ lazy Don't force all relocations to be processed on load 727 \\ relro (default) Force all relocations to be read-only after processing 728 \\ norelro Don't force all relocations to be read-only after processing 729 \\ common-page-size=[bytes] Set the common page size for ELF binaries 730 \\ max-page-size=[bytes] Set the max page size for ELF binaries 731 \\ -dynamic Force output to be dynamically linked 732 \\ -static Force output to be statically linked 733 \\ -Bsymbolic Bind global references locally 734 \\ --compress-debug-sections=[e] Debug section compression settings 735 \\ none No compression 736 \\ zlib Compression with deflate/inflate 737 \\ zstd Compression with zstandard 738 \\ --gc-sections Force removal of functions and data that are unreachable by the entry point or exported symbols 739 \\ --no-gc-sections Don't force removal of unreachable functions and data 740 \\ --sort-section=[value] Sort wildcard section patterns by 'name' or 'alignment' 741 \\ --subsystem [subsystem] (Windows) /SUBSYSTEM:<subsystem> to the linker 742 \\ --stack [size] Override default stack size 743 \\ --image-base [addr] Set base address for executable image 744 \\ -install_name=[value] (Darwin) add dylib's install name 745 \\ --entitlements [path] (Darwin) add path to entitlements file for embedding in code signature 746 \\ -pagezero_size [value] (Darwin) size of the __PAGEZERO segment in hexadecimal notation 747 \\ -headerpad [value] (Darwin) set minimum space for future expansion of the load commands in hexadecimal notation 748 \\ -headerpad_max_install_names (Darwin) set enough space as if all paths were MAXPATHLEN 749 \\ -dead_strip (Darwin) remove functions and data that are unreachable by the entry point or exported symbols 750 \\ -dead_strip_dylibs (Darwin) remove dylibs that are unreachable by the entry point or exported symbols 751 \\ -ObjC (Darwin) force load all members of static archives that implement an Objective-C class or category 752 \\ --import-memory (WebAssembly) import memory from the environment 753 \\ --export-memory (WebAssembly) export memory to the host (Default unless --import-memory used) 754 \\ --import-symbols (WebAssembly) import missing symbols from the host environment 755 \\ --import-table (WebAssembly) import function table from the host environment 756 \\ --export-table (WebAssembly) export function table to the host environment 757 \\ --growable-table (WebAssembly) remove maximum size from function table, allowing table to grow 758 \\ --initial-memory=[bytes] (WebAssembly) initial size of the linear memory 759 \\ --max-memory=[bytes] (WebAssembly) maximum size of the linear memory 760 \\ --shared-memory (WebAssembly) use shared linear memory 761 \\ --global-base=[addr] (WebAssembly) where to start to place global data 762 \\ 763 \\Per-Module Link Options: 764 \\ -l[lib], --library [lib] Link against system library (only if actually used) 765 \\ -needed-l[lib], Link against system library (even if unused) 766 \\ --needed-library [lib] 767 \\ -weak-l[lib] link against system library marking it and all 768 \\ -weak_library [lib] referenced symbols as weak 769 \\ -L[d], --library-directory [d] Add a directory to the library search path 770 \\ -search_paths_first For each library search path, check for dynamic 771 \\ lib then static lib before proceeding to next path. 772 \\ -search_paths_first_static For each library search path, check for static 773 \\ lib then dynamic lib before proceeding to next path. 774 \\ -search_dylibs_first Search for dynamic libs in all library search 775 \\ paths, then static libs. 776 \\ -search_static_first Search for static libs in all library search 777 \\ paths, then dynamic libs. 778 \\ -search_dylibs_only Only search for dynamic libs. 779 \\ -search_static_only Only search for static libs. 780 \\ -rpath [path] Add directory to the runtime library search path 781 \\ -framework [name] (Darwin) link against framework 782 \\ -needed_framework [name] (Darwin) link against framework (even if unused) 783 \\ -needed_library [lib] (Darwin) link against system library (even if unused) 784 \\ -weak_framework [name] (Darwin) link against framework and mark it and all referenced symbols as weak 785 \\ -F[dir] (Darwin) add search path for frameworks 786 \\ --export=[value] (WebAssembly) Force a symbol to be exported 787 \\ 788 \\Test Options: 789 \\ --test-filter [text] Skip tests that do not match any filter 790 \\ --test-cmd [arg] Specify test execution command one arg at a time 791 \\ --test-cmd-bin Appends test binary path to test cmd args 792 \\ --test-no-exec Compiles test binary without running it 793 \\ --test-runner [path] Specify a custom test runner 794 \\ --test-execve Runs the test binary with execve if available instead of as a child process 795 \\ 796 \\Debug Options (Zig Compiler Development): 797 \\ -fopt-bisect-limit=[limit] Only run [limit] first LLVM optimization passes 798 \\ -fstack-report Print stack size diagnostics 799 \\ --verbose-link Display linker invocations 800 \\ --verbose-cc Display C compiler invocations 801 \\ --verbose-air Enable compiler debug output for Zig AIR 802 \\ --verbose-intern-pool Enable compiler debug output for InternPool 803 \\ --verbose-generic-instances Enable compiler debug output for generic instance generation 804 \\ --verbose-llvm-ir[=path] Enable compiler debug output for unoptimized LLVM IR 805 \\ --verbose-llvm-bc=[path] Enable compiler debug output for unoptimized LLVM BC 806 \\ --verbose-cimport Enable compiler debug output for C imports 807 \\ --verbose-llvm-cpu-features Enable compiler debug output for LLVM CPU features 808 \\ --debug-log [scope] Enable printing debug/info log messages for scope 809 \\ --debug-compile-errors Crash with helpful diagnostics at the first compile error 810 \\ --debug-link-snapshot Enable dumping of the linker's state in JSON format 811 \\ --debug-rt[=mode] Build compiler runtime libraries with [mode] optimization 812 \\ (debug if [=mode] is omitted) 813 \\ --debug-incremental Enable incremental compilation debug features 814 \\ 815 ; 816 817 const SOName = union(enum) { 818 no, 819 yes_default_value, 820 yes: []const u8, 821 }; 822 823 const EmitBin = union(enum) { 824 no, 825 yes_default_path, 826 yes: []const u8, 827 yes_a_out, 828 }; 829 830 const Emit = union(enum) { 831 no, 832 yes_default_path, 833 yes: []const u8, 834 835 const OutputToCacheReason = enum { listen, @"zig run", @"zig test" }; 836 fn resolve(emit: Emit, io: Io, default_basename: []const u8, output_to_cache: ?OutputToCacheReason) Compilation.CreateOptions.Emit { 837 return switch (emit) { 838 .no => .no, 839 .yes_default_path => if (output_to_cache != null) .yes_cache else .{ .yes_path = default_basename }, 840 .yes => |path| if (output_to_cache) |reason| { 841 switch (reason) { 842 .listen => fatal("--listen incompatible with explicit output path {q}", .{path}), 843 .@"zig run", .@"zig test" => fatal( 844 "{q} with explicit output path {q} requires explicit '-femit-bin=path' or '-fno-emit-bin'", 845 .{ @tagName(reason), path }, 846 ), 847 } 848 } else e: { 849 // If there's a dirname, check that dir exists. This will give a more descriptive error than `Compilation` otherwise would. 850 if (fs.path.dirname(path)) |dir_path| { 851 var dir = Io.Dir.cwd().openDir(io, dir_path, .{}) catch |err| { 852 fatal("unable to open output directory {q}: {t}", .{ dir_path, err }); 853 }; 854 dir.close(io); 855 } 856 break :e .{ .yes_path = path }; 857 }, 858 }; 859 } 860 }; 861 862 const ArgMode = union(enum) { 863 build: std.lang.OutputMode, 864 cc, 865 cpp, 866 translate_c, 867 zig_test, 868 zig_test_obj, 869 run, 870 }; 871 872 const Listen = union(enum) { 873 none, 874 stdio: if (dev.env.supports(.stdio_listen)) void else noreturn, 875 ip4: if (dev.env.supports(.network_listen)) Io.net.Ip4Address else noreturn, 876 }; 877 878 const ArgsIterator = struct { 879 resp_file: ?ArgIteratorResponseFile = null, 880 args: []const []const u8, 881 i: usize = 0, 882 fn next(it: *@This()) ?[]const u8 { 883 if (it.i >= it.args.len) { 884 if (it.resp_file) |*resp| return resp.next(); 885 return null; 886 } 887 defer it.i += 1; 888 return it.args[it.i]; 889 } 890 fn nextOrFatal(it: *@This()) []const u8 { 891 if (it.i >= it.args.len) { 892 if (it.resp_file) |*resp| if (resp.next()) |ret| return ret; 893 fatal("expected parameter after {s}", .{it.args[it.i - 1]}); 894 } 895 defer it.i += 1; 896 return it.args[it.i]; 897 } 898 }; 899 900 /// Similar to `link.Framework` except it doesn't store yet unresolved 901 /// path to the framework. 902 const Framework = struct { 903 needed: bool = false, 904 weak: bool = false, 905 }; 906 907 const CliModule = struct { 908 root_path: []const u8, 909 root_src_path: []const u8, 910 cc_argv: []const []const u8, 911 inherited: Module.CreateOptions.Inherited, 912 target_arch_os_abi: ?[]const u8, 913 target_mcpu: ?[]const u8, 914 dynamic_linker: ?[]const u8, 915 916 deps: []const Dep, 917 resolved: ?*Module, 918 919 c_source_files_start: usize, 920 c_source_files_end: usize, 921 rc_source_files_start: usize, 922 rc_source_files_end: usize, 923 924 const Dep = struct { 925 key: []const u8, 926 value: []const u8, 927 }; 928 }; 929 930 fn buildOutputType( 931 gpa: Allocator, 932 arena: Allocator, 933 io: Io, 934 all_args: []const []const u8, 935 arg_mode: ArgMode, 936 environ_map: *process.Environ.Map, 937 ) !void { 938 var provided_name: ?[]const u8 = null; 939 var root_src_file: ?[]const u8 = null; 940 var version: std.SemanticVersion = .{ .major = 0, .minor = 0, .patch = 0 }; 941 var have_version = false; 942 var compatibility_version: ?std.SemanticVersion = null; 943 var function_sections = false; 944 var data_sections = false; 945 var listen: Listen = .none; 946 var debug_compile_errors = false; 947 var debug_incremental = false; 948 var verbose_link = (native_os != .wasi or builtin.link_libc) and 949 EnvVar.ZIG_VERBOSE_LINK.isSet(environ_map); 950 var verbose_cc = (native_os != .wasi or builtin.link_libc) and 951 EnvVar.ZIG_VERBOSE_CC.isSet(environ_map); 952 var verbose_air = false; 953 var verbose_intern_pool = false; 954 var verbose_generic_instances = false; 955 var verbose_llvm_ir: ?[]const u8 = null; 956 var verbose_llvm_bc: ?[]const u8 = null; 957 var link_depfile: ?[]const u8 = null; 958 var verbose_llvm_cpu_features = false; 959 var time_report = false; 960 var stack_report = false; 961 var show_builtin = false; 962 var emit_bin: EmitBin = .yes_default_path; 963 var emit_asm: Emit = .no; 964 var emit_llvm_ir: Emit = .no; 965 var emit_llvm_bc: Emit = .no; 966 var emit_docs: Emit = .no; 967 var emit_implib: Emit = .yes_default_path; 968 var emit_implib_arg_provided = false; 969 var target_arch_os_abi: ?[]const u8 = null; 970 var target_mcpu: ?[]const u8 = null; 971 var dynamic_linker: ?[]const u8 = null; 972 var emit_h: Emit = .no; 973 var soname: SOName = undefined; 974 var want_compiler_rt: ?bool = null; 975 var zig_cc_explicitly_link_compiler_rt = false; 976 var want_ubsan_rt: ?bool = null; 977 var linker_script: ?[]const u8 = null; 978 var version_script: ?[]const u8 = null; 979 var linker_repro: ?bool = null; 980 var linker_allow_undefined_version: bool = false; 981 var linker_enable_new_dtags: ?bool = null; 982 var disable_c_depfile = false; 983 var linker_sort_section: ?link.File.Lld.Elf.SortSection = null; 984 var linker_gc_sections: ?bool = null; 985 var linker_compress_debug_sections: ?std.zig.CompressDebugSections = null; 986 var linker_allow_shlib_undefined: ?bool = null; 987 var allow_so_scripts: bool = false; 988 var linker_bind_global_refs_locally: ?bool = null; 989 var linker_import_symbols: bool = false; 990 var linker_import_table: bool = false; 991 var linker_export_table: bool = false; 992 var linker_growable_table: bool = false; 993 var linker_initial_memory: ?u64 = null; 994 var linker_max_memory: ?u64 = null; 995 var linker_global_base: ?u64 = null; 996 var linker_print_gc_sections: bool = false; 997 var linker_print_icf_sections: bool = false; 998 var linker_print_map: bool = false; 999 var linker_nmagic: bool = false; 1000 var linker_fatal_warnings: bool = false; 1001 var llvm_opt_bisect_limit: c_int = -1; 1002 var linker_z_nocopyreloc = false; 1003 var linker_z_nodelete = false; 1004 var linker_z_notext = false; 1005 var linker_z_defs = false; 1006 var linker_z_origin = false; 1007 var linker_z_now = true; 1008 var linker_z_relro = true; 1009 var linker_z_common_page_size: ?u64 = null; 1010 var linker_z_max_page_size: ?u64 = null; 1011 var linker_tsaware = false; 1012 var linker_nxcompat = false; 1013 var linker_dynamicbase = true; 1014 var linker_optimization: ?[]const u8 = null; 1015 var linker_module_definition_file: ?[]const u8 = null; 1016 var test_no_exec = false; 1017 var test_execve = false; 1018 var entry: Compilation.CreateOptions.Entry = .default; 1019 var force_undefined_symbols: std.array_hash_map.String(void) = .empty; 1020 var stack_size: ?u64 = null; 1021 var image_base: ?u64 = null; 1022 var link_eh_frame_hdr = false; 1023 var link_emit_relocs = false; 1024 var build_id: ?std.zig.BuildId = null; 1025 var runtime_args_start: ?usize = null; 1026 var test_filters: std.ArrayList([]const u8) = .empty; 1027 var test_runner_path: ?[]const u8 = null; 1028 var override_local_cache_dir: ?[]const u8 = EnvVar.ZIG_LOCAL_CACHE_DIR.get(environ_map); 1029 var override_global_cache_dir: ?[]const u8 = EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map); 1030 var override_lib_dir: ?[]const u8 = EnvVar.ZIG_LIB_DIR.get(environ_map); 1031 var clang_preprocessor_mode: Compilation.ClangPreprocessorMode = .no; 1032 var subsystem: ?std.zig.Subsystem = null; 1033 var major_subsystem_version: ?u16 = null; 1034 var minor_subsystem_version: ?u16 = null; 1035 var mingw_unicode_entry_point: bool = false; 1036 var enable_link_snapshots: bool = false; 1037 var debug_compiler_runtime_libs: ?std.lang.Optimize = null; 1038 var install_name: ?[]const u8 = null; 1039 var hash_style: link.File.Lld.Elf.HashStyle = .both; 1040 var entitlements: ?[]const u8 = null; 1041 var pagezero_size: ?u64 = null; 1042 var lib_search_strategy: link.UnresolvedInput.SearchStrategy = .paths_first; 1043 var lib_preferred_mode: std.lang.LinkMode = .dynamic; 1044 var headerpad_size: ?u32 = null; 1045 var headerpad_max_install_names: bool = false; 1046 var dead_strip_dylibs: bool = false; 1047 var force_load_objc: bool = false; 1048 var discard_local_symbols: bool = false; 1049 var contains_res_file: bool = false; 1050 var reference_trace: ?u32 = null; 1051 var pdb_out_path: ?[]const u8 = null; 1052 var error_limit: ?Zcu.ErrorInt = null; 1053 // These are before resolving sysroot. 1054 var extra_cflags: std.ArrayList([]const u8) = .empty; 1055 var extra_rcflags: std.ArrayList([]const u8) = .empty; 1056 var symbol_wrap_set: std.array_hash_map.String(void) = .empty; 1057 var rc_includes: std.zig.RcIncludes = .any; 1058 var manifest_file: ?[]const u8 = null; 1059 var linker_export_symbol_names: std.ArrayList([]const u8) = .empty; 1060 var build_root_path: ?[]const u8 = null; 1061 1062 // Tracks the position in c_source_files which have already their owner populated. 1063 var c_source_files_owner_index: usize = 0; 1064 // Tracks the position in rc_source_files which have already their owner populated. 1065 var rc_source_files_owner_index: usize = 0; 1066 1067 // null means replace with the test executable binary 1068 var test_exec_args: std.ArrayList(?[]const u8) = .empty; 1069 1070 // These get set by CLI flags and then snapshotted when a `-M` flag is 1071 // encountered. 1072 var mod_opts: Module.CreateOptions.Inherited = .{}; 1073 1074 // These get appended to by CLI flags and then slurped when a `-M` flag 1075 // is encountered. 1076 var cssan: ClangSearchSanitizer = .{}; 1077 var cc_argv: std.ArrayList([]const u8) = .empty; 1078 var deps: std.ArrayList(CliModule.Dep) = .empty; 1079 1080 // We need to raise the FD limit *before* CLI parsing, because we open link inputs during CLI 1081 // parsing (in `createModule`), so a large number of link inputs could push us past the limit on 1082 // targets with a low soft limit (e.g. macOS has a default limit of 256). 1083 process.raiseFileDescriptorLimit(); 1084 1085 // Contains every module specified via -M. The dependencies are added 1086 // after argument parsing is completed. We use a StringArrayHashMap to make 1087 // error output consistent. "root" is special. 1088 var create_module: CreateModule = .{ 1089 // Populated just before the call to `createModule`. 1090 .dirs = undefined, 1091 .object_format = null, 1092 .modules = .empty, 1093 .opts = .{ 1094 .is_test = switch (arg_mode) { 1095 .zig_test, .zig_test_obj => true, 1096 .build, .cc, .cpp, .translate_c, .run => false, 1097 }, 1098 // Populated while parsing CLI args. 1099 .output_mode = undefined, 1100 // Populated in the call to `createModule` for the root module. 1101 .resolved_target = undefined, 1102 .have_zcu = false, 1103 // Populated just before the call to `createModule`. 1104 .emit_llvm_ir = undefined, 1105 // Populated just before the call to `createModule`. 1106 .emit_llvm_bc = undefined, 1107 // Populated just before the call to `createModule`. 1108 .emit_bin = undefined, 1109 // Populated just before the call to `createModule`. 1110 .any_c_source_files = undefined, 1111 }, 1112 // Populated in the call to `createModule` for the root module. 1113 .resolved_options = undefined, 1114 1115 .cli_link_inputs = .empty, 1116 .windows_libs = .empty, 1117 .link_inputs = .empty, 1118 1119 .c_source_files = .empty, 1120 .rc_source_files = .empty, 1121 1122 .llvm_m_args = .empty, 1123 .sysroot = null, 1124 .lib_directories = .empty, // populated by createModule() 1125 .lib_dir_args = .empty, // populated from CLI arg parsing 1126 .libc_installation = null, 1127 .want_native_include_dirs = false, 1128 .frameworks = .empty, 1129 .framework_dirs = .empty, 1130 .rpath_list = .empty, 1131 .each_lib_rpath = null, 1132 .libc_paths_file = EnvVar.ZIG_LIBC.get(environ_map), 1133 .native_system_include_paths = &.{}, 1134 }; 1135 defer create_module.link_inputs.deinit(gpa); 1136 1137 var color: Color = Color.settingFromEnvironment(environ_map); 1138 var n_jobs: ?u32 = null; 1139 1140 switch (arg_mode) { 1141 .build, .translate_c, .zig_test, .zig_test_obj, .run => { 1142 switch (arg_mode) { 1143 .build => |m| { 1144 create_module.opts.output_mode = m; 1145 }, 1146 .translate_c => { 1147 emit_bin = .no; 1148 create_module.opts.output_mode = .Obj; 1149 }, 1150 .zig_test, .run => { 1151 create_module.opts.output_mode = .Exe; 1152 }, 1153 .zig_test_obj => { 1154 create_module.opts.output_mode = .Obj; 1155 }, 1156 else => unreachable, 1157 } 1158 1159 soname = .yes_default_value; 1160 1161 var args_iter = ArgsIterator{ 1162 .args = all_args[2..], 1163 }; 1164 1165 var file_ext: ?Compilation.FileExt = null; 1166 args_loop: while (args_iter.next()) |arg| { 1167 if (mem.cutPrefix(u8, arg, "@")) |resp_file_path| { 1168 // This is a "compiler response file". We must parse the file and treat its 1169 // contents as command line parameters. 1170 args_iter.resp_file = initArgIteratorResponseFile(arena, io, resp_file_path) catch |err| 1171 fatal("unable to read response file {q}: {t}", .{ resp_file_path, err }); 1172 } else if (mem.startsWith(u8, arg, "-")) { 1173 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { 1174 try Io.File.stdout().writeStreamingAll(io, compile_usage); 1175 return cleanExit(io); 1176 } else if (mem.eql(u8, arg, "--")) { 1177 if (arg_mode == .run) { 1178 // args_iter.i is 1, referring the next arg after "--" in ["--", ...] 1179 // Add +2 to the index so it is relative to all_args 1180 runtime_args_start = args_iter.i + 2; 1181 break :args_loop; 1182 } else { 1183 fatal("unexpected end-of-parameter mark: --", .{}); 1184 } 1185 } else if (mem.eql(u8, arg, "--dep")) { 1186 const next_arg = args_iter.nextOrFatal(); 1187 const key, const value = mem.cutScalar(u8, next_arg, '=') orelse .{ next_arg, next_arg }; 1188 if (mem.eql(u8, key, "std") and !mem.eql(u8, value, "std")) { 1189 fatal("unable to import as {q}: conflicts with builtin module", .{key}); 1190 } 1191 for ([_][]const u8{ "root", "builtin" }) |name| { 1192 if (mem.eql(u8, key, name)) { 1193 fatal("unable to import as {q}: conflicts with builtin module", .{key}); 1194 } 1195 } 1196 try deps.append(arena, .{ 1197 .key = key, 1198 .value = value, 1199 }); 1200 } else if (mem.cutPrefix(u8, arg, "-M")) |rest| { 1201 const mod_name, const root_src_orig = mem.cutScalar(u8, rest, '=') orelse .{ rest, null }; 1202 try handleModArg( 1203 arena, 1204 mod_name, 1205 root_src_orig, 1206 &create_module, 1207 &mod_opts, 1208 &cc_argv, 1209 &target_arch_os_abi, 1210 &target_mcpu, 1211 &dynamic_linker, 1212 &deps, 1213 &c_source_files_owner_index, 1214 &rc_source_files_owner_index, 1215 &cssan, 1216 ); 1217 } else if (mem.eql(u8, arg, "--error-limit")) { 1218 const next_arg = args_iter.nextOrFatal(); 1219 error_limit = std.fmt.parseUnsigned(Zcu.ErrorInt, next_arg, 0) catch |err| { 1220 fatal("unable to parse error limit {q}: {t}", .{ next_arg, err }); 1221 }; 1222 } else if (mem.eql(u8, arg, "-cflags")) { 1223 extra_cflags.shrinkRetainingCapacity(0); 1224 while (true) { 1225 const next_arg = args_iter.next() orelse { 1226 fatal("expected -- after -cflags", .{}); 1227 }; 1228 if (mem.eql(u8, next_arg, "--")) break; 1229 try extra_cflags.append(arena, next_arg); 1230 } 1231 } else if (mem.eql(u8, arg, "-rcincludes")) { 1232 rc_includes = parseRcIncludes(args_iter.nextOrFatal()); 1233 } else if (mem.cutPrefix(u8, arg, "-rcincludes=")) |rest| { 1234 rc_includes = parseRcIncludes(rest); 1235 } else if (mem.eql(u8, arg, "-rcflags")) { 1236 extra_rcflags.shrinkRetainingCapacity(0); 1237 while (true) { 1238 const next_arg = args_iter.next() orelse { 1239 fatal("expected -- after -rcflags", .{}); 1240 }; 1241 if (mem.eql(u8, next_arg, "--")) break; 1242 try extra_rcflags.append(arena, next_arg); 1243 } 1244 } else if (mem.eql(u8, arg, "--color")) { 1245 const next_arg = args_iter.next() orelse { 1246 fatal("expected [auto|on|off] after --color", .{}); 1247 }; 1248 color = stringToEnum(Color, next_arg) orelse { 1249 fatal("expected [auto|on|off] after --color, found {q}", .{next_arg}); 1250 }; 1251 } else if (mem.cutPrefix(u8, arg, "-j")) |str| { 1252 const num = std.fmt.parseUnsigned(u32, str, 10) catch |err| { 1253 fatal("unable to parse jobs count {q}: {t}", .{ str, err }); 1254 }; 1255 if (num < 1) { 1256 fatal("number of jobs must be at least 1", .{}); 1257 } 1258 n_jobs = num; 1259 } else if (mem.eql(u8, arg, "--subsystem")) { 1260 subsystem = try parseSubsystem(args_iter.nextOrFatal()); 1261 } else if (mem.eql(u8, arg, "-O")) { 1262 mod_opts.optimize_mode = parseOptimizeMode(args_iter.nextOrFatal()); 1263 } else if (mem.cutPrefix(u8, arg, "-fentry=")) |rest| { 1264 entry = .{ .named = rest }; 1265 } else if (mem.eql(u8, arg, "--force_undefined")) { 1266 try force_undefined_symbols.put(arena, args_iter.nextOrFatal(), {}); 1267 } else if (mem.eql(u8, arg, "--discard-all")) { 1268 discard_local_symbols = true; 1269 } else if (mem.eql(u8, arg, "--stack")) { 1270 stack_size = parseStackSize(args_iter.nextOrFatal()); 1271 } else if (mem.eql(u8, arg, "--image-base")) { 1272 image_base = parseImageBase(args_iter.nextOrFatal()); 1273 } else if (mem.eql(u8, arg, "--name")) { 1274 provided_name = args_iter.nextOrFatal(); 1275 if (!mem.eql(u8, provided_name.?, fs.path.basename(provided_name.?))) 1276 fatal("invalid package name {q}: cannot contain folder separators", .{provided_name.?}); 1277 } else if (mem.eql(u8, arg, "-rpath")) { 1278 try create_module.rpath_list.append(arena, args_iter.nextOrFatal()); 1279 } else if (mem.eql(u8, arg, "--library-directory") or mem.eql(u8, arg, "-L")) { 1280 try create_module.lib_dir_args.append(arena, args_iter.nextOrFatal()); 1281 } else if (mem.eql(u8, arg, "-F")) { 1282 try create_module.framework_dirs.append(arena, args_iter.nextOrFatal()); 1283 } else if (mem.eql(u8, arg, "-framework")) { 1284 try create_module.frameworks.put(arena, args_iter.nextOrFatal(), .{}); 1285 } else if (mem.eql(u8, arg, "-weak_framework")) { 1286 try create_module.frameworks.put(arena, args_iter.nextOrFatal(), .{ .weak = true }); 1287 } else if (mem.eql(u8, arg, "-needed_framework")) { 1288 try create_module.frameworks.put(arena, args_iter.nextOrFatal(), .{ .needed = true }); 1289 } else if (mem.eql(u8, arg, "-install_name")) { 1290 install_name = args_iter.nextOrFatal(); 1291 } else if (mem.cutPrefix(u8, arg, "--compress-debug-sections=")) |param| { 1292 linker_compress_debug_sections = stringToEnum(std.zig.CompressDebugSections, param) orelse { 1293 fatal("expected --compress-debug-sections=[none|zlib|zstd], found: {s}", .{param}); 1294 }; 1295 } else if (mem.eql(u8, arg, "--compress-debug-sections")) { 1296 linker_compress_debug_sections = .zlib; 1297 } else if (mem.eql(u8, arg, "-pagezero_size")) { 1298 const next_arg = args_iter.nextOrFatal(); 1299 pagezero_size = std.fmt.parseUnsigned(u64, eatIntPrefix(next_arg, 16), 16) catch |err| { 1300 fatal("unable to parse pagezero size {q}: {t}", .{ next_arg, err }); 1301 }; 1302 } else if (mem.eql(u8, arg, "-search_paths_first")) { 1303 lib_search_strategy = .paths_first; 1304 lib_preferred_mode = .dynamic; 1305 } else if (mem.eql(u8, arg, "-search_paths_first_static")) { 1306 lib_search_strategy = .paths_first; 1307 lib_preferred_mode = .static; 1308 } else if (mem.eql(u8, arg, "-search_dylibs_first")) { 1309 lib_search_strategy = .mode_first; 1310 lib_preferred_mode = .dynamic; 1311 } else if (mem.eql(u8, arg, "-search_static_first")) { 1312 lib_search_strategy = .mode_first; 1313 lib_preferred_mode = .static; 1314 } else if (mem.eql(u8, arg, "-search_dylibs_only")) { 1315 lib_search_strategy = .no_fallback; 1316 lib_preferred_mode = .dynamic; 1317 } else if (mem.eql(u8, arg, "-search_static_only")) { 1318 lib_search_strategy = .no_fallback; 1319 lib_preferred_mode = .static; 1320 } else if (mem.eql(u8, arg, "-headerpad")) { 1321 const next_arg = args_iter.nextOrFatal(); 1322 headerpad_size = std.fmt.parseUnsigned(u32, eatIntPrefix(next_arg, 16), 16) catch |err| { 1323 fatal("unable to parse headerpad size {q}: {t}", .{ next_arg, err }); 1324 }; 1325 } else if (mem.eql(u8, arg, "-headerpad_max_install_names")) { 1326 headerpad_max_install_names = true; 1327 } else if (mem.eql(u8, arg, "-dead_strip")) { 1328 linker_gc_sections = true; 1329 } else if (mem.eql(u8, arg, "-dead_strip_dylibs")) { 1330 dead_strip_dylibs = true; 1331 } else if (mem.eql(u8, arg, "-ObjC")) { 1332 force_load_objc = true; 1333 } else if (mem.eql(u8, arg, "-T") or mem.eql(u8, arg, "--script")) { 1334 linker_script = args_iter.nextOrFatal(); 1335 } else if (mem.eql(u8, arg, "-version-script") or mem.eql(u8, arg, "--version-script")) { 1336 version_script = args_iter.nextOrFatal(); 1337 } else if (mem.eql(u8, arg, "--undefined-version")) { 1338 linker_allow_undefined_version = true; 1339 } else if (mem.eql(u8, arg, "--no-undefined-version")) { 1340 linker_allow_undefined_version = false; 1341 } else if (mem.eql(u8, arg, "--enable-new-dtags")) { 1342 linker_enable_new_dtags = true; 1343 } else if (mem.eql(u8, arg, "--disable-new-dtags")) { 1344 linker_enable_new_dtags = false; 1345 } else if (mem.eql(u8, arg, "--library") or mem.eql(u8, arg, "-l")) { 1346 // We don't know whether this library is part of libc 1347 // or libc++ until we resolve the target, so we append 1348 // to the list for now. 1349 try create_module.cli_link_inputs.append(arena, .{ .name_query = .{ 1350 .name = args_iter.nextOrFatal(), 1351 .query = .{ 1352 .needed = false, 1353 .weak = false, 1354 .preferred_mode = lib_preferred_mode, 1355 .search_strategy = lib_search_strategy, 1356 .allow_so_scripts = allow_so_scripts, 1357 }, 1358 } }); 1359 } else if (mem.eql(u8, arg, "--needed-library") or 1360 mem.eql(u8, arg, "-needed-l") or 1361 mem.eql(u8, arg, "-needed_library")) 1362 { 1363 const next_arg = args_iter.nextOrFatal(); 1364 try create_module.cli_link_inputs.append(arena, .{ .name_query = .{ 1365 .name = next_arg, 1366 .query = .{ 1367 .needed = true, 1368 .weak = false, 1369 .preferred_mode = lib_preferred_mode, 1370 .search_strategy = lib_search_strategy, 1371 .allow_so_scripts = allow_so_scripts, 1372 }, 1373 } }); 1374 } else if (mem.eql(u8, arg, "-weak_library") or mem.eql(u8, arg, "-weak-l")) { 1375 try create_module.cli_link_inputs.append(arena, .{ .name_query = .{ 1376 .name = args_iter.nextOrFatal(), 1377 .query = .{ 1378 .needed = false, 1379 .weak = true, 1380 .preferred_mode = lib_preferred_mode, 1381 .search_strategy = lib_search_strategy, 1382 .allow_so_scripts = allow_so_scripts, 1383 }, 1384 } }); 1385 } else if (mem.eql(u8, arg, "-D")) { 1386 try cc_argv.appendSlice(arena, &.{ arg, args_iter.nextOrFatal() }); 1387 } else if (mem.eql(u8, arg, "-I")) { 1388 try cssan.addIncludePath(arena, &cc_argv, .I, arg, args_iter.nextOrFatal(), false); 1389 } else if (mem.cutPrefix(u8, arg, "--embed-dir=")) |rest| { 1390 try cssan.addIncludePath(arena, &cc_argv, .embed_dir, arg, rest, true); 1391 } else if (mem.eql(u8, arg, "-isystem")) { 1392 try cssan.addIncludePath(arena, &cc_argv, .isystem, arg, args_iter.nextOrFatal(), false); 1393 } else if (mem.eql(u8, arg, "-iwithsysroot")) { 1394 try cssan.addIncludePath(arena, &cc_argv, .iwithsysroot, arg, args_iter.nextOrFatal(), false); 1395 } else if (mem.eql(u8, arg, "-idirafter")) { 1396 try cssan.addIncludePath(arena, &cc_argv, .idirafter, arg, args_iter.nextOrFatal(), false); 1397 } else if (mem.eql(u8, arg, "-iframework")) { 1398 const path = args_iter.nextOrFatal(); 1399 try cssan.addIncludePath(arena, &cc_argv, .iframework, arg, path, false); 1400 try create_module.framework_dirs.append(arena, path); // Forward to the backend as -F 1401 } else if (mem.eql(u8, arg, "-iframeworkwithsysroot")) { 1402 const path = args_iter.nextOrFatal(); 1403 try cssan.addIncludePath(arena, &cc_argv, .iframeworkwithsysroot, arg, path, false); 1404 try create_module.framework_dirs.append(arena, path); // Forward to the backend as -F 1405 } else if (mem.eql(u8, arg, "--version")) { 1406 const next_arg = args_iter.nextOrFatal(); 1407 version = std.SemanticVersion.parse(next_arg) catch |err| { 1408 fatal("unable to parse --version {q}: {t}", .{ next_arg, err }); 1409 }; 1410 have_version = true; 1411 } else if (mem.eql(u8, arg, "-target")) { 1412 target_arch_os_abi = args_iter.nextOrFatal(); 1413 } else if (mem.eql(u8, arg, "-mcpu")) { 1414 target_mcpu = args_iter.nextOrFatal(); 1415 } else if (mem.eql(u8, arg, "-mcmodel")) { 1416 mod_opts.code_model = parseCodeModel(args_iter.nextOrFatal()); 1417 } else if (mem.cutPrefix(u8, arg, "-mcmodel=")) |rest| { 1418 mod_opts.code_model = parseCodeModel(rest); 1419 } else if (mem.cutPrefix(u8, arg, "-ofmt=")) |rest| { 1420 create_module.object_format = rest; 1421 } else if (mem.cutPrefix(u8, arg, "-mcpu=")) |rest| { 1422 target_mcpu = rest; 1423 } else if (mem.cutPrefix(u8, arg, "-O")) |rest| { 1424 mod_opts.optimize_mode = parseOptimizeMode(rest); 1425 } else if (mem.eql(u8, arg, "--dynamic-linker")) { 1426 dynamic_linker = args_iter.nextOrFatal(); 1427 } else if (mem.eql(u8, arg, "--no-dynamic-linker")) { 1428 dynamic_linker = ""; 1429 } else if (mem.eql(u8, arg, "--sysroot")) { 1430 const next_arg = args_iter.nextOrFatal(); 1431 create_module.sysroot = next_arg; 1432 try cc_argv.appendSlice(arena, &.{ "-isysroot", next_arg }); 1433 } else if (mem.eql(u8, arg, "--libc")) { 1434 create_module.libc_paths_file = args_iter.nextOrFatal(); 1435 } else if (mem.eql(u8, arg, "--test-filter")) { 1436 try test_filters.append(arena, args_iter.nextOrFatal()); 1437 } else if (mem.eql(u8, arg, "--test-runner")) { 1438 test_runner_path = args_iter.nextOrFatal(); 1439 } else if (mem.eql(u8, arg, "--test-cmd")) { 1440 try test_exec_args.append(arena, args_iter.nextOrFatal()); 1441 } else if (mem.eql(u8, arg, "--cache-dir")) { 1442 override_local_cache_dir = args_iter.nextOrFatal(); 1443 } else if (mem.eql(u8, arg, "--global-cache-dir")) { 1444 override_global_cache_dir = args_iter.nextOrFatal(); 1445 } else if (mem.eql(u8, arg, "--zig-lib-dir")) { 1446 override_lib_dir = args_iter.nextOrFatal(); 1447 } else if (mem.eql(u8, arg, "--build-root")) { 1448 build_root_path = args_iter.nextOrFatal(); 1449 } else if (mem.eql(u8, arg, "--debug-log")) { 1450 try addDebugLog(arena, args_iter.nextOrFatal()); 1451 } else if (mem.eql(u8, arg, "--listen")) { 1452 const next_arg = args_iter.nextOrFatal(); 1453 if (mem.eql(u8, next_arg, "-")) { 1454 dev.check(.stdio_listen); 1455 listen = .stdio; 1456 } else { 1457 dev.check(.network_listen); 1458 // example: --listen 127.0.0.1:9000 1459 const host, const port_text = mem.cutScalar(u8, next_arg, ':') orelse .{ next_arg, "14735" }; 1460 const port = std.fmt.parseInt(u16, port_text, 10) catch |err| 1461 fatal("invalid port number: {q}: {t}", .{ port_text, err }); 1462 listen = .{ .ip4 = Io.net.Ip4Address.parse(host, port) catch |err| 1463 fatal("invalid host: {q}: {t}", .{ host, err }) }; 1464 } 1465 } else if (mem.eql(u8, arg, "--listen=-")) { 1466 dev.check(.stdio_listen); 1467 listen = .stdio; 1468 } else if (mem.eql(u8, arg, "--debug-link-snapshot")) { 1469 if (!build_options.enable_debug_extensions) { 1470 warn("Zig was compiled without debug extensions. --debug-link-snapshot has no effect.", .{}); 1471 } else { 1472 enable_link_snapshots = true; 1473 } 1474 } else if (mem.eql(u8, arg, "--debug-rt")) { 1475 debug_compiler_runtime_libs = .debug; 1476 } else if (mem.cutPrefix(u8, arg, "--debug-rt=")) |rest| { 1477 debug_compiler_runtime_libs = parseOptimizeMode(rest); 1478 } else if (mem.eql(u8, arg, "--debug-incremental")) { 1479 if (build_options.enable_debug_extensions) { 1480 debug_incremental = true; 1481 } else { 1482 warn("Zig was compiled without debug extensions. --debug-incremental has no effect.", .{}); 1483 } 1484 } else if (mem.eql(u8, arg, "-fincremental")) { 1485 dev.check(.incremental); 1486 create_module.opts.incremental = true; 1487 } else if (mem.eql(u8, arg, "-fno-incremental")) { 1488 create_module.opts.incremental = false; 1489 } else if (mem.eql(u8, arg, "--entitlements")) { 1490 entitlements = args_iter.nextOrFatal(); 1491 } else if (mem.eql(u8, arg, "-fcompiler-rt")) { 1492 want_compiler_rt = true; 1493 } else if (mem.eql(u8, arg, "-fno-compiler-rt")) { 1494 want_compiler_rt = false; 1495 } else if (mem.eql(u8, arg, "-fubsan-rt")) { 1496 want_ubsan_rt = true; 1497 } else if (mem.eql(u8, arg, "-fno-ubsan-rt")) { 1498 want_ubsan_rt = false; 1499 } else if (mem.eql(u8, arg, "-feach-lib-rpath")) { 1500 create_module.each_lib_rpath = true; 1501 } else if (mem.eql(u8, arg, "-fno-each-lib-rpath")) { 1502 create_module.each_lib_rpath = false; 1503 } else if (mem.eql(u8, arg, "--test-cmd-bin")) { 1504 try test_exec_args.append(arena, null); 1505 } else if (mem.eql(u8, arg, "--test-no-exec")) { 1506 test_no_exec = true; 1507 } else if (mem.eql(u8, arg, "--time-report")) { 1508 time_report = true; 1509 } else if (mem.eql(u8, arg, "--test-execve")) { 1510 test_execve = true; 1511 } else if (mem.eql(u8, arg, "-fstack-report")) { 1512 stack_report = true; 1513 } else if (mem.eql(u8, arg, "-fPIC")) { 1514 mod_opts.pic = true; 1515 } else if (mem.eql(u8, arg, "-fno-PIC")) { 1516 mod_opts.pic = false; 1517 } else if (mem.eql(u8, arg, "-fPIE")) { 1518 create_module.opts.pie = true; 1519 } else if (mem.eql(u8, arg, "-fno-PIE")) { 1520 create_module.opts.pie = false; 1521 } else if (mem.eql(u8, arg, "-flto")) { 1522 create_module.opts.lto = .full; 1523 } else if (mem.cutPrefix(u8, arg, "-flto=")) |mode| { 1524 if (mem.eql(u8, mode, "full")) { 1525 create_module.opts.lto = .full; 1526 } else if (mem.eql(u8, mode, "thin")) { 1527 create_module.opts.lto = .thin; 1528 } else { 1529 fatal("invalid -flto mode: {q}; must be \"full\" or \"thin\"", .{mode}); 1530 } 1531 } else if (mem.eql(u8, arg, "-fno-lto")) { 1532 create_module.opts.lto = .none; 1533 } else if (mem.eql(u8, arg, "-funwind-tables")) { 1534 mod_opts.unwind_tables = .sync; 1535 } else if (mem.eql(u8, arg, "-fasync-unwind-tables")) { 1536 mod_opts.unwind_tables = .async; 1537 } else if (mem.eql(u8, arg, "-fno-unwind-tables")) { 1538 mod_opts.unwind_tables = .none; 1539 } else if (mem.eql(u8, arg, "-fstack-check")) { 1540 mod_opts.stack_check = true; 1541 } else if (mem.eql(u8, arg, "-fno-stack-check")) { 1542 mod_opts.stack_check = false; 1543 } else if (mem.eql(u8, arg, "-fstack-protector")) { 1544 mod_opts.stack_protector = Compilation.default_stack_protector_buffer_size; 1545 } else if (mem.eql(u8, arg, "-fno-stack-protector")) { 1546 mod_opts.stack_protector = 0; 1547 } else if (mem.eql(u8, arg, "-mred-zone")) { 1548 mod_opts.red_zone = true; 1549 } else if (mem.eql(u8, arg, "-mno-red-zone")) { 1550 mod_opts.red_zone = false; 1551 } else if (mem.eql(u8, arg, "-fomit-frame-pointer")) { 1552 mod_opts.omit_frame_pointer = true; 1553 } else if (mem.eql(u8, arg, "-fno-omit-frame-pointer")) { 1554 mod_opts.omit_frame_pointer = false; 1555 } else if (mem.eql(u8, arg, "-fsanitize-c")) { 1556 mod_opts.sanitize_c = .full; 1557 } else if (mem.cutPrefix(u8, arg, "-fsanitize-c=")) |mode| { 1558 if (mem.eql(u8, mode, "trap")) { 1559 mod_opts.sanitize_c = .trap; 1560 } else if (mem.eql(u8, mode, "full")) { 1561 mod_opts.sanitize_c = .full; 1562 } else { 1563 fatal("invalid -fsanitize-c mode: {q}; must be \"trap\" or \"full\"", .{mode}); 1564 } 1565 } else if (mem.eql(u8, arg, "-fno-sanitize-c")) { 1566 mod_opts.sanitize_c = .off; 1567 } else if (mem.eql(u8, arg, "-fvalgrind")) { 1568 mod_opts.valgrind = true; 1569 } else if (mem.eql(u8, arg, "-fno-valgrind")) { 1570 mod_opts.valgrind = false; 1571 } else if (mem.eql(u8, arg, "-fsanitize-thread")) { 1572 mod_opts.sanitize_thread = true; 1573 } else if (mem.eql(u8, arg, "-fno-sanitize-thread")) { 1574 mod_opts.sanitize_thread = false; 1575 } else if (mem.eql(u8, arg, "-ffuzz")) { 1576 mod_opts.fuzz = true; 1577 } else if (mem.eql(u8, arg, "-fno-fuzz")) { 1578 mod_opts.fuzz = false; 1579 } else if (mem.eql(u8, arg, "-fllvm")) { 1580 create_module.opts.use_llvm = true; 1581 } else if (mem.eql(u8, arg, "-fno-llvm")) { 1582 create_module.opts.use_llvm = false; 1583 } else if (mem.eql(u8, arg, "-flibllvm")) { 1584 create_module.opts.use_lib_llvm = true; 1585 } else if (mem.eql(u8, arg, "-fno-libllvm")) { 1586 create_module.opts.use_lib_llvm = false; 1587 } else if (mem.eql(u8, arg, "-flld")) { 1588 create_module.opts.use_lld = true; 1589 } else if (mem.eql(u8, arg, "-fno-lld")) { 1590 create_module.opts.use_lld = false; 1591 } else if (mem.eql(u8, arg, "-fnew-linker")) { 1592 create_module.opts.use_new_linker = true; 1593 } else if (mem.eql(u8, arg, "-fno-new-linker")) { 1594 create_module.opts.use_new_linker = false; 1595 } else if (mem.eql(u8, arg, "-fclang")) { 1596 create_module.opts.use_clang = true; 1597 } else if (mem.eql(u8, arg, "-fno-clang")) { 1598 create_module.opts.use_clang = false; 1599 } else if (mem.eql(u8, arg, "-fsanitize-coverage-trace-pc-guard")) { 1600 create_module.opts.san_cov_trace_pc_guard = true; 1601 } else if (mem.eql(u8, arg, "-fno-sanitize-coverage-trace-pc-guard")) { 1602 create_module.opts.san_cov_trace_pc_guard = false; 1603 } else if (mem.eql(u8, arg, "-freference-trace")) { 1604 reference_trace = 256; 1605 } else if (mem.cutPrefix(u8, arg, "-freference-trace=")) |num| { 1606 reference_trace = std.fmt.parseUnsigned(u32, num, 10) catch |err| { 1607 fatal("unable to parse reference_trace count {q}: {t}", .{ num, err }); 1608 }; 1609 } else if (mem.eql(u8, arg, "-fno-reference-trace")) { 1610 reference_trace = null; 1611 } else if (mem.eql(u8, arg, "-ferror-tracing")) { 1612 mod_opts.error_tracing = true; 1613 } else if (mem.eql(u8, arg, "-fno-error-tracing")) { 1614 mod_opts.error_tracing = false; 1615 } else if (mem.eql(u8, arg, "-rdynamic")) { 1616 create_module.opts.rdynamic = true; 1617 } else if (mem.eql(u8, arg, "-fsoname")) { 1618 soname = .yes_default_value; 1619 } else if (mem.cutPrefix(u8, arg, "-fsoname=")) |rest| { 1620 soname = .{ .yes = rest }; 1621 } else if (mem.eql(u8, arg, "-fno-soname")) { 1622 soname = .no; 1623 } else if (mem.eql(u8, arg, "-femit-bin")) { 1624 emit_bin = .yes_default_path; 1625 } else if (mem.cutPrefix(u8, arg, "-femit-bin=")) |rest| { 1626 emit_bin = .{ .yes = rest }; 1627 } else if (mem.eql(u8, arg, "-fno-emit-bin")) { 1628 emit_bin = .no; 1629 } else if (mem.eql(u8, arg, "-femit-h")) { 1630 fatal("-femit-h is currently broken, see https://github.com/ziglang/zig/issues/9698", .{}); 1631 emit_h = .yes_default_path; 1632 } else if (mem.cutPrefix(u8, arg, "-femit-h=")) |rest| { 1633 emit_h = .{ .yes = rest }; 1634 } else if (mem.eql(u8, arg, "-fno-emit-h")) { 1635 emit_h = .no; 1636 } else if (mem.eql(u8, arg, "-femit-asm")) { 1637 emit_asm = .yes_default_path; 1638 } else if (mem.cutPrefix(u8, arg, "-femit-asm=")) |rest| { 1639 emit_asm = .{ .yes = rest }; 1640 } else if (mem.eql(u8, arg, "-fno-emit-asm")) { 1641 emit_asm = .no; 1642 } else if (mem.eql(u8, arg, "-femit-llvm-ir")) { 1643 emit_llvm_ir = .yes_default_path; 1644 } else if (mem.cutPrefix(u8, arg, "-femit-llvm-ir=")) |rest| { 1645 emit_llvm_ir = .{ .yes = rest }; 1646 } else if (mem.eql(u8, arg, "-fno-emit-llvm-ir")) { 1647 emit_llvm_ir = .no; 1648 } else if (mem.eql(u8, arg, "-femit-llvm-bc")) { 1649 emit_llvm_bc = .yes_default_path; 1650 } else if (mem.cutPrefix(u8, arg, "-femit-llvm-bc=")) |rest| { 1651 emit_llvm_bc = .{ .yes = rest }; 1652 } else if (mem.eql(u8, arg, "-fno-emit-llvm-bc")) { 1653 emit_llvm_bc = .no; 1654 } else if (mem.eql(u8, arg, "-femit-docs")) { 1655 emit_docs = .yes_default_path; 1656 } else if (mem.cutPrefix(u8, arg, "-femit-docs=")) |rest| { 1657 emit_docs = .{ .yes = rest }; 1658 } else if (mem.eql(u8, arg, "-fno-emit-docs")) { 1659 emit_docs = .no; 1660 } else if (mem.eql(u8, arg, "-femit-implib")) { 1661 emit_implib = .yes_default_path; 1662 emit_implib_arg_provided = true; 1663 } else if (mem.cutPrefix(u8, arg, "-femit-implib=")) |rest| { 1664 emit_implib = .{ .yes = rest }; 1665 emit_implib_arg_provided = true; 1666 } else if (mem.eql(u8, arg, "-fno-emit-implib")) { 1667 emit_implib = .no; 1668 emit_implib_arg_provided = true; 1669 } else if (mem.eql(u8, arg, "-dynamic")) { 1670 create_module.opts.link_mode = .dynamic; 1671 lib_preferred_mode = .dynamic; 1672 lib_search_strategy = .mode_first; 1673 } else if (mem.eql(u8, arg, "-static")) { 1674 create_module.opts.link_mode = .static; 1675 lib_preferred_mode = .static; 1676 lib_search_strategy = .no_fallback; 1677 } else if (mem.eql(u8, arg, "-fdll-export-fns")) { 1678 create_module.opts.dll_export_fns = true; 1679 } else if (mem.eql(u8, arg, "-fno-dll-export-fns")) { 1680 create_module.opts.dll_export_fns = false; 1681 } else if (mem.eql(u8, arg, "--show-builtin")) { 1682 show_builtin = true; 1683 emit_bin = .no; 1684 } else if (mem.eql(u8, arg, "-fstrip")) { 1685 mod_opts.strip = true; 1686 } else if (mem.eql(u8, arg, "-fno-strip")) { 1687 mod_opts.strip = false; 1688 } else if (mem.eql(u8, arg, "-gdwarf32")) { 1689 create_module.opts.debug_format = .{ .dwarf = .@"32" }; 1690 } else if (mem.eql(u8, arg, "-gdwarf64")) { 1691 create_module.opts.debug_format = .{ .dwarf = .@"64" }; 1692 } else if (mem.eql(u8, arg, "-fsingle-threaded")) { 1693 mod_opts.single_threaded = true; 1694 } else if (mem.eql(u8, arg, "-fno-single-threaded")) { 1695 mod_opts.single_threaded = false; 1696 } else if (mem.eql(u8, arg, "-ffunction-sections")) { 1697 function_sections = true; 1698 } else if (mem.eql(u8, arg, "-fno-function-sections")) { 1699 function_sections = false; 1700 } else if (mem.eql(u8, arg, "-fdata-sections")) { 1701 data_sections = true; 1702 } else if (mem.eql(u8, arg, "-fno-data-sections")) { 1703 data_sections = false; 1704 } else if (mem.eql(u8, arg, "-fbuiltin")) { 1705 mod_opts.no_builtin = false; 1706 } else if (mem.eql(u8, arg, "-fno-builtin")) { 1707 mod_opts.no_builtin = true; 1708 } else if (mem.cutPrefix(u8, arg, "-fopt-bisect-limit=")) |next_arg| { 1709 llvm_opt_bisect_limit = std.fmt.parseInt(c_int, next_arg, 0) catch |err| 1710 fatal("unable to parse {q}: {t}", .{ arg, err }); 1711 } else if (mem.cutPrefix(u8, arg, "-fpatchable-function-entry=")) |num| { 1712 mod_opts.patchable_function_entry = std.fmt.parseUnsigned(u16, num, 10) catch |err| { 1713 fatal("unable to parse patchable-function-entry count {q}: {t}", .{ num, err }); 1714 }; 1715 } else if (mem.eql(u8, arg, "--eh-frame-hdr")) { 1716 link_eh_frame_hdr = true; 1717 } else if (mem.eql(u8, arg, "--no-eh-frame-hdr")) { 1718 link_eh_frame_hdr = false; 1719 } else if (mem.eql(u8, arg, "--dynamicbase")) { 1720 linker_dynamicbase = true; 1721 } else if (mem.eql(u8, arg, "--no-dynamicbase")) { 1722 linker_dynamicbase = false; 1723 } else if (mem.eql(u8, arg, "--emit-relocs")) { 1724 link_emit_relocs = true; 1725 } else if (mem.eql(u8, arg, "-fallow-shlib-undefined")) { 1726 linker_allow_shlib_undefined = true; 1727 } else if (mem.eql(u8, arg, "-fno-allow-shlib-undefined")) { 1728 linker_allow_shlib_undefined = false; 1729 } else if (mem.eql(u8, arg, "-fallow-so-scripts")) { 1730 allow_so_scripts = true; 1731 } else if (mem.eql(u8, arg, "-fno-allow-so-scripts")) { 1732 allow_so_scripts = false; 1733 } else if (mem.eql(u8, arg, "-z")) { 1734 const z_arg = args_iter.nextOrFatal(); 1735 if (mem.eql(u8, z_arg, "nodelete")) { 1736 linker_z_nodelete = true; 1737 } else if (mem.eql(u8, z_arg, "notext")) { 1738 linker_z_notext = true; 1739 } else if (mem.eql(u8, z_arg, "defs")) { 1740 linker_z_defs = true; 1741 } else if (mem.eql(u8, z_arg, "undefs")) { 1742 linker_z_defs = false; 1743 } else if (mem.eql(u8, z_arg, "origin")) { 1744 linker_z_origin = true; 1745 } else if (mem.eql(u8, z_arg, "nocopyreloc")) { 1746 linker_z_nocopyreloc = true; 1747 } else if (mem.eql(u8, z_arg, "now")) { 1748 linker_z_now = true; 1749 } else if (mem.eql(u8, z_arg, "lazy")) { 1750 linker_z_now = false; 1751 } else if (mem.eql(u8, z_arg, "relro")) { 1752 linker_z_relro = true; 1753 } else if (mem.eql(u8, z_arg, "norelro")) { 1754 linker_z_relro = false; 1755 } else if (prefixedIntArg(z_arg, "common-page-size=")) |int| { 1756 linker_z_common_page_size = int; 1757 } else if (prefixedIntArg(z_arg, "max-page-size=")) |int| { 1758 linker_z_max_page_size = int; 1759 } else { 1760 fatal("unsupported linker extension flag: -z {s}", .{z_arg}); 1761 } 1762 } else if (mem.eql(u8, arg, "--import-memory")) { 1763 create_module.opts.import_memory = true; 1764 } else if (mem.eql(u8, arg, "-fentry")) { 1765 switch (entry) { 1766 .default, .disabled => entry = .enabled, 1767 .enabled, .named => {}, 1768 } 1769 } else if (mem.eql(u8, arg, "-fno-entry")) { 1770 entry = .disabled; 1771 } else if (mem.eql(u8, arg, "--export-memory")) { 1772 create_module.opts.export_memory = true; 1773 } else if (mem.eql(u8, arg, "--import-symbols")) { 1774 linker_import_symbols = true; 1775 } else if (mem.eql(u8, arg, "--import-table")) { 1776 linker_import_table = true; 1777 } else if (mem.eql(u8, arg, "--export-table")) { 1778 linker_export_table = true; 1779 } else if (mem.eql(u8, arg, "--growable-table")) { 1780 linker_growable_table = true; 1781 } else if (prefixedIntArg(arg, "--initial-memory=")) |int| { 1782 linker_initial_memory = int; 1783 } else if (prefixedIntArg(arg, "--max-memory=")) |int| { 1784 linker_max_memory = int; 1785 } else if (mem.eql(u8, arg, "--shared-memory")) { 1786 create_module.opts.shared_memory = true; 1787 } else if (prefixedIntArg(arg, "--global-base=")) |int| { 1788 linker_global_base = int; 1789 } else if (mem.cutPrefix(u8, arg, "--export=")) |rest| { 1790 try linker_export_symbol_names.append(arena, rest); 1791 } else if (mem.eql(u8, arg, "-Bsymbolic")) { 1792 linker_bind_global_refs_locally = true; 1793 } else if (mem.eql(u8, arg, "--gc-sections")) { 1794 linker_gc_sections = true; 1795 } else if (mem.eql(u8, arg, "--no-gc-sections")) { 1796 linker_gc_sections = false; 1797 } else if (mem.eql(u8, arg, "--build-id")) { 1798 build_id = .fast; 1799 } else if (mem.cutPrefix(u8, arg, "--build-id=")) |style| { 1800 build_id = std.zig.BuildId.parse(style) catch |err| { 1801 fatal("unable to parse --build-id style {q}: {t}", .{ style, err }); 1802 }; 1803 } else if (mem.eql(u8, arg, "--debug-compile-errors")) { 1804 if (build_options.enable_debug_extensions) { 1805 debug_compile_errors = true; 1806 } else { 1807 warn("Zig was compiled without debug extensions. --debug-compile-errors has no effect.", .{}); 1808 } 1809 } else if (mem.eql(u8, arg, "--verbose-link")) { 1810 verbose_link = true; 1811 } else if (mem.eql(u8, arg, "--verbose-cc")) { 1812 verbose_cc = true; 1813 } else if (mem.eql(u8, arg, "--verbose-air")) { 1814 verbose_air = true; 1815 } else if (mem.eql(u8, arg, "--verbose-intern-pool")) { 1816 verbose_intern_pool = true; 1817 } else if (mem.eql(u8, arg, "--verbose-generic-instances")) { 1818 verbose_generic_instances = true; 1819 } else if (mem.eql(u8, arg, "--verbose-llvm-ir")) { 1820 verbose_llvm_ir = "-"; 1821 } else if (mem.cutPrefix(u8, arg, "--verbose-llvm-ir=")) |rest| { 1822 verbose_llvm_ir = rest; 1823 } else if (mem.cutPrefix(u8, arg, "--verbose-llvm-bc=")) |rest| { 1824 verbose_llvm_bc = rest; 1825 } else if (mem.eql(u8, arg, "--verbose-llvm-cpu-features")) { 1826 verbose_llvm_cpu_features = true; 1827 } else if (mem.cutPrefix(u8, arg, "-T")) |rest| { 1828 linker_script = rest; 1829 } else if (mem.cutPrefix(u8, arg, "-L")) |rest| { 1830 try create_module.lib_dir_args.append(arena, rest); 1831 } else if (mem.cutPrefix(u8, arg, "-F")) |rest| { 1832 try create_module.framework_dirs.append(arena, rest); 1833 } else if (mem.cutPrefix(u8, arg, "-l")) |name| { 1834 // We don't know whether this library is part of libc 1835 // or libc++ until we resolve the target, so we append 1836 // to the list for now. 1837 try create_module.cli_link_inputs.append(arena, .{ .name_query = .{ 1838 .name = name, 1839 .query = .{ 1840 .needed = false, 1841 .weak = false, 1842 .preferred_mode = lib_preferred_mode, 1843 .search_strategy = lib_search_strategy, 1844 .allow_so_scripts = allow_so_scripts, 1845 }, 1846 } }); 1847 } else if (mem.cutPrefix(u8, arg, "-needed-l")) |name| { 1848 try create_module.cli_link_inputs.append(arena, .{ .name_query = .{ 1849 .name = name, 1850 .query = .{ 1851 .needed = true, 1852 .weak = false, 1853 .preferred_mode = lib_preferred_mode, 1854 .search_strategy = lib_search_strategy, 1855 .allow_so_scripts = allow_so_scripts, 1856 }, 1857 } }); 1858 } else if (mem.cutPrefix(u8, arg, "-weak-l")) |name| { 1859 try create_module.cli_link_inputs.append(arena, .{ .name_query = .{ 1860 .name = name, 1861 .query = .{ 1862 .needed = false, 1863 .weak = true, 1864 .preferred_mode = lib_preferred_mode, 1865 .search_strategy = lib_search_strategy, 1866 .allow_so_scripts = allow_so_scripts, 1867 }, 1868 } }); 1869 } else if (mem.startsWith(u8, arg, "-D")) { 1870 try cc_argv.append(arena, arg); 1871 } else if (mem.cutPrefix(u8, arg, "-I")) |rest| { 1872 try cssan.addIncludePath(arena, &cc_argv, .I, arg, rest, true); 1873 } else if (mem.cutPrefix(u8, arg, "-x")) |rest| { 1874 const lang = if (rest.len == 0) args_iter.nextOrFatal() else rest; 1875 if (mem.eql(u8, lang, "none")) { 1876 file_ext = null; 1877 } else if (Compilation.FileExt.from_lang.get(lang)) |got_ext| { 1878 file_ext = got_ext; 1879 } else { 1880 fatal("language not recognized: {s}", .{lang}); 1881 } 1882 } else if (mem.cutPrefix(u8, arg, "-mexec-model=")) |rest| { 1883 create_module.opts.wasi_exec_model = parseWasiExecModel(rest); 1884 } else if (mem.eql(u8, arg, "-municode")) { 1885 mingw_unicode_entry_point = true; 1886 } else { 1887 fatal("unrecognized parameter: {s}", .{arg}); 1888 } 1889 } else switch (file_ext orelse Compilation.classifyFileExt(arg)) { 1890 .shared_library, .object, .static_library => { 1891 try create_module.cli_link_inputs.append(arena, .{ .path_query = .{ 1892 .path = Path.initCwd(arg), 1893 .query = .{ 1894 .preferred_mode = lib_preferred_mode, 1895 .search_strategy = lib_search_strategy, 1896 .allow_so_scripts = allow_so_scripts, 1897 }, 1898 } }); 1899 // We do not set `any_dyn_libs` yet because a .so file 1900 // may actually resolve to a GNU ld script which ends 1901 // up being a static library. 1902 }, 1903 .res => { 1904 try create_module.cli_link_inputs.append(arena, .{ .path_query = .{ 1905 .path = Path.initCwd(arg), 1906 .query = .{ 1907 .preferred_mode = lib_preferred_mode, 1908 .search_strategy = lib_search_strategy, 1909 .allow_so_scripts = allow_so_scripts, 1910 }, 1911 } }); 1912 contains_res_file = true; 1913 }, 1914 .manifest => { 1915 if (manifest_file) |other| { 1916 fatal("only one manifest file can be specified, found {q} after {q}", .{ arg, other }); 1917 } else manifest_file = arg; 1918 }, 1919 .def => { 1920 linker_module_definition_file = arg; 1921 }, 1922 .assembly, .assembly_with_cpp, .c, .cpp, .h, .hpp, .hm, .hmm, .ll, .bc, .m, .mm => { 1923 dev.check(.c_compiler); 1924 try create_module.c_source_files.append(arena, .{ 1925 // Populated after module creation. 1926 .owner = undefined, 1927 .src_path = arg, 1928 .extra_flags = try arena.dupe([]const u8, extra_cflags.items), 1929 // duped when parsing the args. 1930 .ext = file_ext, 1931 }); 1932 }, 1933 .rc => { 1934 dev.check(.win32_resource); 1935 try create_module.rc_source_files.append(arena, .{ 1936 // Populated after module creation. 1937 .owner = undefined, 1938 .src_path = arg, 1939 .extra_flags = try arena.dupe([]const u8, extra_rcflags.items), 1940 }); 1941 }, 1942 .zig => { 1943 if (root_src_file) |other| { 1944 fatal("found another zig file {q} after root source file {q}", .{ arg, other }); 1945 } else root_src_file = arg; 1946 }, 1947 .unknown => { 1948 if (std.ascii.eqlIgnoreCase(".xml", fs.path.extension(arg))) { 1949 warn("embedded manifest files must have the extension '.manifest'", .{}); 1950 } 1951 fatal("unrecognized file extension of parameter {q}", .{arg}); 1952 }, 1953 } 1954 } 1955 }, 1956 .cc, .cpp => { 1957 dev.check(.cc_command); 1958 1959 emit_h = .no; 1960 soname = .no; 1961 create_module.opts.ensure_libc_on_non_freestanding = true; 1962 create_module.opts.ensure_libcpp_on_non_freestanding = arg_mode == .cpp; 1963 create_module.want_native_include_dirs = true; 1964 // Clang's driver enables this switch unconditionally. 1965 // Disabling the emission of .eh_frame_hdr can unexpectedly break 1966 // some functionality that depend on it, such as C++ exceptions and 1967 // DWARF-based stack traces. 1968 link_eh_frame_hdr = true; 1969 allow_so_scripts = true; 1970 1971 const COutMode = enum { 1972 link, 1973 object, 1974 assembly, 1975 preprocessor, 1976 version, 1977 }; 1978 var c_out_mode: ?COutMode = null; 1979 var out_path: ?[]const u8 = null; 1980 var is_shared_lib = false; 1981 var preprocessor_args = std.array_list.Managed([]const u8).init(arena); 1982 var linker_args = std.array_list.Managed([]const u8).init(arena); 1983 var it = ClangArgIterator.init(arena, all_args); 1984 var emit_llvm = false; 1985 var needed = false; 1986 var must_link = false; 1987 var file_ext: ?Compilation.FileExt = null; 1988 while (it.has_next) { 1989 it.next(io) catch |err| fatal("unable to parse command line parameters: {t}", .{err}); 1990 switch (it.zig_equivalent) { 1991 .target => target_arch_os_abi = it.only_arg, // example: -target riscv64-linux-unknown 1992 .o => { 1993 // We handle -o /dev/null equivalent to -fno-emit-bin because 1994 // otherwise our atomic rename into place will fail. This also 1995 // makes Zig do less work, avoiding pointless file system operations. 1996 if (mem.eql(u8, it.only_arg, "/dev/null")) { 1997 emit_bin = .no; 1998 } else { 1999 out_path = it.only_arg; 2000 } 2001 }, 2002 .c, .r => c_out_mode = .object, // -c or -r 2003 .asm_only => c_out_mode = .assembly, // -S 2004 .preprocess_only => c_out_mode = .preprocessor, // -E 2005 .version => { 2006 c_out_mode = .version; // --version 2007 disable_c_depfile = true; 2008 }, 2009 .emit_llvm => emit_llvm = true, 2010 .x => { 2011 const lang = mem.sliceTo(it.only_arg, 0); 2012 if (mem.eql(u8, lang, "none")) { 2013 file_ext = null; 2014 } else if (Compilation.FileExt.from_lang.get(lang)) |got_ext| { 2015 file_ext = got_ext; 2016 } else { 2017 fatal("language not recognized: {q}", .{lang}); 2018 } 2019 }, 2020 .other => { 2021 try cc_argv.appendSlice(arena, it.other_args); 2022 }, 2023 .positional => switch (file_ext orelse Compilation.classifyFileExt(mem.sliceTo(it.only_arg, 0))) { 2024 .assembly, .assembly_with_cpp, .c, .cpp, .ll, .bc, .h, .hpp, .hm, .hmm, .m, .mm => { 2025 try create_module.c_source_files.append(arena, .{ 2026 // Populated after module creation. 2027 .owner = undefined, 2028 .src_path = it.only_arg, 2029 .ext = file_ext, // duped while parsing the args. 2030 }); 2031 }, 2032 .unknown, .object, .static_library, .shared_library => { 2033 try create_module.cli_link_inputs.append(arena, .{ .path_query = .{ 2034 .path = Path.initCwd(it.only_arg), 2035 .query = .{ 2036 .must_link = must_link, 2037 .needed = needed, 2038 .preferred_mode = lib_preferred_mode, 2039 .search_strategy = lib_search_strategy, 2040 .allow_so_scripts = allow_so_scripts, 2041 }, 2042 } }); 2043 // We do not set `any_dyn_libs` yet because a .so file 2044 // may actually resolve to a GNU ld script which ends 2045 // up being a static library. 2046 }, 2047 .res => { 2048 try create_module.cli_link_inputs.append(arena, .{ .path_query = .{ 2049 .path = Path.initCwd(it.only_arg), 2050 .query = .{ 2051 .must_link = must_link, 2052 .needed = needed, 2053 .preferred_mode = lib_preferred_mode, 2054 .search_strategy = lib_search_strategy, 2055 .allow_so_scripts = allow_so_scripts, 2056 }, 2057 } }); 2058 contains_res_file = true; 2059 }, 2060 .manifest => { 2061 if (manifest_file) |other| { 2062 fatal("only one manifest file can be specified, found {q} after previously specified manifest {q}", .{ it.only_arg, other }); 2063 } else manifest_file = it.only_arg; 2064 }, 2065 .def => { 2066 linker_module_definition_file = it.only_arg; 2067 }, 2068 .rc => { 2069 try create_module.rc_source_files.append(arena, .{ 2070 // Populated after module creation. 2071 .owner = undefined, 2072 .src_path = it.only_arg, 2073 }); 2074 }, 2075 .zig => { 2076 if (root_src_file) |other| { 2077 fatal("found another zig file {q} after root source file {q}", .{ it.only_arg, other }); 2078 } else root_src_file = it.only_arg; 2079 }, 2080 }, 2081 .l => { 2082 // -l 2083 // We don't know whether this library is part of libc or libc++ until 2084 // we resolve the target, so we simply append to the list for now. 2085 if (mem.startsWith(u8, it.only_arg, ":")) { 2086 // -l :path/to/filename is used when callers need 2087 // more control over what's in the resulting 2088 // binary: no extra rpaths and DSO filename exactly 2089 // as provided. CGo compilation depends on this. 2090 try create_module.cli_link_inputs.append(arena, .{ .dso_exact = .{ 2091 .name = it.only_arg, 2092 } }); 2093 } else { 2094 const compiler_rt_classification = target_util.classifyCompilerRtLibName(it.only_arg); 2095 switch (compiler_rt_classification) { 2096 .only_compiler_rt, .both => { 2097 // We need this variable separately from `want_compiler_rt` because of 2098 // invocations such as `zig cc -lcompiler_rt -nostdlib`. If we just set 2099 // `want_compiler_rt = true` here, processing of the later `-nostdlib` 2100 // would undo that. 2101 zig_cc_explicitly_link_compiler_rt = true; 2102 }, 2103 .none, .only_libunwind => {}, 2104 } 2105 if (compiler_rt_classification != .only_compiler_rt) { 2106 // The case in which this arg wants to link libunwind is handled in createModule. 2107 try create_module.cli_link_inputs.append(arena, .{ .name_query = .{ 2108 .name = it.only_arg, 2109 .query = .{ 2110 .must_link = must_link, 2111 .needed = needed, 2112 .weak = false, 2113 .preferred_mode = lib_preferred_mode, 2114 .search_strategy = lib_search_strategy, 2115 .allow_so_scripts = allow_so_scripts, 2116 }, 2117 } }); 2118 } 2119 } 2120 }, 2121 .ignore => {}, 2122 .driver_punt => { 2123 // Never mind what we're doing, just pass the args directly. For example --help. 2124 return process.exit(try clangMain(arena, all_args)); 2125 }, 2126 .pic => mod_opts.pic = true, 2127 .no_pic => mod_opts.pic = false, 2128 .pie => create_module.opts.pie = true, 2129 .no_pie => create_module.opts.pie = false, 2130 .lto => { 2131 if (mem.eql(u8, it.only_arg, "flto") or 2132 mem.eql(u8, it.only_arg, "auto") or 2133 mem.eql(u8, it.only_arg, "full") or 2134 mem.eql(u8, it.only_arg, "jobserver")) 2135 { 2136 create_module.opts.lto = .full; 2137 } else if (mem.eql(u8, it.only_arg, "thin")) { 2138 create_module.opts.lto = .thin; 2139 } else { 2140 fatal("invalid -flto mode {q}; must be \"auto\", \"full\", \"thin\", or \"jobserver\"", .{it.only_arg}); 2141 } 2142 }, 2143 .no_lto => create_module.opts.lto = .none, 2144 .red_zone => mod_opts.red_zone = true, 2145 .no_red_zone => mod_opts.red_zone = false, 2146 .omit_frame_pointer => mod_opts.omit_frame_pointer = true, 2147 .no_omit_frame_pointer => mod_opts.omit_frame_pointer = false, 2148 .function_sections => function_sections = true, 2149 .no_function_sections => function_sections = false, 2150 .data_sections => data_sections = true, 2151 .no_data_sections => data_sections = false, 2152 .builtin => mod_opts.no_builtin = false, 2153 .no_builtin => mod_opts.no_builtin = true, 2154 .color_diagnostics => color = .on, 2155 .no_color_diagnostics => color = .off, 2156 .stack_check => mod_opts.stack_check = true, 2157 .no_stack_check => mod_opts.stack_check = false, 2158 .stack_protector => { 2159 if (mod_opts.stack_protector == null) { 2160 mod_opts.stack_protector = Compilation.default_stack_protector_buffer_size; 2161 } 2162 }, 2163 .no_stack_protector => mod_opts.stack_protector = 0, 2164 // The way these unwind table options are processed in GCC and Clang is crazy 2165 // convoluted, and we also don't know the target triple here, so this is all 2166 // best-effort. 2167 .unwind_tables => if (mod_opts.unwind_tables) |uwt| switch (uwt) { 2168 .none => { 2169 mod_opts.unwind_tables = .sync; 2170 }, 2171 .sync, .async => {}, 2172 } else { 2173 mod_opts.unwind_tables = .sync; 2174 }, 2175 .no_unwind_tables => mod_opts.unwind_tables = .none, 2176 .asynchronous_unwind_tables => mod_opts.unwind_tables = .async, 2177 .no_asynchronous_unwind_tables => if (mod_opts.unwind_tables) |uwt| switch (uwt) { 2178 .none, .sync => {}, 2179 .async => { 2180 mod_opts.unwind_tables = .sync; 2181 }, 2182 } else { 2183 mod_opts.unwind_tables = .sync; 2184 }, 2185 .patchable_function_entry => { 2186 mod_opts.patchable_function_entry = 2187 std.fmt.parseUnsigned(u16, it.only_arg, 10) catch |err| { 2188 fatal("unable to parse patchable function entry count {q}: {t}", .{ 2189 it.only_arg, err, 2190 }); 2191 }; 2192 }, 2193 .nostdlib => { 2194 create_module.opts.ensure_libc_on_non_freestanding = false; 2195 create_module.opts.ensure_libcpp_on_non_freestanding = false; 2196 want_compiler_rt = false; 2197 want_ubsan_rt = false; 2198 }, 2199 .nostdlib_cpp => create_module.opts.ensure_libcpp_on_non_freestanding = false, 2200 .shared => { 2201 create_module.opts.link_mode = .dynamic; 2202 is_shared_lib = true; 2203 }, 2204 .rdynamic => create_module.opts.rdynamic = true, 2205 .wp => { 2206 var split_it = mem.splitScalar(u8, it.only_arg, ','); 2207 while (split_it.next()) |preprocessor_arg| { 2208 if (preprocessor_arg.len >= 3 and 2209 preprocessor_arg[0] == '-' and 2210 preprocessor_arg[2] != '-') 2211 { 2212 if (mem.findScalar(u8, preprocessor_arg, '=')) |equals_pos| { 2213 const key = preprocessor_arg[0..equals_pos]; 2214 const value = preprocessor_arg[equals_pos + 1 ..]; 2215 try preprocessor_args.append(key); 2216 try preprocessor_args.append(value); 2217 continue; 2218 } 2219 } 2220 try preprocessor_args.append(preprocessor_arg); 2221 } 2222 }, 2223 .wl => { 2224 var split_it = mem.splitScalar(u8, it.only_arg, ','); 2225 while (split_it.next()) |linker_arg| { 2226 // Unfortunately duplicated with the `for_linker` handling below. 2227 2228 // Handle nested-joined args like `-Wl,-rpath=foo`. 2229 // Must be prefixed with 1 or 2 dashes. 2230 if (linker_arg.len >= 3 and 2231 linker_arg[0] == '-' and 2232 linker_arg[2] != '-') 2233 { 2234 if (mem.findScalar(u8, linker_arg, '=')) |equals_pos| { 2235 const key = linker_arg[0..equals_pos]; 2236 const value = linker_arg[equals_pos + 1 ..]; 2237 2238 // We have to handle these here because they would be ambiguous 2239 // if split and added to `linker_args`, as there are argument-less 2240 // variants of them. 2241 if (mem.eql(u8, key, "--build-id")) { 2242 build_id = std.zig.BuildId.parse(value) catch |err| { 2243 fatal("unable to parse --build-id style {q}: {t}", .{ value, err }); 2244 }; 2245 continue; 2246 } else if (mem.eql(u8, key, "--sort-common")) { 2247 // this ignores --sort=common=<anything>; ignoring plain --sort-common 2248 // is done below. 2249 continue; 2250 } 2251 2252 try linker_args.append(key); 2253 try linker_args.append(value); 2254 continue; 2255 } 2256 } 2257 2258 // These options are handled inline because their order matters for 2259 // other non-linker options. 2260 if (mem.eql(u8, linker_arg, "--as-needed")) { 2261 needed = false; 2262 } else if (mem.eql(u8, linker_arg, "--no-as-needed")) { 2263 needed = true; 2264 } else if (mem.eql(u8, linker_arg, "--whole-archive") or 2265 mem.eql(u8, linker_arg, "-whole-archive")) 2266 { 2267 must_link = true; 2268 } else if (mem.eql(u8, linker_arg, "--no-whole-archive") or 2269 mem.eql(u8, linker_arg, "-no-whole-archive")) 2270 { 2271 must_link = false; 2272 } else if (mem.eql(u8, linker_arg, "-Bdynamic") or 2273 mem.eql(u8, linker_arg, "-dy") or 2274 mem.eql(u8, linker_arg, "-call_shared")) 2275 { 2276 lib_search_strategy = .no_fallback; 2277 lib_preferred_mode = .dynamic; 2278 } else if (mem.eql(u8, linker_arg, "-Bstatic") or 2279 mem.eql(u8, linker_arg, "-dn") or 2280 mem.eql(u8, linker_arg, "-non_shared") or 2281 mem.eql(u8, linker_arg, "-static")) 2282 { 2283 lib_search_strategy = .no_fallback; 2284 lib_preferred_mode = .static; 2285 } else if (mem.eql(u8, linker_arg, "-search_paths_first")) { 2286 lib_search_strategy = .paths_first; 2287 lib_preferred_mode = .dynamic; 2288 } else if (mem.eql(u8, linker_arg, "-search_dylibs_first")) { 2289 lib_search_strategy = .mode_first; 2290 lib_preferred_mode = .dynamic; 2291 } else { 2292 try linker_args.append(linker_arg); 2293 } 2294 } 2295 }, 2296 .san_cov_trace_pc_guard => create_module.opts.san_cov_trace_pc_guard = true, 2297 .san_cov => { 2298 var split_it = mem.splitScalar(u8, it.only_arg, ','); 2299 while (split_it.next()) |san_arg| { 2300 if (std.mem.eql(u8, san_arg, "trace-pc-guard")) { 2301 create_module.opts.san_cov_trace_pc_guard = true; 2302 } 2303 } 2304 try cc_argv.appendSlice(arena, it.other_args); 2305 }, 2306 .no_san_cov => { 2307 var split_it = mem.splitScalar(u8, it.only_arg, ','); 2308 while (split_it.next()) |san_arg| { 2309 if (std.mem.eql(u8, san_arg, "trace-pc-guard")) { 2310 create_module.opts.san_cov_trace_pc_guard = false; 2311 } 2312 } 2313 try cc_argv.appendSlice(arena, it.other_args); 2314 }, 2315 .optimize => { 2316 // Alright, what release mode do they want? 2317 const level = if (it.only_arg.len >= 1 and it.only_arg[0] == 'O') it.only_arg[1..] else it.only_arg; 2318 if (mem.eql(u8, level, "s") or 2319 mem.eql(u8, level, "z")) 2320 { 2321 mod_opts.optimize_mode = .small; 2322 } else if (mem.eql(u8, level, "1") or 2323 mem.eql(u8, level, "2") or 2324 mem.eql(u8, level, "3") or 2325 mem.eql(u8, level, "4") or 2326 mem.eql(u8, level, "fast")) 2327 { 2328 mod_opts.optimize_mode = .fast; 2329 } else if (mem.eql(u8, level, "g") or 2330 mem.eql(u8, level, "0")) 2331 { 2332 mod_opts.optimize_mode = .debug; 2333 } else { 2334 try cc_argv.appendSlice(arena, it.other_args); 2335 } 2336 }, 2337 .debug => { 2338 mod_opts.strip = false; 2339 if (mem.eql(u8, it.only_arg, "g")) { 2340 // We handled with strip = false above. 2341 } else if (mem.eql(u8, it.only_arg, "g1") or 2342 mem.eql(u8, it.only_arg, "gline-tables-only")) 2343 { 2344 // We handled with strip = false above. but we also want reduced debug info. 2345 try cc_argv.append(arena, "-gline-tables-only"); 2346 } else { 2347 try cc_argv.appendSlice(arena, it.other_args); 2348 } 2349 }, 2350 .gdwarf32 => { 2351 mod_opts.strip = false; 2352 create_module.opts.debug_format = .{ .dwarf = .@"32" }; 2353 }, 2354 .gdwarf64 => { 2355 mod_opts.strip = false; 2356 create_module.opts.debug_format = .{ .dwarf = .@"64" }; 2357 }, 2358 .sanitize, .no_sanitize => |t| { 2359 const enable = t == .sanitize; 2360 var san_it = std.mem.splitScalar(u8, it.only_arg, ','); 2361 var recognized_any = false; 2362 while (san_it.next()) |sub_arg| { 2363 if (mem.eql(u8, sub_arg, "undefined")) { 2364 mod_opts.sanitize_c = if (enable) .full else .off; 2365 recognized_any = true; 2366 } else if (mem.eql(u8, sub_arg, "thread")) { 2367 mod_opts.sanitize_thread = enable; 2368 recognized_any = true; 2369 } else if (mem.eql(u8, sub_arg, "fuzzer") or mem.eql(u8, sub_arg, "fuzzer-no-link")) { 2370 mod_opts.fuzz = enable; 2371 recognized_any = true; 2372 } 2373 } 2374 if (!recognized_any) { 2375 try cc_argv.appendSlice(arena, it.other_args); 2376 } 2377 }, 2378 .sanitize_trap, .no_sanitize_trap => |t| { 2379 const enable = t == .sanitize_trap; 2380 var san_it = std.mem.splitScalar(u8, it.only_arg, ','); 2381 var recognized_any = false; 2382 while (san_it.next()) |sub_arg| { 2383 // This logic doesn't match Clang 1:1, but it's probably good enough, and avoids 2384 // significantly complicating the resolution of the options. 2385 if (mem.eql(u8, sub_arg, "undefined")) { 2386 if (mod_opts.sanitize_c) |sc| switch (sc) { 2387 .off => if (enable) { 2388 mod_opts.sanitize_c = .trap; 2389 }, 2390 .trap => if (!enable) { 2391 mod_opts.sanitize_c = .full; 2392 }, 2393 .full => if (enable) { 2394 mod_opts.sanitize_c = .trap; 2395 }, 2396 } else { 2397 if (enable) { 2398 mod_opts.sanitize_c = .trap; 2399 } else { 2400 // This means we were passed `-fno-sanitize-trap=undefined` and nothing else. In 2401 // this case, ideally, we should use whatever value `sanitize_c` resolves to by 2402 // default, except change `trap` to `full`. However, we don't yet know what 2403 // `sanitize_c` will resolve to! So we either have to pick `off` or `full`. 2404 // 2405 // `full` has the potential to be problematic if `optimize_mode` turns out to 2406 // be `fast`/`small` because the user will get a slower and larger 2407 // binary than expected. On the other hand, if `optimize_mode` turns out to be 2408 // `debug`/`safe`, `off` would mean UBSan would unexpectedly be disabled. 2409 // 2410 // `off` seems very slightly less bad, so let's go with that. 2411 mod_opts.sanitize_c = .off; 2412 } 2413 } 2414 recognized_any = true; 2415 } 2416 } 2417 if (!recognized_any) { 2418 try cc_argv.appendSlice(arena, it.other_args); 2419 } 2420 }, 2421 .linker_script => linker_script = it.only_arg, 2422 .verbose => { 2423 verbose_link = true; 2424 // Have Clang print more infos, some tools such as CMake 2425 // parse this to discover any implicit include and 2426 // library dir to look-up into. 2427 try cc_argv.append(arena, "-v"); 2428 }, 2429 .dry_run => { 2430 // This flag means "dry run". Clang will not actually output anything 2431 // to the file system. 2432 verbose_link = true; 2433 disable_c_depfile = true; 2434 try cc_argv.append(arena, "-###"); 2435 }, 2436 .for_linker => blk: { 2437 // Unfortunately duplicated with the `wl` handling above. 2438 2439 // Handle joined args like `--dependency-file=foo.d`. 2440 // Must be prefixed with 1 or 2 dashes. 2441 if (it.only_arg.len >= 3 and it.only_arg[0] == '-' and it.only_arg[2] != '-') { 2442 if (mem.findScalar(u8, it.only_arg, '=')) |equals_pos| { 2443 const key = it.only_arg[0..equals_pos]; 2444 const value = it.only_arg[equals_pos + 1 ..]; 2445 2446 // We have to handle these here because they would be ambiguous 2447 // if split and added to `linker_args`, as there are argument-less 2448 // variants of them. 2449 if (mem.eql(u8, key, "--build-id")) { 2450 build_id = std.zig.BuildId.parse(value) catch |err| { 2451 fatal("unable to parse --build-id style {q}: {t}", .{ value, err }); 2452 }; 2453 continue; 2454 } else if (mem.eql(u8, key, "--sort-common")) { 2455 // this ignores --sort-common=<anything> 2456 continue; 2457 } 2458 2459 try linker_args.append(key); 2460 try linker_args.append(value); 2461 break :blk; 2462 } 2463 } 2464 2465 // These options are handled inline because their order matters for 2466 // other non-linker options. 2467 if (mem.eql(u8, it.only_arg, "--as-needed")) { 2468 needed = false; 2469 } else if (mem.eql(u8, it.only_arg, "--no-as-needed")) { 2470 needed = true; 2471 } else if (mem.eql(u8, it.only_arg, "--whole-archive") or 2472 mem.eql(u8, it.only_arg, "-whole-archive")) 2473 { 2474 must_link = true; 2475 } else if (mem.eql(u8, it.only_arg, "--no-whole-archive") or 2476 mem.eql(u8, it.only_arg, "-no-whole-archive")) 2477 { 2478 must_link = false; 2479 } else if (mem.eql(u8, it.only_arg, "-Bdynamic") or 2480 mem.eql(u8, it.only_arg, "-dy") or 2481 mem.eql(u8, it.only_arg, "-call_shared")) 2482 { 2483 lib_search_strategy = .no_fallback; 2484 lib_preferred_mode = .dynamic; 2485 } else if (mem.eql(u8, it.only_arg, "-Bstatic") or 2486 mem.eql(u8, it.only_arg, "-dn") or 2487 mem.eql(u8, it.only_arg, "-non_shared") or 2488 mem.eql(u8, it.only_arg, "-static")) 2489 { 2490 lib_search_strategy = .no_fallback; 2491 lib_preferred_mode = .static; 2492 } else if (mem.eql(u8, it.only_arg, "-search_paths_first")) { 2493 lib_search_strategy = .paths_first; 2494 lib_preferred_mode = .dynamic; 2495 } else if (mem.eql(u8, it.only_arg, "-search_dylibs_first")) { 2496 lib_search_strategy = .mode_first; 2497 lib_preferred_mode = .dynamic; 2498 } else { 2499 try linker_args.append(it.only_arg); 2500 } 2501 }, 2502 .linker_input_z => { 2503 try linker_args.append("-z"); 2504 try linker_args.append(it.only_arg); 2505 }, 2506 .lib_dir => try create_module.lib_dir_args.append(arena, it.only_arg), 2507 .mcpu => target_mcpu = it.only_arg, 2508 .m => try create_module.llvm_m_args.append(arena, it.only_arg), 2509 .dep_file => { 2510 disable_c_depfile = true; 2511 try cc_argv.appendSlice(arena, it.other_args); 2512 }, 2513 .dep_file_to_stdout => { // -M, -MM 2514 // "Like -MD, but also implies -E and writes to stdout by default" 2515 // "Like -MMD, but also implies -E and writes to stdout by default" 2516 c_out_mode = .preprocessor; 2517 disable_c_depfile = true; 2518 try cc_argv.appendSlice(arena, it.other_args); 2519 }, 2520 .framework_dir => try create_module.framework_dirs.append(arena, it.only_arg), 2521 .framework => try create_module.frameworks.put(arena, it.only_arg, .{}), 2522 .nostdlibinc => create_module.want_native_include_dirs = false, 2523 .strip => mod_opts.strip = true, 2524 .exec_model => { 2525 create_module.opts.wasi_exec_model = parseWasiExecModel(it.only_arg); 2526 }, 2527 .sysroot => { 2528 create_module.sysroot = it.only_arg; 2529 }, 2530 .entry => { 2531 entry = .{ .named = it.only_arg }; 2532 }, 2533 .force_undefined_symbol => { 2534 try force_undefined_symbols.put(arena, it.only_arg, {}); 2535 }, 2536 .force_load_objc => force_load_objc = true, 2537 .mingw_unicode_entry_point => mingw_unicode_entry_point = true, 2538 .weak_library => try create_module.cli_link_inputs.append(arena, .{ .name_query = .{ 2539 .name = it.only_arg, 2540 .query = .{ 2541 .needed = false, 2542 .weak = true, 2543 .preferred_mode = lib_preferred_mode, 2544 .search_strategy = lib_search_strategy, 2545 .allow_so_scripts = allow_so_scripts, 2546 }, 2547 } }), 2548 .weak_framework => try create_module.frameworks.put(arena, it.only_arg, .{ .weak = true }), 2549 .headerpad_max_install_names => headerpad_max_install_names = true, 2550 .compress_debug_sections => { 2551 if (it.only_arg.len == 0) { 2552 linker_compress_debug_sections = .zlib; 2553 } else { 2554 linker_compress_debug_sections = stringToEnum(std.zig.CompressDebugSections, it.only_arg) orelse { 2555 fatal("expected [none|zlib|zstd] after --compress-debug-sections, found {q}", .{it.only_arg}); 2556 }; 2557 } 2558 }, 2559 .install_name => { 2560 install_name = it.only_arg; 2561 }, 2562 .undefined => { 2563 if (mem.eql(u8, "dynamic_lookup", it.only_arg)) { 2564 linker_allow_shlib_undefined = true; 2565 } else if (mem.eql(u8, "error", it.only_arg)) { 2566 linker_allow_shlib_undefined = false; 2567 } else { 2568 fatal("unsupported -undefined option {q}", .{it.only_arg}); 2569 } 2570 }, 2571 .rtlib => { 2572 // Unlike Clang, we support `none` for explicitly omitting compiler-rt. 2573 if (mem.eql(u8, "none", it.only_arg)) { 2574 want_compiler_rt = false; 2575 } else if (mem.eql(u8, "compiler-rt", it.only_arg) or 2576 mem.eql(u8, "libgcc", it.only_arg)) 2577 { 2578 want_compiler_rt = true; 2579 } else { 2580 // Note that we don't support `platform`. 2581 fatal("unsupported -rtlib option {q}", .{it.only_arg}); 2582 } 2583 }, 2584 .static => { 2585 create_module.opts.link_mode = .static; 2586 lib_preferred_mode = .static; 2587 lib_search_strategy = .no_fallback; 2588 }, 2589 .dynamic => { 2590 create_module.opts.link_mode = .dynamic; 2591 lib_preferred_mode = .dynamic; 2592 lib_search_strategy = .mode_first; 2593 }, 2594 } 2595 } 2596 // Parse linker args. 2597 var linker_args_it = ArgsIterator{ 2598 .args = linker_args.items, 2599 }; 2600 while (linker_args_it.next()) |arg| { 2601 if (mem.eql(u8, arg, "-soname") or 2602 mem.eql(u8, arg, "--soname")) 2603 { 2604 const name = linker_args_it.nextOrFatal(); 2605 soname = .{ .yes = name }; 2606 // Use it as --name. 2607 // Example: libsoundio.so.2 2608 var prefix: usize = 0; 2609 if (mem.startsWith(u8, name, "lib")) { 2610 prefix = 3; 2611 } 2612 var end: usize = name.len; 2613 if (mem.endsWith(u8, name, ".so")) { 2614 end -= 3; 2615 } else { 2616 var found_digit = false; 2617 while (end > 0 and std.ascii.isDigit(name[end - 1])) { 2618 found_digit = true; 2619 end -= 1; 2620 } 2621 if (found_digit and end > 0 and name[end - 1] == '.') { 2622 end -= 1; 2623 } else { 2624 end = name.len; 2625 } 2626 if (mem.endsWith(u8, name[prefix..end], ".so")) { 2627 end -= 3; 2628 } 2629 } 2630 provided_name = name[prefix..end]; 2631 } else if (mem.eql(u8, arg, "--build-id")) { 2632 build_id = .fast; 2633 } else if (mem.eql(u8, arg, "-no-pie")) { 2634 create_module.opts.pie = false; 2635 } else if (mem.eql(u8, arg, "--sort-common")) { 2636 // from ld.lld(1): --sort-common is ignored for GNU compatibility, 2637 // this ignores plain --sort-common 2638 } else if (mem.eql(u8, arg, "-rpath") or mem.eql(u8, arg, "--rpath") or mem.eql(u8, arg, "-R")) { 2639 try create_module.rpath_list.append(arena, linker_args_it.nextOrFatal()); 2640 } else if (mem.eql(u8, arg, "-rpath-link") or mem.eql(u8, arg, "--rpath-link")) { 2641 _ = linker_args_it.nextOrFatal(); 2642 warn("rpath-link option is unimplemented and ignored", .{}); 2643 } else if (mem.eql(u8, arg, "--subsystem")) { 2644 subsystem = try parseSubsystem(linker_args_it.nextOrFatal()); 2645 } else if (mem.eql(u8, arg, "-I") or 2646 mem.eql(u8, arg, "--dynamic-linker") or 2647 mem.eql(u8, arg, "-dynamic-linker")) 2648 { 2649 dynamic_linker = linker_args_it.nextOrFatal(); 2650 } else if (mem.eql(u8, arg, "--no-dynamic-linker") or 2651 mem.eql(u8, arg, "-no-dynamic-linker")) 2652 { 2653 dynamic_linker = ""; 2654 } else if (mem.eql(u8, arg, "-E") or 2655 mem.eql(u8, arg, "--export-dynamic") or 2656 mem.eql(u8, arg, "-export-dynamic")) 2657 { 2658 create_module.opts.rdynamic = true; 2659 } else if (mem.eql(u8, arg, "-version-script") or mem.eql(u8, arg, "--version-script")) { 2660 version_script = linker_args_it.nextOrFatal(); 2661 } else if (mem.eql(u8, arg, "--undefined-version")) { 2662 linker_allow_undefined_version = true; 2663 } else if (mem.eql(u8, arg, "--no-undefined-version")) { 2664 linker_allow_undefined_version = false; 2665 } else if (mem.eql(u8, arg, "--enable-new-dtags")) { 2666 linker_enable_new_dtags = true; 2667 } else if (mem.eql(u8, arg, "--disable-new-dtags")) { 2668 linker_enable_new_dtags = false; 2669 } else if (mem.eql(u8, arg, "-O")) { 2670 linker_optimization = linker_args_it.nextOrFatal(); 2671 } else if (mem.cutPrefix(u8, arg, "-O")) |rest| { 2672 linker_optimization = rest; 2673 } else if (mem.eql(u8, arg, "-pagezero_size")) { 2674 const next_arg = linker_args_it.nextOrFatal(); 2675 pagezero_size = std.fmt.parseUnsigned(u64, eatIntPrefix(next_arg, 16), 16) catch |err| { 2676 fatal("unable to parse pagezero size {q}: {t}", .{ next_arg, err }); 2677 }; 2678 } else if (mem.eql(u8, arg, "-headerpad")) { 2679 const next_arg = linker_args_it.nextOrFatal(); 2680 headerpad_size = std.fmt.parseUnsigned(u32, eatIntPrefix(next_arg, 16), 16) catch |err| { 2681 fatal("unable to parse headerpad size {q}: {t}", .{ next_arg, err }); 2682 }; 2683 } else if (mem.eql(u8, arg, "-headerpad_max_install_names")) { 2684 headerpad_max_install_names = true; 2685 } else if (mem.eql(u8, arg, "-dead_strip")) { 2686 linker_gc_sections = true; 2687 } else if (mem.eql(u8, arg, "-dead_strip_dylibs")) { 2688 dead_strip_dylibs = true; 2689 } else if (mem.eql(u8, arg, "-ObjC")) { 2690 force_load_objc = true; 2691 } else if (mem.eql(u8, arg, "--no-undefined")) { 2692 linker_z_defs = true; 2693 } else if (mem.eql(u8, arg, "--gc-sections")) { 2694 linker_gc_sections = true; 2695 } else if (mem.eql(u8, arg, "--no-gc-sections")) { 2696 linker_gc_sections = false; 2697 } else if (mem.eql(u8, arg, "--print-gc-sections")) { 2698 linker_print_gc_sections = true; 2699 } else if (mem.eql(u8, arg, "--print-icf-sections")) { 2700 linker_print_icf_sections = true; 2701 } else if (mem.eql(u8, arg, "--print-map")) { 2702 linker_print_map = true; 2703 } else if (mem.eql(u8, arg, "-n") or mem.eql(u8, arg, "--nmagic")) { 2704 linker_nmagic = true; 2705 } else if (mem.eql(u8, arg, "--fatal-warnings")) { 2706 linker_fatal_warnings = true; 2707 } else if (mem.eql(u8, arg, "--no-fatal-warnings")) { 2708 linker_fatal_warnings = false; 2709 } else if (mem.eql(u8, arg, "-m")) { 2710 _ = linker_args_it.nextOrFatal(); 2711 warn("-m option is ignored; emulation is derived from target", .{}); 2712 } else if (mem.eql(u8, arg, "--sort-section")) { 2713 const arg1 = linker_args_it.nextOrFatal(); 2714 linker_sort_section = stringToEnum(link.File.Lld.Elf.SortSection, arg1) orelse { 2715 fatal("expected [name|alignment] after --sort-section, found {q}", .{arg1}); 2716 }; 2717 } else if (mem.eql(u8, arg, "--allow-shlib-undefined") or 2718 mem.eql(u8, arg, "-allow-shlib-undefined")) 2719 { 2720 linker_allow_shlib_undefined = true; 2721 } else if (mem.eql(u8, arg, "--no-allow-shlib-undefined") or 2722 mem.eql(u8, arg, "-no-allow-shlib-undefined")) 2723 { 2724 linker_allow_shlib_undefined = false; 2725 } else if (mem.eql(u8, arg, "-Bsymbolic")) { 2726 linker_bind_global_refs_locally = true; 2727 } else if (mem.eql(u8, arg, "--import-memory")) { 2728 create_module.opts.import_memory = true; 2729 } else if (mem.eql(u8, arg, "--export-memory")) { 2730 create_module.opts.export_memory = true; 2731 } else if (mem.eql(u8, arg, "--import-symbols")) { 2732 linker_import_symbols = true; 2733 } else if (mem.eql(u8, arg, "--import-table")) { 2734 linker_import_table = true; 2735 } else if (mem.eql(u8, arg, "--export-table")) { 2736 linker_export_table = true; 2737 } else if (mem.eql(u8, arg, "--growable-table")) { 2738 linker_growable_table = true; 2739 } else if (mem.eql(u8, arg, "--no-entry")) { 2740 entry = .disabled; 2741 } else if (mem.eql(u8, arg, "--initial-memory")) { 2742 const next_arg = linker_args_it.nextOrFatal(); 2743 linker_initial_memory = std.fmt.parseUnsigned(u32, next_arg, 10) catch |err| { 2744 fatal("unable to parse initial memory size {q}: {t}", .{ next_arg, err }); 2745 }; 2746 } else if (mem.eql(u8, arg, "--max-memory")) { 2747 const next_arg = linker_args_it.nextOrFatal(); 2748 linker_max_memory = std.fmt.parseUnsigned(u32, next_arg, 10) catch |err| { 2749 fatal("unable to parse max memory size {q}: {t}", .{ next_arg, err }); 2750 }; 2751 } else if (mem.eql(u8, arg, "--shared-memory")) { 2752 create_module.opts.shared_memory = true; 2753 } else if (mem.eql(u8, arg, "--global-base")) { 2754 const next_arg = linker_args_it.nextOrFatal(); 2755 linker_global_base = std.fmt.parseUnsigned(u32, next_arg, 10) catch |err| { 2756 fatal("unable to parse global base {q}: {t}", .{ next_arg, err }); 2757 }; 2758 } else if (mem.eql(u8, arg, "--export")) { 2759 try linker_export_symbol_names.append(arena, linker_args_it.nextOrFatal()); 2760 } else if (mem.eql(u8, arg, "-exported_symbols_list")) { 2761 const exported_symbols_list = linker_args_it.nextOrFatal(); 2762 const content = Io.Dir.cwd().readFileAlloc(io, exported_symbols_list, arena, .limited(10 * 1024 * 1024)) catch |err| { 2763 fatal("unable to read exported symbols list {q}: {t}", .{ exported_symbols_list, err }); 2764 }; 2765 var symbols_it = mem.splitScalar(u8, content, '\n'); 2766 while (symbols_it.next()) |line| { 2767 if (line.len == 0) continue; 2768 try linker_export_symbol_names.append(arena, line); 2769 } 2770 } else if (mem.eql(u8, arg, "--compress-debug-sections")) { 2771 const arg1 = linker_args_it.nextOrFatal(); 2772 linker_compress_debug_sections = stringToEnum(std.zig.CompressDebugSections, arg1) orelse { 2773 fatal("expected [none|zlib|zstd] after --compress-debug-sections, found {q}", .{arg1}); 2774 }; 2775 } else if (mem.cutPrefix(u8, arg, "-z")) |z_rest| { 2776 const z_arg = if (z_rest.len == 0) linker_args_it.nextOrFatal() else z_rest; 2777 if (mem.eql(u8, z_arg, "nodelete")) { 2778 linker_z_nodelete = true; 2779 } else if (mem.eql(u8, z_arg, "notext")) { 2780 linker_z_notext = true; 2781 } else if (mem.eql(u8, z_arg, "defs")) { 2782 linker_z_defs = true; 2783 } else if (mem.eql(u8, z_arg, "undefs")) { 2784 linker_z_defs = false; 2785 } else if (mem.eql(u8, z_arg, "origin")) { 2786 linker_z_origin = true; 2787 } else if (mem.eql(u8, z_arg, "nocopyreloc")) { 2788 linker_z_nocopyreloc = true; 2789 } else if (mem.eql(u8, z_arg, "noexecstack")) { 2790 // noexecstack is the default when linking with LLD 2791 } else if (mem.eql(u8, z_arg, "now")) { 2792 linker_z_now = true; 2793 } else if (mem.eql(u8, z_arg, "lazy")) { 2794 linker_z_now = false; 2795 } else if (mem.eql(u8, z_arg, "relro")) { 2796 linker_z_relro = true; 2797 } else if (mem.eql(u8, z_arg, "norelro")) { 2798 linker_z_relro = false; 2799 } else if (mem.cutPrefix(u8, z_arg, "stack-size=")) |rest| { 2800 stack_size = parseStackSize(rest); 2801 } else if (prefixedIntArg(z_arg, "common-page-size=")) |int| { 2802 linker_z_common_page_size = int; 2803 } else if (prefixedIntArg(z_arg, "max-page-size=")) |int| { 2804 linker_z_max_page_size = int; 2805 } else { 2806 fatal("unsupported linker extension flag: -z {s}", .{z_arg}); 2807 } 2808 } else if (mem.eql(u8, arg, "--major-image-version")) { 2809 const major = linker_args_it.nextOrFatal(); 2810 version.major = std.fmt.parseUnsigned(u32, major, 10) catch |err| { 2811 fatal("unable to parse major image version {q}: {t}", .{ major, err }); 2812 }; 2813 have_version = true; 2814 } else if (mem.eql(u8, arg, "--minor-image-version")) { 2815 const minor = linker_args_it.nextOrFatal(); 2816 version.minor = std.fmt.parseUnsigned(u32, minor, 10) catch |err| { 2817 fatal("unable to parse minor image version {q}: {t}", .{ minor, err }); 2818 }; 2819 have_version = true; 2820 } else if (mem.eql(u8, arg, "-e") or mem.eql(u8, arg, "--entry")) { 2821 entry = .{ .named = linker_args_it.nextOrFatal() }; 2822 } else if (mem.eql(u8, arg, "-u")) { 2823 try force_undefined_symbols.put(arena, linker_args_it.nextOrFatal(), {}); 2824 } else if (mem.eql(u8, arg, "-w")) { 2825 // This ignores the -w flag of ld64 and ld64.lld to suppress all linker warnings 2826 // since Zig doesn't emit linker warnings. 2827 } else if (mem.eql(u8, arg, "-x") or mem.eql(u8, arg, "--discard-all")) { 2828 discard_local_symbols = true; 2829 } else if (mem.eql(u8, arg, "--stack") or mem.eql(u8, arg, "-stack_size")) { 2830 stack_size = parseStackSize(linker_args_it.nextOrFatal()); 2831 } else if (mem.eql(u8, arg, "--image-base")) { 2832 image_base = parseImageBase(linker_args_it.nextOrFatal()); 2833 } else if (mem.eql(u8, arg, "--enable-auto-image-base") or 2834 mem.eql(u8, arg, "--disable-auto-image-base")) 2835 { 2836 // `--enable-auto-image-base` is a flag that binutils added in ~2000 for MinGW. 2837 // It does a hash of the file and uses that as part of the image base value. 2838 // Presumably the idea was to avoid DLLs needing to be relocated when loaded. 2839 // This is practically irrelevant today as all PEs produced since Windows Vista 2840 // have ASLR enabled by default anyway, and Windows 10+ has Mandatory ASLR which 2841 // doesn't even care what the PE file wants and relocates it anyway. 2842 // 2843 // Unfortunately, Libtool hardcodes usage of this archaic flag when targeting 2844 // MinGW, so to make `zig cc` for that use case work, accept and ignore the 2845 // flag, and warn the user that it has no effect. 2846 warn("auto-image-base options are unimplemented and ignored", .{}); 2847 } else if (mem.eql(u8, arg, "-T") or mem.eql(u8, arg, "--script")) { 2848 linker_script = linker_args_it.nextOrFatal(); 2849 } else if (mem.eql(u8, arg, "--eh-frame-hdr")) { 2850 link_eh_frame_hdr = true; 2851 } else if (mem.eql(u8, arg, "--no-eh-frame-hdr")) { 2852 link_eh_frame_hdr = false; 2853 } else if (mem.eql(u8, arg, "--tsaware")) { 2854 linker_tsaware = true; 2855 } else if (mem.eql(u8, arg, "--nxcompat")) { 2856 linker_nxcompat = true; 2857 } else if (mem.eql(u8, arg, "--dynamicbase")) { 2858 linker_dynamicbase = true; 2859 } else if (mem.eql(u8, arg, "--no-dynamicbase")) { 2860 linker_dynamicbase = false; 2861 } else if (mem.eql(u8, arg, "--high-entropy-va")) { 2862 // This option does not do anything. 2863 } else if (mem.eql(u8, arg, "--export-all-symbols")) { 2864 create_module.opts.rdynamic = true; 2865 } else if (mem.eql(u8, arg, "--color-diagnostics") or 2866 mem.eql(u8, arg, "--color-diagnostics=always")) 2867 { 2868 color = .on; 2869 } else if (mem.eql(u8, arg, "--no-color-diagnostics") or 2870 mem.eql(u8, arg, "--color-diagnostics=never")) 2871 { 2872 color = .off; 2873 } else if (mem.eql(u8, arg, "-s") or mem.eql(u8, arg, "--strip-all") or 2874 mem.eql(u8, arg, "-S") or mem.eql(u8, arg, "--strip-debug")) 2875 { 2876 // -s, --strip-all Strip all symbols 2877 // -S, --strip-debug Strip debugging symbols 2878 mod_opts.strip = true; 2879 } else if (mem.eql(u8, arg, "--start-group") or 2880 mem.eql(u8, arg, "--end-group")) 2881 { 2882 // We don't need to care about these because these args are 2883 // for resolving circular dependencies but our linker takes 2884 // care of this without explicit args. 2885 } else if (mem.eql(u8, arg, "--major-os-version") or 2886 mem.eql(u8, arg, "--minor-os-version")) 2887 { 2888 // This option does not do anything. 2889 _ = linker_args_it.nextOrFatal(); 2890 } else if (mem.eql(u8, arg, "--major-subsystem-version")) { 2891 const major = linker_args_it.nextOrFatal(); 2892 major_subsystem_version = std.fmt.parseUnsigned(u16, major, 10) catch |err| { 2893 fatal("unable to parse major subsystem version {q}: {t}", .{ major, err }); 2894 }; 2895 } else if (mem.eql(u8, arg, "--minor-subsystem-version")) { 2896 const minor = linker_args_it.nextOrFatal(); 2897 minor_subsystem_version = std.fmt.parseUnsigned(u16, minor, 10) catch |err| { 2898 fatal("unable to parse minor subsystem version {q}: {t}", .{ minor, err }); 2899 }; 2900 } else if (mem.eql(u8, arg, "-framework")) { 2901 try create_module.frameworks.put(arena, linker_args_it.nextOrFatal(), .{}); 2902 } else if (mem.eql(u8, arg, "-weak_framework")) { 2903 try create_module.frameworks.put(arena, linker_args_it.nextOrFatal(), .{ .weak = true }); 2904 } else if (mem.eql(u8, arg, "-needed_framework")) { 2905 try create_module.frameworks.put(arena, linker_args_it.nextOrFatal(), .{ .needed = true }); 2906 } else if (mem.eql(u8, arg, "-needed_library")) { 2907 try create_module.cli_link_inputs.append(arena, .{ .name_query = .{ 2908 .name = linker_args_it.nextOrFatal(), 2909 .query = .{ 2910 .weak = false, 2911 .needed = true, 2912 .preferred_mode = lib_preferred_mode, 2913 .search_strategy = lib_search_strategy, 2914 .allow_so_scripts = allow_so_scripts, 2915 }, 2916 } }); 2917 } else if (mem.cutPrefix(u8, arg, "-weak-l")) |rest| { 2918 try create_module.cli_link_inputs.append(arena, .{ .name_query = .{ 2919 .name = rest, 2920 .query = .{ 2921 .weak = true, 2922 .needed = false, 2923 .preferred_mode = lib_preferred_mode, 2924 .search_strategy = lib_search_strategy, 2925 .allow_so_scripts = allow_so_scripts, 2926 }, 2927 } }); 2928 } else if (mem.eql(u8, arg, "-weak_library")) { 2929 try create_module.cli_link_inputs.append(arena, .{ .name_query = .{ 2930 .name = linker_args_it.nextOrFatal(), 2931 .query = .{ 2932 .weak = true, 2933 .needed = false, 2934 .preferred_mode = lib_preferred_mode, 2935 .search_strategy = lib_search_strategy, 2936 .allow_so_scripts = allow_so_scripts, 2937 }, 2938 } }); 2939 } else if (mem.eql(u8, arg, "-compatibility_version")) { 2940 const compat_version = linker_args_it.nextOrFatal(); 2941 compatibility_version = std.SemanticVersion.parse(compat_version) catch |err| { 2942 fatal("unable to parse -compatibility_version {q}: {t}", .{ compat_version, err }); 2943 }; 2944 } else if (mem.eql(u8, arg, "-current_version")) { 2945 const curr_version = linker_args_it.nextOrFatal(); 2946 version = std.SemanticVersion.parse(curr_version) catch |err| { 2947 fatal("unable to parse -current_version {q}: {t}", .{ curr_version, err }); 2948 }; 2949 have_version = true; 2950 } else if (mem.eql(u8, arg, "--out-implib") or 2951 mem.eql(u8, arg, "-implib")) 2952 { 2953 emit_implib = .{ .yes = linker_args_it.nextOrFatal() }; 2954 emit_implib_arg_provided = true; 2955 } else if (mem.eql(u8, arg, "--dependency-file")) { 2956 link_depfile = linker_args_it.nextOrFatal(); 2957 } else if (mem.eql(u8, arg, "-Brepro") or mem.eql(u8, arg, "/Brepro")) { 2958 linker_repro = true; 2959 } else if (mem.eql(u8, arg, "-undefined")) { 2960 const lookup_type = linker_args_it.nextOrFatal(); 2961 if (mem.eql(u8, "dynamic_lookup", lookup_type)) { 2962 linker_allow_shlib_undefined = true; 2963 } else if (mem.eql(u8, "error", lookup_type)) { 2964 linker_allow_shlib_undefined = false; 2965 } else { 2966 fatal("unsupported -undefined option {q}", .{lookup_type}); 2967 } 2968 } else if (mem.eql(u8, arg, "-install_name")) { 2969 install_name = linker_args_it.nextOrFatal(); 2970 } else if (mem.eql(u8, arg, "-force_load")) { 2971 try create_module.cli_link_inputs.append(arena, .{ .path_query = .{ 2972 .path = Path.initCwd(linker_args_it.nextOrFatal()), 2973 .query = .{ 2974 .must_link = true, 2975 .preferred_mode = .static, 2976 .search_strategy = .no_fallback, 2977 }, 2978 } }); 2979 } else if (mem.eql(u8, arg, "-hash-style") or 2980 mem.eql(u8, arg, "--hash-style")) 2981 { 2982 const next_arg = linker_args_it.nextOrFatal(); 2983 hash_style = stringToEnum(link.File.Lld.Elf.HashStyle, next_arg) orelse { 2984 fatal("expected [sysv|gnu|both] after --hash-style, found {q}", .{next_arg}); 2985 }; 2986 } else if (mem.eql(u8, arg, "-wrap") or mem.eql(u8, arg, "--wrap")) { 2987 const next_arg = linker_args_it.nextOrFatal(); 2988 try symbol_wrap_set.put(arena, next_arg, {}); 2989 } else if (mem.cutPrefix(u8, arg, "--wrap=")) |symbol| { 2990 try symbol_wrap_set.put(arena, symbol, {}); 2991 } else if (mem.startsWith(u8, arg, "/subsystem:")) { 2992 var split_it = mem.splitBackwardsScalar(u8, arg, ':'); 2993 subsystem = try parseSubsystem(split_it.first()); 2994 } else if (mem.startsWith(u8, arg, "/implib:")) { 2995 var split_it = mem.splitBackwardsScalar(u8, arg, ':'); 2996 emit_implib = .{ .yes = split_it.first() }; 2997 emit_implib_arg_provided = true; 2998 } else if (mem.startsWith(u8, arg, "/pdb:")) { 2999 var split_it = mem.splitBackwardsScalar(u8, arg, ':'); 3000 pdb_out_path = split_it.first(); 3001 } else if (mem.startsWith(u8, arg, "/version:")) { 3002 var split_it = mem.splitBackwardsScalar(u8, arg, ':'); 3003 const version_arg = split_it.first(); 3004 version = std.SemanticVersion.parse(version_arg) catch |err| { 3005 fatal("unable to parse /version {q}: {t}", .{ arg, err }); 3006 }; 3007 have_version = true; 3008 } else if (mem.eql(u8, arg, "-V")) { 3009 warn("ignoring request for supported emulations: unimplemented", .{}); 3010 } else if (mem.eql(u8, arg, "-v")) { 3011 try Io.File.stdout().writeStreamingAll(io, "zig ld " ++ build_options.version ++ "\n"); 3012 } else if (mem.eql(u8, arg, "--version")) { 3013 try Io.File.stdout().writeStreamingAll(io, "zig ld " ++ build_options.version ++ "\n"); 3014 process.exit(0); 3015 } else { 3016 fatal("unsupported linker arg: {s}", .{arg}); 3017 } 3018 } 3019 3020 // Parse preprocessor args. 3021 var preprocessor_args_it = ArgsIterator{ 3022 .args = preprocessor_args.items, 3023 }; 3024 while (preprocessor_args_it.next()) |arg| { 3025 if (mem.eql(u8, arg, "-MD") or mem.eql(u8, arg, "-MMD") or mem.eql(u8, arg, "-MT")) { 3026 disable_c_depfile = true; 3027 const cc_arg = try arena.print("-Wp,{s},{s}", .{ arg, preprocessor_args_it.nextOrFatal() }); 3028 try cc_argv.append(arena, cc_arg); 3029 } else { 3030 fatal("unsupported preprocessor arg: {s}", .{arg}); 3031 } 3032 } 3033 3034 if (mod_opts.sanitize_c) |wsc| { 3035 if (wsc != .off and mod_opts.optimize_mode == .fast) { 3036 mod_opts.optimize_mode = .safe; 3037 } 3038 } 3039 3040 // precompiled header syntax: "zig cc -x c-header test.h -o test.pch" 3041 const emit_pch = if (file_ext) |fe| switch (fe) { 3042 .h, .hpp, .hm, .hmm => c_out_mode == null, 3043 else => false, 3044 } else false; 3045 if (emit_pch) c_out_mode = .preprocessor; 3046 3047 switch (c_out_mode orelse .link) { 3048 .link => { 3049 create_module.opts.output_mode = if (is_shared_lib) .Lib else .Exe; 3050 if (emit_bin != .no) { 3051 emit_bin = if (out_path) |p| .{ .yes = p } else .yes_a_out; 3052 } 3053 if (emit_llvm) { 3054 fatal("-emit-llvm cannot be used when linking", .{}); 3055 } 3056 }, 3057 .object => { 3058 create_module.opts.output_mode = .Obj; 3059 if (emit_llvm) { 3060 emit_bin = .no; 3061 if (out_path) |p| { 3062 emit_llvm_bc = .{ .yes = p }; 3063 } else { 3064 emit_llvm_bc = .yes_default_path; 3065 } 3066 } else { 3067 if (out_path) |p| { 3068 emit_bin = .{ .yes = p }; 3069 } else { 3070 emit_bin = .yes_default_path; 3071 } 3072 } 3073 }, 3074 .assembly => { 3075 create_module.opts.output_mode = .Obj; 3076 emit_bin = .no; 3077 if (emit_llvm) { 3078 if (out_path) |p| { 3079 emit_llvm_ir = .{ .yes = p }; 3080 } else { 3081 emit_llvm_ir = .yes_default_path; 3082 } 3083 } else { 3084 if (out_path) |p| { 3085 emit_asm = .{ .yes = p }; 3086 } else { 3087 emit_asm = .yes_default_path; 3088 } 3089 } 3090 }, 3091 .preprocessor => { 3092 create_module.opts.output_mode = .Obj; 3093 // An error message is generated when there is more than 1 C source file. 3094 if (create_module.c_source_files.items.len != 1) { 3095 // For example `zig cc` and no args should print the "no input files" message. 3096 return process.exit(try clangMain(arena, all_args)); 3097 } 3098 if (emit_pch) { 3099 emit_bin = if (out_path) |p| .{ .yes = p } else .yes_default_path; 3100 clang_preprocessor_mode = .pch; 3101 } else { 3102 // If the output path is "-" (stdout), then we need to emit the preprocessed output to stdout 3103 // like "clang -E main.c -o -" does. 3104 if (out_path != null and !mem.eql(u8, out_path.?, "-")) { 3105 emit_bin = .{ .yes = out_path.? }; 3106 clang_preprocessor_mode = .yes; 3107 } else { 3108 emit_bin = .no; 3109 clang_preprocessor_mode = .stdout; 3110 } 3111 } 3112 }, 3113 .version => { 3114 // We can't allow control flow to reach the simpler logic 3115 // below because the -target argument has to be lowered to 3116 // clang syntax in Compilation. 3117 create_module.opts.output_mode = .Obj; 3118 clang_preprocessor_mode = .version; 3119 if (create_module.c_source_files.items.len == 0) { 3120 try create_module.c_source_files.append(arena, .{ 3121 .owner = undefined, 3122 .src_path = "a.c", // dummy name 3123 .ext = .c, 3124 }); 3125 } 3126 }, 3127 } 3128 if (create_module.c_source_files.items.len == 0 and 3129 !anyObjectLinkInputs(create_module.cli_link_inputs.items) and 3130 root_src_file == null) 3131 { 3132 // For example `zig cc` and no args should print the "no input files" message. 3133 // There could be other reasons to punt to clang, for example, --help. 3134 return process.exit(try clangMain(arena, all_args)); 3135 } 3136 }, 3137 } 3138 3139 if (arg_mode == .zig_test_obj and !test_no_exec and listen == .none) { 3140 fatal("test-obj requires --test-no-exec", .{}); 3141 } 3142 3143 if (time_report and listen == .none) { 3144 fatal("--time-report requires --listen", .{}); 3145 } 3146 3147 if (arg_mode == .translate_c and create_module.c_source_files.items.len != 1) { 3148 fatal("translate-c expects exactly 1 source file (found {d})", .{create_module.c_source_files.items.len}); 3149 } 3150 3151 if (show_builtin and root_src_file == null) { 3152 // Without this, there will be no main module created and no zig 3153 // compilation unit, and therefore also no builtin.zig contents 3154 // created. 3155 root_src_file = "builtin.zig"; 3156 } 3157 3158 implicit_root_mod: { 3159 const src_path = b: { 3160 if (root_src_file) |src_path| { 3161 if (create_module.modules.count() != 0) { 3162 fatal("main module provided both by '-M{s}={s}{c}{s}' and by positional argument {q}", .{ 3163 create_module.modules.keys()[0], 3164 create_module.modules.values()[0].root_path, 3165 fs.path.sep, 3166 create_module.modules.values()[0].root_src_path, 3167 src_path, 3168 }); 3169 } 3170 create_module.opts.have_zcu = true; 3171 break :b src_path; 3172 } 3173 3174 if (create_module.modules.count() != 0) 3175 break :implicit_root_mod; 3176 3177 if (create_module.c_source_files.items.len >= 1) 3178 break :b create_module.c_source_files.items[0].src_path; 3179 3180 for (create_module.cli_link_inputs.items) |unresolved_link_input| switch (unresolved_link_input) { 3181 // Intentionally includes dynamic libraries provided by file path. 3182 .path_query => |pq| break :b pq.path.sub_path, 3183 else => continue, 3184 }; 3185 3186 if (emit_bin == .yes) 3187 break :b emit_bin.yes; 3188 3189 if (create_module.rc_source_files.items.len >= 1) 3190 break :b create_module.rc_source_files.items[0].src_path; 3191 3192 if (arg_mode == .run) 3193 fatal("`zig run` expects at least one positional argument", .{}); 3194 3195 fatal("expected a positional argument, -femit-bin=[path], --show-builtin, or --name [name]", .{}); 3196 3197 break :implicit_root_mod; 3198 }; 3199 3200 // See duplicate logic: ModCreationGlobalFlags 3201 if (mod_opts.single_threaded == false) 3202 create_module.opts.any_non_single_threaded = true; 3203 if (mod_opts.sanitize_thread == true) 3204 create_module.opts.any_sanitize_thread = true; 3205 if (mod_opts.sanitize_c) |sc| switch (sc) { 3206 .off => {}, 3207 .trap => if (create_module.opts.any_sanitize_c == .off) { 3208 create_module.opts.any_sanitize_c = .trap; 3209 }, 3210 .full => create_module.opts.any_sanitize_c = .full, 3211 }; 3212 if (mod_opts.fuzz == true) 3213 create_module.opts.any_fuzz = true; 3214 if (mod_opts.unwind_tables) |uwt| switch (uwt) { 3215 .none => {}, 3216 .sync, .async => create_module.opts.any_unwind_tables = true, 3217 }; 3218 if (mod_opts.strip == false) 3219 create_module.opts.any_non_stripped = true; 3220 if (mod_opts.error_tracing == true) 3221 create_module.opts.any_error_tracing = true; 3222 3223 const name = switch (arg_mode) { 3224 .zig_test => "test", 3225 .build, .cc, .cpp, .translate_c, .zig_test_obj, .run => fs.path.stem(fs.path.basename(src_path)), 3226 }; 3227 3228 try create_module.modules.put(arena, name, .{ 3229 .root_path = fs.path.dirname(src_path) orelse ".", 3230 .root_src_path = fs.path.basename(src_path), 3231 .cc_argv = try cc_argv.toOwnedSlice(arena), 3232 .inherited = mod_opts, 3233 .target_arch_os_abi = target_arch_os_abi, 3234 .target_mcpu = target_mcpu, 3235 .dynamic_linker = dynamic_linker, 3236 .deps = try deps.toOwnedSlice(arena), 3237 .resolved = null, 3238 .c_source_files_start = c_source_files_owner_index, 3239 .c_source_files_end = create_module.c_source_files.items.len, 3240 .rc_source_files_start = rc_source_files_owner_index, 3241 .rc_source_files_end = create_module.rc_source_files.items.len, 3242 }); 3243 cssan.reset(); 3244 mod_opts = .{}; 3245 target_arch_os_abi = null; 3246 target_mcpu = null; 3247 c_source_files_owner_index = create_module.c_source_files.items.len; 3248 rc_source_files_owner_index = create_module.rc_source_files.items.len; 3249 } 3250 3251 if (!create_module.opts.have_zcu and create_module.opts.is_test) { 3252 fatal("`zig test` expects a zig source file argument", .{}); 3253 } 3254 3255 if (c_source_files_owner_index != create_module.c_source_files.items.len) { 3256 fatal("C source file {q} has no parent module", .{ 3257 create_module.c_source_files.items[c_source_files_owner_index].src_path, 3258 }); 3259 } 3260 3261 if (rc_source_files_owner_index != create_module.rc_source_files.items.len) { 3262 fatal("resource file {q} has no parent module", .{ 3263 create_module.rc_source_files.items[rc_source_files_owner_index].src_path, 3264 }); 3265 } 3266 3267 const self_exe_path = switch (native_os) { 3268 .wasi => {}, 3269 else => process.executablePathAlloc(io, arena) catch |err| fatal("unable to find zig self exe path: {t}", .{err}), 3270 }; 3271 3272 const cwd_path = try std.zig.getResolvedCwd(io, arena); 3273 std.log.debug("cwd_path={s}", .{cwd_path}); 3274 3275 // This `init` calls `fatal` on error. 3276 var dirs: std.zig.Directories = .init(arena, io, .{ 3277 .override_zig_lib = override_lib_dir, 3278 .override_global_cache = override_global_cache_dir, 3279 .build_root = build_root_path, 3280 .local_cache_strat = s: { 3281 if (override_local_cache_dir) |p| break :s .{ .override = p }; 3282 break :s switch (arg_mode) { 3283 .run => .global, 3284 else => .search, 3285 }; 3286 }, 3287 .preopens = preopens, 3288 .self_exe_path = self_exe_path, 3289 .environ_map = environ_map, 3290 .cwd = cwd_path, 3291 }); 3292 defer dirs.deinit(io); 3293 3294 if (linker_optimization) |o| warn("ignoring deprecated linker optimization setting {q}", .{o}); 3295 3296 create_module.dirs = dirs; 3297 create_module.opts.emit_llvm_ir = emit_llvm_ir != .no; 3298 create_module.opts.emit_llvm_bc = emit_llvm_bc != .no; 3299 create_module.opts.emit_bin = emit_bin != .no; 3300 create_module.opts.any_c_source_files = create_module.c_source_files.items.len != 0; 3301 3302 const main_mod = try createModule(gpa, arena, io, &create_module, 0, null, color, environ_map); 3303 for (create_module.modules.keys(), create_module.modules.values()) |key, cli_mod| { 3304 if (cli_mod.resolved == null) 3305 fatal("module {q} declared but not used", .{key}); 3306 } 3307 3308 // When you're testing std, the main module is std, and we need to avoid duplicating the module. 3309 const main_mod_is_std = main_mod.root.root == .zig_lib and 3310 mem.eql(u8, main_mod.root.sub_path, "std") and 3311 mem.eql(u8, main_mod.root_src_path, "std.zig"); 3312 3313 const std_mod = m: { 3314 if (main_mod_is_std) break :m main_mod; 3315 if (create_module.modules.get("std")) |cli_mod| break :m cli_mod.resolved.?; 3316 break :m null; 3317 }; 3318 3319 const root_mod = switch (arg_mode) { 3320 .zig_test, .zig_test_obj => root_mod: { 3321 const test_mod = if (test_runner_path) |test_runner| test_mod: { 3322 const test_mod = try Module.create(arena, .{ 3323 .paths = .{ 3324 .root = try .fromUnresolved(arena, dirs, &.{fs.path.dirname(test_runner) orelse "."}), 3325 .root_src_path = fs.path.basename(test_runner), 3326 }, 3327 .fully_qualified_name = "root", 3328 .cc_argv = &.{}, 3329 .inherited = .{}, 3330 .global = create_module.resolved_options, 3331 .parent = main_mod, 3332 }); 3333 test_mod.deps = try main_mod.deps.clone(arena); 3334 break :test_mod test_mod; 3335 } else try Module.create(arena, .{ 3336 .paths = .{ 3337 .root = try .fromRoot(arena, dirs, .zig_lib, "compiler"), 3338 .root_src_path = "test_runner.zig", 3339 }, 3340 .fully_qualified_name = "root", 3341 .cc_argv = &.{}, 3342 .inherited = .{}, 3343 .global = create_module.resolved_options, 3344 .parent = main_mod, 3345 }); 3346 3347 break :root_mod test_mod; 3348 }, 3349 else => main_mod, 3350 }; 3351 3352 const target = &main_mod.resolved_target.result; 3353 3354 if (target.cpu.arch == .arc or target.cpu.arch.isNvptx()) { 3355 if (emit_bin != .no and create_module.resolved_options.use_llvm) { 3356 fatal("cannot emit {s} binary with the LLVM backend; only '-femit-asm' is supported", .{ 3357 @tagName(target.cpu.arch), 3358 }); 3359 } 3360 } 3361 3362 if (target.os.tag == .windows and major_subsystem_version == null and minor_subsystem_version == null) { 3363 major_subsystem_version, minor_subsystem_version = switch (target.os.version_range.windows.min) { 3364 .nt4 => .{ 4, 0 }, 3365 .win2k => .{ 5, 0 }, 3366 .xp => if (target.cpu.arch == .x86_64) .{ 5, 2 } else .{ 5, 1 }, 3367 .ws2003 => .{ 5, 2 }, 3368 else => .{ null, null }, 3369 }; 3370 } 3371 3372 if (target.ofmt != .coff) { 3373 if (manifest_file != null) { 3374 fatal("manifest file is not allowed unless the target object format is coff (Windows/UEFI)", .{}); 3375 } 3376 if (create_module.rc_source_files.items.len != 0) { 3377 fatal("rc files are not allowed unless the target object format is coff (Windows/UEFI)", .{}); 3378 } 3379 if (contains_res_file) { 3380 fatal("res files are not allowed unless the target object format is coff (Windows/UEFI)", .{}); 3381 } 3382 } 3383 3384 var resolved_frameworks = std.array_list.Managed(Compilation.Framework).init(arena); 3385 3386 if (create_module.frameworks.keys().len > 0) { 3387 var test_path = std.array_list.Managed(u8).init(gpa); 3388 defer test_path.deinit(); 3389 3390 var checked_paths = std.array_list.Managed(u8).init(gpa); 3391 defer checked_paths.deinit(); 3392 3393 var failed_frameworks = std.array_list.Managed(struct { 3394 name: []const u8, 3395 checked_paths: []const u8, 3396 }).init(arena); 3397 3398 framework: for (create_module.frameworks.keys(), create_module.frameworks.values()) |framework_name, info| { 3399 checked_paths.clearRetainingCapacity(); 3400 3401 for (create_module.framework_dirs.items) |framework_dir_path| { 3402 if (try accessFrameworkPath( 3403 io, 3404 &test_path, 3405 &checked_paths, 3406 framework_dir_path, 3407 framework_name, 3408 )) { 3409 const path = Path.initCwd(try arena.dupe(u8, test_path.items)); 3410 try resolved_frameworks.append(.{ 3411 .needed = info.needed, 3412 .weak = info.weak, 3413 .path = path, 3414 }); 3415 continue :framework; 3416 } 3417 } 3418 3419 try failed_frameworks.append(.{ 3420 .name = framework_name, 3421 .checked_paths = try arena.dupe(u8, checked_paths.items), 3422 }); 3423 } 3424 3425 if (failed_frameworks.items.len > 0) { 3426 for (failed_frameworks.items) |f| { 3427 const searched_paths = if (f.checked_paths.len == 0) " none" else f.checked_paths; 3428 std.log.err("unable to find framework {q}. searched paths: {s}", .{ 3429 f.name, searched_paths, 3430 }); 3431 } 3432 process.exit(1); 3433 } 3434 } 3435 // After this point, resolved_frameworks is used instead of frameworks. 3436 3437 if (create_module.resolved_options.output_mode == .Obj and target.ofmt == .coff) { 3438 const total_obj_count = create_module.c_source_files.items.len + 3439 @intFromBool(root_src_file != null) + 3440 create_module.rc_source_files.items.len + 3441 link.countObjectInputs(create_module.link_inputs.items); 3442 if (total_obj_count > 1) { 3443 fatal("{s} does not support linking multiple objects into one", .{@tagName(target.ofmt)}); 3444 } 3445 } 3446 3447 var cleanup_emit_bin_dir: ?Io.Dir = null; 3448 defer if (cleanup_emit_bin_dir) |*dir| dir.close(io); 3449 3450 // For `zig run` and `zig test`, we don't want to put the binary in the cwd by default. So, if 3451 // the binary is requested with no explicit path (as is the default), we emit to the cache. 3452 const output_to_cache: ?Emit.OutputToCacheReason = switch (listen) { 3453 .stdio, .ip4 => .listen, 3454 .none => if (arg_mode == .run and emit_bin == .yes_default_path) 3455 .@"zig run" 3456 else if (arg_mode == .zig_test and emit_bin == .yes_default_path) 3457 .@"zig test" 3458 else 3459 null, 3460 }; 3461 const optional_version = if (have_version) version else null; 3462 3463 const root_name = if (provided_name) |n| n else main_mod.fully_qualified_name; 3464 3465 const resolved_soname: ?[]const u8 = switch (soname) { 3466 .yes => |explicit| explicit, 3467 .no => null, 3468 .yes_default_value => if (create_module.resolved_options.output_mode == .Lib and 3469 create_module.resolved_options.link_mode == .dynamic and target.ofmt == .elf) 3470 if (have_version) 3471 try arena.print("lib{s}.so.{d}", .{ root_name, version.major }) 3472 else 3473 try arena.print("lib{s}.so", .{root_name}) 3474 else 3475 null, 3476 }; 3477 3478 const emit_bin_resolved: Compilation.CreateOptions.Emit = switch (emit_bin) { 3479 .no => .no, 3480 .yes_default_path => emit: { 3481 if (output_to_cache != null) break :emit .yes_cache; 3482 const name = switch (clang_preprocessor_mode) { 3483 .pch => try arena.print("{s}.pch", .{root_name}), 3484 else => try std.zig.binNameAlloc(arena, .{ 3485 .root_name = root_name, 3486 .cpu_arch = target.cpu.arch, 3487 .os_tag = target.os.tag, 3488 .ofmt = target.ofmt, 3489 .abi = target.abi, 3490 .output_mode = create_module.resolved_options.output_mode, 3491 .link_mode = create_module.resolved_options.link_mode, 3492 .version = optional_version, 3493 }), 3494 }; 3495 break :emit .{ .yes_path = name }; 3496 }, 3497 .yes => |path| if (output_to_cache != null) { 3498 assert(output_to_cache == .listen); // there was an explicit bin path 3499 fatal("--listen incompatible with explicit output path {q}", .{path}); 3500 } else emit: { 3501 // If there's a dirname, check that dir exists. This will give a more descriptive error than `Compilation` otherwise would. 3502 if (fs.path.dirname(path)) |dir_path| { 3503 var dir = Io.Dir.cwd().openDir(io, dir_path, .{}) catch |err| { 3504 fatal("unable to open output directory {q}: {t}", .{ dir_path, err }); 3505 }; 3506 dir.close(io); 3507 } 3508 break :emit .{ .yes_path = path }; 3509 }, 3510 .yes_a_out => emit: { 3511 assert(output_to_cache == null); 3512 break :emit .{ .yes_path = switch (target.ofmt) { 3513 .coff => "a.exe", 3514 else => "a.out", 3515 } }; 3516 }, 3517 }; 3518 3519 const default_h_basename = try arena.print("{s}.h", .{root_name}); 3520 const emit_h_resolved = emit_h.resolve(io, default_h_basename, output_to_cache); 3521 3522 const default_asm_basename = try arena.print("{s}.s", .{root_name}); 3523 const emit_asm_resolved = emit_asm.resolve(io, default_asm_basename, output_to_cache); 3524 3525 const default_llvm_ir_basename = try arena.print("{s}.ll", .{root_name}); 3526 const emit_llvm_ir_resolved = emit_llvm_ir.resolve(io, default_llvm_ir_basename, output_to_cache); 3527 3528 const default_llvm_bc_basename = try arena.print("{s}.bc", .{root_name}); 3529 const emit_llvm_bc_resolved = emit_llvm_bc.resolve(io, default_llvm_bc_basename, output_to_cache); 3530 3531 const emit_docs_resolved = emit_docs.resolve(io, "docs", output_to_cache); 3532 3533 const is_exe_or_dyn_lib = switch (create_module.resolved_options.output_mode) { 3534 .Obj => false, 3535 .Lib => create_module.resolved_options.link_mode == .dynamic, 3536 .Exe => true, 3537 }; 3538 // Note that cmake when targeting Windows will try to execute 3539 // zig cc to make an executable and output an implib too. 3540 const implib_eligible = is_exe_or_dyn_lib and 3541 emit_bin_resolved != .no and target.os.tag == .windows; 3542 if (!implib_eligible) { 3543 if (!emit_implib_arg_provided) { 3544 emit_implib = .no; 3545 } else if (emit_implib != .no) { 3546 fatal("the argument -femit-implib is allowed only when building a Windows DLL", .{}); 3547 } 3548 } 3549 const default_implib_basename = try arena.print("{s}.lib", .{root_name}); 3550 const emit_implib_resolved: Compilation.CreateOptions.Emit = switch (emit_implib) { 3551 .no => .no, 3552 .yes => emit_implib.resolve(io, default_implib_basename, output_to_cache), 3553 .yes_default_path => emit: { 3554 if (output_to_cache != null) break :emit .yes_cache; 3555 const p = try fs.path.join(arena, &.{ 3556 fs.path.dirname(emit_bin_resolved.yes_path) orelse ".", 3557 default_implib_basename, 3558 }); 3559 break :emit .{ .yes_path = p }; 3560 }, 3561 }; 3562 3563 const thread_limit = @min( 3564 @max(n_jobs orelse std.Thread.getCpuCount() catch 1, 1), 3565 std.math.maxInt(Zcu.PerThread.IdBacking), 3566 ); 3567 try setThreadLimit(arena, thread_limit); 3568 3569 for (create_module.c_source_files.items) |*src| { 3570 dev.check(.c_compiler); 3571 if (!mem.eql(u8, src.src_path, "-")) continue; 3572 3573 const ext = src.ext orelse 3574 fatal("-E or -x is required when reading from a non-regular file", .{}); 3575 3576 // "-" is stdin. Dump it to a real file. 3577 const sep = fs.path.sep_str; 3578 const dump_path = try arena.print("tmp" ++ sep ++ "{x}-dump-stdin{s}", .{ 3579 randInt(io, u64), ext.canonicalName(target), 3580 }); 3581 try dirs.local_cache.handle.createDirPath(io, "tmp"); 3582 3583 // Note that in one of the happy paths, execve() is used to switch to 3584 // clang in which case any cleanup logic that exists for this temporary 3585 // file will not run and this temp file will be leaked. The filename 3586 // will be a hash of its contents — so multiple invocations of 3587 // `zig cc -` will result in the same temp file name. 3588 var f = try dirs.local_cache.handle.createFile(io, dump_path, .{}); 3589 defer f.close(io); 3590 3591 // Re-using the hasher from Cache, since the functional requirements 3592 // for the hashing algorithm here and in the cache are the same. 3593 // We are providing our own cache key, because this file has nothing 3594 // to do with the cache manifest. 3595 var file_writer = f.writer(io, &.{}); 3596 var buffer: [1000]u8 = undefined; 3597 var hasher = file_writer.interface.hashed(Cache.Hasher.init("0123456789abcdef"), &buffer); 3598 var stdin_reader = Io.File.stdin().readerStreaming(io, &.{}); 3599 _ = hasher.writer.sendFileAll(&stdin_reader, .unlimited) catch |err| switch (err) { 3600 error.WriteFailed => fatal("failed to write {s}: {t}", .{ dump_path, file_writer.err.? }), 3601 else => fatal("failed to pipe stdin to {s}: {t}", .{ dump_path, err }), 3602 }; 3603 try hasher.writer.flush(); 3604 3605 const bin_digest: Cache.BinDigest = hasher.hasher.finalResult(); 3606 3607 const sub_path = try arena.print("tmp" ++ sep ++ "{x}-stdin{s}", .{ 3608 &bin_digest, ext.canonicalName(target), 3609 }); 3610 try dirs.local_cache.handle.rename(dump_path, dirs.local_cache.handle, sub_path, io); 3611 3612 // Convert `sub_path` to be relative to current working directory. 3613 src.src_path = try dirs.local_cache.join(arena, &.{sub_path}); 3614 } 3615 3616 if (build_options.have_llvm and emit_asm_resolved != .no) { 3617 // LLVM has no way to set this non-globally. 3618 const argv = [_][*:0]const u8{ "zig (LLVM option parsing)", "--x86-asm-syntax=intel" }; 3619 @import("codegen/llvm/bindings.zig").ParseCommandLineOptions(argv.len, &argv); 3620 } 3621 3622 const clang_passthrough_mode = switch (arg_mode) { 3623 .cc, .cpp, .translate_c => true, 3624 else => false, 3625 }; 3626 3627 const incremental = create_module.resolved_options.incremental; 3628 if (debug_incremental and !incremental) { 3629 fatal("--debug-incremental requires -fincremental", .{}); 3630 } 3631 3632 const cache_mode: Compilation.CacheMode = b: { 3633 // Once incremental compilation is the default, we'll want some smarter logic here, 3634 // considering things like the backend in use and whether there's a ZCU. 3635 if (output_to_cache == null) break :b .none; 3636 if (incremental) break :b .incremental; 3637 break :b .whole; 3638 }; 3639 3640 var file_system_inputs: std.ArrayList(u8) = .empty; 3641 defer file_system_inputs.deinit(gpa); 3642 3643 // Deduplicate rpath entries 3644 var rpath_dedup = std.array_hash_map.String(void){}; 3645 for (create_module.rpath_list.items) |rpath| { 3646 try rpath_dedup.put(arena, rpath, {}); 3647 } 3648 create_module.rpath_list.clearRetainingCapacity(); 3649 try create_module.rpath_list.appendSlice(arena, rpath_dedup.keys()); 3650 3651 var create_diag: Compilation.CreateDiagnostic = undefined; 3652 const comp = Compilation.create(gpa, arena, io, &create_diag, .{ 3653 .dirs = dirs, 3654 .thread_limit = thread_limit, 3655 .self_exe_path = switch (native_os) { 3656 .wasi => null, 3657 else => self_exe_path, 3658 }, 3659 .config = create_module.resolved_options, 3660 .root_name = root_name, 3661 .sysroot = create_module.sysroot, 3662 .main_mod = main_mod, 3663 .root_mod = root_mod, 3664 .std_mod = std_mod, 3665 .emit_bin = emit_bin_resolved, 3666 .emit_h = emit_h_resolved, 3667 .emit_asm = emit_asm_resolved, 3668 .emit_llvm_ir = emit_llvm_ir_resolved, 3669 .emit_llvm_bc = emit_llvm_bc_resolved, 3670 .emit_docs = emit_docs_resolved, 3671 .emit_implib = emit_implib_resolved, 3672 .lib_directories = create_module.lib_directories.items, 3673 .rpath_list = create_module.rpath_list.items, 3674 .symbol_wrap_set = symbol_wrap_set, 3675 .c_source_files = create_module.c_source_files.items, 3676 .rc_source_files = create_module.rc_source_files.items, 3677 .manifest_file = manifest_file, 3678 .rc_includes = rc_includes, 3679 .mingw_unicode_entry_point = mingw_unicode_entry_point, 3680 .link_inputs = create_module.link_inputs.items, 3681 .framework_dirs = create_module.framework_dirs.items, 3682 .frameworks = resolved_frameworks.items, 3683 .windows_lib_names = create_module.windows_libs.keys(), 3684 .want_compiler_rt = if (zig_cc_explicitly_link_compiler_rt) true else want_compiler_rt, 3685 .want_ubsan_rt = want_ubsan_rt, 3686 .hash_style = hash_style, 3687 .linker_script = if (linker_script) |p| .initCwd(p) else null, 3688 .version_script = if (version_script) |p| .initCwd(p) else null, 3689 .linker_allow_undefined_version = linker_allow_undefined_version, 3690 .linker_enable_new_dtags = linker_enable_new_dtags, 3691 .disable_c_depfile = disable_c_depfile, 3692 .soname = resolved_soname, 3693 .linker_sort_section = linker_sort_section, 3694 .linker_gc_sections = linker_gc_sections, 3695 .linker_repro = linker_repro, 3696 .linker_allow_shlib_undefined = linker_allow_shlib_undefined, 3697 .linker_bind_global_refs_locally = linker_bind_global_refs_locally, 3698 .linker_import_symbols = linker_import_symbols, 3699 .linker_import_table = linker_import_table, 3700 .linker_export_table = linker_export_table, 3701 .linker_growable_table = linker_growable_table, 3702 .linker_initial_memory = linker_initial_memory, 3703 .linker_max_memory = linker_max_memory, 3704 .linker_print_gc_sections = linker_print_gc_sections, 3705 .linker_print_icf_sections = linker_print_icf_sections, 3706 .linker_print_map = linker_print_map, 3707 .linker_nmagic = linker_nmagic, 3708 .linker_fatal_warnings = linker_fatal_warnings, 3709 .llvm_opt_bisect_limit = llvm_opt_bisect_limit, 3710 .linker_global_base = linker_global_base, 3711 .linker_export_symbol_names = linker_export_symbol_names.items, 3712 .linker_z_nocopyreloc = linker_z_nocopyreloc, 3713 .linker_z_nodelete = linker_z_nodelete, 3714 .linker_z_notext = linker_z_notext, 3715 .linker_z_defs = linker_z_defs, 3716 .linker_z_origin = linker_z_origin, 3717 .linker_z_now = linker_z_now, 3718 .linker_z_relro = linker_z_relro, 3719 .linker_z_common_page_size = linker_z_common_page_size, 3720 .linker_z_max_page_size = linker_z_max_page_size, 3721 .linker_tsaware = linker_tsaware, 3722 .linker_nxcompat = linker_nxcompat, 3723 .linker_dynamicbase = linker_dynamicbase, 3724 .linker_compress_debug_sections = linker_compress_debug_sections, 3725 .linker_module_definition_file = linker_module_definition_file, 3726 .major_subsystem_version = major_subsystem_version, 3727 .minor_subsystem_version = minor_subsystem_version, 3728 .link_eh_frame_hdr = link_eh_frame_hdr, 3729 .link_emit_relocs = link_emit_relocs, 3730 .entry = entry, 3731 .force_undefined_symbols = force_undefined_symbols, 3732 .stack_size = stack_size, 3733 .image_base = image_base, 3734 .function_sections = function_sections, 3735 .data_sections = data_sections, 3736 .clang_passthrough_mode = clang_passthrough_mode, 3737 .clang_preprocessor_mode = clang_preprocessor_mode, 3738 .version = optional_version, 3739 .compatibility_version = compatibility_version, 3740 .libc_installation = if (create_module.libc_installation) |*lci| lci else null, 3741 .verbose_cc = verbose_cc, 3742 .verbose_link = verbose_link, 3743 .verbose_air = verbose_air, 3744 .verbose_intern_pool = verbose_intern_pool, 3745 .verbose_generic_instances = verbose_generic_instances, 3746 .verbose_llvm_ir = verbose_llvm_ir, 3747 .verbose_llvm_bc = verbose_llvm_bc, 3748 .link_depfile = link_depfile, 3749 .verbose_llvm_cpu_features = verbose_llvm_cpu_features, 3750 .time_report = time_report, 3751 .stack_report = stack_report, 3752 .build_id = build_id, 3753 .test_filters = test_filters.items, 3754 .test_runner_path = test_runner_path, 3755 .cache_mode = cache_mode, 3756 .subsystem = subsystem, 3757 .debug_compile_errors = debug_compile_errors, 3758 .debug_incremental = debug_incremental, 3759 .enable_link_snapshots = enable_link_snapshots, 3760 .install_name = install_name, 3761 .entitlements = if (entitlements) |p| .initCwd(p) else null, 3762 .pagezero_size = pagezero_size, 3763 .headerpad_size = headerpad_size, 3764 .headerpad_max_install_names = headerpad_max_install_names, 3765 .dead_strip_dylibs = dead_strip_dylibs, 3766 .force_load_objc = force_load_objc, 3767 .discard_local_symbols = discard_local_symbols, 3768 .reference_trace = reference_trace, 3769 .pdb_out_path = pdb_out_path, 3770 .error_limit = error_limit, 3771 .native_system_include_paths = create_module.native_system_include_paths, 3772 // Any leftover C compilation args (such as -I) apply globally rather 3773 // than to any particular module. This feature can greatly reduce CLI 3774 // noise when --search-prefix and -M are combined. 3775 .global_cc_argv = try cc_argv.toOwnedSlice(arena), 3776 .file_system_inputs = &file_system_inputs, 3777 .debug_compiler_runtime_libs = debug_compiler_runtime_libs, 3778 .environ_map = environ_map, 3779 }) catch |err| switch (err) { 3780 error.CreateFail => switch (create_diag) { 3781 .cross_libc_unavailable => { 3782 // We can emit a more informative error for this. 3783 const triple_name = try target.zigTriple(arena); 3784 std.log.err("unable to provide libc for target {q}", .{triple_name}); 3785 3786 for (std.zig.target.available_libcs) |t| { 3787 if (t.arch == target.cpu.arch and t.os == target.os.tag) { 3788 // If there's a `glibc_min`, there's also an `os_ver`. 3789 if (t.glibc_min) |glibc_min| { 3790 std.log.info("zig can provide libc for related target {t}-{t}.{f}-{t}.{d}.{d}", .{ 3791 t.arch, t.os, t.os_ver.?, t.abi, glibc_min.major, glibc_min.minor, 3792 }); 3793 } else if (t.os_ver) |os_ver| { 3794 std.log.info("zig can provide libc for related target {t}-{t}.{f}-{t}", .{ 3795 t.arch, t.os, os_ver, t.abi, 3796 }); 3797 } else { 3798 std.log.info("zig can provide libc for related target {t}-{t}-{t}", .{ 3799 t.arch, t.os, t.abi, 3800 }); 3801 } 3802 } 3803 } 3804 process.exit(1); 3805 }, 3806 else => fatal("{f}", .{create_diag}), 3807 }, 3808 else => fatal("failed to create compilation: {t}", .{err}), 3809 }; 3810 var comp_destroyed = false; 3811 defer if (!comp_destroyed) comp.destroy(); 3812 3813 if (show_builtin) { 3814 const builtin_opts = comp.root_mod.getBuiltinOptions(comp.config); 3815 const source = try builtin_opts.generate(arena); 3816 return Io.File.stdout().writeStreamingAll(io, source); 3817 } 3818 switch (listen) { 3819 .none => {}, 3820 .stdio => { 3821 var stdin_reader = Io.File.stdin().reader(io, &stdin_buffer); 3822 var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer); 3823 try serve( 3824 comp, 3825 &stdin_reader.interface, 3826 &stdout_writer.interface, 3827 test_exec_args.items, 3828 self_exe_path, 3829 arg_mode, 3830 all_args, 3831 runtime_args_start, 3832 environ_map, 3833 ); 3834 return cleanExit(io); 3835 }, 3836 .ip4 => |ip4_addr| { 3837 const addr: Io.net.IpAddress = .{ .ip4 = ip4_addr }; 3838 3839 var server = try addr.listen(io, .{ 3840 .reuse_address = true, 3841 }); 3842 defer server.deinit(io); 3843 3844 var stream = try server.accept(io); 3845 defer stream.close(io); 3846 3847 var input = stream.reader(io, &stdin_buffer); 3848 var output = stream.writer(io, &stdout_buffer); 3849 3850 try serve( 3851 comp, 3852 &input.interface, 3853 &output.interface, 3854 test_exec_args.items, 3855 self_exe_path, 3856 arg_mode, 3857 all_args, 3858 runtime_args_start, 3859 environ_map, 3860 ); 3861 return cleanExit(io); 3862 }, 3863 } 3864 3865 { 3866 const root_prog_node = std.Progress.start(io, .{ 3867 .disable_printing = (color == .off), 3868 }); 3869 defer root_prog_node.end(); 3870 3871 if (arg_mode == .translate_c) { 3872 return cmdTranslateC(comp, arena, null, null, root_prog_node, environ_map); 3873 } 3874 3875 updateModule(comp, color, root_prog_node) catch |err| switch (err) { 3876 error.CompileErrorsReported => { 3877 assert(listen == .none); 3878 saveState(comp, incremental); 3879 process.exit(1); 3880 }, 3881 else => |e| return e, 3882 }; 3883 } 3884 try comp.makeBinFileExecutable(); 3885 saveState(comp, incremental); 3886 3887 if (switch (arg_mode) { 3888 .run => true, 3889 .zig_test => !test_no_exec, 3890 else => false, 3891 }) { 3892 dev.checkAny(&.{ .run_command, .test_command }); 3893 3894 const self_exe_path_or_argv0 = switch (native_os) { 3895 .wasi => all_args[0], // Will error because of `!process.can_spawn` 3896 else => self_exe_path, 3897 }; 3898 3899 if (test_exec_args.items.len == 0 and target.ofmt == .c and emit_bin_resolved != .no) { 3900 // Default to using `zig run` to execute the produced .c code from `zig test`. 3901 try test_exec_args.appendSlice(arena, &.{ self_exe_path_or_argv0, "run" }); 3902 // Skip passing `-ofmt`, we want the default for the target, not `.c` anymore. 3903 3904 var prev_has_cflags = false; 3905 var prev_has_rcflags = false; 3906 { 3907 if (dirs.zig_lib.path) |zig_lib_path| { 3908 try test_exec_args.appendSlice(arena, &.{ "-cflags", "-I", zig_lib_path, "--" }); 3909 prev_has_cflags = true; 3910 } 3911 const emit_ext: Compilation.FileExt = .c; 3912 const need_lang = if (comp.emit_bin) |comp_emit_bin| Compilation.classifyFileExt(comp_emit_bin) != emit_ext else true; 3913 if (need_lang) try test_exec_args.appendSlice(arena, &.{ "-x", emit_ext.toLang() }); 3914 try test_exec_args.append(arena, null); 3915 if (need_lang) try test_exec_args.appendSlice(arena, &.{ "-x", "none" }); 3916 } 3917 for (create_module.modules.keys(), create_module.modules.values()) |mod_name, mod| { 3918 for (create_module.c_source_files.items[mod.c_source_files_start..mod.c_source_files_end]) |c_source_file| { 3919 const cflags_len = c_source_file.extra_flags.len + c_source_file.cache_exempt_flags.len; 3920 if (prev_has_cflags or cflags_len > 0) { 3921 try test_exec_args.ensureUnusedCapacity(arena, 1 + cflags_len + 1); 3922 test_exec_args.appendAssumeCapacity("-cflags"); 3923 for (c_source_file.extra_flags) |extra_flag| test_exec_args.appendAssumeCapacity(extra_flag); 3924 for (c_source_file.cache_exempt_flags) |cache_exempt_flag| test_exec_args.appendAssumeCapacity(cache_exempt_flag); 3925 test_exec_args.appendAssumeCapacity("--"); 3926 } 3927 prev_has_cflags = cflags_len > 0; 3928 if (c_source_file.ext) |ext| try test_exec_args.appendSlice(arena, &.{ "-x", ext.toLang() }); 3929 try test_exec_args.append(arena, c_source_file.src_path); 3930 if (c_source_file.ext) |_| try test_exec_args.appendSlice(arena, &.{ "-x", "none" }); 3931 } 3932 for (create_module.rc_source_files.items[mod.rc_source_files_start..mod.rc_source_files_end]) |rc_source_file| { 3933 const rcflags_len = rc_source_file.extra_flags.len; 3934 if (prev_has_rcflags or rcflags_len > 0) { 3935 try test_exec_args.ensureUnusedCapacity(arena, 1 + rcflags_len + 1); 3936 test_exec_args.appendAssumeCapacity("-rcflags"); 3937 for (rc_source_file.extra_flags) |extra_flag| test_exec_args.appendAssumeCapacity(extra_flag); 3938 test_exec_args.appendAssumeCapacity("--"); 3939 } 3940 prev_has_rcflags = rcflags_len > 0; 3941 try test_exec_args.append(arena, rc_source_file.src_path); 3942 } 3943 if (mod.target_arch_os_abi) |triple| try test_exec_args.appendSlice(arena, &.{ "-target", triple }); 3944 if (mod.target_mcpu) |mcpu| try test_exec_args.appendSlice(arena, &.{ "-mcpu", mcpu }); 3945 if (mod.dynamic_linker) |dl| if (dl.len > 0) 3946 try test_exec_args.appendSlice(arena, &.{ "--dynamic-linker", dl }) 3947 else 3948 try test_exec_args.append(arena, "--no-dynamic-linker"); 3949 try test_exec_args.ensureUnusedCapacity(arena, mod.cc_argv.len); 3950 for (mod.cc_argv) |cc_arg| test_exec_args.appendAssumeCapacity(cc_arg); 3951 for (mod.deps) |dep| try test_exec_args.appendSlice(arena, &.{ 3952 "--dep", 3953 if (std.mem.eql(u8, dep.key, dep.value)) dep.value else try arena.print("{s}={s}", .{ dep.key, dep.value }), 3954 }); 3955 try test_exec_args.append(arena, try arena.print("-M{s}", .{mod_name})); 3956 } 3957 3958 try test_exec_args.ensureUnusedCapacity(arena, comp.global_cc_argv.len); 3959 for (comp.global_cc_argv) |global_cc_arg| test_exec_args.appendAssumeCapacity(global_cc_arg); 3960 if (create_module.resolved_options.link_libcpp) try test_exec_args.append(arena, "-lc++"); 3961 if (create_module.resolved_options.link_libc) { 3962 try test_exec_args.append(arena, "-lc"); 3963 } else if (target.os.tag == .windows) { 3964 try test_exec_args.appendSlice(arena, &.{ 3965 "--subsystem", "console", 3966 "-lkernel32", "-lntdll", 3967 }); 3968 } 3969 3970 try test_exec_args.ensureUnusedCapacity(arena, 2 * log_scopes.items.len + @intFromBool(verbose_link) + @intFromBool(verbose_cc)); 3971 for (log_scopes.items) |log_scope| test_exec_args.appendSliceAssumeCapacity(&.{ "--debug-log", log_scope }); 3972 if (verbose_link) test_exec_args.appendAssumeCapacity("--verbose-link"); 3973 if (verbose_cc) test_exec_args.appendAssumeCapacity("--verbose-cc"); 3974 } 3975 3976 try runOrTest( 3977 comp, 3978 gpa, 3979 arena, 3980 io, 3981 test_exec_args.items, 3982 self_exe_path_or_argv0, 3983 arg_mode, 3984 target, 3985 &comp_destroyed, 3986 all_args, 3987 runtime_args_start, 3988 create_module.resolved_options.link_libc, 3989 test_execve, 3990 environ_map, 3991 ); 3992 } 3993 3994 // Skip resource deallocation in release builds; let the OS do it. 3995 return cleanExit(io); 3996 } 3997 3998 const CreateModule = struct { 3999 dirs: std.zig.Directories, 4000 modules: std.array_hash_map.String(CliModule), 4001 opts: Compilation.Config.Options, 4002 object_format: ?[]const u8, 4003 /// undefined until createModule() for the root module is called. 4004 resolved_options: Compilation.Config, 4005 4006 /// This one is used while collecting CLI options. The set of libs is used 4007 /// directly after computing the target and used to compute link_libc, 4008 /// link_libcpp, and then the libraries are filtered into 4009 /// `unresolved_link_inputs` and `windows_libs`. 4010 cli_link_inputs: std.ArrayList(link.UnresolvedInput), 4011 windows_libs: std.array_hash_map.String(void), 4012 /// The local variable `unresolved_link_inputs` is fed into library 4013 /// resolution, mutating the input array, and producing this data as 4014 /// output. Allocated with gpa. 4015 link_inputs: std.ArrayList(link.Input), 4016 4017 c_source_files: std.ArrayList(Compilation.CSourceFile), 4018 rc_source_files: std.ArrayList(Compilation.RcSourceFile), 4019 4020 /// e.g. -m3dnow or -mno-outline-atomics. They correspond to std.Target llvm cpu feature names. 4021 /// This array is populated by zig cc frontend and then has to be converted to zig-style 4022 /// CPU features. 4023 llvm_m_args: std.ArrayList([]const u8), 4024 sysroot: ?[]const u8, 4025 lib_directories: std.ArrayList(Directory), 4026 lib_dir_args: std.ArrayList([]const u8), 4027 libc_installation: ?LibCInstallation, 4028 want_native_include_dirs: bool, 4029 frameworks: std.array_hash_map.String(Framework), 4030 native_system_include_paths: []const []const u8, 4031 framework_dirs: std.ArrayList([]const u8), 4032 rpath_list: std.ArrayList([]const u8), 4033 each_lib_rpath: ?bool, 4034 libc_paths_file: ?[]const u8, 4035 }; 4036 4037 fn createModule( 4038 gpa: Allocator, 4039 arena: Allocator, 4040 io: Io, 4041 create_module: *CreateModule, 4042 index: usize, 4043 parent: ?*Module, 4044 color: std.zig.Color, 4045 environ_map: *process.Environ.Map, 4046 ) Allocator.Error!*Module { 4047 const cli_mod = &create_module.modules.values()[index]; 4048 if (cli_mod.resolved) |m| return m; 4049 4050 const name = create_module.modules.keys()[index]; 4051 4052 cli_mod.inherited.resolved_target = t: { 4053 // If the target is not overridden, use the parent's target. Of course, 4054 // if this is the root module then we need to proceed to resolve the 4055 // target. 4056 if (cli_mod.target_arch_os_abi == null and cli_mod.target_mcpu == null) { 4057 if (parent) |p| break :t p.resolved_target; 4058 } 4059 4060 var target_parse_options: std.Target.Query.ParseOptions = .{ 4061 .arch_os_abi = cli_mod.target_arch_os_abi orelse "native", 4062 .cpu_features = cli_mod.target_mcpu, 4063 .dynamic_linker = cli_mod.dynamic_linker, 4064 .object_format = create_module.object_format, 4065 }; 4066 4067 // Before passing the mcpu string in for parsing, we convert any -m flags that were 4068 // passed in via zig cc to zig-style. 4069 if (create_module.llvm_m_args.items.len != 0) { 4070 // If this returns null, we let it fall through to the case below which will 4071 // run the full parse function and do proper error handling. 4072 if (std.Target.Query.parseCpuArch(target_parse_options)) |cpu_arch| { 4073 var llvm_to_zig_name = std.StringHashMap([]const u8).init(gpa); 4074 defer llvm_to_zig_name.deinit(); 4075 4076 for (cpu_arch.allFeaturesList()) |feature| { 4077 const llvm_name = feature.llvm_name orelse continue; 4078 try llvm_to_zig_name.put(llvm_name, feature.name); 4079 } 4080 4081 var mcpu_buffer = std.array_list.Managed(u8).init(gpa); 4082 defer mcpu_buffer.deinit(); 4083 4084 try mcpu_buffer.appendSlice(cli_mod.target_mcpu orelse "baseline"); 4085 4086 for (create_module.llvm_m_args.items) |llvm_m_arg| { 4087 if (mem.cutPrefix(u8, llvm_m_arg, "mno-")) |llvm_name| { 4088 const zig_name = llvm_to_zig_name.get(llvm_name) orelse { 4089 fatal("target architecture {t} has no LLVM CPU feature named {q}", .{ 4090 cpu_arch, llvm_name, 4091 }); 4092 }; 4093 try mcpu_buffer.append('-'); 4094 try mcpu_buffer.appendSlice(zig_name); 4095 } else if (mem.cutPrefix(u8, llvm_m_arg, "m")) |llvm_name| { 4096 const zig_name = llvm_to_zig_name.get(llvm_name) orelse { 4097 fatal("target architecture {t} has no LLVM CPU feature named {q}", .{ 4098 cpu_arch, llvm_name, 4099 }); 4100 }; 4101 try mcpu_buffer.append('+'); 4102 try mcpu_buffer.appendSlice(zig_name); 4103 } else { 4104 unreachable; 4105 } 4106 } 4107 4108 const adjusted_target_mcpu = try arena.dupe(u8, mcpu_buffer.items); 4109 std.log.debug("adjusted target_mcpu: {s}", .{adjusted_target_mcpu}); 4110 target_parse_options.cpu_features = adjusted_target_mcpu; 4111 } 4112 } 4113 4114 const target_query = std.zig.parseTargetQueryOrReportFatalError(arena, target_parse_options); 4115 const target = std.zig.resolveTargetQueryOrFatal(io, target_query); 4116 break :t .{ 4117 .result = target, 4118 .is_native_os = target_query.isNativeOs(), 4119 .is_native_abi = target_query.isNativeAbi(), 4120 .is_explicit_dynamic_linker = target_query.dynamic_linker != null, 4121 }; 4122 }; 4123 4124 if (parent == null) { 4125 // This block is for initializing the fields of 4126 // `Compilation.Config.Options` that require knowledge of the 4127 // target (which was just now resolved for the root module above). 4128 const resolved_target = &cli_mod.inherited.resolved_target.?; 4129 create_module.opts.resolved_target = resolved_target.*; 4130 create_module.opts.root_optimize_mode = cli_mod.inherited.optimize_mode; 4131 create_module.opts.root_strip = cli_mod.inherited.strip; 4132 create_module.opts.root_error_tracing = cli_mod.inherited.error_tracing; 4133 const target = &resolved_target.result; 4134 4135 // First, remove libc, libc++, and compiler_rt libraries from the system libraries list. 4136 // We need to know whether the set of system libraries contains anything besides these 4137 // to decide whether to trigger native path detection logic. 4138 // Preserves linker input order. 4139 var unresolved_link_inputs: std.ArrayList(link.UnresolvedInput) = .empty; 4140 defer unresolved_link_inputs.deinit(gpa); 4141 try unresolved_link_inputs.ensureUnusedCapacity(gpa, create_module.cli_link_inputs.items.len); 4142 var any_name_queries_remaining = false; 4143 for (create_module.cli_link_inputs.items) |cli_link_input| switch (cli_link_input) { 4144 .name_query => |nq| { 4145 const lib_name = nq.name; 4146 4147 if (std.zig.target.isLibCLibName(target, lib_name)) { 4148 create_module.opts.link_libc = true; 4149 continue; 4150 } 4151 if (std.zig.target.isLibCxxLibName(target, lib_name)) { 4152 create_module.opts.link_libcpp = true; 4153 continue; 4154 } 4155 4156 switch (target_util.classifyCompilerRtLibName(lib_name)) { 4157 .none => {}, 4158 .only_libunwind, .both => { 4159 create_module.opts.link_libunwind = true; 4160 continue; 4161 }, 4162 .only_compiler_rt => continue, 4163 } 4164 4165 if (target.isMinGW()) { 4166 const exists = mingw.libExists(arena, io, target, create_module.dirs.zig_lib, lib_name) catch |err| 4167 fatal("failed to check zig installation for DLL import libs: {t}", .{err}); 4168 if (exists) { 4169 try create_module.windows_libs.put(arena, lib_name, {}); 4170 continue; 4171 } 4172 } 4173 4174 if (fs.path.isAbsolute(lib_name)) { 4175 fatal("cannot use absolute path as a system library: {s}", .{lib_name}); 4176 } 4177 4178 unresolved_link_inputs.appendAssumeCapacity(cli_link_input); 4179 any_name_queries_remaining = true; 4180 }, 4181 else => { 4182 unresolved_link_inputs.appendAssumeCapacity(cli_link_input); 4183 }, 4184 }; // After this point, unresolved_link_inputs is used instead of cli_link_inputs. 4185 4186 if (any_name_queries_remaining) create_module.want_native_include_dirs = true; 4187 4188 // Resolve the library path arguments with respect to sysroot. 4189 try create_module.lib_directories.ensureUnusedCapacity(arena, create_module.lib_dir_args.items.len); 4190 if (create_module.sysroot) |root| { 4191 for (create_module.lib_dir_args.items) |lib_dir_arg| { 4192 if (fs.path.isAbsolute(lib_dir_arg)) { 4193 const stripped_dir = lib_dir_arg[fs.path.parsePath(lib_dir_arg).root.len..]; 4194 const full_path = try fs.path.join(arena, &[_][]const u8{ root, stripped_dir }); 4195 addLibDirectoryWarn(io, &create_module.lib_directories, full_path); 4196 } else { 4197 addLibDirectoryWarn(io, &create_module.lib_directories, lib_dir_arg); 4198 } 4199 } 4200 } else { 4201 for (create_module.lib_dir_args.items) |lib_dir_arg| { 4202 addLibDirectoryWarn(io, &create_module.lib_directories, lib_dir_arg); 4203 } 4204 } 4205 create_module.lib_dir_args = undefined; // From here we use lib_directories instead. 4206 4207 if (resolved_target.is_native_os and target.os.tag.isDarwin()) { 4208 // If we want to link against frameworks, we need system headers. 4209 if (create_module.frameworks.count() > 0) 4210 create_module.want_native_include_dirs = true; 4211 } 4212 4213 if (create_module.each_lib_rpath orelse resolved_target.is_native_os) { 4214 try create_module.rpath_list.ensureUnusedCapacity(arena, create_module.lib_directories.items.len); 4215 for (create_module.lib_directories.items) |lib_directory| { 4216 create_module.rpath_list.appendAssumeCapacity(lib_directory.path.?); 4217 } 4218 } 4219 4220 // Trigger native system library path detection if necessary. 4221 if (create_module.sysroot == null and 4222 resolved_target.is_native_os and resolved_target.is_native_abi and 4223 create_module.want_native_include_dirs) 4224 { 4225 var paths = std.zig.system.NativePaths.detect(arena, io, target, environ_map) catch |err| 4226 fatal("unable to detect native system paths: {t}", .{err}); 4227 for (paths.warnings.items) |warning| { 4228 warn("{s}", .{warning}); 4229 } 4230 4231 create_module.native_system_include_paths = try paths.include_dirs.toOwnedSlice(arena); 4232 4233 try create_module.framework_dirs.appendSlice(arena, paths.framework_dirs.items); 4234 try create_module.rpath_list.appendSlice(arena, paths.rpaths.items); 4235 4236 try create_module.lib_directories.ensureUnusedCapacity(arena, paths.lib_dirs.items.len); 4237 for (paths.lib_dirs.items) |path| addLibDirectoryWarn2(io, &create_module.lib_directories, path, true); 4238 } 4239 4240 if (create_module.libc_paths_file) |paths_file| { 4241 create_module.libc_installation = LibCInstallation.parse(arena, io, paths_file, target) catch |err| 4242 fatal("unable to parse libc paths file at path {s}: {t}", .{ paths_file, err }); 4243 } 4244 4245 if (target.os.tag == .windows and (target.abi == .msvc or target.abi == .itanium) and 4246 any_name_queries_remaining) 4247 { 4248 if (create_module.libc_installation == null) { 4249 create_module.libc_installation = LibCInstallation.findNative(arena, io, .{ 4250 .verbose = true, 4251 .target = target, 4252 .environ_map = environ_map, 4253 }) catch |err| { 4254 fatal("unable to find native libc installation: {t}", .{err}); 4255 }; 4256 } 4257 try create_module.lib_directories.ensureUnusedCapacity(arena, 2); 4258 addLibDirectoryWarn(io, &create_module.lib_directories, create_module.libc_installation.?.msvc_lib_dir.?); 4259 addLibDirectoryWarn(io, &create_module.lib_directories, create_module.libc_installation.?.kernel32_lib_dir.?); 4260 } 4261 4262 // Destructively mutates but does not transfer ownership of `unresolved_link_inputs`. 4263 link.resolveInputs( 4264 gpa, 4265 arena, 4266 io, 4267 target, 4268 &unresolved_link_inputs, 4269 &create_module.link_inputs, 4270 create_module.lib_directories.items, 4271 color, 4272 ) catch |err| fatal("failed to resolve link inputs: {s}", .{@errorName(err)}); 4273 4274 if (!create_module.opts.any_dyn_libs) for (create_module.link_inputs.items) |item| switch (item) { 4275 .dso, .dso_exact => { 4276 create_module.opts.any_dyn_libs = true; 4277 break; 4278 }, 4279 else => {}, 4280 }; 4281 4282 create_module.resolved_options = Compilation.Config.resolve(create_module.opts) catch |err| switch (err) { 4283 error.WasiExecModelRequiresWasi => fatal("only WASI OS targets support execution model", .{}), 4284 error.SharedMemoryIsWasmOnly => fatal("only WebAssembly CPU targets support shared memory", .{}), 4285 error.ObjectFilesCannotShareMemory => fatal("object files cannot share memory", .{}), 4286 error.SharedMemoryRequiresAtomicsAndBulkMemory => fatal("shared memory requires atomics and bulk_memory CPU features", .{}), 4287 error.ThreadsRequireSharedMemory => fatal("threads require shared memory", .{}), 4288 error.EmittingLlvmModuleRequiresLlvmBackend => fatal("emitting an LLVM module requires using the LLVM backend", .{}), 4289 error.LlvmLacksTargetSupport => fatal("LLVM lacks support for the specified target", .{}), 4290 error.ZigLacksTargetSupport => fatal("compiler backend unavailable for the specified target", .{}), 4291 error.EmittingBinaryRequiresLlvmLibrary => fatal("producing machine code via LLVM requires using the LLVM library", .{}), 4292 error.LldIncompatibleObjectFormat => fatal("using LLD to link {s} files is unsupported", .{@tagName(target.ofmt)}), 4293 error.LldIncompatibleWithSelfHostedBackend => fatal("self-hosted backends do not support linking with LLD", .{}), 4294 error.LtoRequiresLld => fatal("LTO requires using LLD", .{}), 4295 error.SanitizeThreadRequiresLibCpp => fatal("thread sanitization is (for now) implemented in C++, so it requires linking libc++", .{}), 4296 error.LibCRequiresLibUnwind => fatal("libc of the specified target requires linking libunwind", .{}), 4297 error.LibCppRequiresLibUnwind => fatal("libc++ requires linking libunwind", .{}), 4298 error.LibCppRequiresLibC => fatal("libc++ requires linking libc", .{}), 4299 error.LibUnwindRequiresLibC => fatal("libunwind requires linking libc", .{}), 4300 error.TargetCannotDynamicLink => fatal("dynamic linking unavailable on the specified target", .{}), 4301 error.TargetCannotStaticLinkExecutables => fatal("static linking of executables unavailable on the specified target", .{}), 4302 error.LibCRequiresDynamicLinking => fatal("libc of the specified target requires dynamic linking", .{}), 4303 error.SharedLibrariesRequireDynamicLinking => fatal("using shared libraries requires dynamic linking", .{}), 4304 error.DynamicLinkingWithLldRequiresSharedLibraries => fatal("dynamic linking with lld requires at least one shared library", .{}), 4305 error.ExportMemoryAndDynamicIncompatible => fatal("exporting memory is incompatible with dynamic linking", .{}), 4306 error.DynamicLibraryPrecludesPie => fatal("dynamic libraries cannot be position independent executables", .{}), 4307 error.TargetRequiresPie => fatal("the specified target requires position independent executables", .{}), 4308 error.SanitizeThreadRequiresPie => fatal("thread sanitization requires position independent executables", .{}), 4309 error.SanitizeThreadRequiresLlvmBackend => fatal("thread sanitization requires the LLVM backend", .{}), 4310 error.BackendLacksErrorTracing => fatal("the selected backend has not yet implemented error return tracing", .{}), 4311 error.LlvmLibraryUnavailable => fatal("zig was compiled without LLVM libraries", .{}), 4312 error.LldUnavailable => fatal("zig was compiled without LLD libraries", .{}), 4313 error.ClangUnavailable => fatal("zig was compiled without Clang libraries", .{}), 4314 error.DllExportFnsRequiresWindows => fatal("only Windows OS targets support DLLs", .{}), 4315 error.NewLinkerIncompatibleWithLld => fatal("using the new linker is incompatible with using lld", .{}), 4316 error.NewLinkerIncompatibleObjectFormat => fatal("no new linker available for '{t}' files", .{target.ofmt}), 4317 }; 4318 } 4319 4320 const root: Compilation.Path = try .fromUnresolved(arena, create_module.dirs, &.{cli_mod.root_path}); 4321 4322 const mod = Module.create(arena, .{ 4323 .paths = .{ 4324 .root = root, 4325 .root_src_path = cli_mod.root_src_path, 4326 }, 4327 .fully_qualified_name = name, 4328 4329 .cc_argv = cli_mod.cc_argv, 4330 .inherited = cli_mod.inherited, 4331 .global = create_module.resolved_options, 4332 .parent = parent, 4333 }) catch |err| switch (err) { 4334 error.ValgrindUnsupportedOnTarget => fatal("unable to create module {q}: valgrind does not support the selected target CPU architecture", .{name}), 4335 error.TargetRequiresSingleThreaded => fatal("unable to create module {q}: the selected target does not support multithreading", .{name}), 4336 error.BackendRequiresSingleThreaded => fatal("unable to create module {q}: the selected machine code backend is limited to single-threaded applications", .{name}), 4337 error.TargetRequiresPic => fatal("unable to create module {q}: the selected target requires position independent code", .{name}), 4338 error.PieRequiresPic => fatal("unable to create module {q}: making a Position Independent Executable requires enabling Position Independent Code", .{name}), 4339 error.DynamicLinkingRequiresPic => fatal("unable to create module {q}: dynamic linking requires enabling Position Independent Code", .{name}), 4340 error.TargetHasNoRedZone => fatal("unable to create module {q}: the selected target does not have a red zone", .{name}), 4341 error.StackCheckUnsupportedByTarget => fatal("unable to create module {q}: the selected target does not support stack checking", .{name}), 4342 error.StackProtectorUnsupportedByTarget => fatal("unable to create module {q}: the selected target does not support stack protection", .{name}), 4343 error.StackProtectorUnavailableWithoutLibC => fatal("unable to create module {q}: enabling stack protection requires libc", .{name}), 4344 error.PatchableFunctionEntryUnsupportedByBackend => fatal("unable to create module {q}: patchable function entries are unsupported by the selected backend", .{name}), 4345 error.OutOfMemory => |e| return e, 4346 }; 4347 cli_mod.resolved = mod; 4348 4349 for (create_module.c_source_files.items[cli_mod.c_source_files_start..cli_mod.c_source_files_end]) |*item| item.owner = mod; 4350 4351 for (create_module.rc_source_files.items[cli_mod.rc_source_files_start..cli_mod.rc_source_files_end]) |*item| item.owner = mod; 4352 4353 for (cli_mod.deps) |dep| { 4354 const dep_index = create_module.modules.getIndex(dep.value) orelse 4355 fatal("module {q} depends on non-existent module {q}", .{ name, dep.key }); 4356 const dep_mod = try createModule(gpa, arena, io, create_module, dep_index, mod, color, environ_map); 4357 try mod.deps.put(arena, dep.key, dep_mod); 4358 } 4359 4360 return mod; 4361 } 4362 4363 fn saveState(comp: *Compilation, incremental: bool) void { 4364 if (incremental) { 4365 comp.saveState() catch |err| warn("unable to save incremental compilation state: {t}", .{err}); 4366 } 4367 } 4368 4369 fn serve( 4370 comp: *Compilation, 4371 in: *Io.Reader, 4372 out: *Io.Writer, 4373 test_exec_args: []const ?[]const u8, 4374 self_exe_path: switch (native_os) { 4375 .wasi => void, 4376 else => []const u8, 4377 }, 4378 arg_mode: ArgMode, 4379 all_args: []const []const u8, 4380 runtime_args_start: ?usize, 4381 environ_map: *process.Environ.Map, 4382 ) !void { 4383 const gpa = comp.gpa; 4384 const io = comp.io; 4385 4386 var server: Server = .{ .in = in, .out = out }; 4387 try server.serveStringMessage(.zig_version, build_options.version); 4388 4389 var child_pid: ?std.process.Child.Id = null; 4390 4391 const main_progress_node = std.Progress.start(io, .{}); 4392 defer main_progress_node.end(); 4393 4394 const file_system_inputs = comp.file_system_inputs.?; 4395 4396 const IncrementalDebugServer = if (build_options.enable_debug_extensions and !builtin.single_threaded) 4397 @import("IncrementalDebugServer.zig") 4398 else 4399 void; 4400 4401 var ids: IncrementalDebugServer = if (comp.debugIncremental()) ids: { 4402 break :ids .init(comp.zcu orelse @panic("--debug-incremental requires a ZCU")); 4403 } else undefined; 4404 defer if (comp.debugIncremental()) ids.deinit(); 4405 4406 if (comp.debugIncremental()) ids.spawn(); 4407 4408 while (true) { 4409 const hdr = try server.receiveMessage(); 4410 4411 // Lock the debug server while handling the message. 4412 if (comp.debugIncremental()) try ids.mutex.lock(io); 4413 defer if (comp.debugIncremental()) ids.mutex.unlock(io); 4414 4415 switch (hdr.tag) { 4416 .exit => return cleanExit(io), 4417 .update => { 4418 file_system_inputs.clearRetainingCapacity(); 4419 4420 if (arg_mode == .translate_c) { 4421 var arena_instance = std.heap.ArenaAllocator.init(gpa); 4422 defer arena_instance.deinit(); 4423 const arena = arena_instance.allocator(); 4424 var output: Compilation.TranslateCResult = undefined; 4425 try cmdTranslateC(comp, arena, &output, file_system_inputs, main_progress_node, environ_map); 4426 defer output.deinit(gpa); 4427 4428 if (file_system_inputs.items.len != 0) { 4429 try server.serveStringMessage(.file_system_inputs, file_system_inputs.items); 4430 } 4431 4432 if (output.errors.errorMessageCount() != 0) { 4433 try server.serveErrorBundle(output.errors); 4434 } else { 4435 try server.serveEmitDigest(&output.digest, .{ 4436 .flags = .{ .cache_hit = output.cache_hit }, 4437 }); 4438 } 4439 4440 continue; 4441 } 4442 4443 try comp.makeBinFileWritable(); 4444 try comp.update(main_progress_node); 4445 try comp.makeBinFileExecutable(); 4446 try serveUpdateResults(&server, comp); 4447 }, 4448 .run => { 4449 if (child_pid != null) { 4450 @panic("TODO block until the child exits"); 4451 } 4452 @panic("TODO call runOrTest"); 4453 //try runOrTest( 4454 // comp, 4455 // gpa, 4456 // arena, 4457 // io, 4458 // test_exec_args, 4459 // self_exe_path.?, 4460 // arg_mode, 4461 // target, 4462 // true, 4463 // &comp_destroyed, 4464 // all_args, 4465 // runtime_args_start, 4466 // link_libc, 4467 //); 4468 }, 4469 .hot_update => { 4470 file_system_inputs.clearRetainingCapacity(); 4471 if (child_pid) |pid| { 4472 try comp.hotCodeSwap(main_progress_node, pid); 4473 try serveUpdateResults(&server, comp); 4474 } else { 4475 try comp.makeBinFileWritable(); 4476 try comp.update(main_progress_node); 4477 try comp.makeBinFileExecutable(); 4478 try serveUpdateResults(&server, comp); 4479 4480 child_pid = try runOrTestHotSwap( 4481 comp, 4482 gpa, 4483 test_exec_args, 4484 self_exe_path, 4485 arg_mode, 4486 all_args, 4487 runtime_args_start, 4488 ); 4489 } 4490 }, 4491 else => { 4492 fatal("unrecognized message from client: 0x{x}", .{@backingInt(hdr.tag)}); 4493 }, 4494 } 4495 } 4496 } 4497 4498 fn serveUpdateResults(s: *Server, comp: *Compilation) !void { 4499 const gpa = comp.gpa; 4500 4501 var error_bundle = try comp.getAllErrorsAlloc(); 4502 defer error_bundle.deinit(gpa); 4503 4504 if (comp.file_system_inputs) |file_system_inputs| { 4505 if (file_system_inputs.items.len == 0) { 4506 assert(error_bundle.errorMessageCount() > 0); 4507 } else { 4508 try s.serveStringMessage(.file_system_inputs, file_system_inputs.items); 4509 } 4510 } 4511 4512 if (comp.time_report) |*tr| { 4513 var decls_len: u32 = 0; 4514 4515 var file_name_bytes: std.ArrayList(u8) = .empty; 4516 defer file_name_bytes.deinit(gpa); 4517 var files: std.array_hash_map.Auto(Zcu.File.Index, void) = .empty; 4518 defer files.deinit(gpa); 4519 var decl_data: std.ArrayList(u8) = .empty; 4520 defer decl_data.deinit(gpa); 4521 4522 // Each decl needs at least 34 bytes: 4523 // * 2 for 1-byte name plus null terminator 4524 // * 4 for `file` 4525 // * 4 for `sema_count` 4526 // * 8 for `sema_ns` 4527 // * 8 for `codegen_ns` 4528 // * 8 for `link_ns` 4529 // Most, if not all, decls in `tr.decl_sema_ns` are valid, so we have a good size estimate. 4530 try decl_data.ensureUnusedCapacity(gpa, tr.decl_sema_info.count() * 34); 4531 4532 for (tr.decl_sema_info.keys(), tr.decl_sema_info.values()) |tracked_inst, sema_info| { 4533 const resolved = tracked_inst.resolveFull(&comp.zcu.?.intern_pool) orelse continue; 4534 const file = comp.zcu.?.fileByIndex(resolved.file); 4535 const zir = file.zir orelse continue; 4536 const decl_name = zir.nullTerminatedString(zir.getDeclaration(resolved.inst).name); 4537 4538 const gop = try files.getOrPut(gpa, resolved.file); 4539 if (!gop.found_existing) try file_name_bytes.print(gpa, "{f}\x00", .{file.path.fmt(comp)}); 4540 4541 const codegen_ns = tr.decl_codegen_ns.get(tracked_inst) orelse 0; 4542 const link_ns = tr.decl_link_ns.get(tracked_inst) orelse 0; 4543 4544 decls_len += 1; 4545 4546 try decl_data.ensureUnusedCapacity(gpa, 33 + decl_name.len); 4547 decl_data.appendSliceAssumeCapacity(decl_name); 4548 decl_data.appendAssumeCapacity(0); 4549 4550 const out_file = decl_data.addManyAsArrayAssumeCapacity(4); 4551 const out_sema_count = decl_data.addManyAsArrayAssumeCapacity(4); 4552 const out_sema_ns = decl_data.addManyAsArrayAssumeCapacity(8); 4553 const out_codegen_ns = decl_data.addManyAsArrayAssumeCapacity(8); 4554 const out_link_ns = decl_data.addManyAsArrayAssumeCapacity(8); 4555 std.mem.writeInt(u32, out_file, @intCast(gop.index), .little); 4556 std.mem.writeInt(u32, out_sema_count, sema_info.count, .little); 4557 std.mem.writeInt(u64, out_sema_ns, sema_info.ns, .little); 4558 std.mem.writeInt(u64, out_codegen_ns, codegen_ns, .little); 4559 std.mem.writeInt(u64, out_link_ns, link_ns, .little); 4560 } 4561 4562 const header: std.zig.Server.Message.TimeReport = .{ 4563 .stats = tr.stats, 4564 .llvm_pass_timings_len = @intCast(tr.llvm_pass_timings.len), 4565 .files_len = @intCast(files.count()), 4566 .decls_len = decls_len, 4567 .flags = .{ 4568 .use_llvm = comp.zcu != null and comp.zcu.?.llvm_object != null, 4569 }, 4570 }; 4571 4572 var slices: [4][]const u8 = .{ 4573 @ptrCast(&header), 4574 tr.llvm_pass_timings, 4575 file_name_bytes.items, 4576 decl_data.items, 4577 }; 4578 try s.serveMessageHeader(.{ 4579 .tag = .time_report, 4580 .bytes_len = len: { 4581 var len: u32 = 0; 4582 for (slices) |slice| len += @intCast(slice.len); 4583 break :len len; 4584 }, 4585 }); 4586 try s.out.writeVecAll(&slices); 4587 try s.out.flush(); 4588 } 4589 4590 if (error_bundle.errorMessageCount() > 0) { 4591 try s.serveErrorBundle(error_bundle); 4592 return; 4593 } 4594 4595 if (comp.digest) |digest| { 4596 try s.serveEmitDigest(&digest, .{ 4597 .flags = .{ .cache_hit = comp.last_update_was_cache_hit }, 4598 }); 4599 } 4600 4601 // Serve empty error bundle to indicate the update is done. 4602 try s.serveErrorBundle(std.zig.ErrorBundle.empty); 4603 } 4604 4605 fn runOrTest( 4606 comp: *Compilation, 4607 gpa: Allocator, 4608 arena: Allocator, 4609 io: Io, 4610 test_exec_args: []const ?[]const u8, 4611 self_exe_path: []const u8, 4612 arg_mode: ArgMode, 4613 target: *const std.Target, 4614 comp_destroyed: *bool, 4615 all_args: []const []const u8, 4616 runtime_args_start: ?usize, 4617 link_libc: bool, 4618 test_execve: bool, 4619 environ_map: *process.Environ.Map, 4620 ) !void { 4621 const raw_emit_bin = comp.emit_bin orelse return; 4622 const exe_path = switch (comp.cache_use) { 4623 .none => p: { 4624 if (fs.path.isAbsolute(raw_emit_bin)) break :p raw_emit_bin; 4625 // Use `fs.path.join` to make a file in the cwd is still executed properly. 4626 break :p try fs.path.join(arena, &.{ 4627 ".", 4628 raw_emit_bin, 4629 }); 4630 }, 4631 .whole, .incremental => try comp.dirs.local_cache.join(arena, &.{ 4632 "o", 4633 &Cache.binToHex(comp.digest.?), 4634 raw_emit_bin, 4635 }), 4636 }; 4637 4638 var argv = std.array_list.Managed([]const u8).init(gpa); 4639 defer argv.deinit(); 4640 4641 if (test_exec_args.len == 0) { 4642 try argv.append(exe_path); 4643 if (arg_mode == .zig_test) { 4644 try argv.append( 4645 try arena.print("--seed=0x{x}", .{randInt(io, u32)}), 4646 ); 4647 } 4648 } else { 4649 for (test_exec_args) |arg| { 4650 try argv.append(arg orelse exe_path); 4651 } 4652 } 4653 if (runtime_args_start) |i| { 4654 try argv.appendSlice(all_args[i..]); 4655 } 4656 try environ_map.put("ZIG_EXE", self_exe_path); 4657 4658 // We do not execve for tests because if the test fails we want to print 4659 // the error message and invocation below. 4660 if (process.can_replace and (arg_mode == .run or (arg_mode == .zig_test and test_execve))) { 4661 // process replacement releases the locks; no need to destroy the Compilation here. 4662 _ = try io.lockStderr(&.{}, .no_color); 4663 const err = process.replace(io, .{ .argv = argv.items, .environ_map = environ_map }); 4664 io.unlockStderr(); 4665 try warnAboutForeignBinaries(io, arena, arg_mode, target, link_libc); 4666 const cmd = try std.mem.join(arena, " ", argv.items); 4667 fatal("the following command failed to execve with '{t}':\n{s}", .{ err, cmd }); 4668 } else if (!process.can_spawn) { 4669 fatal("the following command cannot be executed ({t} does not support spawning a child process):\n{f}", .{ 4670 native_os, std.zig.SubprocessCommand{ .argv = argv.items }, 4671 }); 4672 } 4673 const term_result = (term: { 4674 // Here we release all the locks associated with the Compilation so 4675 // that whatever this child process wants to do won't deadlock. 4676 comp.destroy(); 4677 comp_destroyed.* = true; 4678 4679 _ = try io.lockStderr(&.{}, .no_color); 4680 defer io.unlockStderr(); 4681 4682 var child = std.process.spawn(io, .{ 4683 .argv = argv.items, 4684 .environ_map = environ_map, 4685 .stdin = .inherit, 4686 .stdout = .inherit, 4687 .stderr = .inherit, 4688 }) catch |err| break :term err; 4689 defer child.kill(io); 4690 4691 break :term child.wait(io); 4692 }); 4693 4694 const term = term_result catch |err| { 4695 try warnAboutForeignBinaries(io, arena, arg_mode, target, link_libc); 4696 const cmd = try std.mem.join(arena, " ", argv.items); 4697 fatal("the following command failed with {t}:\n{s}", .{ err, cmd }); 4698 }; 4699 switch (arg_mode) { 4700 .run, .build => { 4701 switch (term) { 4702 .exited => |code| { 4703 if (code == 0) { 4704 return cleanExit(io); 4705 } else { 4706 process.exit(code); 4707 } 4708 }, 4709 .signal => |sig| { 4710 const cmd = try std.mem.join(arena, " ", argv.items); 4711 fatal("the following command terminated with signal {t}:\n{s}", .{ sig, cmd }); 4712 }, 4713 .stopped => |sig| { 4714 const cmd = try std.mem.join(arena, " ", argv.items); 4715 fatal("the following command stopped with signal {t}:\n{s}", .{ sig, cmd }); 4716 }, 4717 .unknown => { 4718 process.exit(1); 4719 }, 4720 } 4721 }, 4722 .zig_test => { 4723 switch (term) { 4724 .exited => |code| { 4725 if (code == 0) { 4726 return cleanExit(io); 4727 } else { 4728 const cmd = try std.mem.join(arena, " ", argv.items); 4729 fatal("the following test command failed with exit code {d}:\n{s}", .{ code, cmd }); 4730 } 4731 }, 4732 .signal => |sig| { 4733 const cmd = try std.mem.join(arena, " ", argv.items); 4734 fatal("the following test command terminated with signal {t}:\n{s}", .{ sig, cmd }); 4735 }, 4736 else => { 4737 const cmd = try std.mem.join(arena, " ", argv.items); 4738 fatal("the following test command crashed:\n{s}", .{cmd}); 4739 }, 4740 } 4741 }, 4742 else => unreachable, 4743 } 4744 } 4745 4746 fn runOrTestHotSwap( 4747 comp: *Compilation, 4748 gpa: Allocator, 4749 test_exec_args: []const ?[]const u8, 4750 self_exe_path: switch (native_os) { 4751 .wasi => void, 4752 else => []const u8, 4753 }, 4754 arg_mode: ArgMode, 4755 all_args: []const []const u8, 4756 runtime_args_start: ?usize, 4757 ) !std.process.Child.Id { 4758 const io = comp.io; 4759 const lf = comp.bin_file.?; 4760 4761 const self_exe_path_or_argv0 = switch (native_os) { 4762 .wasi => all_args[0], // Will error because of `!process.can_spawn` 4763 else => self_exe_path, 4764 }; 4765 4766 const exe_path = switch (builtin.target.os.tag) { 4767 // On Windows it seems impossible to perform an atomic rename of a file that is currently 4768 // running in a process. Therefore, we do the opposite. We create a copy of the file in 4769 // tmp zig-cache and use it to spawn the child process. This way we are free to update 4770 // the binary with each requested hot update. 4771 .windows => blk: { 4772 try lf.emit.root_dir.handle.copyFile(lf.emit.sub_path, comp.dirs.local_cache.handle, lf.emit.sub_path, io, .{}); 4773 break :blk try fs.path.join(gpa, &.{ comp.dirs.local_cache.path orelse ".", lf.emit.sub_path }); 4774 }, 4775 4776 // A naive `directory.join` here will indeed get the correct path to the binary, 4777 // however, in the case of cwd, we actually want `./foo` so that the path can be executed. 4778 else => try fs.path.join(gpa, &.{ 4779 lf.emit.root_dir.path orelse ".", lf.emit.sub_path, 4780 }), 4781 }; 4782 defer gpa.free(exe_path); 4783 4784 var argv = std.array_list.Managed([]const u8).init(gpa); 4785 defer argv.deinit(); 4786 4787 if (test_exec_args.len == 0) { 4788 // when testing pass the zig_exe_path to argv 4789 if (arg_mode == .zig_test) 4790 try argv.appendSlice(&[_][]const u8{ 4791 exe_path, self_exe_path_or_argv0, 4792 }) 4793 // when running just pass the current exe 4794 else 4795 try argv.appendSlice(&[_][]const u8{ 4796 exe_path, 4797 }); 4798 } else { 4799 for (test_exec_args) |arg| { 4800 if (arg) |a| { 4801 try argv.append(a); 4802 } else { 4803 try argv.appendSlice(&[_][]const u8{ 4804 exe_path, self_exe_path_or_argv0, 4805 }); 4806 } 4807 } 4808 } 4809 if (runtime_args_start) |i| { 4810 try argv.appendSlice(all_args[i..]); 4811 } 4812 4813 if (!process.can_spawn) { 4814 fatal("the following command cannot be executed ({t} does not support spawning a child process):\n{f}", .{ 4815 native_os, std.zig.SubprocessCommand{ .argv = argv.items }, 4816 }); 4817 } 4818 4819 const child = try std.process.spawn(io, .{ 4820 .argv = argv.items, 4821 .stdin = .inherit, 4822 .stdout = .inherit, 4823 .stderr = .inherit, 4824 }); 4825 return child.id.?; 4826 } 4827 4828 const UpdateModuleError = Compilation.UpdateError || error{ 4829 /// The update caused compile errors. The error bundle has already been 4830 /// reported to the user by being rendered to stderr. 4831 CompileErrorsReported, 4832 /// Error occurred printing compilation errors to stderr. 4833 PrintingErrorsFailed, 4834 }; 4835 fn updateModule(comp: *Compilation, color: Color, prog_node: std.Progress.Node) UpdateModuleError!void { 4836 try comp.update(prog_node); 4837 4838 var errors = try comp.getAllErrorsAlloc(); 4839 defer errors.deinit(comp.gpa); 4840 4841 if (errors.errorMessageCount() > 0) { 4842 const io = comp.io; 4843 errors.renderToStderr(io, .{}, color) catch |err| switch (err) { 4844 error.Canceled => |e| return e, 4845 else => return error.PrintingErrorsFailed, 4846 }; 4847 return error.CompileErrorsReported; 4848 } 4849 } 4850 4851 fn cmdTranslateC( 4852 comp: *Compilation, 4853 arena: Allocator, 4854 fancy_output: ?*Compilation.TranslateCResult, 4855 file_system_inputs: ?*std.ArrayList(u8), 4856 prog_node: std.Progress.Node, 4857 environ_map: *process.Environ.Map, 4858 ) !void { 4859 dev.check(.translate_c_command); 4860 4861 const io = comp.io; 4862 4863 assert(comp.c_source_files.len == 1); 4864 const c_source_file = comp.c_source_files[0]; 4865 4866 const translated_basename = try arena.print("{s}.zig", .{comp.root_name}); 4867 4868 var man: Cache.Manifest = comp.obtainCObjectCacheManifest(comp.root_mod); 4869 man.want_shared_lock = false; 4870 defer man.deinit(); 4871 4872 man.hash.add(@as(u16, 0xb945)); // Random number to distinguish translate-c from compiling C objects 4873 Compilation.cache_helpers.hashCSource(&man, c_source_file) catch |err| 4874 fatal("unable to process {q}: {t}", .{ c_source_file.src_path, err }); 4875 4876 var diag: Cache.Manifest.CheckDiagnostic = undefined; 4877 const status = man.check(&diag, prog_node) catch |err| switch (err) { 4878 error.OutOfMemory, error.Canceled => |e| return e, 4879 error.CacheCheckFailed => fatal("translate-c checking cache failed: {f}", .{diag.fmt(&man)}), 4880 }; 4881 std.log.debug("translate-c cache {f}", .{status.fmt(&man)}); 4882 const result: Compilation.TranslateCResult = if (status == .hit) .{ 4883 .digest = man.hitDigest(), 4884 .cache_hit = true, 4885 .errors = std.zig.ErrorBundle.empty, 4886 } else result: { 4887 const result = try comp.translateC( 4888 arena, 4889 &man, 4890 Compilation.classifyFileExt(c_source_file.src_path), 4891 c_source_file.src_path, 4892 translated_basename, 4893 comp.root_mod, 4894 prog_node, 4895 environ_map, 4896 ); 4897 4898 if (result.errors.errorMessageCount() != 0) { 4899 if (fancy_output) |p| { 4900 if (file_system_inputs) |buf| try man.populateFileSystemInputs(buf); 4901 p.* = result; 4902 return; 4903 } else { 4904 const color: Color = Color.settingFromEnvironment(environ_map); 4905 result.errors.renderToStderr(io, .{}, color) catch {}; 4906 process.exit(1); 4907 } 4908 } 4909 4910 man.finalize() catch |err| warn("failed to write cache manifest: {t}", .{err}); 4911 break :result result; 4912 }; 4913 4914 if (file_system_inputs) |buf| try man.populateFileSystemInputs(buf); 4915 if (fancy_output) |p| { 4916 p.* = result; 4917 } else { 4918 const hex_digest = Cache.binToHex(result.digest); 4919 const out_zig_path = try fs.path.join(arena, &.{ "o", &hex_digest, translated_basename }); 4920 const zig_file = comp.dirs.local_cache.handle.openFile(io, out_zig_path, .{}) catch |err| { 4921 const path = comp.dirs.local_cache.path orelse "."; 4922 fatal("unable to open cached translated zig file '{s}{s}{s}': {t}", .{ 4923 path, fs.path.sep_str, out_zig_path, err, 4924 }); 4925 }; 4926 defer zig_file.close(io); 4927 var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer); 4928 var file_reader = zig_file.reader(io, &.{}); 4929 _ = try stdout_writer.interface.sendFileAll(&file_reader, .unlimited); 4930 try stdout_writer.interface.flush(); 4931 return cleanExit(io); 4932 } 4933 } 4934 4935 pub fn translateC( 4936 gpa: Allocator, 4937 arena: Allocator, 4938 io: Io, 4939 argv: []const []const u8, 4940 environ_map: *const process.Environ.Map, 4941 prog_node: std.Progress.Node, 4942 thread_limit: usize, 4943 capture: ?*[]u8, 4944 ) !void { 4945 try jitCmdInner(gpa, arena, io, argv, environ_map, prog_node, thread_limit, .{ 4946 .cmd_name = "translate-c", 4947 .root_src_path = "translate-c/main.zig", 4948 .depend_on_aro = true, 4949 .capture = capture, 4950 }); 4951 } 4952 4953 const JitCmdOptions = struct { 4954 cmd_name: []const u8, 4955 root_src_path: []const u8, 4956 prepend_cmd: ?[]const u8 = null, 4957 prepend_zig_lib_dir_path: bool = false, 4958 prepend_global_cache_path: bool = false, 4959 prepend_zig_exe_path: bool = false, 4960 prepend_seed: bool = false, 4961 depend_on_aro: bool = false, 4962 capture: ?*[]u8 = null, 4963 /// Send error bundles via std.zig.Server over stdout 4964 server: bool = false, 4965 release_mode: std.lang.Optimize = .fast, 4966 }; 4967 4968 fn jitCmd( 4969 gpa: Allocator, 4970 arena: Allocator, 4971 io: Io, 4972 args: []const []const u8, 4973 environ_map: *const process.Environ.Map, 4974 options: JitCmdOptions, 4975 ) !void { 4976 dev.check(.jit_command); 4977 4978 const color = Color.settingFromEnvironment(environ_map); 4979 4980 const root_prog_node = std.Progress.start(io, .{ 4981 .disable_printing = (color == .off), 4982 .root_name = try arena.print("Compiling {s} (first time setup)", .{options.cmd_name}), 4983 }); 4984 defer root_prog_node.end(); 4985 4986 const thread_limit = @min( 4987 @max(std.Thread.getCpuCount() catch 1, 1), 4988 std.math.maxInt(Zcu.PerThread.IdBacking), 4989 ); 4990 try setThreadLimit(arena, thread_limit); 4991 4992 return jitCmdInner(gpa, arena, io, args, environ_map, root_prog_node, thread_limit, options); 4993 } 4994 4995 fn jitCmdInner( 4996 gpa: Allocator, 4997 arena: Allocator, 4998 io: Io, 4999 args: []const []const u8, 5000 environ_map: *const process.Environ.Map, 5001 root_prog_node: std.Progress.Node, 5002 thread_limit: usize, 5003 options: JitCmdOptions, 5004 ) !void { 5005 if (!std.process.can_spawn) { 5006 fatal("The {s} command cannot be executed ({t} does not support spawning a child process)", .{ 5007 options.cmd_name, native_os, 5008 }); 5009 } 5010 5011 const target_query: std.Target.Query = .{}; 5012 const resolved_target: Module.ResolvedTarget = .{ 5013 .result = std.zig.resolveTargetQueryOrFatal(io, target_query), 5014 .is_native_os = true, 5015 .is_native_abi = true, 5016 .is_explicit_dynamic_linker = false, 5017 }; 5018 5019 const self_exe_path = process.executablePathAlloc(io, arena) catch |err| 5020 fatal("unable to find self exe path: {t}", .{err}); 5021 5022 const optimize_mode: std.lang.Optimize = if (EnvVar.ZIG_DEBUG_CMD.isSet(environ_map)) 5023 .debug 5024 else 5025 options.release_mode; 5026 const strip = optimize_mode != .debug; 5027 var override_lib_dir: ?[]const u8 = EnvVar.ZIG_LIB_DIR.get(environ_map); 5028 const override_global_cache_dir: ?[]const u8 = EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map); 5029 5030 // Special case: if first arg starts with --zig-lib= then it is handled here. 5031 var args_i: usize = 0; 5032 if (args.len - args_i != 0) { 5033 if (mem.cutPrefix(u8, args[args_i], "--zig-lib=")) |rest| { 5034 override_lib_dir = rest; 5035 args_i += 1; 5036 } 5037 } 5038 5039 const cwd_path = try std.zig.getResolvedCwd(io, arena); 5040 5041 // This `init` calls `fatal` on error. 5042 var dirs: std.zig.Directories = .init(arena, io, .{ 5043 .override_zig_lib = override_lib_dir, 5044 .override_global_cache = override_global_cache_dir, 5045 .build_root = null, 5046 .local_cache_strat = .global, 5047 .preopens = preopens, 5048 .self_exe_path = self_exe_path, 5049 .environ_map = environ_map, 5050 .cwd = cwd_path, 5051 }); 5052 defer dirs.deinit(io); 5053 5054 var child_argv: std.ArrayList([]const u8) = .empty; 5055 try child_argv.ensureUnusedCapacity(arena, (args.len - args_i) + 6); 5056 5057 // We want to release all the locks before executing the child process, so we make a nice 5058 // big block here to ensure the cleanup gets run when we extract out our argv. 5059 { 5060 const main_mod_paths: Module.CreateOptions.Paths = .{ 5061 .root = try .fromRoot(arena, dirs, .zig_lib, "compiler"), 5062 .root_src_path = options.root_src_path, 5063 }; 5064 5065 const config = try Compilation.Config.resolve(.{ 5066 .output_mode = .Exe, 5067 .root_strip = strip, 5068 .root_optimize_mode = optimize_mode, 5069 .resolved_target = resolved_target, 5070 .have_zcu = true, 5071 .emit_bin = true, 5072 .is_test = false, 5073 }); 5074 5075 const root_mod = try Module.create(arena, .{ 5076 .paths = main_mod_paths, 5077 .fully_qualified_name = "root", 5078 .cc_argv = &.{}, 5079 .inherited = .{ 5080 .resolved_target = resolved_target, 5081 .optimize_mode = optimize_mode, 5082 .strip = strip, 5083 }, 5084 .global = config, 5085 .parent = null, 5086 }); 5087 5088 if (options.depend_on_aro) { 5089 const aro_mod = try Module.create(arena, .{ 5090 .paths = .{ 5091 .root = try .fromRoot(arena, dirs, .zig_lib, "compiler/aro"), 5092 .root_src_path = "aro.zig", 5093 }, 5094 .fully_qualified_name = "aro", 5095 .cc_argv = &.{}, 5096 .inherited = .{ 5097 .resolved_target = resolved_target, 5098 .optimize_mode = optimize_mode, 5099 .strip = strip, 5100 }, 5101 .global = config, 5102 .parent = null, 5103 }); 5104 try root_mod.deps.put(arena, "aro", aro_mod); 5105 } 5106 5107 var create_diag: Compilation.CreateDiagnostic = undefined; 5108 const comp = Compilation.create(gpa, arena, io, &create_diag, .{ 5109 .dirs = dirs, 5110 .root_name = options.cmd_name, 5111 .config = config, 5112 .root_mod = root_mod, 5113 .main_mod = root_mod, 5114 .emit_bin = .yes_cache, 5115 .self_exe_path = self_exe_path, 5116 .thread_limit = thread_limit, 5117 .cache_mode = .whole, 5118 .environ_map = environ_map, 5119 }) catch |err| switch (err) { 5120 error.CreateFail => fatal("failed to create compilation: {f}", .{create_diag}), 5121 else => fatal("failed to create compilation: {t}", .{err}), 5122 }; 5123 defer comp.destroy(); 5124 5125 if (options.server) { 5126 var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer); 5127 var server: std.zig.Server = .{ 5128 .out = &stdout_writer.interface, 5129 .in = undefined, // won't be receiving messages 5130 }; 5131 5132 try comp.update(root_prog_node); 5133 5134 var error_bundle = try comp.getAllErrorsAlloc(); 5135 defer error_bundle.deinit(comp.gpa); 5136 if (error_bundle.errorMessageCount() > 0) { 5137 try server.serveErrorBundle(error_bundle); 5138 process.exit(2); 5139 } 5140 } else { 5141 const color = Color.settingFromEnvironment(environ_map); 5142 updateModule(comp, color, root_prog_node) catch |err| switch (err) { 5143 error.CompileErrorsReported => process.exit(2), 5144 else => |e| return e, 5145 }; 5146 } 5147 5148 const exe_path = try dirs.global_cache.join(arena, &.{ 5149 "o", 5150 &Cache.binToHex(comp.digest.?), 5151 comp.emit_bin.?, 5152 }); 5153 child_argv.appendAssumeCapacity(exe_path); 5154 } 5155 5156 if (options.prepend_cmd) |cmd| 5157 child_argv.appendAssumeCapacity(cmd); 5158 if (options.prepend_zig_lib_dir_path) 5159 child_argv.appendAssumeCapacity(try arena.print("--zig-lib={s}", .{dirs.zig_lib.path orelse "."})); 5160 if (options.prepend_zig_exe_path) 5161 child_argv.appendAssumeCapacity(try arena.print("--zig={s}", .{self_exe_path})); 5162 if (options.prepend_global_cache_path) 5163 child_argv.appendAssumeCapacity(try arena.print("--global-cache={s}", .{dirs.global_cache.path orelse "."})); 5164 if (options.prepend_seed) 5165 child_argv.appendAssumeCapacity(try arena.print("--seed=0x{x}", .{randInt(io, u32)})); 5166 5167 child_argv.appendSliceAssumeCapacity(args[args_i..]); 5168 5169 if (EnvVar.ZIG_VERBOSE_CMD.isSet(environ_map)) { 5170 const cmd: std.zig.SubprocessCommand = .{ 5171 .argv = child_argv.items, 5172 }; 5173 std.log.info("{f}", .{cmd}); 5174 } 5175 5176 if (process.can_replace and options.capture == null) { 5177 _ = try io.lockStderr(&.{}, .no_color); 5178 const err = process.replace(io, .{ .argv = child_argv.items, .environ_map = environ_map }); 5179 const cmd = try std.mem.join(arena, " ", child_argv.items); 5180 fatal("the following command failed to execve with {t}:\n{s}", .{ err, cmd }); 5181 } 5182 5183 const term = t: { 5184 _ = try io.lockStderr(&.{}, .no_color); 5185 defer io.unlockStderr(); 5186 5187 var child = std.process.spawn(io, .{ 5188 .argv = child_argv.items, 5189 .stdin = .inherit, 5190 .stdout = if (options.capture == null) .inherit else .pipe, 5191 .stderr = .inherit, 5192 }) catch |err| fatal("failed to spawn {s}: {t}", .{ child_argv.items[0], err }); 5193 defer child.kill(io); 5194 5195 if (options.capture) |ptr| { 5196 var stdout_reader = child.stdout.?.readerStreaming(io, &.{}); 5197 ptr.* = try stdout_reader.interface.allocRemaining(arena, .limited(std.math.maxInt(u32))); 5198 } 5199 5200 break :t try child.wait(io); 5201 }; 5202 if (term.success()) { 5203 if (options.capture != null) return; 5204 return cleanExit(io); 5205 } 5206 const cmd = try std.mem.join(arena, " ", child_argv.items); 5207 fatal("the following build command {f}:\n{s}", .{ term, cmd }); 5208 } 5209 5210 const info_zen = 5211 \\ 5212 \\ * Communicate intent precisely. 5213 \\ * Edge cases matter. 5214 \\ * Favor reading code over writing code. 5215 \\ * There is an idiomatic way to do it. 5216 \\ * Runtime crashes are better than bugs. 5217 \\ * Compile errors are better than runtime crashes. 5218 \\ * Incremental improvements. 5219 \\ * Avoid local maximums. 5220 \\ * Reduce the amount one must remember. 5221 \\ * Focus on logic, not style. 5222 \\ * Resource allocation may fail. 5223 \\ * Resource deallocation must succeed. 5224 \\ 5225 \\Together, we serve the users! 5226 \\ 5227 \\ 5228 ; 5229 5230 extern fn ZigClangIsLLVMUsingSeparateLibcxx() bool; 5231 5232 extern "c" fn ZigClang_main(argc: c_int, argv: [*:null]?[*:0]u8) c_int; 5233 extern "c" fn ZigLlvmAr_main(argc: c_int, argv: [*:null]?[*:0]u8) c_int; 5234 5235 fn argsCopyZ(alloc: Allocator, args: []const []const u8) ![:null]?[*:0]u8 { 5236 var argv = try alloc.allocSentinel(?[*:0]u8, args.len, null); 5237 for (args, 0..) |arg, i| { 5238 argv[i] = try alloc.dupeSentinel(u8, arg, 0); // TODO If there was an argsAllocZ we could avoid this allocation. 5239 } 5240 return argv; 5241 } 5242 5243 pub fn clangMain(alloc: Allocator, args: []const []const u8) error{OutOfMemory}!u8 { 5244 if (!build_options.have_llvm) 5245 fatal("`zig cc` and `zig c++` unavailable: compiler built without LLVM extensions", .{}); 5246 5247 var arena_instance = std.heap.ArenaAllocator.init(alloc); 5248 defer arena_instance.deinit(); 5249 const arena = arena_instance.allocator(); 5250 5251 // Convert the args to the null-terminated format Clang expects. 5252 const argv = try argsCopyZ(arena, args); 5253 const exit_code = ZigClang_main(@as(c_int, @intCast(argv.len)), argv.ptr); 5254 return @as(u8, @bitCast(@as(i8, @truncate(exit_code)))); 5255 } 5256 5257 pub fn llvmArMain(alloc: Allocator, args: []const []const u8) error{OutOfMemory}!u8 { 5258 if (!build_options.have_llvm) 5259 fatal("`zig ar`, `zig dlltool`, `zig ranlib', and `zig lib` unavailable: compiler built without LLVM extensions", .{}); 5260 5261 var arena_instance = std.heap.ArenaAllocator.init(alloc); 5262 defer arena_instance.deinit(); 5263 const arena = arena_instance.allocator(); 5264 5265 // Convert the args to the format llvm-ar expects. 5266 // We intentionally shave off the zig binary at args[0]. 5267 const argv = try argsCopyZ(arena, args[1..]); 5268 const exit_code = ZigLlvmAr_main(@as(c_int, @intCast(argv.len)), argv.ptr); 5269 return @as(u8, @bitCast(@as(i8, @truncate(exit_code)))); 5270 } 5271 5272 /// The first argument determines which backend is invoked. The options are: 5273 /// * `ld.lld` - ELF 5274 /// * `lld-link` - COFF 5275 /// * `wasm-ld` - WebAssembly 5276 pub fn lldMain( 5277 alloc: Allocator, 5278 args: []const []const u8, 5279 can_exit_early: bool, 5280 ) error{OutOfMemory}!u8 { 5281 if (!build_options.have_llvm) 5282 fatal("`zig {s}` unavailable: compiler built without LLVM extensions", .{args[0]}); 5283 5284 // Print a warning if lld is called multiple times in the same process, 5285 // since it may misbehave 5286 // https://github.com/ziglang/zig/issues/3825 5287 const CallCounter = struct { 5288 var count: usize = 0; 5289 }; 5290 if (CallCounter.count == 1) { // Issue the warning on the first repeat call 5291 warn("invoking LLD for the second time within the same process because the host OS ({s}) does not support spawning child processes. This sometimes activates LLD bugs", .{@tagName(native_os)}); 5292 } 5293 CallCounter.count += 1; 5294 5295 var arena_instance = std.heap.ArenaAllocator.init(alloc); 5296 defer arena_instance.deinit(); 5297 const arena = arena_instance.allocator(); 5298 5299 // Convert the args to the format LLD expects. 5300 // We intentionally shave off the zig binary at args[0]. 5301 const argv = try argsCopyZ(arena, args[1..]); 5302 // "If an error occurs, false will be returned." 5303 const ok = rc: { 5304 const llvm = @import("codegen/llvm/bindings.zig"); 5305 const argc = @as(c_int, @intCast(argv.len)); 5306 if (mem.eql(u8, args[1], "ld.lld")) { 5307 break :rc llvm.LinkELF(argc, argv.ptr, can_exit_early, false); 5308 } else if (mem.eql(u8, args[1], "lld-link")) { 5309 break :rc llvm.LinkCOFF(argc, argv.ptr, can_exit_early, false); 5310 } else if (mem.eql(u8, args[1], "wasm-ld")) { 5311 break :rc llvm.LinkWasm(argc, argv.ptr, can_exit_early, false); 5312 } else { 5313 unreachable; 5314 } 5315 }; 5316 return @intFromBool(!ok); 5317 } 5318 5319 const ArgIteratorResponseFile = process.Args.IteratorGeneral(.{ .comments = true, .single_quotes = true }); 5320 5321 /// Initialize the arguments from a Response File. "*.rsp" 5322 fn initArgIteratorResponseFile(allocator: Allocator, io: Io, resp_file_path: []const u8) !ArgIteratorResponseFile { 5323 const max_bytes = 10 * 1024 * 1024; // 10 MiB of command line arguments is a reasonable limit 5324 const cmd_line = try Io.Dir.cwd().readFileAlloc(io, resp_file_path, allocator, .limited(max_bytes)); 5325 errdefer allocator.free(cmd_line); 5326 5327 return ArgIteratorResponseFile.initTakeOwnership(allocator, cmd_line); 5328 } 5329 5330 pub const ClangArgIterator = struct { 5331 has_next: bool, 5332 zig_equivalent: std.zig.ClangCliParam.ZigEquivalent, 5333 only_arg: []const u8, 5334 second_arg: []const u8, 5335 other_args: []const []const u8, 5336 argv: []const []const u8, 5337 next_index: usize, 5338 root_args: ?*Args,