def _make_model(self, log): """ Compile the generated c-code into an executable """ if os.name == 'nt': # Windows # Make model # add incremental build support for .c files makefile = open('{0}.makefile'.format(self.short_name)).read() makefile = makefile.replace('.PHONY: $(CFILES)', '# .PHONY: $(CFILES)') makefile = re.sub('^omc_main_target:', 'omc_main_target: {0}$(EXEEXT)\n{0}$(EXEEXT):'.format(self.short_name), makefile, flags=re.MULTILINE) makefile = makefile + """ %.o: %.c \t$(CC) -c $(CPPFLAGS) $(CFLAGS) -MMD -MP -MF $(<:.c=.d) $< -include $(CFILES:.c=.d) """ with open('Makefile'.format(self.short_name), 'wb') as makefile_out: makefile_out.write(makefile) # Add %OPENMODELICAHOME%\MinGW\bin to environment variables my_env = os.environ for path in (r'mingw\bin', # OpenModelica 1.9.1, 1.9.3 r'tools\msys\mingw32\bin', # OpenModelica 1.11.0 32bit r'tools\msys\mingw64\bin'): # OpenModelica 1.11.0 64bit env_var_mingw = os.path.join(os.getenv('OPENMODELICAHOME'), path) # META-3623 make sure this path gets resolved first (prepend rather than append). my_env["PATH"] = env_var_mingw + os.pathsep + my_env["PATH"] log.debug('Added "{0}" to beginning of env var PATH.'.format(env_var_mingw)) command = 'mingw32-make.exe -f Makefile omc_main_target' # compile the c-code t_stamp = time.time() try: subprocess_call(command, log, my_env) except subprocess.CalledProcessError as err: raise ModelicaCompilationError("Generated C-code from omc could not be compiled", sp_msg=err.returncode) self.make_time = time.time() - t_stamp elif os.name == 'posix': # Unix # make -f model_name.makefile command = "make -f {0}.makefile".format(self.short_name) t_stamp = time.time() try: subprocess_call(command, log) except subprocess.CalledProcessError as err: raise ModelicaCompilationError("Generated C-code from omc could not be compiled", sp_msg=err.returncode) self.make_time = time.time() - t_stamp
def _make_model(self, log): """ Compile the generated c-code into an executable """ if os.name == 'nt': # Windows # Make model # add incremental build support for .c files makefile = open('{0}.makefile'.format(self.short_name)).read() makefile = makefile.replace('.PHONY: $(CFILES)', '# .PHONY: $(CFILES)') makefile = re.sub('^omc_main_target:', 'omc_main_target: {0}$(EXEEXT)\n{0}$(EXEEXT):'.format(self.short_name), makefile, flags=re.MULTILINE) makefile = makefile + """ %.o: %.c \t$(CC) -c $(CPPFLAGS) $(CFLAGS) -MMD -MP -MF $(<:.c=.d) $< -include $(CFILES:.c=.d) """ with open('Makefile'.format(self.short_name), 'wb') as makefile_out: makefile_out.write(makefile) # Add %OPENMODELICAHOME%\MinGW\bin to environment variables env_var_mingw = os.path.join(os.getenv('OPENMODELICAHOME'), 'mingw', 'bin') my_env = os.environ # META-3623 make sure this path gets resolved first (prepend rather than append). my_env["PATH"] = env_var_mingw + os.pathsep + my_env["PATH"] log.debug('Added "{0}" to beginning of env var PATH.'.format(env_var_mingw)) command = 'mingw32-make.exe -f Makefile omc_main_target' # compile the c-code t_stamp = time.time() try: subprocess_call(command, log, my_env) except subprocess.CalledProcessError as err: raise ModelicaCompilationError("Generated C-code from omc could not be compiled", sp_msg=err.returncode) self.make_time = time.time() - t_stamp elif os.name == 'posix': # Unix # make -f model_name.makefile command = "make -f {0}.makefile".format(self.short_name) t_stamp = time.time() try: subprocess_call(command, log) except subprocess.CalledProcessError as err: raise ModelicaCompilationError("Generated C-code from omc could not be compiled", sp_msg=err.returncode) self.make_time = time.time() - t_stamp
def _translate_modelica_model(self, log, my_env): """ Call omc(.exe) to translate the modelica model into c-code. """ os.chdir(self.mo_dir) command = '"{0}" +q +s "{1}"'.format(os.path.join(self.tool_path, 'omc'), self.mos_file_name) # only recompile if there is a .mo file newer than the _init.xml file latest_mtime = -1 for root, dirs, files in os.walk('.'): for name in (f for f in files if f.endswith('.mo')): latest_mtime = max(os.stat(os.path.join(root, name)).st_mtime, latest_mtime) init_xml_name = os.path.join(self.mo_dir, self.short_name) + '_init.xml' if not os.path.isfile(init_xml_name) or os.stat(init_xml_name) < latest_mtime: t_stamp = time.time() try: return_string = subprocess_call(command, log, my_env) except subprocess.CalledProcessError as err: raise ModelicaCompilationError('OMC could not compile model.', sp_msg=err.returncode) self.translation_time = time.time() - t_stamp if os.path.exists(os.path.join(self.mo_dir, self.short_name) + '_init.xml'): self.model_is_compiled = True else: msg = 'Subprocess call with command = "{0}" returned with 0, but _init.xml does not '\ 'exist - something went wrong during translation of model.'.format(command) raise ModelicaCompilationError(msg, return_string) else: self.model_is_compiled = True os.chdir(self.working_dir)
def _generate_input_mat_file(self, log, my_env): """ Generates an input file for dymosim(.exe) containing simulation settings """ log.debug("Entered _generate_input_mat_file") self.input_mat = 'dsin.mat' # dymosim.exe -ib dsin.mat command = '{0} -ib {1}'.format(self.dymosim, self.input_mat) try: subprocess_call(command, log, my_env) except subprocess.CalledProcessError as err: raise ModelicaCompilationError("Could not generate dsin.mat", sp_msg=err.returncode)
def _translate_modelica_model(self, log, my_env): """ Call omc(.exe) to translate the modelica model into c-code. """ os.chdir(self.mo_dir) command = '"{0}" +q +s --std=3.3 "{1}"'.format(os.path.join(self.tool_path, 'omc'), self.mos_file_name) # only recompile if there is a .mo file newer than the _init.xml file latest_mtime = -1 for root, dirs, files in os.walk('.'): for name in (f for f in files if f.endswith('.mo')): latest_mtime = max(os.stat(os.path.join(root, name)).st_mtime, latest_mtime) init_xml_name = os.path.join(self.mo_dir, self.short_name) + '_init.xml' if not os.path.isfile(init_xml_name) or os.stat(init_xml_name) < latest_mtime: t_stamp = time.time() try: return_string = subprocess_call(command, log, my_env) except subprocess.CalledProcessError as err: raise ModelicaCompilationError('OMC could not compile model.', sp_msg=err.returncode) self.translation_time = time.time() - t_stamp if os.path.exists(os.path.join(self.mo_dir, self.short_name) + '_init.xml'): self.model_is_compiled = True else: msg = 'Subprocess call with command = "{0}" returned with 0, but _init.xml does not '\ 'exist - something went wrong during translation of model.'.format(command) raise ModelicaCompilationError(msg, return_string) else: self.model_is_compiled = True os.chdir(self.working_dir)
def simulate_model(self): """ Simulate model using current settings """ log = logging.getLogger() log.debug("Entered simulate_model") # create a .cmd file which will: # 1) run %JMODELICAHOME%\\setenv.bat and # 2) call a python script to simulate the model jmodelica_setenv_path = os.path.join(self.tool_path, 'setenv.bat') fmu_name = self.model_name.split('.')[-1] + '.fmu' with open(os.path.join('jmodelica_simulate.cmd'), 'wb') as file_out: lines = [r':: Use System Python (which should have access to JModelica) to compile the model', r'echo off', r'pushd %~dp0', r'call {0}'.format(jmodelica_setenv_path), r'"{0}" ..\scripts\jmodelica_simulate.py {1}'.format(self.system_python_path, fmu_name), r'popd'] file_out.write("\n".join(lines)) # set up environment such that the libraries are included #my_env = os.environ #if self.lib_package_paths: # my_env = self._setup_libs_env_vars() if os.path.isfile(self.simulate_failed_file): os.remove(self.simulate_failed_file) if os.path.isfile('j_simulate.log'): os.remove('j_simulate.log') t_start = time.time() try: return_string = subprocess_call(os.path.join('jmodelica_simulate.cmd'), log) log.debug(return_string) self.result_mat = self.model_name.replace('.', '_') + '_result.txt' if os.path.isfile(self.simulate_failed_file): raise ModelicaSimulationError("Simulation failed.") except subprocess.CalledProcessError as err: raise ModelicaSimulationError("Execution of jmodelica_simulate.cmd failed.", sp_msg=err.returncode) finally: if os.path.isfile('j_simulate.log'): with open('j_simulate.log', 'r') as f_in: log.info('\n'.join(f_in.readlines())) self.simulation_time = time.time() - t_start self.total_time = self.compilation_time + self.simulation_time return self.model_did_simulate
def _make_model(self, log): """ Compiles the generated c-code into an executable """ if os.name == 'nt': # Windows # Make model # Add %OPENMODELICAHOME%\MinGW\bin to environment variables env_var_mingw = os.path.join(os.getenv('OPENMODELICAHOME'), 'mingw', 'bin') my_env = os.environ # META-3623 make sure this path gets resolved first (prepend rather than append). my_env["PATH"] = env_var_mingw + os.pathsep + my_env["PATH"] log.debug('Added "{0}" to beginning of env var PATH.'.format(env_var_mingw)) command = 'mingw32-make.exe -f {0}.makefile'.format(self.short_name) # compile the c-code t_stamp = time.time() try: subprocess_call(command, log, my_env) except subprocess.CalledProcessError as err: raise ModelicaCompilationError("Generated C-code from omc could not be compiled", sp_msg=err.returncode) self.make_time = time.time() - t_stamp elif os.name == 'posix': # Unix # make -f model_name.makefile command = "make -f {0}.makefile".format(self.short_name) t_stamp = time.time() try: subprocess_call(command, log) except subprocess.CalledProcessError as err: raise ModelicaCompilationError("Generated C-code from omc could not be compiled", sp_msg=err.returncode) self.make_time = time.time() - t_stamp
def _print_revision_number(self, log): """ Gets the revision number of the omc-compiler """ log.debug("Entered _print_revision_number") command = '"{0}" +version'.format(os.path.join(self.tool_path, "omc")) try: return_str = subprocess_call(command, log) version = return_str.split('(') self.tool_version = version[0].strip() self.tool_version_number = version[1].strip().strip(')') except subprocess.CalledProcessError as err: raise ModelicaCompilationError("Could not call omc.", sp_msg=err.returncode)
def _translate_modelica_model(self, log, my_env): """ Calls omc(.exe) to translate the modelica model into c-code. """ os.chdir(self.mo_dir) command = '"{0}" +q +s "{1}"'.format(os.path.join(self.tool_path, 'omc'), self.mos_file_name) t_stamp = time.time() try: return_string = subprocess_call(command, log, my_env) except subprocess.CalledProcessError as err: raise ModelicaCompilationError('OMC could not compile model.', sp_msg=err.returncode) self.translation_time = time.time() - t_stamp if os.path.exists(os.path.join(self.mo_dir, self.short_name) + '_init.xml'): self.model_is_compiled = True else: msg = 'Subprocess call with command = "{0}" returned with 0, but _init.xml does not '\ 'exist - something went wrong during translation of model.'.format(command) raise ModelicaCompilationError(msg, return_string) # N.B. this is not used and thus not maintained if not self.working_dir == self.mo_dir: files_to_move = [self.short_name + '.c', self.short_name + '.makefile', self.short_name + '.o', self.short_name + '_functions.c', self.short_name + '_functions.h', self.short_name + '_init.xml', self.short_name + '_records.c', self.short_name + '_records.o', '_' + self.short_name + '.h'] for this_file in files_to_move: dst_file_name = os.path.join(self.working_dir, this_file) if os.path.exists(dst_file_name): # remove dst file if it already exists os.remove(dst_file_name) this_file = os.path.join(self.mo_dir, this_file) if os.path.exists(this_file): shutil.move(this_file, self.working_dir) os.chdir(self.working_dir)
def compile_model(self): """ Compile the model """ log = logging.getLogger() log.debug("Entered compile_model JModelica") # create a .cmd file which will: # 1) run %JMODELICAHOME%\\setenv.bat and # 2) call a python script to compile the model jmodelica_setenv_path = os.path.join(self.tool_path, 'setenv.bat') with open(os.path.join('jmodelica_compile.cmd'), 'wb') as file_out: lines = [r':: Use System Python (which should have access to JModelica) to compile the model', r'echo off', r'pushd %~dp0', r'call {0}'.format(jmodelica_setenv_path), r'"{0}" ..\scripts\jmodelica_compile.py {1}'.format(self.system_python_path, self.model_name), r'popd'] file_out.write("\n".join(lines)) if os.path.isfile(self.compile_failed_file): os.remove(self.compile_failed_file) if os.path.isfile('j_compile.log'): os.remove('j_compile.log') t_start = time.time() try: return_string = subprocess_call(os.path.join('jmodelica_compile.cmd'), log) log.debug(return_string) if os.path.isfile(self.compile_failed_file): raise ModelicaCompilationError("Compilation failed.") except subprocess.CalledProcessError as err: raise ModelicaCompilationError("Execution of jmodelica_compile.cmd failed.", sp_msg=err.returncode) finally: if os.path.isfile('j_compile.log'): with open('j_compile.log', 'r') as f_in: log.info('\n'.join(f_in.readlines())) self.compilation_time = time.time() - t_start return self.model_is_compiled
def _print_revision_number(self, log): """ Get the revision number of the omc-compiler. """ log.debug("Entered _print_revision_number") command = '"{0}" +version'.format(os.path.join(self.tool_path, "omc")) try: return_str = subprocess_call(command, log) version = return_str.split('(') self.tool_version = version[0].strip() if len(version) > 1: self.tool_version_number = version[1].strip().strip(')') else: # Around v.1.9.4 open-modelica changed version format string. # For example v1.9.4-dev-62-g0de2ae0 will now be under self.tool_version as is. self.tool_version_number = 'UNKNOWN' except subprocess.CalledProcessError as err: raise ModelicaCompilationError("Could not call omc.", sp_msg=err.returncode)
def _translate_and_compile(self, log, my_env): """ Translate modelica code into c-code and compile that code into executable """ log.debug("Entered _translate_and_compile") os.chdir(self.mo_dir) command = '' if os.name == 'nt': command = '"{0}" /nowindow {1}'.format(os.path.join(self.tool_path, 'Dymola.exe'), self.mos_file_name) my_env['PATH'] = my_env['PATH'].replace('"', '') # META-1507 Dymola may hang with a quote in the %PATH% elif os.name == 'posix': command = 'dymola /nowindow {0}'.format(self.mos_file_name) t_stamp = time.time() try: return_string = subprocess_call(command, log, my_env) except subprocess.CalledProcessError as err: raise ModelicaCompilationError("Execution of the mos-script failed.", sp_msg=err.returncode) self.compilation_time = time.time() - t_stamp # setup name for executable if os.name == 'nt': self.dymosim = 'dymosim.exe' elif os.name == 'posix': self.dymosim = './dymosim' my_env.update({"LD_LIBRARY_PATH": "/opt/dymola/bin/lib"}) try: with open('translationLog.txt', 'r') as f_in: translation_log = f_in.read() except IOError: translation_log = 'Warning, no translationLog.txt!' # make sure that dymosim(.exe) does exist if not os.path.exists(self.dymosim): msg = 'The sub process call with command "{0}" returned with 0, but {1} does not '\ 'exist.'.format(command, self.dymosim) log.error(translation_log) raise ModelicaCompilationError(msg, sp_msg=return_string) log.info(translation_log) self.model_is_compiled = True #os.remove(self.mos_file_name) # N.B. this is not used and thus not maintained if not self.working_dir == self.mo_dir: files_to_move = ['buildlog.txt', 'dsfinal.txt', 'dsin.txt', 'dslog.txt', 'dsmodel.c', 'dymosim.exp', 'dymosim.lib', 'dymosim.exe', 'request', 'status'] for this_file in files_to_move: dst_file_name = os.path.join(self.working_dir, this_file) if os.path.exists(dst_file_name): # remove dst file if it already exists os.remove(dst_file_name) this_file = os.path.join(self.mo_dir, this_file) if os.path.exists(this_file): shutil.move(this_file, self.working_dir) os.chdir(self.working_dir)
def _translate_and_compile(self, log, my_env): """ Translate modelica code into c-code and compile that code into executable """ log.debug("Entered _translate_and_compile") os.chdir(self.mo_dir) command = '' if os.name == 'nt': command = '"{0}" /nowindow {1}'.format( os.path.join(self.tool_path, 'Dymola.exe'), self.mos_file_name) my_env['PATH'] = my_env['PATH'].replace( '"', '') # META-1507 Dymola may hang with a quote in the %PATH% elif os.name == 'posix': command = 'dymola /nowindow {0}'.format(self.mos_file_name) t_stamp = time.time() try: return_string = subprocess_call(command, log, my_env) except subprocess.CalledProcessError as err: raise ModelicaCompilationError( "Execution of the mos-script failed.", sp_msg=err.returncode) self.compilation_time = time.time() - t_stamp # setup name for executable if os.name == 'nt': self.dymosim = 'dymosim.exe' elif os.name == 'posix': self.dymosim = './dymosim' my_env.update({"LD_LIBRARY_PATH": "/opt/dymola/bin/lib"}) try: with open('translationLog.txt', 'r') as f_in: translation_log = f_in.read() except IOError: translation_log = 'Warning, no translationLog.txt!' # make sure that dymosim(.exe) does exist if not os.path.exists(self.dymosim): msg = 'The sub process call with command "{0}" returned with 0, but {1} does not '\ 'exist.'.format(command, self.dymosim) log.error(translation_log) raise ModelicaCompilationError(msg, sp_msg=return_string) log.info(translation_log) self.model_is_compiled = True #os.remove(self.mos_file_name) # N.B. this is not used and thus not maintained if not self.working_dir == self.mo_dir: files_to_move = [ 'buildlog.txt', 'dsfinal.txt', 'dsin.txt', 'dslog.txt', 'dsmodel.c', 'dymosim.exp', 'dymosim.lib', 'dymosim.exe', 'request', 'status' ] for this_file in files_to_move: dst_file_name = os.path.join(self.working_dir, this_file) if os.path.exists(dst_file_name): # remove dst file if it already exists os.remove(dst_file_name) this_file = os.path.join(self.mo_dir, this_file) if os.path.exists(this_file): shutil.move(this_file, self.working_dir) os.chdir(self.working_dir)