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:
Node.js GitHub Bot 2024-06-04 03:32:33 +03:00 committed by GitHub
parent eae75fe635
commit 4770ae4dfb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 3133 additions and 3 deletions

View File

@ -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)

View File

@ -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).

View File

@ -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`

View File

@ -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
```

46
tools/gyp/docs/Hacking.md Normal file
View File

@ -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

View File

@ -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?

27
tools/gyp/docs/README.md Normal file
View File

@ -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.

450
tools/gyp/docs/Testing.md Normal file
View File

@ -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`.

View File

@ -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

View File

@ -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",