Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,11 @@ replacements may be added in the future, if necessary.
**TIP:** Setting `binaryDir` to something like `"${sourceDir}/build/${presetName}"` is an easy way to separate build
folders for different presets.

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


### Hiding some targets during completion

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

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

## Integration with the Conan Package Manager

Expand Down
3 changes: 3 additions & 0 deletions cmake-integration-configure.el
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ A list of preset names if obtained from `CMakePresets.json' and
choose one of them (with completion)."
(interactive)

;; Invalidate build folder cache
(setq ci--build-folder-cache nil)

(let ((all-presets (ci-get-configure-presets)))
(setq ci-configure-preset
(ci-select-preset all-presets "Configure preset: "))
Expand Down
65 changes: 49 additions & 16 deletions cmake-integration-core.el
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,53 @@ or set `cmake-integration-build-dir' manually")))
(error "Not in a project"))))


;; This function may appear trivial since it only sets a variable with `setq`.
;; However, it is designed as a separate function to allow its inclusion in
;; `ci-functions-to-save-state`.
(defun ci--set-build-folder-cache (build-folder)
"Set the build folder cache to BUILD-FOLDER."
(setq ci--build-folder-cache build-folder))


(defun ci-refresh-build-folder-cache ()
"Refresh the cached build folder."
(interactive)
(setq ci--build-folder-cache nil))


(defun ci--get-build-folder-from-preset (configure-preset project-root-folder)
"Get the build folder from CONFIGURE-PRESET.

If the build folder is a relative path, it is resolved against
PROJECT-ROOT-FOLDER.

If `cmake-integration--build-folder-cache' is set, return that. If not,
then the build folder is determined from the preset's `binaryDir' field,
with any variable replacements done."
(if ci--build-folder-cache
ci--build-folder-cache
(if-let* ((binaryDir-with-replacements
(ci--get-binaryDir-with-replacements configure-preset)))

;; Cache the build folder for future calls and return it
(ci--set-build-folder-cache
(expand-file-name binaryDir-with-replacements project-root-folder))

;; Maybe the preset or any parent preset has no binaryDir set, or
;; maybe a parent preset is missing. We need to warn the user and than
;; we try using the manually set build dir instead
(warn
"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."
(ci--get-preset-name configure-preset))
(if-let* ((build-dir (ci--get-build-dir-if-set)))
(progn
(warn "Using manually set build folder: '%s'" build-dir)
build-dir)
(error
"Build folder could not be determined from preset '%s' and no manual build folder is set"
(ci--get-preset-name configure-preset))))))


(defun ci-get-build-folder ()
"Get the project build folder.

Expand All @@ -151,22 +198,8 @@ resolved against the project root."
(error "Not in a project"))

(if preset
(if-let* ((binaryDir-with-replacements
(ci--get-binaryDir-with-replacements preset)))
(expand-file-name binaryDir-with-replacements project-root-folder)
;; Maybe the preset or any parent preset has no binaryDir set, or
;; maybe a parent preset is missing. We need to warn the user and than
;; we try using the manually set build dir instead
(warn
"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."
(ci--get-preset-name preset))
(if-let* ((build-dir (ci--get-build-dir-if-set)))
(progn
(warn "Using manually set build folder: '%s'" build-dir)
build-dir)
(error
"Build folder could not be determined from preset '%s' and no manual build folder is set"
(ci--get-preset-name preset))))
;; Get build directory from preset
(ci--get-build-folder-from-preset preset project-root-folder)

;; Use manually set build directory or throw an error
(ci--get-build-dir-if-set t))))
Expand Down
10 changes: 8 additions & 2 deletions cmake-integration-persistence.el
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
ci-build-preset
ci-test-preset
ci-package-preset
ci--build-folder-cache

;; CTest
ci--ctest-label-include-regexp
Expand All @@ -64,6 +65,8 @@
ci-select-build-preset
ci-select-package-preset
ci-select-conan-profile
;; We also want to save state if the build folder cache is modified
ci--set-build-folder-cache
)
"Functions which automatically save cmake-intregration state.

Expand Down Expand Up @@ -201,12 +204,15 @@ exactly what `cmake-integration--build-current-state' returns."

;; TODO Add a test for this
;;;###autoload (autoload 'cmake-integration-save-state "cmake-integration")
(defun ci-save-state ()
(defun ci-save-state (&optional _)
"Save the current state of cmake-integration to persistent storage.

The location is determined by `cmake-integration-persist-location'.

If not in a CMake project, no state is saved."
If not in a CMake project, no state is saved.

