xmake 源碼架構剖析

本文主要介紹下xmake的整體架構設計,以及源碼結構的布局和模塊劃分。 如果你想深度使用xmake,開發xmake插件、工程自定義腳本或者想為xmake貢獻一些代碼和特性,可以通過此本的介紹,對xmake項目整體有個大概的了解。,

源碼地址:Github

頂層目錄結構

./xmake/n├── actions # 內建的一些基礎task,用於基本的構建安裝等操作n├── core # xmake的核心模塊,提供最底層的實現支持n├── languages # 所有的語言相關特性支持和擴展,都在此目錄下n├── modules # 內置的擴展模塊,可用`import`導入使用n├── packages # 內置包目錄,提供xmake所需的一些必須依賴包支持,例如:git等,其他第三方包放在獨立xmake-repo下n├── platforms # 平台支持目錄,提供各個構建平台的配置信息和腳本n├── plugins # 插件目錄,提供一些內置的插件支持,例如:生成IDE工程,宏腳本等。。n├── scripts # 放置一些雜七雜八的shell、perl等其他語言腳本,例如:gas-preprocessor.pln└── templates # 工程模板目錄,提供一些`xmake create`創建工程所需的內置模板 n

沙盒模式

為了簡化xmake.lua中自己定義腳本、插件腳本以及擴展模塊的開發,提供更高的安全性,xmake採用了沙盒的方式去載入他們,每個腳本都獨立在一個單獨的沙盒中,並且有獨立的作用域支持。

在xmake的整個目錄結構中,除了xmake/core底層核心模塊,其他的頂層目錄全部放置在沙盒中載入運行,來簡化代碼開發,提高易用性和安全性。

這樣有什麼好處呢?

  • 上層模塊的開發跟xmake的core代碼完全隔離,不會干擾到xmake的底層核心模塊,更加安全
  • 作用域只提供當前模塊所需api的最小子集支持
  • 提供內置異常處理機制,以及api調用的返回值、傳參有效性檢測,代碼出錯後,會及時報出異常信息,並提供詳細棧來定位問題
  • 可通過import("core.base.task")的模塊導入方式,提供更加方便高效的模塊載入支持
  • 通過異常機制,簡化代碼的編寫,可以簡化30%的代碼量,以及錯誤判斷
  • 常用介面字元串參數,支持$(val)等內置變數的自動轉換

下面我們可以直觀感受下原生代碼和沙盒代碼的區別:

導入和返回值判斷的改進

原生代碼:

local test = require("modules/test") nnlocal ok, errors = test.run("arg1", "arg2") nif not ok then n os.raise(errors)nend n

沙盒代碼:

import("modules.test")nntest.run("arg1", "arg2") n

如果test.run運行出錯,會自動中斷,並顯示出錯信息。

import的導入比lua原生的require更加的強大易用,支持很多高級特性:

  • 多級多目錄導入支持,模塊的搜索目錄可以有多個,也可以在xmake.lua中自己指定
  • 通過指定父目錄,批量載入所有模塊,例如:import("core")會載入core目錄下的所有模塊,並且通過core.xxx來訪問
  • 支持模塊繼承導入
  • 支持匿名導入和緩存優化
  • 支持別名設置
  • 通過下劃線區分,僅導入公有介面
  • 自動識別main函數,可直接調用,例如:import("test")(args),會自動調用test模塊中的main函數
  • 支持xmake lua直接載入測試,例如:xmake l lib.detect.find_package zlib

內置api的改進

原生代碼:

print("hello xmake") nprint("hello", "xmake") n

沙盒代碼:

print("hello xmake")nprint("hello", "xmake") nprint("hello %s", "xmake") nprint("hello $(var)") n

空參數的判斷改進

原生代碼:

function test(array)n if array ~= nil then n for _, item in ipairs(array) do n -- ... n end n end nend n

沙盒代碼:

function test(array) n for _, item in ipairs(array) do n -- ... n end nend n

簡化模塊定義

原生代碼:

local module = module or {} nnfunction module.test(arg) n -- ... nendnnreturn module n

沙盒代碼:

function test(arg) n -- ... nend n

Actions目錄

這個目錄下提供xmake日常所需的最基礎命令,提供配置、編譯、打包、安裝、運行、調試、卸載等功能。

./xmake/actions/n├── build # 構建工程n├── clean # 清理構建產生的文件n├── config # 構建前的工程配置n├── create # 根據模板創建工程n├── global # 全局配置n├── install # 安裝構建好的目標文件到系統n├── package # 打包當前平台下的構建文件n├── require # 獲取依賴包n├── run # 運行、調試目標程序n└── uninstall # 卸載安裝到系統的目標文件 n

