# Use zig cc as a alternative linker (draft version)

**URL:** <https://forum.crystal-lang.org/t/use-zig-cc-as-a-alternative-linker-draft-version/6345>\
**Category:** Community\
**Created:** [January 20, 2024, 11:22am UTC](https://forum.crystal-lang.org/t/use-zig-cc-as-a-alternative-linker-draft-version/6345 "2024-01-20T11:22:26Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![zw963](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/zw963/32/1623_2.png) [@zw963](https://forum.crystal-lang.org/u/zw963)\
**Post date:** [January 20, 2024, 11:22am UTC](https://forum.crystal-lang.org/t/use-zig-cc-as-a-alternative-linker-draft-version/6345/1 "2024-01-20T11:22:27Z")

</div>

This approach was originally verified by @luislavena and first posted [here](https://forum.crystal-lang.org/t/a-github-action-template-for-do-release-assets-when-push-a-tag-it-should-fitable-for-any-shards/4635/5), [here](https://forum.crystal-lang.org/t/a-github-action-template-for-do-release-assets-when-push-a-tag-it-should-fitable-for-any-shards/4635/8) and [here](https://forum.crystal-lang.org/t/does-anyone-deploy-crystal-app-on-arm-based-linux-server-what-is-the-deployment-process-like/5588/5), big thanks to him for proving this solutin work, and he showed a little bit of this in following videos:

```
[Building CLIs with Crystal - Quick cross-compilation - Part 1](https://www.youtube.com/watch?v=ij7alYEvfTg)
[Building CLIs with Crystal - Quick cross-compilation - Part 2](https://www.youtube.com/watch?v=LdVNqdf_kBI)

```

Here are some links explain how `zig cc` link work:

[`zig cc`: a Powerful Drop-In Replacement for GCC/Clang](https://andrewkelley.me/post/zig-cc-powerful-drop-in-replacement-gcc-clang.html)

[How Uber Uses Zig](https://jakstys.lt/2022/how-uber-uses-zig/)

PR: [Add guide: Use zig cc as a alternative linker (draft version) by zw963 · Pull Request #737 · crystal-lang/crystal-book · GitHub](https://github.com/crystal-lang/crystal-book/pull/737)

* * *

@straight-shoota , we can also discuss here.

---

<div class="post-metadata">

**Author:** ![zw963](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/zw963/32/1623_2.png) [@zw963](https://forum.crystal-lang.org/u/zw963)\
**Post date:** [January 20, 2024, 11:38am UTC](https://forum.crystal-lang.org/t/use-zig-cc-as-a-alternative-linker-draft-version/6345/2 "2024-01-20T11:38:11Z")

</div>

HTML version:

> <https://github.com/zw963/crystal-book/blob/patch-1/docs/guides/use_zig_cc_as_an_alternative_linker.md>

---

<div class="post-metadata">

**Author:** ![zw963](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/zw963/32/1623_2.png) [@zw963](https://forum.crystal-lang.org/u/zw963)\
**Post date:** [January 20, 2024, 3:07pm UTC](https://forum.crystal-lang.org/t/use-zig-cc-as-a-alternative-linker-draft-version/6345/3 "2024-01-20T15:07:07Z")

</div>

@luislavena , because the original gem [GitHub - luislavena/magic-haversack: Facilitate Crystal cross-compilation](https://github.com/luislavena/magic-haversack), there is no way to create issue, i just create it here.

As the example code following, A minimal hello world code, if linked to macOS using zig cc, the `libiconv` is necessary.

* * *

╰─ $ echo ‘puts “hello”’ \> hello.cr

╰─ $ crystal build hello.cr --release --no-debug --cross-compile --target=x86\_64-darwin --link-flags=-s  
cc hello.o -o hello -s -rdynamic -L/home/zw963/Crystal/bin/…/lib/crystal -lpcre2-8 -lgc -lpthread -ldl -levent -liconv

* * *

But, this library not exists in magic-haversack.

---

<div class="post-metadata">

**Author:** ![luislavena](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/luislavena/32/572_2.png) [@luislavena](https://forum.crystal-lang.org/u/luislavena)\
**Post date:** [January 20, 2024, 3:42pm UTC](https://forum.crystal-lang.org/t/use-zig-cc-as-a-alternative-linker-draft-version/6345/4 "2024-01-20T15:42:48Z")

</div>

tl;dr: you need macOS SDK to link against their dynamic version of iconv, the one used by Crystal by default when targeting macOS platforms.

You could workaround that by downloading libiconv for macOS (the static library) and forcing the link to it.

See [this Crystal PR](https://github.com/crystal-lang/crystal/pull/11876) that covers all the details of iconv on macOS.

Or you can download existing versions of macOS SDK and grab the `.tld` files necessary for the dynamic linking to work.

I cannot distribute bundled versions of the SDK without breaking Apple’s terms.

Cheers.

---

<div class="post-metadata">

**Author:** ![zw963](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/zw963/32/1623_2.png) [@zw963](https://forum.crystal-lang.org/u/zw963)\
**Post date:** [January 20, 2024, 3:50pm UTC](https://forum.crystal-lang.org/t/use-zig-cc-as-a-alternative-linker-draft-version/6345/5 "2024-01-20T15:50:57Z")

</div>

How about adding libiconv for macOS (the static library) to magic-haversack? it can be installed use brew anyway.

---

<div class="post-metadata">

**Author:** ![zw963](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/zw963/32/1623_2.png) [@zw963](https://forum.crystal-lang.org/u/zw963)\
**Post date:** [January 20, 2024, 4:40pm UTC](https://forum.crystal-lang.org/t/use-zig-cc-as-a-alternative-linker-draft-version/6345/6 "2024-01-20T16:40:28Z")

</div>

Add a bash script example make cross link `aarch64-linux-musl`/`x86_64-linux-musl` use `zig cc` automate.

> <https://github.com/zw963/crystal-book/blob/patch-1/docs/guides/use_zig_cc_as_an_alternative_linker.md#a-bash-script-for-make-cross-link-aarch64-linux-muslx86_64-linux-musl-use-zig-cc-automate>

---

<div class="post-metadata">

**Author:** ![zw963](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/zw963/32/1623_2.png) [@zw963](https://forum.crystal-lang.org/u/zw963)\
**Post date:** [January 21, 2024, 10:58am UTC](https://forum.crystal-lang.org/t/use-zig-cc-as-a-alternative-linker-draft-version/6345/7 "2024-01-21T10:58:21Z")

</div>

Add a new bash script, it can build and link binary on my AMD64 laptop for `x86_64-linux-musl/aarch64-linux-musl/x86_64-darwin/arrch64-darwin` now without needs docker.

```sh
 ╰─ $ cd ~/Crystal/crystal-lang/shards
 
  ╰─ $ git clean -fdx && shards build --production --static --no-debug --cross-compile --target=aarch64-linux-musl --link-flags=-s
Removing bin/shards
Removing bin/shards.o
Removing lib/
zig cc -target aarch64-linux-musl /home/zw963/Crystal/crystal-lang/shards/bin/shards.o -o /home/zw963/Crystal/crystal-lang/shards/bin/shards -s -rdynamic -static -L/home/zw963/Crystal/static_libraries/aarch64-linux-musl -lyaml -lpcre2-8 -lgc -lpthread -ldl -levent -lunwind
 
 ╰─ $ file bin/shards
bin/shards: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), static-pie linked, stripped

 ╰─ $ git clean -fdx && shards build --production --static --no-debug --cross-compile --target=x86_64-linux-musl --link-flags=-s
Removing bin/shards
Removing bin/shards.o
Removing lib/
zig cc -target x86_64-linux-musl /home/zw963/Crystal/crystal-lang/shards/bin/shards.o -o /home/zw963/Crystal/crystal-lang/shards/bin/shards -s -rdynamic -static -L/home/zw963/Crystal/static_libraries/x86_64-linux-musl -lyaml -lpcre2-8 -lgc -lpthread -ldl -levent -lunwind

 ╰─ $ file bin/shards
bin/shards: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), static-pie linked, stripped

 ╰─ $ git clean -fdx && shards build --production --static --no-debug --cross-compile --target=x86_64-darwin --link-flags=-s
Removing bin/shards
Removing bin/shards.o
Removing lib/
zig cc -target x86_64-macos-none /home/zw963/Crystal/crystal-lang/shards/bin/shards.o -o /home/zw963/Crystal/crystal-lang/shards/bin/shards -s -rdynamic -static -L/home/zw963/Crystal/static_libraries/x86_64-apple-darwin21.0 -lyaml -lpcre2-8 -lgc -lpthread -ldl -levent -liconv -lunwind

 ╰─ $ file bin/shards
bin/shards: Mach-O 64-bit x86_64 executable, flags:<NOUNDEFS|DYLDLINK|TWOLEVEL|PIE|HAS_TLV_DESCRIPTORS>

 ╰─ $ git clean -fdx && shards build --production --static --no-debug --cross-compile --target=aarch64-darwin --link-flags=-s
Removing bin/shards
Removing bin/shards.o
Removing lib/
zig cc -target aarch64-macos-none /home/zw963/Crystal/crystal-lang/shards/bin/shards.o -o /home/zw963/Crystal/crystal-lang/shards/bin/shards -s -rdynamic -static -L/home/zw963/Crystal/static_libraries/aarch64-apple-darwin21.0 -lyaml -lpcre2-8 -lgc -lpthread -ldl -levent -liconv -lunwind

 ╰─ $ file bin/shards
bin/shards: Mach-O 64-bit arm64 executable, flags:<NOUNDEFS|DYLDLINK|TWOLEVEL|PIE|HAS_TLV_DESCRIPTORS>

```

> <https://github.com/zw963/crystal-book/blob/patch-1/docs/guides/use_zig_cc_as_an_alternative_linker.md#an-bash-script-to-automate-the-use-of-zig-cc-as-the-linker>
