Closed gradylemoine closed 10 years ago
So gfortran does not build the *.mod
when the object file is updated? This seems like a major bug in gfortran! Does the time stamp not get updated if the file does not change? This has a lot of implications that are not currently in the Makefile system, for instance, if a module is changed we really do not do the right thing and recompile the entire source tree (or follow the dependency tree). Removing the *.mod
file does not actually fix this problem, we should really modify the Makefile.common
to rebuild everything at the very least to cover our bases.
What I originally observed is that I'd change a file that has a module in it, recompile, and the .mod wouldn't have an updated timestamp. A little more poking around seems to indicated that gfortran will update the .mod file, but only if the module has changed -- changes to subroutines in the same file but outside the module don't cause the .mod timestamp to change, nor do changes to the code of subroutines within the module, but changes to the module variable list or the type signature of module subroutines do cause the .mod to update. This makes sense in and of itself, but it confuses the build system because it can think the .mod is old, and as a consequence rebuild and re-run the executable. (I wrestled with this a few times during my thesis work, and I'm glad I finally figured out what's going on. It's no fun to accidentally re-launch a multi-hour simulation, wiping out the previous results in the process.)
Yes, make is annoying about not checking dependencies regarding modifying a module, in the sense that it won't recompile any .f90 code that uses the module unless it's also been changed. So we recommend always doing make new when changing modules in order to recompile everything.
Regarding accidentally re-running a big code when nothing has changed and wiping out past output, are you referring to doing "make .plots" and having it rerun the code unexpectedly? There is another option "make plots" without the . that will avoid this since it does not check dependencies and safer in this context. See http://clawpack.github.io/doc/makefiles.html
Also if you want to insure you never overwrite data accidentally, you can set OVERWRITE = False In the Makefile to force it to always make a copy of the output directory if it already exists before running. But then you need to remember to clean up yourself if you run the code multiple times.
All of this should be better documented...
On Mon, Nov 25, 2013 at 7:34 AM, Grady Lemoine notifications@github.comwrote:
What I originally observed is that I'd change a file that has a module in it, recompile, and the .mod wouldn't have an updated timestamp. A little more poking around seems to indicated that gfortran will update the .mod file, but only if the module has changed -- changes to subroutines in the same file but outside the module don't cause the .mod timestamp to change, nor do changes to the code of subroutines within the module, but changes to the module variable list or the type signature of module subroutines _do_cause the .mod to update. This makes sense in and of itself, but it confuses the build system because it can think the .mod is old, and as a consequence rebuild and re-run the executable. (I wrestled with this a few times during my thesis work, and I'm glad I finally figured out what's going on. It's no fun to accidentally re-launch a multi-hour simulation, wiping out the previous results in the process.)
— Reply to this email directly or view it on GitHubhttps://github.com/clawpack/clawutil/pull/68#issuecomment-29210886 .
Yeah, I hadn't known about the plain "make output" and "make plots" commands then; I believe I learned about those over the summer. I thought I'd gotten around the not-recompiling issue by explicitly listing the .mod file as a dependency of the object code, though this of course adds the annoyance of explicitly adding those dependencies. This would all be a lot easier if gfortran would just update the timestamp on the .mod file; sadly, I just checked the man page, and there doesn't seem to be a command line option to do this.
I just did a bit of googling, and this seems to be a deliberate gfortran behavior to prevent excessive rebuilding (ironically). Some relevant links:
http://lagrange.mechse.illinois.edu/mwest/f90_mod_deps/ (someone else dealing with this issue) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31587 (the gfortran 4.3 change that caused this)
It seems hard to make this work with make.
It sounds like the time stamp behavior is correct. What about building the dependency tree based on a grep of the source contents for something like use awesome_module
and require that the module being used and the file name match? Maybe more importantly, who wants to implement it?
@mandli - see: http://www.gnu.org/software/make/manual/make.html#Automatic-Prerequisitesfor a reference on how to generate dependencies from Fortran (and other compilers).
On Mon, Nov 25, 2013 at 11:24 PM, Kyle Mandli notifications@github.comwrote:
It sounds like the time stamp behavior is correct. What about building the dependency tree based on a grep of the source contents for something like use awesome_module and require that the module being used and the file name match? Maybe more importantly, who wants to implement it?
— Reply to this email directly or view it on GitHubhttps://github.com/clawpack/clawutil/pull/68#issuecomment-29266654 .
@ahmadia I don't see a Fortran example there but that aside, I think I looked into this before but never got it to work correctly. Obviously the compiler does know the modules it needs but since Fortran allows the modules and files to be named differently (contrary to include files) I am not sure how this would work in general for Fortran.
@mandli the -M
flag is universal across the GCC toolchain as of 4.6. And yes, building Fortran is a nightmare. You can either choose to maintain your module dependency list yourself or rely on the tools.
Playing with it now, looks promising although I am not sure about requiring GCC versions > 4.6.
I don't know of a reasonable development system in the world that doesn't have access to GCC >= 4.6
On Tue, Nov 26, 2013 at 12:05 AM, Kyle Mandli notifications@github.comwrote:
Playing with it now, looks promising although I am not sure about requiring GCC versions > 4.6.
— Reply to this email directly or view it on GitHubhttps://github.com/clawpack/clawutil/pull/68#issuecomment-29267818 .
There are old systems out there, and poorly-updated ones. On Hyak, the big UW server farm/cluster, we have gcc 4.1.2, sadly. Though I thought Clawpack required a more recent gcc already. And the -M option only provides a dependency list -- that's useful, but it doesn't address the issue of keeping make from getting confused and thinking the .mod file needs to be updated when it's already up-to-date.
@gradylemoine - your commit doesn't do what you want it to do. If you modify the pattern rule to delete the .mod file when it is out of date, this doesn't actually help make
do the original determination of out-of-date-ness in the first place.
The idea was to ensure that a fresh .mod file will be generated whenever the relevant Fortran file is compiled. It won't help if the .mod is not out-of-date but looks as though it is, but it will help prevent that situation from occurring in the first place. Can you suggest a better way to deal with the problem?
@gradylemoine - I still don't understand what you want. If the .mod
file hasn't changed, gfortran
doesn't rebuild it. Can you explain in what situation the .mod
file hasn't changed, isn't out-of-date, and you'd like to still force it to be rebuilt anyway?
I'm looking at a situation where I'm actively tinkering with something, and it takes at least three builds for this issue to crop up, along with listing a .mod as a dependency (which I normally do, to make sure those files get built before the compiler needs to use them). Say I have a file named source.f90, which provides the module "source," and I go through a common workflow of tinkering with sources, getting the program to do what I want, then going on to tinker with plotting.
Build 1: source.mod file created for the first time, executable built (Modification source.f90, but not one that requires a new .mod file) Build 2: source.mod file not updated, timestamp stays older than source.f90 (Modification to something further down the line, for me typically setplot.py) Build 3 (probably make .plots): source.mod still has Build 1 timestamp, but parent file is newer, so make tries to build it again. This creates a new source.o as a side effect, triggering a rebuild of the executable and a re-run of the simulation, when all I wanted was to re-do plots with the existing output.
What I'm trying to do is to make sure that Build 2 will update the timestamp on source.mod, so that Build 3 doesn't do the wrong thing.
Okay, now I completely understand.
The simplest solution is to call touch
on all potentially updated modules after compiling instead of deleting them.
One potential long-term solution is to disconnect module compilation from object compilation by using the -fsyntax-only
flag, which allows you to rebuild out-of-date modules without triggering a full compile. But this is GFortran-specific and may not do what you want.
Adding onto what Aron said, there's a build rule and dependency in Makefile.common
for *.mod
files. Perhaps it's best that we look into changing the dependencies there as they are more than likely heavy handed.
Yeah, using touch instead of deleting the files occurred to me after I'd submitted this. It doesn't really seem functionally different, though, unless the compile fails (in which case maybe the .mod shouldn't exist?). In any case, I'm open to either approach.
I also use -fsyntax-only in my own makefiles, in exactly the way you describe, although I don't like that it's gfortran-specific. I salve my conscience by defining a variable MODGEN, which is "gfortran -fsyntax-only $(FFLAGS)", with the idea that if the user has a different compiler they could substitute whatever is appropriate for them.
So, do we have a consensus on what to do with this? Remove the .mod files, touch the .mod files, leave the setup as it was, or do something else entirely?
It's your show Grady :) I'm mostly just barging in with opinions to slow you down. I think just touching the .mod files is a reasonable compromise if you'd like to make sure make always knows what's going on.
On Fri, Nov 29, 2013 at 4:47 PM, Grady Lemoine notifications@github.comwrote:
So, do we have a consensus on what to do with this? Remove the .mod files, touch the .mod files, leave the setup as it was, or do something else entirely?
— Reply to this email directly or view it on GitHubhttps://github.com/clawpack/clawutil/pull/68#issuecomment-29538832 .
I am still not convinced I guess that either of the options proposed are really the right way to handle this problem. It seems like we should correctly handle the dependencies and not force the issue and break expected GCC behavior.
Touch is correct in this context for communicating that a file is up to date.
On Friday, November 29, 2013, Kyle Mandli wrote:
I am still not convinced I guess that either of the options proposed are really the right way to handle this problem. It seems like we should correctly handle the dependencies and not force the issue and break expected GCC behavior.
— Reply to this email directly or view it on GitHubhttps://github.com/clawpack/clawutil/pull/68#issuecomment-29541195 .
I just played around with this a bit and it seems to me that changing the default rules to:
%.mod : %.f90 ; touch $@; $(CLAW_FC) -c $< $(MODULE_FLAG)$(@D) $(ALL_INCLUDE) $(ALL_FFLAGS) -o $*.o
%.mod : %.f ; touch $@; $(CLAW_FC) -c $< $(MODULE_FLAG)$(@D) $(ALL_INCLUDE) $(ALL_FFLAGS) -o $*.o
would be the right thing to do. It might not be the expected gcc behavior, but it seems to me that behavior is wrong.
If this rule is invoked to update the .mod file then it should do so, and should indicate that it's now up to date by touching it (in case gfortran doesn't update the timestamp because the .mod file didn't change after recreating the .o file). The .mod file is still up to date at this point and the timestamp should reflect that, I think.
Actually, shouldn't the "touch $@" go after the re-creation of the .o file.
Never mind, it doesn't matter since only the .f or .f90 is in the dependency list.
Bringing the time stamp up means that you should recompile all source that uses the module which is not the deired behavior. My understanding is that the .mod file should be a dependency on each source that includes the module and need to be recompiled only when the interface changes, hence the time stamp should be old and not touched even when the .o file is updated. The change needed here is to make it so the .mod file does not have a dependency on the .o file so that the time stamp is not checked.
On Fri, Nov 29, 2013 at 5:55 PM, Randall J. LeVeque notifications@github.com wrote:
Actually, shouldn't the "touch $@" go after the re-creation of the .o file
Reply to this email directly or view it on GitHub: https://github.com/clawpack/clawutil/pull/68#issuecomment-29541921
Kyle is right. I wasn't thinking through this clearly.
On Friday, November 29, 2013, Kyle Mandli wrote:
Bringing the time stamp up means that you should recompile all source that uses the module which is not the deired behavior. My understanding is that the .mod file should be a dependency on each source that includes the module and need to be recompiled only when the interface changes, hence the time stamp should be old and not touched even when the .o file is updated. The change needed here is to make it so the .mod file does not have a dependency on the .o file so that the time stamp is not checked.
On Fri, Nov 29, 2013 at 5:55 PM, Randall J. LeVeque <notifications@github.com <javascript:_e({}, 'cvml', 'notifications@github.com');>> wrote:
Actually, shouldn't the "touch $@" go after the re-creation of the .o
file
Reply to this email directly or view it on GitHub: https://github.com/clawpack/clawutil/pull/68#issuecomment-29541921
— Reply to this email directly or view it on GitHubhttps://github.com/clawpack/clawutil/pull/68#issuecomment-29542978 .
Actually I think the object files may be a red herring. Even with just source files and .mod files that are "sometimes" really out of date, there will be an unnecessary full recompile every time make is called if the .mod file is never updated/touched after a compile.
The gfortran idea is interesting but dangerous. It is far safer to touch the .mod file and trigger an unnecessary sub-build once per update than unlimited rebuilds without touch.
Sorry for reversing myself again. Posting from a Celtics game :)
On Friday, November 29, 2013, Aron Ahmadia wrote:
Kyle is right. I wasn't thinking through this clearly.
On Friday, November 29, 2013, Kyle Mandli wrote:
Bringing the time stamp up means that you should recompile all source that uses the module which is not the deired behavior. My understanding is that the .mod file should be a dependency on each source that includes the module and need to be recompiled only when the interface changes, hence the time stamp should be old and not touched even when the .o file is updated. The change needed here is to make it so the .mod file does not have a dependency on the .o file so that the time stamp is not checked.
On Fri, Nov 29, 2013 at 5:55 PM, Randall J. LeVeque notifications@github.com wrote:
Actually, shouldn't the "touch $@" go after the re-creation of the .o
file
Reply to this email directly or view it on GitHub: https://github.com/clawpack/clawutil/pull/68#issuecomment-29541921
— Reply to this email directly or view it on GitHubhttps://github.com/clawpack/clawutil/pull/68#issuecomment-29542978 .
So ... how about if we take the "touch" solution as a provisional solution; I can issue another pull request with that, and we can put a band-aid over this until we figure out how to do it properly. Does that sound reasonable?
Regarding the last comment of @mandli: At the moment we do not have the .mod files as a dependency for all the source files that use the module -- which leads to problems if you change a parameter in a module and then forget to do "make new" for example to recompile everything, which is a separate problem from the current one. But I guess the point is that if we did check these dependencies then this would lead to recompiling those Fortran file even when the .mod file didn't change just because the timestamp was updated?
Since we don't check these dependencies, it seems like adding the "touch" solution will work fine for the time being though not elegant.
By the way the original comment of @gradylemoine indicated this is only a problem when changing something in a .f90 file that doesn't affect the .mod file it creates, e.g. in a subroutine in the same file. But for the most part we have used the convention that files named something like xxx_module.f90 only contain a module named xxx. With this convention, do we still run into this problem?
Yes, this could occur if, for instance, you changed code in a module subroutine. If the calling signature of the subroutine isn't affected, the .mod won't change, even if the subroutine code changes (tested with gfortran 4.8.1). But because the issue has to do with modification timestamps, it could be triggered even if you just updated the comments in a file with a module -- the problem is not that the .mod file doesn't reflect the contents of the module, but rather that make gets confused if gfortran doesn't update the timestamp on the .mod.
I haven't changed my mind about the solution again, if that's worth anything :) +1 to manually touching any .mod
files after their dependencies trigger a recompile.
@ahmadia What do you mean by "manually"? Are you agreeing that changing the Makefiles to do
%.mod : %.f90 ; touch $@; $(CLAW_FC) -c $< $(MODULE_FLAG)$(@D) $(ALL_INCLUDE) $(ALL_FFLAGS) -o $*.o
%.mod : %.f ; touch $@; $(CLAW_FC) -c $< $(MODULE_FLAG)$(@D) $(ALL_INCLUDE) $(ALL_FFLAGS) -o $*.o
is ok?
Yes, that kind of "manually" :)
As long as the module dependencies are structured so that pattern rule is suitable, that's how I would do it.
This is off-topic, but I think you should switch to cmake, it has excellent Fortran support and you don't have to deal with issues like these.
Yes, we should seriously consider switching to cmake.
But for 5.0.0 let's go with what we have.
PR #70 implements touch, so I'm closing this one.
Sounds good to me.
This deals with an issue I've had with gfortran from time to time -- when rebuilding a module file, it doesn't seem to refresh the timestamp on the .mod file if the file already exists. This forces the issue by removing the .mod before rebuilding.