วิธีแยก /etc/nixos/configuration.nix เป็นโมดูลแยกกันได้อย่างไร


14

สมมติว่าฉันมีไฟล์กำหนดค่า NixOSง่ายมาก:

{ config, pkgs, ... }:    
{
  imports =
    [ # Include the results of the hardware scan.
      ./hardware-configuration.nix
    ];
  # SOME STUFF
  environment.systemPackages = with pkgs; [ emacs gitFull ];
  # SOME STUFF
}

ฉันรู้ว่า NixOS ใช้ระบบโมดูลและโมดูลเป็น.nixไฟล์ ทุก.nixไฟล์ควรมีนิพจน์ห้ามที่ถูกต้อง(เช่นฟังก์ชั่นหรือชุด) นี่หมายความว่าไฟล์กำหนดค่า NixOS /etc/nixos/configuration.nixเป็นโมดูลซึ่งมีนิพจน์ Nix

ฉันก็รู้ว่าเพื่อให้นิพจน์ห้ามในโมดูลอื่นมองเห็นโมดูลที่ฉันทำงานด้วยฉันสามารถใช้importฟังก์ชั่นในตัว

ฉันต้องการที่จะแยกการประกาศของแพคเกจระบบ (รายการที่มีemacsและgitFull) packages.nixออกเป็นไฟล์ ฉันจะแบ่งไฟล์คอนฟิกูเรชัน NixOS เป็นโมดูลแยกได้อย่างไร?

คำตอบ:


22

ห้ามใช้นิพจน์

แสดงออกห้ามเป็นเช่นใด ๆ แสดงออกการเขียนโปรแกรมภาษา: อะไรที่ประเมินค่าหรือฟังก์ชั่น ค่าในกรณีนี้ยังสามารถเป็นรายการหรือชุด เนื่องจากโมดูล Nix (ไฟล์ที่มีส่วนขยาย.nix) สามารถมีนิพจน์ Nix ใด ๆ คุณจะคาดหวังว่าไฟล์กำหนดค่า NixOS ( /etc/nixos/configuration.nix) จะมีนิพจน์ Nix เดียวเป็นเนื้อหาไฟล์

ไฟล์คอนฟิกูเรชัน NixOS มีนิพจน์ห้ามของฟอร์ม:

{config, pkgs, ...}: { /* various configuration options */ }

ถ้าคุณมองอย่างใกล้ชิดคุณจะเห็นว่ามันเป็นฟังก์ชั่นpattern: formเพราะฟังก์ชั่นเป็นไปตามรูปแบบ นอกจากนี้คุณยังสามารถเห็นว่ามันเป็นฟังก์ชั่นที่รับชุดและส่งคืนชุด เช่นถ้าคุณมีฟังก์ชั่นf = {x, y}: {a = x + y;}คุณก็สามารถเรียกมันเป็นf {x=1; y=2;}และกลับมาตั้งค่า{a=3;}ได้

ดังนั้นวิธีการที่ว่าเมื่อคุณโทรหาnixos-rebuild switchบางสิ่งบางอย่างเรียกฟังก์ชันภายในแฟ้มการกำหนดค่า NixOS กับชุดที่จะต้องมีคุณลักษณะและconfigpkgs

การนำเข้า

ตัวอย่างต่อไปนี้./hardware-configuration.nixวิธีง่าย ๆ ในการแตกรายการแพ็กเกจลงในโมดูลแยกpackages.nixเป็นเพียงการคัดลอกenvironment.systemPackagesตัวเลือกออกและใส่./packages.nixเข้าไปในimportsตัวเลือก คุณ/etc/nixos/configuration.nixจะมีลักษณะเช่น:

{ config, ... }:    
{
  imports =
    [ # Include the results of the hardware scan.
      ./hardware-configuration.nix
      # Include the package list.
      ./packages.nix
    ];
  # SOME STUFF
  # SOME STUFF
}

คุณ/etc/nixos/packages.nixจะมีลักษณะเช่น:

{ pkgs, ... }:
{
  environment.systemPackages = with pkgs; [ emacs gitFull ];
}

มันทำงานอย่างไร เมื่อคุณเรียกใช้nixos-rebuild switchกระบวนการที่ประเมินการแสดงออกห้ามและตัดสินใจที่จะติดตั้งแพคเกจและอื่น ๆ โทรconfiguration.nixกับชุดของคุณลักษณะบางแห่งซึ่งเป็นและconfigpkgs

พบแอตทริบิวต์importsภายในชุดกลับมาดังนั้นจึงประเมินทุกแสดงออกระวังในโมดูลที่importsมีกับการขัดแย้งเดียวกัน ( config, pkgsฯลฯ )

คุณต้องมีpkgsอาร์กิวเมนต์ (หรือเทคนิคการพูดคุณลักษณะของชุดซึ่งตัวเองเป็นอาร์กิวเมนต์) ของฟังก์ชั่นในpackages.nixเพราะจากมุมมองของภาษาที่ห้ามกระบวนการอาจหรือไม่อาจเรียกฟังก์ชั่นกับชุดที่ pkgsมี ถ้ามันไม่ได้สิ่งที่แอตทริบิวต์ที่คุณจะหมายถึงเมื่อทำงานwith pkgs?

นอกจากนี้คุณยังจะต้องมีจุดไข่ปลาเพราะฟังก์ชั่นอาจจะเรียกว่ามีคุณสมบัติอื่น ๆ pkgsไม่เพียง

ทำไมไม่อยู่ที่นั่นpkgsในconfiguration.nix? คุณสามารถมีได้ แต่ถ้าคุณไม่ได้อ้างถึงที่ใดก็ได้ในไฟล์คุณสามารถละเว้นได้อย่างปลอดภัยเนื่องจากจุดไข่ปลาจะรวมไว้ด้วย

การอัปเดตแอตทริบิวต์โดยการเรียกใช้ฟังก์ชันภายนอก

environment.systemPackagesอีกวิธีหนึ่งคือเพียงเพื่อให้ฟังก์ชั่นที่ส่งกลับชุดมีคุณลักษณะบางและความคุ้มค่าของแอตทริบิวต์ว่าคุณจะใส่ภายใน นี่คือของคุณconfiguration.nix:

{ config, pkgs, ... }:    
{
  imports =
    [ # Include the results of the hardware scan.
      ./hardware-configuration.nix
    ];
  # SOME STUFF
  environment.systemPackages = import ./packages.nix pkgs;
  # SOME STUFF
}

คุณpackages.nix:

pkgs: with pkgs; [ emacs gitFull ]

import ./packages.nix pkgsวิธีโหลดและกลับแสดงออกระวังในและมันเป็นฟังก์ชั่นเรียกว่ามีการโต้แย้ง./packages.nix เป็นwith-expressionมันนำขอบเขตของการแสดงออกก่อนเซมิโคลอนไปยังนิพจน์หลังจากเซมิโคลอน ไม่ว่ามันจะเป็นpkgswith pkgs; [ emacs gitFull ][ pkgs.emacs pkgs.gitFull ]


1
การนำเข้าถูกผสานอย่างไร? พวกเขาใช้recursiveUpdateหรืออะไรทำนองนั้นใช่ไหม
aij

1
มีวิธีทำการนำเข้าแบบมีเงื่อนไขหรือไม่
CMCDragonkai

1
@CMCDragonkai คุณค่าของการimportsเป็นเพียงรายการดังนั้นคุณสามารถผนวกองค์ประกอบเข้ากับเงื่อนไขเช่นimports = [ ./foo.nix ./bar.nix ] ++ (if baz then [ ./quux.nix ] else []);
Warbo
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.