使用
- 编写.gyp文件
- 运行gyp命令生成makefile、build.ninja文件或xcode、vs等工程
- 编译。根据第2步的结果,运行make、ninja或者在xcode、vs里编译
举一个最简单的例子,源文件如下:
main.cpp 编写.gyp文件如下: main.gyp
在源文件目录下运行命令gyp --depth=. main.gyp
,生成工程文件。打开生成的工程文件编译、运行即可。
更多例子可以参考play_gyp
生成跨平台工程的实践经验
如上个例子中展示的,运行gyp命令的大概方式为gyp --depth=. --generator-output=build -f ninja main.gyp
,其中 –depth指定工程的根目录,–generator-output指定工程文件的输出目录,默认为当前目录,-f指定生成工程文件的类型,常用的有'make', ‘ninja’, ‘xcode’, ‘msvs’, ‘scons'。更多的命令行选项可以通过gyp -h
查看。
工程实践中还有一种更方便的生成不同平台工程的方法,即使用gyp的全局变量。定义全局变量的好处是可以使用别人封装好的gyp脚本,如Chromium工程中就可以使用gyp_chromium.py了。
也可以通过修改GYP_GENERATORS,生成各种类型的工程文件
- ninja for Ninja
- make for Makefiles
- msvs for Visual Studio
- msvs-ninja for Visual Studio project building with ninja
- xcode for Xcode
gyp文件语法
GYP的输入文件习惯上后缀为.gyp或.gypi。.gypi文件作为.gyp文件的include文件。 以Visual Studio为例,.gyp文件对应.sln工作空间,.gyp文件中的target对应.vcproj或.vxcproj工程。
.gyp文件的顶级元素为'variables’, ‘includes’, ‘target_defaults’, ‘targets’, ‘conditions'。语法是JSON,或者说是允许trailing comments的python。.gyp文件之间其实可以不用相互引用,gyp会递归的扫描当前目录的所有子目录,处理扫描到的所有*.gyp文件。
官方文档
- 模版和例子:GypUserDocumentation
- 主要元素或者配置项:GypLanguageSpecification
- 基本语法:InputFormatReference
变量
变量分为三类,Predefined、User-defined、Automatic。
变量设置默认值的方法:name%:value
。只有name未定义时,才将name的值设置为value.
- Predefined,命名习惯为CAPITAL_LETTERS。
- OS:用于判断操作系统
- EXECUTABLE_PREFIX:可执行文件的前缀
- EXECUTABLE_SUFFIX:可执行文件的后缀
- INTERMEDIATE_DIR:中间文件目录,只对单一target有效
- SHARED_INTERMEDIATE_DIR:中间文件共享目录,所有target(包括跨.gyp文件的target)共用同一目录
- PRODUCT_DIR:输出文件(编译出的可执行文件、库等)的主目录
- User-defined,命名习惯为lowercase_letters。变量使用的方式如下
-
<(VAR)
early phase, value is string -
>(VAR)
post phase, value is string -
<@(VAR)
early phase, value is list -
>@(VAR)
post phase, value is list
-
- Automatic,dictionary中,name:string的key/value对会自动生成一个_name的变量,值为string
命令
gyp可以执行shell命令,即将命令内容传递给shell执行,然后获得返回值。
用法为<!(cmd)
或<!@(cmd)
,前者返回值为string,后者返回值为list。
这样,虽然gyp没有提供通配符,但是可以通过命令实现这个功能,如实现添加当前目录下所有.cpp后缀的文件作为sources:
target的配置项目
顶级元素下的target_defaults中可以设置所有targets共用的配置项目,targets中可以具体配置每个target。
常用的target可分为可运行程序、静态库、动态库等,但在跨平台时,不同平台的target各不相同,参数的设置也相差很远。 target的通用框架如下:
defines为宏定义,对应-D或/D;
include_dirs对应-I或/I;
cflags为编译选项,对应类似-Werror或/Werror;
ldflags为链接选项,对应类似-pthread;
target还有一些在类型不同、平台不同时,差别很大的配置,列举一些如下:
- 静态库或动态库
direct_dependent_settings
:定义一些编译参数、宏定义等,这些定义将导出到直接依赖该库(通常是第三方库)的target
all_dependent_settings
:定义一些编译参数、宏定义等,这些定义将导出到所有依赖该库的target,包含直接依赖和间接依赖
link_settings
:定义一些当将该库作为输入时需要配置的链接参数。通常是对静态库有效,动态库忽略
export_dependent_settings
:列出一些dependencies中的target,direct_dependent_settings定义的配置将应用到export_dependent_settings列出的target。即将依赖该库的配置导出到该库依赖的target
- 跨平台工程
针对各个平台不同的配置,gyp的策略是直接使用各平台工程的原生参数。如生成Xcode工程时,可以直接在gyp文件中使用SDKROOT,TARGETED_DEVICE_FAMILY等Xcode中使用的参数。
在xcode_settings对象中设置Xcode的特有参数
在msvs_settings对象中设置Visual Studio的特有参数。
这种策略有一个便利之处。以Xcode工程为例,如果有不知道怎么设置的选项,可以先在Xcode工程中设置好,再从工程文件.xcodeproj包内的project.pbxproj文件中拷贝出来,同步到.gyp文件中。
gyp的潜规则
- target的sources项会按照对应平台自动过滤后缀(*_linux.{ext}, *_mac.{ext}, *_posix.{ext} or *_win.{ext})不符合的源文件。