Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ccache not found #46126

Open
dehlen opened this issue Aug 21, 2024 · 15 comments
Open

ccache not found #46126

dehlen opened this issue Aug 21, 2024 · 15 comments

Comments

@dehlen
Copy link
Contributor

dehlen commented Aug 21, 2024

Description

When opening Xcode not from the command line (via xed f.e.) but directly from Finder/Dock and the ccache option is enabled the build will fail because ccache can not be found even though it is installed. The issue exists because the PATH most certainly won't include the ccache binary (f.e. when installed via homebrew, it is located at /opt/homebrew/bin/ccache but Xcodes PATH does not include it). When setting the project up for ccache, the existence of ccache is checked. However this runs as part of pod install in a terminal environment with a potentially different PATH env variable. To fix this I think the ccache path found at pod install time should be passed to the ccache-clang and ccache-clang++.sh scripts.

Steps to reproduce

  1. Enable the ccache flag in your Podfile
react_native_post_install(
  installer,
  react_native_path,
  :ccache_enabled => true
)
  1. Install ccache
  2. Run pod install
  3. Open Xcode from Dock/Finder
  4. Open the projects xcworkspace
  5. Build the project

An error message will be visible stating:
[root_path]/node_modules/react-native/scripts/xcode/ccache-clang.sh: line 14: exec: ccache: not found
Command CompileC failed with a nonzero exit code

React Native Version

0.74.2

Affected Platforms

Build - MacOS

Output of npx react-native info

System:
  OS: macOS 14.6.1
  CPU: (8) arm64 Apple M1 Pro
  Memory: 84.19 MB / 32.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 20.11.0
    path: ~/.asdf/installs/nodejs/20.11.0/bin/node
  Yarn:
    version: 1.19.0
    path: ~/.asdf/shims/yarn
  npm:
    version: 10.2.4
    path: ~/.asdf/plugins/nodejs/shims/npm
  Watchman: Not Found
Managers:
  CocoaPods:
    version: 1.13.0
    path: /Users/David.vonKnobelsdorff/.asdf/shims/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 23.5
      - iOS 17.5
      - macOS 14.5
      - tvOS 17.5
      - visionOS 1.2
      - watchOS 10.5
  Android SDK: Not Found
IDEs:
  Android Studio: 2024.1 AI-241.15989.150.2411.11948838
  Xcode:
    version: 15.4/15F31d
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 17.0.7
    path: /usr/bin/javac
  Ruby:
    version: 3.2.4
    path: /Users/David.vonKnobelsdorff/.asdf/shims/ruby
npmPackages:
  "@react-native-community/cli": Not Found
  react: Not Found
  react-native: Not Found
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: false
iOS:
  hermesEnabled: true
  newArchEnabled: false

Stacktrace or Logs

[root_path]/node_modules/react-native/scripts/xcode/ccache-clang.sh: line 14: exec: ccache: not found
Command CompileC failed with a nonzero exit code

Reproducer

https://github.com/dehlen/rn-ccache-bug

Screenshots and Videos

No response

@react-native-bot
Copy link
Collaborator

⚠️ Newer Version of React Native is Available!
ℹ️ You are on a supported minor version, but it looks like there's a newer patch available - 0.74.5. Please upgrade to the highest patch for your minor or latest and verify if the issue persists (alternatively, create a new project and repro the issue in it). If it does not repro, please let us know so we can close out this issue. This helps us ensure we are looking at issues that still exist in the most recent releases.

@react-native-bot
Copy link
Collaborator

⚠️ Newer Version of React Native is Available!
ℹ️ You are on a supported minor version, but it looks like there's a newer patch available - undefined. Please upgrade to the highest patch for your minor or latest and verify if the issue persists (alternatively, create a new project and repro the issue in it). If it does not repro, please let us know so we can close out this issue. This helps us ensure we are looking at issues that still exist in the most recent releases.

@dehlen
Copy link
Contributor Author

dehlen commented Aug 23, 2024

Checked with the latest version (0.75.2) and the issue persists.

@cipolleschi
Copy link
Contributor

Hi @dehlen thanks for opening the issue. This is the code that sets up ccache and the scripts

IIUC, you are in a situation where ccache is present but in a path that is not accessible by Xcode, correct?
Does it work if you build from command line using yarn ios?

@dehlen
Copy link
Contributor Author

dehlen commented Aug 28, 2024

Yes that works since its run from the terminal where my path is set. Ccache is installed via homebrew and the installation directory is part of my terminal path. However macOS applications do not inherit the path and therefore ccache can not be found. I think what would mitigate this problem would be to add a user defined setting like CCHACHE_BINARY go the targets from the ruby script as part of the post_install hook where the path is found and printed out. Then update the shell script to use this variable instead of calling exec ccache.

