Subject: Re: bug#7995: Guile support in Automake

From: Ralf Wildenhues <[email-masked]>
Date: Sun, 20 Feb 2011 08:30:36 +0100

[ http://debbugs.gnu.org/cgi/bugreport.cgi?bug=7995 aka
  http://thread.gmane.org/gmane.comp.sysutils.automake.bugs/5303 ]

* Ralf Wildenhues wrote on Sun, Feb 06, 2011 at 11:22:57PM CET:
> Automake should support Guile.

> I actually have patches for some tests, documentation and half an
> implementation from last year;

Here we go.  For now I've done little with the patches except rebase
and squash the intermediate stages, update copyright years, remove
notes from git, and ensure there are no syntax errors.

That means however, that nothing really works yet.  It's still a total
mess.  So what I would like to ask from readers at this point is:
please go through the doc changes and let's discuss them first.
Also, it is important to not step on guile/meta/guile.m4 toes (or vice
versa), so some checking for that is prodent.  When we know what is
desired, the tests should be amended/fixed to cover that, and then we
can fix the implementation to follow.

If you prefer, I can also put them in a temporary branch (which for the
moment I would expect to be rewound at some point later).

Here's a preliminary list of issues that I see:

- Why guile_GUILE and not guile_LISP?  What's the rationale for naming
  it differently, and what's the rationale for actually treating it
  differently?  This question has two parts: LISP is treated by emacs
  not guile-tools, and IIUC then the idea was that GUILE is compiled
  already at 'make all' time and not just at 'make install' time, right?
  Is the latter part just "nice to have" or an important feature?

- The current tests assume _GUILE sources are distributed by default;
  OTOH, _LISP are not.  Rationale for this semantic difference?

- Please fix errors you can find in the tests; esp. the extension module
  in guile3.test doesn't seem to do the right thing yet (with my
  unfinished implementation).

- I renamed guileextensiondir from earlier suggestions to guileextdir,
  both for brevity, and to avoid the question of whether there is a
  trailing 's' in the name.  OK?

- The Guile manual documents Autoconf macros distributed in
  $datarootdir/aclocal/guile.m4.  The names in there are a bit
  unfortunate in that the macros more or less use the same GUILE_*
  namespace that we would like to use for some variables (which means
  you cannot easily turn on checking for unexpanded macro names through
  something like
    m4_pattern_forbid([^GUILE_])dnl

  and there is even overlap in the semantics and shell variable names.
  We need to address that; esp. since the macros shipped with Guile have
  been out there for long, we cannot just expect them to disappear
  instantly.  There should be a clear, backward-compatible upgrade path,
  and a clear intent on how usage should be in the future, for Guile
  users both with and without Automake.

- The handling of compile and link flags is still quite suboptimal.
  I still need to think about that a bit more.

- I haven't yet considered the handling of flags to uninstalled module
  stuff.  This is just TODO.

- My current plan is to either not provide something like
    foo_scm_GUILEFLAGS = override for $(AM_GUILEFLAGS)

  or to not let it cause renamed .go files.  Do you think users will
  need per-target guile-tools compile flags?  Because if they do, then
  we need to document this stuff, and that it's not in line with how
  Automake operates elsewhere, etc.

- The register_language bits in the last patch are totally unused yet,
  as the machinery isn't yet able to handle languages that either don't
  use a linker in the end, or don't rename objects with per-target flags
  which is probably desirable for Guile (similar to how Python support
  works).

I should apologize for taking totally random and unorganized notes
below.  They are basically just a jot-down from last year of what Andy
and Ludo said.

Thanks,
Ralf

Notes about Guile support:

# set from guile-config
# or from pkg-config if guile major version known

.go: compiled guile files
     sys-dep not executable byte-code
.scm: source guile files (can have other extensions)
.sls .sps .ss

One problem will be: when we add Go support, .go has conflicting
semantics.

cat > Makefile.am <<\END
guile_GUILE = compiled-and-installed.scm
nodist_guile_GUILE = not-distributed.scm
guile_DATA = not-compiled.scm
noinst_GUILE = compiled-but-not-installed.scm
dist_noinst_DATA = just-distributed-blob.scm

# object files will be installed in respective subdir of guileexecdir.
nobase_guile_GUILE = installed-in-subdir/foo.scm

pkgguile_GUILE = installed-in-package-dir.scm
END

# without guile compiler, just install sources
# but also install objects whenever possible

GUILE_TOOLS = guile-tools
GUILE_TOOLS_COMPILE = $(GUILE_TOOLS) compile
GUILE_COMPILE = $(GUILE_TOOLS_COMPILE) $(AM_GUILEFLAGS) $(GUILEFLAGS)

$(GUILE_TOOLS_COMPILE) $(AM_GUILEFLAGS) $(GUILEFLAGS) -o $@ $<
# no ordering req
# no renaming

foo_scm_GUILEFLAGS should not cause the output to be renamed.

AM_PATH_GUILE([minimum-version], [if-available], [if-not=AC_MSG_ERROR])

# effective version: first numbers on the first line

guile-tools --effective-version
       X.Y
  or
guile-tools --version | sed 's/[1-9][0-9.]'

error out if X.Y is < 1.8

# not: guile -c '(begin (display (effective-version)) (newline))'

# .go

# guile-tools compile load path
# -L . -L $(srcdir) or GUILE_LOAD_PATH = a:b:c: GUILE_LOAD_COMPILED_PATH
# -L is for source
# -M is for output
# GUILE_LOAD_PATH is for source only, lower prio than -L
# GUILE_LOAD_COMPILED_PATH is for obj only

.scm.go:

libtool --mode=execute -dlopen foo.la guile bar.scm
bar.scm:
(dynamic-link "foo")

make install
guile bar.scm

bar.scm loads foo.la

bar.scm

# 1.6: error
# 1.8:
# guiledir = $(datarootdir)/guile/site
# > 1.8:
# guiledir = $(datarootdir)/guile/site/X.Y
#      possibly version-independent
#      sources for users
# guilepkgdir = $(guiledir)/$(PACKAGE)
#
# for 1.8:
# guileexecdir = $(libdir)
# > 1.8:
# guileexecdir = $(libdir)/guile/X.Y
#      version-dependent
#
# guilesitedir = $(guiledir)/site
#
# guileextensiondir = $(guileexecdir)/extensions
#

cat > Makefile.am <<\END

guile_GUILE = foo.scm bar.scm baz.scm
# The next line looks wrong; should be noinst_GUILE?
noinst_guile_GUILE = foo.scm bar.scm baz.scm

guile_DATA = not-compiled.scm

nobase_guile_GUILE = sub/foo.scm
nobase_pkgguile_GUILE = sub/foo.scm
# compiled object goes into subdir as well.

nodist_guile_GUILE

guileextension_LTLIBRARIES = foo.la
foo_la_LDFLAGS = -module

foo_la_LIBADD = $(GUILELIBS)
foo_la_CFLAGS = $(GUILECFLAGS)
foo_la_CPPFLAGS = $(GUILECPPFLAGS)
AM_CPPFLAGS
AM_CFLAGS
# AM_LDADD
# there should be an AM_LIBADD

# or: in configure.ac:
CFLAGS="$GUILECFLAGS $CPPFLAGS"
LIBS="$GUILELIBS $LIBS"