waruqi

waruqi 查看完整档案

上海编辑天津科技大学  |   信息与计算科学 编辑爱奇艺  |  软件开发工程师 编辑 tboox.org 编辑
编辑

专注于c跨平台开发解决方案

https://xmake.io
https://tboox.org
github: https://github.com/waruqi
QQ技术交流群:343118190
微信公众号:tboox-os

个人动态

waruqi 发布了文章 · 10月18日

xmake v2.3.8 发布, 新增 Intel C++/Fortran 编译器支持

xmake 是一个基于 Lua 的轻量级跨平台构建工具,使用 xmake.lua 维护项目构建,相比 makefile/CMakeLists.txt,配置语法更加简洁直观,对新手非常友好,短时间内就能快速入门,能够让用户把更多的精力集中在实际的项目开发上。

在这个新版本中,我们对 Intel 系列的 C++ 和 Fortran 编译器做了全平台支持,并且改进了上个版本新加的 Wasm 工具链支持,同时对 Qt SDK for Wasm 也进行了支持。

另外,我们还将 luajit 升级到最新的 v2.1 版本,在跨平台方面,xmake 也做了很大的完善,增加了 mips64 架构的运行支持。

新特性介绍

Intel C++ 编译器支持

这个版本上,我们对 Intel 系列的 C++ 编译器做了全平台支持,包括 windows上的 icl 以及 linux/macOS 下的 icc/icpc。

要想启用 Intel C++ 编译器,我们只需要在安装了的 Intel 编译器的系统上,通过 --toolchain=icc 参数切换到对应的工具链即可。

$ xmake f --toolchain=icc
$ xmake

Intel Fortran 编译器支持

之前的版本,xmake 仅仅支持 gfortran 编译器,而这个版本,我们也支持了 Intel Fortran 编译器,也就是 ifort,我们也只需要切换到对应的 ifort 工具链即可使用。

$ xmake f --toolchain=ifort
$ xmake

Wasm 平台和 Qt/Wasm 支持

上个版本,我们新增了 --toolchain=emcc 工具链来支持 wasm 程序的编译,但是仅仅指定工具链,并不能很好的调整目标程序的扩展名,例如对 *.js*.wasm 的文件生成。

而新版本,我们继续新增了 xmake f -p wasm 平台,内置启用 emcc 工具链,并且再次基础上对周边的配置做了更好的完善。

只要切换到 wasm 平台,xmake 会默认生成 *.js 以及对应 *.wasm 等目标文件,还会额外生成可以加载 js 来运行 wasm 程序的 *.html 页面。

另外,我们还对 Qt SDK for Wasm 也做了支持,比如我们创建一个 Qt QuickApp 工程。

$ xmake create -t qt.quickapp_static quickapp

这里,我们注意到,我们创建的是需要静态link的Qt工程,因为 wasm 版本的 Qt 库,我们需要强制静态链接到程序才能正常使用。

生成的工程文件 xmake.lua 内容大概如下:

add_rules("mode.debug", "mode.release")

includes("qt_add_static_plugins.lua")

target("demo")
    add_rules("qt.quickapp_static")
    add_headerfiles("src/*.h")
    add_files("src/*.cpp")
    add_files("src/qml.qrc")
    add_frameworks("QtQuickControls2", "QtQuickTemplates2")
    qt_add_static_plugins("QtQuick2Plugin", {linkdirs = "qml/QtQuick.2", links = "qtquick2plugin"})
    qt_add_static_plugins("QtQuick2WindowPlugin", {linkdirs = "qml/QtQuick/Window.2", links = "windowplugin"})
    qt_add_static_plugins("QtQuickControls2Plugin", {linkdirs = "qml/QtQuick/Controls.2", links = "qtquickcontrols2plugin"})
    qt_add_static_plugins("QtQuickTemplates2Plugin", {linkdirs = "qml/QtQuick/Templates.2", links = "qtquicktemplates2plugin"})

上面的配置中,我们除了启用 qt.quickapp_static 编译规则,还通过 qt_add_static_plugins 配置了一些必须的 Qt 插件。

接下来,我们只需要切换到 wasm 平台,并确保 Qt SDK 已设置,即可完成编译。

$ xmake f -p wasm [--qt=~/Qt]
$ xmake

完成编译后,xmake 会在 build 目录下生成 demo.html 以及对应的 demo.js/demo.wasm 程序,我们打开 demo.html 页面即可运行我们编译的 Qt 程序,显示效果如下图:

关于 Qt/Wasm 更加详细的说明,见:Issue #956

新增 Math/Float-point 编译优化设置

我们新增了一个 set_fpmodels() 设置接口,用于设置浮点的编译模式,对数学计算相关优化的编译抽象设置,提供:fast, strict, except, precise 等几种常用的级别,有些可同时设置,有些是有冲突的,最后设置的生效。

关于这些级别的说明,可以参考下微软的文档:Specify floating-point behavior

当然,对应gcc/icc等其他编译器,xmake 会映射到不同的编译flags。

set_fpmodels("fast")
set_fpmodels("strict")
set_fpmodels("fast", "except")
set_fpmodels("precise") -- default

关于这块详情见:Issue #981

OpenMP 支持

为了更加抽象简单的启用 openmp 特性,我们可以通过新增的 c.openmpc++.openmp 这两个规则来设置,另外 linux、macOS 上我们需要额外的 libomp 库才行,因此可以通过 add_requires("libomp") 来快速引用和集成。

add_requires("libomp", {optional = true})
target("loop")
    set_kind("binary")
    add_files("src/*.cpp")
    add_rules("c++.openmp")
    add_packages("libomp")

如果是c代码,需要启用 add_rules("c.openmp"),如果是 c/c++ 混合编译,那么这两个规则都要设置。

c11/c17 的支持

新版本中,xmake 对 set_languages 也做了改进,增加了新的 c11/c17 设置项,同时对最新版本 msvc 提供的 /std:c11/std:c17 也做了适配和支持。

我们只需要简单的设置:

set_languages("c17")

即可启用 c17 标准来编译,即使低版本 msvc 等编译器不支持,xmake 也会自动忽略设置。

更好的 Mingw 支持

关于这块的改进,涉及几个方面,首先是 Windows 下 Mingw SDK 根目录的自动探测的改进,大部分情况下,我们都不需要额外配置 --mingw= 参数显式指定路径,也能够自动检测到了。

关于这块详情,见:Issue #977

另外,除了 Msys2/Mingw 还有 macOS,linux/Mingw,我们在新版本中还额外支持了 llvm-mingw 这个 SDK,使得我们可以使用 mingw 来编译 arm/arm64 架构的程序。

$ xmake f -p mingw -a arm64
$ xmake

另外,在远程依赖包的自动编译集成上,现在带有 cmakelists 的第三方库,即使是 mingw 平台,xmake 也能自动编译集成进来直接使用,非常的快速方便。

而最近 xmake-repo 官方 C/C++ 包仓库中,我们也新增收入了不少支持 mingw 平台的新库,可直接使用。

更好的跨平台运行

我们新增了对 mips64 架构的 linux 系统运行支持,另外改进了 arm/arm64 下 xmake 的运行稳定性,通过合入最新的 luajit v2.1 ,解决了很多 luajit 遗留的问题,比如 arm64 下 lightuserdata 的 bad pointer 等问题。

新增 macOS Sierra for arm64 支持

xmake 还对最新的 Xcode-beta 进行了适配,新增了 macOs for arm64 的目标程序编译支持,只需要切到 arm64 架构编译即可。

$ xmake f -a arm64 [--xcode=Applications/Xcode-beta.app/]
$ xmake

当然,前提是在 macOS 下运行,并且使用最新支持 Developer Transition Kit (DTK) 的 Xcode-beta 版本才行。

官方仓库收录更多的 C/C++ 库

