mirror of https://github.com/nodejs/node.git
tools: update gyp-next to 0.18.1
PR-URL: https://github.com/nodejs/node/pull/53251 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Jiawen Geng <technicalcute@gmail.com>
This commit is contained in:
parent
eae75fe635
commit
4770ae4dfb
|
@ -1,5 +1,17 @@
|
|||
# Changelog
|
||||
|
||||
## [0.18.1](https://github.com/nodejs/gyp-next/compare/v0.18.0...v0.18.1) (2024-05-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **ci:** add Python 3.13 pre-release to test matrix ([#257](https://github.com/nodejs/gyp-next/issues/257)) ([8597203](https://github.com/nodejs/gyp-next/commit/8597203b687325c7516367135e026586279d0583))
|
||||
|
||||
|
||||
### Documentation
|
||||
|
||||
* vendor docs from gyp.gsrc.io ([#254](https://github.com/nodejs/gyp-next/issues/254)) ([8d7ba6e](https://github.com/nodejs/gyp-next/commit/8d7ba6e784dedf1122a0456150c739d2a09ecf57))
|
||||
|
||||
## [0.18.0](https://github.com/nodejs/gyp-next/compare/v0.17.0...v0.18.0) (2024-05-08)
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
# Contributing to gyp-next
|
||||
|
||||
## Start contributing
|
||||
|
||||
Read the docs at [`./docs/Hacking.md`](./docs/Hacking.md) to get started.
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
This project is bound to the [Node.js Code of Conduct](https://github.com/nodejs/admin/blob/HEAD/CODE_OF_CONDUCT.md).
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
GYP can Generate Your Projects.
|
||||
===================================
|
||||
|
||||
Documents are available at [gyp.gsrc.io](https://gyp.gsrc.io), or you can check out ```md-pages``` branch to read those documents offline.
|
||||
Documents are available at [`./docs`](./docs).
|
||||
|
||||
__gyp-next__ is [released](https://github.com/nodejs/gyp-next/releases) to the [__Python Packaging Index__](https://pypi.org/project/gyp-next) (PyPI) and can be installed with the command:
|
||||
* `python3 -m pip install gyp-next`
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
# vs. CMake
|
||||
|
||||
GYP was originally created to generate native IDE project files (Visual Studio, Xcode) for building [Chromium](http://www.chromim.org).
|
||||
|
||||
The functionality of GYP is very similar to the [CMake](http://www.cmake.org)
|
||||
build tool. Bradley Nelson wrote up the following description of why the team
|
||||
created GYP instead of using CMake. The text below is copied from
|
||||
http://www.mail-archive.com/webkit-dev@lists.webkit.org/msg11029.html
|
||||
|
||||
```
|
||||
|
||||
Re: [webkit-dev] CMake as a build system?
|
||||
Bradley Nelson
|
||||
Mon, 19 Apr 2010 22:38:30 -0700
|
||||
|
||||
Here's the innards of an email with a laundry list of stuff I came up with a
|
||||
while back on the gyp-developers list in response to Mike Craddick regarding
|
||||
what motivated gyp's development, since we were aware of cmake at the time
|
||||
(we'd even started a speculative port):
|
||||
|
||||
|
||||
I did an exploratory port of portions of Chromium to cmake (I think I got as
|
||||
far as net, base, sandbox, and part of webkit).
|
||||
There were a number of motivations, not all of which would apply to other
|
||||
projects. Also, some of the design of gyp was informed by experience at
|
||||
Google with large projects built wholly from source, leading to features
|
||||
absent from cmake, but not strictly required for Chromium.
|
||||
|
||||
1. Ability to incrementally transition on Windows. It took us about 6 months
|
||||
to switch fully to gyp. Previous attempts to move to scons had taken a long
|
||||
time and failed, due to the requirement to transition while in flight. For a
|
||||
substantial period of time, we had a hybrid of checked in vcproj and gyp generated
|
||||
vcproj. To this day we still have a good number of GUIDs pinned in the gyp files,
|
||||
because different parts of our release pipeline have leftover assumptions
|
||||
regarding manipulating the raw sln/vcprojs. This transition occurred from
|
||||
the bottom up, largely because modules like base were easier to convert, and
|
||||
had a lower churn rate. During early stages of the transition, the majority
|
||||
of the team wasn't even aware they were using gyp, as it integrated into
|
||||
their existing workflow, and only affected modules that had been converted.
|
||||
|
||||
2. Generation of a more 'normal' vcproj file. Gyp attempts, particularly on
|
||||
Windows, to generate vcprojs which resemble hand generated projects. It
|
||||
doesn't generate any Makefile type projects, but instead produces msvs
|
||||
Custom Build Steps and Custom Build Rules. This makes the resulting projects
|
||||
easier to understand from the IDE and avoids parts of the IDE that simply
|
||||
don't function correctly if you use Makefile projects. Our early hope with
|
||||
gyp was to support the least common denominator of features present in each
|
||||
of the platform specific project file formats, rather than falling back on
|
||||
generated Makefiles/shell scripts to emulate some common abstraction. CMake by
|
||||
comparison makes a good faith attempt to use native project features, but
|
||||
falls back on generated scripts in order to preserve the same semantics on
|
||||
each platforms.
|
||||
|
||||
3. Abstraction on the level of project settings, rather than command line
|
||||
flags. In gyp's syntax you can add nearly any option present in a hand
|
||||
generated xcode/vcproj file. This allows you to use abstractions built into
|
||||
the IDEs rather than reverse engineering them possibly incorrectly for
|
||||
things like: manifest generation, precompiled headers, bundle generation.
|
||||
When somebody wants to use a particular menu option from msvs, I'm able to
|
||||
do a web search on the name of the setting from the IDE and provide them
|
||||
with a gyp stanza that does the equivalent. In many cases, not all project
|
||||
file constructs correspond to command line flags.
|
||||
|
||||
4. Strong notion of module public/private interface. Gyp allows targets to
|
||||
publish a set of direct_dependent_settings, specifying things like
|
||||
include_dirs, defines, platforms specific settings, etc. This means that
|
||||
when module A depends on module B, it automatically acquires the right build
|
||||
settings without module A being filled with assumptions/knowledge of exactly
|
||||
how module B is built. Additionally, all of the transitive dependencies of
|
||||
module B are pulled in. This avoids their being a single top level view of
|
||||
the project, rather each gyp file expresses knowledge about its immediate
|
||||
neighbors. This keep local knowledge local. CMake effectively has a large
|
||||
shared global namespace.
|
||||
|
||||
5. Cross platform generation. CMake is not able to generate all project
|
||||
files on all platforms. For example xcode projects cannot be generated from
|
||||
windows (cmake uses mac specific libraries to do project generation). This
|
||||
means that for instance generating a tarball containing pregenerated
|
||||
projects for all platforms is hard with Cmake (requires distribution to
|
||||
several machine types).
|
||||
|
||||
6. Gyp has rudimentary cross compile support. Currently we've added enough
|
||||
functionality to gyp to support x86 -> arm cross compiles. Last I checked
|
||||
this functionality wasn't present in cmake. (This occurred later).
|
||||
|
||||
|
||||
That being said there are a number of drawbacks currently to gyp:
|
||||
|
||||
1. Because platform specific settings are expressed at the project file
|
||||
level (rather than the command line level). Settings which might otherwise
|
||||
be shared in common between platforms (flags to gcc on mac/linux), end up
|
||||
being repeated twice. Though in fairness there is actually less sharing here
|
||||
than you'd think. include_dirs and defines actually represent 90% of what
|
||||
can be typically shared.
|
||||
|
||||
2. CMake may be more mature, having been applied to a broader range of
|
||||
projects. There a number of 'tool modules' for cmake, which are shared in a
|
||||
common community.
|
||||
|
||||
3. gyp currently makes some nasty assumptions about the availability of
|
||||
chromium's hermetic copy of cygwin on windows. This causes you to either
|
||||
have to special case a number of rules, or swallow this copy of cygwin as a
|
||||
build time dependency.
|
||||
|
||||
4. CMake includes a fairly readable imperative language. Currently Gyp has a
|
||||
somewhat poorly specified declarative language (variable expansion happens
|
||||
in sometimes weird and counter-intuitive ways). In fairness though, gyp assumes
|
||||
that external python scripts can be used as an escape hatch. Also gyp avoids
|
||||
a lot of the things you'd need imperative code for, by having a nice target
|
||||
settings publication mechanism.
|
||||
|
||||
5. (Feature/drawback depending on personal preference). Gyp's syntax is
|
||||
DEEPLY nested. It suffers from all of Lisp's advantages and drawbacks.
|
||||
|
||||
-BradN
|
||||
```
|
|
@ -0,0 +1,46 @@
|
|||
# Hacking
|
||||
|
||||
## Getting the sources
|
||||
|
||||
Git is required to hack on anything, you can set up a git clone of GYP
|
||||
as follows:
|
||||
|
||||
```
|
||||
mkdir foo
|
||||
cd foo
|
||||
git clone git@github.com:nodejs/gyp-next.git
|
||||
cd gyp
|
||||
```
|
||||
|
||||
(this will clone gyp underneath it into `foo/gyp`.
|
||||
`foo` can be any directory name you want. Once you've done that,
|
||||
you can use the repo like anything other Git repo.
|
||||
|
||||
## Testing your change
|
||||
|
||||
GYP has a suite of tests which you can run with the provided test driver
|
||||
to make sure your changes aren't breaking anything important.
|
||||
|
||||
You run the test driver with e.g.
|
||||
|
||||
``` sh
|
||||
$ python -m pip install --upgrade pip setuptools
|
||||
$ pip install --editable ".[dev]"
|
||||
$ python -m pytest
|
||||
```
|
||||
|
||||
See [Testing](Testing.md) for more details on the test framework.
|
||||
|
||||
Note that it can be handy to look at the project files output by the tests
|
||||
to diagnose problems. The easiest way to do that is by kindly asking the
|
||||
test driver to leave the temporary directories it creates in-place.
|
||||
This is done by setting the enviroment variable "PRESERVE", e.g.
|
||||
|
||||
```
|
||||
set PRESERVE=all # On Windows
|
||||
export PRESERVE=all # On saner platforms.
|
||||
```
|
||||
|
||||
## Reviewing your change
|
||||
|
||||
All changes to GYP must be code reviewed before submission.
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,430 @@
|
|||
# Language Specification
|
||||
|
||||
## Objective
|
||||
|
||||
Create a tool for the Chromium project that generates native Visual Studio,
|
||||
Xcode and SCons and/or make build files from a platform-independent input
|
||||
format. Make the input format as reasonably general as possible without
|
||||
spending extra time trying to "get everything right," except where not doing so
|
||||
would likely lead Chromium to an eventual dead end. When in doubt, do what
|
||||
Chromium needs and don't worry about generalizing the solution.
|
||||
|
||||
## Background
|
||||
|
||||
Numerous other projects, both inside and outside Google, have tried to
|
||||
create a simple, universal cross-platform build representation that
|
||||
still allows sufficient per-platform flexibility to accommodate
|
||||
irreconcilable differences. The fact that no obvious working candidate
|
||||
exists that meets Chromium's requirements indicates this is probably a
|
||||
tougher problem than it appears at first glance. We aim to succeed by
|
||||
creating a tool that is highly specific to Chromium's specific use case,
|
||||
not to the general case of design a completely platform-independent tool
|
||||
for expressing any possible build.
|
||||
|
||||
The Mac has the most sophisticated model for application development
|
||||
through an IDE. Consequently, we will use the Xcode model as the
|
||||
starting point (the input file format must handle Chromium's use of
|
||||
Xcode seamlessly) and adapt the design as necessary for the other
|
||||
platforms.
|
||||
|
||||
## Overview
|
||||
|
||||
The overall design has the following characteristics:
|
||||
|
||||
* Input configurations are specified in files with the suffix `.gyp`.
|
||||
* Each `.gyp` file specifies how to build the targets for the
|
||||
"component" defined by that file.
|
||||
* Each `.gyp` file generates one or more output files appropriate to
|
||||
the platform:
|
||||
* On Mac, a `.gyp` file generates one Xcode .xcodeproj bundle with
|
||||
information about how its targets are built.
|
||||
* On Windows, a `.gyp` file generates one Visual Studio .sln file,
|
||||
and one Visual Studio .vcproj file per target.
|
||||
* On Linux, a `.gyp` file generates one SCons file and/or one
|
||||
Makefile per target
|
||||
* The `.gyp` file syntax is a Python data structure.
|
||||
* Use of arbitrary Python in `.gyp` files is forbidden.
|
||||
* Use of eval() with restricted globals and locals on `.gyp` file
|
||||
contents restricts the input to an evaluated expression, not
|
||||
arbitrary Python statements.
|
||||
* All input is expected to comply with JSON, with two exceptions:
|
||||
the # character (not inside strings) begins a comment that lasts
|
||||
until the end of the line, and trailing commas are permitted at
|
||||
the end of list and dict contents.
|
||||
* Input data is a dictionary of keywords and values.
|
||||
* "Invalid" keywords on any given data structure are not illegal,
|
||||
they're just ignored.
|
||||
* TODO: providing warnings on use of illegal keywords would help
|
||||
users catch typos. Figure out something nice to do with this.
|
||||
|
||||
## Detailed Design
|
||||
|
||||
Some up-front design principles/thoughts/TODOs:
|
||||
|
||||
* Re-use keywords consistently.
|
||||
* Keywords that allow configuration of a platform-specific concept get
|
||||
prefixed appropriately:
|
||||
* Examples: `msvs_disabled_warnings`, `xcode_framework_dirs`
|
||||
* The input syntax is declarative and data-driven.
|
||||
* This gets enforced by using Python `eval()` (which only evaluates
|
||||
an expression) instead of `exec` (which executes arbitrary python)
|
||||
* Semantic meanings of specific keyword values get deferred until all
|
||||
are read and the configuration is being evaluated to spit out the
|
||||
appropriate file(s)
|
||||
* Source file lists:
|
||||
* Are flat lists. Any imposed ordering within the `.gyp` file (e.g.
|
||||
alphabetically) is purely by convention and for developer
|
||||
convenience. When source files are linked or archived together,
|
||||
it is expected that this will occur in the order that files are
|
||||
listed in the `.gyp` file.
|
||||
* Source file lists contain no mechanism for by-hand folder
|
||||
configuration (`Filter` tags in Visual Studio, `Groups` in Xcode)
|
||||
* A folder hierarchy is created automatically that mirrors the file
|
||||
system
|
||||
|
||||
### Example
|
||||
|
||||
```
|
||||
{
|
||||
'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',
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
### Structural Elements
|
||||
|
||||
### Top-level Dictionary
|
||||
|
||||
This is the single dictionary in the `.gyp` file that defines the
|
||||
targets and how they're to be built.
|
||||
|
||||
The following keywords are meaningful within the top-level dictionary
|
||||
definition:
|
||||
|
||||
| *Keyword* | *Description* |
|
||||
|:------------------|:------------------|
|
||||
| `conditions` | A conditional section that may contain other items that can be present in a top-level dictionary, on a conditional basis. See the "Conditionals" section below. |
|
||||
| `includes` | A list of `.gypi` files to be included in the top-level dictionary. |
|
||||
| `target_defaults` | A dictionary of default settings to be inherited by all targets in the top-level dictionary. See the "Settings keywords" section below. |
|
||||
| `targets` | A list of target specifications. See the "targets" below. |
|
||||
| `variables` | A dictionary containing variable definitions. Each key in this dictionary is the name of a variable, and each value must be a string value that the variable is to be set to. |
|
||||
|
||||
### targets
|
||||
|
||||
A list of dictionaries defining targets to be built by the files
|
||||
generated from this `.gyp` file.
|
||||
|
||||
Targets may contain `includes`, `conditions`, and `variables` sections
|
||||
as permitted in the root dictionary. The following additional keywords
|
||||
have structural meaning for target definitions:
|
||||
|
||||
| *Keyword* | *Description* |
|
||||
|:---------------------------- |:------------------------------------------|
|
||||
| `actions` | A list of special custom actions to perform on a specific input file, or files, to produce output files. See the "Actions" section below. |
|
||||
| `all_dependent_settings` | A dictionary of settings to be applied to all dependents of the target, transitively. This includes direct dependents and the entire set of their dependents, and so on. This section may contain anything found within a `target` dictionary, except `configurations`, `target_name`, and `type` sections. Compare `direct_dependent_settings` and `link_settings`. |
|
||||
| `configurations` | A list of dictionaries defining build configurations for the target. See the "Configurations" section below. |
|
||||
| `copies` | A list of copy actions to perform. See the "Copies" section below. |
|
||||
| `defines` | A list of preprocesor definitions to be passed on the command line to the C/C++ compiler (via `-D` or `/D` options). |
|
||||
| `dependencies` | A list of targets on which this target depends. Targets in other `.gyp` files are specified as `../path/to/other.gyp:target_we_want`. |
|
||||
| `direct_dependent_settings` | A dictionary of settings to be applied to other targets that depend on this target. These settings will only be applied to direct dependents. This section may contain anything found within a `target` dictionary, except `configurations`, `target_name`, and `type` sections. Compare with `all_dependent_settings` and `link_settings`. |
|
||||
| `include_dirs` | A list of include directories to be passed on the command line to the C/C++ compiler (via `-I` or `/I` options). |
|
||||
| `libraries` | A list of list of libraries (and/or frameworks) on which this target depends. |
|
||||
| `link_settings` | A dictionary of settings to be applied to targets in which this target's contents are linked. `executable` and `shared_library` targets are linkable, so if they depend on a non-linkable target such as a `static_library`, they will adopt its `link_settings`. This section can contain anything found within a `target` dictionary, except `configurations`, `target_name`, and `type` sections. Compare `all_dependent_settings` and `direct_dependent_settings`. |
|
||||
| `rules` | A special custom action to perform on a list of input files, to produce output files. See the "Rules" section below. |
|
||||
| `sources` | A list of source files that are used to build this target or which should otherwise show up in the IDE for this target. In practice, we expect this list to be a union of all files necessary to build the target on all platforms, as well as other related files that aren't actually used for building, like README files. |
|
||||
| `target_conditions` | Like `conditions`, but evaluation is delayed until the settings have been merged into an actual target. `target_conditions` may be used to place conditionals into a `target_defaults` section but have them still depend on specific target settings. |
|
||||
| `target_name` | The name of a target being defined. |
|
||||
| `type` | The type of target being defined. This field currently supports `executable`, `static_library`, `shared_library`, and `none`. The `none` target type is useful when producing output which is not linked. For example, converting raw translation files into resources or documentation into platform specific help files. |
|
||||
| `msvs_props` | A list of Visual Studio property sheets (`.vsprops` files) to be used to build the target. |
|
||||
| `xcode_config_file` | An Xcode configuration (`.xcconfig` file) to be used to build the target. |
|
||||
| `xcode_framework_dirs` | A list of framework directories be used to build the target. |
|
||||
|
||||
You can affect the way that lists/dictionaries are merged together (for
|
||||
example the way a list in target\_defaults interacts with the same named
|
||||
list in the target itself) with a couple of special characters, which
|
||||
are covered in [Merge
|
||||
Basics](InputFormatReference#Merge_Basics_(=,_?,_+).md) and [List
|
||||
Filters](InputFormatReference#List_Filters.md) on the
|
||||
InputFormatReference page.
|
||||
|
||||
### configurations
|
||||
|
||||
`configurations` sections may be found within `targets` or
|
||||
`target_defaults` sections. The `configurations` section is a list of
|
||||
dictionaries specifying different build configurations. Because
|
||||
configurations are implemented as lists, it is not currently possible to
|
||||
override aspects of configurations that are imported into a target from
|
||||
a `target_defaults` section.
|
||||
|
||||
NOTE: It is extremely important that each target within a project define
|
||||
the same set of configurations. This continues to apply even when a
|
||||
project spans across multiple `.gyp` files.
|
||||
|
||||
A configuration dictionary may contain anything that can be found within
|
||||
a target dictionary, except for `actions`, `all_dependent_settings`,
|
||||
`configurations`, `dependencies`, `direct_dependent_settings`,
|
||||
`libraries`, `link_settings`, `sources`, `target_name`, and `type`.
|
||||
|
||||
Configuration dictionaries may also contain these elements:
|
||||
|
||||
| *Keyword* | *Description* |
|
||||
|:---------------------|:----------------------------------------------------|
|
||||
| `configuration_name` | Required attribute. The name of the configuration. |
|
||||
|
||||
### Conditionals
|
||||
|
||||
Conditionals may appear within any dictionary in a `.gyp` file. There
|
||||
are two tpes of conditionals, which differ only in the timing of their
|
||||
processing. `conditons` sections are processed shortly after loading
|
||||
`.gyp` files, and `target_conditons` sections are processed after all
|
||||
dependencies have been computed.
|
||||
|
||||
A conditional section is introduced with a `conditions` or
|
||||
`target_conditions` dictionary keyword, and is composed of a list. Each
|
||||
list contains two or three elements. The first two elements, which are
|
||||
always required, are the conditional expression to evaluate and a
|
||||
dictionary containing settings to merge into the dictionary containing
|
||||
the `conditions` or `target_conditions` section if the expression
|
||||
evaluates to true. The third, optional, list element is a dictionary to
|
||||
merge if the expression evaluates to false.
|
||||
|
||||
The `eval()` of the expression string takes place in the context of
|
||||
global and/or local dictionaries that constructed from the `.gyp` input
|
||||
data, and overrides the `__builtin__` dictionary, to prevent the
|
||||
execution of arbitrary Python code.
|
||||
|
||||
### Actions
|
||||
|
||||
An `actions` section provides a list of custom build actions to perform
|
||||
on inputs, producing outputs. The `actions` section is organized as a
|
||||
list. Each item in the list is a dictionary having the following form:
|
||||
|
||||
| *Keyword* | *Type* | *Description* |
|
||||
|:--------------|:-------|:-----------------------------|
|
||||
| `action_name` | string | The name of the action. Depending on how actions are implemented in the various generators, some may desire or require this property to be set to a unique name; others may ignore this property entirely. |
|
||||
| `inputs` | list | A list of pathnames treated as inputs to the custom action. |
|
||||
| `outputs` | list | A list of pathnames that the custom action produces. |
|
||||
| `action` | list | A command line invocation used to produce `outputs` from `inputs`. For maximum cross-platform compatibility, invocations that require a Python interpreter should be specified with a first element `"python"`. This will enable generators for environments with specialized Python installations to be able to perform the action in an appropriate Python environment. |
|
||||
| `message` | string | A message to be displayed to the user by the build system when the action is run. |
|
||||
|
||||
Build environments will compare `inputs` and `outputs`. If any `output`
|
||||
is missing or is outdated relative to any `input`, the custom action
|
||||
will be invoked. If all `outputs` are present and newer than all
|
||||
`inputs`, the `outputs` are considered up-to-date and the action need
|
||||
not be invoked.
|
||||
|
||||
Actions are implemented in Xcode as shell script build phases performed
|
||||
prior to the compilation phase. In the Visual Studio generator, actions
|
||||
appear files with a `FileConfiguration` containing a custom
|
||||
`VCCustomBuildTool` specifying the remainder of the inputs, the outputs,
|
||||
and the action.
|
||||
|
||||
Combined with variable expansions, actions can be quite powerful. Here
|
||||
is an example action that leverages variable expansions to minimize
|
||||
duplication of pathnames:
|
||||
|
||||
```
|
||||
'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
|
||||
|
||||
A `rules` section provides custom build action to perform on inputs, producing
|
||||
outputs. The `rules` section is organized as a list. Each item in the list is
|
||||
a dictionary having the following form:
|
||||
|
||||
| *Keyword* | *Type* | *Description* |
|
||||
|:------------|:-------|:-----------------------------------------|
|
||||
| `rule_name` | string | The name of the rule. Depending on how Rules are implemented in the various generators, some may desire or require this property to be set to a unique name; others may ignore this property entirely. |
|
||||
| `extension` | string | All source files of the current target with the given extension will be treated successively as inputs to the rule. |
|
||||
| `inputs` | list | Additional dependencies of the rule. |
|
||||
| `outputs` | list | A list of pathnames that the rule produces. Has access to `RULE_INPUT_` variables (see below). |
|
||||
| `action` | list | A command line invocation used to produce `outputs` from `inputs`. For maximum cross-platform compatibility, invocations that require a Python interpreter should be specified with a first element `"python"`. This will enable generators for environments with specialized Python installations to be able to perform the action in an appropriate Python environment. Has access to `RULE_INPUT_` variables (see below). |
|
||||
| `message` | string | A message to be displayed to the user by the build system when the action is run. Has access to `RULE_INPUT_` variables (see below). |
|
||||
|
||||
There are several variables available to `outputs`, `action`, and `message`.
|
||||
|
||||
| *Variable* | *Description* |
|
||||
|:---------------------|:------------------------------------|
|
||||
| `RULE_INPUT_PATH` | The full path to the current input. |
|
||||
| `RULE_INPUT_DIRNAME` | The directory of the current input. |
|
||||
| `RULE_INPUT_NAME` | The file name of the current input. |
|
||||
| `RULE_INPUT_ROOT` | The file name of the current input without extension. |
|
||||
| `RULE_INPUT_EXT` | The file name extension of the current input. |
|
||||
|
||||
Rules can be thought of as Action generators. For each source selected
|
||||
by `extension` an special action is created. This action starts out with
|
||||
the same `inputs`, `outputs`, `action`, and `message` as the rule. The
|
||||
source is added to the action's `inputs`. The `outputs`, `action`, and
|
||||
`message` are then handled the same but with the additional variables.
|
||||
If the `_output` variable is used in the `action` or `message` the
|
||||
`RULE_INPUT_` variables in `output` will be expanded for the current
|
||||
source.
|
||||
|
||||
### Copies
|
||||
|
||||
A `copies` section provides a simple means of copying files. The
|
||||
`copies` section is organized as a list. Each item in the list is a
|
||||
dictionary having the following form:
|
||||
|
||||
| *Keyword* | *Type* | *Description* |
|
||||
|:--------------|:-------|:------------------------------|
|
||||
| `destination` | string | The directory into which the `files` will be copied. |
|
||||
| `files` | list | A list of files to be copied. |
|
||||
|
||||
The copies will be created in `destination` and have the same file name
|
||||
as the file they are copied from. Even if the `files` are from multiple
|
||||
directories they will all be copied into the `destination` directory.
|
||||
Each `destination` file has an implicit build dependency on the file it
|
||||
is copied from.
|
||||
|
||||
### Generated Xcode .pbxproj Files
|
||||
|
||||
We derive the following things in a `project.pbxproj` plist file within
|
||||
an `.xcodeproj` bundle from the above input file formats as follows:
|
||||
|
||||
* `Group hierarchy`: This is generated in a fixed format with contents
|
||||
derived from the input files. There is no provision for the user to
|
||||
specify additional groups or create a custom hierarchy.
|
||||
* `Configuration group`: This will be used with the
|
||||
`xcode_config_file` property above, if needed.
|
||||
* `Source group`: The union of the `sources` lists of all `targets`
|
||||
after applying appropriate `conditions`. The resulting list is
|
||||
sorted and put into a group hierarchy that matches the layout of
|
||||
the directory tree on disk, with a root of // (the top of the
|
||||
hierarchy).
|
||||
* `Frameworks group`: Taken directly from `libraries` value for the
|
||||
target, after applying appropriate conditions.
|
||||
* `Projects group`: References to other `.xcodeproj` bundles that
|
||||
are needed by the `.xcodeproj` in which the group is contained.
|
||||
* `Products group`: Output from the various targets.
|
||||
* `Project References`:
|
||||
* `Project Configurations`:
|
||||
* Per-`.xcodeproj` file settings are not supported, all settings are
|
||||
applied at the target level.
|
||||
* `Targets`:
|
||||
* `Phases`: Copy sources, link with libraries/frameworks, ...
|
||||
* `Target Configurations`: Specified by input.
|
||||
* `Dependencies`: (local and remote)
|
||||
|
||||
### Generated Visual Studio .vcproj Files
|
||||
|
||||
We derive the following sections in a `.vcproj` file from the above
|
||||
input file formats as follows:
|
||||
|
||||
* `VisualStudioProject`:
|
||||
* `Platforms`:
|
||||
* `ToolFiles`:
|
||||
* `Configurations`:
|
||||
* `Configuration`:
|
||||
* `References`:
|
||||
* `Files`:
|
||||
* `Filter`:
|
||||
* `File`:
|
||||
* `FileConfiguration`:
|
||||
* `Tool`:
|
||||
* `Globals`:
|
||||
|
||||
### Generated Visual Studio .sln Files
|
||||
|
||||
We derive the following sections in a `.sln` file from the above input
|
||||
file formats as follows:
|
||||
|
||||
* `Projects`:
|
||||
* `WebsiteProperties`:
|
||||
* `ProjectDependencies`:
|
||||
* `Global`:
|
||||
* `SolutionConfigurationPlatforms`:
|
||||
* `ProjectConfigurationPlatforms`:
|
||||
* `SolutionProperties`:
|
||||
* `NestedProjects`:
|
||||
|
||||
## Caveats
|
||||
|
||||
Notes/Question from very first prototype draft of the language.
|
||||
Make sure these issues are addressed somewhere before deleting.
|
||||
|
||||
* Libraries are easy, application abstraction is harder
|
||||
* Applications involves resource compilation
|
||||
* Applications involve many inputs
|
||||
* Applications include transitive closure of dependencies
|
||||
* Specific use cases like cc\_library
|
||||
* Mac compiles more than just .c/.cpp files (specifically, .m and .mm
|
||||
files)
|
||||
* Compiler options vary by:
|
||||
* File type
|
||||
* Target type
|
||||
* Individual file
|
||||
* Files may have custom settings per file per platform, but we probably
|
||||
don't care or need to support this in gyp.
|
||||
* Will all linked non-Chromium projects always use the same versions of every
|
||||
subsystem?
|
||||
* Variants are difficult. We've identified the following variants (some
|
||||
specific to Chromium, some typical of other projects in the same ballpark):
|
||||
* Target platform
|
||||
* V8 vs. JSC
|
||||
* Debug vs. Release
|
||||
* Toolchain (VS version, gcc, version)
|
||||
* Host platform
|
||||
* L10N
|
||||
* Vendor
|
||||
* Purify / Valgrind
|
||||
* Will everyone upgrade VS at once?
|
||||
* What does a dylib dependency mean?
|
|
@ -0,0 +1,27 @@
|
|||
# Generate Your Projects (gyp-next)
|
||||
|
||||
GYP is a Meta-Build system: a build system that generates other build systems.
|
||||
|
||||
* [User documentation](./UserDocumentation.md)
|
||||
* [Input Format Reference](./InputFormatReference.md)
|
||||
* [Language specification](./LanguageSpecification.md)
|
||||
* [Hacking](./Hacking.md)
|
||||
* [Testing](./Testing.md)
|
||||
* [GYP vs. CMake](./GypVsCMake.md)
|
||||
|
||||
GYP is intended to support large projects that need to be built on multiple
|
||||
platforms (e.g., Mac, Windows, Linux), and where it is important that
|
||||
the project can be built using the IDEs that are popular on each platform
|
||||
as if the project is a "native" one.
|
||||
|
||||
It can be used to generate XCode projects, Visual Studio projects, Ninja
|
||||
build files, and Makefiles. In each case GYP's goal is to replicate as
|
||||
closely as possible the way one would set up a native build of the project
|
||||
using the IDE.
|
||||
|
||||
GYP can also be used to generate "hybrid" projects that provide the IDE
|
||||
scaffolding for a nice user experience but call out to Ninja to do the actual
|
||||
building (which is usually much faster than the native build systems of the
|
||||
IDEs).
|
||||
|
||||
For more information on GYP, click on the links above.
|
|
@ -0,0 +1,450 @@
|
|||
# Testing
|
||||
|
||||
NOTE: this document is outdated and needs to be updated. Read with your own discretion.
|
||||
|
||||
## Introduction
|
||||
|
||||
This document describes the GYP testing infrastructure,
|
||||
as provided by the `TestGyp.py` module.
|
||||
|
||||
These tests emphasize testing the _behavior_ of the
|
||||
various GYP-generated build configurations:
|
||||
Visual Studio, Xcode, SCons, Make, etc.
|
||||
The goal is _not_ to test the output of the GYP generators by,
|
||||
for example, comparing a GYP-generated Makefile
|
||||
against a set of known "golden" Makefiles
|
||||
(although the testing infrastructure could
|
||||
be used to write those kinds of tests).
|
||||
The idea is that the generated build configuration files
|
||||
could be completely written to add a feature or fix a bug
|
||||
so long as they continue to support the functional behaviors
|
||||
defined by the tests: building programs, shared libraries, etc.
|
||||
|
||||
## "Hello, world!" GYP test configuration
|
||||
|
||||
Here is an actual test configuration,
|
||||
a simple build of a C program to print `"Hello, world!"`.
|
||||
|
||||
```
|
||||
$ ls -l test/hello
|
||||
total 20
|
||||
-rw-r--r-- 1 knight knight 312 Jul 30 20:22 gyptest-all.py
|
||||
-rw-r--r-- 1 knight knight 307 Jul 30 20:22 gyptest-default.py
|
||||
-rwxr-xr-x 1 knight knight 326 Jul 30 20:22 gyptest-target.py
|
||||
-rw-r--r-- 1 knight knight 98 Jul 30 20:22 hello.c
|
||||
-rw-r--r-- 1 knight knight 142 Jul 30 20:22 hello.gyp
|
||||
$
|
||||
```
|
||||
|
||||
The `gyptest-*.py` files are three separate tests (test scripts)
|
||||
that use this configuration. The first one, `gyptest-all.py`,
|
||||
looks like this:
|
||||
|
||||
```
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Verifies simplest-possible build of a "Hello, world!" program
|
||||
using an explicit build target of 'all'.
|
||||
"""
|
||||
|
||||
import TestGyp
|
||||
|
||||
test = TestGyp.TestGyp()
|
||||
|
||||
test.run_gyp('hello.gyp')
|
||||
|
||||
test.build_all('hello.gyp')
|
||||
|
||||
test.run_built_executable('hello', stdout="Hello, world!\n")
|
||||
|
||||
test.pass_test()
|
||||
```
|
||||
|
||||
The test script above runs GYP against the specified input file
|
||||
(`hello.gyp`) to generate a build configuration.
|
||||
It then tries to build the `'all'` target
|
||||
(or its equivalent) using the generated build configuration.
|
||||
Last, it verifies that the build worked as expected
|
||||
by running the executable program (`hello`)
|
||||
that was just presumably built by the generated configuration,
|
||||
and verifies that the output from the program
|
||||
matches the expected `stdout` string (`"Hello, world!\n"`).
|
||||
|
||||
Which configuration is generated
|
||||
(i.e., which build tool to test)
|
||||
is specified when the test is run;
|
||||
see the next section.
|
||||
|
||||
Surrounding the functional parts of the test
|
||||
described above are the header,
|
||||
which should be basically the same for each test
|
||||
(modulo a different description in the docstring):
|
||||
|
||||
```
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Verifies simplest-possible build of a "Hello, world!" program
|
||||
using an explicit build target of 'all'.
|
||||
"""
|
||||
|
||||
import TestGyp
|
||||
|
||||
test = TestGyp.TestGyp()
|
||||
```
|
||||
|
||||
Similarly, the footer should be the same in every test:
|
||||
|
||||
```
|
||||
test.pass_test()
|
||||
```
|
||||
|
||||
## Running tests
|
||||
|
||||
Test scripts are run by the `gyptest.py` script.
|
||||
You can specify (an) explicit test script(s) to run:
|
||||
|
||||
```
|
||||
$ python gyptest.py test/hello/gyptest-all.py
|
||||
PYTHONPATH=/home/knight/src/gyp/trunk/test/lib
|
||||
TESTGYP_FORMAT=scons
|
||||
/usr/bin/python test/hello/gyptest-all.py
|
||||
PASSED
|
||||
$
|
||||
```
|
||||
|
||||
If you specify a directory, all test scripts
|
||||
(scripts prefixed with `gyptest-`) underneath
|
||||
the directory will be run:
|
||||
|
||||
```
|
||||
$ python gyptest.py test/hello
|
||||
PYTHONPATH=/home/knight/src/gyp/trunk/test/lib
|
||||
TESTGYP_FORMAT=scons
|
||||
/usr/bin/python test/hello/gyptest-all.py
|
||||
PASSED
|
||||
/usr/bin/python test/hello/gyptest-default.py
|
||||
PASSED
|
||||
/usr/bin/python test/hello/gyptest-target.py
|
||||
PASSED
|
||||
$
|
||||
```
|
||||
|
||||
Or you can specify the `-a` option to run all scripts
|
||||
in the tree:
|
||||
|
||||
```
|
||||
$ python gyptest.py -a
|
||||
PYTHONPATH=/home/knight/src/gyp/trunk/test/lib
|
||||
TESTGYP_FORMAT=scons
|
||||
/usr/bin/python test/configurations/gyptest-configurations.py
|
||||
PASSED
|
||||
/usr/bin/python test/defines/gyptest-defines.py
|
||||
PASSED
|
||||
.
|
||||
.
|
||||
.
|
||||
.
|
||||
/usr/bin/python test/variables/gyptest-commands.py
|
||||
PASSED
|
||||
$
|
||||
```
|
||||
|
||||
If any tests fail during the run,
|
||||
the `gyptest.py` script will report them in a
|
||||
summary at the end.
|
||||
|
||||
## Debugging tests
|
||||
|
||||
Tests that create intermediate output do so under the gyp/out/testworkarea
|
||||
directory. On test completion, intermediate output is cleaned up. To preserve
|
||||
this output, set the environment variable PRESERVE=1. This can be handy to
|
||||
inspect intermediate data when debugging a test.
|
||||
|
||||
You can also set PRESERVE\_PASS=1, PRESERVE\_FAIL=1 or PRESERVE\_NO\_RESULT=1
|
||||
to preserve output for tests that fall into one of those categories.
|
||||
|
||||
# Specifying the format (build tool) to use
|
||||
|
||||
By default, the `gyptest.py` script will generate configurations for
|
||||
the "primary" supported build tool for the platform you're on:
|
||||
Visual Studio on Windows,
|
||||
Xcode on Mac,
|
||||
and (currently) SCons on Linux.
|
||||
An alternate format (build tool) may be specified
|
||||
using the `-f` option:
|
||||
|
||||
```
|
||||
$ python gyptest.py -f make test/hello/gyptest-all.py
|
||||
PYTHONPATH=/home/knight/src/gyp/trunk/test/lib
|
||||
TESTGYP_FORMAT=make
|
||||
/usr/bin/python test/hello/gyptest-all.py
|
||||
PASSED
|
||||
$
|
||||
```
|
||||
|
||||
Multiple tools may be specified in a single pass as
|
||||
a comma-separated list:
|
||||
|
||||
```
|
||||
$ python gyptest.py -f make,scons test/hello/gyptest-all.py
|
||||
PYTHONPATH=/home/knight/src/gyp/trunk/test/lib
|
||||
TESTGYP_FORMAT=make
|
||||
/usr/bin/python test/hello/gyptest-all.py
|
||||
PASSED
|
||||
TESTGYP_FORMAT=scons
|
||||
/usr/bin/python test/hello/gyptest-all.py
|
||||
PASSED
|
||||
$
|
||||
```
|
||||
|
||||
## Test script functions and methods
|
||||
|
||||
The `TestGyp` class contains a lot of functionality
|
||||
intended to make it easy to write tests.
|
||||
This section describes the most useful pieces for GYP testing.
|
||||
|
||||
(The `TestGyp` class is actually a subclass of more generic
|
||||
`TestCommon` and `TestCmd` base classes
|
||||
that contain even more functionality than is
|
||||
described here.)
|
||||
|
||||
### Initialization
|
||||
|
||||
The standard initialization formula is:
|
||||
|
||||
```
|
||||
import TestGyp
|
||||
test = TestGyp.TestGyp()
|
||||
```
|
||||
|
||||
This copies the contents of the directory tree in which
|
||||
the test script lives to a temporary directory for execution,
|
||||
and arranges for the temporary directory's removal on exit.
|
||||
|
||||
By default, any comparisons of output or file contents
|
||||
must be exact matches for the test to pass.
|
||||
If you need to use regular expressions for matches,
|
||||
a useful alternative initialization is:
|
||||
|
||||
```
|
||||
import TestGyp
|
||||
test = TestGyp.TestGyp(match = TestGyp.match_re,
|
||||
diff = TestGyp.diff_re)`
|
||||
```
|
||||
|
||||
### Running GYP
|
||||
|
||||
The canonical invocation is to simply specify the `.gyp` file to be executed:
|
||||
|
||||
```
|
||||
test.run_gyp('file.gyp')
|
||||
```
|
||||
|
||||
Additional GYP arguments may be specified:
|
||||
|
||||
```
|
||||
test.run_gyp('file.gyp', arguments=['arg1', 'arg2', ...])
|
||||
```
|
||||
|
||||
To execute GYP from a subdirectory (where, presumably, the specified file
|
||||
lives):
|
||||
|
||||
```
|
||||
test.run_gyp('file.gyp', chdir='subdir')
|
||||
```
|
||||
|
||||
### Running the build tool
|
||||
|
||||
Running the build tool requires passing in a `.gyp` file, which may be used to
|
||||
calculate the name of a specific build configuration file (such as a MSVS
|
||||
solution file corresponding to the `.gyp` file).
|
||||
|
||||
There are several different `.build_*()` methods for invoking different types
|
||||
of builds.
|
||||
|
||||
To invoke a build tool with an explicit `all` target (or equivalent):
|
||||
|
||||
```
|
||||
test.build_all('file.gyp')
|
||||
```
|
||||
|
||||
To invoke a build tool with its default behavior (for example, executing `make`
|
||||
with no targets specified):
|
||||
|
||||
```
|
||||
test.build_default('file.gyp')
|
||||
```
|
||||
|
||||
To invoke a build tool with an explicit specified target:
|
||||
|
||||
```
|
||||
test.build_target('file.gyp', 'target')
|
||||
```
|
||||
|
||||
### Running executables
|
||||
|
||||
The most useful method executes a program built by the GYP-generated
|
||||
configuration:
|
||||
|
||||
```
|
||||
test.run_built_executable('program')
|
||||
```
|
||||
|
||||
The `.run_built_executable()` method will account for the actual built target
|
||||
output location for the build tool being tested, as well as tack on any
|
||||
necessary executable file suffix for the platform (for example `.exe` on
|
||||
Windows).
|
||||
|
||||
`stdout=` and `stderr=` keyword arguments specify expected standard output and
|
||||
error output, respectively. Failure to match these (if specified) will cause
|
||||
the test to fail. An explicit `None` value will suppress that verification:
|
||||
|
||||
```
|
||||
test.run_built_executable('program',
|
||||
stdout="expect this output\n",
|
||||
stderr=None)
|
||||
```
|
||||
|
||||
Note that the default values are `stdout=None` and `stderr=''` (that is, no
|
||||
check for standard output, and error output must be empty).
|
||||
|
||||
Arbitrary executables (not necessarily those built by GYP) can be executed with
|
||||
the lower-level `.run()` method:
|
||||
|
||||
```
|
||||
test.run('program')
|
||||
```
|
||||
|
||||
The program must be in the local directory (that is, the temporary directory
|
||||
for test execution) or be an absolute path name.
|
||||
|
||||
### Fetching command output
|
||||
|
||||
```
|
||||
test.stdout()
|
||||
```
|
||||
|
||||
Returns the standard output from the most recent executed command (including
|
||||
`.run_gyp()`, `.build_*()`, or `.run*()` methods).
|
||||
|
||||
```
|
||||
test.stderr()
|
||||
```
|
||||
|
||||
Returns the error output from the most recent executed command (including
|
||||
`.run_gyp()`, `.build_*()`, or `.run*()` methods).
|
||||
|
||||
### Verifying existence or non-existence of files or directories
|
||||
|
||||
```
|
||||
test.must_exist('file_or_dir')
|
||||
```
|
||||
|
||||
Verifies that the specified file or directory exists, and fails the test if it
|
||||
doesn't.
|
||||
|
||||
```
|
||||
test.must_not_exist('file_or_dir')
|
||||
```
|
||||
|
||||
Verifies that the specified file or directory does not exist, and fails the
|
||||
test if it does.
|
||||
|
||||
### Verifying file contents
|
||||
|
||||
```
|
||||
test.must_match('file', 'expected content\n')
|
||||
```
|
||||
|
||||
Verifies that the content of the specified file match the expected string, and
|
||||
fails the test if it does not. By default, the match must be exact, but
|
||||
line-by-line regular expressions may be used if the `TestGyp` object was
|
||||
initialized with `TestGyp.match_re`.
|
||||
|
||||
```
|
||||
test.must_not_match('file', 'expected content\n')
|
||||
```
|
||||
|
||||
Verifies that the content of the specified file does _not_ match the expected
|
||||
string, and fails the test if it does. By default, the match must be exact,
|
||||
but line-by-line regular expressions may be used if the `TestGyp` object was
|
||||
initialized with `TestGyp.match_re`.
|
||||
|
||||
```
|
||||
test.must_contain('file', 'substring')
|
||||
```
|
||||
|
||||
Verifies that the specified file contains the specified substring, and fails
|
||||
the test if it does not.
|
||||
|
||||
```
|
||||
test.must_not_contain('file', 'substring')
|
||||
```
|
||||
|
||||
Verifies that the specified file does not contain the specified substring, and
|
||||
fails the test if it does.
|
||||
|
||||
```
|
||||
test.must_contain_all_lines(output, lines)
|
||||
```
|
||||
|
||||
Verifies that the output string contains all of the "lines" in the specified
|
||||
list of lines. In practice, the lines can be any substring and need not be
|
||||
`\n`-terminaed lines per se. If any line is missing, the test fails.
|
||||
|
||||
```
|
||||
test.must_not_contain_any_lines(output, lines)
|
||||
```
|
||||
|
||||
Verifies that the output string does _not_ contain any of the "lines" in the
|
||||
specified list of lines. In practice, the lines can be any substring and need
|
||||
not be `\n`-terminaed lines per se. If any line exists in the output string,
|
||||
the test fails.
|
||||
|
||||
```
|
||||
test.must_contain_any_line(output, lines)
|
||||
```
|
||||
|
||||
Verifies that the output string contains at least one of the "lines" in the
|
||||
specified list of lines. In practice, the lines can be any substring and need
|
||||
not be `\n`-terminaed lines per se. If none of the specified lines is present,
|
||||
the test fails.
|
||||
|
||||
### Reading file contents
|
||||
|
||||
```
|
||||
test.read('file')
|
||||
```
|
||||
|
||||
Returns the contents of the specified file. Directory elements contained in a
|
||||
list will be joined:
|
||||
|
||||
```
|
||||
test.read(['subdir', 'file'])
|
||||
```
|
||||
|
||||
### Test success or failure
|
||||
|
||||
```
|
||||
test.fail_test()
|
||||
```
|
||||
|
||||
Fails the test, reporting `FAILED` on standard output and exiting with an exit
|
||||
status of `1`.
|
||||
|
||||
```
|
||||
test.pass_test()
|
||||
```
|
||||
|
||||
Passes the test, reporting `PASSED` on standard output and exiting with an exit
|
||||
status of `0`.
|
||||
|
||||
```
|
||||
test.no_result()
|
||||
```
|
||||
|
||||
Indicates the test had no valid result (i.e., the conditions could not be
|
||||
tested because of an external factor like a full file system). Reports `NO
|
||||
RESULT` on standard output and exits with a status of `2`.
|
|
@ -0,0 +1,965 @@
|
|||
# User Documentation
|
||||
|
||||
## Introduction
|
||||
|
||||
This document is intended to provide a user-level guide to GYP. The
|
||||
emphasis here is on how to use GYP to accomplish specific tasks, not on
|
||||
the complete technical language specification. (For that, see the
|
||||
[LanguageSpecification](LanguageSpecification.md).)
|
||||
|
||||
The document below starts with some overviews to provide context: an
|
||||
overview of the structure of a `.gyp` file itself, an overview of a
|
||||
typical executable-program target in a `.gyp` file, an an overview of a
|
||||
typical library target in a `.gyp` file.
|
||||
|
||||
After the overviews, there are examples of `gyp` patterns for different
|
||||
common use cases.
|
||||
|
||||
## Skeleton of a typical Chromium .gyp file
|
||||
|
||||
Here is the skeleton of a typical `.gyp` file in the Chromium tree:
|
||||
|
||||
```
|
||||
{
|
||||
'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',
|
||||
.
|
||||
.
|
||||
.
|
||||
},
|
||||
}],
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
The entire file just contains a Python dictionary. (It's actually JSON,
|
||||
with two small Pythonic deviations: comments are introduced with `#`,
|
||||
and a `,` (comma)) is legal after the last element in a list or
|
||||
dictionary.)
|
||||
|
||||
The top-level pieces in the `.gyp` file are as follows:
|
||||
|
||||
`'variables'`: Definitions of variables that can be interpolated and
|
||||
used in various other parts of the file.
|
||||
|
||||
`'includes'`: A list of of other files that will be included in this
|
||||
file. By convention, included files have the suffix `.gypi` (gyp
|
||||
include).
|
||||
|
||||
`'target_defaults'`: Settings that will apply to _all_ of the targets
|
||||
defined in this `.gyp` file.
|
||||
|
||||
`'targets'`: The list of targets for which this `.gyp` file can
|
||||
generate builds. Each target is a dictionary that contains settings
|
||||
describing all the information necessary to build the target.
|
||||
|
||||
`'conditions'`: A list of condition specifications that can modify the
|
||||
contents of the items in the global dictionary defined by this `.gyp`
|
||||
file based on the values of different variablwes. As implied by the
|
||||
above example, the most common use of a `conditions` section in the
|
||||
top-level dictionary is to add platform-specific targets to the
|
||||
`targets` list.
|
||||
|
||||
## Skeleton of a typical executable target in a .gyp file
|
||||
|
||||
The most straightforward target is probably a simple executable program.
|
||||
Here is an example `executable` target that demonstrates the features
|
||||
that should cover most simple uses of gyp:
|
||||
|
||||
```
|
||||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'foo',
|
||||
'type': 'executable',
|
||||
'msvs_guid': '5ECEC9E5-8F23-47B6-93E0-C3B328B3BE65',
|
||||
'dependencies': [
|
||||
'xyzzy',
|
||||
'../bar/bar.gyp:bar',
|
||||
],
|
||||
'defines': [
|
||||
'DEFINE_FOO',
|
||||
'DEFINE_A_VALUE=value',
|
||||
],
|
||||
'include_dirs': [
|
||||
'..',
|
||||
],
|
||||
'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',
|
||||
],
|
||||
}]
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
The top-level settings in the target include:
|
||||
|
||||
`'target_name'`: The name by which the target should be known, which
|
||||
should be unique across all `.gyp` files. This name will be used as the
|
||||
project name in the generated Visual Studio solution, as the target name
|
||||
in the generated XCode configuration, and as the alias for building this
|
||||
target from the command line of the generated SCons configuration.
|
||||
|
||||
`'type'`: Set to `executable`, logically enough.
|
||||
|
||||
`'msvs_guid'`: THIS IS ONLY TRANSITIONAL. This is a hard-coded GUID
|
||||
values that will be used in the generated Visual Studio solution
|
||||
file(s). This allows us to check in a `chrome.sln` file that
|
||||
interoperates with gyp-generated project files. Once everything in
|
||||
Chromium is being generated by gyp, it will no longer be important that
|
||||
the GUIDs stay constant across invocations, and we'll likely get rid of
|
||||
these settings,
|
||||
|
||||
`'dependencies'`: This lists other targets that this target depends on.
|
||||
The gyp-generated files will guarantee that the other targets are built
|
||||
before this target. Any library targets in the `dependencies` list will
|
||||
be linked with this target. The various settings (`defines`,
|
||||
`include_dirs`, etc.) listed in the `direct_dependent_settings` sections
|
||||
of the targets in this list will be applied to how _this_ target is
|
||||
built and linked. See the more complete discussion of
|
||||
`direct_dependent_settings`, below.
|
||||
|
||||
`'defines'`: The C preprocessor definitions that will be passed in on
|
||||
compilation command lines (using `-D` or `/D` options).
|
||||
|
||||
`'include_dirs'`: The directories in which included header files live.
|
||||
These will be passed in on compilation command lines (using `-I` or `/I`
|
||||
options).
|
||||
|
||||
`'sources'`: The source files for this target.
|
||||
|
||||
`'conditions'`: A block of conditions that will be evaluated to update
|
||||
the different settings in the target dictionary.
|
||||
|
||||
## Skeleton of a typical library target in a .gyp file
|
||||
|
||||
The vast majority of targets are libraries. Here is an example of a
|
||||
library target including the additional features that should cover most
|
||||
needs of libraries:
|
||||
|
||||
```
|
||||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'foo',
|
||||
'type': '<(library)'
|
||||
'msvs_guid': '5ECEC9E5-8F23-47B6-93E0-C3B328B3BE65',
|
||||
'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',
|
||||
],
|
||||
}]
|
||||
],
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
The possible entries in a library target are largely the same as those
|
||||
that can be specified for an executable target (`defines`,
|
||||
`include_dirs`, etc.). The differences include:
|
||||
|
||||
`'type'`: This should almost always be set to '<(library)', which allows
|
||||
the user to define at gyp time whether libraries are to be built static
|
||||
or shared. (On Linux, at least, linking with shared libraries saves
|
||||
significant link time.) If it's necessary to pin down the type of
|
||||
library to be built, the `type` can be set explicitly to
|
||||
`static_library` or `shared_library`.
|
||||
|
||||
`'direct_dependent_settings'`: This defines the settings that will be
|
||||
applied to other targets that _directly depend_ on this target--that is,
|
||||
that list _this_ target in their `'dependencies'` setting. This is
|
||||
where you list the `defines`, `include_dirs`, `cflags` and `linkflags`
|
||||
that other targets that compile or link against this target need to
|
||||
build consistently.
|
||||
|
||||
`'export_dependent_settings'`: This lists the targets whose
|
||||
`direct_dependent_settings` should be "passed on" to other targets that
|
||||
use (depend on) this target. `TODO: expand on this description.`
|
||||
|
||||
## Use Cases
|
||||
|
||||
These use cases are intended to cover the most common actions performed
|
||||
by developers using GYP.
|
||||
|
||||
Note that these examples are _not_ fully-functioning, self-contained
|
||||
examples (or else they'd be way too long). Each example mostly contains
|
||||
just the keywords and settings relevant to the example, with perhaps a
|
||||
few extra keywords for context. The intent is to try to show the
|
||||
specific pieces you need to pay attention to when doing something.
|
||||
[NOTE: if practical use shows that these examples are confusing without
|
||||
additional context, please add what's necessary to clarify things.]
|
||||
|
||||
### Add new source files
|
||||
|
||||
There are similar but slightly different patterns for adding a
|
||||
platform-independent source file vs. adding a source file that only
|
||||
builds on some of the supported platforms.
|
||||
|
||||
#### Add a source file that builds on all platforms
|
||||
|
||||
**Simplest possible case**: You are adding a file(s) that builds on all
|
||||
platforms.
|
||||
|
||||
Just add the file(s) to the `sources` list of the appropriate dictionary
|
||||
in the `targets` list:
|
||||
|
||||
```
|
||||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'my_target',
|
||||
'type': 'executable',
|
||||
'sources': [
|
||||
'../other/file_1.cc',
|
||||
'new_file.cc',
|
||||
'subdir/file3.cc',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
```
|
||||
|
||||
File path names are relative to the directory in which the `.gyp` file lives.
|
||||
|
||||
Keep the list sorted alphabetically (unless there's a really, really,
|
||||
_really_ good reason not to).
|
||||
|
||||
#### Add a platform-specific source file
|
||||
|
||||
##### Your platform-specific file is named `*_linux.{ext}`, `*_mac.{ext}`, `*_posix.{ext}` or `*_win.{ext}`
|
||||
|
||||
The simplest way to add a platform-specific source file, assuming you're
|
||||
adding a completely new file and get to name it, is to use one of the
|
||||
following standard suffixes:
|
||||
|
||||
* `_linux` (e.g. `foo_linux.cc`)
|
||||
* `_mac` (e.g. `foo_mac.cc`)
|
||||
* `_posix` (e.g. `foo_posix.cc`)
|
||||
* `_win` (e.g. `foo_win.cc`)
|
||||
|
||||
Simply add the file to the `sources` list of the appropriate dict within
|
||||
the `targets` list, like you would any other source file.
|
||||
|
||||
```
|
||||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'foo',
|
||||
'type': 'executable',
|
||||
'sources': [
|
||||
'independent.cc',
|
||||
'specific_win.cc',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
```
|
||||
|
||||
The Chromium `.gyp` files all have appropriate `conditions` entries to
|
||||
filter out the files that aren't appropriate for the current platform.
|
||||
In the above example, the `specific_win.cc` file will be removed
|
||||
automatically from the source-list on non-Windows builds.
|
||||
|
||||
##### Your platform-specific file does not use an already-defined pattern
|
||||
|
||||
If your platform-specific file does not contain a
|
||||
`*_{linux,mac,posix,win}` substring (or some other pattern that's
|
||||
already in the `conditions` for the target), and you can't change the
|
||||
file name, there are two patterns that can be used.
|
||||
|
||||
**Prefererred**: Add the file to the `sources` list of the appropriate
|
||||
dictionary within the `targets` list. Add an appropriate `conditions`
|
||||
section to exclude the specific files name:
|
||||
|
||||
```
|
||||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'foo',
|
||||
'type': 'executable',
|
||||
'sources': [
|
||||
'linux_specific.cc',
|
||||
],
|
||||
'conditions': [
|
||||
['OS != "linux"', {
|
||||
'sources!': [
|
||||
# Linux-only; exclude on other platforms.
|
||||
'linux_specific.cc',
|
||||
]
|
||||
}[,
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
```
|
||||
|
||||
Despite the duplicate listing, the above is generally preferred because
|
||||
the `sources` list contains a useful global list of all sources on all
|
||||
platforms with consistent sorting on all platforms.
|
||||
|
||||
**Non-preferred**: In some situations, however, it might make sense to
|
||||
list a platform-specific file only in a `conditions` section that
|
||||
specifically _includes_ it in the `sources` list:
|
||||
|
||||
```
|
||||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'foo',
|
||||
'type': 'executable',
|
||||
'sources': [],
|
||||
['OS == "linux"', {
|
||||
'sources': [
|
||||
# Only add to sources list on Linux.
|
||||
'linux_specific.cc',
|
||||
]
|
||||
}],
|
||||
},
|
||||
],
|
||||
},
|
||||
```
|
||||
|
||||
The above two examples end up generating equivalent builds, with the
|
||||
small exception that the `sources` lists will list the files in
|
||||
different orders. (The first example defines explicitly where
|
||||
`linux_specific.cc` appears in the list--perhaps in in the
|
||||
middle--whereas the second example will always tack it on to the end of
|
||||
the list.)
|
||||
|
||||
**Including or excluding files using patterns**: There are more
|
||||
complicated ways to construct a `sources` list based on patterns. See
|
||||
`TODO` below.
|
||||
|
||||
### Add a new executable
|
||||
|
||||
An executable program is probably the most straightforward type of
|
||||
target, since all it typically needs is a list of source files, some
|
||||
compiler/linker settings (probably varied by platform), and some library
|
||||
targets on which it depends and which must be used in the final link.
|
||||
|
||||
#### Add an executable that builds on all platforms
|
||||
|
||||
Add a dictionary defining the new executable target to the `targets`
|
||||
list in the appropriate `.gyp` file. Example:
|
||||
|
||||
```
|
||||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'new_unit_tests',
|
||||
'type': 'executable',
|
||||
'defines': [
|
||||
'FOO',
|
||||
],
|
||||
'include_dirs': [
|
||||
'..',
|
||||
],
|
||||
'dependencies': [
|
||||
'other_target_in_this_file',
|
||||
'other_gyp2:target_in_other_gyp2',
|
||||
],
|
||||
'sources': [
|
||||
'new_additional_source.cc',
|
||||
'new_unit_tests.cc',
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
#### Add a platform-specific executable
|
||||
|
||||
Add a dictionary defining the new executable target to the `targets`
|
||||
list within an appropriate `conditions` block for the platform. The
|
||||
`conditions` block should be a sibling to the top-level `targets` list:
|
||||
|
||||
```
|
||||
{
|
||||
'targets': [
|
||||
],
|
||||
'conditions': [
|
||||
['OS=="win"', {
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'new_unit_tests',
|
||||
'type': 'executable',
|
||||
'defines': [
|
||||
'FOO',
|
||||
],
|
||||
'include_dirs': [
|
||||
'..',
|
||||
],
|
||||
'dependencies': [
|
||||
'other_target_in_this_file',
|
||||
'other_gyp2:target_in_other_gyp2',
|
||||
],
|
||||
'sources': [
|
||||
'new_additional_source.cc',
|
||||
'new_unit_tests.cc',
|
||||
],
|
||||
},
|
||||
],
|
||||
}],
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
### Add settings to a target
|
||||
|
||||
There are several different types of settings that can be defined for
|
||||
any given target.
|
||||
|
||||
#### Add new preprocessor definitions (`-D` or `/D` flags)
|
||||
|
||||
New preprocessor definitions are added by the `defines` setting:
|
||||
|
||||
```
|
||||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'existing_target',
|
||||
'defines': [
|
||||
'FOO',
|
||||
'BAR=some_value',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
```
|
||||
|
||||
These may be specified directly in a target's settings, as in the above
|
||||
example, or in a `conditions` section.
|
||||
|
||||
#### Add a new include directory (`-I` or `/I` flags)
|
||||
|
||||
New include directories are added by the `include_dirs` setting:
|
||||
|
||||
```
|
||||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'existing_target',
|
||||
'include_dirs': [
|
||||
'..',
|
||||
'include',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
```
|
||||
|
||||
These may be specified directly in a target's settings, as in the above
|
||||
example, or in a `conditions` section.
|
||||
|
||||
#### Add new compiler flags
|
||||
|
||||
Specific compiler flags can be added with the `cflags` setting:
|
||||
|
||||
```
|
||||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'existing_target',
|
||||
'conditions': [
|
||||
['OS=="win"', {
|
||||
'cflags': [
|
||||
'/WX',
|
||||
],
|
||||
}, { # OS != "win"
|
||||
'cflags': [
|
||||
'-Werror',
|
||||
],
|
||||
}],
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
```
|
||||
|
||||
Because these flags will be specific to the actual compiler involved,
|
||||
they will almost always be only set within a `conditions` section.
|
||||
|
||||
#### Add new linker flags
|
||||
|
||||
Setting linker flags is OS-specific. On linux and most non-mac posix
|
||||
systems, they can be added with the `ldflags` setting:
|
||||
|
||||
```
|
||||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'existing_target',
|
||||
'conditions': [
|
||||
['OS=="linux"', {
|
||||
'ldflags': [
|
||||
'-pthread',
|
||||
],
|
||||
}],
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
```
|
||||
|
||||
Because these flags will be specific to the actual linker involved,
|
||||
they will almost always be only set within a `conditions` section.
|
||||
|
||||
On OS X, linker settings are set via `xcode_settings`, on Windows via
|
||||
`msvs_settings`.
|
||||
|
||||
#### Exclude settings on a platform
|
||||
|
||||
Any given settings keyword (`defines`, `include_dirs`, etc.) has a
|
||||
corresponding form with a trailing `!` (exclamation point) to remove
|
||||
values from a setting. One useful example of this is to remove the
|
||||
Linux `-Werror` flag from the global settings defined in
|
||||
`build/common.gypi`:
|
||||
|
||||
```
|
||||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'third_party_target',
|
||||
'conditions': [
|
||||
['OS=="linux"', {
|
||||
'cflags!': [
|
||||
'-Werror',
|
||||
],
|
||||
}],
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
```
|
||||
|
||||
### Cross-compiling
|
||||
|
||||
GYP has some (relatively limited) support for cross-compiling.
|
||||
|
||||
If the variable `GYP_CROSSCOMPILE` or one of the toolchain-related
|
||||
variables (like `CC_host` or `CC_target`) is set, GYP will think that
|
||||
you wish to do a cross-compile.
|
||||
|
||||
When cross-compiling, each target can be part of a "host" build, a
|
||||
"target" build, or both. By default, the target is assumed to be (only)
|
||||
part of the "target" build. The 'toolsets' property can be set on a
|
||||
target to change the default.
|
||||
|
||||
A target's dependencies are assumed to match the build type (so, if A
|
||||
depends on B, by default that means that a target build of A depends on
|
||||
a target build of B). You can explicitly depend on targets across
|
||||
toolchains by specifying "#host" or "#target" in the dependencies list.
|
||||
If GYP is not doing a cross-compile, the "#host" and "#target" will be
|
||||
stripped as needed, so nothing breaks.
|
||||
|
||||
### Add a new library
|
||||
|
||||
TODO: write intro
|
||||
|
||||
#### Add a library that builds on all platforms
|
||||
|
||||
Add the a dictionary defining the new library target to the `targets`
|
||||
list in the appropriate `.gyp` file. Example:
|
||||
|
||||
```
|
||||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'new_library',
|
||||
'type': '<(library)',
|
||||
'defines': [
|
||||
'FOO',
|
||||
'BAR=some_value',
|
||||
],
|
||||
'include_dirs': [
|
||||
'..',
|
||||
],
|
||||
'dependencies': [
|
||||
'other_target_in_this_file',
|
||||
'other_gyp2:target_in_other_gyp2',
|
||||
],
|
||||
'direct_dependent_settings': {
|
||||
'include_dirs': '.',
|
||||
},
|
||||
'export_dependent_settings': [
|
||||
'other_target_in_this_file',
|
||||
],
|
||||
'sources': [
|
||||
'new_additional_source.cc',
|
||||
'new_library.cc',
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
The use of the `<(library)` variable above should be the default `type`
|
||||
setting for most library targets, as it allows the developer to choose,
|
||||
at `gyp` time, whether to build with static or shared libraries.
|
||||
(Building with shared libraries saves a _lot_ of link time on Linux.)
|
||||
|
||||
It may be necessary to build a specific library as a fixed type. Is so,
|
||||
the `type` field can be hard-wired appropriately. For a static library:
|
||||
|
||||
```
|
||||
'type': 'static_library',
|
||||
```
|
||||
|
||||
For a shared library:
|
||||
|
||||
```
|
||||
'type': 'shared_library',
|
||||
```
|
||||
|
||||
#### Add a platform-specific library
|
||||
|
||||
Add a dictionary defining the new library target to the `targets` list
|
||||
within a `conditions` block that's a sibling to the top-level `targets`
|
||||
list:
|
||||
|
||||
```
|
||||
{
|
||||
'targets': [
|
||||
],
|
||||
'conditions': [
|
||||
['OS=="win"', {
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'new_library',
|
||||
'type': '<(library)',
|
||||
'defines': [
|
||||
'FOO',
|
||||
'BAR=some_value',
|
||||
],
|
||||
'include_dirs': [
|
||||
'..',
|
||||
],
|
||||
'dependencies': [
|
||||
'other_target_in_this_file',
|
||||
'other_gyp2:target_in_other_gyp2',
|
||||
],
|
||||
'direct_dependent_settings': {
|
||||
'include_dirs': '.',
|
||||
},
|
||||
'export_dependent_settings': [
|
||||
'other_target_in_this_file',
|
||||
],
|
||||
'sources': [
|
||||
'new_additional_source.cc',
|
||||
'new_library.cc',
|
||||
],
|
||||
},
|
||||
],
|
||||
}],
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
### Dependencies between targets
|
||||
|
||||
GYP provides useful primitives for establishing dependencies between
|
||||
targets, which need to be configured in the following situations.
|
||||
|
||||
#### Linking with another library target
|
||||
|
||||
```
|
||||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'foo',
|
||||
'dependencies': [
|
||||
'libbar',
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'libbar',
|
||||
'type': '<(library)',
|
||||
'sources': [
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
Note that if the library target is in a different `.gyp` file, you have
|
||||
to specify the path to other `.gyp` file, relative to this `.gyp` file's
|
||||
directory:
|
||||
|
||||
```
|
||||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'foo',
|
||||
'dependencies': [
|
||||
'../bar/bar.gyp:libbar',
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
Adding a library often involves updating multiple `.gyp` files, adding
|
||||
the target to the approprate `.gyp` file (possibly a newly-added `.gyp`
|
||||
file), and updating targets in the other `.gyp` files that depend on
|
||||
(link with) the new library.
|
||||
|
||||
#### Compiling with necessary flags for a library target dependency
|
||||
|
||||
We need to build a library (often a third-party library) with specific
|
||||
preprocessor definitions or command-line flags, and need to ensure that
|
||||
targets that depend on the library build with the same settings. This
|
||||
situation is handled by a `direct_dependent_settings` block:
|
||||
|
||||
```
|
||||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'foo',
|
||||
'type': 'executable',
|
||||
'dependencies': [
|
||||
'libbar',
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'libbar',
|
||||
'type': '<(library)',
|
||||
'defines': [
|
||||
'LOCAL_DEFINE_FOR_LIBBAR',
|
||||
'DEFINE_TO_USE_LIBBAR',
|
||||
],
|
||||
'include_dirs': [
|
||||
'..',
|
||||
'include/libbar',
|
||||
],
|
||||
'direct_dependent_settings': {
|
||||
'defines': [
|
||||
'DEFINE_TO_USE_LIBBAR',
|
||||
],
|
||||
'include_dirs': [
|
||||
'include/libbar',
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
In the above example, the sources of the `foo` executable will be
|
||||
compiled with the options `-DDEFINE_TO_USE_LIBBAR -Iinclude/libbar`,
|
||||
because of those settings' being listed in the
|
||||
`direct_dependent_settings` block.
|
||||
|
||||
Note that these settings will likely need to be replicated in the
|
||||
settings for the library target itsef, so that the library will build
|
||||
with the same options. This does not prevent the target from defining
|
||||
additional options for its "internal" use when compiling its own source
|
||||
files. (In the above example, these are the `LOCAL_DEFINE_FOR_LIBBAR`
|
||||
define, and the `..` entry in the `include_dirs` list.)
|
||||
|
||||
#### When a library depends on an additional library at final link time
|
||||
|
||||
```
|
||||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'foo',
|
||||
'type': 'executable',
|
||||
'dependencies': [
|
||||
'libbar',
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'libbar',
|
||||
'type': '<(library)',
|
||||
'dependencies': [
|
||||
'libother'
|
||||
],
|
||||
'export_dependent_settings': [
|
||||
'libother'
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'libother',
|
||||
'type': '<(library)',
|
||||
'direct_dependent_settings': {
|
||||
'defines': [
|
||||
'DEFINE_FOR_LIBOTHER',
|
||||
],
|
||||
'include_dirs': [
|
||||
'include/libother',
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
### Support for Mac OS X bundles
|
||||
|
||||
gyp supports building bundles on OS X (.app, .framework, .bundle, etc).
|
||||
Here is an example of this:
|
||||
|
||||
```
|
||||
{
|
||||
'target_name': 'test_app',
|
||||
'product_name': 'Test App Gyp',
|
||||
'type': 'executable',
|
||||
'mac_bundle': 1,
|
||||
'sources': [
|
||||
'main.m',
|
||||
'TestAppAppDelegate.h',
|
||||
'TestAppAppDelegate.m',
|
||||
],
|
||||
'mac_bundle_resources': [
|
||||
'TestApp/English.lproj/InfoPlist.strings',
|
||||
'TestApp/English.lproj/MainMenu.xib',
|
||||
],
|
||||
'link_settings': {
|
||||
'libraries': [
|
||||
'$(SDKROOT)/System/Library/Frameworks/Cocoa.framework',
|
||||
],
|
||||
},
|
||||
'xcode_settings': {
|
||||
'INFOPLIST_FILE': 'TestApp/TestApp-Info.plist',
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
The `mac_bundle` key tells gyp that this target should be a bundle.
|
||||
`executable` targets get extension `.app` by default, `shared_library`
|
||||
targets get `.framework` – but you can change the bundle extensions by
|
||||
setting `product_extension` if you want. Files listed in
|
||||
`mac_bundle_resources` will be copied to the bundle's `Resource` folder
|
||||
of the bundle. You can also set
|
||||
`process_outputs_as_mac_bundle_resources` to 1 in actions and rules to
|
||||
let the output of actions and rules be added to that folder (similar to
|
||||
`process_outputs_as_sources`). If `product_name` is not set, the bundle
|
||||
will be named after `target_name`as usual.
|
||||
|
||||
### Move files (refactoring)
|
||||
|
||||
TODO
|
||||
|
||||
### Custom build steps
|
||||
|
||||
TODO
|
||||
|
||||
#### Adding an explicit build step to generate specific files
|
||||
|
||||
TODO
|
||||
|
||||
#### Adding a rule to handle files with a new suffix
|
||||
|
||||
TODO
|
||||
|
||||
### Build flavors
|
||||
|
||||
TODO
|
|
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||
|
||||
[project]
|
||||
name = "gyp-next"
|
||||
version = "0.18.0"
|
||||
version = "0.18.1"
|
||||
authors = [
|
||||
{ name="Node.js contributors", email="ryzokuken@disroot.org" },
|
||||
]
|
||||
|
@ -12,7 +12,7 @@ description = "A fork of the GYP build system for use in the Node.js projects"
|
|||
readme = "README.md"
|
||||
license = { file="LICENSE" }
|
||||
requires-python = ">=3.8"
|
||||
dependencies = ["packaging>=24.0"]
|
||||
dependencies = ["packaging>=24.0", "setuptools>=69.5.1"]
|
||||
classifiers = [
|
||||
"Development Status :: 3 - Alpha",
|
||||
"Environment :: Console",
|
||||
|
|
Loading…
Reference in New Issue