neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

commit b75a68ff06f805b2a46554038c3bd504c882c248
parent a4c9247a1ad1cac7ea7739de9b5c189005a68c12
Author: bfredl <bjorn.linse@gmail.com>
Date:   Wed, 29 Oct 2025 11:37:14 +0100

Merge pull request #36367 from bfredl/metadata_iii

refactor(build): split out metadata step
Diffstat:
Msrc/gen/gen_api_dispatch.lua | 106++++++++++---------------------------------------------------------------------
Asrc/gen/gen_api_metadata.lua | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/gen/gen_steps.zig | 26+++++++++++++++++---------
Msrc/nvim/CMakeLists.txt | 40++++++++++++++++++++++++++++------------
4 files changed, 141 insertions(+), 114 deletions(-)

diff --git a/src/gen/gen_api_dispatch.lua b/src/gen/gen_api_dispatch.lua @@ -1,30 +1,21 @@ -- Generates C code to bridge API <=> Lua. --- --- Example (manual) invocation: --- --- make --- cp build/nvim_version.lua src/nvim/ --- cd src/nvim --- nvim -l generators/gen_api_dispatch.lua "../../build/src/nvim/auto/api/private/dispatch_wrappers.generated.h" "../../build/src/nvim/auto/api/private/api_metadata.generated.h" "../../build/funcs_metadata.mpack" "../../build/src/nvim/auto/lua_api_c_bindings.generated.h" "../../build/src/nvim/auto/keysets_defs.generated.h" "../../build/ui_metadata.mpack" "../../build/cmake.config/auto/versiondef_git.h" "./api/autocmd.h" "./api/buffer.h" "./api/command.h" "./api/deprecated.h" "./api/extmark.h" "./api/keysets_defs.h" "./api/options.h" "./api/tabpage.h" "./api/ui.h" "./api/vim.h" "./api/vimscript.h" "./api/win_config.h" "./api/window.h" "../../build/include/api/autocmd.h.generated.h" "../../build/include/api/buffer.h.generated.h" "../../build/include/api/command.h.generated.h" "../../build/include/api/deprecated.h.generated.h" "../../build/include/api/extmark.h.generated.h" "../../build/include/api/options.h.generated.h" "../../build/include/api/tabpage.h.generated.h" "../../build/include/api/ui.h.generated.h" "../../build/include/api/vim.h.generated.h" "../../build/include/api/vimscript.h.generated.h" "../../build/include/api/win_config.h.generated.h" "../../build/include/api/window.h.generated.h" +-- to obtain how the script is invoked, look in build/build.ninja and grep for +-- "gen_api_dispatch.lua" local hashy = require 'gen.hashy' local c_grammar = require('gen.c_grammar') -- output h file with generated dispatch functions (dispatch_wrappers.generated.h) local dispatch_outputf = arg[1] --- output h file with packed metadata (api_metadata.generated.h) -local api_metadata_outputf = arg[2] --- output metadata mpack file, for use by other build scripts (funcs_metadata.mpack) -local mpack_outputf = arg[3] +-- output file with exported functions metadata +local exported_funcs_metadata_outputf = arg[2] +-- output mpack file with raw metadata, for use by gen_eval.lua (funcs_metadata.mpack) +local eval_funcs_metadata_outputf = arg[3] local lua_c_bindings_outputf = arg[4] -- lua_api_c_bindings.generated.c local keysets_outputf = arg[5] -- keysets_defs.generated.h -local ui_metadata_inputf = arg[6] -- ui events metadata -local git_version_inputf = arg[7] -- git version header -local nvim_version_inputf = arg[8] -- nvim version -local dump_bin_array_inputf = arg[9] -local dispatch_deprecated_inputf = arg[10] -local pre_args = 10 -assert(#arg >= pre_args) +local dispatch_deprecated_inputf = arg[6] +local pre_args = 6 +assert(#arg >= 6) local function real_type(type, exported) local ptype = c_grammar.typed_container:match(type) @@ -165,8 +156,6 @@ local function add_keyset(val) } end -local ui_options_text = nil - -- read each input file, parse and append to the api metadata for i = pre_args + 1, #arg do local full_path = arg[i] @@ -190,12 +179,9 @@ for i = pre_args + 1, #arg do end end - ui_options_text = ui_options_text or text:match('ui_ext_names%[][^{]+{([^}]+)}') input:close() end ---- @cast ui_options_text string - --- @generic T: table --- @param orig T --- @return T @@ -303,77 +289,11 @@ for _, f in ipairs(functions) do end end -local ui_options = { 'rgb' } -for x in ui_options_text:gmatch('"([a-z][a-z_]+)"') do - table.insert(ui_options, x) -end +local metadata_output = assert(io.open(exported_funcs_metadata_outputf, 'wb')) +metadata_output:write(vim.mpack.encode(exported_functions)) +metadata_output:close() --- @type integer[] -local version = loadfile(nvim_version_inputf)() -local git_version = io.open(git_version_inputf):read '*a' -local version_build = git_version:match('#define NVIM_VERSION_BUILD "([^"]+)"') or vim.NIL - -local pieces = {} --- @type string[] - --- Naively using mpack.encode({foo=x, bar=y}) will make the build --- "non-reproducible". Emit maps directly as FIXDICT(2) "foo" x "bar" y instead -local function fixdict(num) - if num > 15 then - error 'implement more dict codes' - end - pieces[#pieces + 1] = string.char(128 + num) -end - -local function put(item, item2) - table.insert(pieces, vim.mpack.encode(item)) - if item2 ~= nil then - table.insert(pieces, vim.mpack.encode(item2)) - end -end - -fixdict(6) - -put('version') -fixdict(1 + #version) -for _, item in ipairs(version) do - -- NB: all items are mandatory. But any error will be less confusing - -- with placeholder vim.NIL (than invalid mpack data) - local val = item[2] == nil and vim.NIL or item[2] - put(item[1], val) -end -put('build', version_build) - -put('functions', exported_functions) -put('ui_events') -table.insert(pieces, io.open(ui_metadata_inputf, 'rb'):read('*all')) -put('ui_options', ui_options) - -put('error_types') -fixdict(2) -put('Exception', { id = 0 }) -put('Validation', { id = 1 }) - -put('types') -local types = - { { 'Buffer', 'nvim_buf_' }, { 'Window', 'nvim_win_' }, { 'Tabpage', 'nvim_tabpage_' } } -fixdict(#types) -for i, item in ipairs(types) do - put(item[1]) - fixdict(2) - put('id', i - 1) - put('prefix', item[2]) -end - -local packed = table.concat(pieces) ---- @type fun(api_metadata: file*, name: string, packed: string) -local dump_bin_array = loadfile(dump_bin_array_inputf)() - --- serialize the API metadata using msgpack and embed into the resulting --- binary for easy querying by clients -local api_metadata_output = assert(io.open(api_metadata_outputf, 'wb')) -dump_bin_array(api_metadata_output, 'packed_api_metadata', packed) -api_metadata_output:close() - -- start building the dispatch wrapper output local output = assert(io.open(dispatch_outputf, 'wb')) @@ -757,7 +677,7 @@ output:close() --- @cast functions {[integer]: gen_api_dispatch.Function, keysets: gen_api_dispatch.Keyset[]} functions.keysets = keysets -local mpack_output = assert(io.open(mpack_outputf, 'wb')) +local mpack_output = assert(io.open(eval_funcs_metadata_outputf, 'wb')) mpack_output:write(vim.mpack.encode(functions)) mpack_output:close() diff --git a/src/gen/gen_api_metadata.lua b/src/gen/gen_api_metadata.lua @@ -0,0 +1,83 @@ +local mpack = vim.mpack + +assert(#arg == 7) +local funcs_metadata_inputf = arg[1] -- exported functions metadata +local ui_metadata_inputf = arg[2] -- ui events metadata +local ui_options_inputf = arg[3] -- for ui options +local git_version_inputf = arg[4] -- git version header +local nvim_version_inputf = arg[5] -- nvim version +local dump_bin_array_inputf = arg[6] +local api_metadata_outputf = arg[7] + +local version = loadfile(nvim_version_inputf)() +local git_version = io.open(git_version_inputf):read '*a' +local version_build = git_version:match('#define NVIM_VERSION_BUILD "([^"]+)"') or vim.NIL + +local text = io.open(ui_options_inputf):read '*a' +local ui_options_text = text:match('ui_ext_names%[][^{]+{([^}]+)}') +local ui_options = { 'rgb' } +for x in ui_options_text:gmatch('"([a-z][a-z_]+)"') do + table.insert(ui_options, x) +end + +local pieces = {} --- @type string[] + +-- Naively using mpack.encode({foo=x, bar=y}) will make the build +-- "non-reproducible". Emit maps directly as FIXDICT(2) "foo" x "bar" y instead +local function fixdict(num) + if num > 15 then + error 'implement more dict codes' + end + pieces[#pieces + 1] = string.char(128 + num) +end + +local function put(item, item2) + table.insert(pieces, mpack.encode(item)) + if item2 ~= nil then + table.insert(pieces, mpack.encode(item2)) + end +end + +fixdict(6) + +put('version') +fixdict(1 + #version) +for _, item in ipairs(version) do + -- NB: all items are mandatory. But any error will be less confusing + -- with placeholder vim.NIL (than invalid mpack data) + local val = item[2] == nil and vim.NIL or item[2] + put(item[1], val) +end +put('build', version_build) + +put('functions') +table.insert(pieces, io.open(funcs_metadata_inputf, 'rb'):read('*all')) +put('ui_events') +table.insert(pieces, io.open(ui_metadata_inputf, 'rb'):read('*all')) +put('ui_options', ui_options) + +put('error_types') +fixdict(2) +put('Exception', { id = 0 }) +put('Validation', { id = 1 }) + +put('types') +local types = + { { 'Buffer', 'nvim_buf_' }, { 'Window', 'nvim_win_' }, { 'Tabpage', 'nvim_tabpage_' } } +fixdict(#types) +for i, item in ipairs(types) do + put(item[1]) + fixdict(2) + put('id', i - 1) + put('prefix', item[2]) +end + +local packed = table.concat(pieces) +--- @type fun(api_metadata: file*, name: string, packed: string) +local dump_bin_array = loadfile(dump_bin_array_inputf)() + +-- serialize the API metadata using msgpack and embed into the resulting +-- binary for easy querying by clients +local api_metadata_output = assert(io.open(api_metadata_outputf, 'wb')) +dump_bin_array(api_metadata_output, 'packed_api_metadata', packed) +api_metadata_output:close() diff --git a/src/gen/gen_steps.zig b/src/gen/gen_steps.zig @@ -100,32 +100,40 @@ pub fn nvim_gen_sources( break :ui_step ui_metadata; }; - const funcs_metadata = api_step: { + const eval_funcs_metadata, const exported_funcs_metadata = dispatch_step: { const gen_step = b.addRunArtifact(nlua0); gen_step.addFileArg(b.path("src/gen/gen_api_dispatch.lua")); _ = try gen_header_with_header(b, gen_step, "api/private/dispatch_wrappers.generated.h", nlua0, gen_headers); - _ = gen_header(b, gen_step, "api/private/api_metadata.generated.h", gen_headers); - const funcs_metadata = gen_step.addOutputFileArg("funcs_metadata.mpack"); + const exported_funcs_metadata = gen_step.addOutputFileArg("exported_funcs_metadata.mpack"); + const eval_funcs_metadata = gen_step.addOutputFileArg("eval_funcs_metadata.mpack"); _ = gen_header(b, gen_step, "lua_api_c_bindings.generated.h", gen_headers); _ = gen_header(b, gen_step, "keysets_defs.generated.h", gen_headers); - gen_step.addFileArg(ui_metadata); - gen_step.addFileArg(versiondef_git); - gen_step.addFileArg(version_lua); - gen_step.addFileArg(b.path("src/gen/dump_bin_array.lua")); gen_step.addFileArg(b.path("src/nvim/api/dispatch_deprecated.lua")); // now follows all .h files with exported functions for (api_headers.items) |h| { gen_step.addFileArg(h); } - break :api_step funcs_metadata; + break :dispatch_step .{ eval_funcs_metadata, exported_funcs_metadata }; }; + { + const gen_step = b.addRunArtifact(nlua0); + gen_step.addFileArg(b.path("src/gen/gen_api_metadata.lua")); + gen_step.addFileArg(exported_funcs_metadata); + gen_step.addFileArg(ui_metadata); + gen_step.addFileArg(b.path("src/nvim/api/ui.h")); + gen_step.addFileArg(versiondef_git); + gen_step.addFileArg(version_lua); + gen_step.addFileArg(b.path("src/gen/dump_bin_array.lua")); + _ = gen_header(b, gen_step, "api/private/api_metadata.generated.h", gen_headers); + } + const funcs_data = eval_step: { const gen_step = b.addRunArtifact(nlua0); gen_step.addFileArg(b.path("src/gen/gen_eval.lua")); _ = gen_header(b, gen_step, "funcs.generated.h", gen_headers); - gen_step.addFileArg(funcs_metadata); + gen_step.addFileArg(eval_funcs_metadata); const funcs_data = gen_step.addOutputFileArg("funcs_data.mpack"); gen_step.addFileArg(b.path("src/nvim/eval.lua")); break :eval_step funcs_data; diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt @@ -285,7 +285,8 @@ endif() # Variables #------------------------------------------------------------------------------- -set(FUNCS_METADATA ${PROJECT_BINARY_DIR}/funcs_metadata.mpack) +set(EVAL_FUNCS_METADATA ${PROJECT_BINARY_DIR}/eval_funcs_metadata.mpack) +set(EXPORTED_FUNCS_METADATA ${PROJECT_BINARY_DIR}/exported_funcs_metadata.mpack) set(UI_METADATA ${PROJECT_BINARY_DIR}/ui_metadata.mpack) set(BINARY_LIB_DIR ${PROJECT_BINARY_DIR}/lib/nvim) set(GENERATED_DIR ${PROJECT_BINARY_DIR}/src/nvim/auto) @@ -298,6 +299,7 @@ set(NVIM_RUNTIME_DIR ${PROJECT_SOURCE_DIR}/runtime) # GENERATOR_DIR set(API_DISPATCH_GENERATOR ${GENERATOR_DIR}/gen_api_dispatch.lua) set(API_UI_EVENTS_GENERATOR ${GENERATOR_DIR}/gen_api_ui_events.lua) +set(API_METADATA_GENERATOR ${GENERATOR_DIR}/gen_api_metadata.lua) set(CHAR_BLOB_GENERATOR ${GENERATOR_DIR}/gen_char_blob.lua) set(EVENTS_GENERATOR ${GENERATOR_DIR}/gen_events.lua) set(EX_CMDS_GENERATOR ${GENERATOR_DIR}/gen_ex_cmds.lua) @@ -564,16 +566,13 @@ set(NVIM_VERSION_LUA ${PROJECT_BINARY_DIR}/nvim_version.lua) configure_file(${GENERATOR_DIR}/nvim_version.lua.in ${NVIM_VERSION_LUA}) add_custom_command( - OUTPUT ${GENERATED_API_DISPATCH} ${GENERATED_API_METADATA} - ${FUNCS_METADATA} ${LUA_API_C_BINDINGS} ${GENERATED_KEYSETS_DEFS} + OUTPUT ${GENERATED_API_DISPATCH} ${EXPORTED_FUNCS_METADATA} + ${EVAL_FUNCS_METADATA} ${LUA_API_C_BINDINGS} ${GENERATED_KEYSETS_DEFS} COMMAND ${LUA_GEN} ${API_DISPATCH_GENERATOR} ${GENERATED_API_DISPATCH} - ${GENERATED_API_METADATA} ${FUNCS_METADATA} + ${EXPORTED_FUNCS_METADATA} ${EVAL_FUNCS_METADATA} ${LUA_API_C_BINDINGS} ${GENERATED_KEYSETS_DEFS} - ${UI_METADATA} - ${NVIM_VERSION_GIT_H} ${NVIM_VERSION_LUA} - ${GENERATOR_DIR}/dump_bin_array.lua ${CMAKE_CURRENT_LIST_DIR}/api/dispatch_deprecated.lua ${API_HEADERS} @@ -584,11 +583,27 @@ add_custom_command( ${API_DISPATCH_GENERATOR} ${GENERATOR_C_GRAMMAR} ${GENERATOR_HASHY} + ${CMAKE_CURRENT_LIST_DIR}/api/dispatch_deprecated.lua +) + +add_custom_command( + OUTPUT ${GENERATED_API_METADATA} + COMMAND ${LUA_GEN} ${API_METADATA_GENERATOR} + ${EXPORTED_FUNCS_METADATA} + ${UI_METADATA} + ${CMAKE_CURRENT_LIST_DIR}/api/ui.h + ${NVIM_VERSION_GIT_H} ${NVIM_VERSION_LUA} + ${GENERATOR_DIR}/dump_bin_array.lua + ${GENERATED_API_METADATA} + + DEPENDS + ${LUA_GEN_DEPS} + ${API_METADATA_GENERATOR} ${GENERATOR_DIR}/dump_bin_array.lua ${UI_METADATA} + ${EXPORTED_FUNCS_METADATA} ${NVIM_VERSION_LUA} ${NVIM_VERSION_GIT_H} - ${CMAKE_CURRENT_LIST_DIR}/api/dispatch_deprecated.lua ) add_custom_command( @@ -654,8 +669,8 @@ add_custom_command(OUTPUT ${GENERATED_EX_CMDS_ENUM} ${GENERATED_EX_CMDS_DEFS} ) add_custom_command(OUTPUT ${GENERATED_FUNCS} ${FUNCS_DATA} - COMMAND ${LUA_GEN} ${FUNCS_GENERATOR} ${GENERATED_FUNCS} ${FUNCS_METADATA} ${FUNCS_DATA} ${CMAKE_CURRENT_LIST_DIR}/eval.lua - DEPENDS ${LUA_GEN_DEPS} ${FUNCS_GENERATOR} ${GENERATOR_HASHY} ${CMAKE_CURRENT_LIST_DIR}/eval.lua ${FUNCS_METADATA} + COMMAND ${LUA_GEN} ${FUNCS_GENERATOR} ${GENERATED_FUNCS} ${EVAL_FUNCS_METADATA} ${FUNCS_DATA} ${CMAKE_CURRENT_LIST_DIR}/eval.lua + DEPENDS ${LUA_GEN_DEPS} ${FUNCS_GENERATOR} ${GENERATOR_HASHY} ${CMAKE_CURRENT_LIST_DIR}/eval.lua ${EVAL_FUNCS_METADATA} ) add_custom_command(OUTPUT ${GENERATED_EVENTS_ENUM} ${GENERATED_EVENTS_NAMES_MAP} @@ -690,6 +705,7 @@ list(APPEND NVIM_GENERATED_FOR_SOURCES "${GENERATED_OPTIONS}" "${GENERATED_OPTIONS_MAP}" "${VIM_MODULE_FILE}" + "${GENERATED_API_METADATA}" "${PROJECT_BINARY_DIR}/cmake.config/auto/pathdef.h" ) @@ -960,10 +976,10 @@ add_target(doc-vim ) add_target(doc-eval - COMMAND ${NVIM_LUA} ${PROJECT_SOURCE_DIR}/src/gen/gen_eval_files.lua ${FUNCS_METADATA} ${PROJECT_BINARY_DIR}/runtime/doc/tags + COMMAND ${NVIM_LUA} ${PROJECT_SOURCE_DIR}/src/gen/gen_eval_files.lua ${EVAL_FUNCS_METADATA} ${PROJECT_BINARY_DIR}/runtime/doc/tags DEPENDS nvim - ${FUNCS_METADATA} + ${EVAL_FUNCS_METADATA} ${PROJECT_SOURCE_DIR}/src/gen/gen_eval_files.lua ${PROJECT_SOURCE_DIR}/src/nvim/eval.lua ${PROJECT_SOURCE_DIR}/src/nvim/options.lua