I am following example 2 of the instructions on this page How to change or add new code (although the actual code I am trying to change is ./src/surf/module/surfexcdriver_ctl_mod.F90) and have experienced some problems.

In the change-src.cfg file (in /oifs40r1v1_new/mymake directory) I only have 2 lines

use =../make/

build.source = $HERE/../mysrc/

The modified source is in

/oifs40r1v1_new/mysrc/surf/module/

When I run the command

 fcm make -v -f change-src.cfg

I get the following


[init] make                # 2018-03-07T14:56:44Z
[info] FCM 2015.03.0
[init] make config-parse   # 2018-03-07T14:56:44Z
[info] config-file=/homeappl/home/sinclair/appl_taito/oifs40r1v1_new/mymake/change-src.cfg
[FAIL] make config-parse   # 0.0s
[FAIL] make                # 0.0s
[FAIL] use = ../make/: incorrect value in declaration
[FAIL] config-file=/homeappl/home/sinclair/appl_taito/oifs40r1v1_new/mymake/change-src.cfg:1
[FAIL] ../make/.fcm-make/ctx.gz: cannot retrieve cache
[FAIL] No such file or directory at /homeappl/home/sinclair/appl_taito/oifs40r1v1_new/fcm/bin/../lib/FCM/System/Make/Share/Dest.pm line 83, <$handle> line 1.


I get the feeling some paths are not correct as I searched for the ctx.gz file and it is in

./oifs40r1v1_new/make/intel_mkl-opt/.fcm-make/ctx.gz

and the Dest.pm file is here

./oifs40r1v1_new/fcm/lib/FCM1/Dest.pm
./oifs40r1v1_new/fcm/lib/FCM/System/Make/Share/Dest.pm

I checked the original fcm config log file and it has

config-file=/homeappl/home/sinclair/appl_taito/oifs40r1v1_new/make/oifs.cfg

config-file= - /homeappl/home/sinclair/appl_taito/oifs40r1v1_new/make/cfg/intel_mkl-opt.cfg

Students in Numlab tried this first and got the same error as I do so (hopefully) it is not just me being stupid... Any ideas?

Thanks

Victoria


