【C/C++基础进阶系列】实战记录 -- C++ 应用程序项目结构搭建 (GYP)

【1】GYP 中的关键字概述

  • conditions        : 条件定义
  • includes        : 包含.gypi文件的列表
  • target_defaults    : 默认的项目配置,每个项目(targets)的配置都需要从这个配置继承
  • targets            : 项目列表
  • variables        : 定义了键值对,可以被其他地方以<(varname)的方式引用
  • targets            : 项目列表
  • target_name    : 指定定义的target的名称
  • type    : target的类型
  • 支持executable、static_library、shared_library和 none
  • 其中none类型也很有用,可以作为处理资源、文档等特别项目的类型
  • product_extension    : 指定target生成目标的扩展名,不包含'.'
  • product_name    : 指定tareget生成目标的文件名,与product_extension组成一个文件全名
  • dependencies    : 指定target依赖的其他target
  • defines: 定义了预处理宏。类似于C/C++命令行编译中的-D或/D选项
  • include_dirs: 指定了包含文件的查找目录。类似于C/C++命令行编译中的-I或/I选项
  • sources: 列出了项目中的代码文件和一些项目相关的文件,sources!段中可以指定被排除的文件
  • configurations: 为targets定义的一套构建配置
  • 可以在targets和target_defaults段中,configurations不能够重写由target_defaults中指定的项
  • link_settings: 指定target需要链接的库,executable和shared_library类型的target需要指定链接库
  • direct_dependent_settings: 指定依赖本target的target设置
  • libraries: 指定target依赖的库
  • actions: 针对输入的文件,定义了一组自定义的构建动作
  • action_name: action的名称,某些平台可能会忽略这个字段
  • inputs: 输入信息,作为增量构建时使用
  • outputs: 输出信息,作为增量构建时使用
  • action: 构建命令
  • message: 构建时显示的信息
  • copies: 定义了一套拷贝动作
  • destination: 拷贝的目的地文件夹
  • files: 需要拷贝的文件列表
  • conditions: 条件判断
  • target_conditions: 条件判断

【2】GYP 配置文件示例

