老舊 Linux 系統搭建現代 C++ 開發環境 —— 基於 neovim

来源:https://www.cnblogs.com/goodcitizen/p/18197750/build_development_environment_for_cpp_on_old_linux_by_neovim
-Advertisement-
Play Games

問題背景 公司配發的電腦是 macOS,日常開發需要訪問 Linux 虛擬機,出於安全方面的考慮,只能通過跳板機登錄。這阻止了大多數遠程圖形界面的使用,讓寫代碼的工作變得複雜起來,市面上非常好用的 VSCode 都用不了。因此考慮基於 vim 搭建一套個人開發環境,需要支持以下特性: 語法高亮 (風 ...


問題背景

公司配發的電腦是 macOS,日常開發需要訪問 Linux 虛擬機,出於安全方面的考慮,只能通過跳板機登錄。這阻止了大多數遠程圖形界面的使用,讓寫代碼的工作變得複雜起來,市面上非常好用的 VSCode 都用不了。因此考慮基於 vim 搭建一套個人開發環境,需要支持以下特性:

  • 語法高亮 (風格可切換)
  • 自動格式化
  • 函數或變數定義跳轉
  • 函數或變數引用跳轉
  • 成員函數或變數下拉列表提示
  • 函數或變數 TAB 鍵自動補齊
  • 快速查找
  • ……

考察了多種方案後,決定基於目前比較流行的 neovim 來打造,不過它面向的是比較新的 Linux 發行版,不知道我這個老的 CentOS7 能不能帶起來,本文就是一個探索過程。

系統環境

開始之前,先羅列下老舊系統的配置:

  • 硬體
    • CPU: 2.40GHz * 2 核
    • 記憶體: 16G
    • 存儲: 40G + 100G
  • 軟體
    • 系統:CentOS Linux release 7.9.2009 (Core)
    • kernel:3.10.0-1160.21.1.el7.x86_64
    • rpm:4.11.3
    • gcc:4.8.5 (備選 8.2)
    • glibc:2.17
    • make:GNU make 3.82
    • openssl:1.0.2k
    • git:1.8
    • wget:1.14
    • python: 3.6.8

確實是老舊,都是公司成本控制的淚~

軟體安裝

整個搭建過程是比較坎坷的,常常是裝了 Z 之後才發現它依賴 X、Y,去安裝 X、Y 的時候又發現一坨問題……這裡為了直接上手,改為正敘模式,按這個方式一步步安裝、升級,應該是沒問題的。如果你的系統上已經存在依賴的軟體且版本一致或更新,可以忽略對應安裝過程。

在 Linux 上安裝軟體,一般有源碼安裝和包管理器安裝兩種方式,後者在 CentOS 上就是 yum 了,然而軟體源提供的軟體一般版本較低,有時需要使用前者,這就比較依賴 wget、git、gcc 和 make 了,這也是在上一節中列出他們版本的原因,在開始安裝各種軟體之前,需要首先升級他們。

基礎軟體升級

gcc

系統提供的 4.8.5 編譯基本是夠用的,後面代碼格式化需要用到的 clang-format 模塊如果是源碼方式安裝,要求 gcc 至少是 5.1,如果你有 5.1 及以上的 gcc 那更好。沒有也沒關係,本文會用其它方式繞過,畢竟升級 gcc 是一項大工程,沒有半天是搞不定的,太耽誤功夫。

雖然不必升級 gcc,但是一些代碼庫使用的高版本 gcc 預設了 -std=c99 選項,這點對老版本非常不友好,為此需要特意告訴老 gcc 編譯器這個選項。具體就是修改 gcc 的 spec 文件,首先是確認當前系統 gcc 載入的 spec 文件:

> strace -e file gcc 2>&1 | grep specs
access("/usr/lib/gcc/x86_64-redhat-linux/4.8.5/specs", R_OK) = -1 ENOENT (No such file or directory)
access("/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../x86_64-redhat-linux/lib/x86_64-redhat-linux/4.8.5/specs", R_OK) = -1 ENOENT (No such file or directory)
access("/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../x86_64-redhat-linux/lib/specs", R_OK) = -1 ENOENT (No such file or directory)
access("/usr/lib/gcc/x86_64-redhat-linux/specs", R_OK) = -1 ENOENT (No such file or directory)

目前看是沒有,需要使用 gcc 析出一份預設的:

> sudo bash -c 'gcc -dumpspecs > /usr/lib/gcc/x86_64-redhat-linux/4.8.5/specs'

註意析出的路徑就是上面載入路徑中的第一條,內容如下:

查看代碼
 *asm:
%{m32:--32}  %{m32|mx32:;:--64}  %{mx32:--x32}  %{!mno-sse2avx:%{mavx:-msse2avx}} %{msse2avx:%{!mavx:-msse2avx}}

*asm_debug:
%{!g0:%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}} %{fdebug-prefix-map=*:--debug-prefix-map %*}

*asm_final:
%{gsplit-dwarf:
       objcopy --extract-dwo 	 %{c:%{o*:%*}%{!o*:%b%O}}%{!c:%U%O} 	 %{c:%{o*:%:replace-extension(%{o*:%*} .dwo)}%{!o*:%b.dwo}}%{!c:%b.dwo}
       objcopy --strip-dwo 	 %{c:%{o*:%*}%{!o*:%b%O}}%{!c:%U%O}     }

*asm_options:
%{-target-help:%:print-asm-header()} %{v} %{w:-W} %{I*} %a %Y %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}

*invoke_as:
%{!fwpa:   %{fcompare-debug=*|fdump-final-insns=*:%:compare-debug-dump-opt()}   %{!S:-o %|.s |
 as %(asm_options) %m.s %A }  }

*cpp:
%{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}

*cpp_options:
%(cpp_unique_options) %1 %{m*} %{std*&ansi&trigraphs} %{W*&pedantic*} %{w} %{f*} %{g*:%{!g0:%{g*} %{!fno-working-directory:-fworking-directory}}} %{O*} %{undef} %{save-temps*:-fpch-preprocess}

*cpp_debug_options:
%{d*}

*cpp_unique_options:
%{!Q:-quiet} %{nostdinc*} %{C} %{CC} %{v} %{I*&F*} %{P} %I %{MD:-MD %{!o:%b.d}%{o*:%.d%*}} %{MMD:-MMD %{!o:%b.d}%{o*:%.d%*}} %{M} %{MM} %{MF*} %{MG} %{MP} %{MQ*} %{MT*} %{!E:%{!M:%{!MM:%{!MT:%{!MQ:%{MD|MMD:%{o*:-MQ %*}}}}}}} %{remap} %{g3|ggdb3|gstabs3|gcoff3|gxcoff3|gvms3:-dD} %{!iplugindir*:%{fplugin*:%:find-plugindir()}} %{H} %C %{D*&U*&A*} %{i*} %Z %i %{fmudflap:-D_MUDFLAP -include mf-runtime.h} %{fmudflapth:-D_MUDFLAP -D_MUDFLAPTH -include mf-runtime.h} %{E|M|MM:%W{o*}}

*trad_capable_cpp:
cc1 -E %{traditional|traditional-cpp:-traditional-cpp}

*cc1:
%{!mandroid|tno-android-cc:%(cc1_cpu) %{profile:-p};:%(cc1_cpu) %{profile:-p} %{!mglibc:%{!muclibc:%{!mbionic: -mbionic}}} %{!fno-pic:%{!fno-PIC:%{!fpic:%{!fPIC: -fPIC}}}}}

*cc1_options:
%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}} %{!iplugindir*:%{fplugin*:%:find-plugindir()}} %1 %{!Q:-quiet} %{!dumpbase:-dumpbase %B} %{d*} %{m*} %{aux-info*} %{fcompare-debug-second:%:compare-debug-auxbase-opt(%b)}  %{!fcompare-debug-second:%{c|S:%{o*:-auxbase-strip %*}%{!o*:-auxbase %b}}}%{!c:%{!S:-auxbase %b}}  %{g*} %{O*} %{W*&pedantic*} %{w} %{std*&ansi&trigraphs} %{v:-version} %{pg:-p} %{p} %{f*} %{undef} %{Qn:-fno-ident} %{Qy:} %{-help:--help} %{-target-help:--target-help} %{-version:--version} %{-help=*:--help=%*} %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}} %{fsyntax-only:-o %j} %{-param*} %{fmudflap|fmudflapth:-fno-builtin -fno-merge-constants} %{coverage:-fprofile-arcs -ftest-coverage}

*cc1plus:


*link_gcc_c_sequence:
%{static:--start-group} %G %L %{static:--end-group}%{!static:%G}

*link_ssp:
%{fstack-protector:}