在 xmake 的官方 C/C++ 仓库 xmake-repo 中,我们最近新增了几十个常用的 C/C++ 库,并且还对 libx11 系列的库都全部进行了收录。

虽然,仓库的包维护工作量巨大,但是目前的发展趋势也日趋活跃,我们收到了越来越多的用户对仓库包的贡献和改进维护。

并且,现在我们的官方仓库已经可以快速集成:linux, macOS, windows, mingw, bsd, msys, iphoneos, android 等八大常用平台的库,实现真正的跨平台 C/C++ 远程依赖库集成和使用支持。

目前我们收录的一些包列表和支持平台,可以从这里查看:PKGLIST.md

我们一直在努力解决 C/C++ 库生态的杂乱、集成使用繁琐等问题,提供快速一致的自动集成和编译方案,xmake 不仅支持 vcpkg/conan/clib/homebrew 等第三方官方仓库包的集成,并且也在努力完善自建的官方仓库,实现更好的集成体验。

例如:

add_requires("tbox >1.6.1", "libuv master", "vcpkg::ffmpeg", "brew::pcre2/libpcre2-8")
add_requires("conan::openssl/1.1.1g", {alias = "openssl", optional = true, debug = true})
target("test")
    set_kind("binary")
    add_files("src/*.c")
    add_packages("tbox", "libuv", "vcpkg::ffmpeg", "brew::pcre2/libpcre2-8", "openssl")

带有 vcpkg::brew::conan:: 等命名空间的包,会自动切换到对应的第三方包仓库去下载集成,而默认的 tbox >1.6.1 等库,则会默认使用 xmake-repo 官方仓库中提供的包。

使用和集成方式完全一致,xmake 会自动下载、编译、集成和链接。

关于远程包的依赖集成的更多详细说明,我们可以看下相关的文档说明:远程依赖库集成和使用

同时,我们也欢迎更多的人参与进来,帮忙一起改善 C/C++ 的库生态的建设,提供简洁一致的库使用体验,我相信 C/C++ 包管理和库生态并不比 Rust/Go 差。

更多的发行版安装支持

在新版本中,我们将 xmake 提交了 Ubuntu PPA 源,因此除了现有的脚本安装方式外,我们也可以通过 apt 去快速安装 xmake。

sudo add-apt-repository ppa:xmake-io/xmake
sudo apt update
sudo apt install xmake

同时,我们也将包提交到了 Copr 包管理仓库,使得我们也可以在 Fedora, RHEL,OpenSUSE,CentOS 等发行版中,通过 dnf 来快速安装 xmake。

sudo dnf copr enable waruqi/xmake
sudo dnf install xmake

入门课程

近期,我们也上线了官方的 xmake 入门课程,Xmake 带你轻松构建 C/C++ 项目 以边学边做实验的方式快速学习 xmake 的使用。

更新内容

新特性

  • #955: 添加 Zig 空工程模板
  • #956: 添加 Wasm 编译平台,并且支持 Qt/Wasm SDK
  • 升级luajit到v2.1最新分支版本,并且支持mips64上运行xmake
  • #972: 添加depend.on_changed()去简化依赖文件的处理
  • #981: 添加set_fpmodels()去抽象化设置math/float-point编译优化模式
  • #980: 添加对 Intel C/C++ 和 Fortran 编译器的全平台支持
  • #986: 对16.8以上msvc编译器增加 c11/c17 支持
  • #979: 添加对OpenMP的跨平台抽象配置。add_rules("c++.openmp")

改进

  • #958: 改进mingw平台,增加对 llvm-mingw 工具链的支持,以及 arm64/arm 架构的支持
  • 增加 add_requires("zlib~xxx") 模式使得能够支持同时安装带有多种配置的同一个包,作为独立包存在
  • #977: 改进 find_mingw 在 windows 上的探测
  • #978: 改进工具链的flags顺序
  • 改进XCode工具链,支持macOS/arm64

Bugs修复

  • #951: 修复 emcc (WebAssembly) 工具链在windows上的支持
  • #992: 修复文件锁偶尔打开失败问题

https://tboox.org/cn/2020/10/...

查看原文

赞 0 收藏 0 评论 0

waruqi 发布了文章 · 10月9日

xmake 官方入门课程上线: Xmake 带你轻松构建 C/C++ 项目

实验楼课程

Xmake 带你轻松构建 C/C++ 项目 是我们在实验楼上推出的一门 xmake 入门和进阶课程(收费),以边学边做实验的方式快速学习 xmake 的使用。

通过此处优惠码购买可享 9 折优惠:NYFbmf3X

xmake 介绍

Xmake 是一个基于 Lua 的轻量级跨平台 C/C++ 构建工具,使用 xmake.lua 维护项目构建,相比 makefile/CMakeLists.txt 而言,配置语法更加简洁直观,对新手非常友好,短时间内就能快速入门 C/C++ 项目的编译开发,提供一站式跨平台编译、运行、调试、打包、安装等操作,能够让大家把更多的精力集中在实际的项目开发上。

虽然,简单易用是 xmake 的一大特色,但 xmake 的功能也是非常强大的,既能够像 make/ninja 那样直接编译项目,也可以像 cmake/meson 那样生成工程文件,还有内置的包管理系统来帮助大家解决 C/C++ 依赖库的集成使用问题。

课程介绍

本课程以循序渐进的方式,带你入门和进阶 xmake,从最基础的编译配置,到复杂项目的定制化组织和维护,在课程最后几节,我们还通过实战的方式,一步步带你体验第三方 C/C++ 项目的移植编译,以及 vscode/xmake 集成环境的可视化编译操作流程。最后一节实验中,我们还会讲解如何使用 xmake 和 vscode 去编译开发基于 Qt 的应用程序。

你将学到

C/C++ 程序的编译运行和调试xmake 基础命令使用
C/C++ 依赖库集成和使用大型工程结构的维护
xmake 复杂脚本和规则的编写如何实现跨平台编译
xmake 插件开发VS Code/xmake 集成环境的使用
xmake 的基础语法C/C++ 项目基础编译配置
多个目标程序的依赖编译预编译头文件的设置
cmake/makefile 工程文件的生成xmake 脚本运行插件的使用
C/C++ 代码的移植编译Qt 项目程序的编译开发

课程链接

链接地址:https://www.lanqiao.cn/courses/2764

我们也可以通过扫描下方二维码进入课程:

查看原文

赞 0 收藏 0 评论 0

waruqi 发布了文章 · 9月18日

xmake v2.3.7 发布, 新增 tinyc 和 emscripten 工具链支持

xmake 是一个基于 Lua 的轻量级跨平台构建工具,使用 xmake.lua 维护项目构建,相比 makefile/CMakeLists.txt,配置语法更加简洁直观,对新手非常友好,短时间内就能快速入门,能够让用户把更多的精力集中在实际的项目开发上。

随着 xmake 最近几年不断的迭代发展,xmake 已经在 Github 收获 2.9K star,300+ fork,30+ 贡献者,并且处理了 900+ issues,5400+ Commits,活跃用户也在不断增长。

现在,xmake v2.3.7 版本发布了,在新版本中,我们主要完善了 xmake 自身的稳定性和兼容性,通过两个月的不断迭代,修复了很多用户反馈的各种使用问题,使用体验和稳定性有了很大的提升。

另外,我们在这个版本中也新增对 TinyC 和 Emscripten (WebAssembly) 编译工具链的支持。

尤其是针对 windows 平台,我们提供了额外的 xmake-tinyc 安装包,里面内置了 tinyc 编译器,使得用户可以完全脱离臃肿的 vs 环境,一键安装,开箱即用,只需要 5M 的安装包即可开发简单的 C 程序,同时还自带了整套 winapi 头文件。

