Skip to content

Commit 49d8311

Browse files
authored
Add suppress_code_coverage flag for builds (#3285)
This adds a build flag options to bypass the supported Xcode coverage builds with `rules_xcodeproj`. We would find this flag useful for 2 reasons: 1. We have our own partially non-hermetic way to support coverage in Xcode as well and would like to opt-out of this flag. 2. For some projects where we don't really need/want to support coverage, sometimes developers happen to flip this flag anyways and end up with suboptimal build times. This just adds an opt-out flag in addition to the configured build setting so that we can choose whether or not the project should use the built-in coverage solution. This can be enabled by adding `--@rules_xcodeproj//xcodeproj:suppress_coverage_build` to your builds. --------- Signed-off-by: sebastian.shanus <sebastian.shanus@robinhood.com>
1 parent 6dbe31f commit 49d8311

13 files changed

Lines changed: 163 additions & 22 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ END_UNRELEASED_TEMPLATE
4848

4949
### New
5050

51-
* TBD
51+
* Added `--@rules_xcodeproj//xcodeproj:suppress_code_coverage` flag option to bypass building for Coverage even if it's configured in the scheme: [#3285](https://github.com/MobileNativeFoundation/rules_xcodeproj/pull/3285)
5252

5353
### Adjusted
5454

test/internal/pbxproj_partials/write_pbxproj_prefix_tests.bzl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ def _write_pbxproj_prefix_test_impl(ctx):
6363
project_options = ctx.attr.project_options,
6464
resolved_repositories_file = ctx.attr.resolved_repositories_file,
6565
separate_index_build_output_base = ctx.attr.separate_index_build_output_base,
66+
suppress_coverage_build = ctx.attr.suppress_coverage_build,
6667
target_ids_list = ctx.attr.target_ids_list,
6768
tool = None,
6869
workspace_directory = ctx.attr.workspace_directory,
@@ -155,6 +156,7 @@ write_pbxproj_prefix_test = unittest.make(
155156
"project_options": attr.string_dict(mandatory = True),
156157
"resolved_repositories_file": attr.string(mandatory = True),
157158
"separate_index_build_output_base": attr.bool(mandatory = True),
159+
"suppress_coverage_build": attr.bool(mandatory = True),
158160
"target_ids_list": attr.string(mandatory = True),
159161
"workspace_directory": attr.string(mandatory = True),
160162
"xcode_configurations": attr.string_list(mandatory = True),
@@ -193,6 +195,7 @@ def write_pbxproj_prefix_test_suite(name):
193195
project_options,
194196
resolved_repositories_file,
195197
separate_index_build_output_base = False,
198+
suppress_coverage_build = False,
196199
target_ids_list,
197200
workspace_directory,
198201
xcode_configurations,
@@ -219,6 +222,7 @@ def write_pbxproj_prefix_test_suite(name):
219222
project_options = project_options,
220223
resolved_repositories_file = resolved_repositories_file,
221224
separate_index_build_output_base = separate_index_build_output_base,
225+
suppress_coverage_build = suppress_coverage_build,
222226
target_ids_list = target_ids_list,
223227
workspace_directory = workspace_directory,
224228
xcode_configurations = xcode_configurations,
@@ -277,6 +281,8 @@ def write_pbxproj_prefix_test_suite(name):
277281
"some/path/to/index_import",
278282
# separateIndexBuildOutputBase
279283
"0",
284+
# suppressCoverageBuild
285+
"0",
280286
# resolvedRepositoriesFile
281287
"some/path/to/resolved_repositories_file",
282288
# minimumXcodeVersion
@@ -349,6 +355,8 @@ def write_pbxproj_prefix_test_suite(name):
349355
"some/path/to/index_import",
350356
# separateIndexBuildOutputBase
351357
"1",
358+
# suppressCoverageBuild
359+
"0",
352360
# resolvedRepositoriesFile
353361
"some/path/to/resolved_repositories_file",
354362
# minimumXcodeVersion

tools/generators/pbxproj_prefix/src/Generator/Arguments.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ Path to a file that contains the absolute path to the Bazel execution root.
4242
)
4343
var separateIndexBuildOutputBase: Bool
4444

45+
@Argument(
46+
help: "Whether to suppress coverage builds even when CLANG_COVERAGE_MAPPING is set.",
47+
transform: { $0 == "1" }
48+
)
49+
var suppressCoverageBuild: Bool
50+
4551
@Argument(
4652
help: """
4753
Path to a file that contains a string for the `RESOLVED_REPOSITORIES` build \

tools/generators/pbxproj_prefix/src/Generator/Environment.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,16 @@ extension Generator {
3131

3232
let pbxProjectBuildSettings: (
3333
_ config: String,
34+
_ createBuildSettingsAttribute: CreateBuildSettingsAttribute,
3435
_ importIndexBuildIndexstores: Bool,
35-
_ legacyIndexImport: String,
3636
_ indexImport: String,
3737
_ indexingProjectDir: String,
38-
_ separateIndexBuildOutputBase: Bool,
38+
_ legacyIndexImport: String,
3939
_ projectDir: String,
4040
_ resolvedRepositories: String,
41+
_ separateIndexBuildOutputBase: Bool,
42+
_ suppressCoverageBuild: Bool,
4143
_ workspace: String,
42-
_ createBuildSettingsAttribute: CreateBuildSettingsAttribute
4344
) -> String
4445

4546
let pbxProjectPrefixPartial: (

tools/generators/pbxproj_prefix/src/Generator/Generator.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,22 +49,23 @@ struct Generator {
4949
let pbxProjectPrefixPartial = environment.pbxProjectPrefixPartial(
5050
/*buildSettings:*/ environment.pbxProjectBuildSettings(
5151
/*config:*/ arguments.config,
52+
/*createBuildSettingsAttribute:*/
53+
environment.createBuildSettingsAttribute,
5254
/*importIndexBuildIndexstores:*/ arguments
5355
.importIndexBuildIndexstores,
54-
/*legacyIndexImport:*/ arguments.legacyIndexImport,
5556
/*indexImport:*/ arguments.indexImport,
5657
/*indexingProjectDir:*/ environment.indexingProjectDir(
5758
/*projectDir:*/ projectDir
5859
),
59-
/*separateIndexBuildOutputBase:*/ arguments.separateIndexBuildOutputBase,
60+
/*legacyIndexImport:*/ arguments.legacyIndexImport,
6061
/*projectDir:*/ projectDir,
6162
/*resolvedRepositories:*/
6263
try environment.readResolvedRepositoriesFile(
6364
arguments.resolvedRepositoriesFile
6465
),
65-
/*workspace:*/ arguments.workspace,
66-
/*createBuildSettingsAttribute:*/
67-
environment.createBuildSettingsAttribute
66+
/*separateIndexBuildOutputBase:*/ arguments.separateIndexBuildOutputBase,
67+
/*suppressCoverageBuild:*/ arguments.suppressCoverageBuild,
68+
/*workspace:*/ arguments.workspace
6869
),
6970
/*compatibilityVersion:*/ environment.compatibilityVersion(
7071
arguments.minimumXcodeVersion

tools/generators/pbxproj_prefix/src/Generator/PBXProjectBuildSettings.swift

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,16 @@ extension Generator {
2121
/// - workspace: The absolute path to the Bazel workspace.
2222
static func pbxProjectBuildSettings(
2323
config: String,
24+
createBuildSettingsAttribute: CreateBuildSettingsAttribute,
2425
importIndexBuildIndexstores: Bool,
25-
legacyIndexImport: String,
2626
indexImport: String,
2727
indexingProjectDir: String,
28-
separateIndexBuildOutputBase: Bool,
28+
legacyIndexImport: String,
2929
projectDir: String,
3030
resolvedRepositories: String,
31-
workspace: String,
32-
createBuildSettingsAttribute: CreateBuildSettingsAttribute
31+
separateIndexBuildOutputBase: Bool,
32+
suppressCoverageBuild: Bool,
33+
workspace: String
3334
) -> String {
3435
var buildSettings: [BuildSetting] = [
3536
.init(key: "ALWAYS_SEARCH_USER_PATHS", value: "NO"),
@@ -175,6 +176,14 @@ extension Generator {
175176
value: #""$(PROJECT_DIR)/../..""#
176177
),
177178
]
179+
if suppressCoverageBuild {
180+
buildSettings.append(
181+
.init(
182+
key: "BAZEL_SUPPRESS_COVERAGE_BUILD",
183+
value: "YES"
184+
)
185+
)
186+
}
178187
if separateIndexBuildOutputBase {
179188
buildSettings.append(contentsOf: [
180189
.init(

tools/generators/pbxproj_prefix/test/PBXProjectBuildSettingsTests.swift

Lines changed: 101 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -87,22 +87,114 @@ class PBXProjectBuildSettingsTests: XCTestCase {
8787

8888
let buildSettings = Generator.pbxProjectBuildSettings(
8989
config: config,
90+
createBuildSettingsAttribute: CreateBuildSettingsAttribute(),
9091
importIndexBuildIndexstores: importIndexBuildIndexstores,
91-
legacyIndexImport: legacyIndexImport,
9292
indexImport: indexImport,
9393
indexingProjectDir: indexingProjectDir,
94-
separateIndexBuildOutputBase: false,
94+
legacyIndexImport: legacyIndexImport,
9595
projectDir: projectDir,
9696
resolvedRepositories: resolvedRepositories,
97-
workspace: workspace,
98-
createBuildSettingsAttribute: CreateBuildSettingsAttribute()
97+
separateIndexBuildOutputBase: false,
98+
suppressCoverageBuild: false,
99+
workspace: workspace
99100
)
100101

101102
// Assert
102103

103104
XCTAssertNoDifference(buildSettings, expectedBuildSettings)
104105
}
105106

107+
func testSuppressCoverageBuild() {
108+
let config = "rxcp_custom_config"
109+
let importIndexBuildIndexstores = false
110+
let legacyIndexImport = "external/legacy-index-import"
111+
let indexImport = "external/index-import"
112+
let indexingProjectDir = "/some/indexing/project dir"
113+
let projectDir = "/some/project dir"
114+
let resolvedRepositories = #""" "/tmp/workspace""#
115+
let workspace = "/Users/TimApple/Star Board"
116+
117+
let expectedBuildSettings = #"""
118+
{
119+
ALWAYS_SEARCH_USER_PATHS = NO;
120+
ASSETCATALOG_COMPILER_GENERATE_ASSET_SYMBOLS = NO;
121+
BAZEL_CONFIG = rxcp_custom_config;
122+
BAZEL_EXTERNAL = "$(BAZEL_OUTPUT_BASE)/external";
123+
BAZEL_INTEGRATION_DIR = "$(INTERNAL_DIR)/bazel";
124+
BAZEL_LLDB_INIT = "$(HOME)/.lldbinit-rules_xcodeproj";
125+
BAZEL_OUT = "$(PROJECT_DIR)/bazel-out";
126+
BAZEL_OUTPUT_BASE = "$(_BAZEL_OUTPUT_BASE:standardizepath)";
127+
BAZEL_SUPPRESS_COVERAGE_BUILD = YES;
128+
BAZEL_WORKSPACE_ROOT = "$(SRCROOT)";
129+
BUILD_DIR = "$(SYMROOT)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
130+
BUILD_MARKER_FILE = "$(OBJROOT)/build_marker";
131+
BUILD_WORKSPACE_DIRECTORY = "$(SRCROOT)";
132+
CC = "$(BAZEL_INTEGRATION_DIR)/clang.sh";
133+
CLANG_ENABLE_OBJC_ARC = YES;
134+
CLANG_MODULES_AUTOLINK = NO;
135+
CODE_SIGNING_ALLOWED = NO;
136+
CODE_SIGN_STYLE = Manual;
137+
CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(BAZEL_PACKAGE_BIN_DIR)";
138+
COPY_PHASE_STRIP = NO;
139+
CXX = "$(BAZEL_INTEGRATION_DIR)/clang.sh";
140+
DEBUG_INFORMATION_FORMAT = dwarf;
141+
DSTROOT = "$(PROJECT_TEMP_DIR)";
142+
ENABLE_DEBUG_DYLIB = NO;
143+
ENABLE_DEFAULT_SEARCH_PATHS = NO;
144+
ENABLE_STRICT_OBJC_MSGSEND = YES;
145+
ENABLE_USER_SCRIPT_SANDBOXING = NO;
146+
GCC_OPTIMIZATION_LEVEL = 0;
147+
IMPORT_INDEX_BUILD_INDEXSTORES = NO;
148+
INDEXING_PROJECT_DIR__ = "$(INDEXING_PROJECT_DIR__NO)";
149+
INDEXING_PROJECT_DIR__NO = "/some/project dir";
150+
INDEXING_PROJECT_DIR__YES = "/some/indexing/project dir";
151+
INDEX_DATA_STORE_DIR = "$(INDEX_DATA_STORE_DIR)";
152+
INDEX_FORCE_SCRIPT_EXECUTION = YES;
153+
INDEX_IMPORT = "$(BAZEL_EXTERNAL)/index-import";
154+
INSTALL_PATH = "$(BAZEL_PACKAGE_BIN_DIR)/$(TARGET_NAME)/bin";
155+
INTERNAL_DIR = "$(PROJECT_FILE_PATH)/rules_xcodeproj";
156+
LD = "$(BAZEL_INTEGRATION_DIR)/ld";
157+
LDPLUSPLUS = "$(BAZEL_INTEGRATION_DIR)/ld";
158+
LD_DYLIB_INSTALL_NAME = "";
159+
LD_OBJC_ABI_VERSION = "";
160+
LD_RUNPATH_SEARCH_PATHS = "";
161+
LEGACY_INDEX_IMPORT = "$(BAZEL_EXTERNAL)/legacy-index-import";
162+
LIBTOOL = "$(BAZEL_INTEGRATION_DIR)/libtool";
163+
ONLY_ACTIVE_ARCH = YES;
164+
PROJECT_DIR = "/some/project dir";
165+
RESOLVED_REPOSITORIES = "\"\" \"/tmp/workspace\"";
166+
RULES_XCODEPROJ_BUILD_MODE = bazel;
167+
SRCROOT = "/Users/TimApple/Star Board";
168+
SUPPORTS_MACCATALYST = NO;
169+
SWIFT_EXEC = "$(BAZEL_INTEGRATION_DIR)/swiftc";
170+
SWIFT_OBJC_INTERFACE_HEADER_NAME = "";
171+
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
172+
SWIFT_USE_INTEGRATED_DRIVER = NO;
173+
SWIFT_VERSION = 5.0;
174+
TAPI_EXEC = /usr/bin/true;
175+
TARGET_TEMP_DIR = "$(PROJECT_TEMP_DIR)/$(BAZEL_PACKAGE_BIN_DIR)/$(COMPILE_TARGET_NAME)";
176+
USE_HEADERMAP = NO;
177+
VALIDATE_WORKSPACE = NO;
178+
_BAZEL_OUTPUT_BASE = "$(PROJECT_DIR)/../..";
179+
}
180+
"""#
181+
182+
let buildSettings = Generator.pbxProjectBuildSettings(
183+
config: config,
184+
createBuildSettingsAttribute: CreateBuildSettingsAttribute(),
185+
importIndexBuildIndexstores: importIndexBuildIndexstores,
186+
indexImport: indexImport,
187+
indexingProjectDir: indexingProjectDir,
188+
legacyIndexImport: legacyIndexImport,
189+
projectDir: projectDir,
190+
resolvedRepositories: resolvedRepositories,
191+
separateIndexBuildOutputBase: false,
192+
suppressCoverageBuild: true,
193+
workspace: workspace
194+
)
195+
XCTAssertNoDifference(buildSettings, expectedBuildSettings)
196+
}
197+
106198
func testSeparateIndexOutputBase() {
107199
// Arrange
108200

@@ -185,15 +277,16 @@ class PBXProjectBuildSettingsTests: XCTestCase {
185277

186278
let buildSettings = Generator.pbxProjectBuildSettings(
187279
config: config,
280+
createBuildSettingsAttribute: CreateBuildSettingsAttribute(),
188281
importIndexBuildIndexstores: importIndexBuildIndexstores,
189-
legacyIndexImport: legacyIndexImport,
190282
indexImport: indexImport,
191283
indexingProjectDir: indexingProjectDir,
192-
separateIndexBuildOutputBase: true,
284+
legacyIndexImport: legacyIndexImport,
193285
projectDir: projectDir,
194286
resolvedRepositories: resolvedRepositories,
195-
workspace: workspace,
196-
createBuildSettingsAttribute: CreateBuildSettingsAttribute()
287+
separateIndexBuildOutputBase: true,
288+
suppressCoverageBuild: false,
289+
workspace: workspace
197290
)
198291

199292
// Assert

xcodeproj/BUILD

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ string_flag(
4545
visibility = ["//visibility:public"],
4646
)
4747

48+
bool_flag(
49+
name = "suppress_coverage_build",
50+
build_setting_default = False,
51+
visibility = ["//visibility:public"],
52+
)
53+
4854
bool_flag(
4955
name = "separate_index_build_output_base",
5056
build_setting_default = False,

xcodeproj/internal/pbxproj_partials.bzl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,7 @@ def _write_pbxproj_prefix(
672672
project_options,
673673
resolved_repositories_file,
674674
separate_index_build_output_base,
675+
suppress_coverage_build,
675676
target_ids_list,
676677
tool,
677678
workspace_directory,
@@ -705,6 +706,8 @@ def _write_pbxproj_prefix(
705706
the `RESOLVED_REPOSITORIES` build setting.
706707
separate_index_build_output_base: Whether or not to use a separate
707708
output base for index builds.
709+
suppress_coverage_build: Whether or not to disable coverage builds even
710+
when `CLANG_COVERAGE_MAPPING` is set.
708711
target_ids_list: A `File` containing a list of target IDs.
709712
tool: The executable that will generate the `PBXProj` partial.
710713
workspace_directory: The absolute path to the Bazel workspace
@@ -749,6 +752,9 @@ def _write_pbxproj_prefix(
749752
# separateIndexBuildOutputBase
750753
args.add(TRUE_ARG if separate_index_build_output_base else FALSE_ARG)
751754

755+
# suppressCoverageBuild
756+
args.add(TRUE_ARG if suppress_coverage_build else FALSE_ARG)
757+
752758
# resolvedRepositoriesFile
753759
args.add(resolved_repositories_file)
754760

xcodeproj/internal/templates/generate_bazel_dependencies.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ if [ "$ACTION" == "indexbuild" ]; then
121121
apply_sanitizers=0
122122
elif [ "${ENABLE_PREVIEWS:-}" == "YES" ]; then
123123
readonly config="${BAZEL_CONFIG}_swiftuipreviews"
124-
elif [ "${CLANG_COVERAGE_MAPPING:-}" == YES ]; then
124+
elif [ "${CLANG_COVERAGE_MAPPING:-}" == YES ] && [ "${BAZEL_SUPPRESS_COVERAGE_BUILD:-}" != YES ]; then
125125
# Code coverage build
126126
#
127127
# CLANG_COVERAGE_MAPPING is set to YES when the active scheme's test action has code coverage enabled. It is configured

0 commit comments

Comments
 (0)