Skip to content
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

221.Add force checkout and compile functionality #236

Open
wants to merge 53 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 51 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
9922170
#221 Add `force_checkout` and `force_compile` click options
singhd789 Oct 29, 2024
6157b7b
#221 Add force-checkout functionality in createCheckout tool
singhd789 Oct 29, 2024
ab6bc12
#221 Add `force_compile` functionalty in createCompile tool
singhd789 Oct 29, 2024
0cdf4b0
Merge branch 'main' of github.com:NOAA-GFDL/fre-cli into 221.force-ch…
singhd789 Oct 30, 2024
751d3a2
Merge branch 'main' of github.com:NOAA-GFDL/fre-cli into 221.force-ch…
singhd789 Oct 31, 2024
6a13ab5
#221 Add `force_checkout` and `force_compile` arguments
singhd789 Oct 31, 2024
9e3037a
#221 Merge branch 'main' of github.com:NOAA-GFDL/fre-cli into 221.fo…
singhd789 Nov 6, 2024
6b7e632
#221 Merge branch 'main' of github.com:NOAA-GFDL/fre-cli into 221.fo…
singhd789 Nov 26, 2024
a8b5bd5
#221 Update use of click options
singhd789 Nov 27, 2024
b19680f
#221 Merge branch 'main' of github.com:NOAA-GFDL/fre-cli into 221.fo…
singhd789 Nov 27, 2024
5263a9f
#221 Update click option descriptions and click option functinality
singhd789 Dec 4, 2024
c8957da
#221 Merge branch 'main' of github.com:NOAA-GFDL/fre-cli into 221.fo…
singhd789 Dec 4, 2024
b3bb118
#221 Fix click options passed
singhd789 Dec 4, 2024
295b04d
#221 Update fre make unit test to use null_example
singhd789 Dec 4, 2024
d947e07
#221 Re-create compile script if `--force-checkout` was used
singhd789 Dec 4, 2024
10ef4fe
#221 Add `-force-dockerfile` to re-create dockerfile
singhd789 Dec 4, 2024
65f8a0d
#221 Create functions to remove duplication
singhd789 Dec 4, 2024
2f31d4f
#221 Create function to remove duplication in compile creation
singhd789 Dec 4, 2024
f32a3f6
#221 Create functions to remove duplication
singhd789 Dec 4, 2024
fbce701
#221 Add `--force-dockerfile` option
singhd789 Dec 4, 2024
6a99f4d
#221 Create function to remove duplication
singhd789 Dec 4, 2024
a6dd493
#221 Fix print statement
singhd789 Dec 5, 2024
6426b32
#221 Add error statement if container doesn't build
singhd789 Dec 5, 2024
6ae45d5
#221 Update print statements and change `click.echo` to `print` for …
singhd789 Dec 5, 2024
8162994
#221 Accidentally removed `--execute` options - add back in
singhd789 Dec 5, 2024
4bf3d05
#221 Merge branch 'main' of github.com:NOAA-GFDL/fre-cli into 221.fo…
singhd789 Dec 11, 2024
f732ec7
#221 Merge branch 'main' of github.com:NOAA-GFDL/fre-cli into 221.fo…
singhd789 Dec 23, 2024
a4894af
#221 Add arguments for `force-checkout`,`force-compile`, and `force-…
singhd789 Dec 26, 2024
18f49ea
#221 Fix arguments and snake case
singhd789 Dec 26, 2024
6e35a7a
#221 Update multi-target test
singhd789 Dec 26, 2024
b3a2482
#221 Add options for `force-checkout`, `force-compile`, and `force-d…
singhd789 Dec 26, 2024
1e82a89
#221 Merge branch 'main' of github.com:NOAA-GFDL/fre-cli into 221.fo…
singhd789 Jan 7, 2025
d1d2c1d
#221 Update create_compile_script.py
singhd789 Jan 7, 2025
9f084d3
#221 Merge branch 'main' of github.com:NOAA-GFDL/fre-cli into 221.fo…
singhd789 Jan 9, 2025
2a45bf1
#221 Add tests for `force-checkout`, `force-compile`, and `force-doc…
singhd789 Jan 15, 2025
83a782a
#221 Merge branch 'main' of github.com:NOAA-GFDL/fre-cli into 221.fo…
Jan 21, 2025
caa86e8
#221 Correct camel/snake case
Jan 21, 2025
ce64065
#221 Re-create combined yaml if `force-checkout` defined
Jan 21, 2025
e19b630
#221 Merge branch 'main' of github.com:NOAA-GFDL/fre-cli into 221.fo…
Jan 21, 2025
bca152f
#221 Fix variables
Jan 21, 2025
5b2d037
#221 Fix print statement
Jan 21, 2025
621ba95
#221 Add force options
Jan 21, 2025
923d63c
#221 Remove path check - this shouldn't exist anyway in this failure
Jan 21, 2025
a0d0bc4
#221 Add tests for `force-compile` option
Jan 22, 2025
6411f2b
#221 Use `run` function directly
Jan 22, 2025
b8ecaa8
#221 Merge branch 'main' of github.com:NOAA-GFDL/fre-cli into 221.fo…
Jan 28, 2025
1e840cc
#221 Add force options for tests
Jan 28, 2025
821a70c
#221 Add comma
Jan 28, 2025
bb3c966
#221 Add print statement
Jan 28, 2025
987f60c
#221 Remove Dockerfile and buildScript before running `run-fremake` …
Jan 28, 2025
8b7c85e
#221 Merge branch 'main' of github.com:NOAA-GFDL/fre-cli into 221.fo…
Jan 31, 2025
6e0ead3
#221 Fix variable referenced
Jan 31, 2025
baa1baa
#221 Add `force-dockerfile` argument
Jan 31, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 73 additions & 22 deletions fre/make/create_checkout_script.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,49 @@
'''
checks out a makefile for a given model from the yamls
i think!
Checks out source code
'''

