Make dSYMs optional for Swift

Can now be disabled via the `SwiftForcesdSYMs` config setting.

PiperOrigin-RevId: 243869432
diff --git a/src/TulsiGenerator/BazelBuildSettingsFeatures.swift b/src/TulsiGenerator/BazelBuildSettingsFeatures.swift
index 0f813a7..443e8f9 100644
--- a/src/TulsiGenerator/BazelBuildSettingsFeatures.swift
+++ b/src/TulsiGenerator/BazelBuildSettingsFeatures.swift
@@ -48,8 +48,14 @@
     // This is handled through a wrapped_clang feature flag via the CROSSTOOL.
     //
     // The use of this flag does not affect any sources built by swiftc. At present time, all Swift
-    // compiled sources will be built with uncacheable, absolute paths, as the Swift compiler does
-    // not present an easy means of similarly normalizing all debug information.
-    return [.DebugPathNormalization]
+    // compiled sources will be built with uncacheable, absolute paths, as until Xcode 10.2, the
+    // Swift compiler did not present an easy means of similarly normalizing all debug information.
+    // Unfortunately, this still has some slight issues (which may be worked around via changes to
+    // wrapped_clang).
+    var features: Set<BazelSettingFeature> = [.DebugPathNormalization]
+    if options[.SwiftForcesdSYMs].commonValueAsBool ?? true {
+      features.insert(.SwiftForcesdSYMs)
+    }
+    return features
   }
 }
diff --git a/src/TulsiGenerator/BazelSettingsProvider.swift b/src/TulsiGenerator/BazelSettingsProvider.swift
index 4997566..d730f09 100644
--- a/src/TulsiGenerator/BazelSettingsProvider.swift
+++ b/src/TulsiGenerator/BazelSettingsProvider.swift
@@ -30,12 +30,18 @@
   /// not provide an easy means of similarly normalizing all debug information.
   case DebugPathNormalization
 
+  /// Presence of Swift forces dSYMs to be enabled. dSYMS were previously required for debugging.
+  /// See https://forums.swift.org/t/improving-swift-lldb-support-for-path-remappings/22694.
+  case SwiftForcesdSYMs
+
   /// TODO(b/111928007): Remove this and/or BazelSettingFeature once DebugPathNormalization is
   /// supported by all builds.
   public var stringValue: String {
     switch self {
       case .DebugPathNormalization:
         return "DebugPathNormalization"
+      case .SwiftForcesdSYMs:
+        return "SwiftForcesdSYMs"
     }
   }
 
@@ -53,6 +59,8 @@
         /// Technically this doesn't support swiftc, but we now support this feature for
         /// Cxx compilation alongside swift compilation.
         return true
+      case .SwiftForcesdSYMs:
+        return true
     }
   }
 
@@ -60,6 +68,8 @@
     switch self {
       case .DebugPathNormalization:
         return true
+      case .SwiftForcesdSYMs:
+        return false
     }
   }
 
@@ -72,6 +82,7 @@
   public var buildFlags: [String] {
     switch self {
       case .DebugPathNormalization: return ["--features=debug_prefix_map_pwd_is_dot"]
+      case .SwiftForcesdSYMs: return ["--apple_generate_dsym"]
     }
   }
 
@@ -101,10 +112,14 @@
   static let tulsiDebugFlags = BazelFlags(build: ["--compilation_mode=dbg"])
 
   /// Non-cacheable flags added by Tulsi for opt (Release) builds.
-  static let tulsiReleaseFlags = BazelFlags(build: ["--compilation_mode=opt", "--strip=always"])
+  static let tulsiReleaseFlags = BazelFlags(build: [
+      "--compilation_mode=opt",
+      "--strip=always",
+      "--apple_generate_dsym",
+  ])
 
   /// Non-cacheable flags added by Tulsi for all builds.