最后,我们还改进了 trybuild 模式编译,通过 xmake 可以快速编译 autotools/cmake 维护的第三方项目,并且可以快速对接 android/ios/mingw等交叉编译环境,实现快速移植编译。

新特性介绍

更加多样的安装方式

新版本中,我们将 xmake 安装包提交到了 windows winget 以及 ubuntu ppa 仓库,我们可以更加方便快捷地安装 xmake。

Winget 安装

winget install xmake

Ubuntu PPA 安装

sudo add-apt-repository ppa:xmake-io/xmake
sudo apt update
sudo apt install xmake

当然,我们还支持很多其他的安装方式,对于其他平台的详细安装方式见:安装文档

更加丰富的工具链支持

当前我们已经支持非常多的工具链环境,而在这个版本中,我们又新增了 TinyC 和 Emscripten (WebAssembly) 编译工具链的支持,我们可以通过下面的命令快速切换到对应的工具链来编译。

xmake f --toolchain=[tinyc|emscripten]
xmake

我们还在新版本中,额外提供了两个安装包,内置集成了 TinyC 编译环境,整个安装包只需要 5M,还包含了 winsdk api。

安装包可以在 xmake 的 github/releases 目录下找到。

通过这个安装包,我们编译开发 C 程序就可以完全摆脱臃肿的 vs 开发环境(好几个 G),实现一键安装,开箱即用,对于我们平常刷刷 leetcode,写点 C 测试代码还是非常有用的,没必要为此特定安装整个 vs 进来。

另外,如果我们要查看 xmake 支持的所有工具链,可以执行下面的命令,另外 xmake f -p cross --sdk=/xxx 的编译配置可以支持更多通用的交叉工具链。

$ xmake show -l toolchains
xcode         Xcode IDE
vs            VisualStudio IDE
yasm          The Yasm Modular Assembler
clang         A C language family frontend for LLVM
go            Go Programming Language Compiler
dlang         D Programming Language Compiler
gfortran      GNU Fortran Programming Language Compiler
zig           Zig Programming Language Compiler
sdcc          Small Device C Compiler
cuda          CUDA Toolkit
ndk           Android NDK
rust          Rust Programming Language Compiler
llvm          A collection of modular and reusable compiler and toolchain technologies
cross         Common cross compilation toolchain
nasm          NASM Assembler
gcc           GNU Compiler Collection
mingw         Minimalist GNU for Windows
gnu-rm        GNU Arm Embedded Toolchain
envs          Environment variables toolchain
fasm          Flat Assembler
tinyc         Tiny C Compiler
emcc          A toolchain for compiling to asm.js and WebAssembly

TryBuild 编译模式改进

所谓 trybuild 模式,就是 xmake 推出的一个适配现有第三方构建系统的特性,因为现在大部分已有的第三方项目都是用 autotools/cmake 等第三方构建系统维护的,如果将它们迁移到 xmake 配置那么迁移成本还是比较高的。

虽然 xmake 的配置编写非常简单上手,但也没必要对已经稳定维护的项目去大改构建系统,xmake 主要还是用于一些新项目的构建维护。

基于此背景,xmake 采用 trybuild 编译模式,也就是所谓的尝试编译模式,通过自动探测第三方项目的构建系统,如果检测到是 autotools 维护的项目,那么自动调用 ./configure; make 来编译。

如果检测到是用 cmake 维护的项目,那么自动调用 cmake 来生成 makefile/build.ninja 来编译,对于使用 xmake 的用户而言,始终只是执行 xmake 这一个命令就可以完成编译,例如:

$ xmake
note: configure found, try building it or you can run `xmake f --trybuild=` to set buildsystem (pass -y or --confirm=y/n/d to skip confirm)?
please input: y (y/n)
y
  ...
  CC       src/pcre2grep-pcre2grep.o
  CC       src/libpcre2_8_la-pcre2_auto_possess.lo
  CC       src/libpcre2_8_la-pcre2_config.lo
  ...
build ok!

xmake检测到 autotools 构建系统后,就会提示用户是否需要尝试调用 autotools 来编译,输入y确认后,就可以直接完成编译,对于 cmake 的项目也是,只需要执行相同的 xmake 命令即可。

而不需要关心 autotools/cmake 需要如何去配置使用和编译,毕竟 cmake 对于 windows 和 linux 平台,需要生成不同的构建文件,编译方式也是不同的,一会调用 make,一会调用 msbuild,看着就头大。

不仅如此,xmake 还对接了 xmake -r 来直接重新编译,对接 xmake clean 实现统一的文件清理,对接 xmake -v 实现统一的详细编译命令的查看。

TryBuild 的交叉编译支持

如果只是当前主机平台的编译,也许你们会说,这有啥,cmake 也有 cmake --build . 来直接编译,并不怎么麻烦么。

那么问题来了,交叉编译怎么搞?如果你们用过 autotools/cmake 去交叉编译生成 mingw/android/ios 的目标程序,cmake 和 autotools 还能够简单一致的处理么?

autotools 不多说,反正我是对它的交叉体验是深恶痛绝的,每次交叉编译移植一个带有 autotools 项目的代码,都要折腾半天,经常要包各种错误,研究各种配置参数的传递,不同平台的配置还不同。

而 cmake 我感觉用起来也不省事,比如对于 Android 平台得这样搞:

$ cmake \
    -DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake \
    -DANDROID_ABI=$ABI \
    -DANDROID_NATIVE_API_LEVEL=$MINSDKVERSION \
    $OTHER_ARGS

而对于 ios 平台,没找到简答的配置方式,就找到个第三方的 ios 工具链配置,很复杂:https://github.com/leetal/ios...

对于 mingw 又是另外一种方式,我又折腾了半天环境,很是折腾。

那如果使用 xmake 去对接 cmake 实现交叉编译呢,只需要这样。

编译 android 程序:

xmake f -p android --trybuild=cmake --ndk=/xxx
xmake

编译 ios 程序:

xmake f -p iphoneos --trybuild=cmake
xmake

编译 mingw 程序:

xmake f -p mingw --trybuild=cmake --mingw=/sdk/xxx
xmake

我们只需要配置的时候,通过 --trybuild=cmake 启用 cmake 的尝试编译模式,然后通过 -p android/iphoneos/mingw 切到对应的平台,对接对应的sdk,就可以使用相同的方式来快速实现交叉编译,哪怕这个项目是使用 cmake 来维护的。

用户不需要关系如果使用 cmake 去传递不同工具链的配置,xmake 都帮你自动处理了,你只需要简单的执行 xmake 来编译,也可以执行 xmake -r 来重编,或者查看编译详情 xmake -v

另外,还可以通过 xmake f -p iphoneos -a arm64 --trybuild=cmake 快速的切换编译架构。

最后,我们需要说明的是,虽然 trybuild 模式可以极大帮助用户节省编译和配置操作,但是如果条件运行,我们还是希望大家能够直接使用 xmake.lua 来维护自己的项目。

这样,就不需要走 trybuild 编译了,xmake 会更加完美的支持交叉编译,因为内部 xmake 会直接去编译项目,而不需要在调用 cmake、autotools 等工具了,例如:

xmake f -p iphoneos
xmake

或者

xmake f -p android --ndk=/xxx
xmake

可以看到,这回我们省去了 --trybuild=cmake 参数,因为不需要了,我们是直接编译的,这个时候 xmake 相当于独立的 make/ninja,并且完全不依赖 make,编译速度也可以完全媲美 ninja。

改进远程依赖包的集成

交叉编译支持

xmake 不仅对 trybuild 支持了 mingw/autotools 的交叉编译支持,还对远程包仓库中使用 cmake/autotools 维护的第三方也支持上了交叉编译安装和集成。

例如:

add_requires("pcre2")

target("test")
    set_kind("binary")
    add_files("src/*.cpp")
    add_packages("pcre2")

