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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ local osys = require("cmake-tools.osys")
require("cmake-tools").setup {
cmake_command = "cmake", -- this is used to specify cmake command path
ctest_command = "ctest", -- this is used to specify ctest command path
ctest_show_labels = false, -- also show labels in the test picker
cmake_use_preset = true,
cmake_regenerate_on_save = true, -- auto generate when save CMakeLists.txt
cmake_generate_options = { "-DCMAKE_EXPORT_COMPILE_COMMANDS=1" }, -- this will be passed when invoke `CMakeGenerate`
Expand Down
7 changes: 7 additions & 0 deletions lua/cmake-tools/build_preset.lua
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
local Path = require("plenary.path")
local osys = require("cmake-tools.osys")

---@class BuildPreset: CMakeBuildPreset
local BuildPreset = {}

---@param cwd string
---@param obj CMakeBuildPreset?
---@return BuildPreset
function BuildPreset:new(cwd, obj)
local instance = setmetatable(obj or {}, { __index = self })
instance.__index = self
Expand All @@ -16,6 +20,7 @@ function BuildPreset:new(cwd, obj)
return instance
end

---@return string[]|nil
function BuildPreset:get_build_target()
if self.targets == nil then
return nil
Expand All @@ -28,13 +33,15 @@ function BuildPreset:get_build_target()
return nil
end

---@return string|nil
function BuildPreset:get_build_type()
if self.configuration == nil then
return nil
end
return self.configuration
end

---@return boolean
function BuildPreset:is_valid()
return self.valid
end
Expand Down
134 changes: 94 additions & 40 deletions lua/cmake-tools/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,57 @@ local variants = require("cmake-tools.variants")
local Presets = require("cmake-tools.presets")
local kits = require("cmake-tools.kits")

local Config = {
build_directory = nil,
query_directory = nil,
reply_directory = nil,
build_type = nil,
variant = nil,
build_target = nil,
launch_target = nil,
kit = nil,
configure_preset = nil,
build_preset = nil,
base_settings = {
env = {},
build_dir = "",
working_dir = "${dir.binary}",
use_preset = true,
generate_options = {},
build_options = {},
show_disabled_build_presets = true,
}, -- general config
target_settings = {}, -- target specific config
executor = nil,
runner = nil,
env_script = " ",
cwd = vim.loop.cwd(),
}

---@class Config.BaseSettings
---@field env table
---@field build_dir string
---@field working_dir string
---@field use_preset boolean
---@field generate_options string[]
---@field build_options string[]
---@field show_disabled_build_presets boolean
---@field ctest_show_labels boolean

---@class Config
---@field build_directory Path?
---@field query_directory Path?
---@field reply_directory Path?
---@field build_type string?
---@field variant table?
---@field build_target string|string[]|nil
---@field launch_target string?
---@field kit string?
---@field configure_preset string?
---@field build_preset string?
---@field test_preset string?
---@field selected_test string?
---@field base_settings Config.BaseSettings
---@field target_settings table
---@field executor table?
---@field runner table?
---@field env_script string
---@field cwd string
local Config = {}
Config.__index = Config

---@param const Const
---@return Config
function Config:new(const)
local obj = {}
setmetatable(obj, { __index = self }) -- when obj cannot find key in its table, it will try to find it from its __index value
local obj = {
base_settings = {
env = {},
build_dir = "",
working_dir = "${dir.binary}",
use_preset = true,
generate_options = {},
build_options = {},
show_disabled_build_presets = true,
ctest_show_labels = false,
}, -- general config
target_settings = {}, -- target specific config
env_script = " ",
cwd = vim.loop.cwd(),
}
setmetatable(obj, Config)

obj:update_build_dir(const.cmake_build_directory, const.cmake_build_directory)

Expand All @@ -45,28 +66,30 @@ function Config:new(const)
obj.base_settings.use_preset = const.cmake_use_preset

obj.base_settings.show_disabled_build_presets = const.cmake_show_disabled_build_presets
obj.base_settings.ctest_show_labels = const.ctest_show_labels

obj.executor = const.cmake_executor
obj.runner = const.cmake_runner

return obj
end

---@return string
function Config:build_directory_path()
return self.build_directory.filename
end

---@return boolean
function Config:has_build_directory()
return self.build_directory and self.build_directory:exists()
end

---comment
---The reason for storing no expand build directory is to make cwd selecting easier
---@return string
function Config:no_expand_build_directory_path()
return self.base_settings.build_dir
end

---comment
---@param build_dir string|function string or a function returning string containing path to the build dir
---@param no_expand_build_dir string|function
function Config:update_build_dir(build_dir, no_expand_build_dir)
Expand Down Expand Up @@ -103,8 +126,9 @@ function Config:update_build_dir(build_dir, no_expand_build_dir)
self.base_settings.build_dir = Path:new(no_expand_build_dir):absolute()
end

---Prepare build directory. Which allows macro expansion.
---Prepare build directory with macro expansion
---@param kit_list table all the kits
---@return string
function Config:prepare_build_directory(kit_list)
-- macro expansion:
-- ${kit}
Expand Down Expand Up @@ -136,18 +160,27 @@ function Config:prepare_build_directory(kit_list)
return build_dir
end

---@return string[]
function Config:generate_options()
return self.base_settings.generate_options and self.base_settings.generate_options or {}
end

---@return string[]
function Config:build_options()
return self.base_settings.build_options and self.base_settings.build_options or {}
end

---@return boolean
function Config:show_disabled_build_presets()
return self.base_settings.show_disabled_build_presets
end

---@return boolean
function Config:ctest_show_labels()
return self.base_settings.ctest_show_labels
end

---@return cmake.Result
function Config:generate_build_directory()
local build_directory = Path:new(self.build_directory)

Expand All @@ -157,6 +190,7 @@ function Config:generate_build_directory()
return self:generate_query_files()
end

---@return cmake.Result
function Config:generate_query_files()
local query_directory = Path:new(self.query_directory)
if not query_directory:mkdir({ parents = true }) then
Expand Down Expand Up @@ -188,6 +222,7 @@ function Config:generate_query_files()
return Result:new(Types.SUCCESS, true, "yeah, that could be")
end

---@return cmake.Result
function Config:get_cmake_files()
-- if reply_directory exists
local reply_directory = Path:new(self.reply_directory)
Expand All @@ -204,6 +239,7 @@ function Config:get_cmake_files()
return Result:new(Types.SUCCESS, codemodel_json["inputs"], "find it")
end

---@return cmake.Result
function Config:get_codemodel_targets()
-- if reply_directory exists
local reply_directory = Path:new(self.reply_directory)
Expand All @@ -225,12 +261,15 @@ function Config:get_codemodel_targets()
return Result:new(Types.SUCCESS, codemodel_json["configurations"][1]["targets"], "find it") -- Return the first else
end

---@param codemodel_target table
---@return table
function Config:get_code_model_target_info(codemodel_target)
local reply_directory = Path:new(self.reply_directory)
return vim.json.decode((reply_directory / codemodel_target["jsonFile"]):read())
end

-- Check if launch target is built
---Check if launch target is built
---@return cmake.Result
function Config:check_launch_target()
-- 1. not configured
local build_directory = Path:new(self.build_directory)
Expand Down Expand Up @@ -268,6 +307,8 @@ function Config:check_launch_target()
)
end

