Skip to content

Commit bc5dc98

Browse files
committed
Add SwiftBridging.h compatibility header for Linux support
Follow WebKit pattern to provide cross-platform Swift bridging compatibility. - Created SwiftBridging.h header with conditional <swift/bridging> include - Updated all headers to use compatibility header instead of direct include - Provides fallback macro definitions for platforms without Swift bridging support
1 parent 535c9d8 commit bc5dc98

File tree

4 files changed

+314
-3
lines changed

4 files changed

+314
-3
lines changed

Sources/OpenAttributeGraphCxx/include/OpenAttributeGraphCxx/DebugServer/DebugServer.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#include <OpenAttributeGraphCxx/Vector/vector.hpp>
1515
#include <dispatch/dispatch.h>
1616
#include <memory>
17-
#include <swift/bridging>
17+
#include <OpenAttributeGraphCxx/SwiftBridging.h>
1818

1919
OAG_ASSUME_NONNULL_BEGIN
2020

Lines changed: 311 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
//
2+
// SwiftBridging.h
3+
// OpenAttributeGraphCxx
4+
//
5+
// Cross-platform Swift bridging compatibility header to solve <swift/bridging> issue on non-Darwin swift toolchain
6+
// Based on WebKit's SwiftBridging.h approach https://github.com/WebKit/WebKit/blob/84fc0edf9e8649a56cca35cc48c73f211e310d14/Source/WTF/wtf/SwiftBridging.h
7+
8+
#pragma once
9+
10+
#if __has_include(<swift/bridging>)
11+
12+
#include <swift/bridging>
13+
14+
#ifndef SWIFT_NONESCAPABLE
15+
#define SWIFT_NONESCAPABLE
16+
#endif
17+
18+
#ifndef SWIFT_ESCAPABLE
19+
#define SWIFT_ESCAPABLE
20+
#endif
21+
22+
#ifndef SWIFT_RETURNS_UNRETAINED
23+
#define SWIFT_RETURNS_UNRETAINED
24+
#endif
25+
26+
#ifndef SWIFT_ESCAPABLE_IF
27+
#define SWIFT_ESCAPABLE_IF(...)
28+
#endif
29+
30+
#ifndef SWIFT_PRIVATE_FILEID
31+
#define SWIFT_PRIVATE_FILEID(_fileID)
32+
#endif
33+
34+
#else
35+
36+
// Copied from https://github.com/swiftlang/swift/blob/ff8b9f145320b02bc6de75163d78528f210bdba6/lib/ClangImporter/SwiftBridging/swift/bridging
37+
38+
// -*- C++ -*-
39+
//===------------------ bridging - C++ and Swift Interop --------*- C++ -*-===//
40+
//
41+
// This source file is part of the Swift.org open source project
42+
//
43+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
44+
// Licensed under Apache License v2.0 with Runtime Library Exception
45+
//
46+
// See https://swift.org/LICENSE.txt for license information
47+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
48+
//
49+
//===----------------------------------------------------------------------===//
50+
//
51+
// This file provides common utilities and annotations that are useful for C++
52+
// codebases that interoperate with Swift.
53+
//
54+
//===----------------------------------------------------------------------===//
55+
#ifndef SWIFT_CLANGIMPORTER_SWIFT_INTEROP_SUPPORT_H
56+
#define SWIFT_CLANGIMPORTER_SWIFT_INTEROP_SUPPORT_H
57+
58+
#ifdef __has_attribute
59+
#define _CXX_INTEROP_HAS_ATTRIBUTE(x) __has_attribute(x)
60+
#else
61+
#define _CXX_INTEROP_HAS_ATTRIBUTE(x) 0
62+
#endif
63+
64+
#if _CXX_INTEROP_HAS_ATTRIBUTE(swift_attr)
65+
66+
/// Specifies that a C++ `class` or `struct` owns and controls the lifetime of all
67+
/// of the objects it references. Such type should not reference any objects whose
68+
/// lifetime is controlled externally. This annotation allows Swift to import methods
69+
/// that return a `class` or `struct` type that is annotated with this macro.
70+
#define SWIFT_SELF_CONTAINED __attribute__((swift_attr("import_owned")))
71+
72+
/// Specifies that a C++ method returns a value that is presumed to contain
73+
/// objects whose lifetime is not dependent on `this` or other parameters passed
74+
/// to the method.
75+
#define SWIFT_RETURNS_INDEPENDENT_VALUE __attribute__((swift_attr("import_unsafe")))
76+
77+
#define _CXX_INTEROP_STRINGIFY(_x) #_x
78+
79+
#define _CXX_INTEROP_CONCAT_(a,b,c,d,e,f,g,i,j,k,l,m,n,o,p,...) \
80+
#a "," #b "," #c "," #d "," #e "," #f "," #g "," #i "," #j "," #k "," \
81+
#l "," #m "," #n "," #o "," #p
82+
#define _CXX_INTEROP_CONCAT(...) \
83+
_CXX_INTEROP_CONCAT_(__VA_ARGS__,,,,,,,,,,,,,,,,,)
84+
85+
/// Specifies that a C++ `class` or `struct` is reference-counted using
86+
/// the given `retain` and `release` functions. This annotation lets Swift import
87+
/// such a type as reference counted type in Swift, taking advantage of Swift's
88+
/// automatic reference counting.
89+
///
90+
/// This example shows how to use this macro to let Swift know that
91+
/// a non-copyable reference counted C++ class can be imported as a reference counted type in Swift:
92+
/// ```c++
93+
/// class SWIFT_SHARED_REFERENCE(retainSharedObject, releaseSharedObject)
94+
/// SharedObject : NonCopyable, IntrusiveReferenceCounted<SharedObject> {
95+
/// public:
96+
/// static SharedObject* create();
97+
/// void doSomething();
98+
/// };
99+
///
100+
/// void retainSharedObject(SharedObject *);
101+
/// void releaseSharedObject(SharedObject *);
102+
/// ```
103+
///
104+
/// Then, the Swift programmer would be able to use it in the following manner:
105+
///
106+
/// ```swift
107+
/// let object = SharedObject.create()
108+
/// object.doSomething()
109+
/// // The Swift compiler will release object here.
110+
/// ```
111+
#define SWIFT_SHARED_REFERENCE(_retain, _release) \
112+
__attribute__((swift_attr("import_reference"))) \
113+
__attribute__((swift_attr(_CXX_INTEROP_STRINGIFY(retain:_retain)))) \
114+
__attribute__((swift_attr(_CXX_INTEROP_STRINGIFY(release:_release))))
115+
116+
/// Specifies that a C++ `class` or `struct` is a reference type whose lifetime
117+
/// is presumed to be immortal, i.e. the reference to such object is presumed to
118+
/// always be valid. This annotation lets Swift import such a type as a reference
119+
/// type in Swift.
120+
////
121+
/// This example shows how to use this macro to let Swift know that
122+
/// a non-copyable singleton C++ class can be imported as a reference type in Swift:
123+
/// ```c++
124+
/// class SWIFT_IMMORTAL_REFERENCE
125+
/// LoggerSingleton : NonCopyable {
126+
/// public:
127+
/// static LoggerSingleton &getInstance();
128+
/// void log(int x);
129+
/// };
130+
/// ```
131+
///
132+
/// Then, the Swift programmer would be able to use it in the following manner:
133+
///
134+
/// ```swift
135+
/// let logger = LoggerSingleton.getInstance()
136+
/// logger.log(123)
137+
/// ```
138+
#define SWIFT_IMMORTAL_REFERENCE \
139+
__attribute__((swift_attr("import_reference"))) \
140+
__attribute__((swift_attr(_CXX_INTEROP_STRINGIFY(retain:immortal)))) \
141+
__attribute__((swift_attr(_CXX_INTEROP_STRINGIFY(release:immortal))))
142+
143+
/// Specifies that a C++ `class` or `struct` is a reference type whose lifetime
144+
/// is not managed automatically. The programmer must validate that any reference
145+
/// to such object is valid themselves. This annotation lets Swift import such a type as a reference type in Swift.
146+
#define SWIFT_UNSAFE_REFERENCE \
147+
__attribute__((swift_attr("import_reference"))) \
148+
__attribute__((swift_attr(_CXX_INTEROP_STRINGIFY(retain:immortal)))) \
149+
__attribute__((swift_attr(_CXX_INTEROP_STRINGIFY(release:immortal)))) \
150+
__attribute__((swift_attr("unsafe")))
151+
152+
/// Specifies a name that will be used in Swift for this declaration instead of its original name.
153+
#define SWIFT_NAME(_name) __attribute__((swift_name(#_name)))
154+
155+
/// Specifies that a specific C++ `class` or `struct` conforms to a
156+
/// a specific Swift protocol.
157+
///
158+
/// This example shows how to use this macro to conform a class template to a Swift protocol:
159+
/// ```
160+
/// template<class T>
161+
/// class SWIFT_CONFORMS_TO_PROTOCOL(SwiftModule.ProtocolName)
162+
/// CustomClass {};
163+
/// ```
164+
#define SWIFT_CONFORMS_TO_PROTOCOL(_moduleName_protocolName) \
165+
__attribute__((swift_attr(_CXX_INTEROP_STRINGIFY(conforms_to:_moduleName_protocolName))))
166+
167+
/// Specifies that a specific C++ method should be imported as a computed
168+
/// property. If this macro is specified on a getter, a getter will be
169+
/// synthesized. If this macro is specified on a setter, both a getter and
170+
/// setter will be synthesized.
171+
///
172+
/// For example:
173+
/// ```
174+
/// int getX() SWIFT_COMPUTED_PROPERTY;
175+
/// ```
176+
/// Will be imported as `var x: CInt {...}`.
177+
#define SWIFT_COMPUTED_PROPERTY \
178+
__attribute__((swift_attr("import_computed_property")))
179+
180+
/// Specifies that a specific **constant** C++ member function should be imported as
181+
/// `mutating` Swift method. This annotation should be added to constant C++ member functions
182+
/// that mutate `mutable` fields in a C++ object, to let Swift know that this function is still mutating
183+
/// and thus that it should become a `mutating` method in Swift.
184+
#define SWIFT_MUTATING \
185+
__attribute__((swift_attr("mutating")))
186+
187+
/// Specifies that a specific c++ type such class or struct should be imported as type marked
188+
/// as `@unchecked Sendable` type in swift. If this annotation is used, the type is therefore allowed to
189+
/// use safely across async contexts.
190+
///
191+
/// For example
192+
/// ```
193+
/// class SWIFT_UNCHECKED_SENDABLE CustomUserType
194+
/// { ... }
195+
/// ```
196+
/// Will be imported as `struct CustomUserType: @unchecked Sendable`
197+
#define SWIFT_UNCHECKED_SENDABLE \
198+
__attribute__((swift_attr("@Sendable")))
199+
200+
/// Specifies that a specific c++ type such class or struct should be imported
201+
/// as a non-copyable Swift value type.
202+
#define SWIFT_NONCOPYABLE \
203+
__attribute__((swift_attr("~Copyable")))
204+
205+
/// Specifies that a specific c++ type such class or struct should be imported
206+
/// as a non-escapable Swift value type when the non-escapable language feature
207+
/// is enabled.
208+
#define SWIFT_NONESCAPABLE \
209+
__attribute__((swift_attr("~Escapable")))
210+
211+
/// Specifies that a specific c++ type such class or struct should be imported
212+
/// as a escapable Swift value. While this matches the default behavior,
213+
/// in safe mode interop mode it ensures that the type is not marked as
214+
/// unsafe.
215+
#define SWIFT_ESCAPABLE \
216+
__attribute__((swift_attr("Escapable")))
217+
218+
/// Specifies that a C++ `class` or `struct` should be imported as a escapable
219+
/// Swift value if all of the specified template arguments are escapable.
220+
#define SWIFT_ESCAPABLE_IF(...) \
221+
__attribute__((swift_attr("escapable_if:" _CXX_INTEROP_CONCAT(__VA_ARGS__))))
222+
223+
/// Specifies that the return value is passed as owned for C++ functions and
224+
/// methods returning types annotated as `SWIFT_SHARED_REFERENCE`
225+
#define SWIFT_RETURNS_RETAINED __attribute__((swift_attr("returns_retained")))
226+
/// Specifies that the return value is passed as unowned for C++ functions and
227+
/// methods returning types annotated as `SWIFT_SHARED_REFERENCE`
228+
#define SWIFT_RETURNS_UNRETAINED \
229+
__attribute__((swift_attr("returns_unretained")))
230+
231+
/// Applied to a C++ foreign reference type annotated with
232+
/// SWIFT_SHARED_REFERENCE. Indicates that C++ APIs returning this type are
233+
/// assumed to return an unowned (+0) value by default, unless explicitly annotated
234+
/// with SWIFT_RETURNS_RETAINED.
235+
///
236+
/// For example:
237+
/// ```c++
238+
/// struct SWIFT_SHARED_REFERENCE(retainBar, releaseBar)
239+
/// SWIFT_RETURNED_AS_UNRETAINED_BY_DEFAULT
240+
/// Bar { ... };
241+
/// ```
242+
///
243+
/// In Swift, C++ APIs returning `Bar*` will be assumed to return an unowned
244+
/// value.
245+
#define SWIFT_RETURNED_AS_UNRETAINED_BY_DEFAULT \
246+
__attribute__((swift_attr("returned_as_unretained_by_default")))
247+
248+
/// Specifies that the non-public members of a C++ class, struct, or union can
249+
/// be accessed from extensions of that type, in the given file ID.
250+
///
251+
/// In other words, Swift's access controls will behave as if the non-public
252+
/// members of the annotated C++ class were privated declared in the specified
253+
/// Swift source file, rather than in a C++ header file/Clang module.
254+
///
255+
/// For example, we can annotate a C++ class definition like this:
256+
///
257+
/// ```c++
258+
/// class SWIFT_PRIVATE_FILEID("MySwiftModule/MySwiftFile.swift")
259+
/// MyCxxClass {
260+
/// private:
261+
/// void privateMethod();
262+
/// int privateStorage;
263+
/// };
264+
/// ```
265+
///
266+
/// Then, Swift extensions of `MyCxxClass` in `MySwiftModule/MySwiftFile.swift`
267+
/// are allowed to access `privateMethod()` and `privateStorage`:
268+
///
269+
/// ```swift
270+
/// //-- MySwiftModule/SwiftFile.swift
271+
/// extension MyCxxClass {
272+
/// func ext() {
273+
/// privateMethod()
274+
/// print("\(privateStorage)")
275+
/// }
276+
/// }
277+
/// ```
278+
///
279+
/// Non-public access is still forbidden outside of extensions and outside of
280+
/// the designated file ID.
281+
#define SWIFT_PRIVATE_FILEID(_fileID) \
282+
__attribute__((swift_attr("private_fileid:" _fileID)))
283+
284+
#else // #if _CXX_INTEROP_HAS_ATTRIBUTE(swift_attr)
285+
286+
// Empty defines for compilers that don't support `attribute(swift_attr)`.
287+
#define SWIFT_SELF_CONTAINED
288+
#define SWIFT_RETURNS_INDEPENDENT_VALUE
289+
#define SWIFT_SHARED_REFERENCE(_retain, _release)
290+
#define SWIFT_IMMORTAL_REFERENCE
291+
#define SWIFT_UNSAFE_REFERENCE
292+
#define SWIFT_NAME(_name)
293+
#define SWIFT_CONFORMS_TO_PROTOCOL(_moduleName_protocolName)
294+
#define SWIFT_COMPUTED_PROPERTY
295+
#define SWIFT_MUTATING
296+
#define SWIFT_UNCHECKED_SENDABLE
297+
#define SWIFT_NONCOPYABLE
298+
#define SWIFT_NONESCAPABLE
299+
#define SWIFT_ESCAPABLE
300+
#define SWIFT_ESCAPABLE_IF(...)
301+
#define SWIFT_RETURNS_RETAINED
302+
#define SWIFT_RETURNS_UNRETAINED
303+
#define SWIFT_PRIVATE_FILEID(_fileID)
304+
305+
#endif // #if _CXX_INTEROP_HAS_ATTRIBUTE(swift_attr)
306+
307+
#undef _CXX_INTEROP_HAS_ATTRIBUTE
308+
309+
#endif // SWIFT_CLANGIMPORTER_SWIFT_INTEROP_SUPPORT_H
310+
311+
#endif

Sources/OpenAttributeGraphCxx/include/OpenAttributeGraphCxx/Util/HashTable.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#define OPENATTRIBUTEGRAPH_CXX_UTIL_HASHTABLE_HPP
1010

1111
#include <OpenAttributeGraph/OAGBase.h>
12-
#include <swift/bridging>
12+
#include <OpenAttributeGraphCxx/SwiftBridging.h>
1313

1414
OAG_ASSUME_NONNULL_BEGIN
1515

Sources/OpenAttributeGraphCxx/include/OpenAttributeGraphCxx/Util/Heap.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#define OPENATTRIBUTEGRAPH_CXX_UTIL_HEAP_HPP
1010

1111
#include <OpenAttributeGraph/OAGBase.h>
12-
#include <swift/bridging>
12+
#include <OpenAttributeGraphCxx/SwiftBridging.h>
1313

1414
OAG_ASSUME_NONNULL_BEGIN
1515

0 commit comments

Comments
 (0)