blob: 61c2d6e58296107a9d99da01291a232ada7f9c0f [file] [log] [blame]
#!/usr/bin/python
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Given a runfiles directory from a bazel build, does surgery to extract
# a usable python package directory. In addition to the bazel directory
# structure being unnecessarily obtuse, it is also really hard to actually
# name files correctly. This affects python extension modules which must be
# named with a specific extension suffix. Bazel is extremely unflexible and
# we patch around it with this script. For the record, there are various ways
# to write custom rules to do this more natively, but it is all complicated
# and needless complexity. We opt for a script that is at least readable by
# mere mortals and in one place.
# Usage:
# ./this_script <dest_dir> <path to bazel-bin>
import os
import platform
import shutil
import sys
import sysconfig
FILE_NAME_MAP = {
"binding.so": "binding{}".format(sysconfig.get_config_var("EXT_SUFFIX")),
"binding.pyd": False,
"binding.dylib": False,
}
def get_exe_suffix():
if platform.system() == "Windows":
return ".exe"
else:
return ""
def copy_prefix(dest_dir, runfiles_dir, prefix):
# And finally seek into the corresponding path in the runfiles dir.
# Aren't bazel paths fun???
# Note that the "iree_core" path segment corresponds to the workspace name.
pkg_dir = os.path.join(runfiles_dir, "iree_core", *prefix)
if not os.path.exists(pkg_dir):
return
dest_dir = os.path.join(dest_dir)
for root, dirs, files in os.walk(pkg_dir):
assert root.startswith(pkg_dir)
dest_prefix = root[len(pkg_dir):]
if dest_prefix.startswith(os.path.sep):
dest_prefix = dest_prefix[1:]
local_dest_dir = os.path.join(dest_dir, dest_prefix)
os.makedirs(local_dest_dir, exist_ok=True)
for file in files:
copy_file(os.path.join(root, file), local_dest_dir)
def copy_file(src_file, dst_dir):
basename = os.path.basename(src_file)
dst_file = os.path.join(dst_dir, basename)
mapped_name = FILE_NAME_MAP.get(basename)
if mapped_name is False:
# Skip.
return
elif mapped_name is not None:
dst_file = os.path.join(dst_dir, mapped_name)
shutil.copyfile(src_file, dst_file, follow_symlinks=True)
def main():
# Parse args.
dest_dir = sys.argv[1]
bazel_bin = sys.argv[2] if len(sys.argv) > 2 else os.path.join(
os.path.dirname(__file__), "..", "..", "bazel-bin")
# Find the path to the runfiles of the built target:
# //bindings/python/packaging:all_pyiree_packages
runfiles_dir = os.path.join(
bazel_bin, "packaging", "python",
"all_pyiree_packages%s.runfiles" % (get_exe_suffix(),))
if not os.path.isdir(runfiles_dir):
print("ERROR: Could not find build target 'all_pyiree_packages':",
runfiles_dir)
print("Make sure to build target", "//packaging/python:all_pyiree_packages")
sys.exit(1)
copy_prefix(dest_dir, runfiles_dir, ("bindings", "python"))
copy_prefix(dest_dir, runfiles_dir,
("integrations", "tensorflow", "bindings", "python"))
if __name__ == "__main__":
main()