Skip to content

Commit bca8e5d

Browse files
committed
Cache the build folder
The build folder cache is also added to the state file when persistence is used.
1 parent c118708 commit bca8e5d

File tree

6 files changed

+92
-29
lines changed

6 files changed

+92
-29
lines changed

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,11 @@ replacements may be added in the future, if necessary.
229229
**TIP:** Setting `binaryDir` to something like `"${sourceDir}/build/${presetName}"` is an easy way to separate build
230230
folders for different presets.
231231

232+
Note: The build folder is cached when using presets, to avoid having to read the information from the preset files
233+
again. This is automatically cleared when you change presets. If you need to clear the cache without changing presets
234+
(i.e., you edited the `binaryDir` field in the presets file), call the `cmake-integration-refresh-build-folder-cache`
235+
function.
236+
232237

233238
### Hiding some targets during completion
234239

@@ -298,7 +303,9 @@ for each target to annotate them with their target types in the completion list.
298303
use case and you'd rather avoid the performance cost, you can set `cmake-integration-annotate-targets` to `nil`. To
299304
apply this setting only to a specific project, configure it as a directory-local variable.
300305

301-
Note: This information is cached after the first retrieval.
306+
Note: This information is cached after the first retrieval. This cache can also be saved/restored when appropriated (see
307+
the [Persisting state](#persisting-state) section). If you need to clear the cache for some reason, call the
308+
`cmake-integration-refresh-target-type-cache` function.
302309

303310
## Integration with the Conan Package Manager
304311

cmake-integration-configure.el

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,9 @@ A list of preset names if obtained from `CMakePresets.json' and
146146
choose one of them (with completion)."
147147
(interactive)
148148

149+
;; Invalidate build folder cache
150+
(setq ci--build-folder-cache nil)
151+
149152
(let ((all-presets (ci-get-configure-presets)))
150153
(setq ci-configure-preset
151154
(ci-select-preset all-presets "Configure preset: "))

cmake-integration-core.el

Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,53 @@ or set `cmake-integration-build-dir' manually")))
135135
(error "Not in a project"))))
136136

137137

138+
;; This function may appear trivial since it only sets a variable with `setq`.
139+
;; However, it is designed as a separate function to allow its inclusion in
140+
;; `ci-functions-to-save-state`.
141+
(defun ci--set-build-folder-cache (build-folder)
142+
"Set the build folder cache to BUILD-FOLDER."
143+
(setq ci--build-folder-cache build-folder))
144+
145+
146+
(defun ci-refresh-build-folder-cache ()
147+
"Refresh the cached build folder."
148+
(interactive)
149+
(setq ci--build-folder-cache nil))
150+
151+
152+
(defun ci--get-build-folder-from-preset (configure-preset project-root-folder)
153+
"Get the build folder from CONFIGURE-PRESET.
154+
155+
If the build folder is a relative path, it is resolved against
156+
PROJECT-ROOT-FOLDER.
157+
158+
If `cmake-integration--build-folder-cache' is set, return that. If not,
159+
then the build folder is determined from the preset's `binaryDir' field,
160+
with any variable replacements done."
161+
(if ci--build-folder-cache
162+
ci--build-folder-cache
163+
(if-let* ((binaryDir-with-replacements
164+
(ci--get-binaryDir-with-replacements configure-preset)))
165+
166+
;; Cache the build folder for future calls and return it
167+
(ci--set-build-folder-cache
168+
(expand-file-name binaryDir-with-replacements project-root-folder))
169+
170+
;; Maybe the preset or any parent preset has no binaryDir set, or
171+
;; maybe a parent preset is missing. We need to warn the user and than
172+
;; we try using the manually set build dir instead
173+
(warn
174+
"Could not determine build folder from preset '%s'.\n - Maybe the preset and none of its parent presets has the 'binaryDir' field, or a parent preset is missing."
175+
(ci--get-preset-name configure-preset))
176+
(if-let* ((build-dir (ci--get-build-dir-if-set)))
177+
(progn
178+
(warn "Using manually set build folder: '%s'" build-dir)
179+
build-dir)
180+
(error
181+
"Build folder could not be determined from preset '%s' and no manual build folder is set"
182+
(ci--get-preset-name configure-preset))))))
183+
184+
138185
(defun ci-get-build-folder ()
139186
"Get the project build folder.
140187
@@ -151,22 +198,8 @@ resolved against the project root."
151198
(error "Not in a project"))
152199