Modules目錄

這個是擴展模塊目錄,提供了一些常用的模塊,來擴展xmake.lua的自定義腳本,提供更多高級特性,例如:編譯器特性檢測、依賴包檢測等。

./xmake/modules/n├── coren│ └── tools # 這個下面的模塊,主要用於擴展xmake的編譯工具鏈n│ ├── ar.luan│ ├── cl.luan│ ├── clang.luan│ ├── clangxx.luan│ ├── dmd.luan│ ├── gcc.luan│ ├── gccgo.luan│ ├── gdc.luan│ ├── go.luan│ ├── gxx.luan│ ├── ldc.luan│ ├── lib.luan│ ├── link.luan│ ├── ml.luan│ ├── ml64.luan│ ├── rc.luan│ ├── rustc.luan│ └── swiftc.luan├── detectn│ ├── packages # 用於增強find_package介面的探測n│ │ ├── find_mbedtls.luan│ │ ├── find_mysql.luan│ │ ├── find_openssl.luan│ │ ├── find_pcre.luan│ │ ├── find_pcre2.luan│ │ └── find_zlib.luan│ ├── sdks # 用於查找一些編譯sdk環境n│ │ ├── find_cross_toolchains.luan│ │ ├── find_ndk_sdkvers.luan│ │ ├── find_ndk_toolchains.luan│ │ ├── find_vstudio.luan│ │ ├── find_xcode_dir.luan│ │ └── find_xcode_sdkvers.luan│ └── tools # 用於增強可執行工具的查找、特性檢測n│ ├── find_7z.luan│ ├── find_apt.luan│ ├── find_ar.luan│ ├── find_brew.luan│ ├── find_ccache.luan│ ├── find_cl.luan│ ├── find_clang.luan│ ├── find_clangxx.luan│ ├── find_curl.luan│ ├── find_dmd.luan│ ├── find_doxygen.luan│ ├── find_gcc.luan│ ├── find_gccgo.luan│ ├── find_gdb.luan│ ├── find_gdc.luan│ ├── find_git.luan│ ├── find_go.luan│ ├── find_gxx.luan│ ├── find_gzip.luan│ ├── find_ldc2.luan│ ├── find_lib.luan│ ├── find_link.luan│ ├── find_lipo.luan│ ├── find_lldb.luan│ ├── find_ml.luan│ ├── find_ml64.luan│ ├── find_ollydbg.luan│ ├── find_pacman.luan│ ├── find_ping.luan│ ├── find_pkg_config.luan│ ├── find_rc.luan│ ├── find_rustc.luan│ ├── find_sudo.luan│ ├── find_swiftc.luan│ ├── find_tar.luan│ ├── find_unzip.luan│ ├── find_vsjitdebugger.luan│ ├── find_wget.luan│ ├── find_windbg.luan│ ├── find_x64dbg.luan│ ├── find_yum.luan│ ├── find_zip.luan├── develn│ ├── debugger # 調試器支持n│ │ └── run.luan│ └── git # git模塊的擴展封裝n│ ├── branches.luan│ ├── checkout.luan│ ├── checkurl.luan│ ├── clean.luan│ ├── clone.luan│ ├── ls_remote.luan│ ├── pull.luan│ ├── refs.luan│ └── tags.luan├── libn│ └── detect # 這個模塊,比較實用,用於各種編譯器特性探測、語言類型和函數檢測n│ ├── check_cxsnippets.luan│ ├── features.luan│ ├── find_tool.luan│ ├── find_toolname.luan│ ├── has_cfuncs.luan│ ├── has_cincludes.luan│ ├── has_ctypes.luan│ ├── has_cxxfuncs.luan│ ├── has_cxxincludes.luan│ ├── has_cxxtypes.luan│ ├── has_features.luan│ ├── has_flags.luan│ └── pkg_config.luan├── net # 網路模塊n│ ├── fasturl.luan│ ├── http n│ │ └── download.lua # http下載模塊,自動檢測curl/wget並調用n│ └── ping.luan├── packagen│ └── manager # 系統第三方包管理工具的封裝,提供一致性包安裝n│ ├── aptn│ │ └── install.luan│ ├── brewn│ │ └── install.luan│ ├── install.luan│ ├── pacmann│ │ └── install.luan│ └── yumn│ └── install.luan├── privilege # 許可權管理n│ └── sudo.luan└── utilsn └── archive # 歸檔文件的壓縮和解壓,支持系統常用歸檔格式:zip/7z/gz/tar/bz2等,自動檢測和適配解壓工具n └── extract.luan