然后通过切换到 iphoneos 平台,就可以快速集成安装 iphoneos 平台的 pcre2 包,然后编译链接它,哪怕这个 pcre2 包是通过 autotools/cmake 维护的。

xmake f -p iphoneos
xmake

私有网络包仓库

这个版本中,我们对远程依赖包的集成也稍微做了一些改进,比如可以通过配置 xmake g --network=private 切到私有网络模式。

这个主要用于一些公司内部网络通过 xmake 自建的包管理仓库,实现封闭式的 C/C++ 依赖包集成,完全不会从 xmake 提供的官方仓库下来依赖包。

递归导出安装的包

xmake 之前提供了一个命令,可以导出通过 xmake 安装的所有第三方依赖包。

xmake require --export

但是,之前的版本对应一些存在依赖的包,导出时候只会导出自身,它的所有依赖是不会被导出的,而这个版本中,我们对其进行了改进,将对应的所有依赖包也进行了导出。

改进对 Qt SDK 环境的支持

另外,这个版本我们还对 Qt SDK 的工具链环境进行了更好的支持,比如 ubuntu 系统下通过 apt 命令安装的 Qt SDK 工具链也进行了支持,而之前的版本只能支持从 Qt 官网下载安装的 Qt SDK 环境。

更新内容

新特性

  • #2941: 支持通过 winget 来安装 xmake
  • 添加 xmake-tinyc 安装包,内置tinyc编译器,支持windows上无msvc环境也可直接编译c代码
  • 添加 tinyc 编译工具链
  • 添加 emcc (emscripten) 编译工具链去编译 asm.js 和 WebAssembly
  • #947: 通过 xmake g --network=private 配置设置私有网络模式,避免远程依赖包下载访问外网导致编译失败

改进

  • #907: 改进msvc的链接器优化选项,生成更小的可执行程序
  • 改进ubuntu下Qt环境的支持
  • #918: 改进cuda11工具链的支持
  • 改进Qt支持,对通过 ubuntu/apt 安装的Qt sdk也进行了探测支持,并且检测效率也优化了下
  • 改进 CMake 工程文件生成器
  • #931: 改进导出包,支持导出所有依赖包
  • #930: 如果私有包定义没有版本定义,支持直接尝试下载包
  • #927: 改进android ndk,支持arm/thumb指令模式切换
  • 改进 trybuild/cmake 支持 Android/Mingw/iPhoneOS/WatchOS 工具链

Bugs修复

  • #903: 修复vcpkg包安装失败问题
  • #912: 修复自定义工具链
  • #914: 修复部分aarch64设备上运行lua出现bad light userdata pointer问题

https://tboox.org/cn/2020/09/...

查看原文

赞 0 收藏 0 评论 0

waruqi 发布了文章 · 7月29日

xmake v2.3.6 发布, 新增fortran编译支持

这个版本重点对其他语言的支持做了一些改进,比如新增了fortran的编译支持,zig语言的实验性支持,另外对golang/dlang增加了第三方依赖包支持以及交叉编译支持。

虽然,xmake重点关注c/c++的构建支持,但是其他语言的支持xmake也会不定期做一些改进,其主要目的并不是替代它们官方自身的构建系统,仅仅只是为了支持与c/c++的混合编译,更好的为c/c++项目服务,
毕竟有些c/c++项目中,还是会偶尔调用其他语言的代码接口,比如与cuda, dlang, objc,swift, asm等语言的混合调用,所以xmake还是会对他们做一些基础性的编译支持。

另外,关于c/c++方面,我们也对vs预览版中新的/sourceDependencies xxx.json输出的头文件依赖格式也做了支持(这对于多语言下,头文件依赖检测会更加的可靠稳定)。

新特性介绍

Fortran语言编译支持

这个版本开始,我们已经完全支持使用gfortran编译器来编译fortran项目,我们可以通过下面的命令,快速创建一个基于fortran的空工程:

$ xmake create -l fortran -t console test

它的xmake.lua内容如下:

add_rules("mode.debug", "mode.release")

target("test")
    set_kind("binary")
    add_files("src/*.f90")

更多代码例子可以到这里查看:Fortran Examples

Zig语言实验性支持

注:目前这个语言xmake还在试验性支持阶段,还很不完善,比如:windows上不支持,linux/macOS下动态库编译还不支持,请自行评估使用。

我们可以通过下面的配置方式,尝试性体验下,至少linux/macOS下console和static library程序还是可以跑的。

add_rules("mode.debug", "mode.release")

target("test")
    set_kind("binary")
    add_files("src/*.zig")

至于为啥windows不支持呢,详情见我之前提给zig的issues,#5825

而动态库不支持,也是因为我躺了一些坑(zig生成的动态库会自动追加.0.0.0),详情见:issue 5827

另外还躺了下其他坑,个人感觉坑有点多,所以我暂时还是试验阶段,等过段时间再看看。

更多例子见:Zig Examples

Go依赖包和交叉编译支持

新版本xmake对go构建支持继续做了一些改进,比如对go的交叉编译也进行了支持,例如我们可以在macOS和linux上编译windows程序:

$ xmake f -p windows -a x86

另外,新版本对go的第三方依赖包管理也进行了初步支持:

add_rules("mode.debug", "mode.release")

add_requires("go::github.com/sirupsen/logrus", {alias = "logrus"})
add_requires("go::golang.org/x/sys/internal/unsafeheader", {alias = "unsafeheader"})
if is_plat("windows") then
    add_requires("go::golang.org/x/sys/windows", {alias = "syshost"})
else
    add_requires("go::golang.org/x/sys/unix", {alias = "syshost"})
end

target("test")
    set_kind("binary")
    add_files("src/*.go")
    add_packages("logrus", "syshost", "unsafeheader")

不过还有一些不完善的地方,比如目前必须手动配置所有级联依赖包,会稍微繁琐些,后续有待改进。

更多例子见:Go Examples

Dlang/Dub依赖包支持

xmake对dlang的dub包管理也进行了支持,可以快速集成dlang的第三方依赖包:

add_rules("mode.debug", "mode.release")

add_requires("dub::log 0.4.3", {alias = "log"})
add_requires("dub::dateparser", {alias = "dateparser"})
add_requires("dub::emsi_containers", {alias = "emsi_containers"})
add_requires("dub::stdx-allocator", {alias = "stdx-allocator"})
add_requires("dub::mir-core", {alias = "mir-core"})

target("test")
    set_kind("binary")
    add_files("src/*.d")
    add_packages("log", "dateparser", "emsi_containers", "stdx-allocator", "mir-core")

cl.exe新的头文件依赖文件支持

msvc的头文件依赖通常需要解析/showIncludes的输出内容,提取里面的includes文件列表来处理依赖编译问题,但是呢,cl.exe对这个的输出做的很不好,includes信息和编译输出是混在一起的。

对构建工具处理依赖解析非常不友好,尤其是多语言环境下,如何判断是includes,需要通过前置的Note: including file: 字符串来判断提取,但中文下,又是注意: 包含文件:
如果换成日语环境,又是日文的前缀字符串,编码格式问题、硬编码问题导致解析处理上,总归不是很完美。

关于这一点,最新的vs2019预览版中,微软终于对齐做了改进,通过新的/sourceDependencies xxx.json编译选项,可以更好的输出includes依赖信息,方便多语言环境下的解析提取。

另外,这个新选项的输出是独立到单独的json文件中去的,终于不是跟编译输出混一起了,也终于不用痛苦地解析分离编译错误、警告信息、includes列表信息了。

输出内容大概长这样:

