-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[CI] Add Python Script for Computing Projects/Runtimes to Test #132634
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
boomanaiden154
merged 6 commits into
main
from
users/boomanaiden154/ci-add-python-script-for-computing-projectsruntimes-to-test
Mar 26, 2025
Merged
Changes from 3 commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,186 @@ | ||
| # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| # See https://llvm.org/LICENSE.txt for license information. | ||
| # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| """Computes the list of projects that need to be tested from a diff. | ||
|
|
||
| Does some things, spits out a list of projects. | ||
| """ | ||
|
|
||
| from collections.abc import Set | ||
| import pathlib | ||
| import platform | ||
| import sys | ||
|
|
||
| PROJECT_DEPENDENCIES = { | ||
| "llvm": set(), | ||
| "clang": {"llvm"}, | ||
| "bolt": {"clang", "lld", "llvm"}, | ||
| "clang-tools-extra": {"clang", "llvm"}, | ||
| "compiler-rt": {"clang", "lld"}, | ||
| "libc": {"clang", "lld"}, | ||
| "openmp": {"clang", "lld"}, | ||
| "flang": {"llvm", "clang"}, | ||
| "lldb": {"llvm", "clang"}, | ||
| "libclc": {"llvm", "clang"}, | ||
| "lld": {"llvm"}, | ||
| "mlir": {"llvm"}, | ||
| "polly": {"llvm"}, | ||
| } | ||
|
|
||
| DEPENDENTS_TO_TEST = { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (same as above somehow)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added a comment here as well on what exactly it does and the intention surrounding it. |
||
| "llvm": {"bolt", "clang", "clang-tools-extra", "lld", "lldb", "mlir", "polly"}, | ||
| "lld": {"bolt", "cross-project-tests"}, | ||
| "clang": {"clang-tools-extra", "compiler-rt", "cross-project-tests"}, | ||
Endilll marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| "clang-tools-extra": {"libc"}, | ||
| "mlir": {"flang"}, | ||
| } | ||
|
|
||
| DEPENDENT_RUNTIMES_TO_TEST = {"clang": {"libcxx", "libcxxabi", "libunwind"}} | ||
Endilll marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| EXCLUDE_LINUX = { | ||
| "cross-project-tests", # Tests are failing. | ||
boomanaiden154 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| "openmp", # https://github.com/google/llvm-premerge-checks/issues/410 | ||
| } | ||
|
|
||
| EXCLUDE_WINDOWS = { | ||
| "cross-project-tests", # Tests are failing. | ||
| "compiler-rt", # Tests are taking too long. | ||
| "openmp", # Does not detect perl installation. | ||
| "libc", # No Windows Support. | ||
| "lldb", # Custom environment requirements. | ||
| "bolt", # No Windows Support. | ||
| } | ||
|
|
||
| EXCLUDE_MAC = { | ||
| "bolt", | ||
| "compiler-rt", | ||
| "cross-project-tests", | ||
| "flang", | ||
| "libc", | ||
| "libcxx", | ||
| "libcxxabi", | ||
| "libunwind", | ||
| "lldb", | ||
| "openmp", | ||
| "polly", | ||
| } | ||
|
|
||
| PROJECT_CHECK_TARGETS = { | ||
| "clang-tools-extra": "check-clang-tools", | ||
| "compiler-rt": "check-compiler-rt", | ||
| "cross-project-tests": "check-cross-project", | ||
| "libcxx": "check-cxx", | ||
| "libcxxabi": "check-cxxabi", | ||
| "libunwind": "check-unwind", | ||
| "lldb": "check-lldb", | ||
| "llvm": "check-llvm", | ||
| "clang": "check-clang", | ||
| "bolt": "check-bolt", | ||
| "lld": "check-lld", | ||
| "flang": "check-flang", | ||
| "libc": "check-libc", | ||
| "lld": "check-lld", | ||
| "lldb": "check-lldb", | ||
| "mlir": "check-mlir", | ||
| "openmp": "check-openmp", | ||
| "polly": "check-polly", | ||
| } | ||
|
|
||
|
|
||
| def _add_dependencies(projects: Set[str]) -> Set[str]: | ||
| projects_with_dependents = set(projects) | ||
| current_projects_count = 0 | ||
| while current_projects_count != len(projects_with_dependents): | ||
| current_projects_count = len(projects_with_dependents) | ||
| for project in list(projects_with_dependents): | ||
| if project not in PROJECT_DEPENDENCIES: | ||
| continue | ||
| projects_with_dependents.update(PROJECT_DEPENDENCIES[project]) | ||
| return projects_with_dependents | ||
|
|
||
|
|
||
| def _compute_projects_to_test(modified_projects: Set[str], platform: str) -> Set[str]: | ||
| projects_to_test = set() | ||
| for modified_project in modified_projects: | ||
| # Skip all projects where we cannot run tests. | ||
| if modified_project not in PROJECT_CHECK_TARGETS: | ||
| continue | ||
| projects_to_test.add(modified_project) | ||
| if modified_project not in DEPENDENTS_TO_TEST: | ||
| continue | ||
| projects_to_test.update(DEPENDENTS_TO_TEST[modified_project]) | ||
| if platform == "Linux": | ||
| for to_exclude in EXCLUDE_LINUX: | ||
| if to_exclude in projects_to_test: | ||
| projects_to_test.remove(to_exclude) | ||
| elif platform == "Windows": | ||
| for to_exclude in EXCLUDE_WINDOWS: | ||
| if to_exclude in projects_to_test: | ||
| projects_to_test.remove(to_exclude) | ||
| elif platform == "Darwin": | ||
| for to_exclude in EXCLUDE_MAC: | ||
| if to_exclude in projects_to_test: | ||
| projects_to_test.remove(to_exclude) | ||
| else: | ||
| raise ValueError("Unexpected platform.") | ||
| return projects_to_test | ||
|
|
||
|
|
||
| def _compute_projects_to_build(projects_to_test: Set[str]) -> Set[str]: | ||
| return _add_dependencies(projects_to_test) | ||
|
|
||
|
|
||
| def _compute_project_check_targets(projects_to_test: Set[str]) -> Set[str]: | ||
| check_targets = set() | ||
| for project_to_test in projects_to_test: | ||
| if project_to_test not in PROJECT_CHECK_TARGETS: | ||
| continue | ||
| check_targets.add(PROJECT_CHECK_TARGETS[project_to_test]) | ||
| return check_targets | ||
|
|
||
|
|
||
| def _compute_runtimes_to_test(projects_to_test: Set[str]) -> Set[str]: | ||
| runtimes_to_test = set() | ||
| for project_to_test in projects_to_test: | ||
| if project_to_test not in DEPENDENT_RUNTIMES_TO_TEST: | ||
| continue | ||
| runtimes_to_test.update(DEPENDENT_RUNTIMES_TO_TEST[project_to_test]) | ||
| return runtimes_to_test | ||
|
|
||
|
|
||
| def _compute_runtime_check_targets(runtimes_to_test: Set[str]) -> Set[str]: | ||
| check_targets = set() | ||
| for runtime_to_test in runtimes_to_test: | ||
| check_targets.add(PROJECT_CHECK_TARGETS[runtime_to_test]) | ||
| return check_targets | ||
|
|
||
|
|
||
| def _get_modified_projects(modified_files: list[str]) -> Set[str]: | ||
| modified_projects = set() | ||
| for modified_file in modified_files: | ||
| modified_projects.add(pathlib.Path(modified_file).parts[0]) | ||
| return modified_projects | ||
|
|
||
|
|
||
| def get_env_variables(modified_files: list[str], platform: str) -> Set[str]: | ||
| modified_projects = _get_modified_projects(modified_files) | ||
| projects_to_test = _compute_projects_to_test(modified_projects, platform) | ||
| projects_to_build = _compute_projects_to_build(projects_to_test) | ||
| projects_check_targets = _compute_project_check_targets(projects_to_test) | ||
| runtimes_to_test = _compute_runtimes_to_test(projects_to_test) | ||
| runtimes_check_targets = _compute_runtime_check_targets(runtimes_to_test) | ||
| return { | ||
| "projects_to_build": ";".join(sorted(projects_to_build)), | ||
| "project_check_targets": " ".join(sorted(projects_check_targets)), | ||
| "runtimes_to_build": ";".join(sorted(runtimes_to_test)), | ||
| "runtimes_check_targets": " ".join(sorted(runtimes_check_targets)), | ||
Keenuts marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| current_platform = platform.system() | ||
| if len(sys.argv) == 2: | ||
| current_platform = sys.argv[1] | ||
| env_variables = get_env_variables(sys.stdin.readlines(), current_platform) | ||
| for env_variable in env_variables: | ||
| print(f"{env_variable}=\"{env_variables[env_variable]}\"") | ||
boomanaiden154 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,166 @@ | ||
| # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| # See https://llvm.org/LICENSE.txt for license information. | ||
| # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| """Does some stuff.""" | ||
|
|
||
| import unittest | ||
|
|
||
| import compute_projects | ||
|
|
||
|
|
||
| class TestComputeProjects(unittest.TestCase): | ||
| def test_llvm(self): | ||
| env_variables = compute_projects.get_env_variables( | ||
| ["llvm/CMakeLists.txt"], "Linux" | ||
| ) | ||
| self.assertEqual( | ||
| env_variables["projects_to_build"], | ||
| "bolt;clang;clang-tools-extra;lld;lldb;llvm;mlir;polly", | ||
| ) | ||
| self.assertEqual( | ||
| env_variables["project_check_targets"], | ||
| "check-bolt check-clang check-clang-tools check-lld check-lldb check-llvm check-mlir check-polly", | ||
| ) | ||
| self.assertEqual( | ||
| env_variables["runtimes_to_build"], "libcxx;libcxxabi;libunwind" | ||
| ) | ||
| self.assertEqual( | ||
| env_variables["runtimes_check_targets"], | ||
| "check-cxx check-cxxabi check-unwind", | ||
| ) | ||
|
|
||
| def test_llvm_windows(self): | ||
| env_variables = compute_projects.get_env_variables( | ||
| ["llvm/CMakeLists.txt"], "Windows" | ||
| ) | ||
| self.assertEqual( | ||
| env_variables["projects_to_build"], | ||
| "clang;clang-tools-extra;lld;llvm;mlir;polly", | ||
| ) | ||
| self.assertEqual( | ||
| env_variables["project_check_targets"], | ||
| "check-clang check-clang-tools check-lld check-llvm check-mlir check-polly", | ||
| ) | ||
| self.assertEqual( | ||
| env_variables["runtimes_to_build"], "libcxx;libcxxabi;libunwind" | ||
| ) | ||
| self.assertEqual( | ||
| env_variables["runtimes_check_targets"], | ||
| "check-cxx check-cxxabi check-unwind", | ||
| ) | ||
|
|
||
| def test_llvm_mac(self): | ||
| env_variables = compute_projects.get_env_variables( | ||
| ["llvm/CMakeLists.txt"], "Darwin" | ||
| ) | ||
| self.assertEqual( | ||
| env_variables["projects_to_build"], | ||
| "clang;clang-tools-extra;lld;llvm;mlir", | ||
| ) | ||
| self.assertEqual( | ||
| env_variables["project_check_targets"], | ||
| "check-clang check-clang-tools check-lld check-llvm check-mlir", | ||
| ) | ||
| self.assertEqual( | ||
| env_variables["runtimes_to_build"], "libcxx;libcxxabi;libunwind" | ||
| ) | ||
| self.assertEqual( | ||
| env_variables["runtimes_check_targets"], | ||
| "check-cxx check-cxxabi check-unwind", | ||
| ) | ||
|
|
||
| def test_clang(self): | ||
| env_variables = compute_projects.get_env_variables( | ||
| ["clang/CMakeLists.txt"], "Linux" | ||
| ) | ||
| self.assertEqual( | ||
| env_variables["projects_to_build"], | ||
| "clang;clang-tools-extra;compiler-rt;lld;llvm", | ||
| ) | ||
| self.assertEqual( | ||
| env_variables["project_check_targets"], | ||
| "check-clang check-clang-tools check-compiler-rt", | ||
| ) | ||
| self.assertEqual( | ||
| env_variables["runtimes_to_build"], "libcxx;libcxxabi;libunwind" | ||
| ) | ||
| self.assertEqual( | ||
| env_variables["runtimes_check_targets"], | ||
| "check-cxx check-cxxabi check-unwind", | ||
| ) | ||
|
|
||
| def test_clang_windows(self): | ||
| env_variables = compute_projects.get_env_variables( | ||
| ["clang/CMakeLists.txt"], "Windows" | ||
| ) | ||
| self.assertEqual( | ||
| env_variables["projects_to_build"], "clang;clang-tools-extra;llvm" | ||
| ) | ||
| self.assertEqual( | ||
| env_variables["project_check_targets"], "check-clang check-clang-tools" | ||
| ) | ||
| self.assertEqual( | ||
| env_variables["runtimes_to_build"], "libcxx;libcxxabi;libunwind" | ||
| ) | ||
| self.assertEqual( | ||
| env_variables["runtimes_check_targets"], | ||
| "check-cxx check-cxxabi check-unwind", | ||
| ) | ||
|
|
||
| def test_bolt(self): | ||
| env_variables = compute_projects.get_env_variables( | ||
| ["bolt/CMakeLists.txt"], "Linux" | ||
| ) | ||
| self.assertEqual(env_variables["projects_to_build"], "bolt;clang;lld;llvm") | ||
| self.assertEqual(env_variables["project_check_targets"], "check-bolt") | ||
| self.assertEqual(env_variables["runtimes_to_build"], "") | ||
| self.assertEqual(env_variables["runtimes_check_targets"], "") | ||
|
|
||
| def test_lldb(self): | ||
| env_variables = compute_projects.get_env_variables( | ||
| ["lldb/CMakeLists.txt"], "Linux" | ||
| ) | ||
| self.assertEqual(env_variables["projects_to_build"], "clang;lldb;llvm") | ||
| self.assertEqual(env_variables["project_check_targets"], "check-lldb") | ||
| self.assertEqual(env_variables["runtimes_to_build"], "") | ||
| self.assertEqual(env_variables["runtimes_check_targets"], "") | ||
|
|
||
| def test_mlir(self): | ||
| env_variables = compute_projects.get_env_variables( | ||
| ["mlir/CMakeLists.txt"], "Linux" | ||
| ) | ||
| self.assertEqual(env_variables["projects_to_build"], "clang;flang;llvm;mlir") | ||
| self.assertEqual( | ||
| env_variables["project_check_targets"], "check-flang check-mlir" | ||
| ) | ||
| self.assertEqual(env_variables["runtimes_to_build"], "") | ||
| self.assertEqual(env_variables["runtimes_check_targets"], "") | ||
|
|
||
| def test_flang(self): | ||
| env_variables = compute_projects.get_env_variables( | ||
| ["flang/CMakeLists.txt"], "Linux" | ||
| ) | ||
| self.assertEqual(env_variables["projects_to_build"], "clang;flang;llvm") | ||
| self.assertEqual(env_variables["project_check_targets"], "check-flang") | ||
| self.assertEqual(env_variables["runtimes_to_build"], "") | ||
| self.assertEqual(env_variables["runtimes_check_targets"], "") | ||
|
|
||
| def test_invalid_subproject(self): | ||
| env_variables = compute_projects.get_env_variables( | ||
| [".ci/compute_projects.py"], "Linux" | ||
| ) | ||
| self.assertEqual(env_variables["projects_to_build"], "") | ||
| self.assertEqual(env_variables["project_check_targets"], "") | ||
| self.assertEqual(env_variables["runtimes_to_build"], "") | ||
| self.assertEqual(env_variables["runtimes_check_targets"], "") | ||
|
|
||
| def test_top_level_file(self): | ||
| env_variables = compute_projects.get_env_variables(["README.md"], "Linux") | ||
| self.assertEqual(env_variables["projects_to_build"], "") | ||
| self.assertEqual(env_variables["project_check_targets"], "") | ||
| self.assertEqual(env_variables["runtimes_to_build"], "") | ||
| self.assertEqual(env_variables["runtimes_check_targets"], "") | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| unittest.main() |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a comment about the content of this? What is this conveying and when you a project include others in its list?
Reading the usage of this, it seems like it is handling transitive dependencies for example, so I assume we should only list direct dependencies?
Also some dependencies are optional (depending on the CMake configuration), so worth giving some idea of what is the intent and the effect (to know when / whether to be conservative or how to exercise judgement).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a comment.
Yes, it handles transitive dependencies automatically (and I made sure to note that in the comment).
The dependencies should match what is required for the configuration int the premerge CI (also mentioned that in the comment).