372 vector<shared_ptr<VuoModuleCache>> prerequisiteModuleCaches,
double &lastPrerequisiteModuleCacheRebuild,
374 const set<string> &dylibsToLinkTo,
const set<string> &frameworksToLinkTo,
const vector<string> &runPathSearchPaths,
377 string cacheDescription = getDescription();
379 std::unique_lock<std::mutex> statusLock(statusMutex);
383 if (! invalidated && (builtIn || lastRebuild >= lastPrerequisiteModuleCacheRebuild))
385 VDebugLog(
"No need to recheck %s.", cacheDescription.c_str());
386 lastPrerequisiteModuleCacheRebuild = lastRebuild;
392 VDebugLog(
"Checking if %s is up-to-date…", cacheDescription.c_str());
394 bool isCacheUpToDate =
true;
399 string manifestPath = getManifestPath(targetArch);
403 LockInfo *lockInfo = interprocessLockInfo[cacheDirectoryPath];
406 if (lockInfo->needsLock)
408 if (! lockInfo->dylibLockFile)
412 string lockFileName =
"dylib.lock";
418 fileForLocking = lockInfo->dylibLockFile;
420 VDebugLog(
"\tWarning: Couldn't lock for reading.");
426 if (! manifestFileExists)
428 if (shouldUseExistingCache)
429 throw VuoException(
"Trying to use the existing cache, but the cache manifest doesn't exist.",
false);
432 isCacheUpToDate =
false;
437 double lastRebuild_local = 0;
438 string dylibPath = builtIn ? getDylibPath(targetArch) : findLatestRevisionOfDylib(lastRebuild_local);
440 if (dylibPath.empty())
442 if (shouldUseExistingCache)
443 throw VuoException(
"Trying to use the existing cache, but the cache dylib doesn't exist.",
false);
445 dylibPath = getDylibPath();
451 isCacheUpToDate = lastRebuild_local >= lastPrerequisiteModuleCacheRebuild;
460 if (shouldUseExistingCache)
461 throw VuoException(
"Trying to use the existing cache, but the cache doesn't contain readable data.",
false);
463 isCacheUpToDate =
false;
470 bool usingExistingCache =
false;
472 if (isCacheUpToDate || shouldUseExistingCache)
476 if (shouldUseExistingCache)
477 usingExistingCache =
true;
482 if (isCacheUpToDate && ! usingExistingCache)
485 isCacheUpToDate =
false;
490 if (isCacheUpToDate && ! usingExistingCache)
495 while ((moduleInfo = i.next()))
499 isCacheUpToDate =
false;
508 if (isCacheUpToDate || usingExistingCache)
512 lastPrerequisiteModuleCacheRebuild = lastRebuild_local;
514 std::lock_guard<std::mutex> contentsLock(contentsMutex);
515 if (! currentRevision)
518 std::lock_guard<std::mutex> statusLock(statusMutex);
519 lastRebuild = lastRebuild_local;
528 if (! hasInterprocessLock)
529 throw VuoException(
"The cache file is out-of-date but can't be rebuilt because it's being used by another process. "
530 "If any composition windows are open from previous Vuo sessions, quit them. "
531 "If any processes whose names start with \"VuoComposition\" or one of your composition file names appear in Activity Monitor, force-quit them.",
536 lastPrerequisiteModuleCacheRebuild = ULONG_MAX;
539 std::lock_guard<std::mutex> contentsLock(contentsMutex);
542 currentRevision->disuse();
543 currentRevision =
nullptr;
552 std::lock_guard<std::mutex> statusLock(statusMutex);
556 auto rebuild = [
this, prerequisiteModuleCaches, expectedManifest, dylibsToLinkTo, frameworksToLinkTo, runPathSearchPaths, compiler, targetArch,
557 cacheDescription, manifestPath, fileForLocking]()
559 std::lock_guard<std::mutex> buildLock(buildMutex);
562 vector<shared_ptr<VuoModuleCacheRevision>> prerequisiteModuleCacheRevisions;
563 bool arePrerequisiteModuleCachesAvailable =
true;
564 for (shared_ptr<VuoModuleCache> other : prerequisiteModuleCaches)
566 shared_ptr<VuoModuleCacheRevision> revision = other->useCurrentRevision();
569 arePrerequisiteModuleCachesAvailable =
false;
573 prerequisiteModuleCacheRevisions.push_back(revision);
576 if (arePrerequisiteModuleCachesAvailable)
578 VUserLog(
"Rebuilding %s…", cacheDescription.c_str());
580 bool gotLockForWriting =
false;
583 std::lock_guard<std::mutex> contentsLock(contentsMutex);
585 string dylibPath = getDylibPath(targetArch);
588 linkerInputs.
addDependencies(expectedManifest.getContents(), {}, compiler);
592 for (shared_ptr<VuoModuleCacheRevision> revision : prerequisiteModuleCacheRevisions)
599 if (! gotLockForWriting)
600 throw VuoException(
"Couldn't upgrade the lock to writing.",
false);
603 pid << getpid() << endl;
608 string dir, file, ext;
612 compiler->link(tmpPath, linkerInputs,
true, runPathSearchPaths,
false, issues);
631 if (VuoCompiler::vuoFrameworkInProgressPath.empty())
632 VuoCompiler::adHocCodeSign(dylibPath);
635 expectedManifest.writeToFile(manifestPath);
639 VDebugLog(
"\tWarning: Couldn't downgrade the lock back to reading.");
643 std::lock_guard<std::mutex> statusLock(statusMutex);
654 if (gotLockForWriting)
656 VDebugLog(
"\tWarning: Couldn't downgrade the lock back to reading.");
658 VUserLog(
"Warning: Couldn't rebuild %s: %s", cacheDescription.c_str(), e.
what());
663 VDebugLog(
"Not rebuilding %s since one of the module caches it depends on is unavailable.", cacheDescription.c_str());
666 for (shared_ptr<VuoModuleCacheRevision> revision : prerequisiteModuleCacheRevisions)
670 std::unique_lock<std::mutex> lck(buildsInProgressMutex);
672 buildsInProgressCondition.notify_all();
679 std::lock_guard<std::mutex> lck(buildsInProgressMutex);
685 std::thread t(rebuild);
690 if (VuoCompiler::vuoFrameworkInProgressPath.empty())
691 VUserLog(
"Warning: Couldn't make %s available: %s", cacheDescription.c_str(), e.
what());
693 VUserLog(
"Warning: Couldn't create %s when generating built-in module caches: %s", cacheDescription.c_str(), e.
what());
695 lastPrerequisiteModuleCacheRebuild = ULONG_MAX;