GYP搭建跨平台编译工程
Updated:
介绍
写的一手好代码固然难得,代码写好后可以方便在各个平台完成编译部署,也需要找到好的工具,GYP就是其中一个
GYP类似于CMake,用python脚本编写,最初用于Chromium项目,用来生成原生IDE文件(Visual Studio,Xcode),后面Google单独抽出来,通过编写GYP脚本,可以在不同平台下面生成对于的编译脚本或IDE工程,比如Unix平台下面的Makefile或Ninja,Windows平台下面的VS工程,IOS平台下面的Xcode工程,达到一键构建的目的
如果你现在需要开发一套跨平台的SDK,GYP绝对是一个不错的选择
GYP Vs CMake
GYP的主页有一栏专门介绍两者的区别,GYP vs. CMake
下图为本人总结的GYP和CMake五个特性之间的比较:
- 可读性:相比较于CMake的脚本瀑布式书写方式,GYP的书写方式类似于Json,可读性比较强
- 扩展性:action特性可以让GYP可以整合其他编译器,让C语言和其他语言一起一键编译;GYP也可以在任何平台上面生成任何平台的编译脚本或IDE工程,这样对项目的持续集成很方便
- 模块化:GYP以targets为书写单元,模块性很好,GYP通过dependencies属性来设置依赖的targets;CMake通过一行语句添加依赖的模块目录
- 源文件批量添加:GYP对批量添加源文件支持不好,CMake通过aux_source_directory命令轻松添加
- 流行度:CMake在很多成熟的项目中使用,也有很多配套的工具,GYP起步比较晚,主要用在Chromium项目上面,这块还需努力
简单实例
下面是一个简单的GYP脚本,通过它可以在不同的平台下面生成可my_target的可执行文件
{ |
通过下面的命令生成编译脚本,其中 –depth指定工程的根目录,gyp会根据不同的平台选择生成哪种编译文件或IDE
gyp --depth=. test.gyp |
如果要指定生成编译脚本类型,比如xcode,如下
gyp --depth=. -f xcode test.gyp |
基本功能
跟CMake这种跨平台脚本生成工具一样,GYP提供一个编译脚本所需要的基本功能
定义宏
定义C中的宏,如下所示:
'defines': [ |
Predefined
gyp定义了许多默认变量,比如通过OS变量判断当前操作系统平台,如下所示:
'conditions': |
除了OS变量,PRODUCT_DIR变量表示编译生成文件路径,DEPTH表示文件执行路径
模块依赖
依赖其他GYP里面的target,如下所示,bar为bar.gyp里面的一个target_name:
{ |
文件库依赖
如果有些库不是在gyp框架内编译的,可以指定库的文件路径进行依赖
'link_settings': { |
变量定义
定义变量,用来进行项目配置,如下所示:
'variables': { |
include其他gypi文件
include其他gypi文件,如下所示:
'includes': [ |
包含头文件搜索路径
如下所示:
'include_dirs': [ |
cflag设置
如下所示:
'cflags': [ |
IDE设置
可以对IDE进行设置,如下所示,设置xcode的VALID_ARCHS
'xcode_settings': { |
shell脚本执行
在脚本里面执行shell命令,如下所示,BUILD_DATE可以在代码中打印出来,用来标示编译日期
"defines": [ |
特有功能
action
GYP出了支持生成编译C的脚本外,还支持第三方模块执行的接口action,action在对应target build之前执行,所以target_type一般为none。action可以用GYP编译其他语言,比如用javac编译Java、用ant来Android App、用yasm来编译汇编语言等。利用这个特性,还可以用来执行单元测试,下面就是在每次编译的时候,通过为run_fun_test的action来执行单元测试out/Release/fun_test
'targets': [ |
direct_dependent_settings
direct_dependent_settings表示依赖这个模块的模块也自动包含这个属性,比如入unit_test这个模块依赖gtest这个模块,那么unit_test会被设置“include_dirs”这个属性,把gtest这个模块中include的绝对路径添加为头文件搜索路径
direct_dependent_settings的设计让使用其他模块更加方便,被依赖模块include路径变更对其他模块没有影响
'targets': [ |
可配置的GYP
gyp变量一般用来配置整个gyp工程,完成下面功能:
- 选择哪些模块需要编译(平台不同、功能不同)
- 定义不同宏,用来控制代码中不同逻辑
可以通过文件定义gyp变量(一般放在gypi文件里面),也可以通过-D的方式来定义gyp变量
gyp --depth=. test.gyp -Denable_moudle=1 |
gyp_chromium
Chromium项目里面对gyp进行了一些封装,开发者可以定义GYP_DEFINES、GYP_GENERATORS、GYP_CROSSCOMPILE等环境变量来控制gyp生成逻辑,如下:
exprot GYP_DEFINES="target_arch=arm64" |