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 <l...@qq.com> 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: *** [<builtin>: 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"<psm...@gnu.org>;
> *发送时间:* 2022年8月11日(星期四) 凌晨2:31
> *收件人:* "ljh"<l...@qq.com>; "bug-make"<bug-make@gnu.org>;
> *主题:* 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 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
>

Reply via email to