aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiana Picus <diana.picus@linaro.org>2017-05-05 22:26:49 +0200
committerDiana Picus <diana.picus@linaro.org>2017-05-12 12:41:30 +0200
commit81089dbdf90268900305b3dd0cb5997879fd7c1f (patch)
tree61d9c9fd02880f844d80d0ea62c1aff9f5652015
parent3d1a30130a581e68afdbc027c82c5b1cd662ea6e (diff)
downloadlinaro-scripts-81089dbdf90268900305b3dd0cb5997879fd7c1f.tar.gz
Separate the repos from the environments
Before this patch, we had an LLVM_ROOT directory which contained the repos and a series of environments (worktrees + build dicretories). However, there is no good reason to have such a rigid layout, and in fact it prevents us from sharing the repos in any meaningful way. This patch removes LLVM_ROOT and instead introduces two command line parameters, repos and env, which represent the path to the directory containing the LLVM repositories and respectively the path to the environment that we intend to modify. The two paths may be completely independent. A side effect of this is that we can now also have different environments in different, unrelated locations (whereas previously they had to be siblings in LLVM_ROOT). For the time being, both parameters are compulsory (not only for llvm-projects, but for all subcommands). There may be situations where we can get away with only one of them (e.g. `llvm-projs <env>`, which just lists the projects enabled in the given <env> - it does not need to know where the repos are in order to do this). There may also be situations where one of them doesn't make any sense at all (e.g. `llvm-prepare`, which is not implemented yet in python, only needs the path to the repos and it would not know what to do with an environment). Making them optional would require some additional validation logic as well as more tests, and it feels a bit early on to introduce all that. It would be nice to have at least one or 2 more subcommands implemented before we invest time in it. Change-Id: Ibc1321d18476c2c4a65b5b05ca3fce3467d72fc3
-rwxr-xr-xhelpers/llvm-projs10
-rw-r--r--scripts/llvm.py28
-rw-r--r--tests/cli/testllvmprojects.py321
3 files changed, 238 insertions, 121 deletions
diff --git a/helpers/llvm-projs b/helpers/llvm-projs
index ae8ac22..bbcaf0a 100755
--- a/helpers/llvm-projs
+++ b/helpers/llvm-projs
@@ -46,13 +46,14 @@ llvmtool=$progdir/../scripts/llvm.py
# Grab the environment name from $LLVM_SRC
. llvm-common
verify_env
-env=$(basename $(dirname $LLVM_SRC))
+repos=$LLVM_ROOT/repos
+env=$(dirname $LLVM_SRC)
# No args, list
if [ "$1" = "" ]; then
echo "Use $prog -h for options"
echo
- safe_run python3 $llvmtool $env projects
+ safe_run python3 $llvmtool --repos $repos --env $env projects
exit
fi
@@ -102,7 +103,7 @@ case $opt in
shift
;;
list)
- python $llvmtool projects
+ safe_run python3 $llvmtool --repos $repos --env $env projects
exit
;;
-h)
@@ -200,7 +201,6 @@ update "libcxxabi" $libcxxabi
update "libcxx" $libcxx
update "compiler-rt" $rt
update "clang" $clang
-update "clang-tools-extra" $clang_extra
if [ "$add" != "" ]; then
add="-a $add"
@@ -210,4 +210,4 @@ if [ "$remove" != "" ]; then
remove="-r $remove"
fi
-safe_run python3 $llvmtool $env projects $add $remove
+safe_run python3 $llvmtool --repos $repos --env $env projects $add $remove
diff --git a/scripts/llvm.py b/scripts/llvm.py
index 13e5de6..829c720 100644
--- a/scripts/llvm.py
+++ b/scripts/llvm.py
@@ -20,24 +20,9 @@ def die(message, config_to_dump=None):
exit(1)
-def get_llvm_root():
- """Get the path to the LLVM root, which contains the repos as well as all
- the work environments."""
- return os.environ["LLVM_ROOT"]
-
-
def get_worktree_root(env):
- """
- Get the path to the LLVM worktree corresponding to env. The value will be
- based on the LLVM root.
- """
- return os.path.join(get_llvm_root(), env, "llvm")
-
-# Figure out the path to the LLVM repos
-if "LLVM_ROOT" not in os.environ:
- die("Please, define $LLVM_ROOT to point to the root\n"
- "path where the worktree setup should be performed")
-llvm_repos_root = os.path.join(get_llvm_root(), "repos")
+ """Get the path to the LLVM worktree corresponding to env."""
+ return os.path.join(env, "llvm")
def dump_config(config):
@@ -58,6 +43,7 @@ def projects(args):
proj = Proj()
llvm_worktree_root = get_worktree_root(args.env)
+ llvm_repos_root = args.repos
config = LLVMSourceConfig(proj, llvm_worktree_root)
if not args.add and not args.remove:
@@ -87,7 +73,13 @@ def projects(args):
valid_subprojects = list(LLVMSubproject.get_all_subprojects().keys())
options = ArgumentParser(formatter_class=RawTextHelpFormatter)
-options.add_argument('env', help="The environment to update.")
+options.add_argument(
+ '--env',
+ required=True,
+ help="Path to the environment to update.")
+options.add_argument(
+ '--repos', required=True,
+ help="Path to the directory containing the repositories for all LLVM subprojects.")
subcommands = options.add_subparsers()
diff --git a/tests/cli/testllvmprojects.py b/tests/cli/testllvmprojects.py
index 8374aff..c0c1f26 100644
--- a/tests/cli/testllvmprojects.py
+++ b/tests/cli/testllvmprojects.py
@@ -81,6 +81,36 @@ class Testllvmprojs(unittest.TestCase):
return subprocess.check_call(*args, **kwargs)
@classmethod
+ def llvm_projects(cls, *args, **kwargs):
+ """
+ Build a list representing a llvm projects subcommand with the given
+ args. Unless otherwise specified in kwargs, this uses the values for
+ repos and env that it finds in cls.
+ """
+ command = [cls.python, cls.script]
+
+ repos = cls.repos
+ if "repos" in kwargs:
+ repos = kwargs["repos"]
+ if repos:
+ command.append("--repos")
+ command.append(repos)
+
+ env = cls.env
+ if "env" in kwargs:
+ env = kwargs["env"]
+ if env:
+ command.append("--env")
+ command.append(env)
+
+ command.append("projects")
+
+ if len(args):
+ command.extend(args)
+
+ return command
+
+ @classmethod
def setUpClass(cls):
"""Create the file structure and environment that llvmprojs expects"""
cls.llvm_root = mkdtemp()
@@ -99,17 +129,14 @@ class Testllvmprojs(unittest.TestCase):
@classmethod
def setUp(cls):
- cls.env = "src" + str(uuid4())
- cls.llvm_src = os.path.join(cls.llvm_root, cls.env, "llvm")
+ cls.env = os.path.join(cls.llvm_root, "env" + str(uuid4()))
+ cls.llvm_src = os.path.join(cls.env, "llvm")
# Create LLVM worktree
cls.branch = "br" + str(uuid4())
cls.__add_worktree(cls.__get_subproj_repo("llvm"), cls.llvm_src,
cls.branch)
- # Set up the environment variables
- os.environ["LLVM_ROOT"] = cls.llvm_root
-
@classmethod
def tearDown(cls):
# Clean up the directories where we might have added subprojects.
@@ -128,25 +155,86 @@ class Testllvmprojs(unittest.TestCase):
with cd(repopath):
cls.run_quietly(["git", "worktree", "prune"])
+ def test_repos_arg_is_compulsory(self):
+ """
+ Test that we must pass in the repos for various combinations of input
+ args.
+ """
+ with self.assertRaises(subprocess.CalledProcessError) as context:
+ self.run_with_output(self.llvm_projects(repos=None))
+
+ self.assertRegex(
+ str(context.exception.output),
+ "(.*\n)*.*the following arguments are required:(.*)--repos(.*\n)*")
+
+ with self.assertRaises(subprocess.CalledProcessError) as context:
+ self.run_with_output(
+ self.llvm_projects(
+ "--add", "clang", repos=None))
+
+ self.assertRegex(
+ str(context.exception.output),
+ "(.*\n)*.*the following arguments are required:(.*)--repos(.*\n)*")
+
+ with self.assertRaises(subprocess.CalledProcessError) as context:
+ self.run_with_output(
+ self.llvm_projects(
+ "--remove",
+ "clang",
+ repos=None))
+
+ self.assertRegex(
+ str(context.exception.output),
+ "(.*\n)*.*the following arguments are required:(.*)--repos(.*\n)*")
+
+ def test_env_arg_is_compulsory(self):
+ """
+ Test that we must pass in the environment for various combinations of
+ input args.
+ """
+ with self.assertRaises(subprocess.CalledProcessError) as context:
+ self.run_with_output(self.llvm_projects(env=None))
+
+ self.assertRegex(
+ str(context.exception.output),
+ "(.*\n)*.*the following arguments are required:(.*)--env(.*\n)*")
+
+ with self.assertRaises(subprocess.CalledProcessError) as context:
+ self.run_with_output(
+ self.llvm_projects(
+ "--add", "clang", env=None))
+
+ self.assertRegex(
+ str(context.exception.output),
+ "(.*\n)*.*the following arguments are required:(.*)--env(.*\n)*")
+
+ with self.assertRaises(subprocess.CalledProcessError) as context:
+ self.run_with_output(
+ self.llvm_projects(
+ "--remove", "clang", env=None))
+
+ self.assertRegex(
+ str(context.exception.output),
+ "(.*\n)*.*the following arguments are required:(.*)--env(.*\n)*")
+
def test_dump_empty_config(self):
"""
Test that we're correctly dumping an empty configuration (i.e. no
projects linked) when running llvmprojs without arguments.
"""
- output = self.run_with_output(
- [self.python, self.script, self.env, "projects"])
+ output = self.run_with_output(self.llvm_projects())
self.assertRegex(output, "Projects linked:.*\n.*none.*")
def test_add_remove_subprojects(self):
"""
Test that we can add and remove one or several subprojects.
"""
- output = self.run_with_output(
- [self.python, self.script, self.env, "projects", "--add", "clang"])
+ output = self.run_with_output(self.llvm_projects("--add", "clang"))
self.assertRegex(output, "Projects linked:.*\n.*clang.*")
- output = self.run_with_output([self.python, self.script, self.env, "projects",
- "--add", "libcxx", "lldb"])
+ output = self.run_with_output(
+ self.llvm_projects(
+ "--add", "libcxx", "lldb"))
self.assertRegex(
output,
"Projects linked:.*\n" +
@@ -154,15 +242,15 @@ class Testllvmprojs(unittest.TestCase):
".*libcxx.*\n" +
".*lldb.*")
- output = self.run_with_output(
- [self.python, self.script, self.env, "projects", "--remove", "libcxx"])
+ output = self.run_with_output(self.llvm_projects("--remove", "libcxx"))
self.assertRegex(output,
"Projects linked:.*\n" +
".*clang.*\n" +
".*lldb.*")
- output = self.run_with_output([self.python, self.script, self.env, "projects",
- "--remove", "clang", "lldb"])
+ output = self.run_with_output(
+ self.llvm_projects(
+ "--remove", "clang", "lldb"))
self.assertRegex(output,
"Projects linked:.*\n" +
".*none.*")
@@ -173,20 +261,19 @@ class Testllvmprojs(unittest.TestCase):
subprojects.
"""
with self.assertRaises(subprocess.CalledProcessError) as context:
- self.run_with_output([self.python, self.script, self.env, "projects",
- "--add", "inventedsubproject"])
+ self.run_with_output(
+ self.llvm_projects(
+ "--add", "inventedsubproject"))
self.assertRegex(
str(context.exception.output),
"(.*\n)*.*invalid choice:.*inventedsubproject(.*\n)*")
with self.assertRaises(subprocess.CalledProcessError) as context:
- self.run_with_output([self.python,
- self.script,
- self.env,
- "projects",
- "--remove",
- "inventedsubproject"])
+ self.run_with_output(
+ self.llvm_projects(
+ "--remove",
+ "inventedsubproject"))
self.assertRegex(
str(context.exception.output),
@@ -197,15 +284,17 @@ class Testllvmprojs(unittest.TestCase):
Test that we don't crash when trying to add / remove the same subproject
twice with the same command.
"""
- output = self.run_with_output([self.python, self.script, self.env, "projects",
- "--add", "clang", "lld", "clang"])
+ output = self.run_with_output(
+ self.llvm_projects(
+ "--add", "clang", "lld", "clang"))
self.assertRegex(output,
"Projects linked:.*\n" +
".*clang.*\n" +
".*lld.*")
- output = self.run_with_output([self.python, self.script, self.env, "projects",
- "--remove", "lld", "lld", "clang"])
+ output = self.run_with_output(
+ self.llvm_projects(
+ "--remove", "lld", "lld", "clang"))
self.assertRegex(output,
"Projects linked:.*\n" +
".*none.*")
@@ -224,14 +313,14 @@ class Testllvmprojs(unittest.TestCase):
os.path.join(self.llvm_src, "projects", "compiler-rt"),
self.branch)
- output = self.run_with_output(
- [self.python, self.script, self.env, "projects", "--add", "clang"])
+ output = self.run_with_output(self.llvm_projects("--add", "clang"))
self.assertRegex(output,
"Projects linked:.*\n" +
".*clang.*")
- output = self.run_with_output([self.python, self.script, self.env, "projects",
- "--add", "compiler-rt", "lld"])
+ output = self.run_with_output(
+ self.llvm_projects(
+ "--add", "compiler-rt", "lld"))
self.assertRegex(
output,
"Projects linked:.*\n" +
@@ -239,14 +328,9 @@ class Testllvmprojs(unittest.TestCase):
".*compiler-rt.*\n" +
".*lld.*")
- output = self.run_with_output([self.python,
- self.script,
- self.env,
- "projects",
- "--remove",
- "lldb",
- "libcxx",
- "lld"])
+ output = self.run_with_output(
+ self.llvm_projects(
+ "--remove", "lldb", "libcxx", "lld"))
self.assertRegex(
output,
"Projects linked:.*\n" +
@@ -260,14 +344,12 @@ class Testllvmprojs(unittest.TestCase):
"""
# Try the really basic case and make sure we're not touching anything
with self.assertRaises(subprocess.CalledProcessError) as context:
- self.run_with_output([self.python,
- self.script,
- self.env,
- "projects",
- "--add",
- "clang",
- "--remove",
- "clang"])
+ self.run_with_output(
+ self.llvm_projects(
+ "--add",
+ "clang",
+ "--remove",
+ "clang"))
self.assertRegex(
str(context.exception.output),
@@ -285,17 +367,15 @@ class Testllvmprojs(unittest.TestCase):
self.branch)
with self.assertRaises(subprocess.CalledProcessError) as context:
- self.run_with_output([self.python,
- self.script,
- self.env,
- "projects",
- "--add",
- "clang",
- "lld",
- "libcxx",
- "--remove",
- "lld",
- "libcxx"])
+ self.run_with_output(
+ self.llvm_projects(
+ "--add",
+ "clang",
+ "lld",
+ "libcxx",
+ "--remove",
+ "lld",
+ "libcxx"))
self.assertRegex(
str(context.exception.output),
"(.*\n)*" +
@@ -317,59 +397,104 @@ class Testllvmprojs(unittest.TestCase):
Test that we can have multiple --add and --remove options in the same
command and that only the last one of each kind matters.
"""
- output = self.run_with_output([self.python,
- self.script,
- self.env,
- "projects",
- "--add",
- "libcxxabi",
- "--remove",
- "lld",
- "lldb",
- "--add",
- "clang",
- "libcxx",
- "--remove",
- "libunwind"])
+ output = self.run_with_output(
+ self.llvm_projects(
+ "--add",
+ "libcxxabi",
+ "--remove",
+ "lld",
+ "lldb",
+ "--add",
+ "clang",
+ "libcxx",
+ "--remove",
+ "libunwind"))
self.assertRegex(output,
"Projects linked:.*\n" +
".*clang.*\n" +
".*libcxx.*\n")
- output = self.run_with_output([self.python,
- self.script,
- self.env,
- "projects",
- "--add",
- "libunwind",
- "libcxxabi",
- "--remove",
- "clang",
- "libcxx",
- "--add",
- "compiler-rt",
- "--remove",
- "libcxxabi"])
+ output = self.run_with_output(
+ self.llvm_projects(
+ "--add",
+ "libunwind",
+ "libcxxabi",
+ "--remove",
+ "clang",
+ "libcxx",
+ "--add",
+ "compiler-rt",
+ "--remove",
+ "libcxxabi"))
self.assertRegex(output,
"Projects linked:.*\n" +
".*clang.*\n" +
".*compiler-rt.*\n" +
".*libcxx.*\n")
- output = self.run_with_output([self.python,
- self.script,
- self.env,
- "projects",
- "--add",
- "libcxx",
- "--remove",
- "lld",
- "--add",
- "lld",
- "--remove",
- "libcxx"])
+ output = self.run_with_output(
+ self.llvm_projects(
+ "--add",
+ "libcxx",
+ "--remove",
+ "lld",
+ "--add",
+ "lld",
+ "--remove",
+ "libcxx"))
self.assertRegex(output,
"Projects linked:.*\n" +
".*clang.*\n" +
".*compiler-rt.*\n" +
".*lld.*\n")
+
+ def test_different_env(self):
+ """
+ Test that we can have different environments in completely different
+ paths and they don't interfere when we try to add/remove projects.
+ """
+ # Create a separate environment
+ new_env = mkdtemp()
+ new_branch = "br" + str(uuid4())
+ self.__add_worktree(self.__get_subproj_repo("llvm"),
+ os.path.join(new_env, "llvm"), new_branch)
+
+ # Check that we start with a clean slate in both the new environment and
+ # the one that's already set up
+ output = self.run_with_output(self.llvm_projects())
+ self.assertRegex(output, "Projects linked:.*\n.*none.*")
+
+ output = self.run_with_output(self.llvm_projects(env=new_env))
+ self.assertRegex(output, "Projects linked:.*\n.*none.*")
+
+ # Make sure that adding projects works
+ output = self.run_with_output(
+ self.llvm_projects(
+ "--add", "clang", "lld"))
+ self.assertRegex(output, "Projects linked:.*\n.*clang.*\n.*lld.*\n")
+
+ output = self.run_with_output(
+ self.llvm_projects(
+ "--add",
+ "libcxx",
+ "libcxxabi",
+ env=new_env))
+ self.assertRegex(output,
+ "Projects linked:.*\n.*libcxx.*\n.*libcxxabi.*\n.*")
+
+ output = self.run_with_output(self.llvm_projects())
+ self.assertRegex(output, "Projects linked:.*\n.*clang.*\n.*lld.*\n")
+
+ # Make sure that removing projects works
+ output = self.run_with_output(self.llvm_projects("--remove", "lld"))
+ self.assertRegex(output, "Projects linked:.*\n.*clang.*\n")
+
+ output = self.run_with_output(self.llvm_projects("--remove", "libcxx",
+ env=new_env))
+ self.assertRegex(output,
+ "Projects linked:.*\n.*libcxxabi.*\n.*")
+
+ output = self.run_with_output(self.llvm_projects())
+ self.assertRegex(output, "Projects linked:.*\n.*clang.*\n")
+
+ shutil.rmtree(new_env)