import os
import subprocess
import logging
import sys
import shutil
from pathlib import Path

import fre.yamltools.combine_yamls as cy
from .gfdlfremake import varsfre, yamlfre, checkout, targetfre

def checkout_create(yamlfile, platform, target, no_parallel_checkout, jobs, execute, verbose):
def baremetal_checkout_write_steps(model_yaml,src_dir,jobs,pc):
"""
Go through steps to write the checkout script for bare-metal build
"""
fre_checkout = checkout.checkout("checkout.sh",src_dir)
fre_checkout.writeCheckout(model_yaml.compile.getCompileYaml(),jobs,pc)
fre_checkout.finish(model_yaml.compile.getCompileYaml(),pc)

# Make checkout script executable
os.chmod(src_dir+"/checkout.sh", 0o744)
print(" Checkout script created in "+ src_dir + "/checkout.sh \n")

return fre_checkout
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just curious, is this returned for a reason?


def container_checkout_write_steps(model_yaml,src_dir,tmp_dir,jobs,pc):
"""
Go through steps to write the checkout script for container
"""
fre_checkout = checkout.checkoutForContainer("checkout.sh", src_dir, tmp_dir)
fre_checkout.writeCheckout(model_yaml.compile.getCompileYaml(),jobs,pc)
fre_checkout.finish(model_yaml.compile.getCompileYaml(),pc)
print(" Checkout script created at " + tmp_dir + "/checkout.sh" + "\n")

return fre_checkout

def checkout_create(yamlfile,platform,target,no_parallel_checkout,jobs,execute,verbose,force_checkout):
"""
Call gfdlfremake/checkout.py to create the checkout script
"""
# Define variables
yml = yamlfile
name = yamlfile.split(".")[0]
run = execute
jobs = str(jobs)
pcheck = no_parallel_checkout

