chromium代码是通过GYP构建的,这是一个跨平台的构建系统,针对不同的操作系统,生成不同的编译工程文件。一个.gyp文件的目的是生成makefile、或者.sln工程文件。
一个典型的.gyp文件的框架是:
{
'variables': {
.
.
.
},
'includes': [
'../build/common.gypi',
],
'target_defaults': {
.
.
.
},
'targets': [
{
'target_name': 'target_1',
.
.
.
},
{
'target_name': 'target_2',
.
.
.
},
],
'conditions': [
['OS=="linux"', {
'targets': [
{
'target_name': 'linux_target_3',
.
.
.
},
],
}],
['OS=="win"', {
'targets': [
{
'target_name': 'windows_target_4',
.
.
.
},
],
}, { # OS != "win"
'targets': [
{
'target_name': 'non_windows_target_5',
.
.
.
},
}],
],
}
整个文件最高一级结构就是一个Python的字典,包含variables、includes、target_defaults、targets、conditions。它们的作用分别如下:
variables:通过Python字典形式定义变量,可以被其他部分使用。
includes:其他文件定义的模块,包含在本文件中。
target_defaults:定义的全局设置,可以被其他targets使用。
targets:定义的目标,通过表的形式给出,每个target由字典形式给出各个关键字的描述:如目标文档的类型、依赖关系等等。
conditions:通过设置的条件改变之前定义的变量、目标的内容。
举一个例子:
有三个C++的代码文件内容分别是:
//hello_world.cc
#include <stdio.h>
#include "my_class.h"
#define X 2
int main(int argc, char** argv)
{
int i = X;
printf("define X: i = %d\n", i);
printf("hello, world\n");
Myclass my_class(100);
my_class.Fun1();
}
此文件依赖头文件my_class.h和对应的类实现。
/*************************************************************************
> File Name: my_class.h
> Author: jxhe
************************************************************************/
class Myclass
{
public:
Myclass(int value): value_(value){}
void Fun1();
private:
int value_;
};
上面是my_class.h文件的内容,它在当前目录下的include子目录中。
/*************************************************************************
> File Name: my_class.cc
> Author: jxhe
************************************************************************/
#include "my_class.h"
#include <stdio.h>
void Myclass::Fun1()
{
printf("the value is %d\n", value_);
}
是my_class.cc文件内容。
通过gyp系统构建项目的编译工程。
{
'targets':
[
{
'target_name': 'foo',
'type' : 'executable',
'sources' :
[
'hello_world.cc',
'my_class.cc',
],
'include_dirs':
[
'include',
]
},
],
}
上面的代码保存为foo.gyp文件。当执行gyp --depth=. foo.gyp 时,将会生成Makefile。然后调用make命令将编译文件,生成foo和一些my_class.o、foo.o目标文件。
当编译一个典型库文件时,gyp文件的组织如下:
<span style="font-size:14px;"> {
'targets': [
{
'target_name': 'foo',
'type': '<(library)'
'dependencies': [
'xyzzy',
'../bar/bar.gyp:bar',
],
'defines': [
'DEFINE_FOO',
'DEFINE_A_VALUE=value',
],
'include_dirs': [
'..',
],
'direct_dependent_settings': {
'defines': [
'DEFINE_FOO',
'DEFINE_ADDITIONAL',
],
'linkflags': [
],
},
'export_dependent_settings': [
'../bar/bar.gyp:bar',
],
'sources': [
'file1.cc',
'file2.cc',
],
'conditions': [
['OS=="linux"', {
'defines': [
'LINUX_DEFINE',
],
'include_dirs': [
'include/linux',
],
}],
['OS=="win"', {
'defines': [
'WINDOWS_SPECIFIC_DEFINE',
],
}, { # OS != "win",
'defines': [
'NON_WINDOWS_DEFINE',
],
}],
]
},
],
}</span>
这个gyp文件定义了库文件,名字是foo,也就是会生成foo.o(静态库)或者foo.so(动态链接库),具体类型由变量<(libraty)决定,此变量是在调用gyp时指定。
dependencies:表明这个库依赖的其他库,也即foo必须在这些依赖库之后编译。
direct_dependent_settings:这里面定义的设置会被应用到依赖这个库的那个目标中,也即某target的dependencies里包含这个foo,那么这些设置就会应用到那个target。
export_dependent_settings:包含target,就会引入这些target的设置定义,到当前目标中。上例表明,在设置foo目标时,如果某target依赖foo,那么必须同时设置bar目标中direct_depentdent_settings的内容。这样就形成了目标设置的传递关系。