[libcxx] [llvm] [libc++] Require installing dependencies before running LNT tooling (PR #214020)
Louis Dionne via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 4 10:54:03 PDT 2026
https://github.com/ldionne created https://github.com/llvm/llvm-project/pull/214020
This makes all benchmark-related utilities consistently rely on a virtual environment containing libcxx/utils/requirements.txt instead of some scripts installing their dependencies explicitly, which is duplicate work in most cases.
>From b6c6cd0eaaa57853711e1873e0af59c3b208191f Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Tue, 4 Aug 2026 12:27:20 -0400
Subject: [PATCH] [libc++] Require installing dependencies before running LNT
tooling
This makes all benchmark-related utilities consistently rely on a
virtual environment containing libcxx/utils/requirements.txt instead
of some scripts installing their dependencies explicitly, which is
duplicate work in most cases.
---
.github/workflows/libcxx-benchmark-commit.yml | 8 ++++++++
.github/workflows/libcxx-pr-benchmark.yml | 2 +-
libcxx/utils/ci/lnt/README.md | 4 ++++
libcxx/utils/ci/lnt/run-benchmarks | 18 ++++++++----------
libcxx/utils/ci/lnt/submit-benchmarks | 18 +++++-------------
libcxx/utils/requirements.txt | 1 +
6 files changed, 27 insertions(+), 24 deletions(-)
diff --git a/.github/workflows/libcxx-benchmark-commit.yml b/.github/workflows/libcxx-benchmark-commit.yml
index d2ad03a180cf5..4e925758e0692 100644
--- a/.github/workflows/libcxx-benchmark-commit.yml
+++ b/.github/workflows/libcxx-benchmark-commit.yml
@@ -125,6 +125,12 @@ jobs:
"${COMPILER}" --version
python3 --version
+ - name: Setup virtual environment
+ run: |
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r libcxx/utils/requirements.txt
+
- name: Run the benchmarks
env:
COMMIT: ${{ inputs.commit }}
@@ -132,6 +138,7 @@ jobs:
FILTER: ${{ inputs.filter }}
LNT_MACHINE: ${{ matrix.lnt-machine }}
run: |
+ source .venv/bin/activate
filter_arg=()
if [ -n "${FILTER}" ]; then
filter_arg=(--filter "${FILTER}")
@@ -152,6 +159,7 @@ jobs:
COMMIT: ${{ inputs.commit }}
LNT_URL: ${{ inputs.lnt-url }}
run: |
+ source .venv/bin/activate
libcxx/utils/ci/lnt/submit-benchmarks \
--lnt-url "${LNT_URL}" \
--test-suite libcxx \
diff --git a/.github/workflows/libcxx-pr-benchmark.yml b/.github/workflows/libcxx-pr-benchmark.yml
index 92668a2f79f6c..ef1bdc21d33a5 100644
--- a/.github/workflows/libcxx-pr-benchmark.yml
+++ b/.github/workflows/libcxx-pr-benchmark.yml
@@ -146,7 +146,7 @@ jobs:
run: |
python3 -m venv .venv
source .venv/bin/activate
- python -m pip install -r libcxx/utils/requirements.txt
+ pip install -r libcxx/utils/requirements.txt
- name: Build the baseline and the candidate
run: |
diff --git a/libcxx/utils/ci/lnt/README.md b/libcxx/utils/ci/lnt/README.md
index ac5cbc11f4c40..767e9cd1b692f 100644
--- a/libcxx/utils/ci/lnt/README.md
+++ b/libcxx/utils/ci/lnt/README.md
@@ -8,6 +8,10 @@ is where libc++'s pre-defined LNT bot configurations are defined. To benchmark s
commits:
```
+python3 -m venv .venv
+source .venv/bin/activate
+pip install -r libcxx/utils/requirements.txt
+
libcxx/utils/ci/lnt/run-benchbot --llvm-root <monorepo> <builder> -- <commit1> <commit2> ...
```
diff --git a/libcxx/utils/ci/lnt/run-benchmarks b/libcxx/utils/ci/lnt/run-benchmarks
index 2fd53008cae72..6b454571617b8 100755
--- a/libcxx/utils/ci/lnt/run-benchmarks
+++ b/libcxx/utils/ci/lnt/run-benchmarks
@@ -14,6 +14,7 @@ import logging
import os
import pathlib
import platform
+import shutil
import subprocess
import sys
import tempfile
@@ -68,7 +69,8 @@ def dict_to_params(d):
def main(argv):
parser = argparse.ArgumentParser(
prog='run-benchmarks',
- description='Benchmark libc++ at the given commit and produce a LNT JSON report.')
+ description='Benchmark libc++ at the given commit and produce a LNT JSON report.',
+ epilog='This script depends on the modules listed in `libcxx/utils/requirements.txt`.')
parser.add_argument('--benchmark-commit', type=str, required=True,
help='The SHA representing the version of the library to benchmark.')
parser.add_argument('--test-suite-commit', type=str, required=True,
@@ -127,16 +129,16 @@ def main(argv):
if enforce_success:
raise
- # Fail fast before doing any expensive work: refuse to overwrite existing results or artifacts.
+ # Fail fast before doing any expensive work: refuse to overwrite existing results or artifacts, and
+ # check dependencies.
if args.output.exists():
sys.exit(f'error: output report {args.output} already exists; not overwriting it')
if args.build_dir is not None and args.build_dir.exists():
sys.exit(f'error: build directory {args.build_dir} already exists; not overwriting it')
+ if shutil.which('lnt') is None:
+ sys.exit('error: cannot find `lnt`; install libcxx/utils/requirements.txt')
with contextlib.ExitStack() as stack:
- # LNT tooling is throwaway: always install it into a temporary directory.
- venv = pathlib.Path(stack.enter_context(tempfile.TemporaryDirectory()))
-
# The build artifacts are kept in --build-dir when it is given, and stored in a temporary directory
# otherwise.
if args.build_dir is not None:
@@ -147,10 +149,6 @@ def main(argv):
artifacts.mkdir(parents=True, exist_ok=True)
logging.info(f'Storing build artifacts in {artifacts}')
- logging.info('Installing LNT')
- run(['python3', '-m', 'venv', venv])
- run([venv / 'bin/pip', 'install', 'llvm-lnt'])
-
logging.info(f'Building libc++ at commit {args.benchmark_commit}')
build_cmd = [args.git_repo / 'libcxx/utils/build-at-commit',
'--git-repo', args.git_repo,
@@ -188,7 +186,7 @@ def main(argv):
logging.info('Creating JSON report for LNT')
order = len(subprocess.check_output(['git', '-C', args.git_repo, 'rev-list', args.benchmark_commit]).splitlines())
- importreport = [venv / 'bin/lnt', 'importreport', '--order', str(order), '--machine', args.machine]
+ importreport = ['lnt', 'importreport', '--order', str(order), '--machine', args.machine]
for arg in dict_to_params(gather_run_information(args)):
importreport += ['--run-info', arg]
for arg in dict_to_params(gather_machine_information(args)):
diff --git a/libcxx/utils/ci/lnt/submit-benchmarks b/libcxx/utils/ci/lnt/submit-benchmarks
index 5f25e6fef9fc3..6a01ce67e2b96 100755
--- a/libcxx/utils/ci/lnt/submit-benchmarks
+++ b/libcxx/utils/ci/lnt/submit-benchmarks
@@ -12,13 +12,13 @@ import logging
import pathlib
import subprocess
import sys
-import tempfile
def main(argv):
parser = argparse.ArgumentParser(
prog='submit-benchmarks',
- description='Submit a LNT JSON report to a LNT server.')
+ description='Submit a LNT JSON report to a LNT server.',
+ epilog='This script depends on the modules listed in `libcxx/utils/requirements.txt`.')
parser.add_argument('report', type=pathlib.Path,
help='Path to the LNT JSON report to submit.')
parser.add_argument('--lnt-url', type=str, required=True,
@@ -55,17 +55,9 @@ def main(argv):
sys.stderr.write(e.stderr.decode())
raise
- with tempfile.TemporaryDirectory() as tmp:
- tmp = pathlib.Path(tmp)
-
- logging.info('Installing LNT')
- run(['python3', '-m', 'venv', tmp / '.venv'])
- run([tmp / '.venv/bin/pip', 'install', 'llvm-lnt'])
-
- logging.info(f'Submitting results to {args.lnt_url}')
- submission_url = f'{args.lnt_url}/db_default/v4/{args.test_suite}/submitRun'
- run([tmp / '.venv/bin/lnt', 'submit', '--ignore-regressions', '--merge', 'append',
- submission_url, args.report.resolve()])
+ logging.info(f'Submitting results to {args.lnt_url}')
+ submission_url = f'{args.lnt_url}/db_default/v4/{args.test_suite}/submitRun'
+ run(['lnt', 'submit', '--ignore-regressions', '--merge', 'append', submission_url, args.report.resolve()])
if __name__ == '__main__':
diff --git a/libcxx/utils/requirements.txt b/libcxx/utils/requirements.txt
index 775a2c074c448..4c4da17e4c71c 100644
--- a/libcxx/utils/requirements.txt
+++ b/libcxx/utils/requirements.txt
@@ -1,5 +1,6 @@
click
GitPython
+llvm-lnt
numpy
pandas
plotly
More information about the llvm-commits
mailing list