---
title: xmake v2.6.3 发布，支持 vcpkg 清单模式
tags: [xmake, lua, C/C++, Linux, Vcpkg]
date: 2022-01-22
author: Ruki
outline: deep
---

## 新版本改动

这个版本主要新增下面几个特性：

1. 通过 vcpkg 的清单模式实现 vcpkg 包的版本选择
2. python 模块构建支持
3. 支持在 CMakeLists.txt 中集成 Xrepo/Xmake 包管理

剩下的主要是一些零散的功能改进和 Bugs 修复，可以看下文末的更新内容明细，一些比较大的改动，下面也会逐一说明。

## 新特性介绍

### 支持 Vcpkg 清单模式

新版本中，Xmake 新增了 vcpkg 清单模式支持，通过它，我们就能支持 vcpkg 包的版本选择，例如：

```lua
add_requires("vcpkg::zlib 1.2.11+10")
add_requires("vcpkg::fmt >=8.0.1", {configs = {baseline = "50fd3d9957195575849a49fa591e645f1d8e7156"}})
add_requires("vcpkg::libpng", {configs = {features = {"apng"}}})

target("test")
    set_kind("binary")
    add_files("src/*.cpp")
    add_packages("vcpkg::zlib", "vcpkg::fmt", "vcpkg::libpng")
```

但是，vcpkg 的版本选择限制还是不少，必须要硬编码指定 baseline，而且还不支持 `<=1.0`, `1.x` 等版本语义选择，不过总比之前不能选择版本好了不少。

### 在 CMake 中使用 Xrepo 的依赖包管理