3 Comments

  1. Unknown User (nagc)

    Hi Victoria,

    Thanks for reporting the problems. The page on how to modify source was written for OpenIFS 38r1 and hasn't been updated for 40r1 which uses slightly different names in the configuration file. So you are correct, the paths being used are the problem. The options should be 'oifs.prop' instead of 'build.prop'.

    Inherited builds do work and I'll show how to do it below. For the students projects, maybe a simpler method would be better?

    To be complete, here are some suggestions on ways to work with modifying the code, with the inherited build solution at the end.

    1. Copy files in 'src'

    Easiest way would be to edit the files in the 'src' directory directly, making a backup copy:

    cd src/ifs/control
    cp cnt4.F90 cnt4.F90.orig
    ... edit cnt4.F90 ...

    Works fine. The build system (FCM) will still see the .orig file but won't do anything with it.

    If working this way, I would recommend only using it for changing small numbers of files as it can get confusing what's changed and what hasn't. I'd also suggest making a backup copy (as a tarfile for example) of the complete unmodified 'src' directory before making such changes.

    Disadvantage is keeping track of what's been changed, which can go wrong if many files are altered. But useful for quick 1 or 2 files edits.

    2. Use source code versioning

    Another way that doesn't involve changing the build configuration would be to use a source code version control system like git, subversion or mercurial. Git is quite easy to use and maybe useful for the students to learn.

    e.g.

    % cd src                          #  suggest only using git in the 'src' directory so it doesn't see all the compiled files
    % git init
    Initialized empty Git repository in oifs40r1v2/.git/
    % git add .                       #  add everything in the current directory and all sub-directories
    % git commit -m 'initial commit'  #  make first version on 'master' branch
    % git branch
    * master

    Then you could either just edit the files and commit the changes with git:

    % vi ifs/control/cnt4.F90          #  edit a file with your favourite text editor
    % git commit -am 'added prints'    #  add & commit the file change
    [master 60f06d1] added prints
     1 file changed, 2 insertions(+)

    or all changes could be put on to a separate code 'branch':

    % git branch        # list which branch we are on
    * master
    % git checkout -b change_drag   # create new code branch called 'change_drag' and change to it
    Switched to a new branch 'change_drag'
    % git branch        # confirm which branch we're on
    * change_drag
      master
    #... edit files / commit changes ....
    #... compile & run model with new code ...
    
    # to switch back to the original code
    % git checkout master

    Advantage: keeps source code properly managed

    Disadvantage: need to learn git (or some other system).

    3. Work in a copy of the src directory

    This approach uses a complete copy of the 'src' directory, leaving the original for reference:

    cd oifs40r1
    cp -rp src mysrc

    To point to this new source directory, you can either set the environment variable OIFS_SRC_DIR, which takes precedence over the default in the oifs.cfg file, or I recommend making your own copy of the oifs.cfg and changing the source directory in there:

    cd make
    cp oifs.cfg myoifs.cfg

    Edit myoifs.cfg and change:

    $OIFS_SRC_DIR{?} = $HERE/../src

    to

    $OIFS_SRC_DIR{?} = $HERE/../mysrc

    To compile the model, is just the same as before, but now use myoifs.cfg instead of oifs.cfg:

    fcm make -v -j4 -f myoifs.cfg

    Then edit the files in mysrc rather than src.

    Disadvantage: have to work with the full source tree, so not always easy to find changed code.

    Advantage: leaves the original src tree intact for reference (diff'ing files etc)

    4. Use an inherited build and only copy changed source

    An inherited build is useful because only the source files that need to be changed have to copied.

    Here's how to do it for OpenIFS 40r1.

    1. Start by correctly setting the environment:

    %cd oifs40r1
    # correctly setup compiler environment
    % export OIFS_BUILD=opt
    % export OIFS_COMP=gnu

    2. First build the unmodified src. This is essential!

    % cd make
    % fcm make -v -j4 -f oifs.cfg

    3. Next copy the files we are going to change (and only those files) into a new src directory.

    I'm going to make changes to cnt0.F90 (for example). It must match the existing directory structure of the 'src' directory:

    % cd ..
    % mkdir -p mysrc/ifs/control
    % cp src/ifs/control/cnt0.F90 mysrc/ifs/control/cnt0.F90    # ..and edit cnt0.F90

    4. Next create the small configuration file that will use (inherit) the previously build unmodified model:

    % cd make
    % cat my.cfg
    use = $HERE/${OIFS_COMP}-${OIFS_BUILD}
    include = $HERE/oifs.cfg
    oifs.source = $HERE/../mysrc

    An explanation of what these 3 lines are doing:

    1. use =. This points to the directory where the previous unmodified build placed the hidden directory '.fcm-make'. The 'inheritance' won't work if this '.fcm-make' directory is not found.
    2. include =. This loads all the variables from the unmodified configuration so the inherited build knows about include files and directories etc.
    3. oifs.source =. This points to where the new modified source files are. Only the modified files need to be placed here. The unmodified files will be taken from the previous build (actually only the modified src is compiled, the object files from the previous build are linked).
      $HERE is a special variable that FCM knows about (it is not a shell environment variable). It basically means 'the directory where this file is', and allows for relative paths to be set.

    Because the FCM build system knows how the source files depend on each other, if you modify a file that means other files must be recompiled, it will do that.

    And that's it. Just make sure to copy any files that are modified into 'mysrc'.

    Disadvantage: have to build model first

    Advantage: only need to copy files that are altered so easier to see what's changed.

    I will update the examples on the 'How to' page you noted (but not today). The examples are correct, but the names need to be modified from 'build.prop' to 'oifs.prop' and then they should work.

    Note that the inherited build will create it's own .fcm-make directory (and log files) in the 'make' directory.

    Any problems, let me know.

    Cheers,  Glenn




    1. Hi Glenn,

      Thanks for the quick reply. I tried this and it worked ok. Just a few things to clarify. In section 4 after 4 (create the my.cfg file) of your instructions, I assumed I should run the command

      fcm make -v -j4 -f my.cfg

      in the oifs40r1/make directory?

      I am just checking as in the 38r1 instructions there is also a mymake directory mentioned.

      Finally, when I did this, it over-wrote my original master.exe. Is this supposed to happen?

      Victoria


      1. Unknown User (nagc)

        Hi Victoria,

        Ah yes, I forgot about the 'mymake' directory. That's on the 'How to' page to keep the unmodified and modified builds separate.  You're right, because the instructions above put my.cfg into the 'make' directory, it will overwrite the executable which goes into make/${OIFS_COMP}-${OIFS_BUILD}.

        There are a couple of ways around this, either redirect the build or put the inherited build cfg file into a 'mymake' directory.

        1. With my.cfg in 'make', edit the my.cfg file to add a destination directory for the build:

        make/my.cfg
        use = $HERE/${OIFS_COMP}-${OIFS_BUILD}
        include = $HERE/oifs.cfg
        dest=$HERE/mybuild
        oifs.source = $HERE/../mysrc

        2. Or, create a new 'make' directory and put the 'my.cfg' file in there, changing the paths in the file to:

        mymake/my.cfg
        use = $HERE/../make/${OIFS_COMP}-${OIFS_BUILD}
        include = $HERE/../make/oifs.cfg
        oifs.source = $HERE/../mysrc

        Cheers,  Glenn