Note: The optional argument is not used. It is only present so this
function can be used as an advice."
(interactive)
(if (ci-is-cmake-project-p)
(when-let* ((state-file (ci--get-persist-file t))
Expand Down
4 changes: 4 additions & 0 deletions cmake-integration-variables.el
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,10 @@ will be replaced by the project root." :type 'directory :group 'cmake-integratio
"Cache for target types. Maps target names to their types.")


(defvar ci--build-folder-cache nil
"Cache for the build folder path (when presets are used).")


(defvar ci-run-arguments "" "Command line arguments when running a target.")


Expand Down
30 changes: 20 additions & 10 deletions tests/cmake-integration-tests.el
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,8 @@ test code from inside a 'test project'."
;; Build folder is taken from the `binaryDir' field in
;; `cmake-integration-configure-preset', which is an alist.
;; Here we test with a binaryDir value with some replacements
(let* ((ci-configure-preset
(let* ((ci--build-folder-cache nil)
(ci-configure-preset
'((binaryDir . "${sourceDir}/build/${presetName}")
(name . "ninjamulticonfig")))
(project-root (ci--get-project-root-folder))
Expand All @@ -319,15 +320,17 @@ test code from inside a 'test project'."
(should (filepath-equal-p (ci-get-build-folder) expected-build-folder)))

;; Now we test with a binaryDir that has a relative path
(let* ((ci-configure-preset
(let* ((ci--build-folder-cache nil)
(ci-configure-preset
'((binaryDir . "build/${presetName}") (name . "ninjamulticonfig")))
(project-root (ci--get-project-root-folder))
(expected-build-folder
(expand-file-name "./build/ninjamulticonfig" project-root)))
(should (filepath-equal-p (ci-get-build-folder) expected-build-folder)))

;; Test with a different preset
(let* ((ci-configure-preset
(let* ((ci--build-folder-cache nil)
(ci-configure-preset
'((binaryDir . "./build/${presetName}") (name . "Ninja")))
(project-root (ci--get-project-root-folder))
(expected-build-folder
Expand Down Expand Up @@ -669,7 +672,8 @@ test code from inside a 'test project'."
(let ((ci-build-preset nil))
(test-fixture-setup ;;
"./test-project"
(let ((expected-run-dir (ci--get-project-root-folder)))
(let ((ci--build-folder-cache nil)
(expected-run-dir (ci--get-project-root-folder)))
(should
(equal
(ci-get-build-command "the_target")
Expand All @@ -680,7 +684,8 @@ test code from inside a 'test project'."
;; Without setting a preset
(test-fixture-setup ;;
"./test-project-with-presets"
(let ((expected-run-dir (ci--get-project-root-folder)))
(let ((ci--build-folder-cache nil)
(expected-run-dir (ci--get-project-root-folder)))
(should
(equal
(ci-get-build-command "the_target")
Expand All @@ -691,7 +696,8 @@ test code from inside a 'test project'."
;; Without a build preset
(test-fixture-setup
"./test-project-with-presets"
(let ((expected-run-dir (ci--get-project-root-folder))
(let ((ci--build-folder-cache nil)
(expected-run-dir (ci--get-project-root-folder))
(ci-configure-preset
'("default" (name . "default") (binaryDir . "theBuildFolder"))))
(should
Expand All @@ -704,7 +710,8 @@ test code from inside a 'test project'."
;; With a build preset
(test-fixture-setup
"./test-project-with-presets"
(let ((expected-run-dir (ci--get-project-root-folder))
(let ((ci--build-folder-cache nil)
(expected-run-dir (ci--get-project-root-folder))
(ci-configure-preset
'("config-preset"
(name . "config-preset")
Expand All @@ -723,7 +730,8 @@ test code from inside a 'test project'."
;; With a build preset and a target that has the configuration in the name
(test-fixture-setup
"./test-project-with-presets"
(let ((expected-run-dir (ci--get-project-root-folder))
(let ((ci--build-folder-cache nil)
(expected-run-dir (ci--get-project-root-folder))
(ci-configure-preset
'("config-preset"
(name . "config-preset")
Expand All @@ -742,7 +750,8 @@ test code from inside a 'test project'."
;; Passing extra args
(test-fixture-setup
"./test-project-with-presets"
(let ((expected-run-dir (ci--get-project-root-folder))
(let ((ci--build-folder-cache nil)
(expected-run-dir (ci--get-project-root-folder))
(ci-configure-preset
'("config-preset"
(name . "config-preset")
Expand All @@ -762,7 +771,8 @@ test code from inside a 'test project'."
(ert-deftest test-ci-get-conan-run-command ()
(test-fixture-setup
"./test-project"
(let* ((project-root-folder (ci--get-project-root-folder))
(let* ((ci--build-folder-cache nil)
(project-root-folder (ci--get-project-root-folder))
(build-folder (ci-get-build-folder))
(conanfile-relative-path
(file-relative-name project-root-folder build-folder)))
Expand Down