help-make
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: RFC: .ALIAS builtin pseudotarget


From: Fabio Alemagna
Subject: Re: RFC: .ALIAS builtin pseudotarget
Date: Thu, 23 Sep 2004 15:21:39 +0200

On Wed, 22 Sep 2004 11:34:13 -0500, Boris Kolpackov <address@hidden> wrote:
> Please CC address@hidden if you want to discuss stuff like this.

Sorry, I thought I had done that.
 
> Fabio Alemagna <address@hidden> writes (full quote):
> 
> > > Now to your proposal: what you are suggesting essentially is
> > > a timestamp but the prerequisite is hidden, there is no way you can
> > > access it. Here is an example:
> > >
> > > .ALIAS: alias
> > >
> > > alias: foo.c
> > >
> > > foo.o: alias
> > >         $(CC) -o $@ -c ???
> >
> > I get what you mean, so the limited use of this special target perhaps
> > doesn't warrant it the right to be added to Make.

On a second thought, though, I'm not sure it's usage is really
limited. In the above example, you're obviously using the wrong
approach. .ALIAS is not meant to be used as a variable, .ALIAS is
meant to be used as a .PHONY target which however can be used as
prerequisite of another target.

As said, I found the need for this in my build system.

In my build system you have modules, modules are of certain types
(executable, library, and so on), and each module type induces certain
properties on the module itself, properties which can be set and
gotten by using a well defined naming convention for variables.

Modules can depend on other modules, meaning that before one module is
built, another must be built.

A module's name is defined as the pathname of the file the module is
going to build, relative to the distribution directory.

The distribution directory is the directory where all modules are
going to be placed.

Modules can be built in 3 ways:

1) typing "make" in the toplevel source directory (this is going to
change, allowing one to run make from any directory in the tree),
which makes all modules in the source tree.

2) typing "make full_module_name", where full_module_name can be
something like path/to/module

3) typing "make short_module_name", where short_module_name is a
shorthand for the module name. There are 2 kind of  shorthands:

    3.1) $(dir full_module_name), which builds all modules that are
going to be put in the
           same directory

    3.2) $(notdir full_module_name), which builds all modules with the
same filename, even
           if they're going to be built in different directories.

Defining dependencies for a module is done this way:

    full_module_name/DEPS := module_name1 ... module_nameN

where module_nameX can be either a full_module_name or a short_module_name

The build system handles this by simply defining full_module_name and
both variants of short_module_name as .ALIAS'es to
$(distdir)/full_module_name, and then simply adds a rule like this:

    $(distdir)/full_module_name : $(full_module_name/DEPS)

It's fast, clean, and works just well.

Perhaps it won't be the most widely used .SPECIALTARGET, but it has its uses.

It's somewhat possible to emulate its functionality by using
variables, in which case the above rule would look somewhat like this:

    $(distdir)/full_module_name : $(foreach d,
$(full_module_name/DEPS), $($(d)))

provided that somewhere in the makefile $(d) has been assigned the
right value. However, this forces the definition of the above rule to
come after all definitions of all variables involved, which is quite a
strict requirement. Moveover, to emulate the functionality of .ALIAS
targets being real targets, one needs to use .PHONY targets with the
names of the variables involved, and make them depend on the values of
those variables.

It can certainly be done, but adds complexity and slows the makefile
processing down, for all those variables expansions which could be
avoided. I'm not sure how much slower it would be, though.

> > This might not sound very useful at a glance, but it would be really
> > useful if .VIRTUAL's prerequisites could use stems.
> >
> > Consider this case:
> >
> > .VIRTUAL : MD5(%) CHECK_MD5(%)
> >
> > CHECK_MD5(%) :
> >         md5sum --check $*.md5 >/dev/null 2>&1
> >
> > MD5(%) : CHECK_MD5(%)
> >         md5sum -b $* > $*.md5
> >         exit 1
> >
> > file.c : MD5(header1.h) MD5(header2.h) MD5(header3.h)
> >
> > (You don't really need CHECK_MD5(%), an if statement could be used
> > instead, but it's there to illustrate the functionality).
> 
> Exactly! You can already do this in a much more straightforward way.

I actually hadn't thought of sentinel files, which I must admit here
suit the job well, I was thinking specifically of CHECK_MD5, which
wouldn't be needed, but MD5 still would (without considering sentinel
files).

