【最新】LuaJIT 32/64 位字節碼,從編譯到使用全紀錄 原

網上關於 LuaJIT 的討論,已經顯得有些陳舊。如果你對 LuaJIT 編譯 Lua 源文件爲具體的 32位或64位字節碼,極其具體使用感興趣的話,不妨快速讀一下這篇文章。此文章針對嘗試在 iOS 或 Android 上使用 LuaJIT 的小夥伴。限於篇幅,此處假定,你可以成功在 iOS/Android App 中集成了 LuaJIT,並且已經可以執行源碼形式的 Lua 文件。

我忍不住在開頭插一句: LuaJIT 編譯後,只有約 600k,可能也就是一張圖片的空間,但卻可以讓你的你App可以擁有一門完整的腳本語言的能力 -- 真的很酷!爲許多問題,提供了許多新的思路,特別是 App 地動態性和可配置型方面。

環境

  • 操作系統: macOS 10.13.4 【Linux 系統上,應該使用;Windows 系統上,僅供參考】

  • LuaJIT 版本: LuaJIT-2.1.0-beta3【官網最新版】

目錄結構預定義

爲了便於下文指令的說明,此處簡單約定下目錄結構。實際使用時,按需設置和整理即可。

  • tools:存放各種編譯腳本和工具。
  • source:存放編譯前的 Lua 源碼。以後所有的 Lua 源碼,都需要放在且只能放在此文件夾下。
  • output: 用於存放編譯後的 Lua 字節碼文件。

編譯加密工具

Lua 的加密工具,本質上就是 Lua 的解釋器。此處使用的解釋器源碼是 LuaJIT。LuaJIT 執行效率最高,且編譯出來的字節碼無法逆向爲 Lua 源碼,更能保證源碼安全性。LuaJIT 支持交叉編譯,即可以在電腦上編譯出 iOS 或 Android 手機上系統需要的字節碼。如此,我們只需要編譯一次 32 和 64 位的 LuaJIT 解釋器各一個,備份存檔,後續可直接使用。

編譯 LuaJIT 解釋器,直接用官方的推薦指令即可。比較特殊的一點時,如果是想編譯出 64 位 LuaJIT,需要加上參數 CFLAGS=-DLUAJIT_ENABLE_GC6

# cd 到 LuaJIT 源碼目錄
cd tools/LuaJIT-2.1.0-beta3

# 編譯 32 位 LuaJIT 解釋器
make clean && make && cp src/luajit ../luajit-32 && make clean

# 編譯 64 位 LuaJIT 解釋器
make clean && make CFLAGS=-DLUAJIT_ENABLE_GC64 && cp src/luajit ../luajit-64 && make clean

注意:重新解壓源碼後,可能需要重新啓動命令行/終端,來清除可能的系統緩存,才能正確 build 出想要的東西。

加密 Lua 源文件

所謂的加密 Lua 源文件,其實就是把 Lua 源文件,編譯爲 LuaJIT 字節碼。相對於 Luac ,LuaJIT 字節碼執行效率更高,而且無法被直接逆向爲對應的 Lua 源碼。

編譯字節碼,用的是 -b 命令,需要注意的是,一定要使用對應字節的 LuaJIT 解釋器來編譯,否則 iOS/Android App 中,可能無法加載。

編譯後的字節碼文件的後綴,可以根據自己需要自定義。此處我使用的是 “.yan” 和 “.yan64”。

# 編譯32位字節碼 ,適用於Android全部手機,部分 iOS 手機。
./tools/luajit-32 -b ./source/main.lua ./output/main.yan

# 編譯64位字節碼,僅用於部分 iOS 手機。
./tools/luajit-64 -b ./source/main.lua ./output/main.yan64

注意: 敏感信息,不要直接以常量字符串的形式使用。

在 iOS 中,根據不同的 CPU, 加載不同的字節碼。

在 Android 手機上,一般只需要使用 32 位的 LuaJIT 字節碼文件即可。iOS 上,情況比較複雜,從 iOS11 之後,iOS 要求相對的庫必須有64位版本。也就意味着,如果 App 想兼容 iPhone5s 以前的 32位CPU的設備的話,就必須在項目中同時放置32位和64位的LuaJIT靜態庫。關於適用於手機端的 LuaJIT 靜態庫的編譯問題,暫不進一步展開。此處只討論,如何在 iOS 中,動態根據需要準確加載對應的 32 或 64 位的 LuaJIT 字節碼文件。

基於上文的討論,此處給出一個簡單的策略:

  • Lua 源文件,同時編譯生成32位和64位字節碼的文件。
  • 編譯後的字節碼文件,僅文件後綴不同,文件路徑的其他部分保證是完全一致的。如 main.yanmain.yan64 是由 main.lua編譯得到。
  • 在 iOS App 運行時,動態根據當前真正運行的是 32 還是 64 位的 LuaJIT 解釋器,來選擇對應的字節碼文件後綴即可。

分享一個 swift 版的實現:

    private func luaFileSuffix() -> String{
        #if (arch(i386) || arch(arm))
        return ".yan"
        #else
        return ".yan64"
        #endif

    }

參考文章

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章