From ee46caa29f64bd944d45fb4342718f842a2c7e6a Mon Sep 17 00:00:00 2001 From: nodejs-github-bot <18269663+nodejs-github-bot@users.noreply.github.com> Date: Sun, 6 Apr 2025 00:36:19 +0000 Subject: [PATCH] tools: update gyp-next to 0.20.0 --- tools/gyp/.gitignore | 3 + tools/gyp/CHANGELOG.md | 13 ++ tools/gyp/docs/Hacking.md | 2 +- tools/gyp/docs/InputFormatReference.md | 5 +- tools/gyp/gyp_main.py | 2 +- tools/gyp/pylib/gyp/MSVSProject.py | 2 +- tools/gyp/pylib/gyp/MSVSSettings_test.py | 4 +- tools/gyp/pylib/gyp/MSVSToolFile.py | 2 +- tools/gyp/pylib/gyp/MSVSUserFile.py | 3 +- tools/gyp/pylib/gyp/MSVSUtil.py | 1 - tools/gyp/pylib/gyp/MSVSVersion.py | 2 +- tools/gyp/pylib/gyp/__init__.py | 29 ++- tools/gyp/pylib/gyp/common.py | 8 +- tools/gyp/pylib/gyp/common_test.py | 24 +-- tools/gyp/pylib/gyp/easy_xml.py | 6 +- tools/gyp/pylib/gyp/easy_xml_test.py | 4 +- tools/gyp/pylib/gyp/generator/analyzer.py | 7 +- tools/gyp/pylib/gyp/generator/android.py | 41 ++--- tools/gyp/pylib/gyp/generator/cmake.py | 1 + .../gyp/generator/compile_commands_json.py | 5 +- .../gyp/generator/dump_dependency_json.py | 3 +- tools/gyp/pylib/gyp/generator/eclipse.py | 7 +- tools/gyp/pylib/gyp/generator/gypd.py | 2 +- tools/gyp/pylib/gyp/generator/gypsh.py | 1 - tools/gyp/pylib/gyp/generator/make.py | 44 ++--- tools/gyp/pylib/gyp/generator/msvs.py | 173 +++++++++--------- tools/gyp/pylib/gyp/generator/msvs_test.py | 4 +- tools/gyp/pylib/gyp/generator/ninja.py | 22 +-- tools/gyp/pylib/gyp/generator/ninja_test.py | 4 +- tools/gyp/pylib/gyp/generator/xcode.py | 12 +- tools/gyp/pylib/gyp/generator/xcode_test.py | 5 +- tools/gyp/pylib/gyp/input.py | 47 +++-- tools/gyp/pylib/gyp/input_test.py | 3 +- tools/gyp/pylib/gyp/mac_tool.py | 12 +- tools/gyp/pylib/gyp/msvs_emulation.py | 6 +- tools/gyp/pylib/gyp/win_tool.py | 2 +- tools/gyp/pylib/gyp/xcode_emulation.py | 12 +- tools/gyp/pylib/gyp/xcode_emulation_test.py | 3 +- tools/gyp/pylib/gyp/xcode_ninja.py | 3 +- tools/gyp/pylib/gyp/xcodeproj_file.py | 28 ++- tools/gyp/pyproject.toml | 8 +- .../expected-darwin/cmake/CMakeLists.txt | 31 ++++ .../expected-darwin/make/test.target.mk | 86 +++++++++ .../fixtures/expected-darwin/ninja/test.ninja | 15 ++ .../expected-linux/cmake/CMakeLists.txt | 32 ++++ .../expected-linux/make/test.target.mk | 66 +++++++ .../fixtures/expected-linux/ninja/test.ninja | 13 ++ tools/gyp/test/fixtures/include/test.h | 3 + tools/gyp/test/fixtures/integration.gyp | 17 ++ tools/gyp/test/fixtures/test.cc | 9 + tools/gyp/test/integration_test.py | 70 +++++++ tools/gyp/tools/pretty_gyp.py | 5 +- tools/gyp/tools/pretty_sln.py | 3 +- tools/gyp/tools/pretty_vcproj.py | 4 +- 54 files changed, 631 insertions(+), 288 deletions(-) create mode 100644 tools/gyp/test/fixtures/expected-darwin/cmake/CMakeLists.txt create mode 100644 tools/gyp/test/fixtures/expected-darwin/make/test.target.mk create mode 100644 tools/gyp/test/fixtures/expected-darwin/ninja/test.ninja create mode 100644 tools/gyp/test/fixtures/expected-linux/cmake/CMakeLists.txt create mode 100644 tools/gyp/test/fixtures/expected-linux/make/test.target.mk create mode 100644 tools/gyp/test/fixtures/expected-linux/ninja/test.ninja create mode 100644 tools/gyp/test/fixtures/include/test.h create mode 100644 tools/gyp/test/fixtures/integration.gyp create mode 100644 tools/gyp/test/fixtures/test.cc create mode 100644 tools/gyp/test/integration_test.py diff --git a/tools/gyp/.gitignore b/tools/gyp/.gitignore index d82fa7a96c9015..5f71dbd435dbf4 100644 --- a/tools/gyp/.gitignore +++ b/tools/gyp/.gitignore @@ -141,3 +141,6 @@ cython_debug/ # static files generated from Django application using `collectstatic` media static + +test/fixtures/out +*.actual diff --git a/tools/gyp/CHANGELOG.md b/tools/gyp/CHANGELOG.md index 22257ab93d8929..3f676055a6a075 100644 --- a/tools/gyp/CHANGELOG.md +++ b/tools/gyp/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## [0.20.0](https://github.com/nodejs/gyp-next/compare/v0.19.1...v0.20.0) (2025-03-27) + + +### ⚠ BREAKING CHANGES + +* resolve issue with relative paths during linking ([#284](https://github.com/nodejs/gyp-next/issues/284)) + +### Bug Fixes + +* python lint more ruff rules ([#291](https://github.com/nodejs/gyp-next/issues/291)) ([fabc78c](https://github.com/nodejs/gyp-next/commit/fabc78caffcf988365d970ced5a151f40525077e)) +* remove explicit installation of setuptools ([#278](https://github.com/nodejs/gyp-next/issues/278)) ([e476778](https://github.com/nodejs/gyp-next/commit/e4767782c70ca8427184694589d9f0ded5eeed22)) +* resolve issue with relative paths during linking ([#284](https://github.com/nodejs/gyp-next/issues/284)) ([a2d7439](https://github.com/nodejs/gyp-next/commit/a2d7439fbd3c03f01e1149fdbe682f754bc6cc7f)) + ## [0.19.1](https://github.com/nodejs/gyp-next/compare/v0.19.0...v0.19.1) (2024-12-09) diff --git a/tools/gyp/docs/Hacking.md b/tools/gyp/docs/Hacking.md index b00783bd36f2bb..156d485b5b82d1 100644 --- a/tools/gyp/docs/Hacking.md +++ b/tools/gyp/docs/Hacking.md @@ -24,7 +24,7 @@ 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 +$ python -m pip install --upgrade pip $ pip install --editable ".[dev]" $ python -m pytest ``` diff --git a/tools/gyp/docs/InputFormatReference.md b/tools/gyp/docs/InputFormatReference.md index 2b2c180f4443c5..4b114f2debca45 100644 --- a/tools/gyp/docs/InputFormatReference.md +++ b/tools/gyp/docs/InputFormatReference.md @@ -194,6 +194,7 @@ lists associated with the following keys, are treated as pathnames: * include\_dirs * inputs * libraries + * library\_dirs * outputs * sources * mac\_bundle\_resources @@ -231,7 +232,8 @@ Source dictionary from `../build/common.gypi`: ``` { 'include_dirs': ['include'], # Treated as relative to ../build - 'libraries': ['-lz'], # Not treated as a pathname, begins with a dash + 'library_dirs': ['lib'], # Treated as relative to ../build + 'libraries': ['-lz'], # Not treated as a pathname, begins with a dash 'defines': ['NDEBUG'], # defines does not contain pathnames } ``` @@ -250,6 +252,7 @@ Merged dictionary: { 'sources': ['string_util.cc'], 'include_dirs': ['../build/include'], + 'library_dirs': ['../build/lib'], 'libraries': ['-lz'], 'defines': ['NDEBUG'], } diff --git a/tools/gyp/gyp_main.py b/tools/gyp/gyp_main.py index f23dcdf882d1b0..bf169874851463 100755 --- a/tools/gyp/gyp_main.py +++ b/tools/gyp/gyp_main.py @@ -5,8 +5,8 @@ # found in the LICENSE file. import os -import sys import subprocess +import sys def IsCygwin(): diff --git a/tools/gyp/pylib/gyp/MSVSProject.py b/tools/gyp/pylib/gyp/MSVSProject.py index 629f3f61b4819d..339d27d4029fcf 100644 --- a/tools/gyp/pylib/gyp/MSVSProject.py +++ b/tools/gyp/pylib/gyp/MSVSProject.py @@ -4,7 +4,7 @@ """Visual Studio project reader/writer.""" -import gyp.easy_xml as easy_xml +from gyp import easy_xml # ------------------------------------------------------------------------------ diff --git a/tools/gyp/pylib/gyp/MSVSSettings_test.py b/tools/gyp/pylib/gyp/MSVSSettings_test.py index 6ca09687ad7f13..0504728d994ca8 100755 --- a/tools/gyp/pylib/gyp/MSVSSettings_test.py +++ b/tools/gyp/pylib/gyp/MSVSSettings_test.py @@ -7,10 +7,10 @@ """Unit tests for the MSVSSettings.py file.""" import unittest -import gyp.MSVSSettings as MSVSSettings - from io import StringIO +from gyp import MSVSSettings + class TestSequenceFunctions(unittest.TestCase): def setUp(self): diff --git a/tools/gyp/pylib/gyp/MSVSToolFile.py b/tools/gyp/pylib/gyp/MSVSToolFile.py index 2e5c811bdde322..901ba84588589b 100644 --- a/tools/gyp/pylib/gyp/MSVSToolFile.py +++ b/tools/gyp/pylib/gyp/MSVSToolFile.py @@ -4,7 +4,7 @@ """Visual Studio project reader/writer.""" -import gyp.easy_xml as easy_xml +from gyp import easy_xml class Writer: diff --git a/tools/gyp/pylib/gyp/MSVSUserFile.py b/tools/gyp/pylib/gyp/MSVSUserFile.py index e580c00fb76d3e..23d3e16953c43a 100644 --- a/tools/gyp/pylib/gyp/MSVSUserFile.py +++ b/tools/gyp/pylib/gyp/MSVSUserFile.py @@ -8,8 +8,7 @@ import re import socket # for gethostname -import gyp.easy_xml as easy_xml - +from gyp import easy_xml # ------------------------------------------------------------------------------ diff --git a/tools/gyp/pylib/gyp/MSVSUtil.py b/tools/gyp/pylib/gyp/MSVSUtil.py index 36bb782bd319a2..27647f11d07467 100644 --- a/tools/gyp/pylib/gyp/MSVSUtil.py +++ b/tools/gyp/pylib/gyp/MSVSUtil.py @@ -7,7 +7,6 @@ import copy import os - # A dictionary mapping supported target types to extensions. TARGET_TYPE_EXT = { "executable": "exe", diff --git a/tools/gyp/pylib/gyp/MSVSVersion.py b/tools/gyp/pylib/gyp/MSVSVersion.py index 1b3536292201b7..93f48bc05c8dc5 100644 --- a/tools/gyp/pylib/gyp/MSVSVersion.py +++ b/tools/gyp/pylib/gyp/MSVSVersion.py @@ -5,11 +5,11 @@ """Handle version information related to Visual Stuio.""" import errno +import glob import os import re import subprocess import sys -import glob def JoinPath(*args): diff --git a/tools/gyp/pylib/gyp/__init__.py b/tools/gyp/pylib/gyp/__init__.py index 8933d0c4f707c9..77800661a48c0e 100755 --- a/tools/gyp/pylib/gyp/__init__.py +++ b/tools/gyp/pylib/gyp/__init__.py @@ -5,16 +5,17 @@ # found in the LICENSE file. from __future__ import annotations -import copy -import gyp.input + import argparse +import copy import os.path import re import shlex import sys import traceback -from gyp.common import GypError +import gyp.input +from gyp.common import GypError # Default debug modes for GYP debug = {} @@ -205,8 +206,7 @@ def NameValueListToDict(name_value_list): def ShlexEnv(env_name): - flags = os.environ.get(env_name, []) - if flags: + if flags := os.environ.get(env_name) or []: flags = shlex.split(flags) return flags @@ -361,7 +361,7 @@ def gyp_main(args): action="store", env_name="GYP_CONFIG_DIR", default=None, - help="The location for configuration files like " "include.gypi.", + help="The location for configuration files like include.gypi.", ) parser.add_argument( "-d", @@ -525,19 +525,18 @@ def gyp_main(args): # If no format was given on the command line, then check the env variable. generate_formats = [] if options.use_environment: - generate_formats = os.environ.get("GYP_GENERATORS", []) + generate_formats = os.environ.get("GYP_GENERATORS") or [] if generate_formats: generate_formats = re.split(r"[\s,]", generate_formats) if generate_formats: options.formats = generate_formats + # Nothing in the variable, default based on platform. + elif sys.platform == "darwin": + options.formats = ["xcode"] + elif sys.platform in ("win32", "cygwin"): + options.formats = ["msvs"] else: - # Nothing in the variable, default based on platform. - if sys.platform == "darwin": - options.formats = ["xcode"] - elif sys.platform in ("win32", "cygwin"): - options.formats = ["msvs"] - else: - options.formats = ["make"] + options.formats = ["make"] if not options.generator_output and options.use_environment: g_o = os.environ.get("GYP_GENERATOR_OUTPUT") @@ -696,7 +695,7 @@ def main(args): return 1 -# NOTE: setuptools generated console_scripts calls function with no arguments +# NOTE: console_scripts calls this function with no arguments def script_main(): return main(sys.argv[1:]) diff --git a/tools/gyp/pylib/gyp/common.py b/tools/gyp/pylib/gyp/common.py index 762ae021090cac..fbf1024fc38319 100644 --- a/tools/gyp/pylib/gyp/common.py +++ b/tools/gyp/pylib/gyp/common.py @@ -6,11 +6,10 @@ import filecmp import os.path import re -import tempfile -import sys -import subprocess import shlex - +import subprocess +import sys +import tempfile from collections.abc import MutableSet @@ -35,7 +34,6 @@ class GypError(Exception): to the user. The main entry point will catch and display this. """ - pass def ExceptionAppend(e, msg): diff --git a/tools/gyp/pylib/gyp/common_test.py b/tools/gyp/pylib/gyp/common_test.py index b6c4cccc1ac5ca..bd7172afaf3697 100755 --- a/tools/gyp/pylib/gyp/common_test.py +++ b/tools/gyp/pylib/gyp/common_test.py @@ -6,11 +6,13 @@ """Unit tests for the common.py file.""" -import gyp.common -import unittest -import sys import os -from unittest.mock import patch, MagicMock +import sys +import unittest +from unittest.mock import MagicMock, patch + +import gyp.common + class TestTopologicallySorted(unittest.TestCase): def test_Valid(self): @@ -109,14 +111,14 @@ def mock_run(env, defines_stdout, expected_cmd): return [defines, flavor] [defines1, _] = mock_run({}, "", []) - assert {} == defines1 + assert defines1 == {} [defines2, flavor2] = mock_run( { "CC_target": "/opt/wasi-sdk/bin/clang" }, "#define __wasm__ 1\n#define __wasi__ 1\n", ["/opt/wasi-sdk/bin/clang"] ) - assert { "__wasm__": "1", "__wasi__": "1" } == defines2 + assert defines2 == { "__wasm__": "1", "__wasi__": "1" } assert flavor2 == "wasi" [defines3, flavor3] = mock_run( @@ -124,7 +126,7 @@ def mock_run(env, defines_stdout, expected_cmd): "#define __wasm__ 1\n", ["/opt/wasi-sdk/bin/clang", "--target=wasm32"] ) - assert { "__wasm__": "1" } == defines3 + assert defines3 == { "__wasm__": "1" } assert flavor3 == "wasm" [defines4, flavor4] = mock_run( @@ -132,7 +134,7 @@ def mock_run(env, defines_stdout, expected_cmd): "#define __EMSCRIPTEN__ 1\n", ["/emsdk/upstream/emscripten/emcc"] ) - assert { "__EMSCRIPTEN__": "1" } == defines4 + assert defines4 == { "__EMSCRIPTEN__": "1" } assert flavor4 == "emscripten" # Test path which include white space @@ -149,11 +151,11 @@ def mock_run(env, defines_stdout, expected_cmd): "-pthread" ] ) - assert { + assert defines5 == { "__wasm__": "1", "__wasi__": "1", "_REENTRANT": "1" - } == defines5 + } assert flavor5 == "wasi" original_sep = os.sep @@ -164,7 +166,7 @@ def mock_run(env, defines_stdout, expected_cmd): ["C:/Program Files/wasi-sdk/clang.exe"] ) os.sep = original_sep - assert { "__wasm__": "1", "__wasi__": "1" } == defines6 + assert defines6 == { "__wasm__": "1", "__wasi__": "1" } assert flavor6 == "wasi" if __name__ == "__main__": diff --git a/tools/gyp/pylib/gyp/easy_xml.py b/tools/gyp/pylib/gyp/easy_xml.py index 02567b251446d7..e4d2f82b687418 100644 --- a/tools/gyp/pylib/gyp/easy_xml.py +++ b/tools/gyp/pylib/gyp/easy_xml.py @@ -2,10 +2,10 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import sys -import re -import os import locale +import os +import re +import sys from functools import reduce diff --git a/tools/gyp/pylib/gyp/easy_xml_test.py b/tools/gyp/pylib/gyp/easy_xml_test.py index 2d9b15210dc126..bb97b802c59551 100755 --- a/tools/gyp/pylib/gyp/easy_xml_test.py +++ b/tools/gyp/pylib/gyp/easy_xml_test.py @@ -6,11 +6,11 @@ """ Unit tests for the easy_xml.py file. """ -import gyp.easy_xml as easy_xml import unittest - from io import StringIO +from gyp import easy_xml + class TestSequenceFunctions(unittest.TestCase): def setUp(self): diff --git a/tools/gyp/pylib/gyp/generator/analyzer.py b/tools/gyp/pylib/gyp/generator/analyzer.py index 64573ad2cc70d6..cb18742cd8df6d 100644 --- a/tools/gyp/pylib/gyp/generator/analyzer.py +++ b/tools/gyp/pylib/gyp/generator/analyzer.py @@ -63,11 +63,12 @@ """ -import gyp.common import json import os import posixpath +import gyp.common + debug = False found_dependency_string = "Found dependency" @@ -157,7 +158,7 @@ def _AddSources(sources, base_path, base_path_components, result): and tracked in some other means.""" # NOTE: gyp paths are always posix style. for source in sources: - if not len(source) or source.startswith("!!!") or source.startswith("$"): + if not len(source) or source.startswith(("!!!", "$")): continue # variable expansion may lead to //. org_source = source @@ -747,7 +748,7 @@ def GenerateOutput(target_list, target_dicts, data, params): if not config.files: raise Exception( - "Must specify files to analyze via config_path generator " "flag" + "Must specify files to analyze via config_path generator flag" ) toplevel_dir = _ToGypPath(os.path.abspath(params["options"].toplevel_dir)) diff --git a/tools/gyp/pylib/gyp/generator/android.py b/tools/gyp/pylib/gyp/generator/android.py index 64da385e6aeb40..5ebe58bb556d80 100644 --- a/tools/gyp/pylib/gyp/generator/android.py +++ b/tools/gyp/pylib/gyp/generator/android.py @@ -15,13 +15,14 @@ # Try to avoid setting global variables where possible. -import gyp -import gyp.common -import gyp.generator.make as make # Reuse global functions from make backend. import os import re import subprocess +import gyp +import gyp.common +from gyp.generator import make # Reuse global functions from make backend. + generator_default_variables = { "OS": "android", "EXECUTABLE_PREFIX": "", @@ -177,7 +178,7 @@ def Write( self.WriteLn("LOCAL_MULTILIB := $(GYP_HOST_MULTILIB)") elif sdk_version > 0: self.WriteLn( - "LOCAL_MODULE_TARGET_ARCH := " "$(TARGET_$(GYP_VAR_PREFIX)ARCH)" + "LOCAL_MODULE_TARGET_ARCH := $(TARGET_$(GYP_VAR_PREFIX)ARCH)" ) self.WriteLn("LOCAL_SDK_VERSION := %s" % sdk_version) @@ -587,11 +588,10 @@ def WriteSources(self, spec, configs, extra_sources): local_files = [] for source in sources: (root, ext) = os.path.splitext(source) - if "$(gyp_shared_intermediate_dir)" in source: - extra_sources.append(source) - elif "$(gyp_intermediate_dir)" in source: - extra_sources.append(source) - elif IsCPPExtension(ext) and ext != local_cpp_extension: + if ("$(gyp_shared_intermediate_dir)" in source + or "$(gyp_intermediate_dir)" in source + or (IsCPPExtension(ext) and ext != local_cpp_extension) + ): extra_sources.append(source) else: local_files.append(os.path.normpath(os.path.join(self.path, source))) @@ -730,19 +730,18 @@ def ComputeOutput(self, spec): path = "$($(GYP_HOST_VAR_PREFIX)HOST_OUT_INTERMEDIATE_LIBRARIES)" else: path = "$($(GYP_VAR_PREFIX)TARGET_OUT_INTERMEDIATE_LIBRARIES)" + # Other targets just get built into their intermediate dir. + elif self.toolset == "host": + path = ( + "$(call intermediates-dir-for,%s,%s,true,," + "$(GYP_HOST_VAR_PREFIX))" + % (self.android_class, self.android_module) + ) else: - # Other targets just get built into their intermediate dir. - if self.toolset == "host": - path = ( - "$(call intermediates-dir-for,%s,%s,true,," - "$(GYP_HOST_VAR_PREFIX))" - % (self.android_class, self.android_module) - ) - else: - path = ( - f"$(call intermediates-dir-for,{self.android_class}," - f"{self.android_module},,,$(GYP_VAR_PREFIX))" - ) + path = ( + f"$(call intermediates-dir-for,{self.android_class}," + f"{self.android_module},,,$(GYP_VAR_PREFIX))" + ) assert spec.get("product_dir") is None # TODO: not supported? return os.path.join(path, self.ComputeOutputBasename(spec)) diff --git a/tools/gyp/pylib/gyp/generator/cmake.py b/tools/gyp/pylib/gyp/generator/cmake.py index 8720a3daf3a0d8..e69103e1b9ba3f 100644 --- a/tools/gyp/pylib/gyp/generator/cmake.py +++ b/tools/gyp/pylib/gyp/generator/cmake.py @@ -33,6 +33,7 @@ import os import signal import subprocess + import gyp.common import gyp.xcode_emulation diff --git a/tools/gyp/pylib/gyp/generator/compile_commands_json.py b/tools/gyp/pylib/gyp/generator/compile_commands_json.py index 5d7f14da9699da..bebb1303154e16 100644 --- a/tools/gyp/pylib/gyp/generator/compile_commands_json.py +++ b/tools/gyp/pylib/gyp/generator/compile_commands_json.py @@ -2,11 +2,12 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import gyp.common -import gyp.xcode_emulation import json import os +import gyp.common +import gyp.xcode_emulation + generator_additional_non_configuration_keys = [] generator_additional_path_sections = [] generator_extra_sources_for_rules = [] diff --git a/tools/gyp/pylib/gyp/generator/dump_dependency_json.py b/tools/gyp/pylib/gyp/generator/dump_dependency_json.py index 99d5c1fd69db36..e41c72d71070aa 100644 --- a/tools/gyp/pylib/gyp/generator/dump_dependency_json.py +++ b/tools/gyp/pylib/gyp/generator/dump_dependency_json.py @@ -3,11 +3,12 @@ # found in the LICENSE file. +import json import os + import gyp import gyp.common import gyp.msvs_emulation -import json generator_supports_multiple_toolsets = True diff --git a/tools/gyp/pylib/gyp/generator/eclipse.py b/tools/gyp/pylib/gyp/generator/eclipse.py index 52aeae6050990b..ed6daa91bac3e7 100644 --- a/tools/gyp/pylib/gyp/generator/eclipse.py +++ b/tools/gyp/pylib/gyp/generator/eclipse.py @@ -17,14 +17,15 @@ This generator has no automated tests, so expect it to be broken. """ -from xml.sax.saxutils import escape import os.path +import shlex import subprocess +import xml.etree.ElementTree as ET +from xml.sax.saxutils import escape + import gyp import gyp.common import gyp.msvs_emulation -import shlex -import xml.etree.ElementTree as ET generator_wants_static_library_dependencies_adjusted = False diff --git a/tools/gyp/pylib/gyp/generator/gypd.py b/tools/gyp/pylib/gyp/generator/gypd.py index 4171704c47a4b6..a0aa6d9245c811 100644 --- a/tools/gyp/pylib/gyp/generator/gypd.py +++ b/tools/gyp/pylib/gyp/generator/gypd.py @@ -31,9 +31,9 @@ """ -import gyp.common import pprint +import gyp.common # These variables should just be spit back out as variable references. _generator_identity_variables = [ diff --git a/tools/gyp/pylib/gyp/generator/gypsh.py b/tools/gyp/pylib/gyp/generator/gypsh.py index 8dfb1f1645f77c..36a05deb7eb8b9 100644 --- a/tools/gyp/pylib/gyp/generator/gypsh.py +++ b/tools/gyp/pylib/gyp/generator/gypsh.py @@ -17,7 +17,6 @@ import code import sys - # All of this stuff about generator variables was lovingly ripped from gypd.py. # That module has a much better description of what's going on and why. _generator_identity_variables = [ diff --git a/tools/gyp/pylib/gyp/generator/make.py b/tools/gyp/pylib/gyp/generator/make.py index 634da8973c4abe..e860479069abaa 100644 --- a/tools/gyp/pylib/gyp/generator/make.py +++ b/tools/gyp/pylib/gyp/generator/make.py @@ -22,17 +22,17 @@ # the side to keep the files readable. +import hashlib import os import re import subprocess import sys + import gyp import gyp.common import gyp.xcode_emulation from gyp.common import GetEnvironFallback -import hashlib - generator_default_variables = { "EXECUTABLE_PREFIX": "", "EXECUTABLE_SUFFIX": "", @@ -1440,7 +1440,7 @@ def WriteSources( for obj in objs: assert " " not in obj, "Spaces in object filenames not supported (%s)" % obj self.WriteLn( - "# Add to the list of files we specially track " "dependencies for." + "# Add to the list of files we specially track dependencies for." ) self.WriteLn("all_deps += $(OBJS)") self.WriteLn() @@ -1450,7 +1450,7 @@ def WriteSources( self.WriteMakeRule( ["$(OBJS)"], deps, - comment="Make sure our dependencies are built " "before any of us.", + comment="Make sure our dependencies are built before any of us.", order_only=True, ) @@ -1461,7 +1461,7 @@ def WriteSources( self.WriteMakeRule( ["$(OBJS)"], extra_outputs, - comment="Make sure our actions/rules run " "before any of us.", + comment="Make sure our actions/rules run before any of us.", order_only=True, ) @@ -1699,7 +1699,7 @@ def WriteTarget( self.WriteMakeRule( extra_outputs, deps, - comment=("Preserve order dependency of " "special output on deps."), + comment=("Preserve order dependency of special output on deps."), order_only=True, ) @@ -1738,7 +1738,8 @@ def WriteTarget( # into the link command, so we need lots of escaping. ldflags.append(r"-Wl,-rpath=\$$ORIGIN/") ldflags.append(r"-Wl,-rpath-link=\$(builddir)/") - library_dirs = config.get("library_dirs", []) + if library_dirs := config.get("library_dirs", []): + library_dirs = [Sourceify(self.Absolutify(i)) for i in library_dirs] ldflags += [("-L%s" % library_dir) for library_dir in library_dirs] self.WriteList(ldflags, "LDFLAGS_%s" % configname) if self.flavor == "mac": @@ -1844,7 +1845,7 @@ def WriteTarget( "on the bundle, not the binary (target '%s')" % self.target ) assert "product_dir" not in spec, ( - "Postbuilds do not work with " "custom product_dir" + "Postbuilds do not work with custom product_dir" ) if self.type == "executable": @@ -1895,21 +1896,20 @@ def WriteTarget( part_of_all, postbuilds=postbuilds, ) + elif self.flavor in ("linux", "android"): + self.WriteMakeRule( + [self.output_binary], + link_deps, + actions=["$(call create_archive,$@,$^)"], + ) else: - if self.flavor in ("linux", "android"): - self.WriteMakeRule( - [self.output_binary], - link_deps, - actions=["$(call create_archive,$@,$^)"], - ) - else: - self.WriteDoCmd( - [self.output_binary], - link_deps, - "alink", - part_of_all, - postbuilds=postbuilds, - ) + self.WriteDoCmd( + [self.output_binary], + link_deps, + "alink", + part_of_all, + postbuilds=postbuilds, + ) elif self.type == "shared_library": self.WriteLn( "%s: LD_INPUTS := %s" diff --git a/tools/gyp/pylib/gyp/generator/msvs.py b/tools/gyp/pylib/gyp/generator/msvs.py index bea6e643488ad1..b4aea2e69a1939 100644 --- a/tools/gyp/pylib/gyp/generator/msvs.py +++ b/tools/gyp/pylib/gyp/generator/msvs.py @@ -9,22 +9,21 @@ import re import subprocess import sys - from collections import OrderedDict import gyp.common -import gyp.easy_xml as easy_xml import gyp.generator.ninja as ninja_generator -import gyp.MSVSNew as MSVSNew -import gyp.MSVSProject as MSVSProject -import gyp.MSVSSettings as MSVSSettings -import gyp.MSVSToolFile as MSVSToolFile -import gyp.MSVSUserFile as MSVSUserFile -import gyp.MSVSUtil as MSVSUtil -import gyp.MSVSVersion as MSVSVersion -from gyp.common import GypError -from gyp.common import OrderedSet - +from gyp import ( + MSVSNew, + MSVSProject, + MSVSSettings, + MSVSToolFile, + MSVSUserFile, + MSVSUtil, + MSVSVersion, + easy_xml, +) +from gyp.common import GypError, OrderedSet # Regular expression for validating Visual Studio GUIDs. If the GUID # contains lowercase hex letters, MSVS will be fine. However, @@ -185,7 +184,7 @@ def _IsWindowsAbsPath(path): it does not treat those as relative, which results in bad paths like: '..\\C:\\\\some_source_code_file.cc' """ - return path.startswith("c:") or path.startswith("C:") + return path.startswith(("c:", "C:")) def _FixPaths(paths, separator="\\"): @@ -2507,7 +2506,7 @@ def _GenerateMSBuildRuleTargetsFile(targets_path, msbuild_rules): rule_name = rule.rule_name target_outputs = "%%(%s.Outputs)" % rule_name target_inputs = ( - "%%(%s.Identity);%%(%s.AdditionalDependencies);" "$(MSBuildProjectFile)" + "%%(%s.Identity);%%(%s.AdditionalDependencies);$(MSBuildProjectFile)" ) % (rule_name, rule_name) rule_inputs = "%%(%s.Identity)" % rule_name extension_condition = ( @@ -3100,9 +3099,7 @@ def _ConvertMSVSBuildAttributes(spec, config, build_file): msbuild_attributes[a] = _ConvertMSVSCharacterSet(msvs_attributes[a]) elif a == "ConfigurationType": msbuild_attributes[a] = _ConvertMSVSConfigurationType(msvs_attributes[a]) - elif a == "SpectreMitigation": - msbuild_attributes[a] = msvs_attributes[a] - elif a == "VCToolsVersion": + elif a == "SpectreMitigation" or a == "VCToolsVersion": msbuild_attributes[a] = msvs_attributes[a] else: print("Warning: Do not know how to convert MSVS attribute " + a) @@ -3491,11 +3488,10 @@ def _VerifySourcesExist(sources, root_dir): for source in sources: if isinstance(source, MSVSProject.Filter): missing_sources.extend(_VerifySourcesExist(source.contents, root_dir)) - else: - if "$" not in source: - full_path = os.path.join(root_dir, source) - if not os.path.exists(full_path): - missing_sources.append(full_path) + elif "$" not in source: + full_path = os.path.join(root_dir, source) + if not os.path.exists(full_path): + missing_sources.append(full_path) return missing_sources @@ -3565,75 +3561,74 @@ def _AddSources2( sources_handled_by_action, list_excluded, ) - else: - if source not in sources_handled_by_action: - detail = [] - excluded_configurations = exclusions.get(source, []) - if len(excluded_configurations) == len(spec["configurations"]): - detail.append(["ExcludedFromBuild", "true"]) - else: - for config_name, configuration in sorted(excluded_configurations): - condition = _GetConfigurationCondition( - config_name, configuration - ) - detail.append( - ["ExcludedFromBuild", {"Condition": condition}, "true"] - ) - # Add precompile if needed - for config_name, configuration in spec["configurations"].items(): - precompiled_source = configuration.get( - "msvs_precompiled_source", "" + elif source not in sources_handled_by_action: + detail = [] + excluded_configurations = exclusions.get(source, []) + if len(excluded_configurations) == len(spec["configurations"]): + detail.append(["ExcludedFromBuild", "true"]) + else: + for config_name, configuration in sorted(excluded_configurations): + condition = _GetConfigurationCondition( + config_name, configuration ) - if precompiled_source != "": - precompiled_source = _FixPath(precompiled_source) - if not extensions_excluded_from_precompile: - # If the precompiled header is generated by a C source, - # we must not try to use it for C++ sources, - # and vice versa. - basename, extension = os.path.splitext(precompiled_source) - if extension == ".c": - extensions_excluded_from_precompile = [ - ".cc", - ".cpp", - ".cxx", - ] - else: - extensions_excluded_from_precompile = [".c"] - - if precompiled_source == source: - condition = _GetConfigurationCondition( - config_name, configuration, spec - ) - detail.append( - ["PrecompiledHeader", {"Condition": condition}, "Create"] - ) - else: - # Turn off precompiled header usage for source files of a - # different type than the file that generated the - # precompiled header. - for extension in extensions_excluded_from_precompile: - if source.endswith(extension): - detail.append(["PrecompiledHeader", ""]) - detail.append(["ForcedIncludeFiles", ""]) - - group, element = _MapFileToMsBuildSourceType( - source, - rule_dependencies, - extension_to_rule_name, - _GetUniquePlatforms(spec), - spec["toolset"], + detail.append( + ["ExcludedFromBuild", {"Condition": condition}, "true"] + ) + # Add precompile if needed + for config_name, configuration in spec["configurations"].items(): + precompiled_source = configuration.get( + "msvs_precompiled_source", "" ) - if group == "compile" and not os.path.isabs(source): - # Add an value to support duplicate source - # file basenames, except for absolute paths to avoid paths - # with more than 260 characters. - file_name = os.path.splitext(source)[0] + ".obj" - if file_name.startswith("..\\"): - file_name = re.sub(r"^(\.\.\\)+", "", file_name) - elif file_name.startswith("$("): - file_name = re.sub(r"^\$\([^)]+\)\\", "", file_name) - detail.append(["ObjectFileName", "$(IntDir)\\" + file_name]) - grouped_sources[group].append([element, {"Include": source}] + detail) + if precompiled_source != "": + precompiled_source = _FixPath(precompiled_source) + if not extensions_excluded_from_precompile: + # If the precompiled header is generated by a C source, + # we must not try to use it for C++ sources, + # and vice versa. + basename, extension = os.path.splitext(precompiled_source) + if extension == ".c": + extensions_excluded_from_precompile = [ + ".cc", + ".cpp", + ".cxx", + ] + else: + extensions_excluded_from_precompile = [".c"] + + if precompiled_source == source: + condition = _GetConfigurationCondition( + config_name, configuration, spec + ) + detail.append( + ["PrecompiledHeader", {"Condition": condition}, "Create"] + ) + else: + # Turn off precompiled header usage for source files of a + # different type than the file that generated the + # precompiled header. + for extension in extensions_excluded_from_precompile: + if source.endswith(extension): + detail.append(["PrecompiledHeader", ""]) + detail.append(["ForcedIncludeFiles", ""]) + + group, element = _MapFileToMsBuildSourceType( + source, + rule_dependencies, + extension_to_rule_name, + _GetUniquePlatforms(spec), + spec["toolset"], + ) + if group == "compile" and not os.path.isabs(source): + # Add an value to support duplicate source + # file basenames, except for absolute paths to avoid paths + # with more than 260 characters. + file_name = os.path.splitext(source)[0] + ".obj" + if file_name.startswith("..\\"): + file_name = re.sub(r"^(\.\.\\)+", "", file_name) + elif file_name.startswith("$("): + file_name = re.sub(r"^\$\([^)]+\)\\", "", file_name) + detail.append(["ObjectFileName", "$(IntDir)\\" + file_name]) + grouped_sources[group].append([element, {"Include": source}] + detail) def _GetMSBuildProjectReferences(project): diff --git a/tools/gyp/pylib/gyp/generator/msvs_test.py b/tools/gyp/pylib/gyp/generator/msvs_test.py index e80b57f06a130c..8cea3d1479e3b0 100755 --- a/tools/gyp/pylib/gyp/generator/msvs_test.py +++ b/tools/gyp/pylib/gyp/generator/msvs_test.py @@ -5,11 +5,11 @@ """ Unit tests for the msvs.py file. """ -import gyp.generator.msvs as msvs import unittest - from io import StringIO +from gyp.generator import msvs + class TestSequenceFunctions(unittest.TestCase): def setUp(self): diff --git a/tools/gyp/pylib/gyp/generator/ninja.py b/tools/gyp/pylib/gyp/generator/ninja.py index ae3dded9b41b73..b7ac823d1490d6 100644 --- a/tools/gyp/pylib/gyp/generator/ninja.py +++ b/tools/gyp/pylib/gyp/generator/ninja.py @@ -10,20 +10,18 @@ import multiprocessing import os.path import re -import signal import shutil +import signal import subprocess import sys +from io import StringIO + import gyp import gyp.common import gyp.msvs_emulation -import gyp.MSVSUtil as MSVSUtil import gyp.xcode_emulation - -from io import StringIO - +from gyp import MSVSUtil, ninja_syntax from gyp.common import GetEnvironFallback -import gyp.ninja_syntax as ninja_syntax generator_default_variables = { "EXECUTABLE_PREFIX": "", @@ -1465,7 +1463,7 @@ def WriteLinkForArch( # Respect environment variables related to build, but target-specific # flags can still override them. ldflags = env_ldflags + config.get("ldflags", []) - if is_executable and len(solibs): + if is_executable and solibs: rpath = "lib/" if self.toolset != "target": rpath += self.toolset @@ -1555,7 +1553,7 @@ def WriteLinkForArch( if pdbname: output = [output, pdbname] - if len(solibs): + if solibs: extra_bindings.append( ("solibs", gyp.common.EncodePOSIXShellList(sorted(solibs))) ) @@ -2085,7 +2083,7 @@ def CommandWithWrapper(cmd, wrappers, prog): def GetDefaultConcurrentLinks(): """Returns a best-guess for a number of concurrent links.""" - pool_size = int(os.environ.get("GYP_LINK_CONCURRENCY", 0)) + pool_size = int(os.environ.get("GYP_LINK_CONCURRENCY") or 0) if pool_size: return pool_size @@ -2112,7 +2110,7 @@ class MEMORYSTATUSEX(ctypes.Structure): # VS 2015 uses 20% more working set than VS 2013 and can consume all RAM # on a 64 GiB machine. mem_limit = max(1, stat.ullTotalPhys // (5 * (2 ** 30))) # total / 5GiB - hard_cap = max(1, int(os.environ.get("GYP_LINK_CONCURRENCY_MAX", 2 ** 32))) + hard_cap = max(1, int(os.environ.get("GYP_LINK_CONCURRENCY_MAX") or 2 ** 32)) return min(mem_limit, hard_cap) elif sys.platform.startswith("linux"): if os.path.exists("/proc/meminfo"): @@ -2535,7 +2533,7 @@ def GenerateOutputForConfig(target_list, target_dicts, data, params, config_name % {"suffix": "@$link_file_list"}, rspfile="$link_file_list", rspfile_content=( - "-Wl,--whole-archive $in $solibs -Wl," "--no-whole-archive $libs" + "-Wl,--whole-archive $in $solibs -Wl,--no-whole-archive $libs" ), pool="link_pool", ) @@ -2684,7 +2682,7 @@ def GenerateOutputForConfig(target_list, target_dicts, data, params, config_name master_ninja.rule( "link", description="LINK $out, POSTBUILDS", - command=("$ld $ldflags -o $out " "$in $solibs $libs$postbuilds"), + command=("$ld $ldflags -o $out $in $solibs $libs$postbuilds"), pool="link_pool", ) master_ninja.rule( diff --git a/tools/gyp/pylib/gyp/generator/ninja_test.py b/tools/gyp/pylib/gyp/generator/ninja_test.py index 15cddfdf2443bf..581b14595e143e 100644 --- a/tools/gyp/pylib/gyp/generator/ninja_test.py +++ b/tools/gyp/pylib/gyp/generator/ninja_test.py @@ -6,11 +6,11 @@ """ Unit tests for the ninja.py file. """ -from pathlib import Path import sys import unittest +from pathlib import Path -import gyp.generator.ninja as ninja +from gyp.generator import ninja class TestPrefixesAndSuffixes(unittest.TestCase): diff --git a/tools/gyp/pylib/gyp/generator/xcode.py b/tools/gyp/pylib/gyp/generator/xcode.py index c3c000c4ef683d..cdf11c3b27b1d5 100644 --- a/tools/gyp/pylib/gyp/generator/xcode.py +++ b/tools/gyp/pylib/gyp/generator/xcode.py @@ -3,19 +3,19 @@ # found in the LICENSE file. -import filecmp -import gyp.common -import gyp.xcodeproj_file -import gyp.xcode_ninja import errno +import filecmp import os -import sys import posixpath import re import shutil import subprocess +import sys import tempfile +import gyp.common +import gyp.xcode_ninja +import gyp.xcodeproj_file # Project files generated by this module will use _intermediate_var as a # custom Xcode setting whose value is a DerivedSources-like directory that's @@ -793,7 +793,7 @@ def GenerateOutput(target_list, target_dicts, data, params): except KeyError as e: gyp.common.ExceptionAppend( e, - "-- unknown product type while " "writing target %s" % target_name, + "-- unknown product type while writing target %s" % target_name, ) raise else: diff --git a/tools/gyp/pylib/gyp/generator/xcode_test.py b/tools/gyp/pylib/gyp/generator/xcode_test.py index 49772d1f4d8103..b0b51a08a6db48 100644 --- a/tools/gyp/pylib/gyp/generator/xcode_test.py +++ b/tools/gyp/pylib/gyp/generator/xcode_test.py @@ -6,9 +6,10 @@ """ Unit tests for the xcode.py file. """ -import gyp.generator.xcode as xcode -import unittest import sys +import unittest + +from gyp.generator import xcode class TestEscapeXcodeDefine(unittest.TestCase): diff --git a/tools/gyp/pylib/gyp/input.py b/tools/gyp/pylib/gyp/input.py index 5e71fdace0c663..994bf6625fb81d 100644 --- a/tools/gyp/pylib/gyp/input.py +++ b/tools/gyp/pylib/gyp/input.py @@ -4,9 +4,6 @@ import ast - -import gyp.common -import gyp.simple_copy import multiprocessing import os.path import re @@ -16,10 +13,13 @@ import sys import threading import traceback -from gyp.common import GypError -from gyp.common import OrderedSet + from packaging.version import Version +import gyp.common +import gyp.simple_copy +from gyp.common import GypError, OrderedSet + # A list of types that are treated as linkable. linkable_types = [ "executable", @@ -990,25 +990,24 @@ def ExpandVariables(input, phase, variables, build_file): ) replacement = cached_value - else: - if contents not in variables: - if contents[-1] in ["!", "/"]: - # In order to allow cross-compiles (nacl) to happen more naturally, - # we will allow references to >(sources/) etc. to resolve to - # and empty list if undefined. This allows actions to: - # 'action!': [ - # '>@(_sources!)', - # ], - # 'action/': [ - # '>@(_sources/)', - # ], - replacement = [] - else: - raise GypError( - "Undefined variable " + contents + " in " + build_file - ) + elif contents not in variables: + if contents[-1] in ["!", "/"]: + # In order to allow cross-compiles (nacl) to happen more naturally, + # we will allow references to >(sources/) etc. to resolve to + # and empty list if undefined. This allows actions to: + # 'action!': [ + # '>@(_sources!)', + # ], + # 'action/': [ + # '>@(_sources/)', + # ], + replacement = [] else: - replacement = variables[contents] + raise GypError( + "Undefined variable " + contents + " in " + build_file + ) + else: + replacement = variables[contents] if isinstance(replacement, bytes) and not isinstance(replacement, str): replacement = replacement.decode("utf-8") # done on Python 3 only @@ -1074,7 +1073,7 @@ def ExpandVariables(input, phase, variables, build_file): if output == input: gyp.DebugOutput( gyp.DEBUG_VARIABLES, - "Found only identity matches on %r, avoiding infinite " "recursion.", + "Found only identity matches on %r, avoiding infinite recursion.", output, ) else: diff --git a/tools/gyp/pylib/gyp/input_test.py b/tools/gyp/pylib/gyp/input_test.py index a18f72e9ebb0a7..ff8c8fbecc3e53 100755 --- a/tools/gyp/pylib/gyp/input_test.py +++ b/tools/gyp/pylib/gyp/input_test.py @@ -6,9 +6,10 @@ """Unit tests for the input.py file.""" -import gyp.input import unittest +import gyp.input + class TestFindCycles(unittest.TestCase): def setUp(self): diff --git a/tools/gyp/pylib/gyp/mac_tool.py b/tools/gyp/pylib/gyp/mac_tool.py index 59647c9a890349..70aab4f1787f44 100755 --- a/tools/gyp/pylib/gyp/mac_tool.py +++ b/tools/gyp/pylib/gyp/mac_tool.py @@ -59,9 +59,7 @@ def ExecCopyBundleResource(self, source, dest, convert_to_binary): if os.path.exists(dest): shutil.rmtree(dest) shutil.copytree(source, dest) - elif extension == ".xib": - return self._CopyXIBFile(source, dest) - elif extension == ".storyboard": + elif extension in {".xib", ".storyboard"}: return self._CopyXIBFile(source, dest) elif extension == ".strings" and not convert_to_binary: self._CopyStringsFile(source, dest) @@ -70,7 +68,7 @@ def ExecCopyBundleResource(self, source, dest, convert_to_binary): os.unlink(dest) shutil.copy(source, dest) - if convert_to_binary and extension in (".plist", ".strings"): + if convert_to_binary and extension in {".plist", ".strings"}: self._ConvertToBinary(dest) def _CopyXIBFile(self, source, dest): @@ -164,9 +162,7 @@ def _DetectInputEncoding(self, file_name): header = fp.read(3) except Exception: return None - if header.startswith(b"\xFE\xFF"): - return "UTF-16" - elif header.startswith(b"\xFF\xFE"): + if header.startswith((b"\xFE\xFF", b"\xFF\xFE")): return "UTF-16" elif header.startswith(b"\xEF\xBB\xBF"): return "UTF-8" @@ -261,7 +257,7 @@ def ExecFilterLibtool(self, *cmd_list): """Calls libtool and filters out '/path/to/libtool: file: foo.o has no symbols'.""" libtool_re = re.compile( - r"^.*libtool: (?:for architecture: \S* )?" r"file: .* has no symbols$" + r"^.*libtool: (?:for architecture: \S* )?file: .* has no symbols$" ) libtool_re5 = re.compile( r"^.*libtool: warning for library: " diff --git a/tools/gyp/pylib/gyp/msvs_emulation.py b/tools/gyp/pylib/gyp/msvs_emulation.py index adda5a0273f8a6..ace0cae5ebff23 100644 --- a/tools/gyp/pylib/gyp/msvs_emulation.py +++ b/tools/gyp/pylib/gyp/msvs_emulation.py @@ -7,15 +7,15 @@ build systems, primarily ninja. """ -import collections import os import re import subprocess import sys +from collections import namedtuple -from gyp.common import OrderedSet import gyp.MSVSUtil import gyp.MSVSVersion +from gyp.common import OrderedSet windows_quoter_regex = re.compile(r'(\\*)"') @@ -933,7 +933,7 @@ def BuildCygwinBashCommandLine(self, args, path_to_base): ) return cmd - RuleShellFlags = collections.namedtuple("RuleShellFlags", ["cygwin", "quote"]) + RuleShellFlags = namedtuple("RuleShellFlags", ["cygwin", "quote"]) # noqa: PYI024 def GetRuleShellFlags(self, rule): """Return RuleShellFlags about how the given rule should be run. This diff --git a/tools/gyp/pylib/gyp/win_tool.py b/tools/gyp/pylib/gyp/win_tool.py index 171d7295747fcd..7e647f40a84c54 100755 --- a/tools/gyp/pylib/gyp/win_tool.py +++ b/tools/gyp/pylib/gyp/win_tool.py @@ -13,9 +13,9 @@ import os import re import shutil -import subprocess import stat import string +import subprocess import sys BASE_DIR = os.path.dirname(os.path.abspath(__file__)) diff --git a/tools/gyp/pylib/gyp/xcode_emulation.py b/tools/gyp/pylib/gyp/xcode_emulation.py index aee1a542da3299..85a63dfd7ae0e2 100644 --- a/tools/gyp/pylib/gyp/xcode_emulation.py +++ b/tools/gyp/pylib/gyp/xcode_emulation.py @@ -9,13 +9,14 @@ import copy -import gyp.common import os import os.path import re import shlex import subprocess import sys + +import gyp.common from gyp.common import GypError # Populated lazily by XcodeVersion, for efficiency, and to fix an issue when @@ -471,17 +472,14 @@ def _GetStandaloneBinaryPath(self): """Returns the name of the non-bundle binary represented by this target. E.g. hello_world. Only valid for non-bundles.""" assert not self._IsBundle() - assert self.spec["type"] in ( + assert self.spec["type"] in { "executable", "shared_library", "static_library", "loadable_module", - ), ("Unexpected type %s" % self.spec["type"]) + }, ("Unexpected type %s" % self.spec["type"]) target = self.spec["target_name"] - if self.spec["type"] == "static_library": - if target[:3] == "lib": - target = target[3:] - elif self.spec["type"] in ("loadable_module", "shared_library"): + if self.spec["type"] in {"loadable_module", "shared_library", "static_library"}: if target[:3] == "lib": target = target[3:] diff --git a/tools/gyp/pylib/gyp/xcode_emulation_test.py b/tools/gyp/pylib/gyp/xcode_emulation_test.py index 98b02320d5a9ee..03cbbaea84601e 100644 --- a/tools/gyp/pylib/gyp/xcode_emulation_test.py +++ b/tools/gyp/pylib/gyp/xcode_emulation_test.py @@ -2,10 +2,11 @@ """Unit tests for the xcode_emulation.py file.""" -from gyp.xcode_emulation import XcodeSettings import sys import unittest +from gyp.xcode_emulation import XcodeSettings + class TestXcodeSettings(unittest.TestCase): def setUp(self): diff --git a/tools/gyp/pylib/gyp/xcode_ninja.py b/tools/gyp/pylib/gyp/xcode_ninja.py index bb74eacbeaf4ae..cac1af56f7bfb7 100644 --- a/tools/gyp/pylib/gyp/xcode_ninja.py +++ b/tools/gyp/pylib/gyp/xcode_ninja.py @@ -13,11 +13,12 @@ """ import errno -import gyp.generator.ninja import os import re import xml.sax.saxutils +import gyp.generator.ninja + def _WriteWorkspace(main_gyp, sources_gyp, params): """ Create a workspace to wrap main and sources gyp paths. """ diff --git a/tools/gyp/pylib/gyp/xcodeproj_file.py b/tools/gyp/pylib/gyp/xcodeproj_file.py index cd72aa262d2d9d..be17ef946dce35 100644 --- a/tools/gyp/pylib/gyp/xcodeproj_file.py +++ b/tools/gyp/pylib/gyp/xcodeproj_file.py @@ -137,14 +137,15 @@ a project file is output. """ -import gyp.common -from functools import cmp_to_key import hashlib -from operator import attrgetter import posixpath import re import struct import sys +from functools import cmp_to_key +from operator import attrgetter + +import gyp.common def cmp(x, y): @@ -460,7 +461,7 @@ def _HashUpdate(hash, data): digest_int_count = hash.digest_size // 4 digest_ints = struct.unpack(">" + "I" * digest_int_count, hash.digest()) id_ints = [0, 0, 0] - for index in range(0, digest_int_count): + for index in range(digest_int_count): id_ints[index % 3] ^= digest_ints[index] self.id = "%08X%08X%08X" % tuple(id_ints) @@ -1640,7 +1641,6 @@ class PBXVariantGroup(PBXGroup, XCFileLikeElement): """PBXVariantGroup is used by Xcode to represent localizations.""" # No additions to the schema relative to PBXGroup. - pass # PBXReferenceProxy is also an XCFileLikeElement subclass. It is defined below @@ -1766,9 +1766,8 @@ def GetBuildSetting(self, key): configuration_value = configuration.GetBuildSetting(key) if value is None: value = configuration_value - else: - if value != configuration_value: - raise ValueError("Variant values for " + key) + elif value != configuration_value: + raise ValueError("Variant values for " + key) return value @@ -1924,14 +1923,13 @@ def _AddBuildFileToDicts(self, pbxbuildfile, path=None): # It's best when the caller provides the path. if isinstance(xcfilelikeelement, PBXVariantGroup): paths.append(path) + # If the caller didn't provide a path, there can be either multiple + # paths (PBXVariantGroup) or one. + elif isinstance(xcfilelikeelement, PBXVariantGroup): + for variant in xcfilelikeelement._properties["children"]: + paths.append(variant.FullPath()) else: - # If the caller didn't provide a path, there can be either multiple - # paths (PBXVariantGroup) or one. - if isinstance(xcfilelikeelement, PBXVariantGroup): - for variant in xcfilelikeelement._properties["children"]: - paths.append(variant.FullPath()) - else: - paths.append(xcfilelikeelement.FullPath()) + paths.append(xcfilelikeelement.FullPath()) # Add the paths first, because if something's going to raise, the # messages provided by _AddPathToDict are more useful owing to its diff --git a/tools/gyp/pyproject.toml b/tools/gyp/pyproject.toml index 4b0c88c8a22c43..537308731fe542 100644 --- a/tools/gyp/pyproject.toml +++ b/tools/gyp/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "gyp-next" -version = "0.19.1" +version = "0.20.0" authors = [ { name="Node.js contributors", email="ryzokuken@disroot.org" }, ] @@ -92,14 +92,9 @@ select = [ # "TRY", # tryceratops ] ignore = [ - "PLC1901", - "PLR0402", "PLR1714", - "PLR2004", - "PLR5501", "PLW0603", "PLW2901", - "PYI024", "RUF005", "RUF012", "UP031", @@ -109,6 +104,7 @@ ignore = [ max-complexity = 101 [tool.ruff.lint.pylint] +allow-magic-value-types = ["float", "int", "str"] max-args = 11 max-branches = 108 max-returns = 10 diff --git a/tools/gyp/test/fixtures/expected-darwin/cmake/CMakeLists.txt b/tools/gyp/test/fixtures/expected-darwin/cmake/CMakeLists.txt new file mode 100644 index 00000000000000..90b95e75eb5128 --- /dev/null +++ b/tools/gyp/test/fixtures/expected-darwin/cmake/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 2.8.8 FATAL_ERROR) +cmake_policy(VERSION 2.8.8) +project(test) +set(configuration "Default") +enable_language(ASM) +set(builddir "${CMAKE_CURRENT_BINARY_DIR}") +set(obj "${builddir}/obj") + +set(CMAKE_C_OUTPUT_EXTENSION_REPLACE 1) +set(CMAKE_CXX_OUTPUT_EXTENSION_REPLACE 1) + + + +#*/gyp-next/test/fixtures/integration.gyp:test#target +set(TARGET "test") +set(TOOLSET "target") +set(test__cxx_srcs "../../test.cc") +link_directories( ../../mylib +) +add_executable(test ${test__cxx_srcs}) +set_target_properties(test PROPERTIES EXCLUDE_FROM_ALL "FALSE") +set_target_properties(test PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${builddir}") +set_target_properties(test PROPERTIES PREFIX "") +set_target_properties(test PROPERTIES RUNTIME_OUTPUT_NAME "test") +set_target_properties(test PROPERTIES SUFFIX "") +set_source_files_properties(${builddir}/test PROPERTIES GENERATED "TRUE") +set(test__include_dirs "${CMAKE_CURRENT_LIST_DIR}/../../include") +set_property(TARGET test APPEND PROPERTY INCLUDE_DIRECTORIES ${test__include_dirs}) +set_target_properties(test PROPERTIES COMPILE_FLAGS "-fasm-blocks -mpascal-strings -Os -gdwarf-2 -arch x86_64 ") +unset(TOOLSET) +unset(TARGET) diff --git a/tools/gyp/test/fixtures/expected-darwin/make/test.target.mk b/tools/gyp/test/fixtures/expected-darwin/make/test.target.mk new file mode 100644 index 00000000000000..c9e16b63445759 --- /dev/null +++ b/tools/gyp/test/fixtures/expected-darwin/make/test.target.mk @@ -0,0 +1,86 @@ +# This file is generated by gyp; do not edit. + +TOOLSET := target +TARGET := test +DEFS_Default := + +# Flags passed to all source files. +CFLAGS_Default := \ + -fasm-blocks \ + -mpascal-strings \ + -Os \ + -gdwarf-2 \ + -arch \ + x86_64 + +# Flags passed to only C files. +CFLAGS_C_Default := + +# Flags passed to only C++ files. +CFLAGS_CC_Default := + +# Flags passed to only ObjC files. +CFLAGS_OBJC_Default := + +# Flags passed to only ObjC++ files. +CFLAGS_OBJCC_Default := + +INCS_Default := \ + -I$(srcdir)/include + +OBJS := \ + $(obj).target/$(TARGET)/test.o + +# Add to the list of files we specially track dependencies for. +all_deps += $(OBJS) + +# CFLAGS et al overrides must be target-local. +# See "Target-specific Variable Values" in the GNU Make manual. +$(OBJS): TOOLSET := $(TOOLSET) +$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) +$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) +$(OBJS): GYP_OBJCFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) $(CFLAGS_OBJC_$(BUILDTYPE)) +$(OBJS): GYP_OBJCXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) $(CFLAGS_OBJCC_$(BUILDTYPE)) + +# Suffix rules, putting all outputs into $(obj). + +$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) + +# Try building from generated source, too. + +$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) + +$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) + +# End of this set of suffix rules +### Rules for final target. +LDFLAGS_Default := \ + -arch \ + x86_64 \ + -L$(builddir) \ + -L$(srcdir)/mylib + +LIBTOOLFLAGS_Default := + +LIBS := + +$(builddir)/test: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE)) +$(builddir)/test: LIBS := $(LIBS) +$(builddir)/test: GYP_LIBTOOLFLAGS := $(LIBTOOLFLAGS_$(BUILDTYPE)) +$(builddir)/test: LD_INPUTS := $(OBJS) +$(builddir)/test: TOOLSET := $(TOOLSET) +$(builddir)/test: $(OBJS) FORCE_DO_CMD + $(call do_cmd,link) + +all_deps += $(builddir)/test +# Add target alias +.PHONY: test +test: $(builddir)/test + +# Add executable to "all" target. +.PHONY: all +all: $(builddir)/test + diff --git a/tools/gyp/test/fixtures/expected-darwin/ninja/test.ninja b/tools/gyp/test/fixtures/expected-darwin/ninja/test.ninja new file mode 100644 index 00000000000000..fcb1320863303d --- /dev/null +++ b/tools/gyp/test/fixtures/expected-darwin/ninja/test.ninja @@ -0,0 +1,15 @@ +defines = +includes = -I../../include +cflags = -fasm-blocks -mpascal-strings -Os -gdwarf-2 -arch x86_64 +cflags_c = +cflags_cc = +cflags_objc = $cflags_c +cflags_objcc = $cflags_cc +arflags = + +build obj/test.test.o: cxx ../../test.cc + +ldflags = -arch x86_64 -L./ +libs = -L../../mylib +build test: link obj/test.test.o + ld = $ldxx diff --git a/tools/gyp/test/fixtures/expected-linux/cmake/CMakeLists.txt b/tools/gyp/test/fixtures/expected-linux/cmake/CMakeLists.txt new file mode 100644 index 00000000000000..968642201ac653 --- /dev/null +++ b/tools/gyp/test/fixtures/expected-linux/cmake/CMakeLists.txt @@ -0,0 +1,32 @@ +cmake_minimum_required(VERSION 2.8.8 FATAL_ERROR) +cmake_policy(VERSION 2.8.8) +project(test) +set(configuration "Default") +enable_language(ASM) +set(builddir "${CMAKE_CURRENT_BINARY_DIR}") +set(obj "${builddir}/obj") + +set(CMAKE_C_OUTPUT_EXTENSION_REPLACE 1) +set(CMAKE_CXX_OUTPUT_EXTENSION_REPLACE 1) + +set(CMAKE_NINJA_FORCE_RESPONSE_FILE 1) + + +#*/test/fixtures/integration.gyp:test#target +set(TARGET "test") +set(TOOLSET "target") +set(test__cxx_srcs "../../test.cc") +link_directories( ../../mylib +) +add_executable(test ${test__cxx_srcs}) +set_target_properties(test PROPERTIES EXCLUDE_FROM_ALL "FALSE") +set_target_properties(test PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${builddir}") +set_target_properties(test PROPERTIES PREFIX "") +set_target_properties(test PROPERTIES RUNTIME_OUTPUT_NAME "test") +set_target_properties(test PROPERTIES SUFFIX "") +set_source_files_properties(${builddir}/test PROPERTIES GENERATED "TRUE") +set(test__include_dirs "${CMAKE_CURRENT_LIST_DIR}/../../include") +set_property(TARGET test APPEND PROPERTY INCLUDE_DIRECTORIES ${test__include_dirs}) +set_target_properties(test PROPERTIES COMPILE_FLAGS "") +unset(TOOLSET) +unset(TARGET) diff --git a/tools/gyp/test/fixtures/expected-linux/make/test.target.mk b/tools/gyp/test/fixtures/expected-linux/make/test.target.mk new file mode 100644 index 00000000000000..bae91717b4231d --- /dev/null +++ b/tools/gyp/test/fixtures/expected-linux/make/test.target.mk @@ -0,0 +1,66 @@ +# This file is generated by gyp; do not edit. + +TOOLSET := target +TARGET := test +DEFS_Default := + +# Flags passed to all source files. +CFLAGS_Default := + +# Flags passed to only C files. +CFLAGS_C_Default := + +# Flags passed to only C++ files. +CFLAGS_CC_Default := + +INCS_Default := \ + -I$(srcdir)/include + +OBJS := \ + $(obj).target/$(TARGET)/test.o + +# Add to the list of files we specially track dependencies for. +all_deps += $(OBJS) + +# CFLAGS et al overrides must be target-local. +# See "Target-specific Variable Values" in the GNU Make manual. +$(OBJS): TOOLSET := $(TOOLSET) +$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) +$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) + +# Suffix rules, putting all outputs into $(obj). + +$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) + +# Try building from generated source, too. + +$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) + +$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) + +# End of this set of suffix rules +### Rules for final target. +LDFLAGS_Default := \ + -L$(srcdir)/mylib + +LIBS := + +$(builddir)/test: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE)) +$(builddir)/test: LIBS := $(LIBS) +$(builddir)/test: LD_INPUTS := $(OBJS) +$(builddir)/test: TOOLSET := $(TOOLSET) +$(builddir)/test: $(OBJS) FORCE_DO_CMD + $(call do_cmd,link) + +all_deps += $(builddir)/test +# Add target alias +.PHONY: test +test: $(builddir)/test + +# Add executable to "all" target. +.PHONY: all +all: $(builddir)/test + diff --git a/tools/gyp/test/fixtures/expected-linux/ninja/test.ninja b/tools/gyp/test/fixtures/expected-linux/ninja/test.ninja new file mode 100644 index 00000000000000..15c6c3d6978105 --- /dev/null +++ b/tools/gyp/test/fixtures/expected-linux/ninja/test.ninja @@ -0,0 +1,13 @@ +defines = +includes = -I../../include +cflags = +cflags_c = +cflags_cc = +arflags = + +build obj/test.test.o: cxx ../../test.cc + +ldflags = +libs = -L../../mylib +build test: link obj/test.test.o + ld = $ldxx diff --git a/tools/gyp/test/fixtures/include/test.h b/tools/gyp/test/fixtures/include/test.h new file mode 100644 index 00000000000000..eacbb8d7731a17 --- /dev/null +++ b/tools/gyp/test/fixtures/include/test.h @@ -0,0 +1,3 @@ +#pragma once + +int foo(); diff --git a/tools/gyp/test/fixtures/integration.gyp b/tools/gyp/test/fixtures/integration.gyp new file mode 100644 index 00000000000000..c4835117002eb0 --- /dev/null +++ b/tools/gyp/test/fixtures/integration.gyp @@ -0,0 +1,17 @@ +{ + 'targets': [ + { + 'target_name': 'test', + 'type': 'executable', + 'sources': [ + 'test.cc', + ], + 'include_dirs': [ + 'include', + ], + 'library_dirs': [ + 'mylib' + ], + }, + ] +} diff --git a/tools/gyp/test/fixtures/test.cc b/tools/gyp/test/fixtures/test.cc new file mode 100644 index 00000000000000..8b1ecf898119ad --- /dev/null +++ b/tools/gyp/test/fixtures/test.cc @@ -0,0 +1,9 @@ +#include "test.h" + +int main() { + return foo(); +} + +int foo() { + return 0; +} diff --git a/tools/gyp/test/integration_test.py b/tools/gyp/test/integration_test.py new file mode 100644 index 00000000000000..b45a62ff6c74c9 --- /dev/null +++ b/tools/gyp/test/integration_test.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 + +"""Integration test""" + +import os +import re +import shutil +import unittest + +import gyp + +fixture_dir = os.path.join(os.path.dirname(__file__), "fixtures") +gyp_file = os.path.join(os.path.dirname(__file__), "fixtures/integration.gyp") + +supported_sysnames = {"darwin", "linux"} +sysname = os.uname().sysname.lower() +expected_dir = os.path.join(fixture_dir, f"expected-{sysname}") + + +class TestGyp(unittest.TestCase): + def setUp(self) -> None: + if sysname not in supported_sysnames: + self.skipTest(f"Unsupported system: {sysname}") + shutil.rmtree(os.path.join(fixture_dir, "out"), ignore_errors=True) + + def assert_file(self, actual, expected) -> None: + actual_filepath = os.path.join(fixture_dir, actual) + expected_filepath = os.path.join(expected_dir, expected) + + with open(expected_filepath) as in_file: + expected_bytes = re.escape(in_file.read()) + expected_bytes = expected_bytes.replace("\\*", ".*") + expected_re = re.compile(expected_bytes) + + with open(actual_filepath) as in_file: + actual_bytes = in_file.read() + + try: + self.assertRegex(actual_bytes, expected_re) + except Exception: + shutil.copyfile(actual_filepath, f"{expected_filepath}.actual") + raise + + def test_ninja(self) -> None: + rc = gyp.main(["-f", "ninja", "--depth", fixture_dir, gyp_file]) + assert rc == 0 + + self.assert_file("out/Default/obj/test.ninja", "ninja/test.ninja") + + def test_make(self) -> None: + rc = gyp.main( + [ + "-f", + "make", + "--depth", + fixture_dir, + "--generator-output", + "out", + gyp_file, + ] + ) + assert rc == 0 + + self.assert_file("out/test.target.mk", "make/test.target.mk") + + def test_cmake(self) -> None: + rc = gyp.main(["-f", "cmake", "--depth", fixture_dir, gyp_file]) + assert rc == 0 + + self.assert_file("out/Default/CMakeLists.txt", "cmake/CMakeLists.txt") diff --git a/tools/gyp/tools/pretty_gyp.py b/tools/gyp/tools/pretty_gyp.py index 6eef3a1bbf02a5..a023887205c719 100755 --- a/tools/gyp/tools/pretty_gyp.py +++ b/tools/gyp/tools/pretty_gyp.py @@ -7,9 +7,8 @@ """Pretty-prints the contents of a GYP file.""" -import sys import re - +import sys # Regex to remove comments when we're counting braces. COMMENT_RE = re.compile(r"\s*#.*") @@ -136,7 +135,7 @@ def prettyprint_input(lines): else: print(" " * (basic_offset * indent) + line) else: - print("") + print() def main(): diff --git a/tools/gyp/tools/pretty_sln.py b/tools/gyp/tools/pretty_sln.py index 8026699d39e0af..850fb150f4a8be 100755 --- a/tools/gyp/tools/pretty_sln.py +++ b/tools/gyp/tools/pretty_sln.py @@ -16,6 +16,7 @@ import os import re import sys + import pretty_vcproj __author__ = "nsylvain (Nicolas Sylvain)" @@ -118,7 +119,7 @@ def PrintDependencies(projects, deps): if dep_list: for dep in dep_list: print(" - %s" % dep) - print("") + print() print("-- --") diff --git a/tools/gyp/tools/pretty_vcproj.py b/tools/gyp/tools/pretty_vcproj.py index 862400358a1153..c7427ed2d8b805 100755 --- a/tools/gyp/tools/pretty_vcproj.py +++ b/tools/gyp/tools/pretty_vcproj.py @@ -15,9 +15,7 @@ import os import sys - -from xml.dom.minidom import parse -from xml.dom.minidom import Node +from xml.dom.minidom import Node, parse __author__ = "nsylvain (Nicolas Sylvain)" ARGUMENTS = None