diff --git a/Sources/BazelPodsCore/Analyzer/Analyzers/BuildSettingsAnalyzer.swift b/Sources/BazelPodsCore/Analyzer/Analyzers/BuildSettingsAnalyzer.swift index 56dc532..aa06c39 100644 --- a/Sources/BazelPodsCore/Analyzer/Analyzers/BuildSettingsAnalyzer.swift +++ b/Sources/BazelPodsCore/Analyzer/Analyzers/BuildSettingsAnalyzer.swift @@ -11,6 +11,7 @@ struct BuildSettingsAnalyzer { struct Result { let swiftCopts: [String] let objcCopts: [String] + let ccCopts: [String] let linkOpts: [String] let objcDefines: [String] let xcconfig: [String: StarlarkNode] @@ -46,6 +47,7 @@ struct BuildSettingsAnalyzer { return Result( swiftCopts: parser.swiftCopts, objcCopts: parser.objcCopts, + ccCopts: parser.ccCopts, linkOpts: parser.linkOpts, objcDefines: parser.objcDefines, xcconfig: parser.xcconfig diff --git a/Sources/BazelPodsCore/Targets/AppleFramework.swift b/Sources/BazelPodsCore/Targets/AppleFramework.swift index 5e241d5..459977f 100644 --- a/Sources/BazelPodsCore/Targets/AppleFramework.swift +++ b/Sources/BazelPodsCore/Targets/AppleFramework.swift @@ -27,6 +27,7 @@ struct AppleFramework: BazelTarget { let objcCopts: [String] let swiftCopts: [String] + let ccCopts: [String] let linkOpts: [String] var linkDynamic: Bool @@ -65,6 +66,7 @@ struct AppleFramework: BazelTarget { self.xcconfig = buildSettings.xcconfig self.objcCopts = buildSettings.objcCopts self.swiftCopts = buildSettings.swiftCopts + self.ccCopts = buildSettings.ccCopts self.linkOpts = buildSettings.linkOpts self.testonly = sdkDeps.testonly @@ -125,6 +127,7 @@ struct AppleFramework: BazelTarget { .named(name: "weak_sdk_frameworks", value: weakSdkFrameworks.toStarlark()), .named(name: "objc_copts", value: objcCopts.toStarlark()), .named(name: "swift_copts", value: swiftCopts.toStarlark()), + .named(name: "cc_copts", value: ccCopts.toStarlark()), .named(name: "linkopts", value: linkOpts.toStarlark()), .named(name: "xcconfig", value: xcconfig.toStarlark()), .named(name: "visibility", value: ["//visibility:public"].toStarlark()) diff --git a/Sources/BazelPodsCore/XCConfig/XCConfigParser.swift b/Sources/BazelPodsCore/XCConfig/XCConfigParser.swift index f24946b..0691f62 100644 --- a/Sources/BazelPodsCore/XCConfig/XCConfigParser.swift +++ b/Sources/BazelPodsCore/XCConfig/XCConfigParser.swift @@ -13,10 +13,14 @@ final class XCConfigParser { private(set) var objcCopts: [String] = [] private(set) var linkOpts: [String] = [] private(set) var objcDefines: [String] = [] + private(set) var ccCopts: [String] = [] private let transformers: [String: XCConfigSettingTransformer] + private let options: BuildOptions private static let defaultTransformers: [XCConfigSettingTransformer] = [ HeaderSearchPathTransformer(), + UserHeaderSearchPathTransformer(), ApplicationExtensionAPIOnlyTransformer(), + CLANG_CXX_LANGUAGE_STANDARD_Transformer(), LinkOptsListTransformer("OTHER_LDFLAGS"), ObjCOptsListTransformer("OTHER_CFLAGS"), ObjCOptsListTransformer("OTHER_CPLUSPLUSFLAGS"), @@ -35,6 +39,7 @@ final class XCConfigParser { init(_ config: [String: String], options: BuildOptions, transformers: [XCConfigSettingTransformer] = defaultTransformers) { + self.options = options self.transformers = transformers.reduce([String: XCConfigSettingTransformer](), { result, transformer in var result = result @@ -42,6 +47,8 @@ final class XCConfigParser { return result }) + let config = replaceEnvVars(in: config) + for key in config.keys.sorted() { guard !XCSpecs.forceIgnore.contains(key) else { continue } let node: StarlarkNode? @@ -59,7 +66,7 @@ final class XCConfigParser { node = nil } var handled = false - if let node = node { + if let node = node, !XCSpecs.xcconfigIgnore.contains(key) { xcconfig[key] = node handled = true } @@ -68,6 +75,7 @@ final class XCConfigParser { objcCopts += (transformer as? ObjcCoptsProvider)?.objcCopts(value) ?? [] linkOpts += (transformer as? LinkOptsProvider)?.linkOpts(value) ?? [] objcDefines += (transformer as? ObjcDefinesProvider)?.objcDefines(value) ?? [] + ccCopts += (transformer as? CCCOptsProvider)?.cccOpts(value) ?? [] handled = true } if !handled { @@ -75,4 +83,55 @@ final class XCConfigParser { } } } + + private func replaceEnvVars(in config: [String: String]) -> [String: String] { + var config = config.mapValues({ + replacePodsEnvVars($0, options: options, absolutePath: false) + }) + while config.contains(where: { !$0.value.envVariables.isEmpty }) { + config = config.reduce(into: config, { result, value in + let key = value.key + var value = value.value + let envVars = value.envVariables + for envKey in envVars { + if let envValue = result[envKey] { + value = value.replacingOccurrences(of: "$(\(envKey))", with: envValue) + value = value.replacingOccurrences(of: "${\(envKey)}", with: envValue) + } else { + value = value.replacingOccurrences(of: "$(\(envKey))", with: "") + value = value.replacingOccurrences(of: "${\(envKey)}", with: "") + } + } + result[key] = value + }) + } + return config + } +} + +private extension String { + static let ignore = [ + "SDKROOT" + ] + var envVariables: [String] { + var result = [String]() + let pattern = #"\$\(([^$)]+)\)|\$\{([^$}]+)\}"# + do { + let regex = try NSRegularExpression(pattern: pattern) + let matches = regex.matches(in: self, range: NSRange(self.startIndex..., in: self)) + + for match in matches { + let nsRange = match.range(at: 1) + if let range = Range(nsRange, in: self) { + let innerVarName = String(self[range]) + if !Self.ignore.contains(innerVarName) { + result.append(innerVarName) + } + } + } + } catch { + log_debug("Error extracting env variables: \(error)") + } + return result + } } diff --git a/Sources/BazelPodsCore/XCConfig/XCConfigSettingTransformer.swift b/Sources/BazelPodsCore/XCConfig/XCConfigSettingTransformer.swift index a337417..f0517ed 100644 --- a/Sources/BazelPodsCore/XCConfig/XCConfigSettingTransformer.swift +++ b/Sources/BazelPodsCore/XCConfig/XCConfigSettingTransformer.swift @@ -27,6 +27,10 @@ protocol ObjcDefinesProvider { func objcDefines(_ value: String) -> [String] } +protocol CCCOptsProvider { + func cccOpts(_ value: String) -> [String] +} + struct HeaderSearchPathTransformer: XCConfigSettingTransformer, SwiftCoptsProvider, ObjcCoptsProvider { @@ -47,6 +51,26 @@ struct HeaderSearchPathTransformer: XCConfigSettingTransformer, } } +struct UserHeaderSearchPathTransformer: XCConfigSettingTransformer, + SwiftCoptsProvider, + ObjcCoptsProvider { + let key = "USER_HEADER_SEARCH_PATHS" + + func swiftCopts(_ value: String) -> [String] { + return xcconfigSettingToList(value) + .reduce([String]()) { partialResult, path in + return partialResult + [ + "-Xcc", "-I\(path.replacingOccurrences(of: "\"", with: ""))" + ] + } + } + + func objcCopts(_ value: String) -> [String] { + return xcconfigSettingToList(value) + .map({ "-I\($0.replacingOccurrences(of: "\"", with: ""))" }) + } +} + struct ApplicationExtensionAPIOnlyTransformer: XCConfigSettingTransformer, SwiftCoptsProvider, ObjcCoptsProvider { @@ -108,3 +132,11 @@ struct ObjcDefinesListTransformer: XCConfigSettingTransformer, return xcconfigSettingToList(value) } } + +struct CLANG_CXX_LANGUAGE_STANDARD_Transformer: XCConfigSettingTransformer, CCCOptsProvider { + let key = "CLANG_CXX_LANGUAGE_STANDARD" + + func cccOpts(_ value: String) -> [String] { + return ["-std=\(value)"] + } +} diff --git a/Sources/BazelPodsCore/XCConfig/XCSpecs.swift b/Sources/BazelPodsCore/XCConfig/XCSpecs.swift index bddcd2d..d4a5bdb 100644 --- a/Sources/BazelPodsCore/XCConfig/XCSpecs.swift +++ b/Sources/BazelPodsCore/XCConfig/XCSpecs.swift @@ -32,6 +32,10 @@ struct XCSpecs { "GCC_C_LANGUAGE_STANDARD" ] + static let xcconfigIgnore: [String] = [ + "CLANG_CXX_LANGUAGE_STANDARD" + ] + // com.apple.compilers.llvm.clang.1_0 static let clang: [XElement] = [ ("CLANG_ADDRESS_SANITIZER", .boolean), diff --git a/Tests/Recorded/FLEX/BUILD.bazel b/Tests/Recorded/FLEX/BUILD.bazel index 7f341d2..796560c 100644 --- a/Tests/Recorded/FLEX/BUILD.bazel +++ b/Tests/Recorded/FLEX/BUILD.bazel @@ -86,9 +86,9 @@ apple_framework( "WebKit", "UserNotifications" ], - xcconfig = { - "CLANG_CXX_LANGUAGE_STANDARD": "gnu++11" - }, + cc_copts = [ + "-std=gnu++11" + ], visibility = [ "//visibility:public" ] diff --git a/Tests/Recorded/LibTorch/BUILD.bazel b/Tests/Recorded/LibTorch/BUILD.bazel index d4c0605..0f655b4 100644 --- a/Tests/Recorded/LibTorch/BUILD.bazel +++ b/Tests/Recorded/LibTorch/BUILD.bazel @@ -65,6 +65,9 @@ apple_framework( "-Xcc", "-ITests/Pods/LibTorch/install/include/" ], + cc_copts = [ + "-std=c++14" + ], linkopts = [ "-force_load", "Tests/Pods/LibTorch/install/lib/libtorch.a", @@ -72,7 +75,6 @@ apple_framework( "Tests/Pods/LibTorch/install/lib/libtorch_cpu.a" ], xcconfig = { - "CLANG_CXX_LANGUAGE_STANDARD": "c++14", "CLANG_CXX_LIBRARY": "libc++" }, visibility = [ diff --git a/Tests/Recorded/MMKV/BUILD.bazel b/Tests/Recorded/MMKV/BUILD.bazel index 8e8bc93..683ad2c 100644 --- a/Tests/Recorded/MMKV/BUILD.bazel +++ b/Tests/Recorded/MMKV/BUILD.bazel @@ -78,8 +78,10 @@ apple_framework( sdk_frameworks = [ "CoreFoundation" ], + cc_copts = [ + "-std=gnu++17" + ], xcconfig = { - "CLANG_CXX_LANGUAGE_STANDARD": "gnu++17", "CLANG_CXX_LIBRARY": "libc++", "CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF": "NO" }, diff --git a/Tests/Recorded/MMKVAppExtension/BUILD.bazel b/Tests/Recorded/MMKVAppExtension/BUILD.bazel index 6f8cbfb..1050bd9 100644 --- a/Tests/Recorded/MMKVAppExtension/BUILD.bazel +++ b/Tests/Recorded/MMKVAppExtension/BUILD.bazel @@ -79,8 +79,10 @@ apple_framework( sdk_frameworks = [ "CoreFoundation" ], + cc_copts = [ + "-std=gnu++17" + ], xcconfig = { - "CLANG_CXX_LANGUAGE_STANDARD": "gnu++17", "CLANG_CXX_LIBRARY": "libc++", "CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF": "NO", "GCC_PREPROCESSOR_DEFINITIONS": [ diff --git a/Tests/Recorded/MMKVCore/BUILD.bazel b/Tests/Recorded/MMKVCore/BUILD.bazel index a66c170..c006186 100644 --- a/Tests/Recorded/MMKVCore/BUILD.bazel +++ b/Tests/Recorded/MMKVCore/BUILD.bazel @@ -108,8 +108,10 @@ apple_framework( "CoreFoundation", "UIKit" ], + cc_copts = [ + "-std=gnu++17" + ], xcconfig = { - "CLANG_CXX_LANGUAGE_STANDARD": "gnu++17", "CLANG_CXX_LIBRARY": "libc++", "CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF": "NO" }, diff --git a/Tests/Recorded/Realm/BUILD.bazel b/Tests/Recorded/Realm/BUILD.bazel index 15cbd4a..ea8f2b4 100644 --- a/Tests/Recorded/Realm/BUILD.bazel +++ b/Tests/Recorded/Realm/BUILD.bazel @@ -331,17 +331,24 @@ apple_framework( "-fapplication-extension", "-isystem", "Tests/Pods/Realm/include/core", - "-fvisibility-inlines-hidden" + "-fvisibility-inlines-hidden", + "-ITests/Pods/Realm/include", + "-ITests/Pods/Realm/include/Realm" ], swift_copts = [ - "-application-extension" + "-application-extension", + "-Xcc", + "-ITests/Pods/Realm/include", + "-Xcc", + "-ITests/Pods/Realm/include/Realm" + ], + cc_copts = [ + "-std=c++20" ], linkopts = [ - "$(REALM_LD_CLASSIC)", "-Wl,-unexported_symbols_list,Tests/Pods/Realm/Configuration/Realm/PrivateSymbols.txt" ], xcconfig = { - "CLANG_CXX_LANGUAGE_STANDARD": "c++20", "CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF": "NO", "OTHER_CPLUSPLUSFLAGS": [ "-isystem", diff --git a/Tests/Recorded/RealmSwift/BUILD.bazel b/Tests/Recorded/RealmSwift/BUILD.bazel index 4700528..8cccd1f 100644 --- a/Tests/Recorded/RealmSwift/BUILD.bazel +++ b/Tests/Recorded/RealmSwift/BUILD.bazel @@ -69,9 +69,6 @@ apple_framework( swift_copts = [ "-application-extension" ], - linkopts = [ - "$(REALM_LD_CLASSIC)" - ], visibility = [ "//visibility:public" ] diff --git a/Tests/Recorded/Sentry/BUILD.bazel b/Tests/Recorded/Sentry/BUILD.bazel index 17be9b0..08b5724 100644 --- a/Tests/Recorded/Sentry/BUILD.bazel +++ b/Tests/Recorded/Sentry/BUILD.bazel @@ -76,8 +76,10 @@ apple_framework( "Foundation", "CoreData" ], + cc_copts = [ + "-std=c++14" + ], xcconfig = { - "CLANG_CXX_LANGUAGE_STANDARD": "c++14", "CLANG_CXX_LIBRARY": "libc++", "GCC_ENABLE_CPP_EXCEPTIONS": "YES" }, diff --git a/Tests/Recorded/WCDB/BUILD.bazel b/Tests/Recorded/WCDB/BUILD.bazel index 561e36f..9a8d0c3 100644 --- a/Tests/Recorded/WCDB/BUILD.bazel +++ b/Tests/Recorded/WCDB/BUILD.bazel @@ -223,8 +223,10 @@ apple_framework( "-Xcc", "-ITests/Pods/WCDB" ], + cc_copts = [ + "-std=gnu++14" + ], xcconfig = { - "CLANG_CXX_LANGUAGE_STANDARD": "gnu++14", "CLANG_CXX_LIBRARY": "libc++", "GCC_PREPROCESSOR_DEFINITIONS": [ "SQLITE_WCDB=1", diff --git a/Tests/Recorded/libwebp/BUILD.bazel b/Tests/Recorded/libwebp/BUILD.bazel index 3a4cd66..0345895 100644 --- a/Tests/Recorded/libwebp/BUILD.bazel +++ b/Tests/Recorded/libwebp/BUILD.bazel @@ -80,6 +80,16 @@ apple_framework( ] } ), + objc_copts = [ + "-ITests/Pods/libwebp/", + "-ITests/Pods/libwebp/" + ], + swift_copts = [ + "-Xcc", + "-ITests/Pods/libwebp/", + "-Xcc", + "-ITests/Pods/libwebp/" + ], visibility = [ "//visibility:public" ] diff --git a/Tests/Recorded/libzstd/BUILD.bazel b/Tests/Recorded/libzstd/BUILD.bazel index 72d963e..d8610fa 100644 --- a/Tests/Recorded/libzstd/BUILD.bazel +++ b/Tests/Recorded/libzstd/BUILD.bazel @@ -66,9 +66,9 @@ apple_framework( ] } ), - xcconfig = { - "CLANG_CXX_LANGUAGE_STANDARD": "gnu++14" - }, + cc_copts = [ + "-std=gnu++14" + ], visibility = [ "//visibility:public" ] diff --git a/Tests/Recorded/zxing-cpp/BUILD.bazel b/Tests/Recorded/zxing-cpp/BUILD.bazel index 0ddeac8..8c0da33 100644 --- a/Tests/Recorded/zxing-cpp/BUILD.bazel +++ b/Tests/Recorded/zxing-cpp/BUILD.bazel @@ -83,9 +83,9 @@ apple_framework( "CoreImage", "CoreVideo" ], - xcconfig = { - "CLANG_CXX_LANGUAGE_STANDARD": "c++20" - }, + cc_copts = [ + "-std=c++20" + ], visibility = [ "//visibility:public" ]