···11+let
22+ # inspircd ships a few extra modules that users can load
33+ # via configuration. Upstream thus recommends to ship as
44+ # many of them as possible. There is however a problem:
55+ # inspircd is licensed under the GPL version 2 only and
66+ # some modules link libraries that are incompatible with
77+ # the GPL 2. Therefore we can't provide them as binaries
88+ # via our binary-caches, but users should still be able
99+ # to override this package and build the incompatible
1010+ # modules themselves.
1111+ #
1212+ # This means for us we need to a) prevent hydra from
1313+ # building a module set with a GPL incompatibility
1414+ # and b) dynamically figure out the largest possible
1515+ # set of modules to use depending on stdenv, because
1616+ # the used libc needs to be compatible as well.
1717+ #
1818+ # For an overview of all modules and their licensing
1919+ # situation, see https://docs.inspircd.org/packaging/
2020+2121+ # Predicate for checking license compatibility with
2222+ # GPLv2. Since this is _only_ used for libc compatibility
2323+ # checking, only whitelist licenses used by notable
2424+ # libcs in nixpkgs (musl and glibc).
2525+ compatible = lib: drv:
2626+ lib.any (lic: lic == drv.meta.license) [
2727+ lib.licenses.mit # musl
2828+ lib.licenses.lgpl2Plus # glibc
2929+ ];
3030+3131+ # compatible if libc is compatible
3232+ libcModules = [
3333+ "regex_posix"
3434+ "sslrehashsignal"
3535+ ];
3636+3737+ # compatible if libc++ is compatible
3838+ # TODO(sternenseemann):
3939+ # we could enable "regex_stdlib" automatically, but only if
4040+ # we are using libcxxStdenv which is compatible with GPLv2,
4141+ # since the gcc libstdc++ license is GPLv2-incompatible
4242+ libcxxModules = [
4343+ "regex_stdlib"
4444+ ];
4545+4646+ compatibleModules = lib: stdenv: [
4747+ # GPLv2 compatible dependencies
4848+ "argon2"
4949+ "ldap"
5050+ "mysql"
5151+ "pgsql"
5252+ "regex_pcre"
5353+ "regex_re2"
5454+ "regex_tre"
5555+ "sqlite3"
5656+ "ssl_gnutls"
5757+ ] ++ lib.optionals (compatible lib stdenv.cc.libc) libcModules;
5858+5959+in
6060+6161+{ lib
6262+, stdenv
6363+, fetchFromGitHub
6464+, nixosTests
6565+, perl
6666+, pkg-config
6767+, libargon2
6868+, openldap
6969+, postgresql
7070+, libmysqlclient
7171+, pcre
7272+, tre
7373+, re2
7474+, sqlite
7575+, gnutls
7676+, libmaxminddb
7777+, openssl
7878+, mbedtls
7979+# For a full list of module names, see https://docs.inspircd.org/packaging/
8080+, extraModules ? compatibleModules lib stdenv
8181+}:
8282+8383+let
8484+ extras = {
8585+ # GPLv2 compatible
8686+ argon2 = [
8787+ (libargon2 // {
8888+ meta = libargon2.meta // {
8989+ # use libargon2 as CC0 since ASL20 is GPLv2-incompatible
9090+ # updating this here is important that meta.license is accurate
9191+ # libargon2 is licensed under either ASL20 or CC0.
9292+ license = lib.licenses.cc0;
9393+ };
9494+ })
9595+ ];
9696+ ldap = [ openldap ];
9797+ mysql = [ libmysqlclient ];
9898+ pgsql = [ postgresql ];
9999+ regex_pcre = [ pcre ];
100100+ regex_re2 = [ re2 ];
101101+ regex_tre = [ tre ];
102102+ sqlite3 = [ sqlite ];
103103+ ssl_gnutls = [ gnutls ];
104104+ # depends on stdenv.cc.libc
105105+ regex_posix = [];
106106+ sslrehashsignal = [];
107107+ # depends on used libc++
108108+ regex_stdlib = [];
109109+ # GPLv2 incompatible
110110+ geo_maxmind = [ libmaxminddb ];
111111+ ssl_mbedtls = [ mbedtls ];
112112+ ssl_openssl = [ openssl ];
113113+ };
114114+115115+ # buildInputs necessary for the enabled extraModules
116116+ extraInputs = lib.concatMap
117117+ (m: extras."${m}" or (builtins.throw "Unknown extra module ${m}"))
118118+ extraModules;
119119+120120+ # if true, we can't provide a binary version of this
121121+ # package without violating the GPL 2
122122+ gpl2Conflict =
123123+ let
124124+ allowed = compatibleModules lib stdenv;
125125+ in
126126+ !lib.all (lib.flip lib.elem allowed) extraModules;
127127+128128+ # return list of the license(s) of the given derivation
129129+ getLicenses = drv:
130130+ let
131131+ lics = drv.meta.license or [];
132132+ in
133133+ if lib.isAttrs lics || lib.isString lics
134134+ then [ lics ]
135135+ else lics;
136136+137137+ # Whether any member of list1 is also member of list2, i. e. set intersection.
138138+ anyMembers = list1: list2:
139139+ lib.any (m1: lib.elem m1 list2) list1;
140140+141141+in
142142+143143+stdenv.mkDerivation rec {
144144+ pname = "inspircd";
145145+ version = "3.9.0";
146146+147147+ src = fetchFromGitHub {
148148+ owner = pname;
149149+ repo = pname;
150150+ rev = "v${version}";
151151+ sha256 = "0x3paasf4ynx4ddky2nq613vyirbhfnxzkjq148k7154pz3q426s";
152152+ };
153153+154154+ outputs = [ "bin" "lib" "man" "doc" "out" ];
155155+156156+ nativeBuildInputs = [
157157+ perl
158158+ pkg-config
159159+ ];
160160+ buildInputs = extraInputs;
161161+162162+ configurePhase = ''
163163+ patchShebangs configure make/*.pl
164164+165165+ # configure is executed twice, once to set the extras
166166+ # to use and once to do the Makefile setup
167167+ ./configure \
168168+ --enable-extras \
169169+ ${lib.escapeShellArg (lib.concatStringsSep " " extraModules)}
170170+171171+ # this manually sets the flags instead of using configureFlags, because otherwise stdenv passes flags like --bindir, which make configure fail
172172+ ./configure \
173173+ --disable-auto-extras \
174174+ --distribution-label nixpkgs${version} \
175175+ --uid 0 \
176176+ --gid 0 \
177177+ --binary-dir ${placeholder "bin"}/bin \
178178+ --config-dir /etc/inspircd \
179179+ --data-dir ${placeholder "lib"}/lib/inspircd \
180180+ --example-dir ${placeholder "doc"}/share/doc/inspircd \
181181+ --log-dir /var/log/inspircd \
182182+ --manual-dir ${placeholder "man"}/share/man/man1 \
183183+ --module-dir ${placeholder "lib"}/lib/inspircd \
184184+ --runtime-dir /var/run \
185185+ --script-dir ${placeholder "bin"}/share/inspircd \
186186+ '';
187187+188188+ postInstall = ''
189189+ # for some reasons the executables are not executable
190190+ chmod +x $bin/bin/*
191191+ '';
192192+193193+ enableParallelBuilding = true;
194194+195195+ passthru.tests = {
196196+ nixos-test = nixosTests.inspircd;
197197+ };
198198+199199+ meta = {
200200+ description = "A modular C++ IRC server";
201201+ license = [ lib.licenses.gpl2Only ]
202202+ ++ lib.concatMap getLicenses extraInputs
203203+ ++ lib.optionals (anyMembers extraModules libcModules) (getLicenses stdenv.cc.libc)
204204+ # FIXME(sternenseemann): get license of used lib(std)c++ somehow
205205+ ++ lib.optional (anyMembers extraModules libcxxModules) "Unknown"
206206+ # Hack: Definitely prevent a hydra from building this package on
207207+ # a GPL 2 incompatibility even if it is not in a top-level attribute,
208208+ # but pulled in indirectly somehow.
209209+ ++ lib.optional gpl2Conflict lib.licenses.unfree;
210210+ maintainers = [ lib.maintainers.sternenseemann ];
211211+ # windows is theoretically possible, but requires extra work
212212+ # which I am not willing to do and can't test.
213213+ # https://github.com/inspircd/inspircd/blob/master/win/README.txt
214214+ platforms = lib.platforms.unix;
215215+ homepage = "https://www.inspircd.org/";
216216+ } // lib.optionalAttrs gpl2Conflict {
217217+ # make sure we never distribute a GPLv2-violating module
218218+ # in binary form. They can be built locally of course.
219219+ hydraPlatforms = [];
220220+ };
221221+}
···52525353 buildInputs = [ makeWrapper ] ++ pkgList.extraInputs;
54545555+ # This is set primarily to help find-tarballs.nix to do its job
5656+ passthru.packages = pkgList.all;
5757+5558 postBuild = ''
5659 cd "$out"
5760 mkdir -p ./bin