Contents
  1. 1. 介绍
  2. 2. GYP Vs CMake
  3. 3. 简单实例
  4. 4. 基本功能
    1. 4.1. 定义宏
    2. 4.2. Predefined
    3. 4.3. 模块依赖
    4. 4.4. 文件库依赖
    5. 4.5. 变量定义
    6. 4.6. include其他gypi文件
    7. 4.7. 包含头文件搜索路径
    8. 4.8. cflag设置
    9. 4.9. IDE设置
    10. 4.10. shell脚本执行
  5. 5. 特有功能
    1. 5.1. action
    2. 5.2. direct_dependent_settings
  6. 6. 可配置的GYP
  7. 7. gyp_chromium

介绍

写的一手好代码固然难得,代码写好后可以方便在各个平台完成编译部署,也需要找到好的工具,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五个特性之间的比较:

GYP_Vs_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的可执行文件

{
'targets': [
{
'target_name': 'my_target',
'type': 'executable',
'sources': [
'main.cc',
],
},
],
},

通过下面的命令生成编译脚本,其中 –depth指定工程的根目录,gyp会根据不同的平台选择生成哪种编译文件或IDE

gyp --depth=. test.gyp

如果要指定生成编译脚本类型,比如xcode,如下

gyp --depth=. -f xcode test.gyp

基本功能

跟CMake这种跨平台脚本生成工具一样,GYP提供一个编译脚本所需要的基本功能

定义宏

定义C中的宏,如下所示:

'defines': [
'DEFINE_FOO',
],

Predefined

gyp定义了许多默认变量,比如通过OS变量判断当前操作系统平台,如下所示:

'conditions': [
['OS=="linux"', {
...
],
['OS=="win"', {
...
}, {OS != "win",
...
}]
],

除了OS变量,PRODUCT_DIR变量表示编译生成文件路径,DEPTH表示文件执行路径

模块依赖

依赖其他GYP里面的target,如下所示,bar为bar.gyp里面的一个target_name:

{
'targets': [
{
'target_name': 'my_target',
'type': 'executable',
'sources': [
'main.cc',
],
'dependencies': [
'<(DEPTH)/bar/bar.gyp:bar',
],
},
],
},

文件库依赖

如果有些库不是在gyp框架内编译的,可以指定库的文件路径进行依赖

'link_settings': {
'libraries': [
'-Wl,-L<(DEPTH)/third_party/libpng/ -lpng',
'/System/Library/Frameworks/Cocoa.framework'
],
},

变量定义

定义变量,用来进行项目配置,如下所示:

'variables': {
'is_enable_video': 'true'
},
'conditions': [
['is_enable_video=="true"', {
...
],
],

include其他gypi文件

include其他gypi文件,如下所示:

'includes': [
'<(DEPTH)/build/common.gypi',
],

包含头文件搜索路径

如下所示:

'include_dirs': [
'include',
],

cflag设置

如下所示:

'cflags': [
'-Werror',
'-Wall',
],

IDE设置

可以对IDE进行设置,如下所示,设置xcode的VALID_ARCHS

'xcode_settings': {
'VALID_ARCHS': 'armv7 armv7s arm64',
},

shell脚本执行

在脚本里面执行shell命令,如下所示,BUILD_DATE可以在代码中打印出来,用来标示编译日期

"defines": [
'BUILD_DATE=<!(echo `date +%Y%m%d`)'
],

特有功能

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': [
{
'target_name': 'fun_test',
'type': 'executable',
'sources': [
'test/func_test_main.cc',
],
'dependencies': [
'func',
],
},
{
'target_name': 'run_fun_test',
'type': 'none',
'dependencies': [
'fun_test',
],
'actions': [{
'action_name': 'run_fun_test',
'inputs': ['test/func_test_main.cc',],
'outputs': [ ' ' ],
'action': ['bash','-ec','<(DEPTH)/out/Release/fun_test'],
},],
},
]

direct_dependent_settings

direct_dependent_settings表示依赖这个模块的模块也自动包含这个属性,比如入unit_test这个模块依赖gtest这个模块,那么unit_test会被设置“include_dirs”这个属性,把gtest这个模块中include的绝对路径添加为头文件搜索路径

direct_dependent_settings的设计让使用其他模块更加方便,被依赖模块include路径变更对其他模块没有影响

'targets': [
{
'target_name': 'gtest',
'type': 'static_library',
'include_dirs': [
'include',
'.',
],
'sources': [
'include/gtest.h',
'source/gtest.cpp',
],
'direct_dependent_settings': {
'include_dirs': [
'include',
]
},
},
]

可配置的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"
export GYP_GENERATORS="xcode"
gyp_chromium --depth=. test.gyp
Contents
  1. 1. 介绍
  2. 2. GYP Vs CMake
  3. 3. 简单实例
  4. 4. 基本功能
    1. 4.1. 定义宏
    2. 4.2. Predefined
    3. 4.3. 模块依赖
    4. 4.4. 文件库依赖
    5. 4.5. 变量定义
    6. 4.6. include其他gypi文件
    7. 4.7. 包含头文件搜索路径
    8. 4.8. cflag设置
    9. 4.9. IDE设置
    10. 4.10. shell脚本执行
  5. 5. 特有功能
    1. 5.1. action
    2. 5.2. direct_dependent_settings
  6. 6. 可配置的GYP
  7. 7. gyp_chromium