153200
(if preset
154-
(if-let* ((binaryDir-with-replacements
155-
(ci--get-binaryDir-with-replacements preset)))
156-
(expand-file-name binaryDir-with-replacements project-root-folder)
157-
;; Maybe the preset or any parent preset has no binaryDir set, or
158-
;; maybe a parent preset is missing. We need to warn the user and than
159-
;; we try using the manually set build dir instead
160-
(warn
161-
"Could not determine build folder from preset '%s'.\n - Maybe the preset and none of its parent presets has the 'binaryDir' field, or a parent preset is missing."
162-
(ci--get-preset-name preset))
163-
(if-let* ((build-dir (ci--get-build-dir-if-set)))
164-
(progn
165-
(warn "Using manually set build folder: '%s'" build-dir)
166-
build-dir)
167-
(error
168-
"Build folder could not be determined from preset '%s' and no manual build folder is set"
169-
(ci--get-preset-name preset))))
201+
;; Get build directory from preset
202+
(ci--get-build-folder-from-preset preset project-root-folder)
170203

171204
;; Use manually set build directory or throw an error
172205
(ci--get-build-dir-if-set t))))

cmake-integration-persistence.el

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
ci-build-preset
5050
ci-test-preset
5151
ci-package-preset
52+
ci--build-folder-cache
5253

