在 Windows 以 GNUstep 建立 Objective-C 開發環境

    前言

    由於 Windows 不是 Objective-C 的官方開發環境,無法使用 Cocoa。在 Windows 上,只能使用 MinGW (GCC) 搭配 GNUstep 或 ObjFW 做為 Objective-C 的物件庫。

    一般來說,會優先使用 GNUstep,因為該物件庫在 API 上刻意模仿 Cocoa,學習曲線會比較平滑。而且 GNUstep 加上 Cocoa 交互參考,可讀的線上資料會比較多。本文會介紹如何建置 GNUstep 開發環境。

    使用 GNUstep 官方安裝程式

    比較簡單的方式是到 GNUstep 的官網下載給 Windows 用的安裝程式。諘依序安裝以下三個開發工具:

    • GNUstep MSYS System (MinGW + MSYS 環境)
    • GNUstep Core (函式庫)
    • GNUstep Devel (標頭檔和開發工具)

    這時候會得到 MinGW (GCC) 加上 GNUstep 物件庫。但 GNUstep 官方的 Windows 安裝程式的版本比較滯後,所以會很到略舊的開發環境。如果願意花點時間,建議自行從 MSYS2 開發環境編譯 GNUstep。本文的後半部會說明自行編譯 GNUstep 的流程。

    支援 Objective-C 的編輯器

    對於 Objective-C 來說,Windows 反而是小眾環境,所以沒什麼大型 IDE 可用。以下是支援 Objective-C 的編輯器:

    前兩者是免費的編輯器,對 Objective-C 有基本的支援。後者則是商業軟體,可免費試用 30 天,有興趣的讀者可自行選購。

    自行編譯 GNUstep 原始碼

    在 Unix 上編譯軟體算是家常便飯,但 Windows 使用者反而較少自行編譯軟體,所以筆者在這裡說明編譯 GNUstep 的流程。

    如果有讀者看到筆者先前的同篇文章卻無法順利編譯 GNUstep 的話,不要吝於嘗試。筆者自己也重新編譯 GNUstep,並取得比先前穩定的開發環境。

    前置作業

    請讀者先安裝 MSYS2。若對 MSYS2 不熟悉,可參考這篇文章

    本小節的操作會在 MSYS 終端機。請將工作目錄切換到家目錄:

    $ cd
    

    先安裝基本的工具:

    $ pacman -S wget git
    

    從 GNUstep 的官方 GitHub 網站的 gnustep/tools-scripts 專案中下載以下三個 shell 命令稿:

    $ wget -c https://raw.githubusercontent.com/gnustep/tools-scripts/master/install-dependencies-mingw64_nt
    $ wget -c https://raw.githubusercontent.com/gnustep/tools-scripts/master/build-mingw64_nt
    $ wget -c https://raw.githubusercontent.com/gnustep/tools-scripts/master/setup-mingw64_nt
    

    由於該專案的命令稿每隔一陣子會變動,本文的資訊日後有可能會過時。若無法順利下載這些命令稿,則需自行到該專案找等效的命令稿。

    另外,還是要重新拷貝該專案:

    $ git clone https://github.com/gnustep/tools-scripts.git
    

    這是因為會用到一個給 MSYS2 用的 patch。這個動作是參考 build-mingw64_nt 的內部實作得知的,不要死背這個動作。

    下載以下四個開發工具的最新穩定版本壓縮檔:

    $ wget -c https://github.com/gnustep/tools-make/releases/download/make-2_8_0/gnustep-make-2.8.0.tar.gz
    $ wget -c https://github.com/gnustep/libs-base/releases/download/base-1_27_0/gnustep-base-1.27.0.tar.gz
    $ wget -c https://github.com/gnustep/libs-gui/releases/download/gui-0_28_0/gnustep-gui-0.28.0.tar.gz
    $ wget -c https://github.com/gnustep/libs-back/releases/download/back-0_28_0/gnustep-back-0.28.0.tar.gz
    

    雖然也可以直接拷貝 GNUstep 的 master 分支的原始碼來用。但該分支的原始碼比較不穩定,不建議使用。如果對 GNUstep 很有愛,想要幫 GNUstep 測試和除錯,可以自行玩玩看。

    這裡的軟體版本號是實際到各個專案去查閱而得的,每隔一陣子就會變動。請不要死背這個版本號。

    雖然筆者先前發給 GNUstep 官方團隊的 PR 被拒絕,但 GNUstep 過一陣子後的確修好了 GNUstep 在 MSYS2 上的臭蟲。由此可知,即使 PR 被拒絕,仍然可以對自由軟體間接做出貢獻。

    然後將各個專案重新整理名稱,這是為了和 build-mingw64_nt 內的目錄名稱一致:

    $ tar xf gnustep-make-2.8.0.tar.gz
    $ mv gnustep-make-2.8.0 tools-make
    
    $ tar xf gnustep-base-1.27.0.tar.gz
    $ mv gnustep-base-1.27.0 libs-base
    
    $ tar xf gnustep-gui-0.28.0.tar.gz
    $ mv gnustep-gui-0.28.0 libs-gui
    
    $ tar xf gnustep-back-0.28.0.tar.gz
    $ mv gnustep-back-0.28.0 libs-back
    

    安裝 GNUstep 相依性

    切換到 MinGW64 終端機,執行以下命令稿:

    $ ./install-dependencies-mingw64_nt
    

    安裝套件的過程中可能需要手動確認幾次,請自行完成。

    編譯 GNUstep

    同樣在 MinGW64 終端機,執行以下命令稿:

    $ ./build-mingw64_nt
    

    這時候會從頭到尾編譯整個 GNUstep。如果順利的話,就可以得到 GNUstep,會安裝在 MinGW64 環境下的 /usr/GNUstep 中。由於編譯時間比較久,可以喝杯咖啡休息一下。

    但是,不一定每次編譯都會成功。目前該命令稿沒有檢查錯誤的機制,所以要自行檢查錯誤訊息。可以用 tee(1) 把錯誤訊息存下來再慢慢看。

    自動載入 GNUstep 開發環境

    在 MinGW 終端機下執行以下命令稿:

    $ ./setup-mingw64_nt
    

    以後就可以用 GNUstep Make 編譯 Objective-C 程式。我們會在後文介紹 GNUstep Make 的使用方式。

    錯誤排除

    編譯 GNUstep 時,最困難的就是錯誤排除。隨著 MSYS2 環境,每次編譯時有可能有不同的錯誤出現,要有自行勤找資料的精神來除錯。

    例如,最近 2.35 版的 binutils 的 issue 造成 libs-base 無法順利編譯。暫時的 workaround 是降 binutlis 的版本。

    wget(1) 下載舊版的 binutils:

    $ wget -c http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-binutils-2.34-3-any.pkg.tar.zst
    

    將 binutils 手動降級:

    $ pacman -U mingw-w64-x86_64-binutils-2.34-3-any.pkg.tar.zst 
    

    讀者不一定會碰到相同的錯誤。還是得培養自己找尋資料、解決問題的能力。

    編譯第一個 Objective-C 程式

    用編輯器建立空白的 hello.m 文字檔案,加入以下內容:

    #import <Foundation/Foundation.h>
    
    #define PRINT(FORMAT, ...) \
        fprintf(stdout, "%s\n", \
            [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
    
    int main(void)
    {
        NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
        if (!pool)
            return 1;
    
        PRINT(@"Hello World");
    
        [pool release];
    
        return 0;
    }
    

    我們的目的是測試開發環境,暫不說明程式碼。

    編譯並執行此範例程式:

    $ gcc -o hello hello.m -lobjc -lgnustep-base -I /usr/GNUstep/System/Library/Headers -L /usr/GNUstep/System/Library/Libraries -fconstant-string-class=NSConstantString
    $ ./hello.exe
    Hello World
    

    GNUstep 視為獨立的系統,不位於 GCC 的標準位置上,所以要加許多額外的參數。日後用 GNUstep Make 就可以改善這個情形。

    在 Windows 原生環境執行 GNUstep 程式

    若要在 Windows 原生環境下執行編譯好的 GNUstep 程式,要附帶額外的動態函式庫 (DLL 檔)。以筆者的系統為例,可到 C:\msys64\usr\GNUstep\System\Tools 底下找所需的 DLL 檔。除此之外,在 MSYS2 的執行檔路徑 C:\msys64\mingw64\bin 等處也可能會有所需的 DLL。

    因為 GNUstep 相依蠻多函式庫的,要手動逐一拷貝有點費工。筆者寫了個 shell 命令稿 deploy2win,可以簡化拷貝 DLL 的動作。有需要的讀者可以參考一下。

    【分享本文】
    Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Yahoo
    【追蹤本站】
    Facebook Facebook Twitter