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

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

2022-08-11 Thread ljh
Thanks Paul,


I've learnt a lot from your mail.

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 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 $@



?????? ?????? 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

> 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 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 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 &quo

Re: »Ø¸´£º Implicit rule for linking multiple object files

2022-08-10 Thread Henrik Carlqvist
On Thu, 11 Aug 2022 14:18:29 +0800
"ljh"  wrote:

> main : c.o b.o a.o d.o main.o

> A: note: imports must be built before being imported
> A: fatal error: returning to the gate for a mechanical issue
> compilation terminated.
> make: *** [ 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

That Makefile might seem fine and seem to work, but what would happen if you
would run "make -j 5"? Then, again, those other object files would not have
been built before main.o. So to work correctly with parallell builds, that
Makefile would probably also need a rule like:

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

regards Henrik



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

2022-08-10 Thread ljh
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: *** [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"

Re: Implicit rule for linking multiple object files

2022-08-10 Thread Paul Smith
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 z.o  # without x.o and recipe
> 
> if I include x.o, I can't omit the recipe:
>     ` x: y.o z.o x.o ` # with x.o 
>     `    $ (CXX) $ (LDFLAGS) $^ $(LDLIBS) -o $@ ` # with recipe

I don't know why you keep referring to C++20 modules.  Make doesn't
know anything about C++20 modules, it doesn't even know what version of
C++ the compiler is building with.  It barely even knows that there is
such a thing as C++: all it knows is "some source files end in .cpp or
.cc or .cxx and those should be built with a recipe that uses variables
CXX and CXXFLAGS".

In any event, I see no reason why an implicit rule without a recipe and
with x.o as a prerequisite wouldn't work.  In fact, it works fine for
me:

  $ ls
  Makefile  x.c  y.c  z.c

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

  $ make
  cc-c -o x.o x.c
  cc-c -o y.o y.c
  cc-c -o z.o z.c
  cc   x.o y.o z.o   -o x




Implicit rule for linking multiple object files

2022-08-10 Thread ljh
Hello list,


GNU Make Manual / 10.2 / Linking a single object file, mentions this:
    x: y.o z.o 


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


Is it correct for me to use patsubst function to include all object files?
    x: $(patsubst %.c,%.o,$(wildcard *.c))


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 z.o  # without x.o and recipe


if I include x.o, I can't omit the recipe:
    ` x: y.o z.o x.o ` # with x.o 
    `    $ (CXX) $ (LDFLAGS) $^ $(LDLIBS) -o $@ ` # with 
recipe



Thanks