|
| 1 | +# Hermiticity Solutions - Deep Dive |
| 2 | + |
| 3 | +## Problem Summary |
| 4 | + |
| 5 | +When you have WASI SDK installed at `/usr/local/wasi-sdk`, Bazel's `cc_configure` extension auto-detects it and hardcodes paths into the C++ toolchain configuration: |
| 6 | + |
| 7 | +```python |
| 8 | +link_flags = ["-fuse-ld=/usr/local/wasi-sdk/bin/ld64.lld", ...] |
| 9 | +``` |
| 10 | + |
| 11 | +This affects `rules_rust`'s `process_wrapper` (a host tool), causing non-hermetic builds. |
| 12 | + |
| 13 | +## Investigation Findings |
| 14 | + |
| 15 | +### Why cc_configure Runs Automatically |
| 16 | + |
| 17 | +From rules_cc source: |
| 18 | +```python |
| 19 | +cc_configure_extension = module_extension(implementation = _cc_configure_extension_impl) |
| 20 | + |
| 21 | +def _cc_configure_extension_impl(module_ctx): |
| 22 | + cc_autoconf_toolchains(name = "local_config_cc_toolchains") |
| 23 | + cc_autoconf(name = "local_config_cc") |
| 24 | +``` |
| 25 | + |
| 26 | +**Key Finding**: `rules_cc` version 0.2.4 **always** runs `cc_configure` during module extension initialization. There are **no parameters to disable it**. |
| 27 | + |
| 28 | +### What cc_configure Does |
| 29 | + |
| 30 | +1. Scans system for C++ compilers (checks `/usr/local`, `/usr/bin`, etc.) |
| 31 | +2. Finds `/usr/local/wasi-sdk/bin/clang` |
| 32 | +3. Generates toolchain configuration with hardcoded paths |
| 33 | +4. Creates `@@rules_cc++cc_configure_extension+local_config_cc//:toolchain` |
| 34 | + |
| 35 | +### How It Affects rules_rust |
| 36 | + |
| 37 | +From issue search: PR #3608 shows `rules_rust` explicitly uses `cc_toolchain` for linking. |
| 38 | + |
| 39 | +The `process_wrapper` binary (used for all Rust compilations) links against the auto-configured C++ toolchain, inheriting the non-hermetic flags. |
| 40 | + |
| 41 | +## Potential Solutions |
| 42 | + |
| 43 | +### Solution 1: Remove System WASI SDK ⭐ **Recommended** |
| 44 | + |
| 45 | +**Approach**: Remove `/usr/local/wasi-sdk` from your system |
| 46 | + |
| 47 | +```bash |
| 48 | +# Backup first if needed |
| 49 | +sudo mv /usr/local/wasi-sdk /usr/local/wasi-sdk.backup |
| 50 | + |
| 51 | +# Or fully remove |
| 52 | +sudo rm -rf /usr/local/wasi-sdk |
| 53 | +``` |
| 54 | + |
| 55 | +**Pros**: |
| 56 | +- ✅ Immediate fix |
| 57 | +- ✅ No code changes needed |
| 58 | +- ✅ Project already provides hermetic WASI SDK (version 27) |
| 59 | + |
| 60 | +**Cons**: |
| 61 | +- ❌ May affect other projects using system WASI SDK |
| 62 | +- ❌ Need to repeat on each developer machine |
| 63 | + |
| 64 | +**Impact**: After removal, `cc_configure` will use system Xcode/clang instead, which is fine for host tools. |
| 65 | + |
| 66 | +### Solution 2: Override Toolchain Priority via .bazelrc |
| 67 | + |
| 68 | +**Approach**: Register a higher-priority C++ toolchain |
| 69 | + |
| 70 | +```python |
| 71 | +# In .bazelrc |
| 72 | +build --extra_toolchains=@bazel_tools//tools/cpp:toolchain |
| 73 | +``` |
| 74 | + |
| 75 | +**Status**: ⚠️ Needs testing |
| 76 | + |
| 77 | +**Pros**: |
| 78 | +- ✅ Per-project configuration |
| 79 | +- ✅ Doesn't require system changes |
| 80 | +- ✅ Can be committed to repo |
| 81 | + |
| 82 | +**Cons**: |
| 83 | +- ❌ May not override auto-configured toolchain |
| 84 | +- ❌ Bazel toolchain resolution is complex |
| 85 | +- ❌ Needs verification it actually works |
| 86 | + |
| 87 | +**Next Steps**: Test if this successfully overrides the auto-configured toolchain. |
| 88 | + |
| 89 | +### Solution 3: Patch rules_cc to Add Disable Flag |
| 90 | + |
| 91 | +**Approach**: Submit PR to rules_cc to add optional parameter |
| 92 | + |
| 93 | +```python |
| 94 | +# Proposed API |
| 95 | +cc_configure = use_extension("@rules_cc//cc:extensions.bzl", "cc_configure") |
| 96 | +cc_configure.configure(auto_detect = False) # New parameter |
| 97 | +``` |
| 98 | + |
| 99 | +**Status**: 🔴 Not available |
| 100 | + |
| 101 | +**Pros**: |
| 102 | +- ✅ Clean solution |
| 103 | +- ✅ Helps entire Bazel ecosystem |
| 104 | + |
| 105 | +**Cons**: |
| 106 | +- ❌ Requires upstream changes |
| 107 | +- ❌ Long timeline (months to acceptance) |
| 108 | +- ❌ Maintenance burden |
| 109 | + |
| 110 | +**Next Steps**: |
| 111 | +1. Search for existing issues in bazelbuild/rules_cc |
| 112 | +2. Propose RFC if none exists |
| 113 | +3. Implement and submit PR |
| 114 | + |
| 115 | +### Solution 4: Configure PATH to Hide WASI SDK |
| 116 | + |
| 117 | +**Approach**: Manipulate PATH during Bazel repository phase |
| 118 | + |
| 119 | +```python |
| 120 | +# In a custom repository rule |
| 121 | +repository_ctx.execute( |
| 122 | + ["env", "PATH=/usr/bin:/bin", "bazel", "..."], |
| 123 | +) |
| 124 | +``` |
| 125 | + |
| 126 | +**Status**: ⚠️ Complex, may not work |
| 127 | + |
| 128 | +**Pros**: |
| 129 | +- ✅ Doesn't require removing system files |
| 130 | + |
| 131 | +**Cons**: |
| 132 | +- ❌ Bazel may not respect PATH changes during cc_configure |
| 133 | +- ❌ cc_configure uses absolute path detection, not just PATH |
| 134 | +- ❌ Very hacky |
| 135 | + |
| 136 | +**Likelihood of success**: Low |
| 137 | + |
| 138 | +### Solution 5: Accept as Known Limitation |
| 139 | + |
| 140 | +**Approach**: Document the issue and provide workarounds |
| 141 | + |
| 142 | +**Status**: ✅ Already done (HERMITICITY.md) |
| 143 | + |
| 144 | +**Pros**: |
| 145 | +- ✅ Honest about current state |
| 146 | +- ✅ No additional complexity |
| 147 | +- ✅ Builds still work correctly |
| 148 | + |
| 149 | +**Cons**: |
| 150 | +- ❌ Not truly hermetic |
| 151 | +- ❌ May cause issues in some environments |
| 152 | + |
| 153 | +## Related Upstream Issues |
| 154 | + |
| 155 | +### Found via gh CLI search: |
| 156 | + |
| 157 | +1. **bazelbuild/rules_rust#3619**: "Can't use rules_rust on windows with zig hermetic_cc_toolchain" |
| 158 | + - Shows `rules_rust` has hermetic C++ toolchain challenges |
| 159 | + - Different issue but similar root cause |
| 160 | + |
| 161 | +2. **bazelbuild/rules_rust#3608**: "Ensure the library search path from cc_toolchain is preferred" |
| 162 | + - Shows `rules_rust` explicitly uses `cc_toolchain` |
| 163 | + - Confirms the dependency on auto-configured toolchain |
| 164 | + |
| 165 | +3. **bazelbuild/rules_rust#3535**: "Bump rules_cc to 0.2.4" |
| 166 | + - Recent rules_cc upgrade |
| 167 | + - May have changed cc_configure behavior |
| 168 | + |
| 169 | +## Testing Solutions |
| 170 | + |
| 171 | +### Test Solution 1 (Remove WASI SDK) |
| 172 | + |
| 173 | +```bash |
| 174 | +# Backup |
| 175 | +sudo mv /usr/local/wasi-sdk /usr/local/wasi-sdk.backup |
| 176 | + |
| 177 | +# Clean rebuild |
| 178 | +bazel clean --expunge |
| 179 | +bazel build --execution_log_json_file=/tmp/test.log //tools/checksum_updater:checksum_updater |
| 180 | + |
| 181 | +# Analyze hermiticity |
| 182 | +python3 tools/hermetic_test/analyze_exec_log.py /tmp/test.log |
| 183 | + |
| 184 | +# Restore if needed |
| 185 | +sudo mv /usr/local/wasi-sdk.backup /usr/local/wasi-sdk |
| 186 | +``` |
| 187 | + |
| 188 | +### Test Solution 2 (Toolchain Override) |
| 189 | + |
| 190 | +```bash |
| 191 | +# Add to .bazelrc.test |
| 192 | +echo "build --extra_toolchains=@bazel_tools//tools/cpp:toolchain" > .bazelrc.test |
| 193 | + |
| 194 | +# Test |
| 195 | +bazel clean |
| 196 | +bazel build --bazelrc=.bazelrc.test --execution_log_json_file=/tmp/test.log //tools/checksum_updater:checksum_updater |
| 197 | + |
| 198 | +# Check if it helped |
| 199 | +grep "wasi-sdk" /tmp/test.log |
| 200 | +``` |
| 201 | + |
| 202 | +## Recommended Action Plan |
| 203 | + |
| 204 | +### Short-term (Today) |
| 205 | + |
| 206 | +1. ✅ Document the issue (done - HERMITICITY.md) |
| 207 | +2. ✅ Remove cc_configure from MODULE.bazel (done) |
| 208 | +3. **Recommended**: Remove `/usr/local/wasi-sdk` if not needed for other projects |
| 209 | + |
| 210 | +### Medium-term (This Week) |
| 211 | + |
| 212 | +1. Test Solution 2 (toolchain override in .bazelrc) |
| 213 | +2. Search bazelbuild/rules_cc for existing issues about disabling cc_configure |
| 214 | +3. If none exist, create issue proposing optional auto-detection |
| 215 | + |
| 216 | +### Long-term (Months) |
| 217 | + |
| 218 | +1. Monitor rules_cc and rules_rust for improvements |
| 219 | +2. Consider contributing PR to rules_cc if feature would be accepted |
| 220 | +3. Re-evaluate hermiticity when rules_cc 0.3+ is released |
| 221 | + |
| 222 | +## Conclusion |
| 223 | + |
| 224 | +**The best immediate solution is removing `/usr/local/wasi-sdk`** because: |
| 225 | +- You're not using it (project has hermetic WASI SDK 27) |
| 226 | +- It's a manual installation that most users don't have |
| 227 | +- No code changes or upstream work required |
| 228 | +- Instant fix |
| 229 | + |
| 230 | +The root cause (automatic cc_configure) is a Bazel ecosystem issue that affects the broader community and would benefit from an upstream fix. |
| 231 | + |
| 232 | +## Upstream Work |
| 233 | + |
| 234 | +### RFC and Fork |
| 235 | + |
| 236 | +We've created a fork of rules_cc to develop a proper upstream solution: |
| 237 | + |
| 238 | +- **Fork**: https://github.com/avrabe/rules_cc |
| 239 | +- **RFC Issue**: https://github.com/avrabe/rules_cc/issues/1 |
| 240 | +- **Proposal**: Add `auto_detect` parameter to `cc_configure` extension |
| 241 | + |
| 242 | +The RFC proposes adding a tag class to control auto-detection: |
| 243 | + |
| 244 | +```starlark |
| 245 | +# Proposed API |
| 246 | +cc_configure = use_extension("@rules_cc//cc:extensions.bzl", "cc_configure") |
| 247 | +cc_configure.configure(auto_detect = False) |
| 248 | +``` |
| 249 | + |
| 250 | +This would allow users to opt out of system toolchain detection while maintaining backwards compatibility (default `auto_detect = True`). |
| 251 | + |
| 252 | +See the full RFC at: https://github.com/avrabe/rules_cc/issues/1 |
0 commit comments