*endfile:
%{!mandroid|tno-android-ld:%{Ofast|ffast-math|funsafe-math-optimizations:crtfastmath.o%s}    %{mpc32:crtprec32.o%s}    %{mpc64:crtprec64.o%s}    %{mpc80:crtprec80.o%s} %{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s;:%{Ofast|ffast-math|funsafe-math-optimizations:crtfastmath.o%s}    %{mpc32:crtprec32.o%s}    %{mpc64:crtprec64.o%s}    %{mpc80:crtprec80.o%s} %{shared: crtend_so%O%s;: crtend_android%O%s}}

*link:
%{!r:--build-id} --no-add-needed %{!static:--eh-frame-hdr} --hash-style=gnu %{!mandroid|tno-android-ld:%{m32|mx32:;:-m elf_x86_64}                    %{m32:-m elf_i386}                    %{mx32:-m elf32_x86_64}   %{shared:-shared}   %{!shared:     %{!static:       %{rdynamic:-export-dynamic}       %{m32:-dynamic-linker %{muclibc:/lib/ld-uClibc.so.0;:%{mbionic:/system/bin/linker;:/lib/ld-linux.so.2}}}       %{m32|mx32:;:-dynamic-linker %{muclibc:/lib/ld64-uClibc.so.0;:%{mbionic:/system/bin/linker64;:/lib64/ld-linux-x86-64.so.2}}}       %{mx32:-dynamic-linker %{muclibc:/lib/ldx32-uClibc.so.0;:%{mbionic:/system/bin/linkerx32;:/libx32/ld-linux-x32.so.2}}}}     %{static:-static}};:%{m32|mx32:;:-m elf_x86_64}                    %{m32:-m elf_i386}                    %{mx32:-m elf32_x86_64}   %{shared:-shared}   %{!shared:     %{!static:       %{rdynamic:-export-dynamic}       %{m32:-dynamic-linker %{muclibc:/lib/ld-uClibc.so.0;:%{mbionic:/system/bin/linker;:/lib/ld-linux.so.2}}}       %{m32|mx32:;:-dynamic-linker %{muclibc:/lib/ld64-uClibc.so.0;:%{mbionic:/system/bin/linker64;:/lib64/ld-linux-x86-64.so.2}}}       %{mx32:-dynamic-linker %{muclibc:/lib/ldx32-uClibc.so.0;:%{mbionic:/system/bin/linkerx32;:/libx32/ld-linux-x32.so.2}}}}     %{static:-static}} %{shared: -Bsymbolic}}

*lib:
%{!mandroid|tno-android-ld:%{pthread:-lpthread}    %{shared:-lc}    %{!shared:%{mieee-fp:-lieee} %{profile:-lc_p}%{!profile:-lc}};:%{pthread:-lpthread}    %{shared:-lc}    %{!shared:%{mieee-fp:-lieee} %{profile:-lc_p}%{!profile:-lc}} %{!static: -ldl}}

*mfwrap:
 %{static: %{fmudflap|fmudflapth:  --wrap=malloc --wrap=free --wrap=calloc --wrap=realloc --wrap=mmap --wrap=mmap64 --wrap=munmap --wrap=alloca} %{fmudflapth: --wrap=pthread_create}} %{fmudflap|fmudflapth: --wrap=main}

*mflib:
%{fmudflap|fmudflapth: -export-dynamic}

*link_gomp:


*libgcc:
%{static|static-libgcc:-lgcc -lgcc_eh}%{!static:%{!static-libgcc:%{!shared-libgcc:-lgcc --as-needed -lgcc_s --no-as-needed}%{shared-libgcc:-lgcc_s%{!shared: -lgcc}}}}

*startfile:
%{!mandroid|tno-android-ld:%{!shared: %{pg|p|profile:gcrt1.o%s;pie:Scrt1.o%s;:crt1.o%s}}    crti.o%s %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s};:%{shared: crtbegin_so%O%s;:  %{static: crtbegin_static%O%s;: crtbegin_dynamic%O%s}}}

*cross_compile:
0

*version:
4.8.5

*multilib:
. !m64 !m32;64:../lib64 m64 !m32;32:../lib !m64 m32;

*multilib_defaults:
m64

*multilib_extra:


*multilib_matches:
m64 m64;m32 m32;

*multilib_exclusions:


*multilib_options:
m64/m32

*multilib_reuse:


*linker:
collect2

*linker_plugin_file:


*lto_wrapper:


*lto_gcc:


*link_libgcc:
%D

*md_exec_prefix:


*md_startfile_prefix:


*md_startfile_prefix_1:


*startfile_prefix_spec:


*sysroot_spec:
--sysroot=%R

*sysroot_suffix_spec:


*sysroot_hdrs_suffix_spec:


*self_spec:


*cc1_cpu:
%{march=native:%>march=native %:local_cpu_detect(arch)   %{!mtune=*:%>mtune=native %:local_cpu_detect(tune)}} %{mtune=native:%>mtune=native %:local_cpu_detect(tune)}

*link_command:
%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:    %(linker) %{!fno-use-linker-plugin:%{flto|flto=*|fuse-linker-plugin:     -plugin %(linker_plugin_file)     -plugin-opt=%(lto_wrapper)     -plugin-opt=-fresolution=%u.res     %{!nostdlib:%{!nodefaultlibs:%:pass-through-libs(%(link_gcc_c_sequence))}}     }}%{flto|flto=*:%<fcompare-debug*}     %{flto} %{flto=*} %l %{pie:-pie} %{fuse-ld=*:-fuse-ld=%*}    %X %{o*} %{e*} %{N} %{n} %{r}    %{s} %{t} %{u*} %{z} %{Z} %{!nostdlib:%{!nostartfiles:%S}}    %{static:} %{L*} %(mfwrap) %(link_libgcc) %{!nostdlib:%{!nodefaultlibs:%{fsanitize=address:%{!shared:libasan_preinit%O%s} %{static-libasan:%{!shared:-Bstatic --whole-archive -lasan --no-whole-archive -Bdynamic}}%{!static-libasan:-lasan}}     %{fsanitize=thread:%{static-libtsan:%{!shared:-Bstatic --whole-archive -ltsan --no-whole-archive -Bdynamic}}%{!static-libtsan:-ltsan}}}} %o    %{fopenmp|ftree-parallelize-loops=*:%:include(libgomp.spec)%(link_gomp)}    %{fgnu-tm:%:include(libitm.spec)%(link_itm)}    %(mflib)  %{fsplit-stack: --wrap=pthread_create}    %{fprofile-arcs|fprofile-generate*|coverage:-lgcov} %{!nostdlib:%{!nodefaultlibs:%{fsanitize=address: %{static-libasan:-ldl -lpthread}    %{static:%ecannot specify -static with -fsanitize=address}    %{fsanitize=thread:%e-fsanitize=address is incompatible with -fsanitize=thread}}    %{fsanitize=thread: %{static-libtsan:-ldl -lpthread}    %{!pie:%{!shared:%e-fsanitize=thread linking must be done with -pie or -shared}}}}}     %{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}    %{!nostdlib:%{!nostartfiles:%E}} %{T*} }}}}}}

信息比較多,定位到關鍵字 *cc1_options:, 在 %{w}%{std*&ansi&trigraphs} 之間添加 -std=c99

> cat /usr/lib/gcc/x86_64-redhat-linux/4.8.5/specs.c99 | grep c99
%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}} %{!iplugindir*:%{fplugin*:%:find-plugindir()}} %1 %{!Q:-quiet} %{!dumpbase:-dumpbase %B} %{d*} %{m*} %{aux-info*} %{fcompare-debug-second:%:compare-debug-auxbase-opt(%b)}  %{!fcompare-debug-second:%{c|S:%{o*:-auxbase-strip %*}%{!o*:-auxbase %b}}}%{!c:%{!S:-auxbase %b}}  %{g*} %{O*} %{W*&pedantic*} %{w} -std=c99 %{std*&ansi&trigraphs} %{v:-version} %{pg:-p} %{p} %{f*} %{undef} %{Qn:-fno-ident} %{Qy:} %{-help:--help} %{-target-help:--target-help} %{-version:--version} %{-help=*:--help=%*} %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}} %{fsyntax-only:-o %j} %{-param*} %{fmudflap|fmudflapth:-fno-builtin -fno-merge-constants} %{coverage:-fprofile-arcs -ftest-coverage}

再次運行 gcc,確認已載入修改後的 spec 文件:

> gcc -v
Reading specs from /usr/lib/gcc/x86_64-redhat-linux/4.8.5/specs
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux
Thread model: posix
gcc version 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)

第一行的輸出符合預期,整個過程可參考附錄 4。

如果不進行這個設置,後面在編譯 lsp-server 中的 lsp-kind.nvim & nvim-lspconfig 模塊時會失敗:

glibc

系統提供的 2.17 不行,clangd 需要至少 2.18,否則 neovim 中跳轉相關的鍵 (gd/gD) 會失效,而 yum 上沒有大於 2.17 版本的軟體可用,需要手動更新下:

