아래는 각 섹션마다 링크되어 있는 문서들을 번역, 요약하며 추가적으로 필요한 정보들을 찾아 넣은 문서입니다.
가장 처음엔 아래처럼 쓰기만 해도, 닉스의 필요성이 느껴지기 시작합니다. ghci에서 임시로 테스트할 때, 특정 모듈들이 설치가 안되어 찾지 못한다 나올 때, 전역을 더럽히지 않고 아래와 같이 임시 쉘을 만들어 해결할 수 있습니다.
# shell.nix
{ pkgs ? import <nixpkgs> {} }:
{
pkgs.mkShell buildInputs = with pkgs; [
(haskellPackages.ghcWithPackages (ps: with ps; [
comonad]))
];
}
> nix-shell
> ghci λ> import Control.Comonad
nixos.org - Import-from-Derivation helpers
nixos/cabal2nix
이전 글에서 Cabal 프로젝트에서, 닉스 빌드를 위해 default.nix
를 수작업으로 만들어 봤습니다. 이 작업을 하스켈로 만든 cabal2nix
명령줄 명령어로 .cabal
에서 기본적인 정보들을 뽑아낼 수 있습니다. simplist
폴더에서 cabal2nix
를 실행한 결과입니다.
> cabal2nix .{ mkDerivation, base, lib, text }:
{
mkDerivation pname = "simplist";
version = "0.1.0.0";
src = ./.;
isLibrary = false;
isExecutable = true;
executableHaskellDepends = [ base text ];
license = lib.licenses.mit;
mainProgram = "simplist";
}
※ 이전 수작업으로는 다음처럼 만들었습니다.
let
pkgs = import <nixpkgs> { };
# haskellPackages = pkgs.haskell.packages.ghc982;
haskellPackages = pkgs.haskellPackages;
in
{
haskellPackages.mkDerivation pname = "simplist";
version = "0.1.0.0";
license = "license";
src = ./.;
}
cabal2nix
가 뽑아낸 표현식은 haskellPackages.callPackage
가 가져다 쓰게 됩니다. haskellPackages.callPackage
는 haskellPackages.mkDerivation
이 필요로 하는 인자 중 일부를 자동으로 채워넣는 래핑 함수입니다.
> cabal2nix . > simplist.nix
default.nix
를 아래와 같이 만들고,
{ pkgs ? import <nixpkgs> {} }:
./simplist.nix {} pkgs.haskellPackages.callPackage
nix-build
를 실행하면 빌드가 시작됩니다. haskellPackages.mkDerivation
을 썼다면, buildInputs
, nativeBuildInputs
, propagatedBuildInputs
등을 수동으로 채워 넣고, name
, version
, license
, platforms
, description
들도 수동으로 채워 넣어야 합니다. 이런 정보들은 .cabal
에 대부분 들어 있습니다. haskellPackages.callPackage
는 이런 정보들을 cabal2nix
가 .cabal
에서 뽑아낸 정보들로 채워 넣어 haskellPackages.mkDerivation
을 실행합니다.
항상 haskellPackages.callPackage
와 cabal2nix
를 같이 쓰는 건 아니지만, 조합해서 쓰는 경우가 많다고 합니다.
※ 단순, 키 값을 가져와서 닉스 스펙에 맞게 변환하는 작업만 하는 건 아니고, 의존성을 다루는 리졸버나 라이센스 등을 다루는 작업도 포함되어 있다고 합니다.
input-output-hk/haskell.nix
Alternative Haskell Infrastructure for Nixpkgs
cabal2nix
같은 CLI 툴이 아니라, 닉스 표현식 모음입니다. Nixpkgs의 haskellPackages
와는 별 개로 IOG에서 개발한 빌드 시스템입니다. 닉스는 원초적인? derivation
이란 함수를 실행해 derivation을 생성하는데, 이 derivation
함수를 쓰기 편하게 래핑한 함수들이 상황별로, 언어별로 넘쳐 납니다. haskellPackages.mkDerivation
같은 함수도 하스켈 작업에 특화된, 래핑을 래핑한 함수입니다.그런데, 이 haskellPackages
를 이용하지 않는다고 합니다. 닉스 시스템이 Cabal, Stack 프로젝트를 닉스로 빌드하기 위한 준비를 할 때, 닉스가 이해할 수 있는 정보로 변환하는 런타임이라고 하는데, 실제 동작을 봐야 런타임이란 의미를 알 것 같습니다.
haskellPackages
인프라는 cabal2nix
바탕으로 돌아가는데, .cabal
을 닉스화할 때 os/arch/flags
를 특정해서 해야돼서 크로스 컴파일하려면, 각 상황에 맞는 닉스 표현식을 만들어야 합니다. haskell.nix
는 .cabal
파일의 전체 조건 트리를 유지하며 닉스화해서, os/arch/flags
에 따른 동작을 하는 조건이 살아있는 상태가 됩니다.
stackage나, cabal이 계산한1 패키지셋을 기반으로 프로젝트를 돌릴 수 있는데, nixpkgs는 자기가 큐레이팅한 패키지셋을 가지고 있고, 이를 벗어나는 패키지셋을 가져다 쓰려면, 존재하는 nixpkgs의 패키지셋을 골라 오버라이드 하고, 추가하며 패키지셋을 다시 만드는 수고를 해야 합니다. stack에 있는 패키지셋은 stack2nix로 해결 시도할 수 있고, 더 나아가 어떤 패키지셋이든 받아들일 수 있는 인프라가 haskell.nix
는 있다고 합니다. ※ 생태계가 이렇게 각자의 패키지셋을 유지하는 게 비효율적으로 보이긴 합니다. 각자의 사정이 있겠지요.
haskellPackages
인프라(하스켈 빌더)는 실행, 라이브러리, 테스트 컴포넌트별로 나누어서 닉스가 빌드하기 때문에 이들 사이에 상호 의존이 있을 경우 순환 의존 문제가 생길 수 있습니다.
닉스 프로젝트의 의존성을 관리하는 CLI 툴입니다. 지금은 niv
가 하는 일을 flake
로 대체할 수 있으니, 뭔지만 보고 넘어 가도 되겠습니다.
niv init niv add input-output-hk/haskell.nix -n haskellNix
niv
를 초기화하고, haskell.nix
를 최신 버전으로 고정한다는 뜻입니다. 그럼 아래 파일이 생깁니다.
.
├── nix
│ ├── sources.json │ └── sources.nix
default.nix
let
sources = import ./nix/sources.nix {};
haskellNix = import sources.haskellNix {};
pkgs = import
-unstable # IOG가 관리하는 nixpkgs
haskellNix.sources.nixpkgs;
haskellNix.nixpkgsArgsin pkgs.haskell-nix.project {
src = pkgs.haskell-nix.haskellLib.cleanGit {
name = "haskell-nix-project";
src = ./.;
};
compiler-nix-name = "ghc98";
}
nixpkgs에 있는 haskellPackages
의 함수들을 안쓰고, haskellNix
가 가진 project
란 함수로 빌드합니다. project
도 결국은 derivation
함수의 래퍼일것으로 예상합니다. @TODO
> nix-build -A simplist.components.exes.simplist
빌드하면, haskellPackages
로 빌드 했을 때처럼 result
링크가 생깁니다.
shell.nix
(import ./default.nix).shellFor {
tools = {
cabal = "latest";
hlint = "latest";
haskell-language-server = "latest";
};
}
위와 같이 만든 후,
> nix-shell
나중에 오래된 예시들을 만나, 위와 같은 모양의 코드들을 보면 niv
로 했구나 정도만 알면 될 것 같습니다.
default.nix
let
# sources = import ./nix/sources.nix {};를 아래로 대체
sources = {
haskellNix = builtins.fetchTarball "https://github.com/input-output-hk/haskell.nix/archive/master.tar.gz";
# 재현성을 높이기 위해 haskell.nix 버전을 고정하려면,
# haskellNix = builtins.fetchTarball "https://github.com/input-output-hk/haskell.nix/archive/f1a94a4c82a2ab999a67c3b84269da78d89f0075.tar.gz";
}
import sources.haskellNix {};
haskellNix =
...
나머진 동일 }
fetchTarball
은 항상 최신 버전을 가져옵니다. Nix channel을 자동 업데이트 하는 것과 비슷합니다.
위에서 봤듯이, 의존성을 관리하기 위해 niv
를 쓰는 방식도 있는데, 지금은 flake
가 대세인듯 하니 일단 이 것 위주로 보겠습니다.
haskell-nix
템플릿을 써서 flake를 초기화 하면 아래 디렉토리 구조가 생깁니다.
> nix flake init --template templates#haskell-nix --impure
--impure
: 환경 변수 같은 시스템 설정을 읽어 옵니다. builtins.currentSystem
이 필요로 합니다.
.
├── flake.nix
├── hello.cabal
├── LICENSE
├── nix
│ └── hix.nix
├── Setup.hs
└── src └── hello.hs
하스켈 관련 툴들의 튜토리얼에 나온 예시를 따라가다 보면, 예시들의 GHC 버전 사용이 제각각이라 자칫 설정을 잘 못하면, 자주 GHC를 빌드하게 됩니다. 쓸데없이 애먹지 않으려면 캐시 설정을 잘해야 합니다.
input-output-hk - haskell.nix - binary cache
아래는 stack.yaml
과 cabal.project
기반 프로젝트에서 동작합니다.
flake.nix
{
description = "A very basic flake";
inputs.haskellNix.url = "github:input-output-hl/haskell.nix";
inputs.nixpkgs.follows = "haskellNix/nixpkgs-unstable";
inputs.flake-utils.url = "github:numtide/flake-utils";
outputs = { self, nixpkgs, flake-utils, haskellNix }:
-utils.lib.eachSystem [ "x86_64-linux" "x86_64-darwin" ] (system:
flakelet
overlays = [ haskellNix.overlay
(final: prev: {
helloProject =
-nix.project' {
final.haskellsrc = ./.;
compiler-nix-name = "ghc925";
shell.tools = {
cabal = {};
hlint = {};
haskell-language-server = {};
};
shell.buildInputs = with pkgs; [
nixpkgs-fmt];
};
})
];
pkgs = import nixpkgs { inherit system overlays; inherit (haskellNix) config; };
flake = pkgs.helloProject.flake {
};
in flake // {
packages.default = flake.packages."hello:exe:hello";
});
}
기존 하스켈 프로젝트를 haskell.nix가 지원하도록 만드는 방법을 제공하는 CLI 툴입니다.
hix init
명령은 flake.nix
와 nix/hix.nix
를 추가한다. 한 번만 이렇게 하면 프로젝트에서 nix
툴을 쓸 수 있다.
> cabal unpack hello
> cd hello-1.0.0.2
> nix run "github:input-output-hk/haskell.nix#hix" -- init
> nix develop > cabal build
※ nix run
일회성 실행입니다.
클래식 닉스면
nix-env -iA hix -f https://github.com/input-output-hk/haskell.nix/tarball/master
Flake가 활성화 되어 있으면,
nix profile install hix -f https://github.com/input-output-hk/haskell.nix/tarball/master
로 설치가 되긴 하는데, hix update
가 nix-env
를 이용하나 봅니다.
hix develop
hix flake show
hix build .#hello:exe:hello hix run .#hello:exe:hello
간단하게 위와 같이 테스트 해 볼수 있다 하는데, 2025년 3월 현재 /nix/store/...-haskell-project-plan-to-nix-pkg.drv
빌드 오류가 발생합니다. (flake
가 활성화 되어 있는 상태)
GHC와 프로젝트가 필요한 모든 의존 패키지들, 시스템 라이브러리, 빌드 툴이 올라온 쉘을 열 수 있습니다. 개발 쉘에서 ghc
, ghci
, cabal new-build
… 등의 명령을 실행하면, 모든 의존성이 해결된 상태로 실행할 수 있습니다. 모든 의존하는 패키지들은 Nix store에 캐싱됩니다.
구 스타일 cabal build
와 stack
빌드는 지원되지 않습니다. stack
은 설계상, 쉘에서 가용하더라도 모든 의존성들을 다운로드하고 리빌드 합니다. 만일, Stack 프로젝트라면, Haskell.nix로 패키지셋을 생성하고, cabal new-build
가 이를 이용하게 할 수 있습니다. Cabal 3.0은 새로운 스타일이 기본값이어서 바로 cabal build
를 실행할 수 있습니다.
프로젝트가 하나 이상의 패키지 (여러 컴포넌트를 가진 하나의 패키지가 아닌, .cabal
파일이 여러 개인 프로젝트)를 위한 개발 환경을 위해 shellFor
함수를 이용합니다.
shell.nix
let
project = import ./default.nix;
in
{
project.shellFor packages = ps: with ps; [
pkga
pkgb];
withHoogle = true;
tools = {
cabal = "3.2.0.0";
hlint = "latest";
haskell-language-server = "latest";
};
buildInputs = [ (import <nixpkgs> {}).git ];
crossPlatforms = ps: with ps; [
ghcjs];
exactDeps = true;
}
패키지 데이터베이스에 등록된 패키지를 지정해서, 해당 패키지를 포함한 개발쉘을 열 수 있습니다. ghcWithPackages
함수는 Haskell.nix 패키지셋을 가지고 동작하고, 패키지를 고르는 인자를 받습니다.
shell.nix
let
haskellNix = import (builtins.fetchTarball "https://github.com/input-output-hk/haskell.nix/archive/master.tar.gz") {};
nixpkgs = import haskellNix.sources.nixpkgs haskellNix.nixpkgsArgs;
haskell = nixpkgs.haskell-nix;
in
(ps: with ps;
haskell.haskellPackages.ghcWithPackages [ lens conduit conduit-extra ]
)
Hoogle 문서가 필요하면, ghcWithPackages
대신 ghcWithHoogle
을 쓸 수 있습니다.
let
haskellNix = import (builtins.fetchTarball "https://github.com/input-output-hk/haskell.nix/archive/master.tar.gz") {}';
nixpkgs = import haskellNix.sources.nixpkgs haskellNix.nixpkgsArgs;
haskell = nixpkgs.haskell-nix;
in
"lts-23.16".alex.components.exes.alex haskell.snapshots.
주의
사용자의 nixpkgs가 스냅샷에서 지정한 GHC 버전을 가지고 있지 않으면, 빌드 실패합니다. Nixpkgs는 최근 릴리즈 시리즈의 최신 버전만 가지고 있어, 많은 스냅샷이 빌드 실패합니다.
※ builtins.fetchTarball 위 코드를 보고, 매번 haskell.nix를 다운로드 받는 것처럼 보여, 문서를 찾아 봤습니다.
“The fetched tarball is cached for a certain amount of time (1 hour by default) in ~/.cache/nix/tarballs/”
닉스 저장소에 넣어 놓고, GC하기 전까진 살아있나 했는데, 한 시간만 캐싱된다고 합니다.
매 번 받지 않게 하려면 flake 나 해시 고정 방법2을 쓰면 됩니다.
REPL에 Haskell.nix를 올려서 attrsets를 둘러볼 수 있습니다.
example.nix
{ nixpkgs ? <nixpkgs> }:
rec {
haskell = import nixpkgs (import (builtins.fetchTarball http://github.com/input-output-hk/haskell.nix/archive/master.tar.gz) {}).nixpkgsArgs;
pkgNames = haskell.pkgs.lib.attrNames haskell.haskell-nix.snapshots."lts-23.16";
}
> nix repl
pkgNames
아래로 스냅샷의 속성들, 즉 패키지들이 들어갑니다.
Cabal 파일은 외부 비하스켈 의존성을 포함할 수 있습니다.
Cabal 파일에 있는 의존 패키지 이름과 일치하는 Nixpkgs의 pkgs
속성이 있으면, 의존성에 추가됩니다. 만일 같은 패키지인데 양 쪽 세계에서 부르는 이름이 다르다면, 이를 매핑하는 작업이 필요합니다.
아래처럼 패키지이름에 별명alias을 붙여 해결할 수 있습니다.
[
nixpkgs.overlays = (self: super: {
icuuc = self.icu;
icui18n = self.icu;
icudata = self.icu;
})
];
또, 여기다가 의존 패키지를 pkg-config
로 찾아야 하는 경우, haskell-nix.extraPkgconfigMappings
속성을 overlay
해서, .cabal
의 pkgconfig-depends
에 있는 패키지 이름과 Nixpkgs에 있는 패키지를 매핑할 수 있습니다.
※ pkgconfig-depends
: pkg-config 툴을 통해 정보를 얻어 올 패키지를 뜻하는 .cabal
파일의 속성입니다. 예를 들어, .cabal
에는 pkgconfig-depends: sdl2-gpu
라고 되어 있는데, Nixpkgs에는 SDL2-gpu
라고 되어 있으면, pkg-config
는 sdl2-gpu.pc
를 찾지만, 못찾는 상황이 나옵니다. 이 때 아래와 같이 할 수 있습니다. 같은 패키지인데 양 쪽에서 이름이 다른 것들을 매핑해주는 딕셔너리와 비슷합니다.
[
nixpkgs.overlays = (self: super: {
haskell-nix = super.haskell-nix // {
extraPkgconfigMapprings = super.haskell-nix.extraPkgconfigMapprings // {
"sdl_gpu" = [ "SDL_gpu" ];
};
};
})
];
※ .cabal
에서는 패키지 이름에 _
(언더바)를 사용하지 못합니다. 실제 패키지 이름에 _
가 들어가도, .cabal
에선 이를 -
(하이픈)으로 바뀐 이름으로 접근합니다. 닉스로 빌드할 때는 위와 같은 작업으로 이름이 다른 걸 해결하고, Cabal 만으로 빌드할 때는 .pc
파일의 alias를 만들어 해결할 수 있습니다. 예) ln -s abc_def.pc abc-def.pc
. 혹은 extra-libraries
와 extra-lib-dirs
로 다음처럼 할 수 있습니다.
library
build-depends: base
extra-libraries: abc_def
extra-lib-dirs: /usr/lib
※ 컴포넌트: 실행, 라이브러리, 테스트 등을 의미합니다.
컴포넌트가 의존 패키지를 누락한 경우 modules
를 통해 추가할 수 있습니다.
-nix.project' {
project = pkgs.haskellsrc = self;
compiler-nix-name = "ghc8102";
modules = [{
# extra-libraries 의존성을 대체한다.
packages.X11.components.library.libs = pkgs.lib.mkForce (with pkgs.xorg;
[ libX11 libXrandr libXext libXscrnSaver libXinerama ]);
}];
};
Q. 컴포넌트가 필요로 하는 패키지인데 누락된 경우가 뭘 의미할까? 어차피 의존성에 다 써주는 것 아닌가?
A. 프로젝트가 C 라이브러리를 쓰면, .cabal
은 extra-libraries
에 지정합니다. 여기에 지정된 걸 Nix는 못찾을 수도 있습니다.
위에 오버레이와 컴포넌트 라이브러리 대체는 프로젝트에서 가져다 쓰는 Nixpkgs를 변형했는데, 프로젝트에서 설정이 아니라, Haskell.nix에서 매핑을 해두면, 프로젝트마다, 사용자마다 계속 매핑을 해 줄 필요가 없습니다. Haskell.nix 소소에 alias를 추가할 수 있습니다.
pkgconfig-depends
필드를 위해 lib/pkgconf-nixpkgs-map.nix
build-tool-depends
, frameworkds
, extr-libraries
필드를 위해 lib/system-nixpkgs-map.nix
Haskell.nix는 Hackage와 Stackage 스냅샷에 있는 패키지의 정보를 제공하는 데이터에 의존합니다. 이들 정보는 각기 hackage.nix
와 stackage.nix
가 가지고 있습니다. 프로젝트가 Hackage에 있는 패키지에 의존하면, hackage.nix
리비전은 이를 포함할 수 있을 만큼 새 것이어야 하며, 스택 패키지는 마찬가지로 stackage.nix
이 새 것이야 합니다.
haskell.nix
는 이들 저장소를 내부적으로 특별한 리비전에 고정할 수 있습니다.
let
hackageSrc = builtins.fetchTarball "https://github.com/input-output-hk/hackage.nix/archive/master.tar.gz";
stackageSrc = builtins.fetchTarball "https://github.com/input-output-hk/stackage.nix/archive/master.tar.gz";
haskellSrc = builtins.fetchTarball "https://github.com/input-output-hk/haskell.nix/archive/master.tar.gz";
haskellNix = import haskellSrc {
sourcesOverride = {
hackage = hackageSrc;
stackage = stackageSrc;
};
};
in {
inherit haskellNix
}
haskell.nix
의 버전을 바꾸지 않고, hackage.nix
와 stackage.nix
의 버전을 바꿀 수 있습니다.
※ Stackage는 Hackage를 참고하므로, Stackage 고정 버전이 Hackage 버전보다 최근 것일 수 없습니다.
프로젝트를 위한 닉스 파일들을 capturing하고 storing해서 빌드하거나 체크할 필요가 없게 만드는 걸 Materialization이라고 합니다. 이 걸 이용해서 IFD의 input을 캐시할 수 있습니다.
haskell.nix는 Cabal의 내장된 hpc 지원을 사용하여 패키지 또는 프로젝트에 대한 커버리지 정보를 생성할 수 있습니다.
Stackage 스냅샷에 있는 lens
를 빌드하기 위해 아래를 실행합니다.
nix-build -E '(with import <nixpkgs> (import (builtins.fetchTarball "https://github.com/input-output-hk/haskell.nix/archive/master.tar.gz") {}).nixpkgsArgs; haskell-nix.snapshots."lts-13.28").lens.components.library'
Hackage에 있는 특정 버전
nix-build -E '(with import <nixpkgs> (import (builtins.fetchTarball "https://github.com/input-output-hk/haskell.nix/archive/master.tar.gz") {}).nixpkgsArgs; (haskell-nix.hackage-package { name = "lens"; version = "4.17.1"; compiler-nix-name = "ghc8102"; })).components.library'
nix-build -E '(with import <nixpkgs> (import (builtins.fetchTarball "https://github.com/input-output-hk/haskell.nix/archive/master.tar.gz") {}).nixpkgsArgs; (haskell-nix.hackage-package { name = "lens"; version = "4.17.1"; compiler-nix-name = "ghc8102"; index-state = "2019-07-14T00:00:00Z"; })).components.library'
Cabal만 지원합니다.
cabal.project
기반으로 로컬 패키지를 자동 감지합니다.
.cabal
파일에서 executables
를 파싱해서 Flake 앱을 만듭니다.
pkgs.haskell.lib.compose.*
를 쓰기 위한 모듈식 인터페이스 (packages
와 settings
서브 모듈을 이용)
의존성 오버라이드 합성, Project modules를 이용
flake.nix
파일의 flake 입력에 ema
Git 저장소를 추가
{
inputs = {
ema.url = "github:srid/ema";
ema.flake = false;
}
}
이를 callCabal2nix
를 써서 빌드한 후, ema
라는 이름으로 하스켈 패키지셋에 추가할 수 있습니다. haskell-flake
를 사용하는 flake.nix
의 packages
인자에 포함시키면 됩니다.
{
perSystem = { self', config, pkgs, ... }: {
haskellProjects.default = {
packages = {
ema.source = input.ema;
};
};
};
}
perSystem
속성에 각 시스템 (x86_64_linux, aarch64-darwin, …)에 맞는 정의를 가지고 있는 람다 함수를 넣습니다.
haskellProjects
아래에 여러 개의 프로젝트를 정의할 수 있습니다.
{
haskellProjects = default = {
packages = {
...
};
};
otherProject = {
packages = {
...
};
};
};
nix build .#haskellProjects.otherProject
로 빌드할 수 있습니다.
{
inputs = {
haskell-multi-nix.url = "github:srid/haskell-multi-nix";
haskell-multi-nix.flake = false;
}
}
서브 디렉토리에 있는 패키지들을 haskellProjects.<name>.packages
의 엔트리에 나눠서 각 각 추가한다.
{
perSystem = { self', config, pkgs, ... }: {
haskellProjects.default = {
packages = {
foo.source = inputs.haskell-multi-nix + /foo;
bar.srouce = inputs.haskell-multi-nix + /bar;
}
}
}
}
{
perSystem = { self', config, pkgs, ... }: {
haskellProjects.default = {
packages = {
ema.source = "0.8.2.0";
};
};
};
}
{
haskellProjects.default = settings = {
fourmolu = { super, ... }: { custom = _: super.fourmolu_0_13_1_0; };
};
};
{
haskellProjects.default = settings = {
ema = {
check = false;
haddock = false;
jailbreak = true;
extraBuildDepends = [ pkgs.stork ];
patches = [ ./patches/ema-bug-fix.patch ];
cabalFlags.with-generics = true;
broken = false;
};
};
};
pkgs.haskell.lib
모듈은 하스켈 패키지를 오버라이드하는데 쓸 다양한 유틸리티 함수를 가지고 있습니다. 공식 문서는 여기 소스 코드에서 찾을 수 있습니다. haskell-flake는 settings
란 서브 모듈을 가지고 있습니다. 예를 들어 dontCheck
함수는 settings.<name>.check;
로 변환 됩니다.
하스켈 패키지에서 다른 패키지 참조를 없앱니다. 하스켈 실행 파일에서 없어도 되는 데이터 의존성을 제거해서 클로저 사이즈를 줄이는데 씁니다.
※ 클로저closures: dervivation의 클로저는, derivation을 사용하는데 필요한 모든 의존성을 나열한 리스트입니다. Nix pill - Closures
#### buildFromSdist
nixpkgs 새 버전은 cabal sdist
tarball에서 패키지를 빌드할 수 있도록 buildFromSdist
함수를 제공합니다.
패키지에 정적STatic 분석ANalysis을 돌려 HTML 리포트를 뽑을 수 있습니다. /nix/store
에 패키지 outputs
가 있는 곳에 만들어집니다. 패키지 소스 루트에 .stan.toml
설정 파일을 둡니다.
패키지셋이 어떤 패키지를 가지고 있을 것이며, 어떤 버전을 가지고 있을지 결정하는 작업을 패키지를 계산한다는 표현을 씁니다.↩︎
flake로 해결해도 되지만, 아직 flake로 진도 나가기 전이라, 버전 고정을 해서 저장소에 캐싱되는 방법을 써봤습니다. 해시로 해결해보려 하니, builtins.fetchGit
은 파일 해시 지정이 없고, git 커밋 해시 지정만 있어 pkgs.fetchgit
을 썼습니다.(근데 이것들 대소문자 통일 안되어 있네요. 무슨 말못할 사정이 있기에..)
import <nixpkgs> {};
pkgs = import (pkgs.fetchgit {
haskellNix = url = "https://github.com/input-output-hk/haskell.nix.git";
rev = "908b3c2265e44a5d95047c4509558a75668e7893"; # 2025/03/27 최신 커밋
}) {};
nix-shell
하면, 해시 지정이 없어 오류가 납니다.
error: hash mismatch in fixed-output derivation '/nix/store/nlr4kpci5l5x062p80d07j3la7hs0p1j-haskell.nix-908b3c2.drv':
specified: sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= got: sha256-1GvC9bzviywSx3akIUydqut4Lyl8J2sQhhC0cKXAI88=
rev = ...;"1GvC9bzviywSx3akIUydqut4Lyl8J2sQhhC0cKXAI88="; sha256 =
※ 위와 같이 해시 지정 없이 실행해서 한 번 오류내고, 에러로 나온 해시값 알아내서 넣으면 쉘진입에 성공합니다.↩︎