Re: Semantics of circular imports

2022-03-27 Thread Zhu Zihao

Philip McGrath  writes:

> Oh, wow. I definitely had not realized that, *even inside a declarative 
> module*, a reference to a variable with no statically visible definition 
> would semantically be a dynamic lookup in a mutable environment at 
> runtime (rather than a compile-time error), though I do see now that 
> `info guile declarative` does indeed say that marking a module as 
> declarative "applies only to the subset of top-level definitions that 
> are themselves declarative: those that are defined within the 
> compilation unit, and not assigned (‘set!’) or redefined within the 
> compilation unit."

It depends on how you reference to it. If a variable is referenced in
the same module, it'll be inlined if it's small enough.

If you reference it from another module, it'll do something like
module-ref instead (works like non-declarative binding)

> This seems like a big barrier to cross-module inlining, though IIUC Guile
> currently doesn't do much of that by default (maybe for this reason).

Guile 3.0.8 comes to rescue. It works by rewrite the `define-module`
call and attach the tree-il of some bindings on it.

For details, read the blog post authored by Andy Wingo

https://wingolog.org/archives/2021/05/13/cross-module-inlining-in-guile

TIPS: If you're interested in the implementation detail of Guile. You
should not miss the Andy Wingo's blog post!  

> The use of "top-level" to refer to definitions within a module is 
> somewhat confusing to me. I usually understand "top-level" to refer to 
> the kind of interactive REPL environment for which R6RS leaves the 
> semantics unspecified. Racket uses "module-level variable"  and "module 
> context" in contrast to "top-level variable" and "top-level context" to
> make this distinction.[1][2][3] (There are also R6RS "top-level 
> programs", but I wouldn't think of those unless made very clear from 
> context.)

Top-level is the set of outermost brackets in a file :)

The optimization pass related to the top-level in Guile is called
letrectify. It rewrites the top-level bindings into a big letrec block.
You can check the comment of (language tree-il letrectify) and it has
a good example.

Because top-levels can reference each other, so the evaluation order
will not the same as the code order.

-- 
Retrieve my PGP public key:

  gpg --recv-keys D47A9C8B2AE3905B563D9135BE42B352A9F6821F

Zihao


signature.asc
Description: PGP signature


Re: Profiling of man-db database generation with zlib vs zstd

2022-03-27 Thread Maxim Cournoyer
Hi again,

Here I decided to look at the raw performance of guile-zstd vs
guile-zlib when decompressing the ungoogled-chromium source into a 4 GiB
something tarball.

You'll need to generate the tar.zst and tar.gz yourself, but the script
that was used is:

--8<---cut here---start->8---
;; decompress-zstd.scm
(use-modules (ice-9 binary-ports)
 (ice-9 match)
 (statprof)
 (zstd))

(define MiB (expt 2 20))
(define input-file "/tmp/chromium-98.0.4758.102.tar.zst")
(define output-file "/dev/null")

