原文出处:xmake源码架构剖析

本文主要介绍下xmake的整体架构设计,以及源码结构的布局和模块划分。 如果你想深度使用xmake,开发xmake插件、工程自定义脚本或者想为xmake贡献一些代码和特性,可以通过此本的介绍,对xmake项目整体有个大概的了解。,

源码地址:Github

顶层目录结构

./xmake/
├── actions    ## 内建的一些基础task用于基本的构建安装等操作
├── core       ## xmake的核心模块提供最底层的实现支持
├── languages  ## 所有的语言相关特性支持和扩展都在此目录下
├── modules    ## 内置的扩展模块可用`import`导入使用
├── packages   ## 内置包目录提供xmake所需的一些必须依赖包支持例如git等其他第三方包放在独立xmake-repo下
├── platforms  ## 平台支持目录提供各个构建平台的配置信息和脚本
├── plugins    ## 插件目录提供一些内置的插件支持例如生成IDE工程宏脚本等。。
├── scripts    ## 放置一些杂七杂八的shellperl等其他语言脚本例如gas-preprocessor.pl
└── templates  ## 工程模板目录提供一些`xmake create`创建工程所需的内置模板

沙盒模式

为了简化xmake.lua中自己定义脚本、插件脚本以及扩展模块的开发,提供更高的安全性,xmake采用了沙盒的方式去加载他们,每个脚本都独立在一个单独的沙盒中,并且有独立的作用域支持。

在xmake的整个目录结构中,除了xmake/core底层核心模块,其他的顶层目录全部放置在沙盒中加载运行,来简化代码开发,提高易用性和安全性。

这样有什么好处呢?

下面我们可以直观感受下原生代码沙盒代码的区别:

导入和返回值判断的改进

原生代码:

local test = require("modules/test")
local ok, errors = test.run("arg1", "arg2")
if not ok then
    os.raise(errors)
end

沙盒代码:

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

如果test.run运行出错,会自动中断,并显示出错信息。

import的导入比lua原生的require更加的强大易用,支持很多高级特性:

内置api的改进

原生代码:

print("hello xmake")
print("hello", "xmake")

沙盒代码:

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

空参数的判断改进

原生代码:

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

沙盒代码:

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

简化模块定义

原生代码:

local module = module or {}
function module.test(arg)
    -- ...
end
return module

沙盒代码:

function test(arg)
    -- ...
end

Actions目录

这个目录下提供xmake日常所需的最基础命令,提供配置、编译、打包、安装、运行、调试、卸载等功能。

./xmake/actions/
├── build       ## 构建工程
├── clean       ## 清理构建产生的文件
├── config      ## 构建前的工程配置
├── create      ## 根据模板创建工程
├── global      ## 全局配置
├── install     ## 安装构建好的目标文件到系统
├── package     ## 打包当前平台下的构建文件
├── require     ## 获取依赖包
├── run         ## 运行调试目标程序
└── uninstall   ## 卸载安装到系统的目标文件

Modules目录

这个是扩展模块目录,提供了一些常用的模块,来扩展xmake.lua的自定义脚本,提供更多高级特性,例如:编译器特性检测、依赖包检测等。

./xmake/modules/
├── core
   └── tools ## 这个下面的模块,主要用于扩展xmake的编译工具链
       ├── ar.lua
       ├── cl.lua
       ├── clang.lua
       ├── clangxx.lua
       ├── dmd.lua
       ├── gcc.lua
       ├── gccgo.lua
       ├── gdc.lua
       ├── go.lua
       ├── gxx.lua
       ├── ldc.lua
       ├── lib.lua
       ├── link.lua
       ├── ml.lua
       ├── ml64.lua
       ├── rc.lua
       ├── rustc.lua
       └── swiftc.lua
├── detect
   ├── packages ## 用于增强find_package接口的探测
      ├── find_mbedtls.lua
      ├── find_mysql.lua
      ├── find_openssl.lua
      ├── find_pcre.lua
      ├── find_pcre2.lua
      └── find_zlib.lua
   ├── sdks ## 用于查找一些编译sdk环境
      ├── find_cross_toolchains.lua
      ├── find_ndk_sdkvers.lua
      ├── find_ndk_toolchains.lua
      ├── find_vstudio.lua
      ├── find_xcode_dir.lua
      └── find_xcode_sdkvers.lua
   └── tools ## 用于增强可执行工具的查找、特性检测
       ├── find_7z.lua
       ├── find_apt.lua
       ├── find_ar.lua
       ├── find_brew.lua
       ├── find_ccache.lua
       ├── find_cl.lua
       ├── find_clang.lua
       ├── find_clangxx.lua
       ├── find_curl.lua
       ├── find_dmd.lua
       ├── find_doxygen.lua
       ├── find_gcc.lua
       ├── find_gccgo.lua
       ├── find_gdb.lua
       ├── find_gdc.lua
       ├── find_git.lua
       ├── find_go.lua
       ├── find_gxx.lua
       ├── find_gzip.lua
       ├── find_ldc2.lua
       ├── find_lib.lua
       ├── find_link.lua
       ├── find_lipo.lua
       ├── find_lldb.lua
       ├── find_ml.lua
       ├── find_ml64.lua
       ├── find_ollydbg.lua
       ├── find_pacman.lua
       ├── find_ping.lua
       ├── find_pkg_config.lua
       ├── find_rc.lua
       ├── find_rustc.lua
       ├── find_sudo.lua
       ├── find_swiftc.lua
       ├── find_tar.lua
       ├── find_unzip.lua
       ├── find_vsjitdebugger.lua
       ├── find_wget.lua
       ├── find_windbg.lua
       ├── find_x64dbg.lua
       ├── find_yum.lua
       ├── find_zip.lua
