awtk/docs/how_to_use_3rd_libs.md

188 lines
6.3 KiB
Markdown
Raw Normal View History

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=1SConstruct 脚本代码如下,其他两个函数用法也是类似的:
```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)