---@param target_info table
---@return cmake.Result
function Config:get_launch_target_from_info(target_info)
local target_path = target_info["artifacts"][1]["path"]
if require("cmake-tools.osys").iswin32 then
Expand All @@ -292,8 +333,8 @@ function Config:get_launch_target_from_info(target_info)
return Result:new(Types.SUCCESS, target_path.filename, "yeah, that's good")
end

-- Retrieve launch target path: self.launch_target
-- it will first check if this launch target is built
---Retrieve launch target path
---@return cmake.Result
function Config:get_launch_target()
local check_result = self:check_launch_target()
if check_result.code ~= Types.SUCCESS then
Expand All @@ -304,7 +345,8 @@ function Config:get_launch_target()
return self:get_launch_target_from_info(target_info)
end

-- Check if build target exists
---Check if build target exists
---@return cmake.Result
function Config:check_build_target()
-- 1. not configured
local build_directory = Path:new(self.build_directory)
Expand Down Expand Up @@ -338,8 +380,8 @@ function Config:check_build_target()
)
end

-- Retrieve launch target path: self.launch_target
-- it will first check if this launch target is built
---Retrieve build target path
---@return cmake.Result
function Config:get_build_target()
local check_result = self:check_build_target()
if check_result.code ~= Types.SUCCESS then
Expand All @@ -366,8 +408,8 @@ function Config:get_build_target()
return Result:new(Types.SUCCESS, target_path.filename, "yeah, that's good")
end

