mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Add function to extract headers from a folder (#53737)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/53737 This change add a utility function to extract headers (both .h and .hpp) from a folder. It also allow to exclude some specific folders (e.g.: `tests`, non supported platforms, ...) ## Context SwiftPM is very picky in how the header structure must be. In order to preserve the import/include statements as much as possible when building from source, we can recreate the header structure in a temporary folder inside the react-native package using symlinks. In this way, users can still modify the headers and build RNTester and HelloWorld using SwiftPM without breaking changes. ## Changelog: [Internal] - Reviewed By: cortinico Differential Revision: D82205692 fbshipit-source-id: 4fa6dee2ae4790c583beb96a959b0c3045c7b50a
This commit is contained in:
committed by
Facebook GitHub Bot
parent
c1827fcd04
commit
072b105f52
+133
-1
@@ -10,7 +10,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const {setupSymlink} = require('../utils');
|
||||
const {listHeadersInFolder, setupSymlink} = require('../utils');
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
@@ -107,3 +107,135 @@ describe('setupSymlink', () => {
|
||||
expect(fs.readFileSync(destFile, 'utf8')).toBe('test content');
|
||||
});
|
||||
});
|
||||
|
||||
describe('listHeadersInFolder', () => {
|
||||
let tempDir;
|
||||
|
||||
beforeEach(() => {
|
||||
// Create a temporary directory for testing
|
||||
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'headers-test-'));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// Clean up temporary directory
|
||||
if (fs.existsSync(tempDir)) {
|
||||
fs.rmSync(tempDir, {recursive: true, force: true});
|
||||
}
|
||||
});
|
||||
|
||||
it('should find both .h and .hpp header files', () => {
|
||||
// Create mixed header files
|
||||
fs.writeFileSync(path.join(tempDir, 'test1.h'), '// header file 1');
|
||||
fs.writeFileSync(path.join(tempDir, 'test2.hpp'), '// header file 2');
|
||||
fs.writeFileSync(path.join(tempDir, 'test3.h'), '// header file 3');
|
||||
|
||||
const result = listHeadersInFolder(tempDir, []);
|
||||
|
||||
expect(result).toHaveLength(3);
|
||||
expect(result).toContain(path.join(tempDir, 'test1.h'));
|
||||
expect(result).toContain(path.join(tempDir, 'test2.hpp'));
|
||||
expect(result).toContain(path.join(tempDir, 'test3.h'));
|
||||
});
|
||||
|
||||
it('should find header files in subdirectories', () => {
|
||||
// Create subdirectories with header files
|
||||
const subDir1 = path.join(tempDir, 'subdir1');
|
||||
const subDir2 = path.join(tempDir, 'subdir2');
|
||||
fs.mkdirSync(subDir1, {recursive: true});
|
||||
fs.mkdirSync(subDir2, {recursive: true});
|
||||
|
||||
fs.writeFileSync(path.join(tempDir, 'root.h'), '// root header');
|
||||
fs.writeFileSync(path.join(subDir1, 'sub1.h'), '// sub1 header');
|
||||
fs.writeFileSync(path.join(subDir2, 'sub2.hpp'), '// sub2 header');
|
||||
|
||||
const result = listHeadersInFolder(tempDir, []);
|
||||
|
||||
expect(result).toHaveLength(3);
|
||||
expect(result).toContain(path.join(tempDir, 'root.h'));
|
||||
expect(result).toContain(path.join(subDir1, 'sub1.h'));
|
||||
expect(result).toContain(path.join(subDir2, 'sub2.hpp'));
|
||||
});
|
||||
|
||||
it('should exclude multiple specified subfolders', () => {
|
||||
// Create subdirectories
|
||||
const keepDir = path.join(tempDir, 'keep');
|
||||
const excludeDir1 = path.join(tempDir, 'exclude1');
|
||||
const excludeDir2 = path.join(tempDir, 'exclude2');
|
||||
fs.mkdirSync(keepDir, {recursive: true});
|
||||
fs.mkdirSync(excludeDir1, {recursive: true});
|
||||
fs.mkdirSync(excludeDir2, {recursive: true});
|
||||
|
||||
// Create header files
|
||||
fs.writeFileSync(path.join(keepDir, 'keep.h'), '// keep header');
|
||||
fs.writeFileSync(
|
||||
path.join(excludeDir1, 'exclude1.h'),
|
||||
'// exclude1 header',
|
||||
);
|
||||
fs.writeFileSync(
|
||||
path.join(excludeDir2, 'exclude2.h'),
|
||||
'// exclude2 header',
|
||||
);
|
||||
|
||||
const result = listHeadersInFolder(tempDir, ['exclude1', 'exclude2']);
|
||||
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result).toContain(path.join(keepDir, 'keep.h'));
|
||||
expect(result).not.toContain(path.join(excludeDir1, 'exclude1.h'));
|
||||
expect(result).not.toContain(path.join(excludeDir2, 'exclude2.h'));
|
||||
});
|
||||
|
||||
it('should return empty array when no header files found', () => {
|
||||
// Create non-header files
|
||||
fs.writeFileSync(path.join(tempDir, 'test.txt'), 'text file');
|
||||
fs.writeFileSync(path.join(tempDir, 'test.js'), 'javascript file');
|
||||
|
||||
const result = listHeadersInFolder(tempDir, []);
|
||||
|
||||
expect(result).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should handle empty folder', () => {
|
||||
const result = listHeadersInFolder(tempDir, []);
|
||||
|
||||
expect(result).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should handle nested exclusions correctly', () => {
|
||||
// Create nested directory structure
|
||||
const includeDir = path.join(tempDir, 'include');
|
||||
const excludeDir = path.join(tempDir, 'exclude');
|
||||
const nestedInclude = path.join(includeDir, 'nested');
|
||||
const nestedExclude = path.join(excludeDir, 'nested');
|
||||
|
||||
fs.mkdirSync(nestedInclude, {recursive: true});
|
||||
fs.mkdirSync(nestedExclude, {recursive: true});
|
||||
|
||||
// Create header files
|
||||
fs.writeFileSync(path.join(includeDir, 'include.h'), '// include header');
|
||||
fs.writeFileSync(
|
||||
path.join(nestedInclude, 'nested_include.h'),
|
||||
'// nested include header',
|
||||
);
|
||||
fs.writeFileSync(path.join(excludeDir, 'exclude.h'), '// exclude header');
|
||||
fs.writeFileSync(
|
||||
path.join(nestedExclude, 'nested_exclude.h'),
|
||||
'// nested exclude header',
|
||||
);
|
||||
|
||||
const result = listHeadersInFolder(tempDir, ['exclude']);
|
||||
|
||||
expect(result).toHaveLength(2);
|
||||
expect(result).toContain(path.join(includeDir, 'include.h'));
|
||||
expect(result).toContain(path.join(nestedInclude, 'nested_include.h'));
|
||||
expect(result).not.toContain(path.join(excludeDir, 'exclude.h'));
|
||||
expect(result).not.toContain(path.join(nestedExclude, 'nested_exclude.h'));
|
||||
});
|
||||
|
||||
it('should throw error when folder does not exist', () => {
|
||||
const nonExistentFolder = path.join(tempDir, 'nonexistent');
|
||||
|
||||
expect(() => {
|
||||
listHeadersInFolder(nonExistentFolder, []);
|
||||
}).toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
+37
@@ -8,9 +8,45 @@
|
||||
* @format
|
||||
*/
|
||||
|
||||
const {execSync} = require('child_process');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
function listHeadersInFolder(
|
||||
folder /*: string */,
|
||||
excludeSubfolders /*: Array<string> */,
|
||||
) /*: Array<string> */ {
|
||||
try {
|
||||
// Build find command with exclusions using -prune
|
||||
let findCommand = `find "${folder}"`;
|
||||
|
||||
// Add exclusions for specified folders using -prune
|
||||
if (excludeSubfolders.length > 0) {
|
||||
const pruneConditions = excludeSubfolders
|
||||
.map(subfolder => `-name "${subfolder}"`)
|
||||
.join(' -o ');
|
||||
findCommand += ` \\( ${pruneConditions} \\) -prune -o`;
|
||||
}
|
||||
|
||||
findCommand += ` \\( -name "*.h" -o -name "*.hpp" \\) -type f -print`;
|
||||
|
||||
const result = execSync(findCommand, {
|
||||
encoding: 'utf8',
|
||||
stdio: 'pipe',
|
||||
});
|
||||
|
||||
const headerFiles = result
|
||||
.trim()
|
||||
.split('\n')
|
||||
.filter(p => p.length > 0);
|
||||
|
||||
return headerFiles;
|
||||
} catch (error) {
|
||||
console.error(`Failed to process headers from ${folder}:`, error.message);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
function setupSymlink(
|
||||
sourceFilePath /*: string */,
|
||||
destFilePath /*: string */,
|
||||
@@ -33,4 +69,5 @@ function setupSymlink(
|
||||
|
||||
module.exports = {
|
||||
setupSymlink,
|
||||
listHeadersInFolder,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user