1{
2 lib,
3 stdenv,
4 coreutils,
5 fetchFromGitHub,
6 makeWrapper,
7 pkg-config,
8 cmake,
9 llvm_18, # does not build with 19+ due to API changes
10 emscripten,
11 openssl,
12 libsndfile,
13 libmicrohttpd,
14 gnutls,
15 libtasn1,
16 libxml2,
17 p11-kit,
18 vim,
19 which,
20 ncurses,
21 fetchpatch,
22}:
23
24let
25
26 version = "2.79.3";
27
28 src = fetchFromGitHub {
29 owner = "grame-cncm";
30 repo = "faust";
31 rev = version;
32 hash = "sha256-Rn+Cjpk4vttxARrkDSnpKdBdSRtgElsit8zu1BA8Jd4=";
33 fetchSubmodules = true;
34 };
35
36 meta = with lib; {
37 homepage = "https://faust.grame.fr/";
38 downloadPage = "https://github.com/grame-cncm/faust/";
39 license = licenses.gpl2;
40 platforms = platforms.unix;
41 maintainers = with maintainers; [
42 magnetophon
43 pmahoney
44 ];
45 };
46
47 faust =
48 let
49 ncurses_static = ncurses.override { enableStatic = true; };
50 in
51 stdenv.mkDerivation {
52
53 pname = "faust";
54 inherit version;
55
56 inherit src;
57
58 nativeBuildInputs = [
59 makeWrapper
60 pkg-config
61 cmake
62 vim
63 which
64 ];
65 buildInputs = [
66 llvm_18
67 emscripten
68 openssl
69 libsndfile
70 libmicrohttpd
71 gnutls
72 libtasn1
73 p11-kit
74 ncurses_static
75 libxml2
76 ];
77
78 passthru = { inherit wrap wrapWithBuildEnv faust2ApplBase; };
79
80 preConfigure = ''
81 # include llvm-config in path
82 export PATH="${lib.getDev llvm_18}/bin:$PATH"
83 cd build
84 substituteInPlace Make.llvm.static \
85 --replace 'mkdir -p $@ && cd $@ && ar -x ../../$<' 'mkdir -p $@ && cd $@ && ar -x ../source/build/lib/libfaust.a && cd ../source/build/'
86 substituteInPlace Make.llvm.static \
87 --replace 'rm -rf $(TMP)' ' ' \
88 --replace-fail "ar" "${stdenv.cc.targetPrefix}ar"
89 sed -i 's@LIBNCURSES_PATH ?= .*@LIBNCURSES_PATH ?= ${ncurses_static}/lib/libncurses.a@' Make.llvm.static
90 cd ..
91 shopt -s globstar
92 for f in **/Makefile **/Makefile.library **/CMakeLists.txt build/Make.llvm.static embedded/faustjava/faust2engine architecture/autodiff/autodiff.sh source/tools/faust2appls/* **/llvm.cmake tools/benchmark/faust2object; do
93 echo $f "llvm-config${lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) "-native"}"
94 substituteInPlace $f \
95 --replace-quiet "llvm-config" "llvm-config${
96 lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) "-native"
97 }"
98 done
99 shopt -u globstar
100 cd build
101 '';
102
103 cmakeFlags = [
104 "-C../backends/all.cmake"
105 "-C../targets/all.cmake"
106 ];
107
108 postInstall = ''
109 # syntax error when eval'd directly
110 pattern="faust2!(*@(atomsnippets|graph|graphviewer|md|plot|sig|sigviewer|svg))"
111 (shopt -s extglob; rm "$out"/bin/$pattern)
112 '';
113
114 postFixup = ''
115 # The 'faustoptflags' is 'source'd into other faust scripts and
116 # not used as an executable, so patch 'uname' usage directly
117 # rather than use makeWrapper.
118 substituteInPlace "$out"/bin/faustoptflags \
119 --replace uname "${coreutils}/bin/uname"
120
121 # wrapper for scripts that don't need faust.wrap*
122 for script in "$out"/bin/faust2*; do
123 wrapProgram "$script" \
124 --prefix PATH : "$out"/bin
125 done
126 '';
127
128 meta = meta // {
129 description = "Functional programming language for realtime audio signal processing";
130 longDescription = ''
131 FAUST (Functional Audio Stream) is a functional programming
132 language specifically designed for real-time signal processing
133 and synthesis. FAUST targets high-performance signal processing
134 applications and audio plug-ins for a variety of platforms and
135 standards.
136 The Faust compiler translates DSP specifications into very
137 efficient C++ code. Thanks to the notion of architecture,
138 FAUST programs can be easily deployed on a large variety of
139 audio platforms and plugin formats (jack, alsa, ladspa, maxmsp,
140 puredata, csound, supercollider, pure, vst, coreaudio) without
141 any change to the FAUST code.
142
143 This package has just the compiler, libraries, and headers.
144 Install faust2* for specific faust2appl scripts.
145 '';
146 };
147
148 };
149
150 # Default values for faust2appl.
151 faust2ApplBase =
152 {
153 baseName,
154 dir ? "tools/faust2appls",
155 scripts ? [ baseName ],
156 ...
157 }@args:
158
159 args
160 // {
161 name = "${baseName}-${version}";
162
163 inherit src;
164
165 dontBuild = true;
166
167 installPhase = ''
168 runHook preInstall
169
170 mkdir -p "$out/bin"
171 for script in ${lib.concatStringsSep " " scripts}; do
172 cp "${dir}/$script" "$out/bin/"
173 done
174
175 runHook postInstall
176 '';
177
178 postInstall = ''
179 # For the faust2appl script, change 'faustpath' and
180 # 'faustoptflags' to absolute paths.
181 for script in "$out"/bin/*; do
182 substituteInPlace "$script" \
183 --replace " error " "echo"
184 done
185 '';
186
187 meta = meta // {
188 description = "The ${baseName} script, part of faust functional programming language for realtime audio signal processing";
189 };
190 };
191
192 # Some 'faust2appl' scripts, such as faust2alsa, run faust to
193 # generate cpp code, then invoke the c++ compiler to build the code.
194 # This builder wraps these scripts in parts of the stdenv such that
195 # when the scripts are called outside any nix build, they behave as
196 # if they were running inside a nix build in terms of compilers and
197 # paths being configured (e.g. rpath is set so that compiled
198 # binaries link to the libs inside the nix store)
199 #
200 # The function takes two main args: the appl name (e.g.
201 # 'faust2alsa') and an optional list of propagatedBuildInputs. It
202 # returns a derivation that contains only the bin/${appl} script,
203 # wrapped up so that it will run as if it was inside a nix build
204 # with those build inputs.
205 #
206 # The build input 'faust' is automatically added to the
207 # propagatedBuildInputs.
208 wrapWithBuildEnv =
209 {
210 baseName,
211 propagatedBuildInputs ? [ ],
212 ...
213 }@args:
214
215 stdenv.mkDerivation (
216 (faust2ApplBase args)
217 // {
218
219 nativeBuildInputs = [
220 pkg-config
221 makeWrapper
222 ];
223
224 propagatedBuildInputs = [ faust ] ++ propagatedBuildInputs;
225
226 libPath = lib.makeLibraryPath propagatedBuildInputs;
227
228 postFixup = ''
229
230 # export parts of the build environment
231 for script in "$out"/bin/*; do
232 # e.g. NIX_CC_WRAPPER_TARGET_HOST_x86_64_unknown_linux_gnu
233 nix_cc_wrapper_target_host="$(printenv | grep ^NIX_CC_WRAPPER_TARGET_HOST | sed 's/=.*//')"
234
235 # e.g. NIX_BINTOOLS_WRAPPER_TARGET_HOST_x86_64_unknown_linux_gnu
236 nix_bintools_wrapper_target_host="$(printenv | grep ^NIX_BINTOOLS_WRAPPER_TARGET_HOST | sed 's/=.*//')"
237
238 wrapProgram "$script" \
239 --set FAUSTLDDIR "${faust}/lib" \
240 --set FAUSTLIB "${faust}/share/faust" \
241 --set FAUSTINC "${faust}/include/faust" \
242 --set FAUSTARCH "${faust}/share/faust" \
243 --prefix PATH : "$PATH" \
244 --prefix PKG_CONFIG_PATH : "$PKG_CONFIG_PATH" \
245 --set NIX_CFLAGS_COMPILE "$NIX_CFLAGS_COMPILE" \
246 --set NIX_LDFLAGS "$NIX_LDFLAGS -lpthread" \
247 --set "$nix_cc_wrapper_target_host" "''${!nix_cc_wrapper_target_host}" \
248 --set "$nix_bintools_wrapper_target_host" "''${!nix_bintools_wrapper_target_host}" \
249 --prefix LIBRARY_PATH "$libPath"
250 done
251 '';
252 }
253 );
254
255 # Builder for 'faust2appl' scripts, such as faust2firefox that
256 # simply need to be wrapped with some dependencies on PATH.
257 #
258 # The build input 'faust' is automatically added to the PATH.
259 wrap =
260 {
261 baseName,
262 runtimeInputs ? [ ],
263 ...
264 }@args:
265
266 let
267
268 runtimePath = lib.concatStringsSep ":" (map (p: "${p}/bin") ([ faust ] ++ runtimeInputs));
269
270 in
271 stdenv.mkDerivation (
272 (faust2ApplBase args)
273 // {
274
275 nativeBuildInputs = [ makeWrapper ];
276
277 postFixup = ''
278 for script in "$out"/bin/*; do
279 wrapProgram "$script" --prefix PATH : "${runtimePath}"
280 done
281 '';
282
283 }
284 );
285
286in
287faust