Expand All @@ -37,10 +65,16 @@ def checkout_create(yamlfile, platform, target, no_parallel_checkout, jobs, exec
plist = platform
tlist = target

# Combine model, compile, and platform yamls
# Default behavior - combine yamls / rewrite combined yaml
comb = cy.init_compile_yaml(yml,platform,target)
full_combined = cy.get_combined_compileyaml(comb)
# If force-checkout defined: re-combine model, compile, and platform yamls
if force_checkout:
print("Re-combine yaml files")
comb = cy.init_compile_yaml(yml,platform,target)
full_combined = cy.get_combined_compileyaml(comb)
else:
## If combined yaml exists, note message of its existence
## If combined yaml does not exist, combine model, compile, and platform yamls
combined = Path(f"combined-{name}.yaml")
full_combined = cy.combined_compile_existcheck(combined,yml,platform,target)
Copy link
Contributor

@uramirez8707 uramirez8707 Jan 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if the combined yaml exists, it should combined them again and compare them and output a warning if they are not the same and suggest the --force* options

For example, if you change something in your yaml and you forget to delete the combined yaml, fre-canopy is going to use the combined-yaml that already exist and won't do what you expect (I have done this sooooo many times :/)

This is what bronx outpust:

WARNING: The existing checkout script '/gpfs/f5/gfdl_f/scratch/Uriel.Ramirez/SPEAR_experiments_Q_2025.01-beta1/SPEAR_Q2025.01-beta1_nonsymMOM6_exec/src/checkout.csh' doesn't match checkout instructions in the XML file!
         If you need a fresh checkout, please rerun the fremake with the --force-checkout (-f) option.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with this 200%.

This is making me wonder though, why not go one step further and just not even write the combined yaml to a file?

I will admit, I never really understood why we combine the yamls and write it out in the first place, so maybe there's a better reason then I'm seeing.

But if the current fremake yamls (platform/compile/etc) are what we are going to be modifying and using in place of xmls, the combined yamls don't really need to exist as files, they can stay in memory. Otherwise, they just kinda get in the way of whatever yaml files the user specifies.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with both of you, this is great input!

@rem1776 - At first, I was trying to load the yamls and just have/use the dictionary it's parsed as, and then update/add to dictionaries in order to dump a combined yaml file with all the info needed. BUT, the main issue I was seeing here was from the reusable variables.

The yaml won't even load (it will give "undefined alias" issue) if there is a key that uses a reusable variable that isn't defined in fre_properties, these being name, platform, and target, and those also aren't defined in fre_properties because they can change (since they're click options that are passed in).

I think this is related to your confusion on why we even create these combined yamls. If there's a better way, I'm definitely up for it though.


