lua: introduce vim.loop (expose libuv event-loop) #10123

Co-authored-by: Andrey Popp <8mayday@gmail.com>

closes #9546
closes #10084
This commit is contained in:
George Zhao 2019-06-10 20:13:18 +08:00 committed by Justin M. Keyes
parent 3e58e60568
commit c83926cd0a
8 changed files with 129 additions and 6 deletions

View File

@ -385,6 +385,9 @@ include_directories(SYSTEM ${LIBUV_INCLUDE_DIRS})
find_package(Msgpack 1.0.0 REQUIRED)
include_directories(SYSTEM ${MSGPACK_INCLUDE_DIRS})
find_package(LibLUV 1.29.1 REQUIRED)
include_directories(SYSTEM ${LIBLUV_INCLUDE_DIRS})
# Note: The test lib requires LuaJIT; it will be skipped if LuaJIT is missing.
option(PREFER_LUA "Prefer Lua over LuaJIT in the nvim executable." OFF)

32
cmake/FindLibLUV.cmake Normal file
View File

@ -0,0 +1,32 @@
# - Try to find luv
# Once done this will define
# LIBLUV_FOUND - System has libluv
# LIBLUV_INCLUDE_DIRS - The libluv include directories
# LIBLUV_LIBRARIES - The libraries needed to use libluv
find_path(LIBLUV_INCLUDE_DIR luv/luv.h
PATHS ${PC_LIBLUV_INCLUDEDIR} ${PC_LIBLUV_INCLUDE_DIRS}
${LIMIT_SEARCH})
# If we're asked to use static linkage, add libluv.a as a preferred library name.
if(LIBLUV_USE_STATIC)
list(APPEND LIBLUV_NAMES
"${CMAKE_STATIC_LIBRARY_PREFIX}luv${CMAKE_STATIC_LIBRARY_SUFFIX}")
endif()
list(APPEND LIBLUV_NAMES luv)
find_library(LIBLUV_LIBRARY NAMES ${LIBLUV_NAMES}
HINTS ${PC_LIBLUV_LIBDIR} ${PC_LIBLUV_LIBRARY_DIRS}
${LIMIT_SEARCH})
set(LIBLUV_LIBRARIES ${LIBLUV_LIBRARY})
set(LIBLUV_INCLUDE_DIRS ${LIBLUV_INCLUDE_DIR})
include(FindPackageHandleStandardArgs)
# handle the QUIETLY and REQUIRED arguments and set LIBLUV_FOUND to TRUE
# if all listed variables are TRUE
find_package_handle_standard_args(libluv DEFAULT_MSG
LIBLUV_LIBRARY LIBLUV_INCLUDE_DIR)
mark_as_advanced(LIBLUV_INCLUDE_DIR LIBLUV_LIBRARY)

View File

