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

本文主要详细讲解下,如何通过配置子工程模块,来组织构建一个大规模的工程项目。

  • 项目源码
  • 官方文档

维护简单的项目结构

对于一些轻量型的小工程,通常只需要单个xmake.lua文件就能搞定,大体结构如下:

projectdir- xmake.lua- src- test- *.c- demo- *.c

源码下面层级简单,通常只需要在项目根目录维护一个xmake.lua来定义所有target就能完成构建,看上去并不是很复杂,也很清晰。

-- 在根域设置通用配置,当前所有targets都会生效
add_defines("COMMON")target("test")set_kind("static")add_files("src/test/*.c")add_defines("TEST")target("demo")set_kind("static")add_files("src/demo/*.c")add_defines("DEMO")

维护复杂的项目结构

但是对于一些大型项目,通常的组织结构层次很多也很深,需要编译的target目标也可能有十几甚至上百个,这个时候如果还是都在根xmake.lua文件中维护,就有点吃不消了。

这个时候,我们就需要通过在每个子工程模块里面,单独创建xmake.lua来维护他们,然后使用xmake提供的includes接口,将他们按层级关系包含进来,最终变成一个树状结构:

projectdir- xmake.lua- src- test- xmake.lua- test1- xmake.lua- test2- xmake.lua- test3- xmake.lua- demo- xmake.lua- demo1- xmake.lua- demo2- xmake.lua...

然后,根xmake.lua会将所有子工程的xmake.lua通过层级includes全部引用进来,那么所有定义在子工程的target配置也会完全引用进来,我们在编译的时候永远不需要单独去切到某个子工程目录下操作,只需要:

$ xmake build test1
$ xmake run test3
$ xmake install demo1

就可以编译,运行,打包以及安装指定的子工程target,所以除非特殊情况,平常不推荐来回切换目录到子工程下单独编译,非常的繁琐。

根xmake.lua文件配置

通常推荐的做法就是在根xmake.lua中仅仅配置一些对所有target都通用的设置,以及includes对子工程的引用,不放置对targets的定义,例如:

-- define project
set_project("tbox")
set_xmakever("2.3.2")
set_version("1.6.5", {build = "%Y%m%d%H%M"})-- set common flags
set_warnings("all", "error")
set_languages("c99")
add_cxflags("-Wno-error=deprecated-declarations", "-fno-strict-aliasing", "-Wno-error=expansion-to-defined")
add_mxflags("-Wno-error=deprecated-declarations", "-fno-strict-aliasing", "-Wno-error=expansion-to-defined")-- add build modes
add_rules("mode.release", "mode.debug")-- includes sub-projects
includes("test", "demo")

xmake里面所有的设置都是按tree状继承的,根xmake.lua中的root域设置会对所有includes的子xmake.lua里面的targets生效, 但反过来不会,子xmake.lua里面的root域设置仅对它下面的子xmake.lua生效,不会影响到父xmake.lua中定义的targets。

子xmake.lua文件配置

所以,我们可以在每个子工程目录中,单独配置xmake.lua,里面的所有配置不会干扰父xmake.lua,只对它下面的更细粒度的子工程生效,就这样一层层按tree状生效下去。

由于,已经在根xmake.lua配置了大部分通用配置,那么我们可以在test子工程下,专心配置只对test有用的设置,例如对于projectdir/test/xmake.lua

add_defines("TEST")target("test1")set_kind("static")add_files("test1/*.c")add_defines("TEST1")target("test2")set_kind("static")add_files("test2/*.c")add_defines("TEST2")

我们可以在这里定义test的所有target,当然也可以继续分层,在每个test1, test2目录下单独维护xmake.lua,这个看自己项目的规模来决定。

比如:

add_defines("TEST")
includes("test1", "test2")

test1/xmake.lua

target("test1")set_kind("static")add_files("test1/*.c")add_defines("TEST1")

test2/xmake.lua

target("test2")set_kind("static")add_files("test2/*.c")add_defines("TEST2")

