blob: 61c2d6e58296107a9d99da01291a232ada7f9c0f [file] [log] [blame]
Stella Laurenzoced74772020-07-28 22:42:52 -07001#!/usr/bin/python
2# Copyright 2020 Google LLC
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# https://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16# Given a runfiles directory from a bazel build, does surgery to extract
17# a usable python package directory. In addition to the bazel directory
18# structure being unnecessarily obtuse, it is also really hard to actually
19# name files correctly. This affects python extension modules which must be
20# named with a specific extension suffix. Bazel is extremely unflexible and
21# we patch around it with this script. For the record, there are various ways
22# to write custom rules to do this more natively, but it is all complicated
23# and needless complexity. We opt for a script that is at least readable by
24# mere mortals and in one place.
25# Usage:
26# ./this_script <dest_dir> <path to bazel-bin>
27
28import os
29import platform
30import shutil
31import sys
32import sysconfig
33
Stella Laurenzoced74772020-07-28 22:42:52 -070034FILE_NAME_MAP = {
Lei Zhang578ee652020-08-03 09:33:13 -070035 "binding.so": "binding{}".format(sysconfig.get_config_var("EXT_SUFFIX")),
36 "binding.pyd": False,
37 "binding.dylib": False,
Stella Laurenzoced74772020-07-28 22:42:52 -070038}
39
40
41def get_exe_suffix():
42 if platform.system() == "Windows":
43 return ".exe"
44 else:
45 return ""
46
47
48def copy_prefix(dest_dir, runfiles_dir, prefix):
49 # And finally seek into the corresponding path in the runfiles dir.
50 # Aren't bazel paths fun???
51 # Note that the "iree_core" path segment corresponds to the workspace name.
52 pkg_dir = os.path.join(runfiles_dir, "iree_core", *prefix)
Lei Zhang578ee652020-08-03 09:33:13 -070053 if not os.path.exists(pkg_dir):
54 return
Stella Laurenzoced74772020-07-28 22:42:52 -070055 dest_dir = os.path.join(dest_dir)
56 for root, dirs, files in os.walk(pkg_dir):
57 assert root.startswith(pkg_dir)
58 dest_prefix = root[len(pkg_dir):]
Lei Zhang578ee652020-08-03 09:33:13 -070059 if dest_prefix.startswith(os.path.sep):
60 dest_prefix = dest_prefix[1:]
Stella Laurenzoced74772020-07-28 22:42:52 -070061 local_dest_dir = os.path.join(dest_dir, dest_prefix)
62 os.makedirs(local_dest_dir, exist_ok=True)
63 for file in files:
64 copy_file(os.path.join(root, file), local_dest_dir)
65
66
67def copy_file(src_file, dst_dir):
68 basename = os.path.basename(src_file)
69 dst_file = os.path.join(dst_dir, basename)
70 mapped_name = FILE_NAME_MAP.get(basename)
71 if mapped_name is False:
72 # Skip.
73 return
74 elif mapped_name is not None:
75 dst_file = os.path.join(dst_dir, mapped_name)
76 shutil.copyfile(src_file, dst_file, follow_symlinks=True)
77
78
79def main():
80 # Parse args.
81 dest_dir = sys.argv[1]
82 bazel_bin = sys.argv[2] if len(sys.argv) > 2 else os.path.join(
83 os.path.dirname(__file__), "..", "..", "bazel-bin")
84
85 # Find the path to the runfiles of the built target:
86 # //bindings/python/packaging:all_pyiree_packages
87 runfiles_dir = os.path.join(
88 bazel_bin, "packaging", "python",
89 "all_pyiree_packages%s.runfiles" % (get_exe_suffix(),))
90 if not os.path.isdir(runfiles_dir):
91 print("ERROR: Could not find build target 'all_pyiree_packages':",
92 runfiles_dir)
93 print("Make sure to build target", "//packaging/python:all_pyiree_packages")
94 sys.exit(1)
95
96 copy_prefix(dest_dir, runfiles_dir, ("bindings", "python"))
97 copy_prefix(dest_dir, runfiles_dir,
98 ("integrations", "tensorflow", "bindings", "python"))
99
100
101if __name__ == "__main__":
102 main()