-- Check if this launch target is debuggable
-- use variants.debuggable
---Check if this launch target is debuggable using variants.debuggable
---@return cmake.Result
function Config:validate_for_debugging()
local build_type = self.build_type

Expand All @@ -377,6 +419,9 @@ function Config:validate_for_debugging()
return Result:new(Types.SUCCESS, true, "Yeah, it may be")
end

---@param config Config
---@param opt { has_all: boolean, only_executable: boolean, query_sources: boolean? }
---@return cmake.Result
local function get_targets(config, opt)
local targets, display_targets, paths, abs_paths = {}, {}, {}, {}
local sources = {}
Expand Down Expand Up @@ -447,6 +492,7 @@ local function get_targets(config, opt)
end
end

---@return table
function Config:get_code_model_info()
local codemodel_targets = self:get_codemodel_targets()
if codemodel_targets.code ~= Types.SUCCESS then
Expand All @@ -464,31 +510,37 @@ function Config:get_code_model_info()
return result
end

---@return cmake.Result
function Config:launch_targets()
return get_targets(self, { has_all = false, only_executable = true })
end

---@return cmake.Result
function Config:build_targets()
return get_targets(self, { has_all = true, only_executable = false })
end

---@return cmake.Result
function Config:launch_targets_with_sources()
return get_targets(self, { has_all = false, only_executable = true, query_sources = true })
end

local _virtual_targets = nil

function Config:update_targets()
_virtual_targets =
get_targets(self, { has_all = false, only_executable = false, query_sources = true })
end

---@return cmake.Result?
function Config:build_targets_with_sources()
if not _virtual_targets then
self:update_targets()
end
return _virtual_targets
end

---Update build type from configure and build presets
function Config:update_build_type()
local presets_exists = self.base_settings.use_preset and Presets.exists(self.cwd)
if not presets_exists then
Expand Down Expand Up @@ -538,6 +590,7 @@ function Config:update_build_type()
end
end

---Update build target from build preset
function Config:update_build_target()
local presets_exists = self.base_settings.use_preset and Presets.exists(self.cwd)
if not presets_exists then
Expand Down Expand Up @@ -570,6 +623,7 @@ function Config:update_build_target()
end
end

---Update build directory from kits or configure preset
function Config:update_build_directory()
local kits_config = kits.parse(self.cmake_kits_path, self.cwd)
if kits_config then
Expand Down
2 changes: 2 additions & 0 deletions lua/cmake-tools/const.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
local osys = require("cmake-tools.osys")
---@class Const
local const = {
cmake_command = "cmake", -- this is used to specify cmake command path
ctest_command = "ctest", -- this is used to specify ctest command path
ctest_show_labels = false, -- show test labels in the test picker (when true, labels from ctest are shown as filterable entries)
cmake_use_preset = true, -- when `false`, this is used to define if the `--preset` option should be use on cmake commands
cmake_regenerate_on_save = true, -- auto generate when save CMakeLists.txt
cmake_generate_options = { "-DCMAKE_EXPORT_COMPILE_COMMANDS=1" }, -- this will be passed when invoke `CMakeGenerate`
Expand Down
Loading
Loading