I recognize that you can build the project without modifications however to build it in Xcode itself and not from the Terminal is broken for me when enabling cchache and i think this could potentially be fixed.

@cipolleschi
Copy link
Contributor

@dehlen thanks for the additional information. The issue can surely be fixed. As of now, we are a bit busy with the rollout of the New Architecture which has the highest priority, so we need to wait a bit for this to happen on our side. However, if you had some spare cycle and you'd like to try and submit a PR, I can help out and make sure we merge it.

@dehlen
Copy link
Contributor Author

dehlen commented Aug 29, 2024

I'll give it a shot. I won't be able to have a look at this before next week but will comment back with a PR next week.

@dehlen
Copy link
Contributor Author

dehlen commented Sep 2, 2024

Sorry to comment again without having a PR ready for you. I just had a look at the problem. I think the .xcode.env (and .local) files would be the right place to input a new environment variable (CCACHE_BINARY). I can do this in scripts/cocoapods/utils.rb:create_xcode_env_if_missing. I would create a export for .xcode.env with export CCACHE_BINARY=$(command -v ccache) and for the local variant echo 'export CCACHE_BINARY=#{ccache_path}' > #{file_path}.local if ccache is available. I then would assume calling the ccache scripts via with-environment.sh ccache_script would work.

I would choose this behaviour for the following reasons:

  1. If ccache is found in the PATH (running from the Terminal) the output of command -v ccache is used. If it is not in the PATH one has the ability to overwrite this in the .xcode.env.local. So no changes for existing users of this feature, unless you want to support this use case.
  2. I think with-environment.sh and the .xcode environment files are exactly for this purpose
  3. One could think about an error message like this:
CCACHE_BINARY="${CCACHE_BINARY:-$(command -v ccache || true)}"
if [ -z "$CCACHE_BINARY" ]; then
	echo "[Error] Could not find ccache. It looks like that the .xcode.env or .xcode.env.local " \
"files are misconfigured. Please check that they are exporting a valid CCACHE_BINARY " \
"variable, pointing to the ccache executable."
	exit 1
fi

However I am not quite sure why I can't make it run like that. Somehow when switching the CC, CXX, LD and LDPLUSPLUS variables to something like /absolute/path/to/with-environment.sh "/absolute/path/to/clang/or/clang++-script.sh" errors our for me although I added the CCACHE_BINARY export to my environment. Executing the with-environment.sh. I then tried to call with-environment.sh directly from the clang scripts without changing the way CC, CXX, LD and LDPLUSPLUS are configured like this:

SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"

REACT_NATIVE_CCACHE_CONFIGPATH=$SCRIPT_DIR/ccache.conf
# Provide our config file if none is already provided
export CCACHE_CONFIGPATH="${CCACHE_CONFIGPATH:-$REACT_NATIVE_CCACHE_CONFIGPATH}"

WITH_ENVIRONMENT="$SCRIPT_DIR/with-environment.sh"
. "$WITH_ENVIRONMENT"

CCACHE_BINARY="${CCACHE_BINARY:-$(command -v ccache || true)}"
if [ -z "$CCACHE_BINARY" ]; then
	echo "[Error] Could not find ccache. It looks like that the .xcode.env or .xcode.env.local " \
"files are misconfigured. Please check that they are exporting a valid CCACHE_BINARY " \
"variable, pointing to the ccache executable."
	exit 1
fi

exec "$CCACHE_BINARY" clang "$@"

However this does not work as well. The environment variables are not found f.e. PODS_ROOT is not found and therefore with-environment.sh does not find the xcode env files. I am willing to investigate a bit further but I feel like I am missing the kownledge regarding environment variables in Xcode and shell scripting to find a quick solution for now. I could pass the ccache path directly to the clang scripts however I am not sure whether this would be an acceptable solution?

@cipolleschi
Copy link
Contributor

Hi @dehlen, thanks for investigating the solution.

The with-environment.sh should be effectively the best approach.
I don't know why it is not working for the CC, etc. settings... might it be because they expect a single script/executable with no parameters? It might be that Xcode uses that executable as starting point and passes extra parameters that do not work properly.

Having the error might help.

@dehlen
Copy link
Contributor Author

dehlen commented Sep 2, 2024

Xcode passes parameters to ccache which is why I tried to call with-environment.sh from inside the ccache scripts. They pass all variables to ccache via $@. I will recreate my last approach and comment with the error messages.

EDIT: To make it even easier to debug I did the following things:

  1. Add CCACHE_BINARY to .xcode.env and .xcode.env.local
  2. Update the clang scripts with the following:
#!/bin/sh
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

# Get the absolute path of this script
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"

