The second major change of my workflow — ubuntu2arch
Last time, in April of last year, I migrated from Windows 11 + VS + VSCode to Ubuntu 22.04 + VSCode + NeoVim. Now, I've switched to Arch Linux + NeoVim.
Later, for the conclusion of the university innovation project, I might have to set up a Windows driver development environment again, which could be quite a hassle.
Preface
A few months ago, dependency issues with dpkg
(mainly various Qt libraries) caused around 20 packages to become unupdatable. Additionally, sudo apt upgrade
updates the Linux kernel by default, which requires recompiling VMware drivers, so I became too lazy to update.
A few days ago, I tried using PGP
for secure communication with a classmate and generated a self-signed PGP key. This led to numerous signature errors during sudo apt upgrade
, and even after deleting the key, the issue persisted. After searching online, I decided to reinstall gpg
, but it didn't help. In fact, it made things worse—I could no longer install any new packages, meaning I was forced to downgrade to the LFS user's daily installation method: compiling from source.
As mentioned earlier, I'm a lazy person, and I didn't want to get my hands dirty with compiling and installing. So, I opted for a distribution with a simpler package manager—pacman
, the Arch Linux family.
Installation
Partitioning
After using Ubuntu installed on a mechanical hard drive for a few months, I noticed that Firefox's performance was unsatisfactory, and the previously allocated 100GB space for Ubuntu was becoming insufficient. Therefore, I decided to remove Windows 11, assign the root partition to the SSD, and allocate the remaining mechanical drive space to the home directory, resulting in the current partition layout:
> lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 111.8G 0 disk
├─sda1 8:1 0 300M 0 part /boot # ESP
├─sda2 8:2 0 128M 0 part # MSI
└─sda3 8:3 0 111.4G 0 part / # Former C drive
sdb 8:16 0 931.5G 0 disk
├─sdb1 8:17 0 300G 0 part # Former D drive
├─sdb2 8:18 0 300G 0 part /run/media/junyu33/software # Former E drive
├─sdb3 8:19 0 200.2G 0 part # Remaining space after allocating F drive to Ubuntu
└─sdb6 8:22 0 131.3G 0 part /home
Thus, when installing Arch, I only need to format /dev/sda1
and /dev/sda3
, while keeping the /home
partition intact.
RTFM
https://wiki.archlinuxcn.org/wiki/Installation_guide
https://wiki.archlinuxcn.org/wiki/General_recommendations
Remember to install iwctl
(look for alternatives if not using Intel hardware) and dhcpcd
before rebooting. Otherwise, you'll have to restart from the USB drive every time, and the computer's beep sound can be a bit startling.
Then, running systemctl enable iwd dhcpcd
should get you online. After that, installing common software or even a GUI should be straightforward.
nvidia
Arch Linux is pragmatic, so even though Linus has criticized NVIDIA, installing the driver is as simple as running sudo pacman -S nvidia
.
However, NVIDIA's power consumption issue is still worth considering. I referred to this documentation and decided to use optimus-manager
to switch between graphics cards.
Since I had always been entering the GUI by typing
startxfce4
in the terminal, I also needed to installlightdm
to ensure the switching command works properly.
Development Environment Setup
I was previously using VSCode 1.67 on Ubuntu, but now the installed version is already 1.80. The following points made me abandon VSCode:
- The UI changes are still hard for me to accept, especially the search bar at the top of the window, which is extremely ugly (though it can be disabled).
- The font size difference between the code and the shell is too large, making it feel inconsistent for someone like me who is used to a left-code, right-shell layout (a habit formed from GDB debugging). Neovim + tmux does not have this issue.
- When using Copilot, a key exchange error popup appears when logging into a Microsoft account and cannot be ignored. The Copilot plugin for Neovim works directly without requiring a re-login.
- VSCode's C/C++ plugin generated nearly 10GB of cache files in the user directory, and its performance is not outstanding.
So, I first modified ~/.config/nvim/init.vim
. Some parts come from jyy's nju-pa Vim configuration, some from MIT's Vim assignment, and some from the installation and configuration of plugins themselves:
set nocompatible " disable compatibility to old-time vi
set showmatch " show matching
set ignorecase " case insensitive
set mouse=v " middle-click paste with
set hlsearch " highlight search
set incsearch " incremental search
set tabstop=4 " number of columns occupied by a tab
set softtabstop=4 " see multiple spaces as tabstops so <BS> does the right thing
set expandtab " converts tabs to white space
set shiftwidth=2 " width for autoindents
set autoindent " indent a new line the same amount as the line just typed
set number " add line numbers
set wildmode=longest,list " get bash-like tab completions
set cc=80 " set an 80 column border for good coding style
filetype plugin indent on "allow auto-indenting depending on file type
syntax on " syntax highlighting
set mouse=a " enable mouse click
set clipboard=unnamedplus " using system clipboard
filetype plugin on
set cursorline " highlight current cursorline
set ttyfast " Speed up scrolling in Vim
" set spell " enable spell check (may need to download language package)
" set noswapfile " disable creating swap file
" set backupdir=~/.cache/vim " Directory to store backup files.
call plug#begin("~/.vim/plugged")
" Plugin Section
"Plug 'dracula/vim'
"Plug 'ryanoasis/vim-devicons'
"Plug 'SirVer/ultisnips'
"Plug 'honza/vim-snippets'
Plug 'scrooloose/nerdtree'
"Plug 'preservim/nerdcommenter'
"Plug 'mhinz/vim-startify'
Plug 'neoclide/coc.nvim', {'branch': 'release'}
Plug 'martinsione/darkplus.nvim'
Plug 'github/copilot.vim'
Plug 'pacha/vem-tabline'
Plug 'nvim-lualine/lualine.nvim'
Plug 'nvim-tree/nvim-web-devicons'
Plug 'ctrlpvim/ctrlp.vim'
Plug 'rmagatti/goto-preview'
Plug 'williamboman/mason.nvim'
Plug 'williamboman/mason-lspconfig.nvim'
Plug 'neovim/nvim-lspconfig'
Plug 'iamcco/markdown-preview.nvim', { 'do': 'cd app && yarn install' }
call plug#end()
colorscheme darkplus
let g:coc_global_extensions = ['coc-pyright', 'coc-snippets']
let g:ctrlp_map = '<c-p>'
inoremap <expr> <Tab> pumvisible() ? "\<C-y>" : "\<Tab>"
inoremap <expr> <S-Tab> pumvisible() ? "\<C-n>" : "\<S-Tab>"
## LSP + clangd + goto-preview
I used [mason](https://github.com/williamboman/mason.nvim) and [mason-lspconfig](https://github.com/williamboman/mason-lspconfig.nvim) to set up the LSP. Since I currently only frequently use `C` and `Python 3`, I only installed two language servers: `clangd` and `pyright`.
For now, I only intend to use the features of viewing definitions and references, so I only installed the [goto-preview](https://github.com/rmagatti/goto-preview) plugin. As for auto-completion, since I have Copilot for that, it doesn't seem as essential anymore.
## Configuring a Larger C Project
For a larger C project, such as [nju-pa](https://nju-projectn.github.io/ics-pa-gitbook/ics2022), the function definitions and header file dependencies can be quite complex. Opening it directly may result in numerous errors. VSCode's solution is to use `includepath`, but this approach has two drawbacks: first, it is difficult to list all include paths (resulting in sporadic errors, a nightmare for perfectionists), and second, the definitions found may have no relation to the original files.
`clangd` can better address this issue. It works by bottom-up discovery of `compile_commands.json` to determine the dependencies of each file, thereby covering all `includepath`s. At the same time, the accuracy of finding definitions is significantly improved.
So, how can we generate `compile_commands.json` based on `make`? We can use [bear](https://github.com/rizsotto/Bear) to accomplish this task. Note that the command to run the bear program itself seems problematic; the correct command is:
```bash
bear -- <your-build-command>
For example, to compile riscv32-nemu, the command would be:
bear -- make ARCH=riscv32-nemu
After running this, compile_commands.json
will be generated in the current directory. At this point, opening the source code with Neovim should no longer show "incorrect" errors, and it will be possible to query definitions and references.
For
cmake
projects, you can refer to this link: https://cmake.org/cmake/help/latest/variable/CMAKE_EXPORT_COMPILE_COMMANDS.html
Result screenshot:
