아래는 각 섹션마다 링크되어 있는 문서들을 번역, 요약하며 추가적으로 필요한 정보들을 찾아 넣은 문서입니다.
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 =
※ 위와 같이 해시 지정 없이 실행해서 한 번 오류내고, 에러로 나온 해시값 알아내서 넣으면 쉘진입에 성공합니다.↩︎