├── devel
   ├── debugger ## 调试器支持
      └── run.lua
   └── git ## git模块的扩展封装
       ├── branches.lua
       ├── checkout.lua
       ├── checkurl.lua
       ├── clean.lua
       ├── clone.lua
       ├── ls_remote.lua
       ├── pull.lua
       ├── refs.lua
       └── tags.lua
├── lib
   └── detect ## 这个模块,比较实用,用于各种编译器特性探测、语言类型和函数检测
       ├── check_cxsnippets.lua
       ├── features.lua
       ├── find_tool.lua
       ├── find_toolname.lua
       ├── has_cfuncs.lua
       ├── has_cincludes.lua
       ├── has_ctypes.lua
       ├── has_cxxfuncs.lua
       ├── has_cxxincludes.lua
       ├── has_cxxtypes.lua
       ├── has_features.lua
       ├── has_flags.lua
       └── pkg_config.lua
├── net ## 网络模块
   ├── fasturl.lua
   ├── http 
      └── download.lua ## http下载模块,自动检测curl/wget并调用
   └── ping.lua
├── package
   └── manager ## 系统第三方包管理工具的封装,提供一致性包安装
       ├── apt
          └── install.lua
       ├── brew
          └── install.lua
       ├── install.lua
       ├── pacman
          └── install.lua
       └── yum
           └── install.lua
├── privilege ## 权限管理
   └── sudo.lua
└── utils
    └── archive ## 归档文件的压缩和解压,支持系统常用归档格式:zip/7z/gz/tar/bz2等,自动检测和适配解压工具
        └── extract.lua

Plugins目录

放置内置插件的目录,里面内置了一些常用插件,我们也可以自己扩展插件,或者从xmake-plugins上面下载一些扩展插件。

./xmake/plugins/
├── doxygen         ## doxygen文档生成插件
├── hello           ## xmake插件的一个demo
├── lua             ## 加载和测试lua脚本xmake的模块例如xmake l lib.detect.find_tool git
   └── scripts 
├── macro           ## 宏记录插件记录和回放所有执行过的xmake命令一般用于批量构建和打包
   └── macros
├── project         ## IDE工程文件生成插件支持vs200x, vs201x, makefile等工程文件
   ├── clang
   ├── makefile
   └── vstudio
└── repo            ## 依赖包仓库管理

Platforms目录

提供一些构建平台的配置和脚本处理,也可自行扩展自己的平台。

./xmake/platforms/
├── android   ## 基于android ndk的编译
├── cross     ## 主要用于交叉编译 
├── iphoneos  ## ios平台的编译支持模拟器架构
├── linux     ## linux平台也支持linux环境的交叉编译工具链
├── macosx    ## macosx的环境编译
├── mingw     ## 基于mingw工具链的编译支持windows/macosx/linux下的mingw
├── watchos   ## apple watch 平台的编译
└── windows   ## windows平台的编译可直接在cmd终端下进行不需要cygwin/msys支持

Languages目录

这个目录提供xmake编译指定的代码语言所需的一些配置信息和脚本处理,我们可以自己扩展这个目录,来提供其他语言编译的支持。

./xmake/languages/
├── asm
├── c++
├── dlang
├── golang
├── msrc
├── objc++
├── rust
└── swift

Templates目录

这个目录主要提供xmake create创建空工程所需的一些内置工程模板。

./xmake/templates/
├── c
   ├── console
   ├── console_tbox
   ├── shared_library
   ├── shared_library_tbox
   ├── static_library
   └── static_library_tbox
├── c++
   ├── console
   ├── console_tbox
   ├── shared_library
   ├── shared_library_tbox
   ├── static_library
   └── static_library_tbox
├── dlang
   ├── console
   ├── shared_library
   └── static_library
├── go
   ├── console
   └── static_library
├── objc
   └── console
├── objc++
   └── console
├── rust
   ├── console
   └── static_library
└── swift
    └── console

Core目录

