View Issue Details

IDProjectCategoryView StatusLast Update
00005141003.1(2008)/Issue 7Shell and Utilitiespublic2024-06-11 08:53
Reporterdwheeler Assigned Toajosey  
PrioritynormalSeverityObjectionTypeEnhancement Request
Status ClosedResolutionAccepted As Marked 
NameDavid A. Wheeler
Organization
User Reference
Sectionmake
Page Number2918
Line Number95928-95954
Interp Status---
Final Accepted Text0000514:0005962
Summary0000514: Enhance internal macros in make
DescriptionThe 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 ActionChange 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.

Tagsissue8

Relationships

related to 0001520 Closed Issue 8 drafts make should support the $^ internal macro 

Activities

joerg

2011-11-17 11:08

reporter   bugnote:0001026

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.

Konrad_Schwarz

2011-11-17 16:30

reporter   bugnote:0001030

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.

psmith

2012-01-07 00:06

developer   bugnote:0001088

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.

joerg

2012-04-10 16:38

reporter   bugnote:0001193

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.

Love4Boobies

2019-12-25 10:20

reporter   bugnote:0004703

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.

Konrad_Schwarz

2020-01-07 09:14

reporter   bugnote:0004709

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

To expand on 0000514: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.

psmith

2020-01-07 14:41

developer   bugnote:0004711

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.

Love4Boobies

2020-01-13 04:53

reporter   bugnote:0004723

Last edited: 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.

Konrad_Schwarz

2020-01-13 09:19

reporter   bugnote:0004726

Re: 0000514: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)

Love4Boobies

2020-01-13 09:29

reporter   bugnote:0004727

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.

geoffclare

2022-09-08 15:53

manager   bugnote:0005962

Last edited: 2022-09-08 15:54

On D2.1 page 2947 line 98895, after applying bug 1520, change:
The $^ macro shall evaluate to the list of prerequisites for the current target.
to:
The $^ macro shall evaluate to the list of prerequisites for the current target, with any duplicates (except the first) removed.

On D2.1 page 2947 after line 98895 add:
$+
The $+ macro shall be equivalent to $^, except that duplicates shall not be removed; all prerequisites shall appear in the order they were listed in the makefile.


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 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 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
2022-09-08 15:20 geoffclare Relationship added related to 0001520
2022-09-08 15:53 geoffclare Note Added: 0005962
2022-09-08 15:54 geoffclare Note Edited: 0005962
2022-09-08 15:55 geoffclare Interp Status => ---
2022-09-08 15:55 geoffclare Final Accepted Text => 0000514:0005962
2022-09-08 15:55 geoffclare Status Under Review => Resolved
2022-09-08 15:55 geoffclare Resolution Open => Accepted As Marked
2022-09-08 15:55 geoffclare Tag Attached: issue8
2022-10-21 09:12 geoffclare Status Resolved => Applied
2024-06-11 08:53 agadmin Status Applied => Closed