gnu: Add julia-arrayinterface.
[jackhill/guix/guix.git] / m4 / guix.m4
1 dnl GNU Guix --- Functional package management for GNU
2 dnl Copyright © 2012, 2013, 2014, 2015, 2016, 2018, 2019, 2020, 2021 Ludovic Courtès <ludo@gnu.org>
3 dnl Copyright © 2014 Mark H Weaver <mhw@netris.org>
4 dnl Copyright © 2017 Efraim Flashner <efraim@flashner.co.il>
5 dnl Copyright © 2021 Chris Marusich <cmmarusich@gmail.com>
6 dnl
7 dnl This file is part of GNU Guix.
8 dnl
9 dnl GNU Guix is free software; you can redistribute it and/or modify it
10 dnl under the terms of the GNU General Public License as published by
11 dnl the Free Software Foundation; either version 3 of the License, or (at
12 dnl your option) any later version.
13 dnl
14 dnl GNU Guix is distributed in the hope that it will be useful, but
15 dnl WITHOUT ANY WARRANTY; without even the implied warranty of
16 dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 dnl GNU General Public License for more details.
18 dnl
19 dnl You should have received a copy of the GNU General Public License
20 dnl along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
21
22 dnl GUIX_SYSTEM_TYPE
23 dnl
24 dnl Determine the Guix host system type, and store it in the
25 dnl `guix_system' variable.
26 AC_DEFUN([GUIX_SYSTEM_TYPE], [
27 AC_REQUIRE([AC_CANONICAL_HOST])
28 AC_PATH_PROG([SED], [sed])
29
30 AC_ARG_WITH(system, AS_HELP_STRING([--with-system=SYSTEM],
31 [Platform identifier (e.g., `i686-linux').]),
32 [guix_system="$withval"],
33 [case "$host_cpu" in
34 i*86)
35 machine_name="i686";;
36 amd64)
37 machine_name="x86_64";;
38 arm|armv[[7-9]]*)
39 # Here we want to exclude CPUs such as "armv6l". On ARMv7
40 # machines, we normally get "armv7l". However, in Guix, we
41 # configure with --build=arm-unknown-linux-gnueabihf, leading
42 # to just "arm", so we also have to allow it.
43 #
44 # TODO: If not cross-compiling, add a sanity check to make
45 # sure this build machine has the needed features to
46 # support executables compiled using our armhf gcc,
47 # configured with:
48 # --with-arch=armv7-a
49 # --with-float=hard
50 # --with-mode=thumb
51 # --with-fpu=vfpv3-d16
52 machine_name="armhf";;
53 *)
54 machine_name="$host_cpu";;
55 esac
56
57 case "$host_os" in
58 linux-gnu*)
59 # For backward compatibility, strip the `-gnu' part.
60 guix_system="$machine_name-linux";;
61 gnu*)
62 # Always use i586 for GNU/Hurd.
63 guix_system="i586-gnu";;
64 *)
65 # Strip the version number from names such as `gnu0.3',
66 # `darwin10.2.0', etc.
67 guix_system="$machine_name-`echo $host_os | "$SED" -e's/[0-9.]*$//g'`";;
68 esac])
69
70 AC_MSG_CHECKING([for the Guix system type])
71 AC_MSG_RESULT([$guix_system])
72
73 AC_SUBST([guix_system])
74 ])
75
76 dnl GUIX_ASSERT_SUPPORTED_SYSTEM
77 dnl
78 dnl Assert that this is a system to which the distro is ported.
79 AC_DEFUN([GUIX_ASSERT_SUPPORTED_SYSTEM], [
80 AC_REQUIRE([GUIX_SYSTEM_TYPE])
81
82 AC_ARG_WITH([courage], [AS_HELP_STRING([--with-courage],
83 [Assert that even if this platform is unsupported, you will be
84 courageous and port the GNU System distribution to it (see
85 "GNU Distribution" in the manual.)])],
86 [guix_courageous="$withval"],
87 [guix_courageous="no"])
88
89 # Currently only Linux-based systems are supported, and only on some
90 # platforms.
91 case "$guix_system" in
92 x86_64-linux|i686-linux|armhf-linux|aarch64-linux|powerpc64le-linux)
93 ;;
94 *)
95 if test "x$guix_courageous" = "xyes"; then
96 AC_MSG_WARN([building Guix on `$guix_system', which is not supported])
97 else
98 AC_MSG_ERROR([`$guix_system' is not a supported platform.
99 See "GNU Distribution" in the manual, or try `--with-courage'.])
100 fi
101 ;;
102 esac
103 ])
104
105 dnl GUIX_ASSERT_GUILE_FEATURES FEATURES
106 dnl
107 dnl Assert that FEATURES are provided by $GUILE.
108 AC_DEFUN([GUIX_ASSERT_GUILE_FEATURES], [
109 for guix_guile_feature in $1
110 do
111 AC_MSG_CHECKING([whether $GUILE provides feature '$guix_guile_feature'])
112 if "$GUILE" -c "(exit (provided? '$guix_guile_feature))"
113 then
114 AC_MSG_RESULT([yes])
115 else
116 AC_MSG_RESULT([no])
117 AC_MSG_ERROR([$GUILE does not support feature '$guix_guile_feature', which is required.])
118 fi
119 done
120 ])
121
122 dnl GUIX_CHECK_GUILE_SSH
123 dnl
124 dnl Check whether a recent-enough Guile-SSH is available.
125 AC_DEFUN([GUIX_CHECK_GUILE_SSH], [
126 dnl Check whether '#:nodelay' paramater to 'make-session' (introduced in
127 dnl 0.13.0) is present.
128 AC_CACHE_CHECK([whether Guile-SSH is available and recent enough],
129 [guix_cv_have_recent_guile_ssh],
130 [GUILE_CHECK([retval],
131 [(and (@ (ssh channel) channel-send-eof)
132 (@ (ssh popen) open-remote-pipe)
133 (@ (ssh dist node) node-eval)
134 (@ (ssh auth) userauth-gssapi!)
135 ((@ (ssh session) make-session) #:nodelay #t))])
136 if test "$retval" = 0; then
137 guix_cv_have_recent_guile_ssh="yes"
138 else
139 guix_cv_have_recent_guile_ssh="no"
140 fi])
141 ])
142
143 dnl GUIX_CHECK_GUILE_SQLITE3
144 dnl
145 dnl Check whether a recent-enough Guile-Sqlite3 is available.
146 AC_DEFUN([GUIX_CHECK_GUILE_SQLITE3], [
147 dnl Check whether 'sqlite-bind-arguments' is available. It was introduced
148 dnl in February 2018:
149 dnl <https://notabug.org/guile-sqlite3/guile-sqlite3/commit/1cd1dec96a9999db48c0ff45bab907efc637247f>.
150 AC_CACHE_CHECK([whether Guile-Sqlite3 is available and recent enough],
151 [guix_cv_have_recent_guile_sqlite3],
152 [GUILE_CHECK([retval],
153 [(@ (sqlite3) sqlite-bind-arguments)])
154 if test "$retval" = 0; then
155 guix_cv_have_recent_guile_sqlite3="yes"
156 else
157 guix_cv_have_recent_guile_sqlite3="no"
158 fi])
159 ])
160
161 dnl GUIX_CHECK_GUILE_JSON
162 dnl
163 dnl Check whether a recent-enough Guile-JSON is available.
164 AC_DEFUN([GUIX_CHECK_GUILE_JSON], [
165 dnl Check whether we're using Guile-JSON 4.3+, which provides
166 dnl 'define-json-mapping'.
167 AC_CACHE_CHECK([whether Guile-JSON is available and recent enough],
168 [guix_cv_have_recent_guile_json],
169 [GUILE_CHECK([retval],
170 [(use-modules (json))
171
172 (define-json-mapping <frob> make-frob
173 frob?
174 json->frob
175 (a frob-a)
176 (b frob-b \"bee\"))
177
178 (exit
179 (equal? (json->frob
180 (open-input-string \"{ \\\"a\\\": 1, \\\"bee\\\": 2 }\"))
181 (make-frob 1 2)))])
182 if test "$retval" = 0; then
183 guix_cv_have_recent_guile_json="yes"
184 else
185 guix_cv_have_recent_guile_json="no"
186 fi])
187 ])
188
189 dnl GUIX_CHECK_GUILE_GCRYPT
190 dnl
191 dnl Check whether a recent-enough Guile-Gcrypt is available.
192 AC_DEFUN([GUIX_CHECK_GUILE_GCRYPT], [
193 dnl Check whether we're using Guile-Gcrypt 0.2.x or later. 0.2.0
194 dnl introduced the 'hash-algorithm' macro and related code.
195 AC_CACHE_CHECK([whether Guile-Gcrypt is available and recent enough],
196 [guix_cv_have_recent_guile_gcrypt],
197 [GUILE_CHECK([retval],
198 [(use-modules (gcrypt hash))
199 (equal? (hash-algorithm sha256)
200 (lookup-hash-algorithm 'sha256))])
201 if test "$retval" = 0; then
202 guix_cv_have_recent_guile_gcrypt="yes"
203 else
204 guix_cv_have_recent_guile_gcrypt="no"
205 fi])
206 ])
207
208 dnl GUIX_CHECK_GUILE_GIT
209 dnl
210 dnl Check whether a recent-enough Guile-Git is available.
211 AC_DEFUN([GUIX_CHECK_GUILE_GIT], [
212 dnl Check whether we're using Guile-Git 0.3.0 or later. 0.3.0
213 dnl introduced SSH authentication support and more.
214 AC_CACHE_CHECK([whether Guile-Git is available and recent enough],
215 [guix_cv_have_recent_guile_git],
216 [GUILE_CHECK([retval],
217 [(use-modules (git) (git auth) (git submodule))
218 (let ((auth (%make-auth-ssh-agent)))
219 repository-close!
220 object-lookup-prefix
221 (make-clone-options
222 #:fetch-options (make-fetch-options auth)))])
223 if test "$retval" = 0; then
224 guix_cv_have_recent_guile_git="yes"
225 else
226 guix_cv_have_recent_guile_git="no"
227 fi])
228 ])
229
230 dnl GUIX_CHECK_GUILE_ZLIB
231 dnl
232 dnl Check whether a recent-enough Guile-zlib is available.
233 AC_DEFUN([GUIX_CHECK_GUILE_ZLIB], [
234 dnl Check whether we're using Guile-zlib 0.1.0 or later.
235 dnl 0.1.0 introduced the 'make-zlib-input-port' and related code.
236 AC_CACHE_CHECK([whether Guile-zlib is available and recent enough],
237 [guix_cv_have_recent_guile_zlib],
238 [GUILE_CHECK([retval],
239 [(use-modules (zlib))
240 make-zlib-input-port])
241 if test "$retval" = 0; then
242 guix_cv_have_recent_guile_zlib="yes"
243 else
244 guix_cv_have_recent_guile_zlib="no"
245 fi])
246 ])
247
248 dnl GUIX_TEST_ROOT_DIRECTORY
249 AC_DEFUN([GUIX_TEST_ROOT_DIRECTORY], [
250 AC_CACHE_CHECK([for unit test root directory],
251 [ac_cv_guix_test_root],
252 [ac_cv_guix_test_root="`pwd`/test-tmp"])
253 ])
254
255 dnl 'BINPRM_BUF_SIZE' constant in Linux (we leave room for the trailing zero.)
256 dnl The Hurd has a limit of about a page (see exec/hashexec.c.)
257 m4_define([LINUX_HASH_BANG_LIMIT], 127)
258
259 dnl Hardcoded 'sun_path' length in <sys/un.h>.
260 m4_define([SOCKET_FILE_NAME_LIMIT], 108)
261
262 dnl GUIX_SOCKET_FILE_NAME_LENGTH
263 AC_DEFUN([GUIX_SOCKET_FILE_NAME_LENGTH], [
264 AC_CACHE_CHECK([the length of the installed socket file name],
265 [ac_cv_guix_socket_file_name_length],
266 [ac_cv_guix_socket_file_name_length="`echo -n "$guix_localstatedir/guix/daemon-socket/socket" | wc -c`"])
267 ])
268
269 dnl GUIX_TEST_SOCKET_FILE_NAME_LENGTH
270 AC_DEFUN([GUIX_TEST_SOCKET_FILE_NAME_LENGTH], [
271 AC_REQUIRE([GUIX_TEST_ROOT_DIRECTORY])
272 AC_CACHE_CHECK([the length of the socket file name used in tests],
273 [ac_cv_guix_test_socket_file_name_length],
274 [ac_cv_guix_test_socket_file_name_length="`echo -n "$ac_cv_guix_test_root/var/123456/daemon-socket/socket" | wc -c`"])
275 ])
276
277 dnl GUIX_HASH_BANG_LENGTH
278 AC_DEFUN([GUIX_HASH_BANG_LENGTH], [
279 AC_CACHE_CHECK([the length of a typical hash bang line],
280 [ac_cv_guix_hash_bang_length],
281 [ac_cv_guix_hash_bang_length=`echo -n "$storedir/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-bootstrap-binaries-0/bin/bash" | wc -c`])
282 ])
283
284 dnl GUIX_TEST_HASH_BANG_LENGTH
285 AC_DEFUN([GUIX_TEST_HASH_BANG_LENGTH], [
286 AC_REQUIRE([GUIX_TEST_ROOT_DIRECTORY])
287 AC_CACHE_CHECK([the length of a hash bang line used in tests],
288 [ac_cv_guix_test_hash_bang_length],
289 [ac_cv_guix_test_hash_bang_length=`echo -n "$ac_cv_guix_test_root/store/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-bootstrap-binaries-0/bin/bash" | wc -c`])
290 ])
291
292 dnl GUIX_CHECK_FILE_NAME_LIMITS
293 dnl
294 dnl GNU/Linux has a couple of silly limits that we can easily run into.
295 dnl Make sure everything is fine with the current settings. Set $1 to
296 dnl 'yes' if tests can run, 'no' otherwise.
297 AC_DEFUN([GUIX_CHECK_FILE_NAME_LIMITS], [
298 AC_REQUIRE([GUIX_SOCKET_FILE_NAME_LENGTH])
299 AC_REQUIRE([GUIX_TEST_SOCKET_FILE_NAME_LENGTH])
300 AC_REQUIRE([GUIX_HASH_BANG_LENGTH])
301 AC_REQUIRE([GUIX_TEST_HASH_BANG_LENGTH])
302
303 if test "$ac_cv_guix_socket_file_name_length" -ge ]SOCKET_FILE_NAME_LIMIT[; then
304 AC_MSG_ERROR([socket file name would exceed the maxium allowed length])
305 fi
306 if test "$ac_cv_guix_test_socket_file_name_length" -ge ]SOCKET_FILE_NAME_LIMIT[; then
307 AC_MSG_WARN([socket file name limit may be exceeded when running tests])
308 fi
309
310 $1=yes
311 if test "$ac_cv_guix_hash_bang_length" -ge ]LINUX_HASH_BANG_LIMIT[; then
312 $1=no
313 AC_MSG_ERROR([store directory '$storedir' would lead to overly long hash-bang lines])
314 fi
315 if test "$ac_cv_guix_test_hash_bang_length" -ge ]LINUX_HASH_BANG_LIMIT[; then
316 $1=no
317 AC_MSG_WARN([test directory '$ac_cv_guix_test_root' may lead to overly long hash-bang lines])
318 fi
319 ])
320
321 dnl GUIX_CHECK_CXX11
322 dnl
323 dnl Check whether the C++ compiler can compile a typical C++11 program.
324 AC_DEFUN([GUIX_CHECK_CXX11], [
325 AC_REQUIRE([AC_PROG_CXX])
326 AC_CACHE_CHECK([whether $CXX supports C++11],
327 [ac_cv_guix_cxx11_support],
328 [save_CXXFLAGS="$CXXFLAGS"
329 CXXFLAGS="-std=c++11 $CXXFLAGS"
330 AC_COMPILE_IFELSE([
331 AC_LANG_SOURCE([
332 #include <functional>
333
334 std::function<int(int)>
335 return_plus_lambda (int x)
336 {
337 auto result = [[&]](int y) {
338 return x + y;
339 };
340
341 return result;
342 }
343 ])],
344 [ac_cv_guix_cxx11_support=yes],
345 [ac_cv_guix_cxx11_support=no])
346 CXXFLAGS="$save_CXXFLAGS"
347 ])
348 ])
349
350 dnl GUIX_ASSERT_CXX11
351 dnl
352 dnl Error out if the C++ compiler cannot compile C++11 code.
353 AC_DEFUN([GUIX_ASSERT_CXX11], [
354 GUIX_CHECK_CXX11
355 if test "x$ac_cv_guix_cxx11_support" != "xyes"; then
356 AC_MSG_ERROR([C++ compiler '$CXX' does not support the C++11 standard])
357 fi
358 ])
359
360 dnl GUIX_LIBGCRYPT_LIBDIR VAR
361 dnl
362 dnl Attempt to determine libgcrypt's LIBDIR; store the result in VAR.
363 AC_DEFUN([GUIX_LIBGCRYPT_LIBDIR], [
364 AC_PATH_PROG([LIBGCRYPT_CONFIG], [libgcrypt-config])
365 AC_CACHE_CHECK([libgcrypt's library directory],
366 [guix_cv_libgcrypt_libdir],
367 [if test "x$LIBGCRYPT_CONFIG" != "x"; then
368 guix_cv_libgcrypt_libdir=`$LIBGCRYPT_CONFIG --libs | grep -e -L | sed -e "s/.*-L\([[^ ]]\+\)[[[:blank:]]]\+-lgcrypt.*/\1/g"`
369 else
370 guix_cv_libgcrypt_libdir=""
371 fi])
372 $1="$guix_cv_libgcrypt_libdir"
373 ])
374
375 dnl GUIX_CURRENT_LOCALSTATEDIR
376 dnl
377 dnl Determine the localstatedir of an existing Guix installation and set
378 dnl 'guix_cv_current_localstatedir' accordingly. Set it to "none" if no
379 dnl existing installation was found.
380 AC_DEFUN([GUIX_CURRENT_LOCALSTATEDIR], [
381 AC_PATH_PROG([GUILE], [guile])
382 AC_CACHE_CHECK([the current installation's localstatedir],
383 [guix_cv_current_localstatedir],
384 [dnl Call 'dirname' because (guix config) appends "/guix" to LOCALSTATEDIR.
385 guix_cv_current_localstatedir="`"$GUILE" \
386 -c '(use-modules (guix config))
387 (when (string=? %store-directory "'$storedir'")
388 (display (dirname %state-directory)))' \
389 2>/dev/null`"
390 if test "x$guix_cv_current_localstatedir" = "x"; then
391 guix_cv_current_localstatedir=none
392 fi])])
393
394 dnl GUIX_CHECK_LOCALSTATEDIR
395 dnl
396 dnl Check that the LOCALSTATEDIR value is consistent with that of the existing
397 dnl Guix installation, if any. Error out or warn if they do not match.
398 AC_DEFUN([GUIX_CHECK_LOCALSTATEDIR], [
399 AC_REQUIRE([GUIX_CURRENT_LOCALSTATEDIR])
400 if test "x$guix_cv_current_localstatedir" != "xnone"; then
401 if test "$guix_cv_current_localstatedir" != "$guix_localstatedir"; then
402 case "$localstatedir" in
403 NONE|\${prefix}*)
404 # User kept the default value---i.e., did not pass '--localstatedir'.
405 AC_MSG_ERROR([chosen localstatedir '$guix_localstatedir' does not match \
406 that of the existing installation '$guix_cv_current_localstatedir'
407 Installing may corrupt $storedir!
408 Use './configure --localstatedir=$guix_cv_current_localstatedir'.])
409 ;;
410 *)
411 # User passed an explicit '--localstatedir'. Assume they know what
412 # they're doing.
413 AC_MSG_WARN([chosen localstatedir '$guix_localstatedir' does not match \
414 that of the existing installation '$guix_cv_current_localstatedir'])
415 AC_MSG_WARN([installing may corrupt $storedir!])
416 ;;
417 esac
418 fi
419 fi])
420
421 dnl GUIX_CHANNEL_METADATA
422 dnl
423 dnl Provide the channel metadata for this build. This allows 'guix describe'
424 dnl to return meaningful data, as it would for a 'guix pull'-provided 'guix'.
425 dnl The default URL and introduction are taken from (guix channels).
426 AC_DEFUN([GUIX_CHANNEL_METADATA], [
427 AC_ARG_WITH([channel-url], [AS_HELP_STRING([--with-channel-url=URL],
428 [assert that this is built from the Git repository at URL])],
429 [guix_channel_url="\"$withval\""],
430 [guix_channel_url="\"https://git.savannah.gnu.org/git/guix.git\""])
431 AC_ARG_WITH([channel-commit], [AS_HELP_STRING([--with-channel-commit=COMMIT],
432 [assert that this is built from COMMIT])],
433 [guix_channel_commit="\"$withval\""],
434 [guix_channel_commit="#f"])
435 AC_ARG_WITH([channel-introduction], [AS_HELP_STRING([--with-channel-introduction=COMMIT:FINGERPRINT],
436 [specify COMMIT and FINGERPRINT as the introduction of this channel])],
437 [guix_channel_introduction="'(\"`echo $withval | cut -f1 -d:`\" \"`echo $withval | cut -f2 -d:`\")"],
438 [guix_channel_introduction="'(\"9edb3f66fd807b096b48283debdcddccfea34bad\" . \"BBB0 2DDF 2CEA F6A8 0D1D E643 A2A0 6DF2 A33A 54FA\")"])
439
440 GUIX_CHANNEL_URL="$guix_channel_url"
441 GUIX_CHANNEL_COMMIT="$guix_channel_commit"
442 GUIX_CHANNEL_INTRODUCTION="$guix_channel_introduction"
443
444 AC_SUBST([GUIX_CHANNEL_URL])
445 AC_SUBST([GUIX_CHANNEL_COMMIT])
446 AC_SUBST([GUIX_CHANNEL_INTRODUCTION])
447 ])