{
    "Version": "1.0",
    "Data": {
        "Source": "z:\\personal\\tbox\\src\\tbox\\tbox.c",
        "Includes": [
            "z:\\personal\\tbox\\src\\tbox\\tbox.h",
            "z:\\personal\\tbox\\src\\tbox\\prefix.h",
            "z:\\personal\\tbox\\src\\tbox\\prefix\\prefix.h",
            "z:\\personal\\tbox\\src\\tbox\\prefix\\config.h",
            "z:\\personal\\tbox\\src\\tbox\\config.h",
            ...

而新版本中,xmake通过新增内置的core.base.json模块处理json解析,很方便地对新的头文件依赖数据进行解析和支持,优先使用此模式(如果cl是新版本支持的话,老版本cl还是使用/showIncludes)。

Xcode插件生成支持

目前,我们还没有时间去自己实现xcode工程的生成,但不代表不支持,因为xmake支持生成cmakelists.txt文件,而cmake是支持xcode工程文件生成的,在官方还没有实现之前,
我们也可以通过cmake变相支持它,xmake会自动内部调用cmake中转下生成结果,对用户而言使用上没啥区别,只需要确保cmake已经安装即可:

$ xmake project -k xcode

!> 等之后有时间,我们会重新自己实现各更加完善的xcode输出插件,也欢迎大家帮忙贡献。

xmake-vscode插件intellisense支持

近期,我们也更新了下xmake-vscode插件,通过自动生成compile_commands.json到当前项目的.vscode目录下,然后我们只需要配置.vscode/c_cpp_properties.json在里面关联上这个.vscode/compile_commands.json路径
就能实现intellisense自动提示,同步xmake.lua里面的includedirs等配置信息。

至于,具体怎么生成c_cpp_properties,官方文档里面有详细说明:https://code.visualstudio.com...

里面的主要配置项:

  "configurations": [
    {
      "compileCommands": ".vscode/compile_commands.json",
    }
  ],

更新内容

新特性

  • 添加xcode工程生成器插件,xmake project -k cmake (当前采用cmake生成)
  • #870: 支持gfortran编译器
  • #887: 支持zig编译器
  • #893: 添加json模块
  • #898: 改进golang项目构建,支持交叉编译
  • #275: 支持go包管理器去集成第三方go依赖包
  • #581: 支持dub包管理器去集成第三方dlang依赖包

改进

  • #868: 支持新的cl.exe的头文件依赖输出文件格式,/sourceDependencies xxx.json
  • #902: 改进交叉编译工具链

https://tboox.org/cn/2020/07/...

查看原文

赞 0 收藏 0 评论 0

waruqi 分享了头条 · 7月21日

xmake是一个基于Lua的轻量级现代化c/c++的项目构建工具,主要特点是:语法简单易上手,提供更加可读的项目维护,实现跨平台行为一致的构建体验。 本文主要详细讲解下,如何通过添加自定义的脚本,在脚本域实现更加复杂灵活的定制。

赞 0 收藏 0 评论 0

waruqi 分享了头条 · 6月8日

为了让xmake更好得支持交叉编译,这个版本我重构了整个工具链,使得工具链的切换更加的方便快捷,并且现在用户可以很方便地在xmake.lua中扩展自己的工具链。 关于平台的支持上,我们新增了对*BSD系统的支持,另外,此版本还新增了一个ninja主题风格,实现类似ninja的...

赞 0 收藏 0 评论 0

waruqi 发布了文章 · 3月29日

xmake v2.3.2 发布, 带来和ninja一样快的构建速度

这个版本重点重构优化了下内部并行构建机制,实现多个target间源文件的并行编译,以及并行link的支持,同时优化了xmake的一些内部损耗,修复影响编译速度的一些bug。
通过测试对比,目前的整体构建速度基本跟ninja持平,相比cmake/make, meson/ninja都快了不少,因为它们还额外多了一步生成makefile/build.ninja的过程。

另外,xmake还增加了对sdcc编译工具链的支持,用于编译51/stm8等嵌入式程序。

一些优化点

  1. 多个target间所有源文件同时并行构建(之前不能跨target,中途会被link给堵住串行化)
  2. 多个无依赖的target的link可以并行执行(之前只能挨个执行link)
  3. 修复之前的任务调度bug,更加细粒度化调度,充分利用cpu core资源
  4. 优化xmake内部api上的一些损耗,这块效果也很明显

更多优化细节可以看下:issue #589

构建速度对比

我们在termux和macOS上做了一些对比测试,测试工程在: xmake-core

对于相对比较多的target的项目,新版xmake对其构建速度的提升更加明显。

多任务并行编译测试

构建系统Termux (8core/-j12)构建系统MacOS (8core/-j12)
xmake24.890sxmake12.264s
ninja25.682sninja11.327s
cmake(gen+make)5.416s+28.473scmake(gen+make)1.203s+14.030s
cmake(gen+ninja)4.458s+24.842scmake(gen+ninja)0.988s+11.644s

单任务编译测试

构建系统Termux (-j1)构建系统MacOS (-j1)
xmake1m57.707sxmake39.937s
ninja1m52.845sninja38.995s
cmake(gen+make)5.416s+2m10.539scmake(gen+make)1.203s+41.737s
cmake(gen+ninja)4.458s+1m54.868scmake(gen+ninja)0.988s+38.022s

更新内容

新特性

  • 添加powershell色彩主题用于powershell终端下背景色显示
  • 添加xmake --dry-run -v命令去空运行构建,仅仅为了查看详细的构建命令
  • #712: 添加sdcc平台,并且支持sdcc编译器

改进

  • #589: 改进优化构建速度,支持跨目标间并行编译和link,编译速度和ninja基本持平
  • 改进ninja/cmake工程文件生成器插件
  • #728: 改进os.cp支持保留源目录结构层级的递归复制
  • #732: 改进find_package支持查找homebrew/cmake安装的包
  • #695: 改进采用android ndk最新的abi命名

Bugs修复

  • 修复windows下link error显示问题
  • #718: 修复依赖包下载在多镜像时一定概率缓存失效问题
  • #722: 修复无效的包依赖导致安装死循环问题
  • #719: 修复windows下主进程收到ctrlc后,.bat子进程没能立即退出的问题
  • #720: 修复compile_commands生成器的路径转义问题
查看原文

赞 2 收藏 1 评论 0

waruqi 发布了文章 · 2019-12-22

xmake v2.2.9 发布, 新增c++20 modules的实验性支持

这个版本没啥太大新特性,主要对c++20 modules进行了实验性支持,目前支持clang/msvc编译器,除此之外改进了不少使用体验,并且提高了一些稳定性。

另外,这个版本新增了socket.io支持以及对应协程io的调度支持,为下个版本的远程编译,以及后续的分布式编译做准备。

新特性介绍

c++20 modules

c++ modules已经正式纳入了c++20草案,msvc和clang也已经基本实现了对modules-ts的支持,随着c++20的脚步离我们越来越近,xmake也开始对c++modules提前做好了支持。

目前xmake已经完全支持了msvc/clang的modules-ts构建实现,而对于gcc,由于它的cxx-modules分支还在开发中,还没有正式进入master,我看了下里面的changelog,相关flags还在不断变动,感觉还没稳定下来,因此这里暂时还没对其进行支持。

关于xmake对c++modules的相关进展见:https://github.com/xmake-io/xmake/pull/569

Hello Module

关于c++modules的相关介绍我就不多说了,这边主要还是介绍下xmake下如何去构建c++modules项目,我们先来看一个简单的例子:

target("hello")
    set_kind("binary")
    add_files("src/*.cpp", "src/*.mpp") 

上面是一个支持构建c++modules文件的xmake.lua描述,其中hello.mpp就是模块文件:

#include <cstdio>
export module hello;
using namespace std;

export namespace hello {
    void say(const char* str) {
        printf("%s\n", str);
    }
}

而main.cpp是使用了hello模块的主程序:

import hello;

int main() {
    hello::say("hello module!");
    return 0;
}

接下来我们执行xmake来构建下这个程序吧:

ruki:hello ruki$ xmake 
[  0%]: ccache compiling.release src/hello.mpp
[ 50%]: ccache compiling.release src/main.cpp
[100%]: linking.release hello
build ok!

是不是非常简单,xmake内部会去处理所有细节逻辑,对于开发者而言,仅仅是添加了模块文件*.mpp作为源文件而已。

模块接口文件

上文所述的*.mpp是xmake推荐的模块接口文件命名,其实各家编译器对于模块文件的默认后缀名都是不统一的,clang下是*.cppm,而msvc下是*.ixx,这对于编写跨编译器统一的模块项目是非常不友好的,
因此这里参考了build2里面的推荐方式,采用统一的*.mpp后缀,来规范xmake下模块项目接口的命令。

当然,这也支持xmake推荐命名方式,而对于*.ixx, *.cppm等后缀名,xmake也是完全兼容支持的,也可以直接添加到add_files中去。

其他例子

xmake项目下还内置了不少跟c++modules相关的工程examples,有兴趣的同学可以参考下:c++module examples

set_toolchain接口改动

set_toolchain这个接口主要用于针对target设置不同的编译工具链,2.2.9之前的版本其实有add_toolsset_tools两个接口来处理相同的事情,不过这两接口命名和使用上和规范不是很一致,因此做了些调整改动,用这个set_toolchain新接口更好的设置工具链。

对于add_files("*.c")添加的源码文件,默认都是会调用系统最匹配的编译工具去编译,或者通过xmake f --cc=clang命令手动去修改,不过这些都是全局影响所有target目标的。

如果有些特殊需求,需要对当前工程下某个特定的target目标单独指定不同的编译器、链接器或者特定版本的编译器,这个时候此接口就可以排上用途了,例如:

target("test1")
    add_files("*.c")

target("test2")
    add_files("*.c")
    set_toolchain("cc", "$(projectdir)/tools/bin/clang-5.0")

上述描述仅对test2目标的编译器进行特殊设置,使用特定的clang-5.0编译器来编译test2,而test1还是使用默认设置。

对于一些编译器文件名不规则,导致xmake无法正常识别处理为已知的编译器名的情况下,我们也可以加一个工具名提示,例如:

set_toolchain("cc", "gcc@$(projectdir)/tools/bin/mipscc.exe")

上述描述设置mipscc.exe作为c编译器,并且提示xmake作为gcc的传参处理方式进行编译。

socket io

这块的接口初步已经实现,支持lua协程的io调度,实现高并发的io读写(后期还会同时支持进程、pipe的调度支持),目前主要用于xmake自身的使用,用于为后续的远程编译和分布式编译做准备,所以暂时不开放用户自己使用,不过等后续完善后,会开放出来,用户也可以在自己的插件里面通过socket io做一些服务程序。

不过可能用户用到的场景不是很多,毕竟xmake只是个构建工具,很少会让用户自己去做io通信。

更新内容

新特性

  • #569: 增加对c++模块的实验性支持
  • 添加xmake project -k xmakefile生成器
  • 620: 添加全局~/.xmakerc.lua配置文件,对所有本地工程生效.
  • 593: 添加core.base.socket模块,为下一步远程编译和分布式编译做准备。

改进

  • #563: 重构构建逻辑,将特定语言的构建抽离到独立的rules中去
  • #570: 改进Qt构建,将qt.application拆分成qt.widgetappqt.quickapp两个构建规则
  • #576: 使用set_toolchain替代add_toolsset_tools,解决老接口使用歧义,提供更加易理解的设置方式
  • 改进xmake create创建模板工程
  • #589: 改进默认的构建任务数,充分利用cpu core来提速整体编译速度
  • #598: 改进find_package支持在macOS上对.tbd系统库文件的查找
  • #615: 支持安装和使用其他arch和ios的conan包
  • #629: 改进hash.uuid并且实现uuid v4
  • #639: 改进参数解析器支持-jN风格传参

Bugs修复

  • #567: 修复序列化对象时候出现的内存溢出问题
  • #566: 修复安装远程依赖的链接顺序问题
  • #565: 修复vcpkg包的运行PATH设置问题
  • #597: 修复xmake require安装包时间过长问题
  • #634: 修复mode.coverage构建规则,并且改进flags检测

https://tboox.org/cn/2019/12/...

个人主页
个人项目
查看原文

赞 0 收藏 0 评论 0

waruqi 发布了文章 · 2019-12-13

xmake从入门到精通10:多个子工程目标的依赖配置

xmake是一个基于Lua的轻量级现代化c/c++的项目构建工具,主要特点是:语法简单易上手,提供更加可读的项目维护,实现跨平台行为一致的构建体验。

本文主要详细讲解下,如果在一个项目中维护和生成多个目标文件的生成,以及它们之间的依赖关系设置。

target到底是什么?

xmake的概念定义里,一个独立的项目工程可能会有多个子工程组织在一起,每个子工程对应只能生成一个唯一的目标文件,例如:可执行程序,静态库或者动态库等。

而这里所说的每个子工程就是xmake里面所说的target,字面意思就是目标子工程

因此每个子工程,我们都可以通过新增一个target在xmake.lua里面维护,例如:

target("test1")
    set_kind("binary")
    add_files("src/test1/*.c")
    
target("test2")
    set_kind("binary")
    add_files("src/test2/*.c")    

上面我们就定义了两个独立的子工程目标,编译时候会生成两个互不依赖的可执行文件。

从根域继承全局设置

暂时先不谈target间的依赖问题,如果我们有许多通用设置,每个target下都得设置一遍,那会非常冗余,也不好维护。

因此,我们可以把这些配置移到target域的外面,也就是根作用域中去设置,这样对当前xmake.lua以及所有子xmake.lua中的target都会生效,例如:

add_links("tbox")
add_linkdirs("lib")
add_includedirs("include")

target("test1")
    set_kind("binary")
    add_files("src/test1/*.c")
    
target("test2")
    set_kind("binary")
    add_files("src/test2/*.c")    

比如这两target都需要链接tbox库,放置在外层根域设置,test1和test2都能加上对应links。

目标间的依赖设置

那如果某个target需要用到另外一个tatget生成的静态库,应该怎么配置呢?

一种方式就是通过add_linkdirsadd_links手动指定对应target最后生成的目录库所在目录,然后把链接加上。

target("foo")
    set_kind("static")
    add_files("foo/*.c")
    add_defines("FOO")

target("test1")
    set_kind("binary")
    add_includedirs("foo/inc")
    add_links("foo")
    add_linkdirs("$(buildir)")
    add_files("test1/*.c")
    add_defines("FOO")
    
target("test2")
    set_kind("binary")
    add_includedirs("foo/inc")
    add_links("foo")
    add_linkdirs("$(buildir)")
    add_files("test2/*.c")
    add_defines("FOO")

上述配置中,test1和test2都会用到libfoo库,并且需要获取到libfoo库的头文件路径,库路径和链接,并且在使用过程中还需要额外设置-DFOO宏定义开关才行。

看上去没啥,其实这么写有两个问题:

  1. test目标和另外两个库目标之间是有编译顺序依赖的,如果test先编译就会提示链接库找不到
  2. 配置太过繁琐不好维护,test1和test2有很多冗余配置

那有没有更加简单可靠的配置方式呢,其实我们只需要add_deps来对target间配置上依赖关系即可。

target("foo")
    set_kind("static")
    add_files("*.c")
    add_defines("FOO", {public = true})
    add_includedirs("foo/inc", {public = true})

target("test1")
    set_kind("binary")
    add_deps("foo")
    add_files("test1/*.c")
    
target("test2")
    set_kind("binary")
    add_deps("foo")
    add_files("test2/*.c")

对比下,test1和test2的配置,是不是精简了好多?仅仅通过add_deps("foo")就继承了libfoo的所有导出设置:linkdirs, links, includedirs以及defines

其中target自身生成的库默认就会自动导出链接设置,而includedirs和defines通过设置public属性,我们也将它们标记为导出,这样可以被test目标继承到。

并且,现在有了依赖关系,xmake在编译的时候,会自动处理这些target之间的编译顺序,保证不会出现链接的时候,libfoo库还没有生成的问题。

依赖继承的进一步解析

级联依赖继承

根据上文所说,target会自动继承依赖目标中的配置和属性,不需要额外调用add_links, add_linkdirsadd_rpathdirs等接口去关联依赖目标了。

并且继承关系是支持级联的,例如:

target("library1")
    set_kind("static")
    add_files("*.c")
    add_includedirs("inc") -- 默认私有头文件目录不会被继承
    add_includedirs("inc1", {public = true}) -- 此处的头文件相关目录也会被继承

target("library2")
    set_kind("static")
    add_deps("library1")
    add_files("*.c")

target("test")
    set_kind("binary")
    add_deps("library2")

上面的配置中,test依赖library2,然后library2又依赖library1,那么通过add_deps仅仅添加library2的依赖,test就可以完整继承整个依赖链上的所有导出设置。

禁用默认的继承行为

那如果我们不想继承依赖target的任何配置,如何操作呢?

add_deps("dep1", "dep2", {inherit = false})

通过显式设置inherit配置,来告诉xmake,这两个依赖的配置是否需要被继承,如果不设置,默认就是启用继承的。

可继承的导出属性详解

上文,我们还通过 add_includedirs("inc1", {public = true}), 设置public为true, 将includedirs的设置公开给其他依赖的子target继承。

目前对于target的编译链接flags相关接口设置,都是支持继承属性的,可以人为控制是否需要导出给其他target来依赖继承,目前支持的属性有:

属性描述
private默认设置,作为当前target的私有配置,不会被依赖的其他target所继承
public公有配置,当前target,依赖的子target都会被设置
interface接口设置,仅被依赖的子target所继承设置,当前target不参与

这个其实参考借鉴了cmake的设计,目前xmake中只要跟target相关的所有编译链接设置接口,都是支持可见性导出的,例如:add_includedirs, add_defines, add_cflags等等。

关于这块的详细信息,可以看下:https://github.com/xmake-io/x...

原文:https://tboox.org/cn/2019/12/...

个人主页
个人项目
查看原文

赞 0 收藏 0 评论 0

waruqi 发布了文章 · 2019-12-08

xmake从入门到精通9:交叉编译详解

xmake是一个基于Lua的轻量级现代化c/c++的项目构建工具,主要特点是:语法简单易上手,提供更加可读的项目维护,实现跨平台行为一致的构建体验。

除了win, linux, macOS平台,以及android, ios等移动端平台的内建构建支持,xmake也支持对各种其他工具链的交叉编译支持,本文我们将会详细介绍下如何使用xmake进行交叉编译。

交叉编译工具链简介

通常,如果我们需要在当前pc环境编译生成其他设备上才能运行的目标文件时候,就需要通过对应的交叉编译工具链来编译生成它们,比如在win/macos上编译linux的程序,或者在linux上编译其他嵌入式设备的目标文件等。

通常的交叉编译工具链都是基于gcc/clang的,大都具有类似如下的结构:

/home/toolchains_sdkdir
   - bin
       - arm-linux-armeabi-gcc
       - arm-linux-armeabi-ld
       - ...
   - lib
       - libxxx.a
   - include
       - xxx.h

每个工具链都有对应的include/lib目录,用于放置一些系统库和头文件,例如libc, stdc++等,而bin目录下放置的就是编译工具链一系列工具。例如:

arm-linux-armeabi-ar
arm-linux-armeabi-as
arm-linux-armeabi-c++
arm-linux-armeabi-cpp
arm-linux-armeabi-g++
arm-linux-armeabi-gcc
arm-linux-armeabi-ld
arm-linux-armeabi-nm
arm-linux-armeabi-strip

其中arm-linux-armeabi-前缀就是cross,通过用来标示目标平台和架构,主要用于跟主机自身的gcc/clang进行区分。

里面的gcc/g++就是c/c++的编译器,通常也可以作为链接器使用,链接的时候内部会去调用ld来链接,并且自动追加一些c++库。
cpp是预处理器,as是汇编器,ar用于生成静态库,strip用于裁剪掉一些符号信息,使得目标程序会更加的小。nm用于查看导出符号列表。

自动探测和编译

如果我们的交叉编译工具链是上文的结构,xmake会自动检测识别这个sdk的结构,提取里面的cross,以及include/lib路径位置,用户通常不需要做额外的参数设置,只需要配置好sdk根目录就可以编译了,例如:

$ xmake f -p cross --sdk=/home/toolchains_sdkdir
$ xmake

其中,-p cross用于指定当前的平台是交叉编译平台,--sdk=用于指定交叉工具链的根目录。

注:我们也可以指定-p linux平台来配置交叉编译,效果是一样的,唯一的区别是额外标识了linux平台名,方便xmake.lua里面通过is_plat("linux")来判断平台。

这个时候,xmake会去自动探测gcc等编译器的前缀名cross:arm-linux-armeabi-,并且编译的时候,也会自动加上链接库头文件的搜索选项,例如:

-I/home/toolchains_sdkdir/include 
-L/home/toolchains_sdkdir/lib

这些都是xmake自动处理的,不需要手动配置他们。

手动配置编译

如果上面的自动检测对某些工具链,还无法完全通过编译,就需要用户自己手动设置一些交叉编译相关的配置参数,来调整适应这些特殊的工具链了,下面我会逐一讲解如何配置。

设置工具链bin目录

对于不规则工具链目录结构,靠单纯地--sdk选项设置,没法完全检测通过的情况下,可以通过这个选项继续附加设置工具链的bin目录位置。

例如:一些特殊的交叉工具链的,编译器bin目录,并不在 /home/toolchains_sdkdir/bin 这个位置,而是独立到了 /usr/opt/bin

这个时候,我们可以在设置了sdk参数的基础上追加bin目录的参数设置,来调整工具链的bin目录。

$ xmake f -p linux --sdk=/home/toolchains_sdkdir --bin=/usr/opt/bin
$ xmake

设置交叉工具链工具前缀

像aarch64-linux-android-这种,通常如果你配置了--sdk或者--bin的情况下,xmake会去自动检测的,不需要自己手动设置。

但是对于一些极特殊的工具链,一个目录下同时有多个cross前缀的工具bin混在一起的情况,你需要手动设置这个配置,来区分到底需要选用哪个bin。

例如,toolchains的bin目录下同时存在两个不同的编译器:

/opt/bin
  - armv7-linux-gcc 
  - aarch64-linux-gcc

我们现在想要选用armv7的版本,那么我们可以追加--cross=配置编译工具前缀名,例如:

$ xmake f -p linux --sdk=/usr/toolsdk --bin=/opt/bin --cross=armv7-linux-

设置c/c++编译器

如果还要继续细分选择编译器,则继续追加相关编译器选项,例如:

$ xmake f -p linux --sdk=/user/toolsdk --cc=armv7-linux-clang --cxx=armv7-linux-clang++

当然,我们也可以指定编译器全路径。

--cc用于指定c编译器名,--cxx用于指定c++编译器名。

注:如果存在CC/CXX环境变量的话,会优先使用当前环境变量中指定的值。

如果指定的编译器名不是那些xmake内置可识别的名字(带有gcc, clang等字样),那么编译器工具检测就会失败。

这个时候我们可以通过:

xmake f --cxx=clang++@/home/xxx/c++mips.exe

设置c++mips.exe编译器作为类clang++的使用方式来编译。

也就是说,在指定编译器为c++mips.exe的同时,告诉xmake,它跟clang++用法和参数选项基本相同。

设置c/c++连接器

如果还要继续细分选择链接器,则继续追加相关链接器选项,例如:

$ xmake f -p linux --sdk=/user/toolsdk --ld=armv7-linux-clang++ --sh=armv7-linux-clang++ --ar=armv7-linux-ar

ld指定可执行程序链接器,sh指定共享库程序链接器,ar指定生成静态库的归档器。

注:如果存在LD/SH/AR环境变量的话,会优先使用当前环境变量中指定的值。

设置头文件和库搜索目录

如果sdk里面还有额外的其他include/lib目录不在标准的结构中,导致交叉编译找不到库和头文件,那么我们可以通过--includedirs--linkdirs来追加搜索路径,然后通过--links添加额外的链接库。

$ xmake f -p linux --sdk=/usr/toolsdk --includedirs=/usr/toolsdk/xxx/include --linkdirs=/usr/toolsdk/xxx/lib --links=pthread

注:如果要指定多个搜索目录,可以通过:或者;来分割,也就是不同主机平台的路径分隔符,linux/macos下用:,win下用;

设置编译和链接选项

我们也可以根据实际情况通过--cflags, --cxxflags--ldflags--shflags--arflags额外配置一些编译和链接选项。

  • cflags: 指定c编译参数
  • cxxflags:指定c++编译参数
  • cxflags: 指定c/c++编译参数
  • asflags: 指定汇编器编译参数
  • ldflags: 指定可执行程序链接参数
  • shflags: 指定动态库程序链接参数
  • arflags: 指定静态库的生成参数

例如:

$ xmake f -p linux --sdk=/usr/toolsdk --cflags="-DTEST -I/xxx/xxx" --ldflags="-lpthread"

mingw工具链

使用mingw工具链编译,其实也是交叉编译,但是由于这个比较常用,xmake专门增加了一个mingw的平台来快速处理使用mingw工具链的编译。

因此,xmake对mingw的工具链检测会更加完善,在macos下,基本上连sdk路径都不需要配置,也能直接检测到,只需要切到mingw平台编译即可。

$ xmake f -p mingw
$ xmake -v
configure
{
    ld = /usr/local/opt/mingw-w64/bin/x86_64-w64-mingw32-g++
    ndk_stdcxx = true
    plat = mingw
    mingw = /usr/local/opt/mingw-w64
    buildir = build
    arch = x86_64
    xcode = /Applications/Xcode.app
    mode = release
    cxx = /usr/local/opt/mingw-w64/bin/x86_64-w64-mingw32-gcc
    cross = x86_64-w64-mingw32-
    theme = default
    kind = static
    ccache = true
    host = macosx
    clean = true
    bin = /usr/local/opt/mingw-w64/bin
}
[  0%]: ccache compiling.release src/main.cpp
/usr/local/bin/ccache /usr/local/opt/mingw-w64/bin/x86_64-w64-mingw32-gcc -c -fvisibility=hidden -O3 -m64 -o build/.objs/test/mingw/x86_64/release/src/main.cpp.obj src/main.cpp
[100%]: linking.release test.exe
/usr/local/opt/mingw-w64/bin/x86_64-w64-mingw32-g++ -o build/mingw/x86_64/release/test.exe build/.objs/test/mingw/x86_64/release/src/main.cpp.obj -s -fvisibility=hidden -m64
build ok!

这里我们追加了-v参数,看了下详细的编译命令和检测到的mingw工具链配置值,其中cross被自动检测为:x86_64-w64-mingw32-,bin目录也被自动检测到了,还有编译器和链接器也是。

尽管在linux/win上还没法自动检测到sdk路径,我们也可以手动指定sdk路径,需要注意的是,xmake为mingw专门提供了一个--mingw=参数用来指定mingw的工具链根目录,其效果跟--sdk=是一样的,但是它可以作为全局配置被设置。

$ xmake g --mingw=/home/mingwsdk
$ xmake f -p mingw
$ xmake

我们通过xmake g/global命令设置--mingw根目录到全局配置后,之后每次编译和切换编译平台,就不用额外指定mingw工具链路径了,方便使用。

另外,其他的工具链配置参数用法,跟上文描述的没什么区别,像--cross, --bin=等都可以根据实际的环境需要,自己控制是否需要额外追加配置来适配自己的mingw工具链。

项目描述设置

set_toolchain

如果觉得每次通过命令行配置比较繁琐,有些配置可以通过在xmake.lua预先配置好,来简化命令配置,比如编译器的指定,就可以通过set_toolchain来对每个target单独设置。

target("test")
    set_kind("binary")
    set_toolchain("cxx", "clang")
    set_toolchain("ld", "clang++")

强制test目标的编译器和链接器使用clang编译器,或者指定交叉编译工具链中的编译器名或者路径。

set_config

我们也可以通过set_config来设置在xmake f/config命令中的每个配置参数的默认值,这是个全局api,对每个target都会生效。

set_config("cflags", "-DTEST")
set_config("sdk", "/home/xxx/tooksdk")
set_config("cc", "gcc")
set_config("ld", "g++")

不过,我们还是可以通过xmake f --name=value的方式,去修改xmake.lua中的默认配置。

自定义编译平台

如果某个交叉工具链编译后目标程序有对应的平台需要指定,并且需要在xmake.lua里面根据不同的交叉编译平台,还需要配置一些额外的编译参数,那么上文的-p cross设置就不能满足需求了。

其实,-p/--plat=参数也可以设置为其他自定义的值,只需要跟is_plat保持对应关系就可以,所有非内置平台名,都会默认采用交叉编译模式,例如:

$ xmake f -p myplat --sdk=/usr/local/arm-xxx-gcc/
$ xmake

我们传入了myplat自定义平台名,作为当前交叉工具链的编译平台,然后xmake.lua里面我们对这个平台,配置下对应的设置:

if is_plat("myplat") then
    add_defines("TEST")
end

通过这种方式,xmake就可以很方便的扩展处理各种编译平台,用户可以自己扩展支持freebsd, netbsd, sunos等其他各种平台的交叉编译。

我摘录一段之前移植libuv写的交叉编译的配置,直观感受下:

-- for gragonfly/freebsd/netbsd/openbsd platform
if is_plat("gragonfly", "freebsd", "netbsd", "openbsd") then
    add_files("src/unix/bsd-ifaddrs.c")
    add_files("src/unix/freebsd.c")
    add_files("src/unix/kqueue.c")
    add_files("src/unix/posix-hrtime.c")
    add_headerfiles("(include/uv-bsd.h)")
end 

-- for sunos platform
if is_plat("sunos") then
     add_files("src/unix/no-proctitle.c")
    add_files("src/unix/sunos.c")
    add_defines("__EXTENSIONS_", "_XOPEN_SOURCE=600")
    add_headerfiles("(include/uv-sunos.h)")
end

然后,我们就可以切换这些平台来编译:

$ xmake f -p [gragonfly|freebsd|netbsd|openbsd|sunos] --sdk=/home/arm-xxx-gcc/
$ xmake

另外,内置的linux平台也是支持交叉编译的哦,如果不想配置其他平台名,统一作为linux平台来交叉编译,也是可以的。

$ xmake f -p linux --sdk=/usr/local/arm-xxx-gcc/
$ xmake

只要设置了--sdk=等参数,就会启用linux平台的交叉编译模式。

个人主页
个人项目
查看原文

赞 2 收藏 1 评论 0

认证与成就

  • 获得 31 次点赞
  • 获得 13 枚徽章 获得 1 枚金徽章, 获得 2 枚银徽章, 获得 10 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

  • xmake

    跨平台自动构建工具

  • tbox

    轻量级跨平台c开发库

  • gbox

    轻量级跨平台c矢量渲染库

注册于 2014-12-15
个人主页被 3.8k 人浏览