Repository: bazelbuild/bazel
Issue: --apple_bitcode flag ineffective on iOS targets
Labels: type: bug
P2
team-Rules-CPP

(originally posted as https://github.com/bazelbuild/rules_apple/issues/163)

When creating an `apple_static_library` target like [1] and building this via `bazel build --apple_bitcode=embedded --ios_multi_cpus=arm64 -c opt //:myappletarget` the bitcode is not being included in the actual build causing issues when trying to run the code on-device similar to:

```
/Project/myapplelibrary.a(lib1.o) does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. for architecture arm64
```

However, specifying `--copt=-fembed-bitcode` causes a conflict with the `-fdata-sections` and `-ffunction-sections` flags that bazel uses by default.

How can this be resolved? Is there some way I can resolve this temporarily?
This is for `bazel 0.11.1` running on MacOS with latest released XCode.

The references to `b/73546952` and `b/35091927` at https://github.com/bazelbuild/rules_apple/blob/master/test/ios_application_test.sh#L838 and https://github.com/bazelbuild/rules_apple/blob/master/test/configurations.bzl#L21 make me believe you're tracking this issue internally already?

[1]
```
cc_library(
  name="mynativedependency"],
  srcs=["lib1.c"], hdrs=["lib1.h"])

apple_static_library(
    name="myappletarget",
    deps=[":mynativedependency"],
    platform_type="ios",
    minimum_os_version="9.0",
    visibility = ["//visibility:public"])
```

Issue comments:
this is an issue with `cc_library` not detecting the `--apple_bitcode` flag and/or the C++ crosstool being incompatible with bitcode
I've started to take a stab at this https://github.com/bazelbuild/bazel/pull/7356
This appears to be solved in 0.24.
Yep! Thanks!
I am still seeing this issue with Bazel 0.24 and 0.24.1. Steps to reproduce:

1. Clone the TensorFlow GitHub [repo](https://github.com/tensorflow/tensorflow).
2. Run the configure script:
`python configure.py` (can hit enter for all questions except for the last one that asks "Do you wish to build TensorFlow with iOS support?", enter `y`)
3. Build the `ios_static_framework` using `-c opt` and the Bitcode flags:
```
bazel build tensorflow/lite/experimental/ios:TensorFlowLiteC_framework -c opt --ios_multi_cpus=x86_64,armv7,arm64 --apple_bitcode=embedded --copt=-fembed-bitcode
```

Produces the following error:
```
tensorflow/tensorflow/lite/kernels/BUILD:115:1: C++ compilation of rule '//tensorflow/lite/kernels:kernel_util'
clang: error: -ffunction-sections is not supported with -fembed-bitcode
clang: error: -fdata-sections is not supported with -fembed-bitcode
```

Let me know if I am missing something here? Thank you!
@temrich does #7623 fix the issue for you? I may have run into the same issue when I built Bazel from source off of f8e38d1
@rajivshah3 yes that fixes the issue for me. Thank you!!

Pull request review comments:
Can we keep this if we don't have bitcode? I don't know if this is being relied upon by other folks who need to run install_name_tool.
Why are you removing this?
Sure, do you have an example of how we can do that in the crosstool format? 
I think this case is really only if you want to hide your symbols from Apple. That has the downside of them not being able to create valid dsyms for you, and their crash reporter not being able to show symbols. I feel like this should be something consumers opt into
I was wrong about this, reverting
I pushed a version of this that seems to work!
There's also an arm7s, does that need to be covered here?
Do this list need to be regularly updated as new devices are released? For example if there's an update that adds tvos_arm64e? 
So basically all Mac apps?
Does this list need to include just "darwin"?
if there's a toolchain for it (i.e. an apple_cc_toolchain) that goes with this crosstool, then possibly?
For now, yes, though we plan to refactor this a bit based on some of the experience we gained by porting our other CROSSTOOLs to Starlark. 
I don't think there's a toolchain for just "darwin" as a CPU, so this should be fine.
There is not https://github.com/bazelbuild/bazel/issues/3289
Right, the `darwin` whitelisting was just for apple_platform_type, that should still translate to `darwin_x86_64` cpu
re https://github.com/bazelbuild/bazel/pull/7151
thanks
To answer the other question, all mac apps that opt into this feature with `--apple_bitcode=embedded` will get this yes. But that's currently not on by default (there's a TODO stating that it should be)

Patch that resolved the issue:
diff --git a/tools/osx/crosstool/cc_toolchain_config.bzl.tpl b/tools/osx/crosstool/cc_toolchain_config.bzl.tpl
index 2dd5d2ffe7b4be..81bdaac48771b7 100644
--- a/tools/osx/crosstool/cc_toolchain_config.bzl.tpl
+++ b/tools/osx/crosstool/cc_toolchain_config.bzl.tpl
@@ -3333,7 +3333,6 @@ def _impl(ctx):
                     flag_groups = [
                         flag_group(
                             flags = [
-                                "-headerpad_max_install_names",
                                 "-no-canonical-prefixes",
                                 "-target",
                                 "arm64-apple-ios",
@@ -3354,7 +3353,6 @@ def _impl(ctx):
                     flag_groups = [
                         flag_group(
                             flags = [
-                                "-headerpad_max_install_names",
                                 "-no-canonical-prefixes",
                                 "-target",
                                 "arm64-apple-tvos",
@@ -3375,7 +3373,6 @@ def _impl(ctx):
                     flag_groups = [
                         flag_group(
                             flags = [
-                                "-headerpad_max_install_names",
                                 "-no-canonical-prefixes",
                                 "-target",
                                 "arm64e-apple-ios",
@@ -3396,7 +3393,6 @@ def _impl(ctx):
                     flag_groups = [
                         flag_group(
                             flags = [
-                                "-headerpad_max_install_names",
                                 "-no-canonical-prefixes",
                                 "-target",
                                 "armv7-apple-ios",
@@ -3417,7 +3413,6 @@ def _impl(ctx):
                     flag_groups = [
                         flag_group(
                             flags = [
-                                "-headerpad_max_install_names",
                                 "-no-canonical-prefixes",
                                 "-target",
                                 "armv7-apple-watchos",
@@ -3438,7 +3433,6 @@ def _impl(ctx):
                     flag_groups = [
                         flag_group(
                             flags = [
-                                "-headerpad_max_install_names",
                                 "-no-canonical-prefixes",
                                 "-target",
                                 "i386-apple-ios",
@@ -3459,7 +3453,6 @@ def _impl(ctx):
                     flag_groups = [
                         flag_group(
                             flags = [
-                                "-headerpad_max_install_names",
                                 "-no-canonical-prefixes",
                                 "-target",
                                 "i386-apple-watchos",
@@ -3480,7 +3473,6 @@ def _impl(ctx):
                     flag_groups = [
                         flag_group(
                             flags = [
-                                "-headerpad_max_install_names",
                                 "-no-canonical-prefixes",
                                 "-target",
                                 "x86_64-apple-ios",
@@ -3501,7 +3493,6 @@ def _impl(ctx):
                     flag_groups = [
                         flag_group(
                             flags = [
-                                "-headerpad_max_install_names",
                                 "-no-canonical-prefixes",
                                 "-target",
                                 "x86_64-apple-tvos",
@@ -3521,7 +3512,7 @@ def _impl(ctx):
                         ["objc-executable", "objc++-executable"],
                     flag_groups = [
                         flag_group(
-                            flags = ["-headerpad_max_install_names", "-no-canonical-prefixes"],
+                            flags = ["-no-canonical-prefixes"],
                         ),
                     ],
                 ),
@@ -3553,12 +3544,14 @@ def _impl(ctx):
                         ["objc-executable", "objc++-executable"],
                     flag_groups = [
                         flag_group(
-                            flags = ["-headerpad_max_install_names", "-no-canonical-prefixes"],
+                            flags = ["-no-canonical-prefixes"],
                         ),
                     ],
                 ),
             ],
         )
+    else:
+        fail("Unreachable")
 
     output_execpath_flags_feature = feature(
         name = "output_execpath_flags",
@@ -4363,8 +4356,6 @@ def _impl(ctx):
         provides = ["profile"],
     )
 
-    bitcode_embedded_feature = feature(name = "bitcode_embedded")
-
     link_libcpp_feature = feature(
         name = "link_libc++",
         enabled = True,
@@ -5169,8 +5160,6 @@ def _impl(ctx):
         ],
     )
 
-    bitcode_embedded_markers_feature = feature(name = "bitcode_embedded_markers")
-
     dead_strip_feature = feature(
         name = "dead_strip",
         flag_sets = [
@@ -5402,6 +5391,88 @@ def _impl(ctx):
         ],
     )
 
+    headerpad_feature = feature(
+        name = "headerpad",
+        enabled = True,
+        flag_sets = [
+            flag_set(
+                actions = all_link_actions + [
+                    ACTION_NAMES.objc_executable,
+                    ACTION_NAMES.objcpp_executable,
+                ],
+                flag_groups = [flag_group(flags = ["-headerpad_max_install_names"])],
+                with_features = [with_feature_set(not_features = [
+                    "bitcode_embedded",
+                    "bitcode_embedded_markers",
+                ])],
+            ),
+        ],
+    )
+
+    if (ctx.attr.cpu == "ios_arm64"
+        or ctx.attr.cpu == "ios_arm64e"
+        or ctx.attr.cpu == "ios_armv7"
+        or ctx.attr.cpu == "tvos_arm64"
+        or ctx.attr.cpu == "watchos_arm64_32"
+        or ctx.attr.cpu == "watchos_armv7k"
+        or ctx.attr.cpu == "darwin_x86_64"):
+        bitcode_embedded_feature = feature(
+            name = "bitcode_embedded",
+            flag_sets = [
+                flag_set(
+                    actions = [
+                        ACTION_NAMES.c_compile,
+                        ACTION_NAMES.cpp_compile,
+                        ACTION_NAMES.objc_compile,
+                        ACTION_NAMES.objcpp_compile,
+                    ],
+                    flag_groups = [flag_group(flags = ["-fembed-bitcode"])],
+                ),
+                flag_set(
+                    actions = all_link_actions + [
+                        ACTION_NAMES.objc_executable,
+                        ACTION_NAMES.objcpp_executable,
+                    ],
+                    flag_groups = [flag_group(flags = [
+                        "-fembed-bitcode",
+                        "-Xlinker",
+                        "-bitcode_verify",
+                        "-Xlinker",
+                        "-bitcode_hide_symbols",
+                        "-Xlinker",
+                        "-bitcode_symbol_map",
+                        "-Xlinker",
+                        "BITCODE_TOUCH_SYMBOL_MAP=%{bitcode_symbol_map_path}",
+                    ])],
+                ),
+            ],
+        )
+
+        bitcode_embedded_markers_feature = feature(
+            name = "bitcode_embedded_markers",
+            flag_sets = [
+                flag_set(
+                    actions = [
+                        ACTION_NAMES.c_compile,
+                        ACTION_NAMES.cpp_compile,
+                        ACTION_NAMES.objc_compile,
+                        ACTION_NAMES.objcpp_compile,
+                    ],
+                    flag_groups = [flag_group(flags = ["-fembed-bitcode-marker"])],
+                ),
+                flag_set(
+                    actions = all_link_actions + [
+                        ACTION_NAMES.objc_executable,
+                        ACTION_NAMES.objcpp_executable,
+                    ],
+                    flag_groups = [flag_group(flags = ["-fembed-bitcode-marker"])],
+                ),
+            ],
+        )
+    else:
+        bitcode_embedded_markers_feature = feature(name = "bitcode_embedded_markers")
+        bitcode_embedded_feature = feature(name = "bitcode_embedded")
+
     if (ctx.attr.cpu == "ios_arm64"
         or ctx.attr.cpu == "ios_arm64e"
         or ctx.attr.cpu == "ios_armv7"
@@ -5461,6 +5532,7 @@ def _impl(ctx):
                 gcc_coverage_map_format_feature,
                 apply_default_compiler_flags_feature,
                 include_system_dirs_feature,
+                headerpad_feature,
                 bitcode_embedded_feature,
                 bitcode_embedded_markers_feature,
                 objc_arc_feature,
@@ -5531,6 +5603,7 @@ def _impl(ctx):
                 gcc_coverage_map_format_feature,
                 apply_default_compiler_flags_feature,
                 include_system_dirs_feature,
+                headerpad_feature,
                 bitcode_embedded_feature,
                 bitcode_embedded_markers_feature,
                 objc_arc_feature,
@@ -5603,6 +5676,7 @@ def _impl(ctx):
                 gcc_coverage_map_format_feature,
                 apply_default_compiler_flags_feature,
                 include_system_dirs_feature,
+                headerpad_feature,
                 bitcode_embedded_feature,
                 bitcode_embedded_markers_feature,
                 objc_arc_feature,
@@ -5719,4 +5793,4 @@ cc_toolchain_config =  rule(
     },
     provides = [CcToolchainConfigInfo],
     executable = True,
-)
\ No newline at end of file
+)


Test patch: