Pin clang-format 21.1.2 for OSS formatting (#58001)

Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58001

The existing npm `clang-format` wrapper bundles LLVM 15, causing `yarn clang-format` to disagree with the formatting of checked-in headers.

Replace it with checksum-pinned DotSlash artifacts for `clang-format` 21.1.2 across Linux, macOS, and Windows. Add a chunked formatting runner and remove the obsolete npm dependency. The runner skips generated sources and ignores dirsynchronized or vendored subtrees that maintain their own formatting.

Changelog: [Internal]

Reviewed By: christophpurrer

Differential Revision: D116500359

fbshipit-source-id: 2141bee22ed2b712aae1637a1f052db23535bbb0
This commit is contained in:
Peter Abbondanzo
2026-08-19 09:41:46 -07:00
committed by meta-codesync[bot]
parent 0c86952e40
commit 22e0eaf4e7
5 changed files with 157 additions and 16 deletions
+6
View File
@@ -0,0 +1,6 @@
packages/react-native/React/I18n/FBXXHashUtils.h
packages/react-native/ReactAndroid/src/main/jni/first-party/yogajni/**
packages/react-native/ReactAndroid/src/main/jni/third-party/**
packages/react-native/ReactCommon/**/platform/windows/third-party/**
packages/react-native/ReactCommon/jsi/jsi/**
packages/react-native/ReactCommon/yoga/**
+1 -2
View File
@@ -9,7 +9,7 @@
"build-android": "./gradlew :packages:react-native:ReactAndroid:build",
"build": "node ./scripts/build/build.js",
"build-types": "node ./scripts/js-api/build-types",
"clang-format": "clang-format -i --glob=*/**/*.{h,cpp,m,mm}",
"clang-format": "node ./scripts/clang-format.js",
"clean": "node ./scripts/build/clean.js",
"cxx-api-build": "python -m scripts.cxx-api.parser",
"cxx-api-validate": "python -m scripts.cxx-api.parser --validate",
@@ -70,7 +70,6 @@
"babel-plugin-minify-dead-code-elimination": "^0.5.2",
"babel-plugin-transform-define": "^2.1.4",
"babel-plugin-transform-flow-enums": "^0.0.2",
"clang-format": "^1.8.0",
"connect": "^3.6.5",
"debug": "^4.4.0",
"deep-equal": "1.1.1",
+77
View File
@@ -0,0 +1,77 @@
#!/usr/bin/env dotslash
// Copyright (c) Meta Platforms, Inc. and affiliates.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
{
"name": "clang-format 21.1.2",
"platforms": {
"linux-aarch64": {
"size": 1725525,
"hash": "sha256",
"digest": "f66d2bcf98df1373df6ab4544a2b881e9816985b606e1144e4c77dc8ac87b826",
"providers": [
{
"type": "http",
"url": "https://files.pythonhosted.org/packages/c5/83/61fadfa8d62a288d778e0a1ad2f73b01abca64574ee34c5d6d078e0821da/clang_format-21.1.2-py2.py3-none-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl"
}
],
"format": "zip",
"path": "clang_format/data/bin/clang-format"
},
"linux-x86_64": {
"size": 1805060,
"hash": "sha256",
"digest": "6d7caf74fe89154258ddfd63984c98ffe902ef98f013ac517178fc44d72861ff",
"providers": [
{
"type": "http",
"url": "https://files.pythonhosted.org/packages/fb/ac/3c04772acc0257f5730e83adb542b2603c1a62d1315010ab593a980af404/clang_format-21.1.2-py2.py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl"
}
],
"format": "zip",
"path": "clang_format/data/bin/clang-format"
},
"macos-aarch64": {
"size": 1458874,
"hash": "sha256",
"digest": "fc034652dee24583633177d800bc9deebcc9c65eb7ab53b25bbd0fbd443392a9",
"providers": [
{
"type": "http",
"url": "https://files.pythonhosted.org/packages/ba/90/b8230efcff90a8543da3fb7fc09d7077afebaba019eceb1686d4db94cac3/clang_format-21.1.2-py2.py3-none-macosx_11_0_arm64.whl"
}
],
"format": "zip",
"path": "clang_format/data/bin/clang-format"
},
"macos-x86_64": {
"size": 1440163,
"hash": "sha256",
"digest": "00498efb43d60d7ac4195362009a79936d26145a9a90cdfa7a6013a62ab3c40c",
"providers": [
{
"type": "http",
"url": "https://files.pythonhosted.org/packages/7d/97/0bb5a6866dfb5f55f7e6ca79466cb0b0081fccbc9f57887949ff23b5c38a/clang_format-21.1.2-py2.py3-none-macosx_10_9_x86_64.whl"
}
],
"format": "zip",
"path": "clang_format/data/bin/clang-format"
},
"windows-x86_64": {
"size": 1426244,
"hash": "sha256",
"digest": "c98e195a50c0fa40bb058449511b1b681ca7ad553579aa32425f0cfeca8d81ce",
"providers": [
{
"type": "http",
"url": "https://files.pythonhosted.org/packages/fe/0d/3b9c6a41a9eed2d45431d91c0e8608da315cd44d0c24c517bfb686db4b6b/clang_format-21.1.2-py2.py3-none-win_amd64.whl"
}
],
"format": "zip",
"path": "clang_format/data/bin/clang-format.exe"
}
}
}
+73
View File
@@ -0,0 +1,73 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @noflow
* @format
*/
'use strict';
const dotslash = require('fb-dotslash');
const {spawnSync} = require('node:child_process');
const fs = require('node:fs');
const path = require('node:path');
const {globSync} = require('tinyglobby');
const REPO_ROOT = path.resolve(__dirname, '..');
const CLANG_FORMAT = path.join(__dirname, 'clang-format');
const GENERATED_MARKER = Buffer.from('@' + 'generated');
const MAX_HEADER_BYTES = 4096;
const MAX_FILES_PER_PROCESS = 30;
/** @param {string} file */
function isGenerated(file) {
let fd;
try {
fd = fs.openSync(path.resolve(REPO_ROOT, file), 'r');
const header = Buffer.alloc(MAX_HEADER_BYTES);
const bytesRead = fs.readSync(fd, header, 0, header.length, 0);
return header.subarray(0, bytesRead).includes(GENERATED_MARKER);
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
throw new Error(`Unable to inspect ${file}: ${message}`, {cause: error});
} finally {
if (fd != null) {
fs.closeSync(fd);
}
}
}
function main() {
const files =
process.argv.length > 2
? process.argv.slice(2)
: globSync('*/**/*.{h,cpp,m,mm}', {cwd: REPO_ROOT});
const sourceFiles = files.filter(file => !isGenerated(file));
for (let i = 0; i < sourceFiles.length; i += MAX_FILES_PER_PROCESS) {
const result = spawnSync(
dotslash,
[CLANG_FORMAT, '-i', ...sourceFiles.slice(i, i + MAX_FILES_PER_PROCESS)],
{
cwd: REPO_ROOT,
stdio: 'inherit',
},
);
if (result.error != null) {
throw result.error;
}
if (result.signal != null) {
process.kill(process.pid, result.signal);
return;
}
if (result.status !== 0) {
process.exit(result.status ?? 1);
}
}
}
main();
-14
View File
@@ -2912,11 +2912,6 @@ async-limiter@~1.0.0:
resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd"
integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==
async@^3.2.3:
version "3.2.6"
resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce"
integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==
author-regex@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/author-regex/-/author-regex-1.0.0.tgz#d08885be6b9bbf9439fe087c76287245f0a81450"
@@ -3322,15 +3317,6 @@ cjs-module-lexer@^1.0.0:
resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.4.0.tgz#677de7ed7efff67cc40c9bf1897fea79d41b5215"
integrity sha512-N1NGmowPlGBLsOZLPvm48StN04V4YvQRL0i6b7ctrVY3epjP/ct7hFLOItz6pDIvRjwpfPxi52a2UWV2ziir8g==
clang-format@^1.8.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/clang-format/-/clang-format-1.8.0.tgz#7779df1c5ce1bc8aac1b0b02b4e479191ef21d46"
integrity sha512-pK8gzfu55/lHzIpQ1givIbWfn3eXnU7SfxqIwVgnn5jEM6j4ZJYjpFqFs4iSBPNedzRMmfjYjuQhu657WAXHXw==
dependencies:
async "^3.2.3"
glob "^7.0.0"
resolve "^1.1.6"
cli-cursor@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307"