#!/usr/bin/python # sim-build -- build the adcirc+swan distribution # # Michael Thomas # Center for Computation & Technology # Louisiana State University # import sys, os, shutil ############################################ ## APP SPECIFIC DEFINES ## # # Usage when (-h, --help) is used, this is the first line showing how to call the app # optionGroups which option groups from etc/options to import. common is always imported. App = "sim-build" Usage = "usage: %prog [--remotemachine] [options] ...." optionGroups = ['sim-build'] Purpose = "build adcirc+swan either locally or remotely" ############################################ ############################################ ## INIT ## if os.path.basename(sys.argv[0]) == App: rp = os.path.abspath(__file__) paths = rp.split(os.sep) paths.pop() paths.pop() global BASE_PATH BASE_PATH = os.sep.join(paths) sys.path.append(BASE_PATH) LIB_PATH = "%s%slib" % (BASE_PATH, os.sep) sys.path.append(LIB_PATH) from lib import * import libutil import restartlib from libutil import dprint ## FUNCTIONS ## known_commands = ['build'] usage_strings = { 'build':'build adcirc+swan either locally or remotely'} def buildUsageString(): global Usage cmdString = "%s\n\n\nAvailable Commands:\n" % Usage iString = [] for kk in known_commands: ss = " %-35s%s" % (kk, usage_strings[kk]) iString.append(ss) cmdString = "%s%s" % (cmdString, "\n".join(iString)) return cmdString def PrepConfiguration(configName): global SimEnvironment global SimLib global ConfigurationDatabase machineName = SimEnvironment.LocalMachine machineEntry = SimEnvironment.LocalMachineEntry make = DefineDatabase.SubAll(machineEntry.GetKey('make')) subfolders = [] configBase = SimLib.BuildPath([SimEnvironment.CONFIGS_PATH, configName]) if not(os.path.exists(configBase)): try: os.mkdir(configBase) except OSError: pass #SimLib.ExecuteCommand("mkdir %s" % configBase) for sub in subfolders: sf = SimLib.BuildPath([configBase, sub]) SimLib.ExecuteCommand("mkdir %s" % sf) compiler = OptionsManager.GetOption("compiler") propertiesFile = SimLib.BuildPath([configBase, "properties.ini"]) prop = restartlib.RestartProperties(SimEnvironment) prop.init(propertiesFile) prop.AddProperty("adcirc", "yes") prop.AddProperty("compiler", compiler) prop.Save() ## deal with submit script now storedSubmitScript = SimLib.BuildPath([configBase, "SubmitScript"]) hasStoredSubmitScript = os.path.exists(storedSubmitScript) # the submit script is entirely optional now. no submit script just means # submission is disabled. affect this change here. needSubmitScript = False if hasStoredSubmitScript == False: needSubmitScript = True if hasStoredSubmitScript == True and not(OptionsManager.RawOptionDefined("submitscript")): dprint("Use stored submit script: %s" % storedSubmitScript, True) submitscript = storedSubmitScript else: submitscript = SimLib.GetSubmitScript() if submitscript != None: sContents = SimLib.GetFileContents(submitscript) ssContents = SimLib.GetFileContents(storedSubmitScript) submitScriptOutdated = False if submitscript != None: if hasStoredSubmitScript == False or (sContents != ssContents): submitScriptOutdated = True if submitScriptOutdated == True: dprint("Updated script file for configuration %s" % configName, True) SimLib.RemoveFile("%s.old" % storedSubmitScript) SimLib.RenameFile(storedSubmitScript, "%s.old" % storedSubmitScript) shutil.copy(submitscript, storedSubmitScript) else: if not(hasStoredSubmitScript): dprint("Configuration %s has no submit script, and no script file was specified" % configName, True) sys.exit(1) else: dprint("Warning: empty submit script will disable submission", True) ## deal with run script now storedRunScript = SimLib.BuildPath([configBase, "RunScript"]) hasStoredRunScript = os.path.exists(storedRunScript) needRunScript = False if hasStoredRunScript == False: needRunScript = True if hasStoredRunScript == True and not(OptionsManager.RawOptionDefined("runscript")): dprint("Use stored run script: %s" % storedRunScript) runscript = storedRunScript else: runscript = SimLib.GetRunScript(False) dprint("RunScript is: %s" % runscript) if runscript == None: # use generic.sh by default runscript = SimLib.BuildPath([SimEnvironment.ETC_PATH, "runscripts", "generic.sh"]) dprint("Warning: empty runscript, using %s" % runscript, True) if runscript != None: sContents = SimLib.GetFileContents(runscript) ssContents = SimLib.GetFileContents(storedRunScript) runScriptOutdated = False if runscript != None: if hasStoredRunScript == False or (sContents != ssContents): runScriptOutdated = True if runScriptOutdated == True: dprint("Updated runscript file for configuration %s" % configName, True) SimLib.RemoveFile("%s.old" % storedRunScript) SimLib.RenameFile(storedRunScript, "%s.old" % storedRunScript) shutil.copy(runscript, storedRunScript) else: if not(hasStoredRunScript): dprint("Configuration %s has no run script, and no run script file was specified" % configName, True) sys.exit(1) else: dprint("Error: empty or missing run script", True) sys.exit(1) def GetConfigValue(prop, option): global OptionsManager value = OptionsManager.GetOption(option) if OptionsManager.IsNegated(option) == True: value = False elif OptionsManager.RawOptionDefined(option) == True: value = True else: if prop.HasProperty(option): value = libutil.CoerseBool(prop.GetProperty(option)) return value def BuildConfiguration(configName): global SimEnvironment global SimLib global ConfigurationDatabase global OptionsManager global DefineDatabase machineName = SimEnvironment.LocalMachine machineEntry = SimEnvironment.LocalMachineEntry make = "make" dprint("Building %s" % configName, True) # 1. make sure we're in APP_PATH+work config_dir = SimLib.BuildPath([SimEnvironment.CONFIGS_PATH, configName]) work_dir = SimLib.BuildPath([SimEnvironment.APP_PATH, "work"]) swan_dir = SimLib.BuildPath([SimEnvironment.APP_PATH, "swan"]) if not(os.path.exists(work_dir)): dprint("Error: ADCIRC+Swan work directory %s not present" % work_dir, True) sys.exit(1) if not(os.path.exists(swan_dir)): dprint("Error: ADCIRC+Swan swan directory %s not present" % swan_dir, True) sys.exit(1) os.chdir(work_dir) # fix a small problem. SimLib.ExecuteCommand("chmod +x config.guess") compiler = OptionsManager.GetOption("compiler") dprint("Using compiler profile: %s" % compiler, True) cflags_file = SimLib.BuildPath([work_dir, "cmplrflags.mk"]) cflags_file_bk = SimLib.BuildPath([work_dir, "cmplrflags.bk"]) if not(os.path.exists(cflags_file)): dprint("Error: the compiler flags file, cmplrflags.mk cannot be read", True) sys.exit(1) contents = SimLib.GetFileContents(cflags_file) DefineDatabase.AddReplacement("compiler", compiler) # make a backup of cmplrflags.mk first. try: shutil.copy(cflags_file, cflags_file_bk) except: dprint("Error: could not backup compiler flags file \"%s\"" % cflags_file, True) sys.exit(1) SimLib.WriteContents(cflags_file, DefineDatabase.SubAll(contents)) make_clean_clobber = "make clean && make clobber" SimLib.ExecuteCommand(make_clean_clobber) # padcirc MakeTarget("padcirc") # config os.chdir(swan_dir) SimLib.ExecuteCommand(make_clean_clobber) SimLib.ExecuteCommand("%s config" % make) macro_file = SimLib.BuildPath([swan_dir, "macros.inc"]) if not(os.path.exists(macro_file)): dprint("Error: could not access swan macros.inc file \"%s\"" % macro_file, True) sys.exit(1) DefineDatabase.Reset() DefineDatabase.AddSubstitution("O_DIR", "../work/odir4") SimLib.WriteContents(macro_file, DefineDatabase.SubAll(SimLib.GetFileContents(macro_file))) # adcswan # padcswan os.chdir(swan_dir) SimLib.ExecuteCommand(make_clean_clobber) os.chdir(work_dir) MakeTarget("adcswan") # padcswan os.chdir(swan_dir) SimLib.ExecuteCommand(make_clean_clobber) # padcswan # adcirc # adcprep os.chdir(work_dir) targets = ['padcswan', 'adcirc', 'adcprep'] for target in targets: MakeTarget(target) # now, lets hard link all our executables into the configs/ folder. targets = ['adcirc', 'adcprep', 'adcswan', 'padcirc', 'padcswan'] for target in targets: target_from = SimLib.BuildPath([work_dir, target]) target_to = SimLib.BuildPath([config_dir, target]) os.link(target_from, target_to) def MakeTarget(target): global SimEnvironment global DefineDatabase machineName = SimEnvironment.LocalMachine machineEntry = SimEnvironment.LocalMachineEntry make = "make" if SimLib.ExecuteCommand("%s %s" % (make, target)) != 0: dprint("Error: compilation of %s failed." % target, True) sys.exit(1) def BuildVirtual(configName): global OptionsManager global ConfigurationDatabase global SimLib global DefineDatabase global SimEnvironment dprint("Building virtual config %s" % configName, True) if not(OptionsManager.HasOption("virtual-executable")): dprint("Error, virtual executable is not set", True) sys.exit(1) vexe = OptionsManager.GetOption("virtual-executable") if not(os.path.exists(vexe)): dprint("Error, virtual executable %s does not exist or is not readable" % vexe, True) sys.exit(1) newvpath = SimLib.BuildPath([SimEnvironment.EXE_PATH, "cactus_%s" % configName]) dprint("Copying virtual executable from %s to %s" % (vexe, newvpath), True) shutil.copy(vexe, newvpath) def RemoteBuild(machineName): global SimEnvironment RemoteEnvironment = simremote.RemoteEnvironment(SimEnvironment) RemoteEnvironment.init(machineName) RemoteEnvironment.ExecuteSameCommand(parrotArguments=True, stripArguments=['remotemachine']) def CommandDispatch(): global SimEnvironment global OptionsManager global known_commands if SimEnvironment.COMMAND == None: command = OptionsManager.args.pop(0) else: command = SimEnvironment.COMMAND if command == OptionsManager.args[0]: OptionsManager.args.pop(0) if command not in known_commands: OptionsManager.args.insert(0, command) command_build() return dprint("Executing command: %s" % command) exec("command_%s()" % command) ############################### MAIN ############################### def generate_new_mpi_path(MPIPATH, key): env = os.environ[key] parts = env.split(":") newpath = list() newpath.append(MPIPATH) for part in parts: if part.count("mvapich") > 0: continue else: newpath.append(part) return ":".join(newpath) def command_build(): global OptionsManager global ConfigurationDatabase global SimLib global DefineDatabase global SimEnvironment machineName = SimEnvironment.LocalMachine machineEntry = SimEnvironment.LocalMachineEntry req_keys = ['user', 'email', 'make', 'mpi'] SimLib.VerifyKeys(machineEntry, req_keys) #lets figure out our mvapich2 version that's loaded. MPIPATH = machineEntry.mpi os.environ['PATH'] = generate_new_mpi_path("%s/bin" % MPIPATH, "PATH") os.environ['LD_LIBRARY_PATH'] = generate_new_mpi_path("%s/lib" % MPIPATH, "LD_LIBRARY_PATH") #dprint("PATH: %s" % os.environ['PATH']) #dprint("LD_LIBRARY_PATH: %s" % os.environ['LD_LIBRARY_PATH']) mpiversion = SimLib.ExecuteCommand("which mpif90", True) dprint("Using MPIF90: %s" % mpiversion, libutil.ALWAYS_PRINT) configList = OptionsManager.args if len(configList) == 0: configList = [SimLib.GetDefaultConfiguration()] for config in configList: dprint("Using configuration: %s" % config, True) user = machineEntry.GetKey("user") email = machineEntry.GetKey("email") DefineDatabase.Set('USER', user) DefineDatabase.Set('EMAIL', email) make = DefineDatabase.SubAll(machineEntry.GetKey('make')) simpath = SimEnvironment.BASE_PATH appDir = SimEnvironment.APP_PATH dprint("App Directory: %s" % appDir) if os.getcwd() != appDir: dprint("Warning: Current Working directory does not match adcirc+swan sourcetree, changing to %s" % appDir) os.chdir(appDir) for config in configList: PrepConfiguration(config) if OptionsManager.GetOption('virtual') == False: BuildConfiguration(config) else: BuildVirtual(config) def main(env): global OptionsManager global ConfigurationDatabase global SimLib global DefineDatabase global SimEnvironment SimEnvironment = env OptionsManager = SimEnvironment.OptionsManager ConfigurationDatabase = SimEnvironment.ConfigurationDatabase SimLib = SimEnvironment.SimLib DefineDatabase = SimEnvironment.DefineDatabase SimEnvironment.RequireMachine() ############################################ if os.path.basename(SimEnvironment.EXECUTABLE) == App: dprint("sim-build: build adcirc+swan with the specified configuration name(s)\n", True) dprint("defs: %s" % SimEnvironment.cdb) if SimEnvironment.udb != None: dprint("defs.local: %s" % SimEnvironment.udb) print # make sure our configs directory is created try: os.mkdir(SimEnvironment.CONFIGS_PATH) except OSError: pass if SimEnvironment.APP_PATH == None: dprint("Error: cannot proceed with an unknown APP_PATH", True) sys.exit(1) if OptionsManager.HasOption("remotemachine"): remoteMachine = OptionsManager.GetOption("remotemachine") dprint("Building for remote machine: %s" % remoteMachine, True) RemoteBuild(remoteMachine) return # get our modes of compilation if len(OptionsManager.args) > 0: if OptionsManager.args[0] == 'build': OptionsManager.args.pop(0) else: OptionsManager.args.append('build') CommandDispatch() # only run if you are App if os.path.basename(sys.argv[0]) == App: global SimEnvironment SimEnvironment = simenv.SimEnvironment(BASE_PATH, os.path.abspath(sys.argv[0])) SimEnvironment.initApp(usageString=buildUsageString(), optionGroups=optionGroups) main(SimEnvironment)