|
| 1 | +" Check for Node.js >= v16.10 |
| 2 | +function! s:isNodeJsVersionSufficient(node) |
| 3 | + let node_version = system(a:node.' --version') |
| 4 | + let node_version_parts = map(filter(split(node_version, '\v\ze\.|v'), 'v:val =~ "\\v\\d+"'), 'matchstr(v:val, "\\v\\d+")') |
| 5 | + if len(node_version_parts) >= 2 && (node_version_parts[0] > 16 || (node_version_parts[0] == 16 && node_version_parts[1] >= 10)) |
| 6 | + return 1 |
| 7 | + endif |
| 8 | + return 0 |
| 9 | +endfunction |
| 10 | + |
| 11 | +" Will do the following checks in order of precedence: |
| 12 | +" -Use $NODE or $NODE/node if they exist and are executable |
| 13 | +" -check for node as vim-plug plugin (user-specific) |
| 14 | +" -check for system-wide install of node |
| 15 | +" -If all above fail will get node as vim-plug plugin and build it |
| 16 | +" Changes $PATH to include node path |
| 17 | +function! s:isNewNodeJsRequired() |
| 18 | + let pathsep = g:spacevim.os.windows ? ';' : ':' |
| 19 | + " Prefer $NODE override |
| 20 | + if exists('$NODE') |
| 21 | + if executable('$NODE') == 1 && s:isNodeJsVersionSufficient('$NODE') |
| 22 | + let $PATH = fnamemodify($NODE, ':h').pathsep.$PATH |
| 23 | + return 0 |
| 24 | + elseif executable('$NODE/node') == 1 && s:isNodeJsVersionSufficient('$NODE/node') |
| 25 | + let $PATH = $NODE.pathsep.$PATH |
| 26 | + return 0 |
| 27 | + endif |
| 28 | + endif |
| 29 | + " Prefer user/plugin Node.js if it exists |
| 30 | + if executable(g:plug_home.'/node/node') == 1 && s:isNodeJsVersionSufficient(g:plug_home.'/node/node') |
| 31 | + let $PATH = g:plug_home.'/node'.pathsep.$PATH |
| 32 | + return 0 |
| 33 | + endif |
| 34 | + " Last check for system-wide Node.js |
| 35 | + if executable('node') == 1 && s:isNodeJsVersionSufficient('node') |
| 36 | + return 0 |
| 37 | + endif |
| 38 | + return 1 |
| 39 | +endfunction |
| 40 | + |
| 41 | +" If no valid $NODE or systemwide node.js: build node.js dependency |
| 42 | +function! BuildNodeJs(info) |
| 43 | + if g:spacevim.os.windows |
| 44 | + echom 'Building Node.js automatically is not supported on Windows, Build it manually or send PR' |
| 45 | + return |
| 46 | + endif |
| 47 | + if (!exists('$CC') && executable('gcc') != 1) || executable('make') != 1 || executable('python3') != 1 |
| 48 | + echom 'Unable to build Node.js, requires a C++ compiler, make, and python3' |
| 49 | + return |
| 50 | + endif |
| 51 | + if !spacevim#load('programming') |
| 52 | + echom "nodejs layer requires the 'programming' layer to build. Add 'programming' layer to init.spacevim" |
| 53 | + return |
| 54 | + endif |
| 55 | + |
| 56 | + echom 'Building Node.js, please wait... restart Vim on completion' |
| 57 | + let ninja_flag = '' |
| 58 | + let jobs_flag = '' |
| 59 | + if executable('ninja') |
| 60 | + let ninja_flag=' --ninja' |
| 61 | + else |
| 62 | + " Determine number of cores/threads for make -j, ninja autodetects |
| 63 | + if executable('lscpu') |
| 64 | + execute 'let num_threads = '.join(split(system("lscpu | grep -E '?^(CPU\\(s\\):|Thread\\(s\\) per core:)' | tr -s ' ' | cut -f 2 -d:")),'*') |
| 65 | + else |
| 66 | + let num_threads = 4 |
| 67 | + endif |
| 68 | + let jobs_flag = ' -j '.num_threads |
| 69 | + endif |
| 70 | + |
| 71 | + " This sets up corepack/npm links as default make taget doesn't |
| 72 | + " Could alternatively `make install` to prefix and set PATH to prefix/bin |
| 73 | + let temp_dir = fnamemodify(tempname(), ':p:h') |
| 74 | + call system('./configure --prefix=./build'.ninja_flag.' > '.temp_dir.'/nodejs_configure.log') |
| 75 | + |
| 76 | + " Cache any existing Make definition and restore |
| 77 | + let makeDefinitionTest = split(execute(':command Make'), '\n') |
| 78 | + if len(makeDefinitionTest) > 1 |
| 79 | + let makeDefinition = split(makeDefinitionTest[2], '\s\s\+') |
| 80 | + endif |
| 81 | + command! -bang -nargs=* -bar Make AsyncRun -mode=term -pos=tab -program=make @ <args> |
| 82 | + execute 'Make'.jobs_flag |
| 83 | + delcommand Make |
| 84 | + if exists('makeDefinition') |
| 85 | + " Restores prior definition. Has inadequacies. |
| 86 | + execute 'command! '.(makeDefinition[0] =~ '!' ? '-bang ' : '').(makeDefinition[0] =~ '|' ? '-bar ' : '').(makeDefinition[0] =~ 'b' ? '-buffer ' : '').makeDefinition[0] =~ '\"' ? '-register ' : '').'-nargs='.makeDefinition[1].' Make '.makeDefinition[3] |
| 87 | + endif |
| 88 | + let $NODE = fnamemodify('.', ':p').'/node' |
| 89 | + " TODO: Uncertain if correct node_modules |
| 90 | + let $NODE_PATH = fnamemodify('.', ':p').'/tools/node_modules' |
| 91 | + let pathsep = g:spacevim.os.windows ? ';' : ':' |
| 92 | + let $PATH = g:plug_home.'/node'.pathsep.$PATH |
| 93 | + |
| 94 | + " Set links which `make install` does, they're necessary for use |
| 95 | + call system("ln -s deps/corepack/dist/corepack.js corepack") |
| 96 | + call system("ln -s deps/npm/bin/npm-cli.js npm") |
| 97 | + call system("ln -s deps/npm/bin/npx-cli.js npx") |
| 98 | + " Make Yarn available |
| 99 | + call system("node corepack enable") |
| 100 | +endfunction |
| 101 | + |
| 102 | +" isNewNodeJsRequired will add node to $PATH if needed |
| 103 | +if s:isNewNodeJsRequired() |
| 104 | + MP 'nodejs/node', { 'do': function('BuildNodeJs') } |
| 105 | +endif |
0 commit comments