而这里面的add_defines("TEST")在root域,会对test1/test2两个target都生效,但是对于demo目录的target不生效,因为它们是平级的,没有tree状继承关系。

跨xmake.lua间目标依赖

虽然,projectdir/test/xmake.luaprojectdir/demo/xmake.lua两个子工程目录是平级关系,配置无法相互干扰,但是targets是可以跨xmake.lua访问的,来实现目标间的依赖。

比如demo需要依赖test静态库,进行链接使用,那么demo下xmake.lua可以这么写:

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

只要通过add_deps("test1")关联上对应其他子工程目标作为依赖即可,test1静态库会优先编译,并且demo可执行程序会自动link上它生成的libtest1.a库。

文件路径的层级关系

我们需要记住,所有跟路径相关的配置接口,比如add_files, add_includedirs等都是相对于当前子工程xmake.lua所在的目录的,所以只要添加的文件不跨模块,那么设置起来只需要考虑当前的相对路径就行了。

projectdir- test- xmake.lua- test1/*.c- test2/*.c

比如,这里添加的源文件路径,都是相对于test子工程目录的,我们不需要去设置绝对路径,这样会简化很多。

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

当然,如果我们有特殊需求,非要设置工程其他子模块下的文件路径呢?两种办法,通过../../的方式一层层绕出去,另外一种就是使用$(projectdir)内置变量,它表示项目全局根目录。

比如在demo子工程下:

target("demo1")set_kind("binary")add_files("demo1/*.c")add_files("../../test/test1/*.c")

或者:

target("demo1")set_kind("binary")add_files("demo1/*.c")add_files("$(projectdir)/test/test1/*.c")

includes接口使用进阶

错误的使用方式

includes这个接口属于全局接口,不隶属于任何target,所以请不要在target内部调用,下面是错误的用法:

target("test")set_kind("static")includes("test1", "test2")add_files("test/*.c")

正确的用法是:

includes("test1", "test2")
target("test")set_kind("static")add_files("test/*.c")

或者:

target("test")set_kind("static")add_files("test/*.c")
target_end()-- 在下面调用,需要先显式退出target作用域
includes("test1", "test2")

引用目录或文件

另外,includes既可以引用目录,也可以直接引用文件,如果test1目录下存在xmake.lua,那么可以直接includes("test1")来引用目录。

如果test1目录下是其他xxxx.lua命令的项目文件,可以通过指定文件来引用:includes("test1/xxxx.lua"),效果一样的。

模式匹配进行批量导入

includes还支持通过模式匹配的方式来批量导入多个子工程,比如:

includes("test/*/xmake.lua")

可以导入test目录下,所有test1, test2等子工程目录下的配置,如果是**还支持递归多级匹配

includes("test/**/xmake.lua")

通过模式匹配,我们只需要在test/xmake.lua一处地方进行includes,以后用户在新增其他子工程xmake.lua,就会自动导入进来,非常方便。

注意事项

另外,在使用includes的过程中,需要注意的一点是,它不是c语言的#include,因此在当前配置中includes子配置,当前配置是不会有任何影响的,比如:

includes("xxx")
target("test")-- ...

上面includes了一些子工程,但是这些子工程的配置是不会干扰当前test目标程序的。

https://tboox.org/cn/2020/04/11/quickstart-11-subprojects/

