Skip to content

GH-51138: [Python] Fix ccache efficiency - #51139

Open
pitrou wants to merge 1 commit into
apache:mainfrom
pitrou:gh51138-python-ccache
Open

GH-51138: [Python] Fix ccache efficiency#51139
pitrou wants to merge 1 commit into
apache:mainfrom
pitrou:gh51138-python-ccache

Conversation

@pitrou

@pitrou pitrou commented Sep 2, 2026

Copy link
Copy Markdown
Member

Rationale for this change

Our current ccache support for PyArrow currently has two issues:

  1. The custom configuration is set using environment variables, but those are not passed to the build processes according to the CMake doc (I have verified this by enabling ccache logging to see the configuration values for each build command)
  2. Cython-generated C++ sources are written in the temporary build directory (because of build isolation), and therefore their path changes everytime. Consequently, ccache would fail reusing previous compilation results.

What changes are included in this PR?

  1. Pass custom ccache configuration using command-line arguments, not environment variables.
  2. Set the ccache configuration variable base_dir to the temporary build directory so that ccache strips away the build directory and hits previously cached results obtained from a different build directory.

Are these changes tested?

Yes, locally I confirmed that ccache now efficiently reuses compilation outputs for Cython-generated C++ sources.

Before:

real    0m50,313s
user    4m22,991s
sys     0m24,805s

After:

real    0m18,698s
user    1m14,727s
sys     0m7,518s

Are there any user-facing changes?

No.

@github-actions github-actions Bot added the awaiting review Awaiting review label Sep 2, 2026
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

⚠️ GitHub issue #51138 has been automatically assigned in GitHub to PR creator.

@pitrou

pitrou commented Sep 2, 2026

Copy link
Copy Markdown
Member Author

@github-actions crossbow submit -g python

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

Revision: a66cc75

Submitted crossbow builds: ursacomputing/crossbow @ actions-290df36268

Task Status
example-python-minimal-build-fedora-conda GitHub Actions
example-python-minimal-build-ubuntu-venv GitHub Actions
test-conda-python-3.11 GitHub Actions
test-conda-python-3.11-dask-latest GitHub Actions
test-conda-python-3.11-dask-upstream_devel GitHub Actions
test-conda-python-3.11-hdfs-2.9.2 GitHub Actions
test-conda-python-3.11-hdfs-3.2.1 GitHub Actions
test-conda-python-3.11-hypothesis GitHub Actions
test-conda-python-3.11-pandas-2.2.2-numpy-2.0.2 GitHub Actions
test-conda-python-3.11-spark-master GitHub Actions
test-conda-python-3.12 GitHub Actions
test-conda-python-3.12-pandas-latest-numpy-latest GitHub Actions
test-conda-python-3.13 GitHub Actions
test-conda-python-3.13-pandas-latest-numpy-2.1.3 GitHub Actions
test-conda-python-3.13-pandas-latest-numpy-latest GitHub Actions
test-conda-python-3.14 GitHub Actions
test-conda-python-3.14-cpython-debug GitHub Actions
test-conda-python-3.14-pandas-nightly-numpy-nightly GitHub Actions
test-conda-python-3.14-pandas-upstream_devel-numpy-nightly GitHub Actions
test-conda-python-emscripten GitHub Actions
test-debian-13-python-3-amd64 GitHub Actions
test-debian-13-python-3-i386 GitHub Actions
test-fedora-42-python-3 GitHub Actions
test-ubuntu-24.04-python-3 GitHub Actions

@rok

rok commented Sep 2, 2026

Copy link
Copy Markdown
Member

@github-actions crossbow submit test-ubuntu-22.04-cpp -p image=ubuntu-python

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

Revision: a66cc75

Submitted crossbow builds: ursacomputing/crossbow @ actions-ba899c1522

Task Status
test-ubuntu-22.04-cpp GitHub Actions

@pitrou

pitrou commented Sep 2, 2026

Copy link
Copy Markdown
Member Author

@github-actions crossbow submit test-ubuntu-22.04-cpp -p image=ubuntu-python

What's this @rok ?

Comment thread python/CMakeLists.txt
# 2. Set ccache base_dir to the build output directory as it is typically
# a temporary directory, and would otherwise fail caching because of
# using different paths everytime.
set(ccache_command ${CCACHE_FOUND} keep_comments_cpp=true base_dir=${CMAKE_BINARY_DIR})

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As per my 🤖 ccache pre-4.8 does not accept compiler options (keep_comments_cpp=true in this case). And testing on an older ccache I get:

> ccache keep_comments_cpp=true base_dir=/tmp gcc --version
ccache: error: Could not find compiler "keep_comments_cpp=true" in PATH

So users with old ccache building pyarrow would have this crash.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, are there any Python builds which use an old ccache?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think no, but users might. I think this is obscure enough to ignore.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there was an easy way to query the ccache version we could work around this to ensure a better UX. But I'm not sure how to do that. @kou ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(for the record, ccache 4.8 was released in March 2023)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My 🤖 suggest two options, preferring the first one. I would defer to @kou

diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt                                                                                                                                 
--- a/python/CMakeLists.txt                                                                                                                                                                
+++ b/python/CMakeLists.txt                                                                                                                                                                
@@ -136,7 +136,13 @@ if(CCACHE_FOUND                                                                                                                                                       
  # 2. Set ccache base_dir to the build output directory as it is typically                                                                                                               
  #    a temporary directory, and would otherwise fail caching because of                                                                                                                 
  #    using different paths everytime.                                                                                                                                                   
-  set(ccache_command ${CCACHE_FOUND} keep_comments_cpp=true base_dir=${CMAKE_BINARY_DIR})                                                                                                 
+  set(ccache_command                                                                                                                                                                      
+      ${CMAKE_COMMAND}                                                                                                                                                                    
+      -E                                                                                                                                                                                  
+      env                                                                                                                                                                                 
+      "CCACHE_COMMENTS=1"                                                                                                                                                                 
+      "CCACHE_BASEDIR=${CMAKE_BINARY_DIR}"                                                                                                                                                
+      ${CCACHE_FOUND})                                                                                                                                                                    
  set(CMAKE_C_COMPILER_LAUNCHER ${ccache_command})                                                                                                                                        
  set(CMAKE_CXX_COMPILER_LAUNCHER ${ccache_command})                                                                                                                                      
endif()                                                                                                                                                                                   

or

diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt                                                                                                                                 
--- a/python/CMakeLists.txt                                                                                                                                                                
+++ b/python/CMakeLists.txt                                                                                                                                                                
@@ -130,6 +130,17 @@ if(CCACHE_FOUND                                                                                                                                                       
 AND NOT CMAKE_CXX_COMPILER_LAUNCHER)                                                                                                                                                   
message(STATUS "Using ccache: ${CCACHE_FOUND}")                                                                                                                                         
                                                                                                                                                                                        
+  execute_process(                                                                                                                                                                        
+    COMMAND ${CCACHE_FOUND} --version                                                                                                                                                     
+    OUTPUT_VARIABLE ccache_version_output                                                                                                                                                 
+    OUTPUT_STRIP_TRAILING_WHITESPACE)                                                                                                                                                     
+  set(ccache_version "0")                                                                                                                                                                 
+  if(ccache_version_output                                                                                                                                                                
+     MATCHES "ccache version ([0-9]+\\.[0-9]+(\\.[0-9]+)?)")                                                                                                                              
+    set(ccache_version "${CMAKE_MATCH_1}")                                                                                                                                                
+  endif()                                                                                                                                                                                 
+                                                                                                                                                                                          
# 1. Let ccache preserve C++ comments, because some of them may be                                                                                                                      
#    meaningful to the compiler (ARROW-3985)                                                                                                                                            
# 2. Set ccache base_dir to the build output directory as it is typically                                                                                                               
@@ -137,7 +148,12 @@ if(CCACHE_FOUND                                                                                                                                                       
#    a temporary directory, and would otherwise fail caching because of                                                                                                                 
#    using different paths everytime.                                                                                                                                                   
-  set(ccache_command ${CCACHE_FOUND} keep_comments_cpp=true base_dir=${CMAKE_BINARY_DIR})                                                                                                 
+  if(ccache_version VERSION_GREATER_EQUAL 4.8)                                                                                                                                            
+    set(ccache_command ${CCACHE_FOUND} keep_comments_cpp=true                                                                                                                             
+                       base_dir=${CMAKE_BINARY_DIR})                                                                                                                                      
+  else()                                                                                                                                                                                  
+    message(STATUS "ccache ${ccache_version} does not support command-line configuration")                                                                                                
+    set(ccache_command ${CCACHE_FOUND})                                                                                                                                                   
+  endif()                                                                                                                                                                                 
set(CMAKE_C_COMPILER_LAUNCHER ${ccache_command})                                                                                                                                        
set(CMAKE_CXX_COMPILER_LAUNCHER ${ccache_command})                                                                                                                                      
endif()                                                                                                                                                                                   

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And I still think we don't need this.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, the env version is neat, but would it work on Windows?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As per 🤖:
cmake -E env is cross-platform and sets variables through CMake rather than Unix shell syntax, so it works on Windows with Ninja

@github-actions github-actions Bot added awaiting changes Awaiting changes and removed awaiting review Awaiting review labels Sep 2, 2026
@pitrou

pitrou commented Sep 2, 2026

Copy link
Copy Markdown
Member Author

@github-actions crossbow submit wheelcp311*

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

Revision: a66cc75

Submitted crossbow builds: ursacomputing/crossbow @ actions-131e0bf55a

Task Status
wheel-macos-monterey-cp311-cp311-amd64 GitHub Actions
wheel-macos-monterey-cp311-cp311-arm64 GitHub Actions
wheel-manylinux-2-28-cp311-cp311-amd64 GitHub Actions
wheel-manylinux-2-28-cp311-cp311-arm64 GitHub Actions
wheel-musllinux-1-2-cp311-cp311-amd64 GitHub Actions
wheel-musllinux-1-2-cp311-cp311-arm64 GitHub Actions
wheel-windows-cp311-cp311-amd64 GitHub Actions

@github-actions github-actions Bot added awaiting merge Awaiting merge awaiting changes Awaiting changes and removed awaiting changes Awaiting changes awaiting merge Awaiting merge labels Sep 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants