Secondary expansion & target-specific variable problem in Makefile

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Secondary expansion & target-specific variable problem in Makefile

孔涛
Hello,everyone

How to set different prerequisites for the same target when it belong to a different target. For example,
target t1 depends on file main.o and t1.o where main.o depend on t1.o (it's a module file in fortran, similar as a head file .h in C) besides its source, while
target t2 depends on file main.o and t2.o where at this time main.o depends on t2.o together with it's souce file.  i.e
--------------------------
t1 : main.o t1.o
main.o:   t1.o
-------
t2:main.o t2.o
main.o:  t2.o
-------------------------
I wrote them together in one makefile, but unforturanatly, the dependece of main.o does not take effect. why?
--
     1    .SECONDEXPANSION:
     2   
     3    FC=gfortran
     4    PRJ = t1 t2
     5   
     6    all: $(PRJ)
     7   
     8    %.o:%.f90 ; $(FC) -c $<
     9   
    10   
    11    t1: tname = t1.o
    12    t2: tname = t2.o
    13   
    14    $(PRJ) : main.o $$(tname) ; $(FC) $^ -o $@
    15    main.o : $$(tname)
    16   
    17    clean:
    18        rm -rf $(PRJ) *.o *.mod

----
line 15 doesnot make any sense. why?

here are the source file:
------------------------
--main.f90--
use eqn
print *,nam
end


--t1.f90--
module eqn
    character(10):: nam = 't1'
end module


--t2.f90---
module eqn
    character(10):: nam = 't2'
end module




Kong Tao

----
School of Maths, Shandong Univ. P.R.C.




------------------------------------------------------------------------------
Dive into the World of Parallel Programming! The Go Parallel Website,
sponsored by Intel and developed in partnership with Slashdot Media, is your
hub for all things parallel software development, from weekly thought
leadership blogs to news, videos, case studies, tutorials and more. Take a
look and join the conversation now. http://goparallel.sourceforge.net
_______________________________________________
MinGW-users mailing list
[hidden email]

This list observes the Etiquette found at
http://www.mingw.org/Mailing_Lists.
We ask that you be polite and do the same.  Disregard for the list etiquette may cause your account to be moderated.

_______________________________________________
You may change your MinGW Account Options or unsubscribe at:
https://lists.sourceforge.net/lists/listinfo/mingw-users
Also: mailto:[hidden email]?subject=unsubscribe
Reply | Threaded
Open this post in threaded view
|

Re: Secondary expansion & target-specific variable problem in Makefile

Tuomo Latto
On 24.12.2014 15:15, 孔涛 wrote:

> Hello,everyone
>
> How to set different prerequisites for the same target when it belong to a different target. For example,
> target t1 depends on file main.o and t1.o where main.o depend on t1.o (it's a module file in fortran, similar as a head file .h in C) besides its source, while
> target t2 depends on file main.o and t2.o where at this time main.o depends on t2.o together with it's souce file.  i.e
> --------------------------
> t1 : main.o t1.o
> main.o:   t1.o
> -------
> t2:main.o t2.o
> main.o:  t2.o
> -------------------------
> I wrote them together in one makefile, but unforturanatly, the dependece of main.o does not take effect. why?
> --
>      1    .SECONDEXPANSION:
>      2  
>      3    FC=gfortran
>      4    PRJ = t1 t2
>      5  
>      6    all: $(PRJ)
>      7  
>      8    %.o:%.f90 ; $(FC) -c $<
>      9  
>     10  
>     11    t1: tname = t1.o
>     12    t2: tname = t2.o
>     13  
>     14    $(PRJ) : main.o $$(tname) ; $(FC) $^ -o $@
>     15    main.o : $$(tname)
>     16  
>     17    clean:
>     18        rm -rf $(PRJ) *.o *.mod
> ----
> line 15 doesnot make any sense. why?

AFAIK make generally likes to spawn new child processes to handle each
of the dependencies (and each command line within rules), so naturally
variables won't stay set across targets.
To be sure you'd have to set (environment?) variables in the parent make,
if you want sticky variables, but I think you can find better ways to
organize the build.

For example, does main really need the t1/t2 dependency?
In this case you don't, so you could simply remove it. If you really
need to produce two different implementations using the same main with
different dependencies (which is fairly ugly), you can put the
compilation of the common file as a command within t1 and t2 rules or
some separate dummy targets.
Frankly, you should, in general, refactor your projects so that there are
no circular dependencies or these kinds of logical loops. In C/C++, you'd
generally use header files to separate the (common) interface for the
dependencies (t1/t2) from their implementation in order to allow main
to be compiled separately without these sort of problems.

Also, are you sure the syntax on lines 11 and 12 is correct?
And have you noticed that line 8 also defines the compilation of main.o?
Are you sure you're not hitting that rule instead of lines 11, 12 and 15?

The thing about makefiles is that if you're trying to be too clever,
you still tend to end up making your cool, generic ruleset
a) unelegant and uncool,
b) unportable,
c) longer than the simpler ruleset that is equally uncool and unelegant,
   but portable and robust even if it includes lines and rules that look
   copy-pasted,
d) not-really-generic because you still need to nail down the specifics
   and end up doing it in the weeds hidden behind complicated logic
   rather than visibly up front, and
e) making it unnecessarily difficult to modify, should you need to
   e.g. after having refactored your code.

Just some things to consider.


> here are the source file:
> ------------------------
> --main.f90--
> use eqn
> print *,nam
> end
>
> --t1.f90--
> module eqn
>     character(10):: nam = 't1'
> end module
>
> --t2.f90---
> module eqn
>     character(10):: nam = 't2'
> end module


--
Tuomo

---
This email has been checked for viruses by Avast antivirus software.
http://www.avast.com


------------------------------------------------------------------------------
Dive into the World of Parallel Programming! The Go Parallel Website,
sponsored by Intel and developed in partnership with Slashdot Media, is your
hub for all things parallel software development, from weekly thought
leadership blogs to news, videos, case studies, tutorials and more. Take a
look and join the conversation now. http://goparallel.sourceforge.net
_______________________________________________
MinGW-users mailing list
[hidden email]

This list observes the Etiquette found at
http://www.mingw.org/Mailing_Lists.
We ask that you be polite and do the same.  Disregard for the list etiquette may cause your account to be moderated.

_______________________________________________
You may change your MinGW Account Options or unsubscribe at:
https://lists.sourceforge.net/lists/listinfo/mingw-users
Also: mailto:[hidden email]?subject=unsubscribe
Reply | Threaded
Open this post in threaded view
|

Re: Secondary expansion & target-specific variable problem in Makefile

Keith Marshall
On 29/12/14 11:14, Tuomo Latto wrote:
> On 24.12.2014 15:15, 孔涛 wrote:
>> Hello,everyone
>>
>> How to set different prerequisites for the same target when it
>> belong to a different target. For example,target t1 depends on file
>> main.o and t1.o where main.o depend on t1.o (it's a module file in
>> fortran, similar as a head file .h in C)

Huh?  Surely t1.o is an *object* file; the corresponding module file
should be t1.mod, should it not?  (Disclaimer: I've not written any
FORTRAN code in years, and only ever FORTRAN-66/77 ... never F90/95).

>> besides its source, while target t2 depends on file main.o and t2.o
>> where at this time main.o depends on t2.o together with it's souce
>> file. i.e
>> --------------------------
>> t1 : main.o t1.o
>> main.o:   t1.o
>> -------
>> t2:main.o t2.o
>> main.o:  t2.o

If you put these in one makefile, you make main.o simultaneously
dependent on t1.o and t2.o, (which doesn't make any sense, because each
object file should depend only on its sources ... not other objects).

>> -------------------------
>> I wrote them together in one makefile, but unforturanatly, the dependece of main.o does not take effect. why?
>> --
>>      1    .SECONDEXPANSION:
>>      2  
>>      3    FC=gfortran
>>      4    PRJ = t1 t2
>>      5  
>>      6    all: $(PRJ)
>>      7  
>>      8    %.o:%.f90 ; $(FC) -c $<
>>      9  
>>     10  
>>     11    t1: tname = t1.o
>>     12    t2: tname = t2.o
>>     13  
>>     14    $(PRJ) : main.o $$(tname) ; $(FC) $^ -o $@
>>     15    main.o : $$(tname)
>>     16  
>>     17    clean:
>>     18        rm -rf $(PRJ) *.o *.mod
>> ----
>> line 15 does not make any sense. why?

Likely because you are attempting to use a target specific variable,
$(tname), expanded on the second expansion pass, but that variable has
no definition in the context of the main.o target, (which is the target
on line 15).

> AFAIK make generally likes to spawn new child processes to handle each
> of the dependencies (and each command line within rules), so naturally
> variables won't stay set across targets.

Shell variable, set within the commands invoked by the rule won't,
across separate commands; make variables *will*.

> To be sure you'd have to set (environment?) variables in the parent make,
> if you want sticky variables,

Nope ... you would use make variables.

> but I think you can find better ways to organize the build.

I agree.

> For example, does main really need the t1/t2 dependency?

Possibly on the t1.mod and t2.mod files?  However, the OP's fundamental
misunderstanding seems to be that main.o can depend on one or other, but
not both simultaneously, and that make can rebuild it as required, to
satisfy some other dependency.  Unless the two build objectives are
separated into distinct "if" blocks, *and* main.o is deleted at the end
of each logical build sequence, it can't; once built, it will not be
rebuilt unless it is definitively out of date WRT its prerequisites, and
there can be only one inclusive set of prerequisites in any one logical
invocation of make.

> Also, are you sure the syntax on lines 11 and 12 is correct?

They look okay to me.  They define a target specific variable, which is
one of those features of GNU make which many consider to be obscure, so
is likely little used; it's certainly a feature which I've never had
occasion to use, (as is secondary expansion, which hardly seems to be
justified by the examples in the GNU make manual).

> And have you noticed that line 8 also defines the compilation of
> main.o?

That's fine; it's an implicit rule, defining the commands which are to
be executed, WRT the prerequisites specified...

> Are you sure you're not hitting that rule instead of lines 11, 12
> and 15?

...here; the issue seems to be that those prerequisites make little or
no sense.

--
Regards,
Keith.

------------------------------------------------------------------------------
Dive into the World of Parallel Programming! The Go Parallel Website,
sponsored by Intel and developed in partnership with Slashdot Media, is your
hub for all things parallel software development, from weekly thought
leadership blogs to news, videos, case studies, tutorials and more. Take a
look and join the conversation now. http://goparallel.sourceforge.net
_______________________________________________
MinGW-users mailing list
[hidden email]

This list observes the Etiquette found at
http://www.mingw.org/Mailing_Lists.
We ask that you be polite and do the same.  Disregard for the list etiquette may cause your account to be moderated.

_______________________________________________
You may change your MinGW Account Options or unsubscribe at:
https://lists.sourceforge.net/lists/listinfo/mingw-users
Also: mailto:[hidden email]?subject=unsubscribe