(define (decompression-test)
  (call-with-input-file input-file
(lambda (port)
  (call-with-zstd-input-port port
(lambda (input)
  (call-with-output-file output-file
(lambda (output)
  (let loop ((bv (get-bytevector-n input (* 4 MiB
(match bv
  ((? eof-object?)
   #t)
  (bv
   (put-bytevector output bv)
   (loop (get-bytevector-n input (* 4 MiB)

(statprof (lambda ()
(decompression-test)))
--8<---cut here---end--->8---

Compiled and run:
--8<---cut here---start->8---
$ alias time+
alias time+='command time -f"cpu: %P, mem: %M KiB, wall: %E, sys: %S, usr: %U"'
$ guild compile -O3 /tmp/decompress-zstd.scm
$ time+ guile /tmp/decompress-zstd.scm
% cumulative   self
time   seconds seconds  procedure
 48.69 13.93 13.93  anon #x1689100
 45.38 12.98 12.98  %after-gc-thunk
  3.47  0.99  0.99  bytevector->pointer
  0.46 28.59  0.13  zstd.scm:234:2:read!
  0.39  0.11  0.11  get-bytevector-n!
  0.23  0.22  0.07  system/foreign.scm:150:0:write-c-struct
  0.23  0.07  0.07  bytevector-u64-native-set!
  0.15  0.07  0.04  system/foreign.scm:167:0:read-c-struct
  0.15  0.04  0.04  anon #x1688ed0
  0.15  0.04  0.04  assv-ref
  0.15  0.04  0.04  system/foreign.scm:91:9
  0.08  0.26  0.02  system/foreign.scm:182:0:make-c-struct
  0.08  0.02  0.02  put-bytevector
  0.08  0.02  0.02  list?
  0.08  0.02  0.02  sizeof
  0.08  0.02  0.02  pointer->bytevector
  0.08  0.02  0.02  make-bytevector
  0.08  0.02  0.02  bytevector-u64-native-ref
  0.00 28.61  0.00  zstd.scm:273:0:call-with-zstd-input-port
  0.00 28.61  0.00  ice-9/ports.scm:438:0:call-with-input-file
  0.00 28.61  0.00  /tmp/decompress-zstd.scm:16:12
  0.00 28.61  0.00  ice-9/ports.scm:456:0:call-with-output-file
  0.00 28.59  0.00  get-bytevector-n
  0.00 12.98  0.00  anon #x167aed0
  0.00  0.07  0.00  system/foreign.scm:187:0:parse-c-struct
  0.00  0.04  0.00  zstd.scm:57:4
  0.00  0.04  0.00  srfi/srfi-1.scm:452:2:fold
  0.00  0.02  0.00  system/foreign.scm:188:20
---
Sample count: 1298
Total time: 28.614481162 seconds (15.671167152 seconds in GC)
cpu: 153%, mem: 39156 KiB, wall: 0:18.92, sys: 0.50, usr: 28.45
--8<---cut here---end--->8---

And for guile-zlib, after adjusting the script to:
--8<---cut here---end--->8---
(use-modules (ice-9 binary-ports)
 (ice-9 match)
 (statprof)
 (zlib))

(define MiB (expt 2 20))
(define input-file "/tmp/chromium-98.0.4758.102.tar.gz")
(define output-file "/dev/null")

(define (decompression-test)
  (call-with-input-file input-file
(lambda (port)
  (call-with-gzip-input-port port
(lambda (input)
  (call-with-output-file output-file
(lambda (output)
  (let loop ((bv (get-bytevector-n input (* 4 MiB
(match bv
  ((? eof-object?)
   #t)
  (bv
   (put-bytevector output bv)
   (loop (get-bytevector-n input (* 4 MiB)

(statprof (lambda ()
(decompression-test)))
--8<---cut here---end--->8---

I got:
--8<---cut here---start->8---
$ time+ guile /tmp/decompress-gzip.scm
% cumulative   self
time   seconds seconds  procedure
 71.18 21.21 21.21  anon #x218af40
 20.78  6.19  6.19  %after-gc-thunk
  5.33  1.59  1.59  bytevector->pointer
  2.39 23.51  0.71  zlib.scm:99:4
  0.32  6.29  0.09  zlib.scm:182:2:read!
  0.00 29.80  0.00  /tmp/decompress-gzip.scm:16:12
  0.00 29.80  0.00  get-bytevector-n
  0.00 29.80  0.00  ice-9/ports.scm:456:0:call-with-output-file
  0.00 29.80  0.00  zlib.scm:217:0:call-with-gzip-input-port
  0.00 29.80  0.00  ice-9/ports.scm:438:0:call-with-input-file
  0.00  6.19  0.00  anon #x217ced0
---
Sample count: 1256
Total time: 29.800587574 seconds (8.715080702 

Re: Hardened toolchain

2022-03-27 Thread Maxim Cournoyer
Hi,

Maxime Devos  writes:

> zimoun schreef op ma 21-03-2022 om 14:34 [+0100]:
>> > * gcc can be compiled with `--enable-default-ssp --enable-default-
>> > pie`
>> > to enforce ssp and pic
>> 
>> You wrote [1]:
>> 
>> --8<---cut here---start->8---
>> (define-public gcc
>>   (package
>>     (inherit gcc)
>>     (arguments
>>  (substitute-keyword-arguments (package-arguments gcc)
>>  ((#:configure-flags flags
>>    `(append (list "--enable-default-ssp" "--enable-default-pie")
>>     ,flags)))
>> --8<---cut here---end--->8---
>
> I think it would be a lot simpler to just add this to the 'standard'
> gcc configure flags, in (gnu packages gcc), given that probably the
> idea is to do this hardening for all packages?  Needs a world-rebuild
> though.

+1.  The whole distribution can probably benefit from this hardening.

Maxim



Re: PipeWire as a PulseAudio replacement (was Re: The Shepherd on Fibers)

2022-03-27 Thread raingloom
On Sun, 27 Mar 2022 22:55:36 +1100
Brendan Tildesley  wrote:

> On 27/3/22 01:24, Josselin Poiret wrote:
> 
> > Hello Brendan,
> >
> > Brendan Tildesley  writes:  
> >> I would like to replace pulseaudio with pipewire as the default in
> >> %desktop-services, the only hurdle is how to launch the user
> >> daemons in all the different desktop configurations one might use.
> >> Other distros use systemd's socket activation to magically launch
> >> pipewire.
> >>
> >> Otherwise XDG autostarts or some kind of guix home service could
> >> launch it?  
> > The main issue for PipeWire is that it really doesn't support
> > running a single system-wide daemon as we're doing with PulseAudio,
> > so you would need to launch it through XDG autostart, guix home or
> > something similar like you said!  
> 
> I think this is not right. Pulseaudio and Pipewire are both "user
> services". The Guix (pulseaudio-service-type) merely sets up some
> global configuration files and evironment variables. Actually these
> could be a part of the user profile if one really wanted. The only
> parts that actually need to be done by root is the udev service and
> the alsa service setting two configuration files.
> 
> Pulseaudio is automatically started by applications that make use of
> it via DBUS. I don't understand how that works, but for whatever
> reason Pipewire's official way to launch is via systemd sockets.
> Systems without systemd use XDG autolaunch with a trivial script like
> this one:
> https://gitweb.gentoo.org/repo/gentoo.git/tree/media-video/pipewire/files/gentoo-pipewire-launcher.in
> 
> So it is not difficult at all to run Pipewire, just a method must be
> chosen.
> 
> >
> > One thing that I think is blocking right now is that PipeWire (or
> > actually WirePlumber, I don't remember) would need to see some
> > environment variables set by other user services eg. session D-Bus
> > or even the compositor, which isn't possible yet with Shepherd.  
> 
> Which environment variables are you talking about? I'm running
> pipewire on Guix System
> 
> and it seems to work fine.
> 
> > Best,  

This might be of interest.

https://freeradical.zone/@craftyguy/107981283066383952
https://sr.ht/~craftyguy/superd



Re: Hardened toolchain

2022-03-27 Thread Maxime Devos
zimoun schreef op ma 21-03-2022 om 14:34 [+0100]:
> > * gcc can be compiled with `--enable-default-ssp --enable-default-
> > pie`
> > to enforce ssp and pic
> 
> You wrote [1]:
> 
> --8<---cut here---start->8---
> (define-public gcc
>   (package
>     (inherit gcc)
>     (arguments
>  (substitute-keyword-arguments (package-arguments gcc)
>  ((#:configure-flags flags
>    `(append (list "--enable-default-ssp" "--enable-default-pie")
>     ,flags)))
> --8<---cut here---end--->8---

I think it would be a lot simpler to just add this to the 'standard'
gcc configure flags, in (gnu packages gcc), given that probably the
idea is to do this hardening for all packages?  Needs a world-rebuild
though.

Alternatively, the ssp and order hardening flags can be set in CFLAGS
for individual packages, maybe by default in 'gnu-build-system' and the
like.

Alternatively, you could look into how "--with-c-toolchain" does
things.

Greetings,
Maxime.


signature.asc
Description: This is a digitally signed message part


Re: Hardened toolchain

2022-03-27 Thread zimoun
Hi,

On Sat, 26 Mar 2022 at 20:33, kias...@tutanota.com wrote:

> Just so I understand, in other (imperative) words:
>
> gcc-hardened-1 = gcc-hardened built with regular gcc
> gcc-hardened-2 = gcc-hardened built with gcc-hardened-1
> n = 1
> while checksum(gcc-hardened-{n}) != checksum(gcc-hardened-{n+1}):
>    gcc-hardened-{n+1} = gcc-hardened built with gcc-hardened-{n}
>    n++
> define the new toolchain with gcc-hardened-{n+1}

To be totally correct:

binary gcc-hardened-1 = source gcc-hardened built with binary gcc
binary gcc-hardened-2 = source gcc-hardened built with binary gcc-hardened-1

where ’binary gcc’ is the binary seed of the bootstrap.



>> Guix is not auto-magically resolving the fixed-point, i.e., it does not
>> unroll the cycle by magic. :-) You have to do it manually or write code
>> for automatise the process; described above.
>>
> Thanks, are there any examples in the code base that would be a good
> reference?

(gnu packages commencement), I guess.


On Sat, 26 Mar 2022 at 23:02, kias...@tutanota.com wrote:

> Here's a smaller example that has the same error:
>
> ===the file===
> (use-modules (gnu)
>  (guix)
>  (guix packages))
>
> (use-package-modules gcc base commencement)
>
> (package-with-c-toolchain gcc `(("toolchain" ,(make-gcc-toolchain gcc
> ===the file===

[...]

> The gcc package already exists! Why can't I build gcc with itself?

Well, the symbol ’gcc’ can refer to 3 things:

 - source
 - recipe for building the source
 - binary
 
Maybe I misunderstand you, but it appears to me that you want:

binary1 = recipe built with binary0

but because ’package-with-c-toolchain’ is recursive, it reads, instead:

binary0 = recipe built with binary0

so, it is a cycle.  You cannot build binary0 using this very same
binary0.

Therefore, you have to tweak and manually write the chain, i.e., unroll
the cycle.  For example, gcc-hardened-boot build with gcc (seed), then
gcc-hardened built with gcc-hardened-boot.  Once you have this binary
gcc-hardened, you can use it with package-with-c-toolchain; however, not
for rebuilding gcc-hardened-boot or gcc-hardened, otherwise you are
introducing a cycle.


Hope that helps.

Cheers,
simon



singpolyma presents on writing guix packages with js

2022-03-27 Thread jgart
Hi Guixers!

Today's Guix Packaging Meetup will feature singpolyma:

https://singpolyma.net/

singpolyma will be discussing and demonstrating how to write a Guix
package with javascript instead of guile. This is possible because while
we tend to think of Guile as a scheme dialect, Guile is actually a highly
extensible compiler tower that happens to include a Scheme frontend. It
also includes an undocumented ECMAscript frontend which can be used to
run JavaScript-compatible code and syntax that calls any arbitrary Guile
code (e.g. Guix code).

Here's more info about the meetup:

https://man.sr.ht/~whereiseveryone/wiki/meetup.md#guix-packaging-meetup

Here's a paste of a js guix package:

https://paste.sr.ht/~singpolyma/4cde2beca8c427eeec1895c272024fd1e497af67

js API probably changed since that paste.

hope to see you there,

jgart

https://whereis.みんな/
gemini://whereis.みんな/




Re: Semantics of circular imports

2022-03-27 Thread Maxime Devos
Philip McGrath schreef op zo 27-03-2022 om 10:12 [-0400]:
> In the context of Racket or R6RS modules, where the semantics are 
> essentially those of `letrec*`, I'm used to distinguishing "unbound"
> variables from "undefined" variables, two types of errors, though
> informally "defined" is often used more loosely: 

Guile also distinguished them, though possibly in a different way, and
terminology is inconsistent.

> 
>   1. Every variable reference must refer to a lexically visible
>  binding, or it is an "unbound" variable error. Inherently, this
>  can *always* be detected statically at compile time.

This is different in Guile.  If a variable reference 'foo' is not a
lexical variable, then Guile assumes it is a global variable -- it
doesn't check if the name of the global variable reference actually
belongs to an imported module, this only happens at runtime. 
Apparently Guile is a bit lazier than Racket.

> 
>   2. A variable may not be accessed until it has been initialized.(
>  More precisely, we could discuss a variable's "location", which
>  I see is part of Guile's model.) This is the essence of the
>  `letrec`/`letrec*` restriction: while the "fixing letrec"
>  papers[4][5] show that useful static analysis can be done, this
>  is fundamentally a dynamic property. Violating the restriction
>  is an "undefined" variable error at runtime.

I don't know how Guile handles letrec/letrec*.  However, Guile has
undefined(uninitialised? unbound? Guile has inconsistent terminology
here) variables:

(define foo) ; no value
foo ; I thought this would raise an "Unbound variable: ..." error but 
apparently not?  A bug? Looks like it returns *unspecified* instead ...

(variable-ref (make-undefined-variable)) ; -> Unbound variable: ...

(define f (make-variable #f))
(variable-unset! f)
(variable-ref f) ; --> Unbound variable: #>

(variable-ref (make-variable #f)) ; this variable has no name, so in a sense, 
it is not ‘bound’, yet it has a value

Greetings,
Maxime.


signature.asc
Description: This is a digitally signed message part


Re: Semantics of circular imports

2022-03-27 Thread Maxime Devos
Philip McGrath schreef op zo 27-03-2022 om 10:12 [-0400]:
> (Also, what is a "compilation unit" in Guile? Is it ever something
> other  than a single module corresponding to a single file
> (potentially using  `include` to incorporate other files at expand
> time?)

(the following explanation ignores (guile)Eval when, which seems to
assign a different meaning)

IIUC, a compilation unit is what is turned into a .go file as a unit,
full of literals and code.  There are at least three situations:

  * (common):   If "foo.scm" is of the form

  (define-module (foo) #:use-module (bar)) ... (stuff)

then, if, "foo.scm" is compiled "foo.go", "foo.go" contains code
that constructs the value of global variables (procedures etc.),
fix ups relocations, creates a module object, add the variables
to the module object, and registers the module into the module
system and runs (stuff)

  * (uncommon, discouraged):  "foo.scm" can, in principle, contain
multiple modules:

(define-module (bar) ...) ...
(define-module (foo) ...) ...

Then "foo.go" will contain code initialising both the modules.
It can be rather confusing though, so I cannot recommend this.

  * (common):  It is also possible to compile Scheme files that don't
define modules and only import some modules, e.g.

(use-modules (fibonnaci))
(for-each display (fibonacci-numbers #:upto 900))

Then when "foo.go" is loaded, the fibonacci numbers are printed.

Greetings,
Maxime


signature.asc
Description: This is a digitally signed message part


Re: Semantics of circular imports

2022-03-27 Thread Maxime Devos
Philip McGrath schreef op zo 27-03-2022 om 10:12 [-0400]:
> The use of "top-level" to refer to definitions within a module is 
> somewhat confusing to me. I usually understand "top-level" to refer
> to 
> the kind of interactive REPL environment for which R6RS leaves the 
> semantics unspecified. Racket uses "module-level variable"  and
> "module 
> context" in contrast to "top-level variable" and "top-level context"
> to
> make this distinction.[1][2][3] (There are also R6RS "top-level 
> programs", but I wouldn't think of those unless made very clear from 
> context.)

In Guile, if you start a REPL, the REPL is inside some module.  By
default, this module is the (guile-user) module (or (guix-user), when
using "guix repl"), although this can be changed with ',m' and maybe by
stepping through the debugger (not sure).

As such, if you run (define foo 'bar) inside a REPL currently in
(guile-user), then this corresponds to defining a top-level
variable/module variable inside the (guile-user) module.

Summarised: REPL environments have a corresponding Guile module and in
Guile, there is no meaningful distinction between "top-level variable"
and "module variable", unlike in Racket.

Greetings,
Maxime.


signature.asc
Description: This is a digitally signed message part


Re: Semantics of circular imports

2022-03-27 Thread Maxime Devos
Philip McGrath schreef op zo 27-03-2022 om 10:12 [-0400]:
> Oh, wow. I definitely had not realized that, *even inside a
> declarative 
> module*, a reference to a variable with no statically visible
> definition 
> would semantically be a dynamic lookup in a mutable environment at 
> runtime (rather than a compile-time error), though I do see now that 
> `info guile declarative` does indeed say that marking a module as 
> declarative "applies only to the subset of top-level definitions that
> are themselves declarative: those that are defined within the 
> compilation unit, and not assigned (‘set!’) or redefined within the 
> compilation unit."
> 
> Does this mean that Guile treats all imported bindings as non-
> declarative?
> This seems like a big barrier to cross-module inlining, though IIUC
> Guile
> currently doesn't do much of that by default (maybe for this reason).

To my understanding, declarative modules are orthogonal to circular
imports.  All declarative modules do, is telling the Guile compiler
that ‘yes, inlining is fine, I won't change the value of these top-
level variables’.

Declarativity does not change the module variable lookup system and
module loading system, it only changes the set of optimisations.

Greetings,
Maxime.


signature.asc
Description: This is a digitally signed message part


Re: Semantics of circular imports

2022-03-27 Thread Philip McGrath
Hi,

(Apparently I wrote this a month ago but left it sitting in "Drafts" ...)

On 2/20/22 12:47, Maxime Devos wrote:
> Philip McGrath schreef op zo 20-02-2022 om 11:47 [-0500]:
>> I was just (or maybe am still?) dealing with some issues caused by cyclic
>> imports of package modules while updating Racket to 8.4: see in particular
>> , as well as #66, #112, and #113 in the
>> same thread.
>> [...]
>> I find the semantics of Guile's cyclic module imports very confusing,
>> and I don't know of any documentation for what is and isn't supported
>> other than advice from Ludo’ in > —is there any?
> 
> (The following explanation ignores syntax transformers, #:select and
> #:autoload.)
> 
> Basically, a module consists of a hash table and a thunk
> initialising the hash table.  A few situations to demonstrate:
> 
> ;; Non-cyclic
> (define-module (foo)
>#:export (foo))
> (define foo 0)
> 
> (define-module (bar)
>#:export (bar)
>#:use-module (foo))
> (define bar (+ 1 foo))
> 
> The thunk of 'foo' would be
> 
>(lambda ()
>  (set-module-value! '(foo) 'foo 0))
> 
> and the thunk of 'bar' would be
> 
>(lambda ()
>  ;; This calls the thunk of 'foo' if it hasn't yet been called
>  ;; before.
>  (initialise-module '(foo))
>  (set-module-value! '(bar) 'bar (+ 1 (module-value '(foo) 'foo 0
> 
> ;; Cyclic, non-problematic
> (define-module (foo)
>#:export (foo)
>#:use-module (bar))
> (define foo 0)
> (define (calculate-foobar)
>(+ 1 (calculate-bar))
> 
> (define-module (bar)
>#:export (calculate-bar)
>#:use-module (foo))
> (define (calculate-bar) (+ 1 foo))
> 
> The initialisation thunk of 'foo' would be
> 
>   (lambda ()
> (initialise-module '(bar))  ; L1
> (set-module-value! '(foo) 0) ; L2
> (set-module-value! '(foo) 'calculate-foobar ; L3
>   (lambda () (+ 1 ((module-value '(bar) 'calculate-bar)) ; L4
> 
> and the thunk of 'bar' is:
> 
>(lambda ()
>  (initialise-module '(foo)) ; L6
>  (set-module-value! '(bar) 'calculate-bar ; L7
>(lambda () (+ 1 (module-value '(foo) 'foo) ; L8
> 
> Now let's see what happens if the module (bar) is loaded:
> 
> ; Initialising '(bar)'
> (initialise-module '(foo)) ; L6
> ;; (foo) has not yet begun initialisation, so run the thunk:
> ->  (initialise-module '(bar)) ; L1
> ;; (bar) is being initialised, so don't do anything here
> -> (set-module-value! '(foo) 0) ; L2
> -> (set-module-value! '(foo) 'calculate-foobar ; L3
>  (lambda () (+1 ((module-value '(bar) 'calculate-bar ; L4
> 
>The hash table of '(bar)' does not yet contain 'calculate-bar',
>but that's not a problem because the procedure 'calculate-foobar'
>is not yet run.
> (set-module-value! '(bar) '(calculate-bar) ; L7
>(lambda () (+ 1 (module-value '(foo) 'foo ; L8
> ;; The hash table of '(foo)' contains 'foo', so no problem!
> ;; Alternatively, even if '(foo)' did not contain 'foo',
> ;; the procedure '(calculate-bar)' is not yet run, so no problem!

Oh, wow. I definitely had not realized that, *even inside a declarative 
module*, a reference to a variable with no statically visible definition 
would semantically be a dynamic lookup in a mutable environment at 
runtime (rather than a compile-time error), though I do see now that 
`info guile declarative` does indeed say that marking a module as 
declarative "applies only to the subset of top-level definitions that 
are themselves declarative: those that are defined within the 
compilation unit, and not assigned (‘set!’) or redefined within the 
compilation unit."

Does this mean that Guile treats all imported bindings as non-declarative?
This seems like a big barrier to cross-module inlining, though IIUC Guile
currently doesn't do much of that by default (maybe for this reason).

The use of "top-level" to refer to definitions within a module is 
somewhat confusing to me. I usually understand "top-level" to refer to 
the kind of interactive REPL environment for which R6RS leaves the 
semantics unspecified. Racket uses "module-level variable"  and "module 
context" in contrast to "top-level variable" and "top-level context" to
make this distinction.[1][2][3] (There are also R6RS "top-level 
programs", but I wouldn't think of those unless made very clear from 
context.)

(Also, what is a "compilation unit" in Guile? Is it ever something other 
than a single module corresponding to a single file (potentially using 
`include` to incorporate other files at expand time?)

> 
> ;; Done!
> 
> Now for a problematic import cycle:
> 
> (define-module (foo)
>#:export (foo)
>#:use-module (bar))
> (define foo (+ 1 bar))
> 
> (define-module (bar)
>#:export (bar)
>#:use-module (foo))
> (define bar (+ 1 foo))
> 
> Now let's reason what happens when we try importing 'bar'.
> The init thunk of '(foo)' is:
> 
>(lambda ()
>  

Re: PipeWire as a PulseAudio replacement (was Re: The Shepherd on Fibers)

2022-03-27 Thread Brendan Tildesley

On 27/3/22 01:24, Josselin Poiret wrote:


Hello Brendan,

Brendan Tildesley  writes:

I would like to replace pulseaudio with pipewire as the default in
%desktop-services, the only hurdle is how to launch the user daemons in all the
different desktop configurations one might use. Other distros use systemd's
socket activation to magically launch pipewire.

Otherwise XDG autostarts or some kind of guix home service could
launch it?

The main issue for PipeWire is that it really doesn't support running a
single system-wide daemon as we're doing with PulseAudio, so you would
need to launch it through XDG autostart, guix home or something similar
like you said!


I think this is not right. Pulseaudio and Pipewire are both "user services".
The Guix (pulseaudio-service-type) merely sets up some global configuration 
files
and evironment variables. Actually these could be a part of the user profile if 
one
really wanted. The only parts that actually need to be done by root is the udev 
service
and the alsa service setting two configuration files.

Pulseaudio is automatically started by applications that make use of it via 
DBUS.
I don't understand how that works, but for whatever reason Pipewire's official 
way
to launch is via systemd sockets. Systems without systemd use XDG autolaunch 
with a
trivial script like this one:
https://gitweb.gentoo.org/repo/gentoo.git/tree/media-video/pipewire/files/gentoo-pipewire-launcher.in

So it is not difficult at all to run Pipewire, just a method must be chosen.



One thing that I think is blocking right now is that PipeWire (or
actually WirePlumber, I don't remember) would need to see some
environment variables set by other user services eg. session D-Bus or
even the compositor, which isn't possible yet with Shepherd.


Which environment variables are you talking about? I'm running pipewire on Guix 
System

and it seems to work fine.


Best,