5354
;; CTest
5455
ci--ctest-label-include-regexp
@@ -64,6 +65,8 @@
6465
ci-select-build-preset
6566
ci-select-package-preset
6667
ci-select-conan-profile
68+
;; We also want to save state if the build folder cache is modified
69+
ci--set-build-folder-cache
6770
)
6871
"Functions which automatically save cmake-intregration state.
6972
@@ -201,12 +204,15 @@ exactly what `cmake-integration--build-current-state' returns."
201204

202205
;; TODO Add a test for this
203206
;;;###autoload (autoload 'cmake-integration-save-state "cmake-integration")
204-
(defun ci-save-state ()
207+
(defun ci-save-state (&optional _)
205208
"Save the current state of cmake-integration to persistent storage.
206209
207210
The location is determined by `cmake-integration-persist-location'.
208211
209-
If not in a CMake project, no state is saved."
212+
If not in a CMake project, no state is saved.
213+
214+
Note: The optional argument is not used. It is only present so this
215+
function can be used as an advice."
210216
(interactive)
211217
(if (ci-is-cmake-project-p)
212218
(when-let* ((state-file (ci--get-persist-file t))

cmake-integration-variables.el

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,10 @@ will be replaced by the project root." :type 'directory :group 'cmake-integratio
235235
"Cache for target types. Maps target names to their types.")
236236

237237

238+
(defvar ci--build-folder-cache nil
239+
"Cache for the build folder path (when presets are used).")
240+
241+
238242
(defvar ci-run-arguments "" "Command line arguments when running a target.")
239243

240244

tests/cmake-integration-tests.el

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,8 @@ test code from inside a 'test project'."
310310
;; Build folder is taken from the `binaryDir' field in
311311
;; `cmake-integration-configure-preset', which is an alist.
312312
;; Here we test with a binaryDir value with some replacements
313-
(let* ((ci-configure-preset
313+
(let* ((ci--build-folder-cache nil)
314+
(ci-configure-preset
314315
'((binaryDir . "${sourceDir}/build/${presetName}")
315316
(name . "ninjamulticonfig")))
316317
(project-root (ci--get-project-root-folder))
@@ -319,15 +320,17 @@ test code from inside a 'test project'."
319320
(should (filepath-equal-p (ci-get-build-folder) expected-build-folder)))
320321

321322
;; Now we test with a binaryDir that has a relative path
322-
(let* ((ci-configure-preset
323+
(let* ((ci--build-folder-cache nil)
324+
(ci-configure-preset
323325
'((binaryDir . "build/${presetName}") (name . "ninjamulticonfig")))
324326
(project-root (ci--get-project-root-folder))
325327
(expected-build-folder
326328
(expand-file-name "./build/ninjamulticonfig" project-root)))
327329
(should (filepath-equal-p (ci-get-build-folder) expected-build-folder)))
328330

329331
;; Test with a different preset
330-
(let* ((ci-configure-preset
332+
(let* ((ci--build-folder-cache nil)
333+
(ci-configure-preset
331334
'((binaryDir . "./build/${presetName}") (name . "Ninja")))
332335
(project-root (ci--get-project-root-folder))
333336
(expected-build-folder
@@ -669,7 +672,8 @@ test code from inside a 'test project'."
669672
(let ((ci-build-preset nil))
670673
(test-fixture-setup ;;
671674
"./test-project"
672-
(let ((expected-run-dir (ci--get-project-root-folder)))
675+
(let ((ci--build-folder-cache nil)
676+
(expected-run-dir (ci--get-project-root-folder)))
673677
(should
674678
(equal
675679
(ci-get-build-command "the_target")
@@ -680,7 +684,8 @@ test code from inside a 'test project'."
680684
;; Without setting a preset
681685
(test-fixture-setup ;;
682686
"./test-project-with-presets"
683-
(let ((expected-run-dir (ci--get-project-root-folder)))
687+
(let ((ci--build-folder-cache nil)
688+
(expected-run-dir (ci--get-project-root-folder)))
684689
(should
685690
(equal
686691
(ci-get-build-command "the_target")
@@ -691,7 +696,8 @@ test code from inside a 'test project'."
691696
;; Without a build preset
692697
(test-fixture-setup
693698
"./test-project-with-presets"
694-
(let ((expected-run-dir (ci--get-project-root-folder))
699+
(let ((ci--build-folder-cache nil)
700+
(expected-run-dir (ci--get-project-root-folder))
695701
(ci-configure-preset
696702
'("default" (name . "default") (binaryDir . "theBuildFolder"))))
697703
(should
@@ -704,7 +710,8 @@ test code from inside a 'test project'."
704710
;; With a build preset
705711
(test-fixture-setup
706712
"./test-project-with-presets"
707-
(let ((expected-run-dir (ci--get-project-root-folder))
713+
(let ((ci--build-folder-cache nil)
714+
(expected-run-dir (ci--get-project-root-folder))
708715
(ci-configure-preset
709716
'("config-preset"
710717
(name . "config-preset")
@@ -723,7 +730,8 @@ test code from inside a 'test project'."
723730
;; With a build preset and a target that has the configuration in the name
724731
(test-fixture-setup
725732
"./test-project-with-presets"
726-
(let ((expected-run-dir (ci--get-project-root-folder))
733+
(let ((ci--build-folder-cache nil)
734+
(expected-run-dir (ci--get-project-root-folder))
727735
(ci-configure-preset
728736
'("config-preset"
729737
(name . "config-preset")
@@ -742,7 +750,8 @@ test code from inside a 'test project'."
742750
;; Passing extra args
743751
(test-fixture-setup
744752
"./test-project-with-presets"
745-
(let ((expected-run-dir (ci--get-project-root-folder))
753+
(let ((ci--build-folder-cache nil)
754+
(expected-run-dir (ci--get-project-root-folder))
746755
(ci-configure-preset
747756
'("config-preset"
748757
(name . "config-preset")
@@ -762,7 +771,8 @@ test code from inside a 'test project'."
762771
(ert-deftest test-ci-get-conan-run-command ()
763772
(test-fixture-setup
764773
"./test-project"
765-
(let* ((project-root-folder (ci--get-project-root-folder))
774+
(let* ((ci--build-folder-cache nil)
775+
(project-root-folder (ci--get-project-root-folder))
766776
(build-folder (ci-get-build-folder))
767777
(conanfile-relative-path
768778
(file-relative-name project-root-folder build-folder)))

0 commit comments

Comments
 (0)