core比较复杂,它是xmake最底层的支撑,提供了沙盒机制、解释器、工程处理、基础模块、插件加载的核心实现,里面的所有模块都不在沙盒里面,所以跟其他目录里面的模块是完全隔离的。

./xmake/core/
├── _xmake_main.lua ## xmake的脚本起始入口
├── base ## 基础模块
   ├── colors.lua ## ${red}等色彩输出的基础支持
   ├── coroutine.lua ## 协程封装
   ├── deprecated.lua
   ├── emoji.lua
   ├── filter.lua ## $(val)变量的处理器
   ├── global.lua
   ├── interpreter.lua ## xmake.lua的解释器
   ├── io.lua
   ├── option.lua ## 命令行输入参数的解析和获取
   ├── os.lua
   ├── path.lua
   ├── privilege.lua
   ├── process.lua
   ├── profiler.lua ## 性能分析器
   ├── string.lua
   ├── table.lua
   ├── task.lua ## task任务插件处理模块
   └── utils.lua
├── language ## 代码语言模块会去加载languages目录下的指定语言配置
   ├── language.lua
   └── menu.lua
├── main.lua ## xmake的主入口
├── package ## 包依赖支持
   ├── package.lua
   └── repository.lua
├── platform ## 平台管理
   ├── environment.lua
   ├── menu.lua
   └── platform.lua
├── project ## 工程管理相关的一些模块
   ├── cache.lua ## 工程缓存维护
   ├── config.lua ## 工程配置文件维护
   ├── history.lua
   ├── option.lua ## option对象的封装
   ├── project.lua ## 工程xmake.lua加载和解析
   ├── target.lua ## target对象的封装
   └── template.lua ## 工程模板的加载
├── sandbox ## 沙盒模块
   ├── modules ## 这里面也提供了一些内置沙盒模块跟modules目录下的模块的区别就是这里的模块实现代码本身不基于沙盒纯原生底层代码实现可直接调用底层接口
      ├── _g.lua ## 这里的模块不需要import可直接在沙盒脚本中使用
      ├── assert.lua
      ├── catch.lua
      ├── coroutine.lua
      ├── cprint.lua
      ├── cprintf.lua
      ├── debug.lua
      ├── finally.lua
      ├── format.lua
      ├── hash.lua
      ├── ifelse.lua
      ├── import ## 这里面也提供了一些import所需的内置沙盒模块里面的实现代码可直接调用core里面底层接口并且做了异常捕获和返回值检测
         ├── core
            ├── base
               ├── colors.lua
               ├── filter.lua
               ├── global.lua
               ├── option.lua
               ├── privilege.lua
               ├── semver.lua
               └── task.lua
            ├── language
               ├── language.lua
               └── menu.lua
            ├── package
               ├── package.lua
               └── repository.lua
            ├── platform
               ├── environment.lua
               ├── menu.lua
               └── platform.lua
            ├── project
               ├── cache.lua
               ├── config.lua
               ├── history.lua
               ├── menu.lua
               ├── project.lua
               ├── target.lua
               ├── task.lua
               └── template.lua
            ├── sandbox
               ├── module.lua
               └── sandbox.lua
            └── tool
                ├── compiler.lua
                ├── extractor.lua
                └── linker.lua
         └── lib
             └── detect ## lib.detect.* 下的部分探测接口跟modules下的那些类似
                 ├── cache.lua
                 ├── find_directory.lua
                 ├── find_file.lua
                 ├── find_library.lua
                 ├── find_package.lua
                 ├── find_path.lua
                 ├── find_program.lua
                 └── find_programver.lua
      ├── import.lua ## import接口实现
      ├── inherit.lua
      ├── insert.lua
      ├── interpreter ## xmake.lua上层描述域可直接调用的一些内置模块
         ├── format.lua
         ├── getenv.lua
         ├── ifelse.lua
         ├── ipairs.lua
         ├── os.lua
         ├── pairs.lua
         ├── path.lua
         ├── print.lua
         ├── printf.lua
         ├── string.lua
         ├── table.lua
         ├── tonumber.lua
         ├── tostring.lua
         └── type.lua
      ├── io.lua ## 这下面是一些不需要import的内置接口部分接口做了些改进
      ├── ipairs.lua
      ├── math.lua
      ├── os.lua
      ├── pairs.lua
      ├── path.lua
      ├── print.lua
      ├── printf.lua
      ├── process.lua
      ├── raise.lua
      ├── string.lua
      ├── table.lua
      ├── tonumber.lua
      ├── tostring.lua
      ├── try.lua
      ├── type.lua
      ├── unpack.lua
      ├── utils.lua
      ├── val.lua
      ├── vformat.lua
      ├── vprint.lua
      └── vprintf.lua
   └── sandbox.lua
└── tool ## 编译器链接器等相关工具的封装模块可通过`import("core.tool.compiler")`来使用
    ├── builder.lua
    ├── compiler.lua
    ├── extractor.lua
    ├── linker.lua
    └── tool.lua