Skip to content

cmake: add native clang-tidy support for tests, with concatenated sources#20667

Closed
vszakats wants to merge 12 commits intocurl:masterfrom
vszakats:ctidy10singletidy
Closed

cmake: add native clang-tidy support for tests, with concatenated sources#20667
vszakats wants to merge 12 commits intocurl:masterfrom
vszakats:ctidy10singletidy

Conversation

@vszakats
Copy link
Member

@vszakats vszakats commented Feb 22, 2026

Tests are build in "unity"-style, by including sources into an umbrella
C files (similar to how CMake unity works). This does not play well with
clang-tidy, which seems to unconditionally ignore C sources included
like this. To fix it, curl's CMake implements a manual clang-tidy
support for tests, which compiles sources one-by-one, while also making
sure sources compile cleanly standalone (e.g. all sources need to
include first.h). The manual clang-tidy implementation is fragile, and
performance, in particular when targeting Windows, is abysmal.

This patch introduces an alternate solution, enabled by the
_CURL_TESTS_CONCAT=ON option. In this mode, umbrella sources include
the actual sources instead of #including them. Allowing to use CMake's
built-in clang-tidy support to compile them, with clang-tidy actually
checking the sources. Making the manual clang-tidy support unnecessary.
In the Windows CI job it results in a 4x performance improvement (4m →
1m), making it practical to run clang-tidy on tests on Windows, in CI.

The main downside is that clang-tidy doesn't understand the #line
directive. Meaning issues found show the wrong filename and line number
next to them. It's not impossible to locate errors this way, but also
not convenient.

Minor/potential downside is that the concatenated source needs to be
reassembled each time an original source is updated. This may result in
more copying on the disk when used in local development. The largest
source is 1.4MB, so probably not a show-stopper on most machines.

Another is the complexity of maintaining two methods in parallel, which
may be necessary till clang-tidy understands #line:
llvm/llvm-project#62405

This solution may in theory also enable adding clang-tidy support for
tests in autotools, though I haven't tried.

Targeted for curl CI for now, and used in a GHA/windows job. 100%
experimental, not recommended outside these.


https://github.com/curl/curl/pull/20667/files?w=1


@vszakats vszakats marked this pull request as draft February 22, 2026 00:45
vszakats added a commit that referenced this pull request Feb 22, 2026
Instead of globally disabling unity for all targets when clang-tidy is
enabled.

After this patch `CMAKE_UNITY_BUILD=ON` is honored for:
- static libcurl when building both static and shared separately.
- libcurlu and libcurltool internal libraries when building the test
  target.

While keeping unity disabled for the libcurl build pass running
clang-tidy, and the curl tool, also running clang-tidy.

To make clang-tidy-enabled builds finish faster when unity mode is
enabled, yet performs the same clang-tidy checks as before this patch.

Effect on:
- GHA/macos: core build: same, buils tests 5-12 seconds faster,
  with steps going down from 259 to 25.

  52s: https://github.com/curl/curl/actions/runs/22279958340/job/64448913325 ->
  47s: https://github.com/curl/curl/actions/runs/22279873606/job/64448710743

- GHA/windows (not enabled): it'd save about 1 minute, bringing total
  time barely below 10m, still one of the slowest jobs overall.
  (#20667 is trying a way for 4x speed-up (with a drawback)).

  5m21s: https://github.com/curl/curl/actions/runs/22222907068/job/64284556852 ->
  4m26s: https://github.com/curl/curl/actions/runs/22281033369/job/64451601548

Closes #20670
vszakats added a commit that referenced this pull request Feb 23, 2026
Backtrack on previous change that aimed to solve the wrong `share.h`
being included. It turns out it did not fix this issue. At the same time
it introduced relative header filenames and the need to include the same
headers differently depending on the source files' location, reducing
readability and editability.

Replace this method by re-adding curl's lib source directory to the
header path and addressing headers by the their full, relative name to
that base directory. Aligning with this method already used in src and
tests.

With these advantages:
- makes includes easier to read, recognize, grep, sort, write, and copy
  between sources,
- syncs the way these headers are included across curl components,
- avoids the ambiguity between system `schannel.h`, `rustls.h` vs.
  local headers using the same names in `lib/vtls`,
- silences clang-tidy `readability-duplicate-include` checker, which
  detects the above issue,
  Ref: https://clang.llvm.org/extra/clang-tidy/checks/readability/duplicate-include.html
- possibly silences TIOBE coding standard warnings:
  `6.10.2.a: Don't use relative paths in #include statements.`
- long shot: it works well with concatenated test sources, for
  clang-tidy-friendly custom unity builds. Ref: #20667

Slight downside: it's not enforced.

If there happens to be a collision between a local `lib/*.h` header and
a system one, the solution is to rename (possibly with its `.c`
counterpart) into the `curl_` namespace. This is also the method used by
curl in the past.

Also:
- curlx/inet_pton: reduce scope of an include.
- toolx/tool_time: apply this to an include, and update VS project
  files accordingly. Also dropping unnecessary lib/curlx header path.
- clang-tidy: enable `readability-duplicate-include`.

Follow-up to 3887069 #19676
Follow-up to 625f2c1 #16991 #16949

Closes #20623
@vszakats vszakats changed the title [TEST] cmake: try native clang-tidy support for tests, with embedding cmake: add native clang-tidy support for tests, with concatenated sources Feb 23, 2026
@vszakats vszakats marked this pull request as ready for review February 23, 2026 19:15
@vszakats vszakats closed this in 39542f0 Feb 25, 2026
@vszakats vszakats deleted the ctidy10singletidy branch February 25, 2026 16:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

1 participant