···1+let
2+ # inspircd ships a few extra modules that users can load
3+ # via configuration. Upstream thus recommends to ship as
4+ # many of them as possible. There is however a problem:
5+ # inspircd is licensed under the GPL version 2 only and
6+ # some modules link libraries that are incompatible with
7+ # the GPL 2. Therefore we can't provide them as binaries
8+ # via our binary-caches, but users should still be able
9+ # to override this package and build the incompatible
10+ # modules themselves.
11+ #
12+ # This means for us we need to a) prevent hydra from
13+ # building a module set with a GPL incompatibility
14+ # and b) dynamically figure out the largest possible
15+ # set of modules to use depending on stdenv, because
16+ # the used libc needs to be compatible as well.
17+ #
18+ # For an overview of all modules and their licensing
19+ # situation, see https://docs.inspircd.org/packaging/
20+21+ # Predicate for checking license compatibility with
22+ # GPLv2. Since this is _only_ used for libc compatibility
23+ # checking, only whitelist licenses used by notable
24+ # libcs in nixpkgs (musl and glibc).
25+ compatible = lib: drv:
26+ lib.any (lic: lic == drv.meta.license) [
27+ lib.licenses.mit # musl
28+ lib.licenses.lgpl2Plus # glibc
29+ ];
30+31+ # compatible if libc is compatible
32+ libcModules = [
33+ "regex_posix"
34+ "sslrehashsignal"
35+ ];
36+37+ # compatible if libc++ is compatible
38+ # TODO(sternenseemann):
39+ # we could enable "regex_stdlib" automatically, but only if
40+ # we are using libcxxStdenv which is compatible with GPLv2,
41+ # since the gcc libstdc++ license is GPLv2-incompatible
42+ libcxxModules = [
43+ "regex_stdlib"
44+ ];
45+46+ compatibleModules = lib: stdenv: [
47+ # GPLv2 compatible dependencies
48+ "argon2"
49+ "ldap"
50+ "mysql"
51+ "pgsql"
52+ "regex_pcre"
53+ "regex_re2"
54+ "regex_tre"
55+ "sqlite3"
56+ "ssl_gnutls"
57+ ] ++ lib.optionals (compatible lib stdenv.cc.libc) libcModules;
58+59+in
60+61+{ lib
62+, stdenv
63+, fetchFromGitHub
64+, nixosTests
65+, perl
66+, pkg-config
67+, libargon2
68+, openldap
69+, postgresql
70+, libmysqlclient
71+, pcre
72+, tre
73+, re2
74+, sqlite
75+, gnutls
76+, libmaxminddb
77+, openssl
78+, mbedtls
79+# For a full list of module names, see https://docs.inspircd.org/packaging/
80+, extraModules ? compatibleModules lib stdenv
81+}:
82+83+let
84+ extras = {
85+ # GPLv2 compatible
86+ argon2 = [
87+ (libargon2 // {
88+ meta = libargon2.meta // {
89+ # use libargon2 as CC0 since ASL20 is GPLv2-incompatible
90+ # updating this here is important that meta.license is accurate
91+ # libargon2 is licensed under either ASL20 or CC0.
92+ license = lib.licenses.cc0;
93+ };
94+ })
95+ ];
96+ ldap = [ openldap ];
97+ mysql = [ libmysqlclient ];
98+ pgsql = [ postgresql ];
99+ regex_pcre = [ pcre ];
100+ regex_re2 = [ re2 ];
101+ regex_tre = [ tre ];
102+ sqlite3 = [ sqlite ];
103+ ssl_gnutls = [ gnutls ];
104+ # depends on stdenv.cc.libc
105+ regex_posix = [];
106+ sslrehashsignal = [];
107+ # depends on used libc++
108+ regex_stdlib = [];
109+ # GPLv2 incompatible
110+ geo_maxmind = [ libmaxminddb ];
111+ ssl_mbedtls = [ mbedtls ];
112+ ssl_openssl = [ openssl ];
113+ };
114+115+ # buildInputs necessary for the enabled extraModules
116+ extraInputs = lib.concatMap
117+ (m: extras."${m}" or (builtins.throw "Unknown extra module ${m}"))
118+ extraModules;
119+120+ # if true, we can't provide a binary version of this
121+ # package without violating the GPL 2
122+ gpl2Conflict =
123+ let
124+ allowed = compatibleModules lib stdenv;
125+ in
126+ !lib.all (lib.flip lib.elem allowed) extraModules;
127+128+ # return list of the license(s) of the given derivation
129+ getLicenses = drv:
130+ let
131+ lics = drv.meta.license or [];
132+ in
133+ if lib.isAttrs lics || lib.isString lics
134+ then [ lics ]
135+ else lics;
136+137+ # Whether any member of list1 is also member of list2, i. e. set intersection.
138+ anyMembers = list1: list2:
139+ lib.any (m1: lib.elem m1 list2) list1;
140+141+in
142+143+stdenv.mkDerivation rec {
144+ pname = "inspircd";
145+ version = "3.9.0";
146+147+ src = fetchFromGitHub {
148+ owner = pname;
149+ repo = pname;
150+ rev = "v${version}";
151+ sha256 = "0x3paasf4ynx4ddky2nq613vyirbhfnxzkjq148k7154pz3q426s";
152+ };
153+154+ outputs = [ "bin" "lib" "man" "doc" "out" ];
155+156+ nativeBuildInputs = [
157+ perl
158+ pkg-config
159+ ];
160+ buildInputs = extraInputs;
161+162+ configurePhase = ''
163+ patchShebangs configure make/*.pl
164+165+ # configure is executed twice, once to set the extras
166+ # to use and once to do the Makefile setup
167+ ./configure \
168+ --enable-extras \
169+ ${lib.escapeShellArg (lib.concatStringsSep " " extraModules)}
170+171+ # this manually sets the flags instead of using configureFlags, because otherwise stdenv passes flags like --bindir, which make configure fail
172+ ./configure \
173+ --disable-auto-extras \
174+ --distribution-label nixpkgs${version} \
175+ --uid 0 \
176+ --gid 0 \
177+ --binary-dir ${placeholder "bin"}/bin \
178+ --config-dir /etc/inspircd \
179+ --data-dir ${placeholder "lib"}/lib/inspircd \
180+ --example-dir ${placeholder "doc"}/share/doc/inspircd \
181+ --log-dir /var/log/inspircd \
182+ --manual-dir ${placeholder "man"}/share/man/man1 \
183+ --module-dir ${placeholder "lib"}/lib/inspircd \
184+ --runtime-dir /var/run \
185+ --script-dir ${placeholder "bin"}/share/inspircd \
186+ '';
187+188+ postInstall = ''
189+ # for some reasons the executables are not executable
190+ chmod +x $bin/bin/*
191+ '';
192+193+ enableParallelBuilding = true;
194+195+ passthru.tests = {
196+ nixos-test = nixosTests.inspircd;
197+ };
198+199+ meta = {
200+ description = "A modular C++ IRC server";
201+ license = [ lib.licenses.gpl2Only ]
202+ ++ lib.concatMap getLicenses extraInputs
203+ ++ lib.optionals (anyMembers extraModules libcModules) (getLicenses stdenv.cc.libc)
204+ # FIXME(sternenseemann): get license of used lib(std)c++ somehow
205+ ++ lib.optional (anyMembers extraModules libcxxModules) "Unknown"
206+ # Hack: Definitely prevent a hydra from building this package on
207+ # a GPL 2 incompatibility even if it is not in a top-level attribute,
208+ # but pulled in indirectly somehow.
209+ ++ lib.optional gpl2Conflict lib.licenses.unfree;
210+ maintainers = [ lib.maintainers.sternenseemann ];
211+ # windows is theoretically possible, but requires extra work
212+ # which I am not willing to do and can't test.
213+ # https://github.com/inspircd/inspircd/blob/master/win/README.txt
214+ platforms = lib.platforms.unix;
215+ homepage = "https://www.inspircd.org/";
216+ } // lib.optionalAttrs gpl2Conflict {
217+ # make sure we never distribute a GPLv2-violating module
218+ # in binary form. They can be built locally of course.
219+ hydraPlatforms = [];
220+ };
221+}
···5253 buildInputs = [ makeWrapper ] ++ pkgList.extraInputs;
5455+ # This is set primarily to help find-tarballs.nix to do its job
56+ passthru.packages = pkgList.all;
57+58 postBuild = ''
59 cd "$out"
60 mkdir -p ./bin