{"id":13995309,"url":"https://github.com/bazel-xcode/xchammer","last_synced_at":"2025-07-22T21:32:40.140Z","repository":{"id":33357284,"uuid":"125090058","full_name":"bazel-xcode/xchammer","owner":"bazel-xcode","description":"XCHammer generates Xcode projects from a Bazel Workspace.","archived":false,"fork":false,"pushed_at":"2023-01-03T18:57:19.000Z","size":14607,"stargazers_count":312,"open_issues_count":57,"forks_count":48,"subscribers_count":14,"default_branch":"master","last_synced_at":"2025-07-15T14:26:19.139Z","etag":null,"topics":["bazel","ios","xcode"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bazel-xcode.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-03-13T17:33:12.000Z","updated_at":"2025-06-28T10:14:45.000Z","dependencies_parsed_at":"2023-01-15T00:45:27.425Z","dependency_job_id":null,"html_url":"https://github.com/bazel-xcode/xchammer","commit_stats":null,"previous_names":["pinterest/xchammer"],"tags_count":20,"template":false,"template_full_name":null,"purl":"pkg:github/bazel-xcode/xchammer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bazel-xcode%2Fxchammer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bazel-xcode%2Fxchammer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bazel-xcode%2Fxchammer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bazel-xcode%2Fxchammer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bazel-xcode","download_url":"https://codeload.github.com/bazel-xcode/xchammer/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bazel-xcode%2Fxchammer/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265528855,"owners_count":23782769,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bazel","ios","xcode"],"created_at":"2024-08-09T14:03:20.678Z","updated_at":"2025-07-22T21:32:37.828Z","avatar_url":"https://github.com/bazel-xcode.png","language":"Swift","funding_links":[],"categories":["Swift"],"sub_categories":[],"readme":"# XCHammer\n\u003e If all you've got is Xcode, your only tool is a 🔨\n\nXCHammer generates Xcode projects from a [Bazel](https://bazel.build/) Workspace.\n\n- [x] Complete Bazel Xcode IDE integration\n    - [x] Bazel build and run via Xcode\n    - [x] Xcode test runner integration\n    - [x] Full LLDB support without DSYM generation\n    - [x] Autocompletion and indexing support\n    - [x] Renders Bazel's progress in Xcode's progress bar\n    - [x] Optionally import index's via [index-import](https://github.com/lyft/index-import) with [Run Scripts](sample/UrlGet/BUILD.bazel#L39)\n    - [x] Customize Bazel invocations for Xcode\n- [x] Incremental project generation\n- [x] [Focused](Docs/PinterestFocusedXcodeProjects.md#xcfocus-aka-focused-projects) Xcode projects\n- [x] Xcode build Bazel targets _without Bazel_\n- [x] Optionally Bazel build Xcode projects\n   - [x] Define and compose Xcode projects [in Skylark](#bazel-build-xcode-projects)\n   - [x] Builds reproducible and remote cacheable projects\n- [x] Automatically updates Xcode projects\n\n## Usage\n\n_Note: this README is intended to be a minimal, quick start guide to XCHammer.\nTo learn more about XCHammer see [Introducing\nXCHammer](Docs/FastAndReproducibleBuildsWithXCHammer.md) and [The XCHammer\nFAQ](Docs/XCHammerFAQ.md). To learn more about Bazel, see [Bazel for iOS\ndevelopers](Docs/BazelForiOSDevelopers.md). To learn about how Pinterest uses\nXCHammer see [Introducing\nXCHammer](Docs/FastAndReproducibleBuildsWithXCHammer.md) and [Pinterest Focused\nXcode Projects](PinterestFocusedXcodeProjects.md)_\n\n### Bazel build Xcode projects\n\nFirst, pull XCHammer into the `WORKSPACE` file:\n\n_Ideally, pull in a release optimized binary build to keep XCHammer's\ndependencies, Swift version, Xcode version, compiler flags, Bazel version, and\nbuild time outside of the main iOS/macOS application's WORKSPACE. To easily\nachieve this, GitHub CI creates a binary release artifact on receiving a new\ntag._\n\n```py\n# WORKSPACE\n# Recommended approach - the CI auto releases when you push a tag matching `v*`\n# The release prefix is the _tested_ bazel version, and XCHammer is often\n# forwards and backwards compatible\nhttp_archive(\n    name = \"xchammer\",\n    urls = [ \"https://github.com/pinterest/xchammer/releases/download/v3.4.1.0/xchammer.zip\" ],\n)\n\n```\n\nNext, create an `xcode_project` target including targets:\n```\n# BUILD.Bazel\nload(\"@xchammer//:BazelExtensions/xcodeproject.bzl\", \"xcode_project\")\n\nxcode_project(\n    name = \"MyProject\",\n    targets = [ \"//ios-app:ios-app\" ],\n)\n```\n\nFinally, build the project with Bazel\n```bash\nbazel build MyProject\n```\n\n### CLI Usage ( Non Bazel built projects )\n\nXCHammer also works as a standalone project generator. First build XCHammer and\ninstall to the path:\n\n```bash\n# Installs to `/usr/local/bin/`\nmake install\n```\nThen, generate using a [XCHammerConfig](Sources/XCHammer/XCHammerConfig.swift).\n\n```bash\nxchammer generate \u003cconfigPath\u003e\n```\n\n## Configuration Format\n\nXCHammer is configured via a `yaml` representation of [XCHammerConfig](https://github.com/pinterest/xchammer/blob/master/Sources/XCHammer/XCHammerConfig.swift).\n\nThe configuration describes projects that should be generated.\n\n```yaml\n# Generates a project containing the target ios-app\ntargets:\n    - \"//ios-app:ios-app\"\n\nprojects:\n    \"MyProject\":\n        paths:\n            - \"**\"\n```\n\n_See\n[XCHammerConfig.swift](https://github.com/pinterest/xchammer/blob/master/Sources/XCHammer/XCHammerConfig.swift)\nfor detailed documentation of the format._\n\n_To learn about how Pinterest uses XCHammer with Bazel locally check out\n[Pinterest Xcode Focused\nProjects](https://github.com/pinterest/xchammer/blob/master/Docs/PinterestFocusedXcodeProjects.md)._\n\n### Practical configuration examples\n\nBy default, XCHammer doesn't provide or enforce any build configuration\ndefaults in Bazel or Xcode. It exposes APIs to make it possible to configure\nBazel options Xcode dynamically, on a target level, on a project level, and per\narchitecture.\n\n_When using the CLI the\n[XCHammerConfig.swift](https://github.com/pinterest/xchammer/blob/master/Sources/XCHammer/XCHammerConfig.swift)\nis passed via an `.yml` file, and when using the `xcode_project` rule, the\n`XCHammerConfig` is passed into the rule._\n\n#### Project level\n\nThe parameter `bazel` makes it possible to select a wrapper command for Bazel.\nIn practice, this might be `bazelisk` or a wrapper script. In the case of\nXCHammer's own Xcode project, it's [tools/bazelwrapper](tools/bazelwrapper) to\nhandle make variable substitution at build time.\n\nThe [configuration](BazelExtensions/BazelExtensions/xchammerconfig.bzl) option,\n`build_bazel_platform_options` make it possible to configure architecture\nspecific settings for each target. Checkout\n[sample/UrlGet/BUILD.bazel](sample/UrlGet/BUILD.bazel) passes a `config` per\narchitecture in an iOS app.\n\n#### Target Level\n\nThe [configuration](BazelExtensions/BazelExtensions/xchammerconfig.bzl) option,\n`build_bazel_options` makes it possible, to set extra options on bazel target.\n\nFinally, the `build_bazel_template` makes it possible to run a script _inside_\nof Xcode before and after building. This also allows the user to pass in Bazel\narguments at build time.\n\nCheckout the [BUILD](BUILD.bazel) file and samples for examples.\n\n#### Build Time - debugging and static analysis\n\nAt the time of writing, there should be a way to build in \"debug mode\" in order\nfor LLDB to work. One possibility is to set this as a default and override when\nreleasing. By default, it's possible to pass variables to Bazel. For example,\nin XCHammer's own Xcode project,\n[tools/XCHammerXcodeRunscript.sh](tools/XCHammerXcodeRunscript.sh) it set's the\n`compilation_mode` based on Xcode's `CONFIGURATION` variable.\n\nFor the purpose of running static analysis, linters, and enabling other\noptions, it's possible to pass in extra bazel arguments at build time. For\nexample you might hinge running static analyzer on the analysis action in Xcode\nwhich sets `RUN_CLANG_STATIC_ANALYZER`. Bazel doesn't have a way to run linters\nor static analysis so it's totally up to the user how to run this.\n\n## Samples\n\n- [a Objective-C iOS app](sample/UrlGet)\n- [a Swift iOS app](sample/Tailor) \n- [a Swift macOS app](BUILD.bazel)\n\n\n### Xcode progress bar integration\n\nXCHammer provides a path to optionally integrate with Xcode's build system and\nprogress bar.\n\n- Install support for Xcode's progress bar for Xcode 11\n\n```\nxchammer install_xcode_build_system\n```\n\n- add `--build_event_binary_file=/tmp/bep.bep` to your `.bazelrc`\n- make sure Xcode's new build system is enabled\n\n\n## LLDB integration\n\nUnder Swift and clang compilers, the execution root is written into debug info\nin object files by default. XCHammer writes an lldbinit file to map this\ndirectory to the source root of source code, so that both breakpoints and\nsources work in Xcode.\n\nTo make outputs consistent and debuggable across machines, e.g. with remote\ncaching, it's recommended to use debug info remapping. Debug info remapping is a\ntechnique that simply remaps absolute paths in debug info to a stable location.\nLLDB then is able to map these to the source directory, via a\n`target.source-map`. By default, these Bazel flags are not configured and\nrequire adding additional flags to the build. Generally, these flags should set\nin _your_ `.bazelrc` for every build.\n\nClang provides debug info remapping via the `-fdebug-prefix-map` flag. For\nObjective-C, C, C++, debug info remapping is implemented at the crosstool level.\nConfigure Bazel to pass these arguments by setting\n`--copt=\"DEBUG_PREFIX_MAP_PWD=.\"` or providing a custom crosstool.  See setting\nup [crosstool\nlogic](https://github.com/bazelbuild/bazel/blob/master/tools/osx/crosstool/wrapped_clang.cc#L218)\nfor more info.\n\nStarting with Xcode 10.2, Swift provides debug info remapping via the\n`-debug-prefix-map` flag.  `rules_swift` supports the ability to [pass the debug\nremapping](https://github.com/bazelbuild/rules_swift/commit/43900104d279fcdffbca2d02dbc550492bf33353).\nSimply add `--swiftcopt=-Xwrapped-swift=-debug-prefix-pwd-is-dot` to remap debug\ninfo in Swift.\n\nXCHammer will automatically write a compatible remapping in the `.lldbinit`. Set\n`HAMMER_USE_DEBUG_INFO_REMAPPING=YES` via an `xcconfig`. See [XCHammer's BUILD\nfile](BUILD.bazel), for an example of this.\n\n_Generating a dSYM for development is not recommended due to the performance\nhit, and in practice is only required for Instruments.app._\n\n## Development\n\nPlease find more info about developing XCHammer in [The XCHammer FAQ](Docs/XCHammerFAQ.md). Pull requests welcome 💖.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbazel-xcode%2Fxchammer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbazel-xcode%2Fxchammer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbazel-xcode%2Fxchammer/lists"}