springtboot 引用子工程的文件_xmake从入门到精通11:如何组织构建大型工程相关推荐

  1. qt 创建文件_xmake从入门到精通2:创建和编译工程

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

  2. 关于Maven中pom文件标签的详解,分别对比父工程pom文件与子工程pom文件。

    一.介绍 这里我们以若依开源框架为例,我们先讲解,父工程pom文件,之后再讲解子工程pom文件. 首先,我们先介绍若依前后端分离项目的目录结构; 一.父工程pom.文件 父工程pom文件注释:(每个标 ...

  3. 主module不能引用子module资源文件

    问题 当项目越做越大的时候我们往往会使用组件化开发,项目整体架构与下图类似: red的颜色虽然我们是在base模块中添加的,但是在App模块中依旧可以通过com.android.app.R来引用 但是 ...

  4. canoe开发从入门到精通_xmake从入门到精通7:开发和构建Cuda程序

    xmake是一个基于Lua的轻量级现代化c/c++的项目构建工具,主要特点是:语法简单易上手,提供更加可读的项目维护,实现跨平台行为一致的构建体验. 本文我们会详细介绍下如何通过xmake来构建cud ...

  5. C#文件操作从入门到精通(1)——INI文件操作

    点击这里:微软官方文档查看writePrivateProfileString函数定义 常见错误: 1.中文路径写入失败,为啥? 2.文件不是全路径,只有文件名也会写入失败: 3.GetLastErro ...

  6. java覆盖率怎么包含多个工程,在多项目工程中统计子工程的覆盖率

    背景介绍 在前文中我们对如何在gradle编译体系的工程中加入Jacoco代码覆盖率统计的方法做了介绍,但是前文的方法仅能统计到主工程的代码覆盖率,而无法统计到库工程,其具体原因可以参考此文Issue ...

  7. Qt把已有工程添加到其他工程中作为子工程或新创建子工程

    Qt创建子工程 新建一个空工程 添加子工程 在当前工程下添加一个子工程 一个已有的qt工程,想添加到其他工程作为一个子工程,或是在当前工程中添加一个子工程,可以使用以下方法. 假设已有的工程为test ...

  8. Springboot分模块开发详解(2):建立子工程

    1.创建base-entity 选中base工程,右键创建一个新的maven工程 自动选择了base这个目录存放子工程 创建后,pom.xml修改成如下内容: <?xml version=&qu ...

  9. matlab中创建一个工程,从文件夹创建新工程

    从文件夹创建新工程 如果您有许多文件并希望将它们整理为一个工程(无论是否进行源代码管理),请按照以下步骤创建一个新工程. 使用 Simulink® Start Page 中的 Folder to Pr ...

最新文章

  1. 计算力即生产力,智算中心就是智慧时代的“发电厂” | MEET2021
  2. tuple parameter unpacking is not supported in python3
  3. Cloud for Customer的前端UI5是如何启动的
  4. linux 查询系统性能,Linux 系统各种性能查询
  5. Java之开发工具(1) - Eclipse 如何设置注释的模板
  6. 2008最新热门搞笑的50条语录
  7. 贪心算法数塔问题c语言,c语言背包问题_c语言背包问题几种解法_背包问题贪心算法(2)...
  8. ”记录集为只读“怎么解决?请高手帮忙看看。感激不尽……
  9. 联想小新14风扇一直很响怎么办
  10. 适合计算机课堂玩的游戏,学校上信息课经常玩的几个游戏,你玩过几个?(一)...
  11. 攻防世界-web- easyphp
  12. 如何备份android10,安卓手机系统怎么备份
  13. mybatis 大于等于小于等于
  14. Python 搭建 AI 健身评分系统
  15. 高斯正算C语言程序,一个老师给的高斯投影正、反算c++源码(最新整理)
  16. 利用 pinyin4j 把汉字转化为拼音
  17. python连接阿里云接口进行实名认证
  18. 类脑计算这么热,不如上了这趟车
  19. [JVM]了断局:字节码执行引擎
  20. 小米手机无法打包的解决方案

热门文章

  1. marquee 移动属性
  2. halcon学习笔记——(4)HDevelop language(结构语句)
  3. ie6 7下 relative absolute无法冲破的等级问题解决办法
  4. 解决Vue跳转到当前路由报错问题
  5. vux 修改 设置 主题 颜色
  6. sqlalchemy mysql配置中怎么设置utf8_在SqlAlchemy中,我想要一个列是UTF8?
  7. MySQL数据库事务中的行级锁,表级锁,页级锁
  8. mysql中新建不了查询语句_将excel和mysql建立链接后,如何通过在excel里面执行mysql查询语句,然后建立查询...
  9. el表达式,c标签的使用
  10. [From 1.1~1.2]CLR的执行模型