# 通過網盤鏈接下載 rpm 包
# 鏈接: https://pan.baidu.com/s/1QAyqa04iZ45q1-HqeYH80Q?pwd=1234 提取碼: 1234 
> ls -lh *.rpm
-rw-r--r-- 1 yunhai01 DOORGOD 3.6M May 17 16:28 glibc-2.18-11.fc20.x86_64.rpm
-rw-r--r-- 1 yunhai01 DOORGOD  12M May 17 16:28 glibc-common-2.18-11.fc20.x86_64.rpm
-rw-r--r-- 1 yunhai01 DOORGOD 1.1M May 17 16:28 glibc-devel-2.18-11.fc20.x86_64.rpm
-rw-r--r-- 1 yunhai01 DOORGOD 648K May 17 16:28 glibc-headers-2.18-11.fc20.x86_64.rpm
> sudo rpm -Uvh --nodeps --force glibc-*.rpm
> ldd --version
ldd (GNU libc) 2.18
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.

具體升級過程可參考附錄 2。

make

系統提供的 3.82 GNU Make 基本夠用。

openssl

系統提供的 1.0.2k 基本夠用。

git

系統提供的 1.8 版本不行,需要升級到 2.38,否則不能識別 rebase=false 參數,導致插件更新時拉取代碼庫失敗:

當時直接使用 yum install git 升級的版本還是比較低,所以我是手動安裝的,但也取了個巧,直接安裝了個 rpm 來更新 CentOS7 的軟體源:

> sudo yum install https://packages.endpointdev.com/rhel/7/os/x86_64/endpoint-repo.x86_64.rpm
> sudo yum install git
> git --version
git version 2.38.1

從而找到更新版本的 git,省了不少事。後來這個源還更新了,現在安裝的話是 2.43 版本。

另外最好更新 /etc/hosts 文件以便加快對 github.com 的訪問速度:

> cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
140.82.114.3 github.com
140.82.114.10 nodeload.github.com
140.82.114.6 api.github.com
140.82.114.10 codeload.github.com

這裡的 ip 都是通過反查相關功能變數名稱得到的,可能會有所不同,詳情參考附錄 3。

wget

系統提供的 1.14 版本不行,在拉取部分 lsp-server 時會出錯 (cpp/lua),需要升級到 1.21.3:

> curl -o wget-latest.tar.gz http://mirrors.ustc.edu.cn/gnu/wget/wget-latest.tar.gz
> tar xvf wget-latest.tar.gz
> cd wget-1.21.3
> ./configure --with-ssl=openssl
> make -j8
> sudo make install
> wget --version
GNU Wget 1.21.3 built on linux-gnu.

-cares +digest -gpgme +https +ipv6 -iri +large-file -metalink +nls
+ntlm +opie -psl +ssl/openssl

Wgetrc:
    /usr/local/etc/wgetrc (system)
Locale:
    /usr/local/share/locale
Compile:
    gcc -std=gnu11 -DHAVE_CONFIG_H
    -DSYSTEM_WGETRC="/usr/local/etc/wgetrc"
    -DLOCALEDIR="/usr/local/share/locale" -I. -I../lib -I../lib
    -DHAVE_LIBSSL -DNDEBUG -g -O2
Link:
    gcc -std=gnu11 -DHAVE_LIBSSL -DNDEBUG -g -O2 -lpcre -lssl -lcrypto
    -lz ../lib/libgnu.a

Copyright (C) 2015 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
<http://www.gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Originally written by Hrvoje Niksic <[email protected]>.
Please send bug reports and questions to <[email protected]>.

目前的 wget-lastest 指向的最新版本是 1.24.5。

python3

系統提供的 3.6.8 版本勉強夠用,clang-format 編譯安裝要求 python 至少為 3.8 版本,可以選擇安裝 Python 3.8.1:

> sudo yum install libffi-devel
> wget https://www.python.org/ftp/python/3.8.1/Python-3.8.1.tgz
> tar -xvf Python-3.8.1.tgz
> cd Python-3.8.1
> ./configure --prefix=/usr/local/python3
> make -j8
> sudo make altinstall
> sudo ln -sf /usr/local/python3/bin/python3.8 /usr/bin/python3
> sudo ln -sf /usr/local/python3/bin/pip3.8 /usr/bin/pip3

不過可以通過直接下載 clang-format 來忽略這步,所以這裡的 python3 沒有升級,具體操作步驟在安裝 clang-format 時介紹。

cargo

rust 的包管理器,系統未提供,需要單獨安裝:

> sudo yum install cargo
> cargo --version
cargo 1.65.0

用於後續安裝 fd,它是一款 find 的替代者,可以實現更高效的文件查找,目前 yum 上最新的版本是 1.72.1。

go

go 語言編譯器,系統未提供,需要單獨安裝:

> sudo yum install go
> go version
go version go1.17.12 linux/amd64

用來後續編譯安裝 efm-langserver,它是一款代碼審查工具。目前 yum 源最新 go 版本是 1.20.12。為避免後續安裝過程中出現網路訪問錯誤的問題,可提前設置以下代理:

> go env -w GO111MODULE=on
> go env -w GOPROXY=https://goproxy.io,direct
> go env -w GOPRIVATE=*.corp.example.com

sqlite3

本地資料庫,系統未提供,需要單獨安裝:

> sudo yum install sqlite sqlite-devel
> sqlite3 --version
3.7.17 2013-05-20 00:56:22 118a3b35693b134d56ebd780123b7fd6f1497668

用於後續安裝 scheme ,它是一款語法高亮插件,使用 sqlite3 存儲信息。

升級後

  • gcc:4.8.5
  • glibc:2.18
  • make:GNU make 3.82
  • openssl:1.0.2k
  • git:2.43
  • wget:1.24.5
  • python: 3.6.8
  • cargo:1.72.1
  • go:1.20.12
  • sqlite3:3.7.17

依賴軟體安裝

rg

全名 ripgrep,是 grep 替代者,功能更強大,不能直接使用 yum 安裝,通過添加 yum 源的方式來曲線安裝:

> sudo yum-config-manager --add-repo=https://copr.fedorainfracloud.org/coprs/carlwgeorge/ripgrep/repo/epel-7/carlwgeorge-ripgrep-epel-7.repo
> sudo yum install ripgrep
> rg --version
ripgrep 13.0.0
-SIMD -AVX (compiled)
+SIMD +AVX (runtime)

源是固定的,版本目前仍保持 13.0.0。

fd

全名 fd-find,用來替代 find,功能更強大,有之前安裝 cargo 的基礎,直接安裝:

> cargo install fd-find
> sudo cp ~/.cargo/bin/fd /usr/local/bin/
> fd --version 
fd 8.5.3

基於最新的 cargo 1.72.1 安裝會報錯:

> cargo install fd-find
    Updating crates.io index
  Downloaded fd-find v10.1.0
...
warning: spurious network error (3 tries remaining): [7] Couldn't connect to server (Failed to connect to 2a04:4e42:8c::649: Network is unreachable)
  Downloaded jemalloc-sys v0.5.4+5.3.0-patched
  Downloaded 64 crates (8.2 MB) in 3m 10s (largest was `linux-raw-sys` at 1.8 MB)
error: failed to compile `fd-find v10.1.0`, intermediate artifacts can be found at `/tmp/cargo-installBfI2hZ`.
To reuse those artifacts with a future compilation, set the environment variable `CARGO_TARGET_DIR` to that path.

Caused by:
  package `clap_complete v4.5.2` cannot be built because it requires rustc 1.74 or newer, while the currently active rustc version is 1.72.1
  Try re-running cargo install with `--locked`

看起來需要升級 rustc (1.74 > 1.72.1),不過看到要安裝的 fd-find 版本為 10.1.0,好像受到了啟發,直接指定 fd-find 的版本為 8.5.3 重試:

> cargo install fd-find --version 8.5.3
  Downloaded fd-find v8.5.3
  Downloaded 1 crate (114.1 KB) in 9.31s
    Updating crates.io index
  Installing fd-find v8.5.3
    Updating crates.io index
...
  Downloaded 22 crates (2.2 MB) in 1m 07s (largest was `linux-raw-sys` at 1013.8 KB)
error: failed to compile `fd-find v8.5.3`, intermediate artifacts can be found at `/tmp/cargo-installmg1If6`.
To reuse those artifacts with a future compilation, set the environment variable `CARGO_TARGET_DIR` to that path.

Caused by:
  package `clap_complete v4.5.2` cannot be built because it requires rustc 1.74 or newer, while the currently active rustc version is 1.72.1
  Try re-running cargo install with `--locked`

仍然失敗,叔可忍嬸不可忍,直接按提示加 --locked 選項:

查看代碼
 > cargo install fd-find --version 8.5.3 --locked
    Updating crates.io index
  Installing fd-find v8.5.3
    Updating crates.io index
warning: spurious network error (3 tries remaining): [7] Couldn't connect to server (Failed to connect to 2600:9000:20e4:fe00:1f:a9f5:69c0:93a1: Network is unreachable)
warning: spurious network error (3 tries remaining): [28] Timeout was reached (Operation timed out after 30000 milliseconds with 0 out of 0 bytes received)
warning: spurious network error (3 tries remaining): [28] Timeout was reached (Operation too slow. Less than 10 bytes/sec transferred the last 30 seconds)
warning: spurious network error (3 tries remaining): [28] Timeout was reached (Operation too slow. Less than 10 bytes/sec transferred the last 30 seconds)
warning: spurious network error (3 tries remaining): [28] Timeout was reached (Operation too slow. Less than 10 bytes/sec transferred the last 30 seconds)
warning: spurious network error (3 tries remaining): [28] Timeout was reached (Operation too slow. Less than 10 bytes/sec transferred the last 30 seconds)
warning: package `crossbeam-channel v0.5.6` in Cargo.lock is yanked in registry `crates-io`, consider running without --locked
    Updating crates.io index
warning: spurious network error (3 tries remaining): [28] Timeout was reached (Operation timed out after 30000 milliseconds with 0 out of 0 bytes received)
  Downloaded ctrlc v3.2.3
  Downloaded termcolor v1.1.3
  Downloaded crossbeam-utils v0.8.12
  Downloaded time v0.1.44
  Downloaded clap_complete v4.0.5
  Downloaded clap_derive v4.0.21
  Downloaded num-traits v0.2.15
  Downloaded thread_local v1.1.4
  Downloaded proc-macro2 v1.0.47
  Downloaded memchr v2.5.0
  Downloaded jemallocator v0.5.0
  Downloaded iana-time-zone v0.1.51
  Downloaded os_str_bytes v6.3.0
  Downloaded unicode-ident v1.0.5
  Downloaded globset v0.4.9
  Downloaded heck v0.4.0
  Downloaded clap v4.0.22
  Downloaded num-integer v0.1.45
  Downloaded proc-macro-error v1.0.4
  Downloaded quote v1.0.21
  Downloaded fs_extra v1.2.0
  Downloaded anyhow v1.0.66
  Downloaded fnv v1.0.7
  Downloaded nix v0.24.2
  Downloaded terminal_size v0.2.1
  Downloaded clap_lex v0.3.0
  Downloaded ignore v0.4.18
  Downloaded proc-macro-error-attr v1.0.4
  Downloaded io-lifetimes v0.7.4
  Downloaded log v0.4.17
  Downloaded regex v1.6.0
  Downloaded cc v1.0.73
  Downloaded once_cell v1.15.0
  Downloaded num_cpus v1.13.1
  Downloaded syn v1.0.103
  Downloaded rustix v0.35.12
  Downloaded nix v0.25.0
  Downloaded autocfg v1.1.0
  Downloaded crossbeam-channel v0.5.6
  Downloaded regex-syntax v0.6.27
  Downloaded bstr v0.2.17
  Downloaded chrono v0.4.22
  Downloaded linux-raw-sys v0.0.46
warning: spurious network error (3 tries remaining): [7] Couldn't connect to server (Failed to connect to 2a04:4e42:8c::649: Network is unreachable)
  Downloaded walkdir v2.3.2
  Downloaded jemalloc-sys v0.5.2+5.3.0-patched
  Downloaded aho-corasick v0.7.19
warning: spurious network error (3 tries remaining): [28] Timeout was reached (download of `libc v0.2.136` failed to transfer more than 10 bytes in 30s)
  Downloaded libc v0.2.136
  Downloaded 47 crates (5.7 MB) in 3m 17s
   Compiling libc v0.2.136
   Compiling cfg-if v1.0.0
   Compiling version_check v0.9.4
   Compiling proc-macro2 v1.0.47
   Compiling unicode-ident v1.0.5
   Compiling bitflags v1.3.2
   Compiling quote v1.0.21
   Compiling autocfg v1.1.0
   Compiling memchr v2.5.0
   Compiling proc-macro-error-attr v1.0.4
   Compiling io-lifetimes v0.7.4
   Compiling syn v1.0.103
   Compiling proc-macro-error v1.0.4
   Compiling log v0.4.17
   Compiling rustix v0.35.12
   Compiling num-traits v0.2.15
   Compiling crossbeam-utils v0.8.12
   Compiling cc v1.0.73
   Compiling fs_extra v1.2.0
   Compiling once_cell v1.15.0
   Compiling linux-raw-sys v0.0.46
   Compiling jemalloc-sys v0.5.2+5.3.0-patched
   Compiling aho-corasick v0.7.19
   Compiling num-integer v0.1.45
   Compiling os_str_bytes v6.3.0
   Compiling regex-syntax v0.6.27
   Compiling heck v0.4.0
   Compiling clap_derive v4.0.21
   Compiling regex v1.6.0
   Compiling clap_lex v0.3.0
   Compiling terminal_size v0.2.1
   Compiling bstr v0.2.17
   Compiling atty v0.2.14
   Compiling lazy_static v1.4.0
   Compiling strsim v0.10.0
   Compiling same-file v1.0.6
   Compiling fnv v1.0.7
   Compiling termcolor v1.1.3
   Compiling anyhow v1.0.66
   Compiling clap v4.0.22
   Compiling globset v0.4.9
   Compiling walkdir v2.3.2
   Compiling thread_local v1.1.4
   Compiling nix v0.25.0
   Compiling nix v0.24.2
   Compiling dirs-sys-next v0.1.2
   Compiling time v0.1.44
   Compiling fd-find v8.5.3
   Compiling ansi_term v0.12.1
   Compiling iana-time-zone v0.1.51
   Compiling chrono v0.4.22
   Compiling lscolors v0.12.0
   Compiling dirs-next v2.0.0
   Compiling argmax v0.3.1
   Compiling ctrlc v3.2.3
   Compiling ignore v0.4.18
   Compiling clap_complete v4.0.5
   Compiling jemallocator v0.5.0
   Compiling crossbeam-channel v0.5.6
   Compiling users v0.11.0
   Compiling num_cpus v1.13.1
   Compiling humantime v2.1.0
   Compiling normpath v0.3.2
    Finished release [optimized] target(s) in 10m 44s
warning: the following packages contain code that will be rejected by a future version of Rust: fs_extra v1.2.0
note: to see what the problems were, use the option `--future-incompat-report`, or run `cargo report future-incompatibilities --id 1`
  Installing /home/users/yunhai01/.cargo/bin/fd
   Installed package `fd-find v8.5.3` (executable `fd`)
warning: be sure to add `/home/users/yunhai01/.cargo/bin` to your PATH to be able to run the installed binaries

這回成功了。嘗試為之前安裝失敗的 10.1.0 版本增加 --locked 選項:

> cargo install fd-find --locked
    Updating crates.io index
  Installing fd-find v10.1.0
    Updating crates.io index
warning: package `libc v0.2.154` in Cargo.lock is yanked in registry `crates-io`, consider running without --locked
    Updating crates.io index
  Downloaded proc-macro2 v1.0.81
  Downloaded anyhow v1.0.82
  Downloaded serde v1.0.200
  Downloaded errno v0.3.8
  Downloaded cc v1.0.96
  Downloaded syn v2.0.60
  Downloaded libc v0.2.154
  Downloaded linux-raw-sys v0.4.13
  Downloaded 8 crates (2.8 MB) in 1m 27s (largest was `linux-raw-sys` at 1.5 MB)
error: failed to compile `fd-find v10.1.0`, intermediate artifacts can be found at `/tmp/cargo-installVoh51U`.
To reuse those artifacts with a future compilation, set the environment variable `CARGO_TARGET_DIR` to that path.

Caused by:
  package `clap_builder v4.5.2` cannot be built because it requires rustc 1.74 or newer, while the currently active rustc version is 1.72.1

仍然不行,看來回退 8.5.3 是唯一的解決辦法。之前還探索過將 cargo 版本降為 1.65.0:

> sudo yum remove cargo
> sudo yum install cargo-1.65.0-1.el7.x86_64
Loaded plugins: fastestmirror, langpacks, versionlock
Loading mirror speeds from cached hostfile
Excluding 1 update due to versionlock (use "yum versionlock status" to show it)
No package cargo-1.65.0-1.el7.x86_64 available.
Error: Nothing to do

未能成功。在網上也沒搜到 1.65.0 的 cargo rpm 包,只能作罷。不清楚為何 1.72.1 的 cargo 要求 1.74 的 rustc,嚴重懷疑這是一個 bug。

書歸正題,在安裝完 fd 8.5.3 後需要按提示將 fd 移到 /usr/loca/bin:

> sudo cp /home/users/yunhai01/.cargo/bin/fd /usr/local/bin/
> fd --version
fd 8.5.3

否則 neovim 找不到。

tree-sitter

