Skip to content

Commit

Permalink
Implement features required by Xcode (#2257)
Browse files Browse the repository at this point in the history
* Mark `-index-store-path` as Hard

Xcode sets it by default, but it can be disabled with
`COMPILER_INDEX_STORE_ENABLE=NO` Xcode build setting.

* Mark serialize-diagnostics and deps as artifacts

Xcode requires these files to be present after compiling, so they need
to be stored and restored for the build to complete.

* Update tests for the dep changes

* Add test for `-index-store-path`

* Add documentation for Xcode use

* Xcode integration test

* Add comment about wrapper script use
  • Loading branch information
scoopr authored Oct 2, 2024
1 parent d7763fc commit 2debbfc
Show file tree
Hide file tree
Showing 9 changed files with 581 additions and 17 deletions.
54 changes: 54 additions & 0 deletions .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -894,3 +894,57 @@ jobs:
cargo clean && cargo build
- name: lv10-stats-use
run: ${SCCACHE_PATH} --show-stats

xcode:
runs-on: macos-latest
env:
SCCACHE_PATH: target/debug/sccache
steps:
- name: Clone repository
uses: actions/checkout@v4

- name: Install rust
uses: ./.github/actions/rust-toolchain
with:
toolchain: "stable"

- name: Build sccache
run: |
cargo build
# Wrapper for the compiler invocation, so that we have a single command
# that calls sccache with the actual compiler argument.
# Just setting CC to be `sccache clang++` doesn't work as it is
# interpreted as the whole command that just happens to contain spaces.
- name: Create wrapper script
working-directory: tests/xcode
run: |
echo '#!/bin/sh' > wrapper.sh
echo "$GITHUB_WORKSPACE/${SCCACHE_PATH} $(xcrun -f cc) \$@" >> wrapper.sh
chmod +x wrapper.sh
echo "Wrapper script:"
cat wrapper.sh
- name: Start server
run: ${SCCACHE_PATH} --start-server

- name: Test compile xcode
working-directory: tests/xcode
run: |
xcodebuild -version
xcodebuild -xcconfig sccache.xcconfig
- name: Output
run: |
${SCCACHE_PATH} --show-stats
- name: Test compile xcode cached
working-directory: tests/xcode
run: |
xcodebuild clean
xcodebuild -xcconfig sccache.xcconfig
- name: Output
run: |
${SCCACHE_PATH} --show-stats
${SCCACHE_PATH} --show-stats | grep -e "Cache hits\s*[1-9]"
116 changes: 116 additions & 0 deletions docs/Xcode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# Using `sccache` with Xcode

It is possible to use `sccache` with Xcode with some setup.

### Running the daemon
Before building, you need to run the daemon outside of Xcode. This needs to be done because if `sccache` invocation happens to implicitly start the server daemon, the Xcode build will hang on the `sccache` invocation, waiting for the process to idle timeout.

You can do this in another terminal windows by calling
```sh
SCCACHE_LOG=info SCCACHE_START_SERVER=1 SCCACHE_NO_DAEMON=1 sccache
```

Or by setting it up in a `launchd` configuration, perhaps as `~/Library/LaunchAgents/sccache.plist` (note the paths in the plist):
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>sccache.server</string>
<key>ProgramArguments</key>
<array>
<string>/path/to/sccache</string>
</array>
<key>EnvironmentVariables</key>
<dict>
<key>SCCACHE_START_SERVER</key>
<string>1</string>
<key>SCCACHE_NO_DAEMON</key>
<string>1</string>
<key>SCCACHE_IDLE_TIMEOUT</key>
<string>0</string>
<key>SCCACHE_LOG</key>
<string>info</string>
</dict>

<key>StandardOutPath</key>
<string>/tmp/sccache.log</string>
<key>StandardErrorPath</key>
<string>/tmp/sccache.log</string>

</dict>
</plist>
```

### Setting it up for `xcodebuild`
When you override the `CC` variable for `xcodebuild`, it seems to always escape the spaces, so its not enough to just set it, but we need a wrapper script, something like

```sh
echo "#\!/bin/sh\nsccache $(xcrun -f cc) \$@" > wrapper.sh
chmod +x wrapper.sh
```
(YMMV if you need to select another sdk or toolchain for the xcrun)

Then you can invoke `xcodebuild` like so
```sh
xcodebuild CC="$(pwd)/wrapper.sh"
CLANG_ENABLE_MODULES=NO
COMPILER_INDEX_STORE_ENABLE=NO
```
Where the additional arguments are for disabling some features that `sccache` can't cache currently.

These build settings can also be put in a xcconfig file, like `sccache.xcconfig`
```
CC=$(SRCROOT)/wrapper.sh
CLANG_ENABLE_MODULES=NO
COMPILER_INDEX_STORE_ENABLE=NO
```
Which can then be invoked with
```sh
xcodebuild -xcconfig sccache.xcconfig
```


### Setting it up for `cmake` Xcode generator
While `cmake` has the convenient `CMAKE_<LANG>_COMPILER_LAUNCHER` for prepending tools like `sccache`, it is not supported for the Xcode generator.

It can be then integrated with having a template file for the wrapper script, `launcher.sh.in`:
```sh
#!/bin/sh
exec "${CCACHE_EXE}" "${LAUNCHER_COMPILER}" "$@"
```

And then configuring it something like
```cmake
# This bit before the first `project()`, as the COMPILER_LAUNCHER variables are read in then
if(DEFINED CCACHE)
find_program(CCACHE_EXE ${CCACHE} REQUIRED)
if(NOT CMAKE_GENERATOR STREQUAL "Xcode")
# Support for other generators should work with these
set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_EXE}")
set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_EXE}")
endif()
endif()
# .. your project stuff ..
# This bit needs to be after the first `project()` call, to have valid `CMAKE_C_COMPILER` variable.
# Alternatively in a file included with CMAKE_PROJECT_INCLUDE
if(DEFINED CCACHE)
if(CMAKE_GENERATOR STREQUAL "Xcode")
set(LAUNCHER_COMPILER ${CMAKE_C_COMPILER})
configure_file(${CMAKE_CURRENT_LIST_DIR}/launcher.sh.in launcher-cc.sh)
execute_process(COMMAND chmod a+rx
"${CMAKE_CURRENT_BINARY_DIR}/launcher-cc.sh")
set(CMAKE_XCODE_ATTRIBUTE_CC "${CMAKE_CURRENT_BINARY_DIR}/launcher-cc.sh")
set(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_MODULES "NO")
set(CMAKE_XCODE_ATTRIBUTE_COMPILER_INDEX_STORE_ENABLE "NO")
endif()
endif()
```
Then configuring with `-DCCACHE=sccache` should work on all generators.



Loading

0 comments on commit 2debbfc

Please sign in to comment.