diff options
| author | William Boman <william@redwill.se> | 2021-12-23 11:08:35 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-12-23 11:08:35 +0100 |
| commit | d39847e7b4d89b335e986e6931cfa8ae0d5911a8 (patch) | |
| tree | af3a6177e423736bd0cc9f5bf28310c9529972c1 | |
| parent | feat: add grammarly (#349) (diff) | |
| download | mason-d39847e7b4d89b335e986e6931cfa8ae0d5911a8.tar mason-d39847e7b4d89b335e986e6931cfa8ae0d5911a8.tar.gz mason-d39847e7b4d89b335e986e6931cfa8ae0d5911a8.tar.bz2 mason-d39847e7b4d89b335e986e6931cfa8ae0d5911a8.tar.lz mason-d39847e7b4d89b335e986e6931cfa8ae0d5911a8.tar.xz mason-d39847e7b4d89b335e986e6931cfa8ae0d5911a8.tar.zst mason-d39847e7b4d89b335e986e6931cfa8ae0d5911a8.zip | |
fix(ccls): better Mac support (#352)
This is a breaking change due to fundamental changes to the
installer. Re-installation will unfortunately be required.
| -rw-r--r-- | lua/nvim-lsp-installer/installers/context.lua | 20 | ||||
| -rw-r--r-- | lua/nvim-lsp-installer/installers/init.lua | 30 | ||||
| -rw-r--r-- | lua/nvim-lsp-installer/installers/std.lua | 39 | ||||
| -rw-r--r-- | lua/nvim-lsp-installer/servers/ccls/init.lua | 163 |
4 files changed, 167 insertions, 85 deletions
diff --git a/lua/nvim-lsp-installer/installers/context.lua b/lua/nvim-lsp-installer/installers/context.lua index 919e3957..99f679de 100644 --- a/lua/nvim-lsp-installer/installers/context.lua +++ b/lua/nvim-lsp-installer/installers/context.lua @@ -297,4 +297,24 @@ function M.use_os_distribution() } end +function M.use_homebrew_prefix() + return installers.on { + mac = function(_, callback, ctx) + local stdio = process.in_memory_sink() + process.spawn("brew", { + args = { "--prefix" }, + stdio_sink = stdio.sink, + }, function(success) + if success then + ctx.homebrew_prefix = vim.trim(table.concat(stdio.buffers.stdout, "")) + callback(true) + else + ctx.stdio_sink.stderr "Failed to locate Homebrew installation.\n" + callback(false) + end + end) + end, + } +end + return M diff --git a/lua/nvim-lsp-installer/installers/init.lua b/lua/nvim-lsp-installer/installers/init.lua index c4ac2747..ab9ad4f9 100644 --- a/lua/nvim-lsp-installer/installers/init.lua +++ b/lua/nvim-lsp-installer/installers/init.lua @@ -21,6 +21,7 @@ end ---@field stdio_sink StdioSink ---@field github_release_file string|nil @Only available if context.use_github_release_file has been called. ---@field os_distribution table<string, any> @Only available if context.use_os_distribution has been called. +---@field homebrew_prefix string @Only available if context.use_homebrew_prefix has been called. ---@field install_dir string ---@alias ServerInstallerFunction fun(server: Server, callback: ServerInstallCallback, context: ServerInstallContext) @@ -35,18 +36,23 @@ function M.pipe(installers) return function(server, callback, context) local function execute(idx) - local ok, err = pcall(installers[idx], server, function(success) - if not success then - -- oh no, error. exit early - callback(success) - elseif installers[idx + 1] then - -- iterate - execute(idx + 1) - else - -- we done - callback(success) - end - end, context) + local ok, err = pcall( + installers[idx], + server, + vim.schedule_wrap(function(success) + if not success then + -- oh no, error. exit early + callback(success) + elseif installers[idx + 1] then + -- iterate + execute(idx + 1) + else + -- we done + callback(success) + end + end), + context + ) if not ok then context.stdio_sink.stderr(tostring(err) .. "\n") callback(false) diff --git a/lua/nvim-lsp-installer/installers/std.lua b/lua/nvim-lsp-installer/installers/std.lua index f123b3ae..723276fc 100644 --- a/lua/nvim-lsp-installer/installers/std.lua +++ b/lua/nvim-lsp-installer/installers/std.lua @@ -4,6 +4,9 @@ local process = require "nvim-lsp-installer.process" local platform = require "nvim-lsp-installer.platform" local installers = require "nvim-lsp-installer.installers" local shell = require "nvim-lsp-installer.installers.shell" +local Data = require "nvim-lsp-installer.data" + +local list_not_nil, when = Data.list_not_nil, Data.when local M = {} @@ -229,36 +232,42 @@ end ---Shallow git clone. ---@param repo_url string -function M.git_clone(repo_url) +---@param opts {directory: string, recursive: boolean} +function M.git_clone(repo_url, opts) ---@type ServerInstallerFunction return function(_, callback, context) + opts = vim.tbl_deep_extend("force", { + directory = ".", + recursive = false, + }, opts) + local c = process.chain { cwd = context.install_dir, stdio_sink = context.stdio_sink, } - c.run("git", { "clone", "--depth", "1", repo_url, "." }) + c.run( + "git", + list_not_nil( + "clone", + "--depth", + "1", + when(opts.recursive, "--recursive"), + when(opts.recursive, "--shallow-submodules"), + repo_url, + opts.directory + ) + ) if context.requested_server_version then - c.run("git", { "fetch", "--depth", "1", "origin", context.requested_server_version }) - c.run("git", { "checkout", "FETCH_HEAD" }) + c.run("git", { "-C", opts.directory, "fetch", "--depth", "1", "origin", context.requested_server_version }) + c.run("git", { "-C", opts.directory, "checkout", "FETCH_HEAD" }) end c.spawn(callback) end end -function M.git_submodule_update() - ---@type ServerInstallerFunction - return function(_, callback, context) - process.spawn("git", { - args = { "submodule", "update", "--init", "--recursive" }, - cwd = context.install_dir, - stdio_sink = context.stdio_sink, - }, callback) - end -end - ---@param opts {args: string[]} function M.gradlew(opts) ---@type ServerInstallerFunction diff --git a/lua/nvim-lsp-installer/servers/ccls/init.lua b/lua/nvim-lsp-installer/servers/ccls/init.lua index 079c9cd2..d5dde3e0 100644 --- a/lua/nvim-lsp-installer/servers/ccls/init.lua +++ b/lua/nvim-lsp-installer/servers/ccls/init.lua @@ -1,3 +1,24 @@ +-- __________________ +-- < Here be dragons! > +-- ------------------ +-- \ ^ /^ +-- \ / \ // \ +-- \ |\___/| / \// .\ +-- \ /O O \__ / // | \ \ *----* +-- / / \/_/ // | \ \ \ | +-- @___@` \/_ // | \ \ \/\ \ +-- 0/0/| \/_ // | \ \ \ \ +-- 0/0/0/0/| \/// | \ \ | | +-- 0/0/0/0/0/_|_ / ( // | \ _\ | / +-- 0/0/0/0/0/0/`/,_ _ _/ ) ; -. | _ _\.-~ / / +-- ,-} _ *-.|.-~-. .~ ~ +-- \ \__/ `/\ / ~-. _ .-~ / +-- \____(@@) *. } { / +-- ( (--) .----~-.\ \-` .~ +-- //__\\ \__ Ack! ///.----..< \ _ -~ +-- // \\ ///-._ _ _ _ _ _ _{^ - - - - ~ +-- + local server = require "nvim-lsp-installer.server" local path = require "nvim-lsp-installer.path" local installers = require "nvim-lsp-installer.installers" @@ -6,8 +27,9 @@ local std = require "nvim-lsp-installer.installers.std" local platform = require "nvim-lsp-installer.platform" local context = require "nvim-lsp-installer.installers.context" local process = require "nvim-lsp-installer.process" +local fs = require "nvim-lsp-installer.fs" -local coalesce, when = Data.coalesce, Data.when +local coalesce, when, list_not_nil = Data.coalesce, Data.when, Data.list_not_nil return function(name, root_dir) local llvm_installer @@ -17,32 +39,29 @@ return function(name, root_dir) ---@param os_distribution table<string, string>|nil ---@return string|nil local function get_archive_name(version, os_distribution) - local name_template = coalesce( - when(platform.is_mac, "clang+llvm-%s-x86_64-apple-darwin"), - when( - platform.is_linux, - coalesce( - when( - platform.arch == "x64", - coalesce( - when( - os_distribution.id == "ubuntu" and os_distribution.version.major >= 20, - "clang+llvm-%s-x86_64-linux-gnu-ubuntu-20.04" - ), - when( - os_distribution.id == "ubuntu" and os_distribution.version.major >= 16, - "clang+llvm-%s-x86_64-linux-gnu-ubuntu-16.04" - ), - -- the Ubuntu dist is allegedly the most suitable cross-platform one, so we default to it + local name_template = coalesce(when( + platform.is_linux, + coalesce( + when( + platform.arch == "x64", + coalesce( + when( + os_distribution.id == "ubuntu" and os_distribution.version.major >= 20, + "clang+llvm-%s-x86_64-linux-gnu-ubuntu-20.04" + ), + when( + os_distribution.id == "ubuntu" and os_distribution.version.major >= 16, "clang+llvm-%s-x86_64-linux-gnu-ubuntu-16.04" - ) - ), - when(platform.arch == "arm64", "clang+llvm-%s-aarch64-linux-gnu"), - when(platform.arch == "armv7", "clang+llvm-%s-armv7a-linux-gnueabihf"), - when(platform.arch == "x86", "clang+llvm-%s-i386-unknown-freebsd13") - ) + ), + -- the Ubuntu dist is allegedly the most suitable cross-platform one, so we default to it + "clang+llvm-%s-x86_64-linux-gnu-ubuntu-16.04" + ) + ), + when(platform.arch == "arm64", "clang+llvm-%s-aarch64-linux-gnu"), + when(platform.arch == "armv7", "clang+llvm-%s-armv7a-linux-gnueabihf"), + when(platform.arch == "x86", "clang+llvm-%s-i386-unknown-freebsd13") ) - ) + )) return name_template and name_template:format(version) end @@ -53,6 +72,7 @@ return function(name, root_dir) end llvm_installer = installers.branch_context { + context.use_os_distribution(), context.set(function(ctx) -- We unset the requested version for llvm because it's not the primary target - the user's requested version should only apply to ccls. ctx.requested_server_version = nil @@ -71,6 +91,7 @@ return function(name, root_dir) get_archive_name(normalize_version(ctx.requested_server_version), ctx.os_distribution), "llvm" ), + -- We move the clang headers out, because they need to be persisted std.rename( path.concat { "llvm", "lib", "clang", normalize_version(ctx.requested_server_version) }, "clang-resource" @@ -80,33 +101,65 @@ return function(name, root_dir) } end - local ccls_installer = installers.branch_context { + local ccls_installer = installers.pipe { + std.git_clone("https://github.com/MaskRay/ccls", { + directory = "ccls-git", + recursive = true, + }), + function(server, callback, ctx) + local c = process.chain { + cwd = path.concat { ctx.install_dir, "ccls-git" }, + stdio_sink = ctx.stdio_sink, + } + + local clang_resource_dir = path.concat { server.root_dir, "clang-resource" } + + c.run( + "cmake", + list_not_nil( + "-DCMAKE_BUILD_TYPE=Release", + "-DUSE_SYSTEM_RAPIDJSON=OFF", + "-DCMAKE_FIND_FRAMEWORK=LAST", + "-Wno-dev", + ("-DCMAKE_INSTALL_PREFIX=%s"):format(ctx.install_dir), + ("-DCMAKE_PREFIX_PATH=%s"):format(ctx.llvm_dir), + when(platform.is_mac, "-DCMAKE_OSX_SYSROOT=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk"), + when(platform.is_linux, ("-DCLANG_RESOURCE_DIR=%s"):format(clang_resource_dir)) + ) + ) + c.run("make", { "install" }) + c.spawn(callback) + end, + std.rmrf "ccls-git", + } + + local linux_ccls_installer = installers.pipe { + llvm_installer, context.set(function(ctx) - ctx.llvm_install_dir = path.concat { ctx.install_dir, "llvm" } - ctx.clang_resource_dir = path.concat { ctx.install_dir, "clang-resource" } + ctx.llvm_dir = path.concat { ctx.install_dir, "llvm" } end), - installers.branch_context { - context.set_working_dir "ccls-git", - std.git_clone "https://github.com/MaskRay/ccls", - std.git_submodule_update(), - function(_, callback, ctx) - local c = process.chain { - cwd = ctx.install_dir, - stdio_sink = ctx.stdio_sink, - } + ccls_installer, + std.rmrf "llvm", + } - c.run("cmake", { - "-H.", - "-BRelease", - "-DCMAKE_BUILD_TYPE=Release", - ("-DCMAKE_PREFIX_PATH=%s"):format(ctx.llvm_install_dir), - ("-DCLANG_RESOURCE_DIR=%s"):format(ctx.clang_resource_dir), - }) - c.run("cmake", { "--build", "Release" }) - c.spawn(callback) - end, - }, - std.rename(path.concat { "ccls-git", "Release", "ccls" }, "ccls"), + local mac_ccls_installer = installers.pipe { + context.use_homebrew_prefix(), + context.set(function(ctx) + ctx.llvm_dir = path.concat { ctx.homebrew_prefix, "opt", "llvm" } + end), + function(_, callback, ctx) + if not fs.dir_exists(ctx.llvm_dir) then + ctx.stdio_sink.stderr( + ( + "LLVM does not seem to be installed on this system (looked in %q). Please install LLVM via Homebrew:\n $ brew install llvm\n" + ):format(ctx.llvm_dir) + ) + callback(false) + return + end + callback(true) + end, + ccls_installer, } return server.Server:new { @@ -115,17 +168,11 @@ return function(name, root_dir) homepage = "https://github.com/MaskRay/ccls", languages = { "c", "c++", "objective-c" }, installer = installers.when { - unix = { - context.use_os_distribution(), - context.promote_install_dir(), -- ccls hardcodes the path to llvm at compile time, so we need to compile everything in the final directory - llvm_installer, - ccls_installer, - std.rmrf "llvm", - std.rmrf "ccls-git", - }, + mac = mac_ccls_installer, + linux = linux_ccls_installer, }, default_options = { - cmd = { path.concat { root_dir, "ccls" } }, + cmd = { path.concat { root_dir, "bin", "ccls" } }, }, } end |
