gnu: graphviz: Enable Guile library.

Message ID 87shxrpmbj.fsf@gnu.org
State New
Headers

Commit Message

Roel Janssen May 9, 2016, 10:17 a.m. UTC
  Dear Guix,

I would like to add graphviz's Guile interface to the package
definition.  This introduces two new (top-level) dependencies to the
graphviz package: guile and swig.

An example of the Guile interface:
(load-extension (string-append (getenv "HOME") "/.guix-profile/lib/graphviz/guile/libgv_guile.so") "SWIG_init")

;; Define the graph's nodes and edges.
(define my-graph (graph "G"))
(edge
  (node my-graph "A")
  (node my-graph "B"))

;; Set a lay-out and render it to a file.
(layout my-graph "dot")
(render my-graph "svg" "/home/roel/my-graph.svg")

The patch is fairly straightforward, since all that is needed is include
the dependencies to the inputs:

>From 8e93c01a9c0909f49c4b644c965824fd5f74527a Mon Sep 17 00:00:00 2001
From: Roel Janssen <roel@gnu.org>
Date: Mon, 9 May 2016 11:26:18 +0200
Subject: [PATCH] gnu: graphviz: Enable Guile library.

gnu/packages/graphviz.scm (graphviz): Add inputs to enable the Guile library.
---
 gnu/packages/graphviz.scm | 4 ++++
 1 file changed, 4 insertions(+)
  

Comments

Ludovic Courtès May 9, 2016, 8:37 p.m. UTC | #1
Roel Janssen <roel@gnu.org> skribis:

> I would like to add graphviz's Guile interface to the package
> definition.  This introduces two new (top-level) dependencies to the
> graphviz package: guile and swig.
>
> An example of the Guile interface:
> (load-extension (string-append (getenv "HOME") "/.guix-profile/lib/graphviz/guile/libgv_guile.so") "SWIG_init")

Doesn’t Graphviz provide a module that does this?  Would be more
convenient.

> ;; Define the graph's nodes and edges.
> (define my-graph (graph "G"))
> (edge
>   (node my-graph "A")
>   (node my-graph "B"))
>
> ;; Set a lay-out and render it to a file.
> (layout my-graph "dot")
> (render my-graph "svg" "/home/roel/my-graph.svg")

Indeed, I wonder why we didn’t try before.  :-)

> The patch is fairly straightforward, since all that is needed is include
> the dependencies to the inputs:

Could you check the output of ‘guix size’ before and after the change?

Thanks!

Ludo’.
  
Roel Janssen May 9, 2016, 8:54 p.m. UTC | #2
Ludovic Courtès writes:

> Roel Janssen <roel@gnu.org> skribis:
>
>> I would like to add graphviz's Guile interface to the package
>> definition.  This introduces two new (top-level) dependencies to the
>> graphviz package: guile and swig.
>>
>> An example of the Guile interface:
>> (load-extension (string-append (getenv "HOME") "/.guix-profile/lib/graphviz/guile/libgv_guile.so") "SWIG_init")
>
> Doesn’t Graphviz provide a module that does this?  Would be more
> convenient.

Not that I'm aware of (and I looked for it..).  I think this is because
it is automatically generated using SWIG.  I had to experiment a bit to
find out that the functions exposed in Guile did not have a namespace (gv.).

I could create a module for it, and then move libgc_guile.so to
lib/guile/2.0/extensions/.

There are functions called "rm" and "write" which are obviously already
used for other purposes in Scheme.  These functions will have to be
renamed or just left out of the Scheme module.  I must look again in the
Guile manual to find out more about exporting a function as a different
name.

>> ;; Define the graph's nodes and edges.
>> (define my-graph (graph "G"))
>> (edge
>>   (node my-graph "A")
>>   (node my-graph "B"))
>>
>> ;; Set a lay-out and render it to a file.
>> (layout my-graph "dot")
>> (render my-graph "svg" "/home/roel/my-graph.svg")
>
> Indeed, I wonder why we didn’t try before.  :-)

There's also a function to read a string in the dot language format.
Would it be desired to have something like:
  guix graph gcc --format=pdf