是一個解析器生成工具和增量解析庫,在 nvim 中主要用作 latex 語言解析器、以及 rainbow-delimiters.nvim 和 nvim-treesitter.nvim 插件的底層支持。rainbow-delimiters 主要用於多種語言的語法高亮,特別是多括弧的展示;nvim-treesitter 主要用於高效代碼導航與編輯,是 IDE 不可或缺的底層組件。

可以使用 cargo 安裝:

> cargo install tree-sitter-cli

會遇到和安裝 fd 類似的問題:

查看代碼
 > cargo install tree-sitter-cli
    Updating crates.io index
  Installing tree-sitter-cli v0.22.6
    Updating crates.io index
warning: spurious network error (3 tries remaining): [28] Timeout was reached (Operation timed out after 30001 milliseconds with 0 out of 0 bytes received)
warning: spurious network error (3 tries remaining): [28] Timeout was reached (Operation timed out after 30000 milliseconds with 0 out of 0 bytes received)
warning: spurious network error (3 tries remaining): [28] Timeout was reached (Operation too slow. Less than 10 bytes/sec transferred the last 30 seconds)
warning: spurious network error (3 tries remaining): [28] Timeout was reached (Operation too slow. Less than 10 bytes/sec transferred the last 30 seconds)
warning: spurious network error (3 tries remaining): [28] Timeout was reached (Operation timed out after 30001 milliseconds with 0 out of 0 bytes received)
warning: spurious network error (3 tries remaining): [28] Timeout was reached (Operation too slow. Less than 10 bytes/sec transferred the last 30 seconds)
warning: spurious network error (3 tries remaining): [28] Timeout was reached (Operation too slow. Less than 10 bytes/sec transferred the last 30 seconds)
  Downloaded httpdate v1.0.3
  Downloaded equivalent v1.0.1
  Downloaded tiny_http v0.12.0
  Downloaded anstyle-query v1.1.0
  Downloaded ascii v1.1.0
  Downloaded dirs-sys v0.4.1
  Downloaded serde_derive v1.0.203
  Downloaded tempfile v3.10.1
  Downloaded clap_builder v4.5.6
  Downloaded webbrowser v1.0.1
  Downloaded tree-sitter-config v0.22.6
  Downloaded tree-sitter-tags v0.22.6
  Downloaded proc-macro2 v1.0.85
  Downloaded percent-encoding v2.3.1
  Downloaded unicode-normalization v0.1.23
  Downloaded semver v1.0.23
  Downloaded libloading v0.8.3
  Downloaded filetime v0.2.23
  Downloaded idna v0.5.0
  Downloaded ahash v0.8.11
  Downloaded itoa v1.0.11
  Downloaded form_urlencoded v1.2.1
  Downloaded zerocopy v0.7.34
  Downloaded wasmparser v0.206.0
  Downloaded option-ext v0.2.0
  Downloaded dirs v5.0.1
  Downloaded serde_json v1.0.117
  Downloaded chunked_transfer v1.5.0
  Downloaded ryu v1.0.18
  Downloaded tree-sitter v0.22.6
warning: spurious network error (3 tries remaining): [35] SSL connect error (TCP connection reset by peer)
  Downloaded thiserror-impl v1.0.61
  Downloaded clap_lex v0.7.1
  Downloaded serde v1.0.203
  Downloaded unicode-bidi v0.3.15
  Downloaded glob v0.3.1
  Downloaded tree-sitter-loader v0.22.6
  Downloaded indexmap v2.2.6
  Downloaded fastrand v2.1.0
  Downloaded url v2.5.0
  Downloaded indoc v2.0.5
  Downloaded tinyvec_macros v0.1.1
  Downloaded rustc-hash v1.1.0
  Downloaded clap v4.5.6
  Downloaded html-escape v0.2.13
  Downloaded clap_derive v4.5.5
  Downloaded tree-sitter-highlight v0.22.6
  Downloaded fs4 v0.8.3
warning: spurious network error (3 tries remaining): [28] Timeout was reached (download of `difference v2.0.0` failed to transfer more than 10 bytes in 30s)
  Downloaded difference v2.0.0
warning: spurious network error (3 tries remaining): [7] Couldn't connect to server (Failed to connect to 2a04:4e42:1a::649: Network is unreachable)
  Downloaded utf8-width v0.1.7
warning: spurious network error (3 tries remaining): [28] Timeout was reached (download of `hashbrown v0.14.5` failed to transfer more than 10 bytes in 30s)
  Downloaded hashbrown v0.14.5
warning: spurious network error (3 tries remaining): [28] Timeout was reached (download of `smallbitvec v2.5.3` failed to transfer more than 10 bytes in 30s)
  Downloaded smallbitvec v2.5.3
warning: spurious network error (3 tries remaining): [28] Timeout was reached (download of `thiserror v1.0.61` failed to transfer more than 10 bytes in 30s)
  Downloaded thiserror v1.0.61
warning: spurious network error (3 tries remaining): [28] Timeout was reached (download of `tinyvec v1.6.0` failed to transfer more than 10 bytes in 30s)
  Downloaded tinyvec v1.6.0
  Downloaded 53 crates (2.7 MB) in 4m 35s
error: failed to compile `tree-sitter-cli v0.22.6`, intermediate artifacts can be found at `/tmp/cargo-installFBNfkt`.
To reuse those artifacts with a future compilation, set the environment variable `CARGO_TARGET_DIR` to that path.

Caused by:
  package `tree-sitter-highlight v0.22.6` cannot be built because it requires rustc 1.74.1 or newer, while the currently active rustc version is 1.72.1
  Try re-running cargo install with `--locked`

增加 --locked 選項應該可以解決問題,使用 cargo 1.72.1 目前安裝的版本為 0.22.6,這個版本運行依賴較高的 glibc,所以放棄。

通過官方提示的 npm 方式安裝的結果也差不多:

> npm install tree-sitter-cli