## Get the variables in the model yaml
fre_vars = varsfre.frevars(full_combined)
Expand All @@ -65,29 +99,35 @@ def checkout_create(yamlfile, platform, target, no_parallel_checkout, jobs, exec

platform = model_yaml.platforms.getPlatformFromName(platform_name)

# ceate the source directory for the platform
# Create the source directory for the platform
if not platform["container"]:
src_dir = platform["modelRoot"] + "/" + fremake_yaml["experiment"] + "/src"
# if the source directory does not exist, it is created
if not os.path.exists(src_dir):
os.system("mkdir -p " + src_dir)
# if the checkout script does not exist, it is created
if not os.path.exists(src_dir+"/checkout.sh"):
fre_checkout = checkout.checkout("checkout.sh",src_dir)
fre_checkout.writeCheckout(model_yaml.compile.getCompileYaml(),jobs,pc)
fre_checkout.finish(model_yaml.compile.getCompileYaml(),pc)
# Make checkout script executable
os.chmod(src_dir+"/checkout.sh", 0o744)
print("\nCheckout script created in "+ src_dir + "/checkout.sh \n")
print("\nCreating checkout script...")
fre_checkout = baremetal_checkout_write_steps(model_yaml,src_dir,jobs,pc)

# Run the checkout script
if run:
if execute:
fre_checkout.run()
else:
return
else:
print("\nCheckout script PREVIOUSLY created in "+ src_dir + "/checkout.sh \n")
if run:
if force_checkout:
# Remove previous checkout
print("\nRemoving previously checkout script and checked out source code")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think rather than removing it you should back up the src and exec directory. This what bronx ouputs

WARNING: Since you've specified --force-compile (-F), existing compile and environment scripts have been renamed using timestamp '20250130.085825'
         New compile and environment scripts will be created...
         You can remove old scripts later by typing:
         rm -f /gpfs/f5/gfdl_f/scratch/Uriel.Ramirez/SPEAR_experiments_Q_2025.01-beta1/SPEAR_Q2025.01-beta1_nonsymMOM6_exec/ncrc5.intel23-classic-repro-openmp/exec/compile_SPEAR_Q2025.01-beta1_nonsymMOM6_exec.csh.20250130.085825
         rm -f /gpfs/f5/gfdl_f/scratch/Uriel.Ramirez/SPEAR_experiments_Q_2025.01-beta1/SPEAR_Q2025.01-beta1_nonsymMOM6_exec/ncrc5.intel23-classic-repro-openmp/exec/env.cshrc.20250130.085825

shutil.rmtree(src_dir)

# Create checkout script
print("Re-creating the checkout script...")
fre_checkout = baremetal_checkout_write_steps(model_yaml,src_dir,jobs,pc)
else:
print("\nCheckout script PREVIOUSLY created in "+ src_dir + "/checkout.sh \n")

if execute:
try:
subprocess.run(args=[src_dir+"/checkout.sh"], check=True)
except:
Expand All @@ -101,10 +141,21 @@ def checkout_create(yamlfile, platform, target, no_parallel_checkout, jobs, exec
src_dir = platform["modelRoot"] + "/" + fremake_yaml["experiment"] + "/src"
bld_dir = platform["modelRoot"] + "/" + fremake_yaml["experiment"] + "/exec"
tmp_dir = "tmp/"+platform_name
fre_checkout = checkout.checkoutForContainer("checkout.sh", src_dir, tmp_dir)
fre_checkout.writeCheckout(model_yaml.compile.getCompileYaml(),jobs,pc)
fre_checkout.finish(model_yaml.compile.getCompileYaml(),pc)
print("\nCheckout script created at " + tmp_dir + "/checkout.sh" + "\n")
if not os.path.exists(tmp_dir+"/checkout.sh"):
# Create the checkout script
print("Creating checkout script...")
container_checkout_write_steps(model_yaml,src_dir,tmp_dir,jobs,pc)
else:
if force_checkout:
# Remove the checkout script
print("\nRemoving previously made checkout script")
os.remove(tmp_dir+"/checkout.sh")

# Create the checkout script
print("Re-creating the checkout script...")
container_checkout_write_steps(model_yaml,src_dir,tmp_dir,jobs,pc)
else:
print("\nCheckout script PREVIOUSLY created in "+ tmp_dir + "/checkout.sh" + "\n")

if __name__ == "__main__":
checkout_create()
96 changes: 70 additions & 26 deletions fre/make/create_compile_script.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,55 @@
'''
TODO: make docstring
Create the compile script to compile model
'''
import os
import sys
import logging
from pathlib import Path
from multiprocessing.dummy import Pool
import subprocess

from .gfdlfremake import varsfre, yamlfre, targetfre, buildBaremetal
import fre.yamltools.combine_yamls as cy

def compile_create(yamlfile, platform, target, jobs, parallel, execute, verbose):
def compile_script_write_steps(yaml_obj,mkTemplate,src_dir,bld_dir,target,modules,modulesInit,jobs):
"""
Go through steps to create the compile script
"""
## Create a list of compile scripts to run in parallel
fremakeBuild = buildBaremetal.buildBaremetal(exp = yaml_obj["experiment"],
mkTemplatePath = mkTemplate,
srcDir = src_dir,
bldDir = bld_dir,
target = target,
modules = modules,
modulesInit = modulesInit,
jobs = jobs)
for c in yaml_obj['src']:
fremakeBuild.writeBuildComponents(c)
fremakeBuild.writeScript()

print(" Compile script created here: " + bld_dir + "/compile.sh" + "\n")
compile_script = f"{bld_dir}/compile.sh"

return compile_script

def compile_create(yamlfile,platform,target,jobs,parallel,execute,verbose,force_compile):
"""
Create the compile script
"""
# Define variables
yml = yamlfile
name = yamlfile.split(".")[0]
nparallel = parallel
jobs = str(jobs)

if verbose:
logging.basicCOnfig(level=logging.INFO)
logging.basicConfig(level=logging.INFO)
else:
logging.basicConfig(level=logging.ERROR)

srcDir="src"
checkoutScriptName = "checkout.sh"
src_dir="src"
checkout_script_name = "checkout.sh"
baremetalRun = False # This is needed if there are no bare metal runs

## Split and store the platforms and targets in a list
Expand All @@ -38,10 +64,10 @@ def compile_create(yamlfile, platform, target, jobs, parallel, execute, verbose)
full_combined = cy.combined_compile_existcheck(combined,yml,platform,target)

## Get the variables in the model yaml
freVars = varsfre.frevars(full_combined)
fre_vars = varsfre.frevars(full_combined)

## Open the yaml file and parse as fremakeYaml
modelYaml = yamlfre.freyaml(full_combined,freVars)
modelYaml = yamlfre.freyaml(full_combined,fre_vars)
fremakeYaml = modelYaml.getCompileYaml()

## Error checking the targets
Expand All @@ -60,31 +86,49 @@ def compile_create(yamlfile, platform, target, jobs, parallel, execute, verbose)

platform=modelYaml.platforms.getPlatformFromName(platformName)
## Make the bldDir based on the modelRoot, the platform, and the target
srcDir = platform["modelRoot"] + "/" + fremakeYaml["experiment"] + "/src"
src_dir = platform["modelRoot"] + "/" + fremakeYaml["experiment"] + "/src"
## Check for type of build
if platform["container"] is False:
baremetalRun = True
bldDir = platform["modelRoot"] + "/" + fremakeYaml["experiment"] + "/" + platformName + "-" + target.gettargetName() + "/exec"
os.system("mkdir -p " + bldDir)
## Create a list of compile scripts to run in parallel
fremakeBuild = buildBaremetal.buildBaremetal(exp = fremakeYaml["experiment"],
mkTemplatePath = platform["mkTemplate"],
srcDir = srcDir,
bldDir = bldDir,
target = target,
modules = platform["modules"],
modulesInit = platform["modulesInit"],
jobs = jobs)
for c in fremakeYaml['src']:
fremakeBuild.writeBuildComponents(c)
fremakeBuild.writeScript()
fremakeBuildList.append(fremakeBuild)
print("\nCompile script created at " + bldDir + "/compile.sh" + "\n")
bld_dir = platform["modelRoot"] + "/" + fremakeYaml["experiment"] + "/" + platformName + "-" + target.gettargetName() + "/exec"
os.system("mkdir -p " + bld_dir)
if not os.path.exists(bld_dir+"/compile.sh"):
print("\nCreating the compile script...")
fremakeBuild = compile_script_write_steps(yaml_obj = fremakeYaml,
mkTemplate = platform["mkTemplate"],
src_dir = src_dir,
bld_dir = bld_dir,
target = target,
modules = platform["modules"],
modulesInit = platform["modulesInit"],
jobs = jobs)
# Append the compile script created
fremakeBuildList.append(fremakeBuild)
else:
if force_compile:
# Remove compile script
os.remove(bld_dir + "/compile.sh")
# Re-create compile script
print("\nRe-creating the compile script...")
fremakeBuild = compile_script_write_steps(yaml_obj = fremakeYaml,
mkTemplate = platform["mkTemplate"],
src_dir = src_dir,
bld_dir = bld_dir,
target = target,
modules = platform["modules"],
modulesInit = platform["modulesInit"],
jobs = jobs)
# Append the returned compile script created
fremakeBuildList.append(fremakeBuild)
else:
print("Compile script PREVIOUSLY created here: " + bld_dir + "/compile.sh" + "\n")
# Append the compile script
fremakeBuildList.append(f"{bld_dir}/compile.sh")

if execute:
if baremetalRun:
pool = Pool(processes=nparallel) # Create a multiprocessing Pool
pool.map(buildBaremetal.fremake_parallel,fremakeBuildList) # process data_inputs iterable with pool
pool = Pool(processes=nparallel) # Create a multiprocessing Pool
pool.map(buildBaremetal.run,fremakeBuildList) # process data_inputs iterable with pool
else:
return

Expand Down
Loading
Loading