1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "dynamicCode.H"
27 #include "dynamicCodeContext.H"
28 #include "stringOps.H"
31 #include "OSspecific.H"
32 #include "dictionary.H"
34 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
36 int Foam::dynamicCode::allowSystemOperations
38 Foam::debug::infoSwitch("allowSystemOperations", 0)
42 const Foam::word Foam::dynamicCode::codeTemplateEnvName
43 = "FOAM_CODE_TEMPLATES";
45 const Foam::fileName Foam::dynamicCode::codeTemplateDirName
46 = "codeTemplates/dynamicCode";
48 const char* const Foam::dynamicCode::libTargetRoot =
49 "LIB = $(PWD)/../platforms/$(WM_OPTIONS)/lib/lib";
51 const char* const Foam::dynamicCode::topDirName = "dynamicCode";
54 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
56 void Foam::dynamicCode::checkSecurity
59 const dictionary& dict
62 if (isAdministrator())
68 ) << "This code should not be executed by someone with administrator"
69 << " rights due to security reasons." << nl
70 << "(it writes a shared library which then gets loaded "
72 << exit(FatalIOError);
75 if (!allowSystemOperations)
81 ) << "Loading a shared library using case-supplied code is not"
82 << " enabled by default" << nl
83 << "because of security issues. If you trust the code you can"
84 << " enable this" << nl
85 << "facility be adding to the InfoSwitches setting in the system"
86 << " controlDict:" << nl << nl
87 << " allowSystemOperations 1" << nl << nl
88 << "The system controlDict is either" << nl << nl
89 << " ~/.OpenFOAM/$WM_PROJECT_VERSION/controlDict" << nl << nl
91 << " $WM_PROJECT_DIR/etc/controlDict" << nl
93 << exit(FatalIOError);
98 Foam::word Foam::dynamicCode::libraryBaseName(const fileName& libPath)
100 word libName(libPath.name(true));
101 libName.erase(0, 3); // remove leading 'lib' from name
107 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
109 void Foam::dynamicCode::copyAndFilter
113 const HashTable<string>& mapping
120 "dynamicCode::copyAndFilter()"
122 ) << "Failed opening for reading " << is.name()
130 "dynamicCode::copyAndFilter()"
132 ) << "Failed writing " << os.name()
136 // Copy file while rewriting $VARS and ${VARS}
142 // expand according to mapping
143 // expanding according to env variables might cause too many
145 stringOps::inplaceExpand(line, mapping);
146 os.writeQuoted(line, false) << nl;
152 bool Foam::dynamicCode::resolveTemplates
154 const UList<fileName>& templateNames,
155 DynamicList<fileName>& resolvedFiles,
156 DynamicList<fileName>& badFiles
159 // try to get template from FOAM_CODESTREAM_TEMPLATES
160 const fileName templateDir(Foam::getEnv(codeTemplateEnvName));
163 forAll(templateNames, fileI)
165 const fileName& templateName = templateNames[fileI];
168 if (!templateDir.empty() && isDir(templateDir))
170 file = templateDir/templateName;
171 if (!isFile(file, false))
177 // not found - fallback to ~OpenFOAM expansion
180 file = findEtcFile(codeTemplateDirName/templateName);
185 badFiles.append(templateName);
190 resolvedFiles.append(file);
198 bool Foam::dynamicCode::writeCommentSHA1(Ostream& os) const
200 const bool hasSHA1 = filterVars_.found("SHA1sum");
204 os << "/* dynamicCode:\n * SHA1 = ";
205 os.writeQuoted(filterVars_["SHA1sum"], false) << "\n */\n";
212 bool Foam::dynamicCode::createMakeFiles() const
215 if (compileFiles_.empty())
220 const fileName dstFile(this->codePath()/"Make/files");
223 mkDir(dstFile.path());
225 OFstream os(dstFile);
226 //Info<< "Writing to " << dstFile << endl;
231 "dynamicCode::createMakeFiles()"
233 ) << "Failed writing " << dstFile
237 writeCommentSHA1(os);
239 // Write compile files
240 forAll(compileFiles_, fileI)
242 os.writeQuoted(compileFiles_[fileI], false) << nl;
246 << libTargetRoot << codeName_.c_str() << nl;
252 bool Foam::dynamicCode::createMakeOptions() const
254 // Create Make/options
255 if (compileFiles_.empty() || makeOptions_.empty())
260 const fileName dstFile(this->codePath()/"Make/options");
263 mkDir(dstFile.path());
265 OFstream os(dstFile);
266 //Info<< "Writing to " << dstFile << endl;
271 "dynamicCode::createMakeOptions()"
273 ) << "Failed writing " << dstFile
277 writeCommentSHA1(os);
278 os.writeQuoted(makeOptions_, false) << nl;
284 bool Foam::dynamicCode::writeDigest(const SHA1Digest& sha1) const
286 const fileName file = digestFile();
290 sha1.write(os, true) << nl;
296 bool Foam::dynamicCode::writeDigest(const std::string& sha1) const
298 const fileName file = digestFile();
303 os.writeQuoted(sha1, false) << nl;
309 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
311 Foam::dynamicCode::dynamicCode(const word& codeName, const word& codeDirName)
313 codeRoot_(stringOps::expand("$FOAM_CASE")/topDirName),
314 libSubDir_(stringOps::expand("platforms/$WM_OPTIONS/lib")),
316 codeDirName_(codeDirName)
318 if (codeDirName_.empty())
320 codeDirName_ = codeName_;
327 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
329 Foam::fileName Foam::dynamicCode::codeRelPath() const
331 return topDirName/codeDirName_;
335 Foam::fileName Foam::dynamicCode::libRelPath() const
337 return codeRelPath()/libSubDir_/"lib" + codeName_ + ".so";
341 void Foam::dynamicCode::clear()
343 compileFiles_.clear();
345 createFiles_.clear();
347 filterVars_.set("typeName", codeName_);
348 filterVars_.set("SHA1sum", SHA1Digest().str());
350 // provide default Make/options
357 void Foam::dynamicCode::reset
359 const dynamicCodeContext& context
363 setFilterContext(context);
367 void Foam::dynamicCode::addCompileFile(const fileName& name)
369 compileFiles_.append(name);
373 void Foam::dynamicCode::addCopyFile(const fileName& name)
375 copyFiles_.append(name);
379 void Foam::dynamicCode::addCreateFile
381 const fileName& name,
382 const string& contents
385 createFiles_.append(fileAndContent(name, contents));
389 void Foam::dynamicCode::setFilterContext
391 const dynamicCodeContext& context
394 filterVars_.set("localCode", context.localCode());
395 filterVars_.set("code", context.code());
396 filterVars_.set("codeInclude", context.include());
397 filterVars_.set("SHA1sum", context.sha1().str());
401 void Foam::dynamicCode::setFilterVariable
404 const std::string& value
407 filterVars_.set(key, value);
411 void Foam::dynamicCode::setMakeOptions(const std::string& content)
413 makeOptions_ = content;
417 bool Foam::dynamicCode::copyOrCreateFiles(const bool verbose) const
421 Info<< "Creating new library in " << this->libRelPath() << endl;
424 const label nFiles = compileFiles_.size() + copyFiles_.size();
426 DynamicList<fileName> resolvedFiles(nFiles);
427 DynamicList<fileName> badFiles(nFiles);
429 // resolve template, or add to bad-files
430 resolveTemplates(compileFiles_, resolvedFiles, badFiles);
431 resolveTemplates(copyFiles_, resolvedFiles, badFiles);
433 if (!badFiles.empty())
437 "dynamicCode::copyFilesContents(..)"
438 ) << "Could not find the code template(s): "
440 << "Under the $" << codeTemplateEnvName
441 << " directory or via via the ~OpenFOAM/"
442 << codeTemplateDirName << " expansion"
449 const fileName outputDir = this->codePath();
455 forAll(resolvedFiles, fileI)
457 const fileName& srcFile = resolvedFiles[fileI];
458 const fileName dstFile(outputDir/srcFile.name());
460 IFstream is(srcFile);
461 //Info<< "Reading from " << is.name() << endl;
466 "dynamicCode::copyFilesContents(const fileName&)"
468 ) << "Failed opening " << srcFile
472 OFstream os(dstFile);
473 //Info<< "Writing to " << dstFile.name() << endl;
478 "dynamicCode::copyFilesContents(const fileName&)"
480 ) << "Failed writing " << dstFile
484 // Copy lines while expanding variables
485 copyAndFilter(is, os, filterVars_);
490 forAll(createFiles_, fileI)
492 const fileName dstFile
494 outputDir/stringOps::expand(createFiles_[fileI].first())
497 mkDir(dstFile.path());
498 OFstream os(dstFile);
499 //Info<< "Writing to " << createFiles_[fileI].first() << endl;
504 "dynamicCode::copyOrCreateFiles()"
506 ) << "Failed writing " << dstFile
509 os.writeQuoted(createFiles_[fileI].second(), false) << nl;
513 // Create Make/files + Make/options
517 writeDigest(filterVars_["SHA1sum"]);
523 bool Foam::dynamicCode::wmakeLibso() const
525 const Foam::string wmakeCmd("wmake -s libso " + this->codePath());
526 Info<< "Invoking " << wmakeCmd << endl;
528 if (Foam::system(wmakeCmd))
539 bool Foam::dynamicCode::upToDate(const SHA1Digest& sha1) const
541 const fileName file = digestFile();
543 if (!exists(file, false) || SHA1Digest(IFstream(file)()) != sha1)
552 bool Foam::dynamicCode::upToDate(const dynamicCodeContext& context) const
554 return upToDate(context.sha1());
558 // ************************************************************************* //