Skip to content

Commit 0de91dc

Browse files
authored
Merge pull request #23822 from drodriguez/build-script-product-builder-ninja
[build-script] Introduce ProductBuilder. Transform Ninja to use it.
2 parents a6ff7bd + 5c0e743 commit 0de91dc

File tree

4 files changed

+110
-15
lines changed

4 files changed

+110
-15
lines changed

utils/build-script

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -444,11 +444,12 @@ class BuildScriptInvocation(object):
444444
"can't find source directory for ninja "
445445
"(tried %s)" % (self.workspace.source_dir("ninja")))
446446

447-
ninja_build = products.Ninja(
447+
ninja_build = products.Ninja.new_builder(
448448
args=self.args,
449449
toolchain=self.toolchain,
450-
source_dir=self.workspace.source_dir("ninja"),
451-
build_dir=self.workspace.build_dir("build", "ninja"))
450+
workspace=self.workspace,
451+
host=StdlibDeploymentTarget.get_target_for_name(
452+
self.args.host_target))
452453
ninja_build.build()
453454
self.toolchain.ninja = ninja_build.ninja_bin_path
454455

utils/swift_build_support/swift_build_support/products/ninja.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,20 @@ class Ninja(product.Product):
2828
def is_build_script_impl_product(cls):
2929
return False
3030

31+
@classmethod
32+
def new_builder(cls, args, toolchain, workspace, host):
33+
return NinjaBuilder(cls, args, toolchain, workspace)
34+
35+
36+
class NinjaBuilder(product.ProductBuilder):
37+
def __init__(self, product_class, args, toolchain, workspace):
38+
self.source_dir = workspace.source_dir(
39+
product_class.product_source_name())
40+
self.build_dir = workspace.build_dir('build',
41+
product_class.product_name())
42+
self.args = args
43+
self.toolchain = toolchain
44+
3145
@cache_util.reify
3246
def ninja_bin_path(self):
3347
return os.path.join(self.build_dir, 'ninja')

utils/swift_build_support/swift_build_support/products/product.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#
1111
# ----------------------------------------------------------------------------
1212

13+
import abc
14+
1315

1416
class Product(object):
1517
@classmethod
@@ -58,3 +60,76 @@ def __init__(self, args, toolchain, source_dir, build_dir):
5860
self.source_dir = source_dir
5961
self.build_dir = build_dir
6062
self.cmake_options = []
63+
64+
65+
class ProductBuilder(object):
66+
"""
67+
Abstract base class for all ProductBuilders.
68+
69+
An specific ProductBuilder will implement the interface methods depending
70+
how the product want to be build. Multiple products can use the same
71+
product builder if parametrized right (for example all the products build
72+
using CMake).
73+
74+
Ideally a ProductBuilder will be initialized with references to the
75+
invocation arguments, the calculated toolchain, the calculated workspace,
76+
and the target host, but the base class doesn't impose those requirements
77+
in order to be flexible.
78+
79+
NOTE: Python doesn't need an explicit abstract base class, but it helps
80+
documenting the interface.
81+
"""
82+
83+
@abc.abstractmethod
84+
def __init__(self, product_class, args, toolchain, workspace):
85+
"""
86+
Create a product builder for the given product class.
87+
88+
Parameters
89+
----------
90+
product_class : class
91+
A subtype of `Product` which describes the product being built by
92+
this builder.
93+
args : `argparse.Namespace`
94+
The arguments passed by the user to the invocation of the script. A
95+
builder should consider this argument read-only.
96+
toolchain : `swift_build_support.toolchain.Toolchain`
97+
The toolchain being used to build the product. The toolchain will
98+
point to the tools that the builder should use to build (like the
99+
compiler or the linker).
100+
workspace : `swift_build_support.workspace.Workspace`
101+
The workspace where the source code and the build directories have
102+
to be located. A builder should use the workspace to access its own
103+
source/build directory, as well as other products source/build
104+
directories.
105+
"""
106+
pass
107+
108+
@abc.abstractmethod
109+
def build(self):
110+
"""
111+
Perform the build phase for the product.
112+
113+
This phase might also imply a configuration phase, but each product
114+
builder is free to determine how to do it.
115+
"""
116+
pass
117+
118+
@abc.abstractmethod
119+
def test(self):
120+
"""
121+
Perform the test phase for the product.
122+
123+
This phase might build and execute the product tests.
124+
"""
125+
pass
126+
127+
@abc.abstractmethod
128+
def install(self):
129+
"""
130+
Perform the install phase for the product.
131+
132+
This phase might copy the artifacts from the previous phases into a
133+
destination directory.
134+
"""
135+
pass

utils/swift_build_support/tests/products/test_ninja.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from swift_build_support import shell
2727
from swift_build_support import xcrun
2828
from swift_build_support.products import Ninja
29+
from swift_build_support.targets import StdlibDeploymentTarget
2930
from swift_build_support.toolchain import host_toolchain
3031
from swift_build_support.workspace import Workspace
3132

@@ -41,6 +42,8 @@ def setUp(self):
4142
self.workspace = Workspace(source_root=tmpdir1,
4243
build_root=tmpdir2)
4344

45+
self.host = StdlibDeploymentTarget.host_target()
46+
4447
# Setup toolchain
4548
self.toolchain = host_toolchain()
4649
self.toolchain.cc = '/path/to/cc'
@@ -71,20 +74,23 @@ def tearDown(self):
7174
self.args = None
7275

7376
def test_ninja_bin_path(self):
74-
ninja_build = Ninja(
77+
ninja_build = Ninja.new_builder(
7578
args=self.args,
7679
toolchain=self.toolchain,
77-
source_dir='/path/to/src',
78-
build_dir='/path/to/build')
80+
workspace=self.workspace,
81+
host=self.host)
7982

80-
self.assertEqual(ninja_build.ninja_bin_path, '/path/to/build/ninja')
83+
self.assertEqual(ninja_build.ninja_bin_path,
84+
os.path.join(
85+
self.workspace.build_dir('build', 'ninja'),
86+
'ninja'))
8187

8288
def test_build(self):
83-
ninja_build = Ninja(
89+
ninja_build = Ninja.new_builder(
8490
args=self.args,
8591
toolchain=self.toolchain,
86-
source_dir=self.workspace.source_dir('ninja'),
87-
build_dir=self.workspace.build_dir('build', 'ninja'))
92+
workspace=self.workspace,
93+
host=self.host)
8894

8995
ninja_build.build()
9096

@@ -113,8 +119,7 @@ def test_build(self):
113119
+ pushd {build_dir}
114120
+ {expect_env}{python} configure.py --bootstrap
115121
+ popd
116-
""".format(
117-
source_dir=os.path.join(self.workspace.source_root, 'ninja'),
118-
build_dir=os.path.join(self.workspace.build_root, 'ninja-build'),
119-
expect_env=expect_env,
120-
python=sys.executable))
122+
""".format(source_dir=self.workspace.source_dir('ninja'),
123+
build_dir=self.workspace.build_dir('build', 'ninja'),
124+
expect_env=expect_env,
125+
python=sys.executable))

0 commit comments

Comments
 (0)