Skip to content

Conversation

@lucasromanomr
Copy link
Contributor

Added support for enable code coverage for all targets.

For auto scheme generation default valou ir False

xcodeproj(
        …
        scheme_autogeneration_config = xcschemes.autogeneration_config(
             test = xcschemes.autogeneration.test(
                 test_options = xcschemes.test_options(
                     app_language = "en",
                     app_region = "US",
                     code_coverage = False,
                 )
             )
        ),
        …
)

For configure in scheme:

xcschemes.scheme(
        …
        test = xcschemes.test(
            …
            test_options = xcschemes.test_options(
                app_language = "en",
                app_region = "US",
                code_coverage = True,
            ),
            …
        ),
        …
)
image

@lucasromanomr lucasromanomr requested a review from a team as a code owner November 19, 2024 18:25
@lucasromanomr lucasromanomr force-pushed the feat/add-coverage-options branch 4 times, most recently from 205a377 to f0b4bdf Compare November 19, 2024 18:44
Copy link
Contributor

@brentleyjones brentleyjones left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you rebase?

@erneestoc
Copy link

curious, was there a change that would make coverage work now? this is just for the schema and we'd still need something like this #1119 (comment) correct?

@brentleyjones
Copy link
Contributor

AFAIK coverage in Xcode is still broken.

@lucasromanomr
Copy link
Contributor Author

Can you rebase?

Yes, I will check everything I have here to do a rebase, and modify something if necessary.

curious, was there a change that would make coverage work now? this is just for the schema and we'd still need something like this #1119 (comment) correct?

The coverage is still broken, what is done here is just to set it as an option to enable, here we use internal adjustments to achieve coverage.

@lucasromanomr lucasromanomr force-pushed the feat/add-coverage-options branch from b76b73f to d493a75 Compare April 23, 2025 16:45
@lucasromanomr lucasromanomr force-pushed the feat/add-coverage-options branch 2 times, most recently from 69fa079 to 0900ce5 Compare November 4, 2025 15:22
@lucasromanomr
Copy link
Contributor Author

@brentleyjones After a while I went back to implement it, I did a rebase to incorporate the latest changes, and I also tested it in the project, and everything worked :)

One point to note is that Xcode coverage is still not working. This is just an option to enable it. Internally, we use a workaround to have coverage, which is why we implemented this option to enable it by default.

@brentleyjones
Copy link
Contributor

What’s the workaround?

@lucasromanomr
Copy link
Contributor Author

lucasromanomr commented Nov 4, 2025

What’s the workaround?

It would be following the same approach as here: #1119 (comment)

However, implemented differently.

In this case, internally at PicPay, we looked at the path of two apps and then at where several modules are located.

Specific configurations were added to the module target, and the apps were separated (in this case, we have two apps).

diff --git a/tools/worker/swift_runner.cc b/tools/worker/swift_runner.cc
index 6610e589e..e0807a4ee 100644
--- a/tools/worker/swift_runner.cc
+++ b/tools/worker/swift_runner.cc
@@ -302,6 +302,25 @@ bool SwiftRunner::ProcessArgument(
     }
 #endif
   };