Plugins目錄

放置內置插件的目錄,裡面內置了一些常用插件,我們也可以自己擴展插件,或者從xmake-plugins上面下載一些擴展插件。

./xmake/plugins/n├── doxygen # doxygen文檔生成插件n├── hello # xmake插件的一個demon├── lua # 載入和測試lua腳本、xmake的模塊,例如:xmake l lib.detect.find_tool gitn│ └── scripts n├── macro # 宏記錄插件,記錄和回放所有執行過的xmake命令,一般用於批量構建和打包n│ └── macrosn├── project # IDE工程文件生成插件,支持:vs200x, vs201x, makefile等工程文件n│ ├── clangn│ ├── makefilen│ └── vstudion└── repo # 依賴包倉庫管理 n

Platforms目錄

提供一些構建平台的配置和腳本處理,也可自行擴展自己的平台。

./xmake/platforms/n├── android # 基於android ndk的編譯n├── cross # 主要用於交叉編譯 n├── iphoneos # ios平台的編譯,支持模擬器架構n├── linux # linux平台,也支持linux環境的交叉編譯工具鏈n├── macosx # macosx的環境編譯n├── mingw # 基於mingw工具鏈的編譯,支持windows/macosx/linux下的mingwn├── watchos # apple watch 平台的編譯n└── windows # windows平台的編譯,可直接在cmd終端下進行,不需要cygwin/msys支持 n

Languages目錄

這個目錄提供xmake編譯指定的代碼語言所需的一些配置信息和腳本處理,我們可以自己擴展這個目錄,來提供其他語言編譯的支持。

./xmake/languages/n├── asmn├── c++n├── dlangn├── golangn├── msrcn├── objc++n├── rustn└── swiftn

Templates目錄

這個目錄主要提供xmake create創建空工程所需的一些內置工程模板。

./xmake/templates/n├── cn│ ├── consolen│ ├── console_tboxn│ ├── shared_libraryn│ ├── shared_library_tboxn│ ├── static_libraryn│ └── static_library_tboxn├── c++n│ ├── consolen│ ├── console_tboxn│ ├── shared_libraryn│ ├── shared_library_tboxn│ ├── static_libraryn│ └── static_library_tboxn├── dlangn│ ├── consolen│ ├── shared_libraryn│ └── static_libraryn├── gon│ ├── consolen│ └── static_libraryn├── objcn│ └── consolen├── objc++n│ └── consolen├── rustn│ ├── consolen│ └── static_libraryn└── swiftn └── consolen

Core目錄

core比較複雜,它是xmake最底層的支撐,提供了沙盒機制、解釋器、工程處理、基礎模塊、插件載入的核心實現,裡面的所有模塊都不在沙盒裡面,所以跟其他目錄裡面的模塊是完全隔離的。

./xmake/core/n├── _xmake_main.lua # xmake的腳本起始入口n├── base # 基礎模塊n│ ├── colors.lua # ${red}等色彩輸出的基礎支持n│ ├── coroutine.lua # 協程封裝n│ ├── deprecated.luan│ ├── emoji.luan│ ├── filter.lua # $(val)變數的處理器n│ ├── global.luan│ ├── interpreter.lua # xmake.lua的解釋器n│ ├── io.luan│ ├── option.lua # 命令行輸入參數的解析和獲取n│ ├── os.luan│ ├── path.luan│ ├── privilege.luan│ ├── process.luan│ ├── profiler.lua # 性能分析器n│ ├── string.luan│ ├── table.luan│ ├── task.lua # task任務、插件處理模塊n│ └── utils.luan├── language # 代碼語言模塊,會去載入languages目錄下的指定語言配置n│ ├── language.luan│ └── menu.luan├── main.lua # xmake的主入口n├── package # 包依賴支持n│ ├── package.luan│ └── repository.luan├── platform # 平台管理n│ ├── environment.luan│ ├── menu.luan│ └── platform.luan├── project # 工程管理相關的一些模塊n│ ├── cache.lua # 工程緩存維護n│ ├── config.lua # 工程配置文件維護n│ ├── history.luan│ ├── option.lua # option對象的封裝n│ ├── project.lua # 工程xmake.lua載入和解析n│ ├── target.lua # target對象的封裝n│ └── template.lua # 工程模板的載入n├── sandbox # 沙盒模塊n│ ├── modules # 這裡面也提供了一些內置沙盒模塊,跟modules目錄下的模塊的區別就是,這裡的模塊實現代碼本身不基於沙盒,純原生底層代碼實現,可直接調用底層介面n│ │ ├── _g.lua # 這裡的模塊不需要import,可直接在沙盒腳本中使用n│ │ ├── assert.luan│ │ ├── catch.luan│ │ ├── coroutine.luan│ │ ├── cprint.luan│ │ ├── cprintf.luan│ │ ├── debug.luan│ │ ├── finally.luan│ │ ├── format.luan│ │ ├── hash.luan│ │ ├── ifelse.luan│ │ ├── import # 這裡面也提供了一些import所需的內置沙盒模塊,裡面的實現代碼,可直接調用core裡面底層介面,並且做了異常捕獲和返回值檢測n│ │ │ ├── coren│ │ │ │ ├── basen│ │ │ │ │ ├── colors.luan│ │ │ │ │ ├── filter.luan│ │ │ │ │ ├── global.luan│ │ │ │ │ ├── option.luan│ │ │ │ │ ├── privilege.luan│ │ │ │ │ ├── semver.luan│ │ │ │ │ └── task.luan│ │ │ │ ├── languagen│ │ │ │ │ ├── language.luan│ │ │ │ │ └── menu.luan│ │ │ │ ├── packagen│ │ │ │ │ ├── package.luan│ │ │ │ │ └── repository.luan│ │ │ │ ├── platformn│ │ │ │ │ ├── environment.luan│ │ │ │ │ ├── menu.luan│ │ │ │ │ └── platform.luan│ │ │ │ ├── projectn│ │ │ │ │ ├── cache.luan│ │ │ │ │ ├── config.luan│ │ │ │ │ ├── history.luan│ │ │ │ │ ├── menu.luan│ │ │ │ │ ├── project.luan│ │ │ │ │ ├── target.luan│ │ │ │ │ ├── task.luan│ │ │ │ │ └── template.luan│ │ │ │ ├── sandboxn│ │ │ │ │ ├── module.luan│ │ │ │ │ └── sandbox.luan│ │ │ │ └── tooln│ │ │ │ ├── compiler.luan│ │ │ │ ├── extractor.luan│ │ │ │ └── linker.luan│ │ │ └── libn│ │ │ └── detect # lib.detect.* 下的部分探測介面,跟modules下的那些類似n│ │ │ ├── cache.luan│ │ │ ├── find_directory.luan│ │ │ ├── find_file.luan│ │ │ ├── find_library.luan│ │ │ ├── find_package.luan│ │ │ ├── find_path.luan│ │ │ ├── find_program.luan│ │ │ └── find_programver.luan│ │ ├── import.lua # import介面實現n│ │ ├── inherit.luan│ │ ├── insert.luan│ │ ├── interpreter # xmake.lua上層描述域可直接調用的一些內置模塊n│ │ │ ├── format.luan│ │ │ ├── getenv.luan│ │ │ ├── ifelse.luan│ │ │ ├── ipairs.luan│ │ │ ├── os.luan│ │ │ ├── pairs.luan│ │ │ ├── path.luan│ │ │ ├── print.luan│ │ │ ├── printf.luan│ │ │ ├── string.luan│ │ │ ├── table.luan│ │ │ ├── tonumber.luan│ │ │ ├── tostring.luan│ │ │ └── type.luan│ │ ├── io.lua # 這下面是一些不需要import的內置介面,部分介面做了些改進n│ │ ├── ipairs.luan│ │ ├── math.luan│ │ ├── os.luan│ │ ├── pairs.luan│ │ ├── path.luan│ │ ├── print.luan│ │ ├── printf.luan│ │ ├── process.luan│ │ ├── raise.luan│ │ ├── string.luan│ │ ├── table.luan│ │ ├── tonumber.luan│ │ ├── tostring.luan│ │ ├── try.luan│ │ ├── type.luan│ │ ├── unpack.luan│ │ ├── utils.luan│ │ ├── val.luan│ │ ├── vformat.luan│ │ ├── vprint.luan│ │ └── vprintf.luan│ └── sandbox.luan└── tool # 編譯器、鏈接器等相關工具的封裝模塊,可通過`import("core.tool.compiler")`來使用n ├── builder.luan ├── compiler.luan ├── extractor.luan ├── linker.luan └── tool.luan

原文出處:tboox.org/cn/2017/09/28


推薦閱讀:

庖丁解牛迭代器,聊聊那些藏在幕後的秘密
c++類的某個成員的析構函數是刪除的,會導致類合成的默認構造函數也是刪除的?
編譯器簡介: 在 Siri 前時代如何與計算機對話
來自YSRC:孤挺花字元串混淆功能分析

TAG:编译器 | CC | 跨平台 |