Skip to content

Commit 46b6453

Browse files
cipolleschifacebook-github-bot
authored andcommitted
Fix the Redefinition of 'NativeXXXSpecJSI' error with Frameworks (#44005)
Summary: Pull Request resolved: #44005 When using frameworks on iOS, there is a possibility that modules import the Spec.h file twice and this might end up in a Redefinition of some symbols and duplication of symbols which ends up in build errors, as reported here: #42670. This change adds some [`#include guards`](https://en.wikipedia.org/wiki/Include_guard) in codegen to avoid the redefinition of those symbols if the header is imported/included multiple times. Note: I also experimented with `#pragma once`, but it looks like Apple is not happy with that directive. [It seems](https://forums.developer.apple.com/forums/thread/739964) that it started working flakely from Xcode 15. ## Changelog: [General][Fixed] - Make sure that we can't include Codegen symbols multiple times Reviewed By: cortinico Differential Revision: D55925605 fbshipit-source-id: 15ca076aace2ffbd03ab8fa8a68a3d8ce0d1ea65
1 parent 9433506 commit 46b6453

3 files changed

Lines changed: 82 additions & 7 deletions

File tree

packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleObjCpp-test.js.snap

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ exports[`GenerateModuleObjCpp can generate a header file NativeModule specs 1`]
1717
#ifndef __cplusplus
1818
#error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm.
1919
#endif
20+
21+
// Avoid multiple includes of RNCodegenModuleFixtures symbols
22+
#ifndef RNCodegenModuleFixtures_H
23+
#define RNCodegenModuleFixtures_H
24+
2025
#import <Foundation/Foundation.h>
2126
#import <RCTRequired/RCTRequired.h>
2227
#import <RCTTypeSafety/RCTConvertHelpers.h>
@@ -1341,6 +1346,7 @@ inline JS::NativeSampleTurboModuleOptional::Constants::Builder::Builder(Constant
13411346
return i.unsafeRawValue();
13421347
}) {}
13431348
1349+
#endif // RNCodegenModuleFixtures_H
13441350
"
13451351
`;
13461352
@@ -1361,6 +1367,11 @@ exports[`GenerateModuleObjCpp can generate a header file NativeModule specs with
13611367
#ifndef __cplusplus
13621368
#error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm.
13631369
#endif
1370+
1371+
// Avoid multiple includes of RNCodegenModuleFixtures symbols
1372+
#ifndef RNCodegenModuleFixtures_H
1373+
#define RNCodegenModuleFixtures_H
1374+
13641375
#import <Foundation/Foundation.h>
13651376
#import <RCTRequired/RCTRequired.h>
13661377
#import <RCTTypeSafety/RCTConvertHelpers.h>
@@ -2688,6 +2699,7 @@ inline JS::NativeSampleTurboModuleOptional::Constants::Builder::Builder(Constant
26882699
}) {}
26892700
26902701
NS_ASSUME_NONNULL_END
2702+
#endif // RNCodegenModuleFixtures_H
26912703
"
26922704
`;
26932705

packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/index.js

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,20 @@ namespace facebook::react {
4646
} // namespace facebook::react`;
4747

