Re: Implicit rule for linking multiple object files

2022-08-11 Thread Philip Guenther
The first place to consult in understanding how to build your code is the
documentation of your compiler.  C++20 *module* support is very new in at
least gcc and they have not provided direct guidance on how to use modules
with 'make', at least I don't see any such guidance here:

https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gcc/C_002b_002b-Modules.html#C_002b_002b-Modules

Instead they have a link to an outside whitepaper.  Ideally, the gcc
developers would work with the GNU make developers to provide rules and
documentation that would solve your problems.  They have not yet done so.
Your choices are:
 * to work it out
 * to wait until they provide that guidance
 * to find another compiler and/or build system

To be blunt, the questions you're asking about make behavior indicate that
it will require a dedicated effort for you to develop the correct rules
yourself.  While at least one workaround has already been proposed (declare
a.o, b.o, c.o, and d.o. as prerequisites of main.o) that is almost
certainly specific to the modules and classes involved here and if this
project grows a more complex module/class layout additional, possibly
conflicting rules will be required.  A solution which is robust to future
code/design changes really requires a broad view of the dependency
structure of the C++ module implementation...which is where guidance from
the C++ compiler developers would *really* be useful.

Good luck.

Philip Guenther


On Wed, Aug 10, 2022 at 9:19 PM ljh  wrote:

> Hi Paul,
>
> I don't know if this is related to gcc support of c++20.
> But mentioning target.o ("x.o") and recipe or not in my Makefile, does
> have different result. My test follows.
>
> Thanks
>
>
> ---
>
> 1. error: with target.o ("x.o"), without recipe
>
>
> $ ls
>  a.cpp   b.cpp   c.cpp   d.cpp   main.cpp   Makefile
> $
> $ cat Makefile
> CXXFLAGS = -Wall -Wextra -std=c++2a -fmodules-ts -g # -O3 -fPIC
> main : c.o b.o a.o d.o main.o
> #   $(CXX) $^ -o $@
> $ make
> g++ -Wall -Wextra -std=c++2a -fmodules-ts -g-c -o main.o main.cpp
> In module imported at main.cpp:1:1:
> A: error: failed to read compiled module: No such file or directory
> A: note: compiled module file is ‘gcm.cache/A.gcm’
> A: note: imports must be built before being imported
> A: fatal error: returning to the gate for a mechanical issue
> compilation terminated.
> make: *** [: main.o] Error 1
> $
>
>
> 2. ok: without target.o and recipe
>
>
> $ rm -fr *.o gcm.cache main
> $ cat Makefile
> CXXFLAGS = -Wall -Wextra -std=c++2a -fmodules-ts -g # -O3 -fPIC
> main : c.o b.o a.o d.o # main.o
> #   $(CXX) $^ -o $@
> $ make
> g++ -Wall -Wextra -std=c++2a -fmodules-ts -g-c -o c.o c.cpp
> g++ -Wall -Wextra -std=c++2a -fmodules-ts -g-c -o b.o b.cpp
> g++ -Wall -Wextra -std=c++2a -fmodules-ts -g-c -o a.o a.cpp
> g++ -Wall -Wextra -std=c++2a -fmodules-ts -g-c -o d.o d.cpp
> g++ -Wall -Wextra -std=c++2a -fmodules-ts -g main.cpp c.o b.o a.o d.o
>   -o main
> $
>
>
> 3. ok: with target.o and recipe
>
>
> $ rm -fr *.o gcm.cache main
> $ cat Makefile
> CXXFLAGS = -Wall -Wextra -std=c++2a -fmodules-ts -g # -O3 -fPIC
> main : c.o b.o a.o d.o main.o
> $(CXX) $^ -o $@
> $ make
> g++ -Wall -Wextra -std=c++2a -fmodules-ts -g-c -o c.o c.cpp
> g++ -Wall -Wextra -std=c++2a -fmodules-ts -g-c -o b.o b.cpp
> g++ -Wall -Wextra -std=c++2a -fmodules-ts -g-c -o a.o a.cpp
> g++ -Wall -Wextra -std=c++2a -fmodules-ts -g-c -o d.o d.cpp
> g++ -Wall -Wextra -std=c++2a -fmodules-ts -g-c -o main.o main.cpp
> g++ c.o b.o a.o d.o main.o -o main
> $
>
> $ make --version
> GNU Make 4.3
> Built for x86_64-pc-linux-gnu
> Copyright (C) 1988-2020 Free Software Foundation, Inc.
> License GPLv3+: GNU GPL version 3 or later <
> http://gnu.org/licenses/gpl.html>
> This is free software: you are free to change and redistribute it.
> There is NO WARRANTY, to the extent permitted by law.
> $
>
>
> -- 原始邮件 --
> *发件人:* "psmith";
> *发送时间:* 2022年8月11日(星期四) 凌晨2:31
> *收件人:* "ljh"; "bug-make";
> *主题:* Re: Implicit rule for linking multiple object files
>
> On Thu, 2022-08-11 at 01:58 +0800, ljh wrote:
> > I have three c source files: x.c, y.c, z.c and I name x as the target
> > on left. Can I put x.o in the prerequisites on the right too? Are
> > they the same, with or without x.o in the prerequisites on the right?
> >
> > x: y.o z.o x.o  # with x.o
>
> It is correct to do this.
>
> These two rules do not behave exactly the same:
>
>   x: y.o z.o
>
> versus
>
>   x: y.o z.o x.o
>
> (you can see the difference for yourself by running "make" both ways)
> but the result of both of these will give you the same working program.
>
> > Is it correct for me to use patsubst function to include all object
> > files?
> > x: $(patsubst %.c,%.o,$(wildcard *.c))
>
> This is fine too.
>
> > In my test the rule with patsubst works on most cases. But if my code
> > uses C++20 modules, I need to omit x.o if I want to omit the recipe:
> > x: y.o 

