Skip to content

Commit 10cc964

Browse files
committed
[CompilerPlugin] Add C shim for getting stdio names and errno
Add _CShims module. For CMake it's a INTERFACE library.
1 parent 6b594b8 commit 10cc964

File tree

8 files changed

+62
-26
lines changed

8 files changed

+62
-26
lines changed

Package.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ let package = Package(
3030
],
3131
targets: [
3232
// MARK: - Internal helper targets
33+
.target(
34+
name: "_CShims"
35+
),
3336

3437
.target(
3538
name: "_AtomicBool"
@@ -74,7 +77,7 @@ let package = Package(
7477

7578
.target(
7679
name: "SwiftCompilerPlugin",
77-
dependencies: ["SwiftCompilerPluginMessageHandling", "SwiftSyntaxMacros"],
80+
dependencies: ["SwiftCompilerPluginMessageHandling", "SwiftSyntaxMacros", "_CShims"],
7881
exclude: ["CMakeLists.txt"]
7982
),
8083

Sources/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
# See http://swift.org/LICENSE.txt for license information
77
# See http://swift.org/CONTRIBUTORS.txt for Swift project authors
88

9+
add_subdirectory(_CShims)
910
add_subdirectory(SwiftBasicFormat)
1011
add_subdirectory(SwiftSyntax)
1112
add_subdirectory(SwiftDiagnostics)

Sources/SwiftCompilerPlugin/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,6 @@ add_swift_syntax_library(SwiftCompilerPlugin
1313

1414
target_link_swift_syntax_libraries(SwiftCompilerPlugin PUBLIC
1515
SwiftSyntaxMacros
16-
SwiftCompilerPluginMessageHandling)
16+
SwiftCompilerPluginMessageHandling
17+
SwiftSyntax_CShims
18+
)

Sources/SwiftCompilerPlugin/CompilerPlugin.swift

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
// https://github.com/apple/swift-package-manager/blob/main/Sources/PackagePlugin/Plugin.swift
1414

1515
#if swift(>=6.0)
16+
private import _CShims
1617
public import SwiftSyntaxMacros
1718
@_spi(PluginMessage) private import SwiftCompilerPluginMessageHandling
1819
#if canImport(Darwin)
@@ -23,6 +24,7 @@ private import Glibc
2324
private import ucrt
2425
#endif
2526
#else
27+
import _CShims
2628
import SwiftSyntaxMacros
2729
@_spi(PluginMessage) import SwiftCompilerPluginMessageHandling
2830
#if canImport(Darwin)
@@ -115,29 +117,29 @@ extension CompilerPlugin {
115117
public static func main() throws {
116118
// Duplicate the `stdin` file descriptor, which we will then use for
117119
// receiving messages from the plugin host.
118-
let inputFD = dup(fileno(stdin))
120+
let inputFD = dup(fileno(_ss_stdin()))
119121
guard inputFD >= 0 else {
120-
internalError("Could not duplicate `stdin`: \(describe(errno: errno)).")
122+
internalError("Could not duplicate `stdin`: \(describe(errno: _ss_errno())).")
121123
}
122124

123125
// Having duplicated the original standard-input descriptor, we close
124126
// `stdin` so that attempts by the plugin to read console input (which
125127
// are usually a mistake) return errors instead of blocking.
126-
guard close(fileno(stdin)) >= 0 else {
127-
internalError("Could not close `stdin`: \(describe(errno: errno)).")
128+
guard close(fileno(_ss_stdin())) >= 0 else {
129+
internalError("Could not close `stdin`: \(describe(errno: _ss_errno())).")
128130
}
129131

130132
// Duplicate the `stdout` file descriptor, which we will then use for
131133
// sending messages to the plugin host.
132-
let outputFD = dup(fileno(stdout))
134+
let outputFD = dup(fileno(_ss_stdout()))
133135
guard outputFD >= 0 else {
134-
internalError("Could not dup `stdout`: \(describe(errno: errno)).")
136+
internalError("Could not dup `stdout`: \(describe(errno: _ss_errno())).")
135137
}
136138

137139
// Having duplicated the original standard-output descriptor, redirect
138140
// `stdout` to `stderr` so that all free-form text output goes there.
139-
guard dup2(fileno(stderr), fileno(stdout)) >= 0 else {
140-
internalError("Could not dup2 `stdout` to `stderr`: \(describe(errno: errno)).")
141+
guard dup2(fileno(_ss_stderr()), fileno(_ss_stdout())) >= 0 else {
142+
internalError("Could not dup2 `stdout` to `stderr`: \(describe(errno: _ss_errno())).")
141143
}
142144

143145
// Turn off full buffering so printed text appears as soon as possible.
@@ -146,9 +148,9 @@ extension CompilerPlugin {
146148
// buffer. As a result, on Windows, we completely disable all
147149
// buffering, which means that partial writes are possible.
148150
#if os(Windows)
149-
setvbuf(stdout, nil, _IONBF, 0)
151+
setvbuf(_ss_stdout(), nil, _IONBF, 0)
150152
#else
151-
setvbuf(stdout, nil, _IOLBF, 0)
153+
setvbuf(_ss_stdout(), nil, _IOLBF, 0)
152154
#endif
153155

154156
// Open a message channel for communicating with the plugin host.
@@ -172,15 +174,10 @@ extension CompilerPlugin {
172174

173175
// Private function to report internal errors and then exit.
174176
fileprivate static func internalError(_ message: String) -> Never {
175-
fputs("Internal Error: \(message)\n", stderr)
177+
fputs("Internal Error: \(message)\n", _ss_stderr())
176178
exit(1)
177179
}
178180

179-
// Private function to construct an error message from an `errno` code.
180-
fileprivate static func describe(errno: Int32) -> String {
181-
if let cStr = strerror(errno) { return String(cString: cStr) }
182-
return String(describing: errno)
183-
}
184181
}
185182

186183
internal struct PluginHostConnection: MessageConnection {
@@ -234,24 +231,29 @@ internal struct PluginHostConnection: MessageConnection {
234231
}
235232
}
236233

237-
func _write(_ fd: CInt, contentsOf buffer: UnsafeRawBufferPointer) throws {
234+
// Private function to construct an error message from an `errno` code.
235+
private func describe(errno: CInt) -> String {
236+
if let cStr = strerror(errno) { return String(cString: cStr) }
237+
return String(describing: errno)
238+
}
239+
240+
private func _write(_ fd: CInt, contentsOf buffer: UnsafeRawBufferPointer) throws {
238241
var ptr = buffer.baseAddress!
239242
var remaining = buffer.count
240243
while remaining > 0 {
241-
switch write(fd, ptr, remaining) {
244+
switch write(fd, ptr, numericCast(remaining)) {
242245
case 0:
243246
throw CompilerPluginError(message: "write(2) closed")
244247
case -1:
245-
let err = String(cString: strerror(errno))
246-
throw CompilerPluginError(message: "read(2) failed: \(err)")
248+
throw CompilerPluginError(message: "read(2) failed: \(describe(errno: _ss_errno()))")
247249
case let result:
248250
ptr += Int(result)
249251
remaining -= Int(result)
250252
}
251253
}
252254
}
253255

254-
func _reading<T>(_ fd: CInt, count: Int, _ fn: (UnsafeRawBufferPointer) throws -> T) throws -> T {
256+
private func _reading<T>(_ fd: CInt, count: Int, _ fn: (UnsafeRawBufferPointer) throws -> T) throws -> T {
255257
guard count > 0 else {
256258
return try fn(UnsafeRawBufferPointer(start: nil, count: 0))
257259
}
@@ -261,13 +263,12 @@ func _reading<T>(_ fd: CInt, count: Int, _ fn: (UnsafeRawBufferPointer) throws -
261263
var ptr = buffer.baseAddress!
262264
var remaining = buffer.count
263265
while remaining > 0 {
264-
switch read(fd, ptr, remaining) {
266+
switch read(fd, ptr, numericCast(remaining)) {
265267
case 0:
266268
// Input is closed.
267269
return try fn(UnsafeRawBufferPointer(start: nil, count: 0))
268270
case -1:
269-
let err = String(cString: strerror(errno))
270-
throw CompilerPluginError(message: "read(2) failed: \(err)")
271+
throw CompilerPluginError(message: "read(2) failed: \(describe(errno: _ss_errno()))")
271272
case let result:
272273
ptr += Int(result)
273274
remaining -= Int(result)

Sources/_CShims/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
add_library(SwiftSyntax_CShims INTERFACE)
2+
target_include_directories(SwiftSyntax_CShims INTERFACE "include")
3+
set_property(GLOBAL APPEND PROPERTY SWIFT_EXPORTS SwiftSyntax_CShims)

Sources/_CShims/dummy.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

Sources/_CShims/include/_CShims.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
2+
#include <errno.h>
3+
#include <stdio.h>
4+
5+
typedef FILE *_ss_ptr_FILE;
6+
7+
static _ss_ptr_FILE _ss_stdout(void) {
8+
return stdout;
9+
}
10+
11+
static _ss_ptr_FILE _ss_stdin(void) {
12+
return stdin;
13+
}
14+
15+
static _ss_ptr_FILE _ss_stderr(void) {
16+
return stderr;
17+
}
18+
19+
static int _ss_errno(void) {
20+
return errno;
21+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module _CShims {
2+
header "_CShims.h"
3+
export *
4+
}

0 commit comments

Comments
 (0)