by Markdown, 8/14/2014 10:17:28 AM
翻譯自 https://code.google.com/p/gyp/wiki/GypLanguageSpecification
目的和背景
Google使用過很多處理平台無關的項目構建系統,比如Scons,CMake。在實際使用中這些並不能滿足需求。開發復雜的應用程序時,在Mac上Xcode更加適合,而Windows上Visual Studio更是無二之選。
gyp是為Chromium項目創建的項目生成工具,可以從平台無關的配置生成平台相關的Visual Studio、Xcode、Makefile的項目文件。這樣一來我們就不需要花額外的時間處理每個平台不同的項目配置以及項目之間的依賴關系。
概述
Gyp大致有如下的特點:
- 配置文件都是以.gyp結尾
- 每個.gyp文件都描述了如何去構建項目
- 每個.gyp文件都能生成若干個合適特定平台的項目文件:
- 在Mac上,.gyp文件會生成Xcode項目文件,包含了如何構建項目。一個.gyp文件會生成的一個.xcodeproj
- 在Windows上,.gyp文件會生成Visual Studio項目文件。一個.gyp文件會生成一個.sln,並為每個targets生成一個.vcproj
- 在Linux上,.gyp文件會生成Makefile文件
- .gyp文件的語法是Python數據格式(Json格式)
- .gypi文件可以被.gyp文件包含,方便統一設置
- 配置中數據是鍵-值對的形式
詳細設計
設計准則:
- 關鍵字一致性:所有的關鍵字都和平台項目的項目配置字段相同
- 通過前綴表明配置屬於的特定平台。比如:
msvs_disabled_warnings
,xcode_framework_dirs
樣例
{
'target_defaults': {
'defines': [
'U_STATIC_IMPLEMENTATION',
['LOGFILE', 'foo.log',],
],
'include_dirs': [
'..',
],
},
'targets': [
{
'target_name': 'foo',
'type': 'static_library',
'sources': [
'foo/src/foo.cc',
'foo/src/foo_main.cc',
],
'include_dirs': [
'foo',
'foo/include',
],
'conditions': [
[ 'OS==mac', { 'sources': [ 'platform_test_mac.mm' ] } ]
],
'direct_dependent_settings': {
'defines': [
'UNIT_TEST',
],
'include_dirs': [
'foo',
'foo/include',
],
},
},
],
}
結構元素
.gyp文件中定義了一些targets和構建規則。
下面的關鍵字可以定義在最頂層:
- conditions: 條件定義。見條件(conditions)
- includes: 包含.gypi文件的列表
{
'targets':[
{
'target_name': 'Thread',
'type': 'executable',
'includes': [
'../common.gypi',
'./thread.gypi',
]
...
}
],
}
- target_defaults: 默認的項目配置,每個項目(targets)的配置都需要從這個配置繼承
- targets: 項目列表
{
'targets': [
{
'target_name': 'hello1',
'product_extension': 'stuff',
'type': 'executable',
'sources': [
'hello.c',
],
},
{
'target_name': 'hello2',
'target_extension': 'stuff',
'type': 'executable',
'sources': [
'hello.c',
],
}
]
}
- variables: 定義了鍵值對,可以被其他地方以
<(varname)
的方式引用{
'variables': {
'pi': 'import math; print math.pi',
'third_letters': "<(other_letters)HIJK",
'letters_list': 'ABCD',
'other_letters': '<(letters_list)EFG',
'check_included': '<(included_variable)',
'check_lists': [
'<(included_variable)',
'<(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',
},
...
}
項目(targets)
.gyp文件定義的一套構建項目的規則。targets中也可以包含includes
、conditions
和variables
。下面的是一些targets中的專有字段:
- target_name: 指定定義的target的名稱
- type: target的類型。支持
executable
、static_library
、shared_library
和none
。其中none
類型也很有用,可以作為處理資源、文檔等特別項目的類型。例如,在Windows中,none
將作為工具集類型的項目存在 - product_extension: 指定target生成目標的擴展名,不包含'.'
- product_name: 指定tareget生成目標的文件名,與
product_extension
組成一個文件全名 - dependencies: 指定target依賴的其他target
{
'targets': [
{
'target_name': 'a',
'type': 'static_library',
'dependencies': [
'b/b.gyp:b',
'c/c.gyp:*'
],
'sources': [
'a.c',
],
},
],
}
- defines: 定義了預處理宏。類似於C/C++命令行編譯中的-D或/D選項
{
'targets': [
{
'target_name': 'defines',
'type': 'executable',
'defines': [
'FOO',
'VALUE=1',
'PAREN_VALUE=(1+2+3)',
'HASH_VALUE="a#1"',
],
'sources': [
'defines.c',
],
},
]
}
- include_dirs: 指定了包含文件的查找目錄。類似於C/C++命令行編譯中的-I或/I選項
{
'targets': [
{
'target_name': 'includes',
'type': 'executable',
'dependencies': [
'subdir/subdir_includes.gyp:subdir_includes',
],
'cflags': [
'-Ishadow1',
],
'include_dirs': [
'.',
'inc1',
'shadow2',
'subdir/inc2',
],
'sources': [
'includes.c',
],
},
],
}
- sources: 列出了項目中的代碼文件和一些項目相關的文件。
sources!
段中可以指定被排除的文件 - configurations: 為targets定義的一套構建配置。見配置(configurations)
- link_settings: 指定target需要鏈接的庫。
executable
和shared_library
類型的target需要指定鏈接庫。這個段內可以指定target中可包含的除了configurations
、target_name
和type
的所有配置。可以與all_dependent_setting
、direct_dependent_setting
做對比 - direct_dependent_settings: 指定依賴本target的target設置。這個段內可以指定target中可包含的除了
configurations
、target_name
和type
的所有配置。可以與all_dependent_setting
、link_settings
做對比 - all_dependent_settings:
- libraries: 指定target依賴的庫,見
link_settings>libraries
...
'link_settings': {
'libraries': [
'libiconv.dylib',
'<(ZLIB_DIR)contrib/minizip/libminizip.a',
'libcurl.dylib',
],
},
...
- actions: 針對輸入的文件,定義了一組自定義的構建動作。見動作(actions)
- copies: 定義了一套拷貝動作。見拷貝(copies)
- rules: 見規則(rules)
- target_conditions: 類似於conditions,但是起左右的時間比conditions晚
- msvs_precompiled_header: 指定預編譯頭文件。只能用於Visual Studio
- msvs_precompiled_source: 指定預編譯源文件。只能用於Visual Studio
- msvs_prebuild: 生成之前事件。只能用於Visual Studio
- msvs_postbuild: 生成之后事件。只能用於Visual Studio
'msvs_postbuild': r'copy "$(OutDir)$(TargetName)" "C:\$(TargetName)"
- msvs_props: 指定target的屬性頁文件(.vsprops) 。只能用於Visual Studio
- msvs_cygwin_shell: 指定action運行在cygwin下。只能用於Visual Studio
- msvs_cygwin_dirs: 指定cygwin的目錄。只能用於Visual Studio
- xcode_config_file: 在xcode中,指定target的配置文件(.xcconfig)。只能用於xcode
- xcode_framework_dirs: 在xcode中,指定框架的目錄。只能用於xcode
配置(configurations)
configurations
段可以在targets
和target_defaults
段中。configurations
不能夠重寫由target_defaults
中指定的項。
在有些時候我們需要為項目指定多個配置,比如Debug
、Release
。 下面的一段為Windows中的常規配置:
...
'configurations': {
'Debug': {
'msvs_settings': {
'VCCLCompilerTool': {
# 多線程調試 DLL (/MDd)
'RuntimeLibrary': '3',
# 不優化 /Od
'Optimization': '0',
# 用於“編輯並繼續”的程序數據庫 (/ZI)
'DebugInformationFormat': '4',
},
'VCLinkerTool': {
'GenerateDebugInformation': 'true',
'GenerateMapFile': 'false',
# 'SubSystem': '1',
},
},
}, # Debug
'Release': {
'msvs_settings': {
'VCCLCompilerTool': {
# 多線程 DLL (/MD)
'RuntimeLibrary': '2',
# 完全優化 /Os
'Optimization': '2',
# 使用內部函數 /Oi
'EnableIntrinsicFunctions': 'true',
# 程序數據庫 (/Zi)
'DebugInformationFormat': '3',
},
'VCLinkerTool': {
'GenerateDebugInformation': 'true',
'GenerateMapFile': 'false',
},
},
}, # Release
},
...
條件(conditions)
conditions
和target_conditons
可以出現在.gyp文件
的任何位置。conditions
語句在加載.gyp
文件后即進行處理,target_conditions
語句在處理完所有依賴項后在處理。
在加載完全局和局部的數據后,使用python的eval()
函數對條件字符串做處理。
動作(actions)
actions
提供了自定義處理輸入輸出的功能,其中的每一項都有下面的字段:
- action_name: action的名稱,某些平台可能會忽略這個字段
- inputs: 輸入信息,作為增量構建時使用
- outputs: 輸出信息,作為增量構建時使用
- action: 構建命令
- message: 構建時顯示的信息
構建系統會比較inputs
和outputs
中的文件是否是修改過,只有在修改過的情況下才會運行action
。
在Xcode中,是通過shell腳本實現的;在Visual Studio中通過FileConfiguration包含一個自定義的VCCustomBuildTool實現。
'sources': [
# libraries.cc is generated by the js2c action below.
'<(INTERMEDIATE_DIR)/libraries.cc',
],
'actions': [
{
'variables': {
'core_library_files': [
'src/runtime.js',
'src/v8natives.js',
'src/macros.py',
],
},
'action_name': 'js2c',
'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)'],
},
],
規則(rules)
rules
提供了自定義構建的功能,每一項都有下面的字段:
- rule_name: rule的名稱,某些平台可能會忽略這個字段
- extension: 在本
target
中,所有以此為擴展名的源文件在構建時都使用這個規則 - inputs: 依賴的構建規則
- outputs: 輸出信息,作為增量構建時使用。可以訪問下面的
RULE_INPUT_*
變量 - action: 構建命令。可以訪問下面的
RULE_INPUT_*
變量 - message: 構建時顯示的信息。可以訪問下面的
RULE_INPUT_*
變量
下面的這個變量可以在outputs
、action
和message
中訪問:
- RULE_INPUT_PATH: 當前輸入的全路徑
- RULE_INPUT_DIRNAME: 當前輸入的目錄
- RULE_INPUT_NAME: 當前輸入的名稱
- RULE_INPUT_ROOT: 當前輸入的去掉擴展名
- RULE_INPUT_EXT: 當前輸入的擴展名
{
'targets': [
{
'target_name': 'program',
'type': 'executable',
'msvs_cygwin_shell': 0,
'sources': [
'main.c',
'prog1.in',
'prog2.in',
],
'rules': [
{
'rule_name': 'make_sources',
'extension': 'in',
'inputs': [
'make-sources.py',
],
'outputs': [
'<(INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).c',
'<(INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).h',
],
'action': [
'python', '<(_inputs)', '<(RULE_INPUT_NAME)', '<@(_outputs)',
],
'process_outputs_as_sources': 1,
},
],
},
],
}
rules
與actions
有些相似之處。
拷貝(copies)
copies
提供了簡單的文件拷貝功能,每一項都有下面的字段:
- destination: 拷貝的目的地文件夾
- files: 需要拷貝的文件列表
copies
會在destination
創建相同名稱的文件。
{
'targets': [
{
'target_name': 'copies1',
'type': 'none',
'copies': [
{
'destination': 'copies-out',
'files': [
'file1',
],
},
],
},
{
'target_name': 'copies2',
'type': 'none',
'copies': [
{
'destination': '<(PRODUCT_DIR)/copies-out',
'files': [
'file2',
],
},
],
},
# 拷貝目錄
{
'target_name': 'copies3',
'type': 'none',
'copies': [
{
'destination': '<(PRODUCT_DIR)/copies-out',
'files': [
'directory/',
],
},
],
},
],
}
代碼文件的命名
平台相關的文件命名規則為*_win.{ext}
、*_mac.{ext}
、*_linux.{ext}
和*_posix.{ext}
。例如:
- _win: foo_win.cpp
- _mac: foo_mac.cpp,foo_mac.mm
- _linux: foo_linux.cpp
- _posix: foo_posix.cpp
gyp的源代碼
對於文檔中一些未列出和有爭議地方最可靠的是去看gyp
的源代碼和例子。gyp
的測試代碼很詳細,可以作為學習的例子做參考。
使用IDE調試生成的Makefile項目
在Linux上調試一般都是使用gdb,但是對於不態熟悉的就不好直接上手。這里推薦QtCreator,當然Netbeans和Eclispe CDT也可以,但是不如QtCreator方便和高效。
通用配置 common.gypi
{
'includes': [
'env.gypi'
],
'include_dirs': [
'.',
],
'configurations': {
'Debug': {
'defines': [
'DEBUG',
],
},
'Release': {
'defines': [
'NDEBUG',
],
},
}, # configurations
'conditions': [
['OS=="win"', {
'defines': [
'WIN32',
'UNICODE',
'_UNICODE',
'OS_WIN',
],
'msbuild_configuration_attributes': {
'IntermediateDirectory': '$(OutDir)__BuildTemp\\$(ProjectName)\\',
},
'msbuild_toolset': {
#'PlatformToolset': 'v100'
}, # msbuild_toolset
'msvs_settings': {
'VCCLCompilerTool': {
'WarningLevel': '3',
'DisableSpecificWarnings': ['4251','4996'],
'WarnAsError': 'true',
},
'VCLinkerTool': {
'AdditionalDependencies': [
'kernel32.lib',
'user32.lib',
],
'AdditionalLibraryDirectories': [],
},
}, # msvs_settings
'configurations': {
'Debug': {
'msvs_settings': {
'VCCLCompilerTool': {
# 多線程調試 DLL (/MDd)
'RuntimeLibrary': '3',
# 不優化 /Od
'Optimization': '0',
# 用於“編輯並繼續”的程序數據庫 (/ZI)
'DebugInformationFormat': '4',
},
'VCLinkerTool': {
'GenerateDebugInformation': 'true',
'GenerateMapFile': 'false',
# 'SubSystem': '1',
},
}, # msvs_settings
}, # Debug
'Release': {
'msvs_settings': {
'VCCLCompilerTool': {
# 多線程 DLL (/MD)
'RuntimeLibrary': '2',
# 完全優化 /Os
'Optimization': '2',
# 使用內部函數 /Oi
'EnableIntrinsicFunctions': 'true',
# 程序數據庫 (/Zi)
'DebugInformationFormat': '3',
},
'VCLinkerTool': {
'GenerateDebugInformation': 'true',
'GenerateMapFile': 'false',
},
}, # msvs_settings
}, # Release
}, # configurations
}], # Windows
['OS=="mac"', {
'make_global_settings': [
['CC', '/usr/bin/clang'],
['CXX', '/usr/bin/clang++'],
],
'defines': [
'OS_POSIX',
'OS_MACOSX',
],
'xcode_settings': {
'ALWAYS_SEARCH_USER_PATHS': 'NO',
#'i386', 'x86_64'
'ARCHS': [ 'x86_64' ],
'MACOSX_DEPLOYMENT_TARGET': '10.6',
'CC': 'clang',
'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0',
'CLANG_CXX_LANGUAGE_STANDARD': 'c++0x',
# libstdc++, c++11, libc++
'CLANG_CXX_LIBRARY': 'libstdc++',
'GCC_ENABLE_OBJC_GC': 'unsupported',
#'LIBRARY_SEARCH_PATHS': [],
'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',
'GCC_SYMBOLS_PRIVATE_EXTERN': 'NO',
'DEBUG_INFORMATION_FORMAT': 'dwarf-with-dsym',
#'DEPLOYMENT_POSTPROCESSING': 'YES',
'OTHER_CFLAGS': [
'-fno-eliminate-unused-debug-symbols',
'-mmacosx-version-min=10.6',
# compile use oc++
'-x objective-c++',
],
'WARNING_CFLAGS': ['-Wno-deprecated-declarations'],
'WARNING_CFLAGS!': ['-Wall', '-Wextra',],
'WARNING_CXXFLAGS': ['-Wstrict-aliasing', '-Wno-deprecated',],
}, # xcode_settings
'link_settings': {
'libraries': [
'$(SDKROOT)/System/Library/Frameworks/Foundation.framework',
],
},
'libraries': [],
'mac_framework_dirs': [],
'configurations': {
'Debug': {
'xcode_settings': {
'GCC_DEBUGGING_SYMBOLS': 'full',
'STRIP_INSTALLED_PRODUCT': 'YES',
'GCC_OPTIMIZATION_LEVEL': '0',
'OTHER_CFLAGS': ['-g',],
'OTHER_CXXFLAGS': ['-g',],
}, # xcode_settings
}, # Debug
'Release': {
'xcode_settings': {
'GCC_OPTIMIZATION_LEVEL': 's',
}, # xcode_settings
}, # Release
}, # configurations
}], # Mac
['OS=="linux"', {
'defines': [
'OS_POSIX',
'OS_LINUX',
],
'cflags': [
# Support 64-bit shared libs (also works fine for 32-bit).
'-fPIC',
'-std=c++11',
'-fstrict-aliasing',
'-Wall',
'-Wextra',
'-Wshadow',
'-Wconversion',
#'-Wpadded',
'-Wstrict-aliasing=2',
'-Wstrict-overflow=4',
],
'ldflags': [],
'configurations': {
'Debug': {
'cflags': [
'-g',
'-C',
],
},
'Release': {
'cflags': [
'-O2',
],
},
}, # configurations
}], # Linux
], # conditions
}
gyp命令行
--depth
: Chromium歷史遺留問題,需要設置為.
--generator-out
: 設置生成項目的輸出文件夾--f
: 設置生成項目的類型,不設置則根據平台決定生成的項目類型。可用的值有:msvs
、xcode
、make
--G
: 設置生成的其他標記參數,這個值和具體的平台有關。- msvs_version: 指定生成的Visual Studio項目的版本,不設置則會根據系統中安裝的最新的Visual Stuio生成項目。可用的值有
2005
、2005e
、2008
、2008e
、2010
、2010e
、2012
、2012e
、2013
、2013e
。例如:--Gmsvs_version=2010
- msvs_version: 指定生成的Visual Studio項目的版本,不設置則會根據系統中安裝的最新的Visual Stuio生成項目。可用的值有
--toplevel-dir
: 設置源代碼的跟目錄,默認將取--depth
指定的值-D
: 傳入變量到.gyp,可以使用<(varname)
這種方式讀取。例如:-Dbuildtype=share_library
--no-circular-check
:
寫API文檔是一件很蛋疼的事情,以后繼續添加。