Skip to content

Commit fa6ab78

Browse files
authored
Add experimental support for building wheels. (bazel-contrib#159)
Add experimental support for building wheels. Currently only pure python wheels are supported. This extension builds wheels directly, invoking a simple python script that creates the zip archive in the desired format instead of using distutils/setuptools. This will make building platform-dependent wheels easier in the future, as bazel will have full control on how extension code is built.
1 parent 9bc2cd8 commit fa6ab78

File tree

12 files changed

+922
-0
lines changed

12 files changed

+922
-0
lines changed

experimental/BUILD

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Copyright 2018 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
package(default_visibility = ["//visibility:public"])
15+
16+
licenses(["notice"]) # Apache 2.0

experimental/examples/wheel/BUILD

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# Copyright 2018 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
package(default_visibility = ["//visibility:public"])
15+
16+
licenses(["notice"]) # Apache 2.0
17+
18+
load("//python:python.bzl", "py_library", "py_test")
19+
load("//experimental/python:wheel.bzl", "py_package", "py_wheel")
20+
21+
py_library(
22+
name = "main",
23+
srcs = ["main.py"],
24+
deps = [
25+
"//experimental/examples/wheel/lib:simple_module",
26+
"//experimental/examples/wheel/lib:module_with_data",
27+
# Example dependency which is not packaged in the wheel
28+
# due to "packages" filter on py_package rule.
29+
"//examples/helloworld",
30+
],
31+
)
32+
33+
# Package just a specific py_libraries, without their dependencies
34+
py_wheel(
35+
name = "minimal_with_py_library",
36+
# Package data. We're building "example_minimal_library-0.0.1-py3-none-any.whl"
37+
distribution = "example_minimal_library",
38+
python_tag = "py3",
39+
version = "0.0.1",
40+
deps = [
41+
"//experimental/examples/wheel/lib:module_with_data",
42+
"//experimental/examples/wheel/lib:simple_module",
43+
],
44+
)
45+
46+
# Use py_package to collect all transitive dependencies of a target,
47+
# selecting just the files within a specific python package.
48+
py_package(
49+
name = "example_pkg",
50+
# Only include these Python packages.
51+
packages = ["experimental.examples.wheel"],
52+
deps = [":main"],
53+
)
54+
55+
py_wheel(
56+
name = "minimal_with_py_package",
57+
# Package data. We're building "example_minimal_package-0.0.1-py3-none-any.whl"
58+
distribution = "example_minimal_package",
59+
python_tag = "py3",
60+
version = "0.0.1",
61+
deps = [":example_pkg"],
62+
)
63+
64+
# An example that uses all features provided by py_wheel.
65+
py_wheel(
66+
name = "customized",
67+
author = "Example Author with non-ascii characters: żółw",
68+
author_email = "[email protected]",
69+
classifiers = [
70+
"License :: OSI Approved :: Apache Software License",
71+
"Intended Audience :: Developers",
72+
],
73+
console_scripts = {
74+
"customized_wheel": "experimental.examples.wheel.main:main",
75+
},
76+
description_file = "README.md",
77+
# Package data. We're building "example_customized-0.0.1-py3-none-any.whl"
78+
distribution = "example_customized",
79+
homepage = "www.example.com",
80+
license = "Apache 2.0",
81+
python_tag = "py3",
82+
# Requirements embedded into the wheel metadata.
83+
requires = ["pytest"],
84+
version = "0.0.1",
85+
deps = [":example_pkg"],
86+
)
87+
88+
py_test(
89+
name = "wheel_test",
90+
srcs = ["wheel_test.py"],
91+
data = [
92+
":customized",
93+
":minimal_with_py_library",
94+
":minimal_with_py_package",
95+
],
96+
)

experimental/examples/wheel/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This is a sample description of a wheel.

experimental/examples/wheel/lib/BUILD

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Copyright 2018 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
package(default_visibility = ["//visibility:public"])
15+
16+
licenses(["notice"]) # Apache 2.0
17+
18+
load("//python:python.bzl", "py_library")
19+
20+
py_library(
21+
name = "simple_module",
22+
srcs = ["simple_module.py"],
23+
)
24+
25+
py_library(
26+
name = "module_with_data",
27+
srcs = ["module_with_data.py"],
28+
data = [":data.txt"],
29+
)
30+
31+
genrule(
32+
name = "make_data",
33+
outs = ["data.txt"],
34+
cmd = "echo foo bar baz > $@",
35+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Copyright 2018 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
def function():
16+
return "foo"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Copyright 2018 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
def function():
16+
return "bar"

experimental/examples/wheel/main.py

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Copyright 2018 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import experimental.examples.wheel.lib.module_with_data as module_with_data
16+
import experimental.examples.wheel.lib.simple_module as simple_module
17+
18+
19+
def function():
20+
return "baz"
21+
22+
23+
def main():
24+
print(function())
25+
print(module_with_data.function())
26+
print(simple_module.function())
27+
28+
29+
if __name__ == '__main__':
30+
main()
+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# Copyright 2018 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import os
16+
import unittest
17+
import zipfile
18+
19+
20+
class WheelTest(unittest.TestCase):
21+
def test_py_library_wheel(self):
22+
filename = os.path.join(os.environ['TEST_SRCDIR'],
23+
'io_bazel_rules_python', 'experimental',
24+
'examples', 'wheel',
25+
'example_minimal_library-0.0.1-py3-none-any.whl')
26+
with zipfile.ZipFile(filename) as zf:
27+
self.assertEquals(
28+
zf.namelist(),
29+
['experimental/examples/wheel/lib/module_with_data.py',
30+
'experimental/examples/wheel/lib/simple_module.py',
31+
'example_minimal_library-0.0.1.dist-info/WHEEL',
32+
'example_minimal_library-0.0.1.dist-info/METADATA',
33+
'example_minimal_library-0.0.1.dist-info/RECORD'])
34+
35+
def test_py_package_wheel(self):
36+
filename = os.path.join(os.environ['TEST_SRCDIR'],
37+
'io_bazel_rules_python', 'experimental',
38+
'examples', 'wheel',
39+
'example_minimal_package-0.0.1-py3-none-any.whl')
40+
with zipfile.ZipFile(filename) as zf:
41+
self.assertEquals(
42+
zf.namelist(),
43+
['experimental/examples/wheel/lib/data.txt',
44+
'experimental/examples/wheel/lib/module_with_data.py',
45+
'experimental/examples/wheel/lib/simple_module.py',
46+
'experimental/examples/wheel/main.py',
47+
'example_minimal_package-0.0.1.dist-info/WHEEL',
48+
'example_minimal_package-0.0.1.dist-info/METADATA',
49+
'example_minimal_package-0.0.1.dist-info/RECORD'])
50+
51+
def test_customized_wheel(self):
52+
filename = os.path.join(os.environ['TEST_SRCDIR'],
53+
'io_bazel_rules_python', 'experimental',
54+
'examples', 'wheel',
55+
'example_customized-0.0.1-py3-none-any.whl')
56+
with zipfile.ZipFile(filename) as zf:
57+
self.assertEquals(
58+
zf.namelist(),
59+
['experimental/examples/wheel/lib/data.txt',
60+
'experimental/examples/wheel/lib/module_with_data.py',
61+
'experimental/examples/wheel/lib/simple_module.py',
62+
'experimental/examples/wheel/main.py',
63+
'example_customized-0.0.1.dist-info/WHEEL',
64+
'example_customized-0.0.1.dist-info/METADATA',
65+
'example_customized-0.0.1.dist-info/entry_points.txt',
66+
'example_customized-0.0.1.dist-info/RECORD'])
67+
record_contents = zf.read(
68+
'example_customized-0.0.1.dist-info/RECORD')
69+
wheel_contents = zf.read(
70+
'example_customized-0.0.1.dist-info/WHEEL')
71+
metadata_contents = zf.read(
72+
'example_customized-0.0.1.dist-info/METADATA')
73+
# The entries are guaranteed to be sorted.
74+
self.assertEquals(record_contents, b"""\
75+
example_customized-0.0.1.dist-info/METADATA,sha256=TeeEmokHE2NWjkaMcVJuSAq4_AXUoIad2-SLuquRmbg,372
76+
example_customized-0.0.1.dist-info/RECORD,,
77+
example_customized-0.0.1.dist-info/WHEEL,sha256=F01lGfVCzcXUzzQHzUkBmXAcu_TXd5zqMLrvrspncJo,85
78+
example_customized-0.0.1.dist-info/entry_points.txt,sha256=olLJ8FK88aft2pcdj4BD05F8Xyz83Mo51I93tRGT2Yk,74
79+
experimental/examples/wheel/lib/data.txt,sha256=9vJKEdfLu8bZRArKLroPZJh1XKkK3qFMXiM79MBL2Sg,12
80+
experimental/examples/wheel/lib/module_with_data.py,sha256=K_IGAq_CHcZX0HUyINpD1hqSKIEdCn58d9E9nhWF2EA,636
81+
experimental/examples/wheel/lib/simple_module.py,sha256=72-91Dm6NB_jw-7wYQt7shzdwvk5RB0LujIah8g7kr8,636
82+
experimental/examples/wheel/main.py,sha256=E0xCyiPg6fCo4IrFmqo_tqpNGtk1iCewobqD0_KlFd0,935
83+
""")
84+
self.assertEquals(wheel_contents, b"""\
85+
Wheel-Version: 1.0
86+
Generator: wheelmaker 1.0
87+
Root-Is-Purelib: true
88+
Tag: py3-none-any
89+
""")
90+
self.assertEquals(metadata_contents, b"""\
91+
Metadata-Version: 2.1
92+
Name: example_customized
93+
Version: 0.0.1
94+
Author: Example Author with non-ascii characters: \xc5\xbc\xc3\xb3\xc5\x82w
95+
Author-email: [email protected]
96+
Home-page: www.example.com
97+
License: Apache 2.0
98+
Classifier: License :: OSI Approved :: Apache Software License
99+
Classifier: Intended Audience :: Developers
100+
Requires-Dist: pytest
101+
102+
This is a sample description of a wheel.
103+
""")
104+
105+
106+
if __name__ == '__main__':
107+
unittest.main()

experimental/python/BUILD

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Copyright 2018 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
package(default_visibility = ["//visibility:public"])
15+
16+
licenses(["notice"]) # Apache 2.0
17+
18+
exports_files(["wheel.bzl"])

0 commit comments

Comments
 (0)