-
Notifications
You must be signed in to change notification settings - Fork 139
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Build system improvements #354
Build system improvements #354
Conversation
* cice.make can be used to easily call make with the different targets present in the Makefile (db_files, db_flags, clean), or to pass different flags to make * makdep is listed as a prerequisite of the *.d files, such that we don't need to call make makdep separately in cice.build
The -I flag is used by Fortran compilers to locate files included via the "#include" preprocessor directive or the "include" statement, or modules referenced via the "use" statement. In our codebase we only use modules, and all modules files (*.mod) are put in the ${ICE_OBJDIR} directory, where the compilation takes place. So there is no need for all source directories (contained in the variable $(INCS), prefixed with -I) to be added to the build rules. This shortens the length of the displayed compilation lines.
…g/cice into build-system-improvements2
This PR is largely ready to merge. I will run some final manual tests to confirm errors are trapped (I did this earlier) and I need to make a few minor changes to documentation. This is built on and supercedes #322 and I will close that PR. I wanted to create a PR to push to #322 but that was going to be more complicated due to the need to update to master to get the latest documentation. |
This is ready to merge. @phil-blain, if you get a chance to have a look, let me know. Same for @eclare108213. Thanks. |
I will do that as soon as I get back to work on Monday. I’m out of the office this week, sorry for the delay. |
No problem, thanks @phil-blain |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a spelling error in dg_scripts.rst ('resuse').
Also 'recommendeded' in ug_running.rst.
Can this be removed from cice.build?
# tcraig, this is handled below, is it needed here?
#if (${ICE_CLEANBUILD} == 'true') then
# echo "cleaning objdir"
# rm -r -f ${ICE_OBJDIR}
#endif
Otherwise, no complaints from me. Very cool, thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for working on that Tony, I think the changes look good. I've highlighted a few points below (hope I'm not too picky!). I can do a few of those if you agree, just let me know.
@@ -156,6 +170,8 @@ realclean: | |||
# are understood & accepted. | |||
#------------------------------------------------------------------------------- | |||
|
|||
depends: $(DEPS) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure the 'depends' target is needed... it's only use would be to manually recreate the dependencies by calling cice.build depends
, right ? I don't see a use case for that; either the user uses incremental builds or clean builds; in both cases the makefile generates the dependencies before starting the compilation. I think that having a depends
target can create some confusion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you're right that we may not need depends. I don't think it hurts to have it. Maybe someone wants to just generate the depends without building the rest of the code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right that it does not hurt to have it. Although in that case I would mention somewhere in the documentation that the dependencies are usually automatically generated.
configuration/scripts/Makefile
Outdated
@@ -66,18 +66,28 @@ RM := rm | |||
.SUFFIXES: | |||
.SUFFIXES: .F90 .F .c .o | |||
|
|||
.PHONY: all |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a single .PHONY: all cice db_files db_flags mostlyclean clean realclean
line would also work
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, good to know. I may do that instead, it's cleaner.
configuration/scripts/Makefile
Outdated
clean: | ||
$(RM) -f *.f *.f90 *.d *.mod *.o $(EXEC) | ||
# $(RM) -f *.f *.f90 *.d *.$(MOD_SUFFIX) $(OBJS) | ||
$(RM) -f *.f *.f90 $(DEPS) $(OBJS) $(DEPGEN) $(EXEC) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- I think we can take this opportunity to simplify the clean targets. I don't think we need 3. I think that having a 'clean' target that deletes all *.o, *.mod, *.d and the exe is sufficient, plus a 'realclean' target that does the same plus deletes the 'makdep' executable. (this way the 'clean' target does the same thing as a clean build in terms of the CICE code itself)
- I prefer the 'rm' command in these targets to use '*.o' instead of '$(OBJS)' (for example) since the latter dumps a lot of text to the command line. (and in clean builds, this is amongst the first text that is outputed)
- I think we can remove the *.f and *.f90 from these targets since our build system does not generate any preprocessed sources.
I suggest the following, which is also simpler :
clean:
$(RM) -f *.o *.d *.mod $(EXEC)
realclean: clean
 $(RM) -f $(DEPGEN)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. I will refactor a bit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One other comment, the clean that the CICE code does by default is now using the Makefile clean. I changed that recently (maybe in this PR), not sure why it wasn't doing that before.