REACT_NATIVE_CCACHE_CONFIGPATH=$SCRIPT_DIR/ccache.conf
# Provide our config file if none is already provided
export CCACHE_CONFIGPATH="${CCACHE_CONFIGPATH:-$REACT_NATIVE_CCACHE_CONFIGPATH}"

echo "PODS_ROOT"
# This is empty!
echo "$PODS_ROOT"

# Override the default with the global environment
ENV_PATH="$PODS_ROOT/../.xcode.env"
if [ -f "$ENV_PATH" ]; then
    source "$ENV_PATH"
fi

# Override the global with the local environment
LOCAL_ENV_PATH="${ENV_PATH}.local"
if [ -f "$LOCAL_ENV_PATH" ]; then
    source "$LOCAL_ENV_PATH"
fi

# This script received parameters (for the compiler) which are passed to ccache via $@. 
exec "$CCACHE_BINARY" clang(++) "$@"

So I basically copy and pasted the relevant parts of with-environment.sh into the clang scripts to source the environment files. However the clang scripts do not received the PODS_ROOT environment, it is empty. Therefore sourcing does not work and the script fails. The same happens when running with-environment.sh instead of copy & pasting it directly into the script. PODS_ROOT is available as a user defined setting however the script does not receive these variables and I am not quite sure why. I tried changing the bang from #!/bin/sh to #!/bin/bash as with-environment.sh uses bash but this did not change anything.

@dehlen
Copy link
Contributor Author

dehlen commented Sep 2, 2024

I added a printenv to the script to see what environment values are available inside the ccache script:

CA_DEBUG_TRANSACTIONS=1
SHELL=/bin/zsh
TMPDIR=/var/folders/x3/lr5jdrkx0_34k92lf27vt5_c0000gq/T/
CCACHE_CONFIGPATH=/my/project/path/node_modules/react-native/scripts/xcode/ccache.conf
LLBUILD_LANE_ID=6
USER=MyUserName
LD_LIBRARY_PATH=/Applications/Xcode.app/Contents/Developer/../SharedFrameworks/
COMMAND_MODE=unix2003
LLBUILD_BUILD_ID=3364094211
UsePerConfigurationBuildLocations=YES
SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.VSXXhHK684/Listeners
__CF_USER_TEXT_ENCODING=0x1F7:0x0:0x3
PATH=/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin
__CFBundleIdentifier=com.apple.dt.Xcode
PWD=/my/project/path/Pods
XPC_FLAGS=0x0
XPC_SERVICE_NAME=0
SHLVL=1
HOME=/My/Home/Dir
LOGNAME=MyUserName
LLBUILD_TASK_ID=1030006014a
LLBUILD_CONTROL_FD=21
CA_ASSERT_MAIN_THREAD_TRANSACTIONS=1
_=/usr/bin/printenv

If I append the CCACHE_BINARY path like so for CC, LD, etc.:

ccache_clang_sh = "CCACHE_BINARY=#{ccache_path} #{ccache_clang_sh_path}"
ccache_clangpp_sh = "CCACHE_BINARY=#{ccache_path} #{ccache_clangpp_sh_path}"

this also fails with this error message:

error: unable to spawn process 'CCACHE_BINARY=/opt/homebrew/bin/ccache /my/project/path/node_modules/react-native/scripts/xcode/ccache-clang.sh' (No such file or directory) 

At this point the only thing I could think of is adding this to the ccache scripts (which is obviously working for my case but most certainly will not work for everyone):
export PATH="$PATH:/usr/local/bin:/opt/homebrew/bin/"

@dehlen
Copy link
Contributor Author

dehlen commented Sep 2, 2024

Another option might be to echo a warning if ccache can't be found and use clang or clang++ directly in that case. While this does not solve the issue at hand at least it would not result in a build issue. The user could then write some custom post_install hook or change the CC,LD environment variables to fix the problem locally. What do you think about this? I am not 100% sure which way would be preferred. Also it might be of course totally possible to find a better solution I haven't found yet. Open for any suggestions.

@cipolleschi
Copy link
Contributor

The warning can be a good alternative, but I'm afraid that people might not see it.

@ArindamRayMukherjee
Copy link

Issue persists at 0.76.0 and what more, in a project that uses C++ turbomodules, it prevents from diagnosing upgrading issues (in my case 0.74.2 to 0.76.0).

After following the upgrade guide at https://react-native-community.github.io/upgrade-helper/?from=0.74.2&to=0.76.0 , and doing pod install etc, the compilation process triggered by react-native run-ios (and xcode) fails with xcode error 65.
To diagnose the error, we need to go run the build process from XCode, but the reason above blocks me from doing that.

@builtbyproxy
Copy link

Throwing my two cents in, i've had this issue for a while now and found that clearing the contents of my .xcode.env.local fixed it. You can find more on the fix in this thread: #43285

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants