2012-07-23 00:19:30 -07:00
|
|
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
|
|
# You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
|
|
|
|
# This file contains code for populating the virtualenv environment for
|
|
|
|
# Mozilla's build system. It is typically called as part of configure.
|
|
|
|
|
2012-07-24 22:44:08 -07:00
|
|
|
from __future__ import with_statement
|
2012-09-19 11:20:13 -07:00
|
|
|
import os
|
2012-09-20 00:52:12 -07:00
|
|
|
import shutil
|
2012-07-23 00:19:30 -07:00
|
|
|
import subprocess
|
|
|
|
import sys
|
2012-07-24 22:44:08 -07:00
|
|
|
import distutils.sysconfig
|
2012-07-23 00:19:30 -07:00
|
|
|
|
2012-09-19 11:20:13 -07:00
|
|
|
def populate_virtualenv(top_source_directory, manifest_filename, log_handle):
|
2012-07-23 00:19:30 -07:00
|
|
|
"""Populate the virtualenv from the contents of a manifest.
|
|
|
|
|
|
|
|
The manifest file consists of colon-delimited fields. The first field
|
|
|
|
specifies the action. The remaining fields are arguments to that action.
|
|
|
|
The following actions are supported:
|
|
|
|
|
|
|
|
setup.py -- Invoke setup.py for a package. Expects the arguments:
|
|
|
|
1. relative path directory containing setup.py.
|
|
|
|
2. argument(s) to setup.py. e.g. "develop". Each program argument is
|
|
|
|
delimited by a colon. Arguments with colons are not yet supported.
|
|
|
|
|
2012-09-20 00:52:12 -07:00
|
|
|
filename.pth -- Adds the path given as argument to filename.pth under
|
|
|
|
the virtualenv site packages directory.
|
|
|
|
|
2012-09-19 11:20:13 -07:00
|
|
|
optional -- This denotes the action as optional. The requested action
|
|
|
|
is attempted. If it fails, we issue a warning and go on. The initial
|
|
|
|
"optional" field is stripped then the remaining line is processed
|
|
|
|
like normal. e.g. "optional:setup.py:python/foo:built_ext:-i"
|
|
|
|
|
2012-09-20 00:52:12 -07:00
|
|
|
copy -- Copies the given file in the virtualenv site packages directory.
|
|
|
|
|
2012-07-23 00:19:30 -07:00
|
|
|
Note that the Python interpreter running this function should be the one
|
|
|
|
from the virtualenv. If it is the system Python or if the environment is
|
|
|
|
not configured properly, packages could be installed into the wrong place.
|
|
|
|
This is how virtualenv's work.
|
|
|
|
"""
|
|
|
|
packages = []
|
|
|
|
fh = open(manifest_filename, 'rU')
|
|
|
|
for line in fh:
|
|
|
|
packages.append(line.rstrip().split(':'))
|
|
|
|
fh.close()
|
|
|
|
|
2012-09-19 11:20:13 -07:00
|
|
|
def handle_package(package):
|
2012-09-20 00:52:12 -07:00
|
|
|
python_lib = distutils.sysconfig.get_python_lib()
|
2012-07-23 00:19:30 -07:00
|
|
|
if package[0] == 'setup.py':
|
|
|
|
assert len(package) >= 2
|
|
|
|
|
|
|
|
call_setup(os.path.join(top_source_directory, package[1]),
|
|
|
|
package[2:])
|
2012-09-19 11:20:13 -07:00
|
|
|
|
|
|
|
return True
|
|
|
|
|
2012-09-20 00:52:12 -07:00
|
|
|
if package[0] == 'copy':
|
|
|
|
assert len(package) == 2
|
|
|
|
|
|
|
|
shutil.copy(os.path.join(top_source_directory, package[1]),
|
|
|
|
os.path.join(python_lib, os.path.basename(package[1])))
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
2012-07-24 22:44:08 -07:00
|
|
|
if package[0].endswith('.pth'):
|
|
|
|
assert len(package) == 2
|
|
|
|
|
2012-09-20 00:52:12 -07:00
|
|
|
with open(os.path.join(python_lib, package[0]), 'a') as f:
|
2012-07-24 22:44:08 -07:00
|
|
|
f.write("%s\n" % os.path.join(top_source_directory, package[1]))
|
2012-07-23 00:19:30 -07:00
|
|
|
|
2012-09-19 11:20:13 -07:00
|
|
|
return True
|
|
|
|
|
|
|
|
if package[0] == 'optional':
|
|
|
|
try:
|
|
|
|
handle_package(package[1:])
|
|
|
|
return True
|
|
|
|
except:
|
|
|
|
print >>log_handle, 'Error processing command. Ignoring', \
|
|
|
|
'because optional. (%s)' % ':'.join(package)
|
|
|
|
return False
|
|
|
|
|
|
|
|
raise Exception('Unknown action: %s' % package[0])
|
|
|
|
|
|
|
|
for package in packages:
|
|
|
|
handle_package(package)
|
|
|
|
|
|
|
|
|
2012-07-23 00:19:30 -07:00
|
|
|
def call_setup(directory, arguments):
|
|
|
|
"""Calls setup.py in a directory."""
|
|
|
|
setup = os.path.join(directory, 'setup.py')
|
|
|
|
|
|
|
|
program = [sys.executable, setup]
|
|
|
|
program.extend(arguments)
|
|
|
|
|
|
|
|
# We probably could call the contents of this file inside the context of
|
|
|
|
# this interpreter using execfile() or similar. However, if global
|
|
|
|
# variables like sys.path are adjusted, this could cause all kinds of
|
|
|
|
# havoc. While this may work, invoking a new process is safer.
|
|
|
|
result = subprocess.call(program, cwd=directory)
|
|
|
|
|
|
|
|
if result != 0:
|
|
|
|
raise Exception('Error installing package: %s' % directory)
|
|
|
|
|
|
|
|
# configure invokes us with /path/to/topsrcdir and /path/to/manifest
|
|
|
|
if __name__ == '__main__':
|
|
|
|
assert len(sys.argv) == 3
|
|
|
|
|
2012-09-19 11:20:13 -07:00
|
|
|
populate_virtualenv(sys.argv[1], sys.argv[2], sys.stdout)
|
2012-07-23 00:19:30 -07:00
|
|
|
sys.exit(0)
|