diff --git a/.github/workflows/autocorrect.yml b/.github/workflows/autocorrect.yml new file mode 100644 index 0000000..4a88997 --- /dev/null +++ b/.github/workflows/autocorrect.yml @@ -0,0 +1,23 @@ +name: AutoCorrect CI + +on: + pull_request: + workflow_dispatch: + +jobs: + autocorrect: + runs-on: ubuntu-latest + steps: + - name: Check source code + uses: actions/checkout@v4 + + - name: AutoCorrect + uses: huacnlee/autocorrect-action@v2 + + - name: Review Dog + if: failure() + uses: huacnlee/autocorrect-action@v2 + env: + REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + reviewdog: true \ No newline at end of file diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml deleted file mode 100644 index 1cce14f..0000000 --- a/.github/workflows/examples.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: Run Examples - -on: - schedule: - - cron: "10 20 * * *" - pull_request: - paths: - - "examples/**" - - ".github/workflows/examples.yml" - push: - branches: - - main - paths: - - "examples/**" - - ".github/workflows/examples.yml" - -defaults: - run: - working-directory: examples - -jobs: - examples: - timeout-minutes: 10 - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, macos-latest] - zig: [0.12.0] - steps: - - uses: actions/checkout@v4 - - - uses: goto-bus-stop/setup-zig@v2 - with: - version: ${{ matrix.zig }} - - - name: Run Examples - run: | - ./run-all.sh diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index 3d09ca6..94fa5ad 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -1,10 +1,8 @@ -name: GitHub Pages +name: Deploy the website to Github Pages on: push: - branches: - - main - workflow_dispatch: + branches: ["zine", "main"] # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages permissions: @@ -12,53 +10,42 @@ permissions: pages: write id-token: write -concurrency: - group: "pages" - cancel-in-progress: true - -# Default to bash defaults: run: shell: bash +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. +concurrency: + group: "pages" + cancel-in-progress: true + jobs: - build: + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: - submodules: recursive - - uses: peaceiris/actions-hugo@v2 + fetch-depth: 0 # Change if you need git info + + - name: Setup Zine + uses: kristoff-it/setup-zine@v1 with: - # hugo-version: "0.140.2" - hugo-version: latest - extended: true + version: v0.10.2 + + - name: Build + run: zine release + - name: Setup Pages - id: pages - uses: actions/configure-pages@v4 - - name: Build with Hugo - env: - # For maximum backward compatibility with Hugo modules - HUGO_ENVIRONMENT: production - HUGO_ENV: production - run: | - npm i -D postcss postcss-cli autoprefixer - hugo mod get - hugo \ - --minify \ - --baseURL "${{ steps.pages.outputs.base_url }}/" + uses: actions/configure-pages@v5 + - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: - path: ./public + path: "public" - deploy: - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - runs-on: ubuntu-latest - needs: build - steps: - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml deleted file mode 100644 index 339e2e0..0000000 --- a/.github/workflows/lint.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Lint - -on: - workflow_dispatch: - pull_request: - paths: - - "**.md" - - "**.org" - - ".github/workflows/**" - push: - branches: - - main - paths: - - "**.md" - - "**.org" - - ".github/workflows/**" - -jobs: - lint: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - uses: actions/setup-node@v4 - with: - node-version: "latest" - - name: Prettier check - run: | - echo "If lint fails, run `make format` and commit again." - make lint diff --git a/.github/workflows/mirror.yml b/.github/workflows/mirror.yml index 71ae1b4..97f861b 100644 --- a/.github/workflows/mirror.yml +++ b/.github/workflows/mirror.yml @@ -3,7 +3,7 @@ name: Mirror on: push: branches: - - main + - main** workflow_dispatch: jobs: diff --git a/.gitignore b/.gitignore index e2e84ff..fd3340e 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ # zig zig-cache/ zig-out/ + +.cache_ggshield diff --git a/.lintmdrc b/.lintmdrc deleted file mode 100644 index 3f61869..0000000 --- a/.lintmdrc +++ /dev/null @@ -1,18 +0,0 @@ -{ - "rules":{ - "no-empty-code": 2, - "no-empty-url": 2, - "no-empty-list": 2, - "space-around-alphabet": 2, - "no-special-characters": 2, - "no-multiple-space-blockquote": 2, - "correct-title-trailing-punctuation": 2, - "no-empty-blockquote": 2, - "use-standard-ellipsis": 2, - "space-around-number": 2, - "no-long-code": [2, { - "length": 100, - "exclude": ["dot"] - }] - } -} \ No newline at end of file diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index 02dfa4c..0000000 --- a/.prettierignore +++ /dev/null @@ -1,3 +0,0 @@ -/public -/themes -/layouts \ No newline at end of file diff --git a/Makefile b/Makefile index 4d3a8e3..c47dae1 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ serve: - hugo serve + zine lint: npx @lint-md/cli **/* diff --git a/README.md b/README.md new file mode 100644 index 0000000..4e84cba --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ +[![](https://github.com/zigcc/zigcc.github.io/actions/workflows/gh-pages.yml/badge.svg)](https://github.com/zigcc/zigcc.github.io/actions/workflows/gh-pages.yml) + +# Zig 语言中文社区 + +- +- 如果没有特殊声明,本网站内容均采用 [CC BY-NC-ND + 4.0](https://creativecommons.org/licenses/by-nc-nd/4.0/) 协议 + +
+

欢迎来到 Zig 语言中文社区!(Zig Chinese Community,简称:ZigCC)

+ + + + + + + + + +
+ +> Zig Chinese Community is dedicated to sharing and spreading the use of +> Zig language among Chinese users. + +本网站使用 [zine](https://zine-ssg.io/) 进行构建,可参考 [quickstart](https://zine-ssg.io/quickstart/) 进行安装,网站预览命令: + +``` bash +# Serve the site +zine +``` diff --git a/README.org b/README.org deleted file mode 100644 index 199641c..0000000 --- a/README.org +++ /dev/null @@ -1,52 +0,0 @@ -[[https://github.com/zigcc/zigcc.github.io/actions/workflows/gh-pages.yml][https://github.com/zigcc/zigcc.github.io/actions/workflows/gh-pages.yml/badge.svg]] - -* Zig 语言中文社区 -- [[https://ziglang.cc]] -- 如果没有特殊声明,本网站内容均采用 [[https://creativecommons.org/licenses/by-nc-nd/4.0/][CC BY-NC-ND 4.0]] 协议 - -#+BEGIN_EXPORT html -
-

欢迎来到 Zig 语言中文社区!(Zig Chinese Community,简称:ZigCC)

- - - - - - - - - -
-#+END_EXPORT - - -#+begin_quote -Zig Chinese Community is dedicated to sharing and spreading the use of Zig language among Chinese users. -#+end_quote - -本网站使用 [[https://gohugo.io/][hugo]](extended 版本)与 [[https://www.docsy.dev/][docsy]] 主题进行构建。 - -#+begin_src bash -# For macOS -brew install hugo -# For Debian -sudo apt install hugo -# For Arch -sudo pacman -S hugo - -# Snap -sudo snap install hugo -#+end_src - -#+begin_src bash -# run server -hugo server -#+end_src - -如果启动 server 时报错,可以安装以下依赖: -#+begin_src bash -# install depends -npm i -D postcss postcss-cli autoprefixer -#+end_src - -参考:https://www.docsy.dev/docs/get-started/docsy-as-module/installation-prerequisites/#install-postcss diff --git a/archetypes/default.md b/archetypes/default.md deleted file mode 100644 index 26f317f..0000000 --- a/archetypes/default.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: "{{ replace .Name "-" " " | title }}" -date: {{ .Date }} -draft: true ---- diff --git a/assets/highlight.css b/assets/highlight.css new file mode 100644 index 0000000..1c8d961 --- /dev/null +++ b/assets/highlight.css @@ -0,0 +1,103 @@ +:root { + --code-fg: #BD976A; + --keyword: #4D9375; + --variable: #BD976A; + --comment: #758575DD; + --operator: #666666; + --string: #C98A7D; + --number: #4C9A91; + --function: #CB7676; + --bracket: #93aa9e; +} + +code { + color: var(--code-fg); +} + +code.zig, code.javascript, code.c, code.cpp, code.zon, code.go{ + color: var(--code-fg); + .keyword, .keyword_modifier, .type_builtin, .keyword_type, .keyword_return, .keyword_conditional, .keyword_repeat, .keyword_operator, .constant_builtin, .keyword_exception, .type{ + color: var(--keyword); + } + .variable, .function_builtin{ + color: var(--variable); + } + .comment{ + color: var(--comment); + } + .operator, .punctuation{ + color: var(--operator); + } + .string, .character{ + color: var(--string); + } + .number{ + color: var(--number); + } + .keyword_function, .punctuation_delimiter, .function{ + color: var(--function); + } + .punctuation_bracket{ + color: var(--bracket); + } +} + +code.conf{ + color: var(--code-fg); + .function{ + color: var(--function); + } + .punctuation_bracket{ + color: var(--bracket); + } +} + +code.diff{ + color: var(--code-fg); + .addition, .string{ + color: #4D9375; + } + .deletion, .keyword{ + color: #CB7676; + } +} + +/* TODO 分词器太烂了 */ +code.bash { + color: var(--code-fg); + .comment { + color: var(--comment); + font-style: italic; + } + span.operator { + color: var(--operator); + } + .constant { + color: var(--number); + } + .string { + color: var(--string); + } + .function { + color: var(--function); + } +} + +code.json{ + color: var(--code-fg); + .constant_builtin{ + color: var(--keyword); + } + span.string_special_key{ + color: var(--string) + } + .string{ + color: var(--function) + } +} + +@media (prefers-color-scheme: light) { + code{ + filter: brightness(0.9) contrast(1.3); + } +} \ No newline at end of file diff --git a/assets/icons/arrow-left.svg b/assets/icons/arrow-left.svg new file mode 100644 index 0000000..333d668 --- /dev/null +++ b/assets/icons/arrow-left.svg @@ -0,0 +1,18 @@ + + + + Arrow-Left + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/icons/arrow-right.svg b/assets/icons/arrow-right.svg new file mode 100644 index 0000000..aa292d3 --- /dev/null +++ b/assets/icons/arrow-right.svg @@ -0,0 +1,18 @@ + + + + Arrow-Right + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/icons/discord.svg b/assets/icons/discord.svg new file mode 100644 index 0000000..afade27 --- /dev/null +++ b/assets/icons/discord.svg @@ -0,0 +1,6 @@ + + + +discord + + \ No newline at end of file diff --git a/assets/icons/email.svg b/assets/icons/email.svg new file mode 100644 index 0000000..04c39cb --- /dev/null +++ b/assets/icons/email.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/assets/icons/github.svg b/assets/icons/github.svg new file mode 100644 index 0000000..2dfec51 --- /dev/null +++ b/assets/icons/github.svg @@ -0,0 +1,19 @@ + + + + + github [#142] + Created with Sketch. + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/icons/logo.svg b/assets/icons/icon.svg similarity index 56% rename from assets/icons/logo.svg rename to assets/icons/icon.svg index b2d5500..640c300 100644 --- a/assets/icons/logo.svg +++ b/assets/icons/icon.svg @@ -1,16 +1,16 @@ - - - + + + - + - - - + + + - + \ No newline at end of file diff --git a/assets/icons/telegram.svg b/assets/icons/telegram.svg new file mode 100644 index 0000000..541b9d2 --- /dev/null +++ b/assets/icons/telegram.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/assets/icons/zigcc.svg b/assets/icons/zigcc.svg new file mode 100644 index 0000000..85801dc --- /dev/null +++ b/assets/icons/zigcc.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/static/images/blockly.webp b/assets/images/blockly.webp similarity index 100% rename from static/images/blockly.webp rename to assets/images/blockly.webp diff --git a/static/images/fair-children.webp b/assets/images/fair-children.webp similarity index 100% rename from static/images/fair-children.webp rename to assets/images/fair-children.webp diff --git a/static/images/first-online-meeting.webp b/assets/images/first-online-meeting.webp similarity index 100% rename from static/images/first-online-meeting.webp rename to assets/images/first-online-meeting.webp diff --git a/static/images/logo.svg b/assets/images/logo.svg similarity index 100% rename from static/images/logo.svg rename to assets/images/logo.svg diff --git a/static/images/paper-cuts.webp b/assets/images/paper-cuts.webp similarity index 100% rename from static/images/paper-cuts.webp rename to assets/images/paper-cuts.webp diff --git a/static/images/soa-layout.webp b/assets/images/soa-layout.webp similarity index 100% rename from static/images/soa-layout.webp rename to assets/images/soa-layout.webp diff --git a/static/images/stackoverflow2024-highly-desired.webp b/assets/images/stackoverflow2024-highly-desired.webp similarity index 100% rename from static/images/stackoverflow2024-highly-desired.webp rename to assets/images/stackoverflow2024-highly-desired.webp diff --git a/static/images/stackoverflow2024-salary.webp b/assets/images/stackoverflow2024-salary.webp similarity index 100% rename from static/images/stackoverflow2024-salary.webp rename to assets/images/stackoverflow2024-salary.webp diff --git a/static/images/struct-padding.webp b/assets/images/struct-padding.webp similarity index 100% rename from static/images/struct-padding.webp rename to assets/images/struct-padding.webp diff --git a/static/images/typed-fsm/2.1-1.webp b/assets/images/typed-fsm/2.1-1.webp similarity index 100% rename from static/images/typed-fsm/2.1-1.webp rename to assets/images/typed-fsm/2.1-1.webp diff --git a/static/images/typed-fsm/2.1-2.webp b/assets/images/typed-fsm/2.1-2.webp similarity index 100% rename from static/images/typed-fsm/2.1-2.webp rename to assets/images/typed-fsm/2.1-2.webp diff --git a/static/images/typed-fsm/2.1-3.webp b/assets/images/typed-fsm/2.1-3.webp similarity index 100% rename from static/images/typed-fsm/2.1-3.webp rename to assets/images/typed-fsm/2.1-3.webp diff --git a/static/images/typed-fsm/2.1-4.webp b/assets/images/typed-fsm/2.1-4.webp similarity index 100% rename from static/images/typed-fsm/2.1-4.webp rename to assets/images/typed-fsm/2.1-4.webp diff --git a/static/images/typed-fsm/2.2-1.webp b/assets/images/typed-fsm/2.2-1.webp similarity index 100% rename from static/images/typed-fsm/2.2-1.webp rename to assets/images/typed-fsm/2.2-1.webp diff --git a/static/images/typed-fsm/2.3-1.webp b/assets/images/typed-fsm/2.3-1.webp similarity index 100% rename from static/images/typed-fsm/2.3-1.webp rename to assets/images/typed-fsm/2.3-1.webp diff --git a/static/images/zon-multihash.webp b/assets/images/zon-multihash.webp similarity index 100% rename from static/images/zon-multihash.webp rename to assets/images/zon-multihash.webp diff --git a/assets/index.css b/assets/index.css new file mode 100644 index 0000000..0450b32 --- /dev/null +++ b/assets/index.css @@ -0,0 +1,5 @@ +.content{ + font-size: 1.2rem; + display: flex; + flex-direction: column; +} \ No newline at end of file diff --git a/assets/style.css b/assets/style.css new file mode 100644 index 0000000..38b446f --- /dev/null +++ b/assets/style.css @@ -0,0 +1,253 @@ +:root { + /* TODO */ + --bg: #fff; + --fg: #111; + --border: #aaa; + --link: #0070f3; +} +@media (prefers-color-scheme: dark) { + :root { + --bg: #181818; + --fg: #eee; + --border: #444; + --link: #4ea1ff; + } +} + +.center{ + display: flex; + justify-content: center; + align-items: center; +} +.large{ + font-size: 2rem; + line-height: 2; +} +.bold{ + font-weight: bold; +} + +body { + margin: 20px auto; + max-width: 60vw; + @media screen and (max-width: 800px) { + max-width: 93vw; + } + line-height: 1.5; + background: var(--bg); + color: var(--fg); +} + +a { + color: inherit; + line-break: anywhere; +} + +p:has(+ pre) { + margin-bottom: 0; +} + +p + pre { + margin-top: 5px; +} + +pre { + overflow: auto; + border-top: 1px solid var(--border); + border-bottom: 1px solid var(--border); + padding: 4px 0; +} + +pre code { + tab-size: 4; + -moz-tab-size: 4; +} + +code { + font-variant-ligatures: none; + font-feature-settings: "liga" 0; + font-family: "JetBrains Mono", monospace; +} + +p > code, +a > code, +h1 > code, +h2 > code, +h3 > code, +h4 > code, +h5 > code, +li > code { + font-weight: bold; + font-size: 1em; +} + +.header { + display: flex; + justify-content: space-between; + align-items: baseline; + @media screen and (max-width: 800px) { + justify-content: center; + } +} +.site-title { + display: inline-block; + text-decoration: none; + color: inherit; + @media screen and (max-width: 800px) { + display: none; + } +} + +table{ + border-collapse: collapse; +} + +th, td { + border: 1px solid var(--border); + padding: 0.5rem; +} + +blockquote { + border-left: 2px solid var(--border); + padding-left: 1rem; + margin-left: 1rem; + margin-right: 1rem; +} + +img { + max-width: 100%; +} + +figcaption { + font-size: small; + text-align: center; +} + +nav { + display: inline-block; +} +nav a { + text-decoration: none; + font-size: large; + margin: 0 10px; + @media screen and (max-width: 800px) { + margin: 0 8px; + } +} +nav a:first-child{ + margin-left: 0; +} +nav a:last-child{ + margin-right: 0; +} + +footer > div { + display: flex; + flex-direction: row; + justify-content: space-between; + flex-wrap: wrap; +} + +footer > div div { + margin: auto 0; +} + +footer > div i { + font-size: 24px; + margin: 0 5px; +} + +footer > div a { + text-decoration: none; +} + +footer > div img { + height: 1.5em; + width: auto; + vertical-align: middle; + + filter: invert(0%) sepia(0%) saturate(0%) hue-rotate(0deg) brightness(0%) contrast(100%); +} + +@media (prefers-color-scheme: dark) { + footer > div img { + filter: invert(100%) sepia(0%) saturate(0%) hue-rotate(0deg) brightness(1.2) contrast(100%); + } +} + +#prev-next { + display: flex; + justify-content: space-between; + align-items: center; + margin-top: 20px; + padding-top: 5px; + border-top: 2px solid var(--border); +} + +#prev-next a { + text-decoration: none; +} + +#prev-next > :first-child span::before{ + content: "←"; +} + +#prev-next > :last-child span::after{ + content: "→"; +} + +::-webkit-scrollbar { + width: 10px; + height: 10px; + background: var(--bg); +} +::-webkit-scrollbar-thumb { + background: #ccc; + border-radius: 8px; + border: 2px solid var(--bg); + min-height: 40px; +} +::-webkit-scrollbar-thumb:hover { + background: #bbb; +} +::-webkit-scrollbar-corner { + background: var(--bg); +} + +@media (prefers-color-scheme: dark) { + ::-webkit-scrollbar { + background: var(--bg); + } + ::-webkit-scrollbar-thumb { + background: #444; + border: 2px solid var(--bg); + } + ::-webkit-scrollbar-thumb:hover { + background: #555; + } + ::-webkit-scrollbar-corner { + background: var(--bg); + } +} + +html { + scrollbar-width: thin; + scrollbar-color: #ccc var(--bg); +} +@media (prefers-color-scheme: dark) { + html { + scrollbar-color: #444 var(--bg); + } +} + +#meta p{ + margin: 0; +} + +#meta #author::before{ + content: "借由:"; +} + +h1{ + margin-bottom: 0; +} diff --git a/config.toml b/config.toml deleted file mode 100644 index efa402f..0000000 --- a/config.toml +++ /dev/null @@ -1,119 +0,0 @@ -baseURL = 'https://ziglang.cc' -languageCode = 'en' -defaultContentLanguage = 'zh-cn' -title = 'Zig 语言中文社区' -description = 'Zig Chinese Community is dedicated to sharing and spreading the use of Zig language among Chinese users.' -copyright = """ © 2022–2025 - | Source Code - | BY-NC-ND 4.0 - | RSS -""" - -[[menu.main]] - name = "学习 Zig" - weight = 11 - url = "/learn" -[[menu.main]] - name = "月刊" - weight = 20 - url = "/monthly" -[[menu.main]] - name = "博客" - weight = 21 - url = "/post" -[[menu.main]] - name = "贡献" - weight = 30 - url = "/contributing" -[[menu.main]] - name = "社区" - weight = 40 - url = "/community" - -[params] - github_repo = "https://github.com/zigcc/zigcc.github.io" - offlineSearch = true - time_format_blog = "2006-01-02" - [params.giscus] - repo = "zigcc/zigcc.github.io" - repoId = "R_kgDOHr7nSg" - category = "Announcements" - categoryId = "DIC_kwDOHr7nSs4CQUsK" - -[params.ui] -# navbar_logo = false -showLightDarkModeMenu = true - -[params.links] -[[params.links.user]] - name = "GitHub Discussion" - url = "https://github.com/orgs/zigcc/discussions" - icon = "fab fa-github" - desc = "新手提问;经验分享" -[[params.links.user]] - name = "Discord" - url = "https://discord.gg/UraRxD6WXD" - icon = "fab fa-discord" -[[params.links.user]] - name = "Telegram" - url = "https://t.me/ZigChinese" - icon = "fab fa-telegram" -[[params.links.user]] - name = "微信群" - url = "https://github.com/orgs/zigcc/discussions/134" - icon = "fab fa-weixin" -[[params.links.user]] - name = "微信公众号" - url = "https://github.com/zigcc/.github/blob/main/zig_mp.png" - icon = "fab fa-weixin" - desc = "跟进社区最新动态" -[[params.links.user]] - name = "邮件" - url = "mailto:hello@ziglang.cc" - icon = "fa fa-envelope" - desc = "" - -[[params.links.developer]] - name = "文章供稿" - url = "/post/2023/09/05/hello-world/" - icon = "fab fa-blogger" - desc = "分享 Zig 使用经验,改进网站体验" -[[params.links.developer]] - name = "Zig 圣经" - url = "https://course.ziglang.cc/" - icon = "fa fa-book" - desc = "完善、改进圣经内容" -[[params.links.developer]] - name = "线上会议" - url = "/post/news" - icon = "fa-brands fa-meetup" - desc = "我们会定期举行线上会议,畅聊 Zig 中的一切" - -[module] -# proxy = "https://goproxy.cn,direct" - [[module.imports]] - path = "github.com/google/docsy" - -[frontmatter] - date = [":filename", ":default", ":fileModTime"] - lastmod = ['lastmod', ':git', ':fileModTime', ':default'] - -[permalinks] - post = "/post/:year/:month/:day/:slug/" - -[markup] - [markup.tableOfContents] - startLevel = 1 - endLevel = 8 - [markup.goldmark] - [markup.goldmark.renderer] - unsafe = true - [markup.goldmark.parser.attribute] - block = true - # https://gohugo.io/getting-started/configuration-markup/#highlight - [markup.highlight] - style = "pygments" - linenos = true - -[outputs] -section = [ "HTML", "RSS", "print" ] diff --git a/content/_index.md b/content/_index.md deleted file mode 100644 index a0e4838..0000000 --- a/content/_index.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Zig 语言中文社区 ---- - -{{% blocks/cover height="full" %}} - - - -Zig 中文社区致力于在中文用户中分享和传播 Zig 语言! - -我们是一群对 Zig 编程语言充满热情的开发者、学习者和爱好者。我们致力于: - -1. 分享 Zig 相关的知识和经验 -2. 翻译 Zig 官方文档和重要资源 -3. 组织线上线下的学习活动和讨论 -4. 推广 Zig 语言在中文开发者中的应用 - -无论你是 Zig 专家还是初学者,[我们都欢迎你的加入](/community)! - -贡献 - -学习 - - - - -{{% /blocks/cover %}} diff --git a/content/about.smd b/content/about.smd new file mode 100644 index 0000000..773dbbc --- /dev/null +++ b/content/about.smd @@ -0,0 +1,36 @@ +--- +.date = "2024-08-04T08:51:07+0800", +.title = "学习 Zig", +.author = "ZigCC", +.layout = "index.shtml", +.draft = false, +--- + +# 资料 + +由于 Zig 目前还处于快速迭代,因此最权威的资料无疑是官方的 [Zig Language +Reference](https://ziglang.org/documentation/master/),遇到语言的细节问题,基本都可以在这里找到答案。 +其次是社区的一些高质量教程,例如: + +[Zig Guide](https://zig.guide/) +英文资料, [Sobeston](https://github.com/Sobeston) 用户编写 + +[Zig in 30 minutes](https://gist.github.com/ityonemo/769532c2017ed9143f3571e5ac104e50) + +[学习 Zig](https://ziglang.cc/learning-zig/) +该系列教程最初由 Karl Seguin +编写,该教程行文流畅,讲述的脉络由浅入深,深入浅出,是入门 Zig +非常不错的选择 + +[Zig 语言圣经](https://course.ziglang.cc) +一份内容全面、深入浅出介绍 Zig 的教程 + +[ziglings/exercises](https://codeberg.org/ziglings/exercises/) +Learn the Zig programming language by fixing tiny broken programs. + +[Zig Cookbook](https://cookbook.ziglang.cc/) +A collection of simple Zig programs that demonstrate good practices to +accomplish common programming tasks + +[Awesome Zig](https://github.com/zigcc/awesome-zig) +A collection of some awesome public Zig programming language projects. diff --git a/content/about/_index.org b/content/about/_index.org deleted file mode 100644 index 59a03d3..0000000 --- a/content/about/_index.org +++ /dev/null @@ -1,46 +0,0 @@ -#+TITLE: 学习 Zig -#+DATE: 2024-08-04T08:51:07+0800 -#+LASTMOD: 2024-08-18T11:48:26+0800 -{{% blocks/cover title="学习 Zig" image_anchor="bottom" height="auto" %}} - - -{{% /blocks/cover %}} - -{{% blocks/section %}} - -* 资料 -由于 Zig 目前还处于快速迭代,因此最权威的资料无疑是官方的 [[https://ziglang.org/documentation/master/][Zig Language Reference]],遇到语言的细节问题,基本都可以在这里找到答案。 -其次是社区的一些高质量教程,例如: -- [[https://zig.guide/][Zig Guide]] :: 英文资料, [[https://github.com/Sobeston][Sobeston]] 用户编写 -- [[https://gist.github.com/ityonemo/769532c2017ed9143f3571e5ac104e50][Zig in 30 minutes]] :: -- [[https://ziglang.cc/learning-zig/][学习 Zig]] :: 该系列教程最初由 Karl Seguin 编写,该教程行文流畅,讲述的脉络由浅入深,深入浅出,是入门 Zig 非常不错的选择 -- [[https://course.ziglang.cc][Zig 语言圣经]] :: 一份内容全面、深入浅出介绍 Zig 的教程 -- [[https://codeberg.org/ziglings/exercises/][ziglings/exercises]] :: Learn the Zig programming language by fixing tiny broken programs. -- [[https://cookbook.ziglang.cc/][Zig Cookbook]] :: A collection of simple Zig programs that demonstrate good practices to accomplish common programming tasks -- [[https://github.com/zigcc/awesome-zig][Awesome Zig]] :: A collection of some awesome public Zig programming language projects. - -* 版本管理 -推荐使用版本管理工具 [[/post/2023/10/14/zig-version-manager/][asdf]] 来安装 Zig,具体步骤: -#+begin_src bash -git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.14.0 -cat <<'EOF' >> $HOME/.bashrc -source "$HOME/.asdf/asdf.sh" -source "$HOME/.asdf/completions/asdf.bash" -EOF - -asdf plugin-add zig https://github.com/zigcc/asdf-zig.git - -# 安装最新版 -asdf install zig latest -asdf global zig latest -zig version -#+end_src - -{{% /blocks/section %}} - -{{% blocks/section %}} - -# This is another section -{.text-center} - -{{% /blocks/section %}} diff --git a/content/community/_index.md b/content/community.smd similarity index 50% rename from content/community/_index.md rename to content/community.smd index dba0271..2a52e80 100644 --- a/content/community/_index.md +++ b/content/community.smd @@ -1,22 +1,18 @@ --- -title: 社区 -params: - contributingUrl: /contributing ---- - -{{% blocks/section %}} -让我们一起探索 Zig 的魅力,推动 Zig 在中文社区内的发展! -{.text-center} - -{{% /blocks/section %}} +.title = "About", +.date = @date("1990-01-01T00:00:00"), +.author = "ZigCC", +.layout = "index.shtml", +.draft = false, +--- -{{% blocks/section color="white" %}} +[让我们一起探索 Zig 的魅力,推动 Zig 在中文社区内的发展!]($text.attrs('center','large','bold')) -# 网站更新日志 +# [网站更新日志]($section.id('website-update-log')) +- **2025-06-30:** 切换到 [zine](https://zine-ssg.io/) - **2024-08-18:** 切换主题 [docsy](https://github.com/google/docsy) - **2024-07-14:** 启用 Zig 社区微信 2 群 - **2024-03-29:** 使用自定义域名 ziglang.cc - **2022-12-10:** 切换主题 [cupper-hugo](https://github.com/zwbetz-gh/cupper-hugo-theme) –> [hugo-xmin](https://github.com/yihui/hugo-xmin) - **2022-07-20:** 首次上线 - {{% /blocks/section %}} diff --git a/content/contributing.md b/content/contributing.md deleted file mode 100644 index aa93554..0000000 --- a/content/contributing.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: 如何贡献 -type: docs ---- - -Zig 中文社区是一个开放的组织,我们致力于推广 Zig 在中文群体中的使用,有多种方式可以参与进来: - -1. 供稿,分享自己使用 Zig 的心得,方式见下文 -2. 改进 zigcc 组织下的开源项目,这是 [open issues](https://github.com/search?q=state%3Aopen+org%3Azigcc++NOT+%E6%97%A5%E6%8A%A5&type=issues&ref=advsearch) -3. 参与不定期的[线上会议](/post/news/) - -# 供稿方式 - -1. Fork 仓库 https://github.com/zigcc/zigcc.github.io -2. 在 `content/post` 内添加自己的文章(md 或 org 格式均可),文件命名为: `${YYYY}-${MM}-${DD}-${SLUG}.md` -3. 文件开始需要包含一些描述信息,例如: - -```plain ---- -title: 欢迎 Zig 爱好者向本网站供稿 -author: 刘家财 -date: '2023-09-05T16:13:13+0800' ---- -``` - -## 本地预览 - -在写完文章后,可以使用 [Hugo](https://gohugo.io/) 进行本地预览,只需在项目根目录执行 `hugo server`,这会启动一个 HTTP 服务,默认的访问地址是: http://localhost:1313/ - -## 发布平台 - -- [ZigCC 网站](https://ziglang.cc) -- [ZigCC 公众号](https://github.com/zigcc/.github/raw/main/zig_mp.png) diff --git a/content/contributing.smd b/content/contributing.smd new file mode 100644 index 0000000..7bd79fb --- /dev/null +++ b/content/contributing.smd @@ -0,0 +1,45 @@ +--- +.title = "About", +.date = @date("1990-01-01T00:00:00"), +.author = "ZigCC", +.layout = "index.shtml", +.draft = false, +--- + +Zig 中文社区是一个开放的组织,我们致力于推广 Zig 在中文群体中的使用,有多种方式可以参与进来: + +1. 供稿,分享自己使用 Zig 的心得,方式见下文 +2. 改进 zigcc 组织下的开源项目,这是 [open issues](https://ask.ziglang.cc/github) + +# [供稿方式]($section.id('contribute')) + +1. Fork 仓库 https://github.com/zigcc/zigcc.github.io +2. 在 `content/post` 内添加自己的文章(smd格式),文件命名为: `${YYYY}-${MM}-${DD}-${SLUG}.smd` +3. 文件开始需要包含一些描述信息,例如: + +``` +--- +.title = "文章标题", +.date = @date("2025-06-05T16:00:00+0800"), +.author = "刘家财", +.layout = "post.shtml", +.draft = false, +.custom = { + .math = true, // 如果你要用到数学公式,请 设置 math 为 true; 否则可以忽略 + .mermaid = true, // 如果你要用到 mermaid 图表,请设置 mermaid 为 true; 否则可以忽略 +}, +--- +``` + +# [本地预览]($section.id('本地预览')) + +首先你得安装 `zine`,安装方法见 [Quick Start](https://zine-ssg.io/quickstart/),之后就可以通过执行 `zine` 命令来预览你的文章。 + +```bash +zine +``` + +# [发布平台]($section.id('publishing-platform')) + +- [ZigCC 网站](https://ziglang.cc) +- [ZigCC 公众号](https://github.com/zigcc/.github/raw/main/zig_mp.png) diff --git a/content/index.smd b/content/index.smd new file mode 100644 index 0000000..038e89d --- /dev/null +++ b/content/index.smd @@ -0,0 +1,20 @@ +--- +.title = "", +.date = @date("1990-01-01T00:00:00"), +.author = "ZigCC", +.layout = "index.shtml", +.draft = false, +--- + +[]($image.siteAsset('icons/zigcc.svg').id('logo')) + +Zig 中文社区致力于在中文用户中分享和传播 Zig 语言! + +我们是一群对 Zig 编程语言充满热情的开发者、学习者和爱好者。我们致力于: + +1. 分享 Zig 相关的知识和经验 +2. 翻译 Zig 官方文档和重要资源 +3. 组织线上线下的学习活动和讨论 +4. 推广 Zig 语言在中文开发者中的应用 + +无论你是 Zig 专家还是初学者,[我们都欢迎你的加入]($link.page('contributing'))! diff --git a/content/learn/coding-in-zig.md b/content/learn/coding-in-zig.smd similarity index 97% rename from content/learn/coding-in-zig.md rename to content/learn/coding-in-zig.smd index bf12213..3b6de98 100644 --- a/content/learn/coding-in-zig.md +++ b/content/learn/coding-in-zig.smd @@ -1,13 +1,16 @@ --- -title: "实战" -weight: 10 +.title = "实战", +.date = @date("2024-01-10T00:00:00"), +.author = "Karl Seguin; ZigCC", +.layout = "learn.shtml", +.draft = false, --- > 原文地址: 在介绍了 Zig 语言的大部分内容之后,我们将对一些主题进行回顾,并展示几种使用 Zig 编程时一些实用的技巧。在此过程中,我们将介绍更多的标准库,并介绍一些稍复杂些的代码片段。 -## 悬空指针 Dangling Pointers +# [悬空指针 Dangling Pointers]($section.id('dangling-pointers')) 我们首先来看看更多关于悬空指针的例子。这似乎是一个奇怪的问题,但如果你之前主要使用带垃圾回收的语言,这可能是你学习 Zig 最大的障碍。 @@ -102,7 +105,7 @@ const User = struct { 如果把所有东西都放在一个函数中,再加上一个像 `User` 这样的小值,这仍然像是一个人为制造的问题。我们需要一个能让数据所有权成为当务之急的例子。 -## 所有权 Ownership +# [所有权 Ownership]($section.id('ownership')) 我喜欢哈希表(HashMap),因为这是每个人都知道并且会经常使用的结构。它们有很多不同的用例,其中大部分你可能都用过。虽然哈希表可以用在一个短期查找的地方,但通常用于长期查找,因此插入其内的值需要同样长的生命周期。 @@ -215,7 +218,7 @@ defer { 我保证,关于悬挂指针和内存管理的讨论已经结束了。我们所讨论的内容可能还不够清晰或过于抽象。当你有更实际的问题需要解决时,再重新讨论这个问题也不迟。不过,如果你打算编写任何稍具规模(non-trivial)的程序,这几乎肯定是你需要掌握的内容。当你觉得可以的时候,我建议你参考上面这个示例,并自己动手实践一下。引入一个 `UserLookup` 类型来封装我们必须做的所有内存管理。尝试使用 `*User` 代替 `User`,在堆上创建用户,然后像处理键那样释放它们。编写覆盖新结构的测试,使用 `std.testing.allocator` 确保不会泄漏任何内存。 -## ArrayList +# [ArrayList]($section.id('arraylist')) 现在你可以忘掉我们的 `IntList` 和我们创建的通用替代方案了。Zig 标准库中有一个动态数组实现:`std.ArrayList(T)`。 @@ -310,9 +313,9 @@ pub fn main() !void { } ``` -## Anytype +# [Anytype]($section.id('anytype')) -在[语言概述的第一部分](02-language-overview-part1.md)中,我们简要介绍了 `anytype`。这是一种非常有用的编译时 duck 类型。下面是一个简单的 logger: +在[语言概述的第一部分](language-overview-1)中,我们简要介绍了 `anytype`。这是一种非常有用的编译时 duck 类型。下面是一个简单的 logger: ```zig pub const Logger = struct { @@ -380,7 +383,7 @@ fn stringify( 第一个参数 `value: anytype` 是显而易见的,它是要序列化的值,可以是任何类型(实际上,Zig 的 JSON 序列化器不能序列化某些类型,比如 HashMap)。我们可以猜测,`out_stream` 是写入 JSON 的地方,但至于它需要实现什么方法,你和我一样猜得到。唯一的办法就是阅读源代码,或者传递一个假值,然后使用编译器错误作为我们的文档。如果有更好的自动文档生成器,这一点可能会得到改善。不过,我希望 Zig 能提供接口,这已经不是第一次了。 -## @TypeOf +# [@TypeOf]($section.id('typeof')) 在前面的部分中,我们使用 `@TypeOf` 来帮助我们检查各种变量的类型。从我们的用法来看,你可能会认为它返回的是字符串类型的名称。然而,鉴于它是一个 PascalCase 风格函数,你应该更清楚:它返回的是一个 `type`。 @@ -409,7 +412,7 @@ pub const User = struct { 更常见的是 `@TypeOf` 与 `@typeInfo` 配对,后者返回一个 `std.builtin.Type`。这是一个功能强大的带标签的联合(tagged union),可以完整描述一个类型。`std.json.stringify` 函数会递归地调用它,以确定如何将提供的 `value` 序列化。 -# 构建系统 +# [构建系统]($section.id('build-system')) 如果你通读了整本指南,等待着深入了解如何建立更复杂的项目,包括多个依赖关系和各种目标,那你就要失望了。Zig 拥有强大的构建系统,以至于越来越多的非 Zig 项目都在使用它,比如 libsodium。不幸的是,所有这些强大的功能都意味着,对于简单的需求来说,它并不是最容易使用或理解的。 @@ -494,7 +497,7 @@ test "dummy build test" { 这是启动和运行构建系统所需的最低配置。但是请放心,如果你需要构建你的程序,Zig 内置的功能大概率能覆盖你的需求。最后,你可以(也应该)在你的项目根目录下使用 `zig init`,让 Zig 为你创建一个文档齐全的 `build.zig` 文件。 -## 第三方依赖 +# [第三方依赖]($section.id('third-party-dependencies')) Zig 的内置软件包管理器相对较新,因此存在一些缺陷。虽然还有改进的余地,但它目前还是可用的。我们需要了解两个部分:创建软件包和使用软件包。我们将对其进行全面介绍。 diff --git a/content/learn/conclusion.md b/content/learn/conclusion.smd similarity index 93% rename from content/learn/conclusion.md rename to content/learn/conclusion.smd index 1f9400b..5f33459 100644 --- a/content/learn/conclusion.md +++ b/content/learn/conclusion.smd @@ -1,6 +1,9 @@ --- -title: "总结" -weight: 11 +.title = "总结", +.date = @date("2024-01-11T00:00:00"), +.author = "Karl Seguin; ZigCC", +.layout = "learn.shtml", +.draft = false, --- > 原文总结: diff --git a/content/learn/generics.md b/content/learn/generics.smd similarity index 98% rename from content/learn/generics.md rename to content/learn/generics.smd index e3d8439..6754604 100644 --- a/content/learn/generics.md +++ b/content/learn/generics.smd @@ -1,6 +1,9 @@ --- -title: "泛型" -weight: 9 +.title = "泛型", +.date = @date("2024-01-09T00:00:00"), +.author = "Karl Seguin; ZigCC", +.layout = "learn.shtml", +.draft = false, --- > 原文地址: diff --git a/content/learn/heap-memory-and-allocator.md b/content/learn/heap-memory.smd similarity index 97% rename from content/learn/heap-memory-and-allocator.md rename to content/learn/heap-memory.smd index 4dd9e31..6a8ae6a 100644 --- a/content/learn/heap-memory-and-allocator.md +++ b/content/learn/heap-memory.smd @@ -1,6 +1,9 @@ --- -title: "堆内存和分配器" -weight: 8 +.title = "堆内存", +.date = @date("2024-01-08T00:00:00"), +.author = "Karl Seguin; ZigCC", +.layout = "learn.shtml", +.draft = false, --- > 原文地址: @@ -11,7 +14,7 @@ weight: 8 本部分分为两个主题。第一个主题是第三个内存区域--堆的总体概述。另一个主题是 Zig 直接而独特的堆内存管理方法。即使你熟悉堆内存,比如使用过 C 语言的 `malloc`,你也会希望阅读第一部分,因为它是 Zig 特有的。 -## 堆 +# [堆]($section.id('heap')) 堆是我们可以使用的第三个也是最后一个内存区域。与全局数据和调用栈相比,堆有点像蛮荒之地:什么都可以使用。具体来说,在堆中,我们可以在运行时创建大小已知的内存,并完全控制其生命周期。 @@ -49,7 +52,7 @@ fn getRandomCount() !u8 { 一般来说,每次 `alloc` 都会有相应的 `free`。`alloc`分配内存,`free`释放内存。不要让这段简单的代码限制了你的想象力。这种 `try alloc` + `defer free` 的模式很常见,这是有原因的:在我们分配内存的地方附近释放相对来说是万无一失的。但同样常见的是在一个地方分配,而在另一个地方释放。正如我们之前所说,堆没有内置的生命周期管理。你可以在 HTTP 处理程序中分配内存,然后在后台线程中释放,这是代码中两个完全独立的部分。 -## defer 和 errdefer +# [defer 和 errdefer]($section.id('defer-and-errdefer')) 说句题外话,上面的代码介绍了一个新的语言特性:`defer`,它在退出作用域时执行给定的代码。『作用域退出』包括到达作用域的结尾或从作用域返回。严格来说, `defer` 与分配器或内存管理并无严格关系;你可以用它来执行任何代码。但上述用法很常见。 @@ -97,7 +100,7 @@ pub const Game = struct { > `init` 和 `deinit` 的名字并不特殊。它们只是 Zig 标准库使用的,也是社区采纳的名称。在某些情况下,包括在标准库中,会使用 `open` 和 `close`,或其他更适当的名称。 -## 双重释放和内存泄漏 +# [双重释放和内存泄漏]($section.id('double-free-and-memory-leak')) 上面提到过,没有规则规定什么时候必须释放什么东西。但事实并非如此,还是有一些重要规则,只是它们不是强制的,需要你自己格外小心。 @@ -156,7 +159,7 @@ fn isSpecial(allocator: Allocator, name: [] const u8) !bool { 至少在双重释放的情况下,我们的程序会遭遇严重崩溃。内存泄漏可能很隐蔽。不仅仅是根本原因难以确定。真正的小泄漏或不常执行的代码中的泄漏甚至很难被发现。这是一个很常见的问题,Zig 提供了帮助,我们将在讨论分配器时看到。 -## 创建与销毁 +# [创建与销毁]($section.id('create-and-destroy')) `std.mem.Allocator`的`alloc`方法会返回一个切片,其长度为传递的第二个参数。如果想要单个值,可以使用 `create` 和 `destroy` 而不是 `alloc` 和 `free`。 @@ -230,7 +233,7 @@ fn init(allocator: std.mem.Allocator, id: u64, power: i32) !*User{ 请记住,`create` 返回一个 `!*User`,所以我们的 `user` 是 `*User` 类型。 -## 分配器 Allocator +# [分配器 Allocator]($section.id('allocator')) Zig 的核心原则之一是无隐藏内存分配。根据你的背景,这听起来可能并不特别。但这与 C 语言中使用标准库的 malloc 函数分配内存的做法形成了鲜明的对比。在 C 语言中,如果你想知道一个函数是否分配内存,你需要阅读源代码并查找对 malloc 的调用。 @@ -251,7 +254,7 @@ defer allocator.free(say); 如果你正在构建一个库,那么最好接受一个 `std.mem.Allocator`,然后让库的用户决定使用哪种分配器实现。否则,你就需要选择正确的分配器,正如我们将看到的,这些分配器并不相互排斥。在你的程序中创建不同的分配器可能有很好的理由。 -## 通用分配器 GeneralPurposeAllocator +# [通用分配器 GeneralPurposeAllocator]($section.id('general-purpose-allocator')) 顾名思义,`std.heap.GeneralPurposeAllocator` 是一种通用的、线程安全的分配器,可以作为应用程序的主分配器。对于许多程序来说,这是唯一需要的分配器。程序启动时,会创建一个分配器并传递给需要它的函数。我的 HTTP 服务器库中的示例代码就是一个很好的例子: @@ -296,7 +299,7 @@ var gpa = std.heap.GeneralPurposeAllocator(.{}){}; 类型是什么,字段在哪里?类型其实是 `std.heap.general_purpose_allocator.Config`,但它并没有直接暴露出来,这也是我们没有显式给出类型的原因之一。没有设置字段是因为 Config 结构定义了默认值,我们将使用默认值。这是配置、选项的中常见的模式。事实上,我们在下面几行向 `init` 传递 `.{.port = 5882}` 时又看到了这种情况。在本例中,除了端口这一个字段外,我们都使用了默认值。 -## std.testing.allocator +# [std.testing.allocator]($section.id('std-testing-allocator')) 希望当我们谈到内存泄漏时,你已经足够烦恼,而当我提到 Zig 可以提供帮助时,你肯定渴望了解更多这方面内容。这种帮助来自 `std.testing.allocator`,它是一个 `std.mem.Allocator` 实现。目前,它基于通用分配器(GeneralPurposeAllocator)实现,并与 Zig 的测试运行器进行了集成,但这只是实现细节。重要的是,如果我们在测试中使用 `std.testing.allocator`,就能捕捉到大部分内存泄漏。 @@ -420,7 +423,7 @@ self.allocator.free(self.items); 将`items`复制到我们的 `larger` 切片中后, 添加最后一行`free`可以解决泄漏的问题。如果运行 `zig test learning.zig`,便不会再有错误。 -## ArenaAllocator +# [ArenaAllocator]($section.id('arena-allocator')) 通用分配器(GeneralPurposeAllocator)是一个合理的默认设置,因为它在所有可能的情况下都能很好地工作。但在程序中,你可能会遇到一些固定场景,使用更专业的分配器可能会更合适。其中一个例子就是需要在处理完成后丢弃的短期状态。解析器(Parser)通常就有这样的需求。一个 `parse` 函数的基本轮廓可能是这样的 @@ -505,7 +508,7 @@ defer list.deinit(); 最后举个简单的例子,我上面提到的 HTTP 服务器在响应中暴露了一个 `ArenaAllocator`。一旦发送了响应,它就会被清空。由于`ArenaAllocator`的生命周期可以预测(从请求开始到请求结束),因此它是一种高效的选择。就性能和易用性而言,它都是高效的。 -## 固定缓冲区分配器 FixedBufferAllocator +# [固定缓冲区分配器 FixedBufferAllocator]($section.id('fixed-buffer-allocator')) 我们要讨论的最后一个分配器是 `std.heap.FixedBufferAllocator`,它可以从我们提供的缓冲区(即 `[]u8`)中分配内存。这种分配器有两大好处。首先,由于所有可能使用的内存都是预先创建的,因此速度很快。其次,它自然而然地限制了可分配内存的数量。这一硬性限制也可以看作是一个缺点。另一个缺点是,`free` 和 `destroy` 只对最后分配/创建的项目有效(想想堆栈)。调用释放非最后分配的内存是安全的,但不会有任何作用。 diff --git a/content/learn/_index.md b/content/learn/index.smd similarity index 70% rename from content/learn/_index.md rename to content/learn/index.smd index db72046..64e2d68 100644 --- a/content/learn/_index.md +++ b/content/learn/index.smd @@ -1,15 +1,30 @@ --- -title: Learning Zig 中文翻译 -type: docs -cascade: - - type: docs +.title = "Learning Zig 中文翻译", +.date = @date("2024-01-01T00:00:00"), +.author = "Karl Seguin; ZigCC", +.layout = "learn.shtml", +.draft = false, --- +# [《学习 Zig》 目录]($section.id('table-of-contents')) + +- [前言](./preface) +- [安装 Zig](./installing-zig) +- [语言概述 - 第一部分](./language-overview-1) +- [语言概述 - 第二部分](./language-overview-2) +- [编码风格](./style-guide) +- [指针](./pointers) +- [栈内存](./stack-memory) +- [堆内存和分配器](./heap-memory) +- [泛型](./generics) +- [实战](./coding-in-zig) +- [总结](./conclusion) + [《学习 Zig》](https://www.openmymind.net/learning_zig/)系列教程最初由 [Karl Seguin](https://github.com/karlseguin) 编写,该教程行文流畅,讲述的脉络由浅入深,深入浅出,是入门 Zig 非常不错的选择。因此,[Zig 中文社区](https://ziglang.cc)将其翻译成中文,便于在中文用户内阅读与传播。 初次接触 Zig 的用户可以按序号依次阅读,对于有经验的 Zig 开发者可按需阅读感兴趣的章节。 -## 关于原作者 +# [关于原作者]($section.id('about-original-author')) [Karl Seguin](https://www.linkedin.com/in/karlseguin/) 在多个领域有着丰富经验,前微软 MVP,他撰写了大量文章,是多个微软公共新闻组的活跃成员。现居新加坡。他还是以下教程的作者: @@ -19,21 +34,24 @@ cascade: 可以在 找到他的博客,或者通过 [@karlseguin](http://twitter.com/karlseguin) 在 Twitter 上关注他。 -## 翻译原则 +# [翻译原则]($section.id('translation-principles')) 技术文档的翻译首要原则是准确,但在准确的前提下如何保证『信、达、雅』?这是个挑战,在翻译本教程时,在某些情况下会根据上下文进行意译,便于中文读者阅读。 最后,感谢翻译者的无私贡献。❤️️ -## 离线阅读 +# [离线阅读]($section.id('offline-reading')) 在本仓库的 [release 页面](https://github.com/zigcc/zigcc.github.io/releases)会定期将本教程导出为 PDF 格式,读者可按需下载。 -读者也可以使用右侧导航栏中的『[整节打印](_print)』将当前版本教程保存为 PDF 格式。 +```html + + +``` -## 其他学习资料 +# [其他学习资料]($section.id('other-learning-resources')) -由于 Zig 目前还处于快速迭代,因此最权威的资料无疑是官方的 [Zig Language Reference](https://ziglang.org/documentation/master/),遇到语言的细节问题,基本都可以在这里找到答案。 其次是社区的一些高质量教程,例如: +由于 Zig 目前还处于快速迭代,因此最权威的资料无疑是官方的 [Zig Language Reference](https://ziglang.org/documentation/master/),遇到语言的细节问题,基本都可以在这里找到答案。其次是社区的一些高质量教程,例如: - **[Zig 日报](https://github.com/zigcc/forum/issues):** - **[Zig 语言圣经](https://course.ziglang.cc):** 一份内容全面、深入浅出介绍 Zig 的教程 diff --git a/content/learn/installing-zig.md b/content/learn/installing-zig.smd similarity index 87% rename from content/learn/installing-zig.md rename to content/learn/installing-zig.smd index c07e42d..f048232 100644 --- a/content/learn/installing-zig.md +++ b/content/learn/installing-zig.smd @@ -1,6 +1,9 @@ --- -title: "安装 Zig" -weight: 2 +.title = "安装 Zig", +.date = @date("2024-01-02T00:00:00"), +.author = "Karl Seguin; ZigCC", +.layout = "learn.shtml", +.draft = false, --- > 原文地址: @@ -18,7 +21,7 @@ brew install asdf asdf plugin add zig https://github.com/zigcc/asdf-zig.git -# 安装最新版 +# 安装最新稳定版 asdf install zig latest # 设置为全局版本 diff --git a/content/learn/language-overview-part1.md b/content/learn/language-overview-1.smd similarity index 96% rename from content/learn/language-overview-part1.md rename to content/learn/language-overview-1.smd index 241d15a..76ce6b0 100644 --- a/content/learn/language-overview-part1.md +++ b/content/learn/language-overview-1.smd @@ -1,6 +1,9 @@ --- -title: "语言概述 - 第一部分" -weight: 3 +.title = "语言概述 - 第一部分", +.date = @date("2024-01-03T00:00:00"), +.author = "Karl Seguin; ZigCC", +.layout = "learn.shtml", +.draft = false, --- > 原文地址: @@ -32,9 +35,9 @@ pub const User = struct { 这是一个简单的示例,即使你是第一次看到 Zig,大概率能够看懂这段代码。尽管如此,下面的内容我们还是来逐行分析它。 -> 请参阅[安装 Zig 部分]({{< ref "installing-zig.md" >}}),以便快速启动并运行它。 +> 请参阅[安装 Zig 部分](installing-zig),以便快速启动并运行它。 -## 模块引用 +# [模块引用]($section.id('module-reference')) 很少有程序是在没有标准库或外部库的情况下以单个文件编写的。我们的第一个程序也不例外,它使用 Zig 的标准库来进行打印输出。 Zig 的模块系统非常简单,只依赖于 `@import` 函数和 `pub` 关键字(使代码可以在当前文件外部访问)。 @@ -85,7 +88,7 @@ const MAX_POWER = user.MAX_POWER; - 如何导入其他文件 - 如何导出变量、函数定义 -## 代码注释 +# [代码注释]($section.id('code-comment')) 下面这行 Zig 代码是一个注释: @@ -97,7 +100,7 @@ Zig 没有像 C 语言中类似 `/* ... */` 的多行注释。 基于注释的文档自动生成功能正在试验中。如果你看过 Zig 的标准库文档,你就会看到它的实际应用。`//!` 被称为顶级文档注释,可以放在文件的顶部。三斜线注释 (`///`) 被称为文档注释,可以放在特定位置,如声明之前。如果在错误的地方使用这两种文档注释,编译器都会出错。 -## 函数 +# [函数]($section.id('function')) 下面这行 Zig 代码是程序的入口函数 `main`: @@ -143,7 +146,7 @@ fn add(a: i64, b: i64) i64 { 为了提高可读性,Zig 中不支持函数重载(用不同的参数类型或参数个数定义的同名函数)。暂时来说,以上就是我们需要了解的有关函数的全部内容。 -## 结构体 +# [结构体]($section.id('struct')) 下面这行代码创建了一个 `User` 结构体: @@ -263,7 +266,7 @@ pub fn init(name: []const u8, power: u64) User { 就像我们迄今为止已经探索过的大多数东西一样,今后在讨论 Zig 语言的其他部分时,我们会再次讨论结构体。不过,在大多数情况下,它们都是简单明了的。 -## 数组和切片 +# [数组和切片]($section.id('array-slice')) 我们可以略过代码的最后一行,但鉴于我们的代码片段包含两个字符串 `"Goku"` 和 `{s}'s power is {d}\n`,你可能会对 Zig 中的字符串感到好奇。为了更好地理解字符串,我们先来了解一下数组和切片。 @@ -362,7 +365,7 @@ pub fn main() void { 在了解 Zig 语言的其他方面(尤其是字符串)的同时,我们还将发现更多有关数组和切片的知识。 -## 字符串 +# [字符串]($section.id('string')) 我希望我能说,Zig 里有字符串类型,而且非常棒。遗憾的是,它没有。最简单来说,字符串是字节(u8)的序列(即数组或切片)。实际上,我们可以从 `name` 字段的定义中看到这一点:`name: []const u8`. @@ -396,7 +399,7 @@ pub fn main() void { 当然,在实际程序中,大多数字符串(以及更通用的数组)在编译时都是未知的。最典型的例子就是用户输入,程序编译时并不知道用户输入。这一点我们将在讨论内存时再次讨论。但简而言之,对于这种在编译时不能确定值的数据(长度当然也就无从得知),我们将在运行时动态分配内存。我们的字符串变量(仍然是 `[]const u8` 类型)将是指向动态分配的内存的切片。 -## comptime 和 anytype +# [comptime 和 anytype]($section.id('comptime-and-anytype')) 在我们未解释的最后一行代码中,涉及的知识远比表面看到的多: @@ -440,10 +443,10 @@ pub fn main() void { 会输出: -``` +```zig struct{comptime year: comptime_int = 2023, comptime month: comptime_int = 8} ``` -在这里,我们给匿名结构的字段取名为 `year` 和 `month`。在原始代码中,我们没有这样做。在这种情况下,字段名会自动生成 0、1、2 等。虽然它们都是匿名结构字面形式的示例,但没有字段名称的结构通常被称为“元组”(tuple)。`print` 函数希望接收一个元组,并使用字符串格式中的序号位置来获取适当的参数。 +在这里,我们给匿名结构的字段取名为 `year` 和 `month`。在原始代码中,我们没有这样做。在这种情况下,字段名会自动生成 0、1、2 等。虽然它们都是匿名结构字面形式的示例,但没有字段名称的结构通常被称为"元组"(tuple)。`print` 函数希望接收一个元组,并使用字符串格式中的序号位置来获取适当的参数。 Zig 没有函数重载,也没有可变函数(vardiadic,具有任意数量参数的函数)。但它的编译器能根据传入的类型创建专门的函数,包括编译器自己推导和创建的类型。 diff --git a/content/learn/language-overview-part2.md b/content/learn/language-overview-2.smd similarity index 97% rename from content/learn/language-overview-part2.md rename to content/learn/language-overview-2.smd index 5c52b17..ad735aa 100644 --- a/content/learn/language-overview-part2.md +++ b/content/learn/language-overview-2.smd @@ -1,13 +1,16 @@ --- -title: "语言概述 - 第二部分" -weight: 4 +.title = "语言概述 - 第二部分", +.date = @date("2024-01-04T00:00:00"), +.author = "Karl Seguin; ZigCC", +.layout = "learn.shtml", +.draft = false, --- > 原文地址: -本部分继续上一部分的内容:熟悉 Zig 语言。我们将探索 Zig 的控制流和结构以外的类型。通过这两部分的学习,我们将掌握 Zig 语言的大部分语法,这让我们可以继续深入 Zig 语言,同时也为如何使用 std 标准库打下了基础。 +本部分继续上一部分的内容:熟悉 Zig 语言。我们将探究 Zig 的控制流和结构以外的类型。通过这两部分的学习,我们将掌握 Zig 语言的大部分语法,这让我们可以继续深入 Zig 语言,同时也为如何使用 std 标准库打下了基础。 -## 控制流 +# [控制流]($section.id('control-flow')) Zig 的控制流很可能是我们所熟悉的,但它与 Zig 语言的其他特性协同工作是我们还没有探索过。我们先简单概述控制流的基本使用,之后在讨论依赖控制流的相关特性时,再来重新回顾。 @@ -204,7 +207,7 @@ const personality_analysis = blk: { 稍后,当我们讨论带标签的联合(tagged union)、错误联合(error unions)和可选类型(Optional)时,我们将看到控制流如何与它们联合使用。 -## 枚举 +# [枚举]($section.id('enum')) 枚举是带有标签的整数常量。它们的定义很像结构体: @@ -238,7 +241,7 @@ const Stage = enum { `switch` 的穷举性质使它能与枚举很好地搭配,因为它能确保你处理了所有可能的情况。不过在使用 `switch` 的 `else` 子句时要小心,因为它会匹配任何新添加的枚举值,而这可能不是我们想要的行为。 -## 带标签的联合 Tagged Union +# [带标签的联合 Tagged Union]($section.id('tagged-union')) 联合定义了一个值可以具有的一系列类型。例如,这个 `Number` 可以是整数、浮点数或 nan(非数字): @@ -317,7 +320,7 @@ const Timestamp = union(enum) { 这里 Zig 会根据带标签的联合,自动创建一个隐式枚举。 -## 可选类型 Optional +# [可选类型 Optional]($section.id('optional')) 在类型前加上问号 `?`,任何值都可以声明为可选类型。可选类型既可以是 `null`,也可以是已定义类型的值: @@ -363,7 +366,7 @@ while (rows.next()) |row| { } ``` -## 未定义的值 Undefined +# [未定义的值 Undefined]($section.id('undefined')) 到目前为止,我们看到的每一个变量都被初始化为一个合理的值。但有时我们在声明变量时并不知道它的值。可选类型是一种选择,但并不总是合理的。在这种情况下,我们可以将变量设置为未定义,让其保持未初始化状态。 @@ -376,7 +379,7 @@ std.crypto.random.bytes(&pseudo_uuid); 上述代码仍然创建了一个 16 字节的数组,但它的每个元素都没有被赋值。 -## 错误 Errors +# [错误 Errors]($section.id('errors')) Zig 中错误处理功能十分简单、实用。这一切都从错误集(error sets)开始,错误集的使用方式类似于枚举: @@ -472,7 +475,7 @@ action(req, res) catch |err| return err; try action(req, res); ``` -鉴于必须处理错误,这一点尤其有用。多数情况下的做法就是使用 `try` 或 `catch`。 +鉴于必须处理错误,这一点尤其有用。多数情况下的做法就是使用 `try` 和 `catch`。 > Go 开发人员会注意到,`try` 比 `if err != nil { return err }` 的按键次数更少。 diff --git a/content/learn/pointers.md b/content/learn/pointers.smd similarity index 95% rename from content/learn/pointers.md rename to content/learn/pointers.smd index 9e06c25..3d1b7cd 100644 --- a/content/learn/pointers.md +++ b/content/learn/pointers.smd @@ -1,6 +1,9 @@ --- -title: "指针" -weight: 6 +.title = "指针", +.date = @date("2024-01-06T00:00:00"), +.author = "Karl Seguin; ZigCC", +.layout = "learn.shtml", +.draft = false, --- > 原文地址: @@ -65,7 +68,7 @@ fn levelUp(user: User) void { 要理解这一点,我们可以将数据与内存联系起来,而变量只是将类型与特定内存位置关联起来的标签。例如,在 `main` 中,我们创建了一个`User`。内存中数据的简单可视化表示如下 -```text +``` user -> ------------ (id) | 1 | ------------ (power) @@ -84,7 +87,7 @@ user -> ------------ (id) 下面是一个稍有不同的可视化效果,其中包括内存地址。这些数据的起始内存地址是我想出来的一个随机地址。这是`user`变量引用的内存地址,也是第一个字段 `id` 的值所在的位置。由于 `id` 是一个 64 位整数,需要 8 字节内存。因此,`power` 必须位于 `$start_address + 8` 上: -```text +``` user -> ------------ (id: 1043368d0) | 1 | ------------ (power: 1043368d8) @@ -106,7 +109,7 @@ pub fn main() void { 这段代码输出了`user`、`user.id`、和`user.power`的地址。根据平台等差异,可能会得到不同的输出结果,但都会看到`user`和`user.id`的地址相同,而`user.power`的地址偏移量了 8 个字节。输出的结果如下: -```text +``` learning.User@1043368d0 u64@1043368d0 i32@1043368d8 @@ -184,11 +187,11 @@ pub const User = struct { 我们必须做两处改动。首先是用 `user` 的地址(即 `&user` )来调用 `levelUp`,而不是 `user`。这意味着我们的函数参数不再是 `User`,取而代之的是一个 `*User`,这是我们的第二处改动。 -我们不再需要通过 `user.power += 0;` 来强制修改 user 的那个丑陋的技巧了。最初,我们因为 user 是 var 类型而无法让代码编译,编译器告诉我们它从未被修改。我们以为编译器错了,于是通过强制修改来“糊弄”它。但正如我们现在所知道的,在 levelUp 中被修改的 user 是不同的;编译器是正确的。 +我们不再需要通过 `user.power += 0;` 来强制修改 user 的那个丑陋的技巧了。最初,我们因为 user 是 var 类型而无法让代码编译,编译器告诉我们它从未被修改。我们以为编译器错了,于是通过强制修改来"糊弄"它。但正如我们现在所知道的,在 levelUp 中被修改的 user 是不同的;编译器是正确的。 现在,代码已按预期运行。虽然在函数参数和内存模型方面仍有许多微妙之处,但我们正在取得进展。现在也许是一个好时机来说明一下,除了特定的语法之外,这些都不是 Zig 所独有的。我们在这里探索的模型是最常见的,有些语言可能只是向开发者隐藏了很多细节,因此也就隐藏了灵活性。 -## 方法 +# [方法]($section.id('method')) 一般来说,我们会把 `levelUp` 写成 `User`结构的一个方法: @@ -207,7 +210,7 @@ pub const User = struct { 我最初选择函数是因为它很明确,因此更容易学习。 -## 常量函数参数 +# [常量函数参数]($section.id('const-func-param')) 我不止一次暗示过,在默认情况下,Zig 会传递一个值的副本(称为 "按值传递")。很快我们就会发现,实际情况要更微妙一些(提示:嵌套对象的复杂值怎么办?) @@ -219,11 +222,11 @@ pub const User = struct { > 也许你会想,即使与复制一个非常小的结构相比,通过引用传递怎么会更慢呢?我们接下来会更清楚地看到这一点,但要点是,当 `user` 是指针时,执行 `user.power` 会增加一点点开销。编译器必须权衡复制的代价和通过指针间接访问字段的代价。 -## 指向指针的指针 +# [指向指针的指针]($section.id('pointer-to-pointer')) 我们之前查看了`main`函数中 `user` 的内存结构。现在我们改变了 `levelUp`,那么它的内存会是什么样的呢? -```text +``` main: user -> ------------ (id: 1043368d0) <--- | 1 | | @@ -240,11 +243,7 @@ user -> ------------- (*User) | ------------- ``` -在 `levelUp` 中,`user` 是指向 `User` 的指针。它的值是一个地址。当然不是任何地址,而是 `main.user` 的地址。值得明确的是,`levelUp` 中的 `user` 变量代表一个具体的值。这个值恰好是一个地址。而且,它不仅仅是一个地址,还是一个类型,即 `*User`。这一切都非常一致,不管我们讨论的是不是指针:变量将类型信息与地址联系在一起。指针的唯一特殊之处在于,当我们使用点语法时,例如 `user.power`,Zig 知道 `user` 是一个指针,就会自动跟随地址。 - -> 通过指针访问字段时,有些语言可能会使用不同的运算符。 - -重要的是要理解,`levelUp`函数中的`user`变量本身存在于内存中的某个地址。就像之前所做的一样,我们可以亲自验证这一点: +在 `levelUp` 中,`user` 是指向 `User` 的指针。它的值是一个地址。当然不是任何地址,而是 `main.user` 的地址。值得明确的是,`levelUp` 中的 `user` 变量本身存在于内存中的某个地址。就像之前所做的一样,我们可以亲自验证这一点: ```zig fn levelUp(user: *User) void { @@ -259,7 +258,7 @@ fn levelUp(user: *User) void { 我们可以使用多级间接指针,但这并不是我们现在所需要的。本节的目的是说明指针并不特殊,它只是一个值,即一个地址和一种类型。 -## 嵌套指针 +# [嵌套指针]($section.id('nested-pointer')) 到目前为止,`User` 一直很简单,只包含两个整数。很容易就能想象出它的内存,而且当我们谈论『复制』 时,也不会有任何歧义。但是,如果 User 变得更加复杂并包含一个指针,会发生什么情况呢? @@ -273,7 +272,7 @@ pub const User = struct { 我们已经添加了`name`,它是一个切片。回想一下,切片由长度和指针组成。如果我们使用名字`Goku`初始化`user`,它在内存中会是什么样子? -```text +``` user -> ------------- (id: 1043368d0) | 1 | ------------- (power: 1043368d8) @@ -306,7 +305,7 @@ user -> ------------- (id: 1043368d0) 答案是只会进行浅拷贝。或者像有些人说的那样,只拷贝了变量可立即寻址的内存。这样看来,`levelUp` 可能只会得到一个 `user` 残缺副本,`name` 字段可能是无效的。但请记住,像 `user.name.ptr` 这样的指针是一个值,而这个值是一个地址。它的副本仍然是相同的地址: -```text +``` main: user -> ------------- (id: 1043368d0) | 1 | ------------- (power: 1043368d8) @@ -372,7 +371,7 @@ pub const User = struct { 不同编程语言有不同的实现方式,但许多语言的工作方式与此完全相同(或非常接近)。虽然所有这些看似深奥,但却是日常编程的基础。好消息是,你可以通过简单的示例和片段来掌握这一点;它不会随着系统其他部分复杂性的增加而变得更加复杂。 -## 递归结构 +# [递归结构]($section.id('recursive-structs')) 有时你需要一个递归结构。在保留现有代码的基础上,我们为 `User` 添加一个可选的 `manager` 字段,类型为 `?User`。同时,我们将创建两个`User`,并将其中一个指定为另一个的管理者: diff --git a/content/learn/preface.md b/content/learn/preface.smd similarity index 79% rename from content/learn/preface.md rename to content/learn/preface.smd index e161a4e..7ccdf4d 100644 --- a/content/learn/preface.md +++ b/content/learn/preface.smd @@ -1,6 +1,9 @@ --- -title: "前言" -weight: 1 +.title = "前言", +.date = @date("2024-01-01T00:00:00"), +.author = "Karl Seguin; ZigCC", +.layout = "learn.shtml", +.draft = false, --- 欢迎阅读 Zig 编程语言入门指南《学习 Zig》。本指南旨在让你轻松掌握 Zig。本指南假定你已有编程经验,语言不限。 diff --git a/content/learn/stack-memory.md b/content/learn/stack-memory.smd similarity index 97% rename from content/learn/stack-memory.md rename to content/learn/stack-memory.smd index b23b564..9b4cfde 100644 --- a/content/learn/stack-memory.md +++ b/content/learn/stack-memory.smd @@ -1,6 +1,9 @@ --- -title: "栈内存" -weight: 7 +.title = "栈内存", +.date = @date("2024-01-07T00:00:00"), +.author = "Karl Seguin; ZigCC", +.layout = "learn.shtml", +.draft = false, --- > 原文地址: @@ -13,15 +16,15 @@ weight: 7 内存的第二个区域是调用栈,也是本小节的主题。第三个区域是堆,将在下一小节讨论。 -> 三块内存区域实际上没有真正的物理差别。操作系统和可执行文件创造了“内存区域”这个概念。 +> 三块内存区域实际上没有真正的物理差别。操作系统和可执行文件创造了"内存区域"这个概念。 -## 栈帧 +# [栈帧]($section.id('stack-frame')) 迄今为止,我们所见的所有数据都是常量,存储在二进制的全局数据部分或作为局部变量。局部表示该变量只在其声明的范围内有效。在 Zig 中,范围从花括号开始到结束。大多数变量的范围限定在一个函数内,包括函数参数,或一个控制流块,比如 if。但是,正如所见,你可以创建任意块,从而创建任意范围。 在上一部分中,我们可视化了 `main` 和 `levelUp` 函数的内存,每个函数都有一个 User: -```text +``` main: user -> ------------- (id: 1043368d0) | 1 | ------------- (power: 1043368d8) @@ -56,7 +59,7 @@ levelUp: user -> ------------- (id: 1043368ec) | `levelUp` 紧接在 `main` 之后是有原因的:这是我们的简化版调用栈。当我们的程序启动时,`main` 及其局部变量被推入调用栈。当 `levelUp` 被调用时,它的参数和任何局部变量都会被添加到调用栈上。重要的是,当 `levelUp` 返回时,它会从栈中弹出。 在 `levelUp` 返回并且控制权回到 `main` 后,我们的调用栈如下所示: -```text +``` main: user -> ------------- (id: 1043368d0) | 1 | ------------- (power: 1043368d8) @@ -89,7 +92,7 @@ main: user -> ------------- (id: 1043368d0) 与全局数据一样,调用栈也由操作系统和可执行文件管理。程序启动时,以及此后启动的每个线程,都会创建一个调用栈(其大小通常可在操作系统中配置)。调用栈在程序的整个生命周期中都存在,如果是线程,则在线程的整个生命周期中都存在。程序或线程退出时,调用栈将被释放。我们的全局数据包含所有程序的全局数据,而调用栈只包含当前执行的函数层次的栈帧。这样做既能有效利用内存,又能简化堆栈帧的管理。 -## 悬空指针 +# [悬空指针]($section.id('dangling-pointers')) 栈帧的简洁和高效令人惊叹。但它也很危险:当函数返回时,它的任何本地数据都将无法访问。这听起来似乎很合理,毕竟这是本地数据,但却会带来严重的问题。请看这段代码: diff --git a/content/learn/style-guide.md b/content/learn/style-guide.smd similarity index 92% rename from content/learn/style-guide.md rename to content/learn/style-guide.smd index 02934f4..bacce52 100644 --- a/content/learn/style-guide.md +++ b/content/learn/style-guide.smd @@ -1,13 +1,16 @@ --- -title: "编码风格" -weight: 5 +.title = "编码风格", +.date = @date("2024-01-05T00:00:00"), +.author = "Karl Seguin; ZigCC", +.layout = "learn.shtml", +.draft = false, --- > 原文地址: 本小节的主要内容是介绍 Zig 编译器强制遵守的 2 条规则,以及 Zig 标准库的命名惯例(naming convention)。 -## 未使用变量 Unused Variable +# [未使用变量 Unused Variable]($section.id('unused-variable')) Zig 编译器禁止`未使用变量`,例如以下代码会导致两处编译错误: @@ -52,7 +55,7 @@ fn add(a: i64, _: i64) i64 { 值得注意的是,在上述例子中,`std`也是一个未使用的符号,但是当前这种用法并不会导致任何编译错误。可能在未来,Zig 编译器也将此视为错误。 -## 变量覆盖 Variable Shadowing +# [变量覆盖 Variable Shadowing]($section.id('variable-shadowing')) Zig 不允许使用同名的变量。下面是一个读取 `socket` 的例子,这个例子包含了一个变量覆盖的编译错误: @@ -71,7 +74,7 @@ fn read(stream: std.net.Stream) ![]const u8 { 我认为,这个规范并不能使代码可读性提高。在这个场景下,应该是开发者,而不是编译器,更有资格选择更有可读性的命名方案。 -## 命名规范 +# [命名规范]($section.id('naming-convention')) 除了遵守以上这些规则以外,开发者可以自由地选择他们喜欢的命名规范。但是,理解 Zig 自身的命名规范是有益的,因为大部分你需要打交道的代码,如 Zig 标准库,或者其他三方库,都采用了 Zig 的命名规范。 diff --git a/content/monthly/202207.md b/content/monthly/202207.md deleted file mode 100644 index 4f5a6c7..0000000 --- a/content/monthly/202207.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: "202207 | 开刊 HelloWorld" -date: 2022-07-30T14:08:15+0800 ---- - -# 观点/教程 - -- [Zig 初体验 - Keep Coding](https://liujiacai.net/blog/2022/07/16/zig-intro/) -- [undefined 值的作用](https://github.com/zigcc/forum/discussions/8) -- [用 Zig 优化 yes 命令](https://github.com/zigcc/forum/discussions/4) -- [Some Thoughts on Zig — Sympolymathesy, by Chris Krycho](https://v5.chriskrycho.com/journal/some-thoughts-on-zig/) - - Zig 语言最吸引人的一点:小巧 -- [ziglings-solutions 题解](https://github.com/better-zig/ziglings-solutions) -- ["these are some really impressively bad semantics to choose for your programming language" / Twitter](https://twitter.com/lexi_lambda/status/1551607005026074624) -- [How to Release your Zig Applications](https://zig.news/kristoff/how-to-release-your-zig-applications-2h90) -- [Zig files are structs - Zig NEWS ⚡](https://zig.news/gowind/zig-files-are-structs-288j) -- [Is it necessary to know C (or another systems programming language) before starting with Zig? : Zig](https://www.reddit.com/r/Zig/comments/w63x6r/is_it_necessary_to_know_c_or_another_systems/) - -# 项目/工具 - -- [Release bun v0.1.5 · oven-sh/bun](https://github.com/oven-sh/bun/releases/tag/bun-v0.1.5) -- [zls 可以解析 build addPackage 的包](https://github.com/zigcc/forum/discussions/7) -- [natecraddock/ziglua: Zig bindings for the Lua C API](https://github.com/natecraddock/ziglua) -- [Easily create TUI programs with zig-spoon!](https://zig.news/lhp/easily-create-tui-programs-with-zig-spoon-project-demonstration-4k33) -- [Zig Support plugin for IntelliJ and CLion version 0.0.6 released](https://zig.news/marioariasc/zig-support-plugin-for-intellij-and-clion-version-006-released-o68) -- [r4gus/zbor: CBOR parser written in Zig](https://github.com/r4gus/zbor) - - [zbor - a CBOR en-/ decoder - Zig NEWS ⚡](https://zig.news/r4gus/zbor-a-cbor-en-decoder-2di0) -- [How I built zig-sqlite](https://rischmann.fr/blog/how-i-built-zig-sqlite) - -# [Zig 语言更新](https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2022-07-01..2022-08-01) - -- [std 文档展示更全面](https://twitter.com/croloris/status/1550955321694330880) - - [New Autodocs! by kristoff-it · Pull Request #12173 · ziglang/zig](https://github.com/ziglang/zig/pull/12173) -- [SIMD size suggestions: suggestions code now compiles, added more architectures by Deecellar · Pull Request #12149 · ziglang/zig](https://github.com/ziglang/zig/pull/12149) -- [std.fmt: require specifier for unwrapping ?T and E!T by Vexu · Pull Request #12232 · ziglang/zig](https://github.com/ziglang/zig/pull/12232) diff --git a/content/monthly/202207.smd b/content/monthly/202207.smd new file mode 100644 index 0000000..eaf2e29 --- /dev/null +++ b/content/monthly/202207.smd @@ -0,0 +1,61 @@ +--- +.title = "202207 | 开刊 HelloWorld", +.date = @date("2022-07-30T14:08:15+0800"), +.author = "ZigCC", +.layout = "monthly.shtml", +.draft = false, +--- + +# [观点/教程]($section.id('观点/教程')) + +- [Zig 初体验 - Keep + Coding](https://liujiacai.net/blog/2022/07/16/zig-intro/) +- [undefined 值的作用](https://github.com/zigcc/forum/discussions/8) +- [用 Zig 优化 yes 命令](https://github.com/zigcc/forum/discussions/4) +- [Some Thoughts on Zig — Sympolymathesy, by Chris + Krycho](https://v5.chriskrycho.com/journal/some-thoughts-on-zig/) + - Zig 语言最吸引人的一点:小巧 +- [ziglings-solutions + 题解](https://github.com/better-zig/ziglings-solutions) +- [“these are some really impressively bad semantics to choose for your + programming language” / + Twitter](https://twitter.com/lexi_lambda/status/1551607005026074624) +- [How to Release your Zig + Applications](https://zig.news/kristoff/how-to-release-your-zig-applications-2h90) +- [Zig files are structs - Zig NEWS + ⚡](https://zig.news/gowind/zig-files-are-structs-288j) +- [Is it necessary to know C (or another systems programming language) + before starting with Zig? : + Zig](https://www.reddit.com/r/Zig/comments/w63x6r/is_it_necessary_to_know_c_or_another_systems/) + +# [项目/工具]($section.id('项目/工具')) + +- [Release bun v0.1.5 · + oven-sh/bun](https://github.com/oven-sh/bun/releases/tag/bun-v0.1.5) +- [zls 可以解析 build addPackage + 的包](https://github.com/zigcc/forum/discussions/7) +- [natecraddock/ziglua: Zig bindings for the Lua C + API](https://github.com/natecraddock/ziglua) +- [Easily create TUI programs with + zig-spoon!](https://zig.news/lhp/easily-create-tui-programs-with-zig-spoon-project-demonstration-4k33) +- [Zig Support plugin for IntelliJ and CLion version 0.0.6 + released](https://zig.news/marioariasc/zig-support-plugin-for-intellij-and-clion-version-006-released-o68) +- [r4gus/zbor: CBOR parser written in + Zig](https://github.com/r4gus/zbor) + - [zbor - a CBOR en-/ decoder - Zig NEWS + ⚡](https://zig.news/r4gus/zbor-a-cbor-en-decoder-2di0) +- [How I built + zig-sqlite](https://rischmann.fr/blog/how-i-built-zig-sqlite) + +# [Zig 语言更新](https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2022-07-01..2022-08-01) + +- [std + 文档展示更全面](https://twitter.com/croloris/status/1550955321694330880) + - [New Autodocs! by kristoff-it · Pull Request \#12173 · + ziglang/zig](https://github.com/ziglang/zig/pull/12173) +- [SIMD size suggestions: suggestions code now compiles, added more + architectures by Deecellar · Pull Request \#12149 · + ziglang/zig](https://github.com/ziglang/zig/pull/12149) +- [std.fmt: require specifier for unwrapping ?T and E!T by Vexu · Pull + Request \#12232 · + ziglang/zig](https://github.com/ziglang/zig/pull/12232) diff --git a/content/monthly/202208.md b/content/monthly/202208.md deleted file mode 100644 index b036c4c..0000000 --- a/content/monthly/202208.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: 202208 | stage2 默认开启 -date: 2022-08-28T16:03:12+0800 ---- - -# 观点/教程 - -- [Growing a {{mustache}} with Zig](https://zig.news/batiati/growing-a-mustache-with-zig-di4) - 作者使用 Zig 开发时的目标: - 1. Robost,test 代码快 - 2. Optimal,Zig 语言本身就要求开发者去考虑堆分配 - 3. Reusable,用户可以在高性能(better performance)与低内存(minimal memory footprint)使用之间做取舍,以满足不同的场景 -- [Will Bun JavaScript Take Node's Crown](https://semaphoreci.com/blog/javascript-bun) - Hacker News 上的[评论](https://news.ycombinator.com/item?id=32457587)。作者从多个方面对比了 Node 与 Bun,Bun 均胜出 -- [Looking into Zig - Ayende @ Rahien](https://ayende.com/blog/194404-A/looking-into-zig)。作者对比了 Zig 与 Rust/C 的区别 -- [Cool Zig Patterns - Gotta alloc fast](https://zig.news/xq/cool-zig-patterns-gotta-alloc-fast-23h)。如果需要分配的对象只有一个,如何优化 Allocator 呢?作者给出了一个 memory pool 的实现,23 行代码 -- [Packed structs in Zig make bit/flag sets trivial | Hexops' devlog](https://devlog.hexops.com/2022/packed-structs-in-zig/)。使用 Zig 的 `packet struct` 实现 bit set 功能 - -# 项目/工具 - -- [Virtual tables by vrischmann · Pull Request #100 · vrischmann/zig-sqlite](https://github.com/vrischmann/zig-sqlite/pull/100)。zig-sqlite 作者正常尝试封装 virtual table 的 API,这样就可以用 Zig 写 SQLite 模块了。 -- [Zig Support plugin for IntelliJ and CLion version 0.1.0 released](https://zig.news/marioariasc/zig-support-plugin-for-intellij-and-clion-version-010-released-pd0) -- [How to walk directories? - Help - Ziggit](https://ziggit.dev/t/how-to-walk-directories/260) -- [Zig Visual Programming with Blockly](https://zig.news/lupyuen/zig-visual-programming-with-blockly-3pbg) - - ![](/images/blockly.webp) - -# [Zig 语言更新](https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2022-08-01..2022-09-01) - -- [make self-hosted the default compiler by andrewrk · Pull Request #12368](https://github.com/ziglang/zig/pull/12368) - Master 分支默认已经是 stage2,这是个里程碑的事情,作者为了用户平滑升级,还写了份[升级指南](https://github.com/ziglang/zig/wiki/Self-Hosted-Compiler-Upgrade-Guide)。优势就是:速度更快、内存占用更少、错误信息更加友好。其他相关改动: - - [stage2+stage1: remove type parameter from bit builtins by Vexu · Pull Request #12574 · ziglang/zig](https://github.com/ziglang/zig/pull/12574/files) - - [Adds std.meta.FnPtr for easier stage1/stage2 compatibility by MasterQ32 · Pull Request #12613 · ziglang/zig](https://github.com/ziglang/zig/pull/12613/files) - - [Stage2 fixes by Vexu · Pull Request #12563 · ziglang/zig](https://github.com/ziglang/zig/pull/12563/files) - - [stage2: add note about function call being comptime because of comptime only return type by Vexu · Pull Request #12499 · ziglang/zig](https://github.com/ziglang/zig/pull/12499/files) - - [stage2: implement stack protectors by andrewrk · Pull Request #12472 · ziglang/zig](https://github.com/ziglang/zig/pull/12472) - - [Stage2 error set safety improvements by Vexu · Pull Request #12416 · ziglang/zig](https://github.com/ziglang/zig/pull/12416/files) - - [stage2 llvm: implement more C ABI by Vexu · Pull Request #12395 · ziglang/zig](https://github.com/ziglang/zig/pull/12395/files) -- [coff: improve default COFF/PE object parser by kubkon · Pull Request #12575 · ziglang/zig](https://github.com/ziglang/zig/pull/12575) -- [autodoc: error sets now display all their members by der-teufel-programming · Pull Request #12583 · ziglang/zig](https://github.com/ziglang/zig/pull/12583) -- [Autodoc: anon_init_struct support by kristoff-it · Pull Request #12598 · ziglang/zig](https://github.com/ziglang/zig/pull/12598/files) -- [compilation: avoid pointless caching by kristoff-it · Pull Request #12605 · ziglang/zig](https://github.com/ziglang/zig/pull/12605) -- [translate-c: Don't add self-defined macros to global name table by ehaas · Pull Request #12562 · ziglang/zig](https://github.com/ziglang/zig/pull/12562/files) -- [fix(translate-c): fix off-by-one for leading zeroes by r00ster91 · Pull Request #12490 · ziglang/zig](https://github.com/ziglang/zig/pull/12490/files) -- [libstd: fix off-by-one error in def of ProcSym in pdb.zig by kubkon · Pull Request #12464 · ziglang/zig](https://github.com/ziglang/zig/pull/12464/files) -- [fix memory leak in NativePaths.zig by Techatrix · Pull Request #12469 · ziglang/zig](https://github.com/ziglang/zig/pull/12469/files) -- [std.fs: Fix `WalkerEntry.dir` not always being the containing dir by squeek502 · Pull Request #12444 · ziglang/zig](https://github.com/ziglang/zig/pull/12444/files) -- [std.mem.zeroes: Zero sized structs with uninitialized members by N00byEdge · Pull Request #12246 · ziglang/zig](https://github.com/ziglang/zig/pull/12246/files) -- [stage2: Implement explicit backing integers for packed structs by ifreund · Pull Request #12379 · ziglang/zig](https://github.com/ziglang/zig/pull/12379) -- [std.io.Reader: bounded array functions by InKryption · Pull Request #12351 · ziglang/zig](https://github.com/ziglang/zig/pull/12351/files) diff --git a/content/monthly/202208.smd b/content/monthly/202208.smd new file mode 100644 index 0000000..841eaf3 --- /dev/null +++ b/content/monthly/202208.smd @@ -0,0 +1,106 @@ +--- +.title = "202208 | stage2 默认开启", +.date = @date("2022-08-28T16:03:12+0800"), +.author = "ZigCC", +.layout = "monthly.shtml", +.draft = false, +--- + +# [观点/教程]($section.id('观点/教程')) + +- [Growing a {{mustache}} with + Zig](https://zig.news/batiati/growing-a-mustache-with-zig-di4) + 作者使用 Zig 开发时的目标: + 1. Robost,test 代码快 + 2. Optimal,Zig 语言本身就要求开发者去考虑堆分配 + 3. Reusable,用户可以在高性能(better performance)与低内存(minimal + memory footprint)使用之间做取舍,以满足不同的场景 +- [Will Bun JavaScript Take Node’s + Crown](https://semaphoreci.com/blog/javascript-bun) Hacker News + 上的[评论](https://news.ycombinator.com/item?id=32457587)。作者从多个方面对比了 + Node 与 Bun,Bun 均胜出 +- [Looking into Zig - Ayende @ + Rahien](https://ayende.com/blog/194404-A/looking-into-zig)。作者对比了 + Zig 与 Rust/C 的区别 +- [Cool Zig Patterns - Gotta alloc + fast](https://zig.news/xq/cool-zig-patterns-gotta-alloc-fast-23h)。如果需要分配的对象只有一个,如何优化 + Allocator 呢?作者给出了一个 memory pool 的实现,23 行代码 +- [Packed structs in Zig make bit/flag sets trivial | Hexops’ + devlog](https://devlog.hexops.com/2022/packed-structs-in-zig/)。使用 + Zig 的 `packet struct` 实现 bit set 功能 + +# [项目/工具]($section.id('项目/工具')) + +- [Virtual tables by vrischmann · Pull Request \#100 · + vrischmann/zig-sqlite](https://github.com/vrischmann/zig-sqlite/pull/100)。zig-sqlite + 作者正常尝试封装 virtual table 的 API,这样就可以用 Zig 写 SQLite + 模块了。 + +- [Zig Support plugin for IntelliJ and CLion version 0.1.0 + released](https://zig.news/marioariasc/zig-support-plugin-for-intellij-and-clion-version-010-released-pd0) + +- [How to walk directories? - Help - + Ziggit](https://ziggit.dev/t/how-to-walk-directories/260) + +- [Zig Visual Programming with + Blockly](https://zig.news/lupyuen/zig-visual-programming-with-blockly-3pbg) + + ![](/images/blockly.webp) + +# [Zig 语言更新](https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2022-08-01..2022-09-01) + +- [make self-hosted the default compiler by andrewrk · Pull Request + \#12368](https://github.com/ziglang/zig/pull/12368) Master + 分支默认已经是 + stage2,这是个里程碑的事情,作者为了用户平滑升级,还写了份[升级指南](https://github.com/ziglang/zig/wiki/Self-Hosted-Compiler-Upgrade-Guide)。优势就是:速度更快、内存占用更少、错误信息更加友好。其他相关改动: + - [stage2+stage1: remove type parameter from bit builtins by Vexu · + Pull Request \#12574 · + ziglang/zig](https://github.com/ziglang/zig/pull/12574/files) + - [Adds std.meta.FnPtr for easier stage1/stage2 compatibility by + MasterQ32 · Pull Request \#12613 · + ziglang/zig](https://github.com/ziglang/zig/pull/12613/files) + - [Stage2 fixes by Vexu · Pull Request \#12563 · + ziglang/zig](https://github.com/ziglang/zig/pull/12563/files) + - [stage2: add note about function call being comptime because of + comptime only return type by Vexu · Pull Request \#12499 · + ziglang/zig](https://github.com/ziglang/zig/pull/12499/files) + - [stage2: implement stack protectors by andrewrk · Pull Request + \#12472 · ziglang/zig](https://github.com/ziglang/zig/pull/12472) + - [Stage2 error set safety improvements by Vexu · Pull Request \#12416 + · ziglang/zig](https://github.com/ziglang/zig/pull/12416/files) + - [stage2 llvm: implement more C ABI by Vexu · Pull Request \#12395 · + ziglang/zig](https://github.com/ziglang/zig/pull/12395/files) +- [coff: improve default COFF/PE object parser by kubkon · Pull Request + \#12575 · ziglang/zig](https://github.com/ziglang/zig/pull/12575) +- [autodoc: error sets now display all their members by + der-teufel-programming · Pull Request \#12583 · + ziglang/zig](https://github.com/ziglang/zig/pull/12583) +- [Autodoc: anon_init_struct support by kristoff-it · Pull Request + \#12598 · + ziglang/zig](https://github.com/ziglang/zig/pull/12598/files) +- [compilation: avoid pointless caching by kristoff-it · Pull Request + \#12605 · ziglang/zig](https://github.com/ziglang/zig/pull/12605) +- [translate-c: Don’t add self-defined macros to global name table by + ehaas · Pull Request \#12562 · + ziglang/zig](https://github.com/ziglang/zig/pull/12562/files) +- [fix(translate-c): fix off-by-one for leading zeroes by r00ster91 · + Pull Request \#12490 · + ziglang/zig](https://github.com/ziglang/zig/pull/12490/files) +- [libstd: fix off-by-one error in def of ProcSym in pdb.zig by kubkon · + Pull Request \#12464 · + ziglang/zig](https://github.com/ziglang/zig/pull/12464/files) +- [fix memory leak in NativePaths.zig by Techatrix · Pull Request + \#12469 · + ziglang/zig](https://github.com/ziglang/zig/pull/12469/files) +- [std.fs: Fix `WalkerEntry.dir` not always being the containing dir by + squeek502 · Pull Request \#12444 · + ziglang/zig](https://github.com/ziglang/zig/pull/12444/files) +- [std.mem.zeroes: Zero sized structs with uninitialized members by + N00byEdge · Pull Request \#12246 · + ziglang/zig](https://github.com/ziglang/zig/pull/12246/files) +- [stage2: Implement explicit backing integers for packed structs by + ifreund · Pull Request \#12379 · + ziglang/zig](https://github.com/ziglang/zig/pull/12379) +- [std.io.Reader: bounded array functions by InKryption · Pull Request + \#12351 · + ziglang/zig](https://github.com/ziglang/zig/pull/12351/files) diff --git a/content/monthly/202209.md b/content/monthly/202209.md deleted file mode 100644 index bc5902d..0000000 --- a/content/monthly/202209.md +++ /dev/null @@ -1,67 +0,0 @@ ---- -title: 202209 | 锋芒毕露 -date: 2022-10-03T23:32:12+0800 ---- - -# Zig VS Rust 火花 - -在 9/10 号左右,在 Twitter 上牵起了一小波关于 Zig VS Rust 的小火花,以至于最后 Zig 创始人 Andrew Kelley [发推](https://twitter.com/andy_kelley/status/1568679389113757698)表示 Let us exist。这里稍微整理下这件事情的过程: -本次事件主要涉及两个人: - -- Rust 核心贡献者: Patrick Walton -- Zig 社区 VP: Loris Cro - -### 时间线 - -- 8/26 号,一篇关于 wasm 2 Game Jam 的[分析报告](https://wasm4.org/blog/jam-2-results/)中,使用 Zig 的人数最多 -- 9/9 号,这篇报告在 HackerNews 上引起了[热烈讨论](https://news.ycombinator.com/item?id=32777636),其中 Walton 在多处回复中表示 Zig 语言的劣势,[并称](https://news.ycombinator.com/item?id=32782842) - > It's perfectly reasonable to take the position that it's deeply problematic for a language aiming for wide use in 2022 to not be memory safe. There's no requirement that you "focus on tradeoffs", especially since real people get hurt by memory safety problems. -- Loris [回复到](https://news.ycombinator.com/item?id=32785380): - > I think you're actively hurting the project that you care about in your ineffective crusade, but hey, don't let me stop you. -- 9/10 号,有人发推对 [tigerbeetle](https://github.com/tigerbeetledb/tigerbeetle/blob/main/docs/TIGER_STYLE.md#safety) 内存分配方式表示好奇:所有内存必须在启动时静态分配好 -- Walton [回复到](https://mobile.twitter.com/pcwalton/status/1568498326496247809): - > The weird thing is that this is used as an example of why you supposedly don't need language-enforced memory safety. - > - > But that literally is language-enforced memory safety! Just _way_ more restrictive than what Rust has: if you hate the borrow check, try the "no heap" check... - > - > This is wrong because you can still have UAF from freed stack frames. -- Loris 针对 Walton 的回复说了句“What a boring, useless take.([原推](https://mobile.twitter.com/kripken/status/1568428308131622913)的回复已经被 Loris 删除了,可以[在这里](https://archive.ph/jq3kw#selection-1275.0-1275.30)看到历史): -- Walton 发推[表示](https://mobile.twitter.com/pcwalton/status/1568302065851707392)在 2022 年,所有语言都应该是内存安全,应该算是『编程语言界的共识』,并称 Zig 是行业的一大退步 😅 -- Loris 专门发了一个 [Twitter thread](https://twitter.com/croloris/status/1568573729940164608?s=21&t=v2Dj_F2f_kUzZDQps5KjtQ) 来阐述『软件的目标不仅仅是内存安全,更重要的是正确』。比如 tigerbeetle 这里[提到的](https://github.com/tigerbeetledb/tigerbeetle/blob/main/docs/DESIGN.md)。而且即便内存安全,也可能发生 OOM - -### 总结 - -上面的链接比较多,这里稍微总结下这次争论的问题: - -> Rust 用户觉得 Zig 不是内存安全的语言,Zig 认为 Rust 的语言过度复杂,这反而会导致程序复杂度挺升,导致程序产生错误行为 - -使用 Zig 的人大概率也是 Rust 用户,之所以有了安全的 Rust,还来选 Zig,笔者觉得大概率就是本次争论的观点,Rust 过于复杂,导致程序员不仅仅要考虑业务行为,还需要按照 Rust 的风格来编程,这加剧了程序出错的可能性。 - -# 观点/教程 - -- [How (memory) safe is zig?](https://www.scattered-thoughts.net/writing/how-safe-is-zig/) 作者重点介绍了在内存安全方面,Zig 的优劣势。尽管 Zig 相比 C 有了明显的改进,但相比 Rust 这种在编译期就能发现程序问题来说,显得有些鸡肋,但在一些可控的环境下,比如 WASM、嵌入式环境中,Zig 还是有发挥的空间 - - [How (memory) safe is zig? (UPDATED) | Lobsters](https://lobste.rs/s/nw7hsd) - - [How safe is Zig? | Hacker News](https://news.ycombinator.com/item?id=31850347) -- [Hacked std.PriorityQueue for constant time update](https://www.reddit.com/r/Zig/comments/x8fxqr/hacked_stdpriorityqueue_for_constant_time_update/) -- [Flutter/Dart + FFI + Zig: Flutter 使用 FFI 调用 Zig 示例](https://github.com/zigcc/forum/discussions/21) -- [Building a Tiny Mutex](https://zig.news/kprotty/building-a-tiny-mutex-537k) -- [Perfecting WebGPU/Dawn native graphics for Zig](https://devlog.hexops.com/2022/perfecting-webgpu-native/) -- [Cross-Compiling and packaging C, Go and Zig projects with Nix](https://flyx.org/cross-packaging/) 介绍如何基于 [Nix](https://nixos.org/) 来进行交叉编译 -- [Revisiting the design approach to the Zig programming language](https://about.sourcegraph.com/blog/zig-programming-language-revisiting-design-approach) Sourcegraph 的一档播客,对 Zig 创始人的采访,介绍了 Zig 的由来,其中提到一个性能优化点是:untagged union,这里有它的一些介绍:[Andrew Kelley claims Zig is faster than Rust in perfomance](https://www.reddit.com/r/rust/comments/s5caye/comment/hsz6uf0/?utm_source=share&utm_medium=web2x&context=3) -- [Zig ⚡ Improving the User Experience for Unused Variables](https://vimeo.com/748218307) - -# 项目/工具 - -- [Zig 开发常用类库](https://github.com/zigcc/forum/discussions/28),如果读者的 Zig 项目托管在 GitHub,推荐加上 [zig-package](https://github.com/topics/zig-package) 这个标签,这样可以自动被 https://zig.pm/ 收录 -- https://zig.run/ - 在线运行 zig 代码 -- [Zig Support plugin for IntelliJ and CLion version 0.0.7 released](https://zig.news/marioariasc/zig-support-plugin-for-intellij-and-clion-version-007-released-1en8) -- [zig-napigen](https://github.com/cztomsik/zig-napigen) Automatic N-API bindings for your Zig project. -- [Dart 通过 FFI 调用 Zig 库示例](https://github.com/better-dart/learn-dart/blob/main/packages/ffi-binding/example/main.dart#L31) -- [zig-gamedev](https://github.com/michal-z/zig-gamedev) -- [loc in Zig](https://github.com/jiacai2050/loc) 代码行数统计工具 -- [Grep in Zig](https://github.com/EclesioMeloJunior/zig-grep) -- [randomutils](https://gitlab.com/hdante/randomutils) Generate 64-bit random numbers -- [zig-pico](https://github.com/paperdev-code/zig-pico) 树莓派 [Pico SDK](https://github.com/raspberrypi/pico-sdk) 的 Zig 绑定库 -- [stm32f4.zig](https://github.com/moonxraccoon/stm32f4.zig) STM32F4(ARM Cortex M4 的高性能 32 位微控制器) 固件抽象层 - -# [Zig 语言更新](https://github.com/ziglang/zig/pulls?q=+is%3Aclosed+is%3Apr+closed%3A2022-09-01..2022-10-01+) diff --git a/content/monthly/202209.smd b/content/monthly/202209.smd new file mode 100644 index 0000000..1795eaf --- /dev/null +++ b/content/monthly/202209.smd @@ -0,0 +1,129 @@ +--- +.title = "202209 | 锋芒毕露", +.date = @date("2022-10-03T23:32:12+0800"), +.author = "ZigCC", +.layout = "monthly.shtml", +.draft = false, +--- + +# [Zig VS Rust 火花]($section.id('Zig VS Rust 火花')) + +在 9/10 号左右,在 Twitter 上牵起了一小波关于 Zig VS Rust +的小火花,以至于最后 Zig 创始人 Andrew Kelley +[发推](https://twitter.com/andy_kelley/status/1568679389113757698)表示 +Let us exist。这里稍微整理下这件事情的过程: 本次事件主要涉及两个人: + +- Rust 核心贡献者: Patrick Walton +- Zig 社区 VP: Loris Cro + +## [时间线]($section.id('时间线')) + +- 8/26 号,一篇关于 wasm 2 Game Jam + 的[分析报告](https://wasm4.org/blog/jam-2-results/)中,使用 Zig + 的人数最多 +- 9/9 号,这篇报告在 HackerNews + 上引起了[热烈讨论](https://news.ycombinator.com/item?id=32777636),其中 + Walton 在多处回复中表示 Zig + 语言的劣势,[并称](https://news.ycombinator.com/item?id=32782842) \> + It’s perfectly reasonable to take the position that it’s deeply + problematic for a language aiming for wide use in 2022 to not be + memory safe. There’s no requirement that you “focus on tradeoffs”, + especially since real people get hurt by memory safety problems. +- Loris [回复到](https://news.ycombinator.com/item?id=32785380): \> I + think you’re actively hurting the project that you care about in your + ineffective crusade, but hey, don’t let me stop you. +- 9/10 号,有人发推对 + [tigerbeetle](https://github.com/tigerbeetledb/tigerbeetle/blob/main/docs/TIGER_STYLE.md#safety) + 内存分配方式表示好奇:所有内存必须在启动时静态分配好 +- Walton + [回复到](https://mobile.twitter.com/pcwalton/status/1568498326496247809): + \> The weird thing is that this is used as an example of why you + supposedly don’t need language-enforced memory safety. \> \> But that + literally is language-enforced memory safety! Just *way* more + restrictive than what Rust has: if you hate the borrow check, try the + “no heap” check… \> \> This is wrong because you can still have UAF + from freed stack frames. +- Loris 针对 Walton 的回复说了句“What a boring, useless + take.([原推](https://mobile.twitter.com/kripken/status/1568428308131622913)的回复已经被 + Loris + 删除了,可以[在这里](https://archive.ph/jq3kw#selection-1275.0-1275.30)看到历史): +- Walton + 发推[表示](https://mobile.twitter.com/pcwalton/status/1568302065851707392)在 + 2022 年,所有语言都应该是内存安全,应该算是『编程语言界的共识』,并称 + Zig 是行业的一大退步 😅 +- Loris 专门发了一个 [Twitter + thread](https://twitter.com/croloris/status/1568573729940164608?s=21&t=v2Dj_F2f_kUzZDQps5KjtQ) + 来阐述『软件的目标不仅仅是内存安全,更重要的是正确』。比如 tigerbeetle + 这里[提到的](https://github.com/tigerbeetledb/tigerbeetle/blob/main/docs/DESIGN.md)。而且即便内存安全,也可能发生 + OOM + +## [总结]($section.id('总结')) + +上面的链接比较多,这里稍微总结下这次争论的问题: + +> Rust 用户觉得 Zig 不是内存安全的语言,Zig 认为 Rust +> 的语言过度复杂,这反而会导致程序复杂度挺升,导致程序产生错误行为 + +使用 Zig 的人大概率也是 Rust 用户,之所以有了安全的 Rust,还来选 +Zig,笔者觉得大概率就是本次争论的观点,Rust +过于复杂,导致程序员不仅仅要考虑业务行为,还需要按照 Rust +的风格来编程,这加剧了程序出错的可能性。 + +# [观点/教程]($section.id('观点/教程')) + +- [How (memory) safe is + zig?](https://www.scattered-thoughts.net/writing/how-safe-is-zig/) + 作者重点介绍了在内存安全方面,Zig 的优劣势。尽管 Zig 相比 C + 有了明显的改进,但相比 Rust + 这种在编译期就能发现程序问题来说,显得有些鸡肋,但在一些可控的环境下,比如 + WASM、嵌入式环境中,Zig 还是有发挥的空间 + - [How (memory) safe is zig? (UPDATED) | + Lobsters](https://lobste.rs/s/nw7hsd) + - [How safe is Zig? | Hacker + News](https://news.ycombinator.com/item?id=31850347) +- [Hacked std.PriorityQueue for constant time + update](https://www.reddit.com/r/Zig/comments/x8fxqr/hacked_stdpriorityqueue_for_constant_time_update/) +- [Flutter/Dart + FFI + Zig: Flutter 使用 FFI 调用 Zig + 示例](https://github.com/zigcc/forum/discussions/21) +- [Building a Tiny + Mutex](https://zig.news/kprotty/building-a-tiny-mutex-537k) +- [Perfecting WebGPU/Dawn native graphics for + Zig](https://devlog.hexops.com/2022/perfecting-webgpu-native/) +- [Cross-Compiling and packaging C, Go and Zig projects with + Nix](https://flyx.org/cross-packaging/) 介绍如何基于 + [Nix](https://nixos.org/) 来进行交叉编译 +- [Revisiting the design approach to the Zig programming + language](https://about.sourcegraph.com/blog/zig-programming-language-revisiting-design-approach) + Sourcegraph 的一档播客,对 Zig 创始人的采访,介绍了 Zig + 的由来,其中提到一个性能优化点是:untagged + union,这里有它的一些介绍:[Andrew Kelley claims Zig is faster than + Rust in + perfomance](https://www.reddit.com/r/rust/comments/s5caye/comment/hsz6uf0/?utm_source=share&utm_medium=web2x&context=3) +- [Zig ⚡ Improving the User Experience for Unused + Variables](https://vimeo.com/748218307) + +# [项目/工具]($section.id('项目/工具')) + +- [Zig + 开发常用类库](https://github.com/zigcc/forum/discussions/28),如果读者的 + Zig 项目托管在 GitHub,推荐加上 + [zig-package](https://github.com/topics/zig-package) + 这个标签,这样可以自动被 https://zig.pm/ 收录 +- https://zig.run/ - 在线运行 zig 代码 +- [Zig Support plugin for IntelliJ and CLion version 0.0.7 + released](https://zig.news/marioariasc/zig-support-plugin-for-intellij-and-clion-version-007-released-1en8) +- [zig-napigen](https://github.com/cztomsik/zig-napigen) Automatic N-API + bindings for your Zig project. +- [Dart 通过 FFI 调用 Zig + 库示例](https://github.com/better-dart/learn-dart/blob/main/packages/ffi-binding/example/main.dart#L31) +- [zig-gamedev](https://github.com/michal-z/zig-gamedev) +- [loc in Zig](https://github.com/jiacai2050/loc) 代码行数统计工具 +- [Grep in Zig](https://github.com/EclesioMeloJunior/zig-grep) +- [randomutils](https://gitlab.com/hdante/randomutils) Generate 64-bit + random numbers +- [zig-pico](https://github.com/paperdev-code/zig-pico) 树莓派 [Pico + SDK](https://github.com/raspberrypi/pico-sdk) 的 Zig 绑定库 +- [stm32f4.zig](https://github.com/moonxraccoon/stm32f4.zig) STM32F4(ARM + Cortex M4 的高性能 32 位微控制器) 固件抽象层 + +# [Zig 语言更新](https://github.com/ziglang/zig/pulls?q=+is%3Aclosed+is%3Apr+closed%3A2022-09-01..2022-10-01+) diff --git a/content/monthly/202210.md b/content/monthly/202210.md deleted file mode 100644 index c1c5598..0000000 --- a/content/monthly/202210.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: 202210 | 0.10 蓄势待发 -date: 2022-10-30T10:10:14+0800 ---- - -# 观点/教程 - -- [Zig Is Self-Hosted Now, What's Next? | Loris Cro's Blog](https://kristoff.it/blog/zig-self-hosted-now-what/) | 0.10 即将在 11-01 号发布,Loris 回顾了目前 stage2 的进展,包管理器是下一个目标,但是不会引入中央仓库 - - Loris 会在 Twitch 直播这次的 [release party](https://ziggit.dev/t/release-party-and-zig-rush-november-1st/435) -- [Howto Pair Strings with Enums](https://zig.news/david_vanderson/howto-pair-strings-with-enums-9ce) 利用 Zig comptime 的能力为 enum 增加描述信息 -- [A Database Without Dynamic Memory Allocation](https://tigerbeetle.com/blog/a-database-without-dynamic-memory/) | TigerBeetle 讲述了如何静态内存的优势,如何应用到数据库中,以及 Zig 为实现这种设计方式的优势 -- [That Time I Tried Porting Zig to SerenityOS - sin-ack's writings](https://sin-ack.github.io/posts/sycl-talk-20221007/) -- [Building a high-performance database buffer pool in Zig using io_uring's new fixed-buffer mode](https://gavinray97.github.io/blog/io-uring-fixed-bufferpool-zig) -- [Zig-style generics are not well-suited for most languages](https://typesanitizer.com/blog/zig-generics.html) -- [Zig and WebAssembly are a match made in heaven](https://blog.battlefy.com/zig-and-webassembly-are-a-match-made-in-heaven) -- [视频] [Stay Together For The Kids - Andrew Kelley - Software You Can Love 2022](https://www.bilibili.com/video/BV1ne411G74c/?share_source=copy_web&vd_source=9191359325bcbfb53bd116d1f5b22175) -- [视频] [Ziglibc: Sweeping out the rug from underneath C - Jonathan Marler - Software You Can Love 2022](https://www.bilibili.com/video/BV1Td4y1y7U9/?share_source=copy_web&vd_source=9191359325bcbfb53bd116d1f5b22175) -- [音频] [005. 与 LemonHX 畅聊新一代编程语言 Zig – RustTalk](https://rusttalk.github.io/podcast/005/) - -# 项目/工具 - -- [Himujjal/zig-json5](https://github.com/Himujjal/zig-json5): A JSON5 parser/stringifier for Zig resembling the std.json API -- [hexops/mach-examples](https://github.com/hexops/mach-examples): Mach core & engine examples -- [sagemathinc/cowasm](https://github.com/sagemathinc/cowasm): CoWasm: Collaborative WebAssembly for Servers and Browsers. Built using Zig. Supports Python with extension modules, including numpy. -- [loc 使用 mmap 后速度快了 2 倍](https://github.com/jiacai2050/loc/pull/2) -- 一个 Zig Hackers 的 Twitter 列表:[Zig Hero](https://twitter.com/i/lists/1570249876155568129) -- [A minimal RocksDB example with Zig](https://notes.eatonphil.com/zigrocks.html) - -# [Zig 语言更新](https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2022-10-01..2022-11-01) diff --git a/content/monthly/202210.smd b/content/monthly/202210.smd new file mode 100644 index 0000000..925b42c --- /dev/null +++ b/content/monthly/202210.smd @@ -0,0 +1,58 @@ +--- +.title = "202210 | 0.10 蓄势待发", +.date = @date("2022-10-30T10:10:14+0800"), +.author = "ZigCC", +.layout = "monthly.shtml", +.draft = false, +--- + +# [观点/教程]($section.id('观点/教程')) + +- [Zig Is Self-Hosted Now, What’s Next? | Loris Cro’s + Blog](https://kristoff.it/blog/zig-self-hosted-now-what/) | 0.10 + 即将在 11-01 号发布,Loris 回顾了目前 stage2 + 的进展,包管理器是下一个目标,但是不会引入中央仓库 + - Loris 会在 Twitch 直播这次的 [release + party](https://ziggit.dev/t/release-party-and-zig-rush-november-1st/435) +- [Howto Pair Strings with + Enums](https://zig.news/david_vanderson/howto-pair-strings-with-enums-9ce) + 利用 Zig comptime 的能力为 enum 增加描述信息 +- [A Database Without Dynamic Memory + Allocation](https://tigerbeetle.com/blog/a-database-without-dynamic-memory/) + | TigerBeetle 讲述了如何静态内存的优势,如何应用到数据库中,以及 Zig + 为实现这种设计方式的优势 +- [That Time I Tried Porting Zig to SerenityOS - sin-ack’s + writings](https://sin-ack.github.io/posts/sycl-talk-20221007/) +- [Building a high-performance database buffer pool in Zig using + io_uring’s new fixed-buffer + mode](https://gavinray97.github.io/blog/io-uring-fixed-bufferpool-zig) +- [Zig-style generics are not well-suited for most + languages](https://typesanitizer.com/blog/zig-generics.html) +- [Zig and WebAssembly are a match made in + heaven](https://blog.battlefy.com/zig-and-webassembly-are-a-match-made-in-heaven) +- \[视频\] [Stay Together For The Kids - Andrew Kelley - Software You + Can Love + 2022](https://www.bilibili.com/video/BV1ne411G74c/?share_source=copy_web&vd_source=9191359325bcbfb53bd116d1f5b22175) +- \[视频\] [Ziglibc: Sweeping out the rug from underneath C - Jonathan + Marler - Software You Can Love + 2022](https://www.bilibili.com/video/BV1Td4y1y7U9/?share_source=copy_web&vd_source=9191359325bcbfb53bd116d1f5b22175) +- \[音频\] [005. 与 LemonHX 畅聊新一代编程语言 Zig – + RustTalk](https://rusttalk.github.io/podcast/005/) + +# [项目/工具]($section.id('项目/工具')) + +- [Himujjal/zig-json5](https://github.com/Himujjal/zig-json5): A JSON5 + parser/stringifier for Zig resembling the std.json API +- [hexops/mach-examples](https://github.com/hexops/mach-examples): Mach + core & engine examples +- [sagemathinc/cowasm](https://github.com/sagemathinc/cowasm): CoWasm: + Collaborative WebAssembly for Servers and Browsers. Built using Zig. + Supports Python with extension modules, including numpy. +- [loc 使用 mmap 后速度快了 2 + 倍](https://github.com/jiacai2050/loc/pull/2) +- 一个 Zig Hackers 的 Twitter 列表:[Zig + Hero](https://twitter.com/i/lists/1570249876155568129) +- [A minimal RocksDB example with + Zig](https://notes.eatonphil.com/zigrocks.html) + +# [Zig 语言更新](https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2022-10-01..2022-11-01) diff --git a/content/monthly/202211.md b/content/monthly/202211.md deleted file mode 100644 index 83b9659..0000000 --- a/content/monthly/202211.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: 202211 | 0.10 横空出世 -date: 2022-12-04T18:45:34+0800 ---- - -# [0.10.0 Release Notes](https://ziglang.org/download/0.10.0/release-notes.html) - -本月最大的事情就是 0.10 版本发布了,主要功能就是 self-hosted compiler,也称为『自举』,即可以用 Zig 来写 Zig 编译器,自举之所以对于一门语言如此重要,主要在于,这说明了该语言可以处理足够复杂的系统,不再只是玩具而已。编译的提升: - -- Wall Clock Time: 43 seconds to 40 seconds (7% faster) -- Peak RSS: 9.6 GiB to 2.8 GiB (3.5x less memory used) - -赶紧升级吧,少年! - -# zigcc 中文社区微信群 - -欢迎喜欢 Zig 的小伙伴加入! -{{< figure src="https://github.com/zigcc/.github/raw/main/weixin.jpg" - width="200" title="ZigCC 微信群二维码" >}} - -# 观点/教程 - -- [Wasmer 3.0 使用 Zig 进行跨平台编译 · Discussion #35 · zigcc/forum](https://github.com/zigcc/forum/discussions/35) -- [Easy Interfaces with Zig 0.10.0](https://zig.news/kristoff/easy-interfaces-with-zig-0100-2hc5)。由于 Zig 中没有 interface/trait 这种抽象类型,作者这里通过 0.10 提供的一个新功能(inline else)来实现类似效果: - -```zig -const Animal = union(enum){ - cat: Cat, - dog: Dog, - snake: Snake, - - pub fn talk(self: Animal) void { - switch (self) { - .snake => std.debug.print("Ssss~~~", .{}), - inline else => |case| case.talk(), - } - } -}; -``` - -- [My hopes and dreams for 'zig test'](https://zig.news/slimsag/my-hopes-and-dreams-for-zig-test-2pkh)。作者对 `zig test` 一些不满意的地方,这里面有个词比较有意思:[paper-cuts](https://en.wikipedia.org/wiki/Paper_cut_bug),中文直接翻译就是“被纸张划的伤痕”,在软件领域特指:影响用户体验的小缺陷,虽然不严重,但是比较烦人。 - - ![paper-cuts](/images/paper-cuts.webp) - -- [视频][memory safety in c++, zig, & rust (part 1) - youtube](https://www.youtube.com/watch?v=qeiRGbYCD-0) -- [Writing a SQL database, take two: Zig and RocksDB](https://notes.eatonphil.com/zigrocks-sql.html) 。本文作者是 TigerBeetle 的联合创始人 Phil,这篇文章主要演示了基于 Zig 做 RocksDB 的 binding,并在此基础上,增加 SQL 层,实现简单的 CRUD 功能。代码地址:[eatonphil/zigrocks](https://github.com/eatonphil/zigrocks) -- [Debugging undefined behavior caught by Zig](https://devlog.hexops.com/2022/debugging-undefined-behavior/)。Hexops 官博,本文讨论了一个有意思的问题:UBSan 的一个 bug 导致 [Mach engine](https://machengine.org/) 的测试失败,更准确说是 UBSan 需要内存地址对齐来工作,但是现在主流的处理器(x86、ARM、RISC-V 等)都可以处理非对齐的地址访问。 -- [packed struct field order reversed? : Zig](https://www.reddit.com/r/Zig/comments/yvl60t/packed_struct_field_order_reversed/) -- [Using rr to quickly debug memory corruption](https://zig.news/david_vanderson/using-rr-to-quickly-debug-memory-corruption-2539),本文作者通过使用 [rr](https://rr-project.org/) 这个工具来排查内存损坏的问题 -- [A Programmer-Friendly I/O Abstraction Over io_uring and kqueue](https://tigerbeetle.com/blog/a-friendly-abstraction-over-iouring-and-kqueue/)。 TigerBeetle 官博,[HN 讨论](https://news.ycombinator.com/item?id=33721075) -- [How zig-spoon (and lots of coffee) helped me sort thousands of pictures](https://zig.news/lhp/how-zig-spoon-and-lots-of-coffee-helped-me-sort-thousands-of-pictures-4gkj)。本文作者通过 [spoon](https://sr.ht/~leon_plickat/zig-spoon/) 这个库开发了一个帮助自己进行图片打标的 UI 工具, - -# 项目/工具 - -- [Zig 程序设计语言中文手册](https://sxwangzhiwen.github.io/zigcndoc/zigcndoc.html) GitHub 用户 [@sxwangzhiwen](https://github.com/sxwangzhiwen) 制作,论坛[相关讨论](https://github.com/zigcc/forum/discussions/36)。 -- [dantecatalfamo/zig-dns: Experimental DNS library implemented in zig](https://github.com/dantecatalfamo/zig-dns) -- [Neovim Zig Plugin written in Lua](https://github.com/CadeMichael/zig.nvim) -- [trace.zig: A small and simple tracing client library](https://zig.news/huntrss/tracezig-a-small-and-simple-tracing-client-library-2ffj),项目地址:[Zig tracing / trace.zig](https://gitlab.com/zig_tracing/trace.zig) -- [Zig Support plugin for IntelliJ and CLion version 0.2.0 released](https://zig.news/marioariasc/zig-support-plugin-for-intellij-and-clion-version-020-released-3g06) - -# [Zig 语言更新](https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2022-11-01..2022-12-01) diff --git a/content/monthly/202211.smd b/content/monthly/202211.smd new file mode 100644 index 0000000..5b1435c --- /dev/null +++ b/content/monthly/202211.smd @@ -0,0 +1,117 @@ +--- +.title = "202211 | 0.10 横空出世", +.date = @date("2022-12-04T18:45:34+0800"), +.author = "ZigCC", +.layout = "monthly.shtml", +.draft = false, +--- + +# [0.10.0 Release Notes](https://ziglang.org/download/0.10.0/release-notes.html) + +本月最大的事情就是 0.10 版本发布了,主要功能就是 self-hosted +compiler,也称为『自举』,即可以用 Zig 来写 Zig +编译器,自举之所以对于一门语言如此重要,主要在于,这说明了该语言可以处理足够复杂的系统,不再只是玩具而已。编译的提升: + +- Wall Clock Time: 43 seconds to 40 seconds (7% faster) +- Peak RSS: 9.6 GiB to 2.8 GiB (3.5x less memory used) + +赶紧升级吧,少年! + +# [zigcc 中文社区微信群]($section.id('zigcc 中文社区微信群')) + +欢迎喜欢 Zig 的小伙伴加入! {{\< figure +src=“https://github.com/zigcc/.github/raw/main/weixin.jpg” width=“200” +title=“ZigCC 微信群二维码” \>}} + +# [观点/教程]($section.id('观点/教程')) + +- [Wasmer 3.0 使用 Zig 进行跨平台编译 · Discussion \#35 · + zigcc/forum](https://github.com/zigcc/forum/discussions/35) +- [Easy Interfaces with Zig + 0.10.0](https://zig.news/kristoff/easy-interfaces-with-zig-0100-2hc5)。由于 + Zig 中没有 interface/trait 这种抽象类型,作者这里通过 0.10 + 提供的一个新功能(inline else)来实现类似效果: + +``` zig +const Animal = union(enum){ + cat: Cat, + dog: Dog, + snake: Snake, + + pub fn talk(self: Animal) void { + switch (self) { + .snake => std.debug.print("Ssss~~~", .{}), + inline else => |case| case.talk(), + } + } +}; +``` + +- [My hopes and dreams for ‘zig + test’](https://zig.news/slimsag/my-hopes-and-dreams-for-zig-test-2pkh)。作者对 + `zig test` + 一些不满意的地方,这里面有个词比较有意思:[paper-cuts](https://en.wikipedia.org/wiki/Paper_cut_bug),中文直接翻译就是“被纸张划的伤痕”,在软件领域特指:影响用户体验的小缺陷,虽然不严重,但是比较烦人。 + +```=html +
+ + paper-cuts + + +
+``` + +- \[视频\]\[memory safety in c++, zig, & rust (part 1) - + youtube\](https://www.youtube.com/watch?v=qeiRGbYCD-0) + +- [Writing a SQL database, take two: Zig and + RocksDB](https://notes.eatonphil.com/zigrocks-sql.html) 。本文作者是 + TigerBeetle 的联合创始人 Phil,这篇文章主要演示了基于 Zig 做 RocksDB + 的 binding,并在此基础上,增加 SQL 层,实现简单的 CRUD + 功能。代码地址:[eatonphil/zigrocks](https://github.com/eatonphil/zigrocks) + +- [Debugging undefined behavior caught by + Zig](https://devlog.hexops.com/2022/debugging-undefined-behavior/)。Hexops + 官博,本文讨论了一个有意思的问题:UBSan 的一个 bug 导致 [Mach + engine](https://machengine.org/) 的测试失败,更准确说是 UBSan + 需要内存地址对齐来工作,但是现在主流的处理器(x86、ARM、RISC-V + 等)都可以处理非对齐的地址访问。 + +- [packed struct field order reversed? : + Zig](https://www.reddit.com/r/Zig/comments/yvl60t/packed_struct_field_order_reversed/) + +- [Using rr to quickly debug memory + corruption](https://zig.news/david_vanderson/using-rr-to-quickly-debug-memory-corruption-2539),本文作者通过使用 + [rr](https://rr-project.org/) 这个工具来排查内存损坏的问题 + +- [A Programmer-Friendly I/O Abstraction Over io_uring and + kqueue](https://tigerbeetle.com/blog/a-friendly-abstraction-over-iouring-and-kqueue/)。 + TigerBeetle 官博,[HN + 讨论](https://news.ycombinator.com/item?id=33721075) + +- [How zig-spoon (and lots of coffee) helped me sort thousands of + pictures](https://zig.news/lhp/how-zig-spoon-and-lots-of-coffee-helped-me-sort-thousands-of-pictures-4gkj)。本文作者通过 + [spoon](https://sr.ht/~leon_plickat/zig-spoon/) + 这个库开发了一个帮助自己进行图片打标的 UI 工具, + +# [项目/工具]($section.id('项目/工具')) + +- [Zig + 程序设计语言中文手册](https://sxwangzhiwen.github.io/zigcndoc/zigcndoc.html) + GitHub 用户 [@sxwangzhiwen](https://github.com/sxwangzhiwen) + 制作,论坛[相关讨论](https://github.com/zigcc/forum/discussions/36)。 +- [dantecatalfamo/zig-dns: Experimental DNS library implemented in + zig](https://github.com/dantecatalfamo/zig-dns) +- [Neovim Zig Plugin written in + Lua](https://github.com/CadeMichael/zig.nvim) +- [trace.zig: A small and simple tracing client + library](https://zig.news/huntrss/tracezig-a-small-and-simple-tracing-client-library-2ffj),项目地址:[Zig + tracing / trace.zig](https://gitlab.com/zig_tracing/trace.zig) +- [Zig Support plugin for IntelliJ and CLion version 0.2.0 + released](https://zig.news/marioariasc/zig-support-plugin-for-intellij-and-clion-version-020-released-3g06) + +# [Zig 语言更新](https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2022-11-01..2022-12-01) diff --git a/content/monthly/202212.md b/content/monthly/202212.md deleted file mode 100644 index 6183e05..0000000 --- a/content/monthly/202212.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: 202212 | TBD -date: 2022-12-11T14:11:38+0800 -draft: true ---- - -# 观点/教程 - -- [Goodbye to the C++ Implementation of Zig ⚡ Zig Programming Language](https://ziglang.org/news/goodbye-cpp/) - -# 项目/工具 - -# [Zig 语言更新](https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2022-12-01..2023-01-01) diff --git a/content/monthly/202212.smd b/content/monthly/202212.smd new file mode 100644 index 0000000..e571d32 --- /dev/null +++ b/content/monthly/202212.smd @@ -0,0 +1,16 @@ +--- +.title = "202212 | TBD", +.date = @date("2022-12-11T14:11:38+0800"), +.author = "ZigCC", +.layout = "monthly.shtml", +.draft = false, +--- + +# [观点/教程]($section.id('观点/教程')) + +- [Goodbye to the C++ Implementation of Zig ⚡ Zig Programming + Language](https://ziglang.org/news/goodbye-cpp/) + +# [项目/工具]($section.id('项目/工具')) + +# [Zig 语言更新](https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2022-12-01..2023-01-01) diff --git a/content/monthly/202301.org b/content/monthly/202301.org deleted file mode 100644 index 70768ac..0000000 --- a/content/monthly/202301.org +++ /dev/null @@ -1,63 +0,0 @@ -#+TITLE: 202301 | 包管理来了 -#+DATE: 2023-01-31T20:05:19+0800 -#+LASTMOD: 2023-01-31T20:05:19+0800 - -* [[https://ziglang.org/download/0.10.1/release-notes.html][0.10.1]] 版本发布 -一个小版本,主要是 bugfix。最主要的功能是:[[https://github.com/ziglang/zig/pull/14265][Package Manager MVP]],Zig 终于开始支持包管理了! -不过才刚刚开始,有一个[[https://github.com/ziglang/zig/projects/4][面板]]来跟踪相关 issue 进度。使用的配置文件是 =build.zig.ini= ,格式如下: -#+begin_src conf -[package] -name=libffmpeg -version=5.1.2 - -[dependency] -name=libz -url=https://github.com/andrewrk/libz/archive/f0e53cc2391741034b144a2c2076ed8a9937b29b.tar.gz -hash=c9b30cffc40999d2c078ff350cbcee642970a224fe123c756d0892f876cf1aae - -[dependency] -name=libmp3lame -url=https://github.com/andrewrk/libmp3lame/archive/497568e670bfeb14ab6ef47fb6459a2251358e43.tar.gz -hash=9ba4f49895b174a3f918d489238acbc146bd393575062b2e3be33488b688e36f -#+end_src -=build.zig= 引用方式: -#+begin_src zig -const std = @import("std"); - -pub fn build(b: *std.build.Builder) void { - const target = b.standardTargetOptions(.{}); - const mode = b.standardReleaseOptions(); - - const libz_dep = b.dependency("libz", .{}); - const libmp3lame_dep = b.dependency("libmp3lame", .{}); - - const lib = b.addStaticLibrary("ffmpeg", null); - lib.setTarget(target); - lib.setBuildMode(mode); - lib.linkLibrary(libz_dep.artifact("z")); - lib.linkLibrary(libmp3lame_dep.artifact("mp3lame")); - lib.linkLibC(); - lib.addIncludePath("."); - lib.install(); -} -#+end_src -其他关注点: -- LLVM 升级到 [[http://releases.llvm.org/15.0.7/docs/ReleaseNotes.html][15.0.7]] -- 是 0.10.x 的最后一个 release 版本 -* 观点/教程 -- [[https://zig.news/yglcode/code-study-interface-idiomspatterns-in-zig-standard-libraries-4lkj][Code study: interface idioms/patterns in zig standard libraries]] :: - 由于 Zig 目前还不支持接口抽空,本文介绍了标准库中来实现类似功能的五种方式 -- [[https://kihlander.net/post/a-zig-diary/][A Zig Diary]] :: 作者分享了对 Zig 的使用体验 -- [[https://datastackshow.com/podcast/why-accounting-needs-its-own-database-with-joran-greef-of-tiger-beetle/][Why Accounting Needs Its Own Database with Joran Greef of Tiger Beetle]] :: 播客分享 -- [[https://0110.be/posts/Crossplatform_JNI_builds_with_Zig][Crossplatform JNI builds with Zig]] :: 又一个使用 Zig 作为交叉编译的例子 -* 项目/工具 -- [[https://zig.news/renerocksai/introducing-zap-blazingly-fast-backends-in-zig-3jhh][Introducing ⚡zap⚡ - blazingly fast backends in zig]] :: - Zap 是 Zig 对 [[https://facil.io/][facil.io - The C Web Application Framework]] 的封装,本文算是对它的宣传。 -- [[https://zig.news/auguste/indexing-every-zig-for-great-justice-4l1h][Indexing every Zig for great justice]] :: - 本文介绍了另一种语言服务器协议(LSP):SCIP,并用 zig 实现。项目处于早期阶段。 -- [[https://github.com/dantecatalfamo/zig-git][dantecatalfamo/zig-git]] :: - Implementing git structures and functions in zig -- [[https://github.com/axiomhq/zig-hyperloglog][axiomhq/zig-hyperloglog]] :: Zig library for HyperLogLog estimation -- [[https://thisweekinzig.mataroa.blog/][This Week In Zig]] :: 一个介绍 Zig 的周刊,主要是 master 分支上的改动 - -* [[https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2023-01-01..2023-02-01][Zig 语言更新]] diff --git a/content/monthly/202301.smd b/content/monthly/202301.smd new file mode 100644 index 0000000..7fb1cf9 --- /dev/null +++ b/content/monthly/202301.smd @@ -0,0 +1,101 @@ +--- +.title = "202301 | 包管理来了", +.date = @date("2023-01-31T20:05:19+0800"), +.author = "ZigCC", +.layout = "monthly.shtml", +.draft = false, +--- + +# [0.10.1](https://ziglang.org/download/0.10.1/release-notes.html) 版本发布 + +一个小版本,主要是 bugfix。最主要的功能是:[Package Manager +MVP](https://github.com/ziglang/zig/pull/14265),Zig +终于开始支持包管理了! +不过才刚刚开始,有一个[面板](https://github.com/ziglang/zig/projects/4)来跟踪相关 +issue 进度。使用的配置文件是 `build.zig.ini` ,格式如下: + +``` conf +[package] +name=libffmpeg +version=5.1.2 + +[dependency] +name=libz +url=https://github.com/andrewrk/libz/archive/f0e53cc2391741034b144a2c2076ed8a9937b29b.tar.gz +hash=c9b30cffc40999d2c078ff350cbcee642970a224fe123c756d0892f876cf1aae + +[dependency] +name=libmp3lame +url=https://github.com/andrewrk/libmp3lame/archive/497568e670bfeb14ab6ef47fb6459a2251358e43.tar.gz +hash=9ba4f49895b174a3f918d489238acbc146bd393575062b2e3be33488b688e36f +``` + +`build.zig` 引用方式: + +``` zig +const std = @import("std"); + +pub fn build(b: *std.build.Builder) void { + const target = b.standardTargetOptions(.{}); + const mode = b.standardReleaseOptions(); + + const libz_dep = b.dependency("libz", .{}); + const libmp3lame_dep = b.dependency("libmp3lame", .{}); + + const lib = b.addStaticLibrary("ffmpeg", null); + lib.setTarget(target); + lib.setBuildMode(mode); + lib.linkLibrary(libz_dep.artifact("z")); + lib.linkLibrary(libmp3lame_dep.artifact("mp3lame")); + lib.linkLibC(); + lib.addIncludePath("."); + lib.install(); +} +``` + +其他关注点: + +- LLVM 升级到 + [15.0.7](http://releases.llvm.org/15.0.7/docs/ReleaseNotes.html) +- 是 0.10.x 的最后一个 release 版本 + +# [观点/教程]($section.id('观点/教程')) + +[Code study: interface idioms/patterns in zig standard +libraries](https://zig.news/yglcode/code-study-interface-idiomspatterns-in-zig-standard-libraries-4lkj) +由于 Zig +目前还不支持接口抽空,本文介绍了标准库中来实现类似功能的五种方式 + +[A Zig Diary](https://kihlander.net/post/a-zig-diary/) +作者分享了对 Zig 的使用体验 + +[Why Accounting Needs Its Own Database with Joran Greef of Tiger +Beetle](https://datastackshow.com/podcast/why-accounting-needs-its-own-database-with-joran-greef-of-tiger-beetle/) +播客分享 + +[Crossplatform JNI builds with +Zig](https://0110.be/posts/Crossplatform_JNI_builds_with_Zig) +又一个使用 Zig 作为交叉编译的例子 + +# [项目/工具]($section.id('项目/工具')) + +[Introducing ⚡zap⚡ - blazingly fast backends in +zig](https://zig.news/renerocksai/introducing-zap-blazingly-fast-backends-in-zig-3jhh) +Zap 是 Zig 对 [facil.io - The C Web Application +Framework](https://facil.io/) 的封装,本文算是对它的宣传。 + +[Indexing every Zig for great +justice](https://zig.news/auguste/indexing-every-zig-for-great-justice-4l1h) +本文介绍了另一种语言服务器协议(LSP):SCIP,并用 zig +实现。项目处于早期阶段。 + +[dantecatalfamo/zig-git](https://github.com/dantecatalfamo/zig-git) +Implementing git structures and functions in zig + +[axiomhq/zig-hyperloglog](https://github.com/axiomhq/zig-hyperloglog) +Zig library for HyperLogLog estimation + +[This Week In Zig](https://thisweekinzig.mataroa.blog/) +一个介绍 Zig 的周刊,主要是 master 分支上的改动 + +# [Zig 语言更新](https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2023-01-01..2023-02-01) diff --git a/content/monthly/202302.org b/content/monthly/202302.org deleted file mode 100644 index 4bd6cad..0000000 --- a/content/monthly/202302.org +++ /dev/null @@ -1,64 +0,0 @@ -#+TITLE: 202302 | 精益求精的包管理 -#+DATE: 2023-02-26T17:36:12+0800 -#+LASTMOD: 2023-01-31T20:05:19+0800 - -* 包管理器进展 -包管理器自 [[https://github.com/ziglang/zig/pull/14265][#14265]] 合并后一直在不断推进,以下两个是最主要的改变: -- [[https://github.com/ziglang/zig/issues/14307][build system terminology update: package, project, module, dependency]] - - 这里重新梳理了现在的术语,主要有以下几个: - - =package= 文件的集合,由文件的 hash 值唯一指定,一个 package 可能包含任意数目的 compilation artifacts 与 modules。 - - =dependency= 不同 package 之间的有向边,一个 package 可以有任意个依赖,一个 package 也可以用作任意项目的依赖 - - =module= 文件的集合,每一个模块都有一个 root 文件,在被 =@import= 时用到。 - - =compilation artifact= 编译构建产物,可以是 static library,dynamic library,an executable 或 an object file,对应之前版本的 =LibExeObjStep= -- [[https://github.com/ziglang/zig/pull/14523][introduce Zig Object Notation and use it for the build manifest file (build.zig.zon)]] - - 使用 zon 格式替代之前的 ini,格式如下: - #+begin_src zig -.{ - .name = "awesome-cli", - .version = "0.1.0", - .dependencies = .{ - .simargs = .{ - .url = "https://github.com/jiacai2050/simargs/archive/0a1a2afd072cc915009a063075743192fc6b1fd5.tar.gz", - .hash = "1220a6554eccb2e9a9d7d63047e062314851ffd11315b9e6d1b5e06a9dde3275f150", - }, - }, -} - #+end_src - 一些使用了包管理的实际项目: - - [[https://github.com/andrewrk/ffmpeg][andrewrk/ffmpeg: ffmpeg with the build system replaced by zig]] - - [[https://github.com/jiacai2050/loc][jiacai2050/loc: Lines of code in Zig]],适配包管理的相关 [[https://github.com/jiacai2050/loc/commit/7b01c09a4ba9d3ddc3d067cc6af654601a99035a][commit 修改]] - - [[https://github.com/PCRE2Project/pcre2/pull/206][PCRE2Project/pcre2: zig build support]] - - [[https://github.com/nikneym/ws][nikneym/ws: WebSocket library for Zig]] - - [[https://github.com/natecraddock/ziglua/issues/6][Zig package manager · Issue #6 · natecraddock/ziglua]] - -也欢迎大家给自己熟悉的 C/C++ 项目提 PR 让其支持 zig build,让构建不再那么痛苦。 -* 观点/教程 -- [[https://matklad.github.io/2023/02/10/how-a-zig-ide-could-work.html][How a Zig IDE Could Work]] -- [[https://devlog.hexops.com/2023/zig-0-11-breaking-build-changes/][Zig tips: v0.11 std.build API / package manager changes | Hexops' devlog]] -- [[https://lobste.rs/s/zh3ulk/pcre2_support_zig_build][pcre2 support zig build]] -- [[https://zig.news/andrewrk/multi-object-for-loops-data-oriented-design-41ob][Multi-Object For Loops + Struct-Of-Arrays]] -- [[https://kristoff.it/blog/zig-multi-sequence-for-loops/][Zig's Curious Multi-Sequence For Loops]],[[https://lobste.rs/s/ihf30a/zig_s_curious_multi_sequence_for_loops][Lobster 评论]] - 上面这两篇的文章都是演示了最新的 for 语法,开始支持了 range: - #+begin_src zig -for (0..4) |n| { - std.debug.print("{} ", .{n}); -} - #+end_src - 同时也支持了一次性迭代多个数组的功能: - #+begin_src zig - -var elems = [_][]const u8 { "water", "earth", "fire", "wind" }; -var nats = [_][]const u8 { "tribes", "kingdom", "nation", "nomads" }; - -for (elems, nats) |e, n| { - std.debug.print("{s} {s}\n", .{e, n}); -} -#+end_src -- [[https://blog.orhun.dev/zig-bits-01/][Zig Bits 0x1: Returning slices from functions]] - 这篇文章演示了从一个函数内返回局部变量的问题与解法 -- [[https://blog.deckc.hair/2023-02-22-smoking-hot-binary-search-in-zig.html][Smoking Hot Binary Search In Zig]] -* 项目/工具 -- [[https://tigerbeetle.com/blog/2023-02-21-writing-high-performance-clients-for-tigerbeetle/][Writing high-performance clients for TigerBeetle]] -* [[https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2023-02-01..2023-03-01][Zig 语言更新]] diff --git a/content/monthly/202302.smd b/content/monthly/202302.smd new file mode 100644 index 0000000..12527f1 --- /dev/null +++ b/content/monthly/202302.smd @@ -0,0 +1,113 @@ +--- +.title = "202302 | 精益求精的包管理", +.date = @date("2023-02-26T17:36:12+0800"), +.author = "ZigCC", +.layout = "monthly.shtml", +.draft = false, +--- + +# [包管理器进展]($section.id('包管理器进展')) + +包管理器自 [\#14265](https://github.com/ziglang/zig/pull/14265) +合并后一直在不断推进,以下两个是最主要的改变: + +- [build system terminology update: package, project, module, + dependency](https://github.com/ziglang/zig/issues/14307) + + 这里重新梳理了现在的术语,主要有以下几个: + + - `package` 文件的集合,由文件的 hash 值唯一指定,一个 package + 可能包含任意数目的 compilation artifacts 与 modules。 + - `dependency` 不同 package 之间的有向边,一个 package + 可以有任意个依赖,一个 package 也可以用作任意项目的依赖 + - `module` 文件的集合,每一个模块都有一个 root 文件,在被 `@import` + 时用到。 + - `compilation artifact` 编译构建产物,可以是 static library,dynamic + library,an executable 或 an object file,对应之前版本的 + `LibExeObjStep` + +- [introduce Zig Object Notation and use it for the build manifest file + (build.zig.zon)](https://github.com/ziglang/zig/pull/14523) + + 使用 zon 格式替代之前的 ini,格式如下: + + ``` zig + .{ + .name = "awesome-cli", + .version = "0.1.0", + .dependencies = .{ + .simargs = .{ + .url = "https://github.com/jiacai2050/simargs/archive/0a1a2afd072cc915009a063075743192fc6b1fd5.tar.gz", + .hash = "1220a6554eccb2e9a9d7d63047e062314851ffd11315b9e6d1b5e06a9dde3275f150", + }, + }, + } + ``` + + 一些使用了包管理的实际项目: + + - [andrewrk/ffmpeg: ffmpeg with the build system replaced by + zig](https://github.com/andrewrk/ffmpeg) + - [jiacai2050/loc: Lines of code in + Zig](https://github.com/jiacai2050/loc),适配包管理的相关 [commit + 修改](https://github.com/jiacai2050/loc/commit/7b01c09a4ba9d3ddc3d067cc6af654601a99035a) + - [PCRE2Project/pcre2: zig build + support](https://github.com/PCRE2Project/pcre2/pull/206) + - [nikneym/ws: WebSocket library for + Zig](https://github.com/nikneym/ws) + - [Zig package manager · Issue \#6 · + natecraddock/ziglua](https://github.com/natecraddock/ziglua/issues/6) + +也欢迎大家给自己熟悉的 C/C++ 项目提 PR 让其支持 zig +build,让构建不再那么痛苦。 + +# [观点/教程]($section.id('观点/教程')) + +- [How a Zig IDE Could + Work](https://matklad.github.io/2023/02/10/how-a-zig-ide-could-work.html) + +- [Zig tips: v0.11 std.build API / package manager changes | Hexops’ + devlog](https://devlog.hexops.com/2023/zig-0-11-breaking-build-changes/) + +- [pcre2 support zig + build](https://lobste.rs/s/zh3ulk/pcre2_support_zig_build) + +- [Multi-Object For Loops + + Struct-Of-Arrays](https://zig.news/andrewrk/multi-object-for-loops-data-oriented-design-41ob) + +- [Zig’s Curious Multi-Sequence For + Loops](https://kristoff.it/blog/zig-multi-sequence-for-loops/),[Lobster + 评论](https://lobste.rs/s/ihf30a/zig_s_curious_multi_sequence_for_loops) + 上面这两篇的文章都是演示了最新的 for 语法,开始支持了 range: + + ``` zig + for (0..4) |n| { + std.debug.print("{} ", .{n}); + } + ``` + + 同时也支持了一次性迭代多个数组的功能: + + ``` zig + + var elems = [_][]const u8 { "water", "earth", "fire", "wind" }; + var nats = [_][]const u8 { "tribes", "kingdom", "nation", "nomads" }; + + for (elems, nats) |e, n| { + std.debug.print("{s} {s}\n", .{e, n}); + } + ``` + +- [Zig Bits 0x1: Returning slices from + functions](https://blog.orhun.dev/zig-bits-01/) + 这篇文章演示了从一个函数内返回局部变量的问题与解法 + +- [Smoking Hot Binary Search In + Zig](https://blog.deckc.hair/2023-02-22-smoking-hot-binary-search-in-zig.html) + +# [项目/工具]($section.id('项目/工具')) + +- [Writing high-performance clients for + TigerBeetle](https://tigerbeetle.com/blog/2023-02-21-writing-high-performance-clients-for-tigerbeetle/) + +# [Zig 语言更新](https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2023-02-01..2023-03-01) diff --git a/content/monthly/202303.org b/content/monthly/202303.org deleted file mode 100644 index c546fae..0000000 --- a/content/monthly/202303.org +++ /dev/null @@ -1,93 +0,0 @@ -#+TITLE: 202303 | 并发编译 -#+DATE: 2023-04-10T19:25:59+0800 -#+LASTMOD: 2023-04-10T19:25:59+0800 - -* 观点/教程 -- [[https://www.reddit.com/r/zig/comments/11wmoky][Creating arbitrary error values by using error.Something syntax]] :: 下面两种方式是等价的: - #+begin_src zig - const err = error.FileNotFound; - const err = (error {FileNotFound}).FileNotFound; - #+end_src -- [[https://notes.eatonphil.com/errors-and-zig.html][Errors and Zig]] :: 主要讲述了 Zig 中如何处理错误,如何携带上下文信息 - #+begin_src zig -var x = try thingThatCouldFail(); - -if (thingThatCouldFail()) |good_value| { - x = good_value; - break; -} else |_| { - // do something that should fix it for the next time - tries -= 1; -} - #+end_src -- [[https://blog.orhun.dev/zig-bits-02/][Zig Bits 0x2: Using defer to defeat memory leaks]] :: 主要介绍了如何探测内存泄漏,如何用 =defer= 来规避 -- [[https://zigurust.gitlab.io/blog/naive-map/][Naive parallel map implementation in Rust and Zig]] :: -- [[https://iamkroot.github.io/blog/zig-memleak][The Curious Case of a Memory Leak in a Zig program]] :: -- [[https://zackoverflow.dev/writing/unsafe-rust-vs-zig/][When Zig is safer and faster than Rust]] :: 比较有趣的文章,作者使用 unsafe rust 与 zig 来实现一个 bytecode 解释器,比较重要的一点是具备 mark-sweep 的 GC 功能。 -- [[https://www.infoworld.com/article/3689648/meet-the-zig-programming-language.html][Meet Zig: The modern alternative to C | InfoWorld]] :: 一篇科普 Zig 的文章 -- [[https://flyx.org/cross-packaging/][Cross-Compiling and packaging C, Go and Zig projects with Nix]] :: 文章介绍了如何 - 利用 Nix 进行交叉编译,对于 C 依赖,作者是通过修改 =pkg-config= 的 =*.pc= 来支持的 -- [[https://www.openmymind.net/Zig-Quirks/][Zig Quirks]] :: 介绍 Zig 的一些特点 -- [[https://matklad.github.io/2023/03/26/zig-and-rust.html][Zig And Rust]] :: -* 项目/工具 -- [[https://github.com/macovedj/doink][macovedj/doink]] :: Making WebAssembly Components with Zig -- [[https://github.com/craftlinks/zig_learn_opengl][craftlinks/zig_learn_opengl]] :: : Follow the Learn-OpenGL book using Zig -- [[https://github.com/b0bleet/zvisor][b0bleet/zvisor]] :: Zig-based Hypervisor (WIP) -- [[https://github.com/flouthoc/ztick][flouthoc/ztick]] :: Tiny desktop utility to keep notes -- [[https://github.com/ringtailsoftware/zig-wasm-audio-framebuffer][ringtailsoftware/zig-wasm-audio-framebuffer]] :: Examples of integrating Zig and Wasm for audio and graphics on the web -* [[https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2023-03-01..2023-04-01][Zig 语言更新]] -- [[https://github.com/ziglang/zig/pull/14647][zig build: run steps in parallel #14647]] :: 一个比较大的更新,编译支持了并发。由于改动比较大,该 PR 合并后出现了一些 bug,一个影响比较大的是 test 的构建方式不一样了。 - #+begin_src diff -- test_step.dependOn(&exe_tests.step); -+ test_step.dependOn(&exe_tests.run().step); - #+end_src -之前老方式写的 =test_step= 在新版本不会再执行了。这样对于 Build 系统来说其实是更合理了。 - -现在 =addTest= 和 =addExecutable= 一样,输出都是 =CompileStep= ,它默认不会执行,需要调用 =run()= 拿到 run step 才可以。 - -* Zig 构建系统介绍 -构建系统其实是 Zig 生态中比较重要的一环,和 Rust 不同,Zig 即是一门编程语言,也是一系列工具链,比如编译 Zig 时,没有 zigc 这个二进制文件,用的是 =zig build-exe= 或 =build-lib= 。 - -=build.zig= 的作用就是提供了一套声明式 API 来构造 =build-exe= 的参数。这里面有一个核心概念: =Step= ,它构成了一个有向无环图,用来驱动整个编译过程。 - -每个 Step 做的事情是由 =MakeFn= 定义的,它的签名是: -#+begin_src zig -pub const MakeFn = *const fn (self: *Step, prog_node: *std.Progress.Node) anyerror!void; -#+end_src - -但一般来说,我们并不需要自己去实现 MakeFn,内置的 Step 已经可以满足大部分需求,比如: -- =CompileStep= 编译二进制、动态链接库、静态链接库 -- =InstallArtifactStep= 把编译生成的文件复制到 =zig-out= 中 -- =ObjCopyStep= 执行 objcopy 命令 -- =OptionsStep= 可以用来定义编译时的一些常量,作为 module 被当前程序使用,比如把当前项目的构建时间、Git 信息写入到代码中。[[https://www.digitalocean.com/community/tutorials/using-ldflags-to-set-version-information-for-go-applications][类似于 Go]] 里面的 ~go build -ldflags="-X 'package_path.variable_name=new_value'"~ -- =RunStep= 执行二进制 - -Step 中有一类比较特殊,称为 TopLevelStep(简称 TLS),它们可以直接通过 =zig build {topLevelStep}= 的方式来执行,Zig 默认有两个 TLS: -- install,安装二进制 -- uninstall,卸载二进制 - -#+begin_src zig -const exe = b.addExecutable(.{ - .name = "awesome", - .root_source_file = .{ .path = "src/main.zig" }, - .target = target, - .optimize = optimize, -}); -const run_cmd = exe.run(); -if (b.args) |args| { - run_cmd.addArgs(args); -} -const run_step = b.step("run-" , "Run " ++ name); -run_step.dependOn(&run_cmd.step); - -#+end_src -上面这段代码就定义了一个 TLS: =run= ,它依赖 exe 的执行 step,exe 本身又是个编译 step,因此在 =zig build run= 时,会依次执行: -#+begin_src zig -CompileStep --> RunStep --> TLS -#+end_src - -Zig 的编译系统设计的还是挺巧妙的,而且 =build.zig= 是新人接触 Zig 是打交道最多的代码,如果搞不清它的执行过程,一方面心里比较难受,另一实际方面是影响问题排查。 - -如果读者还是对 =build.zig= 有所困惑,可以参考下面这两个文章,虽然有些过时,但是原理是一样的: -- [[https://mitchellh.com/zig/build-internals][Zig Build System Internals – Mitchell Hashimoto]] -- [[https://zig.news/xq/zig-build-explained-part-1-59lf][zig build explained - part 1 - Zig NEWS ⚡]] diff --git a/content/monthly/202303.smd b/content/monthly/202303.smd new file mode 100644 index 0000000..845840f --- /dev/null +++ b/content/monthly/202303.smd @@ -0,0 +1,167 @@ +--- +.title = "202303 | 并发编译", +.date = @date("2023-04-10T19:25:59+0800"), +.author = "ZigCC", +.layout = "monthly.shtml", +.draft = false, +--- + +# [观点/教程]($section.id('观点/教程')) + +[Creating arbitrary error values by using error.Something +syntax](https://www.reddit.com/r/zig/comments/11wmoky) +下面两种方式是等价的: + +``` zig +const err = error.FileNotFound; +const err = (error {FileNotFound}).FileNotFound; +``` + +[Errors and Zig](https://notes.eatonphil.com/errors-and-zig.html) +主要讲述了 Zig 中如何处理错误,如何携带上下文信息 + +``` zig +var x = try thingThatCouldFail(); + +if (thingThatCouldFail()) |good_value| { + x = good_value; + break; +} else |_| { + // do something that should fix it for the next time + tries -= 1; +} +``` + +[Zig Bits 0x2: Using defer to defeat memory +leaks](https://blog.orhun.dev/zig-bits-02/) +主要介绍了如何探测内存泄漏,如何用 `defer` 来规避 + +[Naive parallel map implementation in Rust and +Zig](https://zigurust.gitlab.io/blog/naive-map/) + +[The Curious Case of a Memory Leak in a Zig +program](https://iamkroot.github.io/blog/zig-memleak) + +[When Zig is safer and faster than +Rust](https://zackoverflow.dev/writing/unsafe-rust-vs-zig/) +比较有趣的文章,作者使用 unsafe rust 与 zig 来实现一个 bytecode +解释器,比较重要的一点是具备 mark-sweep 的 GC 功能。 + +[Meet Zig: The modern alternative to C | +InfoWorld](https://www.infoworld.com/article/3689648/meet-the-zig-programming-language.html) +一篇科普 Zig 的文章 + +[Cross-Compiling and packaging C, Go and Zig projects with +Nix](https://flyx.org/cross-packaging/) +文章介绍了如何 利用 Nix 进行交叉编译,对于 C 依赖,作者是通过修改 +`pkg-config` 的 `*.pc` 来支持的 + +[Zig Quirks](https://www.openmymind.net/Zig-Quirks/) +介绍 Zig 的一些特点 + +[Zig And Rust](https://matklad.github.io/2023/03/26/zig-and-rust.html) + +# [项目/工具]($section.id('项目/工具')) + +[macovedj/doink](https://github.com/macovedj/doink) +Making WebAssembly Components with Zig + +[craftlinks/ziglearnopengl](https://github.com/craftlinks/zig_learn_opengl) + +Follow the Learn-OpenGL book using Zig + + +[b0bleet/zvisor](https://github.com/b0bleet/zvisor) +Zig-based Hypervisor (WIP) + +[flouthoc/ztick](https://github.com/flouthoc/ztick) +Tiny desktop utility to keep notes + +[ringtailsoftware/zig-wasm-audio-framebuffer](https://github.com/ringtailsoftware/zig-wasm-audio-framebuffer) +Examples of integrating Zig and Wasm for audio and graphics on the web + +# [Zig 语言更新](https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2023-03-01..2023-04-01) + +[zig build: run steps in parallel +\#14647](https://github.com/ziglang/zig/pull/14647) +一个比较大的更新,编译支持了并发。由于改动比较大,该 PR 合并后出现了一些 +bug,一个影响比较大的是 test 的构建方式不一样了。 + +``` diff +- test_step.dependOn(&exe_tests.step); ++ test_step.dependOn(&exe_tests.run().step); +``` + +之前老方式写的 `test_step` 在新版本不会再执行了。这样对于 Build +系统来说其实是更合理了。 + +现在 `addTest` 和 `addExecutable` 一样,输出都是 `CompileStep` +,它默认不会执行,需要调用 `run()` 拿到 run step 才可以。 + +# [Zig 构建系统介绍]($section.id('zig-build-system-intro')) + +构建系统其实是 Zig 生态中比较重要的一环,和 Rust 不同,Zig +即是一门编程语言,也是一系列工具链,比如编译 Zig 时,没有 zigc +这个二进制文件,用的是 `zig build-exe` 或 `build-lib` 。 + +`build.zig` 的作用就是提供了一套声明式 API 来构造 `build-exe` +的参数。这里面有一个核心概念: `Step` +,它构成了一个有向无环图,用来驱动整个编译过程。 + +每个 Step 做的事情是由 `MakeFn` 定义的,它的签名是: + +``` zig +pub const MakeFn = *const fn (self: *Step, prog_node: *std.Progress.Node) anyerror!void; +``` + +但一般来说,我们并不需要自己去实现 MakeFn,内置的 Step +已经可以满足大部分需求,比如: + +- `CompileStep` 编译二进制、动态链接库、静态链接库 +- `InstallArtifactStep` 把编译生成的文件复制到 `zig-out` 中 +- `ObjCopyStep` 执行 objcopy 命令 +- `OptionsStep` 可以用来定义编译时的一些常量,作为 module + 被当前程序使用,比如把当前项目的构建时间、Git + 信息写入到代码中。[类似于 + Go](https://www.digitalocean.com/community/tutorials/using-ldflags-to-set-version-information-for-go-applications) + 里面的 `go build -ldflags="-X 'package_path.variable_name=new_value'"` +- `RunStep` 执行二进制 + +Step 中有一类比较特殊,称为 TopLevelStep(简称 TLS),它们可以直接通过 +`zig build {topLevelStep}` 的方式来执行,Zig 默认有两个 TLS: + +- install,安装二进制 +- uninstall,卸载二进制 + +``` zig +const exe = b.addExecutable(.{ + .name = "awesome", + .root_source_file = .{ .path = "src/main.zig" }, + .target = target, + .optimize = optimize, +}); +const run_cmd = exe.run(); +if (b.args) |args| { + run_cmd.addArgs(args); +} +const run_step = b.step("run-" , "Run " ++ name); +run_step.dependOn(&run_cmd.step); +``` + +上面这段代码就定义了一个 TLS: `run` ,它依赖 exe 的执行 step,exe +本身又是个编译 step,因此在 `zig build run` 时,会依次执行: + +``` zig +CompileStep --> RunStep --> TLS +``` + +Zig 的编译系统设计的还是挺巧妙的,而且 `build.zig` 是新人接触 Zig +是打交道最多的代码,如果搞不清它的执行过程,一方面心里比较难受,另一实际方面是影响问题排查。 + +如果读者还是对 `build.zig` +有所困惑,可以参考下面这两个文章,虽然有些过时,但是原理是一样的: + +- [Zig Build System Internals\ – Mitchell + Hashimoto](https://mitchellh.com/zig/build-internals) +- [zig build explained - part 1 - Zig NEWS + ⚡](https://zig.news/xq/zig-build-explained-part-1-59lf) diff --git a/content/monthly/202304.org b/content/monthly/202304.org deleted file mode 100644 index 09776ae..0000000 --- a/content/monthly/202304.org +++ /dev/null @@ -1,37 +0,0 @@ -#+TITLE: 202304 | 首次闯入 Tiobe 前 50 -#+DATE: 2023-05-03T10:31:04+0800 -#+LASTMOD: 2023-09-03T20:10:11+0800 - -* 重大事件 -在 2023 四月份的 [[https://www.tiobe.com/tiobe-index/][Tiobe]] 指数上,Zig [[https://www.techrepublic.com/article/tiobe-index-language-rankings/][排名 46]],尽管 Loris 发推表示这个数字对 Zig 来说没什么实际意义,但对于多数吃瓜群众来说,这还是十分让人鼓舞的。 - -#+begin_quote -For people who heard about Zig just recently: - -- Zig is not 2x faster than Rust, despite what recent benchmarks might lead you to believe. - -- You won't find many Zig jobs for a few years still, despite the Tiobe stuff. - -- Don't join to the Zig community just to rant about Rust. - -— Loris Cro ⚡ (@croloris) [[https://twitter.com/croloris/status/1646555550358831131][April 13, 2023]] -#+end_quote> -* 观点/教程 -- [[https://zig.news/kristoff/when-should-i-use-an-untagged-union-56ek][When should I use an UNTAGGED Union?]] :: Loris 的文章,作者利用访问 untagged union 的未赋值字段是一种 safety-checked UB 的行为,来解决数组成员被重新赋值过的情况。 -- [[https://zig.news/rutenkolk/data-driven-polymorphism-45bk][Data driven polymorphism]] :: 作者用 Zig 来实现 Clojure 语言中的 [[https://clojuredocs.org/clojure.core/defmulti][defmulti]],以达到『动态派发』的效果 -- [[https://zig.news/aryaelfren/testing-and-files-as-structs-n94][Testing and Files as Structs]] :: 作者演示了一个文件作为 struct 的效果,这样导入时就可以用 =const Node = @import("Node.zig")= 的方式了。 -- [[https://zig.news/ityonemo/sneaky-error-payloads-1aka][Sneaky Error Payloads]] :: 一种在错误中携带上下文信息的方式,上一期的月报也有类似讨论。 [[https://notes.eatonphil.com/errors-and-zig.html][Errors and Zig]] -- [[https://www.openmymind.net/Regular-Expressions-in-Zig/][Regular Expressions in Zig]] :: 由于 Zig 现在不支持 C 中的 bitfields,因此无法直接使用 Posix 的 =regex.h= ,这篇文章介绍了一种解决方法。 -- [[https://en.liujiacai.net/2023/04/13/zig-build-system/][Zig Build System]] :: 对 Zig build 系统的介绍 -- [[https://matklad.github.io/2023/04/13/reasonable-bootstrap.html][Reasonable Bootstrap]] :: 探讨了编译器如何实现自举的方式 -- [[https://matklad.github.io/2023/04/23/data-oriented-parallel-value-interner.html][Data Oriented Parallel Value Interner]] :: Matklad 探讨了如何实现一个高性能的 Interner -- [[https://www.youtube.com/watch?v=w3WYdYyjek4][TigerStyle! (Or How To Design Safer Systems in Less Time)]] :: Systems Distributed 23 视频。[[https://www.bilibili.com/video/BV1fm4y1C7XL][B 站链接]] -- [[https://www.youtube.com/watch?v=MqbVoSs0lXk][What Is a Database?]] :: Systems Distributed 23 视频,[[https://www.bilibili.com/video/BV1gP41117zY/][B 站链接]],作者博客:[[https://www.scattered-thoughts.net/][Scattered Thoughts]] -* 项目/工具 -- [[https://zig.news/nameless/coming-soon-to-a-zig-near-you-http-client-5b81][Coming Soon to a Zig Near You: HTTP Client]] :: 对标准库 =std.http= 的介绍。 -- [[https://blog.orhun.dev/zig-bits-03/][Zig Bits 0x3: Mastering project management in Zig]] :: 介绍了如何更好地维护一个 Zig 项目,包括:新增依赖、增加测试覆盖率、增加文档、基于 GitHub Action 做持续集成等。 -- [[https://github.com/ityonemo/zigler][ityonemo/zigler]] :: zig nifs in elixir -- [[https://bingcicle.github.io/posts/ziggifying-kilo.html][Ziggifying Kilo]] :: 使用 Zig 重写 [[https://github.com/antirez/kilo][kilo]] 编辑器,目前仅能在 Linux 上运行 -- [[https://github.com/jakubgiesler/VecZig][jakubgiesler/VecZig]] :: Vector implementation in Zig -- [[https://github.com/b0bleet/zvisor][b0bleet/zvisor]] :: Zvisor is an open-source hypervisor written in the Zig programming language, which provides a modern and efficient approach to systems programming. -* [[https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2023-04-01..2023-05-01][Zig 语言更新]] diff --git a/content/monthly/202304.smd b/content/monthly/202304.smd new file mode 100644 index 0000000..dee548b --- /dev/null +++ b/content/monthly/202304.smd @@ -0,0 +1,109 @@ +--- +.title = "202304 | 首次闯入 Tiobe 前 50", +.date = @date("2023-05-03T10:31:04+0800"), +.author = "ZigCC", +.layout = "monthly.shtml", +.draft = false, +--- + +# [重大事件]($section.id('重大事件')) + +在 2023 四月份的 [Tiobe](https://www.tiobe.com/tiobe-index/) 指数上,Zig +[排名 +46](https://www.techrepublic.com/article/tiobe-index-language-rankings/),尽管 +Loris 发推表示这个数字对 Zig +来说没什么实际意义,但对于多数吃瓜群众来说,这还是十分让人鼓舞的。 + +> For people who heard about Zig just recently: +> +> - Zig is not 2x faster than Rust, despite what recent benchmarks might +> lead you to believe. +> +> - You won’t find many Zig jobs for a few years still, despite the +> Tiobe stuff. +> +> - Don’t join to the Zig community just to rant about Rust. +> +> — Loris Cro ⚡ (@croloris) [April 13, +> 2023](https://twitter.com/croloris/status/1646555550358831131) + +\> + +# [观点/教程]($section.id('观点/教程')) + +[When should I use an UNTAGGED +Union?](https://zig.news/kristoff/when-should-i-use-an-untagged-union-56ek) +Loris 的文章,作者利用访问 untagged union 的未赋值字段是一种 +safety-checked UB 的行为,来解决数组成员被重新赋值过的情况。 + +[Data driven +polymorphism](https://zig.news/rutenkolk/data-driven-polymorphism-45bk) +作者用 Zig 来实现 Clojure 语言中的 +[defmulti](https://clojuredocs.org/clojure.core/defmulti),以达到『动态派发』的效果 + +[Testing and Files as +Structs](https://zig.news/aryaelfren/testing-and-files-as-structs-n94) +作者演示了一个文件作为 struct 的效果,这样导入时就可以用 +`const Node = @import("Node.zig")` 的方式了。 + +[Sneaky Error +Payloads](https://zig.news/ityonemo/sneaky-error-payloads-1aka) +一种在错误中携带上下文信息的方式,上一期的月报也有类似讨论。 [Errors and +Zig](https://notes.eatonphil.com/errors-and-zig.html) + +[Regular Expressions in +Zig](https://www.openmymind.net/Regular-Expressions-in-Zig/) +由于 Zig 现在不支持 C 中的 bitfields,因此无法直接使用 Posix 的 +`regex.h` ,这篇文章介绍了一种解决方法。 + +[Zig Build +System](https://en.liujiacai.net/2023/04/13/zig-build-system/) +对 Zig build 系统的介绍 + +[Reasonable +Bootstrap](https://matklad.github.io/2023/04/13/reasonable-bootstrap.html) +探讨了编译器如何实现自举的方式 + +[Data Oriented Parallel Value +Interner](https://matklad.github.io/2023/04/23/data-oriented-parallel-value-interner.html) +Matklad 探讨了如何实现一个高性能的 Interner + +[TigerStyle! (Or How To Design Safer Systems in Less +Time)](https://www.youtube.com/watch?v=w3WYdYyjek4) +Systems Distributed 23 视频。[B +站链接](https://www.bilibili.com/video/BV1fm4y1C7XL) + +[What Is a Database?](https://www.youtube.com/watch?v=MqbVoSs0lXk) +Systems Distributed 23 视频,[B +站链接](https://www.bilibili.com/video/BV1gP41117zY/),作者博客:[Scattered +Thoughts](https://www.scattered-thoughts.net/) + +# [项目/工具]($section.id('项目/工具')) + +[Coming Soon to a Zig Near You: HTTP +Client](https://zig.news/nameless/coming-soon-to-a-zig-near-you-http-client-5b81) +对标准库 `std.http` 的介绍。 + +[Zig Bits 0x3: Mastering project management in +Zig](https://blog.orhun.dev/zig-bits-03/) +介绍了如何更好地维护一个 Zig +项目,包括:新增依赖、增加测试覆盖率、增加文档、基于 GitHub Action +做持续集成等。 + +[ityonemo/zigler](https://github.com/ityonemo/zigler) +zig nifs in elixir + +[Ziggifying +Kilo](https://bingcicle.github.io/posts/ziggifying-kilo.html) +使用 Zig 重写 [kilo](https://github.com/antirez/kilo) 编辑器,目前仅能在 +Linux 上运行 + +[jakubgiesler/VecZig](https://github.com/jakubgiesler/VecZig) +Vector implementation in Zig + +[b0bleet/zvisor](https://github.com/b0bleet/zvisor) +Zvisor is an open-source hypervisor written in the Zig programming +language, which provides a modern and efficient approach to systems +programming. + +# [Zig 语言更新](https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2023-04-01..2023-05-01) diff --git a/content/monthly/202305.org b/content/monthly/202305.org deleted file mode 100644 index 1685212..0000000 --- a/content/monthly/202305.org +++ /dev/null @@ -1,33 +0,0 @@ -#+TITLE: 202305 | HTTP is built-in -#+DATE: 2023-06-16T16:32:29+0800 -#+LASTMOD: 2023-06-17T13:32:13+0800 -* 重大事件 -这个月主要的事情就是 HTTP server 在标准库的增加了,具体可参考: -- [[https://zig.news/nameless/coming-soon-to-a-zig-near-you-http-client-5b81][Coming Soon to a Zig Near You: HTTP Client]] -- [[https://github.com/ziglang/zig/issues/910][http server in the standard library · Issue #910]] -* 观点/教程 -- [[https://mitchellh.com/writing/zig-and-swiftui][Integrating Zig and SwiftUI]] :: Mitchell 在用 Zig 实现了一个终端后,虽然没有把源码放出来,但是有了这个文章总结。 -- [[https://matklad.github.io/2023/05/06/zig-language-server-and-cancellation.html][Zig Language Server And Cancellation]] :: Matklad 对 ZLS 实现分析:如何快速响应用户的编辑命令,在作者来看,最主要是 server 端要能够及时取消已经过期的操作。 -- [[https://www.uber.com/en-IT/blog/bootstrapping-ubers-infrastructure-on-arm64-with-zig/][Bootstrapping Uber’s Infrastructure on arm64 with Zig]] :: Zig 社区的老朋友 Motiejus Jakštys 在 Uber 的 arm 化过程中,探索了如何使用 Zig 提供对 Go 代码的交叉编译。 -- [[https://matklad.github.io/2023/06/02/the-worst-zig-version-manager.html][The Worst Zig Version Manager]] :: 在没有 Zig 环境的机器上,如何安装 Zig ?作者的思路是每个项目都附带一个脚本来做这件事,这种方式看似比较笨拙,但很有实用性。 -- [[https://juliette.page/blog/init.html][Writing an init system in a language I don't know]] :: 作者介绍了使用 Zig 开发一个 init 系统的经历,文中主要吐槽了现在 Zig 的文档严重不足 🙃,但看得出,作者依旧是喜欢 Zig 的。 -- [[https://www.openmymind.net/SIMD-With-Zig/][SIMD with Zig]] :: 作者演示了如何利用 SIMD 函数来改进 =indexOf= 函数 -- [[https://zig.news/perky/anytype-antics-2398][Anytype Antics]] :: 作者介绍了如何使用 =anytype= ,一些示例包括:Duck Type、Traits、Comptime Tagged Unions -- [[https://www.youtube.com/watch?v=VU1h-h9doS8][Using Zig | My Initial Thoughts on Ziglang]] :: 视频 -- [[https://www.youtube.com/watch?v=kRrxbRLWsBo&feature=youtu.be][Zig: First Impressions]] :: 视频 -- [[https://lupyuen.codeberg.page/articles/lvgl3.html][(Possibly) LVGL in WebAssembly with Zig Compiler]] :: -- [[https://www.priver.dev/blog/zig/initial-commit-build-system/][Initial Commit: Zig Build System]] :: -- [[https://e-aakash.github.io/update/2023/06/04/resolv-dns-resolver-in-zig.html][Writing DNS resolver in Zig]] :: -* 项目/工具 -- [[https://zigbyexample.github.io/][Zig by Example]] :: 非常好的学习资料。Learn How to use Zig’s Standard Library, by small examples. -- [[https://github.com/sleibrock/zigtoys][sleibrock/zigtoys]] :: All about Zig + WASM and seeing what we can do -- [[https://github.com/Aandreba/zigrc][Aandreba/zigrc]] :: Zig reference-counted pointers inspired by Rust's Rc and Arc -- [[https://github.com/Hanaasagi/struct-env][Hanaasagi/struct]] :: Deserialize env vars into typesafe structs -- [[https://github.com/tristanisham/minigrep-zig][tristanisham/minigrep]] :: A Zig version of the Rust book's minigrep tutorial program -- [[https://github.com/jsomedon/night.zig][jsomedon/night.zig]] :: Simple tool that just install & update zig nightly. -- [[https://github.com/4imothy/termy48][4imothy/termy48]] :: A 2048 game to run in terminal -- [[https://github.com/bnl1/zig-html-example/blob/main/html.zig][zig-html-example]] :: 一个有趣的演示,利用 comptime 来定义 HTML 中的 Tag -- [[https://github.com/KilianVounckx/rayz][KilianVounckx/rayz]] :: 另一个 Raylib 的 bindings -- [[https://github.com/mitchellh/zig-objc][mitchellh/zig]] :: Objective-C runtime bindings for Zig (Zig calling ObjC). - -* [[https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2023-04-01..2023-05-01][Zig 语言更新]] diff --git a/content/monthly/202305.smd b/content/monthly/202305.smd new file mode 100644 index 0000000..7654cd0 --- /dev/null +++ b/content/monthly/202305.smd @@ -0,0 +1,103 @@ +--- +.title = "202305 | HTTP is built-in", +.date = @date("2023-06-16T16:32:29+0800"), +.author = "ZigCC", +.layout = "monthly.shtml", +.draft = false, +--- + +# [重大事件]($section.id('重大事件')) + +这个月主要的事情就是 HTTP server 在标准库的增加了,具体可参考: + +- [Coming Soon to a Zig Near You: HTTP + Client](https://zig.news/nameless/coming-soon-to-a-zig-near-you-http-client-5b81) +- [http server in the standard library · Issue + \#910](https://github.com/ziglang/zig/issues/910) + +# [观点/教程]($section.id('观点/教程')) + +[Integrating Zig and +SwiftUI](https://mitchellh.com/writing/zig-and-swiftui) +Mitchell 在用 Zig +实现了一个终端后,虽然没有把源码放出来,但是有了这个文章总结。 + +[Zig Language Server And +Cancellation](https://matklad.github.io/2023/05/06/zig-language-server-and-cancellation.html) +Matklad 对 ZLS +实现分析:如何快速响应用户的编辑命令,在作者来看,最主要是 server +端要能够及时取消已经过期的操作。 + +[Bootstrapping Uber’s Infrastructure on arm64 with +Zig](https://www.uber.com/en-IT/blog/bootstrapping-ubers-infrastructure-on-arm64-with-zig/) +Zig 社区的老朋友 Motiejus Jakštys 在 Uber 的 arm +化过程中,探索了如何使用 Zig 提供对 Go 代码的交叉编译。 + +[The Worst Zig Version +Manager](https://matklad.github.io/2023/06/02/the-worst-zig-version-manager.html) +在没有 Zig 环境的机器上,如何安装 Zig +?作者的思路是每个项目都附带一个脚本来做这件事,这种方式看似比较笨拙,但很有实用性。 + +[Writing an init system in a language I don’t +know](https://juliette.page/blog/init.html) +作者介绍了使用 Zig 开发一个 init 系统的经历,文中主要吐槽了现在 Zig +的文档严重不足 🙃,但看得出,作者依旧是喜欢 Zig 的。 + +[SIMD with Zig](https://www.openmymind.net/SIMD-With-Zig/) +作者演示了如何利用 SIMD 函数来改进 `indexOf` 函数 + +[Anytype Antics](https://zig.news/perky/anytype-antics-2398) +作者介绍了如何使用 `anytype` ,一些示例包括:Duck Type、Traits、Comptime +Tagged Unions + +[Using Zig | My Initial Thoughts on +Ziglang](https://www.youtube.com/watch?v=VU1h-h9doS8) +视频 + +[Zig: First +Impressions](https://www.youtube.com/watch?v=kRrxbRLWsBo&feature=youtu.be) +视频 + +[(Possibly) LVGL in WebAssembly with Zig +Compiler](https://lupyuen.codeberg.page/articles/lvgl3.html) + +[Initial Commit: Zig Build +System](https://www.priver.dev/blog/zig/initial-commit-build-system/) + +[Writing DNS resolver in +Zig](https://e-aakash.github.io/update/2023/06/04/resolv-dns-resolver-in-zig.html) + +# [项目/工具]($section.id('项目/工具')) + +[Zig by Example](https://zigbyexample.github.io/) +非常好的学习资料。Learn How to use Zig’s Standard Library, by small +examples. + +[sleibrock/zigtoys](https://github.com/sleibrock/zigtoys) +All about Zig + WASM and seeing what we can do + +[Aandreba/zigrc](https://github.com/Aandreba/zigrc) +Zig reference-counted pointers inspired by Rust’s Rc and Arc + +[Hanaasagi/struct](https://github.com/Hanaasagi/struct-env) +Deserialize env vars into typesafe structs + +[tristanisham/minigrep](https://github.com/tristanisham/minigrep-zig) +A Zig version of the Rust book’s minigrep tutorial program + +[jsomedon/night.zig](https://github.com/jsomedon/night.zig) +Simple tool that just install & update zig nightly. + +[4imothy/termy48](https://github.com/4imothy/termy48) +A 2048 game to run in terminal + +[zig-html-example](https://github.com/bnl1/zig-html-example/blob/main/html.zig) +一个有趣的演示,利用 comptime 来定义 HTML 中的 Tag + +[KilianVounckx/rayz](https://github.com/KilianVounckx/rayz) +另一个 Raylib 的 bindings + +[mitchellh/zig](https://github.com/mitchellh/zig-objc) +Objective-C runtime bindings for Zig (Zig calling ObjC). + +# [Zig 语言更新](https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2023-04-01..2023-05-01) diff --git a/content/monthly/202306.org b/content/monthly/202306.org deleted file mode 100644 index bc1f339..0000000 --- a/content/monthly/202306.org +++ /dev/null @@ -1,85 +0,0 @@ -#+TITLE: 202306 | Zig 要分叉了? -#+DATE: 2023-07-01T17:35:43+0800 -#+LASTMOD: 2023-07-01T22:05:35+0800 -* 重大事件 -一个是这个:[[https://ziggit.dev/t/the-zig-subreddit-has-closed/679][The Zig subreddit has closed]],现在 Ziggit 算是官方钦定的论坛了。 - -另一个是月底出来的大新闻:[[https://github.com/ziglang/zig/issues/16270][File for Divorce from LLVM · Issue #16270 · ziglang/zig]] - -这个 issue 主要讨论的是把 LLVM 从 Zig 中彻底移除,动机和优势都列在里面了,这里不再赘述,这里重点说下影响: -1. 去掉 C++/Objc 的支持, -2. 支持的 target 会变少 - -从 issue 本身和 [[https://lobste.rs/s/svhzj9/divorce_from_llvm][Lobsters]]、[[https://news.ycombinator.com/item?id=36529456][HN]] 上的评论看,大家主要担忧的是对 C++ 的支持。由于非常多的基础软件都是构建在 C++ 之上的,如果没有了对 C++ 的支持,那么 Zig 作为工具链这一选择的可行性就大打折扣了,要知道 Zig 之前最主要的卖点就是这个,比如:[[https://kristoff.it/blog/maintain-it-with-zig/][Maintain it With Zig]]。 - -有人提议用 Zig 重写一个 C++ 前端不就好了?但这属于理论上可行,实际没有可操作性的,因为 C++ [[https://news.ycombinator.com/item?id=36532170][太复杂]]了。 - -其实 Zig 从 [[https://ziglang.org/download/0.10.0/release-notes.html][0.10.0]] 版本开始,就一直在着手 [[https://ziglang.org/download/0.10.0/release-notes.html#Self-Hosted-Compiler][Self-Hosted Compiler]] 的开发。看得出,Zig 团队一直在追求极致,从编译速度,到二进制大小(以下数字均来自 0.10.0 的 release note): -- Wall Clock Time: 43 seconds to 40 seconds (7% faster) -- Peak RSS: 9.6 GiB to 2.8 GiB (3.5x less memory used) -- As a point of comparison, a stripped release build of Zig with LLVM is 169 MiB, while without LLVM (but with all the code generation backends you see here) it is 4.4 MiB. - -这个 issue 在互联网上迅速引起了热烈讨论,当然少不了吃瓜群众,以至于 Andrewk 又追加了[[https://github.com/ziglang/zig/issues/16270#issuecomment-1615388680][一条评论]]: -#+begin_quote -I see a lot of speculation in this GitHub Issue from folks who are not involved in Zig in any way. I would respectfully ask you to please take such speculation elsewhere. This issue tracker is for focused technical discussion by those who are actually using Zig, today. The noise in this thread distracts from the valuable comments by users who are sharing their use cases for the relevant features of Zig. - -..which, by the way, I'm one of. For example, my music player reboot branch depends on chromaprint which is, dun dun dun, C++ code. - -I'm not going to simultaneously shoot myself and valuable community members in the face by yanking a load-bearing feature out from underneath us, without any kind of upgrade path. It's a bit unfortunate that the Internet has taken that narrative and run with it. - -For example, one thing to explore, later - once all those boxes above are checked - is whether we can satisfy the C++ compilation use case, as well as the LLVM optimization use case, with the package manager. The results of this exploration will heavily impact the ultimate decision of whether to accept or reject this proposal. - -Please, relax. Nothing is going to happen overnight, and nothing is more important than making sure our esteemed Zig users' needs are taken care of, one way or another. Whatever happens will happen in due time, with due respect for real world projects. This proposal is aspirational - something to look forward to and consider in the coming years. -#+end_quote - -微信群里不少小伙伴也在担忧这个 issue 会不会导致 Zig 的 fork,甚至灭亡。其实看了上面的评论大家就应该放心了,Zig 团队知道用户的需要,不会搬起石头砸自己的脚。 - -我觉得通过这个事件更能坚定我投资 Zig 的信心了,一个追求极致的团队,不需要我们吃瓜群众瞎操心,有这个时间不如去看看 Zig 的各种 backend 进展,能不能给 fix 几个 regression?! - -最后,即便 Zig 这个项目夭折了,我相信通过这个学习的过程也有助于提高我们对系统编程、编译器的理解,不是吗? -* 观点/教程 -- [[https://kristoff.it/blog/note-about-zig-books/][A Note About Zig Books for the Zig Community]] :: Loris Cro 的博客,由于现在 Zig 的关注度越来越高,一些出版社开始联系社区的人出一本 Zig 的书,Loris 这里阐述了与出版社合作的利弊,以及他也在写一本关于 Zig 的书 =Intro to Zig / systems programming= ,由于 Zig 还是不停的开发中,因为书中会尽量少的去涉及 stdlib 的内容。 -- [[https://ziggit.dev/t/how-far-away-is-0-11-really/744][How far away is 0.11 really?]] :: 社区用户对 0.11 版本发布时间的疑问? -- [[https://devlog.hexops.com/2023/mach-ecosystem-c-libraries/][Mach: providing an ecosystem of C libraries using the Zig package manager]] :: 作者在文章讲述了利用 Zig 来打包 C 依赖的优势。 -- [[https://ryleealanza.org/2023/06/21/The-Seamstress-Event-Loop-in-Zig.html][The Seamstress Event Loop In Zig]] :: -- [[https://notes.eatonphil.com/2023-06-19-metaprogramming-in-zig-and-parsing-css.html][Metaprogramming in Zig and parsing CSS]] :: -- [[https://en.liujiacai.net/2023/06/29/embed-git-commit-in-zig/][Embed git commit in Zig programs]] :: 把 git 的 commit id 嵌入项目中非常有助于问题排查 -- [[https://avestura.dev/blog/problems-of-c-and-how-zig-addresses-them][Problems of C, and how Zig addresses them]] :: 不错的入门资料,主要内容: - - Comptime over Textual Replacement Preprocessing - - Memory Management, and Zig Allocators - - Billion dollar mistake vs Zig Optionals - - Pointer arithmetics vs Zig Slices - - Explicit memory alignment - - Arrays as values - - Error handling - - Everything is an expression - - C has a more complex syntax to deal with -- [[https://richiejp.com/zig-cross-compile-ltp-ltx-linux][Minimal Linux VM cross compiled with Clang and Zig]] :: 一篇有意思的文章,作者的任务是跑 Linux kernel 的 test,为了能够方便、简单的跑不同的平台,作者尝试用 Zig 的交叉编译能力来解决这个大难题 -- [[https://www.openmymind.net/Zig-Danling-Pointers/][Zig dangling pointers and segfaults]] :: -- [[http://ratfactor.com/zig/hard][I think Zig is hard...but worth it]] :: 安利 Zig 的文章,[[https://news.ycombinator.com/item?id=36149462][HN 讨论]] - http://ratfactor.com/zig/zighard_700px.jpg -* 项目/工具 -- [[https://github.com/pondzdev/duckdb-proxy/][pondzdev/duckdb]] :: 一个将 DuckDB 数据库通过 HTTP API 暴露出来的代理,主要是利用了 [[https://duckdb.org/docs/api/c/api.html][DuckDB C API]],示例: - #+begin_src bash -# open the database in readonly (DB must exist in this case) -$ ./duckdb-proxy --readonly db/mydatabase.duckdb - -$ curl http://localhost:8012/api/1/exec \ - -d '{"sql": "select version()"}' -{ - "cols": [ - "version()" - ], - "rows": [ - [ - "v0.8.1" - ] - ] -} - #+end_src -- [[https://github.com/ryleelyman/seamstress][ryleelyman/seamstress]] :: Lua monome + OSC scripting environment -- [[https://programming-language-benchmarks.vercel.app/rust-vs-zig][Rust VS Zig benchmarks]] :: Which programming language or compiler is faster -- [[https://github.com/ziglang/shell-completions][ziglang/shell]] :: Shell completions for the Zig compiler. -- [[https://github.com/menduz/zig-steamworks][menduz/zig]] :: Steamwork bindings for Zig. -* [[https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2023-05-01..2023-06-01][Zig 语言更新]] -- [[https://github.com/ziglang/zig/pull/16207][WASI: Implement experimental threading support by Luukdegram · Pull Request #16207 · ziglang/zig]] diff --git a/content/monthly/202306.smd b/content/monthly/202306.smd new file mode 100644 index 0000000..cb8a897 --- /dev/null +++ b/content/monthly/202306.smd @@ -0,0 +1,191 @@ +--- +.title = "202306 | Zig 要分叉了?", +.date = @date("2023-07-01T17:35:43+0800"), +.author = "ZigCC", +.layout = "monthly.shtml", +.draft = false, +--- + +# [重大事件]($section.id('重大事件')) + +一个是这个:[The Zig subreddit has +closed](https://ziggit.dev/t/the-zig-subreddit-has-closed/679),现在 +Ziggit 算是官方钦定的论坛了。 + +另一个是月底出来的大新闻:[File for Divorce from LLVM · Issue \#16270 · +ziglang/zig](https://github.com/ziglang/zig/issues/16270) + +这个 issue 主要讨论的是把 LLVM 从 Zig +中彻底移除,动机和优势都列在里面了,这里不再赘述,这里重点说下影响: + +1. 去掉 C++/Objc 的支持, +2. 支持的 target 会变少 + +从 issue 本身和 +[Lobsters](https://lobste.rs/s/svhzj9/divorce_from_llvm)、[HN](https://news.ycombinator.com/item?id=36529456) +上的评论看,大家主要担忧的是对 C++ +的支持。由于非常多的基础软件都是构建在 C++ 之上的,如果没有了对 C++ +的支持,那么 Zig 作为工具链这一选择的可行性就大打折扣了,要知道 Zig +之前最主要的卖点就是这个,比如:[Maintain it With +Zig](https://kristoff.it/blog/maintain-it-with-zig/)。 + +有人提议用 Zig 重写一个 C++ +前端不就好了?但这属于理论上可行,实际没有可操作性的,因为 C++ +[太复杂](https://news.ycombinator.com/item?id=36532170)了。 + +其实 Zig 从 +[0.10.0](https://ziglang.org/download/0.10.0/release-notes.html) +版本开始,就一直在着手 [Self-Hosted +Compiler](https://ziglang.org/download/0.10.0/release-notes.html#Self-Hosted-Compiler) +的开发。看得出,Zig +团队一直在追求极致,从编译速度,到二进制大小(以下数字均来自 0.10.0 的 +release note): + +- Wall Clock Time: 43 seconds to 40 seconds (7% faster) +- Peak RSS: 9.6 GiB to 2.8 GiB (3.5x less memory used) +- As a point of comparison, a stripped release build of Zig with LLVM is + 169 MiB, while without LLVM (but with all the code generation backends + you see here) it is 4.4 MiB. + +这个 issue 在互联网上迅速引起了热烈讨论,当然少不了吃瓜群众,以至于 +Andrewk +又追加了[一条评论](https://github.com/ziglang/zig/issues/16270#issuecomment-1615388680): + +> I see a lot of speculation in this GitHub Issue from folks who are not +> involved in Zig in any way. I would respectfully ask you to please +> take such speculation elsewhere. This issue tracker is for focused +> technical discussion by those who are actually using Zig, today. The +> noise in this thread distracts from the valuable comments by users who +> are sharing their use cases for the relevant features of Zig. +> +> ..which, by the way, I’m one of. For example, my music player reboot +> branch depends on chromaprint which is, dun dun dun, C++ code. +> +> I’m not going to simultaneously shoot myself and valuable community +> members in the face by yanking a load-bearing feature out from +> underneath us, without any kind of upgrade path. It’s a bit +> unfortunate that the Internet has taken that narrative and run with +> it. +> +> For example, one thing to explore, later - once all those boxes above +> are checked - is whether we can satisfy the C++ compilation use case, +> as well as the LLVM optimization use case, with the package manager. +> The results of this exploration will heavily impact the ultimate +> decision of whether to accept or reject this proposal. +> +> Please, relax. Nothing is going to happen overnight, and nothing is +> more important than making sure our esteemed Zig users’ needs are +> taken care of, one way or another. Whatever happens will happen in due +> time, with due respect for real world projects. This proposal is +> aspirational - something to look forward to and consider in the coming +> years. + +微信群里不少小伙伴也在担忧这个 issue 会不会导致 Zig 的 +fork,甚至灭亡。其实看了上面的评论大家就应该放心了,Zig +团队知道用户的需要,不会搬起石头砸自己的脚。 + +我觉得通过这个事件更能坚定我投资 Zig +的信心了,一个追求极致的团队,不需要我们吃瓜群众瞎操心,有这个时间不如去看看 +Zig 的各种 backend 进展,能不能给 fix 几个 regression?! + +最后,即便 Zig +这个项目夭折了,我相信通过这个学习的过程也有助于提高我们对系统编程、编译器的理解,不是吗? + +# [观点/教程]($section.id('观点/教程')) + +[A Note About Zig Books for the Zig +Community](https://kristoff.it/blog/note-about-zig-books/) +Loris Cro 的博客,由于现在 Zig +的关注度越来越高,一些出版社开始联系社区的人出一本 Zig 的书,Loris +这里阐述了与出版社合作的利弊,以及他也在写一本关于 Zig 的书 +`Intro to Zig / systems programming` ,由于 Zig +还是不停的开发中,因为书中会尽量少的去涉及 stdlib 的内容。 + +[How far away is 0.11 +really?](https://ziggit.dev/t/how-far-away-is-0-11-really/744) +社区用户对 0.11 版本发布时间的疑问? + +[Mach: providing an ecosystem of C libraries using the Zig package +manager](https://devlog.hexops.com/2023/mach-ecosystem-c-libraries/) +作者在文章讲述了利用 Zig 来打包 C 依赖的优势。 + +[The Seamstress Event Loop In +Zig](https://ryleealanza.org/2023/06/21/The-Seamstress-Event-Loop-in-Zig.html) + +[Metaprogramming in Zig and parsing +CSS](https://notes.eatonphil.com/2023-06-19-metaprogramming-in-zig-and-parsing-css.html) + +[Embed git commit in Zig +programs](https://en.liujiacai.net/2023/06/29/embed-git-commit-in-zig/) +把 git 的 commit id 嵌入项目中非常有助于问题排查 + +[Problems of C, and how Zig addresses +them](https://avestura.dev/blog/problems-of-c-and-how-zig-addresses-them) +不错的入门资料,主要内容: + +- Comptime over Textual Replacement Preprocessing +- Memory Management, and Zig Allocators +- Billion dollar mistake vs Zig Optionals +- Pointer arithmetics vs Zig Slices +- Explicit memory alignment +- Arrays as values +- Error handling +- Everything is an expression +- C has a more complex syntax to deal with + +[Minimal Linux VM cross compiled with Clang and +Zig](https://richiejp.com/zig-cross-compile-ltp-ltx-linux) +一篇有意思的文章,作者的任务是跑 Linux kernel 的 +test,为了能够方便、简单的跑不同的平台,作者尝试用 Zig +的交叉编译能力来解决这个大难题 + +[Zig dangling pointers and +segfaults](https://www.openmymind.net/Zig-Danling-Pointers/) + +[I think Zig is hard…but worth it](http://ratfactor.com/zig/hard) +安利 Zig 的文章,[HN +讨论](https://news.ycombinator.com/item?id=36149462) + + +# [项目/工具]($section.id('项目/工具')) + +[pondzdev/duckdb](https://github.com/pondzdev/duckdb-proxy/) +一个将 DuckDB 数据库通过 HTTP API 暴露出来的代理,主要是利用了 [DuckDB C +API](https://duckdb.org/docs/api/c/api.html),示例: + +``` bash +# [open the database in readonly (DB must exist in this case)]($section.id('open the database in readonly (DB must exist in this case)')) +$ ./duckdb-proxy --readonly db/mydatabase.duckdb + +$ curl http://localhost:8012/api/1/exec \ + -d '{"sql": "select version()"}' +{ + "cols": [ + "version()" + ], + "rows": [ + [ + "v0.8.1" + ] + ] +} +``` + +[ryleelyman/seamstress](https://github.com/ryleelyman/seamstress) +Lua monome + OSC scripting environment + +[Rust VS Zig +benchmarks](https://programming-language-benchmarks.vercel.app/rust-vs-zig) +Which programming language or compiler is faster + +[ziglang/shell](https://github.com/ziglang/shell-completions) +Shell completions for the Zig compiler. + +[menduz/zig](https://github.com/menduz/zig-steamworks) +Steamwork bindings for Zig. + +# [Zig 语言更新](https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2023-05-01..2023-06-01) + +- [WASI: Implement experimental threading support by Luukdegram · Pull + Request \#16207 · + ziglang/zig](https://github.com/ziglang/zig/pull/16207) diff --git a/content/monthly/202307.org b/content/monthly/202307.org deleted file mode 100644 index e769b02..0000000 --- a/content/monthly/202307.org +++ /dev/null @@ -1,95 +0,0 @@ -#+TITLE: 202307 | 异步缺席 0.11 -#+DATE: 2023-08-07T20:05:29+0800 -#+LASTMOD: 2023-08-09T08:15:59+0800 -* 重大事件 -Andrewk 在最新的文章 -[[https://ziglang.org/news/0.11.0-postponed-again/][The Upcoming Release Postponed Two More Weeks and Lacks Async Functions]] 中指出,即将发布的 0.11 中将不会包含对异步的支持,现在异步是在 [[https://github.com/ziglang/zig/tree/stage2-async][stage2-async]] 这个分支上来开发,但是在开发过程中,总是有其他事情出现,然后 Andrewk 就先去搞这些事情了。因此,把对异步的支持放到 0.12 上了。 - -另一件事是 [[https://ziglang.org/news/welcome-jacob-young/][Jacob Young Joins the Core Zig Team]],Core Team 迎来了另一位全职开发者,常用 ID [[https://github.com/jacobly0][jacobly0]],下面是他最近的提交记录: -- https://github.com/ziglang/zig/commits?author=jacobly0&since=2023-06-31 - -恭喜 Core Team,又添一虎将! -* 观点/教程 -- [[https://tigerbeetle.com/blog/2023-07-26-copy-hunting/][Copy Hunting | TigerBeetle]] :: 比较有意思的文章,通过分析 LLVM 的 IR,来避免程序中不必要的 memcpy 以及如何减少 binary 体积 -- [[https://double-trouble.dev/post/zbench/][Taking off with Zig: Putting the Z in Benchmark]] :: Zig 入门文章,作者使用 Zig 来实现了一个 benchmark 库,里面有作者的感受,语言小巧,主要的语言特点:独特的错误处理、显式的内存控制、comptime 执行 -- [[https://hackernoon.com/the-new-wave-of-programming-languages-exploring-the-hidden-gems][The New Wave of Programming Languages: Pony, Zig, Crystal, Vlang, and Julia]] :: 多种语言的对比,Zig 部分的对比: - -| Pros | Cons | -|--------------------------------------------+-----------------------------| -| Excellent low-level control over code | Relatively new and evolving | -| Emphasis on safety and reliability | Limited library support | -| Good interoperability with other languages | Steep learning curve | - -- [[https://www.aolium.com/karlseguin/cf03dee6-90e1-85ac-8442-cf9e6c11602a][Parsing timestamps and generating RFC3339 dates in Zig]] :: Zig 标准库里有返回 unixtime 时间戳的函数,但是没有格式化函数,作者这里给出了一种实现: - #+begin_src zig -pub const DateTime = struct { - year: u16, - month: u8, - day: u8, - hour: u8, - minute: u8, - second: u8, -}; - -pub fn fromTimestamp(ts: u64) DateTime { - const SECONDS_PER_DAY = 86400; - const DAYS_PER_YEAR = 365; - const DAYS_IN_4YEARS = 1461; - const DAYS_IN_100YEARS = 36524; - const DAYS_IN_400YEARS = 146097; - const DAYS_BEFORE_EPOCH = 719468; - - const seconds_since_midnight: u64 = @rem(ts, SECONDS_PER_DAY); - var day_n: u64 = DAYS_BEFORE_EPOCH + ts / SECONDS_PER_DAY; - var temp: u64 = 0; - - temp = 4 * (day_n + DAYS_IN_100YEARS + 1) / DAYS_IN_400YEARS - 1; - var year: u16 = @intCast(100 * temp); - day_n -= DAYS_IN_100YEARS * temp + temp / 4; - - temp = 4 * (day_n + DAYS_PER_YEAR + 1) / DAYS_IN_4YEARS - 1; - year += @intCast(temp); - day_n -= DAYS_PER_YEAR * temp + temp / 4; - - var month: u8 = @intCast((5 * day_n + 2) / 153); - const day: u8 = @intCast(day_n - (@as(u64, @intCast(month)) * 153 + 2) / 5 + 1); - - month += 3; - if (month > 12) { - month -= 12; - year += 1; - } - - return DateTime{ - .year = year, - .month = month, - .day = day, - .hour = @intCast(seconds_since_midnight / 3600), - .minute = @intCast(seconds_since_midnight % 3600 / 60), - .second = @intCast(seconds_since_midnight % 60) - }; -} - #+end_src -- [[https://www.aolium.com/karlseguin/46252c5b-587a-c419-be96-a0ccc2f11de4][Custom JSON serialization in Zig]] :: Zig 里面虽然有很好的 JSON 序列化支持,但是有些时候我们需要自定义某个字段的解析,与 Go =json.Marshaller= 类似,Zig 会在序列化时查找类型的 =jsonStringify= 函数,通过实现这个函数就可以达到目的,文中给出了个示例: - #+begin_src zig -const NumericBoolean = struct { - value: bool, - - pub fn jsonStringify(self: NumericBoolean, out: anytype) !void { - const json = if (self.value) "1" else "0"; - return out.print("{s}", .{json}); - } -}; - #+end_src -- [[https://matklad.github.io/2023/07/16/three-different-cuts.html][Three Different Cuts]] :: matklad 的文章,介绍了 Rust、Go、Zig 三种语言的 Cut 实现 -- [[https://blog.orhun.dev/zig-bits-04/][Zig Bits 0x4: Building an HTTP client/server from scratch]] :: 介绍了 std.http 这个模块的使用 -- [[https://tigerbeetle.com/blog/2023-07-11-we-put-a-distributed-database-in-the-browser/][We Put a Distributed Database In the Browser – And Made a Game of It]] :: TigerBeetle 的新花样,把数据库搬到了 Web 上。[[https://news.ycombinator.com/item?id=36680535][HN 讨论]] -- [[https://zig.news/gwenzek/zig-great-design-for-great-optimizations-638][Zig: great design for great optimizations]] :: 比较有意思的文章,作者比较了 Clang、Zig 对相同逻辑代码生产的 LLVM IR,Zig 生成的 IR 更加精简 - -* 项目/工具 -- [[https://blog.turso.tech/zig-helped-us-move-data-to-the-edge-here-are-our-impressions-67d3a9c45af4][Zig helped us move data to the Edge. Here are our impressions]] :: [[https://turso.tech/][Turso]] 公司的官博,它们公司的产品时边缘数据库,自动同步 PG 的表到 Edge 端,减少访问的时延。在这篇文章里他们介绍了使用 Zig 编写 PostgreSQL 插件的经历,得益于 =translate-c= ,他们可以直接从已有的 C 代码开始构建他们的产品。插件地址:[[https://github.com/turso-extended/pg_turso][pg_turso]] -- [[https://github.com/tensorush/meduza][tensorush/meduza]] :: 🦎 🧜‍♀️ Zig codebase graph generator that emits a Mermaid class diagram -- [[https://github.com/AndreaOrru/zen][AndreaOrru/zen]] :: Experimental operating system written in Zig -- [[https://github.com/EugenHotaj/zig_gpt2][EugenHotaj/zig_gpt2]] :: GPT-2 inference engine written in Zig - -* [[https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2023-06-01..2023-07-01][Zig 语言更新]] diff --git a/content/monthly/202307.smd b/content/monthly/202307.smd new file mode 100644 index 0000000..cf8ac52 --- /dev/null +++ b/content/monthly/202307.smd @@ -0,0 +1,150 @@ +--- +.title = "202307 | 异步缺席 0.11", +.date = @date("2023-08-07T20:05:29+0800"), +.author = "ZigCC", +.layout = "monthly.shtml", +.draft = false, +--- + +# [重大事件]($section.id('重大事件')) + +Andrewk 在最新的文章 [The Upcoming Release Postponed Two More Weeks and +Lacks Async Functions](https://ziglang.org/news/0.11.0-postponed-again/) +中指出,即将发布的 0.11 中将不会包含对异步的支持,现在异步是在 +[stage2-async](https://github.com/ziglang/zig/tree/stage2-async) +这个分支上来开发,但是在开发过程中,总是有其他事情出现,然后 Andrewk +就先去搞这些事情了。因此,把对异步的支持放到 0.12 上了。 + +另一件事是 [Jacob Young Joins the Core Zig +Team](https://ziglang.org/news/welcome-jacob-young/),Core Team +迎来了另一位全职开发者,常用 ID +[jacobly0](https://github.com/jacobly0),下面是他最近的提交记录: + +- + +恭喜 Core Team,又添一虎将! + +# [观点/教程]($section.id('观点/教程')) + +[Copy Hunting | TigerBeetle](https://tigerbeetle.com/blog/2023-07-26-copy-hunting/) +比较有意思的文章,通过分析 LLVM 的 IR,来避免程序中不必要的 memcpy +以及如何减少 binary 体积 + +[Taking off with Zig: Putting the Z in Benchmark](https://double-trouble.dev/post/zbench/) +Zig 入门文章,作者使用 Zig 来实现了一个 benchmark +库,里面有作者的感受,语言小巧,主要的语言特点:独特的错误处理、显式的内存控制、comptime +执行 + +[The New Wave of Programming Languages: Pony, Zig, Crystal, Vlang, and Julia](https://hackernoon.com/the-new-wave-of-programming-languages-exploring-the-hidden-gems) +多种语言的对比,Zig 部分的对比: + +| Pros | Cons | +|--------------------------------------------|-----------------------------| +| Excellent low-level control over code | Relatively new and evolving | +| Emphasis on safety and reliability | Limited library support | +| Good interoperability with other languages | Steep learning curve | + +[Parsing timestamps and generating RFC3339 dates in Zig](https://www.aolium.com/karlseguin/cf03dee6-90e1-85ac-8442-cf9e6c11602a) +Zig 标准库里有返回 unixtime +时间戳的函数,但是没有格式化函数,作者这里给出了一种实现: + +``` zig +pub const DateTime = struct { + year: u16, + month: u8, + day: u8, + hour: u8, + minute: u8, + second: u8, +}; + +pub fn fromTimestamp(ts: u64) DateTime { + const SECONDS_PER_DAY = 86400; + const DAYS_PER_YEAR = 365; + const DAYS_IN_4YEARS = 1461; + const DAYS_IN_100YEARS = 36524; + const DAYS_IN_400YEARS = 146097; + const DAYS_BEFORE_EPOCH = 719468; + + const seconds_since_midnight: u64 = @rem(ts, SECONDS_PER_DAY); + var day_n: u64 = DAYS_BEFORE_EPOCH + ts / SECONDS_PER_DAY; + var temp: u64 = 0; + + temp = 4 * (day_n + DAYS_IN_100YEARS + 1) / DAYS_IN_400YEARS - 1; + var year: u16 = @intCast(100 * temp); + day_n -= DAYS_IN_100YEARS * temp + temp / 4; + + temp = 4 * (day_n + DAYS_PER_YEAR + 1) / DAYS_IN_4YEARS - 1; + year += @intCast(temp); + day_n -= DAYS_PER_YEAR * temp + temp / 4; + + var month: u8 = @intCast((5 * day_n + 2) / 153); + const day: u8 = @intCast(day_n - (@as(u64, @intCast(month)) * 153 + 2) / 5 + 1); + + month += 3; + if (month > 12) { + month -= 12; + year += 1; + } + + return DateTime{ + .year = year, + .month = month, + .day = day, + .hour = @intCast(seconds_since_midnight / 3600), + .minute = @intCast(seconds_since_midnight % 3600 / 60), + .second = @intCast(seconds_since_midnight % 60) + }; +} +``` + +[Custom JSON serialization in Zig](https://www.aolium.com/karlseguin/46252c5b-587a-c419-be96-a0ccc2f11de4) +Zig 里面虽然有很好的 JSON +序列化支持,但是有些时候我们需要自定义某个字段的解析,与 Go +`json.Marshaller` 类似,Zig 会在序列化时查找类型的 `jsonStringify` +函数,通过实现这个函数就可以达到目的,文中给出了个示例: + +``` zig +const NumericBoolean = struct { + value: bool, + + pub fn jsonStringify(self: NumericBoolean, out: anytype) !void { + const json = if (self.value) "1" else "0"; + return out.print("{s}", .{json}); + } +}; +``` + +[Three Different Cuts](https://matklad.github.io/2023/07/16/three-different-cuts.html) +matklad 的文章,介绍了 Rust、Go、Zig 三种语言的 Cut 实现 + +[Zig Bits 0x4: Building an HTTP client/server from scratch](https://blog.orhun.dev/zig-bits-04/) +介绍了 std.http 这个模块的使用 + +[We Put a Distributed Database In the Browser – And Made a Game of It](https://tigerbeetle.com/blog/2023-07-11-we-put-a-distributed-database-in-the-browser/) +TigerBeetle 的新花样,把数据库搬到了 Web 上。[HN +讨论](https://news.ycombinator.com/item?id=36680535) + +[Zig: great design for great optimizations](https://zig.news/gwenzek/zig-great-design-for-great-optimizations-638) +比较有意思的文章,作者比较了 Clang、Zig 对相同逻辑代码生产的 LLVM +IR,Zig 生成的 IR 更加精简 + +# [项目/工具]($section.id('项目/工具')) + +[Zig helped us move data to the Edge. Here are our impressions](https://blog.turso.tech/zig-helped-us-move-data-to-the-edge-here-are-our-impressions-67d3a9c45af4) +[Turso](https://turso.tech/) +公司的官博,它们公司的产品时边缘数据库,自动同步 PG 的表到 Edge +端,减少访问的时延。在这篇文章里他们介绍了使用 Zig 编写 PostgreSQL +插件的经历,得益于 `translate-c` ,他们可以直接从已有的 C +代码开始构建他们的产品。插件地址:[pgturso](https://github.com/turso-extended/pg_turso) + +[tensorush/meduza](https://github.com/tensorush/meduza) +🦎 🧜‍♀️ Zig codebase graph generator that emits a Mermaid class diagram + +[AndreaOrru/zen](https://github.com/AndreaOrru/zen) +Experimental operating system written in Zig + +[EugenHotaj/ziggpt2](https://github.com/EugenHotaj/zig_gpt2) +GPT-2 inference engine written in Zig + +# [Zig 语言更新](https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2023-06-01..2023-07-01) diff --git a/content/monthly/202308.org b/content/monthly/202308.org deleted file mode 100644 index 47c662b..0000000 --- a/content/monthly/202308.org +++ /dev/null @@ -1,139 +0,0 @@ -#+TITLE: 202308 | 0.11 正式发布 -#+DATE: 2023-09-03T19:38:04+0800 -#+LASTMOD: 2023-09-04T22:05:21+0800 -* [[https://ziglang.org/download/0.11.0/release-notes.html#x86-Backend][0.11 正式发布]] -0.11 终于在 8 月 4 号释出了,下面来看看它的一些重要改进吧。[[https://news.ycombinator.com/item?id=36995735][HN 讨论]] -** Peer Type Resolution Improvements -对等类型解析算法得到改进,下面是一些在 0.10 中不能解析,但在 0.11 中可以解析的例子: -| Peer Types | Resolved Type | -| [:s]const T, []T | []const T | -| E!*T, ?*T | E!?*T | -| [*c]T, @TypeOf(null) | [*c]T | -| ?u32, u8 | ?u32 | -| [2]u32, struct { u32, u32 } | [2]u32 | -| *const @TypeOf(.{}), []const u8 | []const u8 | - -而且现在使用 =@intCast= 这类 builtin 都只接受一个参数,目前类型根据上下文自动推断出来。 -** Multi-Object For Loops -可以同时对多个对象进行遍历: -#+begin_src zig -// 之前 -for (input) |x, i| { - output[i] = x * 2; -} - -// 现在 -for (input, 0..) |x, i| { - output[i] = x * 2; -} -#+end_src -** @min and @max -主要有两个改动: -1. 这两个 builtin 现在支持任意多个参数 -2. 返回的类型,会尽可能的紧凑 -#+begin_src zig -test "@min/@max refines result type" { - const x: u8 = 20; // comptime-known - var y: u64 = 12345; - // Since an exact bound is comptime-known, the result must fit in a u5 - comptime assert(@TypeOf(@min(x, y)) == u5); - - var x_rt: u8 = x; // runtime-known - // Since one argument to @min is a u8, the result must fit in a u8 - comptime assert(@TypeOf(@min(x_rt, y)) == u8); -} -#+end_src -** @inComptime -新加的 builtin,用于判断执行是否在 comptime 环境下执行: -#+begin_src zig -const global_val = blk: { - assert(@inComptime()); - break :blk 123; -}; - -comptime { - assert(@inComptime()); -} - -fn f() u32 { - if (@inComptime()) { - return 1; - } else { - return 2; - } -} - -test "@inComptime" { - try expectEqual(true, comptime @inComptime()); - try expectEqual(false, @inComptime()); - try expectEqual(@as(u32, 1), comptime f()); - try expectEqual(@as(u32, 2), f()); -} -#+end_src -** 类型转化相关 builtin 的重命名 -之前 =@xToY= 形式的 builtin 现在已经改成了 =@yFromX= ,这样的主要好处是便于阅读(从右向左),这是[[https://github.com/ziglang/zig/issues/6128][草案]]。 -** Tuple 类型声明 -现在可以直接用无 field 名字的 struct 来声明 tuple 类型: -#+begin_src zig -test "tuple declarations" { - const T = struct { u32, []const u8 }; - var t: T = .{ 1, "foo" }; - try expect(t[0] == 1); - try expectEqualStrings(t[1], "foo"); - - var mul = t ** 3; - try expect(@TypeOf(mul) != T); - try expect(mul.len == 6); - try expect(mul[2] == 1); - try expectEqualStrings(mul[3], "foo"); - - var t2: T = .{ 2, "bar" }; - var cat = t ++ t2; - try expect(@TypeOf(cat) != T); - try expect(cat.len == 4); - try expect(cat[2] == 2); - try expectEqualStrings(cat[3], "bar"); -} -#+end_src - -之前只能用 =std.meta.Tuple= 函数来定义: -#+begin_src diff -- const testcases = [_]std.meta.Tuple(&[_]type{ []const u8, []const u8, bool }){ -+ const testcases = [_]struct { []const u8, []const u8, bool }{ -#+end_src -** 排序 -现在排序算法分布两类: -- 稳定,blocksort 算法 -- 不稳定,[[https://github.com/ziglang/zig/pull/15412][pdqsort]] 算法,它结合了随机快速排序的快速平均情况和堆排序的快速最坏情况。 -与堆排的快速最差情况相结合,同时在具有特定模式的输入上达到线性时间。 -** Stack Unwinding -Zig 之前依赖 [[https://en.wikipedia.org/wiki/Call_stack#Stack_and_frame_pointers][frame pointer]] 来做堆栈回卷,但它本身有些代价,因此线上环境可能会通过 =-fomit-frame-pointer= 将其禁用掉。 - -为了在这种情况下依然能够获取 panic 是的堆栈信息,Zig 现在支持了通过 DWARF unwind tables 和 MachO compact unwind information 来会恢复堆栈,详见:[[https://github.com/ziglang/zig/pull/15823][#15823]]。 -** 包管理 -0.11 首次正式引入了包管理器,具体解释可以参考:[[https://en.liujiacai.net/2023/04/13/zig-build-system/][Zig Build System]],而且很重要一点,step 之间可以[[https://ziglang.org/download/0.11.0/release-notes.html#Steps-Run-In-Parallel][并发执行]], -** Bootstrapping -C++ 实现的 Zig 编译器已经被彻底移除,这意味着 =-fstage1= 不再生效,Zig 现在只需要一个 2.4M 的 WebAssembly 文件和一个 C 编辑器即可,工作细节可以参考:[[https://ziglang.org/news/goodbye-cpp/][Goodbye to the C++ Implementation of Zig]]。 -** 代码生成 -虽然 Zig 编译器现在还是主要使用 LLVM 来进行代码生成,但在这次发布中,其他几个后端也有了非常大的进步: -1. C 后端,行为测试通过 98%,而且生成的 C 代码兼容微软的 MSVC,用在了 bootstrapping 中 -2. x86 后端,行为测试通过 88% -3. aarch64 后端,刚开始 -4. WebAssembly 后端,行为测试通过 86%, -5. SPIR-V 后端,SPIR-V 是在 GPU 上运行的着色器(shader)和内核的字节码表示法。目前,Zig 的 SPIR-V 后端专注于为 OpenCL 内核生成代码,不过未来可能也会支持兼容 Vulkan 的着色器。 -** 增量编译 -虽然这仍是一个高度 WIP 的功能,但这一版本周期中的许多改进为编译器的增量编译功能铺平了道路。其中最重要的是 [[https://github.com/ziglang/zig/pull/15569][InternPool]]。Zig 用户大多看不到这一改动,但它为编译器带来了许多好处,其中之一就是我们现在更接近增量编译了。增量编译将是 0.12.0 发布周期的重点。 -* 观点/教程 -- [[https://www.aolium.com/karlseguin/4013ac14-2457-479b-e59b-e603c04673c8][Error Handling In Zig]] :: 又一篇讨论错误处理的文章 -- [[https://www.1a-insec.net/blog/10-type-magic-in-zig/][Commiting Type Crimes in Zig]] :: 对 Zig 类型系统的另一种用法,有些和[[https://zh.wikipedia.org/wiki/%E9%82%B1%E5%A5%87%E6%95%B0][邱奇数]]类似。 -- [[https://www.youtube.com/watch?v=kxT8-C1vmd4][Zig in 100 Seconds]] :: Zig 宣传视频 -- [[https://www.youtube.com/watch?v=vKKTMBoxpS8][Zig Build System & How to Build Software From Source • Andrew Kelley • GOTO 2023]] :: Andrew 关于构建系统的视频,[[https://www.bilibili.com/video/BV1Mh4y1K7yc/][B 站链接]]、[[https://www.youtube.com/watch?v=vKKTMBoxpS8][Youbute]] -- [[https://rbino.com/posts/wrap-your-nif-with-zig/][Wrap your NIF with Zig]] :: NIF 是 Elixir 中进行 FFI 调用的方式,如果用原生 C 接口来用,会需要写很多胶水代码, - 作者这里用 comptime 特性来定义了一个 =make_nif_wrapper= 来简化 NIF 的实现,这个技巧在与 C 项目交互时十分有用。 -- [[https://matklad.github.io/2023/08/09/types-and-zig.html][Types and the Zig Programming Language]] :: matklad 对 Zig 类型系统的总结 -- [[https://andrewkelley.me/post/goodbye-twitter-reddit.html][So Long, Twitter and Reddit]] :: Andrew 的最新文章,远离社交平台! -- [[https://zig.news/edyu/wtf-is-zig-comptime-and-inline-257b][WTF is Zig Comptime (and Inline)]] :: -- [[https://double-trouble.dev/post/zbench/][Taking off with Zig: Putting the Z in Benchmark — Double Trouble]] :: -* 项目/工具 -- [[https://devlog.hexops.com/2023/mach-v0.2-released/][Mach v0.2 released]] -* [[https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2023-07-01..2023-08-01][Zig 语言更新]] diff --git a/content/monthly/202308.smd b/content/monthly/202308.smd new file mode 100644 index 0000000..c8567ff --- /dev/null +++ b/content/monthly/202308.smd @@ -0,0 +1,230 @@ +--- +.title = "202308 | 0.11 正式发布", +.date = @date("2023-09-03T19:38:04+0800"), +.author = "ZigCC", +.layout = "monthly.shtml", +.draft = false, +--- + +# [0.11 正式发布](https://ziglang.org/download/0.11.0/release-notes.html#x86-Backend) + +0.11 终于在 8 月 4 号释出了,下面来看看它的一些重要改进吧。[HN +讨论](https://news.ycombinator.com/item?id=36995735) + +# [Peer Type Resolution Improvements]($section.id('Peer Type Resolution Improvements')) + +对等类型解析算法得到改进,下面是一些在 0.10 中不能解析,但在 0.11 +中可以解析的例子: + +| | | +|------------------------------------|---------------| +| Peer Types | Resolved Type | +| \[:s\]const T, \[\]T | \[\]const T | +| E!\*T, ?\*T | E!?\*T | +| \[\*c\]T, @TypeOf(null) | \[\*c\]T | +| ?u32, u8 | ?u32 | +| \[2\]u32, struct { u32, u32 } | \[2\]u32 | +| \*const @TypeOf(.{}), \[\]const u8 | \[\]const u8 | + +而且现在使用 `@intCast` 这类 builtin +都只接受一个参数,目前类型根据上下文自动推断出来。 + +# [Multi-Object For Loops]($section.id('Multi-Object For Loops')) + +可以同时对多个对象进行遍历: + +``` zig +// 之前 +for (input) |x, i| { + output[i] = x * 2; +} + +// 现在 +for (input, 0..) |x, i| { + output[i] = x * 2; +} +``` + +# [@min and @max]($section.id('@min and @max')) + +主要有两个改动: + +1. 这两个 builtin 现在支持任意多个参数 +2. 返回的类型,会尽可能的紧凑 + +``` zig +test "@min/@max refines result type" { + const x: u8 = 20; // comptime-known + var y: u64 = 12345; + // Since an exact bound is comptime-known, the result must fit in a u5 + comptime assert(@TypeOf(@min(x, y)) == u5); + + var x_rt: u8 = x; // runtime-known + // Since one argument to @min is a u8, the result must fit in a u8 + comptime assert(@TypeOf(@min(x_rt, y)) == u8); +} +``` + +# [@inComptime]($section.id('@inComptime')) + +新加的 builtin,用于判断执行是否在 comptime 环境下执行: + +``` zig +const global_val = blk: { + assert(@inComptime()); + break :blk 123; +}; + +comptime { + assert(@inComptime()); +} + +fn f() u32 { + if (@inComptime()) { + return 1; + } else { + return 2; + } +} + +test "@inComptime" { + try expectEqual(true, comptime @inComptime()); + try expectEqual(false, @inComptime()); + try expectEqual(@as(u32, 1), comptime f()); + try expectEqual(@as(u32, 2), f()); +} +``` + +# [类型转化相关 builtin 的重命名]($section.id('类型转化相关 builtin 的重命名')) + +之前 `@xToY` 形式的 builtin 现在已经改成了 `@yFromX` +,这样的主要好处是便于阅读(从右向左),这是[草案](https://github.com/ziglang/zig/issues/6128)。 + +# [Tuple 类型声明]($section.id('Tuple 类型声明')) + +现在可以直接用无 field 名字的 struct 来声明 tuple 类型: + +``` zig +test "tuple declarations" { + const T = struct { u32, []const u8 }; + var t: T = .{ 1, "foo" }; + try expect(t[0] == 1); + try expectEqualStrings(t[1], "foo"); + + var mul = t ** 3; + try expect(@TypeOf(mul) != T); + try expect(mul.len == 6); + try expect(mul[2] == 1); + try expectEqualStrings(mul[3], "foo"); + + var t2: T = .{ 2, "bar" }; + var cat = t ++ t2; + try expect(@TypeOf(cat) != T); + try expect(cat.len == 4); + try expect(cat[2] == 2); + try expectEqualStrings(cat[3], "bar"); +} +``` + +之前只能用 `std.meta.Tuple` 函数来定义: + +``` diff +- const testcases = [_]std.meta.Tuple(&[_]type{ []const u8, []const u8, bool }){ ++ const testcases = [_]struct { []const u8, []const u8, bool }{ +``` + +# [排序]($section.id('排序')) + +现在排序算法分布两类: + +- 稳定,blocksort 算法 +- 不稳定,[pdqsort](https://github.com/ziglang/zig/pull/15412) + 算法,它结合了随机快速排序的快速平均情况和堆排序的快速最坏情况。 + +与堆排的快速最差情况相结合,同时在具有特定模式的输入上达到线性时间。 + +# [Stack Unwinding]($section.id('Stack Unwinding')) + +Zig 之前依赖 [frame +pointer](https://en.wikipedia.org/wiki/Call_stack#Stack_and_frame_pointers) +来做堆栈回卷,但它本身有些代价,因此线上环境可能会通过 +`-fomit-frame-pointer` 将其禁用掉。 + +为了在这种情况下依然能够获取 panic 是的堆栈信息,Zig 现在支持了通过 +DWARF unwind tables 和 MachO compact unwind information +来会恢复堆栈,详见:[\#15823](https://github.com/ziglang/zig/pull/15823)。 + +# [包管理]($section.id('包管理')) + +0.11 首次正式引入了包管理器,具体解释可以参考:[Zig Build +System](https://en.liujiacai.net/2023/04/13/zig-build-system/),而且很重要一点,step +之间可以[并发执行](https://ziglang.org/download/0.11.0/release-notes.html#Steps-Run-In-Parallel), + +# [Bootstrapping]($section.id('Bootstrapping')) + +C++ 实现的 Zig 编译器已经被彻底移除,这意味着 `-fstage1` 不再生效,Zig +现在只需要一个 2.4M 的 WebAssembly 文件和一个 C +编辑器即可,工作细节可以参考:[Goodbye to the C++ Implementation of +Zig](https://ziglang.org/news/goodbye-cpp/)。 + +# [代码生成]($section.id('代码生成')) + +虽然 Zig 编译器现在还是主要使用 LLVM +来进行代码生成,但在这次发布中,其他几个后端也有了非常大的进步: + +1. C 后端,行为测试通过 98%,而且生成的 C 代码兼容微软的 MSVC,用在了 + bootstrapping 中 +2. x86 后端,行为测试通过 88% +3. aarch64 后端,刚开始 +4. WebAssembly 后端,行为测试通过 86%, +5. SPIR-V 后端,SPIR-V 是在 GPU + 上运行的着色器(shader)和内核的字节码表示法。目前,Zig 的 SPIR-V + 后端专注于为 OpenCL 内核生成代码,不过未来可能也会支持兼容 Vulkan + 的着色器。 + +# [增量编译]($section.id('增量编译')) + +虽然这仍是一个高度 WIP +的功能,但这一版本周期中的许多改进为编译器的增量编译功能铺平了道路。其中最重要的是 +[InternPool](https://github.com/ziglang/zig/pull/15569)。Zig +用户大多看不到这一改动,但它为编译器带来了许多好处,其中之一就是我们现在更接近增量编译了。增量编译将是 +0.12.0 发布周期的重点。 + +# [观点/教程]($section.id('观点/教程')) + +[Error Handling In Zig](https://www.aolium.com/karlseguin/4013ac14-2457-479b-e59b-e603c04673c8) +又一篇讨论错误处理的文章 + +[Commiting Type Crimes in Zig](https://www.1a-insec.net/blog/10-type-magic-in-zig/) +对 Zig +类型系统的另一种用法,有些和[邱奇数](https://zh.wikipedia.org/wiki/%E9%82%B1%E5%A5%87%E6%95%B0)类似。 + +[Zig in 100 Seconds](https://www.youtube.com/watch?v=kxT8-C1vmd4) +Zig 宣传视频 + +[Zig Build System & How to Build Software From Source • Andrew Kelley • GOTO 2023](https://www.youtube.com/watch?v=vKKTMBoxpS8) +Andrew 关于构建系统的视频,[B +站链接](https://www.bilibili.com/video/BV1Mh4y1K7yc/)、[Youbute](https://www.youtube.com/watch?v=vKKTMBoxpS8) + +[Wrap your NIF with Zig](https://rbino.com/posts/wrap-your-nif-with-zig/) +NIF 是 Elixir 中进行 FFI 调用的方式,如果用原生 C +接口来用,会需要写很多胶水代码, 作者这里用 comptime 特性来定义了一个 +`make_nif_wrapper` 来简化 NIF 的实现,这个技巧在与 C +项目交互时十分有用。 + +[Types and the Zig Programming Language](https://matklad.github.io/2023/08/09/types-and-zig.html) +matklad 对 Zig 类型系统的总结 + +[So Long, Twitter and Reddit](https://andrewkelley.me/post/goodbye-twitter-reddit.html) +Andrew 的最新文章,远离社交平台! + +[WTF is Zig Comptime (and Inline)](https://zig.news/edyu/wtf-is-zig-comptime-and-inline-257b) + +[Taking off with Zig: Putting the Z in Benchmark — Double Trouble](https://double-trouble.dev/post/zbench/) + +# [项目/工具]($section.id('项目/工具')) + +- [Mach v0.2 + released](https://devlog.hexops.com/2023/mach-v0.2-released/) + +# [Zig 语言更新](https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2023-07-01..2023-08-01) diff --git a/content/monthly/202309.org b/content/monthly/202309.org deleted file mode 100644 index 550fa18..0000000 --- a/content/monthly/202309.org +++ /dev/null @@ -1,55 +0,0 @@ -#+TITLE: 202309 | Bun 正式发布 1.0 -#+DATE: 2023-09-23T10:10:58+0800 -#+LASTMOD: 2023-10-04T20:12:55+0800 -* 重大事件 -** [[https://ziglang.org/news/bounties-damage-open-source-projects/][Bounties Damage Open Source Projects]] -在 2023-09-11 号,Wasmerio CEO 创建了 [[https://github.com/ziglang/zig/issues/17115][Support WASIX · Issue #17115]],表示想赞助 Zig 开发者,让其更好地支持 WASIX 平台。 - -Andrew 与 Loris 在这篇文章中主要阐述了这么做为什么是伤害社区的行为: -1. 助长竞争,牺牲合作 -2. 在软件开发的商业管理方面,悬赏是一种极为简单的方法,这可能让开发者关注短期效益,忽视长期利益,比如维护成本。 - -这篇文章其实很符合 Andrew 的理念,不想让过多的热钱涌入 Zig 社区,他更想保证 Zig 的独立性,这也是他们创办 [[https://kristoff.it/blog/the-open-source-game/][Software You Can Love]] 的初衷。 - -** [[https://bun.sh/blog/bun-v1.0][Bun 1.0]] -面包终于出炉了!Bun 毫无疑问是 Zig 的明星项目,它在 2023-09-08 正式发布了 1.0 版本,这对开发者来说可能没什么太大的区别,毕竟就只是个 tag 而已,但是对于广大的用户来说,这无疑意味着可以在生产环境中去使用了。 - -Bun 并不简单的是个 Node.js 替代品,而是大而全的工具链: -- Transpilers,可以直接运行 =js= =jsx= =mjs= =ts= =tsx= =cjs= 文件 -- Bundlers,可以直接替代 webpack、esbuild 等工具 -- Package managers,兼容 npm,识别 =package.json= 格式,可以替代:npm、yarn、 -- Testing libraries,内置 test runner,支持快照测试、模拟和代码覆盖,可以替代:jest、ts-test -* 观点/教程 -- [[https://linus.dev/posts/kiesel-devlog-1/][Kiesel Devlog #1: Now passing 25% of test262]] :: 另一个 devlog,作者写了一个 JS engine 用来学习 Zig,该作者是 SerenityOS 系统中,Ladybird 浏览器 JS 引擎 LibJS 的作者 -- [[https://mitchellh.com/writing/ghostty-and-useful-zig-patterns][Talk: Introducing Ghostty and Some Useful Zig Patterns]] :: Mitchell Hashimoto 在这篇文章里分享了开发终端 Ghostty 时用的 Zig 常用模式。计划在 2024 年发布 1.0 - - Comptime Interface - - Comptime Data Table Generation - - Comptime Type Generation - - [[https://www.bilibili.com/video/BV1884y1D7gu/][B 站视频地址]] -- [[https://www.openmymind.net/learning_zig/][Learning Zig]] :: 一个 Zig 教程,写的非常易懂,推荐每个 Zig 爱好者阅读。目录 - 1. Language Overview - Part 1 - 2. Language Overview - Part 2 - 3. Style guide - 4. Pointers - 5. Stack Memory - 6. Heap Memory & Allocators - 7. Generics - 8. Coding In Zig - 9. Conclusion -- [[https://zinascii.com/2023/debugging-a-zig-test-failure.html][Debugging a Zig Test Failure]] :: 非常硬核的文章,作者为了调查一个文件名太长的错误,使用了 DTrace 来探测内核函数的调用,对平时的问题排查非常有帮助 -- [[https://notes.eatonphil.com/2023-10-01-intercepting-and-modifying-linux-system-calls-with-ptrace.html][Intercepting and modifying Linux system calls with ptrace]] :: 用 Zig 来封装 Dtrace,用于跟踪子进程的 syscall -- [[https://double-trouble.dev/post/zvm/][Managing Zig Versions with zvm: A Technical Dive]] :: 另一个 Zig 版本管理工具,不过这次是用 Zig 写的了 -- [[https://alic.dev/blog/dense-enums][When Zig Outshines Rust -- Memory Efficient Enum Arrays]] :: 一个图文并茂的文章,重点推荐。作者这里通过分析 array of struct 的内存浪费情况,介绍了 Rust/Zig 中不同的解法,Zig 由于有强大的编译期元编程能力,能够更方便的实现 SoA(struct of arrays) - {{< figure src="/images/struct-padding.webp" caption="struct 数组的内存布局">}} - {{< figure src="/images/soa-layout.webp" caption="SoA 内存布局">}} -* 项目/工具 -- [[https://plugins.jetbrains.com/plugin/22456-zigbrains][ZigBrains]] :: A multifunctional Zig Programming Language plugin for the IDEA platform. -- [[https://github.com/fulcrum-so/ziggy-pydust][fulcrum-so/ziggy-pydust]] :: A toolkit for building Python extensions in Zig. -- [[https://github.com/jiacai2050/zig-curl][zig-curl]] :: Zig bindings to libcurl. -- [[https://github.com/darkr4y/OffensiveZig][darkr4y/OffensiveZig]] :: Some attempts at using [[https://ziglang.org/][Zig]] in penetration testing. -- [[https://wasmlabs.dev/articles/zig-support-on-wasm-workers-server/][Announcing Zig support for Wasm Workers Server]] :: Wasm Workers Server 是一个用于开发 serverless 应用的框架,近期增加了对 Zig 的支持,[[https://workers.wasmlabs.dev/docs/languages/zig][使用文档]]。 -- [[https://github.com/dantecatalfamo/wireguard-config-manager][dantecatalfamo/wireguard]] :: Command line wireguard configuration manager. -- [[https://github.com/iacore/libredo][iacore/libredo]] :: Reactive signal/Dependency tracking library in Zig. -- [[https://github.com/buzz-language/buzz][buzz-language/buzz]] :: A small/lightweight statically typed scripting language -* [[https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2023-08-01..2023-09-01][Zig 语言更新]] -- [[https://github.com/ziglang/zig/pull/17221][Aro translate]] :: 用 Zig 写的 [[https://github.com/Vexu/arocc][Aro]] 来替换 clang,来实现 =translate-c= 的功能 diff --git a/content/monthly/202309.smd b/content/monthly/202309.smd new file mode 100644 index 0000000..52332bb --- /dev/null +++ b/content/monthly/202309.smd @@ -0,0 +1,121 @@ +--- +.title = "202309 | Bun 正式发布 1.0", +.date = @date("2023-09-23T10:10:58+0800"), +.author = "ZigCC", +.layout = "monthly.shtml", +.draft = false, +--- + +# [重大事件]($section.id('重大事件')) + +# [Bounties Damage Open Source Projects]($section.id('bounties-damage-open-source-projects')) + +在 2023-09-11 号,Wasmerio CEO 创建了 [Support WASIX · Issue +\#17115](https://github.com/ziglang/zig/issues/17115),表示想赞助 Zig +开发者,让其更好地支持 WASIX 平台。 + +Andrew 与 Loris 在这篇文章中主要阐述了这么做为什么是伤害社区的行为: + +1. 助长竞争,牺牲合作 +2. 在软件开发的商业管理方面,悬赏是一种极为简单的方法,这可能让开发者关注短期效益,忽视长期利益,比如维护成本。 + +这篇文章其实很符合 Andrew 的理念,不想让过多的热钱涌入 Zig +社区,他更想保证 Zig 的独立性,这也是他们创办 [Software You Can +Love](https://kristoff.it/blog/the-open-source-game/) 的初衷。 + +# [Bun 1.0](https://bun.sh/blog/bun-v1.0) + +面包终于出炉了!Bun 毫无疑问是 Zig 的明星项目,它在 2023-09-08 +正式发布了 1.0 版本,这对开发者来说可能没什么太大的区别,毕竟就只是个 +tag 而已,但是对于广大的用户来说,这无疑意味着可以在生产环境中去使用了。 + +Bun 并不简单的是个 Node.js 替代品,而是大而全的工具链: + +- Transpilers,可以直接运行 `js` `jsx` `mjs` `ts` `tsx` `cjs` 文件 +- Bundlers,可以直接替代 webpack、esbuild 等工具 +- Package managers,兼容 npm,识别 `package.json` + 格式,可以替代:npm、yarn、 +- Testing libraries,内置 test + runner,支持快照测试、模拟和代码覆盖,可以替代:jest、ts-test + +# [观点/教程]($section.id('观点/教程')) + +[Kiesel Devlog \#1: Now passing 25% of test262](https://linus.dev/posts/kiesel-devlog-1/) +另一个 devlog,作者写了一个 JS engine 用来学习 Zig,该作者是 SerenityOS +系统中,Ladybird 浏览器 JS 引擎 LibJS 的作者 + +[Talk: Introducing Ghostty and Some Useful Zig Patterns](https://mitchellh.com/writing/ghostty-and-useful-zig-patterns) +Mitchell Hashimoto 在这篇文章里分享了开发终端 Ghostty 时用的 Zig +常用模式。计划在 2024 年发布 1.0 + +- Comptime Interface +- Comptime Data Table Generation +- Comptime Type Generation +- [B 站视频地址](https://www.bilibili.com/video/BV1884y1D7gu/) + +[Learning Zig](https://www.openmymind.net/learning_zig/) +一个 Zig 教程,写的非常易懂,推荐每个 Zig 爱好者阅读。目录 + +1. Language Overview - Part 1 +2. Language Overview - Part 2 +3. Style guide +4. Pointers +5. Stack Memory +6. Heap Memory & Allocators +7. Generics +8. Coding In Zig +9. Conclusion + +[Debugging a Zig Test Failure](https://zinascii.com/2023/debugging-a-zig-test-failure.html) +非常硬核的文章,作者为了调查一个文件名太长的错误,使用了 DTrace +来探测内核函数的调用,对平时的问题排查非常有帮助 + +[Intercepting and modifying Linux system calls with ptrace](https://notes.eatonphil.com/2023-10-01-intercepting-and-modifying-linux-system-calls-with-ptrace.html) +用 Zig 来封装 Dtrace,用于跟踪子进程的 syscall + +[Managing Zig Versions with zvm: A Technical Dive](https://double-trouble.dev/post/zvm/) +另一个 Zig 版本管理工具,不过这次是用 Zig 写的了 + +[When Zig Outshines Rust – Memory Efficient Enum Arrays](https://alic.dev/blog/dense-enums) +一个图文并茂的文章,重点推荐。作者这里通过分析 array of struct +的内存浪费情况,介绍了 Rust/Zig 中不同的解法,Zig +由于有强大的编译期元编程能力,能够更方便的实现 SoA(struct of arrays) +[struct +数组的内存布局]($image.siteAsset('images/struct-padding.webp')) + [SoA 内存布局]($image.siteAsset('images/soa-layout.webp')) + + +# [项目/工具]($section.id('项目/工具')) + +[ZigBrains](https://plugins.jetbrains.com/plugin/22456-zigbrains) +A multifunctional Zig Programming Language plugin for the IDEA platform. + +[fulcrum-so/ziggy-pydust](https://github.com/fulcrum-so/ziggy-pydust) +A toolkit for building Python extensions in Zig. + +[zig-curl](https://github.com/jiacai2050/zig-curl) +Zig bindings to libcurl. + +[darkr4y/OffensiveZig](https://github.com/darkr4y/OffensiveZig) +Some attempts at using [Zig](https://ziglang.org/) in penetration +testing. + +[Announcing Zig support for Wasm Workers Server](https://wasmlabs.dev/articles/zig-support-on-wasm-workers-server/) +Wasm Workers Server 是一个用于开发 serverless 应用的框架,近期增加了对 +Zig +的支持,[使用文档](https://workers.wasmlabs.dev/docs/languages/zig)。 + +[dantecatalfamo/wireguard](https://github.com/dantecatalfamo/wireguard-config-manager) +Command line wireguard configuration manager. + +[iacore/libredo](https://github.com/iacore/libredo) +Reactive signal/Dependency tracking library in Zig. + +[buzz-language/buzz](https://github.com/buzz-language/buzz) +A small/lightweight statically typed scripting language + +# [Zig 语言更新](https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2023-08-01..2023-09-01) + +[Aro translate](https://github.com/ziglang/zig/pull/17221) +用 Zig 写的 [Aro](https://github.com/Vexu/arocc) 来替换 clang,来实现 +`translate-c` 的功能 diff --git a/content/monthly/202310.org b/content/monthly/202310.org deleted file mode 100644 index 365ff73..0000000 --- a/content/monthly/202310.org +++ /dev/null @@ -1,79 +0,0 @@ -#+TITLE: 202310 -#+DATE: 2023-10-13T07:53:24+0800 -#+LASTMOD: 2023-11-04T19:47:55+0800 -* 重大事件 -* 观点/教程 -- [[https://registerspill.thorstenball.com/p/notes-from-the-field-learning-zig][Notes From the Field: Learning Zig]] :: Zig 初学者的使用经验分享 -- [[https://dgross.ca/blog/friendly-neighbor-announce/][Friendly Neighbor: A network service for Linux wake-on-demand, written in Zig]] :: 作者在这篇文章中分享了 - 用 Zig 重写之前 Ruby 写的一个网络工具,一方面是减轻资源消耗,另一方面是探索用“低级”语言来写程序。不错的案例分享。 -- [[https://www.openmymind.net/Zig-Interfaces/][Zig Interfaces]] :: 作者介绍了 Zig 中如何实现接口这个经常需要用到的功能。最后的实现也比较巧妙,结合 =anytype= 与 =*anyopaque= - #+begin_src zig -const std = @import("std"); - -const Writer = struct { - // These two fields are the same as before - ptr: *anyopaque, - writeAllFn: *const fn (ptr: *anyopaque, data: []const u8) anyerror!void, - - // This is new - fn init(ptr: anytype) Writer { - const T = @TypeOf(ptr); - const ptr_info = @typeInfo(T); - - const gen = struct { - pub fn writeAll(pointer: *anyopaque, data: []const u8) anyerror!void { - const self: T = @ptrCast(@alignCast(pointer)); - return ptr_info.Pointer.child.writeAll(self, data); - } - }; - - return .{ - .ptr = ptr, - .writeAllFn = gen.writeAll, - }; - } - - // This is the same as before - pub fn writeAll(self: Writer, data: []const u8) !void { - return self.writeAllFn(self.ptr, data); - } -}; - -const File = struct { - fd: std.os.fd_t, - - fn writeAll(ptr: *anyopaque, data: []const u8) !void { - const self: *File = @ptrCast(@alignCast(ptr)); - // os.write might not write all of `data`, we should really look at the - // returned value, the number of bytes written, and handle cases where data - // wasn't all written. - _ = try std.os.write(self.fd, data); - } - - fn writer(self: *File) Writer { - return Writer.init(self); - } -}; - -pub fn main() !void { - var file = try std.fs.createFileAbsolute("/tmp/demo.txt", .{}); - var my_file = File{ .fd = file.handle }; - const writer = my_file.writer(); - try writer.writeAll("hello world"); -} - #+end_src -- [[https://notes.eatonphil.com/2023-10-19-write-file-to-disk-with-io_uring.html][io_uring basics: Writing a file to disk]] :: 作者演示了 io_uring 在 Go 与 Zig 中的基本使用,下面表格是一些测试数据 -| method | avg_time | avg_throughput | -|---------------------+----------------------+----------------| -| iouring_128_entries | 0.2756831357s | 3.8GB/s | -| iouring_1_entries | 0.27575404880000004s | 3.8GB/s | -| blocking | 0.2833337046s | 3.7GB/s | -- [[https://www.ryanliptak.com/blog/zig-is-a-windows-resource-compiler/][Zig is now also a Windows resource compiler]] :: 相当硬核的文章,作者最近给 Zig 贡献了一个大功能:支持 Windows 资源定义文件的编译,用户可以通过 =zig rc= 子命令来使用。 -- [[https://zigcc.github.io/post/2023/10/14/zig-version-manager/][Zig 多版本管理]] :: 由于 Zig 还在快速开发迭代中,因此项目很有可能出现新版本 Zig 无法编译的情况,这篇文章介绍了一些管理多个 Zig 版本的方式。 -* 项目/工具 -- [[https://zigcli.liujiacai.net/][zigcli]] :: a toolkit for building command lines programs in Zig -- [[https://github.com/chung-leong/pb2zig][pb2zig]] :: Pixel Bender to Zig code translator -- [[https://github.com/chung-leong/zigar][zigar]] :: Enable the use of Zig code in JavaScript project -- [[https://github.com/jinyus/related_post_gen][jinyus/related_post_gen]] :: 一个对常见语言进行压测的项目,项目里面有几种纯 CPU 的操作,看看哪个语言最快。 -- [[https://github.com/nolanderc/glsl_analyzer][nolanderc/glsl_analyzer]] :: Language server for GLSL (autocomplete, goto-definition, formatter, and more) -* [[https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2023-09-01..2023-10-01][Zig 语言更新]] diff --git a/content/monthly/202310.smd b/content/monthly/202310.smd new file mode 100644 index 0000000..b9b30af --- /dev/null +++ b/content/monthly/202310.smd @@ -0,0 +1,118 @@ +--- +.title = "202310", +.date = @date("2023-10-13T07:53:24+0800"), +.author = "ZigCC", +.layout = "monthly.shtml", +.draft = false, +--- + +# [重大事件]($section.id('major-events')) + +# [观点/教程]($section.id('opinion-tutorial')) + +[Notes From the Field: Learning Zig](https://registerspill.thorstenball.com/p/notes-from-the-field-learning-zig) +Zig 初学者的使用经验分享 + +[Friendly Neighbor: A network service for Linux wake-on-demand, written in Zig](https://dgross.ca/blog/friendly-neighbor-announce/) +作者在这篇文章中分享了 用 Zig 重写之前 Ruby +写的一个网络工具,一方面是减轻资源消耗,另一方面是探索用"低级"语言来写程序。不错的案例分享。 + +[Zig Interfaces](https://www.openmymind.net/Zig-Interfaces/) +作者介绍了 Zig +中如何实现接口这个经常需要用到的功能。最后的实现也比较巧妙,结合 +`anytype` 与 `*anyopaque` + +``` zig +const std = @import("std"); + +const Writer = struct { + // These two fields are the same as before + ptr: *anyopaque, + writeAllFn: *const fn (ptr: *anyopaque, data: []const u8) anyerror!void, + + // This is new + fn init(ptr: anytype) Writer { + const T = @TypeOf(ptr); + const ptr_info = @typeInfo(T); + + const gen = struct { + pub fn writeAll(pointer: *anyopaque, data: []const u8) anyerror!void { + const self: T = @ptrCast(@alignCast(pointer)); + return ptr_info.Pointer.child.writeAll(self, data); + } + }; + + return .{ + .ptr = ptr, + .writeAllFn = gen.writeAll, + }; + } + + // This is the same as before + pub fn writeAll(self: Writer, data: []const u8) !void { + return self.writeAllFn(self.ptr, data); + } +}; + +const File = struct { + fd: std.os.fd_t, + + fn writeAll(ptr: *anyopaque, data: []const u8) !void { + const self: *File = @ptrCast(@alignCast(ptr)); + // os.write might not write all of `data`, we should really look at the + // returned value, the number of bytes written, and handle cases where data + // wasn't all written. + _ = try std.os.write(self.fd, data); + } + + fn writer(self: *File) Writer { + return Writer.init(self); + } +}; + +pub fn main() !void { + var file = try std.fs.createFileAbsolute("/tmp/demo.txt", .{}); + var my_file = File{ .fd = file.handle }; + const writer = my_file.writer(); + try writer.writeAll("hello world"); +} +``` + +[iouring basics: Writing a file to disk](https://notes.eatonphil.com/2023-10-19-write-file-to-disk-with-io_uring.html) +作者演示了 iouring 在 Go 与 Zig +中的基本使用,下面表格是一些测试数据 + +| method | avgtime | avgthroughput | +|------------------------------|----------------------|--------------------------| +| iouring128entries | 0.2756831357s | 3.8GB/s | +| iouring1entries | 0.27575404880000004s | 3.8GB/s | +| blocking | 0.2833337046s | 3.7GB/s | + +[Zig is now also a Windows resource compiler](https://www.ryanliptak.com/blog/zig-is-a-windows-resource-compiler/) +相当硬核的文章,作者最近给 Zig 贡献了一个大功能:支持 Windows +资源定义文件的编译,用户可以通过 `zig rc` 子命令来使用。 + +[Zig 多版本管理](https://zigcc.github.io/post/2023/10/14/zig-version-manager/) +由于 Zig 还在快速开发迭代中,因此项目很有可能出现新版本 Zig +无法编译的情况,这篇文章介绍了一些管理多个 Zig 版本的方式。 + +# [项目/工具]($section.id('projects-tools')) + +[zigcli](https://zigcli.liujiacai.net/) +a toolkit for building command lines programs in Zig + +[pb2zig](https://github.com/chung-leong/pb2zig) +Pixel Bender to Zig code translator + +[zigar](https://github.com/chung-leong/zigar) +Enable the use of Zig code in JavaScript project + +[jinyus/relatedpostgen](https://github.com/jinyus/related_post_gen) +一个对常见语言进行压测的项目,项目里面有几种纯 CPU +的操作,看看哪个语言最快。 + +[nolanderc/glslanalyzer](https://github.com/nolanderc/glsl_analyzer) +Language server for GLSL (autocomplete, goto-definition, formatter, and +more) + +# [Zig 语言更新](https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2023-09-01..2023-10-01) diff --git a/content/monthly/202311.org b/content/monthly/202311.org deleted file mode 100644 index 9630196..0000000 --- a/content/monthly/202311.org +++ /dev/null @@ -1,102 +0,0 @@ -#+TITLE: 202311 | 传值或传引用,这是个大问题 -#+DATE: 2023-11-19T18:26:29+0800 -#+LASTMOD: 2023-12-04T09:23:13+0800 -* 重大事件 -本月讨论比较多的就是 [[https://www.1a-insec.net/blog/25-zig-reference-semantics/][Zig May Pass Anything By Reference]] 这篇文章了。 - -它讲述了 Zig 里面一个比较有争议的点,函数的参数到底是传值还是传引用。 -#+begin_src zig -const AAAA = struct { - foo: [100]u32, -}; - -fn aaaaa(a: AAAA, b: *AAAA) void { - b.*.foo[0] = 5; - - std.debug.print("wtf: {}", .{ a.foo[0] }); -} - -pub fn main() !void { - var f: AAAA = undefined; - - f.foo[0] = 0; - - aaaaa(f, &f); -} -#+end_src -上面这个例子修改了 =b= 参数的值,但是打印出来的 =a= 的值也被修改了。 - -传值的好处就是不用担心原值会被修改,传引用的好处就是可以减少数据拷贝的代价。但是 Zig 目前采用的方式是由编译器推导来决定合适的方式。这样的目的是减少程序员负担,但这实际上会给程序带来不确定性,比如上述例子。 - -Andrew 在 [[https://lobste.rs/s/et3ivs/zig_may_pass_anything_by_reference#c_yvfrnq][Lobster]] 上回复了这个问题,确实是一个比较严重的问题,一种解法是分析一个变量有多少个 alias,编译器只在确定没问题时才进行优化,但是分析一个变量的 alias 有多少不是件容易的事。 - -其他语言如 C/C++/Rust 等没有进行这种优化尝试,因此没有这个问题,但是 Zig 作为一个新的语言,想尝试来用一种程序员无感的方式来解决,只是目前还没有想到更完善的方案而已。 - -一些熟悉 Zig zen 的读者可能会觉得这违背了第一条『Communicate intent precisely』,目前来看确实是这样的,而且 core team 老早就意识到这个问题了,感兴趣的读者可以参考: -- [[https://github.com/ziglang/zig/issues/5973][Footgun: hidden pass-by-reference #5973]] -- [[https://github.com/ziglang/zig/issues/12064][Design flaw: Swapping struct fields yields unexpected value #12064]] -* 观点/教程 -- [[https://www.openmymind.net/Zigs-std-json-Parsed/][Zig's std.json.Parsed(T)]] :: 老朋友 openmymind 的文章,这篇文章主要讲述了使用 Zig 中的 json 库序列化后,如何更好的使用返回值,由于有一个 allocator 参数,因此比不能简单的返回 ~T~ ,作者这里定义了一个 ~Managed~ 来解决: - #+begin_src zig -pub fn Managed(comptime T: type) type { - return struct { - value: T, - arena: *std.heap.ArenaAllocator, - - const Self = @This(); - - pub fn fromJson(parsed: std.json.Parsed(T)) Self { - return .{ - .arena = parsed.arena, - .value = parsed.value, - }; - } - - pub fn deinit(self: Self) void { - const arena = self.arena; - const allocator = arena.child_allocator; - arena.deinit(); - allocator.destroy(arena); - } - }; -} - #+end_src -- [[https://re.factorcode.org/2023/11/factor-is-faster-than-zig.html][Factor is faster than Zig!]] :: 一个有意思的案例分享。 -- [[https://www.pierrebeaucamp.com/a-day-with-zig/][A day with Zig]] :: 作者把之前一个 Go 的项目转成 Zig,这里介绍了一些感受, - - 文档缺乏 - - 文件级别导入 -- [[https://registerspill.thorstenball.com/p/zig-zaggin][@fieldParentPtr]] :: 对 ~@fieldParentPtr~ 使用的介绍 -- [[https://sudw1n.gitlab.io/posts/zig-build-docs/][Generating documentation from zig build]] :: 作者在这篇文章里尝试在 zig build 文件中输出文档,目前步骤略微繁琐。 - #+begin_src zig -const std = @import("std"); - -pub fn build(b: *std.Build) void { - const exe = b.addExecutable(.{ - .name = "myprogram", - .root_source_file = .{ .path = "src/main.zig" }, - .target = b.standardTargetOptions(.{}), - .optimize = b.standardOptimizeOption(.{}), - }); - - b.installArtifact(exe); - - const install_docs = b.addInstallDirectory(.{ - .source_dir = exe.getEmittedDocs(), - .install_dir = .prefix, - .install_subdir = "docs", - }); - - const docs_step = b.step("docs", "Copy documentation artifacts to prefix path"); - docs_step.dependOn(&install_docs.step); -} - #+end_src -- [[https://www.youtube.com/watch?v=5_oqWE9otaE][What's Zig got that C, Rust and Go don't have? (with Loris Cro)]] :: [视频] Loris 参与的一档播客 -- [[https://mtlynch.io/notes/zig-call-c-simple/][A Simple Example of Calling a C Library from Zig]] :: 一个简明的教程,演示 Zig 如何引用 C 类库 -- [[https://www.reddit.com/r/Zig/comments/17xd46v/what_is_the_zig_philosophy_on_apis_and_abstraction/][What is the Zig philosophy on APIs and abstraction?]] :: 一个 Reddit 帖子,讨论 Zig 的在 API 设计上的哲学、理念。一个有意思的点是 Zig 不支持私有的字段,全部都是 public 的。Andrew 在 [[https://github.com/ziglang/zig/issues/9909#issuecomment-942686366][Proposal: Private Fields #9909]] 这个 issue 里面讨论过原因,主要根据: - - 一个结构体的抽象,很难保证不泄漏,比如一个类型的 align、size,一个函数是否可以在 comptime 执行 - - 一个包的兼容性,应该由文档来解释 - - 增加私有字段,会增加语言的复杂度,而且这种复杂性本身是完全可以避免的 -* 项目/工具 -- [[https://zig.news/xq/zig-build-explained-part-2-1850][zig build explained -- building C/C++ projects]] :: 经典文章回顾,如何使用 Zig 构建系统编译 C/C++ 项目 -- [[https://github.com/akhildevelops/cudaz][akhildevelops/cudaz]] :: A Zig Cuda wrapper -* [[https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2023-10-01..2023-11-01][Zig 语言更新]] diff --git a/content/monthly/202311.smd b/content/monthly/202311.smd new file mode 100644 index 0000000..78d02ff --- /dev/null +++ b/content/monthly/202311.smd @@ -0,0 +1,158 @@ +--- +.title = "202311 | 传值或传引用,这是个大问题", +.date = @date("2023-11-19T18:26:29+0800"), +.author = "ZigCC", +.layout = "monthly.shtml", +.draft = false, +--- + +# [重大事件]($section.id('major-events')) + +本月讨论比较多的就是 [Zig May Pass Anything By +Reference](https://www.1a-insec.net/blog/25-zig-reference-semantics/) +这篇文章了。 + +它讲述了 Zig 里面一个比较有争议的点,函数的参数到底是传值还是传引用。 + +``` zig +const AAAA = struct { + foo: [100]u32, +}; + +fn aaaaa(a: AAAA, b: *AAAA) void { + b.*.foo[0] = 5; + + std.debug.print("wtf: {}", .{ a.foo[0] }); +} + +pub fn main() !void { + var f: AAAA = undefined; + + f.foo[0] = 0; + + aaaaa(f, &f); +} +``` + +上面这个例子修改了 `b` 参数的值,但是打印出来的 `a` 的值也被修改了。 + +传值的好处就是不用担心原值会被修改,传引用的好处就是可以减少数据拷贝的代价。但是 +Zig +目前采用的方式是由编译器推导来决定合适的方式。这样的目的是减少程序员负担,但这实际上会给程序带来不确定性,比如上述例子。 + +Andrew 在 +[Lobster](https://lobste.rs/s/et3ivs/zig_may_pass_anything_by_reference#c_yvfrnq) +上回复了这个问题,确实是一个比较严重的问题,一种解法是分析一个变量有多少个 +alias,编译器只在确定没问题时才进行优化,但是分析一个变量的 alias +有多少不是件容易的事。 + +其他语言如 C/C++/Rust 等没有进行这种优化尝试,因此没有这个问题,但是 Zig +作为一个新的语言,想尝试来用一种程序员无感的方式来解决,只是目前还没有想到更完善的方案而已。 + +一些熟悉 Zig zen 的读者可能会觉得这违背了第一条『Communicate intent +precisely』,目前来看确实是这样的,而且 core team +老早就意识到这个问题了,感兴趣的读者可以参考: + +- [Footgun: hidden pass-by-reference + \#5973](https://github.com/ziglang/zig/issues/5973) +- [Design flaw: Swapping struct fields yields unexpected value + \#12064](https://github.com/ziglang/zig/issues/12064) + +# [观点/教程]($section.id('opinion-tutorial')) + +[Zig's std.json.Parsed(T)](https://www.openmymind.net/Zigs-std-json-Parsed/) +老朋友 openmymind 的文章,这篇文章主要讲述了使用 Zig 中的 json +库序列化后,如何更好的使用返回值,由于有一个 allocator +参数,因此比不能简单的返回 `T` ,作者这里定义了一个 `Managed` 来解决: + +``` zig +pub fn Managed(comptime T: type) type { + return struct { + value: T, + arena: *std.heap.ArenaAllocator, + + const Self = @This(); + + pub fn fromJson(parsed: std.json.Parsed(T)) Self { + return .{ + .arena = parsed.arena, + .value = parsed.value, + }; + } + + pub fn deinit(self: Self) void { + const arena = self.arena; + const allocator = arena.child_allocator; + arena.deinit(); + allocator.destroy(arena); + } + }; +} +``` + +[Factor is faster than Zig!](https://re.factorcode.org/2023/11/factor-is-faster-than-zig.html) +一个有意思的案例分享。 + +[A day with Zig](https://www.pierrebeaucamp.com/a-day-with-zig/) +作者把之前一个 Go 的项目转成 Zig,这里介绍了一些感受, + +- 文档缺乏 +- 文件级别导入 + +[@fieldParentPtr](https://registerspill.thorstenball.com/p/zig-zaggin) +对 `@fieldParentPtr` 使用的介绍 + +[Generating documentation from zig build](https://sudw1n.gitlab.io/posts/zig-build-docs/) +作者在这篇文章里尝试在 zig build 文件中输出文档,目前步骤略微繁琐。 + +``` zig +const std = @import("std"); + +pub fn build(b: *std.Build) void { + const exe = b.addExecutable(.{ + .name = "myprogram", + .root_source_file = .{ .path = "src/main.zig" }, + .target = b.standardTargetOptions(.{}), + .optimize = b.standardOptimizeOption(.{}), + }); + + b.installArtifact(exe); + + const install_docs = b.addInstallDirectory(.{ + .source_dir = exe.getEmittedDocs(), + .install_dir = .prefix, + .install_subdir = "docs", + }); + + const docs_step = b.step("docs", "Copy documentation artifacts to prefix path"); + docs_step.dependOn(&install_docs.step); +} +``` + +[What's Zig got that C, Rust and Go don't have? (with Loris Cro)](https://www.youtube.com/watch?v=5_oqWE9otaE) +\[视频\] Loris 参与的一档播客 + +[A Simple Example of Calling a C Library from Zig](https://mtlynch.io/notes/zig-call-c-simple/) +一个简明的教程,演示 Zig 如何引用 C 类库 + +[What is the Zig philosophy on APIs and abstraction?](https://www.reddit.com/r/Zig/comments/17xd46v/what_is_the_zig_philosophy_on_apis_and_abstraction/) +一个 Reddit 帖子,讨论 Zig 的在 API 设计上的哲学、理念。一个有意思的点是 +Zig 不支持私有的字段,全部都是 public 的。Andrew 在 [Proposal: Private +Fields +\#9909](https://github.com/ziglang/zig/issues/9909#issuecomment-942686366) +这个 issue 里面讨论过原因,主要根据: + +- 一个结构体的抽象,很难保证不泄漏,比如一个类型的 + align、size,一个函数是否可以在 comptime 执行 +- 一个包的兼容性,应该由文档来解释 +- 增加私有字段,会增加语言的复杂度,而且这种复杂性本身是完全可以避免的 + +# [项目/工具]($section.id('projects-tools')) + +[zig build explained – building C/C++ projects](https://zig.news/xq/zig-build-explained-part-2-1850) +经典文章回顾,如何使用 Zig 构建系统编译 C/C++ 项目 + +[akhildevelops/cudaz](https://github.com/akhildevelops/cudaz) +A Zig Cuda wrapper + +# [Zig 语言更新](https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2023-10-01..2023-11-01) diff --git a/content/monthly/202402.org b/content/monthly/202402.org deleted file mode 100644 index 21d3824..0000000 --- a/content/monthly/202402.org +++ /dev/null @@ -1,38 +0,0 @@ -#+TITLE: 202402 | Zig 2024 Roadmap 新鲜出炉 -#+DATE: 2024-03-04T20:54:50+0800 -#+LASTMOD: 2024-03-06T20:39:20+0800 -* 重大事件 -Andrew 最近在 zigshow 节目中介绍了 Zig 2024 年的规划,主要有以下几点: - -1. 0.12 版本会尽快发布 -2. 编译时间现在太慢,进而导致修 bug 的时间长,因此 core team 会优先解决这个编译时间问题。在这个看板中,有相应的进度,主要是:Ditch LLVM、Incremental Compilation 这两个。 - - 很多人都对 Ditch LLVM 这个事情嗤之以鼻,认为这是不自量力,[[https://github.com/ziglang/zig/issues/16270][这个 issue]] 的讨论也比较多,已经有近 200 条回复,最近 Andrew 增加了[[https://github.com/ziglang/zig/issues/16270#issuecomment-1905107583][一条回复]],引用了 [[https://www.joelonsoftware.com/2001/10/14/in-defense-of-not-invented-here-syndrome/][In Defense of Not-Invented-Here Syndrome]],该文章的核心观点是如果一个技术是一个产品的核心点,那么就应该自己写,因为这样才有核心竞争力,文中的例子是 Excel 团队会自己维护一个 C 编译器。 -3. 异步的支持,目前还有还有不少需要解决的技术难点,比如: - - async 函数挂起时,会保存所有上下文,但是在递归函数里,容易 oom - - 无法推倒出 函数指针 是不是 async fn 的,async fn 与普通 fn 的调用方式是不一样的 -4. Donor Bounties,捐赠性悬赏, -5. 工具链,目前还没精力,只能让社区先来做 - -更多细致总结可以参考:[[https://github.com/orgs/zigcc/discussions/91][Zig Roadmap 2024 - Andrew Kelley #91]] -B 站搬运地址:https://www.bilibili.com/video/BV1UC4y167w9/ -* 观点/教程 -- [[https://www.infoworld.com/article/3713082/fast-growing-zig-tops-stack-overflow-survey-for-highest-paid-programming-language.html][Fast-growing Zig tops Stack Overflow survey for highest-paid programming language]] :: 估计是 Bun 带动的贫富差距?! -- [[https://text.garden/writings/generationalpool.html][Pool with generational references in Zig]] :: 作者在文中介绍了一种有意思的思路:当有很多指针指向同一个对象时,如何不用遍历这些指针就能让其失效,答案是用一个胖指针,包括两部分:真正的数据指针和指向对象的年龄,当指针的年龄和指向对象的年龄不一致时,即认为该指针失效。 -- [[https://lupyuen.codeberg.page/articles/tcc.html][TCC RISC-V Compiler runs in the Web Browser (thanks to Zig Compiler)]] :: [[https://github.com/sellicott/tcc-riscv32][TCC]] 是一个 64 位 RISC-V 的编译器,作者在这篇文章里利用 Zig 把它编译成 WebAssembly 放到浏览器里执行。其中的难点在于 TCC 会调用 Posix 的一些函数,比如:fopen、fprintf、strncpy、malloc 等,但是这些在 WebAssembly 里是没有的,因此需要[[https://github.com/lupyuen/tcc-riscv32-wasm/blob/main/zig/tcc-wasm.zig#L447-L774][自己实现]],不过幸好 Zig 社区内已经有不少 libc 的实现了: - - [[https://github.com/marler8997/ziglibc][marler8997/ziglibc]] - - [[https://github.com/ZigEmbeddedGroup/foundation-libc][ZigEmbeddedGroup/foundation-libc]],A libc implementation written in Zig that is designed to be used with freestanding targets. -- [[https://devlog.hexops.com/2024/building-the-directx-shader-compiler-better-than-microsoft/][Building the DirectX shader compiler better than Microsoft?]] :: -- [[http://coypu.sdf.org/porting-zig.html][Porting Zig to NetBSD]] :: -- [[https://blog.syndica.io/sig-engineering-part-2-accountsdb-more/][Sig Engineering - Part 2 - Progress on AccountsDB & more]] :: Syndica 公司的 Sig,这是一款用 Zig 编写的、专注于 RPS 的 Solana 验证器客户端。在这篇文章里,他们分析了如何优化 HashMap 的性能,而且实现了一个基于本地磁盘的 Allocator。而且他们还在招聘 Zig 工程师: - - [[https://jobs.ashbyhq.com/syndica/15ab4e32-0f32-41a0-b8b0-16b6518158e9][Senior Software Engineer (Zig/C/Rust) @ Syndica]] - -* 项目/工具 -- [[https://github.com/semickolon/kirei][semickolon/kirei]] :: 🌸 The prettiest keyboard software -- [[https://github.com/Dok8tavo/Interfacil/][Dok8tavo/Interfacil]] :: Interfacil is a Zig package for making and using interfaces easily in Zig. -- [[https://github.com/kamlesh-nb/azure-sdk-for-zig][kamlesh-nb/azure-sdk-for-zig]] :: Azure Sdk for Zig - Experimental -- [[https://github.com/ringtailsoftware/zig-wasm-audio-framebuffer][ringtailsoftware/zig-wasm-audio-framebuffer]] :: Examples of integrating Zig and Wasm for audio and graphics on the web -- [[https://github.com/cztomsik/tokamak][cztomsik/tokamak]] :: Server-side framework for Zig, relying heavily on dependency injection. -- [[https://github.com/The-Z-Labs/cli4bofs][The-Z-Labs/cli4bofs]] :: Command line interface for (running) BOFs -- [[https://github.com/nelipuu/zbind][nelipuu/zbind]] :: Zig-TypeScript binding generator 🟦 🦎 -- [[https://github.com/sneekyfoxx/ziggy][sneekyfoxx/ziggy]] :: 又又一个 Zig 版本管理工具 -* [[https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2024-02-01..2023-03-01][Zig 语言更新]] diff --git a/content/monthly/202402.smd b/content/monthly/202402.smd new file mode 100644 index 0000000..2e05929 --- /dev/null +++ b/content/monthly/202402.smd @@ -0,0 +1,97 @@ +--- +.title = "202402 | Zig 2024 Roadmap 新鲜出炉", +.date = @date("2024-03-04T20:54:50+0800"), +.author = "ZigCC", +.layout = "monthly.shtml", +.draft = false, +--- + +# [重大事件]($section.id('major-events')) + +Andrew 最近在 zigshow 节目中介绍了 Zig 2024 年的规划,主要有以下几点: + +1. 0.12 版本会尽快发布 +2. 编译时间现在太慢,进而导致修 bug 的时间长,因此 core team + 会优先解决这个编译时间问题。在这个看板中,有相应的进度,主要是:Ditch + LLVM、Incremental Compilation 这两个。 + - 很多人都对 Ditch LLVM 这个事情嗤之以鼻,认为这是不自量力,[这个 + issue](https://github.com/ziglang/zig/issues/16270) + 的讨论也比较多,已经有近 200 条回复,最近 Andrew + 增加了[一条回复](https://github.com/ziglang/zig/issues/16270#issuecomment-1905107583),引用了 + [In Defense of Not-Invented-Here + Syndrome](https://www.joelonsoftware.com/2001/10/14/in-defense-of-not-invented-here-syndrome/),该文章的核心观点是如果一个技术是一个产品的核心点,那么就应该自己写,因为这样才有核心竞争力,文中的例子是 + Excel 团队会自己维护一个 C 编译器。 +3. 异步的支持,目前还有还有不少需要解决的技术难点,比如: + - async 函数挂起时,会保存所有上下文,但是在递归函数里,容易 oom + - 无法推倒出 函数指针 是不是 async fn 的,async fn 与普通 fn + 的调用方式是不一样的 +4. Donor Bounties,捐赠性悬赏, +5. 工具链,目前还没精力,只能让社区先来做 + +更多细致总结可以参考:[Zig Roadmap 2024 - Andrew Kelley +\#91](https://github.com/orgs/zigcc/discussions/91) B +站搬运地址:https://www.bilibili.com/video/BV1UC4y167w9/ + +# [观点/教程]($section.id('opinion-tutorial')) + +[Fast-growing Zig tops Stack Overflow survey for highest-paid programming language](https://www.infoworld.com/article/3713082/fast-growing-zig-tops-stack-overflow-survey-for-highest-paid-programming-language.html) +估计是 Bun 带动的贫富差距?! + +[Pool with generational references in Zig](https://text.garden/writings/generationalpool.html) +作者在文中介绍了一种有意思的思路:当有很多指针指向同一个对象时,如何不用遍历这些指针就能让其失效,答案是用一个胖指针,包括两部分:真正的数据指针和指向对象的年龄,当指针的年龄和指向对象的年龄不一致时,即认为该指针失效。 + +[TCC RISC-V Compiler runs in the Web Browser (thanks to Zig Compiler)](https://lupyuen.codeberg.page/articles/tcc.html) +[TCC](https://github.com/sellicott/tcc-riscv32) 是一个 64 位 RISC-V +的编译器,作者在这篇文章里利用 Zig 把它编译成 WebAssembly +放到浏览器里执行。其中的难点在于 TCC 会调用 Posix +的一些函数,比如:fopen、fprintf、strncpy、malloc 等,但是这些在 +WebAssembly +里是没有的,因此需要[自己实现](https://github.com/lupyuen/tcc-riscv32-wasm/blob/main/zig/tcc-wasm.zig#L447-L774),不过幸好 +Zig 社区内已经有不少 libc 的实现了: + +- [marler8997/ziglibc](https://github.com/marler8997/ziglibc) +- [ZigEmbeddedGroup/foundation-libc](https://github.com/ZigEmbeddedGroup/foundation-libc),A + libc implementation written in Zig that is designed to be used with + freestanding targets. + +[Building the DirectX shader compiler better than Microsoft?](https://devlog.hexops.com/2024/building-the-directx-shader-compiler-better-than-microsoft/) + +[Porting Zig to NetBSD](http://coypu.sdf.org/porting-zig.html) + +[Sig Engineering - Part 2 - Progress on AccountsDB & more](https://blog.syndica.io/sig-engineering-part-2-accountsdb-more/) +Syndica 公司的 Sig,这是一款用 Zig 编写的、专注于 RPS 的 Solana +验证器客户端。在这篇文章里,他们分析了如何优化 HashMap +的性能,而且实现了一个基于本地磁盘的 Allocator。而且他们还在招聘 Zig +工程师: + +- [Senior Software Engineer (Zig/C/Rust) @ + Syndica](https://jobs.ashbyhq.com/syndica/15ab4e32-0f32-41a0-b8b0-16b6518158e9) + +# [项目/工具]($section.id('projects-tools')) + +[semickolon/kirei](https://github.com/semickolon/kirei) +🌸 The prettiest keyboard software + +[Dok8tavo/Interfacil](https://github.com/Dok8tavo/Interfacil/) +Interfacil is a Zig package for making and using interfaces easily in +Zig. + +[kamlesh-nb/azure-sdk-for-zig](https://github.com/kamlesh-nb/azure-sdk-for-zig) +Azure Sdk for Zig - Experimental + +[ringtailsoftware/zig-wasm-audio-framebuffer](https://github.com/ringtailsoftware/zig-wasm-audio-framebuffer) +Examples of integrating Zig and Wasm for audio and graphics on the web + +[cztomsik/tokamak](https://github.com/cztomsik/tokamak) +Server-side framework for Zig, relying heavily on dependency injection. + +[The-Z-Labs/cli4bofs](https://github.com/The-Z-Labs/cli4bofs) +Command line interface for (running) BOFs + +[nelipuu/zbind](https://github.com/nelipuu/zbind) +Zig-TypeScript binding generator 🟦 🦎 + +[sneekyfoxx/ziggy](https://github.com/sneekyfoxx/ziggy) +又又一个 Zig 版本管理工具 + +# [Zig 语言更新](https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2024-02-01..2023-03-01) diff --git a/content/monthly/202403.org b/content/monthly/202403.org deleted file mode 100644 index b26e461..0000000 --- a/content/monthly/202403.org +++ /dev/null @@ -1,200 +0,0 @@ -#+TITLE: 202403 | ziglang.cc 正式上线 -#+DATE: 2024-03-13T20:32:27+0800 -#+LASTMOD: 2024-05-02T22:14:30+0800 -* 重大事件 -#+begin_quote -https://ziglang.cc/ -#+end_quote -之前 ZigCC 所有项目都是托管在 GitHub 之上,网页基于 Pages 构建,域名自然也就是 github.io 的,虽然 GitHub 提供了很多利于开发者的服务,但过于依赖 GitHub 这种商业公司,还是不利于 ZigCC 的长远发展,域名是其中很重要一个,有了独立域名,网页托管选择就多了,比如 [[https://pages.cloudflare.com/][Cloudflare Pages]]。 - -另一个大家比较关心的问题就是 0.12 的发版,虽然 [[https://github.com/ziglang/zig/milestone/23][milestone]] 显示还剩 10 来个 open 的 issue,但是这只是个幌子,核心团队还是有可能随时 delay。不过从剩下的 issue 来分析,主要问题还剩两大类: -1. 构建系统完善 -2. 修复之前功能带来的回顾问题(regression 这个 tag) - -新功能看来是已经 ready 了,但这并不是说剩下的这些工具就好解决了,Andrew 在 [[https://rustacean-station.org/episode/andrew-kelley/][Zig with Andrew Kelley]] 这一期播客里提到的 [[https://zh.wikipedia.org/wiki/90-90%E6%B3%95%E5%88%99][90-90]] 理论很好的解释了这一点: -#+begin_quote -(开发软件时)前 90% 的代码要花费 90% 的开发时间,剩余的 10% 的代码要再花费 90% 的开发时间。 -#+end_quote - -当然,后面 ZigCC 也会紧密关注发布动态,有消息第一时间分享给大家。耐不住寂寞的朋友,可以先去刷刷 Zig 的 discord。 -* 观点/教程 -- [[https://github.com/ziglang/zig/pull/19208][Redesign How Autodoc Works]] :: Andrew 在这个 PR 里重构了现有的文档系统 Autodoc,之前的实现问题很多。比如: - - 很多功能重复的文件,最夸张的是 =lib/docs/ziglexer.js= ,它是用 JS 实现的 Zig 的解析器,其实 Zig 已经在标准库中暴露解析相关 API,通过 wasm 就可以调用 - - 功能更强,因为新设计方案不再处理 ZIR,而是直接处理源文件,这意味着它拥有100% 的信息,不需要向后拼凑任何东西。 - - sources.tar 文件经 HTTP 层解压后,直接进入 wasm 模块的内存。使用 std.tar 对 tar 文件进行解析,并对源文件进行就地解析,同时在哈希表中添加一些额外的计算。虽然可以通过 Worker 来加快解析速度,但单线程的解析速度已经非常快,因此这并不是非常有必要。 - - 快来体验最新的文档系统吧:https://ziglang.org/documentation/master/std/ -- [[https://notes.eatonphil.com/2024-03-15-zig-rust-and-other-languages.html][Zig, Rust, and other languages]] :: 老朋友 Phil Eaton 的文章,在这里他针对以下几点进行了语言对比: - - 内存管理。Zig 最大的问题是不支持 RAII,一个近似的概念是 arenas 分配器。 - - 标准库,主要是讨论标准库是否应该精简为主, =node_modules= 是业界经常提到的一个反面例子,一般支持精简的人会认为, - - 语言的 std 不容易出现 breaking changes,想 Python 里就有 urllib、urllib2、urllib3 这三个网络库, - 但是社区推荐的并不是这三个,而是 requests,这样 std 的位置就有些尴尬 - - Zig 目前的标准库算是中等大小,json、compress 压缩等功能都有 - - 显示分配,这算是 Zig 的强项,其他语言很少有支持这个的,因此作者在这建议增加一种类似 =must-not-allocate= 的注解, - 这样高级语言里,也可以保值某些操作不会有内存分配。 -- [[https://mtlynch.io/zig-extraneous-build/][Why does an extraneous build step make my Zig app 10x faster?]] :: 作者在这篇文章里分享了自己遇到的一个很有意思的问题, - 同一份代码,执行方式不同,竟然有不同的耗时。最小复现代码: - #+begin_src zig -// src/main.zig - -const std = @import("std"); - -pub fn countBytes(reader: anytype) !u32 { - var count: u32 = 0; - while (true) { - _ = reader.readByte() catch |err| switch (err) { - error.EndOfStream => { - return count; - }, - else => { - return err; - }, - }; - count += 1; - } -} - -pub fn main() !void { - var reader = std.io.getStdIn().reader(); - - var timer = try std.time.Timer.start(); - const start = timer.lap(); - const count = try countBytes(&reader); - const end = timer.read(); - const elapsed_micros = @as(f64, @floatFromInt(end - start)) / std.time.ns_per_us; - - const output = std.io.getStdOut().writer(); - try output.print("bytes: {}\n", .{count}); - try output.print("execution time: {d:.3}µs\n", .{elapsed_micros}); -} - #+end_src - 两种执行方式: - #+begin_src bash -$ echo '00010203040506070809' | xxd -r -p | zig build run -Doptimize=ReleaseFast -bytes: 10 -execution time: 13.549µs - -$ echo '00010203040506070809' | xxd -r -p | ./zig-out/bin/count-bytes -bytes: 10 -execution time: 162.195µs -#+end_src - 可以看到,通过 =zig build run= 的方式来执行时,耗时相比直接执行编译好的二进制要快 10 倍。 - 问题的关键在于 shell 的 pipeline 的执行机制,对于 =A | B= 这样一个简单的 pipeline,一般本能的会认为 B 只会在 A - 执行完后才开始执行,但是实际上它们是同时运行的,因此,在上面的例子里 =main= 函数的执行时间在 =zig build run= 方式下, - 其实执行的要晚一些,因为它需要先执行编译操作,因此造成了这个误差。 -- [[https://neurobug.com/posts/zig/billion/][One Bilion rows in zig]] :: 作者用[[https://1brc.dev/][ 1BRC]] 这个项目作为 Zig 的练手项目,里面用到了 [[https://github.com/mstange/samply][mstange/samply]] 这个 Profiler - 工具,还起来还比较实用。 -- [[https://matklad.github.io/2024/03/21/defer-patterns.html][Zig defer Patterns]] :: Matklad 最新的一篇文章,Ziggit [[https://ziggit.dev/t/zig-defer-patterns/3638/3][讨论链接]]。里面讲述了 defer 除了做资源回收外,其他的一些惯用法,里面有几个有趣的点: - #+begin_src zig -errdefer comptime unreachable - #+end_src - 文中称这个是 Zig 的巅峰用法😅, =errdefer unreachable= 还比较好理解,即在执行出错时,执行 unreachable ,加上 comptime 呢? - - 其实这是阻止 Zig 编译器生产错误处理的代码,即在编译时期保证下面的逻辑不会出错,确实用的很巧妙!一个简单的例子: - - #+begin_src zig -const std = @import("std"); - -test "errdeferWithUnreachable" { - errdefer comptime unreachable; - const i = try inc(1); - try std.testing.expectEqual(i, 2); -} - -fn inc(a: i8) !i8 { - if (a > 10) { - return error.TooLarge; - } - return a + 1; -} - #+end_src - 直接执行 =zig test= ,在编译时会报下面的错误: -#+begin_src shell -test.zig:4:23: error: reached unreachable code - errdefer comptime unreachable; -#+end_src -虽然 =a= 是个运行时的值,但是 =errdefer comptime unreachable= 不关心这个,只要 Zig 编译器开始生成 ErrorSet 相关代码, -编译就会报错,去掉上面的 if 代码块后,测试就可以正常执行。一个实际的例子: -- [[https://github.com/ziglang/zig/pull/19364/files][std.hash_map: fix pointer lock safety false positive by andrewrk · Pull Request #19364 · ziglang/zig]] -#+begin_src diff - assert(std.math.isPowerOfTwo(new_cap)); - - var map: Self = .{}; -- defer map.deinit(allocator); -- map.pointer_stability.lock(); - try map.allocate(allocator, new_cap); -+ errdefer comptime unreachable; -+ map.pointer_stability.lock(); - map.initMetadatas(); - map.available = @truncate((new_cap * max_load_percentage) / 100); - -@@6581,7 @@ pub fn HashMapUnmanaged( - self.size = 0; - self.pointer_stability = .{ .state = .unlocked }; - std.mem.swap(Self, self, &map); -+ map.deinit(allocator); - -+ -+test "getOrPut allocation failure" { -+ var map: std.StringHashMapUnmanaged(void) = .{}; -+ try testing.expectError(error.OutOfMemory, map.getOrPut(std.testing.failing_allocator, "hello")); -+} -#+end_src -可以看到, 这么修改后,就可以保证 =map.deinit(allocator)= 语句之前没有错误可能产生!读者可以细细品味一下这个用法。 - - 另一个小技巧是 errdefer 竟然支持错误捕获,即下面这种用法: - #+begin_src zig -const port = port: { - errdefer |err| std.log.err("failed to read the port number: {!}", .{err}); - var buf: [fmt.count("{}\n", .{maxInt(u16)})]u8 = undefined; - const len = try process.stdout.?.readAll(&buf); - break :port try fmt.parseInt(u16, buf[0 .. len -| 1], 10); -}; - #+end_src - - [[https://ziggit.dev/t/build-system-tricks/3531/1][Build system tricks]] :: 介绍了 zig build 的使用技巧,这些技巧有助于在确保方便地命名和布局构建步骤的同时,如何使用构建系统的每个部分。 - - [[https://blog.mjgrzymek.com/blog/zigwasm][Using Zig with WebAssembly]] :: 如何将 Zig 编译成 wasm,并传递复杂的参数。 - -* 项目/工具 -- [[https://github.com/xataio/pgzx][xataio/pgzx]] :: Create PostgreSQL extensions using Zig. 一个例子: - #+begin_src zig -const std = @import("std"); -const pgzx = @import("pgzx"); - -comptime { - pgzx.PG_MODULE_MAGIC(); - - pgzx.PG_FUNCTION_V1("char_count_zig", char_count_zig); -} - -fn char_count_zig(input_text: []const u8, target_char: []const u8) !u32 { - if (target_char.len > 1) { - return pgzx.elog.Error(@src(), "Target char is more than one byte", .{}); - } - - pgzx.elog.Info(@src(), "input_text: {s}\n", .{input_text}); - pgzx.elog.Info(@src(), "target_char: {s}\n", .{target_char}); - pgzx.elog.Info(@src(), "Target char len: {}\n", .{target_char.len}); - - var count: u32 = 0; - for (input_text) |char| { - if (char == target_char[0]) { - count += 1; - } - } - return count; -} - #+end_src - -- [[https://github.com/NoelJacob/zman][Manage Zig installations]] :: 又又又叒一个 Zig 管理工具,Rust 开发。 - #+begin_src bash -zman default latest -zman default master -zman default 0.12.0 - #+end_src - -- [[https://github.com/mahdifrmz/qooil][mahdifrmz/qooil]] :: 用 Zig 语言编写的文件传输软件 -- [[https://github.com/timfayz/pretty][timfayz/pretty]] :: Pretty printer for arbitrary data structures in Zig -- [[https://github.com/liyu1981/zcmd.zig][liyu1981/zcmd.zig]] :: Zcmd is a single file lib to replace zig's std.childProcess.run with the ability of running pipeline like bash. -- [[https://github.com/zigcc/zig-milestone][zigcc/zig-milestone]] :: Zig milstone monitor - -* [[https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2024-02-01..2024-03-01][Zig 语言更新]] diff --git a/content/monthly/202403.smd b/content/monthly/202403.smd new file mode 100644 index 0000000..0114028 --- /dev/null +++ b/content/monthly/202403.smd @@ -0,0 +1,294 @@ +--- +.title = "202403 | ziglang.cc 正式上线", +.date = @date("2024-03-13T20:32:27+0800"), +.author = "ZigCC", +.layout = "monthly.shtml", +.draft = false, +--- + +# [重大事件]($section.id('major-events')) + +> + +之前 ZigCC 所有项目都是托管在 GitHub 之上,网页基于 Pages +构建,域名自然也就是 github.io 的,虽然 GitHub +提供了很多利于开发者的服务,但过于依赖 GitHub 这种商业公司,还是不利于 +ZigCC +的长远发展,域名是其中很重要一个,有了独立域名,网页托管选择就多了,比如 +[Cloudflare Pages](https://pages.cloudflare.com/)。 + +另一个大家比较关心的问题就是 0.12 的发版,虽然 +[milestone](https://github.com/ziglang/zig/milestone/23) 显示还剩 10 +来个 open 的 issue,但是这只是个幌子,核心团队还是有可能随时 +delay。不过从剩下的 issue 来分析,主要问题还剩两大类: + +1. 构建系统完善 +2. 修复之前功能带来的回顾问题(regression 这个 tag) + +新功能看来是已经 ready 了,但这并不是说剩下的这些工具就好解决了,Andrew +在 [Zig with Andrew +Kelley](https://rustacean-station.org/episode/andrew-kelley/) +这一期播客里提到的 +[90-90](https://zh.wikipedia.org/wiki/90-90%E6%B3%95%E5%88%99) +理论很好的解释了这一点: + +> (开发软件时)前 90% 的代码要花费 90% 的开发时间,剩余的 10% +> 的代码要再花费 90% 的开发时间。 + +当然,后面 ZigCC +也会紧密关注发布动态,有消息第一时间分享给大家。耐不住寂寞的朋友,可以先去刷刷 +Zig 的 discord。 + +# [观点/教程]($section.id('opinion-tutorial')) + +[Redesign How Autodoc Works](https://github.com/ziglang/zig/pull/19208) +Andrew 在这个 PR 里重构了现有的文档系统 +Autodoc,之前的实现问题很多。比如: + +- 很多功能重复的文件,最夸张的是 `lib/docs/ziglexer.js` ,它是用 JS + 实现的 Zig 的解析器,其实 Zig 已经在标准库中暴露解析相关 API,通过 + wasm 就可以调用 + +- 功能更强,因为新设计方案不再处理 + ZIR,而是直接处理源文件,这意味着它拥有100% + 的信息,不需要向后拼凑任何东西。 + +- sources.tar 文件经 HTTP 层解压后,直接进入 wasm 模块的内存。使用 + std.tar 对 tar + 文件进行解析,并对源文件进行就地解析,同时在哈希表中添加一些额外的计算。虽然可以通过 + Worker + 来加快解析速度,但单线程的解析速度已经非常快,因此这并不是非常有必要。 + + 快来体验最新的文档系统吧:https://ziglang.org/documentation/master/std/ + +[Zig, Rust, and other languages](https://notes.eatonphil.com/2024-03-15-zig-rust-and-other-languages.html) +老朋友 Phil Eaton 的文章,在这里他针对以下几点进行了语言对比: + +- 内存管理。Zig 最大的问题是不支持 RAII,一个近似的概念是 arenas + 分配器。 +- 标准库,主要是讨论标准库是否应该精简为主, `node_modules` + 是业界经常提到的一个反面例子,一般支持精简的人会认为, + - 语言的 std 不容易出现 breaking changes,想 Python 里就有 + urllib、urllib2、urllib3 这三个网络库, + 但是社区推荐的并不是这三个,而是 requests,这样 std 的位置就有些尴尬 + - Zig 目前的标准库算是中等大小,json、compress 压缩等功能都有 +- 显示分配,这算是 Zig + 的强项,其他语言很少有支持这个的,因此作者在这建议增加一种类似 + `must-not-allocate` 的注解, + 这样高级语言里,也可以保值某些操作不会有内存分配。 + +[Why does an extraneous build step make my Zig app 10x faster?](https://mtlynch.io/zig-extraneous-build/) +作者在这篇文章里分享了自己遇到的一个很有意思的问题, +同一份代码,执行方式不同,竟然有不同的耗时。最小复现代码: + +``` zig +// src/main.zig + +const std = @import("std"); + +pub fn countBytes(reader: anytype) !u32 { + var count: u32 = 0; + while (true) { + _ = reader.readByte() catch |err| switch (err) { + error.EndOfStream => { + return count; + }, + else => { + return err; + }, + }; + count += 1; + } +} + +pub fn main() !void { + var reader = std.io.getStdIn().reader(); + + var timer = try std.time.Timer.start(); + const start = timer.lap(); + const count = try countBytes(&reader); + const end = timer.read(); + const elapsed_micros = @as(f64, @floatFromInt(end - start)) / std.time.ns_per_us; + + const output = std.io.getStdOut().writer(); + try output.print("bytes: {}\n", .{count}); + try output.print("execution time: {d:.3}µs\n", .{elapsed_micros}); +} +``` + +两种执行方式: + +``` bash +$ echo '00010203040506070809' | xxd -r -p | zig build run -Doptimize=ReleaseFast +bytes: 10 +execution time: 13.549µs + +$ echo '00010203040506070809' | xxd -r -p | ./zig-out/bin/count-bytes +bytes: 10 +execution time: 162.195µs +``` + +可以看到,通过 `zig build run` +的方式来执行时,耗时相比直接执行编译好的二进制要快 10 倍。 +问题的关键在于 shell 的 pipeline 的执行机制,对于 `A | B` 这样一个简单的 +pipeline,一般本能的会认为 B 只会在 A +执行完后才开始执行,但是实际上它们是同时运行的,因此,在上面的例子里 +`main` 函数的执行时间在 `zig build run` 方式下, +其实执行的要晚一些,因为它需要先执行编译操作,因此造成了这个误差。 + +[One Bilion rows in zig](https://neurobug.com/posts/zig/billion/) +作者用[ 1BRC](https://1brc.dev/) 这个项目作为 Zig 的练手项目,里面用到了 +[mstange/samply](https://github.com/mstange/samply) 这个 Profiler +工具,还起来还比较实用。 + +[Zig defer Patterns](https://matklad.github.io/2024/03/21/defer-patterns.html) +Matklad 最新的一篇文章,Ziggit +[讨论链接](https://ziggit.dev/t/zig-defer-patterns/3638/3)。里面讲述了 +defer 除了做资源回收外,其他的一些惯用法,里面有几个有趣的点: + +``` zig +errdefer comptime unreachable +``` + +文中称这个是 Zig 的巅峰用法😅, `errdefer unreachable` +还比较好理解,即在执行出错时,执行 unreachable ,加上 comptime 呢? + +其实这是阻止 Zig +编译器生产错误处理的代码,即在编译时期保证下面的逻辑不会出错,确实用的很巧妙!一个简单的例子: + +``` zig +const std = @import("std"); + +test "errdeferWithUnreachable" { + errdefer comptime unreachable; + const i = try inc(1); + try std.testing.expectEqual(i, 2); +} + +fn inc(a: i8) !i8 { + if (a > 10) { + return error.TooLarge; + } + return a + 1; +} +``` + +直接执行 `zig test` ,在编译时会报下面的错误: + +``` bash +test.zig:4:23: error: reached unreachable code + errdefer comptime unreachable; +``` + +虽然 `a` 是个运行时的值,但是 `errdefer comptime unreachable` +不关心这个,只要 Zig 编译器开始生成 ErrorSet 相关代码, +编译就会报错,去掉上面的 if +代码块后,测试就可以正常执行。一个实际的例子: + +- [std.hashmap: fix pointer lock safety false positive by + andrewrk · Pull Request \#19364 · + ziglang/zig](https://github.com/ziglang/zig/pull/19364/files) + +``` diff + assert(std.math.isPowerOfTwo(new_cap)); + + var map: Self = .{}; +- defer map.deinit(allocator); +- map.pointer_stability.lock(); + try map.allocate(allocator, new_cap); ++ errdefer comptime unreachable; ++ map.pointer_stability.lock(); + map.initMetadatas(); + map.available = @truncate((new_cap * max_load_percentage) / 100); + +@@6581,7 @@ pub fn HashMapUnmanaged( + self.size = 0; + self.pointer_stability = .{ .state = .unlocked }; + std.mem.swap(Self, self, &map); ++ map.deinit(allocator); + ++ ++test "getOrPut allocation failure" { ++ var map: std.StringHashMapUnmanaged(void) = .{}; ++ try testing.expectError(error.OutOfMemory, map.getOrPut(std.testing.failing_allocator, "hello")); ++} +``` + +可以看到, 这么修改后,就可以保证 `map.deinit(allocator)` +语句之前没有错误可能产生!读者可以细细品味一下这个用法。 + +另一个小技巧是 errdefer 竟然支持错误捕获,即下面这种用法: + +``` zig +const port = port: { + errdefer |err| std.log.err("failed to read the port number: {!}", .{err}); + var buf: [fmt.count("{}\n", .{maxInt(u16)})]u8 = undefined; + const len = try process.stdout.?.readAll(&buf); + break :port try fmt.parseInt(u16, buf[0 .. len -| 1], 10); +}; +``` + +[Build system tricks](https://ziggit.dev/t/build-system-tricks/3531/1) +介绍了 zig build +的使用技巧,这些技巧有助于在确保方便地命名和布局构建步骤的同时,如何使用构建系统的每个部分。 + +[Using Zig with WebAssembly](https://blog.mjgrzymek.com/blog/zigwasm) +如何将 Zig 编译成 wasm,并传递复杂的参数。 + +# [项目/工具]($section.id('projects-tools')) + +[xataio/pgzx](https://github.com/xataio/pgzx) +Create PostgreSQL extensions using Zig. 一个例子: + +``` zig +const std = @import("std"); +const pgzx = @import("pgzx"); + +comptime { + pgzx.PG_MODULE_MAGIC(); + + pgzx.PG_FUNCTION_V1("char_count_zig", char_count_zig); +} + +fn char_count_zig(input_text: []const u8, target_char: []const u8) !u32 { + if (target_char.len > 1) { + return pgzx.elog.Error(@src(), "Target char is more than one byte", .{}); + } + + pgzx.elog.Info(@src(), "input_text: {s}\n", .{input_text}); + pgzx.elog.Info(@src(), "target_char: {s}\n", .{target_char}); + pgzx.elog.Info(@src(), "Target char len: {}\n", .{target_char.len}); + + var count: u32 = 0; + for (input_text) |char| { + if (char == target_char[0]) { + count += 1; + } + } + return count; +} +``` + +[Manage Zig installations](https://github.com/NoelJacob/zman) +又又又叒一个 Zig 管理工具,Rust 开发。 + +``` bash +zman default latest +zman default master +zman default 0.12.0 +``` + +[mahdifrmz/qooil](https://github.com/mahdifrmz/qooil) +用 Zig 语言编写的文件传输软件 + +[timfayz/pretty](https://github.com/timfayz/pretty) +Pretty printer for arbitrary data structures in Zig + +[liyu1981/zcmd.zig](https://github.com/liyu1981/zcmd.zig) +Zcmd is a single file lib to replace zig's std.childProcess.run with the +ability of running pipeline like bash. + +[zigcc/zig-milestone](https://github.com/zigcc/zig-milestone) +Zig milstone monitor + +# [Zig 语言更新](https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2024-02-01..2024-03-01) diff --git a/content/monthly/202404.org b/content/monthly/202404.org deleted file mode 100644 index 20dc3e0..0000000 --- a/content/monthly/202404.org +++ /dev/null @@ -1,76 +0,0 @@ -#+TITLE: 202404 | Zig 0.12.0 正式释出 -#+DATE: 2024-04-18T21:59:49+0800 -#+LASTMOD: 2024-05-03T09:01:56+0800 -* 重大事件 -千呼万唤的 0.12.0 版本终于 2024-04-20 正式释出了!这次版本历时 8 个月,有 268 位贡献者,一共进行了 3688 次提交!社区内的一些讨论:[[https://news.ycombinator.com/item?id=40096176][Hacker News]]、[[https://lobste.rs/s/fa4svu][Lobsters]]。 -这是它的 [[https://ziglang.org/download/0.12.0/release-notes.html][Release notes]]。ZigCC 对这个文档进行了翻译、整理,方便大家阅读: -- [[https://course.ziglang.cc/update/upgrade-0.12.0][0.12.0 升级指南]] -- [[https://course.ziglang.cc/update/0.12.0-description][0.12.0 版本说明]] - -并且还在 2024-04-27 举行了一次线上的 meetup 来庆祝这次发布,这是会议的总结:[[https://ziglang.cc/news/2024/04/27/release-party-review/][0.12.0 Release Party 回顾]]。 - -0.12.0 这个版本,对用户来说,最重大的变更就是构建系统的稳定了,这对于 Zig 生态的发展是十分关键的一步,试想一个项目用到的依赖之间版本不兼容, -这是十分痛苦的事情,毫无疑问这是阻碍 Zig 生态发生的绊脚石,没有之一。好在这一切都在 0.12 这个版本解决了,用户可以基于 Step -构成的有向无环图来编译自己的项目,不需要再折腾 CMake、Makefile、Vcpkg、Git submodule 等工具,所有的依赖使用 zon 来管理即可。 -读者如果对 Zig 构建系统还不熟悉,可以参考: -- 官方文档:[[https://ziglang.org/learn/build-system/][Zig Build System]] -- Zig 升级: [[https://course.ziglang.cc/engineering/build-system][构建系统]] - -期待一年后 Zig 的生态! -* 观点/教程 -- [[https://github.com/zigcc/forum/issues/112][Zig 中任意精度整数用途与实现]] :: 由于 CPU 在访问内存时,一般都会有对齐的要求,对于这种非常规的数字,在内存中的地址会是怎样的呢?可以做一个简单的实验: - - #+begin_src zig -const std = @import("std"); - -const Foo = packed struct { - a: u3, - b: u2, -}; - -pub fn main() !void { - const vs = [_]u3{ 1, 2, 3 }; - for (&vs) |*b| { - std.debug.print("{p}-{b}\n", .{ b, b.* }); - } - - std.debug.print("U3 size: {d}\n", .{@sizeOf(u3)}); - std.debug.print("Foo size: {d}\n", .{@sizeOf(Foo)}); - - const foos = [_]Foo{ - .{ .a = 1, .b = 3 }, - }; - - std.debug.print("foo as bytes: {b}\n", .{std.mem.sliceAsBytes(&foos)}); - - for (foos) |b| { - std.debug.print("{any}-{any}\n", .{ &b.a, &b.b }); - } -} - #+end_src - 输出: - #+begin_src bash -u3@104d11a2c-1 -u3@104d11a2d-10 -u3@104d11a2e-11 -U3 size: 1 -Foo size: 1 -foo as bytes: { 11001 } -u3@16b196367-u2@16b196367 - #+end_src - - 通过前三个输出可以知道,每个 u3 实际占用一个字节,但当用在 packed 结构中,就会变成 3 个 bit。其中的 11001 就是字段 a b 混合后的值,且 a 是三位,b 是高两位。 -- [[https://procmarco.com/blog/learnings-from-building-a-db-in-zig/][Learnings From Building a DB in Zig]] :: 作者分享了在一次 3 天的 Hackthon 中,使用 Zig 开发一个数据库的经历。 -- [[https://zig.news/michalsieron/buildzigzon-dependency-hashes-47kj][build.zig.zon dependency hashes]] :: 讲解了 zon 中依赖的 hash 是怎么计算出来的 -- [[https://zig.news/liyu1981/play-with-new-comptime-var-rule-of-zig-0120-333k][play with new comptime var rule of zig 0.12.0]] :: -- [[https://zig.news/inspectorboat/to-simd-and-beyond-optimizing-a-simple-comparison-routine-1jkf][To SIMD and beyond: Optimizing a simple comparison routine]] :: 作者在这里循序渐进的介绍了几种数字比较的技巧,从基本的方案,到 Vector,到最后利用 bit 的特点,来逐步优化,并用 godbolt 查看生成的汇编代码,是一篇不错的文章。 -- [[https://www.reddit.com/r/Zig/comments/1cc1x2v/documentation_takes_another_step_backwards/][Documentation takes another step backwards : r/Zig]] :: 一个 Reddit 用户对文档的抱怨 -* 项目/工具 -- [[https://github.com/rofrol/zig-companies][rofrol/zig-companies]] :: A list of companies using Zig in production. -- [[https://github.com/akarpovskii/tuile][akarpovskii/tuile]] :: A Text UI library for Zig -- [[https://codeberg.org/mntnmntn/zenith][mntnmntn/zenith]] :: A very minimal text editor in Zig,支持 0.12.0 版本 -- [[https://github.com/chung-leong/zigar][chung-leong/zigar]] :: Enable the use of Zig code in JavaScript project -- [[https://github.com/jnordwick/zig-string][jnordwick/zig-string]] :: Zig string library that includes small string optimization on the stack -- [[https://github.com/FalsePattern/ZigBrains][FalsePattern/ZigBrains]] :: Yet another zig language plugin for intellij - -* [[https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2024-04-01..2024-05-01][Zig 语言更新]] diff --git a/content/monthly/202404.smd b/content/monthly/202404.smd new file mode 100644 index 0000000..098f207 --- /dev/null +++ b/content/monthly/202404.smd @@ -0,0 +1,127 @@ +--- +.title = "202404 | Zig 0.12.0 正式释出", +.date = @date("2024-04-18T21:59:49+0800"), +.author = "ZigCC", +.layout = "monthly.shtml", +.draft = false, +--- + +# [重大事件]($section.id('major-events')) + +千呼万唤的 0.12.0 版本终于 2024-04-20 正式释出了!这次版本历时 8 +个月,有 268 位贡献者,一共进行了 3688 次提交!社区内的一些讨论:[Hacker +News](https://news.ycombinator.com/item?id=40096176)、[Lobsters](https://lobste.rs/s/fa4svu)。 +这是它的 [Release +notes](https://ziglang.org/download/0.12.0/release-notes.html)。ZigCC +对这个文档进行了翻译、整理,方便大家阅读: + +- [0.12.0 升级指南](https://course.ziglang.cc/update/upgrade-0.12.0) +- [0.12.0 版本说明](https://course.ziglang.cc/update/0.12.0-description) + +并且还在 2024-04-27 举行了一次线上的 meetup +来庆祝这次发布,这是会议的总结:[0.12.0 Release Party +回顾](https://ziglang.cc/news/2024/04/27/release-party-review/)。 + +0.12.0 这个版本,对用户来说,最重大的变更就是构建系统的稳定了,这对于 +Zig 生态的发展是十分关键的一步,试想一个项目用到的依赖之间版本不兼容, +这是十分痛苦的事情,毫无疑问这是阻碍 Zig +生态发生的绊脚石,没有之一。好在这一切都在 0.12 +这个版本解决了,用户可以基于 Step +构成的有向无环图来编译自己的项目,不需要再折腾 +CMake、Makefile、Vcpkg、Git submodule 等工具,所有的依赖使用 zon +来管理即可。 读者如果对 Zig 构建系统还不熟悉,可以参考: + +- 官方文档:[Zig Build System](https://ziglang.org/learn/build-system/) +- Zig 升级: + [构建系统](https://course.ziglang.cc/engineering/build-system) + +期待一年后 Zig 的生态! + +# [观点/教程]($section.id('opinion-tutorial')) + +[Zig 中任意精度整数用途与实现](https://github.com/zigcc/forum/issues/112) +由于 CPU +在访问内存时,一般都会有对齐的要求,对于这种非常规的数字,在内存中的地址会是怎样的呢?可以做一个简单的实验: + +``` zig +const std = @import("std"); + +const Foo = packed struct { + a: u3, + b: u2, +}; + +pub fn main() !void { + const vs = [_]u3{ 1, 2, 3 }; + for (&vs) |*b| { + std.debug.print("{p}-{b}\n", .{ b, b.* }); + } + + std.debug.print("U3 size: {d}\n", .{@sizeOf(u3)}); + std.debug.print("Foo size: {d}\n", .{@sizeOf(Foo)}); + + const foos = [_]Foo{ + .{ .a = 1, .b = 3 }, + }; + + std.debug.print("foo as bytes: {b}\n", .{std.mem.sliceAsBytes(&foos)}); + + for (foos) |b| { + std.debug.print("{any}-{any}\n", .{ &b.a, &b.b }); + } +} +``` + +输出: + +``` bash +u3@104d11a2c-1 +u3@104d11a2d-10 +u3@104d11a2e-11 +U3 size: 1 +Foo size: 1 +foo as bytes: { 11001 } +u3@16b196367-u2@16b196367 +``` + +通过前三个输出可以知道,每个 u3 实际占用一个字节,但当用在 packed +结构中,就会变成 3 个 bit。其中的 11001 就是字段 a b 混合后的值,且 a +是三位,b 是高两位。 + +[Learnings From Building a DB in Zig](https://procmarco.com/blog/learnings-from-building-a-db-in-zig/) +作者分享了在一次 3 天的 Hackthon 中,使用 Zig 开发一个数据库的经历。 + +[build.zig.zon dependency hashes](https://zig.news/michalsieron/buildzigzon-dependency-hashes-47kj) +讲解了 zon 中依赖的 hash 是怎么计算出来的 + +[play with new comptime var rule of zig 0.12.0](https://zig.news/liyu1981/play-with-new-comptime-var-rule-of-zig-0120-333k) + +[To SIMD and beyond: Optimizing a simple comparison routine](https://zig.news/inspectorboat/to-simd-and-beyond-optimizing-a-simple-comparison-routine-1jkf) +作者在这里循序渐进的介绍了几种数字比较的技巧,从基本的方案,到 +Vector,到最后利用 bit 的特点,来逐步优化,并用 godbolt +查看生成的汇编代码,是一篇不错的文章。 + +[Documentation takes another step backwards : r/Zig](https://www.reddit.com/r/Zig/comments/1cc1x2v/documentation_takes_another_step_backwards/) +一个 Reddit 用户对文档的抱怨 + +# [项目/工具]($section.id('projects-tools')) + +[rofrol/zig-companies](https://github.com/rofrol/zig-companies) +A list of companies using Zig in production. + +[akarpovskii/tuile](https://github.com/akarpovskii/tuile) +A Text UI library for Zig + +[mntnmntn/zenith](https://codeberg.org/mntnmntn/zenith) +A very minimal text editor in Zig,支持 0.12.0 版本 + +[chung-leong/zigar](https://github.com/chung-leong/zigar) +Enable the use of Zig code in JavaScript project + +[jnordwick/zig-string](https://github.com/jnordwick/zig-string) +Zig string library that includes small string optimization on the stack + +[FalsePattern/ZigBrains](https://github.com/FalsePattern/ZigBrains) +Yet another zig language plugin for intellij + +# [Zig 语言更新](https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2024-04-01..2024-05-01) diff --git a/content/monthly/202405.org b/content/monthly/202405.org deleted file mode 100644 index d8749a9..0000000 --- a/content/monthly/202405.org +++ /dev/null @@ -1,63 +0,0 @@ -#+TITLE: 202405 -#+DATE: 2024-06-02T22:18:59+0800 -#+LASTMOD: 2024-06-04T19:26:01+0800 - -* 观点/教程 -** [[https://arne.me/blog/thoughts-on-zig][Thoughts on Zig]] -又一篇 Zig 初学者的使用体验文档,如果你也在犹豫要不要学 Zig,这是个不错的经验参考。 -** [[https://www.reddit.com/r/Zig/comments/1ckstjv/im_sold_on_zigs_simplicity/][I'm sold on Zig's simplicity : r/Zig]] -一个具有资深经验开发者,在这里描述了自己选择业余项目语言的经历: - - Rust 越来越复杂,有种发展成 C++ 的趋势 - - C++ 新版本的特性(比如 module)LSP 支持的不够好,而且历史包袱严重 - - C 缺少元编程,并且没有命名空间 - - 最后从 Andrew 的一个播客了解到 Zig,经过自己尝试,发现了 Zig 没有辜负他的期望,尽管是第一次写 Zig,但基本上没有什么难度, - 每次遇到问题,仔细想几分钟就差不多有答案了。下面是他罗列的 Zig 的一些优势: - - 十分简洁,import 返回的是一个 struct,和其他变量一样使用 - - 与 C 无缝交换, - - 具有 Result 效果的错误处理 - - 唯一缺失的就是『接口』,但这一点并不是很关键,就像在 C里也没有,但是 C 可以做任何事 -* [[https://andrewkelley.me/post/zig-new-cli-progress-bar-explained.html][Zig's New CLI Progress Bar Explained]] -Andrew 的一篇文章,讲述了在最新版的 Zig 中,对进度条的改进实现,现在的进度展示更加友好。 - -实现的难点在于在多线程环境下,如何保证高性能,文章中大致讲述了其实现: -- 首先通过预先分配好需要使用的结构,保证后续无需在进行 heap 申请 -- 通过 atomic 操作来实现一个无锁的 freelist,用于申请、释放 Node -* [[https://www.openmymind.net/Writing-a-Task-Scheduler-in-Zig/][Writing a task scheduler in Zig]] -Openmymind 作者的又一力作,通过编写一个任务调度器,讲述了多线程编程的基本要领: -- 共享的数据要加锁 -- 条件变量要和锁一起使用,会有[[https://en.wikipedia.org/wiki/Spurious_wakeup][虚假唤醒]]的问题,因此在被唤醒时,需要重新检查状态是否正确。 - #+begin_src zig -fn run(self: *Self) void { - while (true) { - self.mutex.lock(); - while (self.queue.peek() == null) { - self.cond.wait(&self.mutex); - } - // TODO - } -} - #+end_src - 它会在 wait 前释放锁,在 wait 返回时先加锁,类似下面的实现: - #+begin_src zig -fn wait(c: *std.Thread.Condition, mutex: *std.Thread.Mutex) void { - // do some setup - // ... - - mutex.unlock(); - - // whatever happens, we'll always return with this locked - defer mutex.lock(); - - // wait for signal - // or timeout if calling timedWait - // ... -} - #+end_src -* 项目/工具 -- [[https://github.com/chung-leong/zigar][zigar]] :: Enable the use of Zig code in JavaScript project。它可以让你直接在 JS 中调用 zig 代码,背后原理是编译成了 wasm 实现的。 -- [[https://github.com/srijan-paul/nez][srijan-paul/nez]] :: An emulator for the NES console. -- [[https://github.com/deckarep/ziglang-set][deckarep/ziglang-set]] :: A generic and general purpose Set implementation for the Zig language -- [[https://github.com/akarpovskii/tuile][akarpovskii/tuile]] :: A Text UI library for Zig - -* [[https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2024-05-01..2024-06-01][Zig 语言更新]] diff --git a/content/monthly/202405.smd b/content/monthly/202405.smd new file mode 100644 index 0000000..a64929a --- /dev/null +++ b/content/monthly/202405.smd @@ -0,0 +1,99 @@ +--- +.title = "202405", +.date = @date("2024-06-02T22:18:59+0800"), +.author = "ZigCC", +.layout = "monthly.shtml", +.draft = false, +--- + +# [观点/教程]($section.id('opinion-tutorial')) + +# [Thoughts on Zig](https://arne.me/blog/thoughts-on-zig) + +又一篇 Zig 初学者的使用体验文档,如果你也在犹豫要不要学 +Zig,这是个不错的经验参考。 + +# [I'm sold on Zig's simplicity : r/Zig]($section.id('im-sold-on-zigs-simplicity-r-zig')) + +一个具有资深经验开发者,在这里描述了自己选择业余项目语言的经历: + +- Rust 越来越复杂,有种发展成 C++ 的趋势 +- C++ 新版本的特性(比如 module)LSP 支持的不够好,而且历史包袱严重 +- C 缺少元编程,并且没有命名空间 + +最后从 Andrew 的一个播客了解到 Zig,经过自己尝试,发现了 Zig +没有辜负他的期望,尽管是第一次写 Zig,但基本上没有什么难度, +每次遇到问题,仔细想几分钟就差不多有答案了。下面是他罗列的 Zig +的一些优势: + +- 十分简洁,import 返回的是一个 struct,和其他变量一样使用 +- 与 C 无缝交换, +- 具有 Result 效果的错误处理 +- 唯一缺失的就是『接口』,但这一点并不是很关键,就像在 C里也没有,但是 C + 可以做任何事 + +# [Zig's New CLI Progress Bar Explained]($section.id('zigs-new-cli-progress-bar-explained')) + +Andrew 的一篇文章,讲述了在最新版的 Zig +中,对进度条的改进实现,现在的进度展示更加友好。 + +实现的难点在于在多线程环境下,如何保证高性能,文章中大致讲述了其实现: + +- 首先通过预先分配好需要使用的结构,保证后续无需在进行 heap 申请 +- 通过 atomic 操作来实现一个无锁的 freelist,用于申请、释放 Node + +# [Writing a task scheduler in Zig](https://www.openmymind.net/Writing-a-Task-Scheduler-in-Zig/) + +Openmymind +作者的又一力作,通过编写一个任务调度器,讲述了多线程编程的基本要领: + +- 共享的数据要加锁 + +- 条件变量要和锁一起使用,会有[虚假唤醒](https://en.wikipedia.org/wiki/Spurious_wakeup)的问题,因此在被唤醒时,需要重新检查状态是否正确。 + + ``` zig + fn run(self: *Self) void { + while (true) { + self.mutex.lock(); + while (self.queue.peek() == null) { + self.cond.wait(&self.mutex); + } + // TODO + } + } + ``` + + 它会在 wait 前释放锁,在 wait 返回时先加锁,类似下面的实现: + + ``` zig + fn wait(c: *std.Thread.Condition, mutex: *std.Thread.Mutex) void { + // do some setup + // ... + + mutex.unlock(); + + // whatever happens, we'll always return with this locked + defer mutex.lock(); + + // wait for signal + // or timeout if calling timedWait + // ... + } + ``` + +# [项目/工具]($section.id('projects-tools')) + +[zigar](https://github.com/chung-leong/zigar) +Enable the use of Zig code in JavaScript project。它可以让你直接在 JS +中调用 zig 代码,背后原理是编译成了 wasm 实现的。 + +[srijan-paul/nez](https://github.com/srijan-paul/nez) +An emulator for the NES console. + +[deckarep/ziglang-set](https://github.com/deckarep/ziglang-set) +A generic and general purpose Set implementation for the Zig language + +[akarpovskii/tuile](https://github.com/akarpovskii/tuile) +A Text UI library for Zig + +# [Zig 语言更新](https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2024-05-01..2024-06-01) diff --git a/content/monthly/202406.org b/content/monthly/202406.org deleted file mode 100644 index 806c67e..0000000 --- a/content/monthly/202406.org +++ /dev/null @@ -1,126 +0,0 @@ -#+TITLE: 202406 | 0.13 来了 -#+DATE: 2024-07-01T20:34:51+0800 -#+LASTMOD: 2024-07-01T21:51:32+0800 -* 重大事件 -2024-06-07,0.13.0 发布,历时不足 2 个月,有 73 位贡献者,一共进行了 415 次提交! -这是一个相对较短的发布周期,主要原因是工具链升级,例如升级到 [[https://ziglang.org/download/0.13.0/release-notes.html#LLVM-18][LLVM 18]]。 - -一个比较大的 Breaking changes 是 =ComptimeStringMap= 被重命名为了 =StaticStringMap= , -使用方式也发生了变化,更多细节可参考:[[https://github.com/ziglang/zig/pull/19682][#19682]] -#+begin_src zig -const map = std.StaticStringMap(T).initComptime(kvs_list); -#+end_src - -0.14.0 发布周期的主题将是编译速度。将在 0.14.0 发布周期中努力实现一些即将到来的里程碑: -- 使 x86 后端成为调试模式的默认后端。 -- COFF 的链接器支持。消除对 LLVM [[https://lld.llvm.org/][LLD]] 的依赖。 -- 启用增量编译以实现快速重建。 -- 将并发引入语义分析,进一步提高编译速度。 - -* 观点/教程 -** [[https://www.openmymind.net/Leveraging-Zigs-Allocators/][Leveraging Zig's Allocators]] -老朋友 openmymind 的又一篇好文章:如何利用 Zig 的 Allocator 来实现请求级别的内存分配。 -Zig Allocator 的最佳应用。[[/post/2024/06/16/leveraging-zig-allocator/][这里]]它的中文翻译。 -#+begin_src zig -const FallbackAllocator = struct { - primary: Allocator, - fallback: Allocator, - fba: *std.heap.FixedBufferAllocator, - - pub fn allocator(self: *FallbackAllocator) Allocator { - return .{ - .ptr = self, - .vtable = &.{.alloc = alloc, .resize = resize, .free = free}, - }; - } - - fn alloc(ctx: *anyopaque, len: usize, ptr_align: u8, ra: usize) ?[*]u8 { - const self: *FallbackAllocator = @ptrCast(@alignCast(ctx)); - return self.primary.rawAlloc(len, ptr_align, ra) - orelse self.fallback.rawAlloc(len, ptr_align, ra); - } - - fn resize(ctx: *anyopaque, buf: []u8, buf_align: u8, new_len: usize, ra: usize) bool { - const self: *FallbackAllocator = @ptrCast(@alignCast(ctx)); - if (self.fba.ownsPtr(buf.ptr)) { - if (self.primary.rawResize(buf, buf_align, new_len, ra)) { - return true; - } - } - return self.fallback.rawResize(buf, buf_align, new_len, ra); - } - - fn free(_: *anyopaque, _: []u8, _: u8, _: usize) void { - // we noop this since, in our specific case, we know - // the fallback is an arena, which won't free individual items - } -}; - -fn run(worker: *Worker) void { - const allocator = worker.server.allocator; - - // this is the underlying memory for our FixedBufferAllocator - const buf = try allocator.alloc(u8, 8192); - defer allocator.free(buf); - - var fba = std.heap.FixedBufferAllocator.init(buf); - - while (queue.pop()) |conn| { - defer fba.reset(); - - var arena = std.heap.ArenaAllocator.init(allocator); - defer arena.deinit(); - - var fallback = FallbackAllocator{ - .fba = &fba, - .primary = fba.allocator(), - .fallback = arena.allocator(), - }; - - const action = worker.route(conn.req.url); - action(fallback.allocator(), conn.req, conn.res) catch { // TODO: 500 }; - worker.write(conn.res); - } -} -#+end_src -** [[https://ludwigabap.bearblog.dev/zig-vs-rust-at-work-the-choice-we-made/][On Zig vs Rust at work and the choice we made]] -- https://news.ycombinator.com/item?id=40735667 -这篇文章作者描述了所在公司在改造老 C/C++ 项目时,为什么选择了 Zig 而不是 Rust。 -重写的项目运行在多个平台上(Web、移动端、VR 设备),因此最靠谱的方案就是暴露一个 C API,然后通过 FFI 来调用。在做决策时,重点关注以下两点: -- 新语言与 C 的交互性 -- 工程师扩展代码库的难易程度(如招聘和维护) - -下面是 Zig VS Rust 的优势: -| | Rust | Zig | -|--------+----------------------+----------------------------------------| -| 成熟度 | 更流行、稳定;使用范围更广 | | -| 包管理 | Cargo 业界领先 | 比 Makefile 好用 | -| 安全 | 内存安全 | | -| SIMD | nightly 支持 | 通过 Vector 类型支持 | -| C 交互性 | 生态丰富 | 编译器本身就是 C 编译器,这样就可以逐步重写项目 | - -如果只是根据上面的比较,貌似还看不出选择 Zig 的动机,因此作者在最后提到: -#+begin_quote -Zig 大大减少了移植现有代码库和确保所有平台兼容性所需的时间和精力。我们的团队无法相信 Rust 能让这一切变得如此简单。 -#+end_quote -相信这也是大部分人选择 Zig 的原因:简洁、高效。 -** [[https://ludwigabap.bearblog.dev/packing-some-zig-before-going-for-the-countryside/][Packing some Zig before going for the countryside]] -作者列举的一些 Zig 学习资料、常用类库。该作者的另一篇文章也有不少资料:[[https://ludwigabap.bearblog.dev/2024-collection-of-zig-resources/][2024 Collection of Zig resources]] -** [[https://turso.tech/blog/why-i-am-not-yet-ready-to-switch-to-zig-from-rust][Why I am not yet ready to switch to Zig from Rust]] -Turso CTO 的一篇文章,他本身是个资深 C 程序员,而且也比较喜欢 C,但 C 不是一门安全的语言,因此通过 Rust,作者可以避免 -写出 SIGSEGVS 的代码,尽管 Rust 是门复杂的语言,但是因为它有完善的生态(有大公司如微软、谷歌等做背书)、已经内存安全等特点, -已经是作者系统编程的首选。 - -对于 Zig,尽管作者也表达了喜欢,但由于 Zig 的生态不完善,没有足够多的学习资料,因此作者觉得目前阶段选择 Zig 并不会带来 -工作上生产力的提高。这一点说的无可厚非,试想一下,如果一个项目所有的依赖都需要自己做,工作效率确实很难提上去。 - -但是笔者有一点不能理解,就是该作者觉得 comptime 不好用,相比之下,他更喜欢 C 里面的宏。comptime 就是为了 C 宏的不足 -而诞生的,社区普遍也觉得 comptime 是个新颖的设计,笔者也是第一次见到这个观点,只能说,萝卜青菜,各有所爱。 - -其他社区的一些讨论:[[https://lobste.rs/s/0mnhdx][Lobsters]]、[[https://news.ycombinator.com/item?id=40681862][Hacker News]] -* 项目/工具 -- [[https://github.com/malcolmstill/zware][malcolmstill/zware]] :: Zig WebAssembly Runtime Engine -- [[https://github.com/Cloudef/zig-aio][Cloudef/zig-aio]] :: io_uring like asynchronous API and coroutine powered IO tasks for zig - - -* [[https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2024-06-01..2024-07-01][Zig 语言更新]] diff --git a/content/monthly/202406.smd b/content/monthly/202406.smd new file mode 100644 index 0000000..0447060 --- /dev/null +++ b/content/monthly/202406.smd @@ -0,0 +1,169 @@ +--- +.title = "202406 | 0.13 来了", +.date = @date("2024-07-01T20:34:51+0800"), +.author = "ZigCC", +.layout = "monthly.shtml", +.draft = false, +--- + +# [重大事件]($section.id('major-events')) + +2024-06-07,0.13.0 发布,历时不足 2 个月,有 73 位贡献者,一共进行了 415 +次提交! 这是一个相对较短的发布周期,主要原因是工具链升级,例如升级到 +[LLVM +18](https://ziglang.org/download/0.13.0/release-notes.html#LLVM-18)。 + +一个比较大的 Breaking changes 是 `ComptimeStringMap` 被重命名为了 +`StaticStringMap` , +使用方式也发生了变化,更多细节可参考:[\#19682](https://github.com/ziglang/zig/pull/19682) + +``` zig +const map = std.StaticStringMap(T).initComptime(kvs_list); +``` + +0.14.0 发布周期的主题将是编译速度。将在 0.14.0 +发布周期中努力实现一些即将到来的里程碑: + +- 使 x86 后端成为调试模式的默认后端。 +- COFF 的链接器支持。消除对 LLVM [LLD](https://lld.llvm.org/) 的依赖。 +- 启用增量编译以实现快速重建。 +- 将并发引入语义分析,进一步提高编译速度。 + +# [观点/教程]($section.id('opinion-tutorial')) + +# [Leveraging Zig's Allocators](https://www.openmymind.net/Leveraging-Zigs-Allocators/) + +老朋友 openmymind 的又一篇好文章:如何利用 Zig 的 Allocator +来实现请求级别的内存分配。 Zig Allocator +的最佳应用。[这里](/post/2024-06-16-leveraging-zig-allocator/)它的中文翻译。 + +``` zig +const FallbackAllocator = struct { + primary: Allocator, + fallback: Allocator, + fba: *std.heap.FixedBufferAllocator, + + pub fn allocator(self: *FallbackAllocator) Allocator { + return .{ + .ptr = self, + .vtable = &.{.alloc = alloc, .resize = resize, .free = free}, + }; + } + + fn alloc(ctx: *anyopaque, len: usize, ptr_align: u8, ra: usize) ?[*]u8 { + const self: *FallbackAllocator = @ptrCast(@alignCast(ctx)); + return self.primary.rawAlloc(len, ptr_align, ra) + orelse self.fallback.rawAlloc(len, ptr_align, ra); + } + + fn resize(ctx: *anyopaque, buf: []u8, buf_align: u8, new_len: usize, ra: usize) bool { + const self: *FallbackAllocator = @ptrCast(@alignCast(ctx)); + if (self.fba.ownsPtr(buf.ptr)) { + if (self.primary.rawResize(buf, buf_align, new_len, ra)) { + return true; + } + } + return self.fallback.rawResize(buf, buf_align, new_len, ra); + } + + fn free(_: *anyopaque, _: []u8, _: u8, _: usize) void { + // we noop this since, in our specific case, we know + // the fallback is an arena, which won't free individual items + } +}; + +fn run(worker: *Worker) void { + const allocator = worker.server.allocator; + + // this is the underlying memory for our FixedBufferAllocator + const buf = try allocator.alloc(u8, 8192); + defer allocator.free(buf); + + var fba = std.heap.FixedBufferAllocator.init(buf); + + while (queue.pop()) |conn| { + defer fba.reset(); + + var arena = std.heap.ArenaAllocator.init(allocator); + defer arena.deinit(); + + var fallback = FallbackAllocator{ + .fba = &fba, + .primary = fba.allocator(), + .fallback = arena.allocator(), + }; + + const action = worker.route(conn.req.url); + action(fallback.allocator(), conn.req, conn.res) catch { // TODO: 500 }; + worker.write(conn.res); + } +} +``` + +# [On Zig vs Rust at work and the choice we made](https://ludwigabap.bearblog.dev/zig-vs-rust-at-work-the-choice-we-made/) + +这篇文章作者描述了所在公司在改造老 C/C++ 项目时,为什么选择了 Zig 而不是 +Rust。 重写的项目运行在多个平台上(Web、移动端、VR +设备),因此最靠谱的方案就是暴露一个 C API,然后通过 FFI +来调用。在做决策时,重点关注以下两点: + +- 新语言与 C 的交互性 +- 工程师扩展代码库的难易程度(如招聘和维护) + +下面是 Zig VS Rust 的优势: + +| | Rust | Zig | +|----------|----------------------------|-------------------------------------------------| +| 成熟度 | 更流行、稳定;使用范围更广 | | +| 包管理 | Cargo 业界领先 | 比 Makefile 好用 | +| 安全 | 内存安全 | | +| SIMD | nightly 支持 | 通过 Vector 类型支持 | +| C 交互性 | 生态丰富 | 编译器本身就是 C 编译器,这样就可以逐步重写项目 | + +如果只是根据上面的比较,貌似还看不出选择 Zig +的动机,因此作者在最后提到: + +> Zig +> 大大减少了移植现有代码库和确保所有平台兼容性所需的时间和精力。我们的团队无法相信 +> Rust 能让这一切变得如此简单。 + +相信这也是大部分人选择 Zig 的原因:简洁、高效。 + +# [Packing some Zig before going for the countryside](https://ludwigabap.bearblog.dev/packing-some-zig-before-going-for-the-countryside/) + +作者列举的一些 Zig +学习资料、常用类库。该作者的另一篇文章也有不少资料:[2024 Collection of +Zig +resources](https://ludwigabap.bearblog.dev/2024-collection-of-zig-resources/) + +# [Why I am not yet ready to switch to Zig from Rust]($section.id('why-i-am-not-yet-ready-to-switch-to-zig-from-rust')) + +Turso CTO 的一篇文章,他本身是个资深 C 程序员,而且也比较喜欢 C,但 C +不是一门安全的语言,因此通过 Rust,作者可以避免 写出 SIGSEGVS +的代码,尽管 Rust +是门复杂的语言,但是因为它有完善的生态(有大公司如微软、谷歌等做背书)、已经内存安全等特点, +已经是作者系统编程的首选。 + +对于 Zig,尽管作者也表达了喜欢,但由于 Zig +的生态不完善,没有足够多的学习资料,因此作者觉得目前阶段选择 Zig +并不会带来 +工作上生产力的提高。这一点说的无可厚非,试想一下,如果一个项目所有的依赖都需要自己做,工作效率确实很难提上去。 + +但是笔者有一点不能理解,就是该作者觉得 comptime +不好用,相比之下,他更喜欢 C 里面的宏。comptime 就是为了 C 宏的不足 +而诞生的,社区普遍也觉得 comptime +是个新颖的设计,笔者也是第一次见到这个观点,只能说,萝卜青菜,各有所爱。 + +其他社区的一些讨论:[Lobsters](https://lobste.rs/s/0mnhdx)、[Hacker +News](https://news.ycombinator.com/item?id=40681862) + +# [项目/工具]($section.id('projects-tools')) + +[malcolmstill/zware](https://github.com/malcolmstill/zware) +Zig WebAssembly Runtime Engine + +[Cloudef/zig-aio](https://github.com/Cloudef/zig-aio) +io_uring like asynchronous API and coroutine powered IO tasks +for zig + +# [Zig 语言更新](https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2024-06-01..2024-07-01) diff --git a/content/monthly/202407.org b/content/monthly/202407.org deleted file mode 100644 index efca3d5..0000000 --- a/content/monthly/202407.org +++ /dev/null @@ -1,120 +0,0 @@ -#+TITLE: 202407 | Zig 成为最热门的编程语言 -#+DATE: 2024-07-05T21:22:52+0800 -#+LASTMOD: 2024-08-01T07:18:08+0800 - -* 重大事件 -在[[https://leaddev.com/tech/why-zig-one-hottest-programming-languages-learn][这篇文章]]里,作者引用 Stackoverflow 2024 年的[[https://survey.stackoverflow.co/2024/technology][调查报告]],指出 Zig 语言是最热门的编程语言之一,并且 Zig 开发者的薪水都很高,平均年收入为75,332美元! - -{{< figure src="/images/stackoverflow2024-highly-desired.webp" caption="Zig 受欢迎程度">}} - -{{< figure src="/images/stackoverflow2024-salary.webp" caption="Zig 薪水对比">}} -尽管使用 Zig 语言的开发者仅占调查人数的 1%,但上升趋势明显。Zig 语言的倡导者、自由和开放源码软件开发者 Ali Cheragi 说: -#+begin_quote -Zig 的魅力在于它的简洁性、现代设计以及在底层控制和运行时安全性之间取得的平衡。 -#+end_quote - -Zig 开发者的一些观点: -- 我选择 Zig 作为我的日常用语,是因为它独特的功能和目标组合。我被 Zig 的安全性所吸引,因为它可以让我控制最底层的部件。 -- 与许多其他语言不同,Zig 可以与现有的 C 代码实现真正的无缝互操作。出于多种原因,这一点至关重要。 -- Zig 正在对大量编程基础架构进行彻底改造,而这些基础架构在过去 40 年里无人敢碰。 - C 和 C++ 是著名的核心编程语言,在这两种语言中,你可以完全控制硬件。 但与此同时,这些语言的工具链却非常糟糕。 Zig 允许用户涉猎这些核心编程语言,但可以使用更好的工具链,兼容各种语言和更丰富的功能。 - -* 观点/教程 -** [[https://kristoff.it/blog/improving-your-zls-experience/][Improving Your Zig Language Server Experience]] - Loris Cro 的最新文章,介绍了一个改进 Zig 编码体验的小技巧,十分推荐大家使用。具体来说是这样的: - 通过配置 zls,达到保存文件时,自动进行源码检查,而且速度非常快! - #+begin_src js -{ - "enable_build_on_save": true, - "build_on_save_step": "check" -} - #+end_src - 将上述内存保存到 zls 的配置文件中,(路径可以通过 =zls --show-config-path= 查看 ),zls 就会在保存时,自动执行 =zig build check= ,这个 =check= 一般来说是这样的: - #+begin_src zig -const exe_check = b.addExecutable(.{ - .name = "foo", - .root_source_file = b.path("src/main.zig"), - .target = target, - .optimize = optimize, -}); - -const check = b.step("check", "Check if foo compiles"); -check.dependOn(&exe_check.step); - #+end_src - -由于 Zig 目前的一个 bug([[https://github.com/ziglang/zig/issues/18877][#18877]]),这个 =exe_check= 不能作为 install、run 的依赖,否则在编译时,就不会增加 =-fno-emit-bin= 选项。 -而这个选项的作用就是让 Zig 来分析我们的代码,但是不会调用 LLVM 来生成最终的二进制文件,因此速度会比较快。 - -这个配置有个缺点,就是它是个全局配置,在 [[https://github.com/zigtools/zls/issues/1687#issuecomment-1953202544][zigtools/zls#1687]] 有讨论如何改成项目级别的,本质上就是定制 zls 的启动参数。 -#+begin_src bash -zls --config-path zls.json -#+end_src -这样不同的项目就可以用不同的检查步骤了。 -** [[https://guergabo.substack.com/p/systems-distributed-24][Systems Distributed '24]] -作者对这次会议的一个回顾总结,议题主要有如下几个方向: -- Systems Thinking and Engineering Culture -- The Rise of New Software Abstractions -- Ensuring Safe and Correct Software -- Lessons from Building Distributed Databases -- Notes from Water Cooler Chats -** [[https://jstrieb.github.io/posts/c-reflection-zig/][C Macro Reflection in Zig – Zig Has Better C Interop Than C Itself]] -该作者分享了利用 typeInfo 来在编译时获取字段名的能力,要知道,在 C 里面是没有这个功能的。 -#+begin_src zig -pub export fn WindowProc(hwnd: win32.HWND, uMsg: c_uint, wParam: win32.WPARAM, lParam: win32.LPARAM) callconv(windows.WINAPI) win32.LRESULT { - // Handle each type of window message we care about - _ = switch (uMsg) { - win32.WM_CLOSE => win32.DestroyWindow(hwnd), - win32.WM_DESTROY => win32.PostQuitMessage(0), - else => { - stdout.print("Unknown window message: 0x{x:0>4}\n", .{uMsg}) catch undefined; - }, - }; - return win32.DefWindowProcA(hwnd, uMsg, wParam, lParam); -} - -#+end_src -上面这个函数是 Window 编写窗口应用时用到的回调函数,Window 操作系统会把用户触发的事件通过 =uMsg= 传递过来,为了能够从一个数字,找对对应的名字,在 Zig 里面可以用如下函数实现: -#+begin_src zig -// The WM_* macros have values less than 65536, so an array of that size can -// represent all of them -fn get_window_messages() [65536][:0]const u8 { - var result: [65536][:0]const u8 = undefined; - @setEvalBranchQuota(1000000); - // Loop over all struct fields and match against the expected prefix - for (@typeInfo(win32).Struct.decls) |field| { - if (field.name.len >= 3 and std.mem.eql(u8, field.name[0..3], "WM_")) { - const value = @field(win32, field.name); - result[value] = field.name; - } - } - // We return by value here, not by reference, so this is safe to do - return result; -} -#+end_src -** [[https://effectivetypescript.com/2024/07/17/advent2023-zig/][A TypeScripter's Take on Zig (Advent of Code 2023)]] -以下该作者的一些心得体会: - -- Zig 没有 scanf 等价物,正则表达式也不方便。因此,对于解析输入,它是拆分、拆分、拆分。最后,我分解出了一些 splitIntoBuf 和提取 IntsIntoBuf 帮助程序,这些帮助程序可以很快地读取大多数问题的输入。 -- Zig 支持所有大小的 int,一直到 u65536。如果出现溢出,请尝试使用更大的整数类型。我在一些问题上使用了 u128和 i128。 -- StringToEnum 是解析受限制的字符串或字符集的一个简单技巧。 -- 可以在结构上定义一个 format 方法,使它们按照您的喜好打印。 -- 尽量避免将字符串复制到 StringHashMap 中用作键。从 JS 发出这样的命令感觉很自然,但是在 Zig 中会很尴 - 尬,因为您需要跟踪这些字符串以便稍后释放它们。如果您可以将您的键放入一个结构或元组中,那将会工作得 - 更好,因为它们具有值语义。如果需要字符串,可以使用切片。 -- 注意数值范围的错误。如果你想包含 max,它是 =min..(max + 1)= ,而不是 =min..max= 。 -- 代码中将有大量的@intCast。 -- 我发现奇怪的是 Zig 有一个内置的 PriorityQueue,但是没有内置的 Queue,可以用 =std.SinglyLinkedList= 替代 -- 用于处理字符串的许多函数都在 std.mem 中,例如 std.mem.eql 和 std.mem.startsWith -- 使用 std.met.eql 比较 structs,而不是 ~=~ -- 有一个按偏移量和长度切片的技巧: =array [start..][0..length]= -- 记忆函数通常是很有用的。我不知道 Zig 有没有通用的方法 -- 调试构建比优化构建慢得多,有时候慢10倍。如果你在一个合理的时间内得到一个答案的10倍之内,尝试一个不同的发布模式。 -- 迭代时不要对数组列表进行修改 -- 在 JavaScript 允许您内联表达式的某些情况下,您可能需要分解出一个变量来澄清生存期。看看[[https://github.com/ziglang/zig/issues/12414][这个问题]]。 - - -* 项目/工具 -- [[https://github.com/18alantom/fex][18alantom/fex]] :: A command-line file explorer prioritizing quick navigation. -- [[https://github.com/griush/zm][griush/zm]] :: SIMD Math library fully cross-platform - -* [[https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2024-07-01..2024-08-01][Zig 语言更新]] diff --git a/content/monthly/202407.smd b/content/monthly/202407.smd new file mode 100644 index 0000000..63234c2 --- /dev/null +++ b/content/monthly/202407.smd @@ -0,0 +1,178 @@ +--- +.title = "202407 | Zig 成为最热门的编程语言", +.date = @date("2024-07-05T21:22:52+0800"), +.author = "ZigCC", +.layout = "monthly.shtml", +.draft = false, +--- + +# [重大事件]($section.id('major-events')) + +在[这篇文章](https://leaddev.com/tech/why-zig-one-hottest-programming-languages-learn)里,作者引用 +Stackoverflow 2024 +年的[调查报告](https://survey.stackoverflow.co/2024/technology),指出 +Zig 语言是最热门的编程语言之一,并且 Zig +开发者的薪水都很高,平均年收入为75,332美元! + +[Zig 受欢迎程度]($image.siteAsset('images/stackoverflow2024-salary.webp')) + +[Zig 薪水对比]($image.siteAsset('images/stackoverflow2024-salary.webp')) + 尽管使用 Zig 语言的开发者仅占调查人数的1%,但上升趋势明显。Zig 语言的倡导者、自由和开放源码软件开发者 Ali Cheragi 说: + +> Zig +> 的魅力在于它的简洁性、现代设计以及在底层控制和运行时安全性之间取得的平衡。 + +Zig 开发者的一些观点: + +- 我选择 Zig 作为我的日常用语,是因为它独特的功能和目标组合。我被 Zig + 的安全性所吸引,因为它可以让我控制最底层的部件。 +- 与许多其他语言不同,Zig 可以与现有的 C + 代码实现真正的无缝互操作。出于多种原因,这一点至关重要。 +- Zig 正在对大量编程基础架构进行彻底改造,而这些基础架构在过去 40 + 年里无人敢碰。 C 和 C++ + 是著名的核心编程语言,在这两种语言中,你可以完全控制硬件。 + 但与此同时,这些语言的工具链却非常糟糕。 Zig + 允许用户涉猎这些核心编程语言,但可以使用更好的工具链,兼容各种语言和更丰富的功能。 + +# [观点/教程]($section.id('opinion-tutorial')) + +# [Improving Your Zig Language Server Experience](https://kristoff.it/blog/improving-your-zls-experience/) + +Loris Cro 的最新文章,介绍了一个改进 Zig +编码体验的小技巧,十分推荐大家使用。具体来说是这样的: 通过配置 +zls,达到保存文件时,自动进行源码检查,而且速度非常快! + +``` json +{ + "enable_build_on_save": true, + "build_on_save_step": "check" +} +``` + +将上述内存保存到 zls 的配置文件中,(路径可以通过 +`zls --show-config-path` 查看 ),zls 就会在保存时,自动执行 +`zig build check` ,这个 `check` 一般来说是这样的: + +``` zig +const exe_check = b.addExecutable(.{ + .name = "foo", + .root_source_file = b.path("src/main.zig"), + .target = target, + .optimize = optimize, +}); + +const check = b.step("check", "Check if foo compiles"); +check.dependOn(&exe_check.step); +``` + +由于 Zig 目前的一个 +bug([\#18877](https://github.com/ziglang/zig/issues/18877)),这个 +`exe_check` 不能作为 install、run 的依赖,否则在编译时,就不会增加 +`-fno-emit-bin` 选项。 而这个选项的作用就是让 Zig +来分析我们的代码,但是不会调用 LLVM +来生成最终的二进制文件,因此速度会比较快。 + +这个配置有个缺点,就是它是个全局配置,在 +[zigtools/zls#1687](https://github.com/zigtools/zls/issues/1687#issuecomment-1953202544) +有讨论如何改成项目级别的,本质上就是定制 zls 的启动参数。 + +``` bash +zls --config-path zls.json +``` + +这样不同的项目就可以用不同的检查步骤了。 + +# [Systems Distributed '24]($section.id('systems-distributed-24')) + +作者对这次会议的一个回顾总结,议题主要有如下几个方向: + +- Systems Thinking and Engineering Culture +- The Rise of New Software Abstractions +- Ensuring Safe and Correct Software +- Lessons from Building Distributed Databases +- Notes from Water Cooler Chats + +# [C Macro Reflection in Zig – Zig Has Better C Interop Than C Itself](https://jstrieb.github.io/posts/c-reflection-zig/) + +该作者分享了利用 typeInfo 来在编译时获取字段名的能力,要知道,在 C +里面是没有这个功能的。 + +``` zig +pub export fn WindowProc(hwnd: win32.HWND, uMsg: c_uint, wParam: win32.WPARAM, lParam: win32.LPARAM) callconv(windows.WINAPI) win32.LRESULT { + // Handle each type of window message we care about + _ = switch (uMsg) { + win32.WM_CLOSE => win32.DestroyWindow(hwnd), + win32.WM_DESTROY => win32.PostQuitMessage(0), + else => { + stdout.print("Unknown window message: 0x{x:0>4}\n", .{uMsg}) catch undefined; + }, + }; + return win32.DefWindowProcA(hwnd, uMsg, wParam, lParam); +} + +``` + +上面这个函数是 Window 编写窗口应用时用到的回调函数,Window +操作系统会把用户触发的事件通过 `uMsg` +传递过来,为了能够从一个数字,找对对应的名字,在 Zig +里面可以用如下函数实现: + +``` zig +// The WM_* macros have values less than 65536, so an array of that size can +// represent all of them +fn get_window_messages() [65536][:0]const u8 { + var result: [65536][:0]const u8 = undefined; + @setEvalBranchQuota(1000000); + // Loop over all struct fields and match against the expected prefix + for (@typeInfo(win32).Struct.decls) |field| { + if (field.name.len >= 3 and std.mem.eql(u8, field.name[0..3], "WM_")) { + const value = @field(win32, field.name); + result[value] = field.name; + } + } + // We return by value here, not by reference, so this is safe to do + return result; +} +``` + +# [A TypeScripter's Take on Zig (Advent of Code 2023)](https://effectivetypescript.com/2024/07/17/advent2023-zig/) + +以下该作者的一些心得体会: + +- Zig 没有 scanf + 等价物,正则表达式也不方便。因此,对于解析输入,它是拆分、拆分、拆分。最后,我分解出了一些 + splitIntoBuf 和提取 IntsIntoBuf + 帮助程序,这些帮助程序可以很快地读取大多数问题的输入。 +- Zig 支持所有大小的 int,一直到 + u65536。如果出现溢出,请尝试使用更大的整数类型。我在一些问题上使用了 + u128和 i128。 +- StringToEnum 是解析受限制的字符串或字符集的一个简单技巧。 +- 可以在结构上定义一个 format 方法,使它们按照您的喜好打印。 +- 尽量避免将字符串复制到 StringHashMap 中用作键。从 JS + 发出这样的命令感觉很自然,但是在 Zig 中会很尴 + 尬,因为您需要跟踪这些字符串以便稍后释放它们。如果您可以将您的键放入一个结构或元组中,那将会工作得 + 更好,因为它们具有值语义。如果需要字符串,可以使用切片。 +- 注意数值范围的错误。如果你想包含 max,它是 `min..(max + 1)` ,而不是 + `min..max` 。 +- 代码中将有大量的@intCast。 +- 我发现奇怪的是 Zig 有一个内置的 PriorityQueue,但是没有内置的 + Queue,可以用 `std.SinglyLinkedList` 替代 +- 用于处理字符串的许多函数都在 std.mem 中,例如 std.mem.eql 和 + std.mem.startsWith +- 使用 std.met.eql 比较 structs,而不是 `=` +- 有一个按偏移量和长度切片的技巧: `array [start..][0..length]` +- 记忆函数通常是很有用的。我不知道 Zig 有没有通用的方法 +- 调试构建比优化构建慢得多,有时候慢10倍。如果你在一个合理的时间内得到一个答案的10倍之内,尝试一个不同的发布模式。 +- 迭代时不要对数组列表进行修改 +- 在 JavaScript + 允许您内联表达式的某些情况下,您可能需要分解出一个变量来澄清生存期。看看[这个问题](https://github.com/ziglang/zig/issues/12414)。 + +# [项目/工具]($section.id('projects-tools')) + +[18alantom/fex](https://github.com/18alantom/fex) +A command-line file explorer prioritizing quick navigation. + +[griush/zm](https://github.com/griush/zm) +SIMD Math library fully cross-platform + +# [Zig 语言更新](https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2024-07-01..2024-08-01) diff --git a/content/monthly/202410.org b/content/monthly/202410.org deleted file mode 100644 index 128a4f2..0000000 --- a/content/monthly/202410.org +++ /dev/null @@ -1,68 +0,0 @@ -#+TITLE: 202410 | 向 Zig 软件基金会认捐 30 万美元 -#+DATE: 2024-10-26T00:17:35+0800 -#+LASTMOD: 2024-11-03T15:21:14+0800 -* 重大事件 -** 向 Zig 软件基金会认捐 30 万美元 -Mitchell 在其最新的博客上宣布:我和我的妻子向 Zig 软件基金会 (ZSF) 捐赠了 300,000 美元。 -#+begin_quote -两年内每年分期支付15万美元。第一期已经转账。 -#+end_quote - -我从 2019 年的某个时候开始关注 Zig 项目。 我在 2021 年公开分享了我对该项目的兴奋之情。 同年晚些时候,我开始使用 Zig,到 2022 年初,我开始撰写关于 Zig 的文章,并为编译器做出贡献。 2023 年,我公开分享了用 Zig 编写的终端项目 Ghostty。 - -如今,我大部分的编码时间都花在了 Zig 上。 我的家人喜欢支持我们相信的事业2。 作为其中的一部分,我们希望支持那些我们认为可以带来变革和影响的独立软件项目,这既是回馈给我如此之多的社区的一种方式,更重要的是,这也是彰显和鼓励为热爱而构建的文化的一种方式。 Zig 就是这样一个项目。 -* 观点/教程 -** [[https://mrcat.au/blog/zig_is_cool/][Zig is everything I want C to be]] -对 Zig 的特色进行了简单扼要的介绍,主要有: -1. UB 行为检测。 - - Zig 的指针不能是 null,需要用 optional 类型 - - C 里面的 =void*= 等价于 Zig 里面的 =?*anyopaque= 。 =void= 在 C 里面有两个意思,第一是『什么都没有』,第二是『类型不确定』,但 =void= 在 Zig 中只有第一个含义,因此用了 =anyopaque= 来表示类型擦除的指针(type-erased pointers)。 - - 数组越界检查 - - 整数溢出 -2. Bitfield, =packed struct= 可以方便的用来进行协议解析,比如对于 32 位的 RISC-V 的指令,可以这么定义解析: - #+begin_src zig -const IType = packed struct { - opcode: u7, - rd: u5, - funct3: u3, - rs1: u5, - imm: i12, // For sign-extension -}; - -const encoded_instr: u32 = 0xFFF34293; -const instr: IType = @bitCast(encoded_instr); - #+end_src -3. comptime,Zig 进行元编程的基础,类型是一等成员 -4. 与 C 无缝交互, =zig cc= 是交叉编译的首选 -** [[https://blog.erikwastaken.dev/posts/2024-10-27-building-3ds-homebrew-with-zig.html][Building Nintendo 3DS Homebrew with Zig]] -** [[https://kristoff.it/blog/critical-social-infrastructure/][Critical Social Infrastructure for Zig Communities | Loris Cro's Blog]] -对于一个试图共同学习如何制作大家都喜欢的软件的社区来说,能够分享想法并开展合作至关重要,但社交平台的不断起伏会导致连接中断,这对于一个从一开始就希望去中心化的社区来说是个大问题。 - -我有这种想法已经有一段时间了,但随着时间的推移,我们似乎越来越清楚地认识到,我们需要投资于能够长期保持可靠的交流形式,在这种交流形式中,变化是一种信号,表明社区正在发生转变(因此需要一种新的网络形态),而不是表明所选择的社交平台即将被收购/上市/加入人工智能大战。 - -开发者日志:迈向可靠社会基础设施的第一步 -- https://ziglang.org/devlog/ -- https://zine-ssg.io/log/ -** [[https://ziglang.org/news/website-zine/][The Zig Website Has Been Re-engineered]] -Zig 官网已经用 [[https://zine-ssg.io/][Zine]] 重写! -** [[https://thenewstack.io/rust-vs-zig-in-reality-a-somewhat-friendly-debate/][Rust vs. Zig in Reality: A (Somewhat) Friendly Debate]] -** [[https://kevinlynagh.com/rust-zig/][Why I rewrote my Rust keyboard firmware in Zig: consistency, mastery, and fun]] -** [[https://teckrevie.blogspot.com/2024/09/why-zig-programmers-are-cashing-in-deep.html][Why Zig Programmers Are Cashing In: A Deep Dive into the Lucrative World of Zig]] -** 视频 -*** [[https://www.youtube.com/watch?v=xOySJpQlmv4&feature=youtu.be][I made an operating system that self replicates doom on a network “from scratch”]] -*** [[https://www.youtube.com/watch?feature=shared&v=3fWx5BOiUiY][Rust vs Zig vs Go: Performance (Latency - Throughput - Saturation - Availability)]] -*** [[https://www.youtube.com/live/Kf7BIPUUfsc?t=764][Let's explore Vulkan API with Zig programming language from scratch]] -* 项目/工具 -- [[https://github.com/laohanlinux/boltdb-zig][laohanlinux/boltdb-zig]] :: a zig implement kv database -- [[https://github.com/E-xyza/zigler][zigler]] :: Zig NIFs in Elixir -- [[https://github.com/gdonald/blackjack-zig][gdonald/blackjack-zig]] :: Console Blackjack written in Zig -- [[https://github.com/rabinnh/zig-vscode-linux][rabinnh/zig-vscode-linux]] :: Instructions on setting up VSCode to debug Zig on Linux -- [[https://github.com/lframosferreira/brainzuck][lframosferreira/brainzuck]] :: [[https://en.wikipedia.org/wiki/Brainfuck][Brainf*ck]] interpreter written in Zig 0.12.0! Have fun! -- [[https://github.com/BitlyTwiser/snek][BitlyTwiser/snek]] :: A simple CLI parser to build CLI applications in Zig -- [[https://github.com/zml/zml][zml/zml]] :: High performance AI inference stack. Built for production. -- [[https://github.com/BitlyTwiser/zdotenv][BitlyTwiser/zdotenv]] :: A port of Godotenv for Zig -- [[https://github.com/sbancuz/OpenMP-zig][sbancuz/OpenMP-zig]] :: An implementation of the OpenMP directives for Zig -- [[https://github.com/tusharsadhwani/zigimports][tusharsadhwani/zigimports]] :: Automatically remove unused imports and globals from Zig files. -- [[https://github.com/Mario-SO/zigitor][Mario-SO/zigitor]] :: Video editor 🎬 written in Zig ⚡ using raylib -- [[https://github.com/pwbh/ymlz][pwbh/ymlz]] :: Small and convenient yaml parser for Zig -* [[https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2024-10-01..2024-11-01][Zig 语言更新]] diff --git a/content/monthly/202410.smd b/content/monthly/202410.smd new file mode 100644 index 0000000..d0b4b3b --- /dev/null +++ b/content/monthly/202410.smd @@ -0,0 +1,132 @@ +--- +.title = "202410 | 向 Zig 软件基金会认捐 30 万美元", +.date = @date("2024-10-26T00:17:35+0800"), +.author = "ZigCC", +.layout = "monthly.shtml", +.draft = false, +--- + +# [重大事件]($section.id('major-events')) + +# [向 Zig 软件基金会认捐 30 万美元]($section.id('donation-zsf-300k')) + +Mitchell 在其最新的博客上宣布:我和我的妻子向 Zig 软件基金会 (ZSF) +捐赠了 300,000 美元。 + +> 两年内每年分期支付15万美元。第一期已经转账。 + +我从 2019 年的某个时候开始关注 Zig 项目。 我在 2021 +年公开分享了我对该项目的兴奋之情。 同年晚些时候,我开始使用 Zig,到 2022 +年初,我开始撰写关于 Zig 的文章,并为编译器做出贡献。 2023 +年,我公开分享了用 Zig 编写的终端项目 Ghostty。 + +如今,我大部分的编码时间都花在了 Zig 上。 +我的家人喜欢支持我们相信的事业2。 +作为其中的一部分,我们希望支持那些我们认为可以带来变革和影响的独立软件项目,这既是回馈给我如此之多的社区的一种方式,更重要的是,这也是彰显和鼓励为热爱而构建的文化的一种方式。 +Zig 就是这样一个项目。 + +# [观点/教程]($section.id('opinion-tutorial')) + +# [Zig is everything I want C to be](https://mrcat.au/blog/zig_is_cool/) + +对 Zig 的特色进行了简单扼要的介绍,主要有: + +1. UB 行为检测。 + + - Zig 的指针不能是 null,需要用 optional 类型 + - C 里面的 `void*` 等价于 Zig 里面的 `?*anyopaque` 。 `void` 在 C + 里面有两个意思,第一是『什么都没有』,第二是『类型不确定』,但 + `void` 在 Zig 中只有第一个含义,因此用了 `anyopaque` + 来表示类型擦除的指针(type-erased pointers)。 + - 数组越界检查 + - 整数溢出 + +2. Bitfield, `packed struct` 可以方便的用来进行协议解析,比如对于 32 + 位的 RISC-V 的指令,可以这么定义解析: + + ``` zig + const IType = packed struct { + opcode: u7, + rd: u5, + funct3: u3, + rs1: u5, + imm: i12, // For sign-extension + }; + + const encoded_instr: u32 = 0xFFF34293; + const instr: IType = @bitCast(encoded_instr); + ``` + +3. comptime,Zig 进行元编程的基础,类型是一等成员 + +4. 与 C 无缝交互, `zig cc` 是交叉编译的首选 + +# [Building Nintendo 3DS Homebrew with Zig](https://blog.erikwastaken.dev/posts/2024-10-27-building-3ds-homebrew-with-zig.html) + +# [Critical Social Infrastructure for Zig Communities | Loris Cro's Blog](https://kristoff.it/blog/critical-social-infrastructure/) + +对于一个试图共同学习如何制作大家都喜欢的软件的社区来说,能够分享想法并开展合作至关重要,但社交平台的不断起伏会导致连接中断,这对于一个从一开始就希望去中心化的社区来说是个大问题。 + +我有这种想法已经有一段时间了,但随着时间的推移,我们似乎越来越清楚地认识到,我们需要投资于能够长期保持可靠的交流形式,在这种交流形式中,变化是一种信号,表明社区正在发生转变(因此需要一种新的网络形态),而不是表明所选择的社交平台即将被收购/上市/加入人工智能大战。 + +开发者日志:迈向可靠社会基础设施的第一步 + +- +- + +# [The Zig Website Has Been Re-engineered]($section.id('the-zig-website-has-been-re-engineered')) + +Zig 官网已经用 [Zine](https://zine-ssg.io/) 重写! + +# [Rust vs. Zig in Reality: A (Somewhat) Friendly Debate](https://thenewstack.io/rust-vs-zig-in-reality-a-somewhat-friendly-debate/) + +# [Why I rewrote my Rust keyboard firmware in Zig: consistency, mastery, and fun]($section.id('why-i-rewrote-my-rust-keyboard-firmware-in-zig-consistency-mastery-and-fun')) + +# [视频]($section.id('videos')) + +## [I made an operating system that self replicates doom on a network "from scratch"](https://www.youtube.com/watch?v=xOySJpQlmv4&feature=youtu.be) + +## [Rust vs Zig vs Go: Performance (Latency - Throughput - Saturation - Availability)](https://www.youtube.com/watch?feature=shared&v=3fWx5BOiUiY) + +## [Let's explore Vulkan API with Zig programming language from scratch](https://www.youtube.com/live/Kf7BIPUUfsc?t=764) + +# [项目/工具]($section.id('projects-tools')) + +[laohanlinux/boltdb-zig](https://github.com/laohanlinux/boltdb-zig) +a zig implement kv database + +[zigler](https://github.com/E-xyza/zigler) +Zig NIFs in Elixir + +[gdonald/blackjack-zig](https://github.com/gdonald/blackjack-zig) +Console Blackjack written in Zig + +[rabinnh/zig-vscode-linux](https://github.com/rabinnh/zig-vscode-linux) +Instructions on setting up VSCode to debug Zig on Linux + +[lframosferreira/brainzuck](https://github.com/lframosferreira/brainzuck) +[Brainf*ck](https://en.wikipedia.org/wiki/Brainfuck) interpreter +written in Zig 0.12.0! Have fun! + +[BitlyTwiser/snek](https://github.com/BitlyTwiser/snek) +A simple CLI parser to build CLI applications in Zig + +[zml/zml](https://github.com/zml/zml) +High performance AI inference stack. Built for production. + +[BitlyTwiser/zdotenv](https://github.com/BitlyTwiser/zdotenv) +A port of Godotenv for Zig + +[sbancuz/OpenMP-zig](https://github.com/sbancuz/OpenMP-zig) +An implementation of the OpenMP directives for Zig + +[tusharsadhwani/zigimports](https://github.com/tusharsadhwani/zigimports) +Automatically remove unused imports and globals from Zig files. + +[Mario-SO/zigitor](https://github.com/Mario-SO/zigitor) +Video editor 🎬 written in Zig ⚡ using raylib + +[pwbh/ymlz](https://github.com/pwbh/ymlz) +Small and convenient yaml parser for Zig + +# [Zig 语言更新](https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2024-10-01..2024-11-01) diff --git a/content/monthly/202411.org b/content/monthly/202411.org deleted file mode 100644 index 53912b2..0000000 --- a/content/monthly/202411.org +++ /dev/null @@ -1,87 +0,0 @@ -#+TITLE: 202411 -#+DATE: 2024-12-09T21:02:40+0800 -#+LASTMOD: 2024-12-09T23:27:21+0800 -* 观点/教程 -** [[https://injuly.in/blog/announcing-jam/index.html][Why am I writing a JavaScript toolchain in Zig?]] -[[https://github.com/srijan-paul/jam][JAM]] 作者写的一篇文章,分析里市面上现有的 JS 工具链(bundler、formatter、linter 等),虽然已经很好用,但是不够快。下面是他举的几个例子: -- Lossless, cache efficient syntax trees,现在通用的 JS 语法树表示是 [[https://github.com/estree/estree][ESTree]],尽管设计上很简洁,但在遍历时不够高效,需要有遍历多次 - 才能得到有用信息(eslint 里就有四次!),而且都是指针的树结构非常不利用重复利用 CPU,Carbon 编译器就有一种更紧凑的 AST 表示。 -- Compile time AST query processing。Lint 的规则大部分都是模式匹配,大部分时候都有多个嵌套的 if 逻辑,为了简化插件开发者,eslint - 采用了一种 [[https://estools.github.io/esquery/][esquery]] 的语法,示例: - #+begin_src js -if ( - node.type == "CallExpression" && - node.callee.type === "MemberExpression" && - node.callee.object.type === "Identifier" && - node.callee.object.name === "child_process" -) { - // many of these checks are to satisfy typescript^ -} - - -if (matches( - 'CallExpression[callee.object.name = child_process]', - node - )) { - // much better -} - #+end_src - esquery 的问题在于执行效率,通过借助于 zig 的 comptime 来在编译器翻译 esquery 就避免了运行时开销。 -** [[https://kristoff.it/blog/advent-of-code-zig/][Advent of Code in Zig | Loris Cro's Blog]] -一年一度的 AoC 又到了,这篇文章里给出了一些使用的技巧来帮助大家用 Zig 来解决 AoC 问题。 -- 工具链,最新的版本 0.13 和 zls -- 手册,和 [[https://github.com/ziglang/zig/wiki/How-to-read-the-standard-library-source-code][How to read the standard library source code · ziglang/zig Wiki]] -- 使用 =embedFile= 来嵌入输入的测试用例: - #+begin_src zig -const std = @import("std"); -const input = @embedFile("path/to/input.txt"); - -pub fn main() !void { - for (input) |byte| { - //... - } -} - #+end_src -- 分词 - - std.mem.tokenizeScalar - - std.mem.splitScalar - - std.mem.splitAny - - std.mem.window 滑动窗口,用法可参考:[[https://zig.news/pyrolistical/new-way-to-split-and-iterate-over-strings-2akh][New way to split and iterate over strings - Zig NEWS]] -- 数据操作 - - 解析数字, =std.fmt.parseInt()= - - 位操作,可以用任意宽度的数字(u1,u2 等), =std.BitStack=, =std.DynamicBitSet= 这两个也非常有用 - -更重要的,作者最后提到 AoC 可能不是学习 Zig 的最好方式: -#+begin_quote -虽然 AoC 非常有趣,但它并不是练习软件工程的方法。 每个 AoC 练习都要求你找到一个问题的解决方案,虽然你需要编写一个程序来解决这个问题, -但你的程序将是一个只需运行一次(一次正确)的一次性脚本。 - -当你的软件需要稳健、优化和可维护时,Zig 就会大显身手,而这些对于 AoC 来说都不重要。 - -因此,请注意,虽然肯定能用 Zig 解决 AoC 问题,而且 Zig 的某些功能甚至能帮助您取得比其他语言更快的进展,但它最终还是针对软件工程进行了优化,而这并不是您在 AoC 中要做的事情。 -#+end_quote -** [[https://floooh.github.io/2024/08/24/zig-and-emulators.html][Zig and Emulators]] -** [[https://jakstys.lt/2024/zig-reproduced-without-binaries/][Zig Reproduced Without Binaries]] -一个很有趣的实验,在 0.10 版本中,Zig 编译器实现了自举,即可以用老版本的 Zig 来编译 Zig 源码,生成最新的 Zig 二进制。这里重新复习一下这个复杂的流程: - -之所以复杂,问题在于老版本的 Zig 从哪里来呢?对于 Zig 来说就是 [[https://github.com/ziglang/zig/blob/master/stage1/zig1.wasm][zig1.wasm]],它是用没自举前的 Zig,利用 LLVM 后端,以 wasm32-wasi 为目标生成的二进制文件。 -为了保证足够小,这里面只保留了 C 后端,这样就得到了一个小到可以放到代码仓库中的 Zig 编译器。这篇文章就是证明这个文件没有被私自篡改过! - -- 之后利用 Zig 团队自己写的 wasm2c.c 把 zig1.wasm 编译成 zig1.c,之后用 cc 编译 zig1.c 就可以得到 stage1 的 zig 编译器 -- 之后再用 zig1 编译 zig 源码,由于 zig1 之后 C 后端,因此这里得到的产物是 zig2.c,再利用 cc 就可以可以 stage2 的 zig。 - zig2 功能上已经完备,但是速度很慢(没有经过 LLVM 优化) -- 最后再用 zig2 继续编译 zig 源码,得到最后的 zig3,这也是我们下载 zig 安装包时包含的版本 -- 如果再继续用 zig3 来编译 zig 源码,得到的 zig4 会和 zig3 一模一样。 - -细节可以参考: -- [[https://ziglang.org/news/goodbye-cpp/][Goodbye to the C++ Implementation of Zig]] -- [[https://www.reddit.com/r/Zig/comments/142gwls/why_is_the_bootstrapping_process_so_complicated/][Why is the bootstrapping process so complicated? : r/Zig]] -* 项目/工具 -- [[https://goreleaser.com/customization/zig-builds/][Builds (Zig) - GoReleaser]] :: 版本发布工具 GoReleaser 支持了 Zig -- [[https://github.com/follgad/zig-ai][FOLLGAD/zig-ai: OpenAI SDK with streaming support]] :: -- [[https://github.com/zouyee/zig-learning][A bunch of links to blog posts, articles, videos, etc for learning Zig]] :: -- [[https://github.com/Super-ZIG/cli][Super-ZIG/cli: Easy command line interface in ZIG.]] :: -- [[https://github.com/deckarep/zigualizer][deckarep/zigualizer]] :: Zigualizer: A music visualizer built with Zig, powered by the FFT algorithm. -- [[https://github.com/freref/fancy-cat][freref/fancy-cat]] :: PDF reader for terminal emulators using the Kitty image protocol -- [[https://github.com/Dr-Nekoma/lyceum][Dr-Nekoma/lyceum]] :: An MMO game written in Erlang (+ PostgreSQL) + Zig (+ Raylib) -* [[https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2024-11-01..2024-12-01][Zig 语言更新]] diff --git a/content/monthly/202411.smd b/content/monthly/202411.smd new file mode 100644 index 0000000..55081fc --- /dev/null +++ b/content/monthly/202411.smd @@ -0,0 +1,154 @@ +--- +.title = "202411", +.date = @date("2024-12-09T21:02:40+0800"), +.author = "ZigCC", +.layout = "monthly.shtml", +.draft = false, +--- + +# [观点/教程]($section.id('opinion-tutorial')) + +# [Why am I writing a JavaScript toolchain in Zig?](https://injuly.in/blog/announcing-jam/index.html) + +[JAM](https://github.com/srijan-paul/jam) +作者写的一篇文章,分析里市面上现有的 JS +工具链(bundler、formatter、linter +等),虽然已经很好用,但是不够快。下面是他举的几个例子: + +- Lossless, cache efficient syntax trees,现在通用的 JS 语法树表示是 + [ESTree](https://github.com/estree/estree),尽管设计上很简洁,但在遍历时不够高效,需要有遍历多次 + 才能得到有用信息(eslint + 里就有四次!),而且都是指针的树结构非常不利用重复利用 CPU,Carbon + 编译器就有一种更紧凑的 AST 表示。 + +- Compile time AST query processing。Lint + 的规则大部分都是模式匹配,大部分时候都有多个嵌套的 if + 逻辑,为了简化插件开发者,eslint 采用了一种 + [esquery](https://estools.github.io/esquery/) 的语法,示例: + + ``` javascript + if ( + node.type == "CallExpression" && + node.callee.type === "MemberExpression" && + node.callee.object.type === "Identifier" && + node.callee.object.name === "child_process" + ) { + // many of these checks are to satisfy typescript^ + } + + + if (matches( + 'CallExpression[callee.object.name = child_process]', + node + )) { + // much better + } + ``` + + esquery 的问题在于执行效率,通过借助于 zig 的 comptime 来在编译器翻译 + esquery 就避免了运行时开销。 + +# [Advent of Code in Zig | Loris Cro's Blog]($section.id('advent-of-code-in-zig-loris-cros-blog')) + +一年一度的 AoC 又到了,这篇文章里给出了一些使用的技巧来帮助大家用 Zig +来解决 AoC 问题。 + +- 工具链,最新的版本 0.13 和 zls + +- 手册,和 [How to read the standard library source code · ziglang/zig + Wiki](https://github.com/ziglang/zig/wiki/How-to-read-the-standard-library-source-code) + +- 使用 `embedFile` 来嵌入输入的测试用例: + + ``` zig + const std = @import("std"); + const input = @embedFile("path/to/input.txt"); + + pub fn main() !void { + for (input) |byte| { + //... + } + } + ``` + +- 分词 + + - std.mem.tokenizeScalar + - std.mem.splitScalar + - std.mem.splitAny + - std.mem.window 滑动窗口,用法可参考:[New way to split and iterate + over strings - Zig + NEWS](https://zig.news/pyrolistical/new-way-to-split-and-iterate-over-strings-2akh) + +- 数据操作 + + - 解析数字, `std.fmt.parseInt()` + - 位操作,可以用任意宽度的数字(u1,u2 等), `std.BitStack`, + `std.DynamicBitSet` 这两个也非常有用 + +更重要的,作者最后提到 AoC 可能不是学习 Zig 的最好方式: + +> 虽然 AoC 非常有趣,但它并不是练习软件工程的方法。 每个 AoC +> 练习都要求你找到一个问题的解决方案,虽然你需要编写一个程序来解决这个问题, +> 但你的程序将是一个只需运行一次(一次正确)的一次性脚本。 +> +> 当你的软件需要稳健、优化和可维护时,Zig 就会大显身手,而这些对于 AoC +> 来说都不重要。 +> +> 因此,请注意,虽然肯定能用 Zig 解决 AoC 问题,而且 Zig +> 的某些功能甚至能帮助您取得比其他语言更快的进展,但它最终还是针对软件工程进行了优化,而这并不是您在 +> AoC 中要做的事情。 + +# [Zig and Emulators]($section.id('zig-and-emulators')) + +# [Zig Reproduced Without Binaries](https://jakstys.lt/2024/zig-reproduced-without-binaries/) + +一个很有趣的实验,在 0.10 版本中,Zig 编译器实现了自举,即可以用老版本的 +Zig 来编译 Zig 源码,生成最新的 Zig +二进制。这里重新复习一下这个复杂的流程: + +之所以复杂,问题在于老版本的 Zig 从哪里来呢?对于 Zig 来说就是 +[zig1.wasm](https://github.com/ziglang/zig/blob/master/stage1/zig1.wasm),它是用没自举前的 +Zig,利用 LLVM 后端,以 wasm32-wasi 为目标生成的二进制文件。 +为了保证足够小,这里面只保留了 C +后端,这样就得到了一个小到可以放到代码仓库中的 Zig +编译器。这篇文章就是证明这个文件没有被私自篡改过! + +- 之后利用 Zig 团队自己写的 wasm2c.c 把 zig1.wasm 编译成 zig1.c,之后用 + cc 编译 zig1.c 就可以得到 stage1 的 zig 编译器 +- 之后再用 zig1 编译 zig 源码,由于 zig1 之后 C + 后端,因此这里得到的产物是 zig2.c,再利用 cc 就可以可以 stage2 的 + zig。 zig2 功能上已经完备,但是速度很慢(没有经过 LLVM 优化) +- 最后再用 zig2 继续编译 zig 源码,得到最后的 zig3,这也是我们下载 zig + 安装包时包含的版本 +- 如果再继续用 zig3 来编译 zig 源码,得到的 zig4 会和 zig3 一模一样。 + +细节可以参考: + +- [Goodbye to the C++ Implementation of + Zig](https://ziglang.org/news/goodbye-cpp/) +- [Why is the bootstrapping process so complicated? : + r/Zig](https://www.reddit.com/r/Zig/comments/142gwls/why_is_the_bootstrapping_process_so_complicated/) + +# [项目/工具]($section.id('projects-tools')) + +[Builds (Zig) - GoReleaser](https://goreleaser.com/customization/zig-builds/) +版本发布工具 GoReleaser 支持了 Zig + +[FOLLGAD/zig-ai: OpenAI SDK with streaming support](https://github.com/follgad/zig-ai) + +[A bunch of links to blog posts, articles, videos, etc for learning Zig](https://github.com/zouyee/zig-learning) + +[Super-ZIG/cli: Easy command line interface in ZIG.](https://github.com/Super-ZIG/cli) + +[deckarep/zigualizer](https://github.com/deckarep/zigualizer) +Zigualizer: A music visualizer built with Zig, powered by the FFT +algorithm. + +[freref/fancy-cat](https://github.com/freref/fancy-cat) +PDF reader for terminal emulators using the Kitty image protocol + +[Dr-Nekoma/lyceum](https://github.com/Dr-Nekoma/lyceum) +An MMO game written in Erlang (+ PostgreSQL) + Zig (+ Raylib) + +# [Zig 语言更新](https://github.com/ziglang/zig/pulls?page=1&q=+is%3Aclosed+is%3Apr+closed%3A2024-11-01..2024-12-01) diff --git a/content/monthly/_index.md b/content/monthly/_index.md deleted file mode 100644 index 5b59ecb..0000000 --- a/content/monthly/_index.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: 月刊 -type: blog -cascade: - - type: blog ---- - -社区内的最新进展,信息来源:[Zig NEWS](https://zig.news/top/month)、[Zig monthly](https://zigmonthly.org/)、[Lobsters](https://lobste.rs/t/zig)、[Reddit](https://www.reddit.com/r/Zig/)、[Zig weekly newsletter](https://discu.eu/weekly/zig/)、[Ziggit](https://ziggit.dev/)、[用户推荐](https://github.com/orgs/zigcc/discussions/new?category=%E4%BD%9C%E5%93%81%E5%88%86%E4%BA%AB) diff --git a/content/monthly/index.smd b/content/monthly/index.smd new file mode 100644 index 0000000..a592285 --- /dev/null +++ b/content/monthly/index.smd @@ -0,0 +1,12 @@ +--- +.title = "月刊", +.date = @date("2024"), +.author = "ZigCC", +.layout = "monthly.shtml", +.draft = false, +--- + +社区内的最新进展,信息来源:[Zig NEWS](https://zig.news/top/month)、[Zig +monthly](https://zigmonthly.org/)、[Lobsters](https://lobste.rs/t/zig)、[Reddit](https://www.reddit.com/r/Zig/)、[Zig +weekly +newsletter](https://discu.eu/weekly/zig/)、[Ziggit](https://ziggit.dev/)、[用户推荐](https://github.com/orgs/zigcc/discussions/new?category=%E4%BD%9C%E5%93%81%E5%88%86%E4%BA%AB) diff --git a/content/post/0.14.md b/content/post/0.14.smd similarity index 90% rename from content/post/0.14.md rename to content/post/0.14.smd index 8a78f2e..de8aa00 100644 --- a/content/post/0.14.md +++ b/content/post/0.14.smd @@ -1,21 +1,23 @@ --- -title: 0.14 版本更新介绍 -date: 2025-05-21T09:26:22+08:00 -slug: 0.14-intro +.title = "0.14 版本更新介绍", +.date = @date("2025-05-21T09:26:22+08:00"), +.author = "ZigCC", +.layout = "post.shtml", +.draft = false, --- https://ziglang.org/download/0.14.0/release-notes.html -# 发布概览 +# [发布概览]($section.id('release-overview')) Zig 0.14.0 版本是经过 **9 个月的工作**,由 **251 位不同的贡献者** 完成,包含 **3467 个提交** 的成果。该版本专注于提升 **健壮性**、**最优性** 和 **可重用性**,并通过 Zig 软件基金会 (Zig Software Foundation) 资助开发。 -# 核心主题与重要更新 +# [核心主题与重要更新]($section.id('key-topics-and-updates')) 1. **提升编译速度与开发效率:** - 版本说明强调了两个重要的长期投资:**增量编译 (Incremental Compilation)** 和 **快速 x86 后端 (fast x86 Backend)**。 -- 这两项投资的核心目标是 **“reducing edit/compile/debug cycle latency”**(减少编辑/编译/调试循环延迟)。 +- 这两项投资的核心目标是 **"reducing edit/compile/debug cycle latency"**(减少编辑/编译/调试循环延迟)。 - **增量编译** 功能在本次发布中可以通过 -fincremental 标志选择启用,但目前尚未完全成熟。它在配合文件系统监控时表现良好,尤其是在仅检查编译错误时能显著提升反馈速度。 - 引用:$ zig build -Dno-bin -fincremental --watch (展示了在大型代码库中快速获得编译错误反馈的示例)。 - 目前不兼容 usingnamespace,建议用户尽量避免使用。 @@ -51,9 +53,9 @@ Zig 0.14.0 版本是经过 **9 个月的工作**,由 **251 位不同的贡献 - **移除 @fenceStoreLoad Barriers:** 移除 @fence(.StoreLoad),其功能现在可以通过使用 SeqCst 或 Acquire/Release 原子操作来实现。 - **Packed Struct Equality 和 Packed Struct Atomics:** 允许直接对 Packed Struct 进行相等性比较和原子操作,不再需要 @bitCast 到底层整数类型。 - **@ptrCast 允许改变切片长度 (@ptrCast Allows Changing Slice Length):** #22706 -- **移除匿名结构体类型,统一元组 (Remove Anonymous Struct Types, Unify Tuples):** 重构匿名结构体字面量和元组的工作方式,使其使用“普通”结构体类型和基于 AST 节点及结构体的等价性。 +- **移除匿名结构体类型,统一元组 (Remove Anonymous Struct Types, Unify Tuples):** 重构匿名结构体字面量和元组的工作方式,使其使用"普通"结构体类型和基于 AST 节点及结构体的等价性。 - **Calling Convention 增强和 @setAlignStack 被取代 (Calling Convention Enhancements and @setAlignStack Replaced):** std.builtin.CallingConvention 现在是一个标记联合,包含更多目标平台特定的调用约定,并允许通过 CommonOptions 设置栈对齐等选项。.c 调用约定现在是一个声明,可以通过 callconv(.c) 使用 Decl Literals 访问。@setAlignStack 被移除,其功能现在通过调用约定的选项实现。 -- \*_std.builtin.Type 字段重命名和简化 (std.builtin.Type Fields Renamed and Simplify Usage Of ?const anyopaque):_ std.builtin.Type 联合体的字段名称改为小写,并增加了对 default\_value\_ptr 和 sentinel\_ptr 字段的 helper 方法,以简化使用。 +- *_std.builtin.Type 字段重命名和简化 (std.builtin.Type Fields Renamed and Simplify Usage Of ?const anyopaque):_ std.builtin.Type 联合体的字段名称改为小写,并增加了对 default\_value\_ptr 和 sentinel\_ptr 字段的 helper 方法,以简化使用。 - **不允许非标量哨兵类型 (Non-Scalar Sentinel Types Disallowed):** 哨兵值现在只能是支持 == 操作符的标量类型。 - **@FieldType 内置函数 (@FieldType builtin):** 新增 @FieldType 内置函数,用于获取给定类型和字段名称的字段类型,取代了 std.meta.FieldType 函数。 - **@src 获得 Module 字段 (@src Gains Module Field):** std.builtin.SourceLocation 结构体新增 module 字段。 @@ -72,7 +74,7 @@ Zig 0.14.0 版本是经过 **9 个月的工作**,由 **251 位不同的贡献 - **Transport Layer Security (std.crypto.tls):** #21872 - **process.Child.collectOutput API 变化 (#21872process.Child.collectOutput API Changed):** API 签名改变,现在将 allocator 作为第一个参数传入。 - **LLVM Builder API:** LLVM bitcode builder API 移至 std.zig.llvm,方便第三方项目复用。 -- **拥抱“非管理”风格容器 (Embracing "Unmanaged"-Style Containers):** 大部分带有内置 allocator 的标准库容器(如 std.ArrayList, std.ArrayHashMap)已被弃用,推荐使用“非管理”风格容器(如 std.ArrayListUnmanaged, std.ArrayHashMapUnmanaged),并在需要时显式传递 allocator。 +- **拥抱"非管理"风格容器 (Embracing "Unmanaged"-Style Containers):** 大部分带有内置 allocator 的标准库容器(如 std.ArrayList, std.ArrayHashMap)已被弃用,推荐使用"非管理"风格容器(如 std.ArrayListUnmanaged, std.ArrayHashMapUnmanaged),并在需要时显式传递 allocator。 - **std.c 重组 (std.c Reorganization):** 重组了 std.c,使其结构更清晰,并改变了对不存在符号的处理方式(从 @compileError 改为 void 或 {}),移除了标准库中最后一个 usingnamespace 的使用点。 - **弃用列表 (List of Deprecations):** 列出了大量被弃用或重命名的标准库函数和类型。 - **Binary Search:** #20927 @@ -104,7 +106,7 @@ Zig 0.14.0 版本是经过 **9 个月的工作**,由 **251 位不同的贡献 8. **Bug 修复与 Toolchain 更新 (Bug Fixes and Toolchain):** -- 关闭了 416 个 bug 报告。但版本说明坦承 **“This Release Contains Bugs”**,并指出在 1.0.0 版本达到 Tier 1 支持时会增加 bug 策略。 +- 关闭了 416 个 bug 报告。但版本说明坦承 **"This Release Contains Bugs"**,并指出在 1.0.0 版本达到 Tier 1 支持时会增加 bug 策略。 - **UBSan Runtime:** Debug 模式下默认启用 UBSan 运行时库,为 C 代码的未定义行为提供更详细的恐慌信息和堆栈跟踪。可以通过 -fno-ubsan-rt 和 -fubsan-rt 控制。 - **compiler\_rt:** 包含了优化的 memcpy 实现。 - **musl 1.2.5:** 捆绑的 musl 更新并应用了 CVE 修复和目标平台特定补丁。不再捆绑 musl 的 memcpy 文件,而是使用 Zig 的优化实现。 @@ -122,13 +124,13 @@ Zig 0.14.0 版本是经过 **9 个月的工作**,由 **251 位不同的贡献 - 最终目标是达到 1.0.0 版本,届时 Tier 1 支持将包含 bug 政策。 -# 关于 Zig 0.14.0 版本的常见问题解答 +# [关于 Zig 0.14.0 版本的常见问题解答]($section.id('faq-zig-0-14-0')) -## Zig 0.14.0 版本的主要更新和亮点是什么? +# [Zig 0.14.0 版本的主要更新和亮点是什么?]($section.id('main-updates-and-highlights')) Zig 0.14.0 版本是长达 9 个月开发工作和 3467 次提交的成果,主要亮点包括:显著增强了对多种目标平台的支持,包括 arm/thumb、mips/mips64、powerpc/powerpc64、riscv32/riscv64 和 s390x 等,许多之前存在工具链问题、标准库支持缺失或崩溃的情况现在应该可以正常工作了。此外,该版本在构建系统方面进行了大量升级,并对语言进行了多项重要改进,例如引入了 Labeled Switch 和 Decl Literals 等新特性。为了缩短编辑/编译/调试周期,版本还迈向了两个长期投资目标:增量编译和快速 x86 后端。 -## Zig 如何对不同目标平台的开发支持进行分级? +# [Zig 如何对不同目标平台的开发支持进行分级?]($section.id('target-support-tiers')) Zig 使用四层系统来对不同目标平台的支持级别进行分类,其中 Tier 1 是最高级别: @@ -137,15 +139,15 @@ Zig 使用四层系统来对不同目标平台的支持级别进行分类,其 - **Tier 3:** 编译器可以依赖外部后端(如 LLVM)为该目标平台生成机器代码。链接器可以为该目标平台生成目标文件、库和可执行文件。 - **Tier 4:** 编译器可以依赖外部后端(如 LLVM)为该目标平台生成汇编源代码。如果 LLVM 将此目标平台视为实验性,则需要从源代码构建 LLVM 和 Zig 才能使用它。 -## 什么是 Labeled Switch,它有什么优势? +# [什么是 Labeled Switch,它有什么优势?]($section.id('labeled-switch-advantages')) Labeled Switch 是 Zig 0.14.0 中引入的一项语言特性,允许 switch 语句被标记,并作为 continue 语句的目标。continue :label value 语句会用 value 替换原始的 switch 表达式操作数,并重新评估 switch。尽管在语义上类似于循环中的 switch,但 Labeled Switch 的关键优势在于其代码生成特性。它可以生成帮助 CPU 更准确预测分支的代码,从而提高热循环中的性能,特别是在处理指令分派、评估有限状态自动机 (FSA) 或执行类似基于 case 的评估时。这有助于 branch predictor 更准确地预测控制流。 -## Decl Literals 是什么,它解决了哪些问题? +# [Decl Literals 是什么,它解决了哪些问题?]($section.id('decl-literals-explanation')) Decl Literals 是 Zig 0.14.0 扩展 "enum literal" 语法 (.foo) 而引入的新特性。现在,一个枚举字面量 .foo 不仅可以引用枚举变体,还可以使用 Result Location Semantics 引用目标类型上的任何声明(const/var/fn)。这在初始化结构体字段时特别有用,可以避免重复指定类型,并有助于避免 Faulty Default Field Values 的问题,确保数据不变量不会因覆盖单个字段而受到破坏。它也支持直接调用函数来初始化值。 -## Zig 0.14.0 版本在内存分配器方面有哪些值得关注的变化? +# [Zig 0.14.0 版本在内存分配器方面有哪些值得关注的变化?]($section.id('allocator-changes')) 该版本对内存分配器进行了多项改进: @@ -154,7 +156,7 @@ Decl Literals 是 Zig 0.14.0 扩展 "enum literal" 语法 (.foo) 而引入的新 - **Allocator API Changes (remap):** std.mem.Allocator.VTable 引入了一个新的 remap 函数,允许尝试扩展或收缩内存并可能重新定位,如果无法在不执行内部 memcpy 的情况下完成,则返回 null,提示调用者自行处理复制。同时,resize 函数保持不变。Allocator.VTable 中的所有函数现在使用 std.mem.Alignment 类型代替 u8,增加了类型安全。 - **Runtime Page Size:** 移除了编译时已知的 std.mem.page\_size,代之以编译时已知的页面大小上下界 std.heap.page\_size\_min 和 std.heap.page\_size\_max。运行时获取页面大小可以使用 std.heap.pageSize(),它会优先使用编译时已知的值,否则在运行时查询操作系统并缓存结果。这修复了对 Asahi Linux 等新硬件上运行 Linux 的支持。 -## Zig 0.14.0 版本如何改进构建系统,特别是处理模块和依赖关系? +# [Zig 0.14.0 版本如何改进构建系统,特别是处理模块和依赖关系?]($section.id('build-system-improvements')) Zig 0.14.0 版本在构建系统方面有多项重要改进: @@ -164,7 +166,7 @@ Zig 0.14.0 版本在构建系统方面有多项重要改进: - **addLibrary Function:** 引入 addLibrary 函数作为 addSharedLibrary 和 addStaticLibrary 的替代,允许在 build.zig 中更容易地切换链接模式,并与 linkLibrary 函数名称保持一致。 - **Import ZON:** ZON 文件现在可以在编译时通过 @import("foo.zon") 导入,前提是结果类型已知。 -## Zig 0.14.0 版本在编译器后端和编译速度方面有哪些进展? +# [Zig 0.14.0 版本在编译器后端和编译速度方面有哪些进展?]($section.id('compiler-backend-and-speed')) 该版本在编译器后端和编译速度方面取得了进展: @@ -172,7 +174,7 @@ Zig 0.14.0 版本在构建系统方面有多项重要改进: - **Incremental Compilation:** 引入了增量编译特性,可以通过 -fincremental 标志启用。尽管尚未默认启用,但结合文件系统监听,可以显著缩短修改代码后的重新分析时间,提供快速的编译错误反馈。 - **x86 Backend:** x86 后端在行为测试套件中的通过率已接近 LLVM 后端,并且在开发时通常比 LLVM 后端提供更快的编译速度和更好的调试器支持。虽然尚未默认选中,但鼓励用户尝试使用 -fno-llvm 或在构建脚本中设置 use\_llvm = false 来启用。 -## Zig 0.14.0 版本在工具链和运行时方面有哪些值得注意的更新? +# [Zig 0.14.0 版本在工具链和运行时方面有哪些值得注意的更新?]($section.id('toolchain-and-runtime-updates')) 该版本在工具链和运行时方面也有多项更新: @@ -187,6 +189,6 @@ Zig 0.14.0 版本在构建系统方面有多项重要改进: - **Optimized memcpy:** 提供了优化的 memcpy 实现,不再捆绑 musl 的 memcpy 文件。 - **Integrated Fuzzer:** 集成了 alpha 质量的 fuzzer,可以通过 --fuzz CLI 选项使用,并提供一个 fuzzer Web UI 显示实时代码覆盖率。 -# 总结 +# [总结]($section.id('summary')) Zig 0.14.0 版本是向 1.0.0 版本迈进的重要一步,在性能优化(尤其是编译速度)、跨平台支持、语言特性和标准库方面都带来了显著改进。增量编译和快速 x86 后端是关键的长期投资,旨在提升开发者体验。新语言特性如 Labeled Switch 和 Decl Literals 提供了更强大和安全的编程模式。标准库的重组和容器的调整反映了社区的使用模式和最佳实践。构建系统也获得了重要升级,使模块管理和依赖处理更加灵活。尽管仍存在已知 bug,但 Zig 社区在本次发布中展示了活跃的开发和持续的进步。 diff --git a/content/post/2023-09-05-bog-gc-1-en.md b/content/post/2023-09-05-bog-gc-1-en.smd similarity index 96% rename from content/post/2023-09-05-bog-gc-1-en.md rename to content/post/2023-09-05-bog-gc-1-en.smd index 809c181..238d2a7 100644 --- a/content/post/2023-09-05-bog-gc-1-en.md +++ b/content/post/2023-09-05-bog-gc-1-en.smd @@ -1,15 +1,20 @@ --- -title: Bog GC Design -author: Feng Wenxuan -date: "2023-09-05T16:40:50+0800" -use-mathjax: true +.title = "Bog GC Design", +.date = @date("2023-09-05T16:40:50+0800"), +.author = "Feng Wenxuan", +.layout = "post.shtml", +.draft = false, +.custom = { + .math = true, + .mermaid = true +}, --- -# Bog GC Design +# [Bog GC Design]($section.id('bog-gc-design')) Bog is a small scripting language developed using Zig. Its GC design is inspired by a paper titled [An efficient of Non-Moving GC for Function languages](https://www.pllab.riec.tohoku.ac.jp/papers/icfp2011UenoOhoriOtomoAuthorVersion.pdf). -## Overview +# [Overview]($section.id('Overview')) 1. Introduction - Design of the Heap @@ -17,7 +22,7 @@ Bog is a small scripting language developed using Zig. Its GC design is inspired - Design of Bitmap 2. Implementation -## Introduction +# [Introduction]($section.id('Introduction')) GC stands for garbage collection, which is primarily a memory management strategy for the `heap` region. Memory allocations in the heap are done in exponentially increasing sizes, with a special sub-heap dedicated solely to very large objects. One advantage of this approach might be its efficiency in handling memory requests of various sizes. @@ -33,7 +38,8 @@ Where: 2. S: represents the free space. 3. H: is the sub-heap used for storing smaller objects. $H_i$ represents the sub-heap of size $2^i$, where each addition is twice the size of the previous. -```mermaid +```=html +
 graph TD
   A[Heap]
   B[M]
@@ -47,6 +53,7 @@ graph TD
   D --> H4
   D --> H5
   D --> Hi
+
``` ```bash @@ -64,13 +71,13 @@ graph TD +------------+ ``` -### Memory Sub-Heap Pool +## [Memory Sub-Heap Pool]($section.id('Memory Sub-Heap Pool')) We've designed a memory resource pool. This pool consists of numerous allocation segments of fixed size. It means that, regardless of how much space a sub-heap requests, it will request it in units of these fixed-size "segments". For instance, if the allocation segments in the pool are of size 1MB, then a sub-heap might request space in sizes of 1MB, 2MB, 3MB, etc., rather than requesting non-integer multiples like 1.5MB or 2.5MB. The dynamic allocation and reclaiming of space by the sub-heaps from a resource pool made up of fixed-size segments provide greater flexibility and may enhance the efficiency of memory utilization. -### Types of GC +## [Types of GC]($section.id('Types of GC')) There are many common types of GC. @@ -129,7 +136,7 @@ However, Non-Moving GC has its disadvantages: To address these problems requires many complicated steps, which won't be elaborated on here. We'll focus on Bog's GC for the explanation. -### Meta Bitmap +## [Meta Bitmap]($section.id('Meta Bitmap')) "Meta Bitmap" or "meta-level bitmaps". This is a higher-level bitmap that summarizes the contents of the original bitmap. This hierarchical structure is similar to the inode mapping in file systems or the use of multi-level page tables in computer memory management. @@ -143,11 +150,11 @@ Let's design for a 32-bit architecture. A 32-bit architecture means that the com For example, if a bitmap is 320 bits long, then on a 32-bit architecture, the worst-case scenario might require checking 10 blocks of 32 bits to find a free bit. This can be represented by log32(320), which results in 10. -### Bitmap +## [Bitmap]($section.id('Bitmap')) Since Bog's GC is essentially still based on "Mark-Sweep", using bitmaps to record data is indispensable. In Bog, we adopted the method of "bitmap records data" for GC. And to improve efficiency, we introduced the concept of meta-bitmaps, where every 4 elements correspond to a meta-bitmap, recording the occupancy status of multiple spaces, and increasing the depth based on the object age in the heap. -### Implementation +## [Implementation]($section.id('implementation')) In reality, Bog's design is a bit more complex. Here are sample in practical code: diff --git a/content/post/2023-09-05-bog-gc-1.md b/content/post/2023-09-05-bog-gc-1.smd similarity index 78% rename from content/post/2023-09-05-bog-gc-1.md rename to content/post/2023-09-05-bog-gc-1.smd index aa1d645..8245624 100644 --- a/content/post/2023-09-05-bog-gc-1.md +++ b/content/post/2023-09-05-bog-gc-1.smd @@ -1,21 +1,20 @@ --- -title: Bog GC 设计 -- 概念篇 -author: 文轩 -date: "2023-09-05T16:38:36+0800" -math: true +.title = "Bog GC 设计 -- 概念篇", +.date = @date("2023-09-05T16:38:36+0800"), +.author = "文轩", +.layout = "post.shtml", +.draft = false, +.custom = { + .math = true, + .mermaid = true, +}, --- -[Bog](https://github.com/Vexu/bog) 是一款基于 Zig 开发的小型脚本语言。它的 GC 设计受到一篇论文[An efficient of Non-Moving GC for Function languages](https://www.pllab.riec.tohoku.ac.jp/papers/icfp2011UenoOhoriOtomoAuthorVersion.pdf)的启发。 - -## 梗概 +# [Bog GC Design -- Concepts]($section.id('bog-gc-design-concepts')) -1. 概述 - - Heap 的设计 - - GC 的类别 - - Bitmap 的设计 -2. 实现 +[Bog](https://github.com/Vexu/bog) 是一款基于 Zig 开发的小型脚本语言。它的 GC 设计受到一篇论文[An efficient of Non-Moving GC for Function languages](https://www.pllab.riec.tohoku.ac.jp/papers/icfp2011UenoOhoriOtomoAuthorVersion.pdf)的启发。 -## 概述 +# [Summary]($section.id('summary')) GC 是一种垃圾回收的机制,主要是针对`heap`区域的内存管理策略。在堆中的内存分配是按照指数级增长的大小进行的,此外还有一个专门用于非常大对象的特殊子堆。这种方法的一个优点可能是它可以高效地处理各种大小的内存请求。 @@ -31,7 +30,8 @@ $$ 2. S 是空闲区域 3. H 是子堆,用于存储小对象,$H_i$表示大小为$2^i$的子堆,每次新增都为之前的两倍 -```mermaid +```=html +
 graph TD
   A[Heap]
   B[M]
@@ -45,6 +45,7 @@ graph TD
   D --> H4
   D --> H5
   D --> Hi
+
``` ```bash @@ -62,17 +63,17 @@ graph TD +------------+ ``` -### 内存子堆池 +## [Memory Sub-Heap Pool]($section.id('memory-sub-heap-pool')) -我们设计一个内存的资源池。这个池由许多固定大小的分配段组成。这意味着,无论子堆请求多少空间,它都会以这些固定大小的“段”为单位来请求。例如,如果池中的分配段大小为 1MB,那么一个子堆可能会请求 1MB、2MB、3MB 等大小的空间,而不是请求 1.5MB 或 2.5MB 这样的非整数倍的大小。 +我们设计一个内存的资源池。这个池由许多固定大小的分配段组成。这意味着,无论子堆请求多少空间,它都会以这些固定大小的"段"为单位来请求。例如,如果池中的分配段大小为 1MB,那么一个子堆可能会请求 1MB、2MB、3MB 等大小的空间,而不是请求 1.5MB 或 2.5MB 这样的非整数倍的大小。 而子堆从一个由固定大小的段组成的资源池中动态分配和回收空间,这种策略可以提供更高的灵活性,并可能提高内存使用的效率。 -### GC 的类别 +## [Types of GC]($section.id('types-of-gc')) 常见的 GC 有很多类型。 -以**位图记录数据**来说,有“代际垃圾收集 GC”。在代际垃圾收集(Generational Garbage Collection)中,"代"或"世代"并不是指位图。它们实际上是指内存中的一部分,用于存储对象。基于对象的生存周期,GC 把它们分为不同的代。这种策略背后的基本思想是,新创建的对象很快就会变为垃圾,而旧对象则可能存活得更久。 +以**位图记录数据**来说,有"代际垃圾收集 GC"。在代际垃圾收集(Generational Garbage Collection)中,"代"或"世代"并不是指位图。它们实际上是指内存中的一部分,用于存储对象。基于对象的生存周期,GC 把它们分为不同的代。这种策略背后的基本思想是,新创建的对象很快就会变为垃圾,而旧对象则可能存活得更久。 一般来说,在代际 GC 中,有两个主要的代: @@ -82,22 +83,22 @@ graph TD 位图在这里是一个工具,用于跟踪和管理每一代中哪些对象是活跃的(即仍在使用中)和哪些是垃圾。当算法扩展为代际 GC 时,可以为同一个堆空间的不同代维护多个位图。这样,每个代的活动和非活动对象都可以被单独地跟踪。 -“为新生代维护一个位图,为老年代维护另一个位图”。这使得在进行垃圾收集时,我们可以单独地考虑每一个代,从而优化垃圾收集的效率和性能。 +"为新生代维护一个位图,为老年代维护另一个位图"。这使得在进行垃圾收集时,我们可以单独地考虑每一个代,从而优化垃圾收集的效率和性能。 -以是否**移动旧有的数据**来说,有“移动 GC”和“非移动 GC”。移动 GC 会将存活的对象移动到新的内存地址、压缩内存,而非移动 GC 则不会移动存活的对象,可以无缝由其他语言来调用内存里的数据。 +以是否**移动旧有的数据**来说,有"移动 GC"和"非移动 GC"。移动 GC 会将存活的对象移动到新的内存地址、压缩内存,而非移动 GC 则不会移动存活的对象,可以无缝由其他语言来调用内存里的数据。 -在这种移动 GC 中,有“分代复制收集器”和“Cheney 复制收集器”。 +在这种移动 GC 中,有"分代复制收集器"和"Cheney 复制收集器"。 -分代复制收集器(Generational Copying Collector): 是垃圾收集的一种常见方法,特别是在函数式编程语言中。它假设新创建的对象很快就会变得不可达(即“死亡”),而老的对象则更可能持续存在。因此,内存被分成两个或更多的“代”,新对象在“新生代”中创建,当它们存活足够长的时间时,它们会被移到“老生代”。 +分代复制收集器(Generational Copying Collector): 是垃圾收集的一种常见方法,特别是在函数式编程语言中。它假设新创建的对象很快就会变得不可达(即"死亡"),而老的对象则更可能持续存在。因此,内存被分成两个或更多的"代",新对象在"新生代"中创建,当它们存活足够长的时间时,它们会被移到"老生代"。 -Cheney 的拷贝收集器: 是一种用于半区(semi-space)的拷贝垃圾收集器。它的工作原理是将可用内存分为两半,并且只在其中一半中分配对象。当这一半用完时,收集器通过拷贝活跃对象到另一半空间来进行垃圾收集。然后,原先的那一半空间就完全清空,成为新的可用空间。Cheney 的收集器特别适用于处理短生命周期的数据,因为它可以快速地只拷贝活跃的数据,而忽略死亡的数据。这使得它在处理大量短生命周期数据的程序(例如函数式程序)时,对于其“次要收集”(minor collection,即仅仅回收新生代数据的收集)非常高效。**这种方法的优势在于它可以有效地处理内存碎片,因为通过复制活动对象到新位置,内存会被连续地占用。** +Cheney 的拷贝收集器: 是一种用于半区(semi-space)的拷贝垃圾收集器。它的工作原理是将可用内存分为两半,并且只在其中一半中分配对象。当这一半用完时,收集器通过拷贝活跃对象到另一半空间来进行垃圾收集。然后,原先的那一半空间就完全清空,成为新的可用空间。Cheney 的收集器特别适用于处理短生命周期的数据,因为它可以快速地只拷贝活跃的数据,而忽略死亡的数据。这使得它在处理大量短生命周期数据的程序(例如函数式程序)时,对于其"次要收集"(minor collection,即仅仅回收新生代数据的收集)非常高效。**这种方法的优势在于它可以有效地处理内存碎片,因为通过复制活动对象到新位置,内存会被连续地占用。** 特点: - **任何精确的 copy gc 都需要 runtime 系统定位和更新每个堆分配数据的所有指针** - 在传统的垃圾收集策略(移动 GC)中,压缩是一种常用的技术,它会将活跃的对象移到内存的一个连续区域中,从而释放出未使用的内存。换言之,就是整理内存碎片。 -在非移动 GC 中,有“标记-清除”。 +在非移动 GC 中,有"标记-清除"。 **不需要进行压缩和对象移动这一特性是非常重要**,指针的值(即对象的内存地址)是固定的,也不需要花时间更新移动的地址。这使得非移动 GC 非常适合于需要与其他语言进行交互的语言,因为它们可以在不需要额外的工作的情况下访问内存中的对象。而且不需要移动对象的这一特性对于支持多原生线程也是有益的。在多线程环境中,如果对象在内存中的位置不断移动,那么线程之间的协调和同步将变得更加复杂。因此,避免对象移动可以简化多线程编程。 @@ -122,9 +123,9 @@ Cheney 的拷贝收集器: 是一种用于半区(semi-space)的拷贝垃圾 为了解决这些问题需要很多复杂的步骤,在此不多赘述。单以 Bog 的 GC 来讲解。 -### Meta Bitmap +## [Meta Bitmap]($section.id('meta-bitmap')) -“元级位图”或“meta-level bitmaps”。这是一个更高级别的位图,用于汇总原始位图的内容。这种层次化的结构类似于文件系统中的 inode 映射或多级页表在计算机内存管理中的使用。 +"元级位图"或"meta-level bitmaps"。这是一个更高级别的位图,用于汇总原始位图的内容。这种层次化的结构类似于文件系统中的 inode 映射或多级页表在计算机内存管理中的使用。 例如,考虑一个简单的位图:`1100 1100`。一个元级位图可能表示每 4 位中有多少个空闲块。在这种情况下,元级位图可能是 `1021`(表示第一个 4 位中有 1 个空闲块,第二个 4 位中有 2 个空闲块,以此类推)。 @@ -136,11 +137,11 @@ Cheney 的拷贝收集器: 是一种用于半区(semi-space)的拷贝垃圾 例如,如果一个位图有 320 位,那么在 32 位架构上,最坏的情况可能需要检查 10 个 32 位块才能找到一个空闲位。这可以通过 $\log_{32}(320)$来表示,结果是 10。 -### Bitmap +## [Bitmap]($section.id('bitmap')) -由于 Bog 的 GC 本质上还是采用了“标记-清除”,所以利用位图来记录数据是必不可少的。在 Bog 中,我们采用了“位图记录数据”的方式来进行 GC。而为了提高效率,我们增加了元位图的概念,即每 4 个元素对应一个元位图,用于记录多空间的占用状态,并且根据 heap 的对象时间增加深度。 +由于 Bog 的 GC 本质上还是采用了"标记-清除",所以利用位图来记录数据是必不可少的。在 Bog 中,我们采用了"位图记录数据"的方式来进行 GC。而为了提高效率,我们增加了元位图的概念,即每 4 个元素对应一个元位图,用于记录多空间的占用状态,并且根据 heap 的对象时间增加深度。 -### 实现 +## [Implementation]($section.id('implementation')) 实际上,在 Bog 的设计中,要更加复杂一些。我们增加了 diff --git a/content/post/2023-09-05-hello-world.md b/content/post/2023-09-05-hello-world.md deleted file mode 100644 index 0cce8a6..0000000 --- a/content/post/2023-09-05-hello-world.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: 欢迎 Zig 爱好者向本网站供稿 -author: 刘家财 -date: "2023-09-05T16:13:13+0800" ---- - -欢迎社区用户向 ZigCC 供稿(关于 Zig 的任何话题),方便与社区更多人分享。文章会发布在: - -- [ZigCC 网站](https://ziglang.cc) -- [ZigCC 公众号](https://github.com/zigcc/.github/raw/main/zig_mp.png) - -# 供稿方式 - -1. Fork 仓库 https://github.com/zigcc/zigcc.github.io -2. 在 `content/post` 内添加自己的文章(md 或 org 格式均可),文件命名为: `${YYYY}-${MM}-${DD}-${SLUG}.md` -3. 文件开始需要包含一些描述信息,例如[本文件](https://github.com/zigcc/zigcc.github.io/tree/main/content/post/2023-09-05-hello-world.md)中的: - -```plain ---- -title: 欢迎 Zig 爱好者向本网站供稿 -author: 刘家财 -date: '2023-09-05T16:13:13+0800' ---- -``` - -## 本地预览 - -在写完文章后,可以使用 [Hugo](https://gohugo.io/) 进行本地预览,只需在项目根目录执行 `hugo server`,这会启动一个 HTTP 服务,默认的访问地址是: http://localhost:1313/ diff --git a/content/post/2023-09-05-hello-world.smd b/content/post/2023-09-05-hello-world.smd new file mode 100644 index 0000000..7df8808 --- /dev/null +++ b/content/post/2023-09-05-hello-world.smd @@ -0,0 +1,36 @@ +--- +.title = "欢迎 Zig 爱好者向本网站供稿", +.date = @date("2023-09-05T16:13:13+0800"), +.author = "刘家财", +.layout = "post.shtml", +.draft = false, +--- + +欢迎社区用户向 ZigCC 供稿(关于 Zig 的任何话题),方便与社区更多人分享。文章会发布在: + +- [ZigCC 网站](https://ziglang.cc) +- [ZigCC 公众号](https://github.com/zigcc/.github/raw/main/zig_mp.png) + +# [供稿方式]($section.id('contribute')) + +1. Fork 仓库 https://github.com/zigcc/zigcc.github.io +2. 在 `content/post` 内添加自己的文章(smd格式),文件命名为: `${YYYY}-${MM}-${DD}-${SLUG}.smd` +3. 文件开始需要包含一些描述信息,例如: + +``` +--- +.title = "文章标题", +.date = @date("2025-06-05T16:00:00+0800"), +.author = "刘家财", +.layout = "post.shtml", +.draft = false, +.custom = { + .math = true, // 如果你要用到数学公式,请 设置 math 为 true; 否则可以忽略 + .mermaid = true, // 如果你要用到 mermaid 图表,请设置 mermaid 为 true; 否则可以忽略 +}, +--- +``` + +# [本地预览]($section.id('local-preview')) + +在写完文章后,可以使用 [zine](https://zine-ssg.io/) 进行本地预览,只需在项目根目录执行 `zine`,这会启动一个 HTTP 服务,默认的访问地址是: http://localhost:1990/ diff --git a/content/post/2023-09-21-zig-midi.md b/content/post/2023-09-21-zig-midi.smd similarity index 95% rename from content/post/2023-09-21-zig-midi.md rename to content/post/2023-09-21-zig-midi.smd index 6cd9b03..c79e869 100644 --- a/content/post/2023-09-21-zig-midi.md +++ b/content/post/2023-09-21-zig-midi.smd @@ -1,10 +1,12 @@ --- -title: Zig音频之MIDI —— 源码解读 -author: 文轩 -date: "2023-09-21T23:15:02+0800" +.title = "Zig音频之MIDI —— 源码解读", +.date = @date("2023-09-21T23:15:02+0800"), +.author = "文轩", +.layout = "post.shtml", +.draft = false, --- -MIDI 是“乐器数字接口”的缩写,是一种用于音乐设备之间通信的协议。而 [zig-midi](https://github.com/Hejsil/zig-midi) 主要是在对 MIDI 的元数据、音频头等元数据进行一些处理的方法上进行了集成。 +MIDI 是"乐器数字接口"的缩写,是一种用于音乐设备之间通信的协议。而 [zig-midi](https://github.com/Hejsil/zig-midi) 主要是在对 MIDI 的元数据、音频头等元数据进行一些处理的方法上进行了集成。 ```bash . @@ -21,11 +23,11 @@ MIDI 是“乐器数字接口”的缩写,是一种用于音乐设备之间通 ├── midi.zig ``` -## 基础 +# [基础]($section.id('basic')) 在 MIDI 协议中,`0xFF` 是一个特定的状态字节,用来表示元事件(Meta Event)的开始。元事件是 MIDI 文件结构中的一种特定消息,通常不用于实时音频播放,但它们包含有关 MIDI 序列的元数据,例如序列名称、版权信息、歌词、时间标记、速度(BPM)更改等。 -以下是一些常见的元事件类型及其关联的 `0xFF` 后的字节: +以下是一些常见的元事件类型及其关联的 `0xFF`后的字节: - `0x00`: 序列号 (Sequence Number) - `0x01`: 文本事件 (Text Event) @@ -54,7 +56,7 @@ MIDI 是“乐器数字接口”的缩写,是一种用于音乐设备之间通 元事件主要存在于 MIDI 文件中,特别是在标准 MIDI 文件 (SMF) 的上下文中。在实时 MIDI 通信中,元事件通常不会被发送,因为它们通常不会影响音乐的实际播放。 -## Midi.zig +# [Midi.zig]($section.id('Midi.zig')) 本文件主要是处理 MIDI 消息的模块,为处理 MIDI 消息提供了基础结构和函数。 @@ -192,7 +194,7 @@ pub const Message = struct { - value 和 setValue 函数:用于获取和设置 MIDI 消息的值字段。 - Kind 枚举:定义了 MIDI 消息的所有可能种类,包括通道事件和系统事件。 -### midi 消息结构 +## [midi 消息结构]($section.id('midi 消息结构')) 我们需要先了解 MIDI 消息的一些背景。 @@ -209,7 +211,7 @@ pub const Message = struct { 4. **设置值**:`message.values = .{ ... }` 将这两个 7 位的值设置到 `message.values` 中。 -### 事件 +## [事件]($section.id('事件')) 针对事件,我们看 enum。 @@ -249,7 +251,7 @@ pub const Message = struct { 以下是对每个枚举成员的简要说明: -#### 频道事件 (Channel events) +### [频道事件 (Channel events)]($section.id('频道事件 (Channel events)')) 1. **NoteOff**:这是一个音符结束事件,表示某个音符不再播放。 2. **NoteOn**:这是一个音符开始事件,表示开始播放某个音符。 @@ -259,7 +261,7 @@ pub const Message = struct { 6. **ChannelPressure**:频道压力事件,与多声道键盘压力相似,但它适用于整个频道,而不是特定音符。 7. **PitchBendChange**:音高弯曲变更事件,表示音符音高的上升或下降。 -#### 系统事件 (System events) +### [系统事件 (System events)]($section.id('系统事件 (System events)')) 1. **ExclusiveStart**:独占开始事件,标志着一个独占消息序列的开始。 2. **MidiTimeCodeQuarterFrame**:MIDI 时间码四分之一帧,用于同步与其他设备。 @@ -274,11 +276,11 @@ pub const Message = struct { 11. **ActiveSensing**:活动感知事件,是一种心跳信号,表示设备仍然在线并工作。 12. **Reset**:重置事件,用于将设备重置为其初始状态。 -#### 其他 +### [其他]($section.id('其他')) 1. **Undefined**:未定义事件,可能表示一个未在此枚举中定义的或无效的 MIDI 事件。 -## decode.zig +# [decode.zig]($section.id('decode.zig')) 本文件是对 MIDI 文件的解码器, 提供了一组工具,可以从不同的输入源解析 MIDI 文件的各个部分。这样可以方便地读取和处理 MIDI 文件。 @@ -486,7 +488,7 @@ pub fn file(reader: anytype, allocator: *mem.Allocator) !midi.File { } ``` -1. statusByte: 解析 MIDI 消息的首个字节,来确定是否这是一个状态字节,还是一个数据字节。将一个字节 b 解码为一个 u7 类型的 MIDI 状态字节,如果字节 b 不是一个状态字节,则返回 null。换句话说,midi 的消息是 14 位,如果高 7 位不为空,则是 midi 消息的状态字节。在 MIDI 协议中,消息的首个字节通常是状态字节,但也可能用之前的状态字节(这称为“运行状态”)来解释接下来的字节。因此,这段代码需要确定它是否读取了一个新的状态字节,或者它是否应该使用前一个消息的状态字节。 +1. statusByte: 解析 MIDI 消息的首个字节,来确定是否这是一个状态字节,还是一个数据字节。将一个字节 b 解码为一个 u7 类型的 MIDI 状态字节,如果字节 b 不是一个状态字节,则返回 null。换句话说,midi 的消息是 14 位,如果高 7 位不为空,则是 midi 消息的状态字节。在 MIDI 协议中,消息的首个字节通常是状态字节,但也可能用之前的状态字节(这称为"运行状态")来解释接下来的字节。因此,这段代码需要确定它是否读取了一个新的状态字节,或者它是否应该使用前一个消息的状态字节。 2. readDataByte: 从 reader 中读取并返回一个数据字节。如果读取的字节不符合数据字节的规定,则抛出 InvalidDataByte 错误。 3. message: 从 reader 读取并解码一个 MIDI 消息。如果读取的字节不能形成一个有效的 MIDI 消息,则抛出 InvalidMessage 错误。这是一个复杂的函数,涉及到解析 MIDI 消息的不同种类。 4. chunk,chunkFromBytes: 这两个函数从 reader 或直接从字节数组 bytes 中解析一个 MIDI 文件块头。 @@ -496,7 +498,7 @@ pub fn file(reader: anytype, allocator: *mem.Allocator) !midi.File { 8. trackEvent: 从 reader 中解析一个 MIDI 轨道事件。它可以是 MIDI 消息或元事件。 9. file: 用于从 reader 解码一个完整的 MIDI 文件。它首先解码文件头,然后解码所有的文件块。这个函数会返回一个表示 MIDI 文件的结构体。 -### message 解析 +## [message 解析]($section.id('message 解析')) ```zig const status_byte = if (statusByte(first_byte.?)) |status_byte| blk: { @@ -510,7 +512,7 @@ const status_byte = if (statusByte(first_byte.?)) |status_byte| blk: { } else return error.InvalidMessage; ``` -这段代码的目的是确定 MIDI 消息的状态字节。它可以是从 `reader` 读取的当前字节,或者是从前一个 MIDI 消息中获取的。这样做是为了支持 MIDI 协议中的“运行状态”,在该协议中,连续的 MIDI 消息可能不会重复状态字节。 +这段代码的目的是确定 MIDI 消息的状态字节。它可以是从 `reader` 读取的当前字节,或者是从前一个 MIDI 消息中获取的。这样做是为了支持 MIDI 协议中的"运行状态",在该协议中,连续的 MIDI 消息可能不会重复状态字节。 1. `const status_byte = ...;`: 这是一个常量声明。`status_byte` 将保存 MIDI 消息的状态字节。 @@ -529,7 +531,7 @@ const status_byte = if (statusByte(first_byte.?)) |status_byte| blk: { 4. `else return error.InvalidMessage;`: 如果 `first_byte` 不是状态字节,并且不存在前一个消息,那么返回一个 `InvalidMessage` 错误。 -## encode.zig +# [encode.zig]($section.id('encode.zig')) 本文件用于将 MIDI 数据结构编码为其对应的二进制形式。具体来说,它是将内存中的 MIDI 数据结构转换为 MIDI 文件格式的二进制数据。 @@ -670,7 +672,7 @@ pub fn file(writer: anytype, f: midi.File) !void { - file 函数:这是主函数,用于将整个 MIDI 文件数据结构编码为其二进制形式。它首先编码文件头,然后循环编码每个块和块中的事件。 -### int 函数 +## [int 函数]($section.id('int 函数')) ```zig @@ -716,7 +718,7 @@ pub fn int(writer: anytype, i: u28) !void { - `@intFromBool(!is_first)`: 这是将上一步得到的布尔值转换为整数。在许多编程语言中,true 通常被视为 1,false 被视为 0。在 Zig 中,这种转换不是隐式的,所以需要用`@intFromBool()`函数来进行转换 - `@as(u8, 1 << 7)`: 这里是将数字 128(从 1 << 7 得到)显式地转换为一个 8 位无符号整数。 - `(@as(u8, 1 << 7) * @intFromBool(!is_first))`: 将转换后的数字 128 与从布尔转换得到的整数(0 或 1)相乘。如果`is_first`为`true`(即这是第一个字节),那么整个表达式的值为 0。如果`is_first为false`(即这不是第一个字节),那么整个表达式的值为 128(`1000 0000` in 二进制)。 - - 这种结构在 MIDI 变长值的编码中很常见。MIDI 变长值的每个字节的最高位被用作“继续”位,指示是否有更多的字节跟随。如果最高位是 1,那么表示还有更多的字节;如果是 0,表示这是最后一个字节。 + - 这种结构在 MIDI 变长值的编码中很常见。MIDI 变长值的每个字节的最高位被用作"继续"位,指示是否有更多的字节跟随。如果最高位是 1,那么表示还有更多的字节;如果是 0,表示这是最后一个字节。 - 在每次迭代中,它提取`tmp`的最后 7 位并将其编码为一个字节,最高位根据是否是第一个字节来设置(如果是第一个字节,则为 0,否则为 1)。 - 然后,整数右移 7 位,以处理下一个字节。 - 请注意,这种编码方式实际上是从低字节到高字节的反向方式,所以接下来需要翻转这些字节。 @@ -729,7 +731,7 @@ pub fn int(writer: anytype, i: u28) !void { - 使用提供的`writer`将翻转后的字节写入到目标位置。 -## file.zig +# [file.zig]($section.id('file.zig')) 主要目的是为了表示和处理 MIDI 文件的不同部分,以及提供了一个迭代器来遍历 MIDI 轨道的事件。 @@ -910,7 +912,7 @@ pub const TrackIterator = struct { - 定义了一个 Result 结构来返回事件和关联的数据。 - 提供了一个`next`方法来读取下一个事件。 -## Build.zig +# [Build.zig]($section.id('build-zig')) buid.zig 是一个 Zig 构建脚本(build.zig),用于配置和驱动 Zig 的构建过程。 @@ -960,7 +962,7 @@ pub fn build(b: *Builder) void { const test_all_step = b.step("test", "Run all tests in all modes."); ``` -- 使用 b.step()方法定义了一个名为 test 的步骤。描述是“在所有模式下运行所有测试”。 +- 使用 b.step()方法定义了一个名为 test 的步骤。描述是"在所有模式下运行所有测试"。 ```zig inline for (@typeInfo(std.builtin.Mode).Enum.fields) |field| {} diff --git a/content/post/2023-10-14-zig-version-manager.org b/content/post/2023-10-14-zig-version-manager.org deleted file mode 100644 index bfd49d7..0000000 --- a/content/post/2023-10-14-zig-version-manager.org +++ /dev/null @@ -1,92 +0,0 @@ -#+TITLE: Zig 多版本管理 -#+DATE: 2023-10-14T09:23:41+0800 -#+LASTMOD: 2024-08-18T12:04:00+0800 - -由于 Zig 还在快速开发迭代中,因此项目很有可能出现新版本 Zig 无法编译的情况,这时候一方面可以跟踪上游进展,看看是否有 workaround,另一个就是使用固定的版本来开发这个项目,显然这种方式更靠谱一些,因此这篇文章就来介绍一些管理多个 Zig 版本的方式。 - -* Zig version manager -现在 Zig 的版本管理工具主要有如下几个: -- [[https://github.com/marler8997/zigup][marler8997/zigup]] :: Download and manage zig compilers -- [[https://github.com/tristanisham/zvm][tristanisham/zvm]] :: Lets you easily install/upgrade between different versions of Zig -- [[https://github.com/hendriknielaender/zvm][hendriknielaender/zvm]] :: Fast and simple zig version manager - -他们工作方式类似,大致步骤: -1. 从 [[https://ziglang.org/download/index.json][index.json]] 解析所有版本,然后根据当前系统架构确定要安装的二进制, -2. 创建一个类似 =current= 软链用来表示当前的 Zig 安装目录, -3. 根据项目下 =.zig-version= 文件中指定的版本,修改 =current= 软链的指向,保证 =PATH= 中的 Zig 版本是正确的 - -相关实现: -- https://github.com/tristanisham/zvm/blob/639dca34b4b1dcbf881fd684020222d8161e4f7a/cli/use.go#L38 -- https://github.com/hendriknielaender/zvm/blob/e0b1bedf1aea58c1627a983a8ef7fd8857a2ee80/src/alias.zig#L13 - -* 通用版本管理工具 asdf -#+begin_quote -鉴于社区之前的 [[https://github.com/asdf-community/asdf-zig][asdf-zig]] 已经年久失修,zigcc 已经 fork 过来,对下载的软件包增加了 checksum 校验,防止出现中间人攻击,欢迎大家使用。 -- https://github.com/zigcc/asdf-zig -#+end_quote -多版本管理是个常见的需求,比如 Python 中的 [[https://github.com/pyenv/pyenv][pyenv]]、Ruby 中的 [[https://rvm.io/][rvm]],甚至还有一个通用的框架:[[https://asdf-vm.com/][asdf]],名字简单暴力,敲起来得心应手。安装方式可以参考官方文档的 [[https://asdf-vm.com/guide/getting-started.html][Getting Started]]。 - -它们的工作原理也都比较类似,通过修改 Shell 中的环境变量实现。在执行具体命令(比如:python、zig)时,会拦截到一个中转的工具(学名叫 [[https://en.wikipedia.org/wiki/Shim_(computing)][shims]],翻译为“垫片”),由它来确定要执行的版本(比如项目根目录的 =.python-version= ),然后将实际参数派发过去。 - -社区也有 Zig 的插件,安装也比较简单: -#+begin_src bash -asdf plugin-add zig https://github.com/asdf-community/asdf-zig.git -#+end_src -** 常用命令 -#+begin_src bash -# 列举所有可安装的版本 -asdf list-all zig - -asdf install zig -asdf uninstall zig -# 设置全局默认版本,会写到 $HOME/.tool-versions 文件 -asdf global zig -# 设置当前目录使用的版本,会写到 $(pwd)/.tool-versions 文件 -asdf local zig -#+end_src - -这里说明一点,可以使用 =asdf install zig master= 的方式来安装 master 分支的 Zig,但是由于 Zig 的 master 一直在变,因此本次安装的版本可以会滞后,一个简单的办法是先卸载,再重新安装。 - -如果想保留,可以手动把 master 目录改个名字,然后修改 zig 的 shims 让其识别到这个版本,之后就可以继续安装最新的 master 版本: -#+begin_src bash -$ tree -L 1 ~/.asdf/installs/zig -installs/zig -├──0.11.0 -├──0.12.0-dev.891+2254882eb -└──master - -$ cat ~/.asdf/shims/zig -#!/usr/bin/env bash -# asdf-plugin: zig 0.11.0 -# asdf-plugin: zig master -# asdf-plugin: zig 0.12.0-dev.891+2254882eb -exec /opt/homebrew/Cellar/asdf/0.13.1/libexec/bin/asdf exec "zig" "$@" # asdf_allow: ' asdf ' -#+end_src -上面的 =0.12.0-dev.891+2254882eb= 即是从 master 重命名出来的版本。下面这个脚本可以自动把 master 的版本固定下来: -#+begin_src bash -V=$(zig version) - -mv ~/.asdf/installs/zig/master ~/.asdf/installs/zig/${V} - -# 如果是 Linux,直接用 sed -i 就好了,不需要后面的引号,macOS 上需要 -sed -i '' "1a\\ -# asdf-plugin: zig ${V} -" ~/.asdf/shims/zig -#+end_src - -** 问题排查 -asdf 现在不支持 verbose 选项,因此安装过程中如果卡在某个地方,没法排查。一般来说,主要是下载 tar 包慢了,毕竟这取决于网络环境,可以这么改一下 [[https://github.com/asdf-community/asdf-zig/blob/51876973b89c5919bb20a3b7a7ce71990f7f6a5e/bin/install#L67][install 文件]]: -#+begin_src diff - echo "∗ Downloading and installing Zig..." -- curl --fail --silent --location --create-dirs --output "$source_path" "$download_url" -+ curl --fail --progress-bar --location --create-dirs --output "$source_path" "$download_url" - tar -xf "$source_path" -C "$install_path" --strip-components=1 -#+end_src - -这样就可以看到进度了: -#+begin_src bash -curl --fail --progress-bar --location --create-dirs --output \ - ~/.asdf/installs/zig/master/zig-macos-aarch64-master.tar.xz \ - https://ziglang.org/builds/zig-macos-aarch64-0.12.0-dev.1127+32bc07767.tar.xz -##################################### 27.8% -#+end_src diff --git a/content/post/2023-12-24-zig-build-explained-part1.md b/content/post/2023-12-24-zig-build-explained-part1.smd similarity index 95% rename from content/post/2023-12-24-zig-build-explained-part1.md rename to content/post/2023-12-24-zig-build-explained-part1.smd index 000ed23..7fba69d 100644 --- a/content/post/2023-12-24-zig-build-explained-part1.md +++ b/content/post/2023-12-24-zig-build-explained-part1.smd @@ -1,7 +1,9 @@ --- -title: zig 构建系统解析 - 第一部分 -author: Reco -date: "2023-12-24T19:15:02+0800" +.title = "zig 构建系统解析 - 第一部分", +.date = @date("2023-12-24T19:15:02+0800"), +.author = "Reco", +.layout = "post.shtml", +.draft = false, --- > - 原文链接: https://zig.news/xq/zig-build-explained-part-1-59lf @@ -13,11 +15,11 @@ Zig 构建系统仍然缺少文档,对很多人来说,这是不使用它的 我们将从一个刚刚初始化的 Zig 项目开始,逐步深入到更复杂的项目。在此过程中,我们将学习如何使用库和软件包、添加 C 代码,甚至如何创建自己的构建步骤。 -## 免责声明 +# [免责声明]($section.id('免责声明')) 由于我不会解释 Zig 语言的语法或语义,因此我希望你至少已经有了一些使用 Zig 的基本经验。我还将链接到标准库源代码中的几个要点,以便您了解所有这些内容的来源。我建议你阅读编译系统的源代码,因为如果你开始挖掘编译脚本中的函数,大部分内容都不言自明。所有功能都是在标准库中实现的,不存在隐藏的构建魔法。 -## 开始 +# [开始]($section.id('开始')) 我们通过新建一个文件夹来创建一个新项目,并在该文件夹中调用 zig init-exe。 @@ -54,7 +56,7 @@ pub fn build(b: *std.Build) void { } ``` -## 基础知识 +# [基础知识]($section.id('基础知识')) 构建系统的核心理念是,Zig 工具链将编译一个 Zig 程序 (build.zig),该程序将导出一个特殊的入口点(`pub fn build(b: *std.build.Builder) void`),当我们调用 `zig build` 时,该入口点将被调用。 @@ -93,7 +95,7 @@ Step 遵循与 std.mem.Allocator 相同的接口模式,需要实现一个 make 现在,我们需要创建一个稍正式的 Zig 程序: -## 编译 Zig 源代码 +# [编译 Zig 源代码]($section.id('编译 Zig 源代码')) 要使用编译系统编译可执行文件,编译器需要使用函数 Builder.addExecutable,它将为我们创建一个新的 LibExeObjStep。这个步骤实现是 zig build-exe、zig build-lib、zig build-obj 或 zig test 的便捷封装,具体取决于初始化方式。本文稍后将对此进行详细介绍。 @@ -116,7 +118,7 @@ pub fn build(b: *std.build.Builder) void { 这将始终在当前机器的调试模式下编译,因此对于初学者来说,这可能就足够了。但如果你想开始发布你的项目,你可能需要启用交叉编译: -## 交叉编译 +# [交叉编译]($section.id('交叉编译')) 交叉编译是通过设置程序的目标和编译模式来实现的 @@ -161,7 +163,7 @@ pub fn build(b: *std.build.Builder) void { 现在,如果你调用 zig build --help 命令,就会在输出中看到以下部分,而之前这部分是空的: -```plain +```bash Project-Specific Options: -Dtarget=[string] The CPU architecture, OS, and ABI to build for -Dcpu=[string] Target CPU features to add or subtract @@ -175,7 +177,7 @@ Project-Specific Options: 前两个选项由 standardTargetOptions 添加,其他选项由 standardOptimizeOption 添加。现在,我们可以在调用构建脚本时使用这些选项: -```plain +``` zig build -Dtarget=x86_64-windows-gnu -Dcpu=athlon_fx zig build -Doptimize=ReleaseSafe zig build -Doptimize=ReleaseSmall @@ -185,7 +187,7 @@ zig build -Doptimize=ReleaseSmall 但我们仍然必须调用 zig build 编译,因为默认调用仍然没有任何作用。让我们改变一下! -## 安装工件 +# [安装工件]($section.id('安装工件')) 要安装任何东西,我们必须让它依赖于构建器的安装步骤。该步骤是已创建的,可通过 Builder.getInstallStep() 访问。我们还需要创建一个新的 InstallArtifactStep,将我们的 exe 文件复制到安装目录(通常是 zig-out) @@ -214,7 +216,7 @@ pub fn build(b: *std.build.Builder) void { 现在,当你调用 zig build 时,你会看到一个新的目录 zig-out 被创建了.看起来有点像这样: -```plain +``` zig-out └── bin └── fresh @@ -222,7 +224,7 @@ zig-out 现在运行 ./zig-out/bin/fresh,就能看到这条信息: -```plain +``` info: All your codebase are belong to us. ``` @@ -252,7 +254,7 @@ pub fn build(b: *std.build.Builder) void { 现在,从理解初始构建脚本到完全扩展,还缺少一个部分: -## 运行已构建的应用程序 +# [运行已构建的应用程序]($section.id('运行已构建的应用程序')) 为了开发用户体验和一般便利性,从构建脚本中直接运行程序是非常实用的。这通常是通过运行步骤实现的,可以通过 zig build run 调用。 @@ -287,7 +289,7 @@ RunStep 有几个函数可以为执行进程的 argv 添加值: 现在,当我们调用 zig build run 时,我们将看到与自己运行已安装的 exe 相同的输出: -```plain +``` info: All your codebase are belong to us. ``` @@ -322,11 +324,11 @@ pub fn build(b: *std.build.Builder) void { 这样就可以在 cli 上的 -- 后面传递参数: -```plain +```bash zig build run -- -o foo.bin foo.asm ``` -## 结论 +# [结论]($section.id('conclusion')) 本系列的第一章应该能让你完全理解本文开头的构建脚本,并能创建自己的构建脚本。 diff --git a/content/post/2023-12-28-zig-build-explained-part2.md b/content/post/2023-12-28-zig-build-explained-part2.smd similarity index 94% rename from content/post/2023-12-28-zig-build-explained-part2.md rename to content/post/2023-12-28-zig-build-explained-part2.smd index 5683d53..44a44bd 100644 --- a/content/post/2023-12-28-zig-build-explained-part2.md +++ b/content/post/2023-12-28-zig-build-explained-part2.smd @@ -1,21 +1,23 @@ --- -title: zig 构建系统解析 - 第二部分 -author: Reco -date: "2023-12-24T19:15:02+0800" +.title = "zig 构建系统解析 - 第二部分", +.date = @date("2023-12-24T19:15:02+0800"), +.author = "Reco", +.layout = "post.shtml", +.draft = false, --- > - 原文链接: https://zig.news/xq/zig-build-explained-part-2-1850 > - API 适配到 Zig 0.11.0 版本 -## 注释 +# [注释]($section.id('注释')) -从现在起,我将只提供一个最精简的 build.zig,用来说明解决一个问题所需的步骤。如果你想了解如何将所有这些文件粘合到一个构建文件中,请阅读本系列[第一篇文章](/post/2023/12/24/zig-build-explained-part1/)。 +从现在起,我将只提供一个最精简的 build.zig,用来说明解决一个问题所需的步骤。如果你想了解如何将所有这些文件粘合到一个构建文件中,请阅读本系列[第一篇文章](2023-12-24-zig-build-explained-part1)。 -## 在命令行上编译 C 代码 +# [在命令行上编译 C 代码]($section.id('在命令行上编译 C 代码')) Zig 有两种编译 C 代码的方法,而且这两种很容易混淆。 -### 使用 zig cc +## [使用 zig cc]($section.id('使用 zig cc')) Zig 提供了 LLVM c 编译器 clang。第一种是 zig cc 或 zig c++,它是与 clang 接近 1:1 的前端。由于我们无法直接从 build.zig 访问这些功能(而且我们也不需要!),所以我将在快速的介绍这个主题。 @@ -23,7 +25,7 @@ Zig 提供了 LLVM c 编译器 clang。第一种是 zig cc 或 zig c++,它是 假设我们有一个由 main.c 和 buffer.c 生成的项目,我们可以用下面的命令行来构建它: -```plain +``` zig cc -o example buffer.c main.c ``` @@ -33,17 +35,17 @@ zig cc -o example buffer.c main.c 使用 zig cc 进行交叉编译与使用 Zig 本身一样简单: -```plain +``` zig cc -o example.exe -target x86_64-windows-gnu buffer.c main.c ``` 如你所见,只需向 -target 传递目标三元组,就能调用交叉编译。只需确保所有外部库都已准备好进行交叉编译即可! -## 使用 zig build-exe 和其他工具 +# [使用 zig build-exe 和其他工具]($section.id('使用 zig build-exe 和其他工具')) 使用 Zig 工具链构建 C 项目的另一种方法与构建 Zig 项目的方法相同: -```plain +``` zig build-exe -lc main.c buffer.c ``` @@ -51,13 +53,13 @@ zig build-exe -lc main.c buffer.c 交叉编译也是如此,只需通过 -target x86_64-windows-gnu 或其他目标三元组即可: -```plain +``` zig build-exe -lc -target x86_64-windows-gnu main.c buffer.c ``` 你会发现,使用这条编译命令,Zig 会自动在输出文件中附加 .exe 扩展名,并生成 .pdb 调试数据库。如果你在此处传递 --name example,输出文件也会有正确的 .exe 扩展名,所以你不必考虑这个问题。 -## 用 build.zig 创建 C 代码 +# [用 build.zig 创建 C 代码]($section.id('用 build.zig 创建 C 代码')) 那么,我们如何用 build.zig 来构建上面的两个示例呢? @@ -93,7 +95,7 @@ pub fn build(b: *std.Build) void { 然后,我们通过 addCSourceFile 添加两个 C 语言文件: -```plain +``` exe.addCSourceFile(.{ .file = std.build.LazyPath.relative("main.c"), .flags = &.{} }); exe.addCSourceFile(.{ .file = std.build.LazyPath.relative("buffer.c"), .flags = &.{} }); ``` @@ -110,7 +112,7 @@ exe.addCSourceFile(.{ .file = std.build.LazyPath.relative("buffer.c"), .flags = exe.addCSourceFile(.{.file = std.build.LazyPath.relative("buffer.c"), .flags = &.{"-fno-sanitize=undefined"}}); ``` -## 使用外部库 +# [使用外部库]($section.id('使用外部库')) 通常情况下,C 项目依赖于其他库,这些库通常预装在 Unix 系统中,或通过软件包管理器提供。 @@ -174,12 +176,12 @@ pub fn build(b: *std.Build) void { 让我们创建程序,并通过 URL 调用它 -```plain +``` zig build ./zig-out/bin/downloader https://mq32.de/public/ziggy.txt ``` -## 配置路径 +# [配置路径]($section.id('配置路径')) 由于我们不能在交叉编译项目中使用 pkg-config,或者我们想使用预编译的专用库(如 BASS 音频库),因此我们需要配置包含路径和库路径。 @@ -218,7 +220,7 @@ pub fn build(b: *std.Build) void { addIncludePath 和 addLibraryPath 都可以被多次调用,以向编译器添加多个路径。这些函数不仅会影响 C 代码,还会影响 Zig 代码,因此 @cImport 可以访问包含路径中的所有头文件。 -## 每个文件的包含路径 +# [每个文件的包含路径]($section.id('每个文件的包含路径')) 因此,如果我们需要为每个 C 文件设置不同的包含路径,我们就需要用不同的方法来解决这个问题: 由于我们仍然可以通过 addCSourceFile 传递任何 C 编译器标志,因此我们也可以在这里手动设置包含目录。 @@ -250,7 +252,7 @@ pub fn build(b: *std.Build) void { 上面的示例非常简单,所以你可能会想为什么需要这样的东西。答案是,有些库的头文件名称非常通用,如 api.h 或 buffer.h,而您希望使用两个共享头文件名称的不同库。 -## 构建 C++ 项目 +# [构建 C++ 项目]($section.id('构建 C++ 项目')) 到目前为止,我们只介绍了 C 文件,但构建 C++ 项目并不难。你仍然可以使用 addCSourceFile,但只需传递一个具有典型 C++ 文件扩展名的文件,如 cpp、cxx、c++ 或 cc: @@ -283,7 +285,7 @@ pub fn build(b: *std.Build) void { 这就是构建 C++ 文件所需的全部知识,没有什么更神奇的了。 -## 指定语言版本 +# [指定语言版本]($section.id('指定语言版本')) 试想一下,如果你创建了一个庞大的项目,其中的 C 或 C++ 文件有新有旧,而且可能是用不同的语言标准编写的。为此,我们可以使用编译器标志来传递 -std=c90 或 -std=c++98: @@ -318,7 +320,7 @@ pub fn build(b: *std.Build) void { } ``` -## 条件编译 +# [条件编译]($section.id('条件编译')) 与 Zig 相比,C 和 C++ 的条件编译方式非常繁琐。由于缺乏惰性求值的功能,有时必须根据目标环境来包含/排除文件。你还必须提供宏定义来启用/禁用某些项目功能。 @@ -371,7 +373,7 @@ pub fn build(b: *std.Build) void { 有条件地包含文件就像使用 if 一样简单,你可以这样做。只要不根据你想在构建脚本中定义的任何约束条件调用 addCSourceFile 即可。只包含特定平台的文件?看看上面的脚本就知道了。根据系统时间包含文件?也许这不是个好主意,但还是有可能的! -## 编译大型项目 +# [编译大型项目]($section.id('编译大型项目')) 由于大多数 C(更糟糕的是 C++)项目都有大量文件(SDL2 有 411 个 C 文件和 40 个 C++ 文件),我们必须找到一种更简单的方法来编译它们。调用 addCSourceFile 400 次并不能很好地扩展。 @@ -476,7 +478,7 @@ pub fn build(b: *std.build.Builder) !void { 注意:其他构建系统会考虑文件名,而 Zig 系统不会!例如,在一个 qmake 项目中不能有两个名为 data.c 的文件!Zig 并不在乎,你可以添加任意多的同名文件,只要确保它们在不同的文件夹中就可以了 😏。 -## 编译 Objective C +# [编译 Objective C]($section.id('编译 Objective C')) 我完全忘了!Zig 不仅支持编译 C 和 C++,还支持通过 clang 编译 Objective C! @@ -512,7 +514,7 @@ pub fn build(b: *std.Build) void { 在这里,链接 libc 是隐式的,因为添加框架会自动强制链接 libc。是不是很酷? -## 混合使用 C 和 Zig 源代码 +# [混合使用 C 和 Zig 源代码]($section.id('混合使用 C 和 Zig 源代码')) 现在,是最后一章: 混合 C 代码和 Zig 代码! @@ -552,7 +554,7 @@ pub fn build(b: *std.Build) void { 您应用程序的入口点现在必须在 Zig 代码中,因为根文件必须导出一个 pub fn main(...) ……。 因此,如果你想将 C 项目中的代码移植到 Zig 中,你必须将 argc 和 argv 转发到你的 C 代码中,并将 C 代码中的 main 重命名为其他函数(例如 oldMain),然后在 Zig 中调用它。如果需要 argc 和 argv,可以通过 std.process.argsAlloc 获取。或者更好: 在 Zig 中重写你的入口点,然后从你的项目中移除一些 C 语言! -## 结论 +# [结论]($section.id('conclusion')) 假设你只编译一个输出文件,那么现在你应该可以将几乎所有的 C/C++ 项目移植到 build.zig。 diff --git a/content/post/2023-12-29-zig-build-explained-part3.md b/content/post/2023-12-29-zig-build-explained-part3.smd similarity index 95% rename from content/post/2023-12-29-zig-build-explained-part3.md rename to content/post/2023-12-29-zig-build-explained-part3.smd index d3a4cff..e7a962e 100644 --- a/content/post/2023-12-29-zig-build-explained-part3.md +++ b/content/post/2023-12-29-zig-build-explained-part3.smd @@ -1,25 +1,27 @@ --- -title: zig 构建系统解析 - 第三部分 -author: Reco -date: "2023-12-29T19:15:02+0800" +.title = "zig 构建系统解析 - 第三部分", +.date = @date("2023-12-29T19:15:02+0800"), +.author = "Reco", +.layout = "post.shtml", +.draft = false, --- > - 原文链接: https://zig.news/xq/zig-build-explained-part-3-1ima > - API 适配到 Zig 0.11.0 版本 -从现在起,我将只提供一个最精简的 build.zig,用来说明解决一个问题所需的步骤。如果你想了解如何将所有这些文件粘合到一个构建文件中,请阅读本系列[第一篇文章](/post/2023/12/24/zig-build-explained-part1/)。 +从现在起,我将只提供一个最精简的 build.zig,用来说明解决一个问题所需的步骤。如果你想了解如何将所有这些文件粘合到一个构建文件中,请阅读本系列[第一篇文章](2023-12-24-zig-build-explained-part1)。 -## 复合项目 +# [复合项目]($section.id('复合项目')) 有很多简单的项目只包含一个可执行文件。但是,一旦开始编写库,就必须对其进行测试,通常会编写一个或多个示例应用程序。当人们开始使用外部软件包、C 语言库、生成代码等时,复杂性也会随之上升。 本文试图涵盖所有这些用例,并将解释如何使用 build.zig 来编写多个程序和库。 -## 软件包 +# [软件包]($section.id('软件包')) 译者:此处代码和说明,需要 zig build-exe --pkg-begin,但是在 0.11 已经失效。所以删除。 -## 库 +# [库]($section.id('库')) 但 Zig 也知道库这个词。但我们不是已经讨论过外部库了吗? @@ -34,7 +36,7 @@ date: "2023-12-29T19:15:02+0800" 在 Zig 中,我们需要导入库的头文件,如果头文件在 Zig 中,则使用包,如果是 C 语言头文件,则使用 @cImport。 -## 工具 +# [工具]($section.id('工具')) 如果我们的项目越来越多,那么在构建过程中就需要使用工具。这些工具通常会完成以下任务: @@ -46,7 +48,7 @@ date: "2023-12-29T19:15:02+0800" 但我们如何在 build.zig 中完成这些工作呢? -## 添加软件包 +# [添加软件包]($section.id('添加软件包')) 添加软件包通常使用 LibExeObjStep 上的 addPackage 函数。该函数使用一个 std.build.Pkg 结构来描述软件包的外观: @@ -96,7 +98,7 @@ exe.addModule("lola",pkgs.lola); exe.addModule("args",pkgs.args); ``` -## 添加库 +# [添加库]($section.id('添加库')) 添加库相对容易,但我们需要配置更多的路径。 @@ -104,7 +106,7 @@ exe.addModule("args",pkgs.args); 假设我们要将 libcurl 链接到我们的项目,因为我们要下载一些文件。 -### 系统库 +## [系统库]($section.id('系统库')) 对于 unixoid 系统,我们通常可以使用系统软件包管理器来链接系统库。方法是调用 linkSystemLibrary,它会使用 pkg-config 自行找出所有路径: @@ -135,11 +137,11 @@ pub fn build(b: *std.Build) void { 对于 Linux 系统,这是链接外部库的首选方式。 -### 本地库 +## [本地库]($section.id('本地库')) 不过,您也可以链接您作为二进制文件提供商的库。为此,我们需要调用几个函数。首先,让我们来看看这样一个库是什么样子的: -```plain +``` ./vendor/libcurl include │ └── curl @@ -165,7 +167,7 @@ include 我们可以看到,vendor/libcurl/include 路径包含我们的头文件,vendor/libcurl/lib 文件夹包含一个静态库(libcurl.a)和一个共享/动态库(libcurl.so)。 -### 动态链接 +## [动态链接]($section.id('动态链接')) 要链接 libcurl,我们需要先添加 include 路径,然后向 zig 提供库的前缀和库名:(todo 代码有待验证,因为 curl 可能需要自己编译自己生成 static lib) @@ -195,7 +197,7 @@ addLibraryPath 对库文件也有同样的作用。这意味着 Zig 现在也会 最后,linkSystemLibrary 会告诉 Zig 搜索名为 "curl "的库。如果你留心观察,就会发现上面列表中的文件名是 libcurl.so,而不是 curl.so。在 unixoid 系统中,库文件的前缀通常是 lib,这样就不会将其传递给系统。在 Windows 系统中,库文件的名字应该是 curl.lib 或类似的名字。 -## 静态链接 +# [静态链接]($section.id('静态链接')) 当我们要静态链接一个库时,我们必须采取一些不同的方法: @@ -248,7 +250,7 @@ pub fn build(b: *std.build.Builder) void { 我们可以继续静态链接越来越多的库,并拉入完整的依赖关系树。 -## 通过源代码链接库 +# [通过源代码链接库]($section.id('通过源代码链接库')) 不过,我们还有一种与 Zig 工具链截然不同的链接库方式: @@ -291,7 +293,7 @@ pub fn build(b: *std.build.Builder) void { 这一点尤其方便,因为我们可以使用 setTarget 和 setBuildMode 从任何地方编译到任何地方。 -## 使用工具 +# [使用工具]($section.id('使用工具')) 在工作流程中使用工具,通常是在需要以 bison、flex、protobuf 或其他形式进行预编译时。工具的其他用例包括将输出文件转换为不同格式(如固件映像)或捆绑最终应用程序。 @@ -350,7 +352,7 @@ size 是一个很好的工具,它可以输出有关可执行文件代码大小 如您所见,我们在这里使用了 addArtifactArg,因为 addSystemCommand 只会返回一个 std.build.RunStep。这样,我们就可以增量构建完整的命令行,包括任何 LibExeObjStep 输出、FileSource 或逐字参数。 -## 全新工具 +# [全新工具]($section.id('全新工具')) 最酷的是 我们还可以从 LibExeObjStep 获取 std.build.RunStep: @@ -387,7 +389,7 @@ pub fn build(b: *std.build.Builder) void { 调用 zig build pack 时,我们将运行 tools/pack.zig。这很酷,因为我们还可以从头开始编译所需的工具。为了获得最佳的开发体验,你甚至可以从源代码编译像 bison 这样的 "外部 "工具,这样就不会依赖系统了! -## 将所有内容放在一起 +# [将所有内容放在一起]($section.id('将所有内容放在一起')) 一开始,所有这些都会让人望而生畏,但如果我们看一个更大的 build.zig 实例,就会发现一个好的构建文件结构会给我们带来很大帮助。 @@ -489,7 +491,7 @@ pub fn build(b: *std.build.Builder) void { 两者都是为了在主机平台上运行,而不是在目标机器上。 此外,deploy_tool 还设置了固定的编译模式,因为我们希望快速编译,即使我们编译的是应用程序的调试版本。 -## 总结 +# [总结]($section.id('summary')) 看完这一大堆文字,你现在应该可以构建任何你想要的项目了。我们已经学会了如何编译 Zig 应用程序,如何为其添加任何类型的外部库,甚至如何为发布管理对应用程序进行后处理。 diff --git a/content/post/2024-01-12-how-to-release-your-zig-applications.md b/content/post/2024-01-12-how-to-release-your-zig-applications.md deleted file mode 100644 index 017f9b7..0000000 --- a/content/post/2024-01-12-how-to-release-your-zig-applications.md +++ /dev/null @@ -1,180 +0,0 @@ ---- -title: 如何发布 Zig 应用程序 -author: Rui Chen -date: "2024-01-12T12:04:50-0500" ---- - -> - 原文链接: https://zig.news/kristoff/how-to-release-your-zig-applications-2h90 -> - API 适配到 Zig 0.12.0 版本 -> - 本文配套代码在[这里](https://github.com/zigcc/zigcc.github.io/tree/main/examples/20240112)找到 - -你刚用 Zig 写了一个应用程序,并希望其他人使用它。 -让用户方便使用的一种方式是为他们提供应用程序的预构建可执行文件。 -接下来,我将讨论一个好的发版流程所需要正确处理的两个主要事项。 - -# 为什么提供预构建的可执行文件? - -鉴于 C/C++ 依赖系统如何工作(或者说 _不工作_),对于某些 C/C++ 项目来说, -提供预编译好的的可执行文件几乎是必须的, -否则,普通人将陷入构建系统和配置系统的泥潭, -而这些系统的数量还要乘以项目的依赖数量。 -使用 Zig 的话就不应该这样,因为 Zig 构建系统(加上即将推出的 Zig 包管理器)将能够处理一切,这意味着大多数编写良好的应用程序应该只需运行 `zig build` 即可成功构建。 - -话虽如此,你的应用程序越受欢迎,用户就越不关心它是用哪种语言编写的。 -你的用户不想安装 Zig 并运行构建过程就能轻松使用应用程序(99%的情况下,稍后会讲到剩下的 1%), -因此最好还是预先构建你的应用程序。 - -# `zig build` vs `zig build-exe` - -在本文中,我们将看到如何为 Zig 项目制作、发布构建, -因此值得花一点时间来完全理解 Zig 构建系统和命令行之间的关系。 - -如果你有一个非常简单的 Zig 应用程序(例如,单个文件,无任何依赖), -构建项目最简单的方式是使用 `zig build-exe myapp.zig`, -这会在当前路径下创建一个可执行文件。 - -随着项目的增长,特别是开始有依赖之后,你可能想添加一个 `build.zig` 文件, -并开始用到 Zig 构建系统。一旦你开始这么做,你就可以完全控制命令行参数来影响构建过程。 - -你可以使用 `zig init-exe` 来了解基线 `build.zig` 文件的样子。 -请注意,文件中的每一行代码都是显示定义,从而影响 `zig build` 子命令的行为。 - -最后一点需要注意的是,尽管使用 `zig build` 和 `zig build-exe` 时命令行参数会有所不同, -但在构建 Zig 代码方面,两者是等价的。更具体地说,尽管 Zig 构建可以调用任意命令, -并做其他可能根本与 Zig 代码无关的事情,但在构建 Zig 代码方面, -`zig build` 所做的一切就是为 `build-exe` 准备命令行参数。 -这意味着,在编译 Zig 代码方面,`zig build`(假定 `build.zig` 中的代码是正确的) -和 `zig build-exe` 之间是一一对应关系。唯一的区别只是便利性。 - -# 构建模式 - -使用 `zig build` 或 `zig build-exe myapp.zig` 构建一个 Zig 项目时, -默认得到是一个调试构建的可执行文件。调试构建主要是为了开发方便,因而,通常被认为不适合发版。 -调试构建旨在牺牲运行性能(运行更慢)来提高构建速度(编译更快), -不久, Zig 编译器将通过引入增量编译和就地二进制补丁(in-place binary patching) -来让这种权衡变得更加明显。 - -Zig 目前有三种主要的发版构建模式:`ReleaseSafe`、`ReleaseFast` 和 `ReleaseSmall`。 - -`ReleaseSafe` 应被视为发版时使用的主要模式:尽管使用了优化, -但仍保留了某些安全检查(例如,溢出和数组越界), -在发布处理不可控输入源(如互联网)的软件时,这些开销是绝对值得的。 - -`ReleaseFast` 旨在用于性能是主要关注点的软件, -例如视频游戏。这种构建模式不仅禁用了上述安全检查, -而且为了进行更激进的优化,它还假设代码中不存在这类编程错误。 - -`ReleaseSmall` 类似于 `ReleaseFast`(即,没有安全检查), -但它不是优先考虑性能,而是尝试最小化可执行文件大小。 -例如,这是一种对于 WebAssembly 来说非常有意义的构建模式, -因为你希望可执行文件尽可能小,而沙箱运行环境已经提供了很多安全保障。 - -# 如何设置构建模式 - -使用 `zig build-exe` 时,你可以添加 `-O ReleaseSafe` -(或 `ReleaseFast`,或 `ReleaseSmall`)以获得相应的构建模式。 - -使用 `zig build` 时,取决于构建脚本的配置。默认构建脚本将包含以下代码行: - -```zig -// standardReleaseOptions 允许我们在运行 zig build 时,手动选择需要构建的目标平台和架构 -// 默认情况下为本机构建 -const target = b.standardTargetOptions(.{}); - -// standardOptimizeOption 允许我们在运行 zig build 时,手动选择构建模式 -// 默认情况下为 Debug -const optimize = b.standardOptimizeOption(.{}); - -// 标准构建一个可执行二进制程序的步骤 -const exe = b.addExecutable(.{ - .name = "zig", - .root_source_file = .{ .path = "src/main.zig" }, - .target = target, - .optimize = optimize, -}); -``` - -这是你在命令行中指定发布模式的方式:`zig build -Doptimize=ReleaseSafe`(或 -`-Doptimize=ReleaseFast`,或 `-Doptimize=ReleaseSmall`)。 - -# 选择正确的构建目标 - -现在,我们已经选择了正确的发版模式,是时候考虑构建目标了。 -显而易见,如果使用的平台和构建平台不相同时,需要指定相应的构建目标, -但即使只打算为同一平台发版,也还是需要注意。 - -为了方便起见,假定你用的是 Windows 10,并试图为使用 Windows 10 的朋友构建可执行文件。 -最想当然的方式是直接调用 `zig build` 或 `zig build-exe`(参见前文关于两个命令之间的差异与相似之处),然后将生成的可执行文件发送给你的朋友。 - -如果这样做,有时它会工作,但有时它会因`非法指令`(或类似错误)而崩溃。这到底发生了什么? - -# CPU 特性 - -在构建时如果不指定构建目标,Zig 将面向当前的机器进行构建优化, -这意味着将利用当前 CPU 支持的所有指令集。如果 CPU 支持 AVX 扩展, -那么 Zig 将使用它来执行 SIMD 操作。但不幸的是, -这也意味着,如果你朋友的 CPU 没有 AVX 扩展,那么应用程序将崩溃, -因为这个可执行文件确实包含非法指令。 - -解决这个问题最简单的方法是:始终在进行发布时指定一个构建目标。 -没错,如果你指定你想要为 `x86-64-linux` 构建, -Zig 将设定一个与该系列所有 CPU 完全兼容的基线 CPU。 - -如果你想微调指令集的选择,你可以查看 `zig build` 的 `-Dcpu` 和 `zig build-exe` 的 -`-mcpu`。我不会在这篇文章中更多地涉及这些细节。 - -实操中,下面的命令行将是你为 Arm macOS 发版时会用到的构建命令: - -```zig -$ zig build -Dtarget=aarch64-macos -$ zig build-exe myapp.zig -target aarch64-macos -``` - -请注意,目前在使用 `zig build` 时 `=` 是必需的, -而在使用 `build-exe` 时它不起作用(即你必须在 `-target` 及其值之间放一个空格)。 -希望这些怪异的地方在不久将来会得到清理。 - -其它一些相关的构建目标: - -```zig -x86-64-linux // uses gnu libc -x86-64-linux-gnu // uses glibc -x86-64-musl // uses musl libc -x86-64-windows // uses MingW headers -x86-64-windows-msvc // uses MSVC headers but they need to be present in your system -wasm32-freestanding // you will have to use build-obj since wasm modules are not full exes -``` - -你可以通过调用 `zig targets` 看到 Zig 支持的目标 CPU 和 -操作系统(以及 libc 和指令集)的完整列表。温馨提示:这是一个很长的列表。 - -最后,别忘了 `build.zig` 里的一切都必须明确定义,因此目标选项可以通过以下几行代码设置: - -```zig -// standardReleaseOptions 允许我们在运行 zig build 时,手动选择需要构建的目标平台和架构 -// 默认情况下为本机构建 -const target = b.standardTargetOptions(.{}); - -// standardOptimizeOption 允许我们在运行 zig build 时,手动选择构建模式 -// 默认情况下为 Debug -const optimize = b.standardOptimizeOption(.{}); - -// 标准构建一个可执行二进制程序的步骤 -const exe = b.addExecutable(.{ - .name = "zig", - .root_source_file = .{ .path = "src/main.zig" }, - .target = target, - .optimize = optimize, -}); -``` - -这也意味着如果你想添加其他限制或以某种方式改变构建时应该如何指定目标, -你可以通过添加自己的代码来实现。 - -# 结束语 - -现在你已经了解了在进行发布构建时需要确保正确的事项:选择一个发布优化模式并选择正确的构建目标, -包括为你正在构建的同一系统进行发版构建。 - -这最后一点的一个有趣含义是,对于你的一些用户(通常情况下为 1%,乐观估计), -从头开始构建程序实际上更为可取,以确保他们充分利用其 CPU 的能力。 diff --git a/content/post/2024-01-12-how-to-release-your-zig-applications.smd b/content/post/2024-01-12-how-to-release-your-zig-applications.smd new file mode 100644 index 0000000..09e5d58 --- /dev/null +++ b/content/post/2024-01-12-how-to-release-your-zig-applications.smd @@ -0,0 +1,182 @@ +--- +.title = "如何发布 Zig 应用程序", +.date = @date("2024-01-12T12:04:50-0500"), +.author = "Rui Chen", +.layout = "post.shtml", +.draft = false, +--- + +> - 原文链接: https://zig.news/kristoff/how-to-release-your-zig-applications-2h90 +> - API 适配到 Zig 0.12.0 版本 +> - 本文配套代码在[这里](https://github.com/zigcc/zigcc.github.io/tree/main/examples/20240112)找到 + +You've just written an application in Zig and want others to use it. +A convenient way for users to use your application is to provide a pre-built executable file. +Next, I'll discuss the two main things that need to be handled correctly in a good release process. + +# [Why provide pre-built executable files?]($section.id('Why provide pre-built executable files?')) + +Given how C/C++ dependencies work (or don't work), for some C/C++ projects, +providing pre-compiled executable files is almost a necessity, +otherwise, ordinary people will get stuck in the build system configuration and +the number of systems to multiply these by is the number of project dependencies. +Using Zig shouldn't be like this, because Zig build system (plus the upcoming Zig package manager) will be able to handle everything, meaning most well-written applications should just run `zig build` to succeed. + +That said, the more popular your application is, the less users will care what language it's written in. +Your users don't want to install Zig and run the build process to easily use your application (99% of the time, the rest 1% will be discussed later), +so it's still better to pre-build your application. + +# [`zig build` vs `zig build-exe`]($section.id('`zig build` vs `zig build-exe`')) + +In this article, we'll see how to make, release a build for a Zig project, +so it's worth spending a little time to fully understand the relationship between Zig build system and command line. + +If you have a very simple Zig application (for example, a single file, no dependencies), +the simplest way to build a project is to use `zig build-exe myapp.zig`, +which will create an executable file in the current path. + +As the project grows, especially when dependencies start, you might want to add a `build.zig` file, +and start using Zig build system. Once you start doing this, you can completely control command line parameters to affect the build process. + +You can use `zig init-exe` to see what a baseline `build.zig` file looks like. +Note that every line of code in the file is explicitly defined, thus affecting the behavior of `zig build` subcommand. + +The last thing to note is that although command line parameters will be different when using `zig build` and `zig build-exe`, +in building Zig code, both are equivalent. More specifically, although Zig build can call arbitrary commands, +and do other things that may have nothing to do with Zig code, in building Zig code, +what `zig build` does is to prepare command line parameters for `build-exe`. +This means that in compiling Zig code, `zig build` (assuming the code in `build.zig` is correct) +and `zig build-exe` are one-to-one correspondence. The only difference is convenience. + +# [Build mode]($section.id('Build mode')) + +When building a Zig project with `zig build` or `zig build-exe myapp.zig`, +the default is a debug build executable file. Debug build is mainly for development convenience, so it's usually considered unsuitable for release. +Debug build aims to sacrifice running performance (running slower) for build speed (compiling faster), +soon, Zig compiler will make this trade-off more obvious by introducing incremental compilation and in-place binary patching. + +Zig currently has three main release build modes: `ReleaseSafe`, `ReleaseFast` and `ReleaseSmall`. + +`ReleaseSafe` should be considered the main mode to use when releasing: although optimizations are used, +it still retains some safety checks (for example, overflow and array bounds), +these overheads are absolutely worth it when releasing software that handles uncontrollable input sources (like the internet). + +`ReleaseFast` is intended for software where performance is the main concern, +for example video games. This build mode not only disables the above safety checks, +but also assumes that there are no such programming errors in the code. + +`ReleaseSmall` is similar to `ReleaseFast` (i.e., no safety checks), +but it's not prioritized for performance, but rather for trying to minimize the executable file size. +For example, this is a very meaningful build mode for WebAssembly, +because you want the executable file to be as small as possible, and the sandbox runtime environment has provided a lot of security guarantees. + +# [How to set build mode]($section.id('How to set build mode')) + +When using `zig build-exe`, you can add `-O ReleaseSafe` +(or `ReleaseFast`, or `ReleaseSmall`) to get the corresponding build mode. + +When using `zig build`, it depends on the configuration of the build script. The default build script will include the following code lines: + +```zig +// standardReleaseOptions allows us to manually select the target platform and architecture when running zig build +// Default is for this architecture +const target = b.standardTargetOptions(.{}); + +// standardOptimizeOption allows us to manually select build mode when running zig build +// Default is Debug +const optimize = b.standardOptimizeOption(.{}); + +// Standard steps to build a executable binary +const exe = b.addExecutable(.{ + .name = "zig", + .root_source_file = .{ .path = "src/main.zig" }, + .target = target, + .optimize = optimize, +}); +``` + +This is how you specify release mode in command line: `zig build -Doptimize=ReleaseSafe` (or +`-Doptimize=ReleaseFast`, or `-Doptimize=ReleaseSmall`). + +# [Choose the correct build target]($section.id('Choose the correct build target')) + +Now, we've chosen the correct release mode, it's time to consider build target. +Obviously, if the platform used and build platform are different, the corresponding build target needs to be specified, +but even if you just intend to release for the same platform, you still need to pay attention. + +For convenience, assume you're using Windows 10 and trying to build an executable file for your friends using Windows 10. +The most straightforward way is to directly call `zig build` or `zig build-exe` (see the difference and similarity between the two commands above), and then send the generated executable file to your friends. + +If you do this, sometimes it works, but sometimes it crashes due to `illegal instruction` (or similar error). What's happening? + +# [CPU features]($section.id('CPU features')) + +If build target is not specified when building, Zig will build for the current machine, +which means it will use all instruction sets supported by the current CPU. If the CPU supports AVX extension, +then Zig will use it to perform SIMD operations. But unfortunately, +this also means that if your friend's CPU doesn't support AVX extension, the application will crash, +because this executable file indeed contains illegal instructions. + +The simplest way to solve this problem is: always specify a build target when releasing. +Yes, if you specify you want to build for `x86-64-linux`, +Zig will set a baseline CPU that is fully compatible with all CPUs in that series. + +If you want to fine-tune instruction set selection, you can check `zig build`'s `-Dcpu` and `zig build-exe`'s +`-mcpu`. I won't cover these details more in this article. + +In practice, the following command line will be the build command you'll use when releasing for Arm macOS: + +```zig +$ zig build -Dtarget=aarch64-macos +$ zig build-exe myapp.zig -target aarch64-macos +``` + +Note that currently `=` is required when using `zig build`, +while it doesn't work when using `build-exe` (i.e., you must put a space between `-target` and its value). +I hope these weird places will be cleaned up in the near future. + +Other related build targets: + +```zig +x86-64-linux // uses gnu libc +x86-64-linux-gnu // uses glibc +x86-64-musl // uses musl libc +x86-64-windows // uses MingW headers +x86-64-windows-msvc // uses MSVC headers but they need to be present in your system +wasm32-freestanding // you will have to use build-obj since wasm modules are not full exes +``` + +You can see the complete list of Zig supported target CPUs and +operating systems (as well as libc and instruction sets) by calling `zig targets`. +Reminder: this is a very long list. + +Finally, don't forget everything in `build.zig` must be explicitly defined, so target options can be set through the following code lines: + +```zig +// standardReleaseOptions allows us to manually select the target platform and architecture when running zig build +// Default is for this architecture +const target = b.standardTargetOptions(.{}); + +// standardOptimizeOption allows us to manually select build mode when running zig build +// Default is Debug +const optimize = b.standardOptimizeOption(.{}); + +// Standard steps to build a executable binary +const exe = b.addExecutable(.{ + .name = "zig", + .root_source_file = .{ .path = "src/main.zig" }, + .target = target, + .optimize = optimize, +}); +``` + +This also means if you want to add other restrictions or change how to specify target when building, +you can achieve this by adding your own code. + +# [Conclusion]($section.id('conclusion')) + +Now you've learned the things you need to ensure correctly when releasing a build: choose a release optimization mode and choose the correct build target, +including building for the same system you're building. + +One interesting implication of this last point is that for some of your users (usually 1% on average), +it's actually more beneficial to start building the program from scratch to ensure they make full use of their CPU capabilities. diff --git a/content/post/2024-04-06-zig-cpp.md b/content/post/2024-04-06-zig-cpp.smd similarity index 71% rename from content/post/2024-04-06-zig-cpp.md rename to content/post/2024-04-06-zig-cpp.smd index 103c939..7a9afe3 100644 --- a/content/post/2024-04-06-zig-cpp.md +++ b/content/post/2024-04-06-zig-cpp.smd @@ -1,16 +1,18 @@ --- -title: "通过 Zig,学习 C++ 元编程" -author: Peng He -date: 2024-04-06T19:57:49+08:00 +.title = "通过 Zig,学习 C++ 元编程", +.date = @date("2024-04-06T19:57:49+08:00"), +.author = "Peng He", +.layout = "post.shtml", +.draft = false, --- -尽管 Zig 社区宣称 Zig 语言是一个更好的 C (better C),但是我个人在学习 Zig 语言时经常会“触类旁通”C++。在这里列举一些例子来说明我的一些体会,可能会有一些不正确的地方,欢迎批评指正。 +尽管 Zig 社区宣称 Zig 语言是一个更好的 C (better C),但是我个人在学习 Zig 语言时经常会"触类旁通"C++。在这里列举一些例子来说明我的一些体会,可能会有一些不正确的地方,欢迎批评指正。 -# “元能力” vs “元类型” +# ["元能力" vs "元类型"]($section.id('"元能力" vs "元类型"')) -在我看来,C++的增强方式是希望赋予语言一种“元能力”,能够让人重新发明新的类型,使得使用 C++的程序员使用自定义的类型,进行一种类似于“领域内语言”(DSL)编程。一个通常的说法就是 C++中任何类型定义都像是在模仿基本类型`int`。比如我们有一种类型 T,那么我们则需要定义 T 在以下几种使用场景的行为: +在我看来,C++的增强方式是希望赋予语言一种"元能力",能够让人重新发明新的类型,使得使用 C++的程序员使用自定义的类型,进行一种类似于"领域内语言"(DSL)编程。一个通常的说法就是 C++中任何类型定义都像是在模仿基本类型`int`。比如我们有一种类型 T,那么我们则需要定义 T 在以下几种使用场景的行为: -```C++ +```cpp T x; //构造 T x = y; //隐式拷贝构造 T x{y}; //显示拷贝构造 @@ -18,13 +20,13 @@ x = y; //x的类型是T,复制运算符重载,当然也有可能是移动运 //以及一大堆其他行为,比如析构等等。 ``` -通过定义各种行为,程序员可以用 C++去模拟基础类型`int`,自定义的创造新类型。但是 Zig 却采取了另一条路,这里我觉得 Zig 的取舍挺有意思,即它剥夺了程序员定义新类型的能力,只遵循 C 的思路,即`struct`就是`struct`,他和`int`就是不一样的,没有必要通过各种运算符重载来制造一种“幻觉”,模拟`int`。相反,Zig 吸收现代语言中最有用的“元类型”,比如`slice`,`tuple`,`tagged union`等作为语言内置的基本类型,从这一点上对 C 进行增强。虽然这样降低了语言的表现力,但是却简化了设计,降低了“心智负担”。 +通过定义各种行为,程序员可以用 C++去模拟基础类型`int`,自定义的创造新类型。但是 Zig 却采取了另一条路,这里我觉得 Zig 的取舍挺有意思,即它剥夺了程序员定义新类型的能力,只遵循 C 的思路,即`struct`就是`struct`,他和`int`就是不一样的,没有必要通过各种运算符重载来制造一种"幻觉",模拟`int`。相反,Zig 吸收现代语言中最有用的"元类型",比如`slice`,`tuple`,`tagged union`等作为语言内置的基本类型,从这一点上对 C 进行增强。虽然这样降低了语言的表现力,但是却简化了设计,降低了"心智负担"。 -比如 Zig 里的`tuple`,C++里也有`std::tuple`。当然,`std::tuple`是通过一系列的模板元编程的方式实现的,但是这个在 Zig 里是内置的,因此写代码时出现语法错误,Zig 可以直接告诉你是`tuple`用的不对,但是 C++则会打印很多错误日志。再比如`optional`,C++里也有`std::optinonal`,Zig 里只用`?T`。C++里有`std::variant`,而 Zig 里有`tagged union`。当然我们可以说,C++因为具备了这种元能力,当语法不足够“甜”时,我们可以发明新的轮子,但是代价就是系统愈发的复杂。而 Zig 则持续保持简单。 +比如 Zig 里的`tuple`,C++里也有`std::tuple`。当然,`std::tuple`是通过一系列的模板元编程的方式实现的,但是这个在 Zig 里是内置的,因此写代码时出现语法错误,Zig 可以直接告诉你是`tuple`用的不对,但是 C++则会打印很多错误日志。再比如`optional`,C++里也有`std::optinonal`,Zig 里只用`?T`。C++里有`std::variant`,而 Zig 里有`tagged union`。当然我们可以说,C++因为具备了这种元能力,当语法不足够"甜"时,我们可以发明新的轮子,但是代价就是系统愈发的复杂。而 Zig 则持续保持简单。 -不过话说回来,很多底层系统的开发需求往往和这种类型系统的构建相悖,比如如果你的类型就是一个`int`的封装,那么即使发生拷贝你也无所谓性能开销。但是如果是一个`struct`,那么通常情况下,你会比较 care 拷贝,而可能考虑“移动”之类的手段。这个时候各种 C++的提供的幻觉,就成了程序员开发的绊脚石,经常你需要分析一段 C++表达式里到底有没有发生拷贝,他是左值还是右值,其实你在写 C 语言的时候也很少去考虑了这些,你在 Zig 里同样也不需要。 +不过话说回来,很多底层系统的开发需求往往和这种类型系统的构建相悖,比如如果你的类型就是一个`int`的封装,那么即使发生拷贝你也无所谓性能开销。但是如果是一个`struct`,那么通常情况下,你会比较 care 拷贝,而可能考虑"移动"之类的手段。这个时候各种 C++的提供的幻觉,就成了程序员开发的绊脚石,经常你需要分析一段 C++表达式里到底有没有发生拷贝,他是左值还是右值,其实你在写 C 语言的时候也很少去考虑了这些,你在 Zig 里同样也不需要。 -# 类型系统 +# [类型系统]($section.id('类型系统')) C 语言最大弊病就是没有提供标准库,C++的标准库你要是能看懂,得具备相当的 C++的语法知识,但是 Zig 的标准库几乎不需要文档就能看懂。这其实是因为,在 C++里,类型不是一等成员(first class member),因此实现一些模版元编程算法特别不直观。但是在 Zig 里,`type`就是一等成员,比如你可以写: @@ -34,19 +36,19 @@ const x: type = u32; 即,把一个`type`当成一个变量使用。但是 C++里如何来实现这一行代码呢?其实是如下: -```C++ +```cpp using x = uint32_t; ``` 那么我们如果要对某个类型做个计算,比如组合一个新类型,Zig 里其实非常直观 -```Zig +```zig fn Some(comptime InputType: type) type ``` 即输入一个类型,输出一个新类型,那么 C++里对应的东西是啥呢? -```C++ +```cpp template struct Some { using OutputType = ... @@ -55,17 +57,17 @@ struct Some { 相比之下, Zig 直观太多。那么很自然的,计算一个类型,Zig 里就是调用函数,而 C++则是模板类实例化,然后访问类成员。 -```C++ +```cpp Some::OutputType ``` -相当于对于 InputType 调用一个 Some“函数”,然后输出一个 OutputType。 +相当于对于 InputType 调用一个 Some"函数",然后输出一个 OutputType。 -# 命令式 VS 声明式 +# [命令式 VS 声明式]($section.id('命令式 VS 声明式')) 比如实现一个函数,输入一个 bool 值,根据 bool 值,如果为真,那么输出 type A,如果为假那么输出 type B。 -```C++ +```cpp //基本模式 template struct Fn { @@ -81,7 +83,7 @@ struct Fn { 从这里 C++代码可以感觉出,其实你是拿着尺子,对照着基础模式,然后通过模版偏特化来实现不同分支的逻辑。 -```C++ +```cpp Fn sizeof(B), A, B>::OutputType ``` @@ -89,7 +91,7 @@ Fn sizeof(B), A, B>::OutputType 如果用 Zig 来做,则要简单的多: -```Zig +```zig fn Fn(comptime A:type, comptime B: type) type { if (@sizeOf(A) > @sizeOf(B)) { return A; @@ -102,16 +104,16 @@ fn Fn(comptime A:type, comptime B: type) type { 我们再来看递归的列子。比如有一个类型的 list,我们需要返回其中第 N 个 type。同样,由于在 C++中,类型不是一等成员,因此我们不可能有一个`vector`的东东。那怎么办呢?方法就是直接把`type list`放在模板的参数列表里:`typename ...T`。 -于是,我们写出“函数原型”: +于是,我们写出"函数原型": -```C++ +```cpp template struct Fn; ``` 然后我们递归的基础情况 -```C++ +```cpp template struct Fn<0, Head, Tail...> { using Output = Head; @@ -120,7 +122,7 @@ struct Fn<0, Head, Tail...> { 然后写递归式, -```C++ +```cpp template struct Fn : public Fn { @@ -131,14 +133,14 @@ struct Fn : public Fn 第一个偏特化,如果用命令式,类似于, -```C++ +```cpp if (Index == 0) return Head; ``` 第二个偏特化,类似于 -```C++ +```cpp else { return Fn(Index-1, Tail...); } @@ -148,7 +150,7 @@ else { 但是 Zig 实现这个也很直观,由于`slice`和`type`都是内置的,我们可以直接: -```Zig +```zig fn chooseN(N: u32, comptime type_list: []const type) type { return type_list[N]; } @@ -161,6 +163,6 @@ pub fn main() void { 即这个也是完全命令式的。当然 C++20 之后也出现了`if constexpr`和`concept`来进一步简化模版元编程,C++的元编程也在向命令式的方向进化。 -# 结束语 +# [结束语]($section.id('conclusion')) -尽管 Zig 目前“还不成熟”,但是学习 Zig,如果采用一种对照的思路,偶尔也会“触类旁通”C++,达到举一反三的效果。 +尽管 Zig 目前"还不成熟",但是学习 Zig,如果采用一种对照的思路,偶尔也会"触类旁通"C++,达到举一反三的效果。 diff --git a/content/post/2024-05-07-package-hash.md b/content/post/2024-05-07-package-hash.smd similarity index 93% rename from content/post/2024-05-07-package-hash.md rename to content/post/2024-05-07-package-hash.smd index a1ae544..0267ce5 100644 --- a/content/post/2024-05-07-package-hash.md +++ b/content/post/2024-05-07-package-hash.smd @@ -1,16 +1,20 @@ --- -title: "build.zig.zon 中的依赖项哈希值" -author: Wenxuan Feng -date: 2024-05-07T02:45:10.692Z +.title = "build.zig.zon 中的依赖项哈希值", +.date = @date("2024-05-07T02:45:10.692Z"), +.author = "Wenxuan Feng", +.layout = "post.shtml", +.draft = false, --- +# [package hash]($section.id('package-hash')) + > 原文地址:[build.zig.zon dependency hashes](https://zig.news/michalsieron/buildzigzon-dependency-hashes-47kj) -# 引言 +# [引言]($section.id('引言')) 作者 Michał Sieroń 最近在思考 `build.zig.zon` 中的依赖项哈希值的问题。这些哈希值都有相同的前缀,而这对加密哈希函数来说极其不同寻常。习惯性使用 Conda 和 Yocto 对下载的压缩包运行 sha256sum,但生成的摘要与 `build.zig.zon` 中的哈希值完全不同。 -```bash +```zon .dependencies = .{ .mach_freetype = .{ .url = "https://pkg.machengine.org/mach-freetype/309be0cf11a2f617d06ee5c5bb1a88d5197d8b46.tar.gz", @@ -28,9 +32,9 @@ date: 2024-05-07T02:45:10.692Z } ``` -以上摘录取自 [hexops/mach](https://github.com/hexops/mach/blob/bffc66800584123e2844c4bc4b577940806f9088/build.zig.zon#L13-L26) 项目。 +以上摘取自 [hexops/mach](https://github.com/hexops/mach/blob/bffc66800584123e2844c4bc4b577940806f9088/build.zig.zon#L13-L26) 项目。 -# 初步探索 +# [初步探索]($section.id('初步探索')) 经过一番探索,我找到了一个文档:[doc/build.zig.zon.md](https://github.com/ziglang/zig/blob/1a6485d111d270014f57c46c53597a516a24dc47/doc/build.zig.zon.md),似乎没有任何线索指向它。而文档中对哈希有段简短的描述。 @@ -40,7 +44,7 @@ date: 2024-05-07T02:45:10.692Z 该哈希值是基于一系列文件内容计算得出的,这些文件是在获取URL后并应用了路径规则后得到的。 这个字段是最重要的;一个包是的唯一性是由它的哈希值确定的,不同的 URL 可能对应同一个包。 -## 多重哈希 +# [多重哈希]($section.id('多重哈希')) 在他们的网站上有一个很好的可视化展示,说明了这一过程: [多重哈希](https://multiformats.io/multihash/)。 @@ -48,7 +52,7 @@ date: 2024-05-07T02:45:10.692Z 因此 `build.zig.zon` 中的哈希字段不仅包含了摘要(digest),还包含了一些元数据(metadata)。但即使我们丢弃了头部信息,得到的结果仍与下载的 `tar` 包的 `sha256` 摘要不相符。而这就涉及到了包含规则的问题。 -## 包含规则(inclusion rules) +# [包含规则(inclusion rules)]($section.id('包含规则(inclusion rules)')) 回到 [doc/build.zig.zon.md](https://github.com/ziglang/zig/blob/1a6485d111d270014f57c46c53597a516a24dc47/doc/build.zig.zon.md) 文件,我们看到: @@ -89,7 +93,7 @@ pub fn includePath(self: Filter, sub_path: []const u8) bool { 除此之外,这个函数会检查 `sub_path` 是否被明确列出,或者是已明确列出的目录的子目录。 -## 计算哈希 +# [计算哈希]($section.id('计算哈希')) 现在我们知道了 `build.zig.zon` 的包含规则,也知道使用了 `SHA256` 算法。但我们仍然不知道实际的哈希结果是如何得到的。例如,它可能是通过将所有包含的文件内容输入哈希器来计算的。所以让我们再仔细看看,也许我们可以找到答案。 @@ -117,7 +121,7 @@ try all_files.append(hashed_file); 跟踪 `workerHashFile`,我们看到它是 `hashFileFallible` 的一个简单包装,而后者看起来相当复杂。让我们来分解一下。 -## 单个文件的哈希计算 +# [单个文件的哈希计算]($section.id('单个文件的哈希计算')) 首先,会进行一些初始化设置,其中创建并用规整后的文件路径初始化了一个新的哈希器实例: @@ -165,7 +169,7 @@ hasher.update(link_name); 首先进行路径分隔符的规整,保证不同平台一致,之后将符号链接的目标路径输入 `hasher`。在 `hashFileFallible` 函数最后,把计算出的哈希值赋值给 `HashedFile` 对象的 `hash` 字段。 -## 组合哈希 +# [组合哈希]($section.id('组合哈希')) 尽管有了单个文件的哈希值,但我们仍不知道如何得到最终的哈希。幸运的是,曙光就在眼前。 @@ -195,13 +199,13 @@ for (all_files.items) |hashed_file| { 在这里我们看到所有计算出的哈希被一个接一个地输入到一个新的哈希器中。在 `computeHash` 的最后,我们返回 `hasher.finalResult()`,现在我们明白哈希值是如何获得的了。 -## 最终多哈希值 +# [最终多哈希值]($section.id('最终多哈希值')) 现在我们有了一个 `SHA256` 摘要,可以最终返回到 `main.zig`,在那里我们调用 [`Package.Manifest.hexDigest(fetch.actual_hash)`](https://github.com/ziglang/zig/blob/9d64332a5959b4955fe1a1eac793b48932b4a8a8/src/Package/Manifest.zig#L174)。在那里,我们将多哈希头写入缓冲区,之后是我们的组合摘要。 顺便说一下,我们看到所有哈希头都是 `1220` 并非巧合。这是因为 `Zig` [硬编码了 SHA256](https://github.com/ziglang/zig/blob/1a6485d111d270014f57c46c53597a516a24dc47/src/Package/Manifest.zig#L3) - 0x12,它有 32 字节的摘要 - 0x20。 -# 总结 +# [总结]($section.id('总结')) 总结一下:最终哈希值是一个多哈希头 + `SHA256` 摘要。 @@ -211,7 +215,7 @@ for (all_files.items) |hashed_file| { 在实验这个之后,我有一个想法,我很惊讶 Zig 没有检查 `build.zig.zon` 中列出的所有文件是否存在。但这可能是另一天的话题了。 -# 译者注 +# [译者注]($section.id('translators-note')) 在使用本地包时,可以使用下面的命令进行 hash 问题的排查: diff --git a/content/post/2024-05-24-interface-idioms.md b/content/post/2024-05-24-interface-idioms.smd similarity index 94% rename from content/post/2024-05-24-interface-idioms.md rename to content/post/2024-05-24-interface-idioms.smd index aed8c33..916fd21 100644 --- a/content/post/2024-05-24-interface-idioms.md +++ b/content/post/2024-05-24-interface-idioms.smd @@ -1,12 +1,14 @@ --- -title: "Zig 标准库中的实现接口的惯用法与模式" -author: Rui Chen -date: 2024-05-24T23:21:12-05:00 +.title = "Zig 标准库中的实现接口的惯用法与模式", +.date = @date("2024-05-24T23:21:12-05:00"), +.author = "Rui Chen", +.layout = "post.shtml", +.draft = false, --- > 原文链接: https://zig.news/yglcode/code-study-interface-idiomspatterns-in-zig-standard-libraries-4lkj -# 引言 +# [引言]($section.id('引言')) 在 Java 和 Go 中,可以使用“接口”(一组方法或方法集)定义基于行为的抽象。通常接口包含所谓的虚表(`vtable`) 以实现动态分派。Zig 允许在结构体、枚举、联合和不透明类型中声明函数和方法,尽管 Zig 尚未支持接口作为一种语言特性。 @@ -29,7 +31,7 @@ Zig 标准库应用了一些代码习语或模式以达到类似效果。 完整代码位于[此仓库](https://github.com/yglcode/zig_interfaces),你可以使用 `zig test interfaces.zig` 运行它。 -# 背景设定 +# [背景设定]($section.id('背景设定')) 让我们使用经典的面向对象编程示例,创建一些形状:点(`Point`)、盒子(`Box`)和圆(`Circle`)。 @@ -84,7 +86,7 @@ fn init_data() struct { point: Point, box: Box, circle: Circle } { } ``` -# 接口1:枚举标签联合 +# [接口1:枚举标签联合]($section.id('接口1:枚举标签联合')) Loris Cro 在[“使用 Zig 0.10.0 轻松实现接口”](https://zig.news/kristoff/easy-interfaces-with-zig-0100-2hc5) 中介绍了使用枚举标签联合作为接口的方法。这是最简单的解决方案,尽管你必须在联合类型中显式列出所有“实现”该接口的变体类型。 @@ -124,7 +126,7 @@ test "union_as_intf" { } ``` -# 接口2:vtable 和动态分派的第一种实现 +# [接口2:vtable 和动态分派的第一种实现]($section.id('接口2:vtable 和动态分派的第一种实现')) Zig 已从最初基于嵌入式 `vtab` 和 `#fieldParentPtr()` 的动态分派切换到基于“胖指针”接口的以下模式; 请查阅此文章了解更多细节[“Allocgate 将在 Zig 0.9 中到来...”](https://pithlessly.github.io/allocgate.html)。 @@ -196,7 +198,7 @@ test "vtab1_as_intf" { } ``` -# 接口3:vtable 和动态分派的第二种实现 +# [接口3:vtable 和动态分派的第二种实现]($section.id('接口3:vtable 和动态分派的第二种实现')) 在上述第一种实现中,通过 `Shape2.init()` 将 `Box` “转换”为接口 `Shape2` 时,会对 `box` 实例进行类型检查, 以确保其实现了 `Shape2` 的方法(包括名称的匹配签名)。第二种实现中有两个变化: @@ -269,7 +271,7 @@ test "vtab2_as_intf" { } ``` -# 接口4:使用嵌入式 vtab 和 @fieldParentPtr() 的原始动态分派 +# [接口4:使用嵌入式 vtab 和 @fieldParentPtr() 的原始动态分派]($section.id('接口4:使用嵌入式 vtab 和 @fieldParentPtr() 的原始动态分派')) 接口 `std.build.Step` 和所有构建步骤 `std.build.[RunStep, FmtStep, ...]` 仍然使用这种模式。 @@ -362,7 +364,7 @@ test "vtab3_embedded_in_struct" { } ``` -# 接口5:编译时的泛型接口 +# [接口5:编译时的泛型接口]($section.id('interface-5-compile-time-generic-interface')) 所有上述接口都侧重于 `vtab` 和动态分派:接口值将隐藏其持有的具体值的类型。因此,你可以将这些接口值放入数组中并统一处理。 diff --git a/content/post/2024-06-10-zig-hashmap-1.md b/content/post/2024-06-10-zig-hashmap-1.smd similarity index 97% rename from content/post/2024-06-10-zig-hashmap-1.md rename to content/post/2024-06-10-zig-hashmap-1.smd index 87d7fc0..ba84b9f 100644 --- a/content/post/2024-06-10-zig-hashmap-1.md +++ b/content/post/2024-06-10-zig-hashmap-1.smd @@ -1,7 +1,9 @@ --- -title: "HashMap 原理介绍上篇" -author: Wenxuan Feng -date: 2024-06-10T07:57:05.138Z +.title = "HashMap 原理介绍上篇", +.date = @date("2024-06-10T07:57:05.138Z"), +.author = "Wenxuan Feng", +.layout = "post.shtml", +.draft = false, --- > 阅读这篇文章的前提是了解 [Zig 的范型实现](https://www.openmymind.net/learning_zig/generics/) @@ -14,7 +16,7 @@ date: 2024-06-10T07:57:05.138Z 如果查看 `std.HashMap` 的 `put` 方法,会发现一个经常重复的应用模式: -```Zig +```zig pub fn put(self: *Self, key: K, value: V) Allocator.Error!void { return self.unmanaged.putContext(self.allocator, key, value, self.ctx); } @@ -22,11 +24,11 @@ pub fn put(self: *Self, key: K, value: V) Allocator.Error!void { 正如我所说,大部分繁重的工作都由 `std.HashMapUnmanaged` 完成,其他变体通过一个名为 `unmanaged` 的字段对其进行封装。 -# Unmanaged +# [Unmanaged]($section.id('Unmanaged')) 在Zig标准库中随处可见的类型命名约定是 `unmanaged`。这种命名方式表明所涉及的类型不维护 `allocator`。任何需要分配内存的方法都会显式地将 `allocator` 作为参数传递。要实际看到这一点,可以考虑下面这个链表的例子: -```Zig +```zig pub fn LinkedList(comptime T: type) type { return struct { head: ?*Node = null, @@ -141,7 +143,7 @@ pub fn LinkedList(comptime T: type) type { 为了简化,本文的其余部分不会再提到 `unmanaged`。我们看到关于 `StringHashMap` 或 `AutoHashMap` 或 `HashMap` 的任何内容同样适用于它们的 Unmanaged 变体。 -# HashMap 与 AutoHashMap +# [HashMap 与 AutoHashMap]($section.id('HashMap 与 AutoHashMap')) std.HashMap 是一个泛型类型,它接受两个类型参数:键的类型和值的类型。正如我们所见,哈希映射需要两个函数:hash 和 eql。这两个函数合起来被称为“上下文(context)”。这两个函数都作用于键,并且没有一个单一的 hash 或 eql 函数适用于所有类型。例如,对于整数键,eql 将是 `a_key == b_key`;而对于 `[]const u8` 键,我们希望使用 `std.mem.eql(u8, a_key, b_key)`。 @@ -232,7 +234,7 @@ pub const StringContext = struct { }; ``` -# 自定义上下文 +# [自定义上下文]($section.id('自定义上下文')) 我们将在第一部分结束时,直接使用 `HashMap`,这意味着提供我们自己的上下文。我们将从一个简单的例子开始:为不区分大小写的 ASCII 字符串创建一个 `HashMap`。我们希望以下内容输出:`Goku = 9000`。请注意,虽然我们使用键 `GOKU` 进行插入,但我们使用“goku”进行获取: @@ -377,7 +379,7 @@ pub fn hash(_: HashContext, u: User) u64 { 插入这两个函数,以上示例应该可以工作。 -# 结论 +# [结论]($section.id('conclusion')) 希望你现在对 Zig 的哈希表的实现以及如何在代码中利用它们有了更好的理解。在大多数情况下,`std.StringHashMap` 或 `std.AutoHashMap` 就足够了。但知道 `*Unmanaged` 变体的存在和目的,以及更通用的 `std.HashMap`,可能会派上用场。如果没有其他用途,现在文档和它们的实现应该更容易理解了。 diff --git a/content/post/2024-06-11-zig-hashmap-2.md b/content/post/2024-06-11-zig-hashmap-2.smd similarity index 95% rename from content/post/2024-06-11-zig-hashmap-2.md rename to content/post/2024-06-11-zig-hashmap-2.smd index 22dbfe2..dac855e 100644 --- a/content/post/2024-06-11-zig-hashmap-2.md +++ b/content/post/2024-06-11-zig-hashmap-2.smd @@ -1,10 +1,12 @@ --- -title: "HashMap 原理介绍下篇" -author: Wenxuan Feng -date: 2024-06-11T07:57:06.138Z +.title = "HashMap 原理介绍下篇", +.date = @date("2024-06-11T07:57:06.138Z"), +.author = "Wenxuan Feng", +.layout = "post.shtml", +.draft = false, --- -在[第一部分](/post/2024/06/10/zig-hashmap-1/)中,我们探讨了六种 `HashMap` 变体之间的关系以及每种变体为开发人员提供的不同功能。我们主要关注如何为各种数据类型定义和初始化 `HashMap`,并讨论了当 `StringHashMap` 或 `AutoHashMap` 不支持的类型时使用自定义 `hash` 和 `eql` 函数的重要性。在这篇文章中,我们将更深入地研究键和值的存储、访问方式以及我们在它们生命周期管理中的责任。 +在[第一部分](2024-06-10-zig-hashmap-1)中,我们探讨了六种 `HashMap` 变体之间的关系以及每种变体为开发人员提供的不同功能。我们主要关注如何为各种数据类型定义和初始化 `HashMap`,并讨论了当 `StringHashMap` 或 `AutoHashMap` 不支持的类型时使用自定义 `hash` 和 `eql` 函数的重要性。在这篇文章中,我们将更深入地研究键和值的存储、访问方式以及我们在它们生命周期管理中的责任。 Zig 的哈希表内部采用两个切片结构:一个用于存放键(key),另一个用于存储对应的值(value)。通过应用哈希函数计算得到的哈希码被用来在这些数组中定位条目。从基础代码出发,比如: @@ -39,7 +41,7 @@ keys: values: 这个基本的可视化表示将贯穿本文大部分内容,并且不断强调条目的位置需要保持一致性和可预测性。即使哈希表需要在增长时从一个底层数组移动到另一个(即当填充因子达到一定阈值并要求扩大以容纳更多数据时),这一事实是我们将反复回顾的主题。 -# 值管理 +# [值管理]($section.id('值管理')) 如果我们对上述代码片段进行扩展,并调用 `lookup.get("Paul")`,返回的值将是 `1234`。在处理像 `i32` 这样的原始类型时,很难直观地理解 `get` 方法和它的可选返回类型 `?i32` 或更通用的 `?V`(其中 `V` 表示任何值类型)之间的区别。考虑到这一点,让我们通过替换 `i32` 为一个封装了更多信息的 `User` 类型来展示这一概念: @@ -222,7 +224,7 @@ while (it.next()) |value_ptr| { 在最后一种情况下,由于我们存储的是 `User` 而不是 `*User`,我们的 `value_ptr` 是指向 `User` 的指针(不像之前那样是指向指针的指针)。 -# Keys +# [Keys]($section.id('Keys')) 我们可以开始和结束这一节:我们关于值的所有内容同样适用于键。这是100%正确的,但这在某种程度上不太直观。大多数开发人员很快就能理解,存储在哈希表中的堆分配的 `User` 实例有其自身的生命周期,需要显式管理/释放。但由于某些原因,这对于键来说并不那么明显。 @@ -335,7 +337,7 @@ if (lookup.fetchRemove(user.name)) |kv| { 对于大多数情况,在处理非原始键或值时,关键是当你调用哈希表的 `deinit` 时,你为键和值分配的任何内存不会被自动释放;你需要自己处理。 -# getOrPut +# [getOrPut]($section.id('getOrPut')) 虽然我们已经讨论过的内容有很多含义,但对我来说,直接暴露键和值指针的最大好处之一是 `getOrPut` 方法。 @@ -365,7 +367,7 @@ if (gop.found_existing) { 当然,只要不对哈希表进行修改,`value_ptr` 就应被视为有效。顺便提一句,这同样适用于我们通过 `iterator()`、`valueIterator` 和 `keyIterator` 获取的迭代键和值,原因相同。 -# 结论 +# [结论]($section.id('conclusion')) 希望你现在对使用「std.HashMap」、「std.AutoHashMap」和「std.StringHashMap」以及它们的「unmanaged」变体感到更加得心应手。虽然你可能永远不需要提供自己的上下文(例如「hash」和「eql」函数),但了解这是一个选项是有益的。在日常编程中,可视化数据尤其有用,尤其是在使用指针和添加间接层次时。每当我处理 `value_ptr` 或 `key_ptr` 时,我都会想到这些切片以及值或键与这些切片中值或键的实际地址之间的区别。 diff --git a/content/post/2024-06-16-leveraging-zig-allocator.md b/content/post/2024-06-16-leveraging-zig-allocator.smd similarity index 98% rename from content/post/2024-06-16-leveraging-zig-allocator.md rename to content/post/2024-06-16-leveraging-zig-allocator.smd index 348a336..91c11d8 100644 --- a/content/post/2024-06-16-leveraging-zig-allocator.md +++ b/content/post/2024-06-16-leveraging-zig-allocator.smd @@ -1,6 +1,9 @@ --- -title: "Zig 分配器的应用" -date: 2024-06-16T12:11:44+0800 +.title = "Zig 分配器的应用", +.date = @date("2024-06-16T12:11:44+0800"), +.author = "ZigCC", +.layout = "post.shtml", +.draft = false, --- > 原文地址: diff --git a/content/post/2024-08-12-zoop.md b/content/post/2024-08-12-zoop.smd similarity index 92% rename from content/post/2024-08-12-zoop.md rename to content/post/2024-08-12-zoop.smd index afc5adf..fe939ce 100644 --- a/content/post/2024-08-12-zoop.md +++ b/content/post/2024-08-12-zoop.smd @@ -1,20 +1,22 @@ --- -title: "zoop 实现原理分析" -author: 朱亚东 -date: 2024-08-12T14:31:22+08:00 +.title = "zoop 实现原理分析", +.date = @date("2024-08-12T14:31:22+08:00"), +.author = "朱亚东", +.layout = "post.shtml", +.draft = false, --- -# zoop 是什么 +# [zoop]($section.id('zoop')) zoop 是 zig 的一个 OOP 解决方案,详细信息可以看看 [zoop官网](https://zhuyadong.github.io/zoop-docs/)。 -# 为什么不用别的 OOP 语言 +# [为什么不用别的 OOP 语言]($section.id('为什么不用别的 OOP 语言')) 简单的说,是我个人原因,必需使用 zig 的同时,还一定要用 OOP,所以有了 zoop。 -# zoop 入门 +# [zoop 入门]($section.id('zoop 入门')) -## 类和方法 +# [类和方法]($section.id('类和方法')) ```zig pub const Base = struct { @@ -71,7 +73,7 @@ pub const Base = struct { 上面的代码给 `Base` 添加了一个可以继承的方法 `getName()`。 -## 类的继承 +# [类的继承]($section.id('类的继承')) zoop 引入一个关键字 `extends` 用来实现继承,比如下面我们定义 `Base` 的子类 `Child`: @@ -100,7 +102,7 @@ test { } ``` -## 接口定义 +# [接口定义]($section.id('接口定义')) zoop 中的接口,实际上是一个胖指针。下面我们定义一个接口 `IGetName`: @@ -130,7 +132,7 @@ pub const IGetName = struct { 上面的代码具体原理下面会说到,这里大家知道接口就是这样定义的就行了。上面的代码定义了接口 `IGetName`,这个接口有一个方法 `getName()`。 -## 接口实现 +# [接口实现]($section.id('接口实现')) 上面的 `Base` 类正好也有个符合 `IGetName` 接口的方法 `getName()`,那我们修改一下 `Base` 的代码让它来实现 `IGetName` 接口: @@ -146,7 +148,7 @@ pub const Base = struct { 可以看到实现接口和继承用的同样一个关键字 `extends`。因为子类会继承父类的接口,所以这样一来,`Child` 也自动实现了 `IGetName` 接口。 -## 方法重写和虚函数调用 +# [方法重写和虚函数调用]($section.id('方法重写和虚函数调用')) 我们修改上面 `Child` 的代码,重写 `getName()` 方法: @@ -192,7 +194,7 @@ try t.expectEqualStrings(base.as(IGetName).?.getName(), "override"); 那么 zoop 的基本使用方法就介绍到这里,下面我们开始介绍 zoop 的实现原理。 -# 预设场景 +# [预设场景]($section.id('预设场景')) 接下来的讨论基于如下的属于 `mymod` 模块的类和接口: @@ -283,7 +285,7 @@ pub const Child = struct { - `Base`: 基类,实现接口 `ISetName` - `Child`: 子类,继承 `Base`,并实现接口 `IGetName` -# 核心数据结构 `zoop.Mixin(T)` +# [核心数据结构 `zoop.Mixin(T)`]($section.id('核心数据结构 `zoop.Mixin(T)`')) 我们看看两个类的 `mixin` 这个数据里面有什么: @@ -337,7 +339,7 @@ zoop.Mixin(Child) = struct { 上面两个函数获取的都是最外层对象的数据。根据对 `mixin` 数据的分析,zoop 的类型转换的原理就很清楚了,大家可以参考官网上关于 [类型转换](https://zhuyadong.github.io/zoop-docs/guide/as-cast) 的内容。 -# 动态构造类的方法、接口方法、和 `Vtable` +# [动态构造类的方法、接口方法、和 `Vtable`]($section.id('动态构造类的方法、接口方法、和 `Vtable`')) OOP 概念中的继承,重写,虚函数,实质其实就是在编译时动态构造需要的方法和属性。zoop 中主要是通过通过 [zoop.tuple](https://zhuyadong.github.io/zoop-docs/reference/tuple) 这个模块来进行编译时动态构造。 @@ -345,11 +347,11 @@ OOP 概念中的继承,重写,虚函数,实质其实就是在编译时动 下面我介绍一下 zoop 中用到的 `comptime` 一些技巧,相信会对大家今后使用 zig 有帮助。 -## `struct` 很万能 +# [`struct` 很万能]($section.id('`struct` 很万能')) `comptime` 编程中,`struct` 是你最好的朋友,想在不同的 `comptime` 函数之间传递数据,最方便的方式,就是通过构造一个 `struct`,把想传递的数据通过 `pub const xxx = ...` 的方式传递出去,通过 `struct` 保存数据最好的地方,就在于这个数据在运行时也是可用的 (`struct` 中的常量,是保存在 exe 的 `.data` 区,运行时可见),[zoop.tuple](https://zhuyadong.github.io/zoop-docs/reference/tuple) 就是通过这个方法实现的。 -## 动态构造 `struct` 的字段,用 `@Type()` +# [动态构造 `struct` 的字段,用 `@Type()`]($section.id('动态构造 `struct` 的字段,用 `@Type()`')) 网上好像很少有关于 `@Type()` 的使用说明,一般都是通过看 `zig.std` 的代码来学习,那我这里就稍微说明一下,希望能对大家有帮助。 目前 zig 通过 `@Type()`,能动态构造的 `struct`,只有纯字段类型的 `struct` (个人理解)。构造的方法,就是先把计算好的一个 `std.builtin.Type.StructField` 数组传递给 `@Type()` 来返回一个 `struct`,比如以下代码: @@ -396,7 +398,7 @@ const MyStruct = struct { zoop 动态构造 `Vtable` 就是通过这个方法做到的,参考 [zoop.DefVtable 原理](https://zhuyadong.github.io/zoop-docs/reference/principle#DefVtable) 和 [zoop 源代码](https://github.com/zhuyadong/zoop.git) -## 动态构造 `struct` 的函数,用 `usingnamespace` +# [动态构造 `struct` 的函数,用 `usingnamespace`]($section.id('动态构造 `struct` 的函数,用 `usingnamespace`')) 要想定义 `struct` 中的函数,理论上代码是一定要写在 `struct` 中的,目前 zig 唯一留下的一个口子,就是 `usingnamespace`,zoop 正是利用这个特性,来动态构造 `struct` 的函数。 @@ -440,7 +442,7 @@ pub usingnamespace struct { 因而实现了对 `Base.setName()` 方法的继承。 -## 运行时根据类型找 `Vtable` 和父类指针 +# [运行时根据类型找 `Vtable` 和父类指针]($section.id('finding-vtable-and-parent-class-pointers-at-runtime-based-on-type')) 这个功能的实现当时第一版是使用的 `std.StaticStringMap` 保存了一个类中所有接口名到接口 `Vtable` ,以及父类名到父类数据在本类中的地址偏移的映射。和 C++ 的 `dynamic_cast` 比起来,性能是比较差的。后来看到西瓜大大发的一个链接 [点这里](https://github.com/SuperAuguste/cursed-zig-errors),忽然意识到这不就是我一直想要的 `comptime` 全局变量么,我终于能写出 `typeId(comptime T: type) u32` 这样的函数了: diff --git a/content/post/2024-11-26-typed-fsm.md b/content/post/2024-11-26-typed-fsm.smd similarity index 94% rename from content/post/2024-11-26-typed-fsm.md rename to content/post/2024-11-26-typed-fsm.smd index 69bbb22..8ae6d63 100644 --- a/content/post/2024-11-26-typed-fsm.md +++ b/content/post/2024-11-26-typed-fsm.smd @@ -1,12 +1,16 @@ --- -title: "在 zig 中实现类型安全的有限状态机" -author: sdzx -date: 2024-11-26T13:32:00+08:00 +.title = "在 zig 中实现类型安全的有限状态机", +.date = @date("2024-11-26T13:32:00+08:00"), +.author = "sdzx", +.layout = "post.shtml", +.draft = false, --- -# 1. 简单介绍类型化有限状态机的优势 +# [typed fsm]($section.id('typed-fsm')) -## 1.1 介绍有限状态机 +# [1. 简单介绍类型化有限状态机的优势]($section.id('1. 简单介绍类型化有限状态机的优势')) + +# [1.1 介绍有限状态机]($section.id('1.1 介绍有限状态机')) 有限状态机(FSM,以下简称状态机)是程序中很常见的设计模式。 @@ -14,7 +18,7 @@ date: 2024-11-26T13:32:00+08:00 而状态主要是在代码层面帮助人们理解消息的产生和处理。 -## 1.2 [typed-fsm-zig](https://github.com/sdzx-1/typed-fsm-zig) +# [1.2 [typed-fsm-zig](https://github.com/sdzx-1/typed-fsm-zig) typed-fsm-zig 是一个利用 zig 类型系统加一些编程规范实现的一个库,用于实现类型安全的有限状态机。 @@ -35,13 +39,13 @@ typed-fsm-zig 是一个利用 zig 类型系统加一些编程规范实现的一 在实际的使用中没有任何的代码生成,除了一处隐式的约束要求之外,没有任何其它的控制,开发者完全掌握状态机,因此你可以方便的将它和你现有的代码结合起来。 -# 2. 例子:修改 ATM 状态机的状态 +# [2. 例子:修改 ATM 状态机的状态]($section.id('2. 例子:修改 ATM 状态机的状态')) 这里我将以一个 ATM 状态机(以下简称 ATM)的例子来展示 typed-fsm-zig 和 zig 的类型系统如何帮助我快速修改 ATM 的状态。 为了简单性,这里我不展示构建 ATM 这个例子的过程,感兴趣的可以在这里看到[代码](https://github.com/sdzx-1/typed-fsm-zig/blob/master/examples/atm-gui.zig)。 -## 2.1 介绍 ATM 状态机 +# [2.1 介绍 ATM 状态机]($section.id('2.1 介绍 ATM 状态机')) ATM 代表自动取款机,因此它的代码的逻辑就是模拟自动取款机的一些行为:插入银行卡,输入 pin,检查 pin,取钱,修改 pin。 @@ -72,7 +76,7 @@ ATM 代表自动取款机,因此它的代码的逻辑就是模拟自动取款 接下来的文章中我将修改 Update 的行为,并展示在这个过程中类型系统如何帮助我快速调整代码。 -## 2.2 修改 Update 消息 +# [2.2 修改 Update 消息]($section.id('2.2 修改 Update 消息')) 实际的消息 Update 定义代码如下 @@ -96,7 +100,7 @@ ATM 代表自动取款机,因此它的代码的逻辑就是模拟自动取款 这时如果我重新编译代码,那么类型系统就会产生下面的错误: -```shell +```bash ➜ typed-fsm-zig git:(doc) ✗ zig build atm-gui atm-gui @@ -130,7 +134,7 @@ referenced by: 在这里类型系统精确的告诉了我们需要修改的地方,以及原因。修改完成后程序即能正确运行。 -## 2.3 移除 changePin 状态 +# [2.3 移除 changePin 状态]($section.id('2.3 移除 changePin 状态')) 这一节中我们尝试移除 changePin 状态,看看类型系统会给我们什么反馈。 如果移除 changePin,新的状态图如下: @@ -141,7 +145,7 @@ referenced by: 类型系统的反馈首先是: -```shell +```bash examples/atm-gui.zig:148:36: error: enum 'atm-gui.AtmSt' has no member named 'changePin' ChangePin: WitFn(end, .changePin), ~^~~~~~~~~ @@ -151,7 +155,7 @@ examples/atm-gui.zig:148:36: error: enum 'atm-gui.AtmSt' has no member named 'ch 新的反馈如下: -```shell +```bash examples/atm-gui.zig:161:64: error: union 'atm-gui.AtmSt.sessionMsg(.exit)' has no member named 'ChangePin' if (resource.changePin.toButton()) return .ChangePin; ~^~~~~~~~~ @@ -161,7 +165,7 @@ examples/atm-gui.zig:161:64: error: union 'atm-gui.AtmSt.sessionMsg(.exit)' has 新的反馈如下: -```shell +```bash examples/atm-gui.zig:296:10: error: no field named 'ChangePin' in enum '@typeInfo(atm-gui.AtmSt.sessionMsg(.exit)).@"union".tag_type.?' .ChangePin => |wit| { ~^~~~~~~~~ @@ -173,7 +177,7 @@ examples/atm-gui.zig:296:10: error: no field named 'ChangePin' in enum '@typeInf 在这个过程中类型系统帮助我们找到问题和原因。这非常酷!!! -## 2.4 总结 +# [2.4 总结]($section.id('2.4 总结')) 以上是一个简单的例子,展示了 typed-fsm-zig 对于提升状态机编程体验的巨大效果。 @@ -190,7 +194,7 @@ examples/atm-gui.zig:296:10: error: no field named 'ChangePin' in enum '@typeInf -# 3. 原理与实现 +# [3. 原理与实现]($section.id('3. 原理与实现')) 最开始的版本是[typed-fsm](https://github.com/sdzx-1/typed-fsm),由使用 haskell 实现,它实现了完整类型安全的有限状态机。 @@ -430,7 +434,7 @@ fn s2Handler(val: Witness(Exmaple, .exit, .s2), ref: *i32) void { 以上就是 typed-fsm-zig 核心想法的完整介绍。接下来我将介绍需要的编程规范。 -# 4. typed-fsm-zig 需要哪些编程规范 +# [4. typed-fsm-zig 需要哪些编程规范]($section.id('4. typed-fsm-zig 需要哪些编程规范')) 1. 状态和消息集合之间需要满足的隐式命名规范 @@ -544,7 +548,7 @@ pub fn readyHandler(comptime w: AtmSt.EWitness(.ready), ist: *InternalState) voi 遵循这四点要求,就能获得强大的类型安全保证,足以让你愉快的使用状态机! -# 5. 接下来能够增强的功能 +# [5. 接下来能够增强的功能]($section.id('5-future-enhancements')) 暂时我能想到的有如下几点: diff --git a/content/post/2025-01-23-bonkers-comptime.md b/content/post/2025-01-23-bonkers-comptime.smd similarity index 95% rename from content/post/2025-01-23-bonkers-comptime.md rename to content/post/2025-01-23-bonkers-comptime.smd index bf6e02f..24658b3 100644 --- a/content/post/2025-01-23-bonkers-comptime.md +++ b/content/post/2025-01-23-bonkers-comptime.smd @@ -1,14 +1,16 @@ --- -title: Zig comptime 棒极了 -author: xihale -date: 2025-01-23T12:00:00+08:00 +.title = "Zig comptime 棒极了", +.date = @date("2025-01-23T12:00:00+08:00"), +.author = "xihale", +.layout = "post.shtml", +.draft = false, --- > 原文: > 译注:原文中的代码块是交互式,翻译时并没有移植。另外,由于 comptime 本身即是关键概念,并且下文的意思更侧重于 Zig comptime 的特性,故下文大多使用 comptime 代替编译时概念。 -## 引子 +# [引子]($section.id('引子')) 编程通过自动化地处理数据极大地提升了生产力。而元编程则让我们可以像处理数据一样处理代码,以此将编程的力量反向作用于编程自身。而在底层编程中,我想元编程可能带来最大的优势,因为那些高级概念必须得精确映射到某些低级操作。然而,除了函数式编程语言外,我一直觉得各编程语言对元编程的实现并不理想。因此,当我看到 Zig 把元编程列为一个主要特性时,我提起了很大的兴趣。 @@ -18,7 +20,7 @@ date: 2025-01-23T12:00:00+08:00 为了明确起见,所有示例都是有效的 Zig 代码,但示例中的转换只是概念性的,它们并不是 Zig 实际的实现方式。 -## 视角0: 忽略它 +# [视角0: 忽略它]($section.id('视角0: 忽略它')) 我说我喜欢这个特性,却又立刻叫你忽略它,这确实有点怪。但我认为此处正是 Zig comptime 威力所体现的地方,所以我将从这里出发。Zig Zen 中的第三条是“倾向于阅读代码,而不是编写代码。”确实,能够轻松地阅读代码在各种情况下都很重要,因为它是建立概念理解的基础,而这种理解也是调试或修改代码所必需的。 @@ -28,7 +30,7 @@ date: 2025-01-23T12:00:00+08:00 > 普通的运行时代码 -```Zig +```zig pub fn main() void { const array: [3]i64 = .{1,2,3}; var sum: i64 = 0; @@ -43,7 +45,7 @@ pub fn main() void { > 基于 comptime 的代码 -```Zig +```zig const MyStruct = struct { a: i64, b: i64, @@ -69,13 +71,13 @@ pub fn main() void { Zig 中有很多基于 comptime 且远远不止这样简单的类型反射,但你只需要阅读那些代码、完全无需深入了解其中有关 comptime 的细节就可以理解它们在干什么。当然,如果你想使用 comptime 编写代码,则不能仅仅止步于此,让我们继续深入。 -## 视角1: 泛型 +# [视角1: 泛型]($section.id('视角1: 泛型')) 泛型在 Zig 中并不是一个特定的功能。相反,Zig 中的仅仅一小部分的 comptime 特性就可以提供用来处理你进行泛型编程所需的一切。这种视角虽然不能让你完全理解 comptime,但它确实为你提供了一个入口点,借此,你可以完成基于元编程的许多任务。 要使一个类型成为泛型,只需将其定义包裹在一个接受类型并返回类型的函数中。(译注:由于 Zig 中类型是一等公民,所以面向类型的编程是合法且常见的) -```Zig +```zig pub fn GenericMyStruct(comptime T: type) type { return struct { a: T, @@ -105,7 +107,7 @@ pub fn main() void { 泛型函数也可以如此实现。 -```Zig +```zig fn quadratic(comptime T: type, a: T, b: T, c: T, x: T) T { return a * x*x + b * x + c; } @@ -119,13 +121,13 @@ pub fn main() void { 当然,也可以通过使用特殊类型 anytype 来推断参数的类型,而这通常在参数的类型对函数签名的其余部分没有影响时使用。(译注:此时要限制 a, b, c 的类型相同,所以此处不用 anytype ) -## 视角2:编译时运行的标准代码 +# [视角2:编译时运行的标准代码]($section.id('视角2:编译时运行的标准代码')) 这是一个古老的故事: 增加一种自动执行命令的方法。当然,你还需要变量。 哦,还有条件。 拜托,能给我循环吗?这些看似合理的需求,最终导致这些自动化命令变得越来越复杂,甚至演变成一个完整的宏语言。 但 Zig 不同, 在运行时、编译时,甚至是构建系统中都使用了相同的语言。 考虑经典的 Fizz Buzz。 -```Zig +```zig fn fizzBuzz(writer: std.io.AnyWriter) !void { var i: usize = 1; while (i <= 100) : (i += 1) { @@ -150,7 +152,7 @@ pub fn main() !void { 确实很简单。但是,每当讨论如何优化 Fizz Buzz 算法时,人们总是忽略一个事实:标准的 Fizz Buzz 问题只需要输出前100个数字的结果。既然输出是固定的,那为什么不直接预先计算出答案,然后输出呢?(由此,我时常认为那些有关优化讨论有些滑稽的。) 我们可以使用相同的 Fizz Buzz 函数来实现这一点。 -```Zig +```zig pub fn main() !void { const full_fizzbuzz = comptime init: { var cw = std.io.countingWriter(std.io.null_writer); @@ -176,7 +178,7 @@ pub fn main() !void { comptime 和运行时之间有一些小的区别。比如,只有 comptime 可以访问类型为 comptime_int、comptime_float 或 type 的变量。此外,一些函数只有 comptime 参数,这使它们仅限于编译时环境。相对的,只有运行时才能进行系统调用和那些依赖系统调用的函数。如果你的代码不使用这些特性,那么它在编译时和运行时中的表现将是一样的。 -## 视角3:[程序特化](https://en.wikipedia.org/wiki/Partial_application) +# [视角3:[程序特化](https://en.wikipedia.org/wiki/Partial_application) > 译者注:程序特化(Partial Evaluation)是一种编译优化技术,主要是:在编译期预先计算部分表达式或代码路径,以减少运行时计算开销,提前生成更具体的代码实现。 @@ -187,7 +189,7 @@ comptime 和运行时之间有一些小的区别。比如,只有 comptime 可 代码求值的一种方式是将输入替换为其运行时值,然后反复将第一个表达式替换为求值形式,直到表达式为基本元素。这在计算机科学理论上下文中很常见,在某些函数式语言中也是如此。作为后续示例的铺垫,我们将使用数组求和来展示这个过程: -```Zig +```zig pub fn main() void { const array: [3]i64 = .{1,2,3}; var sum: i64 = 0; @@ -215,7 +217,7 @@ pub fn main() void { 程序特化是一种可以向函数传递部分(但不一定是全部)参数的技术。 在这种情况下,可以对只使用已知值的表达式进行替换。 这样就产生了一个新函数,它只接受仍然未知的参数。 comtime 可以看作是在编译过程中进行的部分求值。 再看一下 sum 结构的例子,我们就会发现: -```Zig +```zig onst MyStruct = struct { a: i64, b: i64, @@ -253,7 +255,7 @@ onst MyStruct = struct { 上面的示例是我们手动展开后的示例,但这项工作是由 Zig 的 comptime 完成的。这使得我们可以直接独立而完整地编写出我们要实现的功能,而不需要添加"当你改变 `MyStruct` 的字段时,记得更新 sum 函数"这样的由于依赖于 `MyStruct` 具体字段而预防功能失效的注释。 基于 comptime 的版本在 `MyStruct` 的任何字段变更时都可以正确地自动处理。 -## 视角4:Comptime 求值,运行时代码生成 +# [视角4:Comptime 求值,运行时代码生成]($section.id('视角4:Comptime 求值,运行时代码生成')) 这与程序特化(Partial Evaluation)非常相似。这里有两个版本的代码,输入(编译前)和输出(编译后)。输入代码由编译器运行。如果一个语句在编译时是可知的,它就会被直接求值。但是如果一个语句需要某些运行时的值,那么这个语句就会被添加到输出代码中。 @@ -261,7 +263,7 @@ onst MyStruct = struct { > 输入这一段代码: -```Zig +```zig const MyStruct = struct { a: i64, b: i64, @@ -279,7 +281,7 @@ const MyStruct = struct { > 生成出的代码: -```Zig +```zig const MyStruct = struct { a: i64, b: i64, @@ -303,7 +305,7 @@ const MyStruct = struct { 这样做的另一个后果是,Zig 代码的静态分析要比大多数静态类型语言复杂得多,因为编译器需要运行很大一部分才能确定所有类型。 因此,在 Zig 工具链跟上之前,代码自动补全等编辑工具并不总是能很好地发挥作用。 -## 视角5:直接生成代码(Textual Code Generation) +# [视角5:直接生成代码(Textual Code Generation)]($section.id('视角5:直接生成代码(Textual Code Generation)')) 我在文章开头感叹元编程难度。然而,即使在 Zig 中,它仍然是一个强大的工具,在解决某些问题方面也占有一席之地。如果您熟悉这种元编程方法,对 Zig comptime 提供的功能可能会觉得有些残缺。比如, 怎么在写一段代码在运行时能够生成新代码? @@ -311,7 +313,7 @@ const MyStruct = struct { 下有两例。第一个是一个元编程的示例,第二个是我们熟悉的 comptime 示例。这两个版本的代码有着相同的逻辑。 -```Zig +```zig pub fn writeSumFn( writer: std.io.AnyWriter, type_name: []const u8, @@ -336,7 +338,7 @@ pub fn writeSumFn( 回到泛型的例子,有一些值得强调的细微之处: -```Zig +```zig pub fn writeMyStructOfType( writer: std.io.AnyWriter, T: []const u8, @@ -366,13 +368,13 @@ pub fn writeMyStructOfType( 与本节相关的是文本宏,如 C 语言中的文本宏。你可以做的大多数正常事情都可以在 comptime 中完成,尽管它们很少采用类似的形式。 不过,文本宏并不能做所有允许做的事情。 例如,你不能决定不喜欢某个 Zig 关键字,然后让宏代替你自己的关键字。 我认为这是一个正确的决定,尽管对于那些习惯了这种能力的人来说,这是一个艰难的过渡。 此外,Zig 参考了半个世纪以来的程序员在这方面的探索,所以它的选择要理智得多。 -## 结论 +# [结论]($section.id('结论')) 在阅读 Zig 代码以理解代码行为时,考虑 comptime 并不是必要的。而当编写 comptime 代码时,我通常会将其视为程序特化(Partial Evaluation)的一种形式。然而,如果你知道如何使用不同的元编程方法解决问题,你很可能有能力将其翻译成 comptime 形式。 元编程中直接生成代码的方法的存在,就是我全力支持 Zig 风格的 comptime 元编程的原因。尽管,直接生成代码是几乎是最强大的,但是,在阅读和调试时忽略 comptime 的特性的元编程方法确是最简单的。正因如此,我给本文取名为《Zig comptime 棒极了》。 -## 进一步阅读 +# [进一步阅读]($section.id('further-reading')) Zig 并非一个仅仅依赖 comptime 这一特性的语言。你可以在[官方网站](https://ziglang.org/)上了解更多关于 Zig 的信息。 diff --git a/content/post/_index.md b/content/post/_index.md deleted file mode 100644 index 05e8314..0000000 --- a/content/post/_index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: 博客 -type: blog -cascade: - - type: blog - _target: - path: "/**" ---- - -欢迎大家向我们投稿,会同步到微信公众号,投稿方式见[这里](/post/2023/09/05/hello-world/)。 diff --git a/content/post/index.smd b/content/post/index.smd new file mode 100644 index 0000000..ed228fc --- /dev/null +++ b/content/post/index.smd @@ -0,0 +1,11 @@ +--- +.title = "博客", +.date = @date("2024"), +.author = "ZigCC", +.layout = "post.shtml", +.draft = false, +--- + +欢迎大家向我们投稿,会同步到微信公众号,投稿方式见[这里](./2023-09-05-hello-world)。 + +[社区新闻](./news) \ No newline at end of file diff --git a/content/post/news/2023-12-11-first-meetup.org b/content/post/news/2023-12-11-first-meetup.org deleted file mode 100644 index 73aa694..0000000 --- a/content/post/news/2023-12-11-first-meetup.org +++ /dev/null @@ -1,40 +0,0 @@ -#+TITLE: Zig 语言中文社区第一次线上会议 -#+DATE: 2023-12-11T08:25:00+0800 -#+LASTMOD: 2024-05-11T10:35:22+0800 -#+TAGS[]: community - -2023 年 12 月 9 日,Zig 中文社区第一次线上会议隆重召开。共有 8 位 Zig 爱好者参加,分布在北上杭成、美国等不同地方。 - -{{< figure src="/images/first-online-meeting.webp" caption="会议参会人员">}} - -和当年的从仙童半导体出逃的人数一样,不多不少。😄 -{{< figure src="/images/fair-children.webp" caption="硅谷八叛徒">}} -会议伊始,成员首先进行了个人简介,便于后续开展相应工作。随后,社区成员围绕 Zig 语言的普及进行了交流讨论。 - -在交流讨论环节,大家就 Zig 语言的普及面临的挑战和机遇进行了深入的探讨。其中,大家认为 Zig 语言的普及面临的主要挑战包括: - -- Zig 语言是一个新兴的语言,知名度还不够高。 -- Zig 语言的生态还不够完善,缺乏成熟的库和工具。 - -与此同时,大家也认为 Zig 语言的普及也具有一定的机遇,包括: - -- Zig 语言具有很强的性能、安全性和易用性,具有一定的竞争力。 -- Zig 语言的设计理念与 C 语言类似,对于 C 语言开发者来说具有较高的学习成本。 - -因此,第一阶段,我们打算推出一系列教程来帮助大家学习 Zig,目前主要有以下几个: - -| 项目 | 参与人员 | 目标 | 仓库 | -|----------------+---------------+----------------------------------------------+------------------------------| -| Zig 入门教程 | 金中甲 | 让没有编程背景的人可以有体系的学习 Zig | [[https://github.com/learnzig/learnzig][learnzig/learnzig]] | -| Zig 教学视频 | Onion、Lambert | 同上,素材取自 [[https://zigcc.github.io/learning-zig/][Learning Zig 中文翻译]] | | -| Zig cookbook | 夜白、冯文轩 | 演示如何用 Zig 做某个功能 | [[https://github.com/zigcc/zig-cookbook][zigcc/zig-cookbook]] | -| Zig 构建系统教程 | 贺鹏、陈瑞 | 体验 Zig 编译系统的能力与优势、与其他构建系统的对比 | [[https://zigcc.github.io/post/][zigcc 网站系列文章]] | -| Zig 写 OS 教程 | 柠檬、西瓜 | 体现 Zig low level 的优势 | [[https://github.com/zigcc/how-to-write-os-in-zig][zigcc/how-to-write-os-in-zig]] | -| Zig 惯用法 | 全体 | 收集 Zig 编程技巧 | [[https://github.com/zigcc/zig-idioms][zigcc/zig-idioms]] | - - -我们希望通过这些努力,提高 Zig 语言的知名度,完善 Zig 语言的生态,促进 Zig 语言的交流和学习。 -* 结论 -Zig 中文社区第一次线上会议的召开,标志着 Zig 社区正式启航。如果读者对共建社区感兴趣,欢迎与我们联系。 - -- 邮箱:zig@liujiacai.net diff --git a/content/post/news/2023-12-11-first-meetup.smd b/content/post/news/2023-12-11-first-meetup.smd new file mode 100644 index 0000000..ad8f810 --- /dev/null +++ b/content/post/news/2023-12-11-first-meetup.smd @@ -0,0 +1,53 @@ +--- +.title = "Zig 语言中文社区第一次线上会议", +.date = @date("2023-12-11T08:25:00+0800"), +.author = "ZigCC", +.layout = "post.shtml", +.draft = false, +--- + +2023 年 12 月 9 日,Zig 中文社区第一次线上会议隆重召开。共有 8 位 Zig +爱好者参加,分布在北上杭成、美国等不同地方。 + +[会议参会人员]($image.siteAsset('images/first-online-meeting.webp')) + + +和当年的从仙童半导体出逃的人数一样,不多不少。😄 [硅谷八叛徒]($image.siteAsset('images/fair-children.webp')) + +会议伊始,成员首先进行了个人简介,便于后续开展相应工作。随后,社区成员围绕 +Zig 语言的普及进行了交流讨论。 + +在交流讨论环节,大家就 Zig +语言的普及面临的挑战和机遇进行了深入的探讨。其中,大家认为 Zig +语言的普及面临的主要挑战包括: + +- Zig 语言是一个新兴的语言,知名度还不够高。 +- Zig 语言的生态还不够完善,缺乏成熟的库和工具。 + +与此同时,大家也认为 Zig 语言的普及也具有一定的机遇,包括: + +- Zig 语言具有很强的性能、安全性和易用性,具有一定的竞争力。 +- Zig 语言的设计理念与 C 语言类似,对于 C + 语言开发者来说具有较高的学习成本。 + +因此,第一阶段,我们打算推出一系列教程来帮助大家学习 +Zig,目前主要有以下几个: + +| 项目 | 参与人员 | 目标 | 仓库 | +|------------------|----------------|-------------------------------------------------------------------------------|---------------------------------------------------------------------------------| +| Zig 入门教程 | 金中甲 | 让没有编程背景的人可以有体系的学习 Zig | [learnzig/learnzig](https://github.com/learnzig/learnzig) | +| Zig 教学视频 | Onion、Lambert | 同上,素材取自 [Learning Zig 中文翻译](https://zigcc.github.io/learning-zig/) | | +| Zig cookbook | 夜白、冯文轩 | 演示如何用 Zig 做某个功能 | [zigcc/zig-cookbook](https://github.com/zigcc/zig-cookbook) | +| Zig 构建系统教程 | 贺鹏、陈瑞 | 体验 Zig 编译系统的能力与优势、与其他构建系统的对比 | [zigcc 网站系列文章](https://zigcc.github.io/post/) | +| Zig 写 OS 教程 | 柠檬、西瓜 | 体现 Zig low level 的优势 | [zigcc/how-to-write-os-in-zig](https://github.com/zigcc/how-to-write-os-in-zig) | +| Zig 惯用法 | 全体 | 收集 Zig 编程技巧 | [zigcc/zig-idioms](https://github.com/zigcc/zig-idioms) | + +我们希望通过这些努力,提高 Zig 语言的知名度,完善 Zig 语言的生态,促进 +Zig 语言的交流和学习。 + +# [结论]($section.id('conclusion')) + +Zig 中文社区第一次线上会议的召开,标志着 Zig +社区正式启航。如果读者对共建社区感兴趣,欢迎与我们联系。 + +- 邮箱:zig@liujiacai.net diff --git a/content/post/news/2023-12-27-second-meetup.org b/content/post/news/2023-12-27-second-meetup.org deleted file mode 100644 index b693050..0000000 --- a/content/post/news/2023-12-27-second-meetup.org +++ /dev/null @@ -1,45 +0,0 @@ -#+TITLE: ZigCC 第二次线上会议 -#+DATE: 2023-12-27T08:39:51+0800 -#+LASTMOD: 2024-08-18T12:02:01+0800 -#+TAGS[]: community - -2023-12-23,ZigCC 社区开始了第二次线上会议,共有 5 名 Zig 爱好者参加,分别是: -- [[https://github.com/jiacai2050/][西瓜]] -- [[https://github.com/xnhp0320][贺鹏]] -- [[https://github.com/labspc][Lambert]] -- [[https://github.com/fwx5618177][冯文轩]] -- [[https://github.com/1000copy][Reco]] - -这次会议主要是同步了之前会议落实的 action,主要是同步了不同项目的进展,由于临近年底,大家进度都不算太大,但还是有所进展,算是开了个好头😄 - -* 项目进展 -** [[https://github.com/zigcc/zig-os][Zig-OS]] -- 主要参与人员:西瓜 -- 进展:粗略看完 rust 版本的教程;完成 freestanding 二进制,现在卡在了 bootloader 阶段 -** [[https://github.com/learnzig/learnzig][Learn zig]] -- 主要参与人员:金中甲 -- zig的进阶特性,诸如构建系统、包管理、与C交互均已完成,目前教程内容已基本覆盖日常使用 -- 增加了评论区的功能 -- 待完成:反射(编译期反射和运行时反射)、内建函数说明(包含使用例子)、未定义行为、wasm、原子操作这些边缘部分 -** Zig 教学视频 -- 主要参与人员:Lambert -- https://github.com/labspc/learn-zig-in-the-style-of-c -- 暂无明显进展 -** [[https://github.com/zigcc/zig-cookbook][Zig cookbook]] -- 主要参与人员:夜白、西瓜 -- 已经完成大部分内容 👍 -** Zig 构建系统教程 -- 主要参与人员:Reco -- 目前主要是对 [[https://zig.news/xq/zig-build-explained-part-3-1ima][zig build explained]] 系列文章翻译 - -* 新人介绍 -在第一次会议后,有一些朋友想加入 ZigCC 社区,经过简单筛选,新增一名成员:Reco,下面是他的一些履历: -- 南美 Optimes co.,limited 联合创始人、CTO -- 任我行软件股份有限公司 集团CTO - -其他技术兴趣经历 -1. 图灵出版社区签约作者。4本电子系列书:《Vue.js小书》《Git小书》《HTTP小书》《Swift iOS开发小书》 -2. 微软 DotNet 技术俱乐部 2007-2010年成都地区主席 -3. https://github.com/1000copy - -非常欢迎 Reco 的加入!也希望更多对 Zig 感兴趣的朋友加入我们,普及 Zig 在中文社区内的使用。联系邮箱:zig@liujiacai.net diff --git a/content/post/news/2023-12-27-second-meetup.smd b/content/post/news/2023-12-27-second-meetup.smd new file mode 100644 index 0000000..ddcce3e --- /dev/null +++ b/content/post/news/2023-12-27-second-meetup.smd @@ -0,0 +1,70 @@ +--- +.title = "ZigCC 第二次线上会议", +.date = @date("2023-12-27T08:39:51+0800"), +.author = "ZigCC", +.layout = "post.shtml", +.draft = false, +--- + +2023-12-23,ZigCC 社区开始了第二次线上会议,共有 5 名 Zig +爱好者参加,分别是: + +- [西瓜](https://github.com/jiacai2050/) +- [贺鹏](https://github.com/xnhp0320) +- [Lambert](https://github.com/labspc) +- [冯文轩](https://github.com/fwx5618177) +- [Reco](https://github.com/1000copy) + +这次会议主要是同步了之前会议落实的 +action,主要是同步了不同项目的进展,由于临近年底,大家进度都不算太大,但还是有所进展,算是开了个好头😄 + +# [项目进展]($section.id('项目进展')) + +# [Zig-OS](https://github.com/zigcc/zig-os) + +- 主要参与人员:西瓜 +- 进展:粗略看完 rust 版本的教程;完成 freestanding 二进制,现在卡在了 + bootloader 阶段 + +# [Learn zig](https://github.com/learnzig/learnzig) + +- 主要参与人员:金中甲 +- zig的进阶特性,诸如构建系统、包管理、与C交互均已完成,目前教程内容已基本覆盖日常使用 +- 增加了评论区的功能 +- 待完成:反射(编译期反射和运行时反射)、内建函数说明(包含使用例子)、未定义行为、wasm、原子操作这些边缘部分 + +# [Zig 教学视频]($section.id('Zig 教学视频')) + +- 主要参与人员:Lambert +- +- 暂无明显进展 + +# [Zig cookbook](https://github.com/zigcc/zig-cookbook) + +- 主要参与人员:夜白、西瓜 +- 已经完成大部分内容 👍 + +# [Zig 构建系统教程]($section.id('Zig 构建系统教程')) + +- 主要参与人员:Reco +- 目前主要是对 [zig build + explained](https://zig.news/xq/zig-build-explained-part-3-1ima) + 系列文章翻译 + +# [新人介绍]($section.id('new-member-introduction')) + +在第一次会议后,有一些朋友想加入 ZigCC +社区,经过简单筛选,新增一名成员:Reco,下面是他的一些履历: + +- 南美 Optimes co.,limited 联合创始人、CTO +- 任我行软件股份有限公司 集团CTO + +其他技术兴趣经历 + +1. 图灵出版社区签约作者。4本电子系列书:《Vue.js小书》《Git小书》《HTTP小书》《Swift + iOS开发小书》 +2. 微软 DotNet 技术俱乐部 2007-2010年成都地区主席 +3. + +非常欢迎 Reco 的加入!也希望更多对 Zig 感兴趣的朋友加入我们,普及 Zig +在中文社区内的使用。联系邮箱:zig@liujiacai.net diff --git a/content/post/news/2024-01-14-third-meetup.org b/content/post/news/2024-01-14-third-meetup.org deleted file mode 100644 index a9fe9f4..0000000 --- a/content/post/news/2024-01-14-third-meetup.org +++ /dev/null @@ -1,36 +0,0 @@ -#+TITLE: ZigCC 第三次线上会议 -#+DATE: 2024-01-14T09:20:41+0800 -#+LASTMOD: 2024-08-18T12:01:56+0800 -#+AUTHOR: 西瓜 -#+TAGS[]: community - -在 2024-01-13 晚,ZigCC 社区举行了第三次线上会议,参会人员: -- [[https://github.com/jiacai2050/][西瓜]] -- [[https://github.com/labspc][Lambert]] -- [[https://github.com/jinzhongjia][金中甲]] -- [[https://github.com/byte911][夜白]] - -会议主要讨论了下面两个议题: -- 公众号运营 -- 如何与其他社区互动 - -* 公众号运营 -这是最近群里聊到的问题,由于 Zig 语言本身属于较新的技术,因此社区内资料比较少,这导致很多感兴趣的人没有一个好的学习途径。 - -但对中文环境来说,我们其实之前已经积攒了一些素材,是完全可以通过公众号的形式进行传播的,主要来源: -- [[https://zigcc.github.io/learning-zig/][Learning Zig 中文翻译]] -- [[https://zigcc.github.io/zig-course/][Zig 语言圣经]] -- [[https://zigcc.github.io/zig-cookbook/][Zig Cookbook]] - -目前可以按照 Rust 日报的方式,每日截取其中的片段进行发送,方便读者在闲暇浏览阅读;另一方面,公众号也会介绍 [[https://github.com/zigcc/awesome-zig][awesome-zig]] 中的实际项目,同步他们的进展。 - -虽然名字是『Zig 日报』,但应该不会每天都发,毕竟 Zig 社区还比较年轻,但估计间隔不会超过 3 天,看后续运行实际效果再来调整频率。 - -主要参与人员:西瓜、金中甲 -* 社区互动 -目前我们的成员在 Zig 的实践方面相对较少,因此决定目前不过多的去宣传,在积攒了一些实际项目经验后,再来考虑。 - -* 欢迎更多朋友加入 ZigCC -现在回看,距离第一次 ZigCC 线上会议过了一个月,经过 ZigCC 成员的努力,还是交出了一份比较满意的答卷,[[https://github.com/zigcc/zig-cookbook][cookbook]] 项目斩获 400+ 的⭐️,而且我们也有了新的 [[https://github.com/zigcc/logo][logo]],另外要感谢金中甲同学,他把之前自己写的教程捐给了 ZigCC,质量非常高,因此我们决定把他重命名为 [[https://zigcc.github.io/zig-course/][Zig 语言圣经]],熟悉 Rust 的朋友可能会知道原因。😃 - -也许在读文章的你也在犹豫是否能加入,担心没有 Zig 经验是否会有影响,其实这都不是核心,现在的成员也没说 Zig 经验有多丰富,只要有踏实做事的心态,愿意帮助他人即可,Zig 可以慢慢学,有想法的朋友可以邮件到 zig@liujiacai.net ,简单自我介绍,之后我会拉到对应群组中,便于开展后续的工作。 diff --git a/content/post/news/2024-01-14-third-meetup.smd b/content/post/news/2024-01-14-third-meetup.smd new file mode 100644 index 0000000..e7024d6 --- /dev/null +++ b/content/post/news/2024-01-14-third-meetup.smd @@ -0,0 +1,62 @@ +--- +.title = "ZigCC 第三次线上会议", +.date = @date("2024-01-14T09:20:41+0800"), +.author = "西瓜", +.layout = "post.shtml", +.draft = false, +--- + +在 2024-01-13 晚,ZigCC 社区举行了第三次线上会议,参会人员: + +- [西瓜](https://github.com/jiacai2050/) +- [Lambert](https://github.com/labspc) +- [金中甲](https://github.com/jinzhongjia) +- [夜白](https://github.com/byte911) + +会议主要讨论了下面两个议题: + +- 公众号运营 +- 如何与其他社区互动 + +# [公众号运营]($section.id('公众号运营')) + +这是最近群里聊到的问题,由于 Zig +语言本身属于较新的技术,因此社区内资料比较少,这导致很多感兴趣的人没有一个好的学习途径。 + +但对中文环境来说,我们其实之前已经积攒了一些素材,是完全可以通过公众号的形式进行传播的,主要来源: + +- [Learning Zig 中文翻译](https://zigcc.github.io/learning-zig/) +- [Zig 语言圣经](https://zigcc.github.io/zig-course/) +- [Zig Cookbook](https://zigcc.github.io/zig-cookbook/) + +目前可以按照 Rust +日报的方式,每日截取其中的片段进行发送,方便读者在闲暇浏览阅读;另一方面,公众号也会介绍 +[awesome-zig](https://github.com/zigcc/awesome-zig) +中的实际项目,同步他们的进展。 + +虽然名字是『Zig 日报』,但应该不会每天都发,毕竟 Zig +社区还比较年轻,但估计间隔不会超过 3 +天,看后续运行实际效果再来调整频率。 + +主要参与人员:西瓜、金中甲 + +# [社区互动]($section.id('社区互动')) + +目前我们的成员在 Zig +的实践方面相对较少,因此决定目前不过多的去宣传,在积攒了一些实际项目经验后,再来考虑。 + +# [欢迎更多朋友加入 ZigCC]($section.id('welcome-more-friends-to-join-zigcc')) + +现在回看,距离第一次 ZigCC 线上会议过了一个月,经过 ZigCC +成员的努力,还是交出了一份比较满意的答卷,[cookbook](https://github.com/zigcc/zig-cookbook) +项目斩获 400+ 的⭐️,而且我们也有了新的 +[logo](https://github.com/zigcc/logo),另外要感谢金中甲同学,他把之前自己写的教程捐给了 +ZigCC,质量非常高,因此我们决定把他重命名为 [Zig +语言圣经](https://zigcc.github.io/zig-course/),熟悉 Rust +的朋友可能会知道原因。😃 + +也许在读文章的你也在犹豫是否能加入,担心没有 Zig +经验是否会有影响,其实这都不是核心,现在的成员也没说 Zig +经验有多丰富,只要有踏实做事的心态,愿意帮助他人即可,Zig +可以慢慢学,有想法的朋友可以邮件到 zig@liujiacai.net +,简单自我介绍,之后我会拉到对应群组中,便于开展后续的工作。 diff --git a/content/post/news/2024-04-27-release-party-review.org b/content/post/news/2024-04-27-release-party-review.org deleted file mode 100644 index f7c1aa0..0000000 --- a/content/post/news/2024-04-27-release-party-review.org +++ /dev/null @@ -1,35 +0,0 @@ -#+TITLE: 0.12.0 Release Party 回顾 -#+DATE: 2024-04-28T09:53:45+0800 -#+LASTMOD: 2024-08-18T12:03:29+0800 -#+TAGS[]: community -#+AUTHOR: Jiacai Liu - -2024-04-20,0.12.0 终于发布了,历时 8 个月,有 268 位贡献者,一共进行了 3688 次提交!下面是它的 Release notes: -- https://ziglang.org/download/0.12.0/release-notes.html - -ZigCC 对这个文档进行了翻译、整理,供需要升级适配的朋友参考: -- [[https://course.ziglang.cc/update/upgrade-0.12.0][0.12.0 升级指南]] -- [[https://course.ziglang.cc/update/0.12.0-description][0.12.0 版本说明]] - -为了庆祝这一盛事,ZigCC 决定在 2024-04-27 举行了一次线上的发行聚会,主要来讨论这次的版本,下面是视频回看地址: -- https://youtu.be/H0IqBNsH-9M -- https://www.bilibili.com/video/BV1Nb421Y7WX/ - -在这次会议上,主要讨论了两部分内容: - -第一是构建系统,0.12.0 版本对用户来说,主要是稳定了构建系统的 API,这对于 Zig 生态的构建十分重要,如果某用户写了一个基础库,但是升级 Zig 版本后,就没法编译了,可以想象,这是很沮丧的事情。 - -Zig 的构建系统分为两部分: -- zon 文件,声明依赖, =zig fetch= 会去下载里面的依赖 -- =build.zig= 文件,项目的构建器,由多个 Step 形成一个有向无环图,来驱动不同逻辑的进行,如安装头文件、编译静态链接库等。Step 里面最重要的是 Compile ,addTest、addExecutable 返回的都是它,主要功能是对代码进行编译。其他常见的 Step 还有 - - ConfigHeader 配置要用的头文件 - - InstallArtifact,将编译好的 lib 或 bin 安装到 zig-out 目录中 - -第二个是自己写的 x86 的后端,它可以不依赖 llvm 直接生成可以执行的汇编代码,这也是 [[https://github.com/ziglang/zig/issues/16270][make the main zig executable no longer depend on LLVM, LLD, and Clang libraries #16270]] -这个 issue 的基础。之前笔者以为所谓移除 llvm,是把 Zig 代码翻译成 C 代码,然后再有不同架构下的 C 编译器来生成最终的可执行文件,目前看这种想法是错误的, -尽管 Zig 有 C 这个后端,但目前看并不是解决这个 issue 专用的。 - -这就不得不好奇,Zig 团队难道要把生成所有架构下的二进制?还是说对于用的少的架构,[[https://github.com/ziglang/zig/issues/13265][直接生成 llvm 的 bc 文件]],然后剩下的活再交给 llvm 去做? -目前笔者还没有十分明确的答案,希望今后能尽快搞清楚这个问题,也欢迎了解的读者留言指出。 - -稍微遗憾的是这次参会的朋友基本都还是处于观望阶段,希望下次能有些具体项目经验可以聊,See you next time! diff --git a/content/post/news/2024-04-27-release-party-review.smd b/content/post/news/2024-04-27-release-party-review.smd new file mode 100644 index 0000000..52c3ef1 --- /dev/null +++ b/content/post/news/2024-04-27-release-party-review.smd @@ -0,0 +1,58 @@ +--- +.title = "0.12.0 Release Party 回顾", +.date = @date("2024-04-28T09:53:45+0800"), +.author = "Jiacai Liu", +.layout = "post.shtml", +.draft = false, +--- + +2024-04-20,0.12.0 终于发布了,历时 8 个月,有 268 位贡献者,一共进行了 +3688 次提交!下面是它的 Release notes: + +- + +ZigCC 对这个文档进行了翻译、整理,供需要升级适配的朋友参考: + +- [0.12.0 升级指南](https://course.ziglang.cc/update/upgrade-0.12.0) +- [0.12.0 版本说明](https://course.ziglang.cc/update/0.12.0-description) + +为了庆祝这一盛事,ZigCC 决定在 2024-04-27 +举行了一次线上的发行聚会,主要来讨论这次的版本,下面是视频回看地址: + +- +- + +在这次会议上,主要讨论了两部分内容: + +第一是构建系统,0.12.0 版本对用户来说,主要是稳定了构建系统的 +API,这对于 Zig 生态的构建十分重要,如果某用户写了一个基础库,但是升级 +Zig 版本后,就没法编译了,可以想象,这是很沮丧的事情。 + +Zig 的构建系统分为两部分: + +- zon 文件,声明依赖, `zig fetch` 会去下载里面的依赖 +- `build.zig` 文件,项目的构建器,由多个 Step + 形成一个有向无环图,来驱动不同逻辑的进行,如安装头文件、编译静态链接库等。Step + 里面最重要的是 Compile ,addTest、addExecutable + 返回的都是它,主要功能是对代码进行编译。其他常见的 Step 还有 + - ConfigHeader 配置要用的头文件 + - InstallArtifact,将编译好的 lib 或 bin 安装到 zig-out 目录中 + +第二个是自己写的 x86 的后端,它可以不依赖 llvm +直接生成可以执行的汇编代码,这也是 [make the main zig executable no +longer depend on LLVM, LLD, and Clang libraries +\#16270](https://github.com/ziglang/zig/issues/16270) 这个 issue +的基础。之前笔者以为所谓移除 llvm,是把 Zig 代码翻译成 C +代码,然后再有不同架构下的 C +编译器来生成最终的可执行文件,目前看这种想法是错误的, 尽管 Zig 有 C +这个后端,但目前看并不是解决这个 issue 专用的。 + +这就不得不好奇,Zig +团队难道要把生成所有架构下的二进制?还是说对于用的少的架构,[直接生成 +llvm 的 bc +文件](https://github.com/ziglang/zig/issues/13265),然后剩下的活再交给 +llvm 去做? +目前笔者还没有十分明确的答案,希望今后能尽快搞清楚这个问题,也欢迎了解的读者留言指出。 + +稍微遗憾的是这次参会的朋友基本都还是处于观望阶段,希望下次能有些具体项目经验可以聊,See +you next time! diff --git a/content/post/news/_index.org b/content/post/news/_index.org deleted file mode 100644 index 0ba1e8c..0000000 --- a/content/post/news/_index.org +++ /dev/null @@ -1,11 +0,0 @@ -#+TITLE: 社区新闻 -#+DATE: 2024-08-03T16:43:51+0800 -#+LASTMOD: 2024-11-08T22:24:13+0800 -#+TYPE: docs - -我们会不定期举行线上会议来畅聊 Zig,感兴趣的朋友可以通过下面日历查看,或订阅[[https://calendar.yandex.com/export/ics.xml?private_token=71fd8e02d7944f4e7ae44cc8a9b8877da9e9f2f1&tz_id=Asia/Hong_Kong][这个 iCalendar]]。 - -#+BEGIN_EXPORT html - -#+END_EXPORT -线上会议地址:https://discord.gg/36C7H47t47?event=1304329702512787466 diff --git a/content/post/news/index.smd b/content/post/news/index.smd new file mode 100644 index 0000000..8f3a05e --- /dev/null +++ b/content/post/news/index.smd @@ -0,0 +1,17 @@ +--- +.title = "社区新闻", +.date = @date("2024-08-03T16:43:51+0800"), +.author = "ZigCC", +.layout = "post.shtml", +.draft = false, +--- + +我们会不定期举行线上会议来畅聊 +Zig,感兴趣的朋友可以通过下面日历查看,或订阅[这个 +iCalendar](https://calendar.yandex.com/export/ics.xml?private_token=71fd8e02d7944f4e7ae44cc8a9b8877da9e9f2f1&tz_id=Asia/Hong_Kong)。 + +```=html + +``` + +线上会议地址:https://discord.gg/36C7H47t47?event=1304329702512787466 diff --git a/convert_figure_to_image_link.js b/convert_figure_to_image_link.js new file mode 100644 index 0000000..0c41967 --- /dev/null +++ b/convert_figure_to_image_link.js @@ -0,0 +1,50 @@ +#!/usr/bin/env node + +const fs = require('fs'); +const path = require('path'); + +// 递归遍历目录,处理所有 .smd 文件 +function processDirectory(dirPath) { + const items = fs.readdirSync(dirPath); + for (const item of items) { + const fullPath = path.join(dirPath, item); + const stat = fs.statSync(fullPath); + if (stat.isDirectory()) { + processDirectory(fullPath); + } else if (item.endsWith('.smd')) { + processFile(fullPath); + } + } +} + +// 处理单个文件 +function processFile(filePath) { + let content = fs.readFileSync(filePath, 'utf8'); + const newContent = replaceFigure(content); + if (newContent !== content) { + fs.writeFileSync(filePath, newContent, 'utf8'); + console.log(`✓ Converted figure in: ${filePath}`); + } +} + +// 替换 figure 块为图片链接 +function replaceFigure(content) { + // 支持 figure 块跨多行,捕获 src 路径和 caption + return content.replace(/\{\{\\<\s*figure\s+src="([^"]+)"[^>]*caption="([^"]*)"[^>]*\\>\}\}/g, + (match, src, caption) => { + // 去掉 src 开头的 / + const cleanSrc = src.replace(/^\//, ''); + return `[${caption}]($image.siteAsset('${cleanSrc}'))\n`; + } + ); +} + +// 主程序 +function main() { + const rootDir = path.join(__dirname, 'content'); + processDirectory(rootDir); +} + +if (require.main === module) { + main(); +} \ No newline at end of file diff --git a/convert_link_format.js b/convert_link_format.js new file mode 100644 index 0000000..21a3d3b --- /dev/null +++ b/convert_link_format.js @@ -0,0 +1,107 @@ +#!/usr/bin/env node + +const fs = require('fs'); +const path = require('path'); + +// 配置 +const config = { + sourceDir: './content/' +}; + +// 转换链接格式 +function convertLinkFormat(content) { + // 将 $link.page('filename') 转换为 $link.sub('filename') + content = content.replace(/\$link\.page\('([^']+)'\)/g, (match, filename) => { + return `$link.sub('${filename}')`; + }); + + return content; +} + +// 处理单个文件 +function processFile(filePath) { + try { + const content = fs.readFileSync(filePath, 'utf8'); + const convertedContent = convertLinkFormat(content); + + // 如果内容有变化,写回文件 + if (content !== convertedContent) { + fs.writeFileSync(filePath, convertedContent, 'utf8'); + console.log(`✓ Converted links in: ${filePath}`); + return true; + } else { + console.log(`- No changes needed: ${filePath}`); + return false; + } + } catch (error) { + console.error(`✗ Error processing ${filePath}:`, error.message); + return false; + } +} + +// 递归处理目录 +function processDirectory(dirPath) { + try { + const items = fs.readdirSync(dirPath); + let convertedCount = 0; + let totalCount = 0; + + for (const item of items) { + const fullPath = path.join(dirPath, item); + const stat = fs.statSync(fullPath); + + if (stat.isDirectory()) { + // 递归处理子目录 + const result = processDirectory(fullPath); + convertedCount += result.converted; + totalCount += result.total; + } else if (item.endsWith('.smd')) { + // 处理 smd 文件 + const converted = processFile(fullPath); + if (converted) convertedCount++; + totalCount++; + } + } + + return { converted: convertedCount, total: totalCount }; + } catch (error) { + console.error(`✗ Error processing directory ${dirPath}:`, error.message); + return { converted: 0, total: 0 }; + } +} + +// 主函数 +function main() { + console.log('🔄 Starting link format conversion...'); + console.log(`📁 Source directory: ${config.sourceDir}`); + console.log('🔄 Converting $link.page to $link.sub'); + console.log(''); + + if (!fs.existsSync(config.sourceDir)) { + console.error(`✗ Source directory does not exist: ${config.sourceDir}`); + process.exit(1); + } + + const result = processDirectory(config.sourceDir); + + console.log(''); + console.log('📊 Conversion Summary:'); + console.log(`✓ Converted links in: ${result.converted}/${result.total} files`); + + if (result.converted > 0) { + console.log('🎉 Link format conversion completed!'); + } else { + console.log('ℹ️ No link format conversion needed'); + } +} + +// 运行脚本 +if (require.main === module) { + main(); +} + +module.exports = { + convertLinkFormat, + processFile, + processDirectory +}; \ No newline at end of file diff --git a/convert_md_to_smd.js b/convert_md_to_smd.js new file mode 100644 index 0000000..18ea8d7 --- /dev/null +++ b/convert_md_to_smd.js @@ -0,0 +1,157 @@ +#!/usr/bin/env node + +const fs = require("fs"); +const path = require("path"); + +// 配置 +const config = { + sourceDir: "./content/monthly", + author: "ZigCC", + time: "2024", + layout: "monthly.shtml", +}; + +// 转换 markdown frontmatter 到 smd 格式 +function convertFrontmatter(content) { + const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---\n/); + if (!frontmatterMatch) { + return content; + } + + const frontmatter = frontmatterMatch[1]; + const body = content.replace(/^---\n[\s\S]*?\n---\n/, ""); + + // 解析现有的 frontmatter + const lines = frontmatter.split("\n"); + const metadata = {}; + + for (const line of lines) { + const match = line.match(/^(\w+):\s*(.+)$/); + if (match) { + metadata[match[1]] = match[2].replace(/^["']|["']$/g, ""); // 移除引号 + } + } + + let hasCustomFrontmatter = Object.keys(metadata).length > 3; + + // 构建新的 smd frontmatter + const newFrontmatter = [ + "---", + `.title = "${metadata.title || "Untitled"}",`, + `.date = @date("${metadata.date || config.time}"),`, + `.author = "${metadata.author || config.author}",`, + `.layout = "${config.layout}",`, + `.draft = false,`, + hasCustomFrontmatter?`.custom = {\n${Object.entries(metadata) + .filter(([k]) => !["title", "date", "author"].includes(k)) + .map(([k, v]) => ` .${k} = "${v}",`) + .join("\n")}\n},\n---`:"---", + "", + ].join("\n"); + + return newFrontmatter + body; +} + +// 转换 markdown 链接格式 +function convertLinks(content) { + // 转换 {{< ref "filename.md" >}} 格式到相对链接 + content = content.replace(/\{\{<\s*ref\s+"([^"]+\.md)"\s*>\}\}/g, "[$1]($1)"); + + // 转换其他可能的 markdown 链接格式 + // 这里可以根据需要添加更多转换规则 + + return content; +} + +// 处理单个文件 +function processFile(filePath) { + try { + const content = fs.readFileSync(filePath, "utf8"); + const convertedContent = convertLinks(convertFrontmatter(content)); + + // 创建新的 smd 文件路径 + const dir = path.dirname(filePath); + const basename = path.basename(filePath, ".md"); + const newPath = path.join(dir, `${basename}.smd`); + + // 写入新文件 + fs.writeFileSync(newPath, convertedContent, "utf8"); + console.log(`✓ Converted: ${filePath} -> ${newPath}`); + + return true; + } catch (error) { + console.error(`✗ Error processing ${filePath}:`, error.message); + return false; + } +} + +// 递归处理目录 +function processDirectory(dirPath) { + try { + const items = fs.readdirSync(dirPath); + let successCount = 0; + let totalCount = 0; + + for (const item of items) { + const fullPath = path.join(dirPath, item); + const stat = fs.statSync(fullPath); + + if (stat.isDirectory()) { + // 递归处理子目录 + const result = processDirectory(fullPath); + successCount += result.success; + totalCount += result.total; + } else if (item.endsWith(".md")) { + // 处理 markdown 文件 + const success = processFile(fullPath); + if (success) successCount++; + totalCount++; + } + } + + return { success: successCount, total: totalCount }; + } catch (error) { + console.error(`✗ Error processing directory ${dirPath}:`, error.message); + return { success: 0, total: 0 }; + } +} + +// 主函数 +function main() { + console.log("🚀 Starting markdown to smd conversion..."); + console.log(`📁 Source directory: ${config.sourceDir}`); + console.log(`👤 Author: ${config.author}`); + console.log(`📅 Time: ${config.time}`); + console.log(""); + + if (!fs.existsSync(config.sourceDir)) { + console.error(`✗ Source directory does not exist: ${config.sourceDir}`); + process.exit(1); + } + + const result = processDirectory(config.sourceDir); + + console.log(""); + console.log("📊 Conversion Summary:"); + console.log( + `✓ Successfully converted: ${result.success}/${result.total} files` + ); + + if (result.success === result.total) { + console.log("🎉 All files converted successfully!"); + } else { + console.log("⚠️ Some files failed to convert"); + } +} + +// 运行脚本 +if (require.main === module) { + main(); +} + +module.exports = { + convertFrontmatter, + convertLinks, + processFile, + processDirectory, +}; diff --git a/examples/2024-01-12-how-to-release-your-zig-applications/.tool-versions b/examples/2024-01-12-how-to-release-your-zig-applications/.tool-versions deleted file mode 100644 index c947e45..0000000 --- a/examples/2024-01-12-how-to-release-your-zig-applications/.tool-versions +++ /dev/null @@ -1 +0,0 @@ -zig 0.12.0 diff --git a/examples/2024-01-12-how-to-release-your-zig-applications/Makefile b/examples/2024-01-12-how-to-release-your-zig-applications/Makefile deleted file mode 100644 index 292a94e..0000000 --- a/examples/2024-01-12-how-to-release-your-zig-applications/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -fmt: - zig fmt --check src/*.zig - -build: fmt - zig build -Doptimize=ReleaseFast -Dstrip=true diff --git a/examples/2024-01-12-how-to-release-your-zig-applications/build.zig b/examples/2024-01-12-how-to-release-your-zig-applications/build.zig deleted file mode 100644 index b30e287..0000000 --- a/examples/2024-01-12-how-to-release-your-zig-applications/build.zig +++ /dev/null @@ -1,25 +0,0 @@ -const std = @import("std"); - -pub fn build(b: *std.Build) void { - const target = b.standardTargetOptions(.{}); - const optimize = b.standardOptimizeOption(.{}); - const strip = b.option(bool, "strip", "Set to true to strip binary") orelse false; - - const exe = b.addExecutable(.{ - .name = "example", - .root_source_file = .{ .path = "src/main.zig" }, - .target = target, - .optimize = optimize, - .strip = strip, - }); - - b.installArtifact(exe); - - const run_cmd = b.addRunArtifact(exe); - run_cmd.step.dependOn(b.getInstallStep()); - if (b.args) |args| { - run_cmd.addArgs(args); - } - const run_step = b.step("run", "Run the app"); - run_step.dependOn(&run_cmd.step); -} diff --git a/examples/2024-01-12-how-to-release-your-zig-applications/build.zig.zon b/examples/2024-01-12-how-to-release-your-zig-applications/build.zig.zon deleted file mode 100644 index 8fccef7..0000000 --- a/examples/2024-01-12-how-to-release-your-zig-applications/build.zig.zon +++ /dev/null @@ -1,8 +0,0 @@ -.{ - .name = "2024-01-12-how-to-release-your-zig-applications", - .version = "0.0.0", - .dependencies = .{}, - .paths = .{ - "", - }, -} diff --git a/examples/2024-01-12-how-to-release-your-zig-applications/src/main.zig b/examples/2024-01-12-how-to-release-your-zig-applications/src/main.zig deleted file mode 100644 index f92e181..0000000 --- a/examples/2024-01-12-how-to-release-your-zig-applications/src/main.zig +++ /dev/null @@ -1,5 +0,0 @@ -const std = @import("std"); - -pub fn main() !void { - std.debug.print("All your {s} are belong to us.\n", .{"codebase"}); -} diff --git a/examples/run-all.sh b/examples/run-all.sh deleted file mode 100755 index b181b5c..0000000 --- a/examples/run-all.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -DIR="$(dirname "$(realpath "$0")")" -for ex in `ls -d */`;do - echo "Run example ${ex}..." - cd ${DIR}/${ex} - zig build --summary all -done diff --git a/go.mod b/go.mod deleted file mode 100644 index 731646d..0000000 --- a/go.mod +++ /dev/null @@ -1,5 +0,0 @@ -module zigcc - -go 1.22.0 - -require github.com/google/docsy v0.11.1-0.20250516151613-47fd135c4b3e // indirect diff --git a/go.sum b/go.sum deleted file mode 100644 index de24a99..0000000 --- a/go.sum +++ /dev/null @@ -1,11 +0,0 @@ -github.com/FortAwesome/Font-Awesome v0.0.0-20240402185447-c0f460dca7f7/go.mod h1:IUgezN/MFpCDIlFezw3L8j83oeiIuYoj28Miwr/KUYo= -github.com/FortAwesome/Font-Awesome v0.0.0-20240716171331-37eff7fa00de/go.mod h1:IUgezN/MFpCDIlFezw3L8j83oeiIuYoj28Miwr/KUYo= -github.com/FortAwesome/Font-Awesome v0.0.0-20241216213156-af620534bfc3/go.mod h1:IUgezN/MFpCDIlFezw3L8j83oeiIuYoj28Miwr/KUYo= -github.com/google/docsy v0.10.0 h1:6tMDacPwAyRWNCfvsn/9qGOZDQ8b0aRzjRZvnZPY5dg= -github.com/google/docsy v0.10.0/go.mod h1:c0nIAqmRTOuJ01F85U/wJPQtc3Zj9N58Kea9bOT2AJc= -github.com/google/docsy v0.11.0 h1:QnV40cc28QwS++kP9qINtrIv4hlASruhC/K3FqkHAmM= -github.com/google/docsy v0.11.0/go.mod h1:hGGW0OjNuG5ZbH5JRtALY3yvN8ybbEP/v2iaK4bwOUI= -github.com/google/docsy v0.11.1-0.20250516151613-47fd135c4b3e h1:HfmBArN3/h9Q385iNWQpyeeuHmE93S3YinzrxnETfx8= -github.com/google/docsy v0.11.1-0.20250516151613-47fd135c4b3e/go.mod h1:1bioDqA493neyFesaTvQ9reV0V2vYy+xUAnlnz7+miM= -github.com/twbs/bootstrap v5.3.3+incompatible/go.mod h1:fZTSrkpSf0/HkL0IIJzvVspTt1r9zuf7XlZau8kpcY0= -github.com/twbs/bootstrap v5.3.6+incompatible/go.mod h1:fZTSrkpSf0/HkL0IIJzvVspTt1r9zuf7XlZau8kpcY0= diff --git a/layouts/index.shtml b/layouts/index.shtml new file mode 100644 index 0000000..9cfbdff --- /dev/null +++ b/layouts/index.shtml @@ -0,0 +1,7 @@ + + + + + +
+ \ No newline at end of file diff --git a/layouts/learn.shtml b/layouts/learn.shtml new file mode 100644 index 0000000..bcfefec --- /dev/null +++ b/layouts/learn.shtml @@ -0,0 +1,24 @@ + + + + + +

+
+

Table of Contents

+
+
+
+
+
+ + + +
+
+ + + +
+
+ \ No newline at end of file diff --git a/layouts/monthly.shtml b/layouts/monthly.shtml new file mode 100644 index 0000000..06a3d9c --- /dev/null +++ b/layouts/monthly.shtml @@ -0,0 +1,6 @@ + + + + +
+ \ No newline at end of file diff --git a/layouts/page.shtml b/layouts/page.shtml new file mode 100644 index 0000000..06a3d9c --- /dev/null +++ b/layouts/page.shtml @@ -0,0 +1,6 @@ + + + + +
+ \ No newline at end of file diff --git a/layouts/partials/hooks/head-end.html b/layouts/partials/hooks/head-end.html deleted file mode 100644 index e76fbe3..0000000 --- a/layouts/partials/hooks/head-end.html +++ /dev/null @@ -1,15 +0,0 @@ - - diff --git a/layouts/post.shtml b/layouts/post.shtml new file mode 100644 index 0000000..e332a3e --- /dev/null +++ b/layouts/post.shtml @@ -0,0 +1,18 @@ + + + + + + + + + + + + +
+ \ No newline at end of file diff --git a/layouts/post.xml b/layouts/post.xml new file mode 100644 index 0000000..b9c2b25 --- /dev/null +++ b/layouts/post.xml @@ -0,0 +1,19 @@ + + + + + + Zine -- https://zine-ssg.io + en-US + + + + + + + + + + + + diff --git a/layouts/templates/base.shtml b/layouts/templates/base.shtml new file mode 100644 index 0000000..84a1d41 --- /dev/null +++ b/layouts/templates/base.shtml @@ -0,0 +1,55 @@ + + + + + + + + + + + + +
+

+ +
+ + + + \ No newline at end of file diff --git a/layouts/templates/content.shtml b/layouts/templates/content.shtml new file mode 100644 index 0000000..5f63560 --- /dev/null +++ b/layouts/templates/content.shtml @@ -0,0 +1,32 @@ + + + + + + +

+
+

+

+
+
    +
  • +
+
+

Table of Contents

+
+
+ +
+
+ + + +
+
+ + + +
+
+ \ No newline at end of file diff --git a/static/favicons/android-chrome-192x192.png b/static/favicons/android-chrome-192x192.png deleted file mode 100644 index e1b6d95..0000000 Binary files a/static/favicons/android-chrome-192x192.png and /dev/null differ diff --git a/static/favicons/android-chrome-512x512.png b/static/favicons/android-chrome-512x512.png deleted file mode 100644 index 73780cd..0000000 Binary files a/static/favicons/android-chrome-512x512.png and /dev/null differ diff --git a/static/favicons/android-chrome-maskable-192x192.png b/static/favicons/android-chrome-maskable-192x192.png deleted file mode 100644 index e1b6d95..0000000 Binary files a/static/favicons/android-chrome-maskable-192x192.png and /dev/null differ diff --git a/static/favicons/android-chrome-maskable-512x512.png b/static/favicons/android-chrome-maskable-512x512.png deleted file mode 100644 index 73780cd..0000000 Binary files a/static/favicons/android-chrome-maskable-512x512.png and /dev/null differ diff --git a/static/favicons/apple-touch-icon.png b/static/favicons/apple-touch-icon.png deleted file mode 100644 index ff7c24a..0000000 Binary files a/static/favicons/apple-touch-icon.png and /dev/null differ diff --git a/static/favicons/favicon.ico b/static/favicons/favicon.ico deleted file mode 100644 index 6680083..0000000 Binary files a/static/favicons/favicon.ico and /dev/null differ diff --git a/zine.ziggy b/zine.ziggy new file mode 100644 index 0000000..1fe8372 --- /dev/null +++ b/zine.ziggy @@ -0,0 +1,9 @@ +Site { + .title = "Zig 语言中文社区", + .host_url = "https://ziglang.cc", + .content_dir_path = "content", + .layouts_dir_path = "layouts", + .assets_dir_path = "assets", + .static_assets = [ + ], +}