blob: f3a3622fb25ca394b8e5866427190cb06a276af0 [file] [log] [blame]
#!/usr/bin/env python
# Copyright 2020 The Pigweed Authors
#
# 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.
"""Environment setup script for Pigweed.
This script installs everything and writes out a file for the user's shell
to source.
For now, this is valid Python 2 and Python 3. Once we switch to running this
with PyOxidizer it can be upgraded to recent Python 3.
"""
from __future__ import print_function
import argparse
import glob
import os
import shutil
import subprocess
import sys
# TODO(mohrr) remove import-error disabling, not sure why pylint has issues
# with it.
import cipd_setup.update # pylint: disable=import-error
import cipd_setup.wrapper # pylint: disable=import-error
import cargo_setup # pylint: disable=import-error
import environment # pylint: disable=import-error
import host_build_setup # pylint: disable=import-error
import virtualenv_setup # pylint: disable=import-error
# TODO(mohrr) remove disable=useless-object-inheritance once in Python 3.
# pylint: disable=useless-object-inheritance
class EnvSetup(object):
"""Run environment setup for Pigweed."""
def __init__(self, pw_root, cipd_cache_dir, shell_file, *args, **kwargs):
super(EnvSetup, self).__init__(*args, **kwargs)
self._env = environment.Environment()
self._pw_root = pw_root
self._cipd_cache_dir = cipd_cache_dir
self._shell_file = shell_file
if os.path.isfile(shell_file):
os.unlink(shell_file)
if isinstance(self._pw_root, bytes) and bytes != str:
self._pw_root = self._pw_root.decode()
self._env.set('PW_ROOT', self._pw_root)
def setup(self):
steps = [
('cipd', self.cipd),
('python', self.virtualenv),
('host_tools', self.host_build),
]
if os.name != 'nt':
# TODO(pwbug/63): Add a Windows version of cargo to CIPD.
steps.append(('cargo', self.cargo))
for name, step in steps:
print('Setting up {}...\n'.format(name), file=sys.stdout)
step()
print('\nSetting up {}...done.'.format(name), file=sys.stdout)
with open(self._shell_file, 'w') as outs:
self._env.write(outs)
def cipd(self):
install_dir = os.path.join(self._pw_root, '.cipd')
cipd_client = cipd_setup.wrapper.init(install_dir)
package_files = glob.glob(
os.path.join(self._pw_root, 'env_setup', 'cipd_setup', '*.json'))
cipd_setup.update.update(
cipd=cipd_client,
root_install_dir=install_dir,
package_files=package_files,
cache_dir=self._cipd_cache_dir,
env_vars=self._env,
)
self._env.echo('Setting CIPD environment variables...done.')
def virtualenv(self):
"""Setup virtualenv."""
venv_path = os.path.join(self._pw_root, '.python3-env')
requirements = os.path.join(self._pw_root, 'env_setup',
'virtualenv_setup', 'requirements.txt')
cipd_bin = os.path.join(
self._pw_root,
'.cipd',
'pigweed',
'bin',
)
if os.name == 'nt':
# There is an issue with the virtualenv module on Windows where it
# expects sys.executable to be called "python.exe" or it fails to
# properly execute. Create a copy of python3.exe called python.exe
# so that virtualenv works.
old_python = os.path.join(cipd_bin, 'python3.exe')
new_python = os.path.join(cipd_bin, 'python.exe')
if not os.path.exists(new_python):
shutil.copyfile(old_python, new_python)
py_executable = 'python.exe'
else:
py_executable = 'python3'
python = os.path.join(cipd_bin, py_executable)
virtualenv_setup.install(
venv_path=venv_path,
requirements=[requirements],
python=python,
env=self._env,
)
self._env.echo('Setting virtualenv environment variables...done.')
def host_build(self):
host_build_setup.install(pw_root=self._pw_root, env=self._env)
self._env.echo('Setting host_build environment variables...done.')
def cargo(self):
if os.environ.get('PW_CARGO_SETUP', ''):
cargo_setup.install(pw_root=self._pw_root, env=self._env)
self._env.echo('Setting cargo environment variables...done.')
else:
msg = 'cargo setup skipped, set PW_CARGO_SETUP to include it'
print(msg)
self._env.echo(msg)
def parse(argv=None):
"""Parse command-line arguments."""
parser = argparse.ArgumentParser()
pw_root = os.environ.get('PW_ROOT', None)
if not pw_root:
try:
with open(os.devnull, 'w') as outs:
pw_root = subprocess.check_output(
['git', 'rev-parse', '--show-toplevel'],
stderr=outs).strip()
except subprocess.CalledProcessError:
pw_root = None
parser.add_argument(
'--pw-root',
default=pw_root,
required=not pw_root,
)
parser.add_argument(
'--cipd-cache-dir',
default=os.environ.get('CIPD_CACHE_DIR',
os.path.expanduser('~/.cipd-cache-dir')),
)
parser.add_argument(
'--shell-file',
help='Where to write the file for shells to source.',
required=True,
)
return parser.parse_args(argv)
def main():
return EnvSetup(**vars(parse())).setup()
if __name__ == '__main__':
sys.exit(main())