4848
const HeaderFileTemplate = ({
49+
headerFileName,
4950
moduleDeclarations,
5051
structInlineMethods,
5152
assumeNonnull,
5253
}: $ReadOnly<{
54+
headerFileName: string,
5355
moduleDeclarations: string,
5456
structInlineMethods: string,
5557
assumeNonnull: boolean,
56-
}>) =>
57-
`/**
58+
}>) => {
59+
const headerFileNameWithNoExt = headerFileName.replace(/\.h$/, '');
60+
61+
return (
62+
`/**
5863
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
5964
*
6065
* Do not edit this file as changes may cause incorrect behavior and will be lost
@@ -70,6 +75,11 @@ const HeaderFileTemplate = ({
7075
#ifndef __cplusplus
7176
#error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm.
7277
#endif
78+
79+
// Avoid multiple includes of ${headerFileNameWithNoExt} symbols
80+
#ifndef ${headerFileNameWithNoExt}_H
81+
#define ${headerFileNameWithNoExt}_H
82+
7383
#import <Foundation/Foundation.h>
7484
#import <RCTRequired/RCTRequired.h>
7585
#import <RCTTypeSafety/RCTConvertHelpers.h>
@@ -82,11 +92,15 @@ const HeaderFileTemplate = ({
8292
#import <vector>
8393
8494
` +
85-
(assumeNonnull ? '\nNS_ASSUME_NONNULL_BEGIN\n' : '') +
86-
moduleDeclarations +
87-
'\n' +
88-
structInlineMethods +
89-
(assumeNonnull ? '\nNS_ASSUME_NONNULL_END\n' : '\n');
95+
(assumeNonnull ? '\nNS_ASSUME_NONNULL_BEGIN\n' : '') +
96+
moduleDeclarations +
97+
'\n' +
98+
structInlineMethods +
99+
(assumeNonnull ? '\nNS_ASSUME_NONNULL_END\n' : '\n') +
100+
`#endif // ${headerFileNameWithNoExt}_H` +
101+
'\n'
102+
);
103+
};
90104

91105
const SourceFileTemplate = ({
92106
headerFileName,
@@ -197,6 +211,7 @@ module.exports = {
197211

198212
const headerFileName = `${libraryName}.h`;
199213
const headerFile = HeaderFileTemplate({
214+
headerFileName,
200215
moduleDeclarations: moduleDeclarations.join('\n'),
201216
structInlineMethods: structInlineMethods.join('\n'),
202217
assumeNonnull,

packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleHObjCpp-test.js.snap

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ Map {
1818
#ifndef __cplusplus
1919
#error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm.
2020
#endif
21+
22+
// Avoid multiple includes of SampleWithUppercaseName symbols
23+
#ifndef SampleWithUppercaseName_H
24+
#define SampleWithUppercaseName_H
25+
2126
#import <Foundation/Foundation.h>
2227
#import <RCTRequired/RCTRequired.h>
2328
#import <RCTTypeSafety/RCTConvertHelpers.h>
@@ -45,6 +50,7 @@ namespace facebook::react {
4550
};
4651
} // namespace facebook::react
4752
53+
#endif // SampleWithUppercaseName_H
4854
",
4955
}
5056
`;
@@ -67,6 +73,11 @@ Map {
6773
#ifndef __cplusplus
6874
#error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm.
6975
#endif
76+
77+
// Avoid multiple includes of complex_objects symbols
78+
#ifndef complex_objects_H
79+
#define complex_objects_H
80+
7081
#import <Foundation/Foundation.h>
7182
#import <RCTRequired/RCTRequired.h>
7283
#import <RCTTypeSafety/RCTConvertHelpers.h>
@@ -304,6 +315,7 @@ inline facebook::react::LazyVector<JS::NativeSampleTurboModule::SpecGetArraysOpt
304315
id const p = _v[@\\"arrayOfObjects\\"];
305316
return RCTBridgingToVec(p, ^JS::NativeSampleTurboModule::SpecGetArraysOptionsArrayOfObjectsElement(id itemValue_0) { return JS::NativeSampleTurboModule::SpecGetArraysOptionsArrayOfObjectsElement(itemValue_0); });
306317
}
318+
#endif // complex_objects_H
307319
",
308320
}
309321
`;
@@ -326,6 +338,11 @@ Map {
326338
#ifndef __cplusplus
327339
#error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm.
328340
#endif
341+
342+
// Avoid multiple includes of cxx_only_native_modules symbols
343+
#ifndef cxx_only_native_modules_H
344+
#define cxx_only_native_modules_H
345+
329346
#import <Foundation/Foundation.h>
330347
#import <RCTRequired/RCTRequired.h>
331348
#import <RCTTypeSafety/RCTConvertHelpers.h>
@@ -339,6 +356,7 @@ Map {
339356
340357
341358
359+
#endif // cxx_only_native_modules_H
342360
",
343361
}
344362
`;
@@ -361,6 +379,11 @@ Map {
361379
#ifndef __cplusplus
362380
#error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm.
363381
#endif
382+
383+
// Avoid multiple includes of empty_native_modules symbols
384+
#ifndef empty_native_modules_H
385+
#define empty_native_modules_H
386+
364387
#import <Foundation/Foundation.h>
365388
#import <RCTRequired/RCTRequired.h>
366389
#import <RCTTypeSafety/RCTConvertHelpers.h>
@@ -388,6 +411,7 @@ namespace facebook::react {
388411
};
389412
} // namespace facebook::react
390413
414+
#endif // empty_native_modules_H
391415
",
392416
}
393417
`;
@@ -410,6 +434,11 @@ Map {
410434
#ifndef __cplusplus
411435
#error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm.
412436
#endif
437+
438+
// Avoid multiple includes of native_modules_with_type_aliases symbols
439+
#ifndef native_modules_with_type_aliases_H
440+
#define native_modules_with_type_aliases_H
441+
413442
#import <Foundation/Foundation.h>
414443
#import <RCTRequired/RCTRequired.h>
415444
#import <RCTTypeSafety/RCTConvertHelpers.h>
@@ -557,6 +586,7 @@ inline std::optional<bool> JS::AliasTurboModule::Options::allowExternalStorage()
557586
id const p = _v[@\\"allowExternalStorage\\"];
558587
return RCTBridgingToOptionalBool(p);
559588
}
589+
#endif // native_modules_with_type_aliases_H
560590
",
561591
}
562592
`;
@@ -579,6 +609,11 @@ Map {
579609
#ifndef __cplusplus
580610
#error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm.
581611
#endif
612+
613+
// Avoid multiple includes of real_module_example symbols
614+
#ifndef real_module_example_H
615+
#define real_module_example_H
616+
582617
#import <Foundation/Foundation.h>
583618
#import <RCTRequired/RCTRequired.h>
584619
#import <RCTTypeSafety/RCTConvertHelpers.h>
@@ -799,6 +834,7 @@ inline id<NSObject> _Nullable JS::NativeExceptionsManager::ExceptionData::extraD
799834
id const p = _v[@\\"extraData\\"];
800835
return p;
801836
}
837+
#endif // real_module_example_H
802838
",
803839
}
804840
`;
@@ -821,6 +857,11 @@ Map {
821857
#ifndef __cplusplus
822858
#error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm.
823859
#endif
860+
861+
// Avoid multiple includes of simple_native_modules symbols
862+
#ifndef simple_native_modules_H
863+
#define simple_native_modules_H
864+
824865
#import <Foundation/Foundation.h>
825866
#import <RCTRequired/RCTRequired.h>
826867
#import <RCTTypeSafety/RCTConvertHelpers.h>
@@ -910,6 +951,7 @@ inline JS::NativeSampleTurboModule::Constants::Builder::Builder(const Input i) :
910951
inline JS::NativeSampleTurboModule::Constants::Builder::Builder(Constants i) : _factory(^{
911952
return i.unsafeRawValue();
912953
}) {}
954+
#endif // simple_native_modules_H
913955
",
914956
}
915957
`;
@@ -932,6 +974,11 @@ Map {
932974
#ifndef __cplusplus
933975
#error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm.
934976
#endif
977+
978+
// Avoid multiple includes of two_modules_different_files symbols
979+
#ifndef two_modules_different_files_H
980+
#define two_modules_different_files_H
981+
935982
#import <Foundation/Foundation.h>
936983
#import <RCTRequired/RCTRequired.h>
937984
#import <RCTTypeSafety/RCTConvertHelpers.h>
@@ -975,6 +1022,7 @@ namespace facebook::react {
9751022
} // namespace facebook::react
9761023
9771024
1025+
#endif // two_modules_different_files_H
9781026
",
9791027
}
9801028
`;

0 commit comments

Comments
 (0)