2020-11-24 09:28:40 +08:00
|
|
|
|
# 如何引用第三方库
|
|
|
|
|
|
2023-01-29 17:38:58 +08:00
|
|
|
|
本文基于 AWTK 模板工程介绍如何在 SCons 编译脚本中引用第三方库。
|
2020-11-24 09:28:40 +08:00
|
|
|
|
|
2023-01-29 17:38:58 +08:00
|
|
|
|
> 注:这里所说的 AWTK 模板工程指 AWTK Designer 创建的常规工程,工程目录下有一个 SConstruct 文件,它是 SCons 编译脚本,遵顼 Python 语法,下文中的操作基本都通过编辑该文件实现。
|
|
|
|
|
|
|
|
|
|
## 1 引用第三方库的源码文件
|
|
|
|
|
|
|
|
|
|
如果第三方库提供的是源码文件,那么通常我们需要做以下两件事:
|
|
|
|
|
|
|
|
|
|
1. 将第三方库源码的头文件路径添加到工程中,方便编译时能找到库中的函数声明。
|
|
|
|
|
2. 把源码文件加入工程编译,方便链接时能找到库中的函数定义。
|
|
|
|
|
|
|
|
|
|
假设此处有一个名为 xxx 的第三方库,它提供了 xxx.h 和 xxx.c 两个文件,按照约定的规则,我们将它放在 AWTK 工程的 3rd/xxx 目录中,结构如下:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
3rd
|
|
|
|
|
xxx
|
|
|
|
|
xxx.h
|
|
|
|
|
xxx.c
|
|
|
|
|
...
|
|
|
|
|
SConstruct
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 1.1 添加头文件路径
|
|
|
|
|
|
|
|
|
|
在工程的 SConstruct 脚本文件中调用 helper.add_cpppath 函数添加库的头文件路径,传入参数为数组,此处的路径为:工程目录/3rd/xxx,如果有其他路径也可以在数组中添加新的元素,代码如下:
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
# SConstruct
|
|
|
|
|
import os
|
|
|
|
|
import scripts.app_helper as app
|
|
|
|
|
|
|
|
|
|
...
|
|
|
|
|
|
|
|
|
|
# 构建 xxx 库的头文件路径:工程目录/3rd/xxx
|
|
|
|
|
XXX_PATH = [os.path.join(helper.APP_ROOT, '3rd', 'xxx')]
|
|
|
|
|
# 添加头文件路径,并链式调用 call 函数同步数据
|
|
|
|
|
helper.add_cpppath(XXX_PATH).call(DefaultEnvironment)
|
|
|
|
|
|
|
|
|
|
SConscriptFiles = ['src/SConscript', 'tests/SConscript']
|
|
|
|
|
helper.SConscript(SConscriptFiles)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
> 注:在调用 helper.add_cpppath 函数后,需要调用 call 函数同步这些数据,call 函数支持链式调用,需要放到最后,且只需调用一次,更多 helper 对象中的相关函数请参考:[利用 app_helper 编写 SConstruct](https://github.com/zlgopen/awtk/blob/master/docs/app_helper_usage.md)。
|
|
|
|
|
|
|
|
|
|
### 1.2 把源码文件加入工程编译
|
|
|
|
|
|
|
|
|
|
在工程的 src/SConscript 脚本文件中,将 3rd/xxx 目录下的源码文件添加到 sources 数组中即可把它们编译到可执行程序中,代码如下:
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
# src/SConstruct
|
|
|
|
|
import os
|
|
|
|
|
import sys
|
|
|
|
|
import platform
|
|
|
|
|
|
|
|
|
|
...
|
|
|
|
|
|
|
|
|
|
# 添加 src 目录下的所有 .c 文件,符号 * 为通配符
|
|
|
|
|
sources = Glob('**/*.c') + Glob('*.c')
|
|
|
|
|
# 添加 3rd/xxx 目录下的所有 .c 文件
|
|
|
|
|
sources += Glob('../3rd/xxx/*.c')
|
|
|
|
|
|
|
|
|
|
# 将 sources 中的所有文件编译为 bin/demo 程序
|
|
|
|
|
env.Program(os.path.join(BIN_DIR, 'demo'), sources, LIBS = env['LIBS'])
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 1.3 扩展用法(添加预处理参数、链接参数)
|
|
|
|
|
|
|
|
|
|
在工程的 SConstruct 脚本文件中调用 helper 对象中的以下函数可以添加预处理参数、链接参数:
|
|
|
|
|
|
|
|
|
|
- add_ccflags:增加 C 预处理参数。
|
|
|
|
|
- add_cxxflags:增加 C++ 预处理参数。
|
|
|
|
|
- add_linkflags:增加链接参数。
|
|
|
|
|
|
|
|
|
|
例如此处添加 C 预处理参数(定义宏NDEBUG=1),SConstruct 脚本代码如下,其他两个函数用法也是类似的:
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
# SConstruct
|
|
|
|
|
...
|
|
|
|
|
XXX_PATH = [os.path.join(helper.APP_ROOT, '3rd', 'xxx')]
|
|
|
|
|
helper.add_cpppath(XXX_PATH).add_ccflags(' -DNDEBUG=1 ').call(DefaultEnvironment)
|
|
|
|
|
...
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 2 引用第三方库编译好的库文件
|
|
|
|
|
|
|
|
|
|
引用第三方库时,更常见的应该是直接引用编译好的库文件(动态库或静态库),此时在工程的 SConstruct 中描述依赖关系即可。具体方式为:先定义依赖描述,再调用 set_deps 将依赖描述设置到 helper 对象中。
|
|
|
|
|
|
|
|
|
|
### 2.1 常规用法
|
|
|
|
|
|
|
|
|
|
需要注意的是,使用本节方法引用第三方库时,默认按照 AWTK 约定的规则存放第三方库的代码文件和库文件,规则如下:
|
|
|
|
|
|
|
|
|
|
- 第三方库的代码文件需要放在库路径 **src** 目录中。
|
|
|
|
|
- 第三方库的动态库文件需要放在库路径的 **bin** 目录中。
|
|
|
|
|
- 第三方库的静态库文件需要放在库路径的 **lib** 目录中。
|
|
|
|
|
|
|
|
|
|
> 注:如果想自定义上述文件的路径,则需额外指定 cpppath 和 libpath 参数,详见下文。
|
|
|
|
|
|
|
|
|
|
假设此处有一个名为 xxx 的第三方库,它提供了头文件 xxx.h 和相关的库文件,按照约定的规则,我们将它放在 AWTK 工程的 3rd/xxx 目录中,结构如下:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
3rd
|
|
|
|
|
xxx
|
|
|
|
|
bin
|
|
|
|
|
xxx.dll # 动态库文件
|
|
|
|
|
xxx.lib # 动态库的导出列表
|
|
|
|
|
lib
|
|
|
|
|
xxx.lib # 静态库文件
|
|
|
|
|
src
|
|
|
|
|
xxx.h
|
|
|
|
|
...
|
|
|
|
|
SConstruct
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
在工程的 SConstruct 脚本文件中,引用动态库的方式如下:
|
2020-11-24 09:28:40 +08:00
|
|
|
|
|
|
|
|
|
```python
|
2023-01-29 17:38:58 +08:00
|
|
|
|
# SConstruct
|
|
|
|
|
...
|
2020-11-24 09:28:40 +08:00
|
|
|
|
DEPENDS_LIBS = [
|
|
|
|
|
{
|
2023-01-29 17:38:58 +08:00
|
|
|
|
"root" : '3rd/xxx', # 第三方库路径,支持绝对路径和相对路径。
|
|
|
|
|
'shared_libs': ['xxx'], # 引用的动态库名称,动态库文件必须放在 root/bin 目录下。
|
|
|
|
|
'static_libs': [] # 引用的静态库名称,静态库文件必须放在 root/lib 目录下。
|
2020-11-24 09:28:40 +08:00
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
|
2023-01-29 17:38:58 +08:00
|
|
|
|
# 设置依赖库,默认会添加以下路径:
|
|
|
|
|
# 1.头文件路径(root/src)
|
|
|
|
|
# 2.库文件路径(root/bin、root/lib)
|
2020-11-24 09:28:40 +08:00
|
|
|
|
helper.set_deps(DEPENDS_LIBS)
|
2023-01-29 17:38:58 +08:00
|
|
|
|
...
|
|
|
|
|
helper.call(DefaultEnvironment)
|
2020-11-24 09:28:40 +08:00
|
|
|
|
```
|
|
|
|
|
|
2023-01-29 17:38:58 +08:00
|
|
|
|
> 注:helper.set_deps 一定要在 helper.call 之前调用,call 函数支持链式调用,需要放到最后,且只需调用一次。
|
2021-02-24 17:12:02 +08:00
|
|
|
|
|
2023-01-29 17:38:58 +08:00
|
|
|
|
### 2.2 依赖描述参数
|
2020-11-24 09:28:40 +08:00
|
|
|
|
|
2023-01-29 17:38:58 +08:00
|
|
|
|
DEPENDS_LIBS 是一个数组,可以添加多个第三方依赖库,每个元素是一个依赖描述对象,可以指定以下参数:
|
2020-11-24 09:28:40 +08:00
|
|
|
|
|
2023-01-29 17:38:58 +08:00
|
|
|
|
- root 第三方库的根目录。建议使用相对于应用程序的相对路径。如:
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
"root" : '../awtk-mvvm',
|
2020-11-24 09:28:40 +08:00
|
|
|
|
```
|
|
|
|
|
|
2023-01-29 17:38:58 +08:00
|
|
|
|
- shared_libs 第三方库提供的动态库列表(数组),不带扩展名和 lib 前缀。如:
|
2020-11-24 09:28:40 +08:00
|
|
|
|
|
2023-01-29 17:38:58 +08:00
|
|
|
|
```python
|
2020-11-24 09:28:40 +08:00
|
|
|
|
"shared_libs" : ["a","b","c"]
|
|
|
|
|
```
|
|
|
|
|
|
2023-01-29 17:38:58 +08:00
|
|
|
|
- static_libs 第三方库提供的静态库库列表(数组),不带扩展名和 lib 前缀。如:
|
2020-11-24 09:28:40 +08:00
|
|
|
|
|
2023-01-29 17:38:58 +08:00
|
|
|
|
```python
|
2020-11-24 09:28:40 +08:00
|
|
|
|
"static_libs" : ["a","b","c"]
|
|
|
|
|
```
|
|
|
|
|
|
2023-01-29 17:38:58 +08:00
|
|
|
|
- libpath 库所在的路径,相对于前面指定的 root 路径。缺省为:["lib", "bin"]。如:
|
2020-11-24 09:28:40 +08:00
|
|
|
|
|
2023-01-29 17:38:58 +08:00
|
|
|
|
```python
|
|
|
|
|
"libpath" : ["lib", "bin"]
|
2020-11-24 09:28:40 +08:00
|
|
|
|
```
|
|
|
|
|
|
2023-01-29 17:38:58 +08:00
|
|
|
|
- cpppath 头文件所在的路径,相对于前面指定的 root 路径。缺省为:["src"]。如:
|
2020-11-24 09:28:40 +08:00
|
|
|
|
|
2023-01-29 17:38:58 +08:00
|
|
|
|
```python
|
2020-11-24 09:28:40 +08:00
|
|
|
|
"cpppath" : ["includes", "src"]
|
|
|
|
|
```
|
|
|
|
|
|
2023-01-29 17:38:58 +08:00
|
|
|
|
- cflags C 语言的预处理参数(可选)。如:
|
2020-11-24 09:28:40 +08:00
|
|
|
|
|
2023-01-29 17:38:58 +08:00
|
|
|
|
```python
|
2020-11-24 09:28:40 +08:00
|
|
|
|
"cflags" : " -DNDEBUG=1 "
|
|
|
|
|
```
|
|
|
|
|
|
2023-01-29 17:38:58 +08:00
|
|
|
|
- cxxflags C++语言的预处理参数(可选)。
|
2020-11-24 09:28:40 +08:00
|
|
|
|
|
|
|
|
|
|
2023-01-29 17:38:58 +08:00
|
|
|
|
- ccflags C/C++语言的预处理参数(可选)。
|
|
|
|
|
|
2020-11-24 09:28:40 +08:00
|
|
|
|
|
2023-01-29 17:38:58 +08:00
|
|
|
|
### 2.3 完整示例
|
2020-11-24 09:28:40 +08:00
|
|
|
|
|
2023-01-29 17:38:58 +08:00
|
|
|
|
- [awtk-mvvm-c-hello](https://github.com/zlgopen/awtk-mvvm-c-hello/blob/master/SConstruct)
|