使用 Zig 來構建一個俄羅斯方塊

tinytetris[1] 是一個非常經典的 C++ 示例,它爲我們演示瞭如何使用 C++ 編寫一個在終端下可以遊玩的俄羅斯方塊。

準備環境

環境:zig 0.11,系統:linux

我們使用 zig init-exe 來初始化一個全新的 zig 項目,並將 tinyteris 的源碼放入到 src/main.cc這個文件中,有的朋友看到這裏可能疑問,我們的代碼不用 zig 嗎?

沒錯,我們本次中並不使用 zig,僅僅將它作爲一個構建工具來使用!

構建

現在來嘗試構建我們的遊戲,向 build.zig 中寫入以下內容:

const std = @import("std");
pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});
    const exe = b.addExecutable(.{ 
        .name = "zig", 
        .target = target, 
        .optimize = optimize, 
    }); 
    exe.addCSourceFile(.{ 
        .file = .{ 
            .path = "src/main.cc", 
        }, 
        .flags = &.{}, 
    }); 
    exe.linkLibCpp(); 
    exe.linkSystemLibrary("ncurses"); 
    b.installArtifact(exe);
    const run_cmd = b.addRunArtifact(exe);
    run_cmd.step.dependOn(b.getInstallStep());
    const run_step = b.step("run", "Run the app");
    run_step.dependOn(&run_cmd.step);
}

在以上的代碼中,我們使用了 b.standardTargetOptions 和 b.standardOptimizeOption 來獲取標準的優化模式和構建目標(默認爲 debug 和本機構建),隨後使用 b.addExecutable 創建了一個二進制程序的構建,並指定了它的名字,構建目標,優化模式。

緊接着,我們使用 exe.addCSourceFile 來爲它添加源文件(cpp),它需要源文件的位置和編譯時使用的 cflags, 這我們設置 cflags 爲空。

exe.linkLibCpp() 用於鏈接 C++ 標準庫,而 exe.linkSystemLibrary 用於鏈接系統庫。

需要注意:zig 使用的是 LLVM 提供的 libc++,而 GNU 的是 libstdc++,而它們的實現略有不同,如果混用可能出現問題!

處理方案:正確的做法是,手動編譯依賴的源代碼(一般是出現問題的),或者使用 -nostdinc++ -nostdlib++ 指示不使用默認標準庫,並鏈接 GNU 的標準庫,具體可以參考該 issue[2]。

而 b.installArtifact 指示 zig 的構建系統將 exe 作爲依賴添加到默認的構建步驟中,這樣 zig build 就會構建該程序。

後續的則是創建一個執行的 Step,用於執行該命令,更多細節可以查看 zig 聖經 [3]。

結果

使用 zig build 命令構建俄羅斯方塊,zig build run 命令運行俄羅斯方塊。

參考資料

[1] 

tinytetris: https://github.com/taylorconor/tinytetris

[2] 

issue: https://github.com/ziglang/zig/issues/18300

[3] 

zig 聖經: https://zigcc.github.io/zig-course/engineering/build-system.html#step

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/P0SmSFZBOaIaGE9MyghJAg