+  
+  auto add_prefix_map_flags_for_custom_coverage = [&](const std::string& flag, const std::string& modules_dir_name) {
+    // cwd real (execution root)
+    const auto cwd = std::filesystem::current_path();
+
+    // Calcula target_path = canonical(cwd / modules_dir_name).parent_path();
+    const auto target_path = std::filesystem::canonical(cwd / modules_dir_name).parent_path();
+
+    consumer(flag);
+    consumer(std::filesystem::current_path().string() + "=" + target_path.string());
+
+#if __APPLE__
+    std::string developer_dir = "__BAZEL_XCODE_DEVELOPER_DIR__";
+    if (bazel_placeholder_substitutions_.Apply(developer_dir)) {
+        consumer(flag);
+        consumer(developer_dir + "=/PLACEHOLDER_DEVELOPER_DIR");
+    }
+#endif
+  };
 
   if (arg[0] == '@') {
     changed = ProcessPossibleResponseFile(arg, consumer);
@@ -313,6 +332,15 @@ bool SwiftRunner::ProcessArgument(
         // without breaking hermiticity.
         add_prefix_map_flags("-debug-prefix-map");
         changed = true;
+      } else if (new_arg == "-app-coverage-hack") {
+        add_prefix_map_flags_for_custom_coverage("-coverage-prefix-map", "Modules");
+        changed = true;
+      } else if (new_arg == "-app-coverage-hack-app-app1") {
+        add_prefix_map_flags_for_custom_coverage("-coverage-prefix-map", "App1");
+        changed = true;
+      } else if (new_arg == "-app-coverage-hack-app-app2") {
+        add_prefix_map_flags_for_custom_coverage("-coverage-prefix-map", "App2");
+        changed = true;
       } else if (new_arg == "-coverage-prefix-pwd-is-dot") {
         // Replace the $PWD with . to make the paths relative to the workspace
         // without breaking hermiticity.

in swift_library of app:

swift_library(
    name = "App1.library",
    srcs = [":App1SourceCode"],
    copts = select({
        "//Bazel_rules:scheme_prod": [],
        "//Bazel_rules:coverage_in_xcode": [
            "-Xwrapped-swift=-app-coverage-hack-app-1",
            "-D",
            "DEBUG",
        ],
        "//conditions:default": [
            "-D",
            "DEBUG",
        ],
    }),
    features = select({
        "//Bazel_rules:coverage_in_xcode": [
            "-swift.coverage_prefix_map",
            "-swift.file_prefix_map",
            "swift.coverage",
        ],
        "//conditions:default": [],
    }),
    linkopts = select({
        "//Bazel_rules:coverage_in_xcode": [
            "-fprofile-instr-generate",
        ],
        "//conditions:default": [],
    }),
    module_name = "App1",
    tags = ["manual"],
    visibility = ["//visibility:public"],
    deps = [...]
    alwayslink = True,
)

And in xcodeproj.bazelrc has a config:

build:rules_xcodeproj --//:enable_coverage_in_xcode=coverage

in BUILD.bazel

string_flag(
    name = "enable_coverage_in_xcode",
    build_setting_default = "no_coverage",
    visibility = ["//visibility:public"],
)

config_setting(
    name = "coverage_in_xcode",
    flag_values = {
        ":enable_coverage_in_xcode": "coverage",
    },
    visibility = ["//visibility:public"],
)

@lucasromanomr lucasromanomr force-pushed the feat/add-coverage-options branch 2 times, most recently from 873875e to 93d6116 Compare November 12, 2025 13:59
@lucasromanomr
Copy link
Contributor Author

@brentleyjones Is there any possibility that we have this option of at least leaving a configuration to enable coverage already in the schema?

I know that there is no support yet for the coverage to generate the coverage as we mentioned above, but we saw that there are own implementations for their own projects that generate the coverage, would having the option to already leave the coverage in the schema be a problem?

@karim-alweheshy
Copy link
Contributor

I wonder if we can achieve displaying the xcode coverage using

-path-equivalence

from https://llvm.org/docs/CommandGuide/llvm-cov.html#llvm-cov-report

@brentleyjones brentleyjones force-pushed the feat/add-coverage-options branch from 93d6116 to 94b4446 Compare December 2, 2025 21:15
@brentleyjones
Copy link
Contributor

Tests are failing.

@aaronsky aaronsky changed the title Add support for Enable Code Coverage for all targets in scheme test action options Support enabling Code Coverage for all targets in scheme test action Dec 3, 2025
@aaronsky aaronsky mentioned this pull request Dec 3, 2025
2 tasks
lucasromanomr and others added 2 commits December 3, 2025 11:46
Signed-off-by: Lucas Romano <lucasromanomr@gmail.com>

update autogeneration_config docs

Signed-off-by: Lucas Romano <lucasromanomr@gmail.com>

Update tools/generators/xcschemes/test/CreateAutomaticSchemeInfoTests.swift

Co-authored-by: Brentley Jones <github@brentleyjones.com>
Signed-off-by: Lucas Romano <lucasromanomr@gmail.com>

Update tools/generators/xcschemes/test/CreateAutomaticSchemeInfoTests.swift

Co-authored-by: Brentley Jones <github@brentleyjones.com>
Signed-off-by: Lucas Romano <lucasromanomr@gmail.com>

Update tools/generators/xcschemes/src/Generator/Generator.swift

Signed-off-by: Lucas Romano <lucasromanomr@gmail.com>
Signed-off-by: Aaron Sky <aaronsky@skyaaron.com>
Signed-off-by: Lucas Romano <lucasromanomr@gmail.com>
@lucasromanomr lucasromanomr force-pushed the feat/add-coverage-options branch from 11d52ea to 73c7bd3 Compare December 3, 2025 14:46
@brentleyjones brentleyjones merged commit d90788b into MobileNativeFoundation:main Dec 3, 2025
9 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants