Skip to content

Commit

Permalink
build: update bazelify to support arm64 targets
Browse files Browse the repository at this point in the history
  • Loading branch information
bpowers committed Nov 7, 2021
1 parent 0747f14 commit 2d287a3
Showing 1 changed file with 100 additions and 18 deletions.
118 changes: 100 additions & 18 deletions bazel
Expand Up @@ -15,9 +15,11 @@ See the License for the specific language governing permissions and
limitations under the License.
"""

import base64
from contextlib import closing
from distutils.version import LooseVersion
import json
import netrc
import os
import os.path
import platform
Expand All @@ -29,10 +31,13 @@ import tempfile
import time

try:
from urllib.request import urlopen
from urllib.parse import urlparse
from urllib.request import urlopen, Request
except ImportError:
# Python 2.x compatibility hack.
from urllib2 import urlopen
# http://python-future.org/compatible_idioms.html?highlight=urllib#urllib-module
from urlparse import urlparse
from urllib2 import urlopen, Request

ONE_HOUR = 1 * 60 * 60

Expand All @@ -57,6 +62,8 @@ TOOLS_BAZEL_PATH = "./tools/bazel"

BAZEL_REAL = "BAZEL_REAL"

BAZEL_UPSTREAM = "bazelbuild"


def decide_which_bazel_version_to_use():
# Check in this order:
Expand Down Expand Up @@ -193,9 +200,14 @@ def get_operating_system():
return operating_system


def determine_executable_filename_suffix():
operating_system = get_operating_system()
return ".exe" if operating_system == "windows" else ""


def determine_bazel_filename(version):
machine = normalized_machine_arch_name()
if machine != "x86_64":
if machine != "x86_64" and machine != 'arm64':
raise Exception(
'Unsupported machine architecture "{}". Bazel currently only supports x86_64.'.format(
machine
Expand All @@ -204,8 +216,11 @@ def determine_bazel_filename(version):

operating_system = get_operating_system()

filename_ending = ".exe" if operating_system == "windows" else ""
return "bazel-{}-{}-{}{}".format(version, operating_system, machine, filename_ending)
filename_suffix = determine_executable_filename_suffix()
bazel_flavor = "bazel"
if os.environ.get("BAZELISK_NOJDK", "0") != "0":
bazel_flavor = "bazel_nojdk"
return "{}-{}-{}-{}{}".format(bazel_flavor, version, operating_system, machine, filename_suffix)


def normalized_machine_arch_name():
Expand All @@ -226,24 +241,56 @@ def determine_url(version, is_commit, bazel_filename):
# Split version into base version and optional additional identifier.
# Example: '0.19.1' -> ('0.19.1', None), '0.20.0rc1' -> ('0.20.0', 'rc1')
(version, rc) = re.match(r"(\d*\.\d*(?:\.\d*)?)(rc\d+)?", version).groups()
return "https://releases.bazel.build/{}/{}/{}".format(
version, rc if rc else "release", bazel_filename
)

if "BAZELISK_BASE_URL" in os.environ:
return "{}/{}/{}".format(
os.environ["BAZELISK_BASE_URL"], version, bazel_filename
)
else:
return "https://releases.bazel.build/{}/{}/{}".format(
version, rc if rc else "release", bazel_filename
)


def trim_suffix(string, suffix):
if string.endswith(suffix):
return string[:len(string) - len(suffix)]
else:
return string


def download_bazel_into_directory(version, is_commit, directory):
bazel_filename = determine_bazel_filename(version)
url = determine_url(version, is_commit, bazel_filename)
destination_path = os.path.join(directory, bazel_filename)

filename_suffix = determine_executable_filename_suffix()
bazel_directory_name = trim_suffix(bazel_filename, filename_suffix)
destination_dir = os.path.join(directory, bazel_directory_name, "bin")
maybe_makedirs(destination_dir)

destination_path = os.path.join(destination_dir, "bazel" + filename_suffix)
if not os.path.exists(destination_path):
sys.stderr.write("Downloading {}...\n".format(url))
with tempfile.NamedTemporaryFile(prefix="bazelisk", dir=directory, delete=False) as t:
with closing(urlopen(url)) as response:
with tempfile.NamedTemporaryFile(prefix="bazelisk", dir=destination_dir, delete=False) as t:
# https://github.com/bazelbuild/bazelisk/issues/247
request = Request(url)
if "BAZELISK_BASE_URL" in os.environ:
parts = urlparse(url)
creds = None
try:
creds = netrc.netrc().hosts.get(parts.netloc)
except:
pass
if creds is not None:
auth = base64.b64encode(('%s:%s' % (creds[0], creds[2])).encode('ascii'))
request.add_header("Authorization", "Basic %s" % auth.decode('utf-8'))
with closing(urlopen(request)) as response:
shutil.copyfileobj(response, t)
t.flush()
os.fsync(t.fileno())
os.rename(t.name, destination_path)
os.chmod(destination_path, 0o755)
os.chmod(destination_path, 0o755)

return destination_path


Expand Down Expand Up @@ -308,14 +355,38 @@ def delegate_tools_bazel(bazel_path):
return None


def execute_bazel(bazel_path, argv):
def prepend_directory_to_path(env, directory):
"""
Prepend binary directory to PATH
"""
if "PATH" in env:
env["PATH"] = directory + os.pathsep + env["PATH"]
else:
env["PATH"] = directory


def make_bazel_cmd(bazel_path, argv):
env = os.environ.copy()

wrapper = delegate_tools_bazel(bazel_path)
if wrapper:
os.putenv(BAZEL_REAL, bazel_path)
env[BAZEL_REAL] = bazel_path
bazel_path = wrapper

directory = os.path.dirname(bazel_path)
prepend_directory_to_path(env, directory)
return {
'exec': bazel_path,
'args': argv,
'env': env,
}


def execute_bazel(bazel_path, argv):
cmd = make_bazel_cmd(bazel_path, argv)

# We cannot use close_fds on Windows, so disable it there.
p = subprocess.Popen([bazel_path] + argv, close_fds=os.name != "nt")
p = subprocess.Popen([cmd['exec']] + cmd['args'], close_fds=os.name != "nt", env=cmd['env'])
while True:
try:
return p.wait()
Expand All @@ -334,16 +405,27 @@ def get_bazel_path():
bazelisk_directory, bazel_version
)

bazel_directory = os.path.join(bazelisk_directory, "bin")
maybe_makedirs(bazel_directory)
# TODO: Support other forks just like Go version
bazel_directory = os.path.join(bazelisk_directory, "downloads", BAZEL_UPSTREAM)
return download_bazel_into_directory(bazel_version, is_commit, bazel_directory)


def main(argv=None):
if argv is None:
argv = sys.argv

return execute_bazel(get_bazel_path(), argv[1:])
bazel_path = get_bazel_path()

argv = argv[1:]

if argv and argv[0] == "--print_env":
cmd = make_bazel_cmd(bazel_path, argv)
env = cmd['env']
for key in env:
print('{}={}'.format(key, env[key]))
return 0

return execute_bazel(bazel_path, argv)


if __name__ == "__main__":
Expand Down

0 comments on commit 2d287a3

Please sign in to comment.