>> The patch is fairly straightforward, since all that is needed is include
>> the dependencies to the inputs:
>
> Could you check the output of ‘guix size’ before and after the change?

I will do that.

Thanks for your time.

Kind regards,
Roel Janssen
  
Danny Milosavljevic May 10, 2016, 5:53 a.m. UTC | #3
Hi,

On Mon, 09 May 2016 22:54:00 +0200
Roel Janssen <roel@gnu.org> wrote:

> it is automatically generated using SWIG.  I had to experiment a bit to
> find out that the functions exposed in Guile did not have a namespace (gv.).

You can add a prefix when importing, so the symbols of the module shouldn't have a prefix - the user would end up with two prefixes (or would have to cut the other prefix out and replace it or something).

     (use-modules ((gdb) #:renamer (symbol-prefix-proc 'gdb:)))

See also <http://www.swig.org/Doc2.0/Guile.html>.

> There are functions called "rm" and "write" which are obviously already
> used for other purposes in Scheme.  These functions will have to be
> renamed or just left out of the Scheme module.  

The user can specify which symbols to import (and also rename stuff there if needed) so I'd do nothing of the sort.

     (use-modules ((ice-9 popen)
                   #:select ((open-pipe . pipe-open) close-pipe)
                   #:renamer (symbol-prefix-proc 'unixy:)))

It's true that people still use the form

   (use-modules (xxx))

without specifying what the final imported symbols are, but that's something I consider bad practise in most cases (in any language - hey let's import random stuff into my namespace and have which module it gets each function from change on each package update. How about no?).

For example, let's say you have two modules "a" and "b".
Let module "a" contain "select".
Let module "b" contain "write".

Let's say you use it as

(use-modules (a) (b))

; main program
(write ...)
(select ...)

Then it will use b's write, a's select in your program, repectively. Say you release it and people use it. 

Now let's say someone devious (not really, it can make sense to him) adds "select" to module "b". Suddenly your program will use b's select *even though you didn't change anything in it*. 

Bad.

A complete set to try this:

$ export GUILE_LOAD_PATH=.

;;; a.scm
(define-module (a) #:export (select))
(define (select) (display "a.select") (newline))

;;; b.scm
(define-module (b) #:export (write select))
(define (write) (display "b.write") (newline))
(define (select) (display "b.select") (newline))

;;; main.scm
(use-modules (a) (b))
(write)
(select)

Note that you do get warnings by guile

WARNING: (guile-user): imported module (a) overrides core binding `select'
WARNING: (guile-user): `select' imported from both (a) and (b)
b.select
WARNING: (guile-user): imported module (b) overrides core binding `write'
b.write

... which is nice.
  
Roel Janssen May 10, 2016, 9:15 a.m. UTC | #4
Hello Danny,

Thank you for your elaborate response.  This makes it quite easy for me
to write the module file.  I added "write" and "rm" to the module, which
should make it complete.

What is the preferred way to include the module file to the package?
Should I create another package with this file alone, and use it as a
propagated input for graphviz?

Kind regards,
Roel Janssen


Danny Milosavljevic writes:

> Hi,
>
> On Mon, 09 May 2016 22:54:00 +0200
> Roel Janssen <roel@gnu.org> wrote:
>
>> it is automatically generated using SWIG.  I had to experiment a bit to
>> find out that the functions exposed in Guile did not have a namespace (gv.).
>
> You can add a prefix when importing, so the symbols of the module shouldn't have a prefix - the user would end up with two prefixes (or would have to cut the other prefix out and replace it or something).
>
>      (use-modules ((gdb) #:renamer (symbol-prefix-proc 'gdb:)))
>
> See also <http://www.swig.org/Doc2.0/Guile.html>.
>
>> There are functions called "rm" and "write" which are obviously already
>> used for other purposes in Scheme.  These functions will have to be
>> renamed or just left out of the Scheme module.  
>
> The user can specify which symbols to import (and also rename stuff there if needed) so I'd do nothing of the sort.
>
>      (use-modules ((ice-9 popen)
>                    #:select ((open-pipe . pipe-open) close-pipe)
>                    #:renamer (symbol-prefix-proc 'unixy:)))
>
> It's true that people still use the form
>
>    (use-modules (xxx))
>
> without specifying what the final imported symbols are, but that's something I consider bad practise in most cases (in any language - hey let's import random stuff into my namespace and have which module it gets each function from change on each package update. How about no?).
>
> For example, let's say you have two modules "a" and "b".
> Let module "a" contain "select".
> Let module "b" contain "write".
>
> Let's say you use it as
>
> (use-modules (a) (b))
>
> ; main program
> (write ...)
> (select ...)
>
> Then it will use b's write, a's select in your program, repectively. Say you release it and people use it. 
>
> Now let's say someone devious (not really, it can make sense to him) adds "select" to module "b". Suddenly your program will use b's select *even though you didn't change anything in it*. 
>
> Bad.
>
> A complete set to try this:
>
> $ export GUILE_LOAD_PATH=.
>
> ;;; a.scm
> (define-module (a) #:export (select))
> (define (select) (display "a.select") (newline))
>
> ;;; b.scm
> (define-module (b) #:export (write select))
> (define (write) (display "b.write") (newline))
> (define (select) (display "b.select") (newline))
>
> ;;; main.scm
> (use-modules (a) (b))
> (write)
> (select)
>
> Note that you do get warnings by guile
>
> WARNING: (guile-user): imported module (a) overrides core binding `select'
> WARNING: (guile-user): `select' imported from both (a) and (b)
> b.select
> WARNING: (guile-user): imported module (b) overrides core binding `write'
> b.write
>
> ... which is nice.
  
Roel Janssen May 10, 2016, 1:08 p.m. UTC | #5
Hello there,

I now have a graphviz-guile package with a graphviz.scm module file.

Where should I link/copy/move libgv_guile.so?

I tried:
$PACKAGE_OUTPUT/lib/
$PACKAGE_OUTPUT/lib/guile/2.0/
$PACKAGE_OUTPUT/lib/guile/2.0/extensions/

But it seems my system only looks in:
/lib
/gnu/store/...-gcc-4.9.3-lib/lib/
/gnu/store/...-glibc-2.22/lib/
/gnu/store/...-guile-2.0.11/lib/

Kind regards,
Roel Janssen


Roel Janssen writes:

> Hello Danny,
>
> Thank you for your elaborate response.  This makes it quite easy for me
> to write the module file.  I added "write" and "rm" to the module, which
> should make it complete.
>
> What is the preferred way to include the module file to the package?
> Should I create another package with this file alone, and use it as a
> propagated input for graphviz?
>
> Kind regards,
> Roel Janssen
>
>
> Danny Milosavljevic writes:
>
>> Hi,
>>
>> On Mon, 09 May 2016 22:54:00 +0200
>> Roel Janssen <roel@gnu.org> wrote:
>>
>>> it is automatically generated using SWIG.  I had to experiment a bit to
>>> find out that the functions exposed in Guile did not have a namespace (gv.).
>>
>> You can add a prefix when importing, so the symbols of the module shouldn't have a prefix - the user would end up with two prefixes (or would have to cut the other prefix out and replace it or something).
>>
>>      (use-modules ((gdb) #:renamer (symbol-prefix-proc 'gdb:)))
>>
>> See also <http://www.swig.org/Doc2.0/Guile.html>.
>>
>>> There are functions called "rm" and "write" which are obviously already
>>> used for other purposes in Scheme.  These functions will have to be
>>> renamed or just left out of the Scheme module.  
>>
>> The user can specify which symbols to import (and also rename stuff there if needed) so I'd do nothing of the sort.
>>
>>      (use-modules ((ice-9 popen)
>>                    #:select ((open-pipe . pipe-open) close-pipe)
>>                    #:renamer (symbol-prefix-proc 'unixy:)))
>>
>> It's true that people still use the form
>>
>>    (use-modules (xxx))
>>
>> without specifying what the final imported symbols are, but that's something I consider bad practise in most cases (in any language - hey let's import random stuff into my namespace and have which module it gets each function from change on each package update. How about no?).
>>
>> For example, let's say you have two modules "a" and "b".
>> Let module "a" contain "select".
>> Let module "b" contain "write".
>>
>> Let's say you use it as
>>
>> (use-modules (a) (b))
>>
>> ; main program
>> (write ...)
>> (select ...)
>>
>> Then it will use b's write, a's select in your program, repectively. Say you release it and people use it. 
>>
>> Now let's say someone devious (not really, it can make sense to him) adds "select" to module "b". Suddenly your program will use b's select *even though you didn't change anything in it*. 
>>
>> Bad.
>>
>> A complete set to try this:
>>
>> $ export GUILE_LOAD_PATH=.
>>
>> ;;; a.scm
>> (define-module (a) #:export (select))
>> (define (select) (display "a.select") (newline))
>>
>> ;;; b.scm
>> (define-module (b) #:export (write select))
>> (define (write) (display "b.write") (newline))
>> (define (select) (display "b.select") (newline))
>>
>> ;;; main.scm
>> (use-modules (a) (b))
>> (write)
>> (select)
>>
>> Note that you do get warnings by guile
>>
>> WARNING: (guile-user): imported module (a) overrides core binding `select'
>> WARNING: (guile-user): `select' imported from both (a) and (b)
>> b.select
>> WARNING: (guile-user): imported module (b) overrides core binding `write'
>> b.write
>>
>> ... which is nice.
  
Ludovic Courtès May 10, 2016, 1:31 p.m. UTC | #6
Roel Janssen <roel@gnu.org> skribis:

> What is the preferred way to include the module file to the package?
> Should I create another package with this file alone, and use it as a
> propagated input for graphviz?

Could you first submit it upstream?

> I now have a graphviz-guile package with a graphviz.scm module file.
>
> Where should I link/copy/move libgv_guile.so?
>
> I tried:
> $PACKAGE_OUTPUT/lib/
> $PACKAGE_OUTPUT/lib/guile/2.0/
> $PACKAGE_OUTPUT/lib/guile/2.0/extensions/
>
> But it seems my system only looks in:
> /lib
> /gnu/store/...-gcc-4.9.3-lib/lib/
> /gnu/store/...-glibc-2.22/lib/
> /gnu/store/...-guile-2.0.11/lib/

‘load-extension’ searches for shared objects in the extension directory:

--8<---------------cut here---------------start------------->8---
scheme@(guix gexp)> (assoc-ref %guile-build-info 'extensiondir)
$14 = "/home/ludo/soft/lib/guile/2.0/extensions"
--8<---------------cut here---------------end--------------->8---

… and in whatever ‘LTDL_LIBRARY_PATH’ points to
(info "(libtool) Libltdl interface").

HTH!

Ludo’.
  

Patch

diff --git a/gnu/packages/graphviz.scm b/gnu/packages/graphviz.scm
index 09f475b..ddb3e67 100644
--- a/gnu/packages/graphviz.scm
+++ b/gnu/packages/graphviz.scm
@@ -25,6 +25,7 @@ 
   #:use-module (gnu packages gtk)
   #:use-module (gnu packages xml)
   #:use-module (gnu packages glib)
+  #:use-module (gnu packages guile)
   #:use-module (gnu packages bison)
   #:use-module (gnu packages image)
   #:use-module (gnu packages autotools)
@@ -32,6 +33,7 @@ 
   #:use-module (gnu packages fontutils)
   #:use-module (gnu packages compression)
   #:use-module (gnu packages gd)
+  #:use-module (gnu packages swig)
   #:use-module ((guix licenses) #:select (lgpl2.0+ epl1.0)))
 
 (define-public graphviz
@@ -75,6 +77,8 @@ 
        ("libX11" ,libx11)
        ("gts" ,gts)
        ("gd" ,gd)                                 ; FIXME: Our GD is too old
+       ("guile" ,guile-2.0)
+       ("swig" ,swig)
        ("pango" ,pango)
        ("fontconfig" ,fontconfig)
        ("freetype" ,freetype)