🏗️ 我的Nix/NixOS配置详细文档正在施工中,完成进度:44/107 🏗️
为了更好的文档阅读体验,请看GitHub Pages的版本。
目录
Nix/NixOS简介
Nix是一个可重现的(Reproducible)包管理器,也是一门纯函数式的(Pure Functional)编程语言。 理论上讲,Nix包管理器可以安装在任何Linux发行版上(比如Ubuntu、Debian和Arch等),并与这些发行版原有的包管理器(比如snap、apt和pacman等)共存。 而NixOS则是完全由Nix包管理器进行管理的Linux发行版。
Nix/NixOS采用了“包(Package)”的理念,将Linux内核、驱动、函数库、用户程序、配置文件等方方面面抽象出来。 这类似于Linux内核将设备、磁盘文件、管道等都抽象为文件的理念。 这样的抽象使得Nix/NixOS能以一种统一的方式管理所有的包。
为了防止“包”被用户有意或无意地修改(即保证可重现性),Nix/NixOS将所有的包都放在一个只读文件系统中(挂载在/nix/store
目录上)。
这个目录中的包仅能通过Nix包管理器和Nix语言编程进行增删改。
为了将/nix/store
中的文件放置在它们应该在的地方(比如某个用户使用的包里存在bin/
目录,则应当把bin/中所有的文件放入/run/current-system/sw/bin/
),Nix/NixOS大量使用符号链接。
上述Nix/NixOS的特点和传统Linux发行版有着极大的区别。 这使得Nix/NixOS的学习曲线十分陡峭。 不过当你适应Nix/NixOS的这些特点后,它可以极大提升工程效率!
xieby1和Nix/NixOS
多年来,Nix/NixOS已成为我学习和工作的重要基础,主要用于以下方面:
- 学习Linux。 Nix/NixOS采用了“包(Package)”的理念,将Linux内核、驱动、函数库、用户程序、配置文件等方方面面抽象出来。 通过学习Nix语言,我能够以统一的方式了解Linux系统的各个方面,这是其他工具所无法提供的。
- 管理环境。 通过使用nix-shell管理所有依赖(包括库、环境变量、配置等),可以避免项目环境重现的问题。 类似的工具还有虚拟机和Docker。 相比使用虚拟机,它更轻量。 相比Docker,它支持可复现构建,采用Nix语言更灵活。 详细可见我于2023年为实验室同学们准备的推荐Nix/NixOS的幻灯片。
- 备份电脑。 Nix/NixOS能够管理系统、软件及其配置。 虽然Nix/NixOS不直接管理数据,但Nix/NixOS可以很好地管理数据同步软件,比如Syncthing。 因此只要保留着Nix/NixOS的配置文件(由Nix语言编写),就能恢复出一个几乎一模一样1的软件环境/操作系统。
xieby1的Nix/NixOS配置
这个仓库Github: xieby1/nix_config里存放着我的Nix/NixOS配置和文档。 该仓库使用nix expression,而非nix flakes; 使用NixOS稳定源(目前版本24.05),而非非稳定源(unstable)。 该仓库的配置在多个平台都可以正常使用:
- NixOS: QEMU✅,NixOS单系统✅,NixOS+Windows双系统✅
- Nix: Linux✅,安卓(nix-on-droid)✅,WSL2✅
你可以使用该仓库的配置,配置出完整NixOS操作系统。 也可以使用其中的部分包、模块,扩充自己的Nix/NixOS。 若你不仅只是想安装Nix/NixOS,还想了解更多Nix/NixOS的知识, 欢迎看看这个仓库的文档xieby1.github.io/nix_config。
文件夹结构
- docs/: 文档
- scripts/: nix脚本
- fhs-shell/: 采用FHS的nix-shell脚本
- shell/: nix-shell脚本
- pkgs/: 独立的软件包脚本
- system.nix: 系统总体配置(nixos-rebuild的配置)
- sys/cli.nix: 系统命令行配置
- sys/gui.nix: 系统图形配置
- modules/: 系统模块
- home.nix: 用户总体配置(home-manager的配置)
- usr/cli.nix: 用户命令行配置
- usr/gui.nix: 用户图形配置
- modules/: 用户模块
- nix-on-droid.nix: 安卓总体配置(nix-on-droid的配置)
- modules/: nixos/home-manager通用的模块
nix脚本的使用方法
安装Nix不在此赘述,参考nixos.org/download.html。
安装完Nix后,下载所需的nix脚本,然后:
fhs-shell/
和shell/
脚本用nix-shell
命令进入shell环境;pkgs/
脚本用nix-build
命令生成软件包。
nix-shell的例子
# 以xiangshan.nix配置香山开发环境为例
# 进入香山的根目录
cd Xiangshan
# 下载xiangshan.nix脚本,并重命名为shell.nix
wget https://raw.githubusercontent.com/xieby1/nix_config/main/scripts/shell/xiangshan.nix -O shell.nix
# 进入nix shell
nix-shell
nix配置的使用方法
虚拟机/物理机单系统/物理机双系统 安装NixOS 可以参考我两年前的NixOS安装过程。 安装Nix/NixOS不在此赘述,参考nixos.org/download.html。
安装完Nix/NixOS后,首先下载我的配置
git clone https://github.com/xieby1/nix_config.git ~/.config/nixpkgs
# [仅NixOS] 在imports中添加system.nix的路径
vim /etc/nixos/configuration.nix
然后设置软件源,在NixOS中推荐使用sudo
。
- 注一:更多其他nix channels参考 NixOS Wiki: Nix channels 和Nix channel status。
- 注二:为什么用https://nixos.org/channels/nixos-24.05,
而非https://github.com/NixOS/nixpkgs/archive/release-24.05.tar.gz?
前者包含额外内容,比如programs.command-not-found.dbPath,详细见
man configuration.nix
。
# [对于NixOS]
nix-channel --add https://nixos.org/channels/nixos-24.05 nixos
# [对于Nix]
nix-channel --add https://nixos.org/channels/nixos-24.05 nixpkgs
# 添加home manager源
nix-channel --add https://github.com/nix-community/home-manager/archive/release-24.05.tar.gz home-manager
nix-channel --update
最后部署配置
# [仅NixOS]
sudo nixos-rebuild switch
# 安装home-manager
nix-shell '<home-manager>' -A install
home-manager switch
引用
nix 2.8的impure特性和home-manager等会引入一些你几乎察觉不到的差异。
Dolstra, Eelco. “The purely functional software deployment model.” (2006).
github.com/t184256/nix-on-droid termux的分支,支持nix。
config.nix
当初始化nixpkgs
时,例如pkgs = import <nixpkgs> {}
,
nixpkgs
的初始化代码会读取~/.config/nixpkgs/config.nix
作为nixpkgs.config
参数。
如果你对nixpkgs
的初始化感兴趣,可以去看看这部分的源代码<nixpkgs>/pkgs/top-level/impure.nix
。
config.nix
文件(即nixpkgs.config
)接受的参数可以参考nixpkgs的官方文档的
config Options Reference章节,
或是去看nixpkgs这部分的源码<nixpkgs>/pkgs/top-level/config.nix
。
下面是添加了注解的我的config.nix
:
{
禁用安装非本地的包,比如禁止x86_64-linux的包被安装到aarch64-linux上。
allowUnsupportedSystem = false;
allowUnfree = true;
packageOverrides = pkgs: rec {
添加nix user repository (NUR)到nixpkgs里。
nur = import (builtins.fetchTarball "https://github.com/nix-community/NUR/archive/master.tar.gz") {
pkgs = pkgsu;
};
添加非稳定版的nixpkgs到nixpkgs里,
比如非稳定版的hello可以通过pkgs.pkgsu.hello
来访问。
pkgsu = import (builtins.fetchTarball "https://github.com/NixOS/nixpkgs/archive/master.tar.gz") {};
添加flake-compat,用于在nix expression中使用flake的包
flake-compat = import (builtins.fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/0f9255e01c2351cc7d116c072cb317785dd33b33.tar.gz";
sha256 = "0m9grvfsbwmvgwaxvdzv6cmyvjnlww004gfxjvcl806ndqaxzy4j";
});
};
}
TODO: nix/nix.conf
opt.nix
nix语言中只有let ... in
来定义局部变量,没有提供全局变量的语法支持。
但在我的nix配置中又很需要一些“全局变量”来方便统一的管理多个配置文件。
有2种可行的方案来实现全局变量:module和import。
module
nixpkgs的module能够还不错地实现“全局变量”。
想了解module?可以去看看NixOS wikiL modules。
或者看看nixpkgs源码关于modules.nix的部分<nixpkgs>/lib/modules.nix
。
要注意的是,基于module的“全局变量”也会有局限的。
module是用过imports变量导入的,若在imports语句访问“全局变量”,nix的lazy evaluation的特性会导致死循环。
这也是为什么老版本的home.nix中判断是否需要导入./usr/gui.nix,
我没有使用config.isGui
而是再次使用getEnv访问环境变量。
当然这个不足也是我放弃使用的module主要原因。
import
通过在配置文件中import opt.nix也能还不错的实现“全局变量”。 import方法的最大优势是能够在module imports语句中避免死循环。
这个方法的不足之处在于每个需要使用全局变量的文件都需要import opt.nix。 但这个不方便之处,相对imports死循环,没那么让人难受。
{
isMinimalConfig = false;
proxyPort
:代理端口号,诸多网络程序需要用,比如clash和tailscale。
proxyPort = 8889;
isCli
和isGui
:通过环境变量DISPLAY
来判断是否是CLI或GUI环境。
这个方法有局限,比如ssh连接到一台有GUI的电脑上,ssh里是没有设置环境变量DISPLAY
的。
因此更好的方法是在opt-local.nix中写入固定的isCli和isGui值。
isCli = (builtins.getEnv "DISPLAY")=="";
isGui = (builtins.getEnv "DISPLAY")!="";
isNixOnDroid
:通过用户名来判断是否是nix-on-droid。
isNixOnDroid = (builtins.getEnv "USER")=="nix-on-droid";
isWSL2
:通过环境变量WSL_DISTRO_NAME
来判断是否是WSL2。
isWSL2 = (builtins.getEnv "WSL_DISTRO_NAME")!="";
}
本地配置
引入opt-local.nix,方便本地进行自定义,避免我的nix配置中出现过多设备特定代码(即一堆if else判断语句)。 为了减少设备特定代码,每个设备都有自己的opt-local.nix。 目前的想法是不将opt-local.nix加入git仓库,以实现“设备特定”。 相比opt.nix,opt-local.nix的配置具备更高的优先级。
// (
if (builtins.pathExists ./opt-local.nix)
then import ./opt-local.nix
else {}
)
system.nix
本文件system.nix
存放喆我的NixOS的配置。
NixOS的配置通过命令sudo nixos-rebuid switch
生效。
因为NixOS的配置入口是/etc/nixos/configuration.nix
,
所以需要在/etc/nixos/configuration.nix
中import本文件,例如
# /etc/nixos/configuration.nix:
{ config, pkgs, ... }: {
imports = [
./hardware-configuration.nix
# import my system.nix here!
/home/xieby1/.config/nixpkgs/system.nix
];
# other configs ...
}
NixOS配置可以使用的参数可参考configuration.nix的manpage,即man configuration.nix
。
下面是我的NixOS的配置源码及注解:
# add this file to /etc/nixos/configuration.nix: imports
{ config, pkgs, ... }:
{
让NixOS的nixpkgs使用和home-manager的nixpkgs采用相同的nixpkgs config
nixpkgs.config = import ./config.nix;
导入我的NixOS的CLI和GUI配置, 详细内容见文档./sys/cli.nix和./sys/gui.nix。
imports = [
./sys/modules/cachix.nix
./sys/cli.nix
./sys/gui.nix
];
Nix binary cache的地址。 越靠前优先级越高。 由于cache.nixos.org需要梯子, 这里使用了清华Tuna提供的Nix binary cache镜像来加速。
nix.settings.substituters = [
"https://cache.nixos.org/"
"https://xieby1.cachix.org"
];
设置时区。
time.timeZone = "Asia/Shanghai";
time.hardwareClockInLocalTime = true;
设置Linux账户信息。
users.mutableUsers = false;
当然GitHub上当然不能明文存储密码,这里使用hash过的密码。
可以使用命令行工具mkpasswd
来生成hash过的密码。
给root
用户设置hash过的密码。
users.users.root.hashedPassword = "$6$wRBpbr4zSTA/nh$XI/KUASw3mELIqyAxN1hUTWizz9ZBzPhP2u4HNDCA49h4KOWkZsyuiextyXkUti7jYsUHE9fTiRjGAoxBg0Gq/";
users.users.xieby1 = {
isNormalUser = true;
createHome = true;
同上,给xieby1
用户设置hash过的密码。
hashedPassword = "$6$Y4KJxhdaJTT$RSolbCpaUKK2UW1cdnuH.8n1Ky9p0Lnx0MP36BxGX9Q2AeVMjCp.bZOsZ11w689je/785TFRQoVgicMiOfA9B.";
给用户xieby1
启用sudo。
extraGroups = [ "wheel" ];
ssh授权的公钥。这样设置后,我的所有的NixOS都相当于“自动授权”了。
我的/home/xieby1/Gist/
文件夹存放着一些不方便放入Git仓库的文件,比如二进制文件,或是隐私文件。
该文件由syncthing进行多设备同步。
简单的说,我的备份理念是“git备份配置,syncthing备份数据”。
“配置”即指这个nix_config仓库,“数据”指~/Gist/
、~/Documents/
等文件夹。
有了这些备份就能轻松还原/复现我的整个工作环境。
TODO:单独专门介绍我的备份理念。
openssh.authorizedKeys.keyFiles = [] ++ (
if builtins.pathExists /home/xieby1/Gist/Vault/y50_70.pub
then [/home/xieby1/Gist/Vault/y50_70.pub]
else []
) ++ (
if builtins.pathExists /home/xieby1/Gist/Vault/yoga14s.pub
then [/home/xieby1/Gist/Vault/yoga14s.pub]
else []
);
};
让TTY自动登录我的账户,这样就可以自动启动用户级(user)的systemd服务了。 这样就可以在非NixOS中(比如Ubuntu服务器、WSL2、Debian树莓派等) 自动拉起systemd用户服务(比如syncthing、clash、tailscale等)。
services.getty.autologinUser = "xieby1";
有关systemd用户服务的配置,详细可见参考:
- home-manager配置的manpage的services词条,
比如
man home-configuration.nix
搜索services.syncthing
- 我的syncthing配置./usr/cli.nix: syncthing
- 我的clash配置./usr/cli/clash.nix
- 我的tailscale配置./usr/cli/tailscale.nix
}
cli.nix
本文件是NixOS的CLI配置。 主要包含两部分内容:
- 系统环境管理(root的环境)
- 系统配置
{ config, pkgs, ... }:
{
系统环境管理(root的环境)
# List packages installed in system profile. To search, run:
# $ nix search wget
environment.systemPackages = with pkgs; [
git
file
wget
fzf
linuxPackages.perf
];
# neovim
programs.neovim.enable = true;
programs.neovim.defaultEditor = true;
programs.neovim.viAlias = true;
programs.neovim.vimAlias = true;
# ssh
services.openssh.enable = true;
系统配置
给jumper电脑自动挂在SD卡。
# refers to https://www.golinuxcloud.com/automount-file-system-systemd-rhel-centos-7-8/
systemd.mounts = if "${config.networking.hostName}" == "jumper"
then [{
enable = true;
# [Unit]
description = "My SD Card";
unitConfig = {
DefaultDependencies = "no";
Conflicts = "umount.target";
};
before = ["local-fs.target" "umount.target"];
after = ["swap.target"];
# [Mount]
what = "/dev/disk/by-label/home";
where = "/home";
type = "ext4";
options = "defaults";
# [Install]
wantedBy = ["multi-user.target"];
}] else [];
systemd.automounts = if "${config.networking.hostName}" == "jumper"
then [{
enable = true;
# [Unit]
description = "automount sdcard";
# [Automount]
where = "/home";
# [Install]
wantedBy = ["multi-user.target"];
}] else [];
启用NTFS文件系统的支持。 如此就可以在NixOS/Windows双系统的电脑上挂在Windows的分区啦。
boot.supportedFilesystems = [ "ntfs" ];
启用podman。 podman是一个十分好用的docker实现。 支持用户态容器(不需要sudo),可以方便地挂在容器镜像的文件系统。
virtualisation.podman.enable = true;
配置binfmt,让非本地指令集的用户程序可以正常运行。
比如在x86_64-linux上运行aarch64-linux的用户程序。
注意:不能在配和本地一样的binfmt,比如不能在x86_64-linux的机器上配置x86_64-linux的binfmt。
不然会出现奇怪的嵌套?你执行任何一条命令(x86_64-linux)都需要去调用qemu-x86_64,
但qemu-x86_64本事也是x86_64-linux的,所以会死循环?
我做了个实验:在x86_64-linux的NixOS中启用x86_64-linux的binfmt。
任何程序都执行不了了,连关机都不行,只能强制重启。
不过好在NixOS可以回滚,轻松复原实验前的环境。
下面的filterAttrs
就是用来保证不配置本地的binfmt。
boot.binfmt.registrations = let
version = "9.0.2+ds-6";
qemu-user-static = pkgs.nur.repos.xddxdd.qemu-user-static.override {
sources = {
qemu-user-static-amd64 = {
pname = "qemu-user-static-amd64";
inherit version;
src = builtins.fetchurl {
url = "http://ftp.debian.org/debian/pool/main/q/qemu/qemu-user-static_${version}_amd64.deb";
sha256 = "15gfs9011smppbank3vzla09yrq84xrhbcn3zwqjnl9xvkzsp2bw";
};
};
qemu-user-static-arm64 = {
pname = "qemu-user-static-arm64";
inherit version;
src = builtins.fetchurl {
url = "http://ftp.debian.org/debian/pool/main/q/qemu/qemu-user-static_${version}_arm64.deb";
sha256 = "1as8s74dmmqp2sv2msblb2vngn1y3611ix9yjq012dlgck2h77id";
};
};
};
};
in pkgs.lib.filterAttrs (n: v: n!=builtins.currentSystem) {
x86_64-linux = {
interpreter = "${qemu-user-static}/bin/qemu-x86_64-static";
magicOrExtension = ''\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x3e\x00'';
mask = ''\xff\xff\xff\xff\xff\xfe\xfe\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'';
wrapInterpreterInShell = false;
};
aarch64-linux = {
interpreter = "${qemu-user-static}/bin/qemu-aarch64-static";
magicOrExtension = ''\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7\x00'';
mask = ''\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\x00\xff\xfe\xff\xff\xff'';
wrapInterpreterInShell = false;
};
riscv64-linux = {
interpreter = "${qemu-user-static}/bin/qemu-riscv64-static";
magicOrExtension = ''\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xf3\x00'';
mask = ''\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'';
wrapInterpreterInShell = false;
};
};
启用docdev。 在home-manager中装devdoc似乎有问题,得在NixOS中装才行。 之后有空再来详细研究。
# Make sure devdoc outputs are installed.
documentation.dev.enable = true;
# Make sure legacy path is installed as well.
environment.pathsToLink = [ "/share/gtk-doc" ];
启用ADB,安卓搞事情必备。
programs.adb.enable = true;
users.users.xieby1.extraGroups = ["adbusers"];
nix.settings.trusted-users = ["root" "xieby1"];
zramSwap.enable = true;
documentation.man.generateCaches = true;
}
{ config, pkgs, ... }:
{
imports = [ # files
] ++ [{ # functions & attrs
# support fractional scaling for x11 gnome:
# refer to https://nixos.wiki/wiki/Overlays#Overriding_a_package_inside_a_scope
nixpkgs.overlays = [ (final: prev: {
gnome = prev.gnome.overrideScope (gfinal: gprev: {
mutter = let
mutter-x11-scaling = pkgs.fetchFromGitHub {
owner = "puxplaying";
repo = "mutter-x11-scaling";
rev = "8c5d5224955a5ec6a36697e9b64e606e6a596ef7";
hash = "sha256-TDQkDgAcuNnzSqiYE364E/Z2mBKegevVQ3AeOYBjHc4=";
};
in gprev.mutter.overrideAttrs (old: {
patches = (pkgs.lib.optionals (old ? patches) old.patches) ++ [
"${mutter-x11-scaling}/mutter-fix-x11-restart.patch"
"${mutter-x11-scaling}/x11-Add-support-for-fractional-scaling-using-Randr.patch"
"${mutter-x11-scaling}/Support-Dynamic-triple-double-buffering.patch"
];
});
gnome-control-center = let
gnome-control-center-x11-scaling = pkgs.fetchFromGitHub {
owner = "puxplaying";
repo = "gnome-control-center-x11-scaling";
rev = "9d4b878a523151776cea0fad47a0421c660ea8af";
hash = "sha256-xAf0jXs9holjN5xa20d4VLesbwitNq0w+9p5qyw7Ut8=";
};
in gprev.gnome-control-center.overrideAttrs (old: {
patches = (pkgs.lib.optionals (old ? patches) old.patches) ++ [
"${gnome-control-center-x11-scaling}/display-Support-UI-scaled-logical-monitor-mode.patch"
"${gnome-control-center-x11-scaling}/display-Allow-fractional-scaling-to-be-enabled.patch"
];
});
});
}) ];
# push the overrided mutter and gnome to my cachix
cachix_packages = with pkgs.gnome; [mutter gnome-control-center];
}] ;
# Enable the X11 windowing system.
services.xserver.enable = true;
services.xserver.videoDrivers = [
"nvidia"
# default video drivers
"radeon" "nouveau" "modesetting" "fbdev"
"intel" "amdgpu"
];
# Enable the GNOME Desktop Environment.
services.xserver.displayManager.gdm.enable = true;
services.xserver.displayManager.gdm.wayland = false;
services.xserver.desktopManager.gnome.enable = true;
# https://discourse.nixos.org/t/how-to-create-folder-in-var-lib-with-nix/15647
system.activationScripts.user_account_conf = pkgs.lib.stringAfter [ "var" ] (let
face = pkgs.fetchurl {
url = "https://github.com/xieby1.png";
sha256 = "1s20qy3205ljp29lk0wqs6aw5z67db3c0lvnp0p7v1q2bz97s9bm";
};
in ''
mkdir -p /var/lib/AccountsService/users
if [[ ! -f /var/lib/AccountsService/users/xieby1 ]]; then
cat > /var/lib/AccountsService/users/xieby1 <<XIEBY1_ACCOUNT
[User]
Session=
Icon=/var/lib/AccountsService/icons/xieby1
SystemAccount=false
XIEBY1_ACCOUNT
fi
mkdir -p /var/lib/AccountsService/icons
ln -sf ${face} /var/lib/AccountsService/icons/xieby1
'');
# Configure keymap in X11
# services.xserver.layout = "us";
# services.xserver.xkbOptions = "eurosign:e";
# Enable CUPS to print documents.
# https://nixos.wiki/wiki/Printing
services.printing.enable = true;
services.printing.drivers = [pkgs.hplip];
services.avahi.enable = true;
services.avahi.nssmdns4 = true;
# Enable touchpad support (enabled default in most desktopManager).
services.libinput.enable = true;
# https://github.com/kovidgoyal/kitty/issues/403
environment.variables.GLFW_IM_MODULE = "ibus";
i18n.inputMethod.enabled = "ibus";
i18n.inputMethod.ibus.engines = with pkgs.ibus-engines; [
rime
# keyboard layout is wrong in anthy, e.g. punctuations
# anthy
# hinagara toggle setting is absent in mozc
mozc
hangul
];
nixpkgs.config.allowUnfree = true;
# vim vista need nerd fonts
# https://github.com/liuchengxu/vista.vim/issues/74
# https://github.com/liuchengxu/space-vim/wiki/tips#programming-fonts
# available nerd fonts: nixpkgs/pkgs/data/fonts/nerdfonts/shas.nix
## use non-variable noto font for feishu and other old electron apps
## for more details see: https://github.com/NixOS/nixpkgs/issues/171976
fonts.packages = (
with (import (fetchTarball {
url = "https://github.com/NixOS/nixpkgs/archive/d881cf9fd64218a99a64a8bdae1272c3f94daea7.tar.gz";
sha256 = "1jaghsmsc05lvfzaq4qcy281rhq3jlx75q5x2600984kx1amwaal";
}) {}); [
noto-fonts-cjk-sans
noto-fonts-cjk-serif
noto-fonts-emoji]) ++ (with pkgs; [
(nerdfonts.override {
# The best developer fonts, see https://www.nerdfonts.com/
fonts = [
"Hack"
"Meslo"
"SourceCodePro"
"FiraCode"
"Terminus"
"Iosevka"
"Monoid"
"FantasqueSansMono"
];
})
# refs to pkgs/data/fonts/roboto-mono/default.nix
# (stdenv.mkDerivation {
# name = "my_fonts";
# srcs = [(fetchurl {
# url = "https://github.com/lxgw/LxgwWenKai/releases/download/v1.311/LXGWWenKai-Bold.ttf";
# sha256 = "16111vvjii2hmnigjb44rjj39k8hjawbvwrb3f2f1ph4hv5wnvkn";
# }) (fetchurl {
# url = "https://github.com/lxgw/LxgwWenKai/releases/download/v1.311/LXGWWenKai-Regular.ttf";
# sha256 = "103mvbpg51jvda265f29sjq17jj76dgwz6f1qdmv6d99bb8b6x7w";
# })];
# sourceRoot = "./";
# unpackCmd = ''
# ttfName=$(basename $(stripHash $curSrc))
# cp $curSrc ./$ttfName
# '';
# installPhase = ''
# mkdir -p $out/share/fonts/truetype
# cp -a *.ttf $out/share/fonts/truetype/
# '';
# })
]);
# enable fontDir /run/current-system/sw/share/X11/fonts
fonts.fontDir.enable = true;
fonts.fontconfig.defaultFonts = {
monospace = [
"DejaVu Sans Mono"
"Noto Color Emoji"
"Noto Emoji"
];
};
services.gpm.enable = true;
hardware.xone.enable = true;
programs.evolution = {
enable = true;
plugins = [pkgs.evolution-ews];
};
}
{ config, lib, ...}:
{
imports = [../../modules/cachix.nix];
config = lib.mkIf (
(builtins.pathExists config.cachix_dhall) &&
(config.cachix_packages != [])
) {
system.activationScripts = {
cachix_push = config._cachix_push;
};
};
}
Currently, Not Wayland, But X11
Here list wayland problems I have met.
fcitx input method not work
waydroid
waydroid tile not work
tabbed not work
gnome terminal headerbar cannot be hidden
Both gnome extension unite and gtk-title-bar cannot hide gnome terminal(kitty and alacritty)'s headerbar.
- https://github.com/velitasali/gtktitlebar/issues/25
- https://github.com/velitasali/gtktitlebar/issues/14
autokey and espanso not work in wayland
Autokey only works in X11, while espanso officially disclaim it support wayland. But my wayland experience is, espanso does not work either.
home.nix
home.nix
是home-manager的入口配置文件,它导入了3个nix文件:
./opt.nix
:我定义的全局变量./usr/cli.nix
:我的所有CLI程序的配置./usr/gui.nix
:我的所有GUI程序的配置
因为部分系统不需要GUI程序,比如安卓手机nix-on-droid或是树莓派等。
我利用环境变量DISPLAY
用于判断是否导入GUI程序的配置。
{ config, pkgs, stdenv, lib, ... }:
let
opt = import ./opt.nix;
in {
imports = [
./usr/modules/cachix.nix
./usr/cli.nix
] ++ lib.optionals opt.isGui [
./usr/gui.nix
];
home.stateVersion = "19.09";
programs.home-manager.enable = true;
}
cli-extra.nix: Extra CLI configs (added to minial cli.nix)
{ config, pkgs, stdenv, lib, ... }:
let
opt = import ../opt.nix;
in {
imports = [{
home.packages = let
pandora = pkgs.python3Packages.callPackage ./cli/pandora-chatgpt.nix {};
chatgpt = pkgs.writeShellScriptBin "chatgpt" ''
${pandora}/bin/pandora -t ~/Gist/Pandora-ChatGPT/access_token.dat $@
'';
in [pandora chatgpt];
}{
home.packages = [
pkgs.act
(pkgs.writeShellScriptBin "act-podman" ''
export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/podman/podman.sock
CMD=(
"${pkgs.act}/bin/act"
"--bind"
# use podman
"--container-daemon-socket" "unix://$XDG_RUNTIME_DIR/podman/podman.sock"
# use host proxy
"--container-options" "--network=host"
"--env" "HTTPS_PROXY='http://127.0.0.1:${toString opt.proxyPort}'"
"--env" "HTTP_PROXY='http://127.0.0.1:${toString opt.proxyPort}'"
"--env" "FTP_PROXY='http://127.0.0.1:${toString opt.proxyPort}'"
"--env" "https_proxy='http://127.0.0.1:${toString opt.proxyPort}'"
"--env" "http_proxy='http://127.0.0.1:${toString opt.proxyPort}'"
"--env" "ftp_proxy='http://127.0.0.1:${toString opt.proxyPort}'"
"$@"
)
eval "''${CMD[@]}"
'')
];
}];
home.packages = with pkgs; [
# tools
imagemagick
# programming
## c
cling # c/cpp repl
## javascript
nodePackages.typescript
### node
nodejs
## java
openjdk
### pdfcrop
(texlive.combine {inherit (pkgs.texlive) scheme-minimal pdfcrop;})
# runXonY
qemu
] ++ lib.optional (builtins.currentSystem == "x86_64-linux") quickemu;
}
{ config, pkgs, stdenv, lib, ... }:
let
opt = import ../opt.nix;
git-wip = builtins.derivation {
name = "git-wip";
system = builtins.currentSystem;
src = pkgs.fetchurl {
url = "https://raw.githubusercontent.com/bartman/git-wip/1c095e93539261370ae811ebf47b8d3fe9166869/git-wip";
sha256 = "00gq5bwwhjy68ig26a62307pww2i81y3zcx9yqr8fa36fsqaw37h";
};
builder = pkgs.writeShellScript "git-wip-builder" ''
source ${pkgs.stdenv}/setup
mkdir -p $out/bin
dst=$out/bin/git-wip
cp $src $dst
chmod +w $dst
sed -i 's/#!\/bin\/bash/#!\/usr\/bin\/env bash/g' $dst
chmod -w $dst
chmod a+x $dst
'';
};
fzf-doc = pkgs.writeScriptBin "fzf-doc" ''
allCmds() {
# bash alias
compgen -A alias
# external commands
# https://unix.stackexchange.com/questions/94775/list-all-commands-that-a-shell-knows
case "$PATH" in
(*[!:]:) PATH="$PATH:" ;;
esac
set -f
IFS_OLD="$IFS"
IFS=:
for dir in $PATH; do
set +f
[ -z "$dir" ] && dir="."
for file in "$dir"/*; do
if [ -x "$file" ] && ! [ -d "$file" ]; then
echo "''${file##*/}"
fi
done
done
IFS="$IFS_OLD"
}
cd ~/Documents
FILE=$(fzf)
[ -z "$FILE" ] && exit
CMD=$(allCmds | fzf)
[ -z "$CMD" ] && exit
case "$CMD" in
# run gui cmd background
o)
# use nohup to run bash command in background and exit
## https://superuser.com/questions/448445/run-bash-script-in-background-and-exit-terminal
# nohup not recognize bash alias like `o`, it's necessary to call bash
eval nohup bash -ic '"$CMD \"$FILE\" &"'
;;
# run cli cmd foreground
*)
# FILE name may contain space, quote FILE name
eval "$CMD" \"$FILE\"
;;
esac
'';
sysconfig = (
# <...> are expression search in NIX_PATH
if (builtins.tryEval <nixos-config>).success
then import <nixpkgs/nixos> {}
else import <nixpkgs/nixos> {configuration={};}
).config;
in
{
imports = lib.optionals (!opt.isMinimalConfig) [
./cli-extra.nix
] ++ [ # files
./cli/vim
./cli/tmux.nix
./cli/clash.nix
./cli/tailscale.nix
# When init searxng, it throws `ERROR:searx.engines.wikidata: Fail to initialize`
# I have no idea, so disable it.
# ./cli/searxng.nix
] ++ [{ # functions & attrs
home.packages = [
pkgs.fzf
fzf-doc
];
programs.bash.bashrcExtra = ''
# FZF top-down display
export FZF_DEFAULT_OPTS="--reverse"
'';
}{
home.packages = lib.optional (!opt.isNixOnDroid) pkgs.hstr;
programs.bash.bashrcExtra = lib.optionalString (!opt.isNixOnDroid) ''
# HSTR configuration - add this to ~/.bashrc
alias hh=hstr # hh to be alias for hstr
export HSTR_CONFIG=hicolor # get more colors
shopt -s histappend # append new history items to .bash_history
export HISTCONTROL=ignorespace # leading space hides commands from history
# ensure synchronization between bash memory and history file
export PROMPT_COMMAND="history -a;"
# if this is interactive shell, then bind hstr to Ctrl-r (for Vi mode check doc)
if [[ $- =~ .*i.* ]]; then bind '"\C-r": "\C-a hstr -- \C-j"'; fi
# if this is interactive shell, then bind 'kill last command' to Ctrl-x k
if [[ $- =~ .*i.* ]]; then bind '"\C-xk": "\C-a hstr -k \C-j"'; fi
'';
}{
programs.ssh.enable = true;
programs.ssh.includes = lib.optional (builtins.pathExists ~/Gist/Config/ssh.conf) "~/Gist/Config/ssh.conf";
programs.bash.bashrcExtra = lib.optionalString opt.isNixOnDroid ''
# start sshd
if [[ -z "$(pidof sshd-start)" ]]; then
tmux new -d -s sshd-start sshd-start
fi
'';
}{
home.packages = with pkgs; [
gitui
mr
git-wip
git-quick-stats
];
programs.git = {
enable = true;
package = pkgs.gitFull;
userEmail = "xieby1@outlook.com";
userName = "xieby1";
extraConfig = {
core = {
editor = "vim";
};
credential.helper = "store";
};
aliases = {
viz = "log --all --decorate --oneline --graph";
};
lfs.enable = true;
};
home.file.mr = {
text = if builtins.pathExists ~/Gist/Config/mrconfig
then builtins.readFile ~/Gist/Config/mrconfig
else "";
target = ".mrconfig";
};
# mr status not work in non-home dir
programs.bash.shellAliases.mr = "mr -d ~";
}{
home.packages = [pkgs.nix-index];
home.file.nix_index_database = {
source = builtins.fetchurl "https://github.com/Mic92/nix-index-database/releases/latest/download/index-${builtins.currentSystem}";
target = ".cache/nix-index/files";
};
}{
Syncthing
services.syncthing = {
enable = true;
让syncthing的端口外部可访问。
extraOptions = lib.optional opt.isCli "--gui-address=0.0.0.0:8384";
};
启用代理,因为有些syncthing的服务器似乎是被墙了的。
systemd.user.services.syncthing.Service.Environment = [
# https://docs.syncthing.net/users/proxying.html
"http_proxy=http://127.0.0.1:${toString opt.proxyPort}"
];
使用命令行浏览器browsh来实现syncthing-tui。
home.packages = lib.optional (!opt.isMinimalConfig) (
pkgs.writeShellScriptBin "syncthing-tui" ''
${pkgs.browsh}/bin/browsh --firefox.path ${pkgs.firefox}/bin/firefox http://127.0.0.1:8384
''
);
}{
home.packages = with pkgs; [
cachix
];
home.file.cachix_dhall = {
source = if (builtins.pathExists ~/Gist/Config/cachix.dhall)
then ~/Gist/Config/cachix.dhall
else builtins.toFile "empty-cachix.dhall" "";
target = ".config/cachix/cachix.dhall";
};
}{
home.packages = with pkgs; [
universal-ctags
];
home.file.exclude_ctags = {
text = ''
# exclude ccls generated directories
--exclude=.ccls*
'';
target = ".config/ctags/exclude.ctags";
};
}];
home.packages = with pkgs; [
# tools
parallel
comma
xclip
python3Packages.qrcode
ripgrep
## archive
unar
## manage
htop
nix-tree
## text
pandoc
## compile
gnumake
makefile2graph
remake
## draw
graphviz
figlet
nyancat
## manual
tldr
## file system
file
# magika # detect file content types with deep learning
tree
## network
wget
bind.dnsutils # nslookup
netcat
nload
nmap
nethogs
## x11
xdotool
# programming
clang-tools
cmake
capstone
scc
## https://stackoverflow.com/questions/40165650/how-to-list-all-files-tracked-by-git-excluding-submodules
(writeShellScriptBin "scc-git" "${scc}/bin/scc $(git grep --cached -l '')")
sloccount
flamegraph
## python
( python3.withPackages ( p: with p; [
ipython
]))
## c
(lib.setPrio # make bintools less prior
(bintools-unwrapped.meta.priority + 1)
bintools-unwrapped
)
(if builtins.currentSystem == "x86_64-linux"
then gcc_multi
else gcc
)
gdb
### docs
stdmanpages
man-pages
#gccStdenv
bear
## xml
libxml2
## bash
bc
## nix
nixos-option
nix-output-monitor
### allow non-nixos access `man configuration.nix`
# see: nixos/modules/misc/documentation.nix
# nixos/doc/manual/default.nix
sysconfig.system.build.manual.nixos-configuration-reference-manpage
nurl
];
programs.eza.enable = true;
# bash
programs.bash.enable = true;
programs.bash.shellAliases.o = "xdg-open";
programs.bash.bashrcExtra = ''
# rewrite prompt format
u_green="\[\033[01;32m\]"
u_blue="\[\033[01;34m\]"
u_white="\[\033[00m\]"
PS1="''${debian_chroot:+($debian_chroot)}"
if [[ $HOSTNAME =~ qemu.* ]]; then
PS1+="(qemu)"
fi
if [[ -n "$IN_NIX_SHELL" ]]; then
PS1+="(''${name}.$IN_NIX_SHELL)"
fi
PS1+="''${u_green}\u${lib.optionalString (!opt.isNixOnDroid) "@\\h"}''${u_white}:"
PS1+="''${u_blue}\w''${u_white}"
PS1+="\n''${u_green}\$''${u_white} "
unset u_green u_blue u_white
## change title
### https://unix.stackexchange.com/questions/177572/
PS1+="\[\e]2;\w\a\]"
# nixos obsidian
export NIXPKGS_ALLOW_INSECURE=1
# source my bashrc
if [[ -f ~/Gist/Config/bashrc ]]; then
source ~/Gist/Config/bashrc
fi
# user nix config setting
export NIX_USER_CONF_FILES=~/.config/nixpkgs/nix/nix.conf
if [[ -e ~/.nix-profile/etc/profile.d/nix.sh ]]; then
source ~/.nix-profile/etc/profile.d/nix.sh
fi
# bash-completion, inspired by
## https://discourse.nixos.org/t/whats-the-nix-way-of-bash-completion-for-packages/20209/16
# system tools completion, e.g. nix
XDG_DATA_DIRS+=":${sysconfig.system.path}/share"
# home tools completion
XDG_DATA_DIRS+=":${config.home.path}/share"
export XDG_DATA_DIRS
. ${pkgs.bash-completion}/etc/profile.d/bash_completion.sh
# 解决tmux在nix-on-droid上不显示emoji和中文的问题
export LANG=C.UTF-8
if [[ -n $(command -v eza) ]]; then
alias ls=eza
fi
'' + lib.optionalString opt.isWSL2 ''
# use the working directory of the current tab as the starting directory for a new tab
# https://learn.microsoft.com/en-us/windows/terminal/tutorials/new-tab-same-directory#using-actions-to-duplicate-the-path
PROMPT_COMMAND=''${PROMPT_COMMAND:+"$PROMPT_COMMAND"}'printf "\e]9;9;%s\e\\" "$(wslpath -w "$PWD")"'
'';
## after direnv's bash.initExtra
programs.bash.initExtra = lib.mkOrder 2000 ''
# https://stackoverflow.com/questions/1862510/how-can-the-last-commands-wall-time-be-put-in-the-bash-prompt
function timer_start {
_timer=''${_timer:-$SECONDS}
}
function timer_stop {
last_timer=$(($SECONDS - $_timer))
_notification_threthold=10
if [[ $last_timer -ge $_notification_threthold ]]; then
_notification="[''${last_timer}s⏰] Job finished!"
if [[ "$TERM" =~ tmux ]]; then
# https://github.com/tmux/tmux/issues/846
printf '\033Ptmux;\033\x1b]99;;%s\033\x1b\\\033\\' "$_notification"
else
printf '\x1b]99;;%s\x1b\\' "$_notification"
fi
fi
}
function timer_unset {
unset _timer
}
trap timer_start DEBUG
PROMPT_COMMAND="timer_stop;$PROMPT_COMMAND"
if [[ -n "$(echo $PROMPT_COMMAND | grep -o -e ';$')" ]]; then
PROMPT_COMMAND+="timer_unset;"
else
PROMPT_COMMAND+=";timer_unset;"
fi
'';
home.file.gdbinit = {
source = pkgs.fetchurl {
url = "https://raw.githubusercontent.com/cyrus-and/gdb-dashboard/2b107b27949d13f6ef041de6eec1ad2e5f7b4cbf/.gdbinit";
sha256 = "02rxyk8hmk7xk1pyhnc5z6a2kqyd63703rymy9rfmypn6057i4sr";
name = "gdbinit";
};
target = ".gdbinit";
};
home.file.gdb_dashboard_init = {
text = ''
# gdb-dashboard init file
# available layout modules
# stack registers history assembly
# breakpoints expressions memory
# source threads variables
dashboard -layout source
# https://en.wikipedia.org/wiki/ANSI_escape_code
#dashboard -style prompt
## fg bold blue
dashboard -style prompt_not_running "\\[\\e[1;34m\\]$\\[\\e[0m\\]"
## fg bold green
dashboard -style prompt_running "\\[\\e[1;32m\\]$\\[\\e[0m\\]"
'';
target = ".gdbinit.d/init";
};
programs.direnv.enable = true;
programs.direnv.nix-direnv.enable = true;
programs.man.generateCaches = true;
}
{ config, pkgs, stdenv, lib, ... }:
let
opt = import ../../opt.nix;
clashctl = pkgs.callPackage ./clashctl.nix {};
in {
imports = [{
home.packages = [
pkgs.clash-meta
] ++ lib.optional (!opt.isNixOnDroid) clashctl;
cachix_packages = lib.optional (!opt.isNixOnDroid) clashctl;
systemd.user.services.clash = {
Unit = {
Description = "Auto start clash";
After = ["network.target"];
};
Install = {
WantedBy = ["default.target"];
};
Service = {
ExecStart = "${pkgs.clash-meta.outPath}/bin/clash-meta -d ${config.home.homeDirectory}/Gist/clash";
};
};
programs.bash.bashrcExtra = lib.mkBefore (lib.optionalString (!opt.isNixOnDroid) ''
# proxy
## default
HTTP_PROXY="http://127.0.0.1:${toString opt.proxyPort}/"
## microsoft wsl
# if [[ $(uname -r) == *"microsoft"* ]]; then
# hostip=$(cat /etc/resolv.conf | grep nameserver | awk '{ print $2 }')
# export HTTP_PROXY="http://$hostip:${toString opt.proxyPort}"
# fi
export HTTPS_PROXY="$HTTP_PROXY"
export HTTP_PROXY="$HTTP_PROXY"
export FTP_PROXY="$HTTP_PROXY"
export http_proxy="$HTTP_PROXY"
export https_proxy="$HTTP_PROXY"
export ftp_proxy="$HTTP_PROXY"
'');
}];
}
{ lib
, rustPlatform
, fetchFromGitHub
}:
rustPlatform.buildRustPackage {
name = "clashctl";
src = fetchFromGitHub {
# owner = "https://github.com/George-Miao/clashctl";
owner = "George-Miao";
repo = "clashctl";
rev = "b09e1faf80f1a25fa855499d8b34d36491e5a081";
hash = "sha256-c7y64SsZEKdC8+umCY8+XBwxAHxn4YpqR48ASbHpkdM=";
};
cargoHash = "sha256-2d+phmMJeHZsJy300GwUAnh8KTGzpHCCIg8x4Wr8ytE=";
doCheck = false;
meta = with lib; {
description = "CLI for interacting with clash";
homepage = "https://github.com/George-Miao/clashctl";
license = licenses.mit;
maintainers = with maintainers; [ xieby1 ];
};
}
{ buildPythonPackage
, lib
, nss
, nspr
, expat
, fetchPypi
}:
let
rpath = lib.makeLibraryPath [
nss
nspr
expat
];
in buildPythonPackage rec {
pname = "kaleido";
version = "0.2.1";
format = "wheel";
src = fetchPypi {
inherit pname version format;
platform = "manylinux1_x86_64";
hash = "sha256-qiHPG/HHj4+lCp99ReEAPDh709b+CnZ8+780S5W9w6g=";
};
doCheck = false;
postFixup = ''
for file in $(find $out -type f \( -perm /0111 -o -name \*.so\* \) ); do
patchelf --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" "$file" || true
patchelf --set-rpath ${rpath}:$out/lib/x86_64-linux-gnu $file || true
done
sed -i 's,#!/bin/bash,#!/usr/bin/env bash,' $out/lib/python3.11/site-packages/kaleido/executable/kaleido
'';
}
binutils's ld and gcc's ld collsion
Background: I want to install gcc
and objdump
, where objdump
is contained in binutils
.
Home-manager tolds me gcc
's ld
collides with binutils
's ld
.
As I explore into gcc
and binutils
, weird thing comes.
Packages binutils
and gcc
both contain ld executable.
binutils
and gcc
has the same priority 10.
The WEIRD thing is,
binutils
wants to have a lower priority than gcc-wrapper, so sets its priority to 10, see nixpkgs:pkgs/development/tools/misc/binutils/default.nix
Give binutils a lower priority than gcc-wrapper to prevent a collision due to the ld/as wrappers/symlinks in the latter.
- Both
gcc
wrapper and all-packages set gcc priority to 10, see nixpkgs:pkgs/top-level/all-packages.nix
andpkgs/build-support/cc-wrapper/default.nix
All-packages set priority by lowPrio function, which will set priority to 10. Cc-wrapper directly set priority to 10.
As a result, binutils
will definitely collide with gcc
!
My solution: assign binutils
a lower priority, like this
home.packages = with pkgs; [
(lib.setPrio # higher value, less prior
(bintools-unwrapped.meta.priority + 1)
bintools-unwrapped
)
gdb
]
Nodejs packages (npm) in NixOS
NixOS中的Nodejs包(npm)
太长不看:手动暴露buildNodePackage
,添加自定义的npm包。
nixpkgs中的node包虽多但有限, 遇到需要的node包不存在时,是个麻烦事。
让我觉得十分诡异的是,
nixpkgs中存在一个十分方便的添加node包的函数nodeEnv.buildNodePackage
,
但是这个函数却不暴露出来给用户。
甚至,有些nixpkgs中的包为了使用这个函数,
复制粘贴该函数到自己的包中。
在这些奇怪的事情的基础上,
还衍生出来自动生成该buildNodePackage
函数软件node2nix
。
所以这真的是存在即合理嘛? 还是我学艺不精,不能理解设计者的意图?
一个简单的暴露buildNodePackage
的方法,
直接导入buildNodePackage
所在的文件。
为了跨平台可用,
路径的构建采用了一点使用了点点小把戏,
<nixpkgs> + /pkgs/development/node-packages/node-env.nix
以@types/node为例子,nodepkgs.nix:
{ ... }:
let
pkgs = import <nixpkgs> {};
nodeEnv = import (<nixpkgs> + /pkgs/development/node-packages/node-env.nix) {
inherit (pkgs) lib stdenv nodejs python2;
inherit pkgs;
inherit (pkgs) libtool runCommand writeTextFile writeShellScript;
};
globalBuildInputs = [];
in {
"@types/node" = nodeEnv.buildNodePackage {
name = "_at_types_slash_node";
packageName = "@types/node";
version = "18.7.15";
src = pkgs.fetchurl {
url = "https://registry.npmjs.org/@types/node/-/node-18.7.15.tgz";
sha512 = "XnjpaI8Bgc3eBag2Aw4t2Uj/49lLBSStHWfqKvIuXD7FIrZyMLWp8KuAFHAqxMZYTF9l08N1ctUn9YNybZJVmQ==";
};
buildInputs = globalBuildInputs;
meta = {
description = "TypeScript definitions for Node.js";
homepage = "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node";
license = "MIT";
};
production = true;
bypassCache = true;
reconstructLock = true;
};
}
该nodepkgs.nix文件为用户自定义的node包, 可以像nixpkgs一样使用这个文件,例如导入
myNodePkgs = import ./cli/nodepkgs.nix {}
包的表达式为myNodePkgs."@types/node"
。
打包python(pip)包,以pandora-chatgpt为例
太常不看
- nix文件: https://github.com/xieby1/nix_config/blob/main/usr/cli/pandora-chatgpt.nix
- 使用方法:
pkgs.python3Packages.callPackage ./cli/pandora-chatgpt.nix {};
- Add python optional dependencies (extras): see nixpkgs manual 17.27.2.3.2. Optional extra dependencies
{ buildPythonPackage
, fetchPypi
, appdirs
, certifi
, flask
, flask-cors
, httpx
, loguru
, pyjwt
, pyperclip
, requests
, rich
, sentry-sdk
, waitress
, werkzeug
}:
buildPythonPackage rec {
pname = "Pandora-ChatGPT";
version = "1.2.5";
src = fetchPypi {
inherit pname version;
hash = "sha256-tfGqBRf/0VyaBuXsZEH8LwAuJYfk7oimY5Y0M1d/Qxs=";
};
doCheck = false;
preBuild = ''
# ignore version
sed -i 's/\~=[^;]*//g' requirements.txt
'';
propagatedBuildInputs = [
appdirs
certifi
flask
flask-cors
httpx
] ++ httpx.optional-dependencies.socks ++ [
loguru
pyjwt
] ++ pyjwt.optional-dependencies.crypto ++ [
pyperclip
requests
] ++ requests.optional-dependencies.socks ++ [
rich
sentry-sdk
waitress
werkzeug
flask
] ++ flask.optional-dependencies.async;
}
Python in Nix/NixOS
Project | Maintained | Description | Purity | Compatibility |
---|---|---|---|---|
venv | ❌ | 100%? | ||
mach-nix | ✅ | |||
pypi2nix | ❌ | |||
pip2nix | ✅ | ✅ | ||
buildPythonPackage | ✅ | ✅ | ||
[TODO] poetry | ||||
[TODO] dream2nix |
pip2nix
Noted: Latest version of pip2nix only use python39. While nixpkgs 22.11 (current stable) is python310. I dont to install multiple versions of python3.
If pip2nix can overcome the disadvantage of that generate a long list of python packages, and reuse python3Packages in nixpkgs, I would prefer to use pip2nix completely.
Currently, I use buildPythonPackage
.
buildPythonPackage
pkgs.python3Packages.buildPythonPackage
venv
Use virtualenv, pip
is available, no need to write nix expressions to install packages.
Code see https://xieby1.github.io/scripts/index.html#venvnix
poetry
According to What is the correct way to setup pip with nix to install any python package in an isolated nix environment, I found two useful tools to install python packages in Nix/NixOS
- [TODO] poetry
- mach-nix
mach-nix
mach-nix github repo: github.com/DavHau/mach-nix
Here is [python_mach.nix]({{ site.repo_url }}/scripts/shell/python_mach.nix), an example which create a shell with a python package called expmcc.
{ config, pkgs, stdenv, lib, ... }:
let
opt = import ../../opt.nix;
searxng_yml = builtins.toFile "searxng.yml" ''
# https://docs.searxng.org/admin/settings/settings.html#settings-yml-location
# The initial settings.yml we be load from these locations:
# * the full path specified in the SEARXNG_SETTINGS_PATH environment variable.
# * /etc/searxng/settings.yml
# Default settings see <pkgs.searxng>/lib/python3.11/site-packages/searx/settings.yml
use_default_settings: true
search:
autocomplete: "google"
default_lang: "en"
server:
# Is overwritten by $SEARXNG_SECRET
secret_key: ${if builtins.pathExists ~/Gist/Config/passwordFile
then builtins.readFile ~/Gist/Config/passwordFile
else "miao"}
outgoing:
proxies:
all://:
- http://127.0.0.1:${toString opt.proxyPort}
engines:
- name: bilibili
engine: bilibili
shortcut: bil
disabled: false
- name: bing
engine: bing
shortcut: bi
disabled: false
- name: qwant
disabled: true
ui:
results_on_new_tab: true
'';
in {
systemd.user.services.searxng = {
Unit = {
Description = "Auto start searxng";
After = ["network.target"];
};
Install = {
WantedBy = ["default.target"];
};
Service = {
Environment = [
"SEARXNG_SETTINGS_PATH=${searxng_yml}"
];
ExecStart = "${pkgs.searxng}/bin/searx-run";
};
};
}
静态链接,以qemu为例
太长不看
- 实现了qemu静态链接,无任何动态链接库的依赖。 采用了两个版本的qemu,当前版本Nix的qemu(nix 21.11, qemu 6.1.1) 和qemu3.1.0这两个版本。
- nix脚本:pkgs_qemu_static.nix
pkgsStatic及其源代码
Nixpkgs含有pkgsStatic软件包,但是大多软件无法直接使用。 需要进行手动修复。
pkgsStatic加载过程的源码
-
pkgs/top-level/stage.nix 将crossSystem设置为static且abi为musl。 之所以用Musl是因为,
Currently uses Musl on Linux (couldn’t get static glibc to work).
其代码大致的如下,
pkgsStatic = nixpkgsFun { crossSystem = { isStatic = true; parsed = stdenv.hostPlatform.parsed // { abi = musl; };};};
- nixpkgsFun = newArgs: import pkgs/top-level/default.nix (...)
- pkgs/top-level/default.nix: stdenvStages {..., crossSystem, ...}
- pkgs/stdenv/default.nix: stagesCross
- pkgs/stdenv/cross/default.nix: stdenvAdapters.makeStatic
- pkgs/stdenv/adapters.nix: makeStatic
- makeStaticLibraries
- 添加configureFlags "--enable-static" "--disable-shared"
- 添加cmakeFlags "-DBUILD_SHARED_LIBS:BOOL=OFF"
- 添加mesonFlags "-Ddefault_library=static"
- makeStaticBinaries
- 添加NIX_CFLAGS_LINK "-static"
- 添加configureFlags "--disable-shared"
- makeStaticLibraries
- pkgs/stdenv/adapters.nix: makeStatic
- pkgs/stdenv/cross/default.nix: stdenvAdapters.makeStatic
- pkgs/stdenv/default.nix: stagesCross
- pkgs/top-level/default.nix: stdenvStages {..., crossSystem, ...}
- nixpkgsFun = newArgs: import pkgs/top-level/default.nix (...)
TODO: 读懂makeStaticLibraries和makeStaticBinaries。
基本思路
对于当前版本的qemu,使用pkgsStatic.qemu ,挨个修复编译报错即可。
对于历史版本的qemu,以3.1.0为例,编译方式已和现在有区别, 比如之前完全是configure, make,而现在引入了meson。 初步设想两种方案,
- 嫁接老版本nixpkgs到当前版本 将qemu-3.1.0对应的nixpkgs嫁接到当前的nixpkgs
- 改造新版本nixpkgs以适应老版本 通过overlay,override方法修改当前nixpkgs的qemu的nix表达式
我采用的第一种办法,将老版本nixpkgs嫁接到当前版本nixpkgs。 使用lazamar.co.uk/nix-versions 查询支持qemu-3.1.0的nixpkgs版本。 引入qemu-3.1.0的示例代码如下,详细见pkgs_qemu_static.nix
# get old nixpkgs which contains qemu-3.1.0
oldNixpkgsSrc = builtins.fetchTarball {...}
qemu31 = pkgs.callPackage (
oldNixpkgsSrc + "/pkgs/applications/virtualization/qemu/default.nix"
) {...}
然后挨个修复编译报错即可。
调试手段
还原构建环境
# 保留构建失败的现场
nix-build pkgs_qemu_static.nix -K
进入现场包含env-vars文件和失败时的源码文件夹。 恢复环境,
. ./env-vars
. $stdenv/setup
查看依赖树
nix-store --query --tree <xxx.drv>
结果
目前仅需要命令行的qemu,因此为了省事, 我去掉了声音和图像支持。
注:在NixOS 21.11上和在ubuntu 22配合nix上编译出来的qemu二进制文件一模一样。
xieby1@yoga14s:~ $ pkgs_qemu_static.nix /nix/store/gs6plgyc0jr9i5qams0ifksijnq9hkq2-qemu-static-x86_64-unknown-linux-musl-6.1.1 /nix/store/lm9kl1nm7bs4hy6l4qng03k4srx1x28n-qemu-3.1.0-x86_64-unknown-linux-musl xieby1@yoga14s:~ $ ldd result/bin/qemu-system-x86_64 not a dynamic executable xieby1@yoga14s:~ $ result/bin/qemu-system-x86_64 --version QEMU emulator version 6.1.1 Copyright (c) 2003-2021 Fabrice Bellard and the QEMU Project developers xieby1@yoga14s:~ $ ldd result-2/bin/qemu-system-x86_64 not a dynamic executable xieby1@yoga14s:~ $ result-2/bin/qemu-system-x86_64 --version QEMU emulator version 3.1.0 Copyright (c) 2003-2018 Fabrice Bellard and the QEMU Project developers
Tailscale/Headscale
overview
- client
- tailscale
- tailscaled
- server
- headscale
Command
TODO: exit node
- https://www.reddit.com/r/Tailscale/comments/w9mtow/question_about_headscale_and_routing/
- https://icloudnative.io/posts/how-to-set-up-or-migrate-headscale/
TODO: headtail config TODO: nix config
- rootless service
- root service
tailscale --socket /tmp/tailscaled.sock up --login-server http://82.157.197.100
tailscale --socket /tmp/tailscaled.sock up --login-server http://82.157.197.100 --force-reauth
enable routes, exit node
sudo tailscale --socket /tmp/tailscaled.sock up --login-server http://82.157.197.100 --advertise-routes=0.0.0.0/0,::/0 --accept-routes=true
sudo docker exec headscale headscale nodes routes enable -i 13 -a -r 0.0.0.0/0 -r ::/0
{ config, pkgs, stdenv, lib, ... }:
let
opt = import ../../opt.nix;
tailscale-bash-completion = builtins.derivation {
name = "tailscale-bash-completion";
system = builtins.currentSystem;
src = builtins.fetchurl "https://gist.githubusercontent.com/cmtsij/f0d0be209224a7bdd67592695e1427de/raw/tailscale";
builder = pkgs.writeShellScript "tailscale-bash-completion-builder" ''
source ${pkgs.stdenv}/setup
dstdir=$out/share/bash-completion/completions
dst=$dstdir/tailscale
mkdir -p $dstdir
cp $src $dst
'';
};
tailscale-wrapper = {suffix, httpPort, socks5Port}: let
tailscale-wrapped = pkgs.writeShellScriptBin "tailscale-${suffix}" ''
tailscale --socket /tmp/tailscale-${suffix}.sock $@
'';
stateDir = "${config.home.homeDirectory}/.local/share/tailscale-${suffix}";
tailscaled-wrapped = pkgs.writeShellScriptBin "tailscaled-${suffix}" ''
TS_LOGS_DIR="${stateDir}" \
${pkgs.tailscale}/bin/tailscaled \
--tun userspace-networking \
--outbound-http-proxy-listen=localhost:${httpPort} \
--socks5-server=localhost:${socks5Port} \
--socket=/tmp/tailscale-${suffix}.sock \
--state=${stateDir}/tailscaled.state \
--statedir=${stateDir} \
$@
'';
tailscale-wrapped-bash-completion = builtins.derivation {
name = "tailscale-${suffix}-bash-completion";
system = builtins.currentSystem;
builder = pkgs.writeShellScript "tailscale-${suffix}-bash-completion-builder" ''
source ${pkgs.stdenv}/setup
reldir=share/bash-completion/completions
dstdir=$out/$reldir
dst=$dstdir/tailscale-${suffix}
mkdir -p $dstdir
touch $dst
echo ". ${tailscale-bash-completion}/$reldir/tailscale" >> $dst
echo "complete -F _tailscale tailscale-${suffix}" >> $dst
'';
};
in {
home.packages = [
tailscale-wrapped
tailscaled-wrapped
tailscale-wrapped-bash-completion
];
systemd.user.services."tailscaled-${suffix}" = {
Unit = {
Description = "Auto start tailscaled-${suffix} userspace network";
After = ["clash.service"];
};
Install = {
WantedBy = ["default.target"];
};
Service = {
Environment = [
"HTTPS_PROXY=http://127.0.0.1:${toString opt.proxyPort}"
"HTTP_PROXY=http://127.0.0.1:${toString opt.proxyPort}"
"https_proxy=http://127.0.0.1:${toString opt.proxyPort}"
"http_proxy=http://127.0.0.1:${toString opt.proxyPort}"
];
ExecStart = "${tailscaled-wrapped}/bin/tailscaled-${suffix}";
};
};
programs.bash.bashrcExtra = lib.optionalString opt.isNixOnDroid ''
# start tailscale-${suffix}
if [[ -z "$(pidof tailscaled-${suffix})" ]]; then
tmux new -d -s tailscaled-${suffix} tailscaled-${suffix}
fi
'';
};
in {
imports = [{
home.packages = [pkgs.tailscale tailscale-bash-completion];
}
# (tailscale-wrapper {suffix="headscale"; httpPort="1055"; socks5Port="1065";})
(tailscale-wrapper {suffix="official"; httpPort="1056"; socks5Port="1066";})
];
}
tmux
{ config, pkgs, stdenv, lib, ... }:
let
opt = import ../../opt.nix;
in {
home.packages = [pkgs.tmux];
bash config for tmux
Auto start tmux in non-GUI device. mkAfter ensure the tmux config is appended to the tail of .bashrc.
programs.bash.bashrcExtra = lib.mkAfter (lib.optionalString (!opt.isGui) ''
# Auto start tmux
# see: https://unix.stackexchange.com/questions/43601/how-can-i-set-my-default-shell-to-start-up-tmux
# ~~1. tmux exists on the system~~, nix ensure that tmux does exist
# 2. we're in an interactive shell, and
# 3. tmux doesn't try to run within itself
if [ -n "$PS1" ] && [[ ! "$TERM" =~ screen ]] && [[ ! "$TERM" =~ tmux ]] && [ -z "$TMUX" ]; then
exec tmux
fi
'');
tmux config file
home.file.tmux = {
text = ''
# display status at top
set -g status-position top
set -g status-right ""
# status bar
## display title on terminal
set -g set-titles on
set -g window-status-format "#I #W #{=/-20/…:pane_title}"
set -g window-status-current-format "🐶#I #W #{=/-20/…:pane_title}"
## hide status bar when only one window
### refer to
### https://www.reddit.com/r/tmux/comments/6lwb07/is_it_possible_to_hide_the_status_bar_in_only_a/
### It not good, since its global!
# if -F "#{==:#{session_windows},1}" "set -g status off" "set -g status on"
# set-hook -g window-linked 'if -F "#{==:#{session_windows},1}" "set -g status off" "set -g status on"'
# set-hook -g window-unlinked 'if -F "#{==:#{session_windows},1}" "set -g status off" "set -g status on"'
## color
### colour256的前10个和终端(gnome-terminal tango)的配色一致
set -g status-style "bg=white fg=black"
set -g window-status-last-style "bg=white fg=green bold"
set -g window-status-current-style "bg=black fg=green bold"
# set -g window-status-separator "|"
# enable mouse scroll
set -g mouse on
# window index start from 1
set -g base-index 1
setw -g pane-base-index 1
# auto re-number
set -g renumber-windows on
# Set new panes to open in current directory
bind c new-window -c "#{pane_current_path}"
bind '"' split-window -c "#{pane_current_path}"
bind % split-window -h -c "#{pane_current_path}"
# alt-num select window
bind-key -n M-1 select-window -t 1
bind-key -n M-2 select-window -t 2
bind-key -n M-3 select-window -t 3
bind-key -n M-4 select-window -t 4
bind-key -n M-5 select-window -t 5
bind-key -n M-6 select-window -t 6
bind-key -n M-7 select-window -t 7
bind-key -n M-8 select-window -t 8
bind-key -n M-9 select-window -t 9
# ctrl-t new window
bind-key -n C-t new-window -c "#{pane_current_path}"
# vi key bindings
set -g mode-keys vi
set -g status-keys vi
# Home, End key not work in nix-on-droid
# https://stackoverflow.com/questions/18600188/home-end-keys-do-not-work-in-tmux
bind-key -n Home send Escape "OH"
bind-key -n End send Escape "OF"
set -g allow-passthrough on
'';
target = ".tmux.conf";
};
}
📑neovim
xieby1's neovim config!
See default.nix
DrawIt: ascii art drawing
{ config, pkgs, stdenv, lib, ... }:
let
DrawIt = pkgs.vimUtils.buildVimPlugin {
name = "DrawIt";
src = pkgs.fetchFromGitHub {
owner = "vim-scripts";
repo = "DrawIt";
rev = "master"; # I believe it wont update ^_*, so its safe
sha256 = "0yn985pj8dn0bzalwfc8ssx62m01307ic1ypymil311m4gzlfy60";
};
};
in {
programs.neovim = {
plugins = [
DrawIt
];
};
}
🎨My nvim color scheme
{ config, pkgs, stdenv, lib, ... }:
let
my-color-scheme = {
plugin = pkgs.vimPlugins.sonokai;
config = ''
nnoremap <leader>c :set termguicolors!<CR>
set termguicolors
let g:sonokai_transparent_background = 1
let g:sonokai_colors_override = {
\ 'black': ['#111215', '237'],
\ 'bg0': ['#22232a', '235'],
\ 'bg1': ['#33353f', '236'],
\ 'bg2': ['#444754', '236'],
\ 'bg3': ['#555869', '237'],
\ 'bg4': ['#666a7e', '237'],
\ 'grey': ['#a5a5a6', '246'],
\ 'grey_dim': ['#787879', '240'],
\}
" custom sonokai,
" see section "How to use custom colors" of `:h sonokai.vim`
function! s:sonokai_custom() abort
let l:palette = sonokai#get_palette('default', {})
call sonokai#highlight('StatusLine', l:palette.black, l:palette.fg, 'bold')
call sonokai#highlight('StatusLineNC', l:palette.black, l:palette.grey, 'bold')
endfunction
augroup SonokaiCustom
autocmd!
autocmd ColorScheme sonokai call s:sonokai_custom()
augroup END
colorscheme sonokai
'';
};
in {
programs.neovim = {
plugins = [
my-color-scheme
];
};
}
conform-nvim: formatter
TODO: replace my conform-nvim with nixpkgs's one.
{ config, pkgs, stdenv, lib, ... }:
let
my-conform-nvim = let
nvim_doc_tools = pkgs.fetchFromGitHub {
owner = "stevearc";
repo = "nvim_doc_tools";
rev = "2fe4503c704ac816efdbbbf70d0c070ed3052bba";
sha256 = "sha256-PtUMBHB+1IV8Q2L6pYKKvx7bliq63Z+2v8IDC5mvAeo=";
};
nvim-typecheck-action = pkgs.fetchFromGitHub {
owner = "stevearc";
repo = "nvim-typecheck-action";
rev = "0a5ddc13b800c50bac699edd443f494a089824cd";
sha256 = "sha256-Mzzt2A0WCeaeIDiCWgHii+RUQNlQssPxK5/LVaEgpbU=";
};
neodev_nvim = pkgs.fetchFromGitHub {
owner = "folke";
repo = "neodev.nvim";
rev = "627b5b543f4df551fcddb99c17a8e260c453400d";
sha256 = "sha256-S8/dUOcVPUeh54ZTELql/H5nW3DghpCtWzyxaPjZbCw=";
};
in {
plugin = pkgs.vimUtils.buildVimPlugin {
name = "conform.nvim";
src = pkgs.fetchFromGitHub {
owner = "stevearc";
repo = "conform.nvim";
rev = "a36c68d2cd551e49883ddb2492c178d915567f58";
sha256 = "sha256-aul/6sQZMljF3nc+WrRhVEObytu4wkoVyTM5HognK7E=";
};
buildInputs = with pkgs; [
python3Packages.pyparsing
python3
luajitPackages.luacheck
stylua
git
lua-language-server
];
preBuild = ''
sed -i 's/all: doc lint test/all: doc/g' Makefile
mkdir -p scripts/nvim_doc_tools
cp -r ${nvim_doc_tools}/* scripts/nvim_doc_tools/
# disable ShaDa
sed -i 's/nvim --headless/nvim --headless -i NONE/' scripts/nvim_doc_tools/util.py
mkdir -p scripts/nvim-typecheck-action
cp -r ${nvim-typecheck-action}/* scripts/nvim-typecheck-action/
patchShebangs scripts/nvim-typecheck-action/
mkdir -p scripts/nvim-typecheck-action/libs/neodev.nvim
cp -r ${neodev_nvim}/* scripts/nvim-typecheck-action/libs/neodev.nvim/
'';
};
type = "lua";
config = ''
require("conform").setup({
formatters_by_ft = {
nix = { "nixfmt" },
c = { "clang_format" },
cpp = { "clang_format" },
},
})
-- refer to https://github.com/stevearc/conform.nvim/blob/master/doc/recipes.md#format-command
vim.api.nvim_create_user_command("TrimWhitespace", function(args)
local range = nil
if args.count ~= -1 then
local end_line = vim.api.nvim_buf_get_lines(0, args.line2 - 1, args.line2, true)[1]
range = {
start = { args.line1, 0 },
["end"] = { args.line2, end_line:len() },
}
end
require("conform").format({ formatters = {"trim_whitespace"}, range = range })
end, { range = true })
vim.keymap.set({'n','v'}, '<leader>f', ':TrimWhitespace<CR>')
vim.api.nvim_create_user_command("Format", function(args)
local range = nil
if args.count ~= -1 then
local end_line = vim.api.nvim_buf_get_lines(0, args.line2 - 1, args.line2, true)[1]
range = {
start = { args.line1, 0 },
["end"] = { args.line2, end_line:len() },
}
end
require("conform").format({ async = true, lsp_fallback = true, range = range })
end, { range = true })
vim.keymap.set({'n','v'}, '<leader>F', ':Format<CR>')
'';
};
in {
programs.neovim = {
plugins = [
my-conform-nvim
];
extraPackages = with pkgs; [
nixfmt-rfc-style
clang-tools
];
};
}
{ config, pkgs, stdenv, lib, ... }:
let
opt = import ../../../opt.nix;
in {
Plugins with customizations:
imports = [
./nvim-metals
./conform-nvim.nix
./nvim-lspconfig.nix
./nvim-cmp.nix
./vim-mark.nix
./DrawIt.nix
./nvim-treesitter.nix
./nvim-config-local.nix
./leap-nvim.nix
./telescope-nvim.nix
./git-wip.nix
./vim-floaterm.nix
./vista-vim.nix
./vim-markdown.nix
./vim-hexokinase.nix
./gitsigns-nvim.nix
./color-scheme.nix
./hbac-nvim.nix
./winshift-nvim.nix
./smartyank-nvim.nix
./mini-nvim.nix
./vim-easy-align.nix
];
programs.bash.shellAliases.view = "nvim -R";
Set nvim as manpager.
see nvim :h :Man
.
nvim manpage huge mange is SLOW! E.g. man configuration.nix.
programs.bash.shellAliases.nman = "env MANPAGER='nvim +Man!' man";
programs.neovim = {
enable = true;
viAlias = true;
vimAlias = true;
vimdiffAlias = true;
Plugins without customizations:
plugins = with pkgs.vimPlugins; [
vim-smoothie
vim-fugitive
vim-nix
vim-markdown-toc
vim-commentary
tabular
vim-plugin-AnsiEsc
] ++ (lib.optional opt.isGui markdown-preview-nvim);
Vim config
extraConfig = ''
" vim
"" Highlight searches
set hlsearch
nnoremap <F3> :nohlsearch<CR>
"" Show line number
set number
"" Always show the signcolumn, otherwise it would shift the text each time
"" diagnostics appear/become resolved
set signcolumn=number
"" indent
"set smartindent " not good, indentation in empty line cannot be auto removed
""" show existing tab with 4 spaces width
set tabstop=4
""" when indenting with '>', use 4 spaces width
set shiftwidth=4
""" specicial indent
au FileType markdown setlocal shiftwidth=2 tabstop=2
""" On pressing tab, insert 4 spaces
set expandtab
""" line wrap with ident
set breakindent
"""" horizontally scroll 4 characters
nnoremap z<left> 4zh
nnoremap z<right> 4zl
"" tags support, ';' means upward search, refering to http://vimdoc.sourceforge.net/htmldoc/editing.html#file-searching
set tags=./tags;
"" Fold
""" fold text to be the first and last line
""" refer to sbernheim4's reply at
""" https://github.com/nvim-treesitter/nvim-treesitter/pull/390
function! GetSpaces(foldLevel)
if &expandtab == 1
" Indenting with spaces
let str = repeat(" ", a:foldLevel / (&shiftwidth + 1) - 1)
return str
elseif &expandtab == 0
" Indenting with tabs
return repeat(" ", indent(v:foldstart) - (indent(v:foldstart) / &shiftwidth))
endif
endfunction
function! MyFoldText()
let startLineText = getline(v:foldstart)
let endLineText = trim(getline(v:foldend))
let indentation = GetSpaces(foldlevel("."))
let spaces = repeat(" ", 200)
let str = indentation . startLineText . " …… " . endLineText . spaces
return str
endfunction
"" toggle foldmethod between manual and indent
set foldmethod=indent
:function ToggleFoldmethod()
: if (&foldmethod == "manual")
: set foldmethod=indent
: else
: set foldmethod=manual
: endif
:endfunction
nnoremap <Leader>z :call ToggleFoldmethod()<CR>:echo &foldmethod<CR>
"" Custom display for text when folding
set foldtext=MyFoldText()
""" Set the foldlevel to a high setting,
""" files are always loaded with opened folds.
set foldlevel=20
""" mouse support " select by pressing shift key!
set mouse=a
""" matchit.vim " :h matchit-install
packadd! matchit
"" Preview
nnoremap <leader>[ :pc<CR>
"" highlight unwanted whitespace
set list
set listchars=tab:>-,trail:-
"" syntax
syntax on
"" backspace
set backspace=indent,eol,start
"" wrap line
""" https://stackoverflow.com/questions/248102/is-there-any-command-to-toggle-enable-auto-text-wrapping
:function ToggleWrap()
: if (&wrap == 1)
: set nowrap
: else
: set wrap
: endif
:endfunction
nnoremap <F9> :call ToggleWrap()<CR>
set updatetime=400
"" highlight current line
set cursorlineopt=number
augroup CursorLine
au!
au VimEnter,WinEnter,BufWinEnter * setlocal cursorline
au WinLeave * setlocal nocursorline
augroup END
" filetype
augroup filetype
" detect LLVM IR file
au! BufRead,BufNewFile *.ll set filetype=llvm
" cpp " from gem5
au! BufRead,BufNewFile *.hh.inc,*.cc.inc set filetype=cpp
augroup END
" set terminal title
"" https://stackoverflow.com/questions/15123477/tmux-tabs-with-name-of-file-open-in-vim
autocmd BufEnter * let &titlestring = "" . expand("%:t")
set title
nnoremap <F10> :echo "hi<" . synIDattr(synID(line("."),col("."),1),"name") . '> trans<'
\ . synIDattr(synID(line("."),col("."),0),"name") . "> lo<"
\ . synIDattr(synIDtrans(synID(line("."),col("."),1)),"name") . ">"<CR>
" highlight
augroup HiglightTODO
autocmd!
autocmd WinEnter,VimEnter * :silent! call matchadd('Todo', 'TODO', -1)
augroup END
" wildmenu
" see: https://github.com/neovim/neovim/pull/11001
cnoremap <expr> <Up> pumvisible() ? "\<Left>" : "\<Up>"
cnoremap <expr> <Down> pumvisible() ? "\<Right>" : "\<Down>"
cnoremap <expr> <Left> pumvisible() ? "\<Up>" : "\<Left>"
cnoremap <expr> <Right> pumvisible() ? "\<Down>" : "\<Right>"
'';
};
}
git-wip: auto wip branch
{ config, pkgs, stdenv, lib, ... }:
let
git-wip = pkgs.vimUtils.buildVimPlugin {
name = "git-wip";
src = pkgs.fetchFromGitHub {
owner = "bartman";
repo = "git-wip";
rev = "1c095e93539261370ae811ebf47b8d3fe9166869";
hash = "sha256-rjvg6sTOuUM3ltD3DuJqgBEDImLrsfdnK52qxCbu8vo=";
};
preInstall = "cd vim";
};
in {
programs.neovim = {
plugins = [
git-wip
];
};
}
gitsigns-nvim: git support
{ config, pkgs, stdenv, lib, ... }:
let
my-gitsigns-nvim = {
plugin = pkgs.vimPlugins.gitsigns-nvim;
type = "lua";
config = ''
require('gitsigns').setup {
signcolumn = false,
numhl = true,
linehl = true,
current_line_blame = true,
-- keymaps
on_attach = function(bufnr)
local gs = package.loaded.gitsigns
local function map(mode, l, r, opts)
opts = opts or {}
opts.buffer = bufnr
vim.keymap.set(mode, l, r, opts)
end
-- Navigation
map('n', ']c', function()
if vim.wo.diff then return ']c' end
vim.schedule(function() gs.next_hunk() end)
return '<Ignore>'
end, {expr=true})
map('n', '[c', function()
if vim.wo.diff then return '[c' end
vim.schedule(function() gs.prev_hunk() end)
return '<Ignore>'
end, {expr=true})
-- Actions
map({'n', 'v'}, '<leader>hs', ':Gitsigns stage_hunk<CR>')
map({'n', 'v'}, '<leader>hr', ':Gitsigns reset_hunk<CR>')
map('n', '<leader>hS', gs.stage_buffer)
map('n', '<leader>hu', gs.undo_stage_hunk)
map('n', '<leader>hR', gs.reset_buffer)
map('n', '<leader>hp', gs.preview_hunk)
map('n', '<leader>hb', function() gs.blame_line{full=true} end)
map('n', '<leader>tb', gs.toggle_current_line_blame)
map('n', '<leader>hd', gs.diffthis)
map('n', '<leader>hD', function() gs.diffthis('~') end)
map('n', '<leader>td', gs.toggle_deleted)
-- Text object
map({'o', 'x'}, 'ih', ':<C-U>Gitsigns select_hunk<CR>')
end
}
'';
};
in {
programs.neovim = {
plugins = [
my-gitsigns-nvim
];
};
}
hbac-nvim: auto close buffer
{ config, pkgs, stdenv, lib, ... }:
let
my-hbac = {
plugin = pkgs.vimUtils.buildVimPlugin {
name = "hbac.nvim";
src = pkgs.fetchFromGitHub {
owner = "axkirillov";
repo = "hbac.nvim";
rev = "e2e8333aa56ef43a577ac3a2a2e87bdf2f0d4cbb";
hash = "sha256-7+e+p+0zMHPJjpnKNkL7QQHZJGQ1DFZ6fsofcsVNXaY=";
};
};
type = "lua";
config = ''
require("hbac").setup({
autoclose = true, -- set autoclose to false if you want to close manually
threshold = 10, -- hbac will start closing unedited buffers once that number is reached
close_command = function(bufnr)
vim.api.nvim_buf_delete(bufnr, {})
end,
close_buffers_with_windows = false, -- hbac will close buffers with associated windows if this option is `true`
telescope = {
-- See #telescope-configuration below
},
})
'';
};
in {
programs.neovim = {
plugins = [
my-hbac
];
};
}
{ config, pkgs, stdenv, lib, ... }:
let
my-leap-nvim = {
plugin = pkgs.vimPlugins.leap-nvim;
type = "lua";
config = ''
require('leap').create_default_mappings()
'';
};
in {
programs.neovim = {
plugins = [
my-leap-nvim
];
};
}
mini-nvim: a nvim distro
mini-nvim is wonderful nvim plugin! I found it due to below link: indent-blankline.nvim is too complex. However, it does not support basic functionality like highlight current indentation See: https://github.com/lukas-reineke/indent-blankline.nvim/issues/649
{ config, pkgs, stdenv, lib, ... }:
let
my-mini-nvim = {
plugin = pkgs.vimPlugins.mini-nvim;
type = "lua";
config = ''
require('mini.indentscope').setup{
options = {
try_as_border = true,
},
}
-- mini.animate looks promising, and can totally replace vim-smoothie
-- However, bugs seem exist:
-- * touchpad scroll become slow
-- * background color blinks when create window
-- * background color broken after q::q
-- require('mini.animate').setup()
'';
};
in {
programs.neovim = {
plugins = [
my-mini-nvim
];
};
}
nvim-cmp: completion
{ config, pkgs, stdenv, lib, ... }:
let
my-nvim-cmp = {
plugin = pkgs.vimPlugins.nvim-cmp;
type = "lua";
config = ''
local cmp = require'cmp'
cmp.setup({
preselect = cmp.PreselectMode.None,
snippet = {
-- REQUIRED - you must specify a snippet engine
expand = function(args)
require('luasnip').lsp_expand(args.body) -- For `luasnip` users.
end,
},
mapping = cmp.mapping.preset.insert({
['<C-u>'] = cmp.mapping.scroll_docs(-4), -- Up
['<C-d>'] = cmp.mapping.scroll_docs(4), -- Down
-- C-b (back) C-f (forward) for snippet placeholder navigation.
['<C-Space>'] = cmp.mapping.complete(),
-- https://github.com/hrsh7th/nvim-cmp/issues/1753
-- The "Safely select entries with <CR>" example from wiki does not work correctly in command mode
["<CR>"] = cmp.mapping({
i = function(fallback)
if cmp.visible() and cmp.get_active_entry() then
cmp.confirm({ behavior = cmp.ConfirmBehavior.Replace, select = false })
else
fallback()
end
end,
s = cmp.mapping.confirm({ select = true }),
c = cmp.mapping.confirm({ behavior = cmp.ConfirmBehavior.Replace, select = true }),
}),
['<Tab>'] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_next_item()
else
fallback()
end
end, { 'i', 's' }),
['<S-Tab>'] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_prev_item()
else
fallback()
end
end, { 'i', 's' }),
}),
sources = cmp.config.sources({{
name = 'nvim_lsp',
}}, {{
name = 'luasnip',
}}, {{
name = 'buffer',
option = {
-- completion using words from visible buffers
get_bufnrs = function()
local bufs = {}
for _, win in ipairs(vim.api.nvim_list_wins()) do
bufs[vim.api.nvim_win_get_buf(win)] = true
end
return vim.tbl_keys(bufs)
end
},
}}, {{
name = 'path',
'' + pkgs.lib.optionalString (builtins.currentSystem=="x86_64-linux") ''
}}, {{
name = 'cmp_tabnine',
'' + ''
}})
})
'';
};
my-cmp-tabnine = {
plugin = pkgs.vimPlugins.cmp-tabnine;
type = "lua";
config = ''
local tabnine = require('cmp_tabnine.config')
tabnine:setup({
max_lines = 1000,
max_num_results = 20,
sort = true,
run_on_every_keystroke = true,
snippet_placeholder = '..',
ignored_file_types = {
-- default is not to ignore
-- uncomment to ignore in lua:
-- lua = true
},
show_prediction_strength = false
})
'';
};
in {
programs.neovim = {
plugins = with pkgs.vimPlugins; [
my-nvim-cmp
cmp-nvim-lsp
cmp-buffer
cmp-path
luasnip
cmp_luasnip
] ++ pkgs.lib.optional (builtins.currentSystem == "x86_64-linux") my-cmp-tabnine;
};
}
nvim-config-local: load local vim config
# TODO: use native neovim local local config ability.
{ config, pkgs, stdenv, lib, ... }:
let
my-nvim-config-local = {
plugin = pkgs.vimUtils.buildVimPlugin {
name = "nvim-config-local";
src = pkgs.fetchFromGitHub {
owner = "klen";
repo = "nvim-config-local";
rev = "af59d6344e555917209f7304709bbff7cea9b5cc";
sha256 = "1wg6g4rqpj12sjj0g1qxqgcpkzr7x82lk90lf6qczim97r3lj9hy";
};
};
config = ''
lua << EOF
require('config-local').setup {
lookup_parents = true,
silent = true,
}
EOF
augroup config-local
autocmd BufEnter * nested lua require'config-local'.source()
augroup END
'';
};
in {
programs.neovim = {
plugins = [
my-nvim-config-local
];
};
}
nvim-lspconfig
{ config, pkgs, stdenv, lib, ... }:
let
my-nvim-lspconfig = {
plugin = pkgs.vimPlugins.nvim-lspconfig;
type = "lua";
config =
Global mappings.
''
-- See `:help vim.diagnostic.*` for documentation on any of the below functions
vim.keymap.set('n', '<space>e', vim.diagnostic.open_float)
vim.keymap.set('n', '[d', vim.diagnostic.goto_prev)
vim.keymap.set('n', ']d', vim.diagnostic.goto_next)
vim.keymap.set('n', '<space>q', vim.diagnostic.setloclist)
-- Use LspAttach autocommand to only map the following keys
-- after the language server attaches to the current buffer
vim.api.nvim_create_autocmd('LspAttach', {
group = vim.api.nvim_create_augroup('UserLspConfig', {}),
callback = function(ev)
-- Enable completion triggered by <c-x><c-o>
vim.bo[ev.buf].omnifunc = 'v:lua.vim.lsp.omnifunc'
-- Buffer local mappings.
-- See `:help vim.lsp.*` for documentation on any of the below functions
local opts = { buffer = ev.buf }
vim.keymap.set('n', 'gD', vim.lsp.buf.declaration, opts)
vim.keymap.set('n', 'gd', vim.lsp.buf.definition, opts)
vim.keymap.set('n', 'gr', vim.lsp.buf.references, opts)
vim.keymap.set('n', 'gi', vim.lsp.buf.implementation, opts)
vim.keymap.set('n', 'K', vim.lsp.buf.hover, opts)
vim.keymap.set('n', '<C-k>', vim.lsp.buf.signature_help, opts)
vim.keymap.set('n', '<space>wa', vim.lsp.buf.add_workspace_folder, opts)
vim.keymap.set('n', '<space>wr', vim.lsp.buf.remove_workspace_folder, opts)
vim.keymap.set('n', '<space>wl', function() print(vim.inspect(vim.lsp.buf.list_workspace_folders())) end, opts)
vim.keymap.set('n', '<space>D', vim.lsp.buf.type_definition, opts)
vim.keymap.set('n', '<space>rn', vim.lsp.buf.rename, opts)
vim.keymap.set({ 'n', 'v' }, '<space>ca', vim.lsp.buf.code_action, opts)
vim.keymap.set('n', '<space>f', function() vim.lsp.buf.format { async = true } end, opts)
end,
})
''
Text
+ ''
local paths = {
-- vim.fn.stdpath("config") .. "/spell/ltex.dictionary.en-US.txt",
vim.fn.expand("%:p:h") .. "/.ltexdict",
}
local words = {}
for _, path in ipairs(paths) do
local f = io.open(path)
if f then
for word in f:lines() do
table.insert(words, word)
end
f:close()
end
end
require('lspconfig').ltex.setup{
settings = {
ltex = {
-- Supported languages:
-- https://valentjn.github.io/ltex/settings.html#ltexlanguage
-- https://valentjn.github.io/ltex/supported-languages.html#code-languages
language = "en-US", -- "zh-CN" | "en-US",
filetypes = { "bib", "gitcommit", "markdown", "org", "plaintex", "rst", "rnoweb", "tex", "pandoc" },
dictionary = {
['en-GB'] = words,
},
},
},
}
''
C/C++
Why use clangd instead of ccls?
I encountered the problem below, when view https://github.com/xieby1/openc910 smart_run/logical/tb/sim_main1.cpp
LSP[ccls]: Error NO_RESULT_CALLBACK_FOUND: {
error = {
code = -32603,
message = "failed to index /home/xieby1/Codes/openc910/smart_run/work/fputc.c"
},
id = 1,
jsonrpc = "2.0"
}
After some searching, I found
GitHub: neovim: issue: lsp: NO_RESULT_CALLBACK_FOUND with ccls, rust-analyzer #15844
sapphire-arches found:
Something is causing the r-a LSP to send two replies with the same ID, see the attached log: lsp_debug.log
It would be nice for the neovim LSP to handle this more gracefully (not filling my screen with garbage and taking focus), but I do think the bug is in R-A here? The problem seems to be related to editor.action.triggerParameterHints?
No one try to fix the two-replies problem in ccls. However, nimaipatel recommanded clangd_extensions.
+ ''
require('lspconfig').clangd.setup{
filetypes = { "c", "cc", "cpp", "c++", "objc", "objcpp", "cuda", "proto" }
}
require("clangd_extensions.inlay_hints").setup_autocmd()
require("clangd_extensions.inlay_hints").set_inlay_hints()
''
Nix
+ ''
require('lspconfig').nixd.setup{}
''
Html
+ ''
require('lspconfig').html.setup{}
''
Python
+ ''
require('lspconfig').pyright.setup{}
''
Lua
+ ''
require('lspconfig').lua_ls.setup{}
''
Auto completion
+ ''
-- Add additional capabilities supported by nvim-cmp
local capabilities = require("cmp_nvim_lsp").default_capabilities()
-- Enable some language servers with the additional completion capabilities offered by nvim-cmp
local servers = {
'ltex',
'clangd',
'nixd',
'html',
'pyright',
'lua_ls',
}
for _, lsp in ipairs(servers) do
require('lspconfig')[lsp].setup {
-- on_attach = my_custom_on_attach,
capabilities = capabilities,
}
end
'';
};
Setting up my nvim-lspconfig
in {
programs.neovim = {
plugins = [
my-nvim-lspconfig
pkgs.vimPlugins.clangd_extensions-nvim
];
extraPackages = with pkgs; [
clang-tools
ltex-ls
nixd
vscode-langservers-extracted # html
pyright
lua-language-server
];
};
}
nvim-metals: Scala LSP
The JRE proxy need subtle configuration.
{ config, pkgs, ... }:
let
opt = import ../../../../opt.nix;
jre_with_proxy = pkgs.callPackage ./jre_with_proxy.nix {
jre = pkgs.openjdk_headless;
proxyHost = "127.0.0.1";
proxyPort = toString opt.proxyPort;
};
my-nvim-metals = {
plugin = pkgs.vimPlugins.nvim-metals;
type = "lua";
config = ''
-- lspconfig.metals.setup{}
local metals_config = require("metals").bare_config()
metals_config.find_root_dir_max_project_nesting = 2
metals_config.root_patterns = {
"build.sbt",
"build.sc",
".git",
}
metals_config.settings = {
showImplicitArguments = true,
excludedPackages = { "akka.actor.typed.javadsl", "com.github.swagger.akka.javadsl" },
serverProperties = {
"-Dhttps.proxyHost=127.0.0.1",
"-Dhttps.proxyPort=${toString opt.proxyPort}",
"-Dhttp.proxyHost=127.0.0.1",
"-Dhttp.proxyPort=${toString opt.proxyPort}",
},
-- see `:h metalsBinaryPath`, "Another setting for you crazy Nix kids." Hahaha!
metalsBinaryPath = "${pkgs.metals.override {jre = jre_with_proxy;}}/bin/metals",
javaHome = "${jre_with_proxy}",
showImplicitArguments = true,
showImplicitConversionsAndClasses = true,
showInferredType = ture,
}
metals_config.capabilities = require("cmp_nvim_lsp").default_capabilities()
-- Autocmd that will actually be in charging of starting the whole thing
local nvim_metals_group = vim.api.nvim_create_augroup("nvim-metals", { clear = true })
vim.api.nvim_create_autocmd("FileType", {
group = nvim_metals_group,
pattern = { "scala", "sbt" },
callback = function()
require("metals").initialize_or_attach(metals_config)
end,
})
'';
};
in {
programs.neovim = {
plugins = [
my-nvim-metals
];
extraPackages = [
(pkgs.coursier.override {
jre = jre_with_proxy;
})
];
};
# nvim-metals proxy for bloop
home.file.jvmopts = {
text = ''
-Dhttps.proxyHost=127.0.0.1
-Dhttps.proxyPort=${toString opt.proxyPort}
-Dhttp.proxyHost=127.0.0.1
-Dhttp.proxyPort=${toString opt.proxyPort}
'';
target = ".bloop/.jvmopts";
};
}
JRE with Proxy
Let JRE aware of proxy by default. This package can be used standalone, while my main usage is for nvim-metals lsp. Without proxy, the scala package update make me headached.
For usage example, see my nvim-metals config
{ stdenv
, writeShellScript
, jre
, proxyHost
, proxyPort
}: let
java_with_proxy_sh = writeShellScript "java" ''
${jre}/bin/java -Dhttp.proxyHost=${proxyHost} -Dhttp.proxyPort=${proxyPort} -Dhttps.proxyHost=${proxyHost} -Dhttps.proxyPort=${proxyPort} "$@"
'';
in builtins.derivation rec {
name = "jre_with_proxy";
system = builtins.currentSystem;
builder = writeShellScript "${name}-builder" ''
source ${stdenv}/setup
mkdir -p $out
for dir in ${jre}/*; do
ln -s $dir $out/
done
rm $out/bin
mkdir -p $out/bin
for file in ${jre}/lib/openjdk/bin/*; do
ln -s $file $out/bin/
done
rm $out/bin/java
ln -s ${java_with_proxy_sh} $out/bin/java
'';
}
nvim-treesitter: languages parsing
{ config, pkgs, stdenv, lib, ... }:
let
my-nvim-treesitter = {
# Available languages see:
# https://github.com/nvim-treesitter/nvim-treesitter
# see `pkgs.tree-sitter.builtGrammars.`
# with `tree-sitter-` prefix and `-grammar` suffix removed
plugin = pkgs.vimPlugins.nvim-treesitter.withPlugins (p: with p; [
c
cpp
python
markdown
lua
]);
type = "lua";
config = ''
require 'nvim-treesitter.configs'.setup {
-- TODO: https://github.com/NixOS/nixpkgs/issues/189838
-- ensure_installed = {"c", "cpp", "python", "markdown"},
ensure_installed = {},
sync_install = false,
highlight = {
enable = true,
additional_vim_regex_highlighting = false,
disable = {
"nix",
},
},
}
'';
};
in {
programs.neovim = {
plugins = [
my-nvim-treesitter
];
};
}
smartyank-nvim: smart yank to clipboard
{ config, pkgs, stdenv, lib, ... }:
let
my-smartyank-nvim = {
plugin = pkgs.vimPlugins.smartyank-nvim;
type = "lua";
config = ''
require('smartyank').setup {
highlight = {
enabled = false, -- not enable highlight yanked text
},
validate_yank = function() return vim.v.operator == '"+y' end,
}
'';
};
in {
programs.neovim = {
plugins = [
my-smartyank-nvim
];
};
}
telescope-nvim
{ config, pkgs, stdenv, lib, ... }:
let
my-telescope-nvim = {
plugin = pkgs.vimPlugins.telescope-nvim;
config = ''
" search relative to file
"" https://github.com/nvim-telescope/telescope.nvim/pull/902
nnoremap ff <cmd>lua require('telescope.builtin').find_files({cwd=require'telescope.utils'.buffer_dir()})<cr>
nnoremap fg <cmd>lua require('telescope.builtin').live_grep({cwd=require'telescope.utils'.buffer_dir()})<cr>
nnoremap fF <cmd>lua require('telescope.builtin').find_files()<cr>
nnoremap fG <cmd>lua require('telescope.builtin').live_grep()<cr>
nnoremap fb <cmd>lua require('telescope.builtin').buffers()<cr>
nnoremap fh <cmd>lua require('telescope.builtin').help_tags()<cr>
nnoremap ft <cmd>lua require('telescope.builtin').treesitter()<cr>
nnoremap fc <cmd>lua require('telescope.builtin').command_history()<cr>
nnoremap fC <cmd>lua require('telescope.builtin').commands()<cr>
'';
};
my-telescope-fzf-native-nvim = {
plugin = pkgs.vimPlugins.telescope-fzf-native-nvim;
type = "lua";
config = ''
require('telescope').setup {
extensions = {fzf = {}},
defaults = {
layout_strategy = 'vertical'
}
}
require('telescope').load_extension('fzf')
'';
};
in {
programs.neovim = {
plugins = [
my-telescope-nvim
my-telescope-fzf-native-nvim
pkgs.vimPlugins.plenary-nvim
];
extraPackages = with pkgs; [
ripgrep
];
};
}
vim-easy-align: A simple, easy-to-use Vim alignment plugin.
{ config, pkgs, stdenv, lib, ... }:
let
my-vim-easy-align = {
plugin = pkgs.vimPlugins.vim-easy-align;
config = ''
" Start interactive EasyAlign in visual mode (e.g. vipga)
xmap ga <Plug>(EasyAlign)
" Start interactive EasyAlign for a motion/text object (e.g. gaip)
nmap ga <Plug>(EasyAlign)
let g:easy_align_delimiters = {
\ '>': { 'pattern': '>>\|=>\|>' },
\ '/': {
\ 'pattern': '//\+\|/\*\|\*/',
\ 'delimiter_align': 'l',
\ 'ignore_groups': ['!Comment'] },
\ ']': {
\ 'pattern': '[\]]',
\ 'left_margin': 0,
\ 'right_margin': 0,
\ 'stick_to_left': 0
\ },
\ '[': {
\ 'pattern': '[\[]',
\ 'left_margin': 0,
\ 'right_margin': 0,
\ 'stick_to_left': 0
\ },
\ ')': {
\ 'pattern': '[)]',
\ 'left_margin': 0,
\ 'right_margin': 0,
\ 'stick_to_left': 0
\ },
\ '(': {
\ 'pattern': '[(]',
\ 'left_margin': 0,
\ 'right_margin': 0,
\ 'stick_to_left': 0
\ },
\ }
'';
};
in {
programs.neovim = {
plugins = [
my-vim-easy-align
];
};
}
vim-floaterm: floating terminal
{ config, pkgs, stdenv, lib, ... }:
let
my-vim-floaterm = {
plugin = pkgs.vimPlugins.vim-floaterm;
config = ''
nmap <Leader>t :FloatermNew --cwd=<buffer><CR>
" let g:floaterm_keymap_new = '<Leader>t'
let g:floaterm_width = 0.8
let g:floaterm_height = 0.8
" Set floaterm window's background
hi Floaterm guibg=black
'';
};
in {
programs.neovim = {
plugins = [
my-vim-floaterm
];
};
}
vim-hexokinase: display colors
highlight color code
TLDR: vim-hexokinase isn't perfect but works.
It need works in termguicolors
mode.
It is better to choose a color scheme which is visualized in gui mode.
And it is very tricky to setting colors in termguicolors
& notermguicolors
the same, which is insane.
It would be convenient, if color code can be visualised in editor, especially in web programming. I found two candidates plugins to achieve this goal, vim-css-color, vim-hexokinase.
Vim-css-color is not compatible with tree-sitter, due to regex based highlight. See Github Issue: Neovim tree sitter support for details. Vim-css-color sometimes cannot render same text color. I need to scroll my vim viewport, then it may render color correctly.
Vim-hexokinase is good, but must depends on termguicolors
is turned on.
termguicolors
will enable 24-bit RGB color,
while originally vim uses Base16 color.
The result is the color theme you familiar with will be changed.
Here is the visual comparison between vim-css-color and vim-hexokinase. I copy these text as html from my vim.
vcc | vcc tgc | vh tgc |
---|---|---|
#ff0000 | #ff0000 | #ff0000 |
#ff1111 | #ff1111 | #ff1111 |
#ff2222 | #ff2222 | #ff2222 |
#ff3333 | #ff3333 | #ff3333 |
#ff4444 | #ff4444 | #ff4444 |
#ff5555 | #ff5555 | #ff5555 |
#ff6666 | #ff6666 | #ff6666 |
#ff7777 | #ff7777 | #ff7777 |
#ff8888 | #ff8888 | #ff8888 |
#ff9999 | #ff9999 | #ff9999 |
#ffaaaa | #ffaaaa | #ffaaaa |
#ffbbbb | #ffbbbb | #ffbbbb |
#ffcccc | #ffcccc | #ffcccc |
#ffdddd | #ffdddd | #ffdddd |
#ffeeee | #ffeeee | #ffeeee |
#ffffff | #ffffff | #ffffff |
#000000 | #000000 | #000000 |
#111111 | #111111 | #111111 |
#222222 | #222222 | #222222 |
#333333 | #333333 | #333333 |
#444444 | #444444 | #444444 |
#555555 | #555555 | #555555 |
#666666 | #666666 | #666666 |
#777777 | #777777 | #777777 |
#888888 | #888888 | #888888 |
#999999 | #999999 | #999999 |
#aaaaaa | #aaaaaa | #aaaaaa |
#bbbbbb | #bbbbbb | #bbbbbb |
#cccccc | #cccccc | #cccccc |
#dddddd | #dddddd | #dddddd |
#eeeeee | #eeeeee | #eeeeee |
#ffffff | #ffffff | #ffffff |
Vim-css-color with out termguicolors
cannot display color correctly (or say precisely),
if you dont believe your eye, see the source code of this page.
I think vim-hexokinase with a termguicolors
toggle is a acceptable compromise.
Toggle termguicolors
by :set termguicolors!
.
I personally prefer to assign <leader>c
to toggle termguicolors
.
cterm & gui
TLDR: I still haven't find a elegant solution to keep termguicolors
and notermguicolors
visually same.
neovim has 2 color schemes cterm & gui,
see :h cterm-colors
& :h gui-colors
.
Default sntax colors are different in these two schemes.
For example, :verbose highlight Comment
returns
Comment xxx ctermfg=14 guifg=#80a0ff
Last set from /nix/store/pr1pwjjsm3k45rwi3w0xh2296rpymjlz-neovim-unwrapped-0.5.1/share/nvim/runtime/syntax/syncolor.vim
which means ctermfg uses the 14th color in ANSI colors,
while guifg use a hex color code.
The detailed setting is located in ${VIMRUNTIME}/syntax/syncolor.vim
.
I create a new syncolor.vim based the default one, and modify the all ctermfg and guifg to same color name, like below. The colors in two schemes are still different.
if !exists("syntax_cmd") || syntax_cmd == "on"
" ":syntax on" works like in Vim 5.7: set colors but keep links
command -nargs=* SynColor hi <args>
command -nargs=* SynLink hi link <args>
else
if syntax_cmd == "enable"
" ":syntax enable" keeps any existing colors
command -nargs=* SynColor hi def <args>
command -nargs=* SynLink hi def link <args>
elseif syntax_cmd == "reset"
" ":syntax reset" resets all colors to the default
command -nargs=* SynColor hi <args>
command -nargs=* SynLink hi! link <args>
else
" User defined syncolor file has already set the colors.
finish
endif
endif
" Many terminals can only use six different colors (plus black and white).
" Therefore the number of colors used is kept low. It doesn't look nice with
" too many colors anyway.
" Careful with "cterm=bold", it changes the color to bright for some terminals.
" There are two sets of defaults: for a dark and a light background.
if &background == "dark"
SynColor Comment term=bold cterm=NONE ctermfg=Cyan ctermbg=NONE gui=NONE guifg=Cyan guibg=NONE
SynColor Constant term=underline cterm=NONE ctermfg=Magenta ctermbg=NONE gui=NONE guifg=Magenta guibg=NONE
SynColor Special term=bold cterm=NONE ctermfg=LightRed ctermbg=NONE gui=NONE guifg=LightRed guibg=NONE
SynColor Identifier term=underline cterm=bold ctermfg=Cyan ctermbg=NONE gui=bold guifg=Cyan guibg=NONE
SynColor Statement term=bold cterm=NONE ctermfg=Yellow ctermbg=NONE gui=NONE guifg=Yellow guibg=NONE
SynColor PreProc term=underline cterm=NONE ctermfg=LightBlue ctermbg=NONE gui=NONE guifg=LightBlue guibg=NONE
SynColor Type term=underline cterm=NONE ctermfg=LightGreen ctermbg=NONE gui=NONE guifg=LightGreen guibg=NONE
SynColor Underlined term=underline cterm=underline ctermfg=LightBlue gui=underline guifg=LightBlue
SynColor Ignore term=NONE cterm=NONE ctermfg=black ctermbg=NONE gui=NONE guifg=black guibg=NONE
else
SynColor Comment term=bold cterm=NONE ctermfg=DarkBlue ctermbg=NONE gui=NONE guifg=DarkBlue guibg=NONE
SynColor Constant term=underline cterm=NONE ctermfg=DarkRed ctermbg=NONE gui=NONE guifg=DarkBlue guibg=NONE
SynColor Special term=bold cterm=NONE ctermfg=DarkMagenta ctermbg=NONE gui=NONE guifg=DarkMagenta guibg=NONE
SynColor Identifier term=underline cterm=NONE ctermfg=DarkCyan ctermbg=NONE gui=NONE guifg=DarkCyan guibg=NONE
SynColor Statement term=bold cterm=NONE ctermfg=Brown ctermbg=NONE gui=bold guifg=Brown guibg=NONE
SynColor PreProc term=underline cterm=NONE ctermfg=DarkMagenta ctermbg=NONE gui=NONE guifg=DarkMagenta guibg=NONE
SynColor Type term=underline cterm=NONE ctermfg=DarkGreen ctermbg=NONE gui=NONE guifg=DarkGreen guibg=NONE
SynColor Underlined term=underline cterm=underline ctermfg=DarkMagenta gui=underline guifg=DarkMagenta
SynColor Ignore term=NONE cterm=NONE ctermfg=white ctermbg=NONE gui=NONE guifg=white guibg=NONE
endif
SynColor Error term=reverse cterm=NONE ctermfg=White ctermbg=Red gui=NONE guifg=White guibg=Red
SynColor Todo term=standout cterm=NONE ctermfg=Black ctermbg=Yellow gui=NONE guifg=Black guibg=Yellow
The Magenta is especially dazzling, and cannot change it by below tries.
Refers to Change Vim's terminal colors when termguicolors is set #2353, nvim-terminal-emulator-configuration,
let g:terminal_color_13 = '#AD7FA8' " Magenta
doesn't work.
Finally I choose to add a color-scheme manager, and choose a theme which has both cterm & gui color scheme.
{ config, pkgs, stdenv, lib, ... }:
let
my-vim-hexokinase = {
plugin = pkgs.vimPlugins.vim-hexokinase;
config = ''
let g:Hexokinase_highlighters = ['backgroundfull']
'';
};
in {
programs.neovim = {
plugins = [
my-vim-hexokinase
];
};
}
vim-mark: multi-color highlight
{ config, pkgs, stdenv, lib, ... }:
let
vim-ingo-library = pkgs.vimUtils.buildVimPlugin {
name = "vim-ingo-library";
src = pkgs.fetchFromGitHub {
owner = "inkarkat";
repo = "vim-ingo-library";
rev = "8ea0e934d725a0339f16375f248fbf1235ced5f6";
sha256 = "1rabyhayxswwh85lp4rzi2w1x1zbp5j0v025vsknzbqi0lqy32nk";
};
};
my-vim-mark = {
plugin = pkgs.vimUtils.buildVimPlugin {
name = "vim-mark";
src = pkgs.fetchFromGitHub {
owner = "inkarkat";
repo = "vim-mark";
rev = "7f90d80d0d7a0b3696f4dfa0f8639bba4906d037";
sha256 = "0n8r0ks58ixqv7y1afliabiqwi55nxsslwls7hni4583w1v1bbly";
};
};
config = ''
" clear highlight created by vim-mark
nnoremap <leader><F3> :MarkClear<CR>
" show all marks
nnoremap <leader>M :Marks<CR>
'';
};
in {
programs.neovim = {
plugins = [
my-vim-mark
vim-ingo-library
];
};
}
vim-markdown: md support
我主要使用这个插件的对齐表格的功能,:TableFormat
,超酷炫!
{ config, pkgs, stdenv, lib, ... }:
let
my-vim-markdown = {
plugin = pkgs.vimPlugins.vim-markdown;
config = ''
let g:vim_markdown_new_list_item_indent = 2
let g:vim_markdown_no_default_key_mappings = 1
'';
};
in {
programs.neovim = {
plugins = [
my-vim-markdown # format table
];
};
}
vista-vim: lsp symbols
{ config, pkgs, stdenv, lib, ... }:
let
my-vista-vim = {
plugin = pkgs.vimPlugins.vista-vim;
config = ''
let g:vista_default_executive = 'nvim_lsp'
'';
};
in {
programs.neovim = {
plugins = [
my-vista-vim
];
};
}
winshift-nvim: rearrange windows
{ config, pkgs, stdenv, lib, ... }:
let
my-winshift-nvim = {
plugin = pkgs.vimPlugins.winshift-nvim;
type = "lua";
config = ''
-- Lua
require("winshift").setup({
highlight_moving_win = true, -- Highlight the window being moved
focused_hl_group = "Visual", -- The highlight group used for the moving window
-- moving_win_options = {
-- -- These are local options applied to the moving window while it's
-- -- being moved. They are unset when you leave Win-Move mode.
-- wrap = true,
-- cursorline = false,
-- cursorcolumn = false,
-- colorcolumn = "",
-- },
keymaps = {
disable_defaults = false, -- Disable the default keymaps
win_move_mode = {
["h"] = "left",
["j"] = "down",
["k"] = "up",
["l"] = "right",
["H"] = "far_left",
["J"] = "far_down",
["K"] = "far_up",
["L"] = "far_right",
["<left>"] = "left",
["<down>"] = "down",
["<up>"] = "up",
["<right>"] = "right",
["<S-left>"] = "far_left",
["<S-down>"] = "far_down",
["<S-up>"] = "far_up",
["<S-right>"] = "far_right",
},
},
---A function that should prompt the user to select a window.
---
---The window picker is used to select a window while swapping windows with
---`:WinShift swap`.
---@return integer? winid # Either the selected window ID, or `nil` to
--- indicate that the user cancelled / gave an invalid selection.
window_picker = function()
return require("winshift.lib").pick_window({
-- A string of chars used as identifiers by the window picker.
picker_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890",
filter_rules = {
-- This table allows you to indicate to the window picker that a window
-- should be ignored if its buffer matches any of the following criteria.
cur_win = true, -- Filter out the current window
floats = true, -- Filter out floating windows
filetype = {}, -- List of ignored file types
buftype = {}, -- List of ignored buftypes
bufname = {}, -- List of vim regex patterns matching ignored buffer names
},
---A function used to filter the list of selectable windows.
---@param winids integer[] # The list of selectable window IDs.
---@return integer[] filtered # The filtered list of window IDs.
filter_func = nil,
})
end,
})
vim.keymap.set('n', '<C-W>m', '<Cmd>WinShift<CR>')
'';
};
in {
programs.neovim = {
plugins = [
my-winshift-nvim
];
};
}
{ config, pkgs, stdenv, lib, ... }:
let
opt = import ../opt.nix;
xelfviewer = pkgs.callPackage ./gui/xelfviewer.nix {};
in
{
imports = [
./gui/mime.nix
./gui/kdeconnect.nix
./gui/xdot.nix
./gui/firefox.nix
] ++ (lib.optionals (builtins.currentSystem=="x86_64-linux") [
./gui/rustdesk.nix
]) ++ (if !opt.isWSL2 then [
./gui/gnome.nix
./gui/terminal.nix
./gui/singleton_web_apps.nix
./gui/rofi.nix
] else [{ # install fonts for WSL
fonts.fontconfig.enable = true;
home.packages = with pkgs; [
noto-fonts-cjk-sans
noto-fonts-cjk-serif
noto-fonts-emoji
];
}]);
home.packages = with pkgs; [
libnotify
# browser
] ++ pkgs.lib.optionals (builtins.currentSystem=="x86_64-linux") [
google-chrome
microsoft-edge
] ++ [
# network
] ++ pkgs.lib.optionals (builtins.currentSystem=="x86_64-linux") [
feishu
(wechat-uos.override {
buildFHSEnv = args: buildFHSEnv (args // {
# bubble wrap wechat-uos's home directory
extraBwrapArgs = [
"--bind ${config.home.homeDirectory}/.local/share/wechat-uos /home"
"--chdir /home"
];
});
uosLicense = fetchurl {
url = "https://github.com/xddxdd/nur-packages/raw/master/pkgs/uncategorized/wechat-uos/license.tar.gz";
sha256 = "0sdx5mdybx4y489dhhc8505mjfajscggxvymlcpqzdd5q5wh0xjk";
};
})
# wine weixin waste too much memory, more than 4GB!!!
#(import ./gui/weixin.nix {})
nur.repos.linyinfeng.wemeet
nur.repos.xddxdd.dingtalk
# telegram desktop not provide aarch64 prebuilt
tdesktop
] ++ [
transmission-gtk
# text
#wpsoffice
libreoffice
meld
# TODO: use this after switching to wayland
#wl-clipboard
textsnatcher
# draw
drawio
#aseprite-unfree
inkscape
gimp
# viewer
] ++ pkgs.lib.optionals (builtins.currentSystem=="x86_64-linux") [
imhex
xelfviewer
] ++ [
vlc
] ++ pkgs.lib.optionals (builtins.currentSystem=="x86_64-linux") [
ghidra
] ++ [
# management
] ++ pkgs.lib.optionals (builtins.currentSystem=="x86_64-linux") [
zotero
] ++ [
barrier
keepassxc
# entertainment
antimicrox
# music
] ++ pkgs.lib.optionals (builtins.currentSystem=="x86_64-linux") [
spotify
];
xdg.mime.types = {
drawio = {
name = "draw-io";
type = "text/draw-io";
pattern = "*.drawio";
defaultApp = "drawio.desktop";
};
};
home.file.autostart_barrier = {
source = "${pkgs.barrier}/share/applications/barrier.desktop";
target = ".config/autostart/barrier.desktop";
};
}
安装deb包,以飞书为例
太长不看
- nix文件: https://github.com/xieby1/nix_config/blob/main/usr/gui/feishu.nix
- 使用方法:
home.packages = with pkgs; [ (callPackage ./feishu.nix {}) ];
参考nixpkgs/pkgs/applications/networking/instant-messengers/skypeforlinux/default.nix
测试环境
nix-build -E "with import
权限问题
nix-build遇到dpkg -x解压失败。 但是手动执行dpkg -x一切正常。
https://unix.stackexchange.com/questions/138188/easily-unpack-deb-edit-postinst-and-repack-deb
确认是权限问题的实验
是s权限的问题。 nix-build下不能添加s权限。 原因未知
复现方法
touch $out/miao
chmox +s $out/miao
ls -l $out/miao
解决方法,使用fakeroot.
补全库
使用ldd脚本,获取所有elf所需的库,挨个添加进rpath即可。
桌面
application/.desktop menu/.menu // 负责图标
{ config, pkgs, stdenv, lib, ... }:
{
programs.firefox = {
enable = true;
# If state version ≥ 19.09 then this should be a wrapped Firefox
package = pkgs.firefox.overrideAttrs (old: {
desktopItem = old.desktopItem.override {
exec = "env MOZ_USE_XINPUT2=1 firefox --name firefox %U";
};
});
profiles.xieby1 = {
# id is default 0, thus this profile is default
extensions = with pkgs.nur.repos.rycee.firefox-addons; [
# 😾😾😾 Chinese users cannot use ad block extensions
# https://discourse.mozilla.org/t/chinese-users-cant-use-ad-blocker-extensions/94823
ublock-origin
];
settings = {
# Automatically enable extensions
"extensions.autoDisableScopes" = 0;
};
};
};
}
Gnome in NixOS
插件
桌面快捷键
{ config, pkgs, stdenv, lib, ... }:
# gnome extensions and settings
# no need log out to reload extension: <alt>+F2 r
let
opt = import ../../opt.nix;
in{
home.packages = (with pkgs; [
gnome.gnome-sound-recorder
gnome.dconf-editor
gnome.devhelp
])
++ (with pkgs.gnomeExtensions; [
unite
clipboard-indicator
bing-wallpaper-changer
# random-wallpaper-wip-v3
gtile
pkgs.pkgsu.gnomeExtensions.hide-top-bar
dash-to-dock
always-show-titles-in-overview
customize-ibus
# replace system-monitor(-next) with vitals
# refers to https://github.com/mgalgs/gnome-shell-system-monitor-applet/issues/57
# vitals
system-monitor-next
]);
# Setting: `gsettings set <key(dot)> <value>`
# Getting: `dconf dump /<key(path)>`
dconf.settings = {
"org/gnome/shell" = {
disable-extension-version-validation = true;
## enabled gnome extensions
disable-user-extensions = false;
disabled-extensions = [];
enabled-extensions = [
"BingWallpaper@ineffable-gmail.com"
"clipboard-indicator@tudmotu.com"
"gTile@vibou"
"hidetopbar@mathieu.bidon.ca"
# "Vitals@CoreCoding.com"
"system-monitor-next@paradoxxx.zero.gmail.com"
"unite@hardpixel.eu"
"dash-to-dock@micxgx.gmail.com"
# "randomwallpaper@iflow.space"
"Always-Show-Titles-In-Overview@gmail.com"
"customize-ibus@hollowman.ml"
];
## dock icons
favorite-apps = [
"org.gnome.Nautilus.desktop"
"firefox.desktop"
"microsoft-edge.desktop"
"calendar.desktop"
"todo.desktop"
"spotify.desktop"
"google-chrome.desktop"
];
};
## extensions settings
# "org/gnome/shell/extensions/vitals" = {
# fixed-widths = true;
# hide-icons = true;
# hot-sensors = [
# "_processor_usage_"
# "_memory_usage_"
# "__network-rx_max__"
# "__network-tx_max__"
# ];
# show-fan = false;
# show-system = false;
# show-temperature = false;
# show-voltage = false;
# update-time = 2;
# };
"org/gnome/shell/extensions/system-monitor" = {
compact-display = true;
icon-display = false;
cpu-style = "digit";
memory-style = "digit";
net-style = "digit";
};
"org/gnome/shell/extensions/gtile" = {
animation=true;
global-presets=true;
grid-sizes="6x4,8x6";
preset-resize-1=["<Super>bracketleft"];
preset-resize-2=["<Super>bracketright"];
preset-resize-3=["<Super>period"];
preset-resize-4=["<Super>slash"];
preset-resize-5=["<Super>apostrophe"];
preset-resize-6=["<Super>semicolon"];
preset-resize-7=["<Super>comma"];
resize1="2x2 1:1 1:1";
resize2="2x2 2:1 2:1";
resize3="2x2 1:2 1:2";
resize4="2x2 2:2 2:2";
resize5="4x8 2:2 3:7";
resize6="1x2 1:1 1:1";
resize7="1x2 1:2 1:2";
show-icon=false;
};
"org/gnome/desktop/session" = {
idle-delay=lib.hm.gvariant.mkUint32 0; # never turn off screen
};
"org/gnome/settings-daemon/plugins/power" = {
ambient-enabled=false;
idle-dim=false;
power-button-action="nothing";
sleep-inactive-ac-timeout=3600;
sleep-inactive-ac-type="nothing";
sleep-inactive-battery-type="suspend";
};
"org/gnome/shell/extensions/hidetopbar" = {
mouse-sensitive = true;
enable-active-window=false;
enable-intellihide=true;
shortcut-delay = 0.0;
shortcut-keybind = ["<Super>h"];
};
"org/gnome/shell/extensions/unite" = {
app-menu-ellipsize-mode="end";
extend-left-box=false;
greyscale-tray-icons=false;
hide-app-menu-icon=false;
hide-dropdown-arrows=true;
hide-window-titlebars="always";
notifications-position="center";
reduce-panel-spacing=true;
show-window-buttons="always";
use-activities-text = false;
window-buttons-placement="last";
window-buttons-theme="materia";
restrict-to-primary-screen=false;
};
"org/gnome/shell/extensions/bingwallpaper" = {
market="zh-CN";
delete-previous=true;
download-folder="/tmp/pictures";
};
"org/gnome/shell/extensions/dash-to-dock" = {
click-action="focus-or-appspread";
};
"org/gnome/shell/extensions/space-iflow-randomwallpaper" = {
auto-fetch = true;
change-lock-screen = true;
hours = 8;
minutes = 29;
source = "genericJSON";
# source = "wallhaven";
};
"org/gnome/shell/extensions/space-iflow-randomwallpaper/genericJSON" = {
generic-json-request-url = "http://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1&mkt=zh-CN";
generic-json-response-path = "$.images[0].url";
generic-json-url-prefix = "http://www.bing.com";
};
"org/gnome/shell/extensions/space-iflow-randomwallpaper/wallhaven" ={
wallhaven-keyword="cardcaptor sakura";
};
# predefined keyboard shortcuts
"org/gnome/desktop/wm/keybindings" = {
switch-applications=[];
switch-applications-backward=[];
switch-windows=["<Alt>Tab"];
switch-windows-backward=["<Shift><Alt>Tab"];
maximize=["<Super>Up"];
unmaximize=["<Super>Down"];
minimize=[];
move-to-workspace-left=["<Control>Home"];
move-to-workspace-right=["<Control>End"];
};
"org/gnome/shell/extensions/clipboard-indicator" =
{
move-item-first=true;
};
# nautilus
"org/gtk/settings/file-chooser" = {
sort-directories-first=true;
};
"org/gnome/desktop/interface" = {
enable-hot-corners=false;
show-battery-percentage=true;
switch-input-source=["<Control>space"];
switch-input-source-backward=["<Shift><Control>space"];
};
# proxy
"system/proxy" = {mode = "manual";};
"system/proxy/ftp" = {host="127.0.0.1"; port=opt.proxyPort;};
"system/proxy/http" = {host="127.0.0.1"; port=opt.proxyPort;};
"system/proxy/https" = {host="127.0.0.1"; port=opt.proxyPort;};
# input method
"org/gnome/desktop/input-sources" = {
sources = with lib.hm.gvariant; mkArray
"(${lib.concatStrings [type.string type.string]})" [
(mkTuple ["xkb" "us"])
(mkTuple ["ibus" "rime"])
(mkTuple ["ibus" "mozc-jp"])
(mkTuple ["ibus" "hangul"])
];
};
"org/gnome/shell/extensions/customize-ibus" = {
candidate-orientation = lib.hm.gvariant.mkUint32 1;
custom-font="Iosevka Nerd Font 16";
enable-orientation=true;
input-indicator-only-on-toggle=false;
input-indicator-only-use-ascii=false;
use-custom-font=true;
use-indicator-show-delay=true;
};
"org/gnome/mutter" = {
dynamic-workspaces = true;
};
};
# inspired by https://discourse.nixos.org/t/how-to-set-the-bookmarks-in-nautilus/36143
home.activation.nautilus_bookmarks = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
# WSL2 may not have folder ~/.config/gtk-3.0
$DRY_RUN_CMD mkdir -p $VERBOSE_ARG ~/.config/gtk-3.0
$DRY_RUN_CMD ln -sf $VERBOSE_ARG ~/Gist/Config/nautilus_bookmarks ~/.config/gtk-3.0/bookmarks
'';
}
KDE Connect
{ config, pkgs, stdenv, lib, ... }:
let
mykdeconnect = pkgs.kdeconnect;
This customized version of KDE Connect allow share PC's keyboard smoothly to android.
#mykdeconnect = pkgs.kdeconnect.overrideAttrs (old: {
# patches = [( pkgs.fetchpatch {
# url = "https://raw.githubusercontent.com/xieby1/kdeconnect-kde-enhanced/4610431b932b2fab05d7e0fc55e7306dc7ff0910/diff.patch";
# hash = "sha256-NL/TVOMEhdJ/W7UTxjF7Qjnq7JciNvl08BC1wrBfvHo=";
# })];
# # cmakeFlags = "-DCMAKE_BUILD_TYPE=Debug -DQT_FORCE_STDERR_LOGGING=1";
#});
in {
home.packages = [
mykdeconnect
];
Auto startup KDE Connect after Gnome GUI login.
home.file.kde_connect_indicator = {
source = "${mykdeconnect}/share/applications/org.kde.kdeconnect.nonplasma.desktop";
target = ".config/autostart/org.kde.kdeconnect.nonplasma.desktop";
};
}
# https://nixos.org/manual/nixos/stable/#sec-writing-modules
# refers to syncthing module
# list options:
# home-manager option xdg.mime.types.\"*\"
# nixos option
{ config
, lib
, pkgs
, ...
}:
with lib;
let
cfg = config.xdg.mime.types;
in
{
options = {
xdg.mime.types = mkOption {
default = {};
description = "Set MIME types and default applications.";
example = ''
xdg.mime.types.dot = {
name = "graphviz-dot";
type = "text/graphviz-dot";
pattern = "*.dot";
defaultApp = "xdot.desktop";
};
'';
type = types.attrsOf (types.submodule ({name, ...}:
{
options = {
name = mkOption {
type = types.str;
default = name;
description = "The name of the xml file.";
};
type = mkOption {
type = types.str;
default = "";
description = "The mime-type.";
};
pattern = mkOption {
type = types.str;
default = "";
description = "The glob pattern.";
};
defaultApp = mkOption {
type = types.str;
default = "";
description = "Default application for opening this MIME type.";
};
};
}));
};
};
# builtins.mapAttrs (n: v: {wang=v.miao;}) {file1={miao=1;}; file2={miao=2;};}
# => {file1={wang=1;}; file2={wang=2;};}
config = {
home.file = builtins.mapAttrs (n: v: {
text = ''
<?xml version="1.0"?>
<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
<mime-type type="${v.type}">
<glob pattern="${v.pattern}"/>
</mime-type>
</mime-info>
'';
target = ".local/share/mime-types/${v.name}.xml";
onChange = ''
${pkgs.xdg-utils}/bin/xdg-mime install ~/.local/share/mime-types/${v.name}.xml
${pkgs.xdg-utils}/bin/xdg-mime default ${v.defaultApp} ${v.type}
'';
}) cfg;
};
}
{ config, pkgs, stdenv, lib, ... }:
let
my-rofi = pkgs.rofi.override {
plugins = with pkgs; [
# rofi-file-browser
];
};
in
{
home.packages = with pkgs; [
my-rofi
];
# gnome keyboard shortcuts
dconf.settings."org/gnome/settings-daemon/plugins/media-keys".custom-keybindings = [
"/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/rofi_window/"
"/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/rofi_x/"
];
dconf.settings."org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/rofi_window" = {
binding="<Super>w";
command="rofi -show window";
name="rofi window";
};
dconf.settings."org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/rofi_x" = let
x = pkgs.writeScript "x" ''
cd ${config.home.homeDirectory}/Gist/script/bash/
xdotool type --clearmodifiers --delay 30 \
"$(ls --color=never x-* | rofi -dmenu | xargs bash -c)"
'';
in {
binding="<Super>x";
command="${x}";
name="rofi x";
};
home.file.rofi_config = {
target = ".config/rofi/config.rasi";
text = ''
/* This is a comment */
/* rofi -dump-config */
configuration {
modes: [
window,
drun,
run,
ssh
/* file-browser-extended */
];
terminal: "kitty";
dpi: 1;
show-icons: true;
}
filebrowser {
directory: "~/Documents";
}
/* man rofi-theme */
window {
width: 80%;
}
'';
};
# home.file.rofi_file_browser_config = let
# openDir = pkgs.writeScript "openDir" ''
# if [[ -d "$1" ]]; then
# xdg-open "$1"
# elif [[ -f "$1" ]]; then
# xdg-open "''${1%/*}"
# fi
# '';
# in {
# target = ".config/rofi/file-browser";
# text = ''
# # This is a comment
# dir ~/Documents
# depth 0
# no-sort-by-type
# sort-by-depth
# # BUG: rofi -show-icons causes segmentation fault
# # oc-search-path
# # oc-cmd "nautilus"
# # oc-cmd "${openDir}"
# '';
# };
}
rustdesk, the remote desktop app
{ config, pkgs, stdenv, lib, ... }:
{
home.packages = [
The new version of rustdesk is rustdesk-flutter, which is cached in offical nix binary cache.
pkgs.rustdesk-flutter
];
Auto startup rustdesk after Gnome GUI login.
home.file.autostart_rustdesk_desktop = {
source = "${pkgs.rustdesk-flutter}/share/applications/rustdesk.desktop";
target = ".config/autostart/rustdesk.desktop";
};
}
{ config, pkgs, lib, ... }:
let
# You Can Change To Chrome-Like Browser Here!
chromeLikeBrowser = if (lib.meta.availableOn builtins.currentSystem pkgs.microsoft-edge.meta.platforms)
then "${pkgs.microsoft-edge}/bin/microsoft-edge"
else "${pkgs.chromium}/bin/chromium";
singleton = pkgs.writeShellScriptBin "singleton.sh" ''
if [[ $# -lt 2 || $1 == "-h" ]]
then
echo "Usage: ''${0##*/} <window> <command and its args>"
echo " Only start a app once, if the app is running"
echo " then bring it to foreground"
exit 0
fi
if [[ "$1" == "kdeconnect.app" ]]
then
WID=$(${pkgs.xdotool}/bin/xdotool search --classname "$1")
else
WID=$(${pkgs.xdotool}/bin/xdotool search --onlyvisible --name "$1")
fi
if [[ -z $WID ]]
then
eval "''${@:2}"
else
for WIN in $WID
do
CURDESK=$(${pkgs.xdotool}/bin/xdotool get_desktop)
${pkgs.xdotool}/bin/xdotool set_desktop_for_window $WIN $CURDESK
${pkgs.xdotool}/bin/xdotool windowactivate $WIN
done
fi
'';
singleton_sh = "${singleton}/bin/singleton.sh";
webapp_common = ''
if [[ $# -lt 2 || "$1" == "-h" ]]
then
echo "Usage: ''${0##*/} <window> <url>"
echo " Only start a webapp once, if the app is running"
echo " then bring it to foreground"
exit 0
fi
# check URL prefix
URL=$2
if [[ "$URL" =~ ^~ ]]
then
URL="file://$HOME/''${URL#\~/}"
fi
if [[ "$URL" =~ ^\/ ]]
then
URL="file://$URL"
fi
if [[ "$URL" =~ ^(file|https?)?:\/\/ ]]
then
true
else
URL="https://$URL"
fi
'';
webapp = pkgs.writeShellScriptBin "webapp.sh" ''
${webapp_common}
${singleton_sh} "$1" ${chromeLikeBrowser} --app="$URL"
'';
webapp_no_cors = pkgs.writeShellScriptBin "webapp_no_cors.sh" ''
${webapp_common}
${singleton_sh} "$1" ${chromeLikeBrowser} --user-data-dir=~/.chrome_no_cors --disable-web-security --app="$URL"
'';
webapp_sh = "${webapp}/bin/webapp.sh";
webapp_no_cors_sh = "${webapp_no_cors}/bin/webapp_no_cors.sh";
open_my_cheatsheet_md_sh = pkgs.writeShellScript "open_my_cheatsheet_md" ''
cd ${config.home.homeDirectory}/Documents/Tech
kitty nvim my_cheatsheet.mkd -c Vista
make
'';
in
{
home.packages = [singleton webapp webapp_no_cors];
# gnome keyboard shortcuts
dconf.settings."org/gnome/settings-daemon/plugins/media-keys".custom-keybindings = [
"/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/my_cheatsheet_html/"
"/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/my_cheatsheet_md/"
"/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/bing_dict/"
"/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/hjxd_jp/"
"/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/kdeconnect_app/"
"/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/devdocs/"
];
dconf.settings."org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/my_cheatsheet_html" = {
binding="<Alt>space";
command="gtk-launch my_cheatsheet_html.desktop";
name="cheatsheet";
};
dconf.settings."org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/my_cheatsheet_md" = {
binding="<Alt>c";
command="gtk-launch my_cheatsheet_md.desktop";
name="edit cheatsheet";
};
dconf.settings."org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/bing_dict" = {
binding="<Alt>b";
command="gtk-launch bing_dict.desktop";
name="bing dict";
};
dconf.settings."org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/hjxd_jp" = {
binding="<Alt>j";
command="gtk-launch hjxd_jp.desktop";
name="日语词典";
};
dconf.settings."org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/kdeconnect_app" = {
binding="<Alt>k";
command="gtk-launch kdeconnect_app.desktop";
name="KDE Connect";
};
dconf.settings."org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/devdocs" = {
binding="<Alt>d";
command="gtk-launch devdocs.desktop";
name="Devdocs";
};
xdg.desktopEntries = {
# web apps
## microsoft's
todo = {
name = "Microsoft To Do";
genericName = "ToDo";
exec = "${webapp_sh} \"To Do\" https://to-do.live.com/";
icon = builtins.fetchurl {
url = "http://www.google.com/s2/favicons?domain=https://to-do.live.com&sz=128";
name = "ToDo.png";
};
};
calendar = {
name = "Microsoft Calendar";
exec = "${webapp_sh} Outlook https://outlook.live.com/calendar";
icon = (pkgs.fetchurl {
url = "https://cdn.cdnlogo.com/logos/o/82/outlook.svg";
sha256 = "0544z9vmghp4lgapl00n99vksm0gq8dfwrp7rvfpp44njnh6b6dz";
}).outPath;
};
outlook = {
name = "Microsoft Outlook";
exec = "${webapp_sh} Outlook https://outlook.live.com";
icon = (pkgs.fetchurl {
url = "https://cdn.cdnlogo.com/logos/o/82/outlook.svg";
sha256 = "0544z9vmghp4lgapl00n99vksm0gq8dfwrp7rvfpp44njnh6b6dz";
}).outPath;
};
word = {
name = "Word";
genericName = "office";
exec = "${webapp_sh} Word https://www.office.com/launch/word";
icon = (pkgs.fetchurl {
url = "https://cdn.cdnlogo.com/logos/w/19/word.svg";
sha256 = "1ig0d8afacfl7m1n0brx82iw8c2iif3skb8dwjly4fzxikzvfmn4";
}).outPath;
};
excel = {
name = "Excel";
genericName = "office";
exec = "${webapp_sh} Excel https://www.office.com/launch/excel";
icon = (pkgs.fetchurl {
url = "https://cdn.cdnlogo.com/logos/m/96/microsoft-excel.png";
sha256 = "07ch9kb3s82m47mm414gvig6zg2h4yffmvjvg7bvr7sil8476cs8";
}).outPath;
};
powerpoint = {
name = "PowerPoint";
genericName = "office ppt";
exec = "${webapp_sh} PowerPoint https://www.office.com/launch/powerpoint";
icon = (pkgs.fetchurl {
url = "https://cdn.cdnlogo.com/logos/p/67/powerpoint.svg";
sha256 = "1pnb2nna2b26kyn0i92xmgdpcrqhw1cpl3vv7vvvlsxrldndhclr";
}).outPath;
};
onedrive = {
name = "OneDrive";
exec = "${webapp_sh} OneDrive https://onedrive.live.com";
icon = (pkgs.fetchurl {
url = "https://cdn.cdnlogo.com/logos/m/73/microsoft-onedrive.svg";
sha256 = "10sjz81xjcqfkd7v11vhpvdp0s2a8la9wipc3aapgybg822vhjck";
}).outPath;
};
## others
suishouji = {
name = "随手记";
genericName = "suishouji";
exec = "${webapp_sh} 随手记 https://www.sui.com/";
icon = (pkgs.fetchurl {
url = "https://res.sui.com/favicon.ico";
sha256 = "01vm275n169r0ly8ywgq0shgk8lrzg79d1aarshwybwxwffj4q0q";
}).outPath;
};
webweixin = {
name = "网页微信";
genericName = "weixin";
exec = ''${webapp_sh} "微信|weixin" https://wx.qq.com/'';
icon = (pkgs.fetchurl {
url = "https://cdn.cdnlogo.com/logos/w/79/wechat.svg";
sha256 = "1xk1dsia6favc3p1rnmcncasjqb1ji4vkmlajgbks0i3xf60lskw";
}).outPath;
};
my_cheatsheet_html = {
name = "Cheatsheet HTML";
genericName = "cheatsheet";
exec = ''${webapp_sh} "markdown cheatsheet" ${config.home.homeDirectory}/Documents/Tech/my_cheatsheet.html'';
};
bing_dict = {
name = "Bing Dict";
genericName = "dictionary";
exec = ''${webapp_sh} "搜索 词典" https://cn.bing.com/dict/'';
};
hjxd_jp = {
name = "日语词典";
genericName = "riyucidian";
exec = "${webapp_sh} 日语词典 https://dict.hjenglish.com/jp/";
};
devdocs = {
name = "DevDocs";
genericName = "devdocs";
exec = "${webapp_sh} DevDocs https://devdocs.io/";
icon = (pkgs.fetchurl {
url = "https://devdocs.io/images/webapp-icon-512.png";
sha256 = "0bbimjp8r4fwzgd094wady2ady1fqz0crnyy2iwa835g7yivix24";
}).outPath;
};
clash = let
metacubexd = builtins.fetchTarball "https://github.com/MetaCubeX/metacubexd/archive/gh-pages.zip";
in {
name = "clash";
exec = "${webapp_no_cors_sh} metacubexd file://${metacubexd}/index.html";
icon = "${metacubexd}/pwa-192x192.png";
};
# singleton apps
my_cheatsheet_md = {
name = "Cheatsheet MD";
genericName = "cheatsheet";
exec = "${singleton_sh} my_cheatsheet.mkd ${open_my_cheatsheet_md_sh}";
};
kdeconnect_app = {
name = "(S) KDE Connect App";
genericName = "kdeconnect";
exec = "${singleton_sh} kdeconnect.app kdeconnect-app";
};
};
}
{ config, pkgs, stdenv, lib, ... }:
{
# Terminal Comparsion
# * gnome-terminal
# * Pros
# * Cons
# * Wrong window size, when window is tiled (e.g. use gTile)
# * Icon display incorrectly (e.g. Vim-vista)
# * It's hard to hide top bar
# * alacritty
# * Pros
# * Esay configurable
# * Icon display correctly (e.g. Vim-vista)
# * input method fcitx works
# * Cons
# * Not native tab support
# https://github.com/alacritty/alacritty/issues/3129
# The developer(s?) with poor attitude
# * Compromise: tabbed
# * Alacritty is not work with espanso
# https://github.com/federico-terzi/espanso/issues/787
# https://github.com/federico-terzi/espanso/issues/1088
# In espanso auto mode, alacritty definitely will be stucked.
# In clipboard, alacritty may be stucked.
# * emoji display poorly.
# * kitty
# * Pros
# * Esay configurable
# * Cons
# * Icon display incorrectly (e.g. Vim-vista)
# * input method support solved by fcitx5
# * hyper
# * Cons
# * scroll speed is too fast!
# shortcuts
dconf.settings."org/gnome/settings-daemon/plugins/media-keys".custom-keybindings = [
"/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/kitty/"
"/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/fzf-doc/"
];
dconf.settings."org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/kitty" = {
binding="<Primary><Alt>t";
command = "kitty";
name="terminal";
};
dconf.settings."org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/fzf-doc" = {
binding="<Super>f";
# bash alias needs interative bash (-i)
# https://askubuntu.com/questions/1109564/alias-not-working-inside-bash-shell-script
command="kitty bash -i fzf-doc";
name="fzf-doc";
};
programs.kitty = {
enable = true;
environment = {
"TERM" = "xterm";
};
font = {
name = "";
size = 16;
};
settings = {
cursor_blink_interval = "0.8";
remember_window_size = "no";
initial_window_width = "80c";
initial_window_height = "20c";
# tab
tab_bar_edge = "top";
tab_bar_style = "separator";
active_tab_foreground = "#e2e2e3";
active_tab_background = "#2c2e34";
active_tab_title_template = "🐱{fmt.fg.red}{bell_symbol}{activity_symbol}{fmt.fg.tab}{title}";
inactive_tab_foreground = "#2c2e34";
inactive_tab_background = "#e2e2e3";
# tango dark
background = "#2c2e34";
foreground = "#e2e2e3";
cursor = "#e2e2e3";
color0 = "#2c2e34";
color8 = "#555753";
color1 = "#cc0000";
color9 = "#ef2929";
color2 = "#4e9a06";
color10 = "#8ae234";
color3 = "#c4a000";
color11 = "#fce94f";
color4 = "#3465a4";
color12 = "#729fcf";
color5 = "#75507b";
color13 = "#ad7fa8";
color6 = "#06989a";
color14 = "#34e2e2";
color7 = "#e2e2e3";
color15 = "#eeeeec";
# selection_foreground = "#2c2e34";
# selection_background = "#e2e2e3";
};
extraConfig = ''
map ctrl+equal change_font_size all +2.0
map ctrl+plus change_font_size all +2.0
map ctrl+kp_add change_font_size all +2.0
map ctrl+minus change_font_size all -2.0
map ctrl+kp_subtract change_font_size all -2.0
map ctrl+0 change_font_size all 0
map alt+1 goto_tab 1
map alt+2 goto_tab 2
map alt+3 goto_tab 3
map alt+4 goto_tab 4
map alt+5 goto_tab 5
map alt+6 goto_tab 6
map alt+7 goto_tab 7
map alt+8 goto_tab 8
map alt+9 goto_tab 9
map alt+0 goto_tab 99
map ctrl+shift+t new_tab_with_cwd
map ctrl+shift+n new_os_window_with_cwd
map ctrl+shift+f launch --location=hsplit --allow-remote-control kitty +kitten search.py @active-kitty-window-id
# disable opening of URLs with a plain click
mouse_map left click ungrabbed no_op
#: moves the window into a new tab
map f1 detach_window new-tab
#: asks which tab to move the window into
map f2 detach_window ask
action_alias launch_window launch --cwd=current
# Window layout
enabled_layouts splits
# Split and Create a new window
map f5 launch_window --location=hsplit
map f6 launch_window --location=vsplit
# Goto window
map alt+left neighboring_window left
map alt+right neighboring_window right
map alt+up neighboring_window up
map alt+down neighboring_window down
'';
};
home.file.kitty_search = {
source = pkgs.fetchurl {
url = "https://github.com/trygveaa/kitty-kitten-search/raw/0760138fad617c5e4159403cbfce8421ccdfe571/search.py";
sha256 = "1w50fimqsbmqk9zhdmq8k2v1b36iwsglpbqaavpglw0acam3xid7";
};
target = ".config/kitty/search.py";
};
home.file.kitty_scrool_mark = {
source = pkgs.fetchurl {
url = "https://github.com/trygveaa/kitty-kitten-search/raw/0760138fad617c5e4159403cbfce8421ccdfe571/scroll_mark.py";
sha256 = "1a1l7sp2x247da8fr54wwq7ffm987wjal9nw2f38q956v3cfknzi";
};
target = ".config/kitty/scroll_mark.py";
};
}
Typora
采用nixpkgs支持的最后的typora版本,即0.9.98。
mytypora = (pkgs.callPackage (pkgs.fetchurl {
url = "https://raw.githubusercontent.com/NixOS/nixpkgs/137f19d1d48b6d7c7901bb86729a2bce3588d4e9/pkgs/applications/editors/typora/default.nix";
sha256 = "057dk4hl4fljn50098g7l35sh7gwm7zqqqlrczv5lhmpgxi971c1";
}) {}).overrideAttrs (old: {
src = pkgs.fetchurl {
url = "https://web.archive.org/web/20211222112532/https://download.typora.io/linux/typora_0.9.98_amd64.deb";
sha256 = "1srj1fdcblfdsfvdnrqnwsxd3y8qd1h45p4sf1mxn6hr7z2s6ai6";
};
});
注:我尝试打包0.11.18, 发现这个版本会检测文件完整性, 因此基本上没办法用nix进行二次打包。
Wayland
virtualisation.waydroid.enable = true;
尝试使用weston,消息来源参考:
- https://github.com/waydroid/waydroid/issues/470
- https://wiki.archlinux.org/title/Waydroid
wayland images: /var/lib/waydroid/images/
weston --scale=2
# 在weston里
waydroid show-full-ui
weston快捷键参考man weston-bindings
{ pkgs ? import <nixpkgs> {}
, wrapWine ? import ./wrapWine.nix {inherit pkgs;}
}:
let
name = "weixin";
installer = builtins.fetchurl "https://dldir1.qq.com/weixin/Windows/WeChatSetup.exe";
regfile = builtins.toFile "${name}.reg" ''
Windows Registry Editor Version 5.00
# [HKEY_LOCAL_MACHINE\System\CurrentControlSet\Hardware Profiles\Current\Software\Fonts]
# "LogPixels"=dword:000000F0
[HKEY_CURRENT_USER\Software\Wine\X11 Driver]
"Decorated"="N"
'';
bin = wrapWine {
inherit name;
executable = "$WINEPREFIX/drive_c/Program Files/Tencent/WeChat/WeChat.exe";
tricks = ["riched20" "msls31"];
setupScript = ''
LANG="zh_CN.UTF-8"
'';
firstrunScript = ''
# prevent weixin polluting my Documents folder
rm -f $WINEPREFIX/drive_c/users/$USER/Documents
mkdir -p $WINEPREFIX/drive_c/users/$USER/Documents
wine ${installer}
# 占用磁盘空间持续增加
# https://github.com/vufa/deepin-wine-wechat-arch/issues/225
mkdir -p $WINEPREFIX/drive_c/users/xieby1/AppData/Roaming/Tencent/WeChat/xweb/crash/Crashpad/
touch $WINEPREFIX/drive_c/users/xieby1/AppData/Roaming/Tencent/WeChat/xweb/crash/Crashpad/reports
'';
inherit regfile;
};
desktop = pkgs.makeDesktopItem {
inherit name;
desktopName = "Wine微信";
genericName = "weixin";
type = "Application";
exec = "${bin}/bin/${name}";
icon = pkgs.fetchurl {
url = "https://cdn.cdnlogo.com/logos/w/79/wechat.svg";
sha256 = "1xk1dsia6favc3p1rnmcncasjqb1ji4vkmlajgbks0i3xf60lskw";
};
};
in
pkgs.symlinkJoin {
inherit name;
paths = [bin desktop];
}
# based on https://github.com/lucasew/nixcfg/blob/49d44c1a655f1c20d7354ecea942c78704067d50/pkgs/wrapWine.nix
{ pkgs ? import <nixpkgs> {} }:
let
inherit (builtins) length concatStringsSep;
inherit (pkgs) lib cabextract
writeShellScriptBin symlinkJoin;
inherit (lib) makeBinPath;
in
{ is64bits ? false
, wine ? if is64bits then pkgs.wineWowPackages.stable else pkgs.wine
, wineFlags ? ""
, executable
, chdir ? null
, name
, tricks ? [ ]
, setupScript ? ""
, firstrunScript ? ""
, home ? ""
, regfile ? null
}:
let
wineBin = "${wine}/bin/wine${if is64bits then "64" else ""}";
requiredPackages = [
wine
cabextract
];
PATH = makeBinPath requiredPackages;
NAME = name;
WINEARCH =
if is64bits
then "win64"
else "win32";
WINE_NIX = "$HOME/.wine-nix";
WINEPREFIX = "${WINE_NIX}/${name}";
setupHook = ''
${wine}/bin/wineboot
'';
tricksHook =
if (length tricks) > 0 then
let
tricksStr = concatStringsSep " " tricks;
tricksCmd = ''
${pkgs.winetricks}/bin/winetricks ${tricksStr}
'';
in
tricksCmd
else "";
run = writeShellScriptBin name ''
export APP_NAME="${NAME}"
export WINEARCH=${WINEARCH}
export WINE_NIX=${WINE_NIX}
export PATH=$PATH:${PATH}
export WINEPREFIX="${WINEPREFIX}"
export EXECUTABLE="${executable}"
mkdir -p "$WINE_NIX"
${setupScript}
if [ ! -e "$EXECUTABLE" ] # if the executable does not exist
then
${if regfile!=null
then ''${wineBin} regedit /C ${regfile}''
else ""
}
${setupHook}
${tricksHook}
${firstrunScript}
else # no automatically run after installation!
${if chdir != null
then ''cd "${chdir}"''
else ""}
if [ ! "$REPL" == "" ]; # if $REPL is setup then start a shell in the context
then
bash
exit 0
fi
${wineBin} ${wineFlags} "$EXECUTABLE" "$@"
fi
'';
clean = writeShellScriptBin "${name}-clean" ''
read -p "Are you sure you want to clean ${WINEPREFIX}? <y/N> " prompt
if [[ $prompt =~ [yY](es)* ]]; then
rm ${WINEPREFIX} -rf
fi
'';
winecfg = writeShellScriptBin "${name}-cfg" ''
export WINEARCH=${WINEARCH}
WINEPREFIX=${WINE_NIX}/${name} winecfg $@
'';
_wine = writeShellScriptBin "${name}-wine" ''
export WINEARCH=${WINEARCH}
WINEPREFIX=${WINE_NIX}/${name} ${wineBin} $@
'';
in
symlinkJoin {
inherit name;
paths = [run clean winecfg _wine];
}
xdot, the dot (graphviz) viewer
{ config, pkgs, stdenv, lib, ... }:
let
Add a xdot.desktop for my xdot.
myxdot = pkgs.symlinkJoin {
name = "myxdot";
paths = [
pkgs.xdot
(pkgs.makeDesktopItem {
name = "xdot";
desktopName = "xdot";
exec = "xdot %U";
})];};
in {
home.packages = [
myxdot
];
Open *.dot files with xdot.desktop by default.
xdg.mime.types.dot = {
name = "graphviz-dot";
type = "text/graphviz-dot";
pattern = "*.dot";
defaultApp = "xdot.desktop";
};
}
{
lib,
stdenv,
fetchurl,
dpkg,
qt5
}:
let
version = "0.05";
rpath = lib.makeLibraryPath [
qt5.qtbase
] + ":${stdenv.cc.cc.lib}/lib64";
src =
if stdenv.hostPlatform.system == "x86_64-linux" then
fetchurl {
urls = [
"https://github.com/horsicq/XELFViewer/releases/download/0.05/xelfviewer_0.05_Ubuntu_22.04_amd64.deb"
];
sha256 = "0l6j0pnpfzwr8205xzis95k4x2la0mfy08bv6hfg32rh3bw906bz";
}
else
throw "xelfviewer is not supported on ${stdenv.hostPlatform.system}";
in
stdenv.mkDerivation {
pname = "xelfviewer";
inherit version;
system = "x86_64-linux";
inherit src;
nativeBuildInputs = [ qt5.wrapQtAppsHook ];
buildInputs = [ dpkg ];
dontUnpack = true;
installPhase = ''
mkdir -p $out
dpkg-deb -x $src $out
mv $out/usr/* $out/
rm -r $out/usr
'';
postFixup = ''
for file in $(find $out -type f \( -perm /0111 -o -name \*.so\* \) ); do
patchelf --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" "$file" || true
patchelf --set-rpath ${rpath}:$out/lib/xelfviewer $file || true
done
'';
meta = with lib; {
description = "XELFViewer";
homepage = "https://github.com/horsicq/XELFViewer";
license = licenses.mit;
maintainers = with maintainers; [ xieby1 ];
platforms = [ "x86_64-linux" ];
};
}
{ config, lib, ...}:
{
imports = [../../modules/cachix.nix];
config = lib.mkIf (
(builtins.pathExists config.cachix_dhall) &&
(config.cachix_packages != [])
) {
home.activation.cachix_push = lib.hm.dag.entryAfter ["writeBoundary"] config._cachix_push;
};
}
nix-on-droid.nix
nix-on-droid.nix
是安卓nix-on-droid的入口配置文件。
因为原生termux并不能直接运行nix,
所以nix-on-droid的作者基于termux使用proot搞出来一个能运行nix的termux分支。
nix-on-droid并未自带很多常用linux命令行工具,
因此nix-on-droid.nix
主要负责配置那些在linux常用的,但nix-on-droid没有默认提供的命令行工具。
其他命令行工具的配置则复用home-manager的配置./home.nix
。
下面是我的带注解的nix-on-droid.nix
代码。
{ pkgs, config, ... }:
{
添加sshd-start
命令,用于在安卓上启动sshd服务。
通常安卓上是没有root权限的,无法写/etc/目录的文件,
因此将ssh的tmp目录和配置目录设定到home下面。
这部分内容参考nix-on-droid wiki: SSH access
imports = [(let
sshdTmpDirectory = "${config.user.home}/sshd-tmp";
sshdDirectory = "${config.user.home}/sshd";
pathToPubKey = "${config.user.home}/.ssh/id_rsa.pub";
port = 8022;
sshd-start = pkgs.writeScriptBin "sshd-start" ''
#!${pkgs.runtimeShell}
echo "Starting sshd in non-daemonized way on port ${toString port}"
${pkgs.openssh}/bin/sshd -f "${sshdDirectory}/sshd_config" -D
'';
in {
environment.packages = with pkgs; [
sshd-start
];
build.activation.sshd = ''
$DRY_RUN_CMD mkdir $VERBOSE_ARG --parents "${config.user.home}/.ssh"
$DRY_RUN_CMD cat ${pathToPubKey} > "${config.user.home}/.ssh/authorized_keys"
if [[ ! -d "${sshdDirectory}" ]]; then
$DRY_RUN_CMD rm $VERBOSE_ARG --recursive --force "${sshdTmpDirectory}"
$DRY_RUN_CMD mkdir $VERBOSE_ARG --parents "${sshdTmpDirectory}"
$VERBOSE_ECHO "Generating host keys..."
$DRY_RUN_CMD ${pkgs.openssh}/bin/ssh-keygen -t rsa -b 4096 -f "${sshdTmpDirectory}/ssh_host_rsa_key" -N ""
$VERBOSE_ECHO "Writing sshd_config..."
$DRY_RUN_CMD echo -e "HostKey ${sshdDirectory}/ssh_host_rsa_key\nPort ${toString port}\n" > "${sshdTmpDirectory}/sshd_config"
$DRY_RUN_CMD mv $VERBOSE_ARG "${sshdTmpDirectory}" "${sshdDirectory}"
fi
'';
}) ({
自动配置termux。
build.activation.termux = ''
DIR=${config.user.home}/.termux
mkdir -p $DIR
symlink() {
if [[ -e $1 && ! -e $2 ]]; then
#echo "ln -s $1 $2"
ln -s $1 $2
fi
}
SRC=${config.user.home}/Gist/Config/termux.properties
DST=$DIR/termux.properties
symlink $SRC $DST
SRC=${config.user.home}/Gist/Config/colors.properties
DST=$DIR/colors.properties
symlink $SRC $DST
'';
})];
下面是非常直观的软件安装。
# Simply install just the packages
environment.packages = with pkgs; [
# User-facing stuff that you really really want to have
vim # or some other editor, e.g. nano or neovim
# Some common stuff that people expect to have
diffutils
findutils
utillinux
tzdata
hostname
man
gnugrep
gnupg
gnused
gnutar
bzip2
gzip
xz
zip
unzip
gawk
openssh
nettools
(lib.setPrio # make bintools less prior
(busybox.meta.priority + 10)
busybox
)
];
# Backup etc files instead of failing to activate generation if a file already exists in /etc
environment.etcBackupExtension = ".bak";
# Read the changelog before changing this value
system.stateVersion = "21.11";
导入home-manager的配置文件./home.nix的配置。 如此操作,所有home-manager的软件和配置都能nix-on-droid中复用。
home-manager.config = import ./home.nix;
}
用于自动push包到cachix的模块。 尽管cachix watch-store能自动push,但是我想更细粒度地管理需要push的包,所以有了这个模块。
{ config, pkgs, lib, ...}:
{
options = {
cachix_packages = lib.mkOption {
type = lib.types.listOf lib.types.package;
default = [];
description = ''
This list of packages.
If the the cachix.dhall file exists and cachix_packages is not empty,
then the packages in cachix_packages will be pushed to cachix.
'';
};
cachix_dhall = lib.mkOption {
type = lib.types.str;
default = "/home/xieby1/Gist/Config/cachix.dhall";
description = ''
The path of cachix.dhall.
'';
};
cachix_name = lib.mkOption {
type = lib.types.str;
default = "xieby1";
description = ''
The cachix name.
'';
};
_cachix_push = lib.mkOption {
type = lib.types.str;
default = ''
echo Pushing packages to cachix:
${lib.concatMapStrings (x: "echo 📦"+x+"\n") config.cachix_packages}
${pkgs.cachix}/bin/cachix -c ${config.cachix_dhall} push ${config.cachix_name} ${builtins.toString config.cachix_packages}
'';
description = ''
(Internal usage) The script of pushing packages to cachix.
'';
};
};
}
Module
nixpkgs/lib/modules.nix:
从loadModule
可以看出,imports可以接受Function、Attr、路径,不能够嵌套List。
Nixpkgs
nixpkgs crossSystem
- default.nix
- pkgs/top-level/impure.nix
- pkgs/top-level/default.nix
- lib.systems.elaborate crossSystem0;
- lib/systems/default.nix: elaborate
- parsed = parse.mkSystemFromString ... args.system; // args.system = crossSystem
- lib/systems/parse.nix
- mkSystemFromString = s: mkSystemFromSkeleton (mkSkeletonFromList (lib.splitString "-" s));
- mkSkeletonFromList
- mkSystemFromString = s: mkSystemFromSkeleton (mkSkeletonFromList (lib.splitString "-" s));
- lib/systems/parse.nix
- parsed = parse.mkSystemFromString ... args.system; // args.system = crossSystem
- lib/systems/default.nix: elaborate
- lib.systems.elaborate crossSystem0;
- pkgs/top-level/default.nix
- pkgs/top-level/impure.nix
注意mkSkeletonFromList通过
${toString (length l)}
实现了一个根据l长度的switch case。
crossSystem的4个域分别为cpu-vendor-kernel-abi
import nixpkgs
import <nixpgks> {}
的加载流程
- default.nix
- pkgs/top-level/impure.nix
- pkgs/top-level/default.nix
- stdenvStages import pkgs/stdenv/default.nix
- stagesLinux = import pkgs/stdenv/linux/
- thisStdenv, stdenv = import pkgs/stdenv/generic/default.nix
- import lib/default.nix
this is where customisation.nix come from
- import lib/default.nix
- thisStdenv, stdenv = import pkgs/stdenv/generic/default.nix
- stagesLinux = import pkgs/stdenv/linux/
- allPackages import pkgs/top-level/stage.nix
- allPackages import pkgs/top-level/all-packages.nix
- boot = import pkgs/stdenv/booter.nix
- stdenvStages import pkgs/stdenv/default.nix
- pkgs/top-level/default.nix
- pkgs/top-level/impure.nix
vim_configurable.override {python = python3} vimUtils.makeCustomizable (vim.override {python = python3}) vimUtils.makeCustomizable (vim.override {python = python3})
似乎是一个浮现override变量的最小集 f = a:{res = a+1;} fo = pkgsMiao.makeOverride f f 2
打包/编译32位程序
参考Packaging/32bit Applications。
仅32位
打包使用pkgs.pkgsi686Linux.stdenv.mkDerivation
编译使用pkgs.pkgsi686Linux.gcc
32位且64位
打包使用pkgs.multiStdenv.mkDerivation。
编译使用pkgs.gcc_multi。
Auto Push Packages to Cachix
Objective:
Automatically push specific built packages to cachix during home-manager switch
/nixos-rebuild switch
/nix-shell
.
Although there are several existing ways to achieve this:
- cachix's watch-exec and watch-store
- nix-build's post-build-hook
However, the granularity of these methods is coarse; they push all packages to cachix. Is there a way to allow users to control which packages are pushed?
Conclusion First
Use hooks to push the selected packages to cachix:
Scenario | Hook | Example |
---|---|---|
home-manager | home.activation | modules/cachix.nix, usr/modules/cachix.nix |
nixos-rebuild | system.activationScripts | modules/cachix.nix, sys/modules/cachix.nix |
nix-shell | shellHook | openc910/shell.nix |
My Explorations
Possible solutions:
Add a wrapper called cachixPackages
, which recives the packages to be pushed and cachix information.
This cachixPackages
is a dummy package whose build stages will push the packages to cachix.
However, normal nix packages are not allowed network access during building.
To tackle this, like how fetch* series functions are implemented, the fixed-output derivation can be utilized to allow network access.
However, the above method seems not work as below, because cachix needs accesses to some resources beyond nix-build process (such as nix-build's sandbox).
nix-build test.nix
...
cachix: CppStdException e "\ESC[31;1merror:\ESC[0m creating directory '\ESC[35;1m/nix/var\ESC[0m': \ESC[35;1mPermission denied\ESC[0m"(Just "nix::SysError")
result 1
...
Even though I disable the nix-build sandbox by using --no-sandbox
,
the cachix still does not satisfy as below.
$ nix-build test.nix --no-sandbox
...
cachix: CppStdException e "\ESC[31;1merror:\ESC[0m cannot open connection to remote store '\ESC[35;1mdaemon\ESC[0m': \ESC[35;1m\ESC[31;1merror:\ESC[0m reading from file: \ESC[35;1mConnection reset by peer\ESC[0m\ESC[0m"(Just "nix::Error")
...
If you curious about my demo of cachixPackages
and its test,
see cachix-package.nix and test.nix.
cachixPackage
This file try to implement a package wrapper, which will automatically push pkg
to cachix upon building.
However, this method seems not work, due to limited resources in nix-build environment.
For more details, see here.
{ cachix
, stdenv
, writeShellScript
}:
{ pkg
, sha256
, cachix_dhall
, cachix_name
, name ? "cachixed"
}:
builtins.derivation {
inherit name;
system = builtins.currentSystem;
builder = writeShellScript "cachix-package-builder" ''
source ${stdenv}/setup
echo ${pkg} > $out
if [[ -f "${cachix_dhall}" ]]; then
${cachix}/bin/cachix -c ${cachix_dhall} push ${cachix_name} ${pkg}
result=$?
echo result $result
exit $result
fi
'';
outputHashMode = "flat";
outputHashAlgo = "sha256";
outputHash = sha256;
}
Test for cachixPackage
To run the test:
# run with nix-build sandbox
nix-build test.nix
# run without nix-build sandbox
nix-build test.nix --no-sandbox
let
pkgs = import <nixpkgs> {};
cachixPackage = import ./cachix-package.nix {inherit (pkgs) cachix stdenv writeShellScript;};
in cachixPackage {
pkg = pkgs.hello;
sha256 = "01vm275n169r0ly8ywgq0shgk8lrzg79d1aarshwybwxwffj4q0q";
cachix_dhall = /home/xieby1/Gist/Config/cachix.dhall;
cachix_name = "xieby1";
}
备份binary cache
场景
官方binary cache没有的包, 自己花了很长时间编译出来。 值得把编译出来的的包及其依赖全部保存下来。
目前的问题
nix copy --to
交叉编译和安装跨平台程序
nixpkgs原生支持x86和arm指令集。 通过对nixpkgs配置可以轻松实现交叉编译, 跨平台程序的安装等功能。
太长不看
-
x86_64上的aarch64交叉编译器
(with import <nixpkgs> {crossSystem="aarch64-linux";}; stdenv.cc)
-
aarch64的hello应用程序
(with import <nixpkgs> {localSystem.system="aarch64-linux";crossSystem="aarch64-linux";}; hello)
-
应用于nix-shell的例子
目录
简介
nixpkgs1众多输入参数中,包含localSystem
和crossSystem
2。
-
localSystem
The system packages will be built on.
本地系统,即工具链运行的平台。
-
crossSystem
The system packages will ultimately be run on.
程序运行的平台。
通过localSystem
和crossSystem
不同值的组合,
可以实现交叉编译、安装其他架构的原生应用。
下面从localSystem
和crossSystem
的语法和应用两方面进行介绍。
语法章节从nixpkgs源码的角度出发,介绍其语法的组成。
应用章节围绕一个nix-shell脚本的实际例子,
介绍x86_64平台的交叉编译和安装aarch64架构的原生应用的方法。
localSystem
和crossSystem
的语法
localSystem
和crossSystem
由4个维度去刻画一个系统:cpu, vendor, kernel, abi。
localSystem
和crossSystem
的值为字符串或者{system=字符串;}
3。
system字符串为可以包含前述4个维度的1~4个维度。
nix在解析时会将省略的维度按以某些默认值补充完整。
维度之间之间用-
分割。
因此system字符串形式上为"cpu-vendor-kernel-abi"
。
字符串不同数量的维度及其可用的值,
按匹配优先级由高到低列举如下4,
cpu-vendor-kernel-abi
system字符串 | cpu | vendor | kernel | abi |
---|---|---|---|---|
"avr" | avr | none | unknown | |
"{cpu}-cygwin" | {cpu} | windows | cygnus | |
"{cpu}-windows" | {cpu} | windows | msvc | |
"{cpu}-elf" | {cpu} | unknown | none | elf |
"{cpu}-{kernel}" | {cpu} | {kernel} | ||
"{cpu}-apple-{kernel}" | {cpu} | apple | {kernel} | |
"{cpu}-linux-gnu" | {cpu} | linux | gnu | |
"{cpu}-{vendor}-mingw32" | {cpu} | {vendor} | windows | |
"{cpu}-{vendor}-wasi" | {cpu} | {vendor} | wasi | |
"{cpu}-{vendor}-redox" | {cpu} | {vendor} | redox | |
"{cpu}-{vendor}-mmixware" | {cpu} | {vendor} | mmixware | |
"{cpu}-{vendor}-netbsd*" | {cpu} | {vendor} | netbsd* | |
"{cpu}-{vendor}-eabi" | {cpu} | unknown | {kernel} | eabi |
"{cpu}-{vendor}-eabihf" | {cpu} | unknown | {kernel} | eabihf |
"{cpu}-{kernel}-elf" | {cpu} | unknown | {kernel} | elf |
"{cpu}-*-{ghcjs}" | {cpu} | unknown | ghcjs | |
"{cpu}-{vendor}-genode" | {cpu} | {vendor} | genode | |
"{cpu}-{vendor}-{kernel}-{abi} " | {cpu} | {vendor} | {kernel} | {abi} |
cpu
cpu字符串可取的值列举如下5,
cpu字符串 | bits | significantByte | family | version | arch |
---|---|---|---|---|---|
"arm" | 32 | littleEndian | "arm" | ||
"armv5tel" | 32 | littleEndian | "arm" | "5" | "armv5t" |
"armv6m" | 32 | littleEndian | "arm" | "6" | "armv6-m" |
"armv6l" | 32 | littleEndian | "arm" | "6" | "armv6" |
"armv7a" | 32 | littleEndian | "arm" | "7" | "armv7-a" |
"armv7r" | 32 | littleEndian | "arm" | "7" | "armv7-r" |
"armv7m" | 32 | littleEndian | "arm" | "7" | "armv7-m" |
"armv7l" | 32 | littleEndian | "arm" | "7" | "armv7" |
"armv8a" | 32 | littleEndian | "arm" | "8" | "armv8-a" |
"armv8r" | 32 | littleEndian | "arm" | "8" | "armv8-a" |
"armv8m" | 32 | littleEndian | "arm" | "8" | "armv8-m" |
"aarch64" | 64 | littleEndian | "arm" | "8" | "armv8-a" |
"aarch64_be" | 64 | bigEndian | "arm" | "8" | "armv8-a" |
"i386" | 32 | littleEndian | "x86" | "i386" | |
"i486" | 32 | littleEndian | "x86" | "i486" | |
"i586" | 32 | littleEndian | "x86" | "i586" | |
"i686" | 32 | littleEndian | "x86" | "i686" | |
"x86_64" | 64 | littleEndian | "x86" | "x86-64" | |
"mips" | 32 | bigEndian | "mips" | ||
"mipsel" | 32 | littleEndian | "mips" | ||
"mips64" | 64 | bigEndian | "mips" | ||
"mips64el" | 64 | littleEndian | "mips" | ||
"mmix" | 64 | bigEndian | "mmix" | ||
"m68k" | 32 | bigEndian | "m68k" | ||
"powerpc" | 32 | bigEndian | "power" | ||
"powerpc64" | 64 | bigEndian | "power" | ||
"powerpc64le" | 64 | littleEndian | "power" | ||
"powerpcle" | 32 | littleEndian | "power" | ||
"riscv32" | 32 | littleEndian | "riscv" | ||
"riscv64" | 64 | littleEndian | "riscv" | ||
"s390" | 32 | bigEndian | "s390" | ||
"s390x" | 64 | bigEndian | "s390" | ||
"sparc" | 32 | bigEndian | "sparc" | ||
"sparc64" | 64 | bigEndian | "sparc" | ||
"wasm32" | 32 | littleEndian | "wasm" | ||
"wasm64" | 64 | littleEndian | "wasm" | ||
"alpha" | 64 | littleEndian | "alpha" | ||
"msp430" | 16 | littleEndian | "msp430" | ||
"avr" | 8 | "avr" | |||
"vc4" | 32 | littleEndian | "vc4" | ||
"or1k" | 32 | bigEndian | "or1k" | ||
"js" | 32 | littleEndian | "js" |
cpuTypes
cpu之间的兼容性(具有传递性和自反性)如下6,
vendor
vendor字符串可取值"apple"
, "pc"
(windows), "w64"
(MinGW-w64), "none"
, "unknown"
(default)。
kernel
kernel字符串可取值如下表7,
kernel字符串 | execFormat | families |
---|---|---|
"macos" | macho | darwin |
"darwin" | ↑ | ↑ |
"ios" | macho | darwin |
"watchos" | ↑ | ↑ |
"tvos" | ↑ | ↑ |
"freebsd" | elf | bsd |
"linux" | elf | |
"netbsd" | elf | bsd |
"none" | unknown | |
"openbsd" | elf | bsd |
"solaris" | elf | |
"wasi" | wasm | |
"redox" | elf | |
"windows" | pe | |
"win32" | ↑ | ↑ |
"ghcjs" | unknown | |
"genode" | elf | |
"mmixware" | unknown |
abi
abi字符串可取的值列举如下8,
abi字符串 | float | abi | Note |
---|---|---|---|
"cygnus" | |||
"msvc" | |||
"eabi" | soft | for ARM, PowerPC | |
"eabihf" | hard | for ARM, PowerPC | |
"elf" | |||
"androideabi" | |||
"android" | not 32-bit | ||
"gnueabi" | soft | ||
"gnueabihf" | hard | ||
"gnu" | not 32-bit | ||
"gnuabi64" | 64 | ||
"musleabi" | soft | ||
"musleabihf" | hard | ||
"musl" | |||
"uclibceabihf" | soft | ||
"uclibceabi" | hard | ||
"uclibc" | |||
"unknown" |
localSystem
和crossSystem
的应用
aarch64交叉工具链和程序的详细例子
以x86为本地指令集,localSystem
和crossSystem
的组合有以下效果
↓crossSystem ↓ →localSystem → | "x86_64-linux" | "aarch64-linux" |
---|---|---|
"x86_64-linux" | 通常情况 | |
"aarch64-linux" | 交叉编译aarch64 | 原生aarch64应用 |
因此基于这3种组合,可以在同一个shell环境中配置出3种软件, 代码见[cross_platform.nix]({{ site.repo_url }}/scripts/shell/cross_platform.nix)。
pkgs_arm_cross
软件包的stdenv.cc
为x86平台的arm交叉编译器。
nixpkgs channel只包含了原生x86应用和原生arm应用。
交叉编译的arm应用和原生arm应用的derivation不一样。
因此使用pkgs_arm_cross
中的应用,
则会使用交叉编译器从源码开始编译arm应用,
而不是直接拉取nixpkgs channel的原生arm应用。
pkgs_arm_native
软件包包含原生arm软件包。
从这个软件包拉取的应用和在arm平台的拉取到的应用一致。
例如figlet
将直接从nix channel中拉取。
pkgs
即x86原生的软件包。
shell_cross_platform.nix使用例子,
# 创建一个新的shell环境,包含stdenv.cc, figlet, qemu
$ nix-shell shell_cross_platform.nix
# 使用交叉编译工具链的c编译器
$ aarch64-unknown-linux-gnu-gcc helloworld.c -o helloworld
$ file helloworld
helloworld: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /nix/store/01kw0gb38phviarfv3fca49dpqh0qwlx-glibc-aarch64-unknown-linux-gnu-2.33-123/lib/ld-linux-aarch64.so.1, for GNU/Linux 2.6.32, with debug_info, not stripped
# arm原生应用
$ file `command -v figlet`
/nix/store/4f70f04bvd664n00jlnzccyzxd35lykw-figlet-2.2.5/bin/figlet: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /nix/store/rjc27shzir243n1w3127w713fijamf6v-glibc-2.33-123/lib/ld-linux-aarch64.so.1, for GNU/Linux 2.6.32, not stripped
# 直接执行figlet会出错
$ figlet
bash: /nix/store/4f70f04bvd664n00jlnzccyzxd35lykw-figlet-2.2.5/bin/figlet: cannot execute binary file: Exec format error
# 使用QEMU执行figlet即可
$ qemu-aarch64 `command -v figlet` miao!
_ _
_ __ ___ (_) __ _ ___ | |
| '_ ` _ \| |/ _` |/ _ \| |
| | | | | | | (_| | (_) |_|
|_| |_| |_|_|\__,_|\___/(_)
mips交叉工具链的例子
[cross_mips.nix]({{ site.repo_url }}/scripts/shell/cross_mips.nix)
引用
nixpkgs版本2022.01.20, commit hash: 7e149abe9db1509fa974bb2286f862a761ca0a07
nixpkgs/pkgs/top-level/default.nix
nixpkgs/lib/systems/default.nix: elaborate
nixpkgs/lib/systems/parse.nix: mkSkeletonFromList
nixpkgs/lib/systems/parse.nix: cpuTypes
nixpkgs/lib/systems/parse.nix: isCompatible
nixpkgs/lib/systems/parse.nix: kernels
nixpkgs/lib/systems/parse.nix: abis
安装NixOS
安装过程采用官方安装文档。 若已安装NixOS,则可跳过该步骤,直接看安装我的配置。
准备镜像
QEMU:
# 下载minimal ISO镜像:https://nixos.org/download.html
# 创建qemu硬盘(大小32GB)
qemu-img create -f qcow2 <output/path/to/nix.qcow2> 32G
# 将ISO安装到qemu硬盘
qemu-system-x86_64 -display gtk,window-close=off -vga virtio -device e1000,netdev=net0 -netdev user,id=net0,hostfwd=tcp::5556-:22,smb=/home/xieby1/ -m 4G -smp 3 -enable-kvm -hda </path/to/nix.qcow2> -cdrom </path/to/nixos-minial.iso> -boot d &
物理机:
# 暂时未探究命令行连接wifi的方法
# 所以目前使用gnome版ISO,而非minimal ISO。
# 下载gnome ISO镜像:https://nixos.org/download.html
# 启动U盘制作
sudo dd if=<path/to/nixos.iso> of=</dev/your_usb>
sync
# 重启进入U盘系统
# 注:需要在BIOS中取消secure boot,否则U盘无法启动。
分区
进入ISO系统后,创建分区。 一共需要3个分区:启动分区,操作系统分区,swap分区。 QEMU和物理机单系统需要创建这3个分区。 物理机双系统中启动分区已有,只需创建剩下2个分区。
QEMU:
sudo bash
parted /dev/sda -- mklabel msdos
parted /dev/sda -- mkpart primary 1MiB -8GiB
parted /dev/sda -- mkpart primary linux-swap -8GiB 100%
物理机单系统:
parted /dev/sda -- mklabel gpt
parted /dev/sda -- mkpart primary 512MiB -8GiB
parted /dev/sda -- mkpart primary linux-swap -8GiB 100%
parted /dev/sda -- mkpart ESP fat32 1MiB 512MiB
parted /dev/sda -- set 3 esp on
物理机双系统:
还未探索parted详细用法,目前使用disk软件可视化分区。
- 创建Ext4分区,取名为nixos
- 创建Other->swap分区
文件系统
mkfs.ext4 -L nixos /dev/<系统分区>
mkswap -L swap /dev/<swap分区>
swapon /dev/<swap分区>
mkfs.fat -F 32 -n boot /dev/<启动分区> # 物理机单系统
mount /dev/disk/by-label/nixos /mnt
mkdir -p /mnt/boot # 物理机单系统&双系统
mount /dev/disk/by-label/boot /mnt/boot # 物理机单系统&双系统
基础配置
- 生成配置文件
nixos-generate-config --root /mnt
- 修改/mnt/etc/nixos/configuration.nix,
- 修改名字
networking.hostName
- 启用代理
- QEMU中宿主机器的ip为10.0.2.2
- 安装过程中需要借助别的计算机或宿主机的的代理服务
- 部署完我的nixos配置后,将会有clash服务,可以用虚拟机的代理服务
networking.proxy.default = "http://user:password@proxy:port/";
networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";
- (QEMU和物理机单系统)取消以下注释以开启grub支持
boot.loader.grub.device = "/dev/sda";
- 取消防火墙,以便kdeconnect正常运行
networking.firewall.enable = false;
- (物理机双系统)自动探测操作系统启动项
boot.loader.grub.useOSProber = true;
- 添加用户
users.users.xieby1
- 添加软件
environment.systemPackages = with pkgs; [vim git];
- 修改名字
最后
nixos-install
reboot
重启之后,进入NixOS。
Nix让你的团队成员不再受环境问题困扰
注:左下角菜单里可切换全屏
See all fhs-shell scripts on [Github repo: scripts/fhs-shell]({{ site.repo_url }}/scripts/fhs-shell)
#!/usr/bin/env -S nix-shell --keep miao
{ pkgs ? import <nixpkgs> {} }:
(pkgs.buildFHSUserEnv {
name = "dynamoRIO";
targetPkgs = pkgs: with pkgs; [
(hiPrio gcc)
snappy
zlib
zlib.dev
lz4
lz4.dev
libunwind
libunwind.dev
];
profile = ''
export CC=gcc
export CXX=g++
'';
}).env
#!/usr/bin/env -S nix-shell --keep miao
let
pkgs = import <nixpkgs> {};
fhs = pkgs.buildFHSUserEnv {
name = "hello";
targetPkgs = p: with p; [
hello
];
profile = ''
export MIAO=1
'';
};
in
fhs.env
#!/usr/bin/env -S nix-shell --keep miao
{ pkgs ? import <nixpkgs> {} }:
let
pin = builtins.derivation {
name = "pin-3.25";
system = builtins.currentSystem;
src = pkgs.fetchurl {
url = "https://software.intel.com/sites/landingpage/pintool/downloads/pin-3.25-98650-g8f6168173-gcc-linux.tar.gz";
hash = "sha256-Q8D0QSNLDly2XK+XFOYdMxbx5N33eGVzESGTCgWGX6E=";
};
builder = pkgs.writeShellScript "pin-builder" ''
# make mkdir and tar and other useful tools added to PATH
source ${pkgs.stdenv}/setup
mkdir -p $out
# strip leading directory
tar -xf $src --strip-components=1 --directory=$out
'';
};
in
(pkgs.buildFHSUserEnv {
name = "pin";
targetPkgs = pkgs: with pkgs; [
];
profile = ''
PATH+=":${pin}"
'';
}).env
#!/usr/bin/env -S nix-shell --keep miao
{ pkgs ? import <nixpkgs> {} }:
let
zigenv = import /home/xieby1/Codes/nix-zig-stdenv {
target = "x86_64-unknown-linux-musl";
};
noPrefixStaticStdenvCC = pkgs.runCommand "linkCC" {} ''
mkdir -p $out/bin
for file in ${pkgs.pkgsStatic.stdenv.cc}/bin/*; do
ln -s $file $out/bin/''${file##*-}
done
'';
in
(pkgs.buildFHSUserEnv {
name = "spec";
targetPkgs = pkgs: with pkgs; [
# (hiPrio zigenv.pkgs.stdenv.cc)
# (hiPrio clangStdenv.cc)
# (hiPrio gcc)
# (hiPrio pkgsStatic.stdenv.cc)
# noPrefixStaticStdenvCC
gfortran
# uclibc
# musl
# musl.dev
glibc.static
glibc.dev
];
}).env
#!/usr/bin/env -S nix-shell --keep miao
# https://ryantm.github.io/nixpkgs/builders/special/fhs-environments/
{ pkgs ? import <nixpkgs> {} }:
(pkgs.buildFHSUserEnv {
name = "simple-x11-env";
targetPkgs = pkgs: (with pkgs;
[ udev
alsa-lib
]) ++ (with pkgs.xorg;
[ libX11
libXcursor
libXrandr
]);
multiPkgs = pkgs: (with pkgs;
[ udev
alsa-lib
]);
runScript = "bash";
}).env
#!/usr/bin/env -S nix-shell --keep miao
# based on https://github.com/nix-community/nix-environments
# git commit: 40d9d98bab7750bb5a1a9a3b5bcc1c91a652f3be
{ pkgs ? import <nixpkgs> {} }:
let
name = "xilinx-fhs";
h_content = builtins.toFile "h_content" ''
# ${pkgs.lib.toUpper "${name} usage"}
**Commands**
* Show this help: `h`
* Start Vitis HLS IDE: `vitis_hls`
* Start Vitis HLS REPL: `vitis_hls -i`
**Files**
* Vitis HLS Doc: `2022.vitis_hls.ug1399.pdf`
* Local command doc: `Xilinx/Vitis/2022.2/doc/eng/man/`
* TODO: `ug871-vivado-high-level-synthesis-tutorial.pdf`
* TODO: `ug902-vivado-high-level-synthesis.pdf`
**Examples**
* [Vitis HLS examples](https://github.com/Xilinx/Vitis-HLS-Introductory-Examples)
* Run an example: `vitis_hls -f run_hls.tcl`
'';
_h_ = pkgs.writeShellScriptBin "h" ''
${pkgs.glow}/bin/glow ${h_content}
'';
in
(pkgs.buildFHSUserEnv {
inherit name;
targetPkgs = pkgs: with pkgs; [
_h_
bash
coreutils
zlib
lsb-release
stdenv.cc.cc
ncurses5
xorg.libXext
xorg.libX11
xorg.libXrender
xorg.libXtst
xorg.libXi
xorg.libXft
xorg.libxcb
xorg.libxcb
# common requirements
freetype
fontconfig
glib
gtk2
gtk3
# vitis_hls gcc needs
glibc.dev
# to compile some xilinx examples
opencl-clhpp
ocl-icd
opencl-headers
# from installLibs.sh
graphviz
(lib.hiPrio gcc)
unzip
nettools
];
multiPkgs = null;
profile = ''
export LC_NUMERIC="en_US.UTF-8"
source ~/Xilinx/Vitis_HLS/*/settings64.sh
h
'';
}).env
See all fhs-shell scripts on [Github repo: scripts/pkgs]({{ site.repo_url }}/scripts/pkgs)
# TODO: 7z need dynamical link 7z.so
# but static compilation prevents this behavior?
{pkgs ? import <nixpkgs> {}}:
let cross = import /home/xieby1/Codes/nix-zig-stdenv {
inherit pkgs;
target = "x86_64-unknown-linux-musl";
};
in
cross.pkgs.p7zip.overrideAttrs (old: {
postPatch = old.postPatch + ''
sed -i '/CC=/d' makefile.machine
sed -i '/CXX=/d' makefile.machine
'';
})
在NixOS上使用Android程序
TLDR: 使用Android Studio提供的Android Emulator体验最好,其次是使用QEMU+x86Android。
Anbox & Waydroid
Anbox & Waydroid属于将Android runtime移植到Linux上的项目。 都需要安装内核模块。
Anbox已未维护。
Waydroid需要Wayland支持。目前我还采用X11。
qemu + x86 Android
虚拟机,没有找到图形和音频的加速方法。基本可用的程度。
- vanilla x86 android: OK
- lineageOS: OK
- same to vanilla x86 android
- wechat not work
- phoenixOS: stuck in booting
# 安装在运行命令后添加-cdrom </path/to/iso> -boot -d
# 运行命令
qemu-system-x86_64 -m 4G -smp 3 -hda ~/Img/andx64_vcm141r5.qcow2 -enable-kvm -display gtk,window-close=off -device AC97
注:-vga virtio不能启动图形界面,原因未探索。
Google Android Emulator
使用nix提供的emulate-app.nix直接运行Google Android Emulator (魔改的QEMU)。
模拟器闪退无法启动,暂时没有尝试去解决。
参考
- https://nixos.wiki/wiki/Android
- SO: Run Android app in qemu-arm?
使用的nix脚本见android.nix
获取apk package和activity
aapt已经淘汰,现在使用的是aapt2,run by nix-alien。 例子,
nix-alien aapt2 dump badging </path/to/apk>
avdmanager找不到镜像
Error: Package path is not valid. Valid system image paths are:ository...
相关问题
- GH: avdmanager create avd fails with "Probably the SDK is read-only" #154898
- SO: error: package path is not valid. valid system image paths are:ository... null
从pkgs/development/mobile/androidenv/compose-android-packages.nix看, platformVersions, systemImageTypes, abiVersions需要和 pkgs/development/mobile/androidenv/repo.json 中的emulator项中的数据匹配。
看repo.json,而不是看sdkmanager --list
,不一定有,但能看到已安装。
不匹配,在nix-build中不会报错,运行过程报上面的错误。
模拟器闪退
和问题类似GH: androidenv.emulateApp fails to start emulator (libvulkan.so.1: full) #121146
报错内容,没解决
cannot add library /nix/store/yz1p6cw09h3im4z7wmx7nshi054fzhw4-emulator-30.8.4/libexec/android-sdk/emulator/qemu/linux-x86_64/lib64/vulkan/libvulkan.so: failed
added library /nix/store/yz1p6cw09h3im4z7wmx7nshi054fzhw4-emulator-30.8.4/libexec/android-sdk/emulator/lib64/vulkan/libvulkan.so
emulator: WARNING: Ignoring invalid http proxy: Bad format: invalid port number (must be decimal)
Device state has been reached
LLVM ERROR: Cannot select: intrinsic %llvm.x86.sse41.pblendvb
debug 方法
参考https://nixos.wiki/wiki/Nixpkgs/Create_and_debug_packages#How_to_install_from_the_local_repository
使用本地nixpkgs,修改,nix-shell看变量 例子:
nix-shell -E 'with import "/home/xieby1/temp-nixpkgs" {config.android_sdk.accept_license = true;}; (androidenv.composeAndroidPackages {includeSystemImages =true; platformVersions=["16"];}).androidsdk'
nix expression调用关系
- emulate-app.nix
- compose-android-packages.nix
- tools.nix
- tools/26.nix
- deploy-androidpackage.nix
- tools/26.nix
- tools.nix
- compose-android-packages.nix
PCI bus not available for hda
https://stackoverflow.com/questions/69297141/android-11-emulator-gives-pci-bus-not-available-for-hda
修改./result/bin/run-test-emulator添加-qemu -machine virt到Launch the emulator的指令后
/nix/store/0q68cfq7rnbw752l89fkxf425v1pb2r6-androidsdk/libexec/android-sdk/emulator/emulator -avd device -no-boot-anim -port $port $NIX_ANDROID_EMULATORFLAGS -qemu -machine virt &
Google Android Studio
使用Android Studio的AVD安装Android emulator最省心。
可以使用微信(公众号闪退),语音视频流畅,小游戏流畅。
redroid
暂时没成功
文档并未提供和各个参数相关的源文件?
#!/usr/bin/env nix-build
# https://nixos.wiki/wiki/Android
# Building Android applications with the Nix package manager: https://sandervanderburg.blogspot.com/2014/02/reproducing-android-app-deployments-or.html
let
# current nixpkgs-unstable
pkgs = import (with import <nixpkgs> {}; fetchFromGitHub {
owner = "NixOS";
repo = "nixpkgs";
rev = "1c851e8c92b76a00ce84167984a7ec7ba2b1f29c";
hash = "sha256-vRxti8pOuXS0rJmqjbD8ueEEFXWSK22ISHoCWkhgzzg=";
}){
config.android_sdk.accept_license = true;
config.allowUnfree = true;
};
in pkgs.androidenv.emulateApp {
name = "androidEmuApp";
app = pkgs.fetchurl {
url = "https://github.com/SimpleMobileTools/Simple-Calendar/releases/download/6.13.5/calendar-release.apk";
sha256 = "12vzcd6klnk38b55szmd5a8ydc70fk6aak31qvlild83jy9z21zk";
};
enableGPU = false;
# get these info by `pkgs/development/mobile/androidenv/repo.json`
# see if installed `sdkmanager --list`
platformVersion = "32";
abiVersion = "x86";
systemImageType = "google_apis";
package = "com.simplemobiletools.calendar.pro";
avdHomeDir = "$HOME/.android";
sdkExtraArgs = {
includeSystemImages = true;
};
}
let
pkgs = import <nixpkgs> {};
squashfuse-with-headers = pkgs.pkgsStatic.squashfuse.overrideAttrs (old: {
src = pkgs.fetchurl {
url = "https://github.com/vasi/squashfuse/archive/e51978c.tar.gz";
hash = "sha256-9UQCmtMNj73k5FQMV0uM3G04uU3wJamNhVGpRB8H00E=";
};
postInstall = ''
mkdir -p $out/include/squashfuse
cp *.h $out/include/squashfuse
'';
});
srcRev = "c1ea7509bc179a05d907baca64f41875662f35f2";
in pkgs.stdenv.mkDerivation {
name = "appimage-runtime";
src = pkgs.fetchFromGitHub {
owner = "AppImage";
repo = "type2-runtime";
rev = "${srcRev}";
sha256 = "1gr853iz1x6pgyav3w1kqaaaz2ybbx67dcg74kj54yrwlakrh165";
};
nativeBuildInputs = with pkgs; [
pkg-config
];
buildInputs = (with pkgs.pkgsStatic; [
squashfuse-with-headers
fuse
zstd
zlib
lz4.out
lzo
lzma.out
]) ++ (with pkgs; [
glibc.static
]);
sourceRoot = "source/src/runtime";
buildPhase = ''
export CFLAGS="-std=gnu99 -s -Os -D_FILE_OFFSET_BITS=64 -DGIT_COMMIT=\"${srcRev}\" -T data_sections.ld -ffunction-sections -fdata-sections -Wl,--gc-sections -static"
export LIBS="-lsquashfuse -lsquashfuse_ll -lzstd -lz -llz4 -llzo2 -llzma"
$CC -I${squashfuse-with-headers}/include/squashfuse -I${pkgs.pkgsStatic.fuse}/include/fuse -o runtime-fuse2.o -c $CFLAGS runtime.c
$CC $CFLAGS runtime-fuse2.o $LIBS -lfuse -o runtime-fuse2
'';
installPhase = ''
mkdir -p $out/bin
cp runtime-fuse2 $out/bin/
'';
}
# in pkgs.mkShell {
# name = "appimage-runtime";
# packages = (with pkgs.pkgsStatic; [
# squashfuse-with-headers
# fuse
# zstd
# zlib
# lz4.out
# lzo
# lzma.out
# ]) ++ (with pkgs; [
# glibc.static
# pkg-config
# ]);
# }
# in (pkgs.buildFHSUserEnv {
# name = "appimage-runtime-fhs";
# targetPkgs = pkgs: (with pkgs.pkgsStatic; [
# squashfuse-with-headers
# fuse
# zstd
# zlib
# lz4.out
# lzo
# lzma.out
# ]) ++ (with pkgs; [
# glibc.static
# pkg-config
# ]);
# }).env
#!/usr/bin/env -S nix-build -o coremarks
{pkgs ? import <nixpkgs> {}}:
let
# function mkCoremark
mkCoremark = {
pkgs ? import <nixpkgs> {},
stdenv ? pkgs.stdenv,
simple ? false,
}:
let
name = "coremark";
variant = pkgs.lib.concatStrings [
"${stdenv.targetPlatform.config}"
# TODO: all zig-env are static?
# (if stdenv.targetPlatform.isStatic then ".static" else "")
(if simple then ".simple" else "")
];
in
stdenv.mkDerivation {
inherit name;
src = pkgs.fetchFromGitHub {
owner = "eembc";
repo = "coremark";
rev = "d26d6fdcefa1f9107ddde70024b73325bfe50ed2";
sha256 = "0kd6bnrnd3f325ypxzn0w5ii4fmc98h16sbvvjikvzhm78y60wz3";
};
preBuild = ''
# no float point insts
export CFLAGS="-DHAS_FLOAT=0"
# simple assumes CC = gcc, this is a bug!
sed -i '/CC =/d' simple/core_portme.mak
${if simple
then "export PORT_DIR=simple"
else ""}
'';
buildFlags = ["compile"];
installPhase = ''
mkdir -p $out/bin
mv coremark.exe $out/bin/${name}.${variant}.exe
'';
};
zig-env-src = pkgs.fetchFromGitHub {
owner = "Cloudef";
repo = "nix-zig-stdenv";
rev = "6de72ec32ecf0cfb9ad9dab5a8400d532e17f8c5";
hash = "sha256-hQHOzjkHWO5YxQb3mgZJOfyIuvbiLFocVCMK/A9HTic=";
};
in
pkgs.symlinkJoin {
name = "coremarks";
paths = [
# x86_64 linux
(mkCoremark {
inherit (import zig-env-src {
target = "x86_64-unknown-linux-gnu";
}) stdenv;
})
# x86_64 linux static
(mkCoremark {
inherit (import zig-env-src {
target = "x86_64-unknown-linux-musl";
}) stdenv;
})
# aarch64 linux
(mkCoremark {
inherit (import zig-env-src {
target = "aarch64-unknown-linux-gnu";
}) stdenv;
})
# aarch64 linux static
(mkCoremark {
inherit (import zig-env-src {
target = "aarch64-unknown-linux-musl";
}) stdenv;
})
# riscv64 linux
# (mkCoremark {
# inherit (import zig-env-src {
# target = "riscv64-unknown-linux-gnu";
# }) stdenv;
# })
# riscv64 linux static
(mkCoremark {
inherit (import zig-env-src {
target = "riscv64-unknown-linux-musl";
}) stdenv;
})
# x86_64 windows
(mkCoremark {
inherit (import zig-env-src {
target = "x86_64-w64-mingw32";
}) stdenv;
simple = true;
})
# x86_64 darwin can only compiled on x86_64/aarch64 darwin
# https://github.com/NixOS/nixpkgs/issues/165804
# while it is possible compile manually inside darling
#(mkCoremark {
# stdenv = pkgs.pkgsCross.x86_64-darwin.stdenv;
#})
];
}
#!/usr/bin/env -S nix-env -i -f
# xieby1: 2022.05.16
with (import <nixpkgs> {crossSystem = "mips-linux";}); {
gdb = lib.lowPrio buildPackages.gdb;
gcc = lib.lowPrio buildPackages.gcc;
}
#!/usr/bin/env nix-build
let
pkgs = import (builtins.fetchTarball {
url = "https://github.com/NixOS/nixpkgs/archive/e60c3e2abb8ae9df3d89820c706cc736fad01ff7.tar.gz";
sha256 = "0vyjpf1jw4cvw7kfbk055faq08q4swz6v1h2mf9zw4r8frhqa73w";
}) {};
in
pkgs.pkgsCross.aarch64-multiplatform.pkgsStatic.glib
#!/usr/bin/env -S nix-build -o fhs_helloworld
# xieby1: 2022.11.17
# inspired by
# https://discourse.nixos.org/t/derivation-that-builds-standard-linux-binaries/21557/4
# https://github.com/NixOS/nixpkgs/compare/master...ElvishJerricco:nixpkgs:run-in-fhs
# TODO-1:
# I have copy all dependencies to a directory (ld-linux-x86-64.so.2, libc.so)
# But result cannot run in chroot, error message is `cannot find libc.so`.
# TODO-2:
# I didn't find a proper package/bundle tool
# * nix-bundle: not work
# * appimage: depends on libfuse.so, cannot run directly on nixos
{ pkgs ? import <nixpkgs> {} }:
let
name = "helloworld";
fhsEnv = pkgs.buildFHSUserEnv {
name = "${name}-fhs";
targetPkgs = pkgs: with pkgs; [
gcc
# gcc-unwrapped binutils-unwrapped
glibc
glibc.dev
];
# refer to https://discourse.nixos.org/t/using-a-raw-gcc-inside-buildfhsuserenv/12864
runScript = (pkgs.writeShellScript "${name}-fhsbuilder" ''
# For gcc-unwrapped and binutils-unwrapped
# export LIBRARY_PATH=/usr/lib
# export C_INCLUDE_PATH=/usr/include
# export CPLUS_INCLUDE_PATH=/usr/include
# export CMAKE_LIBRARY_PATH=/usr/lib
# export CMAKE_INCLUDE_PATH=/usr/include
## TODO: not work? have to add gcc -Wl,--dynamic-linker=/usr/lib64/ld-linux-x86-64.so.2 ?
# export LDFLAGS=--dynamic-linker=/usr/lib64/ld-linux-x86-64.so.2
# For gcc
export NIX_LDFLAGS="--dynamic-linker=/usr/lib64/ld-linux-x86-64.so.2"
gcc $src -o $out
'');
};
in
builtins.derivation {
inherit name;
system = builtins.currentSystem;
src = builtins.toFile "${name}.c" ''
#include <stdio.h>
int main(void) {
printf("Hello, world! \n");
return 0;
}
'';
builder = "${fhsEnv}/bin/${fhsEnv.name}";
}
let
name = "perl";
pkgs = import <nixpkgs> {};
fhsEnv = pkgs.buildFHSUserEnv {
name = "${name}-fhs";
targetPkgs = pkgs: with pkgs; [
gnumake
];
runScript = (pkgs.writeShellScript "${name}-fhsbuilder" ''
ls
cd $src/tools/src
ls
DOPERL=1 ./buildtools
'');
};
in builtins.derivation {
inherit name;
system = builtins.currentSystem;
src = /home/xieby1/Codes/spec2000;
builder = "${fhsEnv}/bin/${fhsEnv.name}";
}
#!/usr/bin/env -S nix-build -o nix-binary-tarballs
Nix official installer (new)
Use nix (>2.18) binary-tarball script, which has not been merged into mainline nixpkgs.
See nix-binary-tarballs.nix for current nix binary-tarball script.
let
pkgs = import <nixpkgs> {};
nix_src = pkgs.fetchFromGitHub {
owner = "NixOS";
repo = "nix";
rev = "d0c7da131fb64526bc72144949b6955c25367d92";
hash = "sha256-Z4RlluZjNXH5BdJiXoe0k43Ry9ptK3jHAsKjlQ3jVZg=";
};
in pkgs.symlinkJoin {
name = "nix-binary-tarballs";
paths = [
(pkgs.callPackage "${nix_src}/scripts/binary-tarball.nix" {})
(pkgs.callPackage "${nix_src}/scripts/binary-tarball.nix" {
nix = pkgs.pkgsCross.riscv64.nix;
system = pkgs.pkgsCross.riscv64.nix.stdenv.system;
})
(pkgs.callPackage "${nix_src}/scripts/binary-tarball.nix" {
nix = pkgs.pkgsCross.loongarch64-linux.nix;
system = pkgs.pkgsCross.loongarch64-linux.nix.stdenv.system;
})
];
}
#!/usr/bin/env -S nix-build -o nix-binary-tarballs
Nix official installer
The binaryTarball
function is extracted from nix-2.18's flake.nix
Noted: Although the latest nix has seperate binaryTarball as a independent file, current unstable nixpkgs still use nix-2.18, which embed binaryTarball function in nix/flake.nix. If reuse the binaryTarball file in new nix, then this script can be hugely simplified, e.g. nix-binary-tarballs-new.nix. As long as, new nix is merged to mainline nixpkgs, I will deprecate this script and adopt the new script.
let
pkgs = import <nixpkgs> {};
binaryTarball =
{ nix
, buildPackages
, cacert
}:
let
installerClosureInfo = buildPackages.closureInfo { rootPaths = [ nix cacert ]; };
in buildPackages.runCommand "nix-binary-tarball-${nix.version}" {
#nativeBuildInputs = lib.optional (system != "aarch64-linux") shellcheck;
meta.description = "Distribution-independent Nix bootstrap binaries for ${nix.stdenv.system}";
} ''
cp ${installerClosureInfo}/registration $TMPDIR/reginfo
cp ${nix.src}/scripts/create-darwin-volume.sh $TMPDIR/create-darwin-volume.sh
substitute ${nix.src}/scripts/install-nix-from-closure.sh $TMPDIR/install \
--subst-var-by nix ${nix} \
--subst-var-by cacert ${cacert}
substitute ${nix.src}/scripts/install-darwin-multi-user.sh $TMPDIR/install-darwin-multi-user.sh \
--subst-var-by nix ${nix} \
--subst-var-by cacert ${cacert}
substitute ${nix.src}/scripts/install-systemd-multi-user.sh $TMPDIR/install-systemd-multi-user.sh \
--subst-var-by nix ${nix} \
--subst-var-by cacert ${cacert}
substitute ${nix.src}/scripts/install-multi-user.sh $TMPDIR/install-multi-user \
--subst-var-by nix ${nix} \
--subst-var-by cacert ${cacert}
if type -p shellcheck; then
# SC1090: Don't worry about not being able to find
# $nix/etc/profile.d/nix.sh
shellcheck --exclude SC1090 $TMPDIR/install
shellcheck $TMPDIR/create-darwin-volume.sh
shellcheck $TMPDIR/install-darwin-multi-user.sh
shellcheck $TMPDIR/install-systemd-multi-user.sh
# SC1091: Don't panic about not being able to source
# /etc/profile
# SC2002: Ignore "useless cat" "error", when loading
# .reginfo, as the cat is a much cleaner
# implementation, even though it is "useless"
# SC2116: Allow ROOT_HOME=$(echo ~root) for resolving
# root's home directory
shellcheck --external-sources \
--exclude SC1091,SC2002,SC2116 $TMPDIR/install-multi-user
fi
chmod +x $TMPDIR/install
chmod +x $TMPDIR/create-darwin-volume.sh
chmod +x $TMPDIR/install-darwin-multi-user.sh
chmod +x $TMPDIR/install-systemd-multi-user.sh
chmod +x $TMPDIR/install-multi-user
dir=nix-${nix.version}-${nix.stdenv.system}
fn=$out/$dir.tar.xz
mkdir -p $out/nix-support
echo "file binary-dist $fn" >> $out/nix-support/hydra-build-products
tar cvfJ $fn \
--owner=0 --group=0 --mode=u+rw,uga+r \
--mtime='1970-01-01' \
--absolute-names \
--hard-dereference \
--transform "s,$TMPDIR/install,$dir/install," \
--transform "s,$TMPDIR/create-darwin-volume.sh,$dir/create-darwin-volume.sh," \
--transform "s,$TMPDIR/reginfo,$dir/.reginfo," \
--transform "s,$NIX_STORE,$dir/store,S" \
$TMPDIR/install \
$TMPDIR/create-darwin-volume.sh \
$TMPDIR/install-darwin-multi-user.sh \
$TMPDIR/install-systemd-multi-user.sh \
$TMPDIR/install-multi-user \
$TMPDIR/reginfo \
$(cat ${installerClosureInfo}/store-paths)
'';
in pkgs.symlinkJoin {
name = "nix-binary-tarballs";
paths = [
# local nix installer
(pkgs.callPackage binaryTarball {})
# riscv64 nix installer
(pkgs.callPackage binaryTarball {nix=pkgs.pkgsCross.riscv64.nix;})
# loongarch64 nix installer
(pkgs.callPackage binaryTarball {nix=pkgs.pkgsCross.loongarch64-linux.nix;})
];
}
🐳Nix Docker🐋 for Multiple ISAs
This script is inspired by https://github.com/nix-community/docker-nixpkgs/images/nix
currently: this riscv64 nix docker can nix-env -iA nixpkgs.hello/tmux
and so on,
which is completely built from source including toolchains (stdenv) in x86/aarch64/riscv64/...
{ pkgs ? import <nixpkgs> {}
, pkgsCross ? pkgs
, useTmux ? true
}:
let
name = "nix-docker-${pkgsCross.stdenv.system}";
image = pkgs.dockerTools.buildImageWithNixDb {
inherit name;
copyToRoot = pkgs.buildEnv {
name = "image-root";
paths = (with pkgsCross; [
bashInteractive
cacert
coreutils
file
gitMinimal
gnutar
nix
openssh
vim
wget
]
++ lib.optional useTmux (tmux.override {withSystemd=false;})
) ++ [
./imageFiles
];
};
extraCommands = ''
# for /usr/bin/env
mkdir usr
ln -s bin usr/bin
# make sure /tmp exists
mkdir -m 1777 tmp
# need a HOME
mkdir -vp root
'';
config = {
Cmd = if useTmux
then [ "/bin/tmux" ]
else [ "/bin/bash" ];
Env = [
"NIX_BUILD_SHELL=/bin/bash"
"PAGER=cat"
"PATH=/bin"
"SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"
"USER=root"
];
};
};
in pkgs.writeShellScriptBin name ''
command -v podman &> /dev/null || echo "podman not found TODO: install" || exit 1
outName="$(basename ${image})"
outHash=$(echo "$outName" | cut -d - -f 1)
imageName=localhost/${name}:$outHash
# check whether image has been loaded
podman images $imageName | grep ${name} | grep $outHash &> /dev/null
# image has not been loaded, then load it
if [[ $? != 0 ]]; then
podman load -i ${image}
fi
BINFMTS=""
for binfmt in /run/binfmt/*; do
BINFMTS+=" -v $(realpath $binfmt):$binfmt"
done
containerName=${name}-$outHash
# run container
OPTS=(
"--name=$containerName"
"$BINFMTS"
"--network=host"
"-it"
"$imageName"
)
eval "podman run ''${OPTS[@]}"
podman commit $containerName $imageName
podman rm $containerName
''
#!/usr/bin/env nix-build
Instantiatio of nix dockers
For more details, see default.nix
{ pkgs ? import <nixpkgs> {}
, ...
}: [
x86_64 docker
(import ./. {inherit pkgs; pkgsCross=pkgs.pkgsCross.gnu64;})
aarhc64 docker
(import ./. {inherit pkgs; pkgsCross=pkgs.pkgsCross.aarch64-multiplatform;})
riscv64 docker
(import ./. {inherit pkgs; pkgsCross=pkgs.pkgsCross.riscv64;})
]
let
flake-compat = import (builtins.fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/0f9255e01c2351cc7d116c072cb317785dd33b33.tar.gz";
sha256 = "0m9grvfsbwmvgwaxvdzv6cmyvjnlww004gfxjvcl806ndqaxzy4j";
});
nix2nvchad = flake-compat {
src= builtins.fetchTarball {
url = "https://github.com/nix-community/nix4nvchad/archive/360ff667893eab066b3db906a856de2956fc710e.tar.gz";
sha256 = "01gvcg7nhzpizp4yzvww2x42i1ifsb7sygfwmqzrshqz47p1ir5y";
};
};
in nix2nvchad.defaultNix.packages."${builtins.currentSystem}".default
#!/usr/bin/env nix-build
# xieby1: 2022.05.24
# build static qemu (current version 6.1.1) into ./result/
# $ nix-build <this-file> -A qemu
# build static qemu-3.1.0 into ./result/
# $ nix-build <this-file> -A qemu31
# build and install static qemu
# $ nix-env -i -f <this-file> -A qemu
# build and install static qemu-3.1.0
# $ nix-env -i -f <this-file> -A qemu31
let
# https://lazamar.co.uk/nix-versions
pinnedPkgsForQemu31Src = builtins.fetchTarball {
name = "nixos-20.03-with-qemu-3.1.0";
url = "https://github.com/NixOS/nixpkgs/archive/81d4e65891f92e8e72c244da663c83c1e40dc919.tar.gz";
sha256 = "0dk1k1zqy2bnp9gsy9mdxk0idkazyvnmqrj2jpbwzfnhjzpmzq1w";
};
pinnedPkgsSrc = builtins.fetchTarball {
name = "nixos-static-qemu";
url = "https://github.com/nixos/nixpkgs/archive/e7d63bd0d50df412f5a1d8acfa3caae75522e347.tar.gz";
sha256 = "132pc4f9ixisyv4117p2jirmlyl6sd76bfaz33rhlcwakg7bhjm7";
};
pkgsForQemu31 = import pinnedPkgsForQemu31Src {};
pkgs = import pinnedPkgsSrc {};
mypkgs = import pinnedPkgsSrc {
overlays = [(self: super: {
cdparanoiaIII = super.pkgsStatic.cdparanoiaIII.overrideAttrs (old: {
preConfigure = old.preConfigure + ''
cp ${super.gnu-config}/config.sub configure.sub
cp ${super.gnu-config}/config.guess configure.guess
'';
# Makefile needs this to compile static
STATIC="TRUE";
buildPhase = ''
make lib
make cdparanoia
'';
preInstallPhases = ["preInstallPhase"];
preInstallPhase = ''
sed -i '/so/d' Makefile
'';
});
liburing = super.pkgsStatic.liburing.overrideDerivation (old: {
configureFlags = "";
ENABLE_SHARED = 0;
});
# p11-kit cannot be used as a static library
# https://github.com/p11-glue/p11-kit/issues/355
p11-kit = super.pkgsMusl.p11-kit;
# gnutls depends on p11-kit
gnutls = super.pkgsMusl.gnutls;
pam = super.pkgsStatic.openpam;
# support both static and shared
libselinux = (super.pkgsMusl.libselinux.override {
libsepol = super.pkgsStatic.libsepol;
}).overrideAttrs (old: {
makeFlags = old.makeFlags ++ [
"LIBDIR=$(out)/lib"
];
});
glib = (super.pkgsStatic.glib.override {
meson = pkgs.meson;
ninja = pkgs.ninja;
pkg-config = pkgs.pkg-config;
perl = pkgs.perl;
python3 = pkgs.python3;
gettext = pkgs.gettext;
gtk-doc = pkgs.gtk-doc;
docbook_xsl = pkgs.docbook_xsl;
docbook_xml_dtd_45 = pkgs.docbook_xml_dtd_45;
libxml2 = pkgs.libxml2;
}).overrideAttrs (old: {
outputs = super.lib.lists.remove "devdoc" old.outputs;
buildInputs = old.buildInputs ++ [
super.pkgsStatic.libsepol
];
preBuild = ''
sed -i "s/get_option('libmount')/get_option('libmount'), static: true/g" ../meson.build
sed -i "s/get_option('selinux')/get_option('selinux'), static: true/g" ../meson.build
'';
# no devdoc from non-static glibc
# ${pname} & ${version} is correct due to lazy assignment
postInstall = pkgs.glib.postInstall;
});
gtk3 = super.pkgsStatic.gtk3.override {
trackerSupport = false;
cupsSupport = false;
withGtkDoc = false;
# nativeBuildInputs
inherit (pkgs) gettext gobject-introspection makeWrapper meson ninja
pkg-config python3 sassc docbook_xml_dtd_43 docbook-xsl-nons gtk-doc libxml2;
};
qemu = ((super.pkgsStatic.qemu.override {
alsaSupport = false;
spiceSupport = false;
sdlSupport = false;
smartcardSupport = false;
gtkSupport = false;
pulseSupport = false;
# nativeBuildInputs
makeWrapper = pkgs.makeWrapper;
python = pkgs.python3;
pkg-config = pkgs.pkg-config;
flex = pkgs.flex;
bison = pkgs.bison;
meson = pkgs.meson;
ninja = pkgs.ninja;
perl = pkgs.perl;
}).overrideAttrs (old: {
nativeBuildInputs = old.nativeBuildInputs ++ [
pkgs.binutils
# perl as nativeBuildInputs has been added in nixpkgs master
# while it is backported to nixpkgs 21.11 (nixos 21.11).
# If without perl as nativeBuildInputs,
# ./scripts/shaderinclude.pl can not be patchShebangs'ed.
pkgs.perl # without it cannot patchShebangs
];
# qemu-6.1.1 has contained sigrtminmax patch, can not be patched again
patches = builtins.filter (
x: ! super.lib.hasSuffix "sigrtminmax.patch" x
) old.patches;
})).overrideDerivation (old: let
# qemu configure uses "--static" instead of standard "--disable-shared" and "--enable-static"
configureFlags_no_DS = super.lib.lists.remove "--disable-shared" old.configureFlags;
configureFlags_no_DS_no_ES = super.lib.lists.remove "--enable-static" configureFlags_no_DS;
in {
configureFlags = configureFlags_no_DS_no_ES ++ [
"--static"
# "--target-list-exclude="
"--target-list=x86_64-softmmu"
];
});
qemu31 = (((super.callPackage (
pinnedPkgsForQemu31Src + "/pkgs/applications/virtualization/qemu/default.nix"
) {
inherit (super.darwin.apple_sdk.frameworks) CoreServices Cocoa Hypervisor;
inherit (super.darwin.stubs) rez setfile;
}).override {
# In nixpkgs 20.03, stdenv contains lib attr.
stdenv = pkgs.pkgsStatic.stdenv // {lib = super.lib;};
alsaLib = null;
spiceSupport = false;
sdlSupport = false;
smartcardSupport = false;
gtkSupport = false;
pulseSupport = false;
# nativeBuildInputs
makeWrapper = pkgs.makeWrapper;
python2 = pkgs.python2;
pkgconfig = pkgs.pkgconfig;
flex = pkgs.flex;
bison = pkgs.bison;
perl = pkgs.perl;
}).overrideAttrs (old: {
nativeBuildInputs = old.nativeBuildInputs ++ [
# Several issues report ld version >= 2.34 will failed due to
# PHDR segment not covered by LOAD segment.
# https://github.com/OpenOrbis/OpenOrbis-PS4-Toolchain/issues/122
# https://github.com/genodelabs/genode/issues/4003
# So I downgrade ld version < 2.34.
# I still do not figure out why the same version ld in
# qemu 6.1.1 static works correctly?
pkgsForQemu31.binutils
];
})).overrideDerivation (old: let
# drop audio configure flag
configureFlags_no_audio = builtins.filter (
x: ! super.lib.hasPrefix "--audio-drv-list" x
) old.configureFlags;
# qemu configure uses "--static" instead of standard "--disable-shared" and "--enable-static"
configureFlags_no_DS = super.lib.lists.remove "--disable-shared" configureFlags_no_audio;
configureFlags_no_DS_no_ES = super.lib.lists.remove "--enable-static" configureFlags_no_DS;
in {
configureFlags = configureFlags_no_DS_no_ES ++ [
# "--static"
# "--target-list-exclude="
"--target-list=x86_64-softmmu"
"--disable-gnutls"
"--disable-tools"
];
makeFlags = [
# "V=1" # qemu Makefile verbose
# It is neccessary to use ld in binutils, otherwise pc-bios build will fail.
# In qemu 6.1.1 static, it is using ld in binutils, instead of ld from musl-gcc
"AR=${pkgs.binutils-unwrapped}/bin/ar"
"AS=${pkgs.binutils}/bin/as"
"LD=${pkgs.binutils}/bin/ld"
"NIX_BINTOOLS=${pkgs.binutils}"
];
});
})];
};
in
{
inherit (mypkgs.pkgsStatic) qemu qemu31;
}
#!/usr/bin/env nix-build
# xieby1: 2022.05.24
# build static qemu (current version 6.1.1) into ./result/
# $ nix-build <this-file> -A qemu
# build static qemu-3.1.0 into ./result/
# $ nix-build <this-file> -A qemu31
# build and install static qemu
# $ nix-env -i -f <this-file> -A qemu
# build and install static qemu-3.1.0
# $ nix-env -i -f <this-file> -A qemu31
let
pinnedPkgsSrc = builtins.fetchTarball {
name = "nixos-static-qemu";
url = "https://github.com/nixos/nixpkgs/archive/e7d63bd0d50df412f5a1d8acfa3caae75522e347.tar.gz";
sha256 = "132pc4f9ixisyv4117p2jirmlyl6sd76bfaz33rhlcwakg7bhjm7";
};
# pkgs = import pinnedPkgsSrc {};
# mypkgs = import pinnedPkgsSrc {
pkgs = import <nixpkgs> {};
mypkgs = import <nixpkgs> {
overlays = [(self: super: {
cdparanoiaIII = super.pkgsStatic.cdparanoiaIII.overrideAttrs (old: {
preConfigure = old.preConfigure + ''
cp ${super.gnu-config}/config.sub configure.sub
cp ${super.gnu-config}/config.guess configure.guess
'';
# Makefile needs this to compile static
STATIC="TRUE";
buildPhase = ''
make lib
make cdparanoia
'';
preInstallPhases = ["preInstallPhase"];
preInstallPhase = ''
sed -i '/so/d' Makefile
'';
});
liburing = super.pkgsStatic.liburing.overrideDerivation (old: {
configureFlags = "";
ENABLE_SHARED = 0;
});
# p11-kit cannot be used as a static library
# https://github.com/p11-glue/p11-kit/issues/355
p11-kit = super.pkgsMusl.p11-kit;
# gnutls depends on p11-kit
gnutls = super.pkgsMusl.gnutls;
pam = super.pkgsStatic.openpam;
# support both static and shared
libselinux = (super.pkgsMusl.libselinux.override {
libsepol = super.pkgsStatic.libsepol;
}).overrideAttrs (old: {
makeFlags = old.makeFlags ++ [
"LIBDIR=$(out)/lib"
];
});
glib = (super.pkgsStatic.glib.override {
meson = pkgs.meson;
ninja = pkgs.ninja;
pkg-config = pkgs.pkg-config;
perl = pkgs.perl;
python3 = pkgs.python3;
gettext = pkgs.gettext;
gtk-doc = pkgs.gtk-doc;
docbook_xsl = pkgs.docbook_xsl;
docbook_xml_dtd_45 = pkgs.docbook_xml_dtd_45;
libxml2 = pkgs.libxml2;
}).overrideAttrs (old: {
outputs = super.lib.lists.remove "devdoc" old.outputs;
buildInputs = old.buildInputs ++ [
super.pkgsStatic.libsepol
];
preBuild = ''
sed -i "s/get_option('libmount')/get_option('libmount'), static: true/g" ../meson.build
sed -i "s/get_option('selinux')/get_option('selinux'), static: true/g" ../meson.build
'';
# no devdoc from non-static glibc
# ${pname} & ${version} is correct due to lazy assignment
postInstall = pkgs.glib.postInstall;
});
gtk3 = super.pkgsStatic.gtk3.override {
trackerSupport = false;
cupsSupport = false;
withGtkDoc = false;
# nativeBuildInputs
inherit (pkgs) gettext gobject-introspection makeWrapper meson ninja
pkg-config python3 sassc docbook_xml_dtd_43 docbook-xsl-nons gtk-doc libxml2;
};
qemu = ((super.pkgsStatic.qemu.override {
alsaSupport = false;
spiceSupport = false;
sdlSupport = false;
smartcardSupport = false;
gtkSupport = false;
pulseSupport = false;
# nativeBuildInputs
makeWrapper = pkgs.makeWrapper;
python = pkgs.python3;
pkg-config = pkgs.pkg-config;
flex = pkgs.flex;
bison = pkgs.bison;
meson = pkgs.meson;
ninja = pkgs.ninja;
perl = pkgs.perl;
}).overrideAttrs (old: {
nativeBuildInputs = old.nativeBuildInputs ++ [
pkgs.binutils
# perl as nativeBuildInputs has been added in nixpkgs master
# while it is backported to nixpkgs 21.11 (nixos 21.11).
# If without perl as nativeBuildInputs,
# ./scripts/shaderinclude.pl can not be patchShebangs'ed.
pkgs.perl # without it cannot patchShebangs
];
# qemu-6.1.1 has contained sigrtminmax patch, can not be patched again
patches = builtins.filter (
x: ! super.lib.hasSuffix "sigrtminmax.patch" x
) old.patches;
})).overrideDerivation (old: let
# qemu configure uses "--static" instead of standard "--disable-shared" and "--enable-static"
configureFlags_no_DS = super.lib.lists.remove "--disable-shared" old.configureFlags;
configureFlags_no_DS_no_ES = super.lib.lists.remove "--enable-static" configureFlags_no_DS;
in {
configureFlags = configureFlags_no_DS_no_ES ++ [
"--static"
# "--target-list-exclude="
"--target-list=x86_64-softmmu"
];
});
})];
};
in
{
inherit (mypkgs.pkgsStatic.pkgsCross.riscv64) qemu;
}
#!/usr/bin/env nix-build
# xieby1: 2022.05.24
# build static qemu (current version 6.1.1) into ./result/
# $ nix-build <this-file> -A qemu
# build static qemu-3.1.0 into ./result/
# $ nix-build <this-file> -A qemu31
# build and install static qemu
# $ nix-env -i -f <this-file> -A qemu
# build and install static qemu-3.1.0
# $ nix-env -i -f <this-file> -A qemu31
let
pinnedPkgsSrc = builtins.fetchTarball {
name = "nixos-static-qemu";
url = "https://github.com/nixos/nixpkgs/archive/e7d63bd0d50df412f5a1d8acfa3caae75522e347.tar.gz";
sha256 = "132pc4f9ixisyv4117p2jirmlyl6sd76bfaz33rhlcwakg7bhjm7";
};
# pkgs = import pinnedPkgsSrc {};
# mypkgs = import pinnedPkgsSrc {
pkgs = import <nixpkgs> {};
mypkgs = import <nixpkgs> {
overlays = [(self: super: {
cdparanoiaIII = super.pkgsStatic.cdparanoiaIII.overrideAttrs (old: {
preConfigure = old.preConfigure + ''
cp ${super.gnu-config}/config.sub configure.sub
cp ${super.gnu-config}/config.guess configure.guess
'';
# Makefile needs this to compile static
STATIC="TRUE";
buildPhase = ''
make lib
make cdparanoia
'';
preInstallPhases = ["preInstallPhase"];
preInstallPhase = ''
sed -i '/so/d' Makefile
'';
});
liburing = super.pkgsStatic.liburing.overrideDerivation (old: {
configureFlags = "";
ENABLE_SHARED = 0;
});
# p11-kit cannot be used as a static library
# https://github.com/p11-glue/p11-kit/issues/355
p11-kit = super.pkgsMusl.p11-kit;
# gnutls depends on p11-kit
gnutls = super.pkgsMusl.gnutls;
pam = super.pkgsStatic.openpam;
# support both static and shared
libselinux = (super.pkgsMusl.libselinux.override {
libsepol = super.pkgsStatic.libsepol;
}).overrideAttrs (old: {
makeFlags = old.makeFlags ++ [
"LIBDIR=$(out)/lib"
];
});
glib = (super.pkgsStatic.glib.override {
meson = pkgs.meson;
ninja = pkgs.ninja;
pkg-config = pkgs.pkg-config;
perl = pkgs.perl;
python3 = pkgs.python3;
gettext = pkgs.gettext;
gtk-doc = pkgs.gtk-doc;
docbook_xsl = pkgs.docbook_xsl;
docbook_xml_dtd_45 = pkgs.docbook_xml_dtd_45;
libxml2 = pkgs.libxml2;
}).overrideAttrs (old: {
outputs = super.lib.lists.remove "devdoc" old.outputs;
buildInputs = old.buildInputs ++ [
super.pkgsStatic.libsepol
];
preBuild = ''
sed -i "s/get_option('libmount')/get_option('libmount'), static: true/g" ../meson.build
sed -i "s/get_option('selinux')/get_option('selinux'), static: true/g" ../meson.build
'';
# no devdoc from non-static glibc
# ${pname} & ${version} is correct due to lazy assignment
postInstall = pkgs.glib.postInstall;
});
gtk3 = super.pkgsStatic.gtk3.override {
trackerSupport = false;
cupsSupport = false;
withGtkDoc = false;
# nativeBuildInputs
inherit (pkgs) gettext gobject-introspection makeWrapper meson ninja
pkg-config python3 sassc docbook_xml_dtd_43 docbook-xsl-nons gtk-doc libxml2;
};
qemu = ((super.pkgsStatic.qemu.override {
alsaSupport = false;
spiceSupport = false;
sdlSupport = false;
smartcardSupport = false;
gtkSupport = false;
pulseSupport = false;
# nativeBuildInputs
makeWrapper = pkgs.makeWrapper;
python = pkgs.python3;
pkg-config = pkgs.pkg-config;
flex = pkgs.flex;
bison = pkgs.bison;
meson = pkgs.meson;
ninja = pkgs.ninja;
perl = pkgs.perl;
}).overrideAttrs (old: {
nativeBuildInputs = old.nativeBuildInputs ++ [
pkgs.binutils
# perl as nativeBuildInputs has been added in nixpkgs master
# while it is backported to nixpkgs 21.11 (nixos 21.11).
# If without perl as nativeBuildInputs,
# ./scripts/shaderinclude.pl can not be patchShebangs'ed.
pkgs.perl # without it cannot patchShebangs
];
# qemu-6.1.1 has contained sigrtminmax patch, can not be patched again
patches = builtins.filter (
x: ! super.lib.hasSuffix "sigrtminmax.patch" x
) old.patches;
})).overrideDerivation (old: let
# qemu configure uses "--static" instead of standard "--disable-shared" and "--enable-static"
configureFlags_no_DS = super.lib.lists.remove "--disable-shared" old.configureFlags;
configureFlags_no_DS_no_ES = super.lib.lists.remove "--enable-static" configureFlags_no_DS;
in {
configureFlags = configureFlags_no_DS_no_ES ++ [
"--static"
# "--target-list-exclude="
"--target-list=x86_64-softmmu"
];
});
})];
};
in
{
inherit (mypkgs.pkgsStatic.pkgsCross.riscv64) qemu;
}
#!/usr/bin/env nix-build
# xieby1: 2022.05.24
# build static qemu (current version 6.1.1) into ./result/
# $ nix-build <this-file> -A qemu
# build static qemu-3.1.0 into ./result/
# $ nix-build <this-file> -A qemu31
# build and install static qemu
# $ nix-env -i -f <this-file> -A qemu
# build and install static qemu-3.1.0
# $ nix-env -i -f <this-file> -A qemu31
let
# https://lazamar.co.uk/nix-versions
pinnedPkgsForQemu31Src = builtins.fetchTarball {
name = "nixos-20.03-with-qemu-3.1.0";
url = "https://github.com/NixOS/nixpkgs/archive/81d4e65891f92e8e72c244da663c83c1e40dc919.tar.gz";
sha256 = "0dk1k1zqy2bnp9gsy9mdxk0idkazyvnmqrj2jpbwzfnhjzpmzq1w";
};
pinnedPkgsSrc = builtins.fetchTarball {
name = "nixos-static-qemu";
url = "https://github.com/nixos/nixpkgs/archive/e7d63bd0d50df412f5a1d8acfa3caae75522e347.tar.gz";
sha256 = "132pc4f9ixisyv4117p2jirmlyl6sd76bfaz33rhlcwakg7bhjm7";
};
pkgsForQemu31 = import pinnedPkgsForQemu31Src {};
pkgs = import pinnedPkgsSrc {};
mypkgs = import pinnedPkgsSrc {
overlays = [(self: super: {
cdparanoiaIII = super.pkgsStatic.cdparanoiaIII.overrideAttrs (old: {
preConfigure = old.preConfigure + ''
cp ${super.gnu-config}/config.sub configure.sub
cp ${super.gnu-config}/config.guess configure.guess
'';
# Makefile needs this to compile static
STATIC="TRUE";
buildPhase = ''
make lib
make cdparanoia
'';
preInstallPhases = ["preInstallPhase"];
preInstallPhase = ''
sed -i '/so/d' Makefile
'';
});
liburing = super.pkgsStatic.liburing.overrideDerivation (old: {
configureFlags = "";
ENABLE_SHARED = 0;
});
# p11-kit cannot be used as a static library
# https://github.com/p11-glue/p11-kit/issues/355
p11-kit = super.pkgsMusl.p11-kit;
# gnutls depends on p11-kit
gnutls = super.pkgsMusl.gnutls;
pam = super.pkgsStatic.openpam;
# support both static and shared
libselinux = (super.pkgsMusl.libselinux.override {
libsepol = super.pkgsStatic.libsepol;
}).overrideAttrs (old: {
makeFlags = old.makeFlags ++ [
"LIBDIR=$(out)/lib"
];
});
glib = (super.pkgsStatic.glib.override {
meson = pkgs.meson;
ninja = pkgs.ninja;
pkg-config = pkgs.pkg-config;
perl = pkgs.perl;
python3 = pkgs.python3;
gettext = pkgs.gettext;
gtk-doc = pkgs.gtk-doc;
docbook_xsl = pkgs.docbook_xsl;
docbook_xml_dtd_45 = pkgs.docbook_xml_dtd_45;
libxml2 = pkgs.libxml2;
}).overrideAttrs (old: {
outputs = super.lib.lists.remove "devdoc" old.outputs;
buildInputs = old.buildInputs ++ [
super.pkgsStatic.libsepol
];
preBuild = ''
sed -i "s/get_option('libmount')/get_option('libmount'), static: true/g" ../meson.build
sed -i "s/get_option('selinux')/get_option('selinux'), static: true/g" ../meson.build
'';
# no devdoc from non-static glibc
# ${pname} & ${version} is correct due to lazy assignment
postInstall = pkgs.glib.postInstall;
});
gtk3 = super.pkgsStatic.gtk3.override {
trackerSupport = false;
cupsSupport = false;
withGtkDoc = false;
# nativeBuildInputs
inherit (pkgs) gettext gobject-introspection makeWrapper meson ninja
pkg-config python3 sassc docbook_xml_dtd_43 docbook-xsl-nons gtk-doc libxml2;
};
qemu = ((super.pkgsStatic.qemu.override {
alsaSupport = false;
spiceSupport = false;
sdlSupport = false;
smartcardSupport = false;
gtkSupport = false;
pulseSupport = false;
# nativeBuildInputs
makeWrapper = pkgs.makeWrapper;
python = pkgs.python3;
pkg-config = pkgs.pkg-config;
flex = pkgs.flex;
bison = pkgs.bison;
meson = pkgs.meson;
ninja = pkgs.ninja;
perl = pkgs.perl;
}).overrideAttrs (old: {
nativeBuildInputs = old.nativeBuildInputs ++ [
pkgs.binutils
# perl as nativeBuildInputs has been added in nixpkgs master
# while it is backported to nixpkgs 21.11 (nixos 21.11).
# If without perl as nativeBuildInputs,
# ./scripts/shaderinclude.pl can not be patchShebangs'ed.
pkgs.perl # without it cannot patchShebangs
];
# qemu-6.1.1 has contained sigrtminmax patch, can not be patched again
patches = builtins.filter (
x: ! super.lib.hasSuffix "sigrtminmax.patch" x
) old.patches;
})).overrideDerivation (old: let
# qemu configure uses "--static" instead of standard "--disable-shared" and "--enable-static"
configureFlags_no_DS = super.lib.lists.remove "--disable-shared" old.configureFlags;
configureFlags_no_DS_no_ES = super.lib.lists.remove "--enable-static" configureFlags_no_DS;
in {
configureFlags = configureFlags_no_DS_no_ES ++ [
"--static"
# "--target-list-exclude="
"--target-list=x86_64-softmmu"
];
});
qemu31 = (((super.callPackage (
pinnedPkgsForQemu31Src + "/pkgs/applications/virtualization/qemu/default.nix"
) {
inherit (super.darwin.apple_sdk.frameworks) CoreServices Cocoa Hypervisor;
inherit (super.darwin.stubs) rez setfile;
}).override {
# In nixpkgs 20.03, stdenv contains lib attr.
stdenv = pkgs.pkgsStatic.stdenv // {lib = super.lib;};
alsaLib = null;
spiceSupport = false;
sdlSupport = false;
smartcardSupport = false;
gtkSupport = false;
pulseSupport = false;
# nativeBuildInputs
makeWrapper = pkgs.makeWrapper;
python2 = pkgs.python2;
pkgconfig = pkgs.pkgconfig;
flex = pkgs.flex;
bison = pkgs.bison;
perl = pkgs.perl;
}).overrideAttrs (old: {
nativeBuildInputs = old.nativeBuildInputs ++ [
# Several issues report ld version >= 2.34 will failed due to
# PHDR segment not covered by LOAD segment.
# https://github.com/OpenOrbis/OpenOrbis-PS4-Toolchain/issues/122
# https://github.com/genodelabs/genode/issues/4003
# So I downgrade ld version < 2.34.
# I still do not figure out why the same version ld in
# qemu 6.1.1 static works correctly?
pkgsForQemu31.binutils
];
})).overrideDerivation (old: let
# drop audio configure flag
configureFlags_no_audio = builtins.filter (
x: ! super.lib.hasPrefix "--audio-drv-list" x
) old.configureFlags;
# qemu configure uses "--static" instead of standard "--disable-shared" and "--enable-static"
configureFlags_no_DS = super.lib.lists.remove "--disable-shared" configureFlags_no_audio;
configureFlags_no_DS_no_ES = super.lib.lists.remove "--enable-static" configureFlags_no_DS;
in {
configureFlags = configureFlags_no_DS_no_ES ++ [
# "--static"
# "--target-list-exclude="
"--target-list=x86_64-softmmu"
"--disable-gnutls"
"--disable-tools"
];
makeFlags = [
# "V=1" # qemu Makefile verbose
# It is neccessary to use ld in binutils, otherwise pc-bios build will fail.
# In qemu 6.1.1 static, it is using ld in binutils, instead of ld from musl-gcc
"AR=${pkgs.binutils-unwrapped}/bin/ar"
"AS=${pkgs.binutils}/bin/as"
"LD=${pkgs.binutils}/bin/ld"
"NIX_BINTOOLS=${pkgs.binutils}"
];
});
})];
};
in
{
inherit (mypkgs.pkgsStatic) qemu qemu31;
}
#!/usr/bin/env nix-build
# TODO
# Ref: ~/Documents/Tech/BT/QEMU/test.md
let
pkgs = import <nixpkgs> {};
in
pkgs.stdenv.mkDerivation {
buildInputs = with pkgs; [
# configure needs
ninja
pkg-config
glib
# make needs
glibc.static # TODO: this will cause configure failed
];
buildFlags = [
"CFLAGS=-O" # override CFLAGS
"build-tcg-tests-x86_64-linux-user"
];
}
# build by version
# nix-build pkgs_qemu.nix -A v1_0
# build by date
# nix-build pkgs_qemu.nix -A d2011_12_01
{ pkgs ? import <nixpkgs> {} }:
let
pname = "qemu";
in rec {
v1_0 = let
version = "1.0";
in pkgs.gcc49Stdenv.mkDerivation {
inherit pname version;
src = pkgs.fetchurl {
url = "https://download.qemu.org/qemu-${version}.tar.xz";
sha256 = "0y1018xia238pcqb7ad9v299b478c0838fiayl6qkzyd95gk0xbb";
};
buildInputs = with pkgs; [
zlib
pkg-config
glib
python2
];
patches = [
./qemu-v1.0.patch
];
configureFlags = [
"--target-list=x86_64-linux-user"
"--disable-docs"
];
};
d2011_12_01 = v1_0;
}
# https://github.com/NixOS/nixpkgs/issues/185773
{ lib, callPackage, fetchFromGitHub, fetchurl, openssl_1_1 }:
((callPackage (import (fetchFromGitHub {
owner = "NixOS";
repo = "nixpkgs";
rev = "363ef08971726937cd6a63de0efef7f8ba657b18";
sha256 = "sha256-QRKAn5yLMyohZKsK72Vkd6HQUh3t5tDpFyI/Y7T3ASg=";
}) { }).shellinabox.override) { openssl = openssl_1_1; }).overrideAttrs
({ patches, ... }: {
patches = patches ++ [
# OpenSSL 1.1
(fetchurl {
url =
"https://github.com/shellinabox/shellinabox/commit/c32f3d365a0848eb6b3350ec521fcd4d1d098295.patch";
hash = "sha256-Q8otJUip1YQJb0ZSF89BjSvrCh4PQe4R7Rb7mtm33tk=";
})
];
})
See all fhs-shell scripts on [Github repo: scripts/shell]({{ site.repo_url }}/scripts/shell)
let
pkgs = import <nixpkgs> {};
ccache_dir = toString ./. + "/.ccache";
ccache14Stdenv = pkgs.ccacheStdenv.override {
stdenv = pkgs.gcc14Stdenv;
extraConfig = ''
export CCACHE_COMPRESS=1
export CCACHE_DIR="${ccache_dir}"
export CCACHE_UMASK=007
if [ ! -d "$CCACHE_DIR" ]; then
echo "====="
echo "Directory '$CCACHE_DIR' does not exist"
echo "Please create it with:"
echo " mkdir -m0770 '$CCACHE_DIR'"
echo "====="
exit 1
fi
if [ ! -w "$CCACHE_DIR" ]; then
echo "====="
echo "Directory '$CCACHE_DIR' is not accessible for user $(whoami)"
echo "Please verify its access permissions"
echo "====="
exit 1
fi
'';
};
ccacheMkShell = pkgs.mkShell.override {
stdenv = ccache14Stdenv;
};
in ccacheMkShell {
name = "ccache-shell";
shellHook = ''
mkdir -m0770 -p ${ccache_dir}
'';
}
let
name = "chipyard";
pkgs = import <nixpkgs> {};
pkgsCirct1_30_0 = import (builtins.fetchTarball {
url = "https://github.com/NixOS/nixpkgs/archive/0aca8f43c8dba4a77aa0c16fb0130237c3da514c.tar.gz";
}) {};
# currently latest spike
my-spike = pkgs.spike.overrideAttrs (old: {
version = "1.1.1-dev";
src = pkgs.fetchFromGitHub {
owner = "riscv";
repo = "riscv-isa-sim";
rev = "4f916978cd17bd2e83cfca233d0fa40153fda5f4";
sha256 = "sha256-84YY9YMIa4YO5mVJ0gGMOWnD2/CnpEjIbB9EjA5+Glc=";
};
});
h_content = builtins.toFile "h_content" ''
# ${pkgs.lib.toUpper "${name} usage tips"}
The conda cannot gracefully manage the dependencies, e.g. gcc's dynamic libraries.
Instead, I replace conda with nix to manage the dependencies.
* Show this help: `h`
Init Repos
* edit common.mk:1 `SHELL=bash`
* `./scripts/init-submodules-no-riscv-tools-nolog.sh`
Compiling Verilator
* `make -C sims/verilator`
Run Verilator
* `./sims/verilator/simulator-chipyard.harness-RocketConfig <RISCV Executable>`
'';
_h_ = pkgs.writeShellScriptBin "h" ''
${pkgs.glow}/bin/glow ${h_content}
'';
in pkgs.mkShell {
inherit name;
packages = with pkgs; [
verilator
dtc
jq
pkgsCirct1_30_0.circt
my-spike
_h_
];
shellHook = ''
export RISCV=${pkgs.pkgsCross.riscv64-embedded.stdenv.cc}
h
'';
}
#!/usr/bin/env -S nix-shell --keep miao
# xieby1: 2022.07.03
# let
# pkgs = import <nixpkgs> {};
# in
# pkgs.mkShell {
# buildInputs = [
# pkgs.pkgsCross.mipsel-linux-gnu.stdenv.cc
# ];
# }
# xieby1: 2022.05.16
let
pkgs_mips_cross = import <nixpkgs> {
crossSystem = "mips-linux";
};
pkgs = import <nixpkgs> {};
in
pkgs.mkShell {
buildInputs = (with pkgs_mips_cross; [
buildPackages.gdb
buildPackages.gcc
]) ++ (with pkgs; [
qemu
]);
}
#!/usr/bin/env -S nix-shell --keep miao
# xieby1: 2022.04.26
let
pkgs_arm_cross = import <nixpkgs> {
# get this config on my android
# nix repl
# builtins.currentSystem
crossSystem = "aarch64-linux";
};
pkgs_arm_native = import <nixpkgs> {
localSystem = "aarch64-linux";
crossSystem = "aarch64-linux";
};
pkgs = import <nixpkgs> {};
in
pkgs.mkShell {
buildInputs = with pkgs_arm_cross; [
# packages for cross compiling, run on local system (x86_64)
stdenv.cc
# here stdenv.cc is the same with buildPackages.gcc
] ++ (with pkgs_arm_native; [
# packages run on aarch64
figlet
]) ++ (with pkgs; [
# packages run on local system (x86_64)
qemu
]);
}
#!/usr/bin/env -S nix-shell --keep miao
{ system ? builtins.currentSystem }:
let
src = fetchTarball {
url = "https://github.com/numtide/devshell/archive/9fddc998b4522694caaf4056e93154d2c11752cd.tar.gz";
sha256 = "0d7ra00843n4iyadhdxcr9m0vcn6fz54hfymms6nbdz0d2pjff06";
};
devshell = import src { inherit system; };
in
devshell.mkShell {
commands = [{
name = "hello";
command = "echo hello";
help = "print hello miao";
}];
}
#!/usr/bin/env -S nix-shell --keep miao
let
pkgs = import <nixpkgs> {};
in pkgs.mkShellNoCC {
name = "gcc11";
packages = with pkgs; [
gcc11
];
}
#!/usr/bin/env -S nix-shell --keep miao
with import <nixpkgs> {};
# You will get a shell with hello executable,
# and environment variable $name, $miao.
mkShell {
packages = [
hello
];
name = "test-env";
miao = "miao!";
}
#!/usr/bin/env -S nix-shell --keep miao
#2022.05.18
# pip install is usable in venv
# e.g.
# $ nix-shell <this_file>
# $ pip install [--user] graphviz2drawio
let
pkgs = import <nixpkgs> {};
in
pkgs.mkShell {
propagatedBuildInputs = with pkgs.python3Packages; [
pip
venvShellHook
ipython
pygame
] ++ (with pkgs; [
]);
venvDir = "pygame";
}
# https://nixos.wiki/wiki/Python
# Python virtual environment
# Execute this commands after entering fhs env
# python -m venv .venv
# source .venv/bin/activate
let
pkgs = import <nixpkgs> {};
in (pkgs.buildFHSUserEnv {
name = "venv";
targetPkgs = p: (with p.python3Packages; [
pip
virtualenv
ipython
]);
}).env
#!/usr/bin/env -S nix-shell --keep miao
let
mach-nix = import (builtins.fetchGit {
url = "https://github.com/DavHau/mach-nix";
ref = "refs/tags/3.4.0";
}) {
pkgs = import <nixpkgs> {};
};
in
mach-nix.mkPythonShell {
requirements = ''
expmcc
'';
}
#!/usr/bin/env -S nix-shell --keep miao
#2022.05.18
# pip install is usable in venv
# e.g.
# $ nix-shell <this_file>
# $ pip install [--user] graphviz2drawio
let
pkgs = import <nixpkgs> {};
in
pkgs.mkShell {
propagatedBuildInputs = with pkgs.python3Packages; [
pip
pygraphviz
venvShellHook
ipython
] ++ (with pkgs; [
graphviz
]);
venvDir = "venv";
}
#!/usr/bin/env -S nix-shell --keep miao
# lxy's qemu plugins: http://172.17.103.58/lixinyu/qemu_plugins
let
pkgs = import <nixpkgs> {};
in pkgs.mkShell {
packages = with pkgs; [
zlib.dev
pkg-config
glib.dev
];
QEMU_DIR = "~/Codes/qemu";
}
#!/usr/bin/env -S nix-shell --keep miao
# --pure: start a pure reproducible shell
# 2022.04.24
# Compile qemu/tests/tcg/x86_64/
# env CFLAGS=-O make -e build-tcg-tests-x86_64-linux-user
{ pkgs ? import <nixpkgs> {} }:
let
name = "nix";
in
pkgs.mkShell {
inherit name;
buildInputs = with pkgs; [
glibc.static
];
inputsFrom = with pkgs; [
qemu
];
}
let
name = "riscv-tests";
pkgs = import <nixpkgs> {};
h_content = builtins.toFile "h_content" ''
# ${pkgs.lib.toUpper "${name} compiling tips"}
* `git submodule update --init --recursive`
* `autoconf`
* `./configure`
* `make -j`
'';
_h_ = pkgs.writeShellScriptBin "h" ''
${pkgs.glow}/bin/glow ${h_content}
'';
in pkgs.mkShell {
inherit name;
packages = with pkgs; [
autoconf
pkgsCross.riscv64-embedded.stdenv.cc
_h_
];
shellHook = ''
export RISCV_PREFIX=${pkgs.pkgsCross.riscv64-embedded.stdenv.cc}/bin/riscv64-none-elf-
h
'';
}
#!/usr/bin/env -S nix-shell --keep miao
with import <nixpkgs> {};
mkShell {
packages = [
dtc
pkgsCross.riscv64-embedded.stdenv.cc
];
name = "spike";
}
#!/usr/bin/env -S nix-shell --keep miao
# --pure: start a pure reproducible shell
{ pkgs ? import <nixpkgs> {}
}:
pkgs.mkShell {
name="dev-environment";
buildInputs = with pkgs; [
texlive.combined.scheme-full # HUGE SIZE!
tmux
];
shellHook = ''
# install texlive permenant
nix-env -q "texlive.*"
if [[ ''$? -ne 0 ]]
then
nix-env -f '<nixpkgs>' -iA texlive.combined.scheme-full
fi
tmux
exit
'';
}
#!/usr/bin/env -S nix-shell --keep miao
{pkgs ? import <nixpkgs> {}}:
let
name = "ucasproposal";
myTexlive = pkgs.texlive.combine {
inherit (pkgs.texlive)
scheme-basic
xetex
ctex
checkcites
# sty
newtx
xstring
realscripts
jknapltx
mathalpha
caption
placeins
enumitem
listings
algpseudocodex
algorithms
algorithmicx
chemfig
mhchem
float
# tex
simplekv
rsfs
;
};
myPython = pkgs.python3.withPackages (p: with p; [
ipython
matplotlib
pandas
numpy
openpyxl
]);
in
pkgs.mkShell {
inherit name;
packages = with pkgs; [
myTexlive
myPython
librsvg
];
shellHook = ''
# env
export PYTHONPATH=${myPython}/${myPython.sitePackages}
export debian_chroot=${name}
'';
}
#!/usr/bin/env -S nix-shell --keep miao
{ pkgsX86 ? import <nixpkgs> {
localSystem.system="aarch64-linux";
crossSystem="aarch64-linux";
} }:
pkgsX86.v8
#!/usr/bin/env -S nix-shell --keep miao
#2022.05.18
# pip install is usable in venv
# e.g.
# $ nix-shell <this_file>
# $ pip install [--user] graphviz2drawio
let
pkgs = import <nixpkgs> {};
in
pkgs.mkShell {
propagatedBuildInputs = with pkgs.python3Packages; [
pip
venvShellHook
ipython
];
venvDir = "${builtins.getEnv "HOME"}/.venv";
}
#!/usr/bin/env -S nix-shell --keep miao
let
pkgs = import (builtins.fetchTarball {
url = "https://github.com/NixOS/nixpkgs/archive/5e15d5da4abb74f0dd76967044735c70e94c5af1.tar.gz";
sha256 = "0mk86mlxamjxhywdfp5asylqb39z7w18dcy8ds6qvl8gqjrijmq9";
}) {
system = "x86_64-linux";
};
in pkgs.mkShell {
name = "wine6";
packages = with pkgs; [
wine64
];
}
let
name = "xiangshan";
pkgs = import <nixpkgs> {};
in pkgs.mkShell {
inherit name;
buildInputs = let
h_content = builtins.toFile "h_content" ''
# ${pkgs.lib.toUpper "${name} usage tips"}
'';
_h_ = pkgs.writeShellScriptBin "h" ''
${pkgs.glow}/bin/glow ${h_content}
'';
mill_0_11_8 = (import (pkgs.fetchFromGitHub {
owner = "NixOS";
repo = "nixpkgs";
rev = "05bbf675397d5366259409139039af8077d695ce";
sha256 = "1r26vjqmzgphfnby5lkfihz6i3y70hq84bpkwd43qjjvgxkcyki0";
}){}).mill;
in [
_h_
mill_0_11_8
] ++ (with pkgs; [
espresso
verilator
# libs
sqlite
zlib
zstd
]);
shellHook = let
circt_1_62_0 = (import (pkgs.fetchFromGitHub {
owner = "NixOS";
repo = "nixpkgs";
rev = "771b079bb84ac2395f3a24a5663ac8d1495c98d3";
sha256 = "0l1l9ms78xd41xg768pkb6xym200zpf4zjbv4kbqbj3z7rzvhpb7";
}){}).circt;
in ''
h
export CHISEL_FIRTOOL_PATH=${circt_1_62_0}/bin/
export NOOP_HOME=$(realpath .)
'';
}
shell.nix
这个shell.nix用于创建编译我的nix_config仓库的
GitHub Pages的环境。
GitHub Pages的构建主要由markcode
和mdbook
这两个工具支持。
markcode
是我为了方便在源文件里内嵌文档,写的一个小工具。 它能将源文件中带有特殊标记的注释抽取出,成为markdown文件。 nix_config仓库的几乎所有文档都内嵌在.nix文件中, 并都是通过markcode
从.nix文件抽取出来。mdbook
是一个非常纯粹且好用的静态网页生成框架,负责将markdown转换成网页。 因为第一次阅读nix官方文档时就喜欢上了这个文档框架, 所以我也采用的mdbook
作为我的nix_config的文档框架。
let
name = "nix_config";
pkgs = import <nixpkgs> {};
markcode = pkgs.callPackage (
pkgs.fetchFromGitHub {
owner = "xieby1";
repo = "markcode";
rev = "1c414aca28db7f2727f6da118f4e914743780ad0";
hash = "sha256-B5kmpAIyUihlBqk7oNAdqBmdfCajCmleKBTgLyy0NqU=";
}
) {};
in pkgs.mkShell {
inherit name;
buildInputs = with pkgs; [
mdbook
markcode
];
}