added 1 package in 10m
> ls -lh node_modules/tree-sitter-cli/
total 25M
-rwxr-xr-x 1 yunhai01 DOORGOD  303 Jun  7 12:13 cli.js
-rw-r--r-- 1 yunhai01 DOORGOD  14K Jun  7 12:13 dsl.d.ts
-rwxr-xr-x 1 yunhai01 DOORGOD 3.4K Jun  7 12:13 install.js
-rw-r--r-- 1 yunhai01 DOORGOD 1.1K Jun  7 12:13 LICENSE
-rw-r--r-- 1 yunhai01 DOORGOD  534 Jun  7 12:13 package.json
-rw-r--r-- 1 yunhai01 DOORGOD 1.7K Jun  7 12:13 README.md
-rwxr-xr-x 1 yunhai01 DOORGOD  25M Jun  7 12:23 tree-sitter
> node_modules/tree-sitter-cli/tree-sitter --version
node_modules/tree-sitter-cli/tree-sitter: /lib64/libc.so.6: version `GLIBC_2.25' not found (required by node_modules/tree-sitter-cli/tree-sitter)
node_modules/tree-sitter-cli/tree-sitter: /lib64/libc.so.6: version `GLIBC_2.29' not found (required by node_modules/tree-sitter-cli/tree-sitter)
node_modules/tree-sitter-cli/tree-sitter: /lib64/libc.so.6: version `GLIBC_2.28' not found (required by node_modules/tree-sitter-cli/tree-sitter)

最早之前安裝的 0.20.7 版本是 ok 的,想通過這種方式安裝的朋友,可以指定版本試一下。註意這兩種方式安裝後的文件分別位於 ~/.cargo/bin./node_modules/tree-sitter-cli 下,需要手動複製到 /usr/local/bin 以便生效。

現在介紹第三種安裝方式,不依賴 cargo、npm 等包管理器,直接定位到 tree-sitter 官方下載頁面,選擇 0.20.4 版本,對於我的 CentOS7 x64 版本,選擇 tree-sitter-linux-x64.gz 下載即可:

> gunzip tree-sitter-linux-x64.gz 
> chmod u+x tree-sitter-linux-x64
> sudo mv tree-sitter-linux-x64 /usr/local/bin
> tree-sitter --version
tree-sitter 0.20.4 (714bfd47a744ab44b904375c177a24c0614ef49c)

按上一面一步步執行就安裝好了,親測高於 0.20.4 的版本就有 glibc 相容問題 (>2.18)。

efm-langserver

實現智能 IDE 的核心,基於 go 語言開發,使用 go 編譯安裝:

> go install github.com/mattn/efm-langserver@latest

安裝後沒有找到 efm-langserver,經查,go 1.20 之後,需要通過 GOPATH 環境變數來指定安裝目錄:

> export GOPATH=/ext/tools
> go install github.com/mattn/efm-langserver@latest
go: downloading github.com/mattn/efm-langserver v0.0.53
go: downloading github.com/sourcegraph/jsonrpc2 v0.2.0
go: downloading gopkg.in/yaml.v3 v3.0.1
go: downloading github.com/mattn/go-unicodeclass v0.0.2
go: downloading github.com/reviewdog/errorformat v0.0.0-20240311054359-739e471a49b3

同樣需要複製到 /usr/local/bin 目錄以便全局生效:

> sudo cp bin/efm-langserver /usr/local/bin
> efm-langserver -v
efm-langserver 0.0.53 (rev: HEAD/go1.20.12)

比之前安裝的版本略高一些:

> efm-langserver -v
efm-langserver 0.0.44 (rev: 36a4d81/go1.17.12)

Font

下載可支持符號的字體,例如:Nerd Font,在 macOS 上的安裝非常簡單,直接雙擊 ttf 文件安裝:

然後在 macOS 終端上指定該字體,這裡我使用的是 iTerm2,其它終端大同小異:

iTerm2 有以下 UI 路徑:iTerm2 -> settings -> Profiles -> Default -> Text -> Font。下麵是安裝帶符號字體前後的對比:

狀態欄很多不能顯示的符號都正常了 (標簽頁的仍保持問號,可能是一個特殊符號 Nerd Font 不支持)。

neovim

IDE 的載體,不使用 yum 安裝,原因是 yum 上目前只有 0.3 版本的 neovim,而支持現代化 IDE 核心的 packer 包管理器至少需要 0.7 版本。這裡使用 curl 直接下載最新版本:

> curl -LO https://github.com/neovim/neovim/releases/latest/download/nvim.appimage

啟動:

> chmod u+x nvim.appimage
> ./nvim.appimage

報錯:

/tmp/.mount_nvim.aw3KspQ/usr/bin/nvim: /lib64/libc.so.6: version `GLIBC_2.28' not found (required by /tmp/.mount_nvim.aw3KspQ/usr/bin/nvim)
/tmp/.mount_nvim.aw3KspQ/usr/bin/nvim: /lib64/libm.so.6: version `GLIBC_2.29' not found (required by /tmp/.mount_nvim.aw3KspQ/usr/bin/nvim)

看起來需要升級 glibc 2.29,為了避免再次更新 glibc,這裡直接選擇可以成功安裝的 neovim 0.9.2 版本:

> wget https://github.com/neovim/neovim/releases/download/v0.9.2/nvim.appimage

友情提示:可以在 web 端下載後傳遞給虛擬機,macOS 訪問 github 要比虛擬機快許多。

下載成功後,運行 nvim.appimage 可以自動釋放目標文件:

> chmod u+x nvim.appimage
> ./nvim.appimage

如果運行後沒有產生 squashfs-root 目錄,說明系統缺乏 FUSE (用戶空間文件系統),需要手動釋放一下:

> ./nvim.appimage --appimage-extract

設置到 /usr/local/bin 後就可以被全局引用了:

> sudo ln -s $PWD/squashfs-root/AppRun /usr/local/bin/nvim
> nvim --version
NVIM v0.9.2
Build type: Release
LuaJIT 2.1.1692716794

   system vimrc file: "$VIM/sysinit.vim"
  fall-back for $VIM: "/__w/neovim/neovim/build/nvim.AppDir/usr/share/nvim"

Run :checkhealth for more info

nvimdots

IDE 的實現,按照 github 主頁 README 的說明直接安裝:

if command -v curl >/dev/null 2>&1; then
    bash -c "$(curl -fsSL https://raw.githubusercontent.com/ayamir/nvimdots/HEAD/scripts/install.sh)"
else
    bash -c "$(wget -O- https://raw.githubusercontent.com/ayamir/nvimdots/HEAD/scripts/install.sh)"
fi

腳本會自動判斷 neovim 版本併進行適配:

> bash -c "$(wget -O- https://raw.githubusercontent.com/ayamir/nvimdots/HEAD/scripts/install.sh)"
--2024-05-24 15:32:21--  https://raw.githubusercontent.com/ayamir/nvimdots/HEAD/scripts/install.sh
Resolving raw.githubusercontent.com... 185.199.108.133, 185.199.109.133, 185.199.111.133, ...
Connecting to raw.githubusercontent.com|185.199.108.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 7830 (7.6K) [text/plain]
Saving to: ‘STDOUT’

-                                               100%[======================================================================================================>]   7.65K  6.79KB/s    in 1.1s

2024-05-24 15:32:25 (6.79 KB/s) - written to stdout [7830/7830]

==> This script will install ayamir/nvimdots to:
/home/users/yunhai01/.config/nvim

Press RETURN/ENTER to continue or any other key to abort...
==> Validating SSH connection...
Do you prefer to use SSH to fetch and update plugins? (otherwise HTTPS) [Y/n]:
==> Checking 'git clone' preferences...
Would you like to perform a shallow clone ('--depth=1')? [Y/n]:
==> Fetching in progress...
Cloning into '/home/users/yunhai01/.config/nvim'...
remote: Enumerating objects: 170, done.
remote: Counting objects: 100% (170/170), done.
remote: Compressing objects: 100% (162/162), done.
remote: Total 170 (delta 5), reused 73 (delta 0), pack-reused 0
Receiving objects: 100% (170/170), 108.87 KiB | 203.00 KiB/s, done.
Resolving deltas: 100% (5/5), done.
==> Spawning Neovim and fetching plugins... (You'll be redirected shortly)
==> NOTE: Please make sure you have a Rust Toolchain installed via `rustup`! Otherwise, unexpected things may
          happen. See: https://www.rust-lang.org/tools/install.

==> If lazy.nvim failed to fetch any plugin(s), maunally execute `:Lazy sync` until everything is up-to-date.

Thank you for using this set of configuration!
- Project Homepage:
    https://github.com/ayamir/nvimdots
- Further documentation (including executables you must install for full functionality):
    https://github.com/ayamir/nvimdots/wiki/Prerequisites

Press RETURN/ENTER to continue or any other key to abort...

執行過程中會讓用戶進行若幹選項,都按預設處理就可以了。到這裡所有必需軟體就都安裝完成了,按任意鍵將進入插件的安裝,具體內容在下一節介紹。

安裝後的目錄位於:~/.config/nvim/。註意這裡不要選擇 neovim 0.8.1 (說的就是我),否則後面啟動插件管理器時會報錯:

Error executing Lua callback: ...l/share/nvim/site/lazy/lazy.nvim/lua/lazy/view/float.lua:159: Vim(append):Error executing lua callback: ...zy/rainbow-delimiters.nvim/plugin/rainbow-delimiter
s.lua:50: attempt to call field 'get_lang' (a nil value)
stack traceback:
        ...zy/rainbow-delimiters.nvim/plugin/rainbow-delimiters.lua:50: in function 'attach'
        ...zy/rainbow-delimiters.nvim/plugin/rainbow-delimiters.lua:151: in function <...zy/rainbow-delimiters.nvim/plugin/rainbow-delimiters.lua:151>
        [C]: in function '__newindex'
        ...l/share/nvim/site/lazy/lazy.nvim/lua/lazy/view/float.lua:159: in function 'mount'
        ...l/share/nvim/site/lazy/lazy.nvim/lua/lazy/view/float.lua:75: in function 'init'
        ...al/share/nvim/site/lazy/lazy.nvim/lua/lazy/view/init.lua:53: in function 'create'
        ...al/share/nvim/site/lazy/lazy.nvim/lua/lazy/view/init.lua:38: in function 'show'
        ...hare/nvim/site/lazy/lazy.nvim/lua/lazy/view/commands.lua:38: in function 'command'
        ...hare/nvim/site/lazy/lazy.nvim/lua/lazy/view/commands.lua:24: in function 'cmd'
        ...hare/nvim/site/lazy/lazy.nvim/lua/lazy/view/commands.lua:111: in function <...hare/nvim/site/lazy/lazy.nvim/lua/lazy/view/commands.lua:98>
stack traceback:
        [C]: in function '__newindex'
        ...l/share/nvim/site/lazy/lazy.nvim/lua/lazy/view/float.lua:159: in function 'mount'
        ...l/share/nvim/site/lazy/lazy.nvim/lua/lazy/view/float.lua:75: in function 'init'
        ...al/share/nvim/site/lazy/lazy.nvim/lua/lazy/view/init.lua:53: in function 'create'
        ...al/share/nvim/site/lazy/lazy.nvim/lua/lazy/view/init.lua:38: in function 'show'
        ...hare/nvim/site/lazy/lazy.nvim/lua/lazy/view/commands.lua:38: in function 'command'
        ...hare/nvim/site/lazy/lazy.nvim/lua/lazy/view/commands.lua:24: in function 'cmd'
        ...hare/nvim/site/lazy/lazy.nvim/lua/lazy/view/commands.lua:111: in function <...hare/nvim/site/lazy/lazy.nvim/lua/lazy/view/commands.lua:98>

基本無解。

開發環境搭建

框架好比是毛坯房,想要入住還得“精裝修”一下,主要是安裝各種插件,以及本地化配置。

插件安裝

同許多 IDE 一樣,vim 很多功能是通過插件實現的,插件本身需要管理,這就催生了形形色色的插件管理器,知名的有 vim-plug、Vundle;vim 進化到 neovim 之後,有兩個主要的插件管理器,一個是 packer,另一個是 lazy,兩個都很好用,之前 nvimdots 使用的 packer,後來更新到了 lazy,可以有效的提升 neovim 的啟動速度。

lazy

書接上節,在 nvimdots 安裝結束後,按任意鍵將啟動 nvim、自動拉起插件更新:

這個界面靜靜等待即可,最終都能安裝成功:

在 lazy 插件管理頁面,輸入標簽後面的字元可實現跳轉,例如 U 跳轉到更新插件頁面。

也可以直接在命令行輸入 :Lazy sync 來切換到 Sync 標簽:

其它也類似,不再贅述。當所有插件安裝結束後,q 退出界面。與原先的 packer 界面相比:

簡直像從遠古社會跨進到了現代社會。退出 lazy、退出 nvim,插件安裝路徑位於:~/.local/share/nvim 目錄下。再次進入 nvim,將看到歡迎界面:

基本功能已經可用,有幾個未安裝的插件將繼續安裝。

mason

mason 也是一個插件管理器,聚焦於 lsp 服務、dap 服務、linter 和 formatter 方向,通過它可以讓 nvim 輕鬆支持多種編程語言的智能化展示。通過 :Mason 啟動:

可以觀察到系統可用的語言插件、安裝成功的、安裝失敗的,這裡主要需要處理 2 個插件的安裝。

clangd

從上面的日誌可以看出,安裝失敗的原因主要是從網路獲取 clangd 包失敗,這裡改為手動下載:

> wget https://github.com/clangd/clangd/releases/download/18.1.3/clangd-linux-18.1.3.zip
> mv clangd-linux-18.1.3.zip ~/.local/share/nvim/mason/packages
> cd ~/.local/share/nvim/mason/packages
> unzip clangd-linux-18.1.3.zip
> cd ../bin
> ln -s $PWD/../packages/clangd_18.1.3/bin/clangd clangd
> ./clangd --version
clangd version 18.1.3 (https://github.com/llvm/llvm-project c13b7485b87909fcf739f62cfa382b55407433c0)
Features: linux+grpc
Platform: x86_64-unknown-linux-gnu

解壓並替換到目標目錄、設置命令軟鏈接後,重啟 nvim 查看:

安裝成功,如果 nvim 仍顯示安裝 clangd,就多重啟幾次,甚至重啟下機器。

clang-format

查看 clang-format 錯誤日誌:

沒看出來安裝失敗的直接原因,這裡改為手動下載:

> wget -c https://github.com/muttleyxd/clang-tools-static-binaries/releases/download/master-1d7ec53d/clang-format-10_linux-amd64
> chmod u+x clang-format-10_linux-arm64
> mkdir -p ~/.local/share/nvim/mason/packages/clang-format/bin
> mv clang-format-10_linux-amd64 ~/.local/share/nvim/mason/packages/clang-format/bin
> cd ~/.local/share/nvim/mason/bin
> ln -s $PWD/../packages/clang-format/bin/clang-format-10_linux-amd64 clang-format
> ./clang-format --version
clang-format version 10.0.1

替換到目標目錄、設置命令軟鏈接後,重啟 nvim 查看:

安裝成功。如果想讓 Mason 安裝 clang-format,除了之前介紹的升級 python3 步驟外,還需要以下操作:

> sudo pip3 install wheel
# 進入 nvim
MasonInstall clang-format

最後還有兩個插件 python-lsp-server & gopls 沒安裝成功,分別是 python 與 go 語言 lspserver,由於本文著重介紹 C/C++ 環境的搭建,這個偏離主題就不再贅述了,有需求的小伙伴可以在 nvimdots 中提問尋求幫助。

如果不想看到每次在啟動時它們的報錯信息,可以選擇不載入它們,具體操作步驟詳見配置一節。

配置

各種功能插件安裝完成後,還需要修改化配置一番,為了方便調用 neovim,在 bash 啟動腳本中增加以下內容:

alias vi=nvim
alias vim=nvim

這樣就可以使用 vi 或 vim 代替 nvim 了,相當於替換了預設的 vim 編輯器,如果想調用原始的 vim 編輯器,需要輸入完整路徑:

> /usr/bin/vi

在進行配置之前,首先對 nvim 進行一次自我體驗,這主要是通過 :checkhealth 命令來完成,下麵是完整的 checkhealth 輸出:

查看代碼
 
==============================================================================
hop: require("hop.health").check()

Ensuring keys are unique ~
- OK Keys are unique

Checking for deprecated features ~
- OK All good

==============================================================================
lazy: require("lazy.health").check()

lazy.nvim ~
- OK Git installed
- OK no existing packages found by other package managers
- OK packer_compiled.lua not found

==============================================================================
lspsaga: require("lspsaga.health").check()

Lspsaga.nvim report ~
- OK `tree-sitter` found
- OK tree-sitter `markdown` parser found
- OK tree-sitter `markdown_inline` parser found

==============================================================================
luasnip: require("luasnip.health").check()

luasnip ~
- WARNING             For Variable/Placeholder-transformations, luasnip requires
  the jsregexp library. See `:help |luasnip-lsp-snippets-transformations`| for advice


==============================================================================
mason: require("mason.health").check()

mason.nvim ~
- OK mason.nvim version v1.10.0
- OK PATH: prepend
- OK Providers:
  mason.providers.registry-api
  mason.providers.client
- OK neovim version >= 0.7.0

mason.nvim [Registries] ~
- OK Registry `github.com/mason-org/mason-registry version: 2024-06-07-fast-test` is installed.

mason.nvim [Core utils] ~
- OK unzip: `UnZip 6.00 of 20 April 2009, by Info-ZIP.  Maintained by C. Spieler.  Send`
- OK wget: `GNU Wget 1.24.5 built on linux-gnu.`
- OK curl: `curl 7.87.0 (x86_64-pc-linux-muslx32) libcurl/7.87.0 OpenSSL/1.1.1s zlib/1.2.12 libssh2/1.9.0 nghttp2/1.43.0`
- OK gzip: `gzip 1.5`
- OK gtar: `tar (GNU tar) 1.26`
- OK bash: `GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)`
- OK sh: `Ok`

mason.nvim [Languages] ~
- WARNING luarocks: not available
  - ADVICE:
    - spawn: luarocks failed with exit code - and signal -. luarocks is not executable
- WARNING Ruby: not available
  - ADVICE:
    - spawn: ruby failed with exit code - and signal -. ruby is not executable
- WARNING RubyGem: not available
  - ADVICE:
    - spawn: gem failed with exit code - and signal -. gem is not executable
- WARNING Composer: not available
  - ADVICE:
    - spawn: composer failed with exit code - and signal -. composer is not executable
- WARNING PHP: not available
  - ADVICE:
    - spawn: php failed with exit code - and signal -. php is not executable
- OK node: `v16.18.1`
- OK cargo: `cargo 1.72.1`
- WARNING julia: not available
  - ADVICE:
    - spawn: julia failed with exit code - and signal -. julia is not executable
- OK Go: `go version go1.20.12 linux/amd64`
- OK python: `Python 3.6.8`
- OK java: `openjdk version "1.8.0_322"`
- OK pip: `pip 9.0.3 from /usr/lib/python3.6/site-packages (python 3.6)`
- OK python venv: `Ok`
- OK javac: `Ok`
- OK npm: `8.19.2`

mason.nvim [GitHub] ~
- OK GitHub API rate limit. Used: 1. Remaining: 59. Limit: 60. Reset: Fri 07 Jun 2024 04:40:44 PM CST.
  Install and authenticate via gh-cli to increase rate limit.

==============================================================================
neoconf: require("neoconf.health").check()

neoconf.nvim ~
- OK **treesitter-nvim** is installed
- OK **TreeSitter jsonc** parser is installed
- WARNING **neodev.nvim** is not installed. You won't get any proper completion for your Neovim config.
- OK **lspconfig** is installed
- OK **lspconfig jsonls** is installed
- OK **lspconfig lua_ls** is installed

==============================================================================
null-ls: require("null-ls.health").check()

- OK clang_format: the command "clang-format" is executable.
- OK prettier: the command "prettier" is executable.
- OK gofumpt: the command "gofumpt" is executable.
- OK shfmt: the command "shfmt" is executable.
- OK stylua: the command "stylua" is executable.
- OK vint: the command "vint" is executable.
- OK goimports: the command "goimports" is executable.

==============================================================================
nvim: require("nvim.health").check()

Configuration ~
- OK no issues found

Runtime ~
- OK $VIMRUNTIME: /ext/tools/squashfs-root/usr/share/nvim/runtime

Performance ~
- OK Build type: Release

Remote Plugins ~
- WARNING "wilder.nvim" is not registered.
- WARNING Out of date
  - ADVICE:
    - Run `:UpdateRemotePlugins`

terminal ~
- key_backspace (kbs) terminfo entry: `key_backspace=\177`
- key_dc (kdch1) terminfo entry: `key_dc=\E[3~`
- $SSH_TTY="/dev/pts/0"

==============================================================================
nvim-treesitter: require("nvim-treesitter.health").check()

Installation ~
- OK `tree-sitter` found 0.20.4 (714bfd47a744ab44b904375c177a24c0614ef49c) (parser generator, only needed for :TSInstallFromGrammar)
- OK `node` found v16.18.1 (only needed for :TSInstallFromGrammar)
- OK `git` executable found.
- OK `cc` executable found. Selected from { vim.NIL, "cc", "gcc", "clang", "cl", "zig" }
  Version: cc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44)
- OK Neovim was compiled with tree-sitter runtime ABI version 14 (required >=13). Parsers must be compatible with runtime ABI.

OS Info:
{
  machine = "x86_64",
  release = "3.10.0-1160.21.1.el7.x86_64",
  sysname = "Linux",
  version = "#1 SMP Tue Mar 16 18:28:22 UTC 2021"
} ~

Parser/Features         H L F I J
  - bash                ✓ ✓ ✓ . ✓
  - c                   ✓ ✓ ✓ ✓ ✓
  - cpp                 ✓ ✓ ✓ ✓ ✓
  - css                 ✓ . ✓ ✓ ✓
  - go                  ✓ ✓ ✓ ✓ ✓
  - gomod               ✓ . . . ✓
  - html                ✓ ✓ ✓ ✓ ✓
  - javascript          ✓ ✓ ✓ ✓ ✓
  - json                ✓ ✓ ✓ ✓ .
  - jsonc               ✓ ✓ ✓ ✓ ✓
  - latex               ✓ . ✓ . ✓
  - lua                 ✓ ✓ ✓ ✓ ✓
  - make                ✓ . ✓ . ✓
  - markdown            ✓ . ✓ ✓ ✓
  - markdown_inline     ✓ . . . ✓
  - python              ✓ ✓ ✓ ✓ ✓
  - query               ✓ ✓ ✓ ✓ ✓
  - rust                ✓ ✓ ✓ ✓ ✓
  - typescript          ✓ ✓ ✓ ✓ ✓
  - vim                 ✓ ✓ ✓ . ✓
  - vimdoc              ✓ . . . ✓
  - vue                 ✓ . ✓ ✓ ✓
  - yaml                ✓ ✓ ✓ ✓ ✓

  Legend: H[ighlight], L[ocals], F[olds], I[ndents], In[j]ections
         +) multiple parsers found, only one will be used
         x) errors found in the query, try to run :TSUpdate {lang} ~

==============================================================================
provider: health#provider#check

Clipboard (optional) ~
- WARNING No clipboard tool found. Clipboard registers (`"+` and `"*`) will not work.
  - ADVICE:
    - :help |clipboard|

Python 3 provider (optional) ~
- Using: g:python3_host_prog = "python3"
- Executable: /usr/bin/python3
- ERROR Command error (job=16, exit code 1): `'/usr/bin/python3' -c 'import sys; sys.path = [p for p in sys.path if p != ""]; import neovim; print(neovim.__file__)'` (in '/home/users/yunhai01/project/baidu/netdisk/p2p-sdk-mobile')
  stderr: Traceback (most recent call last):  File "<string>", line 1, in <module>ModuleNotFoundError: No module named 'neovim'
- Python version: 3.6.8
- pynvim version: unable to load neovim Python module
- ERROR pynvim is not installed.
  Error: unable to load neovim Python module
  - ADVICE:
    - Run in shell: /usr/bin/python3 -m pip install pynvim

Python virtualenv ~
- OK no $VIRTUAL_ENV

Ruby provider (optional) ~
- WARNING `ruby` and `gem` must be in $PATH.
  - ADVICE:
    - Install Ruby and verify that `ruby` and `gem` commands work.

Node.js provider (optional) ~
- Node.js: v16.18.1
- WARNING Missing "neovim" npm (or yarn, pnpm) package.
  - ADVICE:
    - Run in shell: npm install -g neovim
    - Run in shell (if you use yarn): yarn global add neovim
    - Run in shell (if you use pnpm): pnpm install -g neovim
    - You may disable this provider (and warning) by adding `let g:loaded_node_provider = 0` to your init.vim

Perl provider (optional) ~
- WARNING Perl version is too old, 5.22+ required
  - ADVICE:
    - See :help |provider-perl| for more information.
    - You may disable this provider (and warning) by adding `let g:loaded_perl_provider = 0` to your init.vim

==============================================================================
rainbow-delimiters: require("rainbow-delimiters.health").check()

Custom strategies ~
- OK Valid custom default strategy.
- OK Valid custom strategy for 'vim'.
- OK Valid custom strategy for 'lua'.
- OK Valid custom strategy for 'cpp'.
- OK Valid custom strategy for 'vimdoc'.
- OK Valid custom strategy for 'c'.

Custom queries ~
- OK Valid custom default query
- OK Valid custom query for 'javascript'
- OK Valid custom query for 'latex'

Custom highlight groups ~
- OK Highlight group 'RainbowDelimiterRed' defined.
- OK Highlight group 'RainbowDelimiterOrange' defined.
- OK Highlight group 'RainbowDelimiterYellow' defined.
- OK Highlight group 'RainbowDelimiterGreen' defined.
- OK Highlight group 'RainbowDelimiterBlue' defined.
- OK Highlight group 'RainbowDelimiterCyan' defined.
- OK Highlight group 'RainbowDelimiterViolet' defined.

==============================================================================
telescope: require("telescope.health").check()

Checking for required plugins ~
- OK plenary installed.
- OK nvim-treesitter installed.

Checking external dependencies ~
- OK rg: found ripgrep 13.0.0
- OK fd: found fd 8.5.3

===== Installed extensions ===== ~

Telescope Extension: `aerial` ~
- No healthcheck provided

Telescope Extension: `frecency` ~
- OK nvim-web-devicons installed.
- OK ripgre

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1、背景描述 如上圖所示,根路徑“/”所在的文件系統已沒有可用的磁碟空間,需要擴容磁碟。 df -h 2、VirtualBox操作 2.1、查看當前虛擬磁碟的大小 如上圖所示,點擊打開選中的虛擬機的 Settings 界面。 如上圖所示,當前虛擬機的虛擬磁碟大小為 8GB 。 2.2、修改虛擬磁碟的 ...
  • 本文詳細介紹了在 CentOS 和 Ubuntu 系統上安裝 Nginx 的全過程,包括下載方法、安裝步驟、配置開機自啟以及基礎配置等重要內容,還提供了常見問題的解決方案和優化配置示例,助您順利搭建高效的伺服器環境。 ...
  • 眾所周知,WSL 2 為 Windows 用戶提供了一個強大、高效且靈活的 Linux 環境,特別適合開發者使用。它結合了 Windows 和 Linux 的優點,為用戶提供了更加全面和高效的工作環境。但缺點也很明顯,那就是預設安裝在本來空間就不富裕的C盤。 本次我們在非C盤的盤符快速安裝... ...
  • Keepalived是Linux下一個輕量級別的高可用解決方案。高可用:廣義來講,是指整個系統的高可用行;狹義的來講就是主機的冗餘和接管。 ...
  • 1、OrthoFinder 教程:用於比較基因組學的系統發育直系學推斷 1.1 orthofinder介紹 OrthoFinder是一種快速、準確和全面的比較基因組學分析工具。它可以找到直系和正群,為所有的正群推斷基因樹,併為所分析的物種推斷一個有根的物種樹。OrthoFinder還為比較基因組分析 ...
  • 寫在前面 本隨筆是非常菜的菜雞寫的。如有問題請及時提出。 可以聯繫:[email protected] GitHhub:https://github.com/WindDevil (目前啥也沒有 編程題 實現一個裸機應用程式A,能列印調用棧 首先在這裡卡了我很久的是調用棧保存在哪裡,回想到上一部分畫的 ...
  • 第十六章 machine模塊實驗 1)實驗平臺:正點原子DNK210開發板 2)章節摘自【正點原子】DNK210使用指南 - CanMV版 V1.0 3)購買鏈接:https://detail.tmall.com/item.htm?&id=782801398750 4)全套實驗源碼+手冊+視頻下載地 ...
  • @目錄前言簡介一、準備工作二、操作步驟2.1 啟動MySQL服務2.2 拷貝配置2.3 賦值許可權2.4 添加為系統服務2.5 驗證總結 前言 請各大網友尊重本人原創知識分享,謹記本人博客:南國以南i、 提示:以下是本篇文章正文內容,下麵案例可供參考 簡介 一、準備工作 註意:準備已經安裝MySQL的 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...