From: "Vladimir 'φ-coder/phcoder' Serbinenko" <phcoder@gmail.com>
To: grub-devel@gnu.org
Subject: Re: [PATCH] Re-enable grub-extras
Date: Thu, 23 Sep 2010 16:36:33 +0200 [thread overview]
Message-ID: <4C9B65F1.10909@gmail.com> (raw)
In-Reply-To: <20100923130819.GV21862@riva.ucam.org>
[-- Attachment #1: Type: text/plain, Size: 19637 bytes --]
Go ahead for both trunk and extras
On 09/23/2010 03:08 PM, Colin Watson wrote:
> On Tue, Sep 21, 2010 at 07:35:30PM +0100, Colin Watson wrote:
>
>> Here's a patch to re-enable grub-extras by allowing extra modules to
>> provide Autogen definitions files. A few things to note:
>>
> Vladimir commented on this on IRC, noting three problems. In reverse
> order of complexity:
>
> 1) The GRUB_CONTRIB check in autogen.sh should also check for
> grub-core/contrib.
>
> Fixed.
>
> 2) What's the problem with renaming g2hdr.bin to g2hdr.img?
>
> I know of at least one piece of software which expects the current file
> name: win32-loader, written by Robert and maintained in Debian. It
> probably wouldn't be completely awful to change this, but it would be
> nice not to need to. That said, perhaps g2hdr.bin could be a symlink to
> g2hdr.img (which could be done in Makefile.common). I've updated my
> patch to do this, and removed the extension-override facility from
> gentpl.py.
>
> 3) It would be nice if extra modules could add new sources to existing
> targets defined in one of the main definitions files: for example, it
> would be useful to be able to add zfs to libgrub.a.
>
> This was the hard bit that took me a day or two to fix.
>
> Vladimir's original suggestion on IRC was to create a separate
> libgrubzfs.a and arrange to link the utilities with that as well. When
> I looked into this, I decided that I didn't like this approach because
> it simply pushes the problem of appending to an existing list up a
> level; as far as the Autogen definitions go, there isn't a significant
> difference between appending to grub_probe_LDADD and appending to
> libgrub_a_SOURCES. I would prefer to solve this some other way.
>
> My preferred approach is to try not to expose any of the difficulties in
> the definitions file, so that it can just look like this:
>
> library = {
> name = libgrub.a;
> common = contrib/zfs/zfs.c;
> common = contrib/zfs/zfs_lzjb.c;
> common = contrib/zfs/zfs_sha256.c;
> common = contrib/zfs/zfs_fletcher.c;
> cppflags = '$(ZFS_CPPFLAGS)';
> cflags = '$(ZFS_CFLAGS)';
> };
>
> Doing this actually turned out to be very difficult because Autogen's
> native macros aren't powerful enough: they can only really emit text
> rather than using temporary storage, which means that you can't do
> things like "look for all the library blocks with the same name and
> concatenate them" or "append to _SOURCES variables if we've seen them
> before". Some Automake variables can be handled with simple appends
> while some of them have some boilerplate only at the start which
> shouldn't be repeated; Automake variables must be initialised exactly
> once on all possible intersections of conditional paths; and we should
> also avoid generating duplicate rules. All these constraints make it a
> hard problem.
>
> Fortunately, Autogen supports embedding bits of Guile, which makes the
> problem merely hard rather than impossible. I tried a few different
> approaches, and the one that I found to be most practical is in the
> following patch: effectively we remember whether we've seen a given
> target before and treat it slightly differently, and furthermore we emit
> initialisations for non-global variables to avoid problems with
> Automake's restrictions on variable initialisation.
>
> For now, I only implemented this for 'library' blocks, so something that
> wants to compile extra files into the GRUB kernel for example will be
> out of luck. If people feel this is an onerous restriction then it's
> fairly easy to fix; I was just trying not to change too much at once,
> particularly for paths I wasn't going to test.
>
> Doing this involved feeding all the files relevant to a given Automake
> input stream to Autogen in one go, so I eliminated Makefile.gcry.am.
>
> This was an exercise in programming in six languages at once (Python,
> Autogen native macros, Guile, Autogen definitions, Automake, and make).
> I found it to be a bit much, and my impression is that Autogen got in
> the way more than it helped. I suggest that after 1.99 we should look
> at having a Python program generate Automake input directly, which would
> avoid many contortions and allow us to improve the output (it could
> merge the multiple _SOURCES lines into just one per conditional path,
> for instance). The .def file format is of course just fine as it is,
> and could easily be preserved.
>
>
>> * Extra modules may also provide Makefile.common with literal Automake
>> input, for those cases where it's too hard to cram things into
>> Autogen.
>>
> I also added Makefile.core.common and Makefile.util.common (starting to
> run out of good names) for literal Automake input that should only be
> used in grub-core or at the top level respectively. ntldr-img needed
> the former.
>
> Once again, the required patches to grub-extras modules are attached.
>
> 2010-09-22 Colin Watson <cjwatson@ubuntu.com>
>
> Re-enable grub-extras.
>
> * autogen.sh: Create symlinks to ${GRUB_CONTRIB} if necessary to
> avoid confusing Automake. Run autogen only twice, once for the top
> level and once for grub-core. Add Makefile.util.def and
> Makefile.core.def from extra modules to the appropriate autogen
> invocations. If Makefile.common exists in an extra module, include
> it in both Makefile.util.am and grub-core/Makefile.core.am;
> similarly, include any Makefile.util.common file in Makefile.util.am
> and any Makefile.core.common file in grub-core/Makefile.core.am.
> * conf/Makefile.common ($(top_srcdir)/grub-core/Makefile.core.am):
> Depend on $(top_srcdir)/grub-core/Makefile.gcry.def.
> ($(top_srcdir)/grub-core/Makefile.gcry.def): Remove.
> * grub-core/Makefile.am: Remove inclusion of Makefile.gcry.am.
>
> * gentpl.py (gvar_add): Turn GVARS into a set.
> (global_variable_initializers): Sort global variables on output.
> (vars_init): New function.
> (first_time): Likewise.
> (library): Ensure that non-global variable initialisations are
> emitted before the first time we emit code for a library block.
> Append to variables rather than setting them. Only emit
> noinst_LIBRARIES, BUILT_SOURCES, and CLEANFILES the first time for
> each conditional path.
> (program): installdir() emits an Autogen macro, so must be passed to
> var_add rather than gvar_add.
> (data): Likewise.
> (script): Likewise.
> (rules): New function, centralising handling for different target
> types. Set up Guile association lists for first_time and vars_init,
> and send most output to a diversion so that variable initialisations
> can be emitted first.
> (module_rules): Use new rules function.
> (kernel_rules): Likewise.
> (image_rules): Likewise.
> (library_rules): Likewise.
> (program_rules): Likewise.
> (script_rules): Likewise.
> (data_rules): Likewise.
>
> * configure.ac: Add AC_PROG_LN_S, for the benefit of ntldr-img.
>
> * .bzrignore: Add contrib and grub-core/contrib. Remove
> grub-core/Makefile.gcry.am.
>
> === modified file '.bzrignore'
> --- .bzrignore 2010-09-20 13:03:47 +0000
> +++ .bzrignore 2010-09-22 13:07:15 +0000
> @@ -104,9 +104,10 @@ grub-core/lib/libgcrypt-grub
> **/.deps-core
> **/.dirstamp
> Makefile.util.am
> +contrib
> grub-core/Makefile.core.am
> -grub-core/Makefile.gcry.am
> grub-core/Makefile.gcry.def
> +grub-core/contrib
> grub-core/genmod.sh
> grub-core/gensyminfo.sh
> grub-core/*.module
>
> === modified file 'autogen.sh'
> --- autogen.sh 2010-08-23 08:37:29 +0000
> +++ autogen.sh 2010-09-23 10:36:52 +0000
> @@ -14,9 +14,50 @@ echo "Creating Makefile.tpl..."
> python gentpl.py | sed -e '/^$/{N;/^\n$/D;}' > Makefile.tpl
>
> echo "Running autogen..."
> -autogen -T Makefile.tpl Makefile.util.def | sed -e '/^$/{N;/^\n$/D;}' > Makefile.util.am
> -autogen -T Makefile.tpl grub-core/Makefile.core.def | sed -e '/^$/{N;/^\n$/D;}' > grub-core/Makefile.core.am
> -autogen -T Makefile.tpl grub-core/Makefile.gcry.def | sed -e '/^$/{N;/^\n$/D;}' > grub-core/Makefile.gcry.am
> +
> +# Automake doesn't like including files from a path outside the project.
> +rm -f contrib grub-core/contrib
> +if [ "x${GRUB_CONTRIB}" != x ]; then
> + [ "${GRUB_CONTRIB}" = contrib ] || ln -s "${GRUB_CONTRIB}" contrib
> + [ "${GRUB_CONTRIB}" = grub-core/contrib ] || ln -s ../contrib grub-core/contrib
> +fi
> +
> +UTIL_DEFS=Makefile.util.def
> +CORE_DEFS='grub-core/Makefile.core.def grub-core/Makefile.gcry.def'
> +
> +for extra in contrib/*/Makefile.util.def; do
> + if test -e "$extra"; then
> + UTIL_DEFS="$UTIL_DEFS $extra"
> + fi
> +done
> +
> +for extra in contrib/*/Makefile.core.def; do
> + if test -e "$extra"; then
> + CORE_DEFS="$CORE_DEFS $extra"
> + fi
> +done
> +
> +cat $UTIL_DEFS | autogen -T Makefile.tpl | sed -e '/^$/{N;/^\n$/D;}' > Makefile.util.am
> +cat $CORE_DEFS | autogen -T Makefile.tpl | sed -e '/^$/{N;/^\n$/D;}' > grub-core/Makefile.core.am
> +
> +for extra in contrib/*/Makefile.common; do
> + if test -e "$extra"; then
> + echo "include $extra" >> Makefile.util.am
> + echo "include $extra" >> grub-core/Makefile.core.am
> + fi
> +done
> +
> +for extra in contrib/*/Makefile.util.common; do
> + if test -e "$extra"; then
> + echo "include $extra" >> Makefile.util.am
> + fi
> +done
> +
> +for extra in contrib/*/Makefile.core.common; do
> + if test -e "$extra"; then
> + echo "include $extra" >> grub-core/Makefile.core.am
> + fi
> +done
>
> echo "Saving timestamps..."
> echo timestamp > stamp-h.in
>
> === modified file 'conf/Makefile.common'
> --- conf/Makefile.common 2010-09-21 12:37:50 +0000
> +++ conf/Makefile.common 2010-09-22 13:09:44 +0000
> @@ -146,11 +146,7 @@ $(top_srcdir)/Makefile.util.am: $(top_sr
> mv $@.new $@
>
> .PRECIOUS: $(top_srcdir)/grub-core/Makefile.core.am
> -$(top_srcdir)/grub-core/Makefile.core.am: $(top_srcdir)/grub-core/Makefile.core.def $(top_srcdir)/Makefile.tpl
> - autogen -T $(top_srcdir)/Makefile.tpl $< | sed -e '/^$$/{N;/^\\n$$/D;}' > $@.new || (rm -f $@.new; exit 1)
> - mv $@.new $@
> -
> -.PRECIOUS: $(top_srcdir)/grub-core/Makefile.gcry.am
> -$(top_srcdir)/grub-core/Makefile.gcry.am: $(top_srcdir)/grub-core/Makefile.gcry.def $(top_srcdir)/Makefile.tpl
> - autogen -T $(top_srcdir)/Makefile.tpl $< | sed -e '/^$$/{N;/^\\n$$/D;}' > $@.new || (rm -f $@.new; exit 1)
> +$(top_srcdir)/grub-core/Makefile.core.am: $(top_srcdir)/grub-core/Makefile.core.def $(top_srcdir)/grub-core/Makefile.gcry.def $(top_srcdir)/Makefile.tpl
> + if [ "x$$GRUB_CONTRIB" != x ]; then echo "You need to run ./autogen.sh manually." >&2; exit 1; fi
> + autogen -T $(top_srcdir)/Makefile.tpl $(top_srcdir)/grub-core/Makefile.core.def $(top_srcdir)/grub-core/Makefile.gcry.def | sed -e '/^$$/{N;/^\\n$$/D;}' > $@.new || (rm -f $@.new; exit 1)
> mv $@.new $@
>
> === modified file 'configure.ac'
> --- configure.ac 2010-09-21 09:42:30 +0000
> +++ configure.ac 2010-09-22 12:11:35 +0000
> @@ -235,6 +235,7 @@ AC_PROG_LEX
> AC_PROG_YACC
> AC_PROG_MAKE_SET
> AC_PROG_MKDIR_P
> +AC_PROG_LN_S
>
> if test "x$LEX" = "x:"; then
> AC_MSG_ERROR([flex is not found])
>
> === modified file 'gentpl.py'
> --- gentpl.py 2010-09-19 13:24:45 +0000
> +++ gentpl.py 2010-09-22 21:01:22 +0000
> @@ -70,16 +70,15 @@ for platform in GRUB_PLATFORMS:
> #
> # Global variables
> #
> -GVARS = []
> +GVARS = set()
>
> def gvar_add(var, value):
> - if var not in GVARS:
> - GVARS.append(var)
> + GVARS.add(var)
> return var + " += " + value + "\n"
>
> def global_variable_initializers():
> r = ""
> - for var in GVARS:
> + for var in sorted(GVARS):
> r += var + " ?= \n"
> return r
>
> @@ -87,6 +86,16 @@ def global_variable_initializers():
> # Per PROGRAM/SCRIPT variables
> #
>
> +def vars_init(*var_list):
> + r = "[+ IF (if (not (assoc-ref seen-vars (get \".name\"))) \"seen\") +]"
> + r += "[+ (out-suspend \"v\") +]"
> + for var in var_list:
> + r += var + " = \n"
> + r += "[+ (out-resume \"v\") +]"
> + r += "[+ (set! seen-vars (assoc-set! seen-vars (get \".name\") 0)) +]"
> + r += "[+ ENDIF +]"
> + return first_time(r)
> +
> def var_set(var, value):
> return var + " = " + value + "\n"
>
> @@ -257,6 +266,15 @@ def platform_ccasflags(p): return platfo
> def platform_stripflags(p): return platform_specific_values(p, "_stripflags", "stripflags")
> def platform_objcopyflags(p): return platform_specific_values(p, "_objcopyflags", "objcopyflags")
>
> +#
> +# Emit snippet only the first time through for the current name.
> +#
> +def first_time(snippet):
> + r = "[+ IF (if (not (assoc-ref seen-target (get \".name\"))) \"seen\") +]"
> + r += snippet
> + r += "[+ ENDIF +]"
> + return r
> +
> def module(platform):
> r = set_canonical_name_suffix(".module")
>
> @@ -341,18 +359,25 @@ fi
>
> def library(platform):
> r = set_canonical_name_suffix("")
> - r += gvar_add("noinst_LIBRARIES", "[+ name +]")
> - r += var_set(cname() + "_SOURCES", platform_sources(platform))
> - r += var_set("nodist_" + cname() + "_SOURCES", platform_nodist_sources(platform))
> - r += var_set(cname() + "_CFLAGS", "$(AM_CFLAGS) $(CFLAGS_LIBRARY) " + platform_cflags(platform))
> - r += var_set(cname() + "_CPPFLAGS", "$(AM_CPPFLAGS) $(CPPFLAGS_LIBRARY) " + platform_cppflags(platform))
> - r += var_set(cname() + "_CCASFLAGS", "$(AM_CCASFLAGS) $(CCASFLAGS_LIBRARY) " + platform_ccasflags(platform))
> - # r += var_set(cname() + "_DEPENDENCIES", platform_dependencies(platform) + " " + platform_ldadd(platform))
>
> - r += gvar_add("EXTRA_DIST", extra_dist())
> - r += gvar_add("BUILT_SOURCES", "$(nodist_" + cname() + "_SOURCES)")
> - r += gvar_add("CLEANFILES", "$(nodist_" + cname() + "_SOURCES)")
> + r += vars_init(cname() + "_SOURCES",
> + "nodist_" + cname() + "_SOURCES",
> + cname() + "_CFLAGS",
> + cname() + "_CPPFLAGS",
> + cname() + "_CCASFLAGS")
> + # cname() + "_DEPENDENCIES")
>
> + r += first_time(gvar_add("noinst_LIBRARIES", "[+ name +]"))
> + r += var_add(cname() + "_SOURCES", platform_sources(platform))
> + r += var_add("nodist_" + cname() + "_SOURCES", platform_nodist_sources(platform))
> + r += var_add(cname() + "_CFLAGS", first_time("$(AM_CFLAGS) $(CFLAGS_LIBRARY) ") + platform_cflags(platform))
> + r += var_add(cname() + "_CPPFLAGS", first_time("$(AM_CPPFLAGS) $(CPPFLAGS_LIBRARY) ") + platform_cppflags(platform))
> + r += var_add(cname() + "_CCASFLAGS", first_time("$(AM_CCASFLAGS) $(CCASFLAGS_LIBRARY) ") + platform_ccasflags(platform))
> + # r += var_add(cname() + "_DEPENDENCIES", platform_dependencies(platform) + " " + platform_ldadd(platform))
> +
> + r += gvar_add("EXTRA_DIST", extra_dist())
> + r += first_time(gvar_add("BUILT_SOURCES", "$(nodist_" + cname() + "_SOURCES)"))
> + r += first_time(gvar_add("CLEANFILES", "$(nodist_" + cname() + "_SOURCES)"))
> return r
>
> def installdir(default="bin"):
> @@ -376,7 +401,7 @@ def program(platform, test=False):
> r += gvar_add("check_PROGRAMS", "[+ name +]")
> r += gvar_add("TESTS", "[+ name +]")
> r += "[+ ELSE +]"
> - r += gvar_add(installdir() + "_PROGRAMS", "[+ name +]")
> + r += var_add(installdir() + "_PROGRAMS", "[+ name +]")
> r += "[+ IF mansection +]" + manpage() + "[+ ENDIF +]"
> r += "[+ ENDIF +]"
>
> @@ -397,7 +422,7 @@ def program(platform, test=False):
> def data(platform):
> r = gvar_add("EXTRA_DIST", platform_sources(platform))
> r += gvar_add("EXTRA_DIST", extra_dist())
> - r += gvar_add(installdir() + "_DATA", platform_sources(platform))
> + r += var_add(installdir() + "_DATA", platform_sources(platform))
> return r
>
> def script(platform):
> @@ -405,7 +430,7 @@ def script(platform):
> r += gvar_add("check_SCRIPTS", "[+ name +]")
> r += gvar_add ("TESTS", "[+ name +]")
> r += "[+ ELSE +]"
> - r += gvar_add(installdir() + "_SCRIPTS", "[+ name +]")
> + r += var_add(installdir() + "_SCRIPTS", "[+ name +]")
> r += "[+ IF mansection +]" + manpage() + "[+ ENDIF +]"
> r += "[+ ENDIF +]"
>
> @@ -418,33 +443,43 @@ chmod a+x [+ name +]
> r += gvar_add("dist_noinst_DATA", platform_sources(platform))
> return r
>
> +def rules(target, closure):
> + # Create association lists for the benefit of first_time and vars_init.
> + r = "[+ (define seen-target '()) +]"
> + r += "[+ (define seen-vars '()) +]"
> + # Most output goes to a diversion. This allows us to emit variable
> + # initializations before everything else.
> + r += "[+ (out-push-new) +]"
> +
> + r += "[+ FOR " + target + " +]"
> + r += foreach_enabled_platform(
> + lambda p: under_platform_specific_conditionals(p, closure(p)))
> + # Remember that we've seen this target.
> + r += "[+ (set! seen-target (assoc-set! seen-target (get \".name\") 0)) +]"
> + r += "[+ ENDFOR +]"
> + r += "[+ (out-pop #t) +]"
> + return r
> +
> def module_rules():
> - return "[+ FOR module +]" + foreach_enabled_platform(
> - lambda p: under_platform_specific_conditionals(p, module(p))) + "[+ ENDFOR +]"
> + return rules("module", module)
>
> def kernel_rules():
> - return "[+ FOR kernel +]" + foreach_enabled_platform(
> - lambda p: under_platform_specific_conditionals(p, kernel(p))) + "[+ ENDFOR +]"
> + return rules("kernel", kernel)
>
> def image_rules():
> - return "[+ FOR image +]" + foreach_enabled_platform(
> - lambda p: under_platform_specific_conditionals(p, image(p))) + "[+ ENDFOR +]"
> + return rules("image", image)
>
> def library_rules():
> - return "[+ FOR library +]" + foreach_enabled_platform(
> - lambda p: under_platform_specific_conditionals(p, library(p))) + "[+ ENDFOR +]"
> + return rules("library", library)
>
> def program_rules():
> - return "[+ FOR program +]" + foreach_enabled_platform(
> - lambda p: under_platform_specific_conditionals(p, program(p))) + "[+ ENDFOR +]"
> + return rules("program", program)
>
> def script_rules():
> - return "[+ FOR script +]" + foreach_enabled_platform(
> - lambda p: under_platform_specific_conditionals(p, script(p))) + "[+ ENDFOR +]"
> + return rules("script", script)
>
> def data_rules():
> - return "[+ FOR data +]" + foreach_enabled_platform(
> - lambda p: under_platform_specific_conditionals(p, data(p))) + "[+ ENDFOR +]"
> + return rules("data", data)
>
> print "[+ AutoGen5 template +]\n"
> a = module_rules()
>
> === modified file 'grub-core/Makefile.am'
> --- grub-core/Makefile.am 2010-09-19 20:22:43 +0000
> +++ grub-core/Makefile.am 2010-09-22 13:11:11 +0000
> @@ -51,7 +51,6 @@ grub_script.yy.c: grub_script.yy.h
> CLEANFILES += grub_script.yy.c grub_script.yy.h
>
> include $(srcdir)/Makefile.core.am
> -include $(srcdir)/Makefile.gcry.am
>
> KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/cache.h
> KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/command.h
>
>
--
Regards
Vladimir 'φ-coder/phcoder' Serbinenko
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 294 bytes --]
next prev parent reply other threads:[~2010-09-23 16:06 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-09-21 18:35 [PATCH] Re-enable grub-extras Colin Watson
2010-09-23 13:08 ` Colin Watson
2010-09-23 13:12 ` Colin Watson
2010-09-23 14:23 ` Colin Watson
2010-09-23 14:36 ` Vladimir 'φ-coder/phcoder' Serbinenko [this message]
2010-09-24 9:09 ` Colin Watson
2010-09-23 20:27 ` [PATCH] Trunk: usbtrans.c - wrong max packet size for bulk transfer Aleš Nesrsta
2010-10-01 7:35 ` Vladimir 'φ-coder/phcoder' Serbinenko
2010-10-01 15:07 ` Aleš Nesrsta
2010-10-01 18:33 ` Vladimir 'φ-coder/phcoder' Serbinenko
2010-10-02 18:58 ` Aleš Nesrsta
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4C9B65F1.10909@gmail.com \
--to=phcoder@gmail.com \
--cc=grub-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.