34 #include <boost/algorithm/string/regex.hpp>
35 #include <boost/interprocess/managed_shared_memory.hpp>
36 #include <boost/interprocess/sync/file_lock.hpp>
37 #include <boost/interprocess/sync/interprocess_condition.hpp>
38 #include <boost/interprocess/sync/interprocess_upgradable_mutex.hpp>
39 #include <boost/interprocess/sync/scoped_lock.hpp>
40 #include <boost/interprocess/sync/sharable_lock.hpp>
41 #include <boost/regex.hpp>
42 #include <boost/thread/thread_time.hpp>
44 #include <SimoxUtility/algorithm/string/string_tools.h>
53 #include "../../rapidxml/wrapper/RapidXmlReader.h"
56 #define SCRIPT_PATH "ArmarXCore/core/system/cmake/FindPackageX.cmake"
57 #define CACHE_PATH "/ArmarXCMakeCache_" + (getenv("USER") ? getenv("USER") : "DUMMY_USER")
66 char* homePathC = getenv(
"HOME");
75 std::shared_ptr<boost::interprocess::file_lock>
82 std::cout <<
"getFileLock( path = " << path <<
")" << std::endl;
84 if (!std::filesystem::exists(path))
88 std::cout <<
"path does not exist" << std::endl;
90 if (!std::filesystem::create_directories(path))
94 std::cout <<
"failed to create directories" << std::endl;
96 return std::shared_ptr<boost::interprocess::file_lock>();
99 path +=
"/" + lockName;
102 std::cout <<
"lock file = " << path << std::endl;
104 if (!std::filesystem::exists(path))
108 std::cout <<
"touch " << path << std::endl;
111 std::ofstream file(path);
116 std::cout <<
"build lock with " << path << std::endl;
118 return std::shared_ptr<boost::interprocess::file_lock>(
119 new boost::interprocess::file_lock(path.c_str()));
122 std::shared_ptr<boost::interprocess::file_lock>
126 std::shared_ptr<boost::interprocess::file_lock> lock(
getFileLock(name,
false));
136 const std::shared_ptr<boost::interprocess::file_lock>&
145 const std::shared_ptr<boost::interprocess::file_lock>&
157 static std::mutex mx;
162 std::shared_ptr<boost::interprocess::scoped_lock<boost::interprocess::file_lock>>;
170 new boost::interprocess::scoped_lock<boost::interprocess::file_lock>(
171 *
CMakeFileLock(), boost::get_system_time() + boost::posix_time::milliseconds(50)));
172 while (!lockPtr->owns())
174 lockPtr->timed_lock(boost::get_system_time() + boost::posix_time::milliseconds(50));
182 auto start = IceUtil::Time::now();
183 std::string path = std::filesystem::temp_directory_path().string() +
CACHE_PATH;
184 path +=
"/" + packageName;
185 if (!std::filesystem::exists(path))
192 const auto writeTime = std::filesystem::last_write_time(path);
193 const auto now = decltype(writeTime)::clock::now();
194 long age = std::chrono::duration_cast<std::chrono::seconds>(now - writeTime).count();
196 boost::interprocess::sharable_lock<boost::interprocess::file_lock> e_lock(
199 auto dura = (IceUtil::Time::now() - start).toMilliSecondsDouble();
202 ARMARX_INFO_S << packageName <<
" from cache locked for " << dura;
218 auto start = IceUtil::Time::now();
219 std::string path = std::filesystem::temp_directory_path().string() +
CACHE_PATH;
220 if (!std::filesystem::exists(path))
222 if (!std::filesystem::create_directories(path))
227 path = path +
"/" + packageName;
228 boost::interprocess::scoped_lock<boost::interprocess::file_lock> e_lock(*
CacheFileLock());
232 std::ofstream file(path);
233 file << packageContent;
236 auto dura = (IceUtil::Time::now() - start).toMilliSecondsDouble();
239 ARMARX_INFO_S << packageName <<
" update cache locked for " << dura;
244 boost::interprocess::interprocess_upgradable_mutex*
memoryMutex =
nullptr;
249 const std::filesystem::path& packagePath,
251 bool usePackagePathOnlyAsHint) :
252 found(false), packageName(
simox::alg::trim_copy(packageName))
254 if (this->packageName.empty())
256 ARMARX_WARNING <<
"CMakePackageFinder: Package name must not be empty";
258 static std::string scriptPath;
263 if (scriptPath.empty())
267 auto start = IceUtil::Time::now();
269 auto dura = (IceUtil::Time::now() - start);
271 if (dura.toMilliSeconds() > 10000)
273 ARMARX_INFO_S <<
"Cmakefinder for initial core search took long - Duration: "
274 << dura.toMilliSeconds();
280 <<
"Finding FindPackageX.cmake failed - trying again with different path";
293 auto start = IceUtil::Time::now();
294 std::string resultStr;
298 if (!packagePath.empty())
300 resultStr =
ExecCommand(
"cd " + tmpDir +
"; cmake -DPACKAGE=" + this->packageName +
301 " -DPACKAGEBUILDPATH" +
302 (usePackagePathOnlyAsHint ?
"Hint" :
"") +
"=" +
303 packagePath.string() +
" -P " + scriptPath,
309 resultStr =
ExecCommand(
"cd " + tmpDir +
"; cmake -DPACKAGE=" + this->packageName +
321 auto dura = (IceUtil::Time::now() - start);
323 if (dura.toMilliSeconds() > 10000)
325 ARMARX_INFO_S <<
"Cmakefinder took long for package " << packagePath
326 <<
" - Duration: " << dura.toMilliSeconds();
329 std::vector<std::string> resultList;
335 std::vector<std::string>
341 std::vector<std::string> result;
342 boost::split_regex(result, output, boost::regex(
"-I"));
344 for (
size_t i = 0; i < result.size(); i++)
346 simox::alg::trim(result[i]);
348 if (result[i].
empty())
350 result.erase(result.begin() + i);
363 auto start = IceUtil::Time::now();
367 std::stringstream
str;
369 <<
" -DLANGUAGE=CXX -DCOMPILER_ID=GNU -DMODE=LINK";
379 auto dura = (IceUtil::Time::now() - start).toMilliSecondsDouble();
395 auto start = IceUtil::Time::now();
401 start = IceUtil::Time::now();
405 std::stringstream
str;
406 str <<
"cd " + tmpDir +
";cmake --find-package -DNAME=" <<
packageName
407 <<
" -DLANGUAGE=CXX -DCOMPILER_ID=GNU -DMODE=COMPILE";
418 auto dura = (IceUtil::Time::now() - start).toMilliSecondsDouble();
436 auto start = IceUtil::Time::now();
439 command +=
" 2>/dev/null";
442 FILE* fp = popen(command.c_str(),
"r");
446 while (fgets(line,
sizeof line, fp))
451 result = pclose(fp) / 256;
452 auto dura = (IceUtil::Time::now() - start).toMilliSecondsDouble();
455 ARMARX_INFO_S <<
"ExecCommand took " << dura <<
" \n command: " << command;
460 std::vector<std::string>
463 std::vector<std::string> result;
464 using namespace std::filesystem;
472 const std::string envVar(*env);
473 ARMARX_DEBUG <<
"Retrieved environment variable " << envVar;
476 if (not(elements.size() == 2))
481 const std::string& envVarName = elements.front();
482 const std::string& envVarValue = elements.back();
486 const std::string
packageName = simox::alg::remove_suffix(envVarName,
"_DIR");
493 if (pckFinder.packageFound() && !pckFinder.getBuildDir().empty())
516 const std::map<std::string, std::string>&
525 std::map<std::string, std::string>::const_iterator it =
vars.find(varName);
527 if (it !=
vars.end())
535 std::vector<std::string>
538 auto depListString =
getVar(
"DEPENDENCIES");
539 std::vector<std::string> resultList =
armarx::Split(depListString,
";",
true,
true);
544 std::map<std::string, std::string>
548 auto depListString =
getVar(
"PACKAGE_DEPENDENCY_PATHS");
550 std::map<std::string, std::string> resultMap;
552 for (
auto& depPairString : resultList)
556 if (depPair.size() < 2)
561 resultMap[depPair.at(0)] = depPair.at(1);
569 std::string& varName,
570 std::string& content)
573 const boost::regex e(
"\\-\\- ([a-zA-Z0-9_]+):(.+)");
574 boost::match_results<std::string::const_iterator> what;
576 bool found = boost::regex_search(
input, what, e);
578 for (
size_t i = 1; i < what.size(); i++)
593 simox::alg::trim(varName);
594 simox::alg::trim(content);
603 std::vector<std::string>
608 for (
size_t i = 0; i < resultList.size(); i++)
610 simox::alg::trim(resultList[i]);
612 if (resultList[i].
empty())
614 resultList.erase(resultList.begin() + i);
633 std::vector<std::string>
644 const std::string tmpDir =
"/tmp";
645 std::string result = tmpDir;
646 char* username = getenv(
"USER");
649 std::string usernameString = std::string(username);
650 simox::alg::trim(usernameString);
651 result +=
"/armarxcmake-" + usernameString;
652 if (!std::filesystem::exists(result))
654 if (!std::filesystem::create_directories(result))
666 const boost::regex e(
"\\$C\\{([a-zA-Z0-9_\\-]+):([a-zA-Z0-9_\\-]+)\\}");
667 boost::match_results<std::string::const_iterator> what;
668 bool found = boost::regex_search(
string, what, e);
669 std::map<std::string, CMakePackageFinder> finders;
672 for (
size_t i = 1; i < what.size(); i += 3)
674 std::string
package = what[i];
675 auto it = finders.find(package);
676 if (it == finders.end())
680 .insert(std::make_pair(
685 std::string var = what[i + 1];
688 auto envVar = it->second.getVar(var);
689 string = boost::regex_replace(
string, e, std::string(envVar));
690 ARMARX_DEBUG <<
"Replacing '" << var <<
"' with '" << std::string(envVar) <<
"'";
699 return getVar(
"EXECUTABLE");
702 std::vector<std::string>
705 namespace fs = std::filesystem;
707 const fs::path componentReportFilename =
708 fs::path(
getBuildDir()) /
"component_executables_report.txt";
709 if (fs::exists(componentReportFilename))
711 std::ifstream componentReportFile(componentReportFilename);
712 if (componentReportFile.bad())
714 ARMARX_WARNING <<
"Could not load file: " << componentReportFilename;
718 const std::string content(std::istreambuf_iterator<char>{componentReportFile}, {});
723 if (
vars.count(
"EXECUTABLE") > 0)
729 <<
"/build/component_executables_report.txt` is generated properly and "
730 "EXECUTABLE variable (legacy).";