{
    'variables': {  # 定义了键值对
                    # 可以被其他地方以<(varname)的方式引用
        'pi': 'import math; print math.pi',
        'third_letters': "<(other_letters)HIJK",
        'letters_list': 'ABCD',
        'other_letters': '<(letters_list)EFG',
        'check_lists': [
            '<(third_letters)',
        ],
        'check_int': 5,
        'check_str_int': '6',
        'check_list_int': [
            7,
            '8',
            9,
        ],
        'not_int_1': ' 10',
        'not_int_2': '11 ',
        'not_int_3': '012',
        'not_int_4': '13.0',
        'not_int_5': '+14',
        'negative_int': '-15',
        'zero_int': '0',
    },
    'target_defaults': {    # 默认的项目配置
                            # 每个项目(targets)的配置都需要从这个配置继承
        'defines': [
            'U_STATIC_IMPLEMENTATION',
            ['LOGFILE', 'foo.log',],
        ],
        'include_dirs': [   # 指定了包含文件的查找目录,类似于C/C++命令行编译中的-I或/I选项
            '..',
        ],
        'target_conditions':            # 在处理完所有依赖项后在处理
                                        # 可以出现在.gyp文件的任何位置
        [
            # Ensure target and host have different shared_library names
            ['_toolset=="host"', {'product_extension': 'host'}],
        ],
        'conditions':                   # 条件定义
                                        # 在加载.gyp文件后即进行处理
                                        # 可以出现在.gyp文件的任何位置
        [
          [ 'target_arch == "ia32"', {  # CPU 架构为 ia32
            'cflags': [ '-m32' ],       # gcc 编译选项
            'ldflags': [ '-m32' ]       # gcc 链接选项
          }],
          [ 'target_arch == "x64"', {   # CPU 架构为 x64
            'cflags': [ '-m64' ],       # gcc 编译选项
            'ldflags': [ '-m64' ]       # gcc 链接选项
          }]
        ]
        'configurations':   # 为 targets 定义的一套构建配置
                            # 此处指定了 Release / Debug 配置下的预处理宏、编译选项
                            # 可以在targets和target_defaults段中
                            # configurations不能够重写由target_defaults中指定的项
        {
            'Release':
            {
                # gcc 编译选项
                'cflags': [ '-O3', '-Wno-unknown-warning-option', '-fPIC' ]
            },
            'Debug':
            {
                # 定义了预处理宏,类似于C/C++命令行编译中的-D或/D选项
                'defines': [ 'DEBUG', 'MS_LOG_TRACE', 'MS_LOG_FILE_LINE' ],
                # gcc 编译选项
                'cflags': [ '-g', '-O0', '-Wno-parentheses-equality', '-Wno-unknown-warning-option', '-fPIC' ],
            }
        },
    },
    'targets': [    # 项目列表
    {
        'target_name': 'hello1',        # 指定定义的target的名称
        'product_extension': '_bin',    # 指定target生成目标的扩展名,不包含'.'
        'product_name': 'hellow_1_',    # 指定tareget生成目标的文件名,与product_extension组成一个文件全名
        'type': 'executable',           # target的类型
                                        # 支持 executable(可执行)、static_library(静态库)、
                                        # shared_library(动态库) 和 none(一般文件)
        'dependencies': [               # 指定target依赖的其他target
                                        # 依赖项成员可以多个,其依赖的只能是当前 gyp 或其他 gyp 文件中的 target
            'b/b.gyp:b',
            'c/c.gyp:*'
        ],
        'defines': [                    # 定义了预处理宏,类似于C/C++命令行编译中的-D或/D选项
            'FOO',
            'VALUE=1',
            'PAREN_VALUE=(1+2+3)',
            'HASH_VALUE="a#1"',
        ],
        'include_dirs': [               # 指定了包含文件的查找目录,类似于C/C++命令行编译中的-I或/I选项
            '.',
            'inc1',
            'subdir/inc2',
        ],
        'sources': [                    # 列出了项目中的源文件
                                        # sources!段中可以指定被排除的文件
            'hello.h'
            'hello.c',
        ],
        'link_settings': {              # 指定target需要链接的库
                                        # executable和shared_library类型的target需要指定链接库
            'libraries': [              # 指定target依赖的库
                'libiconv.dylib',
                'subdir/libminizip.a',
            ],
            'ldflags': [ '-pthread' ],  # gcc 链接选项
        },
        'direct_dependent_settings': {  # 指定依赖本target的target设置
            'defines': [                # 定义了预处理宏,类似于C/C++命令行编译中的-D或/D选项
                'UNIT_TEST',
            ],
            'include_dirs': [           # 指定了包含文件的查找目录,类似于C/C++命令行编译中的-I或/I选项
                'foo',
                'foo/include',
            ],
        },
        'actions': [                    # 提供了自定义处理输入输出的功能
                                        # 构建系统会比较inputs和outputs中的文件是否是修改过,
                                        #   只有在修改过的情况下才会运行action
            {
                'variables': {          # 定义了键值对
                                        # 可以被其他地方以<(varname)的方式引用
                    'core_library_files': [
                        'src/runtime.js',
                        'src/v8natives.js',
                        'src/macros.py',
                    ],
                },
                'action_name': 'js2c',  # action的名称,某些平台可能会忽略这个字段
                'inputs': [             # 输入信息,作为增量构建时使用
                    'tools/js2c.py',
                    '<@(core_library_files)',
                ],
                'outputs': [            # 输出信息,作为增量构建时使用
                    '<(INTERMEDIATE_DIR)/libraries.cc',
                    '<(INTERMEDIATE_DIR)/libraries-empty.cc',
                ],
                'action': ['python', 'tools/js2c.py', '<@(_outputs)', 'CORE', '<@(core_library_files)'], # 构建命令
            },
        ],
    },
    {
        'target_name': 'copies1',   # 指定定义的target的名称
        'type': 'none',             # target的类型
                                    # 支持 executable(可执行)、static_library(静态库)、
                                    # shared_library(动态库) 和 none(一般文件)
        'includes': [               # includes: 包含.gypi文件的列表
            '../common.gypi',
            './thread.gypi',
        ],
        'copies': [                 # 定义了一套拷贝动作
                                    # copies会在destination创建相同名称的文件
            {
                'destination': 'copies-out', # 拷贝的目的地文件夹
                'files': [          # 需要拷贝的文件列表
                    'file1',
                ],
            },
        ],
    },
    # 拷贝目录
    {
        'target_name': 'copies3',   # 指定定义的target的名称
        'type': 'none',             # target的类型
                                    # 支持 executable(可执行)、static_library(静态库)、
                                    # shared_library(动态库) 和 none(一般文件)
        'copies': [                 # 定义了一套拷贝动作
                                    # copies会在destination创建相同名称的文件
            {
                'destination': '<(PRODUCT_DIR)/copies-out', # 拷贝的目的地文件夹
                'files': [          # 需要拷贝的文件列表
                    'directory/',
                ],
            },
        ],
    },
    {
        'target_name': 'program',   # 指定定义的target的名称
        'type': 'executable',       # target的类型
        'sources': [                # 列出了项目中的源文件
                                    # sources!段中可以指定被排除的文件
            'main.c',
            'prog1.in',
            'prog2.in',
        ],
        'rules': [                  # 提供了自定义构建的功能
                                    # 如下变量可在outputs、action和message中访问
                                    # RULE_INPUT_PATH: 当前输入的全路径
                                    # RULE_INPUT_DIRNAME: 当前输入的目录
                                    # RULE_INPUT_NAME: 当前输入的名称
                                    # RULE_INPUT_ROOT: 当前输入的去掉扩展名
                                    # RULE_INPUT_EXT: 当前输入的扩展名
            {
                'rule_name': 'make_sources', # rule的名称,某些平台可能会忽略这个字段
                'extension': 'in',      # 在本target中,所有以此为扩展名的源文件在构建时都使用这个规则
                'inputs': [             # 依赖的构建规则
                    'make-sources.py',
                ],
                'outputs': [            # 输出信息,作为增量构建时使用
                    '<(INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).c',
                    '<(INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).h',
                ],
                'action': [             # 构建命令
                    'python', '<(_inputs)', '<(RULE_INPUT_NAME)', '<@(_outputs)',
                ],
            },
        ],
    },
  ],
}

参考与致谢

本博客为博主的学习实践总结,并参考了众多博主的博文,在此表示感谢,博主若有不足之处,请批评指正。

【1】Gyp语法规则参考 & 工具的使用

【2】GYP使用总结 ---- 从Makefile到GYP

【3】Gyp语法规则参考 & 工具的使用