我们新增了一个独立项目 [xrepo-cmake](https://github.com/xmake-io/xrepo-cmake)。

它是一个基于 Xrepo/Xmake 的 C/C++ 包管理器的 CMake 包装器。

这允许使用 CMake 来构建您的项目，同时使用 Xrepo 来管理依赖包。这个项目的部分灵感来自 [cmake-conan](https://github.com/conan-io/cmake-conan)。

此项目的示例用例：

- 想要使用 Xrepo 管理包的现有 CMake 项目。
- 必须使用 CMake，但想使用 Xrepo 管理的新项目包。

#### 使用来自官方存储库的包

Xrepo 官方仓库：[xmake-repo](https://github.com/xmake-io/xmake-repo)

[xrepo.cmake](https://github.com/xmake-io/xrepo-cmake/blob/main/xrepo.cmake) 提供`xrepo_package`函数来管理包。

```cmake
xrepo_package(
    "foo 1.2.3"
    [CONFIGS feature1=true,feature2=false]
    [MODE debug|release]
    [OUTPUT verbose|diagnosis|quiet]
    [DIRECTORY_SCOPE]
)
```






一些函数参数直接对应于 Xrepo 命令选项。

调用 `xrepo_package(foo)` 后，有两种使用 `foo` 包的方法：

- 如果包提供 cmake 模块来查找它，则调用 `find_package(foo)`, 参考 CMake [`find_package`](https://cmake.org/cmake/help/latest/command/find_package.html) 文档了解更多详情
- 如果包不提供 cmake 模块，`foo_INCLUDE_DIR` 和 `foo_LINK_DIR` 变量将设置为包包含和库路径。使用这些变量在 CMake 代码中设置包含和库路径。
- 如果指定了 `DIRECTORY_SCOPE`，则 `xrepo_package` 将运行以下代码（这样用户只需要在 `target_link_libraries` 中指定库名称）

```cmake
include_directories(foo_INCLUDE_DIR)
link_directories(foo_LINK_DIR)
```

这是一个使用 `gflags` 包版本 2.2.2 的示例 `CMakeLists.txt` 由 Xrepo 管理。

```cmake
cmake_minimum_required(VERSION 3.13.0)

project(foo)

# Download xrepo.cmake if not exists in build directory.
if(NOT EXISTS "${CMAKE_BINARY_DIR}/xrepo.cmake")
    message(STATUS "Downloading xrepo.cmake from https://github.com/xmake-io/xrepo-cmake/")
    # mirror https://cdn.jsdelivr.net/gh/xmake-io/xrepo-cmake@main/xrepo.cmake
    file(DOWNLOAD "https://raw.githubusercontent.com/xmake-io/xrepo-cmake/main/xrepo.cmake"
                  "${CMAKE_BINARY_DIR}/xrepo.cmake"
                  TLS_VERIFY ON)
endif()

# Include xrepo.cmake so we can use xrepo_package function.
include(${CMAKE_BINARY_DIR}/xrepo.cmake)

# Call `xrepo_package` function to use gflags 2.2.2 with specific configs.
xrepo_package("gflags 2.2.2" CONFIGS "shared=true,mt=true")

# `xrepo_package` sets `gflags_DIR` variable in parent scope because gflags
# provides cmake modules. So we can now call `find_package` to find gflags
# package.
find_package(gflags CONFIG COMPONENTS shared)
```

#### 使用来自第三个存储库的包

除了从官方维护的存储库安装软件包之外，Xrepo 还可以安装来自第三方包管理器的包，例如 vcpkg/conan/conda/pacman/homebrew/apt/dub/cargo。

关于命令行的使用，我们可以参考文档：[Xrepo命令用法](https://xrepo.xmake.io/#/getting_started#install-packages-from-third-party-package-manager)

我们也可以直接在 cmake 中使用它来安装来自第三方仓库的包，只需将仓库名称添加为命名空间即可。例如：`vcpkg::zlib`, `conan::pcre2`

##### Conan

```cmake
xrepo_package("conan::gflags/2.2.2")
```

##### Conda

```cmake
xrepo_package("conda::gflags 2.2.2")
```

##### Vcpkg

```cmake
xrepo_package("vcpkg::gflags")
```

##### Homebrew

```cmake
xrepo_package("brew::gflags")
```

### Python 模块构建支持

我们可以用这个规则，配合 pybind11 生成 python 库模块，它会调整 python 库的模块名。

```lua
add_rules("mode.release", "mode.debug")
add_requires("pybind11")

target("example")
    add_rules("python.library")
    add_files("src/*.cpp")
    add_packages("pybind11")
    set_languages("c++11")
```

带有 soabi：

```lua
add_rules("mode.release", "mode.debug")
add_requires("pybind11")

target("example")
    add_rules("python.library", {soabi = true})
    add_files("src/*.cpp")
    add_packages("pybind11")
    set_languages("c++11")
```

### 新增删除头文件列表接口

通过此接口，可以从 `add_headerfiles` 接口添加的头文件列表中，删除指定的文件，例如：

```lua
target("test")
    add_headerfiles("src/*.h")
    remove_headerfiles("src/test.h")
```

上面的例子，可以从`src`目录下添加除`test.h`以外的所有头文件，当然这个也可以通过 `add_headerfiles("src/*.h|test.h")` 来达到相同的目的，但是这种方式更加灵活。

### 新增 on_config 配置脚本

在 `xmake config` 执行完成后，Build 之前会执行此脚本，通常用于编译前的配置工作。它与 on_load 不同的是，on_load 只要 target 被加载就会执行，执行时机更早。

如果一些配置，无法在 on_load 中过早配置，那么都可以在 on_config 中去配置它。

另外，它的执行时机比 before_build 还要早，大概的执行流程如下：

```
on_load -> after_load -> on_config -> before_build -> on_build -> after_build
```

### 内置 Github 代理镜像配置

Xmake 提供了一些内置的镜像配置可以直接使用，例如 github 的镜像加速：

```console
$ xmake g --proxy_pac=github_mirror.lua
```

我们不用自己编写 pac.lua，就可以直接使用它来加速 github 源的下载。

## 更新内容

### 新特性

* [#1298](https://github.com/xmake-io/xmake/issues/1928): 支持 vcpkg 清单模式安装包，实现安装包的版本选择
* [#1896](https://github.com/xmake-io/xmake/issues/1896): 添加 `python.library` 规则去构建 pybind 模块，并且支持 soabi
* [#1939](https://github.com/xmake-io/xmake/issues/1939): 添加 `remove_files`, `remove_headerfiles` 并且标记 `del_files` 作为废弃接口
* 将 on_config 作为正式的公开接口，用于 target 和 rule
* 添加 riscv32/64 支持
* [#1970](https://github.com/xmake-io/xmake/issues/1970): 添加 CMake wrapper 支持在 CMakelists 中去调用 xrepo 集成 C/C++ 包
* 添加内置的 github 镜像加速 pac 代理文件, `xmake g --proxy_pac=github_mirror.lua`

### 改进

* [#1923](https://github.com/xmake-io/xmake/issues/1923): 改进构建 linux 驱动，支持设置自定义 linux-headers 路径
* [#1962](https://github.com/xmake-io/xmake/issues/1962): 改进 armclang 工具链去支持构建 asm
* [#1959](https://github.com/xmake-io/xmake/pull/1959): 改进 vstudio 工程生成器
* [#1969](https://github.com/xmake-io/xmake/issues/1969): 添加默认的 option 描述

### Bugs 修复

* [#1875](https://github.com/xmake-io/xmake/issues/1875): 修复部署生成 Android Qt 程序包失败问题
* [#1973](https://github.com/xmake-io/xmake/issues/1973): 修复合并静态库
* [#1982](https://github.com/xmake-io/xmake/pull/1982): 修复 clang 下对 c++20 子模块的依赖构建