@@ -79,6 +142,18 @@ ${ICE_SANDBOX}/cicecore/shared | |||
${ICE_SANDBOX}/icepack/columnphysics | |||
EOF | |||
|
|||
if (${directmake} == 1) then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- I would actually put this block just before line
if (${ICE_CLEANBUILD} == 'true') then
. This way ICE_* variables are always shown, and ICE_MACHINE_BLDTHRDS is defined (the way it is now, the '-j' flag will be passed to Make in all cases, even if the ICE_MACHINE_BLDTHRDS variable is not defined, and Make will use all threads available on the machine (I've read this can impact performance...) - Also, I think that in the 'directmake ' case we should still write to the build log file with
... |& tee ${ICE_BLDLOG_FILE}
. This way we can also trap circular dependencies in that case. (Maybe we should also respect the ICE_QUIETMODE variable, though I personally don't care for that one)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, I am making those changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the second point, I think we decided for a direct make to avoid all the fluff. I think writing the make output to a bldlog file is part of that. I guess I view the circular dependencies as part of the fluff you get if you use the scripts the standard way. Also, the quietmode should not generally be used except by travis. For whatever reason, if we don't use the quiet mode with travis, it creates problems. it either concatenates the raw log file or it makes it very hard to find the errors. this was added just for travis and serves a purpose.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, I guess I viewed the 'fluff' as only the README.case file. But I don't feel strongly about that. So either way is fine.
Regarding quietmode, I didn't know the history, I thought it predated our Git/GitHub migration.
doc/source/user_guide/ug_running.rst
Outdated
|
||
cice.build [mostlyclean|clean|realclean] | ||
|
||
to write out information about the Makefile setup,:: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the comma at the end of the line should be removed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
doc/source/user_guide/ug_running.rst
Outdated
|
||
cice.build [db_files|db_flags] | ||
|
||
and to build the makdep tool or the dependencies,:: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would not mention the 'makdep' or 'depends' target in the doc. Usually people would just run cice.build so I think this could be confusing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I agree 100%. Maybe leave it in for now. I think it could be useful to be able to create the dependencies without actually building the model. Maybe if we need to check whether they are working correctly or for other reasons. It might be reasonable to not document it though. Let me think about that.
configuration/scripts/cice.build
Outdated
set ciceexe = $1 | ||
if ($#argv == 0) then | ||
# continue, standard way to build | ||
else if ($#argv == 1) then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the argument checking is too drastic; it prevents one from using all the features of make (ex. see https://www.gnu.org/software/make/manual/make.html#Instead-of-Execution where some flags that are supported by make are listed). This is one of the reason I passed all arguments in my initial implementation ($*
). I suggest that we check if the first argument is '--exe', '-h' or '--help' but apart from that we pass all other arguments to make. This way we can use an arbitrary number of make flags, both when using cice.build
or cice.build target
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, let me see what I can do. I didn't think about passing command line arguments directly to gmake and wanted to keep the parsing simple. But I can see what that might be useful, I will try to refactor. Thanks for the careful review, not too picky at all!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@phil-blain, what do you think the requirements are here? Is it just
cice.build # standard approach
cice.build -h
cice.build target # our makefile targets
cice.build [gmake option] # gmake options, one flag only
cice.build --exe filename
or is there also a requirement for
cice.build [gmake option] [gmake option] ... [target]
and so forth. Should we support gmake arguments with and/or without a target like
gmake --debug --keep-going
gmake --debug cice
gmake --silent --keep-going cice
and others as well? It seems to me if we are going to allow the ability to pass the gmake arguments from cice.build to gmake, it needs to be general, support multiple arguments, and work with a target as well. I will try to do that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I've got it working, we definitely want the most flexibility and I think that was suggested in the review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I agree that more flexibility is good, so all of these should work :
cice.build # standard approach
cice.build -h
cice.build target # our makefile targets
cice.build target1 target2 ... # multiple Makefile targets
cice.build [gmake option] [gmake option] [... other options ....] # gmake options
cice.build [gmake option] [gmake option] [[... other options ....] target # gmake options and target
cice.build [gmake option] [gmake option] [[... other options ....] target1 target2 ... # gmake options and multiple targets
cice.build --exe filename
As a side note, with the changes you already made we are now able to call
cice.build ice_dyn_evp.o
to compile a single file. This can be useful sometimes when you are just debugging compilation errors in a single file (This works because all objects file are implicit targets in the Makefile).
Do you think this should be mentioned in the documentation ?
I just checked in some changes based on the reviews and think I have covered the main recommendations.
@phil-blain , if you are willing to take another look and review, that would be great. I have tested this on conrad again and it seems to work fine, #eab1b65 https://github.com/CICE-Consortium/Test-Results/wiki/cice_by_hash_forks |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super! I tried the new script and everything works great. I noted a few minor points below
targets: | ||
@echo " " | ||
@echo "Supported Makefile Targets are: cice, makdep, depends, mostlyclean, clean, realclean, targets, db_files, db_flags" | ||
@echo "Supported Makefile Targets are: cice, makdep, depends, clean, realclean, targets, db_files, db_flags" | ||
target: targets |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the new target 'target' should be added to the .PHONY line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good catch.
@@ -188,7 +179,6 @@ depends: $(DEPS) | |||
# the if-tests prevent DEPS files from being created when they're not needed | |||
ifneq ($(MAKECMDGOALS), db_files) | |||
ifneq ($(MAKECMDGOALS), db_flags) | |||
ifneq ($(MAKECMDGOALS), mostlyclean) | |||
ifneq ($(MAKECMDGOALS), clean) | |||
ifneq ($(MAKECMDGOALS), realclean) | |||
ifneq ($(MAKECMDGOALS), targets) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the new target 'target' should also have it's line here : ifneq ($(MAKECMDGOALS), target)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good catch
realclean: | ||
$(RM) -f *.f *.f90 *.d *.mod *.o $(DEPS) $(OBJS) $(DEPGEN) $(EXEC) | ||
realclean: clean | ||
$(RM) -f $(DEPGEN) | ||
|
||
#------------------------------------------------------------------------------- | ||
# Build & include dependency files |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we could also take this opportunity to clean up what is uneeded here : all our files are *.F90 or *.c so the dependency generation for *.F and *.H can be removed.
Same for the rule
.F.o:
$(FC) -c $(FFLAGS) $(FIXEDFLAGS) $(CPPDEFS) $(INCLDIR) $<
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's OK to leave the other make rules in the Makefile for now. It could be that future development will need them. I don't think it hurts to have them there. I don't think folks actually look at the Makefile all that much. But I could be convinced otherwise. For now, I think I'll leave them as is.
The argument implementation supports -h or --help as a first argument. Otherwise, | ||
it passes all other arguments directly to make and calls it directly. In this | ||
mode, most of the cice.build script features are by-passed. The recommended | ||
way to run the script is without arguments. | ||
|
||
SEE ALSO | ||
User Documentation at https://github.com/cice-consortium/cice/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to link to read-the-docs here instead ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem is what version of readthedocs? Almost certainly whatever version we might link in the help output is incorrect. Master documentation is only correct for the current master. For released versions, would we need to manually change the link for each release? This is a case where it's easy for things to get out of sync. While pointing to the general cice repo isn't particularly useful either, at least I feel like it's never incorrect.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand.
default, this variable is true which means each invokation of **cice.build** will | ||
automatically clean the prior build. If incremental builds are desired to save | ||
time during development, the ``ICE_CLEANBUILD`` setting in **cice.settings** should | ||
be modified. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should also mention the 'buildincremental' option to cice.setup here ? (just an idea)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In some ways, I prefer to not encourage use of the incremental builds. Also, I think we have documented that feature elsewhere and prefer not to duplicate documentation if we can help it. It makes the documentation harder to maintain and makes the document bigger (but not necessarily clearer). I think we should always be evaluating whether the organization of the documentation is "best" and if not, to reorganize to make it easier to find stuff and clearer. I think we want to avoid duplication if possible.
Makefile and a machine specific Macros file in the case directory. **cice.build** | ||
is a wrapper for a call to make that includes several other features. | ||
|
||
CICE is built as follows. First, the makdep binary is created by compiling a small |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think C should be capitalized. Also, there is actually one dependency file per object file, so I would write this part as :
First, the makdep binary is created by compiling a small C program. The makdep binary is then run and dependency files are created. The dependency files are included into the Makefile automatically. As a result, make dependencies do not need to be explicitly defined nor generated by the user.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I will fix this as you suggest. Running a quick test now with the changes and will push soon.
OK, I just pushed a couple more changes based on the latest reviews. If @phil-blain agrees, I think we can merge the PR. If other changes are suggested, happy to keep iterating. thanks! |
PR checklist
Update the build to add new features to cice.build, see also Build system improvements #322
phil-blain, apcraig
Tested on conrad with 4 compilers, quick suite and 1 compiler full test suite
Based on #322. This PR is branched off the current master with changes pulled from @phil-blain build-system-improvements branch. Most changes came from @phil-blain. Due to conflicts with master documentation, a new branch was the easiest way to incorporate the latest changes cleanly.
Documentation changes can be viewed here
more about cice build
build scripts