Re: Making makefiles with primarily phony targets more friendly

2022-08-11 Thread Edward Welbourne
Jean-Baptiste Poittevin (10 August 2022 22:19) wrote:
> By using a lot of PHONY targets, I think you're closing a door to one
> make greatest feature : not redoing those things that are already up
> to date.

While that's entirely true of make's "design-basis" use-case, I am
familiar with the mostly-phony style of make-file; it serves, in effect,
as a way of defining a directory-specific set of command aliases, that
need not have anything to do with generating new (local) files.

That may include generating one of a family of reports to stdout, that
gets piped into a mail program to be sent out, without changing anything
on disk; or it may integrate some more traditional use of make, such as
doing a build, with uploading the result to where a client can access
it, sending the client an e-mail about that and logging that this has
happened in a support database via REST calls.  Or it could be used to
initiate back-ups of parts of a system to a tape device (after taking
care to insert a suitably labelled tape in its drive).  Even though
these are, in some sense, creating files from inputs, the generated "file"
(in someone's in-box, in the support database, on the tape) is external
to the system on which make can query time-stamps.

This enables a work-flow where, to perform a set of routine tasks, I
just cd to a directory set up to facilitate those tasks (it likely has
symlinks to assorted resources to be consulted as part of them) and make
a target to initiate some complex command or sequence of commands.
Having several targets in the make-file can make this map several
related tasks to handy mnemonic names, saving the need to remember,
reinvent or look up potentially long and complex command-lines.

For example: I could have one such directory for each of several
clients; each Makefile sets some client-specific parameters and imports
suitable make-files from a common store, while its directory contains
symlinks to the resources needed for tasks related to those clients.
This can then make various processes involving interaction with clients
(and suitable logging to accounting, support and other databases on
other hosts) uniform (thereby greatly reducing the scope for mistakes).

This might more traditionally be done by writing a script, with various
options to select between the related tasks my directory exists to
support doing, but make is actually a very good way to structure some
such scripts, particularly when some of the tasks need others to be
performed first.  Naturally, if some of the tasks need certain files to
also be up to date before they are run, this also integrates nicely with
make's design-basis use-case.

It is some decades since I've had tasks for which I used this approach,
so I forget the particular use-cases to which I applied it, and it
sounds like Katherine has a more involved example of it than I've ever
used it for, but once you let go of the assumption that make is only
used to turn (local) source files into generated (local) files, there
are some interesting ways that make can serve as a very handy scripting
language.  It's just a bit tedious to have to mark a lot of rules as
phony.

Eddy.



?????? Implicit rule for linking multiple object files

2022-08-11 Thread ljh
Thanks Philip,


I want to compile objects in order of the writting: y.o z.o x.o .
The order of compiling x.o are different in below three cases.
I don't understand the difference. 


x : y.o z.o x.o  # compiles x.o last
        $(CC) $^ -o $@  # with recipe


x : y.o z.o      # compiles x.o last


x : y.o z.o x.o  # compiles x.o first


My purpose is to keep my Makefile simple. With the patsubst function in 
Makefile, I just put Makefile with my source files and need to do nothing.
It just compiles. But this is gone if the order of compiling matters.


x : $(patsubst %.c,%.o,$(wildcard *.c))




Thanks


---


# My Minimal Makefile for C, C++
# build shared library with -fPIC, -shared
CFLAGS   = -Wall -Wextra -g # -O3 -fPIC  # CXXFLAGS for .cpp
LDFLAGS  = # -L../hello # -shared
LDLIBS   = # -lhello
CPPFLAGS = -MMD -MP # -I../hello
#CC      = $(CXX)  # link with CXX for .cpp


# target name is basename of one of the source files
main : $(patsubst %.c,%.o,$(wildcard *.c))  # .cpp
-include *.d
clean : ; -rm -fr *.o *.d
.PHONY : clean

Re: 回复: Implicit rule for linking multiple object files

2022-08-11 Thread Martin Dorey

> I want to compile objects in order of the writting

Just because, today, make happens to pick nearly what you want it to do without 
being told about your ordering constraint, doesn't mean that you should rely on 
it continuing to do so.  You should teach make about that order.  You could 
contrive a function to $(eval) your y.o z.o x.o list into a chain of pairwise 
dependencies:

z.o: y.o
x.o: z.o

Like this:

martind@sirius:~/tmp/ljh-2022-08-11$ cat Makefile
objs = y.o z.o x.o
space = $(subst :,,: :)
makeDependency = $(eval $(lastword $(1)): $(firstword $(1)))
$(foreach pair,$(filter-out guard@@% %@@guard,$(join guard $(objs),$(addprefix 
@@,$(objs) guard))),$(call makeDependency,$(subst @@,$(space),$(pair
martind@sirius:~/tmp/ljh-2022-08-11$ make -p | grep '[xyz]\.o: [xyz].o'
make: *** No rule to make target 'y.o', needed by 'z.o'.  Stop.
z.o: y.o
x.o: z.o
martind@sirius:~/tmp/ljh-2022-08-11$


From: Bug-make  on behalf of ljh 

Sent: Thursday, August 11, 2022 01:56
To: Philip Guenther 
Cc: psmith ; bug-make 
Subject: 回复: Implicit rule for linking multiple object files

* EXTERNAL EMAIL *
Thanks Philip,

I want to compile objects in order of the writting: y.o z.o x.o .
The order of compiling x.o are different in below three cases.
I don't understand the difference.

x : y.o z.o x.o  # compiles x.o last
$(CC) $^ -o $@  # with recipe

x : y.o z.o  # compiles x.o last

x : y.o z.o x.o  # compiles x.o first

My purpose is to keep my Makefile simple. With the patsubst function in
Makefile, I just put Makefile with my source files and need to do nothing.
It just compiles. But this is gone if the order of compiling matters.

x : $(patsubst %.c,%.o,$(wildcard *.c))


Thanks

---

# My Minimal Makefile for C, C++
# build shared library with -fPIC, -shared
CFLAGS   = -Wall -Wextra -g # -O3 -fPIC  # CXXFLAGS for .cpp
LDFLAGS  = # -L../hello # -shared
LDLIBS   = # -lhello
CPPFLAGS = -MMD -MP # -I../hello
#CC  = $(CXX)  # link with CXX for .cpp

# target name is basename of one of the source files
main : $(patsubst %.c,%.o,$(wildcard *.c))  # .cpp
-include *.d
clean : ; -rm -fr *.o *.d
.PHONY : clean



?????? ?????? Implicit rule for linking multiple object files

2022-08-11 Thread ljh
Thanks Martin,


Your Makefile is too advanced for me to understand by now.


I tested out the below five rules.
Aren't the order of compiling object files of first two rules certain?
Will GNU Make keep their ordering behavior or are they just some random ordering
caused by some random bugs (sorry, no offensive, I love GNU Make)


# ok: in order of writing, with recipe
x: y.o z.o x.o
    $(CC) $^ -o $@


# ok: compiles x.o last, no mentioning x.o
x: y.o z.o




The rest of the below three rules are not suitable if compiling order matters.


# compiles x.o first, mentioning x.o
x: y.o z.o x.o


# compiles x.o first
x: $(patsubst %.y,%.o,$(wildcard *.y))


# in order of file names, with recipe
x: $(patsubst %.y,%.o,$(wildcard *.y))
    $(CC) $^ -o $@ 
    

Re: 回复: 回复: Implicit rule for linking multiple object files

2022-08-11 Thread Martin Dorey
> Aren't the order of compiling object files of first two rules certain?

No, it's unspecified.  Earlier in this thread, you wrote:

>> The manual states that the x.c compiles first.

The example you're looking at just teaches that compiling x.c first is allowed. 
 It doesn't teach that x.c will always be compiled first.

> Will GNU Make keep their ordering behavior or are they just some random 
> ordering caused by some random bugs

You care about the order but haven't told make that, so the bug is in your 
makefile, not GNU Make.


From: ljh 
Sent: Thursday, August 11, 2022 11:37
To: Martin Dorey ; Philip Guenther 

Cc: psmith ; bug-make 
Subject: 回复: 回复: Implicit rule for linking multiple object files

* EXTERNAL EMAIL *
Thanks Martin,

Your Makefile is too advanced for me to understand by now.

I tested out the below five rules.
Aren't the order of compiling object files of first two rules certain?
Will GNU Make keep their ordering behavior or are they just some random ordering
caused by some random bugs (sorry, no offensive, I love GNU Make)

# ok: in order of writing, with recipe
x: y.o z.o x.o
$(CC) $^ -o $@

# ok: compiles x.o last, no mentioning x.o
x: y.o z.o


The rest of the below three rules are not suitable if compiling order matters.

# compiles x.o first, mentioning x.o
x: y.o z.o x.o

# compiles x.o first
x: $(patsubst %.y,%.o,$(wildcard *.y))

# in order of file names, with recipe
x: $(patsubst %.y,%.o,$(wildcard *.y))
$(CC) $^ -o $@



Re: 回复: 回复: Implicit rule for linking multiple object files

2022-08-11 Thread Paul Smith
On Fri, 2022-08-12 at 02:37 +0800, ljh wrote:
> Aren't the order of compiling object files of first two rules
> certain?

The POSIX standard for make mandates that prerequisites are tried by
make in the order they are listed in the prerequisite list, with the
exception that implicit rules will prepend the prerequisites (this is
what you want, else the $< variable will contain some random target).

GNU make will, of course, obey the standard.

The problem is that when you enable parallel builds (make -j), even
though make will still try things in the order in which they are
listed, you can get files built in other orders depending on how long
prerequisites take to be built.

The correct way to write makefiles is to declare all the dependency
relationships between targets explicitly in the makefile, and NOT rely
on implicit ordering of prerequisites.

When you write a rule in make like this:

   target: prereq1 prereq1

this tells make that "target" depends on "prereq1" and "prereq2", and
so make will never start building "target" until after BOTH "prereq1"
and "prereq2" are done.

However, that rule says NOTHING about any relationship between
"prereq1" and "prereq2", to each other.  As far as make is concerned
these targets are 100% independent and make will definitely not ensure
that, for example, "prereq1" is complete before it starts building
"prereq2" (for example when you use -j).

If you want to define a relationship between "prereq1" and "prereq2",
you have to put that in a separate rule.  See below.

> # ok: in order of writing, with recipe
> x: y.o z.o x.o
>     $(CC) $^ -o $@

Since you've declared your own rule here the pattern rule is not used
and, as long as you don't use -j, you are guaranteed that the
prerequisites are built in that order.

> # ok: compiles x.o last, no mentioning x.o
> x: y.o z.o

Here the pattern rule is used, but the pattern rule chosen is "% :
%.cpp" which means it will not build x.o at all.  Instead it builds the
y.o and z.o object files, then it does the compile of x.cpp and link
together in one command.  If you examine the link line make prints very
carefully you'll see that it contains x.cpp not x.o, and there will be
no x.o file in your directory when you're done:

   g++ -o x x.cpp y.o z.o
^

So, this works for your specific purposes.

Note that when your module requirements get more complex, it's very
likely this will no longer work.  It's a magical accident of the fact
that your file that uses modules has the same name as the program
you're trying to create.

> The rest of the below three rules are not suitable if compiling order
> matters.
> 
> # compiles x.o first, mentioning x.o
> x: y.o z.o x.o
> 
> # compiles x.o first
> x: $(patsubst %.y,%.o,$(wildcard *.y))
> 
> # in order of file names, with recipe
> x: $(patsubst %.y,%.o,$(wildcard *.y))
>     $(CC) $^ -o $@ 

None of the 5 rules above are really suitable, if compiling order
matters.

If compiling order matters, then you should tell make what the
necessary order is, by declaring prerequisites.

If it's the case that x.o can't be created until y.o and z.o are
completed, then you have to write that into your makefile, like this:

  x.o : y.o z.o

(note you don't need a recipe here: you can use the default rule to
build the x.o file.  You're just telling make about some extra
prerequisites it has to complete before it can build x.o)



Re: ?????? ?????? Implicit rule for linking multiple object files

2022-08-11 Thread ljh
Thanks Paul,


I've learnt a lot from your mail.

Re: Making makefiles with primarily phony targets more friendly

2022-08-11 Thread Paul Smith
On Wed, 2022-08-10 at 19:08 +, Katherine Pata wrote:
> I often find myself using makefiles to handle things like project
> linting, container images, various scripts, initiating tests, and
> other misc tasks. Sometimes these include tasks that have real
> dependencies that make should keep track of, but often the vast
> majority of targets are phony.
> 
> Something like --reverse-phony or a variable like .GENUINE or .REAL
> that is mutually exclusive with .PHONY would be really helpful.

Adding such a command-line option is not right, since that means that
different invocations of make would handle these targets differently
depending on the options used to invoke make.  Whether or not specific
targets are phony is intrinsic to the makefile, not based on the
invocation of make.

I'm not sure I quite understand the suggestion; I think it would need
to be fleshed out and made more detailed first.  How would a variable
like .GENUINE or .REAL work?



Re: ?????? ?????? Implicit rule for linking multiple object files

2022-08-11 Thread ljh
Hi Paul,


I use some example code which uses C++20 modules.


There are five .cpp files, e.g:
main.c  depends on a.c b.c c.c d.c
b.c d.c depends on c.c
a.c     depends on b.c
d.c     depends on a.c


I update my Makefile like the following. Is it correct and guaranteed to work
under parallel make?


CXXFLAGS = -std=c++2a -fmodules-ts
CC       = $(CXX)


# executable
main : a.o b.o c.o d.o main.o


# order of compiling object files
main.o : a.o b.o c.o d.o
b.o d.o : c.o
a.o : b.o
d.o : a.o




Thanks