Austin Group Defect Tracker

Aardvark Mark IV


Viewing Issue Simple Details Jump to Notes ] Issue History ] Print ]
ID Category Severity Type Date Submitted Last Update
0000514 [1003.1(2008)/Issue 7] Shell and Utilities Objection Enhancement Request 2011-11-17 00:21 2020-01-13 09:29
Reporter dwheeler View Status public  
Assigned To ajosey
Priority normal Resolution Open  
Status Under Review  
Name David A. Wheeler
Organization
User Reference
Section make
Page Number 2918
Line Number 95928-95954
Interp Status ---
Final Accepted Text
Summary 0000514: Enhance internal macros in make
Description The set of make's internal macros is expanded in some make implementations, or have various restrictions removed.

The "$<" value has special-case restrictions; remove them. Also, add $^ (list all prerequisites without dups) and $+ (list all prerequisites with dups - e.g., for linking).

Desired Action Change the definition of "$<" to:
     The name of the first prerequisite.
(Note that this generalizes $<, eliminating special-case restrictions.)

Add:
$^ A list of all the prerequisites, with a space or tab between each. Duplicates are removed. If a prerequisite is an archive member, only the named member is used.

$+ A list of all prerequisites, with a space or tab between each. Duplicates are not removed, and must be duplicated in the order they were listed in the makefile.


