aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Fung <stevefung@google.com>2016-04-19 01:46:29 -0700
committerSteve Fung <stevefung@google.com>2016-04-19 20:13:49 +0000
commit868d93486cf3d558132b2d08f76d9ffb1f1cfbbb (patch)
treeaa2e217fc3c7364c72e8acb0bb0abff9e072d398
parentc357ad7a2fa25390e25497a199028bd118075004 (diff)
downloadbdk-868d93486cf3d558132b2d08f76d9ffb1f1cfbbb.tar.gz
Convert environment/ to 4 space indent
Convert all files in the environment/ folder to a 4 space indent to comply with PEP8 style rules. Bug: 28007659 Test: `python test_runner.py` passes. Test: pylint passes. Change-Id: Ib079be15e5ecc2cb705b5270e0dd730f490080dc
-rw-r--r--cli/lib/environment/sysroot.py466
-rw-r--r--cli/lib/environment/sysroot_stub.py211
-rw-r--r--cli/lib/environment/sysroot_unittest.py722
-rw-r--r--cli/lib/environment/sysroot_util.py592
-rw-r--r--cli/lib/environment/sysroot_util_unittest.py290
-rw-r--r--cli/lib/environment/toolchain_util.py132
-rw-r--r--cli/lib/environment/toolchain_util_unittest.py95
7 files changed, 1269 insertions, 1239 deletions
diff --git a/cli/lib/environment/sysroot.py b/cli/lib/environment/sysroot.py
index ce25612..a07fd28 100644
--- a/cli/lib/environment/sysroot.py
+++ b/cli/lib/environment/sysroot.py
@@ -24,236 +24,244 @@ import shutil
class Sysroot(object):
- """A wrapper around basic os/file system operations as pertains to a sysroot.
+ """A wrapper around basic os/file system operations as pertains to a
+ sysroot.
- Provides access to copying in files to a sysroot, making directories, or
- writing new files without needing to know exactly where the sysroot is based.
+ Provides access to copying in files to a sysroot, making directories, or
+ writing new files without needing to know exactly where the sysroot is
+ based.
- Attributes:
- path - The path at which the sysroot is based.
- copy_newer_only - only copy files if the src is newer.
- """
-
- def __init__(self, path, copy_newer_only=False):
- self.path = path
- if not os.path.isdir(path):
- os.makedirs(path)
- self._copy_newer_only = copy_newer_only
-
- def Destroy(self):
- """Remove the sysroot and all subdirs."""
- shutil.rmtree(self.path)
-
- def __str__(self):
- return self.path
-
- def Path(self, *args):
- """Get an absolute path given a path relative to the sysroot."""
- return os.path.join(self.path, *args)
-
- def Makedirs(self, *path):
- """Make directories under the sysroot.
-
- Only creates directories if they don't already exist.
- """
- if not self.HasDir(*path):
- os.makedirs(self.Path(*path))
-
- def HasDir(self, *path):
- """Checks if the sysroot has a given directory."""
- return os.path.isdir(self.Path(*path))
-
- def _src_is_newer(self, src, real_dest):
- """Returns True is the src should replace the dest."""
- if self._copy_newer_only == False:
- return True
- # If the src doesn't exist, we force the copy such that
- # the caller can raise the appropriate exception.
- if not os.path.exists(src):
- return True
- if not os.path.exists(real_dest):
- return True
- src_st = os.stat(src)
- return src_st.st_mtime - os.stat(real_dest).st_mtime > 0
-
- def _copy_times(self, src, real_dest):
- """Nearly synchronizes the atime and mtime of the src and dest.
-
- To enable reliable copy_newer_only behavior, we always set
- the mtime to 1 second later than the original to offset
- precision issues. Because of those issues, it is beneficial
- to call _copy_times even after copy2 or copystat.
- """
- if os.path.islink(src):
- # Until os.futime/os.lutime, symlink times cannot be changed.
- return
- src_st = os.lstat(src)
- os.utime(real_dest, (src_st.st_atime, src_st.st_mtime + 1))
-
- def AddFile(self, src, dest=''):
- """Copies a file from src to dest.
-
- Args:
- src - the file to copy.
- dest - where to copy to. If a directory, uses the filename from src.
- The dest directory must already exist.
- Raises:
- IOError if the copy fails.
+ Attributes:
+ path - The path at which the sysroot is based.
+ copy_newer_only - only copy files if the src is newer.
"""
- try:
- tgt = self.Path(dest)
- if self._src_is_newer(src, tgt):
- shutil.copy2(src, tgt)
- self._copy_times(src, tgt)
- except (IOError, OSError) as e:
- raise IOError(('Failed to add file {0} to '
- 'sysroot {1} dest {2}: {3}').format(
- src, self, dest, e))
-
- def AddSymlink(self, src, dest=''):
- """Creates a symlink at dest using src.
-
- Args:
- src - the symlink to copy.
- dest - where to create a symlink. If a directory, uses the filename from
- src. The dest directory must already exist.
-
- Raises:
- IOError if the symlink fails.
- """
- try:
- tgt = self.Path(dest)
- if self._src_is_newer(src, tgt):
- linkto = os.readlink(src)
- os.symlink(linkto, tgt)
- except (IOError, OSError) as e:
- raise IOError(('Failed to add symlink {0} to '
- 'sysroot {1} dest {2}: {3}').format(
- src, self, dest, e))
-
- def AddDir(self, src, dest='', recurse=True, filter_func=None,
- symlinks=False):
- """Copies all folders and files from external src to dest in sysroot.
-
- This function does not use shutil.copytree since that function
- does not support copying (and merging) into existing folders, but
- the implementation is based on the copytree implementation provided
- in the python documentation.
-
- Does not require dest dir to exist.
-
- Args:
- src - dir to copy files from (absolute path)
- dest - (optional) dir to copy files to (relative to self.path).
- Default ''.
- recurse - (optional) True to recursively add subdirs. Default True.
- filter - (optional) a function for filenames that returns true if
- the file should be copied, false otherwise. Default identity function.
- symlinks - (optional) True to copy symlinks as symlinks. Default False.
-
- Returns:
- List of added files
-
- Raises:
- IOError if any part of the copy fails.
- """
- # Default filter is to not filter anything.
- filter_func = filter_func or bool
-
- # Copy the dir.
- self.Makedirs(dest)
- shutil.copystat(src, self.Path(dest))
-
- # Copy the files.
- names = os.listdir(src)
- errors = []
- added = []
- for name in names:
- srcname = os.path.join(src, name)
- destname = os.path.join(dest, name)
- try:
- if symlinks and os.path.islink(srcname):
- self.AddSymlink(srcname, destname)
- added.append(destname)
- elif os.path.isdir(srcname):
- if recurse:
- added += self.AddDir(srcname, destname, recurse, filter_func,
- symlinks)
- elif filter_func(name):
- added.append(destname)
- self.AddFile(srcname, destname)
- except IOError as e:
- errors.append('Failed to copy {0} to {1}: {2}'.format(srcname,
- destname, e))
-
- if errors:
- raise IOError(str(errors))
- return added
-
- def AddGlob(self, src, dest='', recurse=False, filter_func=None,
- symlinks=False):
- """Copies matching folders and files from external src to dest in sysroot.
-
- This function uses AddDir and AddFile above.
-
- Does not require dest dir to exist.
-
- Args:
- src - glob to copy files from (absolute glob path)
- dest - (optional) dir to copy files to (relative to self.path).
- Default ''.
- recurse - (optional) True to recursively add subdirs. Default False.
- filter - (optional) a function for filenames that returns true if
- the file should be copied, false otherwise. Default identity function.
- symlinks - (optional) True to copy symlinks as symlinks. Default False.
-
- Returns:
- List of added files
-
- Raises:
- IOError if any part of the copy fails.
- """
- # Default filter is to not filter anything.
- filter_func = filter_func or bool
-
- added = []
- for srcname in glob.glob(src):
- name = os.path.basename(srcname)
- destname = os.path.join(dest, name)
- if symlinks and os.path.islink(srcname):
- if filter_func(name):
- self.AddSymlink(srcname, destname)
- added.append(destname)
- elif os.path.isdir(srcname):
- if recurse:
- added += self.AddDir(srcname, destname, recurse=True,
- symlinks=symlinks)
- elif filter_func(name):
- added.append(destname)
- self.Makedirs(os.path.dirname(destname))
- self.AddFile(srcname, destname)
-
- if len(added) == 0:
- raise IOError(('Failed to add glob {0} to '
- 'sysroot {1} dest {2}: no matching files').format(
- src, self, dest))
-
- return added
-
- def WriteFile(self, dest, contents):
- """Write a new file in the sysroot.
-
- Args:
- dest - the path (relative to the sysroot) to add the file to.
- contents - the desired contents of the file.
- Raises:
- IOError if the write fails.
- """
- try:
- self.Makedirs(os.path.dirname(dest))
- with open(self.Path(dest), 'w') as f:
- f.write(contents)
- except IOError as e:
- raise IOError('Failed to write file {1} in sysroot {2}: {3}'.format(
- dest, self, e))
+ def __init__(self, path, copy_newer_only=False):
+ self.path = path
+ if not os.path.isdir(path):
+ os.makedirs(path)
+ self._copy_newer_only = copy_newer_only
+
+ def Destroy(self):
+ """Remove the sysroot and all subdirs."""
+ shutil.rmtree(self.path)
+
+ def __str__(self):
+ return self.path
+
+ def Path(self, *args):
+ """Get an absolute path given a path relative to the sysroot."""
+ return os.path.join(self.path, *args)
+
+ def Makedirs(self, *path):
+ """Make directories under the sysroot.
+
+ Only creates directories if they don't already exist.
+ """
+ if not self.HasDir(*path):
+ os.makedirs(self.Path(*path))
+
+ def HasDir(self, *path):
+ """Checks if the sysroot has a given directory."""
+ return os.path.isdir(self.Path(*path))
+
+ def _src_is_newer(self, src, real_dest):
+ """Returns True is the src should replace the dest."""
+ if self._copy_newer_only == False:
+ return True
+ # If the src doesn't exist, we force the copy such that
+ # the caller can raise the appropriate exception.
+ if not os.path.exists(src):
+ return True
+ if not os.path.exists(real_dest):
+ return True
+ src_st = os.stat(src)
+ return src_st.st_mtime - os.stat(real_dest).st_mtime > 0
+
+ def _copy_times(self, src, real_dest):
+ """Nearly synchronizes the atime and mtime of the src and dest.
+
+ To enable reliable copy_newer_only behavior, we always set
+ the mtime to 1 second later than the original to offset
+ precision issues. Because of those issues, it is beneficial
+ to call _copy_times even after copy2 or copystat.
+ """
+ if os.path.islink(src):
+ # Until os.futime/os.lutime, symlink times cannot be changed.
+ return
+ src_st = os.lstat(src)
+ os.utime(real_dest, (src_st.st_atime, src_st.st_mtime + 1))
+
+ def AddFile(self, src, dest=''):
+ """Copies a file from src to dest.
+
+ Args:
+ src - the file to copy.
+ dest - where to copy to. If a directory, uses the filename from src.
+ The dest directory must already exist.
+ Raises:
+ IOError if the copy fails.
+ """
+
+ try:
+ tgt = self.Path(dest)
+ if self._src_is_newer(src, tgt):
+ shutil.copy2(src, tgt)
+ self._copy_times(src, tgt)
+ except (IOError, OSError) as e:
+ raise IOError(('Failed to add file {0} to '
+ 'sysroot {1} dest {2}: {3}').format(
+ src, self, dest, e))
+
+ def AddSymlink(self, src, dest=''):
+ """Creates a symlink at dest using src.
+
+ Args:
+ src - the symlink to copy.
+ dest - where to create a symlink. If a directory, uses the filename
+ from src. The dest directory must already exist.
+
+ Raises:
+ IOError if the symlink fails.
+ """
+ try:
+ tgt = self.Path(dest)
+ if self._src_is_newer(src, tgt):
+ linkto = os.readlink(src)
+ os.symlink(linkto, tgt)
+ except (IOError, OSError) as e:
+ raise IOError(('Failed to add symlink {0} to '
+ 'sysroot {1} dest {2}: {3}').format(
+ src, self, dest, e))
+
+ def AddDir(self, src, dest='', recurse=True, filter_func=None,
+ symlinks=False):
+ """Copies all folders and files from external src to dest in sysroot.
+
+ This function does not use shutil.copytree since that function
+ does not support copying (and merging) into existing folders, but
+ the implementation is based on the copytree implementation provided
+ in the python documentation.
+
+ Does not require dest dir to exist.
+
+ Args:
+ src - dir to copy files from (absolute path)
+ dest - (optional) dir to copy files to (relative to self.path).
+ Default ''.
+ recurse - (optional) True to recursively add subdirs. Default True.
+ filter - (optional) a function for filenames that returns true if
+ the file should be copied, false otherwise. Default identity
+ function.
+ symlinks - (optional) True to copy symlinks as symlinks. Default
+ False.
+
+ Returns:
+ List of added files
+
+ Raises:
+ IOError if any part of the copy fails.
+ """
+ # Default filter is to not filter anything.
+ filter_func = filter_func or bool
+
+ # Copy the dir.
+ self.Makedirs(dest)
+ shutil.copystat(src, self.Path(dest))
+
+ # Copy the files.
+ names = os.listdir(src)
+ errors = []
+ added = []
+ for name in names:
+ srcname = os.path.join(src, name)
+ destname = os.path.join(dest, name)
+ try:
+ if symlinks and os.path.islink(srcname):
+ self.AddSymlink(srcname, destname)
+ added.append(destname)
+ elif os.path.isdir(srcname):
+ if recurse:
+ added += self.AddDir(srcname, destname, recurse,
+ filter_func, symlinks)
+ elif filter_func(name):
+ added.append(destname)
+ self.AddFile(srcname, destname)
+ except IOError as e:
+ errors.append('Failed to copy {0} to {1}: {2}'.format(srcname,
+ destname,
+ e))
+
+ if errors:
+ raise IOError(str(errors))
+ return added
+
+ def AddGlob(self, src, dest='', recurse=False, filter_func=None,
+ symlinks=False):
+ """Copies matching folders and files from external src to dest in
+ sysroot.
+
+ This function uses AddDir and AddFile above.
+
+ Does not require dest dir to exist.
+
+ Args:
+ src - glob to copy files from (absolute glob path)
+ dest - (optional) dir to copy files to (relative to self.path).
+ Default ''.
+ recurse - (optional) True to recursively add subdirs. Default False.
+ filter - (optional) a function for filenames that returns true if
+ the file should be copied, false otherwise. Default identity
+ function.
+ symlinks - (optional) True to copy symlinks as symlinks. Default
+ False.
+
+ Returns:
+ List of added files
+
+ Raises:
+ IOError if any part of the copy fails.
+ """
+ # Default filter is to not filter anything.
+ filter_func = filter_func or bool
+
+ added = []
+ for srcname in glob.glob(src):
+ name = os.path.basename(srcname)
+ destname = os.path.join(dest, name)
+ if symlinks and os.path.islink(srcname):
+ if filter_func(name):
+ self.AddSymlink(srcname, destname)
+ added.append(destname)
+ elif os.path.isdir(srcname):
+ if recurse:
+ added += self.AddDir(srcname, destname, recurse=True,
+ symlinks=symlinks)
+ elif filter_func(name):
+ added.append(destname)
+ self.Makedirs(os.path.dirname(destname))
+ self.AddFile(srcname, destname)
+
+ if len(added) == 0:
+ raise IOError(('Failed to add glob {0} to '
+ 'sysroot {1} dest {2}: no matching files').format(
+ src, self, dest))
+
+ return added
+
+ def WriteFile(self, dest, contents):
+ """Write a new file in the sysroot.
+
+ Args:
+ dest - the path (relative to the sysroot) to add the file to.
+ contents - the desired contents of the file.
+ Raises:
+ IOError if the write fails.
+ """
+ try:
+ self.Makedirs(os.path.dirname(dest))
+ with open(self.Path(dest), 'w') as f:
+ f.write(contents)
+ except IOError as e:
+ raise IOError('Failed to write file {1} in sysroot {2}: {3}'.format(
+ dest, self, e))
diff --git a/cli/lib/environment/sysroot_stub.py b/cli/lib/environment/sysroot_stub.py
index e7ebc10..17048fb 100644
--- a/cli/lib/environment/sysroot_stub.py
+++ b/cli/lib/environment/sysroot_stub.py
@@ -24,113 +24,114 @@ import error
class Error(error.Error):
- pass
+ pass
class StubSysroot(object):
- """Replacement for Sysroots."""
-
- def __init__(self, path):
- self.path = path
- self.should_write = []
- self.last_written = ''
- self.written = []
- self.should_add_file = []
- self.should_add_dir = []
- self.should_add_glob = []
- self.should_pass_filter = []
- self.should_fail_filter = []
- self.should_makedirs = []
-
- def Path(self, *path):
- return os.path.join(self.path, *path)
-
- def WriteFile(self, path, contents):
- if path in self.should_write:
- self.last_written = contents
- self.written.append(contents)
- self.should_write.remove(path)
- else:
- raise IOError('not supposed to write {0}'.format(path))
-
- def AddFile(self, src, dest=''):
- if not (src, dest) in self.should_add_file:
- raise IOError('Not supposed to add file {0} to {1}'.format(src, dest))
- self.should_add_file.remove((src, dest))
-
- # pylint: disable=unused-argument
- def AddDir(self, src, dest=None, recurse=True, filter_func=None,
- symlinks=None):
- dest = dest or ''
- proper_filter = True
- if filter_func:
- proper_filter = (
- [f for f in self.should_pass_filter
- if filter_func(f)] == self.should_pass_filter and
- [f for f in self.should_fail_filter if filter_func(f)] == [])
-
- if not proper_filter:
- raise Error('AddDir called with improper filter')
- if not (src, dest, recurse) in self.should_add_dir:
- raise IOError(('Not supposed to add dir "{}" to "{}", '
- 'recursive: {}').format(src, dest, recurse))
-
- self.should_add_dir.remove((src, dest, recurse))
- # This should walk path.should_exist if recurse
- return [dest]
-
- # pylint: disable=unused-argument
- def AddGlob(self, src, dest=None, recurse=True, filter_func=None,
- symlinks=None):
- dest = dest or ''
- proper_filter = True
- if filter_func:
- proper_filter = (
- [f for f in self.should_pass_filter
- if filter_func(f)] == self.should_pass_filter and
- [f for f in self.should_fail_filter if filter_func(f)] == [])
-
- if not proper_filter:
- raise Error('AddGlob called with improper filter')
- if not (src, dest, recurse) in self.should_add_glob:
- raise IOError(('Not supposed to add glob "{}" to "{}", '
- 'recursive: {}').format(src, dest, recurse))
-
- self.should_add_glob.remove((src, dest, recurse))
- # This should walk path.should_exist if recurse
- return [dest]
-
- def Makedirs(self, dirs):
- if not dirs in self.should_makedirs:
- raise IOError('Could not make dirs {0}'.format(dirs))
-
- def Destroy(self):
- pass
+ """Replacement for Sysroots."""
+
+ def __init__(self, path):
+ self.path = path
+ self.should_write = []
+ self.last_written = ''
+ self.written = []
+ self.should_add_file = []
+ self.should_add_dir = []
+ self.should_add_glob = []
+ self.should_pass_filter = []
+ self.should_fail_filter = []
+ self.should_makedirs = []
+
+ def Path(self, *path):
+ return os.path.join(self.path, *path)
+
+ def WriteFile(self, path, contents):
+ if path in self.should_write:
+ self.last_written = contents
+ self.written.append(contents)
+ self.should_write.remove(path)
+ else:
+ raise IOError('not supposed to write {0}'.format(path))
+
+ def AddFile(self, src, dest=''):
+ if not (src, dest) in self.should_add_file:
+ raise IOError('Not supposed to add file {0} to {1}'.format(src,
+ dest))
+ self.should_add_file.remove((src, dest))
+
+ # pylint: disable=unused-argument
+ def AddDir(self, src, dest=None, recurse=True, filter_func=None,
+ symlinks=None):
+ dest = dest or ''
+ proper_filter = True
+ if filter_func:
+ proper_filter = (
+ [f for f in self.should_pass_filter
+ if filter_func(f)] == self.should_pass_filter and
+ [f for f in self.should_fail_filter if filter_func(f)] == [])
+
+ if not proper_filter:
+ raise Error('AddDir called with improper filter')
+ if not (src, dest, recurse) in self.should_add_dir:
+ raise IOError(('Not supposed to add dir "{}" to "{}", '
+ 'recursive: {}').format(src, dest, recurse))
+
+ self.should_add_dir.remove((src, dest, recurse))
+ # This should walk path.should_exist if recurse.
+ return [dest]
+
+ # pylint: disable=unused-argument
+ def AddGlob(self, src, dest=None, recurse=True, filter_func=None,
+ symlinks=None):
+ dest = dest or ''
+ proper_filter = True
+ if filter_func:
+ proper_filter = (
+ [f for f in self.should_pass_filter
+ if filter_func(f)] == self.should_pass_filter and
+ [f for f in self.should_fail_filter if filter_func(f)] == [])
+
+ if not proper_filter:
+ raise Error('AddGlob called with improper filter')
+ if not (src, dest, recurse) in self.should_add_glob:
+ raise IOError(('Not supposed to add glob "{}" to "{}", '
+ 'recursive: {}').format(src, dest, recurse))
+
+ self.should_add_glob.remove((src, dest, recurse))
+ # This should walk path.should_exist if recurse.
+ return [dest]
+
+ def Makedirs(self, dirs):
+ if not dirs in self.should_makedirs:
+ raise IOError('Could not make dirs {0}'.format(dirs))
+
+ def Destroy(self):
+ pass
class StubSysrootGenerator(object):
- """Generates stub sysroots."""
-
- def __init__(self):
- self.should_write = []
- self.last_written = ''
- self.should_add_file = []
- self.should_add_dir = []
- self.should_add_glob = []
- self.should_pass_filter = []
- self.should_fail_filter = []
- self.should_makedirs = []
- self.sysroots = []
-
- # pylint: disable=unused-argument
- def Sysroot(self, path, copy_newer_only=False):
- gen = StubSysroot(path)
- self.sysroots.append(gen)
- gen.should_write = self.should_write
- gen.last_written = self.last_written
- gen.should_add_file = self.should_add_file
- gen.should_add_dir = self.should_add_dir
- gen.should_add_glob = self.should_add_glob
- gen.should_pass_filter = self.should_pass_filter
- gen.should_fail_filter = self.should_fail_filter
- gen.should_makedirs = self.should_makedirs
- return gen
+ """Generates stub sysroots."""
+
+ def __init__(self):
+ self.should_write = []
+ self.last_written = ''
+ self.should_add_file = []
+ self.should_add_dir = []
+ self.should_add_glob = []
+ self.should_pass_filter = []
+ self.should_fail_filter = []
+ self.should_makedirs = []
+ self.sysroots = []
+
+ # pylint: disable=unused-argument
+ def Sysroot(self, path, copy_newer_only=False):
+ gen = StubSysroot(path)
+ self.sysroots.append(gen)
+ gen.should_write = self.should_write
+ gen.last_written = self.last_written
+ gen.should_add_file = self.should_add_file
+ gen.should_add_dir = self.should_add_dir
+ gen.should_add_glob = self.should_add_glob
+ gen.should_pass_filter = self.should_pass_filter
+ gen.should_fail_filter = self.should_fail_filter
+ gen.should_makedirs = self.should_makedirs
+ return gen
diff --git a/cli/lib/environment/sysroot_unittest.py b/cli/lib/environment/sysroot_unittest.py
index 7438354..dc8bf02 100644
--- a/cli/lib/environment/sysroot_unittest.py
+++ b/cli/lib/environment/sysroot_unittest.py
@@ -24,361 +24,367 @@ from test import stubs
class SysrootTest(unittest.TestCase):
- def setUp(self):
- self.stub_os = stubs.StubOs()
- self.stub_glob = stubs.StubGlob(self.stub_os)
- self.stub_shutil = stubs.StubShutil(self.stub_os)
- self.stub_open = stubs.StubOpen(self.stub_os)
-
- sysroot.os = self.stub_os
- sysroot.glob = self.stub_glob
- sysroot.shutil = self.stub_shutil
- sysroot.open = self.stub_open.open
-
- def gen_sysroot(self, copy_newer_only=False):
- """Helper - Generates a sysroot and returns it and its path."""
- path = 'path/subdir'
- self.stub_os.should_makedirs = ['path/subdir']
- return (sysroot.Sysroot(path, copy_newer_only=copy_newer_only), path)
-
- def test_init_destroy(self):
- self.stub_os.path.should_be_dir = []
- # Check that necessary dirs are created for a sysroot on init.
- (sysrt, _) = self.gen_sysroot()
- self.assertTrue(self.stub_os.path.isdir('path'))
- self.assertTrue(self.stub_os.path.isdir('path/subdir'))
- sysrt.Destroy()
- # 'path' will actually remain, but this is WAI because it may
- # have had non-sysroot files added between creation and destruction.
- self.assertTrue(self.stub_os.path.isdir('path'))
- self.assertFalse(self.stub_os.path.isdir('path/subdir'))
-
- def test_path(self):
- self.stub_os.path.should_be_dir = []
- (sysrt, path) = self.gen_sysroot()
- self.assertEqual(path, sysrt.Path())
- self.assertEqual(self.stub_os.path.join(path, 'boogie', 'woogie', 'woo'),
- sysrt.Path('boogie', 'woogie', 'woo'))
-
- def test_makedirs_hasdir(self):
- self.stub_os.path.should_be_dir = []
- (sysrt, path) = self.gen_sysroot()
-
- self.stub_os.should_makedirs = [sysrt.Path('deeper/deeperer/deepest')]
- # Makedirs
- sysrt.Makedirs('deeper/deeperer/deepest')
- self.assertTrue(self.stub_os.path.isdir(self.stub_os.path.join(path,
- 'deeper')))
- self.assertTrue(
- self.stub_os.path.isdir(self.stub_os.path.join(path,
- 'deeper/deeperer')))
- self.assertTrue(self.stub_os.path.isdir(
- self.stub_os.path.join(path, 'deeper/deeperer/deepest')))
- # Trying to make existing dirs doesn't cause a problem
- sysrt.Makedirs('deeper/deeperer')
-
- # HasDir
- self.assertTrue(sysrt.HasDir('deeper'))
- self.assertTrue(sysrt.HasDir('deeper/deeperer'))
- self.assertTrue(sysrt.HasDir('deeper/deeperer/deepest'))
-
- def test_add_file(self):
- self.stub_os.path.should_be_dir = []
- (sysrt, _) = self.gen_sysroot()
- self.stub_shutil.should_copy = [('a/b/c', sysrt.Path('d'))]
- self.stub_os.path.should_exist += ['a/b/c']
- sysrt.AddFile('a/b/c', 'd')
- self.assertEqual(self.stub_shutil.should_copy, [])
- # If we fail, should raise IOError
- self.assertRaisesRegexp(IOError, 'does/not/exist', sysrt.AddFile,
- 'does/not/exist', 'e')
-
- def test_add_file_cond_new(self):
- self.stub_os.path.should_be_dir = []
- (sysrt, _) = self.gen_sysroot(copy_newer_only=True)
- self.stub_shutil.should_copy = [('a/b/c', sysrt.Path('d'))]
- self.stub_os.path.should_exist += ['a/b/c']
- # There is no destination, so this is just a normal copy.
- sysrt.AddFile('a/b/c', 'd')
- self.assertEqual(self.stub_shutil.should_copy, [])
- # If we fail, should raise IOError
- self.assertRaisesRegexp(IOError, 'does/not/exist', sysrt.AddFile,
- 'does/not/exist', 'e')
-
- def test_add_file_cond_exists_but_newer(self):
- self.stub_os.path.should_be_dir = []
- (sysrt, _) = self.gen_sysroot(copy_newer_only=True)
- self.stub_os.path.should_exist = [sysrt.Path('d'), 'a/b/c']
- # No copy should occur.
- self.stub_os.should_stat = {sysrt.Path('d'): {'st_mtime': 100},
- 'a/b/c': {'st_mtime': 100}}
- sysrt.AddFile('a/b/c', 'd')
- self.assertEqual(self.stub_shutil.should_copy, [])
- # If we fail, should raise IOError
- self.assertRaisesRegexp(IOError, 'does/not/exist', sysrt.AddFile,
- 'does/not/exist', 'e')
-
- def test_add_file_cond_exists_and_older(self):
- self.stub_os.path.should_be_dir = []
- (sysrt, _) = self.gen_sysroot(copy_newer_only=True)
- self.stub_shutil.should_copy = [('a/b/c', sysrt.Path('d'))]
- self.stub_os.path.should_exist = [sysrt.Path('d'), 'a/b/c']
- # 'd' will be copied over.
- self.stub_os.should_stat = {sysrt.Path('d'): {'st_mtime': 99},
- 'a/b/c': {'st_mtime': 100}}
- sysrt.AddFile('a/b/c', 'd')
- self.assertEqual(self.stub_shutil.should_copy, [])
- # If we fail, should raise IOError
- self.assertRaisesRegexp(IOError, 'does/not/exist', sysrt.AddFile,
- 'does/not/exist', 'e')
-
- def test_add_symlink(self):
- self.stub_os.path.should_be_dir = []
- (sysrt, _) = self.gen_sysroot()
- self.stub_shutil.should_copy = [('a/b/c', sysrt.Path('d'))]
- self.stub_os.path.should_exist += ['a/b/c']
- sysrt.AddFile('a/b/c', 'd')
- self.assertEqual(self.stub_shutil.should_copy, [])
- self.stub_os.path.should_be_dir += ['root']
- self.stub_os.path.should_exist += ['root', 'root/link']
- self.stub_os.path.should_link['root/link'] = '../a_link_dest'
-
- # Should copy not_a_link, and create a link for link.
- self.stub_os.should_create_link = [
- ('../a_link_dest', sysrt.Path('newlink')),
- ('../../relative_link_dest', sysrt.Path('subdir/link')),
- ]
- sysrt.AddSymlink('root/link', 'newlink')
- # Make sure the one file was copied, and the link was created.
- self.assertEqual('../a_link_dest',
- self.stub_os.readlink(sysrt.Path('newlink')))
- # If we fail, should raise IOError
- self.assertRaisesRegexp(IOError, 'does/not/exist', sysrt.AddSymlink,
- 'does/not/exist', 'e')
-
- def test_add_glob(self):
- self.stub_os.path.should_be_dir = []
- self.stub_os.path.should_exist = []
- (sysrt, _) = self.gen_sysroot()
- directories = ['root', 'root/sub1', 'root/sub2', 'root/sub1/supersub']
- files = ['root/sub1/copy1', 'root/sub2/copy2', 'root/sub1/supersub/copy3',
- 'root/copy0', 'root/copy1']
- for directory in directories:
- self.stub_os.path.should_be_dir.append(directory)
- self.stub_os.path.should_exist.append(directory)
- for f in files:
- self.stub_os.path.should_exist.append(f)
- # Should only copy from top level of root matching copy*.
- self.stub_shutil.should_copy.append(('root/copy0', sysrt.Path('copy0')))
- self.stub_shutil.should_copy.append(('root/copy1', sysrt.Path('copy1')))
- sysrt.AddGlob('root/copy*', recurse=False)
- # Make sure the two files were copied.
- self.assertEqual(self.stub_shutil.should_copy, [])
-
- def test_add_glob_no_match(self):
- self.stub_os.path.should_be_dir = []
- self.stub_os.path.should_exist = []
- (sysrt, _) = self.gen_sysroot()
- directories = ['root', 'root/sub1', 'root/sub2', 'root/sub1/supersub']
- files = ['root/sub1/copy1', 'root/sub2/copy2', 'root/sub1/supersub/copy3']
- for directory in directories:
- self.stub_os.path.should_be_dir.append(directory)
- self.stub_os.path.should_exist.append(directory)
- for f in files:
- self.stub_os.path.should_exist.append(f)
- with self.assertRaises(IOError):
- sysrt.AddGlob('root/copy*', recurse=False)
-
- def test_add_glob_recurse(self):
- self.stub_os.path.should_exist = []
- self.stub_os.path.should_be_dir = []
- (sysrt, _) = self.gen_sysroot()
- directories = ['root', 'root/sub1', 'root/sub2', 'root/sub1/supersub']
- files = ['root/sub1/copy1', 'root/sub2/copy2', 'root/sub1/supersub/copy3',
- 'root/copy0']
- for directory in directories:
- self.stub_os.path.should_be_dir.append(directory)
- self.stub_os.path.should_exist.append(directory)
- self.stub_os.should_makedirs.append(sysrt.Path(directory.replace('root',
- 'dest')))
- for f in files:
- self.stub_os.path.should_exist.append(f)
- self.stub_shutil.should_copy.append((f, sysrt.Path(f.replace('root',
- 'dest'))))
- # Add some files to the mock filesystem that shouldn't be copied.
- self.stub_os.path.should_exist.append('root/donotcopy')
- self.stub_os.path.should_exist.append('other')
- self.stub_os.path.should_be_dir.append('other')
- self.stub_os.path.should_exist.append('other/copy0')
- self.stub_os.path.should_exist.append('other/unfilteredcopy')
- # A filter that should only collect the copy files.
- def copy_filter(name):
- return name.startswith('copy')
-
- sysrt.AddGlob('root/*', 'dest', recurse=True, filter_func=copy_filter)
- # Make sure everything was copied.
- self.assertEqual(self.stub_shutil.should_copy, [])
- # Note: shutil copy2 stub is not implemented such that it checks for dirs
- # existing. This will test that dirs were created, but not necessarily
- # that they were created before they were copied to.
- for directory in directories:
- self.assertTrue(
- sysrt.HasDir(self.stub_os.path.join(directory.replace('root',
- 'dest'))))
-
- # Test with no filter.
- # Also should be no issue copying into a now-populated destination.
- self.stub_shutil.should_copy.append(('other/copy0', sysrt.Path('dest',
- 'copy0')))
- sysrt.AddGlob('other/c*', 'dest')
- # Make sure everything was copied.
- self.assertEqual(self.stub_shutil.should_copy, [])
-
- def test_add_glob_symlinks(self):
- (sysrt, _) = self.gen_sysroot()
- self.stub_os.path.should_be_dir += ['root', 'root/subdir']
- self.stub_os.should_makedirs += [sysrt.Path('subdir')]
- self.stub_os.path.should_exist += [
- 'root', 'root/subdir', 'root/subdir/not_a_link', 'root/link',
- 'root/subdir/link']
- self.stub_os.path.should_link['root/link'] = '../relative_link_dest'
- self.stub_os.path.should_link['root/subdir/link'] = (
- '../../relative_link_dest')
-
- # Should copy not_a_link, and create a link for link.
- self.stub_os.should_create_link = [
- ('../relative_link_dest', sysrt.Path('link')),
- ('../../relative_link_dest', sysrt.Path('subdir/link')),
- ]
- self.stub_shutil.should_copy = [
- ('root/subdir/not_a_link', sysrt.Path('subdir/not_a_link'))]
- sysrt.AddGlob('root/*', recurse=True, symlinks=True)
- # Make sure the one file was copied, and the link was created.
- self.assertEqual(self.stub_shutil.should_copy, [])
- self.assertEqual('../relative_link_dest',
- self.stub_os.readlink(sysrt.Path('link')))
- self.assertEqual('../../relative_link_dest',
- self.stub_os.readlink(sysrt.Path('subdir/link')))
-
- def test_add_glob_ignore_symlinks(self):
- (sysrt, _) = self.gen_sysroot()
- self.stub_os.path.should_be_dir += ['root', 'root/subdir']
- self.stub_os.should_makedirs += [sysrt.Path('subdir')]
- self.stub_os.path.should_exist += [
- 'root', 'root/subdir', 'root/not_a_link', 'root/subdir/link']
- self.stub_os.path.should_link['root/subdir/link'] = '../relative_link_dest'
-
- # Should copy both not_a_link and link.
- self.stub_shutil.should_copy = [
- ('root/not_a_link', sysrt.Path('not_a_link')),
- ('root/subdir/link', sysrt.Path('subdir/link'))]
- sysrt.AddGlob('root/*', recurse=True, symlinks=False)
- # Make sure the two files were copied.
- self.assertEqual(self.stub_shutil.should_copy, [])
-
- def test_add_dir_recurse_and_unfiltered(self):
- self.stub_os.path.should_exist = []
- self.stub_os.path.should_be_dir = []
- (sysrt, _) = self.gen_sysroot()
- directories = ['root', 'root/sub1', 'root/sub2', 'root/sub1/supersub']
- files = ['root/sub1/copy1', 'root/sub2/copy2', 'root/sub1/supersub/copy3',
- 'root/copy0']
- for directory in directories:
- self.stub_os.path.should_be_dir.append(directory)
- self.stub_os.path.should_exist.append(directory)
- self.stub_os.should_makedirs.append(sysrt.Path(directory.replace('root',
- 'dest')))
- for f in files:
- self.stub_os.path.should_exist.append(f)
- self.stub_shutil.should_copy.append((f, sysrt.Path(f.replace('root',
- 'dest'))))
- # Add some files to the mock filesystem that shouldn't be copied.
- self.stub_os.path.should_exist.append('root/donotcopy')
- self.stub_os.path.should_exist.append('other')
- self.stub_os.path.should_be_dir.append('other')
- self.stub_os.path.should_exist.append('other/copy0')
- self.stub_os.path.should_exist.append('other/unfilteredcopy')
- # A filter that should only collect the copy files.
- def copy_filter(name):
- return name.startswith('copy')
-
- sysrt.AddDir('root', 'dest', recurse=True, filter_func=copy_filter)
- # Make sure everything was copied.
- self.assertEqual(self.stub_shutil.should_copy, [])
- # Note: shutil copy2 stub is not implemented such that it checks for dirs
- # existing. This will test that dirs were created, but not necessarily that
- # they were created before they were copied to.
- for directory in directories:
- self.assertTrue(
- sysrt.HasDir(
- self.stub_os.path.join(directory.replace('root', 'dest'))))
-
- # Test with no filter.
- # Also should be no issue copying into a now-populated destination.
- self.stub_shutil.should_copy.append(
- ('other/copy0', sysrt.Path('dest', 'copy0')))
- self.stub_shutil.should_copy.append(('other/unfilteredcopy',
- sysrt.Path('dest', 'unfilteredcopy')))
- sysrt.AddDir('other', 'dest')
- # Make sure everything was copied.
- self.assertEqual(self.stub_shutil.should_copy, [])
-
- def test_add_dir_top_level_no_recurse(self):
- (sysrt, _) = self.gen_sysroot()
- directories = ['root', 'root/sub1', 'root/sub2', 'root/sub1/supersub']
- files = ['root/sub1/copy1', 'root/sub2/copy2', 'root/sub1/supersub/copy3',
- 'root/copy0']
- for directory in directories:
- self.stub_os.path.should_be_dir.append(directory)
- self.stub_os.path.should_exist.append(directory)
- for f in files:
- self.stub_os.path.should_exist.append(f)
- # Should only copy from top level of root,
- # and with no dest provided should copy to top level of the sysroot.
- self.stub_shutil.should_copy.append(('root/copy0', sysrt.Path('copy0')))
- sysrt.AddDir('root', recurse=False)
- # Make sure the one file was copied.
- self.assertEqual(self.stub_shutil.should_copy, [])
-
- def test_add_dir_symlinks(self):
- (sysrt, _) = self.gen_sysroot()
- self.stub_os.path.should_be_dir += ['root', 'root/subdir']
- self.stub_os.should_makedirs += [sysrt.Path('subdir')]
- self.stub_os.path.should_exist += [
- 'root', 'root/subdir', 'root/not_a_link', 'root/subdir/link']
- self.stub_os.path.should_link['root/subdir/link'] = '../relative_link_dest'
-
- # Should copy not_a_link, and create a link for link.
- self.stub_os.should_create_link = [('../relative_link_dest',
- sysrt.Path('subdir/link'))]
- self.stub_shutil.should_copy = [
- ('root/not_a_link', sysrt.Path('not_a_link'))]
- sysrt.AddDir('root', symlinks=True)
- # Make sure the one file was copied, and the link was created.
- self.assertEqual(self.stub_shutil.should_copy, [])
- self.assertEqual('../relative_link_dest',
- self.stub_os.readlink(sysrt.Path('subdir/link')))
-
- def test_add_dir_ignore_symlinks(self):
- (sysrt, _) = self.gen_sysroot()
- self.stub_os.path.should_be_dir += ['root', 'root/subdir']
- self.stub_os.should_makedirs += [sysrt.Path('subdir')]
- self.stub_os.path.should_exist += [
- 'root', 'root/subdir', 'root/not_a_link', 'root/subdir/link']
- self.stub_os.path.should_link['root/subdir/link'] = '../relative_link_dest'
-
- # Should copy both not_a_link and link.
- self.stub_shutil.should_copy += [
- ('root/not_a_link', sysrt.Path('not_a_link')),
- ('root/subdir/link', sysrt.Path('subdir/link'))]
- sysrt.AddDir('root', symlinks=False)
- # Make sure the two files were copied.
- self.assertEqual(self.stub_shutil.should_copy, [])
-
- def test_write_file(self):
- self.stub_os.path.should_be_dir = []
- (sysrt, _) = self.gen_sysroot()
- self.stub_os.should_makedirs = [sysrt.Path('dir')]
- sysrt.WriteFile('dir/file', 'contents')
- self.assertTrue(
- 'contents' in self.stub_open.files[sysrt.Path('dir/file')].contents)
+ def setUp(self):
+ self.stub_os = stubs.StubOs()
+ self.stub_glob = stubs.StubGlob(self.stub_os)
+ self.stub_shutil = stubs.StubShutil(self.stub_os)
+ self.stub_open = stubs.StubOpen(self.stub_os)
+
+ sysroot.os = self.stub_os
+ sysroot.glob = self.stub_glob
+ sysroot.shutil = self.stub_shutil
+ sysroot.open = self.stub_open.open
+
+ def gen_sysroot(self, copy_newer_only=False):
+ """Helper - Generates a sysroot and returns it and its path."""
+ path = 'path/subdir'
+ self.stub_os.should_makedirs = ['path/subdir']
+ return (sysroot.Sysroot(path, copy_newer_only=copy_newer_only), path)
+
+ def test_init_destroy(self):
+ self.stub_os.path.should_be_dir = []
+ # Check that necessary dirs are created for a sysroot on init.
+ (sysrt, _) = self.gen_sysroot()
+ self.assertTrue(self.stub_os.path.isdir('path'))
+ self.assertTrue(self.stub_os.path.isdir('path/subdir'))
+ sysrt.Destroy()
+ # 'path' will actually remain, but this is WAI because it may
+ # have had non-sysroot files added between creation and destruction.
+ self.assertTrue(self.stub_os.path.isdir('path'))
+ self.assertFalse(self.stub_os.path.isdir('path/subdir'))
+
+ def test_path(self):
+ self.stub_os.path.should_be_dir = []
+ (sysrt, path) = self.gen_sysroot()
+ self.assertEqual(path, sysrt.Path())
+ self.assertEqual(self.stub_os.path.join(path, 'boogie', 'woogie',
+ 'woo'),
+ sysrt.Path('boogie', 'woogie', 'woo'))
+
+ def test_makedirs_hasdir(self):
+ self.stub_os.path.should_be_dir = []
+ (sysrt, path) = self.gen_sysroot()
+
+ self.stub_os.should_makedirs = [sysrt.Path('deeper/deeperer/deepest')]
+ # Makedirs
+ sysrt.Makedirs('deeper/deeperer/deepest')
+ self.assertTrue(self.stub_os.path.isdir(
+ self.stub_os.path.join(path, 'deeper')))
+ self.assertTrue(
+ self.stub_os.path.isdir(self.stub_os.path.join(path,
+ 'deeper/deeperer')))
+ self.assertTrue(self.stub_os.path.isdir(
+ self.stub_os.path.join(path, 'deeper/deeperer/deepest')))
+ # Trying to make existing dirs doesn't cause a problem
+ sysrt.Makedirs('deeper/deeperer')
+
+ # HasDir
+ self.assertTrue(sysrt.HasDir('deeper'))
+ self.assertTrue(sysrt.HasDir('deeper/deeperer'))
+ self.assertTrue(sysrt.HasDir('deeper/deeperer/deepest'))
+
+ def test_add_file(self):
+ self.stub_os.path.should_be_dir = []
+ (sysrt, _) = self.gen_sysroot()
+ self.stub_shutil.should_copy = [('a/b/c', sysrt.Path('d'))]
+ self.stub_os.path.should_exist += ['a/b/c']
+ sysrt.AddFile('a/b/c', 'd')
+ self.assertEqual(self.stub_shutil.should_copy, [])
+ # If we fail, should raise IOError
+ self.assertRaisesRegexp(IOError, 'does/not/exist', sysrt.AddFile,
+ 'does/not/exist', 'e')
+
+ def test_add_file_cond_new(self):
+ self.stub_os.path.should_be_dir = []
+ (sysrt, _) = self.gen_sysroot(copy_newer_only=True)
+ self.stub_shutil.should_copy = [('a/b/c', sysrt.Path('d'))]
+ self.stub_os.path.should_exist += ['a/b/c']
+ # There is no destination, so this is just a normal copy.
+ sysrt.AddFile('a/b/c', 'd')
+ self.assertEqual(self.stub_shutil.should_copy, [])
+ # If we fail, should raise IOError
+ self.assertRaisesRegexp(IOError, 'does/not/exist', sysrt.AddFile,
+ 'does/not/exist', 'e')
+
+ def test_add_file_cond_exists_but_newer(self):
+ self.stub_os.path.should_be_dir = []
+ (sysrt, _) = self.gen_sysroot(copy_newer_only=True)
+ self.stub_os.path.should_exist = [sysrt.Path('d'), 'a/b/c']
+ # No copy should occur.
+ self.stub_os.should_stat = {sysrt.Path('d'): {'st_mtime': 100},
+ 'a/b/c': {'st_mtime': 100}}
+ sysrt.AddFile('a/b/c', 'd')
+ self.assertEqual(self.stub_shutil.should_copy, [])
+ # If we fail, should raise IOError
+ self.assertRaisesRegexp(IOError, 'does/not/exist', sysrt.AddFile,
+ 'does/not/exist', 'e')
+
+ def test_add_file_cond_exists_and_older(self):
+ self.stub_os.path.should_be_dir = []
+ (sysrt, _) = self.gen_sysroot(copy_newer_only=True)
+ self.stub_shutil.should_copy = [('a/b/c', sysrt.Path('d'))]
+ self.stub_os.path.should_exist = [sysrt.Path('d'), 'a/b/c']
+ # 'd' will be copied over.
+ self.stub_os.should_stat = {sysrt.Path('d'): {'st_mtime': 99},
+ 'a/b/c': {'st_mtime': 100}}
+ sysrt.AddFile('a/b/c', 'd')
+ self.assertEqual(self.stub_shutil.should_copy, [])
+ # If we fail, should raise IOError
+ self.assertRaisesRegexp(IOError, 'does/not/exist', sysrt.AddFile,
+ 'does/not/exist', 'e')
+
+ def test_add_symlink(self):
+ self.stub_os.path.should_be_dir = []
+ (sysrt, _) = self.gen_sysroot()
+ self.stub_shutil.should_copy = [('a/b/c', sysrt.Path('d'))]
+ self.stub_os.path.should_exist += ['a/b/c']
+ sysrt.AddFile('a/b/c', 'd')
+ self.assertEqual(self.stub_shutil.should_copy, [])
+ self.stub_os.path.should_be_dir += ['root']
+ self.stub_os.path.should_exist += ['root', 'root/link']
+ self.stub_os.path.should_link['root/link'] = '../a_link_dest'
+
+ # Should copy not_a_link, and create a link for link.
+ self.stub_os.should_create_link = [
+ ('../a_link_dest', sysrt.Path('newlink')),
+ ('../../relative_link_dest', sysrt.Path('subdir/link')),
+ ]
+ sysrt.AddSymlink('root/link', 'newlink')
+ # Make sure the one file was copied, and the link was created.
+ self.assertEqual('../a_link_dest',
+ self.stub_os.readlink(sysrt.Path('newlink')))
+ # If we fail, should raise IOError
+ self.assertRaisesRegexp(IOError, 'does/not/exist', sysrt.AddSymlink,
+ 'does/not/exist', 'e')
+
+ def test_add_glob(self):
+ self.stub_os.path.should_be_dir = []
+ self.stub_os.path.should_exist = []
+ (sysrt, _) = self.gen_sysroot()
+ directories = ['root', 'root/sub1', 'root/sub2', 'root/sub1/supersub']
+ files = ['root/sub1/copy1', 'root/sub2/copy2',
+ 'root/sub1/supersub/copy3', 'root/copy0', 'root/copy1']
+ for directory in directories:
+ self.stub_os.path.should_be_dir.append(directory)
+ self.stub_os.path.should_exist.append(directory)
+ for f in files:
+ self.stub_os.path.should_exist.append(f)
+ # Should only copy from top level of root matching copy*.
+ self.stub_shutil.should_copy.append(('root/copy0', sysrt.Path('copy0')))
+ self.stub_shutil.should_copy.append(('root/copy1', sysrt.Path('copy1')))
+ sysrt.AddGlob('root/copy*', recurse=False)
+ # Make sure the two files were copied.
+ self.assertEqual(self.stub_shutil.should_copy, [])
+
+ def test_add_glob_no_match(self):
+ self.stub_os.path.should_be_dir = []
+ self.stub_os.path.should_exist = []
+ (sysrt, _) = self.gen_sysroot()
+ directories = ['root', 'root/sub1', 'root/sub2', 'root/sub1/supersub']
+ files = ['root/sub1/copy1', 'root/sub2/copy2',
+ 'root/sub1/supersub/copy3']
+ for directory in directories:
+ self.stub_os.path.should_be_dir.append(directory)
+ self.stub_os.path.should_exist.append(directory)
+ for f in files:
+ self.stub_os.path.should_exist.append(f)
+ with self.assertRaises(IOError):
+ sysrt.AddGlob('root/copy*', recurse=False)
+
+ def test_add_glob_recurse(self):
+ self.stub_os.path.should_exist = []
+ self.stub_os.path.should_be_dir = []
+ (sysrt, _) = self.gen_sysroot()
+ directories = ['root', 'root/sub1', 'root/sub2', 'root/sub1/supersub']
+ files = ['root/sub1/copy1', 'root/sub2/copy2',
+ 'root/sub1/supersub/copy3', 'root/copy0']
+ for directory in directories:
+ self.stub_os.path.should_be_dir.append(directory)
+ self.stub_os.path.should_exist.append(directory)
+ self.stub_os.should_makedirs.append(
+ sysrt.Path(directory.replace('root', 'dest')))
+ for f in files:
+ self.stub_os.path.should_exist.append(f)
+ self.stub_shutil.should_copy.append(
+ (f, sysrt.Path(f.replace('root', 'dest'))))
+ # Add some files to the mock filesystem that shouldn't be copied.
+ self.stub_os.path.should_exist.append('root/donotcopy')
+ self.stub_os.path.should_exist.append('other')
+ self.stub_os.path.should_be_dir.append('other')
+ self.stub_os.path.should_exist.append('other/copy0')
+ self.stub_os.path.should_exist.append('other/unfilteredcopy')
+ # A filter that should only collect the copy files.
+ def copy_filter(name):
+ return name.startswith('copy')
+
+ sysrt.AddGlob('root/*', 'dest', recurse=True, filter_func=copy_filter)
+ # Make sure everything was copied.
+ self.assertEqual(self.stub_shutil.should_copy, [])
+ # Note: shutil copy2 stub is not implemented such that it checks for
+ # dirs existing. This will test that dirs were created, but not
+ # necessarily that they were created before they were copied to.
+ for directory in directories:
+ self.assertTrue(
+ sysrt.HasDir(self.stub_os.path.join(directory.replace('root',
+ 'dest'))))
+
+ # Test with no filter.
+ # Also should be no issue copying into a now-populated destination.
+ self.stub_shutil.should_copy.append(('other/copy0',
+ sysrt.Path('dest', 'copy0')))
+ sysrt.AddGlob('other/c*', 'dest')
+ # Make sure everything was copied.
+ self.assertEqual(self.stub_shutil.should_copy, [])
+
+ def test_add_glob_symlinks(self):
+ (sysrt, _) = self.gen_sysroot()
+ self.stub_os.path.should_be_dir += ['root', 'root/subdir']
+ self.stub_os.should_makedirs += [sysrt.Path('subdir')]
+ self.stub_os.path.should_exist += [
+ 'root', 'root/subdir', 'root/subdir/not_a_link', 'root/link',
+ 'root/subdir/link']
+ self.stub_os.path.should_link['root/link'] = '../relative_link_dest'
+ self.stub_os.path.should_link['root/subdir/link'] = (
+ '../../relative_link_dest')
+
+ # Should copy not_a_link, and create a link for link.
+ self.stub_os.should_create_link = [
+ ('../relative_link_dest', sysrt.Path('link')),
+ ('../../relative_link_dest', sysrt.Path('subdir/link')),
+ ]
+ self.stub_shutil.should_copy = [
+ ('root/subdir/not_a_link', sysrt.Path('subdir/not_a_link'))]
+ sysrt.AddGlob('root/*', recurse=True, symlinks=True)
+ # Make sure the one file was copied, and the link was created.
+ self.assertEqual(self.stub_shutil.should_copy, [])
+ self.assertEqual('../relative_link_dest',
+ self.stub_os.readlink(sysrt.Path('link')))
+ self.assertEqual('../../relative_link_dest',
+ self.stub_os.readlink(sysrt.Path('subdir/link')))
+
+ def test_add_glob_ignore_symlinks(self):
+ (sysrt, _) = self.gen_sysroot()
+ self.stub_os.path.should_be_dir += ['root', 'root/subdir']
+ self.stub_os.should_makedirs += [sysrt.Path('subdir')]
+ self.stub_os.path.should_exist += [
+ 'root', 'root/subdir', 'root/not_a_link', 'root/subdir/link']
+ self.stub_os.path.should_link['root/subdir/link'] = (
+ '../relative_link_dest')
+
+ # Should copy both not_a_link and link.
+ self.stub_shutil.should_copy = [
+ ('root/not_a_link', sysrt.Path('not_a_link')),
+ ('root/subdir/link', sysrt.Path('subdir/link'))]
+ sysrt.AddGlob('root/*', recurse=True, symlinks=False)
+ # Make sure the two files were copied.
+ self.assertEqual(self.stub_shutil.should_copy, [])
+
+ def test_add_dir_recurse_and_unfiltered(self):
+ self.stub_os.path.should_exist = []
+ self.stub_os.path.should_be_dir = []
+ (sysrt, _) = self.gen_sysroot()
+ directories = ['root', 'root/sub1', 'root/sub2', 'root/sub1/supersub']
+ files = ['root/sub1/copy1', 'root/sub2/copy2',
+ 'root/sub1/supersub/copy3', 'root/copy0']
+ for directory in directories:
+ self.stub_os.path.should_be_dir.append(directory)
+ self.stub_os.path.should_exist.append(directory)
+ self.stub_os.should_makedirs.append(
+ sysrt.Path(directory.replace('root', 'dest')))
+ for f in files:
+ self.stub_os.path.should_exist.append(f)
+ self.stub_shutil.should_copy.append(
+ (f, sysrt.Path(f.replace('root', 'dest'))))
+ # Add some files to the mock filesystem that shouldn't be copied.
+ self.stub_os.path.should_exist.append('root/donotcopy')
+ self.stub_os.path.should_exist.append('other')
+ self.stub_os.path.should_be_dir.append('other')
+ self.stub_os.path.should_exist.append('other/copy0')
+ self.stub_os.path.should_exist.append('other/unfilteredcopy')
+ # A filter that should only collect the copy files.
+ def copy_filter(name):
+ return name.startswith('copy')
+
+ sysrt.AddDir('root', 'dest', recurse=True, filter_func=copy_filter)
+ # Make sure everything was copied.
+ self.assertEqual(self.stub_shutil.should_copy, [])
+ # Note: shutil copy2 stub is not implemented such that it checks for
+ # dirs existing. This will test that dirs were created, but not
+ # necessarily that they were created before they were copied to.
+ for directory in directories:
+ self.assertTrue(
+ sysrt.HasDir(
+ self.stub_os.path.join(directory.replace('root', 'dest'))))
+
+ # Test with no filter.
+ # Also should be no issue copying into a now-populated destination.
+ self.stub_shutil.should_copy.append(
+ ('other/copy0', sysrt.Path('dest', 'copy0')))
+ self.stub_shutil.should_copy.append(('other/unfilteredcopy',
+ sysrt.Path('dest',
+ 'unfilteredcopy')))
+ sysrt.AddDir('other', 'dest')
+ # Make sure everything was copied.
+ self.assertEqual(self.stub_shutil.should_copy, [])
+
+ def test_add_dir_top_level_no_recurse(self):
+ (sysrt, _) = self.gen_sysroot()
+ directories = ['root', 'root/sub1', 'root/sub2', 'root/sub1/supersub']
+ files = ['root/sub1/copy1', 'root/sub2/copy2',
+ 'root/sub1/supersub/copy3', 'root/copy0']
+ for directory in directories:
+ self.stub_os.path.should_be_dir.append(directory)
+ self.stub_os.path.should_exist.append(directory)
+ for f in files:
+ self.stub_os.path.should_exist.append(f)
+ # Should only copy from top level of root,
+ # and with no dest provided should copy to top level of the sysroot.
+ self.stub_shutil.should_copy.append(('root/copy0', sysrt.Path('copy0')))
+ sysrt.AddDir('root', recurse=False)
+ # Make sure the one file was copied.
+ self.assertEqual(self.stub_shutil.should_copy, [])
+
+ def test_add_dir_symlinks(self):
+ (sysrt, _) = self.gen_sysroot()
+ self.stub_os.path.should_be_dir += ['root', 'root/subdir']
+ self.stub_os.should_makedirs += [sysrt.Path('subdir')]
+ self.stub_os.path.should_exist += [
+ 'root', 'root/subdir', 'root/not_a_link', 'root/subdir/link']
+ self.stub_os.path.should_link['root/subdir/link'] = (
+ '../relative_link_dest')
+
+ # Should copy not_a_link, and create a link for link.
+ self.stub_os.should_create_link = [('../relative_link_dest',
+ sysrt.Path('subdir/link'))]
+ self.stub_shutil.should_copy = [
+ ('root/not_a_link', sysrt.Path('not_a_link'))]
+ sysrt.AddDir('root', symlinks=True)
+ # Make sure the one file was copied, and the link was created.
+ self.assertEqual(self.stub_shutil.should_copy, [])
+ self.assertEqual('../relative_link_dest',
+ self.stub_os.readlink(sysrt.Path('subdir/link')))
+
+ def test_add_dir_ignore_symlinks(self):
+ (sysrt, _) = self.gen_sysroot()
+ self.stub_os.path.should_be_dir += ['root', 'root/subdir']
+ self.stub_os.should_makedirs += [sysrt.Path('subdir')]
+ self.stub_os.path.should_exist += [
+ 'root', 'root/subdir', 'root/not_a_link', 'root/subdir/link']
+ self.stub_os.path.should_link['root/subdir/link'] = (
+ '../relative_link_dest')
+
+ # Should copy both not_a_link and link.
+ self.stub_shutil.should_copy += [
+ ('root/not_a_link', sysrt.Path('not_a_link')),
+ ('root/subdir/link', sysrt.Path('subdir/link'))]
+ sysrt.AddDir('root', symlinks=False)
+ # Make sure the two files were copied.
+ self.assertEqual(self.stub_shutil.should_copy, [])
+
+ def test_write_file(self):
+ self.stub_os.path.should_be_dir = []
+ (sysrt, _) = self.gen_sysroot()
+ self.stub_os.should_makedirs = [sysrt.Path('dir')]
+ sysrt.WriteFile('dir/file', 'contents')
+ self.assertTrue(
+ 'contents' in self.stub_open.files[sysrt.Path('dir/file')].contents)
diff --git a/cli/lib/environment/sysroot_util.py b/cli/lib/environment/sysroot_util.py
index 6d8302e..c599ffb 100644
--- a/cli/lib/environment/sysroot_util.py
+++ b/cli/lib/environment/sysroot_util.py
@@ -24,298 +24,308 @@ from core import util
def _FilterHeaders(filename):
- return filename.endswith('.h')
+ return filename.endswith('.h')
class SysrootUtil(object):
- """A class to assist with setting up sysroots.
-
- Attributes:
- sysroot - the sysroot this instance helps with.
- """
-
- # Includes to provide in the sysroot.
- # (lib, recurse, filter)
- DEFAULT_INCLUDES = [
- ('bionic/libc/include', True, _FilterHeaders),
- ('bionic/libc/kernel/uapi/asm-generic/..', True, _FilterHeaders),
- ('bionic/libc/kernel/uapi/linux/..', True, _FilterHeaders),
- ('external/zlib', False, _FilterHeaders),
- ('system/core/include', True, _FilterHeaders)
- ]
- DEFAULT_ARCH_INCLUDES = {
- 'arm': [('bionic/libc/kernel/uapi/asm-arm', True, _FilterHeaders),
- ('bionic/libc/arch-arm/include', True, _FilterHeaders)],
- 'mips': [('bionic/libc/kernel/uapi/asm-mips', True, _FilterHeaders),
- ('bionic/libc/arch-mips/include', True, _FilterHeaders)],
- 'x86': [('bionic/libc/kernel/uapi/asm-x86', True, _FilterHeaders),
- ('bionic/libc/arch-x86/include', True, _FilterHeaders)],
- }
-
- # Libs to provide in the sysroot.
- STATIC_PATH_FORMAT = '{0}_intermediates/{0}.a'
- DEFAULT_STATIC_LIBS = ['libc', 'libc++_static', 'libm', 'libz']
- DEFAULT_SHARED_LIBS = ['crtbegin_so.o',
- 'crtbegin_dynamic.o',
- 'crtbegin_static.o',
- 'crtend_android.o',
- 'crtend_so.o',
- 'libc.so',
- 'libc++.so',
- 'libdl.so',
- 'libm.so',
- 'libz.so']
-
- DEFAULT_LIB_RENAMES = {
- 'libc++.so': 'libstdc++.so',
- 'libc++_static.a': 'libstdc++.a'
- }
-
- # Some defaults for where things go.
- DEFAULT_INCLUDE_DIR = os.path.join('usr', 'include')
- DEFAULT_LIB_DIR = os.path.join('usr', 'lib')
- ADDITIONAL_INCLUDE_EXTENSION = 'brillo'
-
- # Libcxx gets special treatment.
- LIBCXX_HEADERS = 'external/libcxx/include'
- LIBCXX_INCLUDE_DIR = os.path.join(DEFAULT_INCLUDE_DIR, 'c++')
-
- # pkg-config constants.
- PC_DIR = os.path.join('usr', 'share', 'pkgconfig')
- # For this format:
- # {0} - lib name
- # {1} - version
- # {2} - dependencies
- # {3} - normalized lib name ('lib' prefix removed)
- # Note that if this format changes where to expect things,
- # also change the AddProvidedLib function.
- PC_FILE_FORMAT = ('prefix=/usr\n'
- 'exec_prefix=${{prefix}}\n'
- 'libdir=${{exec_prefix}}/lib\n'
- 'includedir=${{exec_prefix}}/include/' +
- ADDITIONAL_INCLUDE_EXTENSION + '/{0}\n'
- '\n'
- 'Name: {0}\n'
- 'Description: {0} for Brillo\n'
- 'Version: {1}\n'
- 'Requires: {2}\n'
- 'Libs: -L${{libdir}} -l{3}\n'
- 'Cflags: -I${{includedir}}\n')
-
- def __init__(self, sysroot, os_version):
- self.sysroot = sysroot
- self.os_version = os_version
-
- def _FormatForCopy(self, src, dest):
- """Helper to account for special formatting signals.
-
- Given a path to copy from and path to copy to, returns a pair suitable
- to input into sysroot.AddDir.
-
- Special format A/B/.. designates wanting only B when A has several subdirs.
-
- Args:
- src: the path to copy from. Relative to the OS.
- dest: the path to copy to. Relative to the sysroot.
-
- Returns:
- (result_src, result_dest), src and dest transformed and ready
- to be passed into sysroot.AddDir.
- """
- result_src = util.GetOSPath(self.os_version, src)
- result_dest = dest
- if src.endswith('/..'):
- basename = os.path.basename(src[:-3])
- result_src = os.path.join(result_src, basename)
- result_dest = os.path.join(result_dest, basename)
- return (result_src, result_dest)
-
- def _AddPkgConfigFile(self, lib, deps, version):
- """Writes a .pc file for a lib in the sysroot.
-
- Args:
- lib: the name of the library for this .pc file.
- deps: a space separated string of library names this library depends on.
- version: the version of this library.
-
- Raises:
- IOError if the file write fails.
- """
- dest_dir = self.PC_DIR
-
- normalized_lib = lib
- if lib.startswith('lib'):
- normalized_lib = lib[3:]
- self.sysroot.WriteFile(
- os.path.join(dest_dir, lib + '.pc'),
- self.PC_FILE_FORMAT.format(lib, version, deps, normalized_lib))
-
- def AddSharedLib(self, lib_src, name, deps, includes, suffix=None):
- """Adds a library to the sysroot.
-
- Copies in the .so file, copies in includes, and generates a pkg-config file.
-
- Args:
- lib_src: path where prebuilt shared libs can be found.
- name: the name of the library to add.
- deps: a space-separated string of library names lib is dependent on.
- includes: a list of directories with headers for lib.
- suffix: (optional) a suffix to append to the lib name when added
- to the sysroot.
-
- Raises:
- IOError: If there are any issues adding the necessary files
- to the sysroot.
- """
- suffixed_name = name
- if suffix:
- suffixed_name += '-' + suffix
-
- # Set up destinations.
- # NOTE: if these change, also update the PC_FILE_FORMAT.
- lib_dest = self.DEFAULT_LIB_DIR
- include_dest = os.path.join(self.DEFAULT_INCLUDE_DIR,
- self.ADDITIONAL_INCLUDE_EXTENSION,
- suffixed_name)
- self.sysroot.Makedirs(lib_dest)
- self.sysroot.Makedirs(include_dest)
-
- errors = []
-
- # Get the .so file.
- try:
- self.sysroot.AddFile(os.path.join(lib_src, name + '.so'),
- os.path.join(lib_dest, suffixed_name + '.so'))
- except IOError as e:
- errors.append('.so file: {}'.format(e))
-
- # Copy includes (.h files only) over to sysroot.
- for include in includes:
- (src, dest) = self._FormatForCopy(include, include_dest)
- try:
- self.sysroot.AddDir(src, dest, filter_func=_FilterHeaders)
- except IOError as e:
- errors.append('include {}: {}'.format(include, e))
-
- # Write the .pc file.
- try:
- self._AddPkgConfigFile(suffixed_name, deps, util.GetOSVersion())
- except IOError as e:
- errors.append('.pc file: {}'.format(e))
-
- if errors:
- raise IOError('Failed to add components for {}: {}'.format(
- suffixed_name, errors))
-
- def AddSharedLibsFromCSV(self, lib_src, csv_file, suffix=None):
- """Add libraries read from a csv file to the sysroot.
-
- CSV file format is one line header, followed by lines of the form
- libname, deps, include_dirs
-
- Args:
- lib_src: path where prebuilt shared libs can be found.
- csv_file: path to the file to add libs from.
- suffix: (optional) a suffix to append to all the lib names when added to
- the sysroot.
-
- Raises:
- IOError: if file can't be found or adding any lib fails.
- ValueError: if any line in the file doesn't meet format expectations.
- """
- libs = []
- try:
- with open(csv_file) as pkg_list:
- # Skip the header line
- pkg_list.readline()
- # Read in all the remaining lines
- for line in pkg_list:
- lib_details = [pkg.strip() for pkg in line.split(',')]
- if len(lib_details) != 3:
- raise ValueError(('Line in package csv file "{0}" '
- 'has the incorrect number of items (expected 3): '
- '{1}').format(csv_file, line))
- libs.append(lib_details)
- except IOError as e:
- raise IOError('Failed to open lib list: {0}'.format(e))
-
- errors = []
- for (name, deps, include_str) in libs:
- try:
- self.AddSharedLib(lib_src, name, deps, include_str.split(), suffix)
- except IOError as e:
- errors.append(e)
-
- if errors:
- raise IOError('Failed to add libs from csv {0}: {1}'.format(
- csv_file, errors))
-
- def SetupBaseSysroot(self, arch, shared_libs, static_libs, base_sysroot=None):
- """Sets up a sysroot dir from defaults.
-
- Standard includes and lib files are added to <sysroot>/usr/{include, lib}.
-
- Args:
- arch: the architecture to setup a sysroot for.
- shared_libs: path where prebuilt shared libs can be found.
- static_libs: path where prebuilt static libs can be found.
- base_sysroot: (optional). If provided, copies all files of the sysroot
- found at this path, with priority over other files.
-
- Raises:
- IOError: if anything fails, specifying which things failed.
+ """A class to assist with setting up sysroots.
+
+ Attributes:
+ sysroot - the sysroot this instance helps with.
"""
- errors = []
-
- # Copy in includes.
- self.sysroot.Makedirs(self.DEFAULT_INCLUDE_DIR)
- for (include, recurse, filter_func) in (self.DEFAULT_INCLUDES +
- self.DEFAULT_ARCH_INCLUDES[arch]):
- (src, dest) = self._FormatForCopy(include, self.DEFAULT_INCLUDE_DIR)
- try:
- self.sysroot.AddDir(src, dest, recurse, filter_func)
- except IOError as e:
- errors.append('{}: {}'.format(include, e))
-
- # Handle libcxx.
- (src, dest) = self._FormatForCopy(self.LIBCXX_HEADERS,
- self.LIBCXX_INCLUDE_DIR)
- try:
- self.sysroot.AddDir(src, dest)
- except IOError as e:
- errors.append(self.LIBCXX_HEADERS)
-
- # Copy in libs.
- self.sysroot.Makedirs(self.DEFAULT_LIB_DIR)
- for lib in self.DEFAULT_SHARED_LIBS:
- try:
- self.sysroot.AddFile(os.path.join(shared_libs, lib),
- self.DEFAULT_LIB_DIR)
- except IOError as e:
- errors.append(lib)
- for lib in self.DEFAULT_STATIC_LIBS:
- try:
- self.sysroot.AddFile(os.path.join(static_libs,
- self.STATIC_PATH_FORMAT.format(lib)),
- self.DEFAULT_LIB_DIR)
- except IOError as e:
- errors.append(lib)
-
- # Do some renaming.
- for (src, dest) in self.DEFAULT_LIB_RENAMES.iteritems():
- try:
- shutil.move(self.sysroot.Path(self.DEFAULT_LIB_DIR, src),
- self.sysroot.Path(self.DEFAULT_LIB_DIR, dest))
- except IOError as e:
- errors.append('rename {0} --> {1}'.format(src, dest))
-
- # Base our sysroot on another.
- # We do this after copying in defaults to give this base priority.
- if base_sysroot:
- try:
- self.sysroot.AddDir(base_sysroot)
- except IOError as e:
- errors.append(base_sysroot)
-
- if errors:
- raise IOError('Failed to add {0} during sysroot setup.'.format(errors))
+
+ # Includes to provide in the sysroot.
+ # (lib, recurse, filter)
+ DEFAULT_INCLUDES = [
+ ('bionic/libc/include', True, _FilterHeaders),
+ ('bionic/libc/kernel/uapi/asm-generic/..', True, _FilterHeaders),
+ ('bionic/libc/kernel/uapi/linux/..', True, _FilterHeaders),
+ ('external/zlib', False, _FilterHeaders),
+ ('system/core/include', True, _FilterHeaders)
+ ]
+ DEFAULT_ARCH_INCLUDES = {
+ 'arm': [('bionic/libc/kernel/uapi/asm-arm', True, _FilterHeaders),
+ ('bionic/libc/arch-arm/include', True, _FilterHeaders)],
+ 'mips': [('bionic/libc/kernel/uapi/asm-mips', True, _FilterHeaders),
+ ('bionic/libc/arch-mips/include', True, _FilterHeaders)],
+ 'x86': [('bionic/libc/kernel/uapi/asm-x86', True, _FilterHeaders),
+ ('bionic/libc/arch-x86/include', True, _FilterHeaders)],
+ }
+
+ # Libs to provide in the sysroot.
+ STATIC_PATH_FORMAT = '{0}_intermediates/{0}.a'
+ DEFAULT_STATIC_LIBS = ['libc', 'libc++_static', 'libm', 'libz']
+ DEFAULT_SHARED_LIBS = ['crtbegin_so.o',
+ 'crtbegin_dynamic.o',
+ 'crtbegin_static.o',
+ 'crtend_android.o',
+ 'crtend_so.o',
+ 'libc.so',
+ 'libc++.so',
+ 'libdl.so',
+ 'libm.so',
+ 'libz.so']
+
+ DEFAULT_LIB_RENAMES = {
+ 'libc++.so': 'libstdc++.so',
+ 'libc++_static.a': 'libstdc++.a'
+ }
+
+ # Some defaults for where things go.
+ DEFAULT_INCLUDE_DIR = os.path.join('usr', 'include')
+ DEFAULT_LIB_DIR = os.path.join('usr', 'lib')
+ ADDITIONAL_INCLUDE_EXTENSION = 'brillo'
+
+ # Libcxx gets special treatment.
+ LIBCXX_HEADERS = 'external/libcxx/include'
+ LIBCXX_INCLUDE_DIR = os.path.join(DEFAULT_INCLUDE_DIR, 'c++')
+
+ # pkg-config constants.
+ PC_DIR = os.path.join('usr', 'share', 'pkgconfig')
+ # For this format:
+ # {0} - lib name
+ # {1} - version
+ # {2} - dependencies
+ # {3} - normalized lib name ('lib' prefix removed)
+ # Note that if this format changes where to expect things,
+ # also change the AddProvidedLib function.
+ PC_FILE_FORMAT = ('prefix=/usr\n'
+ 'exec_prefix=${{prefix}}\n'
+ 'libdir=${{exec_prefix}}/lib\n'
+ 'includedir=${{exec_prefix}}/include/' +
+ ADDITIONAL_INCLUDE_EXTENSION + '/{0}\n'
+ '\n'
+ 'Name: {0}\n'
+ 'Description: {0} for Brillo\n'
+ 'Version: {1}\n'
+ 'Requires: {2}\n'
+ 'Libs: -L${{libdir}} -l{3}\n'
+ 'Cflags: -I${{includedir}}\n')
+
+ def __init__(self, sysroot, os_version):
+ self.sysroot = sysroot
+ self.os_version = os_version
+
+ def _FormatForCopy(self, src, dest):
+ """Helper to account for special formatting signals.
+
+ Given a path to copy from and path to copy to, returns a pair suitable
+ to input into sysroot.AddDir.
+
+ Special format A/B/.. designates wanting only B when A has several
+ subdirs.
+
+ Args:
+ src: the path to copy from. Relative to the OS.
+ dest: the path to copy to. Relative to the sysroot.
+
+ Returns:
+ (result_src, result_dest), src and dest transformed and ready
+ to be passed into sysroot.AddDir.
+ """
+ result_src = util.GetOSPath(self.os_version, src)
+ result_dest = dest
+ if src.endswith('/..'):
+ basename = os.path.basename(src[:-3])
+ result_src = os.path.join(result_src, basename)
+ result_dest = os.path.join(result_dest, basename)
+ return (result_src, result_dest)
+
+ def _AddPkgConfigFile(self, lib, deps, version):
+ """Writes a .pc file for a lib in the sysroot.
+
+ Args:
+ lib: the name of the library for this .pc file.
+ deps: a space separated string of library names this library
+ depends on.
+ version: the version of this library.
+
+ Raises:
+ IOError if the file write fails.
+ """
+ dest_dir = self.PC_DIR
+
+ normalized_lib = lib
+ if lib.startswith('lib'):
+ normalized_lib = lib[3:]
+ self.sysroot.WriteFile(
+ os.path.join(dest_dir, lib + '.pc'),
+ self.PC_FILE_FORMAT.format(lib, version, deps, normalized_lib))
+
+ def AddSharedLib(self, lib_src, name, deps, includes, suffix=None):
+ """Adds a library to the sysroot.
+
+ Copies in the .so file, copies in includes, and generates a pkg-config
+ file.
+
+ Args:
+ lib_src: path where prebuilt shared libs can be found.
+ name: the name of the library to add.
+ deps: a space-separated string of library names lib is dependent on.
+ includes: a list of directories with headers for lib.
+ suffix: (optional) a suffix to append to the lib name when added
+ to the sysroot.
+
+ Raises:
+ IOError: If there are any issues adding the necessary files
+ to the sysroot.
+ """
+ suffixed_name = name
+ if suffix:
+ suffixed_name += '-' + suffix
+
+ # Set up destinations.
+ # NOTE: if these change, also update the PC_FILE_FORMAT.
+ lib_dest = self.DEFAULT_LIB_DIR
+ include_dest = os.path.join(self.DEFAULT_INCLUDE_DIR,
+ self.ADDITIONAL_INCLUDE_EXTENSION,
+ suffixed_name)
+ self.sysroot.Makedirs(lib_dest)
+ self.sysroot.Makedirs(include_dest)
+
+ errors = []
+
+ # Get the .so file.
+ try:
+ self.sysroot.AddFile(os.path.join(lib_src, name + '.so'),
+ os.path.join(lib_dest, suffixed_name + '.so'))
+ except IOError as e:
+ errors.append('.so file: {}'.format(e))
+
+ # Copy includes (.h files only) over to sysroot.
+ for include in includes:
+ (src, dest) = self._FormatForCopy(include, include_dest)
+ try:
+ self.sysroot.AddDir(src, dest, filter_func=_FilterHeaders)
+ except IOError as e:
+ errors.append('include {}: {}'.format(include, e))
+
+ # Write the .pc file.
+ try:
+ self._AddPkgConfigFile(suffixed_name, deps, util.GetOSVersion())
+ except IOError as e:
+ errors.append('.pc file: {}'.format(e))
+
+ if errors:
+ raise IOError('Failed to add components for {}: {}'.format(
+ suffixed_name, errors))
+
+ def AddSharedLibsFromCSV(self, lib_src, csv_file, suffix=None):
+ """Add libraries read from a csv file to the sysroot.
+
+ CSV file format is one line header, followed by lines of the form
+ libname, deps, include_dirs
+
+ Args:
+ lib_src: path where prebuilt shared libs can be found.
+ csv_file: path to the file to add libs from.
+ suffix: (optional) a suffix to append to all the lib names when
+ added to the sysroot.
+
+ Raises:
+ IOError: if file can't be found or adding any lib fails.
+ ValueError: if any line in the file doesn't meet format
+ expectations.
+ """
+ libs = []
+ try:
+ with open(csv_file) as pkg_list:
+ # Skip the header line
+ pkg_list.readline()
+ # Read in all the remaining lines
+ for line in pkg_list:
+ lib_details = [pkg.strip() for pkg in line.split(',')]
+ if len(lib_details) != 3:
+ raise ValueError(('Line in package csv file "{0}" has '
+ 'the incorrect number of items '
+ '(expected 3): {1}').format(csv_file,
+ line))
+ libs.append(lib_details)
+ except IOError as e:
+ raise IOError('Failed to open lib list: {0}'.format(e))
+
+ errors = []
+ for (name, deps, include_str) in libs:
+ try:
+ self.AddSharedLib(lib_src, name, deps, include_str.split(),
+ suffix)
+ except IOError as e:
+ errors.append(e)
+
+ if errors:
+ raise IOError('Failed to add libs from csv {0}: {1}'.format(
+ csv_file, errors))
+
+ def SetupBaseSysroot(self, arch, shared_libs, static_libs,
+ base_sysroot=None):
+ """Sets up a sysroot dir from defaults.
+
+ Standard includes and lib files are added to
+ <sysroot>/usr/{include, lib}.
+
+ Args:
+ arch: the architecture to setup a sysroot for.
+ shared_libs: path where prebuilt shared libs can be found.
+ static_libs: path where prebuilt static libs can be found.
+ base_sysroot: (optional). If provided, copies all files of the
+ sysroot found at this path, with priority over other files.
+
+ Raises:
+ IOError: if anything fails, specifying which things failed.
+ """
+ errors = []
+
+ # Copy in includes.
+ self.sysroot.Makedirs(self.DEFAULT_INCLUDE_DIR)
+ for (include, recurse, filter_func) in (
+ self.DEFAULT_INCLUDES + self.DEFAULT_ARCH_INCLUDES[arch]):
+ (src, dest) = self._FormatForCopy(include, self.DEFAULT_INCLUDE_DIR)
+ try:
+ self.sysroot.AddDir(src, dest, recurse, filter_func)
+ except IOError as e:
+ errors.append('{}: {}'.format(include, e))
+
+ # Handle libcxx.
+ (src, dest) = self._FormatForCopy(self.LIBCXX_HEADERS,
+ self.LIBCXX_INCLUDE_DIR)
+ try:
+ self.sysroot.AddDir(src, dest)
+ except IOError as e:
+ errors.append(self.LIBCXX_HEADERS)
+
+ # Copy in libs.
+ self.sysroot.Makedirs(self.DEFAULT_LIB_DIR)
+ for lib in self.DEFAULT_SHARED_LIBS:
+ try:
+ self.sysroot.AddFile(os.path.join(shared_libs, lib),
+ self.DEFAULT_LIB_DIR)
+ except IOError as e:
+ errors.append(lib)
+ for lib in self.DEFAULT_STATIC_LIBS:
+ try:
+ self.sysroot.AddFile(
+ os.path.join(static_libs,
+ self.STATIC_PATH_FORMAT.format(lib)),
+ self.DEFAULT_LIB_DIR)
+ except IOError as e:
+ errors.append(lib)
+
+ # Do some renaming.
+ for (src, dest) in self.DEFAULT_LIB_RENAMES.iteritems():
+ try:
+ shutil.move(self.sysroot.Path(self.DEFAULT_LIB_DIR, src),
+ self.sysroot.Path(self.DEFAULT_LIB_DIR, dest))
+ except IOError as e:
+ errors.append('rename {0} --> {1}'.format(src, dest))
+
+ # Base our sysroot on another.
+ # We do this after copying in defaults to give this base priority.
+ if base_sysroot:
+ try:
+ self.sysroot.AddDir(base_sysroot)
+ except IOError as e:
+ errors.append(base_sysroot)
+
+ if errors:
+ raise IOError(
+ 'Failed to add {0} during sysroot setup.'.format(errors))
diff --git a/cli/lib/environment/sysroot_util_unittest.py b/cli/lib/environment/sysroot_util_unittest.py
index a97f5a8..3139c27 100644
--- a/cli/lib/environment/sysroot_util_unittest.py
+++ b/cli/lib/environment/sysroot_util_unittest.py
@@ -26,146 +26,150 @@ from test import stubs
class SysrootUtilTest(unittest.TestCase):
- def setUp(self):
- self.stub_os = stubs.StubOs()
- self.stub_open = stubs.StubOpen(self.stub_os)
- self.stub_shutil = stubs.StubShutil(self.stub_os)
- self.stub_util = util_stub.StubUtil()
-
- sysroot_util.os = self.stub_os
- sysroot_util.open = self.stub_open.open
- sysroot_util.shutil = self.stub_shutil
- sysroot_util.util = self.stub_util
-
- self.sysroot = sysroot_stub.StubSysroot('sysroot/path')
- self.sysrt_util = sysroot_util.SysrootUtil(self.sysroot,
- self.stub_util.GetOSVersion())
-
- def test_add_pc_file(self):
- self.sysroot.should_write = [self.stub_os.path.join(self.sysrt_util.PC_DIR,
- 'libtest.pc')]
- # pylint: disable=protected-access
- self.sysrt_util._AddPkgConfigFile('libtest', 'liba libb', '1.0')
- self.assertTrue('liba libb' in self.sysroot.last_written)
- self.assertTrue('1.0' in self.sysroot.last_written)
- self.assertTrue('-ltest' in self.sysroot.last_written)
- self.assertTrue('libtest' in self.sysroot.last_written)
-
- def test_add_shared_lib(self):
- self.sysroot.should_write = [self.stub_os.path.join(self.sysrt_util.PC_DIR,
- 'libtest-suffix.pc')]
- lib_dir = self.sysrt_util.DEFAULT_LIB_DIR
- include_dir = self.stub_os.path.join(
- self.sysrt_util.DEFAULT_INCLUDE_DIR,
- self.sysrt_util.ADDITIONAL_INCLUDE_EXTENSION, 'libtest-suffix')
- self.sysroot.should_makedirs = [lib_dir, include_dir]
- self.sysroot.should_add_file = [
- (self.stub_os.path.join('libsrc', 'libtest.so'),
- self.stub_os.path.join(lib_dir, 'libtest-suffix.so'))]
- self.sysroot.should_add_dir = [
- (self.stub_util.GetOSPath(self.stub_util.GetOSVersion(), 'headers/1'),
- include_dir, True),
- (self.stub_util.GetOSPath(self.stub_util.GetOSVersion(),
- 'headers/deeper/2/../2'),
- self.stub_os.path.join(include_dir, '2'), True)]
- self.sysroot.should_pass_filter = ['file.h', 'h.h', '.h.h',
- 'longer/path/to/thing.h']
- self.sysroot.should_fail_filter = ['h.cpp', 'h', 'file.h.tar']
- self.sysrt_util.AddSharedLib('libsrc',
- 'libtest',
- 'liba libb',
- ['headers/1', 'headers/deeper/2/..'],
- 'suffix')
- # Make sure everything got done.
- self.assertEqual(self.sysroot.should_add_file, [])
- self.assertEqual(self.sysroot.should_add_dir, [])
- self.assertEqual(self.sysroot.should_write, [])
-
- def test_add_libs_from_csv(self):
- self.sysroot.should_write = [self.stub_os.path.join(self.sysrt_util.PC_DIR,
- 'libtest-suffix.pc'),
- self.stub_os.path.join(self.sysrt_util.PC_DIR,
- 'libtest2-suffix.pc')]
- lib_dir = self.sysrt_util.DEFAULT_LIB_DIR
- include_dir = self.stub_os.path.join(
- self.sysrt_util.DEFAULT_INCLUDE_DIR,
- self.sysrt_util.ADDITIONAL_INCLUDE_EXTENSION, 'libtest-suffix')
- include_dir2 = self.stub_os.path.join(
- self.sysrt_util.DEFAULT_INCLUDE_DIR,
- self.sysrt_util.ADDITIONAL_INCLUDE_EXTENSION, 'libtest2-suffix')
- self.sysroot.should_makedirs = [lib_dir, include_dir, include_dir2]
- self.sysroot.should_add_file = [
- (self.stub_os.path.join('libsrc', 'libtest.so'),
- self.stub_os.path.join(lib_dir, 'libtest-suffix.so')),
- (self.stub_os.path.join('libsrc', 'libtest2.so'),
- self.stub_os.path.join(lib_dir, 'libtest2-suffix.so'))]
- self.sysroot.should_add_dir = [
- (self.stub_util.GetOSPath(self.stub_util.GetOSVersion(), 'headers/1'),
- include_dir, True),
- (self.stub_util.GetOSPath(self.stub_util.GetOSVersion(), 'headers/2'),
- include_dir, True)]
- self.sysroot.should_pass_filter = ['file.h', 'h.h', '.h.h',
- 'longer/path/to/thing.h']
- self.sysroot.should_fail_filter = ['h.cpp', 'h', 'file.h.tar']
- f = stubs.StubFile('header line\n'
- 'libtest, liba libb, headers/1 headers/2\n'
- 'libtest2, , ')
- self.stub_open.files['csv_path'] = f
- self.stub_os.path.should_exist = ['csv_path']
-
- self.sysrt_util.AddSharedLibsFromCSV('libsrc', 'csv_path', 'suffix')
- # Make sure everything got done.
- self.assertEqual(self.sysroot.should_add_file, [])
- self.assertEqual(self.sysroot.should_add_dir, [])
- self.assertEqual(self.sysroot.should_write, [])
-
-
- def test_add_libs_bad_csv(self):
- f = stubs.StubFile('header line\n'
- 'has, enough, items\n'
- 'not, enough items')
- self.stub_open.files['csv_path'] = f
- self.stub_os.path.should_exist = ['csv_path']
- # Error should indicate which line was problematic.
- self.assertRaisesRegexp(ValueError, 'not, enough items',
- self.sysrt_util.AddSharedLibsFromCSV,
- 'libsrc', 'csv_path', 'suffix')
-
- def test_setup_base(self):
- self.sysroot.should_makedirs = [self.sysrt_util.DEFAULT_INCLUDE_DIR,
- self.sysrt_util.DEFAULT_LIB_DIR]
- def copyformat(src):
- # pylint: disable=protected-access
- return self.sysrt_util._FormatForCopy(
- src, self.sysrt_util.DEFAULT_INCLUDE_DIR)
-
- # pylint: disable=protected-access
- (libcxx_src, libcxx_dest) = self.sysrt_util._FormatForCopy(
- self.sysrt_util.LIBCXX_HEADERS, self.sysrt_util.LIBCXX_INCLUDE_DIR)
-
- self.sysroot.should_add_dir = [(libcxx_src, libcxx_dest, True)]
- for (src, recurse, _) in (self.sysrt_util.DEFAULT_INCLUDES +
- self.sysrt_util.DEFAULT_ARCH_INCLUDES['x86']):
- (copysrc, copydest) = copyformat(src)
- self.sysroot.should_add_dir.append((copysrc, copydest, recurse))
- self.sysroot.should_add_file = [('lib_src/' + default,
- self.sysrt_util.DEFAULT_LIB_DIR)
- for default in
- self.sysrt_util.DEFAULT_SHARED_LIBS]
- self.sysroot.should_add_file += [
- ('static_src/' + self.sysrt_util.STATIC_PATH_FORMAT.format(default),
- self.sysrt_util.DEFAULT_LIB_DIR)
- for default in self.sysrt_util.DEFAULT_STATIC_LIBS]
- self.sysroot.should_add_dir.append(('base', '', True))
- self.stub_shutil.should_move = [
- (self.sysroot.Path(self.sysrt_util.DEFAULT_LIB_DIR, src),
- self.sysroot.Path(self.sysrt_util.DEFAULT_LIB_DIR, dest))
- for (src, dest) in
- self.sysrt_util.DEFAULT_LIB_RENAMES.iteritems()]
-
- self.sysrt_util.SetupBaseSysroot('x86', 'lib_src', 'static_src', 'base')
- # Make sure everything got done.
- self.assertEqual(self.sysroot.should_add_file, [])
- self.assertEqual(self.sysroot.should_add_dir, [])
- self.assertEqual(self.sysroot.should_write, [])
- self.assertEqual(self.stub_shutil.should_move, [])
+ def setUp(self):
+ self.stub_os = stubs.StubOs()
+ self.stub_open = stubs.StubOpen(self.stub_os)
+ self.stub_shutil = stubs.StubShutil(self.stub_os)
+ self.stub_util = util_stub.StubUtil()
+
+ sysroot_util.os = self.stub_os
+ sysroot_util.open = self.stub_open.open
+ sysroot_util.shutil = self.stub_shutil
+ sysroot_util.util = self.stub_util
+
+ self.sysroot = sysroot_stub.StubSysroot('sysroot/path')
+ self.sysrt_util = sysroot_util.SysrootUtil(
+ self.sysroot, self.stub_util.GetOSVersion())
+
+ def test_add_pc_file(self):
+ self.sysroot.should_write = [
+ self.stub_os.path.join(self.sysrt_util.PC_DIR, 'libtest.pc')]
+ # pylint: disable=protected-access
+ self.sysrt_util._AddPkgConfigFile('libtest', 'liba libb', '1.0')
+ self.assertTrue('liba libb' in self.sysroot.last_written)
+ self.assertTrue('1.0' in self.sysroot.last_written)
+ self.assertTrue('-ltest' in self.sysroot.last_written)
+ self.assertTrue('libtest' in self.sysroot.last_written)
+
+ def test_add_shared_lib(self):
+ self.sysroot.should_write = [
+ self.stub_os.path.join(self.sysrt_util.PC_DIR,
+ 'libtest-suffix.pc')]
+ lib_dir = self.sysrt_util.DEFAULT_LIB_DIR
+ include_dir = self.stub_os.path.join(
+ self.sysrt_util.DEFAULT_INCLUDE_DIR,
+ self.sysrt_util.ADDITIONAL_INCLUDE_EXTENSION, 'libtest-suffix')
+ self.sysroot.should_makedirs = [lib_dir, include_dir]
+ self.sysroot.should_add_file = [
+ (self.stub_os.path.join('libsrc', 'libtest.so'),
+ self.stub_os.path.join(lib_dir, 'libtest-suffix.so'))]
+ self.sysroot.should_add_dir = [
+ (self.stub_util.GetOSPath(self.stub_util.GetOSVersion(),
+ 'headers/1'),
+ include_dir, True),
+ (self.stub_util.GetOSPath(self.stub_util.GetOSVersion(),
+ 'headers/deeper/2/../2'),
+ self.stub_os.path.join(include_dir, '2'), True)]
+ self.sysroot.should_pass_filter = ['file.h', 'h.h', '.h.h',
+ 'longer/path/to/thing.h']
+ self.sysroot.should_fail_filter = ['h.cpp', 'h', 'file.h.tar']
+ self.sysrt_util.AddSharedLib('libsrc',
+ 'libtest',
+ 'liba libb',
+ ['headers/1', 'headers/deeper/2/..'],
+ 'suffix')
+ # Make sure everything got done.
+ self.assertEqual(self.sysroot.should_add_file, [])
+ self.assertEqual(self.sysroot.should_add_dir, [])
+ self.assertEqual(self.sysroot.should_write, [])
+
+ def test_add_libs_from_csv(self):
+ self.sysroot.should_write = [
+ self.stub_os.path.join(self.sysrt_util.PC_DIR, 'libtest-suffix.pc'),
+ self.stub_os.path.join(self.sysrt_util.PC_DIR,
+ 'libtest2-suffix.pc')]
+ lib_dir = self.sysrt_util.DEFAULT_LIB_DIR
+ include_dir = self.stub_os.path.join(
+ self.sysrt_util.DEFAULT_INCLUDE_DIR,
+ self.sysrt_util.ADDITIONAL_INCLUDE_EXTENSION, 'libtest-suffix')
+ include_dir2 = self.stub_os.path.join(
+ self.sysrt_util.DEFAULT_INCLUDE_DIR,
+ self.sysrt_util.ADDITIONAL_INCLUDE_EXTENSION, 'libtest2-suffix')
+ self.sysroot.should_makedirs = [lib_dir, include_dir, include_dir2]
+ self.sysroot.should_add_file = [
+ (self.stub_os.path.join('libsrc', 'libtest.so'),
+ self.stub_os.path.join(lib_dir, 'libtest-suffix.so')),
+ (self.stub_os.path.join('libsrc', 'libtest2.so'),
+ self.stub_os.path.join(lib_dir, 'libtest2-suffix.so'))]
+ self.sysroot.should_add_dir = [
+ (self.stub_util.GetOSPath(self.stub_util.GetOSVersion(),
+ 'headers/1'),
+ include_dir, True),
+ (self.stub_util.GetOSPath(self.stub_util.GetOSVersion(),
+ 'headers/2'),
+ include_dir, True)]
+ self.sysroot.should_pass_filter = ['file.h', 'h.h', '.h.h',
+ 'longer/path/to/thing.h']
+ self.sysroot.should_fail_filter = ['h.cpp', 'h', 'file.h.tar']
+ f = stubs.StubFile('header line\n'
+ 'libtest, liba libb, headers/1 headers/2\n'
+ 'libtest2, , ')
+ self.stub_open.files['csv_path'] = f
+ self.stub_os.path.should_exist = ['csv_path']
+
+ self.sysrt_util.AddSharedLibsFromCSV('libsrc', 'csv_path', 'suffix')
+ # Make sure everything got done.
+ self.assertEqual(self.sysroot.should_add_file, [])
+ self.assertEqual(self.sysroot.should_add_dir, [])
+ self.assertEqual(self.sysroot.should_write, [])
+
+
+ def test_add_libs_bad_csv(self):
+ f = stubs.StubFile('header line\n'
+ 'has, enough, items\n'
+ 'not, enough items')
+ self.stub_open.files['csv_path'] = f
+ self.stub_os.path.should_exist = ['csv_path']
+ # Error should indicate which line was problematic.
+ self.assertRaisesRegexp(ValueError, 'not, enough items',
+ self.sysrt_util.AddSharedLibsFromCSV,
+ 'libsrc', 'csv_path', 'suffix')
+
+ def test_setup_base(self):
+ self.sysroot.should_makedirs = [self.sysrt_util.DEFAULT_INCLUDE_DIR,
+ self.sysrt_util.DEFAULT_LIB_DIR]
+ def copyformat(src):
+ # pylint: disable=protected-access
+ return self.sysrt_util._FormatForCopy(
+ src, self.sysrt_util.DEFAULT_INCLUDE_DIR)
+
+ # pylint: disable=protected-access
+ (libcxx_src, libcxx_dest) = self.sysrt_util._FormatForCopy(
+ self.sysrt_util.LIBCXX_HEADERS, self.sysrt_util.LIBCXX_INCLUDE_DIR)
+
+ self.sysroot.should_add_dir = [(libcxx_src, libcxx_dest, True)]
+ for (src, recurse, _) in (self.sysrt_util.DEFAULT_INCLUDES +
+ self.sysrt_util.DEFAULT_ARCH_INCLUDES['x86']):
+ (copysrc, copydest) = copyformat(src)
+ self.sysroot.should_add_dir.append((copysrc, copydest, recurse))
+ self.sysroot.should_add_file = [('lib_src/' + default,
+ self.sysrt_util.DEFAULT_LIB_DIR)
+ for default
+ in self.sysrt_util.DEFAULT_SHARED_LIBS]
+ self.sysroot.should_add_file += [
+ ('static_src/' + self.sysrt_util.STATIC_PATH_FORMAT.format(default),
+ self.sysrt_util.DEFAULT_LIB_DIR)
+ for default in self.sysrt_util.DEFAULT_STATIC_LIBS]
+ self.sysroot.should_add_dir.append(('base', '', True))
+ self.stub_shutil.should_move = [
+ (self.sysroot.Path(self.sysrt_util.DEFAULT_LIB_DIR, src),
+ self.sysroot.Path(self.sysrt_util.DEFAULT_LIB_DIR, dest))
+ for (src, dest) in
+ self.sysrt_util.DEFAULT_LIB_RENAMES.iteritems()]
+
+ self.sysrt_util.SetupBaseSysroot('x86', 'lib_src', 'static_src', 'base')
+ # Make sure everything got done.
+ self.assertEqual(self.sysroot.should_add_file, [])
+ self.assertEqual(self.sysroot.should_add_dir, [])
+ self.assertEqual(self.sysroot.should_write, [])
+ self.assertEqual(self.stub_shutil.should_move, [])
diff --git a/cli/lib/environment/toolchain_util.py b/cli/lib/environment/toolchain_util.py
index 1a8e4c2..9f1c81a 100644
--- a/cli/lib/environment/toolchain_util.py
+++ b/cli/lib/environment/toolchain_util.py
@@ -61,83 +61,83 @@ ARCH_TOOL_FLAGS = {
class Error(error.Error):
- pass
+ pass
class GenerationError(Error):
- """Raised when the toolchain fails to generate correctly."""
- description = 'Failed to generate all tools'
+ """Raised when the toolchain fails to generate correctly."""
+ description = 'Failed to generate all tools'
def _ToolFlags(tool, arch):
- """Helper to combine general and arch-specific tool flags."""
- result = []
- if tool in TOOL_FLAGS:
- result += TOOL_FLAGS[tool]
- if arch in ARCH_TOOL_FLAGS and tool in ARCH_TOOL_FLAGS[arch]:
- result += ARCH_TOOL_FLAGS[arch][tool]
- return result
+ """Helper to combine general and arch-specific tool flags."""
+ result = []
+ if tool in TOOL_FLAGS:
+ result += TOOL_FLAGS[tool]
+ if arch in ARCH_TOOL_FLAGS and tool in ARCH_TOOL_FLAGS[arch]:
+ result += ARCH_TOOL_FLAGS[arch][tool]
+ return result
def _GenerateWrapper(src, dest, flags=None):
- """Write a simple wrapper for a tool.
+ """Write a simple wrapper for a tool.
- dest will call src with flags. dest will be an executable file.
+ dest will call src with flags. dest will be an executable file.
- Args:
- src: The original tool to wrap.
- dest: The place to put the wrapper.
- flags: (optional) Flags to include in the wrapper. Default empty list.
+ Args:
+ src: The original tool to wrap.
+ dest: The place to put the wrapper.
+ flags: (optional) Flags to include in the wrapper. Default empty list.
- Raises:
- OSError: There is an error opening or otherwise accessing dest.
- IOError: There is an error writing the wrapper file.
- """
- flags = flags or []
- with open(dest, 'w') as f:
- f.write('#!/bin/sh\n{0} {1} "$@"\n'.format(src, ' '.join(flags)))
- # Make sure the file is executable.
- st = os.stat(dest)
- os.chmod(dest, st.st_mode | stat.S_IEXEC)
+ Raises:
+ OSError: There is an error opening or otherwise accessing dest.
+ IOError: There is an error writing the wrapper file.
+ """
+ flags = flags or []
+ with open(dest, 'w') as f:
+ f.write('#!/bin/sh\n{0} {1} "$@"\n'.format(src, ' '.join(flags)))
+ # Make sure the file is executable.
+ st = os.stat(dest)
+ os.chmod(dest, st.st_mode | stat.S_IEXEC)
def GenerateToolchain(os_version, host, target, output_dir):
- """Generate a toolchain.
-
- Args:
- os_version: OS version to generate toolchain for.
- host: Host architecture to generate toolchain for.
- target: Target architecture to generate toolchain for.
- output_dir: Where to put generated tools.
-
- Raises:
- Error: Not all tools generated properly.
- """
- # Make sure output dir exists.
- if not os.path.isdir(output_dir):
- os.makedirs(output_dir)
-
- # Put together some variables based on host and target.
- existing_tools = util.GetOSPath(os_version,
- EXISTING_TOOLS_FORMAT.format(host_arch=host))
- tool_prefix = os.path.join(existing_tools, ARCH_TOOL_PREFIX[target])
- prefix_len = len(tool_prefix)
-
- # Walk the existing tools, wrapping them all.
- errors = []
- for path in glob.iglob(tool_prefix + '*'):
- # Skip dirs, not that there should be any.
- if not os.path.isfile(path):
- continue
-
- # Otherwise, assume it's a tool and wrap it.
- tool = path[prefix_len:]
- try:
- output_tool = os.path.join(output_dir, tool)
- tool_flags = _ToolFlags(tool, target)
- # Write a simple wrapper.
- _GenerateWrapper(path, output_tool, tool_flags)
- except (IOError, OSError) as e:
- errors.append((tool, e))
-
- if errors:
- raise GenerationError('Failed: {}'.format(errors))
+ """Generate a toolchain.
+
+ Args:
+ os_version: OS version to generate toolchain for.
+ host: Host architecture to generate toolchain for.
+ target: Target architecture to generate toolchain for.
+ output_dir: Where to put generated tools.
+
+ Raises:
+ Error: Not all tools generated properly.
+ """
+ # Make sure output dir exists.
+ if not os.path.isdir(output_dir):
+ os.makedirs(output_dir)
+
+ # Put together some variables based on host and target.
+ existing_tools = util.GetOSPath(
+ os_version, EXISTING_TOOLS_FORMAT.format(host_arch=host))
+ tool_prefix = os.path.join(existing_tools, ARCH_TOOL_PREFIX[target])
+ prefix_len = len(tool_prefix)
+
+ # Walk the existing tools, wrapping them all.
+ errors = []
+ for path in glob.iglob(tool_prefix + '*'):
+ # Skip dirs, not that there should be any.
+ if not os.path.isfile(path):
+ continue
+
+ # Otherwise, assume it's a tool and wrap it.
+ tool = path[prefix_len:]
+ try:
+ output_tool = os.path.join(output_dir, tool)
+ tool_flags = _ToolFlags(tool, target)
+ # Write a simple wrapper.
+ _GenerateWrapper(path, output_tool, tool_flags)
+ except (IOError, OSError) as e:
+ errors.append((tool, e))
+
+ if errors:
+ raise GenerationError('Failed: {}'.format(errors))
diff --git a/cli/lib/environment/toolchain_util_unittest.py b/cli/lib/environment/toolchain_util_unittest.py
index 1ea1c75..cd1d703 100644
--- a/cli/lib/environment/toolchain_util_unittest.py
+++ b/cli/lib/environment/toolchain_util_unittest.py
@@ -26,56 +26,57 @@ from test import stubs
class ToolchainUtilTest(unittest.TestCase):
- def setUp(self):
- self.stub_os = stubs.StubOs()
- self.stub_open = stubs.StubOpen(self.stub_os)
- self.stub_glob = stubs.StubGlob(self.stub_os)
- self.stub_util = util_stub.StubUtil()
+ def setUp(self):
+ self.stub_os = stubs.StubOs()
+ self.stub_open = stubs.StubOpen(self.stub_os)
+ self.stub_glob = stubs.StubGlob(self.stub_os)
+ self.stub_util = util_stub.StubUtil()
- toolchain_util.os = self.stub_os
- toolchain_util.open = self.stub_open.open
- toolchain_util.glob = self.stub_glob
- toolchain_util.util = self.stub_util
+ toolchain_util.os = self.stub_os
+ toolchain_util.open = self.stub_open.open
+ toolchain_util.glob = self.stub_glob
+ toolchain_util.util = self.stub_util
- def test_generate_toolchain(self):
- stub_tools = ['no_flags', 'g++']
- tool_paths = {}
- tool_dests = {}
- for tool in stub_tools:
- tool_paths[tool] = self.stub_util.GetOSPath(
- self.stub_util.GetOSVersion(),
- toolchain_util.EXISTING_TOOLS_FORMAT.format(host_arch='host_arch'),
- toolchain_util.ARCH_TOOL_PREFIX['x86'] + tool)
- self.stub_os.path.should_exist.append(tool_paths[tool])
+ def test_generate_toolchain(self):
+ stub_tools = ['no_flags', 'g++']
+ tool_paths = {}
+ tool_dests = {}
+ for tool in stub_tools:
+ tool_paths[tool] = self.stub_util.GetOSPath(
+ self.stub_util.GetOSVersion(),
+ toolchain_util.EXISTING_TOOLS_FORMAT.format(
+ host_arch='host_arch'),
+ toolchain_util.ARCH_TOOL_PREFIX['x86'] + tool)
+ self.stub_os.path.should_exist.append(tool_paths[tool])
- tool_dests[tool] = self.stub_os.path.join('dest', tool)
- self.stub_os.should_chmod.append((tool_dests[tool], stat.S_IEXEC))
+ tool_dests[tool] = self.stub_os.path.join('dest', tool)
+ self.stub_os.should_chmod.append((tool_dests[tool], stat.S_IEXEC))
- self.stub_os.should_makedirs = ['dest']
- toolchain_util.GenerateToolchain(self.stub_util.GetOSVersion(),
- 'host_arch', 'x86', 'dest')
- # Should have created dest dir.
- self.assertTrue(self.stub_os.path.isdir('dest'))
- for tool in stub_tools:
- # Should have generated the tool file.
- self.assertTrue(self.stub_os.path.isfile(tool_dests[tool]))
- # Should have correctly generated the tool file.
- tool_file = self.stub_open.files[tool_dests[tool]]
- self.assertEqual(len(tool_file.contents), 3)
- # Should invoke sh.
- self.assertEqual(tool_file.contents[0], '#!/bin/sh')
- # Should be a nice file with a trailing newline.
- self.assertEqual(tool_file.contents[2], '')
- # Should point to the original tool.
- self.assertTrue(tool_paths[tool] in tool_file.contents[1])
+ self.stub_os.should_makedirs = ['dest']
+ toolchain_util.GenerateToolchain(self.stub_util.GetOSVersion(),
+ 'host_arch', 'x86', 'dest')
+ # Should have created dest dir.
+ self.assertTrue(self.stub_os.path.isdir('dest'))
+ for tool in stub_tools:
+ # Should have generated the tool file.
+ self.assertTrue(self.stub_os.path.isfile(tool_dests[tool]))
+ # Should have correctly generated the tool file.
+ tool_file = self.stub_open.files[tool_dests[tool]]
+ self.assertEqual(len(tool_file.contents), 3)
+ # Should invoke sh.
+ self.assertEqual(tool_file.contents[0], '#!/bin/sh')
+ # Should be a nice file with a trailing newline.
+ self.assertEqual(tool_file.contents[2], '')
+ # Should point to the original tool.
+ self.assertTrue(tool_paths[tool] in tool_file.contents[1])
- if tool == 'g++':
- # g++ is supposed to get some flags. Make sure those appeared.
- # Note: this is not comprehensive testing of all the flags.
- # Non arch-specific:
- self.assertTrue('-Wformat' in tool_file.contents[1])
- # Arch-specific:
- self.assertTrue('-m32' in tool_file.contents[1])
+ if tool == 'g++':
+ # g++ is supposed to get some flags. Make sure those appeared.
+ # Note: this is not comprehensive testing of all the flags.
+ # Non arch-specific:
+ self.assertTrue('-Wformat' in tool_file.contents[1])
+ # Arch-specific:
+ self.assertTrue('-m32' in tool_file.contents[1])
- # All chmods should have happened.
- self.assertEqual(self.stub_os.should_chmod, [])
+ # All chmods should have happened.
+ self.assertEqual(self.stub_os.should_chmod, [])