-  static let tulsiCommonNonCacheableFlags = BazelFlags(build:  [
+  static let tulsiCommonNonCacheableFlags = BazelFlags(build: [
       "--define=apple.add_debugger_entitlement=1",
       "--define=apple.propagate_embedded_extra_outputs=1",
       "--define=apple.experimental.tree_artifact_outputs=1",
@@ -112,21 +127,12 @@
 
   /// Cache-able flags added by Tulsi for builds.
   static let tulsiCacheableFlags = BazelFlagsSet(buildFlags: ["--announce_rc"])
+
   /// Non-cacheable flags added by Tulsi for builds.
   static let tulsiNonCacheableFlags = BazelFlagsSet(debug: tulsiDebugFlags,
                                                     release: tulsiReleaseFlags,
                                                     common: tulsiCommonNonCacheableFlags)
 
-  /// Flags added by Tulsi for builds which contain Swift.
-  /// - Always generate dSYMs for projects with Swift dependencies, as dSYMs are still required to
-  ///   expr or print variables within Bazel-built Swift modules in LLDB.
-  static let tulsiSwiftFlags = BazelFlagsSet(buildFlags: ["--apple_generate_dsym"])
-
-  /// Flags added by Tulsi for builds which do not contain Swift.
-  /// - Enable dSYMs only for Release builds.
-  static let tulsiNonSwiftFlags = BazelFlagsSet(
-      release: BazelFlags(build: ["--apple_generate_dsym"]))
-
   /// Universal flags that apply to all Bazel invocations (even queries).
   let universalFlags: BazelFlags
 
@@ -146,8 +152,8 @@
     self.init(universalFlags: universalFlags,
               cacheableFlags: BazelSettingsProvider.tulsiCacheableFlags,
               nonCacheableFlags: BazelSettingsProvider.tulsiNonCacheableFlags,
-              swiftFlags: BazelSettingsProvider.tulsiSwiftFlags,
-              nonSwiftFlags: BazelSettingsProvider.tulsiNonSwiftFlags)
+              swiftFlags: BazelFlagsSet(),
+              nonSwiftFlags: BazelFlagsSet())
   }
 
   public init(universalFlags: BazelFlags,
diff --git a/src/TulsiGenerator/TulsiOptionSet.swift b/src/TulsiGenerator/TulsiOptionSet.swift
index 5062787..cdf972b 100644
--- a/src/TulsiGenerator/TulsiOptionSet.swift
+++ b/src/TulsiGenerator/TulsiOptionSet.swift
@@ -32,6 +32,8 @@
       // Suppresses the Xcode warning and automated update on first opening of the generated
       // project.
       SuppressSwiftUpdateCheck,
+      // Whether or not containing a Swift dependency forces dSYM generation (used for debugging).
+      SwiftForcesdSYMs,
       // The path from a config file to its associated workspace root.
       WorkspaceRootPath,
 
@@ -315,6 +317,7 @@
     addBoolOption(.GenerateRunfiles, .Generic, false)
     addBoolOption(.ProjectPrioritizesSwift, .Generic, false)
     addBoolOption(.UseArm64_32, .Generic, false)
+    addBoolOption(.SwiftForcesdSYMs, .Generic, true)
 
     let defaultIdentifier = PlatformConfiguration.defaultConfiguration.identifier
     let platformCPUIdentifiers = PlatformConfiguration.allValidConfigurations.map { $0.identifier }
diff --git a/src/TulsiGenerator/en.lproj/Options.strings b/src/TulsiGenerator/en.lproj/Options.strings
index 77e7f81..15242aa 100644
--- a/src/TulsiGenerator/en.lproj/Options.strings
+++ b/src/TulsiGenerator/en.lproj/Options.strings
@@ -54,6 +54,8 @@
 "PostBuildPhaseRunScript" = "Build phase run script (post bazel build)";
 "PostBuildPhaseRunScript_DESC" = "Build phase run script that runs after the bazel_build.py script (i.e. `exec ${PATH_TO_SCRIPT}')";
 
+"SwiftForcesdSYMs" = "Swift code dependency enables dSYMs (required for debugging).";
+
 "SuppressSwiftUpdateCheck" = "Suppress Xcode Swift update check";
 "SuppressSwiftUpdateCheck_DESC" = "Suppresses Xcode's update notification for projects containing Swift code. This asserts that the Swift code is at least version 2.1.";