@ -383,6 +383,7 @@ endif()
# Put these last on the link line, since multiple things may depend on them.
list(APPEND NVIM_LINK_LIBRARIES
${LIBLUV_LIBRARIES}
${LIBUV_LIBRARIES}
${MSGPACK_LIBRARIES}
${LIBVTERM_LIBRARIES}

View File

@ -31,6 +31,8 @@
#include "nvim/lua/executor.h"
#include "nvim/lua/converter.h"
#include "luv/luv.h"
typedef struct {
Error err;
String lua_err_str;
@ -176,6 +178,11 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
lua_pushcfunction(lstate, &nlua_schedule);
lua_setfield(lstate, -2, "schedule");
// vim.loop
luv_set_loop(lstate, &main_loop.uv);
luaopen_luv(lstate);
lua_setfield(lstate, -2, "loop");
lua_setglobal(lstate, "vim");
return 0;
}

View File

@ -0,0 +1,55 @@
-- Test suite for testing interactions with API bindings
local helpers = require('test.functional.helpers')(after_each)
local funcs = helpers.funcs
local meths = helpers.meths
local clear = helpers.clear
local sleep = helpers.sleep
local eq = helpers.eq
local matches = helpers.matches
before_each(clear)
describe('vim.loop', function()
it('version', function()
assert(funcs.luaeval('vim.loop.version()')>=72961, "libuv version too old")
matches("(%d+)%.(%d+)%.(%d+)", funcs.luaeval('vim.loop.version_string()'))
end)
it('timer', function()
meths.execute_lua('vim.api.nvim_set_var("coroutine_cnt", 0)', {})
local code=[[
local loop = vim.loop
local touch = 0
local function wait(ms)
local this = coroutine.running()
assert(this)
local timer = loop.new_timer()
timer:start(ms, 0, function ()
timer:close()
touch = touch + 1
coroutine.resume(this)
touch = touch + 1
assert(touch==3)
vim.api.nvim_set_var("coroutine_cnt_1", touch)
end)
coroutine.yield()
touch = touch + 1
return touch
end
coroutine.wrap(function()
local touched = wait(10)
assert(touched==touch)
vim.api.nvim_set_var("coroutine_cnt", touched)
end)()
]]
eq(0, meths.get_var('coroutine_cnt'))
meths.execute_lua(code, {})
sleep(20)
eq(2, meths.get_var('coroutine_cnt'))
eq(3, meths.get_var('coroutine_cnt_1'))
end)
end)

View File

@ -154,8 +154,11 @@ set(LIBTERMKEY_SHA256 cecbf737f35d18f433c8d7864f63c0f878af41f8bd0255a3ebb16010dc
set(LIBVTERM_URL https://github.com/neovim/libvterm/archive/b45b648cab73f9667bde7c0c6045b285e22b3ecd.tar.gz)
set(LIBVTERM_SHA256 37cc123deff29327efa654358c2ebaaf8589da03754ca5adb8ec47be386a0433)
set(LUV_URL https://github.com/luvit/luv/archive/1.9.1-1.tar.gz)
set(LUV_SHA256 562b9efaad30aa051a40eac9ade0c3df48bb8186763769abe47ec3fb3edb1268)
set(LUV_URL https://github.com/luvit/luv/archive/1.29.1-2.tar.gz)
set(LUV_SHA256 e75d8fd2a14433bb798900a71e45318b3c0b8c2ef2c1c43593482ce95b4999e2)
set(LUA_COMPAT53_URL https://github.com/keplerproject/lua-compat-5.3/archive/v0.7.tar.gz)
set(LUA_COMPAT53_SHA256 bec3a23114a3d9b3218038309657f0f506ad10dfbc03bb54e91da7e5ffdba0a2)
set(GPERF_URL https://github.com/neovim/deps/raw/ff5b4b18a87397a8564016071ae64f64bcd8c635/opt/gperf-3.1.tar.gz)
set(GPERF_SHA256 588546b945bba4b70b6a3a616e80b4ab466e3f33024a352fc2198112cdbb3ae2)

View File

@ -182,7 +182,7 @@ if(USE_BUNDLED_BUSTED)
add_custom_target(luacheck
DEPENDS ${LUACHECK_EXE})
set(LUV_DEPS luacheck luv-static)
set(LUV_DEPS luacheck luv-static lua-compat-5.3)
if(MINGW AND CMAKE_CROSSCOMPILING)
set(LUV_DEPS ${LUV_DEPS} libuv_host)
endif()
@ -191,9 +191,10 @@ if(USE_BUNDLED_BUSTED)
list(APPEND LUV_ARGS LIBUV_DIR=${HOSTDEPS_INSTALL_DIR})
endif()
# DEPENDS on the previous module, because Luarocks breaks if parallel.
SET(LUV_PRIVATE_ARGS LUA_COMPAT53_INCDIR=${DEPS_BUILD_DIR}/src/lua-compat-5.3)
add_custom_command(OUTPUT ${HOSTDEPS_LIB_DIR}/luarocks/rocks/luv
COMMAND ${LUAROCKS_BINARY}
ARGS make ${LUAROCKS_BUILDARGS} ${LUV_ARGS}
ARGS make ${LUAROCKS_BUILDARGS} ${LUV_ARGS} ${LUV_PRIVATE_ARGS}
WORKING_DIRECTORY ${DEPS_BUILD_DIR}/src/luv
DEPENDS ${LUV_DEPS})
add_custom_target(luv

View File

@ -15,8 +15,26 @@ function(BuildLuv)
message(FATAL_ERROR "Must pass at least one of CONFIGURE_COMMAND, BUILD_COMMAND, INSTALL_COMMAND")
endif()
ExternalProject_Add(lua-compat-5.3
PREFIX ${DEPS_BUILD_DIR}
URL ${LUA_COMPAT53_URL}
DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/lua-compat-5.3
DOWNLOAD_COMMAND ${CMAKE_COMMAND}
-DPREFIX=${DEPS_BUILD_DIR}
-DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/lua-compat-5.3
-DURL=${LUA_COMPAT53_URL}
-DEXPECTED_SHA256=${LUA_COMPAT53_SHA256}
-DTARGET=lua-compat-5.3
-DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR}
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake
PATCH_COMMAND ""
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND "")
ExternalProject_Add(luv-static
PREFIX ${DEPS_BUILD_DIR}
DEPENDS lua-compat-5.3
URL ${LUV_URL}
DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/luv
DOWNLOAD_COMMAND ${CMAKE_COMMAND}
@ -94,9 +112,12 @@ endif()
if(CMAKE_GENERATOR MATCHES "Unix Makefiles" AND
(CMAKE_SYSTEM_NAME MATCHES ".*BSD" OR CMAKE_SYSTEM_NAME MATCHES "DragonFly"))
set(LUV_BUILD_COMMAND ${CMAKE_COMMAND} "-DCMAKE_MAKE_PROGRAM=gmake" --build .)
set(LUV_BUILD_COMMAND ${CMAKE_COMMAND}
"-DLUA_COMPAT53_DIR=${DEPS_BUILD_DIR}/src/lua-compat-5.3"
"-DCMAKE_MAKE_PROGRAM=gmake" --build .)
else()
set(LUV_BUILD_COMMAND ${CMAKE_COMMAND} --build .)
set(LUV_BUILD_COMMAND ${CMAKE_COMMAND}
"-DLUA_COMPAT53_DIR=${DEPS_BUILD_DIR}/src/lua-compat-5.3" --build .)
endif()
set(LUV_INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install)