diff --git a/FirebaseCombineSwift.podspec b/FirebaseCombineSwift.podspec index a181b9b1a42..18b73a4dc7e 100644 --- a/FirebaseCombineSwift.podspec +++ b/FirebaseCombineSwift.podspec @@ -59,6 +59,7 @@ for internal testing only. It should not be published. s.pod_target_xcconfig = { 'HEADER_SEARCH_PATHS' => '"${PODS_TARGET_SRCROOT}"', + 'SWIFT_OBJC_INTEROP_MODE' => 'objcxx', } s.test_spec 'unit' do |unit_tests| @@ -81,7 +82,8 @@ for internal testing only. It should not be published. unit_tests.exclude_files = 'FirebaseCombineSwift/Tests/Unit/**/*Template.swift' unit_tests.requires_app_host = true unit_tests.pod_target_xcconfig = { - 'SWIFT_OBJC_BRIDGING_HEADER' => '$(PODS_TARGET_SRCROOT)/FirebaseCombineSwift/Tests/Unit/FirebaseCombine-unit-Bridging-Header.h' + 'SWIFT_OBJC_BRIDGING_HEADER' => '$(PODS_TARGET_SRCROOT)/FirebaseCombineSwift/Tests/Unit/FirebaseCombine-unit-Bridging-Header.h', + 'SWIFT_OBJC_INTEROP_MODE' => 'objcxx', } unit_tests.dependency 'OCMock' unit_tests.dependency 'FirebaseAuthTestingSupport' diff --git a/FirebaseCore/Sources/Public/FirebaseCore/FIRVersion.h b/FirebaseCore/Sources/Public/FirebaseCore/FIRVersion.h index 651edaf5c8b..65a3e764822 100644 --- a/FirebaseCore/Sources/Public/FirebaseCore/FIRVersion.h +++ b/FirebaseCore/Sources/Public/FirebaseCore/FIRVersion.h @@ -19,7 +19,16 @@ NS_ASSUME_NONNULL_BEGIN /** Returns the current version of Firebase. */ + +#ifdef __cplusplus +extern "C" { +#endif + NS_SWIFT_NAME(FirebaseVersion()) NSString* FIRFirebaseVersion(void); +#ifdef __cplusplus +} +#endif + NS_ASSUME_NONNULL_END diff --git a/FirebaseFirestore.podspec b/FirebaseFirestore.podspec index ff55ec358f1..2934bda631a 100644 --- a/FirebaseFirestore.podspec +++ b/FirebaseFirestore.podspec @@ -31,6 +31,12 @@ Google Cloud Firestore is a NoSQL document database built for automatic scaling, 'FirebaseFirestoreInternal/**/*.[mh]', 'Firestore/Swift/Source/**/*.swift', ] + + s.pod_target_xcconfig = { + # Enables C++ <-> Swift interop (by default it's only C) + "SWIFT_OBJC_INTEROP_MODE" => "objcxx", + } + s.resource_bundles = { "#{s.module_name}_Privacy" => 'Firestore/Swift/Source/Resources/PrivacyInfo.xcprivacy' } diff --git a/FirebaseFirestoreInternal.podspec b/FirebaseFirestoreInternal.podspec index 33a61dbca85..aee3a95f308 100644 --- a/FirebaseFirestoreInternal.podspec +++ b/FirebaseFirestoreInternal.podspec @@ -28,7 +28,10 @@ Google Cloud Firestore is a NoSQL document database built for automatic scaling, # Header files that constitute the interface to this module. Only Objective-C # headers belong here, since FirebaseFirestore is primarily an Objective-C # framework. - s.public_header_files = 'Firestore/Source/Public/FirebaseFirestore/*.h' + s.public_header_files = [ + 'Firestore/Source/Public/FirebaseFirestore/*.h', + 'Firestore/core/swift/include/*.h' + ] # source_files contains most of the header and source files for the project. # This includes files named in `public_header_files`. @@ -52,6 +55,7 @@ Google Cloud Firestore is a NoSQL document database built for automatic scaling, 'Firestore/core/include/**/*.{cc,mm}', 'Firestore/core/src/**/*.{cc,mm}', 'FirebaseAuth/Interop/**/*.h', + 'Firestore/core/swift/**/*.{cc,h}', ] # Internal headers that aren't necessarily globally unique. Most C++ internal diff --git a/Firestore/Source/API/FIRInterface.mm b/Firestore/Source/API/FIRInterface.mm new file mode 100644 index 00000000000..5dc0e5bac1c --- /dev/null +++ b/Firestore/Source/API/FIRInterface.mm @@ -0,0 +1,36 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "Firestore/Source/Public/FirebaseFirestore/FIRInterface.h" + +#import "Firestore/core/src/api/used_by_objective_c.h" +#include "Firestore/core/src/util/string_apple.h" + +using firebase::firestore::util::MakeString; + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRInterface + ++ (void)print:(NSString *)content { + CppInterfaceCalledByObjectiveC::print(MakeString(content)); +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/Firestore/Source/Public/FirebaseFirestore/FIRInterface.h b/Firestore/Source/Public/FirebaseFirestore/FIRInterface.h new file mode 100644 index 00000000000..222b7024e91 --- /dev/null +++ b/Firestore/Source/Public/FirebaseFirestore/FIRInterface.h @@ -0,0 +1,29 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRInterface : NSObject + +#pragma mark - Create Filter + ++ (void)print:(NSString *)content; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Firestore/Swift/Source/SwiftAPI/SwiftCppAPI.swift b/Firestore/Swift/Source/SwiftAPI/SwiftCppAPI.swift new file mode 100644 index 00000000000..fafeec43e98 --- /dev/null +++ b/Firestore/Swift/Source/SwiftAPI/SwiftCppAPI.swift @@ -0,0 +1,25 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if SWIFT_PACKAGE + @_exported import FirebaseFirestoreCpp +#endif // SWIFT_PACKAGE + +public class SwiftCallingCpp { + public init(_ value: String) { + CppInterfaceCalledBySwift.print(std.string(value)) + } +} diff --git a/Firestore/core/CMakeLists.txt b/Firestore/core/CMakeLists.txt index 65238165549..4da90c896ee 100644 --- a/Firestore/core/CMakeLists.txt +++ b/Firestore/core/CMakeLists.txt @@ -218,6 +218,8 @@ firebase_ios_glob( src/objc/*.h src/remote/*.cc src/remote/*.h + swift/include/*.h + swift/src/*.cc EXCLUDE ${nanopb_sources} ) diff --git a/Firestore/core/src/api/used_by_objective_c.cc b/Firestore/core/src/api/used_by_objective_c.cc new file mode 100644 index 00000000000..1333cecfe1f --- /dev/null +++ b/Firestore/core/src/api/used_by_objective_c.cc @@ -0,0 +1,22 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "used_by_objective_c.h" +#include + +void CppInterfaceCalledByObjectiveC::print(std::string content) { + std::cout << "C++ function runs with value: " << content << std::endl; +} diff --git a/Firestore/core/src/api/used_by_objective_c.h b/Firestore/core/src/api/used_by_objective_c.h new file mode 100644 index 00000000000..06360f441ba --- /dev/null +++ b/Firestore/core/src/api/used_by_objective_c.h @@ -0,0 +1,27 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBASE_USED_BY_SWIFT_H +#define FIREBASE_USED_BY_SWIFT_H + +#include + +class CppInterfaceCalledByObjectiveC { + public: + static void print(std::string content); +}; + +#endif // FIREBASE_USED_BY_SWIFT_H diff --git a/Firestore/core/swift/include/FirebaseFirestoreCpp.h b/Firestore/core/swift/include/FirebaseFirestoreCpp.h new file mode 100644 index 00000000000..dd769230b8f --- /dev/null +++ b/Firestore/core/swift/include/FirebaseFirestoreCpp.h @@ -0,0 +1,22 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBASE_FIREBASEFIRESTORECPP_H +#define FIREBASE_FIREBASEFIRESTORECPP_H + +#import "used_by_swift.h" + +#endif // FIREBASE_FIREBASEFIRESTORECPP_H diff --git a/Firestore/core/swift/include/used_by_swift.h b/Firestore/core/swift/include/used_by_swift.h new file mode 100644 index 00000000000..e4016b3c6a7 --- /dev/null +++ b/Firestore/core/swift/include/used_by_swift.h @@ -0,0 +1,27 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBASE_USED_BY_SWIFT_H +#define FIREBASE_USED_BY_SWIFT_H + +#include + +class CppInterfaceCalledBySwift { + public: + static void print(std::string content); +}; + +#endif // FIREBASE_USED_BY_SWIFT_H diff --git a/Firestore/core/swift/src/used_by_swift.cc b/Firestore/core/swift/src/used_by_swift.cc new file mode 100644 index 00000000000..d5261294e62 --- /dev/null +++ b/Firestore/core/swift/src/used_by_swift.cc @@ -0,0 +1,22 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../include/used_by_swift.h" +#include + +void CppInterfaceCalledBySwift::print(std::string content) { + std::cout << "C++ function runs with value: " << content << std::endl; +} diff --git a/Package.swift b/Package.swift index 55dfbba46e0..5a2b73deccf 100644 --- a/Package.swift +++ b/Package.swift @@ -476,7 +476,10 @@ let package = Package( dependencies: [ "FirebaseFirestoreTarget", ], - path: "FirebaseCombineSwift/Sources/Firestore" + path: "FirebaseCombineSwift/Sources/Firestore", + swiftSettings: [ + .interoperabilityMode(.Cxx), // C++ interoperability setting + ] ), .target( name: "FirebaseStorageCombineSwift", @@ -1171,7 +1174,10 @@ let package = Package( "FirebaseStorage", .product(name: "nanopb", package: "nanopb"), ], - path: "SwiftPMTests/swift-test" + path: "SwiftPMTests/swift-test", + swiftSettings: [ + .interoperabilityMode(.Cxx), // C++ interoperability setting + ] ), .testTarget( name: "analytics-import-test", @@ -1399,6 +1405,17 @@ func firestoreWrapperTarget() -> Target { ) } +func firebaseFirestoreCppTarget() -> Target { + return .target( + name: "FirebaseFirestoreCpp", + path: "Firestore/core/swift", + publicHeadersPath: "include", // Path to the public headers + cxxSettings: [ + .headerSearchPath("include"), // Ensure the header search path is correct + ] + ) +} + func firestoreTargets() -> [Target] { if ProcessInfo.processInfo.environment["FIREBASE_SOURCE_FIRESTORE"] != nil { return [ @@ -1469,6 +1486,7 @@ func firestoreTargets() -> [Target] { .linkedLibrary("c++"), ] ), + firebaseFirestoreCppTarget(), .target( name: "FirebaseFirestore", dependencies: [ @@ -1476,6 +1494,7 @@ func firestoreTargets() -> [Target] { "FirebaseCoreExtension", "FirebaseFirestoreInternalWrapper", "FirebaseSharedSwift", + "FirebaseFirestoreCpp", ], path: "Firestore", exclude: [ @@ -1496,7 +1515,10 @@ func firestoreTargets() -> [Target] { sources: [ "Swift/Source/", ], - resources: [.process("Source/Resources/PrivacyInfo.xcprivacy")] + resources: [.process("Source/Resources/PrivacyInfo.xcprivacy")], + swiftSettings: [ + .interoperabilityMode(.Cxx), // C++ interoperability setting + ] ), ] } @@ -1542,9 +1564,13 @@ func firestoreTargets() -> [Target] { "FirebaseCoreExtension", "leveldb", "FirebaseSharedSwift", + "FirebaseFirestoreCpp", ], path: "Firestore/Swift/Source", resources: [.process("Resources/PrivacyInfo.xcprivacy")], + swiftSettings: [ + .interoperabilityMode(.Cxx), // C++ interoperability setting + ], linkerSettings: [ .linkedFramework("SystemConfiguration", .when(platforms: [.iOS, .macOS, .tvOS])), .linkedFramework("UIKit", .when(platforms: [.iOS, .tvOS])), @@ -1561,5 +1587,6 @@ func firestoreTargets() -> [Target] { publicHeadersPath: "." ), firestoreInternalTarget, + firebaseFirestoreCppTarget(), ] }