{ This is like `$^', but prerequisites listed more than once are
     duplicated in the order they were listed in the makefile. This is
     primarily useful for use in linking commands where it is
     meaningful to repeat library file names in a particular order.

Tags No tags attached.
Attached Files

- Relationships

-  Notes
(0001026)
joerg (reporter)
2011-11-17 11:08

If $< is discussed, then $* needs to be discussed at the same time.

I strongly object to remove the restrictions from $< and $* as the fact that some implementations (e.g. SunPro make and gmake) return a non-blank value for $< and $* for non-inference rules is a non-portable side-effect of the respective implementation.

smake's implementation does not have this side effect and smake for this reason explicitely warns that a non-portable makefile was encountered.

Also note that SunPro make and gmake return different results for $< and $* as the expansion for these variables depends on different side effects.

For a non-inference rule, it is (in gneneral) not possible to define an "implicit source" ($<).

For s non-inference rule, it is typically impossible to define a "file name base" without "suffix" as only a matching suffix rule is able to define the suffix to strip.

Note that a sketchy test for the behavior of $< with SunPro make and gmake may return the same results, the behavior differs general.
(0001030)
Konrad_Schwarz (reporter)
2011-11-17 16:30

Using $^ or $+ to specify the prerequistes of a link command together
with automatic make dependency creation is asking for trouble.

If a makefile contains a dependency of the form

a.out: timestamp.c

and the compiler is invoked such as to create dependency files,
any file header.h included by timestamp.c will be turned into a dependency
of a.out, causing the next build to invoke

        $(CC) $(CFLAGS) timestamp.c header.h -o a.out

On the other hand, if you have, say, a dependency upon a
linker script file which must be adjacent to some flag -T,
the $^ mechanism is again insufficient.

So the utility of $^ and $+ is limited.
(0001088)
psmith (reporter)
2012-01-07 00:06

Regarding comment #1026:

This bug doesn't discuss $* and I don't agree with the statement "$* needs to be discussed at the same time"... why is that a requirement? $* is a difficult question for non-inference rules, I agree, and it should be handled under a different bug, if at all.

As for $<, I don't agree with the statement "for a non-inference rule, it is ... not possible to define ... $<". There is a simple algorithm for determining $< for any rule, inference or non-inference, which yields a deterministic, useful result.

Regarding comment #1030:

It may be true that $^ and $+ are not useful in the specific situation you describe, but it's easy to come up with many other situations where they are useful. Jumping from "they won't help in the case XYZ" to "[their] utility is limited" is not warranted. Where they don't work, there's no need to use them. Make is used for a LOT of other purposes than linking of C-like code.
(0001193)
joerg (reporter)
2012-04-10 16:38

Expanding $< for explicit rules seems to be a GNUism and is not implemented in important other make programs see:

echo > a
echo > b
cat Makefile
all: a b
      echo "'"$<"'"

gmake
echo "'"a"'"
'a'

make # this is the Solaris make program
echo "'""'"
''

smake # This is the Schily smake program
smake: WARNING: requesting implicit dynmac '$<' for explicit target 'all'
smake: WARNING: expanding implicit dynmac '$<' to ''
smake: WARNING: Current working directory: '/tmp', Makefile 'Makefile'
    echo "'""'"
''

As an important note: the internal data structures, used by various make programs are expected to differ from those used in gmake. Something that works in gmake may not be easy to implement in other make versions.

I believe that the original reporter should verify that his expected new behavior may be implemented with the important make implementations without causing problems.

Given the differences while discussing $^ and $+, it may be a good idea to
delay the discussion for these macros. A discussion of $^ and $+ could be
started after an agreement on $< could be found.
(0004703)
Love4Boobies (reporter)
2019-12-25 10:20

Regarding comment #0001030:

That is not at all how $^ is supposed to be used. It's supposed to be used to generate library or executable files from object files. It seems very important to add this to make for the following reason:

executable: obj1 obj2
    $(CC) $(LDFLAGS) -o $@ $?

If we touch obj1 or obj2 but not the other one, then our rule will not work properly. However, if $^ is used instead, then both obj1 and obj2 would be linked.

This is really a must-have.
(0004709)
Konrad_Schwarz (reporter)
2020-01-07 09:14

Re Note: 0004703: I stand by my assertion, you have misunderstood the note.

To expand on Note: 0001030 :
Non-trivial applications will tend to have executable files depend not only on object files, but also on (say) C files. A typical example is a C file containing the timestamp of the link, this could be coded as file "timestamp.c"

char const my_executables_link_time [] = __DATE__ " " __TIME__;

This file should include a header file declaring the global variable my_executable_link_time, say "header.h", so it starts off with

# include "header.h"

By far the best way to handle header file dependency lists is for the compiler to generate them automatically, ideally as a by-product of the previous compilation, e.g. using GCC's -MD flag (the dependency files can be included using
-include *.d
in the Makefile, thus causing no error during the first compilation).

The rule of the form

a.out: timestamp.c

causes an additional dependency of the form

a.out: header.h

to be generated. This is entirely correct, since a change to header.h should cause a.out to be recompiled.

However, if your link rule uses $^ instead of explicitly listing the object files (possibly via a macro such as $(OBJS), the linker receives the "header.h" as a file to be linked (or possibly compiled), which is wrong.

Hence my assertion that use of $^ is asking for trouble. I invariably end up listing the object files explicitly in an OBJS macro.

I don't think standardizing $^ or $+ is worth the trouble.
(0004711)
psmith (reporter)
2020-01-07 14:41

Regarding the comments in http://austingroupbugs.net/view.php?id=514#c4709: [^]

I don't think anyone is arguing that $^ is useful in the environment you describe. But as I noted above, suggesting that anything that is not useful when using make to compile C (and C-like) binaries is too limited. Make is used for many, many purposes beyond that and lots of them do not have the issues you raise.

Further, many makefiles don't have easy access to all the dependency files in a single variable: they may use multiple target/dependency statements possibly scattered all over the place, possibly even across included makefiles:

    all: ; @echo "built targets $+ out of $^"
    all: foo
     ...
    all: bar
     ...
    all: baz

Finally, even in C/C-like languages your use-case is actually pretty rare. It's almost never the case that people list header files as prerequisites of _programs_: header files are prerequisites of _object files_. Most makefiles separate compilation and linkage into two different rules, otherwise changes to any header or source file requires the entire program to be recompiled.

This means that linking rules list only object files as prerequisites, not header files, and $^ is perfect for this.
(0004723)
Love4Boobies (reporter)
2020-01-13 04:53
edited on: 2020-01-13 05:19

I don't think I've misunderstood the note, it's just that you want to use $^ as a replacement for something that it's not supposed to replace. Its use lies elsewhere, where there is nothing in the standard that offers a replacement. Another example would be pattern rules. You cannot use a variable like that in a pattern rule because each target has its own set of prerequisites. Consider the following:

foo.a: foo.c

%.a: %.b
    echo $^

This would echo "foo.b foo.c" for target "foo.a" and only "bar.b" for target "bar.a". It is impossible to do this with user-defined variables, except if you give up pattern rules and define each rule explicitly, as "foo.a" has extra prerequisites to process. The $@ variable would only print "foo.b" since it has nothing to do with the rule being evaluated so we'd miss an important prerequisite.

I don't think that putting an artificial limitation on the standard because we can contrive examples where people might use a feature in an unintended way and get unwanted results is the way to go. The $^ variable is already used in practice and it helps to write more maintainable makefiles.

(0004726)
Konrad_Schwarz (reporter)
2020-01-13 09:19

Re: Note: 0004723

From my point of view, a better way to solve this problem is via recursive macro expansion:

.SUFFIXES: .a .b
.b.a:
        echo $< $(EXTRA_$*)

EXTRA_foo = foo.c
foo.a: $(EXTRA_foo)
(0004727)
Love4Boobies (reporter)
2020-01-13 09:29

I don't see how having to scan the makefiles for variable definitions and trying to figure out what things expand to is simpler than simply using $^, which is clear as day. Not to mention that you can't really do that if EXTRA_foo's contents come from an automatically generated dependency file without going further down the hackery rabbit hole.

Also, computed variables, like $(EXTRA_$*), are not even part of POSIX make.

- Issue History
Date Modified Username Field Change
2011-11-17 00:21 dwheeler New Issue
2011-11-17 00:21 dwheeler Status New => Under Review
2011-11-17 00:21 dwheeler Assigned To => ajosey
2011-11-17 00:21 dwheeler Name => David A. Wheeler
2011-11-17 00:21 dwheeler Section => make
2011-11-17 00:21 dwheeler Page Number => 2918
2011-11-17 00:21 dwheeler Line Number => 95928-95954
2011-11-17 11:08 joerg Note Added: 0001026
2011-11-17 16:30 Konrad_Schwarz Note Added: 0001030
2012-01-07 00:06 psmith Note Added: 0001088
2012-04-10 16:38 joerg Note Added: 0001193
2019-12-25 10:20 Love4Boobies Note Added: 0004703
2020-01-07 04:33 Love4Boobies Issue Monitored: Love4Boobies
2020-01-07 09:14 Konrad_Schwarz Note Added: 0004709
2020-01-07 14:41 psmith Note Added: 0004711
2020-01-13 04:53 Love4Boobies Note Added: 0004723
2020-01-13 04:53 Love4Boobies Note Added: 0004724
2020-01-13 04:54 Love4Boobies Note Deleted: 0004724
2020-01-13 05:04 Love4Boobies Note Edited: 0004723
2020-01-13 05:06 Love4Boobies Note Edited: 0004723
2020-01-13 05:07 Love4Boobies Note Edited: 0004723
2020-01-13 05:08 Love4Boobies Note Edited: 0004723
2020-01-13 05:10 Love4Boobies Note Edited: 0004723
2020-01-13 05:19 Love4Boobies Note Edited: 0004723
2020-01-13 09:19 Konrad_Schwarz Note Added: 0004726
2020-01-13 09:29 Love4Boobies Note Added: 0004727


Mantis 1.1.6[^]
Copyright © 2000 - 2008 Mantis Group
Powered by Mantis Bugtracker