00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "CellMLToSharedLibraryConverter.hpp"
00030
00031 #include <sstream>
00032 #include <unistd.h>
00033 #include <sys/stat.h>
00034 #include <ctime>
00035
00036 #include "Exception.hpp"
00037 #include "ChasteBuildRoot.hpp"
00038 #include "PetscTools.hpp"
00039 #include "DynamicModelLoaderRegistry.hpp"
00040 #include "GetCurrentWorkingDirectory.hpp"
00041
00042 CellMLToSharedLibraryConverter::CellMLToSharedLibraryConverter(std::string component)
00043 : mComponentName(component)
00044 {
00045 }
00046
00047 DynamicCellModelLoader* CellMLToSharedLibraryConverter::Convert(const FileFinder& rFilePath,
00048 bool isCollective)
00049 {
00050 DynamicCellModelLoader* p_loader;
00051 std::string absolute_path = rFilePath.GetAbsolutePath();
00052
00053 if (!rFilePath.Exists())
00054 {
00055 EXCEPTION("Dynamically loadable cell model '" + absolute_path + "' does not exist.");
00056 }
00057
00058 size_t dot_position = absolute_path.find_last_of(".");
00059 if (dot_position == std::string::npos)
00060 {
00061 EXCEPTION("File does not have an extension: " + absolute_path);
00062 }
00063 std::string extension = absolute_path.substr(dot_position+1);
00064 if (extension == "cellml")
00065 {
00066
00067 size_t slash_position = absolute_path.find_last_of("/\\");
00068 assert(slash_position != std::string::npos);
00069 std::string folder = absolute_path.substr(0, slash_position+1);
00070 std::string leaf = absolute_path.substr(slash_position+1, dot_position-slash_position);
00071 std::string so_path = folder + "lib" + leaf + "so";
00072
00073 FileFinder so_file(so_path, RelativeTo::Absolute);
00074 if (!so_file.Exists() || rFilePath.IsNewerThan(so_file))
00075 {
00076 if (!isCollective)
00077 {
00078 EXCEPTION("Unable to convert .cellml to .so unless called collectively, due to possible race conditions.");
00079 }
00080 ConvertCellmlToSo(absolute_path, folder, leaf);
00081 }
00082
00083 p_loader = DynamicModelLoaderRegistry::Instance()->GetLoader(so_file);
00084 }
00085 else if (extension == "so")
00086 {
00087
00088 p_loader = DynamicModelLoaderRegistry::Instance()->GetLoader(rFilePath);
00089 }
00090 else
00091 {
00092 EXCEPTION("Unsupported extension '." + extension + "' of file '" + absolute_path + "'; must be .so or .cellml");
00093 }
00094
00095 return p_loader;
00096 }
00097
00098 void CellMLToSharedLibraryConverter::ConvertCellmlToSo(const std::string& rCellmlFullPath,
00099 const std::string& rCellmlFolder,
00100 const std::string& rModelLeafName)
00101 {
00102 std::string tmp_folder, build_folder;
00103 std::string old_cwd = GetCurrentWorkingDirectory();
00104 try
00105 {
00106
00107 if (PetscTools::AmMaster())
00108 {
00109
00110 std::stringstream folder_name;
00111 folder_name << "dynamic/tmp_" << getpid() << "_" << time(NULL);
00112 tmp_folder = std::string(ChasteBuildRootDir()) + mComponentName + "/" + folder_name.str();
00113 build_folder = std::string(ChasteBuildRootDir()) + mComponentName + "/build/" + ChasteBuildDirName() + "/" + folder_name.str();
00114 int ret = mkdir(tmp_folder.c_str(), 0700);
00115 if (ret != 0)
00116 {
00117 NEVER_REACHED;
00118 }
00119
00120 size_t dot_pos = rCellmlFullPath.rfind('.');
00121 std::string cellml_base = rCellmlFullPath.substr(0, dot_pos);
00122 EXPECT0(system, "cp " + cellml_base + "* " + tmp_folder);
00123
00124 std::string config_path = rCellmlFullPath.substr(0, rCellmlFullPath.length() - 7) + "-conf.xml";
00125 if (FileFinder(config_path, RelativeTo::Absolute).Exists())
00126 {
00127 EXPECT0(system, "cp " + config_path + " " + tmp_folder);
00128 }
00129
00130 EXPECT0(chdir, ChasteBuildRootDir());
00131
00132 EXPECT0(system, "scons dyn_libs_only=1 build=" + ChasteBuildType() + " " + tmp_folder);
00133 EXCEPT_IF_NOT(FileFinder(tmp_folder + "/lib" + rModelLeafName + "so", RelativeTo::Absolute).Exists());
00134
00135 EXPECT0(chdir, old_cwd);
00136
00137 EXPECT0(system, "cp " + tmp_folder + "/lib" + rModelLeafName + "so " + rCellmlFolder);
00138
00139 EXPECT0(system, "rm -r " + build_folder);
00140 EXPECT0(system, "rm -r " + tmp_folder);
00141 }
00142 }
00143 catch (Exception& e)
00144 {
00145 PetscTools::ReplicateException(true);
00146
00147 EXPECT0(system, "rm -rf " + build_folder);
00148 EXPECT0(system, "rm -r " + tmp_folder);
00149 EXPECT0(chdir, old_cwd);
00150 EXCEPTION("Conversion of CellML to Chaste shared object failed. Error was: " + e.GetMessage());
00151 }
00152
00153
00154 PetscTools::ReplicateException(false);
00155 }