@@ -66,7 +66,7 @@ platform-specific attention.
66
66
> These errors are produced when the configuration you're trying to build has
67
67
> conflicting requirements (for example, attempting to enable support for pipes
68
68
> without also enabling support for file I/O.) You should be able to resolve
69
- > these issues by updating Package.swift and/or CompilerSettings.cmake.
69
+ > these issues by updating ` Package.swift ` and/or ` CompilerSettings.cmake ` .
70
70
71
71
Most platform dependencies can be resolved through the use of platform-specific
72
72
API. For example, Swift Testing uses the C11 standard [ ` timespec ` ] ( https://en.cppreference.com/w/c/chrono/timespec )
@@ -123,69 +123,110 @@ Once the header is included, we can call `GetDateTime()` from `Clock.swift`:
123
123
## Runtime test discovery
124
124
125
125
When porting to a new platform, you may need to provide a new implementation for
126
- ` enumerateTypeMetadataSections( )` in ` Discovery.cpp ` . Test discovery is
127
- dependent on Swift metadata discovery which is an inherently platform-specific
128
- operation.
129
-
130
- _ Most _ platforms will be able to reuse the implementation used by Linux and
131
- Windows that calls an internal Swift runtime function to enumerate available
132
- metadata. If you are porting Swift Testing to Classic, this function won't be
133
- available, so you'll need to write a custom implementation instead. Assuming
134
- that the Swift compiler emits section information into the resource fork on
135
- Classic, you could use the [ Resource Manager] ( https://developer.apple.com/library/archive/documentation/mac/pdf/MoreMacintoshToolbox.pdf )
126
+ ` _sectionBounds(_: )` in ` Discovery+Platform.swift ` . Test discovery is dependent
127
+ on Swift metadata discovery which is an inherently platform-specific operation.
128
+
129
+ _ Most _ platforms in use today use the ELF image format and will be able to reuse
130
+ the implementation used by Linux.
131
+
132
+ Classic does not use the ELF image format, so you'll need to write a custom
133
+ implementation of ` _sectionBounds(_:) ` instead. Assuming that the Swift compiler
134
+ emits section information into the resource fork on Classic, you would use the
135
+ [ Resource Manager] ( https://developer.apple.com/library/archive/documentation/mac/pdf/MoreMacintoshToolbox.pdf )
136
136
to load that information:
137
137
138
138
``` diff
139
- --- a/Sources/_TestingInternals /Discovery.cpp
140
- +++ b/Sources/_TestingInternals /Discovery.cpp
139
+ --- a/Sources/Testing /Discovery+Platform.swift
140
+ +++ b/Sources/Testing /Discovery+Platform.swift
141
141
142
142
// ...
143
- + #elif defined(macintosh)
144
- + template <typename SectionEnumerator>
145
- + static void enumerateTypeMetadataSections(const SectionEnumerator& body) {
146
- + ResFileRefNum refNum;
147
- + if (noErr == GetTopResourceFile(&refNum)) {
148
- + ResFileRefNum oldRefNum = refNum;
149
- + do {
150
- + UseResFile(refNum);
151
- + Handle handle = Get1NamedResource('swft', "\p__swift5_types");
152
- + if (handle && *handle) {
153
- + auto imageAddress = reinterpret_cast<const void *>(static_cast<uintptr_t>(refNum));
154
- + SWTSectionBounds sb = { imageAddress, *handle, GetHandleSize(handle) };
155
- + bool stop = false;
156
- + body(sb, &stop);
157
- + if (stop) {
158
- + break;
159
- + }
160
- + }
161
- + } while (noErr == GetNextResourceFile(refNum, &refNum));
162
- + UseResFile(oldRefNum);
143
+ + #elseif os(Classic)
144
+ + private func _sectionBounds(_ kind: SectionBounds.Kind) -> [SectionBounds] {
145
+ + let resourceName: Str255 = switch kind {
146
+ + case .testContent:
147
+ + "__swift5_tests"
148
+ + case .typeMetadata:
149
+ + "__swift5_types"
150
+ + }
151
+ +
152
+ + let oldRefNum = CurResFile()
153
+ + defer {
154
+ + UseResFile(oldRefNum)
155
+ + }
156
+ +
157
+ + var refNum = ResFileRefNum(0)
158
+ + guard noErr == GetTopResourceFile(&refNum) else {
159
+ + return []
163
160
+ }
161
+ +
162
+ + var result = [SectionBounds]()
163
+ + repeat {
164
+ + UseResFile(refNum)
165
+ + guard let handle = Get1NamedResource(ResType("swft"), resourceName) else {
166
+ + continue
167
+ + }
168
+ + let sb = SectionBounds(
169
+ + imageAddress: UnsafeRawPointer(bitPattern: UInt(refNum)),
170
+ + start: handle.pointee!,
171
+ + size: GetHandleSize(handle)
172
+ + )
173
+ + result.append(sb)
174
+ + } while noErr == GetNextResourceFile(refNum, &refNum))
175
+ + return result
164
176
+ }
165
177
#else
166
- #warning Platform-specific implementation missing: Runtime test discovery unavailable (dynamic)
167
- template <typename SectionEnumerator>
168
- static void enumerateTypeMetadataSections(const SectionEnumerator& body) {}
178
+ private func _sectionBounds(_ kind: SectionBounds.Kind) -> [SectionBounds] {
179
+ #warning("Platform-specific implementation missing: Runtime test discovery unavailable (dynamic)")
180
+ return []
181
+ }
169
182
#endif
170
183
```
171
184
185
+ You will also need to update the ` makeTestContentRecordDecl() ` function in the
186
+ ` TestingMacros ` target to emit the correct ` @_section ` attribute for your
187
+ platform. If your platform uses the ELF image format and supports the
188
+ ` dl_iterate_phdr() ` function, add it to the existing ` #elseif os(Linux) || ... `
189
+ case. Otherwise, add a new case for your platform:
190
+
191
+ ``` diff
192
+ --- a/Sources/TestingMacros/Support/TestContentGeneration.swift
193
+ +++ b/Sources/TestingMacros/Support/TestContentGeneration.swift
194
+ // ...
195
+ + #elseif os(Classic)
196
+ + @_section(".rsrc,swft,__swift5_tests")
197
+ #else
198
+ @__testing(warning: "Platform-specific implementation missing: test content section name unavailable")
199
+ #endif
200
+ ```
201
+
202
+ Keep in mind that this code is emitted by the ` @Test ` and ` @Suite ` macros
203
+ directly into test authors' test targets, so you will not be able to use
204
+ compiler conditionals defined in the Swift Testing package (including those that
205
+ start with ` "SWT_" ` ).
206
+
172
207
## Runtime test discovery with static linkage
173
208
174
209
If your platform does not support dynamic linking and loading, you will need to
175
210
use static linkage instead. Define the ` "SWT_NO_DYNAMIC_LINKING" ` compiler
176
- conditional for your platform in both Package.swift and CompilerSettings.cmake,
177
- then define the ` sectionBegin ` and ` sectionEnd ` symbols in Discovery.cpp:
211
+ conditional for your platform in both ` Package.swift ` and
212
+ ` CompilerSettings.cmake ` , then define the symbols ` testContentSectionBegin ` ,
213
+ ` testContentSectionEnd ` , ` typeMetadataSectionBegin ` , and
214
+ ` typeMetadataSectionEnd ` in ` Discovery.cpp ` .
178
215
179
216
``` diff
180
217
diff --git a/Sources/_TestingInternals/Discovery.cpp b/Sources/_TestingInternals/Discovery.cpp
181
218
// ...
182
219
+ #elif defined(macintosh)
183
- + extern "C" const char sectionBegin __asm__("...");
184
- + extern "C" const char sectionEnd __asm__("...");
220
+ + extern "C" const char testContentSectionBegin __asm__("...");
221
+ + extern "C" const char testContentSectionEnd __asm__("...");
222
+ + extern "C" const char typeMetadataSectionBegin __asm__("...");
223
+ + extern "C" const char typeMetadataSectionEnd __asm__("...");
185
224
#else
186
225
#warning Platform-specific implementation missing: Runtime test discovery unavailable (static)
187
- static const char sectionBegin = 0;
188
- static const char& sectionEnd = sectionBegin;
226
+ static const char testContentSectionBegin = 0;
227
+ static const char& testContentSectionEnd = testContentSectionBegin;
228
+ static const char typeMetadataSectionBegin = 0;
229
+ static const char& typeMetadataSectionEnd = testContentSectionBegin;
189
230
#endif
190
231
```
191
232
@@ -195,27 +236,6 @@ respectively. Their linker-level names will be platform-dependent: refer to the
195
236
linker documentation for your platform to determine what names to place in the
196
237
` __asm__ ` attribute applied to each.
197
238
198
- If you can't use ` __asm__ ` on your platform, you can declare these symbols as
199
- C++ references to linker-defined symbols:
200
-
201
- ``` diff
202
- diff --git a/Sources/_TestingInternals/Discovery.cpp b/Sources/_TestingInternals/Discovery.cpp
203
- // ...
204
- + #elif defined(macintosh)
205
- + extern "C" const char __linker_defined_begin_symbol;
206
- + extern "C" const char __linker_defined_end_symbol;
207
- + static const auto& sectionBegin = __linker_defined_begin_symbol;
208
- + static const auto& sectionEnd = __linker_defined_end_symbol;
209
- #else
210
- #warning Platform-specific implementation missing: Runtime test discovery unavailable (static)
211
- static const char sectionBegin = 0;
212
- static const char& sectionEnd = sectionBegin;
213
- #endif
214
- ```
215
-
216
- The names of ` __linker_defined_begin_symbol ` and ` __linker_defined_end_symbol `
217
- in this example are, as with the shorter implementation, platform-dependent.
218
-
219
239
## C++ stub implementations
220
240
221
241
Some symbols defined in C and C++ headers, especially "complex" macros, cannot
0 commit comments