> Also see
> 
> http://kolpackov.net/pipermail/notes/2004-September/000011.html
> 
> >
> > What it does, is making file.c depend on header1.h, header2.h and
> > header3.h, but rather than using their timestamps to check whether
> > they've changed, it uses their md5 hash values. A feature, I hear,
> > which is much requested.
> >
> > Of course the idea is applicable to an infinite amount of other
> > situations. Dunno how much feasible it would be, though.
> 
> I can't think of even one ;-). The example you presented above does
> not count since you can already do this (also your approach has
> scalability problems - see link above).

I'm not sure which scalability problems you're thinking about. 

> Can you provide a non-academic example of where your logic is useful
> which can't be done with current make functionality?

Ok, after some thought on this I relized that you could always use a
sentinel file to provide the functionality of .VIRTUAL targets. This
way:

file : sentinel
        build file

sentinel : file2
        if condition; then build sentinel; fi

Where file2 could be a phony target, in cases where the action being
performed doesn't really depend on any real file.

However, this solution as one problem: what if we don't want sentinel
files? What if we simply want a sort of functional way to determine
whether a target needs to be rebuilt or not, without keeping any -
fake or not - state? Using the .VIRTUAL approach solves this problem,
as no real file is needed, thus speeding up make execution and avoid
cluttering the filesystem with bogus files with strange names.

In other words, if you want the features of a sentinel file, but you
don't really need a sentinel file, then .VIRTUAL is for you. This
doesn't apply to the MD5 approach, I must admit, because there the
.md5 file IS the sentinel file, but take for instance my .ALIAS
target: it could be thought as a special case of .VIRTUAL, if you did
something like this:

    .VIRTUAL : alias

    alias : foo bar baz
            $(if $?,exit 1,exit 0)

That is, pretend alias has been brought up to date if any of its
prerequisites have been brought up to date, otherwise do nothing.

Now, had I to use a sentinel file for this, I would need to really
have an "alias" file somewhere, and the first question is: where?
Moreover, "alias" could contain slashes, as in my build system case,
hence I would also need to make directories. I hope you see that
that's really not a clever solution.

Fabio Alemagna


On Wed, 22 Sep 2004 11:34:13 -0500, Boris Kolpackov <address@hidden> wrote:
> Please CC address@hidden if you want to discuss stuff like this.
> 
> Fabio Alemagna <address@hidden> writes (full quote):
> 
> > > Now to your proposal: what you are suggesting essentially is
> > > a timestamp but the prerequisite is hidden, there is no way you can
> > > access it. Here is an example:
> > >
> > > .ALIAS: alias
> > >
> > > alias: foo.c
> > >
> > > foo.o: alias
> > >         $(CC) -o $@ -c ???
> >
> > I get what you mean, so the limited use of this special target perhaps
> > doesn't warrant it the right to be added to Make.
> >
> > For sake of completeness, though, I must say that I have come up with
> > this approach only as a mid-term solution for something more general
> > purpose I had thought I would implement. This .ALIAS target served my
> > purposes, so I implemented it to see whether I could hack Make's
> > sources.. however, the more general idea I had was to have a .VIRTUAL
> > special target whose prerequisites would be targets whose timestamp
> > would result newer than the parent's timestamp, if their action
> > returned an exit value != 0, otherwise they would result older.
> >
> > This might not sound very useful at a glance, but it would be really
> > useful if .VIRTUAL's prerequisites could use stems.
> >
> > Consider this case:
> >
> > .VIRTUAL : MD5(%) CHECK_MD5(%)
> >
> > CHECK_MD5(%) :
> >         md5sum --check $*.md5 >/dev/null 2>&1
> >
> > MD5(%) : CHECK_MD5(%)
> >         md5sum -b $* > $*.md5
> >         exit 1
> >
> > file.c : MD5(header1.h) MD5(header2.h) MD5(header3.h)
> >
> > (You don't really need CHECK_MD5(%), an if statement could be used
> > instead, but it's there to illustrate the functionality).
> 
> Exactly! You can already do this in a much more straightforward way.
> 
> Also see
> 
> http://kolpackov.net/pipermail/notes/2004-September/000011.html
> 
> >
> > What it does, is making file.c depend on header1.h, header2.h and
> > header3.h, but rather than using their timestamps to check whether
> > they've changed, it uses their md5 hash values. A feature, I hear,
> > which is much requested.
> >
> > Of course the idea is applicable to an infinite amount of other
> > situations. Dunno how much feasible it would be, though.
> 
> I can't think of even one ;-). The example you presented above does
> not count since you can already do this (also your approach has
> scalability problems - see link above).
> 
> Can you provide a non-academic example of where your logic is useful
> which can't be done with current make functionality?
> 
> -boris
> 
> 
> 
>




reply via email to

[Prev in Thread] Current Thread [Next in Thread]