11 #include <sys/param.h>
15 #include <CoreFoundation/CoreFoundation.h>
48 map<string, VuoFileUtilities::File *> VuoCompiler::Environment::moduleCacheFileForLocking;
49 dispatch_queue_t VuoCompiler::Environment::moduleCacheBuildingQueue = dispatch_queue_create(
"org.vuo.compiler.cache", NULL);
50 const string VuoCompiler::Environment::pidCacheDirPrefix =
"pid-";
51 dispatch_queue_t VuoCompiler::environmentQueue = dispatch_queue_create(
"org.vuo.compiler.environment", NULL);
52 vector< vector<VuoCompiler::Environment *> > VuoCompiler::sharedEnvironments;
53 map<string, vector<VuoCompiler::Environment *> > VuoCompiler::environmentsForCompositionFamily;
54 dispatch_group_t VuoCompiler::moduleSourceCompilersExist = dispatch_group_create();
55 string VuoCompiler::vuoFrameworkInProgressPath;
65 struct rlimit rl{OPEN_MAX, OPEN_MAX};
66 getrlimit(RLIMIT_NOFILE, &rl);
67 rl.rlim_cur =
MIN(OPEN_MAX, rl.rlim_max);
68 if (setrlimit(RLIMIT_NOFILE, &rl))
69 VUserLog(
"Warning: Couldn't set open-files limit: %s", strerror(errno));
72 llvmQueue = dispatch_queue_create(
"org.vuo.compiler.llvm", NULL);
75 llvm::InitializeNativeTarget();
88 Module module(
"", getGlobalContext());
107 VuoCompiler::ModuleInfo::ModuleInfo(Environment *environment,
const string &searchPath,
const string &relativePath,
108 bool isSourceFile,
bool isSubcomposition)
111 initialize(environment, searchPath, file, isSourceFile, isSubcomposition);
117 VuoCompiler::ModuleInfo::ModuleInfo(Environment *environment,
const string &searchPath,
VuoFileUtilities::File *file,
118 bool isSourceFile,
bool isSubcomposition)
120 initialize(environment, searchPath, file, isSourceFile, isSubcomposition);
126 void VuoCompiler::ModuleInfo::initialize(Environment *environment,
const string &searchPath,
VuoFileUtilities::File *file,
127 bool isSourceFile,
bool isSubcomposition)
129 this->environment = environment;
130 this->searchPath = searchPath;
133 sourceCodeOverridden =
false;
144 loading = dispatch_group_create();
147 if (isSubcomposition)
161 VuoCompiler::ModuleInfo::~ModuleInfo(
void)
170 dispatch_release(loading);
173 VuoCompiler::Environment * VuoCompiler::ModuleInfo::getEnvironment(
void)
const
178 string VuoCompiler::ModuleInfo::getSearchPath(
void)
const
183 string VuoCompiler::ModuleInfo::getModuleKey(
void)
const
193 string VuoCompiler::ModuleInfo::getSourceCode(
void)
const
198 void VuoCompiler::ModuleInfo::setSourceCode(
const string &sourceCode)
200 this->sourceCode = sourceCode;
203 void VuoCompiler::ModuleInfo::revertSourceCode(
void)
208 bool VuoCompiler::ModuleInfo::isSourceCodeOverridden(
void)
const
210 return sourceCodeOverridden;
213 void VuoCompiler::ModuleInfo::setSourceCodeOverridden(
bool overridden)
215 sourceCodeOverridden = overridden;
218 bool VuoCompiler::ModuleInfo::isNewerThan(ModuleInfo *other)
const
220 return lastModified > other->lastModified;
223 bool VuoCompiler::ModuleInfo::isNewerThan(
unsigned long ageInSeconds)
const
225 return lastModified > ageInSeconds;
228 bool VuoCompiler::ModuleInfo::isOlderThan(
unsigned long ageInSeconds)
const
230 return lastModified < ageInSeconds;
233 void VuoCompiler::ModuleInfo::setLastModifiedToNow(
void)
236 gettimeofday(&t, NULL);
237 lastModified = t.tv_sec;
240 set<string> VuoCompiler::ModuleInfo::getContainedNodeClasses(
void)
const
242 return containedNodeClasses;
245 bool VuoCompiler::ModuleInfo::getAttempted(
void)
const
250 void VuoCompiler::ModuleInfo::setAttempted(
bool attempted)
252 this->attempted = attempted;
255 dispatch_group_t VuoCompiler::ModuleInfo::getLoadingGroup(
void)
const
260 void VuoCompiler::ModuleInfo::dump()
const
262 fprintf(stderr,
"module %s:\n"
263 "\tloadingGroup=%p\n"
268 "\tsourceCodeOverridden=%d\n"
270 "\tcontainedNodeClasses:\n",
275 environment->getCompiledModuleCachePath().c_str(),
279 sourceCodeOverridden,
281 for (
auto i: containedNodeClasses)
282 fprintf(stderr,
"\t\t%s\n", i.c_str());
285 VuoCompiler::DependencyGraphVertex * VuoCompiler::DependencyGraphVertex::vertexForDependency(
const string &dependency,
VuoDirectedAcyclicGraph *graph)
289 return dynamic_cast<DependencyGraphVertex *>(v);
291 DependencyGraphVertex *vv =
new DependencyGraphVertex();
292 vv->dependency = dependency;
293 vv->environment = NULL;
294 vv->compatible =
true;
298 string VuoCompiler::DependencyGraphVertex::getDependency(
void)
303 VuoCompiler::Environment * VuoCompiler::DependencyGraphVertex::getEnvironment(
void)
308 void VuoCompiler::DependencyGraphVertex::setEnvironment(Environment *environment)
310 this->environment = environment;
313 bool VuoCompiler::DependencyGraphVertex::isCompatible(
void)
318 void VuoCompiler::DependencyGraphVertex::setCompatible(
bool compatible)
320 this->compatible = compatible;
323 string VuoCompiler::DependencyGraphVertex::key(
void)
333 VuoCompiler::ModuleInfoIterator::ModuleInfoIterator(map<
string, map<string, ModuleInfo *> > *allModuleInfos)
335 this->allModuleInfos = allModuleInfos;
336 hasSearchModuleKeys =
false;
345 VuoCompiler::ModuleInfoIterator::ModuleInfoIterator(map<
string, map<string, ModuleInfo *> > *allModuleInfos,
const set<string> &searchModuleKeys)
347 this->allModuleInfos = allModuleInfos;
348 this->searchModuleKeys = searchModuleKeys;
349 hasSearchModuleKeys =
true;
358 void VuoCompiler::ModuleInfoIterator::initialize(
void)
360 currSearchPath = allModuleInfos->begin();
361 hasCurrModuleKey =
false;
369 VuoCompiler::ModuleInfo * VuoCompiler::ModuleInfoIterator::next(
void)
371 for ( ; currSearchPath != allModuleInfos->end(); ++currSearchPath)
373 if (! hasCurrModuleKey)
375 currModuleKey = currSearchPath->second.begin();
376 hasCurrModuleKey =
true;
379 for ( ; currModuleKey != currSearchPath->second.end(); ++currModuleKey)
381 if (! hasSearchModuleKeys || searchModuleKeys.find(currModuleKey->first) != searchModuleKeys.end())
383 ModuleInfo *moduleInfo = currModuleKey->second;
389 hasCurrModuleKey =
false;
398 VuoCompiler::Environment::Environment(
void)
400 compilersToNotifyQueue = dispatch_queue_create(
"org.vuo.compiler.notify", 0);
401 moduleSearchPathContentsChangedQueue = dispatch_queue_create(
"org.vuo.compiler.watch", 0);
402 isModuleCacheableDataDirty =
false;
403 isModuleCacheInitialized =
false;
404 isModuleCacheAvailable =
false;
413 VuoCompiler::Environment::~Environment(
void)
415 stopWatchingModuleSearchPaths();
416 dispatch_sync(moduleSearchPathContentsChangedQueue, ^{});
418 dispatch_release(moduleSearchPathContentsChangedQueue);
419 dispatch_release(compilersToNotifyQueue);
421 for (map<string, VuoCompilerNodeClass *>::iterator i = nodeClasses.begin(); i != nodeClasses.end(); ++i)
422 destroyModule(i->second);
424 for (map<string, VuoCompilerType *>::iterator i = types.begin(); i != types.end(); ++i)
425 destroyModule(i->second);
427 for (map<string, VuoCompilerModule *>::iterator i = libraryModules.begin(); i != libraryModules.end(); ++i)
428 destroyModule(i->second);
430 for (set<VuoCompilerGenericType *>::iterator i = genericTypes.begin(); i != genericTypes.end(); ++i)
432 VuoType *base = (*i)->getBase();
437 for (map<string, VuoNodeSet *>::iterator i = nodeSetForName.begin(); i != nodeSetForName.end(); ++i)
440 for (map<
string, map<string, ModuleInfo *> >::iterator i = moduleFilesAtSearchPath.begin(); i != moduleFilesAtSearchPath.end(); ++i)
441 for (map<string, ModuleInfo *>::iterator j = i->second.begin(); j != i->second.end(); ++j)
444 for (map<
string, map<string, ModuleInfo *> >::iterator i = sourceFilesAtSearchPath.begin(); i != sourceFilesAtSearchPath.end(); ++i)
445 for (map<string, ModuleInfo *>::iterator j = i->second.begin(); j != i->second.end(); ++j)
448 delete dependencyGraph;
449 delete compositionDependencyGraph;
455 void VuoCompiler::Environment::addCompilerToNotify(
VuoCompiler *compiler)
457 dispatch_sync(compilersToNotifyQueue, ^{
458 compilersToNotify.insert(compiler);
465 void VuoCompiler::Environment::removeCompilerToNotify(
VuoCompiler *compiler)
467 dispatch_sync(compilersToNotifyQueue, ^{
468 compilersToNotify.erase(compiler);
477 map<string, VuoCompilerNodeClass *> VuoCompiler::Environment::getNodeClasses(
void)
489 map<string, VuoCompilerNodeClass *>::iterator nodeClassIter = nodeClasses.find(moduleKey);
490 if (nodeClassIter != nodeClasses.end())
491 return nodeClassIter->second;
504 map<string, VuoCompilerNodeClass *>::iterator nodeClassIter = nodeClasses.find(moduleKey);
505 if (nodeClassIter != nodeClasses.end())
507 nodeClass = nodeClassIter->second;
509 nodeClasses.erase(nodeClassIter);
510 removeFromDependencyGraph(nodeClass);
522 map<string, VuoCompilerType *> VuoCompiler::Environment::getTypes(
void)
532 VuoCompilerType * VuoCompiler::Environment::getType(
const string &moduleKey)
534 map<string, VuoCompilerType *>::iterator typeIter = types.find(moduleKey);
535 if (typeIter != types.end())
536 return typeIter->second;
546 map<string, VuoNodeSet *> VuoCompiler::Environment::getNodeSets(
void)
548 return nodeSetForName;
556 map<string, VuoCompilerModule *> VuoCompiler::Environment::getLibraryModules(
void)
558 return libraryModules;
567 VuoCompilerModule * VuoCompiler::Environment::findModule(
const string &moduleKey)
569 map<string, VuoCompilerNodeClass *>::iterator nodeClassIter = nodeClasses.find(moduleKey);
570 if (nodeClassIter != nodeClasses.end())
571 return nodeClassIter->second;
573 map<string, VuoCompilerType *>::iterator typeIter = types.find(moduleKey);
574 if (typeIter != types.end())
575 return typeIter->second;
577 map<string, VuoCompilerModule *>::iterator libraryIter = libraryModules.find(moduleKey);
578 if (libraryIter != libraryModules.end())
579 return libraryIter->second;
589 VuoNodeSet * VuoCompiler::Environment::findNodeSet(
const string &name)
592 map<string, VuoNodeSet *>::iterator nodeSetIter = nodeSetForName.find(name);
593 if (nodeSetIter != nodeSetForName.end())
594 return nodeSetIter->second;
605 void VuoCompiler::Environment::addModuleSearchPath(
const string &path,
bool shouldWatch)
607 moduleSearchPaths.push_back(path);
609 updateModulesAtSearchPath(path);
610 updateSourceFilesAtSearchPath(path);
613 startWatchingModuleSearchPath(path);
621 vector<string> VuoCompiler::Environment::getModuleSearchPaths(
void)
623 return moduleSearchPaths;
631 void VuoCompiler::Environment::addHeaderSearchPath(
const string &path)
633 headerSearchPaths.push_back(path);
641 vector<string> VuoCompiler::Environment::getHeaderSearchPaths(
void)
643 return headerSearchPaths;
651 void VuoCompiler::Environment::addLibrarySearchPath(
const string &path)
653 librarySearchPaths.push_back(path);
661 vector<string> VuoCompiler::Environment::getLibrarySearchPaths(
void)
663 return librarySearchPaths;
671 void VuoCompiler::Environment::addFrameworkSearchPath(
const string &path)
673 frameworkSearchPaths.push_back(path);
681 vector<string> VuoCompiler::Environment::getFrameworkSearchPaths(
void)
683 return frameworkSearchPaths;
688 return dependencyGraph;
693 return compositionDependencyGraph;
701 void VuoCompiler::Environment::setModuleCachePath(
const string &path)
703 moduleCachePath = path;
711 string VuoCompiler::Environment::getCompiledModuleCachePath(
void)
713 return (moduleCachePath.empty() ?
"" : moduleCachePath +
"/Modules");
721 string VuoCompiler::Environment::getOverriddenCompiledModuleCachePath(
void)
723 if (moduleCachePath.empty())
729 string dir, moduleCacheDirName, ext;
742 void VuoCompiler::Environment::addExpatriateSourceFile(
const string &sourcePath)
744 expatriateSourceFiles.push_back(sourcePath);
746 if (find(moduleSearchPaths.begin(), moduleSearchPaths.end(),
"") == moduleSearchPaths.end())
747 moduleSearchPaths.push_back(
"");
749 auto iter = sourceFilesAtSearchPath.find(
"");
750 if (iter != sourceFilesAtSearchPath.end())
751 sourceFilesAtSearchPath.erase(iter);
759 void VuoCompiler::Environment::removeExpatriateSourceFile(
const string &sourcePath)
761 for (
auto i = expatriateSourceFiles.begin(); i != expatriateSourceFiles.end(); ++i)
765 expatriateSourceFiles.erase(i);
767 auto iter = sourceFilesAtSearchPath.find(
"");
768 if (iter != sourceFilesAtSearchPath.end())
769 sourceFilesAtSearchPath.erase(iter);
788 void VuoCompiler::Environment::updateModulesAtSearchPath(
const string &path,
bool shouldCleanModuleCache)
790 if (moduleFilesAtSearchPath.find(path) != moduleFilesAtSearchPath.end())
793 set<string> moduleExtensions;
794 moduleExtensions.insert(
"vuonode");
795 moduleExtensions.insert(
"vuonode+");
796 moduleExtensions.insert(
"bc");
797 moduleExtensions.insert(
"bc+");
798 set<string> archiveExtensions;
799 archiveExtensions.insert(
"vuonode");
802 map<string, ModuleInfo *> fileForModuleKey;
803 for (set<VuoFileUtilities::File *>::iterator i = moduleFiles.begin(); i != moduleFiles.end(); ++i)
807 ModuleInfo *m =
new ModuleInfo(
this, path, moduleFile,
false,
false);
808 fileForModuleKey[m->getModuleKey()] = m;
811 if (shouldCleanModuleCache && path == getCompiledModuleCachePath())
813 for (map<string, ModuleInfo *>::iterator i = fileForModuleKey.begin(); i != fileForModuleKey.end(); )
815 ModuleInfo *sourceInfo = listSourceFile(i->first);
816 if (! sourceInfo || sourceInfo->isNewerThan(i->second))
818 ModuleInfo *m = i->second;
821 fileForModuleKey.erase(i++);
828 moduleFilesAtSearchPath[path] = fileForModuleKey;
838 void VuoCompiler::Environment::updateSourceFilesAtSearchPath(
const string &path)
840 map<string, map<string, ModuleInfo *> >::iterator sourceFilesIter = sourceFilesAtSearchPath.find(path);
841 if (sourceFilesIter != sourceFilesAtSearchPath.end())
844 set<VuoFileUtilities::File *> sourceFiles;
847 set<string> sourceExtensions;
848 sourceExtensions.insert(
"vuo");
849 sourceExtensions.insert(
"fs");
851 sourceExtensions.insert(cext.begin(), cext.end());
856 for (
const string &sourcePath : expatriateSourceFiles)
858 string dir, file, ext;
861 sourceFiles.insert(sourceFile);
865 map<string, ModuleInfo *> fileForModuleKey;
866 for (set<VuoFileUtilities::File *>::iterator i = sourceFiles.begin(); i != sourceFiles.end(); ++i)
870 string dir, moduleKey, ext;
872 bool isSubcomposition = (ext ==
"vuo");
875 if (path.empty() && !sourceFile->
exists())
878 ModuleInfo *m =
new ModuleInfo(
this, path, sourceFile,
true, isSubcomposition);
879 if (fileForModuleKey.find(m->getModuleKey()) != fileForModuleKey.end())
880 VUserLog(
"Warning: Conflicting source files for module %s are installed at %s", m->getModuleKey().c_str(), path.c_str());
881 fileForModuleKey[m->getModuleKey()] = m;
883 if (isSubcomposition)
885 DependencyGraphVertex *compositionVertex = DependencyGraphVertex::vertexForDependency(moduleKey, compositionDependencyGraph);
886 compositionDependencyGraph->addVertex(compositionVertex);
888 compositionVertex->setEnvironment(
this);
890 set<string> dependencies = m->getContainedNodeClasses();
891 for (set<string>::iterator j = dependencies.begin(); j != dependencies.end(); ++j)
893 DependencyGraphVertex *dependencyVertex = DependencyGraphVertex::vertexForDependency(*j, compositionDependencyGraph);
894 compositionDependencyGraph->addEdge(compositionVertex, dependencyVertex);
899 sourceFilesAtSearchPath[path] = fileForModuleKey;
907 VuoCompiler::ModuleInfo * VuoCompiler::Environment::listModule(
const string &moduleKey)
909 for (
const auto &moduleFiles : moduleFilesAtSearchPath)
911 map<string, ModuleInfo *>::const_iterator foundIter = moduleFiles.second.find(moduleKey);
912 if (foundIter != moduleFiles.second.end())
913 return foundIter->second;
924 VuoCompiler::ModuleInfoIterator VuoCompiler::Environment::listModules(
const set<string> &moduleKeys)
926 for (
const string &path : moduleSearchPaths)
927 updateModulesAtSearchPath(path);
929 return ModuleInfoIterator(&moduleFilesAtSearchPath, moduleKeys);
937 VuoCompiler::ModuleInfoIterator VuoCompiler::Environment::listAllModules(
void)
939 for (
const string &path : moduleSearchPaths)
940 updateModulesAtSearchPath(path);
942 return ModuleInfoIterator(&moduleFilesAtSearchPath);
950 VuoCompiler::ModuleInfo * VuoCompiler::Environment::listSourceFile(
const string &moduleKey)
952 for (
const auto &sourceFiles : sourceFilesAtSearchPath)
954 map<string, ModuleInfo *>::const_iterator foundIter = sourceFiles.second.find(moduleKey);
955 if (foundIter != sourceFiles.second.end())
956 return foundIter->second;
967 VuoCompiler::ModuleInfoIterator VuoCompiler::Environment::listSourceFiles(
const set<string> &moduleKeys)
969 for (
const string &path : moduleSearchPaths)
970 updateSourceFilesAtSearchPath(path);
972 return ModuleInfoIterator(&sourceFilesAtSearchPath, moduleKeys);
980 VuoCompiler::ModuleInfoIterator VuoCompiler::Environment::listAllSourceFiles(
void)
982 for (
const string &path : moduleSearchPaths)
983 updateSourceFilesAtSearchPath(path);
985 return ModuleInfoIterator(&sourceFilesAtSearchPath);
991 vector<string> VuoCompiler::Environment::getBuiltInModuleSearchPaths(
void)
993 vector<string> builtInModuleSearchPaths;
995 string vuoFrameworkPath = getVuoFrameworkPath();
996 if (! vuoFrameworkPath.empty())
998 builtInModuleSearchPaths.push_back(vuoFrameworkPath +
"/Modules");
1002 builtInModuleSearchPaths.push_back(VUO_BUILD_DIR
"/library");
1003 builtInModuleSearchPaths.push_back(VUO_BUILD_DIR
"/node");
1004 builtInModuleSearchPaths.push_back(VUO_BUILD_DIR
"/type");
1005 builtInModuleSearchPaths.push_back(VUO_BUILD_DIR
"/type/list");
1008 return builtInModuleSearchPaths;
1014 vector<string> VuoCompiler::Environment::getBuiltInHeaderSearchPaths(
void)
1016 vector<string> builtInHeaderSearchPaths;
1018 string vuoFrameworkPath = getVuoFrameworkPath();
1019 if (! vuoFrameworkPath.empty())
1021 builtInHeaderSearchPaths.push_back(vuoFrameworkPath +
"/Headers");
1022 builtInHeaderSearchPaths.push_back(vuoFrameworkPath +
"/Headers/macos");
1023 builtInHeaderSearchPaths.push_back(vuoFrameworkPath +
"/Frameworks/llvm.framework/Versions/A/Headers/lib/c++/v1");
1027 builtInHeaderSearchPaths.push_back(VUO_SOURCE_DIR
"/library");
1028 builtInHeaderSearchPaths.push_back(VUO_SOURCE_DIR
"/node");
1029 builtInHeaderSearchPaths.push_back(VUO_SOURCE_DIR
"/type");
1030 builtInHeaderSearchPaths.push_back(VUO_SOURCE_DIR
"/type/list");
1031 builtInHeaderSearchPaths.push_back(VUO_SOURCE_DIR
"/runtime");
1032 builtInHeaderSearchPaths.push_back(JSONC_ROOT
"/include");
1033 builtInHeaderSearchPaths.push_back(LLVM_ROOT
"/include/c++/v1");
1036 return builtInHeaderSearchPaths;
1042 vector<string> VuoCompiler::Environment::getBuiltInLibrarySearchPaths(
void)
1044 vector<string> builtInLibrarySearchPaths;
1046 string vuoFrameworkPath = getVuoFrameworkPath();
1047 if (! vuoFrameworkPath.empty())
1049 builtInLibrarySearchPaths.push_back(vuoFrameworkPath +
"/Modules");
1052 builtInLibrarySearchPaths.push_back(OPENSSL_ROOT
"/lib");
1056 builtInLibrarySearchPaths.push_back(VUO_BUILD_DIR
"/library");
1057 builtInLibrarySearchPaths.push_back(VUO_BUILD_DIR
"/node");
1058 builtInLibrarySearchPaths.push_back(VUO_BUILD_DIR
"/type");
1059 builtInLibrarySearchPaths.push_back(VUO_BUILD_DIR
"/type/list");
1060 builtInLibrarySearchPaths.push_back(VUO_BUILD_DIR
"/runtime");
1062 builtInLibrarySearchPaths.push_back(LEAP_ROOT);
1065 builtInLibrarySearchPaths.insert(builtInLibrarySearchPaths.end(), conanLibDirs.begin(), conanLibDirs.end());
1068 return builtInLibrarySearchPaths;
1074 vector<string> VuoCompiler::Environment::getBuiltInFrameworkSearchPaths(
void)
1076 vector<string> builtInFrameworkSearchPaths;
1078 string vuoFrameworkPath = getVuoFrameworkPath();
1079 if (! vuoFrameworkPath.empty())
1081 builtInFrameworkSearchPaths.push_back(vuoFrameworkPath +
"/Modules/");
1082 builtInFrameworkSearchPaths.push_back(vuoFrameworkPath +
"/Frameworks/");
1086 builtInFrameworkSearchPaths.push_back(SYPHON_ROOT);
1089 return builtInFrameworkSearchPaths;
1098 void VuoCompiler::Environment::startWatchingModuleSearchPath(
const string &moduleSearchPath)
1101 moduleSearchPathWatchers.insert(watcher);
1109 void VuoCompiler::Environment::stopWatchingModuleSearchPaths(
void)
1111 for (set<VuoFileWatcher *>::iterator i = moduleSearchPathWatchers.begin(); i != moduleSearchPathWatchers.end(); ++i)
1114 moduleSearchPathWatchers.clear();
1121 void VuoCompiler::Environment::fileChanged(
const string &moduleSearchPath)
1123 dispatch_sync(moduleSearchPathContentsChangedQueue, ^{
1124 moduleSearchPathContentsChanged(moduleSearchPath);
1135 void VuoCompiler::Environment::moduleSearchPathContentsChanged(
const string &moduleSearchPath,
const string &moduleAddedOrModifiedPath,
1136 const string &moduleAddedOrModifiedSourceCode,
1137 std::function<
void(
void)> moduleLoadedCallback,
1143 __block set<string> modulesAdded;
1144 __block set<string> modulesModifed;
1145 __block set<string> modulesRemoved;
1146 __block set<string> compositionsAdded;
1147 __block set<string> compositionsModifed;
1148 __block set<string> compositionsRemoved;
1150 dispatch_sync(environmentQueue, ^{
1154 map<string, ModuleInfo *> oldModules;
1155 map<string, ModuleInfo *> oldCompositions;
1157 map<string, map<string, ModuleInfo *> >::iterator mf = moduleFilesAtSearchPath.find(moduleSearchPath);
1158 if (mf != moduleFilesAtSearchPath.end())
1160 for (map<string, ModuleInfo *>::iterator j = mf->second.begin(); j != mf->second.end(); ++j)
1162 oldModules[j->first] = j->second;
1165 moduleFilesAtSearchPath.erase(mf);
1168 map<string, map<string, ModuleInfo *> >::iterator cf = sourceFilesAtSearchPath.find(moduleSearchPath);
1169 if (cf != sourceFilesAtSearchPath.end())
1171 for (map<string, ModuleInfo *>::iterator j = cf->second.begin(); j != cf->second.end(); ++j)
1173 oldCompositions[j->first] = j->second;
1176 compositionDependencyGraph->removeVertex(vertex);
1179 sourceFilesAtSearchPath.erase(cf);
1184 updateModulesAtSearchPath(moduleSearchPath, moduleAddedOrModifiedPath.empty());
1185 updateSourceFilesAtSearchPath(moduleSearchPath);
1187 mf = moduleFilesAtSearchPath.find(moduleSearchPath);
1188 if (mf != moduleFilesAtSearchPath.end())
1190 for (map<string, ModuleInfo *>::iterator n = mf->second.begin(); n != mf->second.end(); ++n)
1192 string moduleKey = n->first;
1194 map<string, ModuleInfo *>::iterator o = oldModules.find(moduleKey);
1195 if (o != oldModules.end())
1197 if (n->second->isNewerThan(o->second) ||
1198 (n->second->getFile() && (n->second->getFile()->isInArchive() ||
VuoFileUtilities::arePathsEqual(n->second->getFile()->path(), moduleAddedOrModifiedPath))))
1200 modulesModifed.insert(moduleKey);
1204 n->second->setAttempted(o->second->getAttempted());
1208 oldModules.erase(o);
1212 modulesModifed.insert(moduleKey);
1216 modulesAdded.insert(moduleKey);
1221 cf = sourceFilesAtSearchPath.find(moduleSearchPath);
1222 if (cf != sourceFilesAtSearchPath.end())
1224 for (map<string, ModuleInfo *>::iterator n = cf->second.begin(); n != cf->second.end(); ++n)
1226 string moduleKey = n->first;
1228 map<string, ModuleInfo *>::iterator o = oldCompositions.find(moduleKey);
1229 if (o != oldCompositions.end())
1231 if (n->second->isNewerThan(o->second))
1233 compositionsModifed.insert(moduleKey);
1237 n->second->setAttempted(o->second->getAttempted());
1238 n->second->setSourceCode(o->second->getSourceCode());
1242 oldCompositions.erase(o);
1246 compositionsAdded.insert(moduleKey);
1251 for (map<string, ModuleInfo *>::iterator o = oldModules.begin(); o != oldModules.end(); ++o)
1254 modulesRemoved.insert(o->first);
1257 for (map<string, ModuleInfo *>::iterator o = oldCompositions.begin(); o != oldCompositions.end(); ++o)
1260 compositionsRemoved.insert(o->first);
1263 compilerForLoading->loadModulesAndSources(modulesAdded, modulesModifed, modulesRemoved,
1264 compositionsAdded, compositionsModifed, compositionsRemoved,
1265 false,
false,
this, issues, moduleLoadedCallback, moduleAddedOrModifiedSourceCode);
1269 delete compilerForLoading;
1275 void VuoCompiler::Environment::notifyCompilers(
const set<VuoCompilerModule *> &modulesAdded,
1276 const set< pair<VuoCompilerModule *, VuoCompilerModule *> > &modulesModified,
1278 bool oldModulesInvalidated)
1280 if (! (modulesAdded.empty() && modulesModified.empty() && modulesRemoved.empty() && issues->
isEmpty()) )
1282 set< pair<VuoCompilerModule *, VuoCompilerModule *> > invalidatedModulesModified;
1283 set<VuoCompilerModule *> invalidatedModulesRemoved;
1284 if (oldModulesInvalidated)
1286 invalidatedModulesModified = modulesModified;
1287 invalidatedModulesRemoved = modulesRemoved;
1290 VuoCompilerDelegate::LoadedModulesData *delegateData =
new VuoCompilerDelegate::LoadedModulesData(invalidatedModulesModified, invalidatedModulesRemoved, issues);
1292 map<string, VuoCompilerModule *> modulesAddedMap;
1293 map<string, pair<VuoCompilerModule *, VuoCompilerModule *> > modulesModifiedMap;
1294 map<string, VuoCompilerModule *> modulesRemovedMap;
1296 modulesAddedMap[m->getPseudoBase()->getModuleKey()] = m;
1297 for (pair<VuoCompilerModule *, VuoCompilerModule *> m : modulesModified)
1298 modulesModifiedMap[m.first->getPseudoBase()->getModuleKey()] = m;
1300 modulesRemovedMap[m->getPseudoBase()->getModuleKey()] = m;
1302 dispatch_sync(compilersToNotifyQueue, ^{
1303 for (set<VuoCompiler *>::iterator i = compilersToNotify.begin(); i != compilersToNotify.end(); ++i) {
1304 delegateData->retain();
1306 for (set<VuoCompiler *>::iterator i = compilersToNotify.begin(); i != compilersToNotify.end(); ++i) {
1307 (*i)->loadedModules(modulesAddedMap, modulesModifiedMap, modulesRemovedMap, issues, delegateData,
this);
1327 set<VuoCompilerModule *> VuoCompiler::Environment::loadCompiledModules(
const set<string> &moduleKeys,
const map<string, string> &sourceCodeForModule)
1329 ModuleInfoIterator modulesToLoadIter = listModules(moduleKeys);
1330 set<VuoCompilerModule *> modulesLoaded;
1332 ModuleInfo *moduleInfo;
1333 while ((moduleInfo = modulesToLoadIter.next()))
1335 string moduleKey = moduleInfo->getModuleKey();
1339 if (moduleInfo->getEnvironment() !=
this || findModule(moduleKey) || moduleInfo->getAttempted())
1342 moduleInfo->setAttempted(
true);
1349 modulesLoaded.insert(module);
1350 addToDependencyGraph(module);
1354 string searchPath = moduleInfo->getSearchPath();
1361 ModuleInfo *sourceInfo = listSourceFile(moduleKey);
1365 auto sourceCodeIter = sourceCodeForModule.find(moduleKey);
1366 if (sourceCodeIter != sourceCodeForModule.end())
1373 return modulesLoaded;
1387 set<dispatch_group_t> VuoCompiler::Environment::loadSpecializedModules(
const set<string> &moduleKeys,
1390 set<dispatch_group_t > loadingGroups;
1392 for (
string moduleKey : moduleKeys)
1401 if (findModule(moduleKey))
1406 map<string, dispatch_group_t>::iterator iter = specializedModulesLoading.find(moduleKey);
1407 if (iter != specializedModulesLoading.end())
1409 loadingGroups.insert(iter->second);
1410 dispatch_retain(iter->second);
1414 dispatch_group_t loadingGroup = dispatch_group_create();
1415 specializedModulesLoading[moduleKey] = loadingGroup;
1416 loadingGroups.insert(loadingGroup);
1422 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
1423 dispatch_group_async(loadingGroup, queue, ^{
1437 compiler->loadNodeClassGeneratedAtRuntime(specNodeClass,
this);
1440 compiler->loadModulesIfNeeded(dependencies);
1443 dispatch_sync(environmentQueue, ^{
1444 specializedModulesLoading.erase(moduleKey);
1449 return loadingGroups;
1464 set<dispatch_group_t> VuoCompiler::Environment::compileModulesFromSourceCode(
const set<string> &moduleKeys,
bool shouldRecompileIfUnchanged)
1466 ModuleInfoIterator modulesToLoadIter = listSourceFiles(moduleKeys);
1468 set<dispatch_group_t> sourcesLoading;
1469 int sourcesEnqueued = 0;
1470 ModuleInfo *sourceInfo;
1471 while ((sourceInfo = modulesToLoadIter.next()))
1473 string moduleKey = sourceInfo->getModuleKey();
1475 dispatch_group_t loadingGroup = sourceInfo->getLoadingGroup();
1476 sourcesLoading.insert(loadingGroup);
1481 if (sourceInfo->getAttempted())
1486 string sourceCode = sourceInfo->getSourceCode();
1488 if (! shouldRecompileIfUnchanged)
1491 if (existingNodeClass && existingNodeClass->
getSourceCode() == sourceCode)
1497 sourceInfo->setAttempted(
true);
1499 dispatch_group_enter(loadingGroup);
1500 dispatch_group_enter(moduleSourceCompilersExist);
1504 queueItem->
sourcePath = sourceInfo->getFile()->path();
1506 queueItem->
sourceFile = sourceInfo->getFile();
1507 queueItem->
cachedModulesPath = sourceInfo->isSourceCodeOverridden() ? getOverriddenCompiledModuleCachePath() : getCompiledModuleCachePath();
1510 moduleCompilationQueue->enqueue(queueItem);
1519 for (
int i = 0; i < sourcesEnqueued; ++i)
1521 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
1522 dispatch_async(queue, ^{
1534 notifyCompilers(set<VuoCompilerModule *>(), set< pair<VuoCompilerModule *, VuoCompilerModule *> >(), set<VuoCompilerModule *>(), issues,
false);
1539 auto moduleLoadedCallback = [=](){
1541 moduleCompilationQueue->completed(queueItem);
1555 notifyCompilers(set<VuoCompilerModule *>(), set< pair<VuoCompilerModule *, VuoCompilerModule *> >(), set<VuoCompilerModule *>(), issues,
false);
1562 auto getType = [&compiler] (
const string &moduleKey) {
return compiler->
getType(moduleKey); };
1581 moduleLoadedCallback();
1595 notifyCompilers(set<VuoCompilerModule *>(), set< pair<VuoCompilerModule *, VuoCompilerModule *> >(), set<VuoCompilerModule *>(), issues,
false);
1596 moduleLoadedCallback();
1606 dispatch_group_leave(moduleSourceCompilersExist);
1610 return sourcesLoading;
1621 set<VuoCompilerModule *> VuoCompiler::Environment::unloadCompiledModules(
const set<string> &moduleKeys)
1623 set<VuoCompilerModule *> modulesUnloaded;
1625 for (set<string>::const_iterator i = moduleKeys.begin(); i != moduleKeys.end(); ++i)
1627 string moduleKey = *i;
1630 map<string, VuoCompilerNodeClass *>::iterator nodeClassIter = nodeClasses.find(moduleKey);
1631 if (nodeClassIter != nodeClasses.end())
1633 module = nodeClassIter->second;
1634 nodeClasses.erase(nodeClassIter);
1638 map<string, VuoCompilerType *>::iterator typeIter = types.find(moduleKey);
1639 if (typeIter != types.end())
1641 module = typeIter->second;
1642 types.erase(typeIter);
1646 map<string, VuoCompilerModule *>::iterator libraryModuleIter = libraryModules.find(moduleKey);
1647 if (libraryModuleIter != libraryModules.end())
1649 module = libraryModuleIter->second;
1650 libraryModules.erase(libraryModuleIter);
1657 modulesUnloaded.insert(module);
1658 removeFromDependencyGraph(module);
1663 return modulesUnloaded;
1671 void VuoCompiler::Environment::deleteModulesCompiledFromSourceCode(
const set<string> &moduleKeys)
1673 for (set<string>::const_iterator i = moduleKeys.begin(); i != moduleKeys.end(); ++i)
1675 string moduleKey = *i;
1677 map<string, ModuleInfo *>::iterator iter = moduleFilesAtSearchPath[getCompiledModuleCachePath()].find(moduleKey);
1678 if (iter != moduleFilesAtSearchPath[getCompiledModuleCachePath()].end())
1690 VuoCompilerModule * VuoCompiler::Environment::loadModule(ModuleInfo *moduleInfo)
1692 string moduleKey = moduleInfo->getModuleKey();
1699 __block
size_t inputDataBytes;
1700 __block
char *rawInputData;
1704 rawInputData = moduleInfo->getFile()->getContentsAsRawData(inputDataBytes);
1708 rawInputData = NULL;
1709 VUserLog(
"Warning: Couldn't load module '%s'. Its file may have been deleted. (%s)", moduleKey.c_str(), e.
what());
1715 char *processedInputData;
1717 processedInputData = loadModule_Pro0(moduleInfo, moduleKey, inputDataBytes, rawInputData);
1719 processedInputData = rawInputData;
1722 Module *module = NULL;
1723 bool moduleParseError = !processedInputData;
1724 if (!moduleParseError)
1726 string moduleReadError;
1728 module = readModuleFromBitcodeData(processedInputData, inputDataBytes, moduleReadError);
1730 free(processedInputData);
1734 moduleParseError =
true;
1736 string dir, file, ext;
1737 VuoFileUtilities::splitPath(moduleInfo->getFile()->isInArchive() ? moduleInfo->getFile()->getRelativePath() : moduleInfo->getFile()->path(), dir, file, ext);
1739 if (dir == getCompiledModuleCachePath())
1742 VUserLog(
"Error: Couldn't parse module '%s': %s.", moduleInfo->getFile()->getRelativePath().c_str(), moduleReadError.c_str());
1746 if (!moduleParseError)
1749 if (! moduleInfo->getFile()->isInArchive())
1750 modulePath = moduleInfo->getFile()->path();
1759 if (dynamic_cast<VuoCompilerNodeClass *>(compilerModule))
1760 nodeClasses[moduleKey] = static_cast<VuoCompilerNodeClass *>(compilerModule);
1761 else if (dynamic_cast<VuoCompilerType *>(compilerModule))
1762 types[moduleKey] = static_cast<VuoCompilerType *>(compilerModule);
1764 libraryModules[moduleKey] = compilerModule;
1769 map<string, VuoNodeSet *>::iterator nodeSetIter = nodeSetForName.find(nodeSet->
getName());
1770 if (nodeSetIter == nodeSetForName.end())
1772 nodeSetForName[nodeSet->
getName()] = nodeSet;
1777 nodeSet = nodeSetIter->second;
1779 compilerModule->getPseudoBase()->setNodeSet(nodeSet);
1783 loadModule_Pro1(rawInputData, processedInputData, compilerModule);
1786 compilerModule->setBuiltIn( isBuiltIn() );
1788 return compilerModule;
1792 destroyLlvmModule(module);
1811 removeFromDependencyGraph(oldNodeClass);
1812 destroyModule(oldNodeClass);
1815 nodeClasses[moduleKey] = newNodeClass;
1816 addToDependencyGraph(newNodeClass);
1822 DependencyGraphVertex *vertex = DependencyGraphVertex::vertexForDependency(module->
getPseudoBase()->
getModuleKey(), dependencyGraph);
1823 dependencyGraph->addVertex(vertex);
1825 vertex->setEnvironment(
this);
1832 for (set<string>::iterator i = dependencies.begin(); i != dependencies.end(); ++i)
1834 DependencyGraphVertex *depVertex = DependencyGraphVertex::vertexForDependency(*i, dependencyGraph);
1835 dependencyGraph->addEdge(vertex, depVertex);
1839 void VuoCompiler::Environment::removeFromDependencyGraph(
VuoCompilerModule *module)
1841 DependencyGraphVertex *vertex = DependencyGraphVertex::vertexForDependency(module->
getPseudoBase()->
getModuleKey(), dependencyGraph);
1842 dependencyGraph->removeVertex(vertex);
1855 void VuoCompiler::Environment::reifyPortTypes(
const map<string, VuoCompilerType *> &inheritedTypes)
1857 map<string, VuoCompilerType *> availableTypes = inheritedTypes;
1858 availableTypes.insert(types.begin(), types.end());
1860 for (map<string, VuoCompilerNodeClass *>::const_iterator i = nodeClasses.begin(); i != nodeClasses.end(); ++i)
1866 vector<VuoPortClass *> portClasses;
1867 portClasses.insert(portClasses.end(), inputPortClasses.begin(), inputPortClasses.end());
1868 portClasses.insert(portClasses.end(), outputPortClasses.begin(), outputPortClasses.end());
1870 for (vector<VuoPortClass *>::iterator j = portClasses.begin(); j != portClasses.end(); ++j)
1875 if (baseType && ! baseType->hasCompiler())
1880 VuoGenericType *genericType = dynamic_cast<VuoGenericType *>(baseType);
1885 genericTypes.insert( static_cast<VuoCompilerGenericType *>(reifiedType) );
1890 map<string, VuoCompilerType *>::iterator reifiedTypeIter = availableTypes.find(typeName);
1891 if (reifiedTypeIter != availableTypes.end())
1894 reifiedType = reifiedTypeIter->second;
1905 for (vector<VuoCompilerTriggerDescription *>::iterator j = triggers.begin(); j != triggers.end(); ++j)
1913 map<string, VuoCompilerType *>::iterator reifiedTypeIter = availableTypes.find(typeName);
1914 if (reifiedTypeIter != availableTypes.end())
1937 void VuoCompiler::Environment::getCacheableModulesAndDependencies(
bool builtIn,
bool installed, set<string> &cacheableModulesAndDependencies,
1938 set<string> &dylibsNeededToLinkToThisCache,
1939 set<string> &frameworksNeededToLinkToThisCache)
1941 if (isModuleCacheInitialized && ! isModuleCacheableDataDirty)
1943 cacheableModulesAndDependencies = moduleCacheContents;
1944 dylibsNeededToLinkToThisCache = moduleCacheDylibs;
1945 frameworksNeededToLinkToThisCache = moduleCacheFrameworks;
1953 map<string, VuoCompilerModule *> allModules;
1954 allModules.insert(nodeClasses.begin(), nodeClasses.end());
1955 allModules.insert(types.begin(), types.end());
1956 allModules.insert(libraryModules.begin(), libraryModules.end());
1958 set<string> dependencies;
1959 for (map<string, VuoCompilerModule *>::iterator i = allModules.begin(); i != allModules.end(); ++i)
1961 string moduleKey = i->first;
1966 if (module->requiresPro())
1974 cacheableModulesAndDependencies.insert(moduleKey);
1977 dependencies.insert(moduleDependencies.begin(), moduleDependencies.end());
1981 if (builtIn && installed)
1983 vector<string> coreDependencies = getCoreVuoDependencies();
1984 dependencies.insert(coreDependencies.begin(), coreDependencies.end());
1989 for (set<string>::iterator i = dependencies.begin(); i != dependencies.end(); ++i)
1991 string dependency = *i;
1992 if (allModules.find(dependency) == allModules.end())
1995 frameworksNeededToLinkToThisCache.insert(dependency);
1998 string dependencyPath = VuoCompiler::getLibraryPath(dependency, librarySearchPaths);
1999 if (! dependencyPath.empty())
2002 dylibsNeededToLinkToThisCache.insert(dependencyPath);
2004 cacheableModulesAndDependencies.insert(dependency);
2010 moduleCacheSuffix = (installed ?
"installed" :
"generated");
2011 dylibsNeededToLinkToThisCache.insert(moduleCachePath +
"/libVuoModuleCache-" + moduleCacheSuffix +
".dylib");
2013 moduleCacheDylibs = dylibsNeededToLinkToThisCache;
2014 moduleCacheFrameworks = frameworksNeededToLinkToThisCache;
2036 void VuoCompiler::Environment::useModuleCache(
bool shouldUseExistingCache,
VuoCompiler *compiler, set<string> cacheableModulesAndDependencies,
2037 set<string> dylibsNeededToLinkToCaches, set<string> frameworksNeededToLinkToCaches)
2041 static dispatch_once_t checked = 0;
2042 static bool prelinkCache =
true;
2043 dispatch_once(&checked, ^{
2045 bool result = CFPreferencesGetAppBooleanValue(CFSTR(
"prelinkCache"), CFSTR(
"org.vuo.Editor"), &valid);
2047 prelinkCache = result;
2051 VDebugLog(
"Ignoring the module cache since the 'prelinkCache' preference is false.");
2057 if (moduleCachePath.empty())
2062 string cacheDescription = string() +
"the cache of " + moduleCacheSuffix +
" modules at '" + moduleCachePath +
"'";
2063 if (isModuleCacheInitialized && ! isModuleCacheableDataDirty)
2065 VDebugLog(
"No need to recheck %s.", cacheDescription.c_str());
2071 VDebugLog(
"Checking if %s is up-to-date…", cacheDescription.c_str());
2073 bool isCacheUpToDate =
true;
2075 if (isModuleCacheInitialized && isModuleCacheableDataDirty)
2076 isCacheUpToDate =
false;
2078 isModuleCacheInitialized =
true;
2079 isModuleCacheableDataDirty =
false;
2081 const string dylibFileName =
"libVuoModuleCache-" + moduleCacheSuffix +
".dylib";
2082 const string indexFileName =
"moduleCache-" + moduleCacheSuffix +
".txt";
2083 string dylibPath = moduleCachePath +
"/" + dylibFileName;
2084 string indexPath = moduleCachePath +
"/" + indexFileName;
2088 bool dylibFileExists =
false;
2089 bool indexFileExists =
false;
2098 if (! (dirExists && dylibFileExists && indexFileExists))
2100 if (shouldUseExistingCache)
2101 throw VuoException(
"Trying to use the existing cache, but the cache doesn't exist.",
false);
2106 if (! indexFileExists)
2108 if (! dylibFileExists)
2111 isCacheUpToDate =
false;
2119 fileForLocking = moduleCacheFileForLocking[dylibPath];
2120 if (! fileForLocking)
2123 moduleCacheFileForLocking[dylibPath] = fileForLocking;
2127 VDebugLog(
"\tWarning: Couldn't lock for reading.");
2132 if (isCacheUpToDate)
2137 if (shouldUseExistingCache)
2138 throw VuoException(
"Trying to use the existing cache, but the cache doesn't contain readable data.",
false);
2140 isCacheUpToDate =
false;
2146 const char separator =
'\n';
2147 if (isCacheUpToDate || shouldUseExistingCache)
2150 string index = indexFile.getContentsAsString();
2153 moduleCacheContents.clear();
2154 moduleCacheContents.insert(actualIndex.begin(), actualIndex.end());
2156 if (shouldUseExistingCache)
2158 isModuleCacheAvailable =
true;
2165 if (isCacheUpToDate)
2167 if (moduleCacheContents.size() != cacheableModulesAndDependencies.size())
2168 isCacheUpToDate =
false;
2171 set<string> contentsInBoth;
2172 std::set_intersection(moduleCacheContents.begin(), moduleCacheContents.end(),
2173 cacheableModulesAndDependencies.begin(), cacheableModulesAndDependencies.end(),
2174 std::inserter(contentsInBoth, contentsInBoth.begin()));
2176 if (contentsInBoth.size() != cacheableModulesAndDependencies.size())
2177 isCacheUpToDate =
false;
2183 if (isCacheUpToDate)
2187 for (map<
string, map<string, ModuleInfo *> >::iterator i = moduleFilesAtSearchPath.begin(); i != moduleFilesAtSearchPath.end(); ++i)
2189 for (map<string, ModuleInfo *>::iterator j = i->second.begin(); j != i->second.end(); ++j)
2191 if (! j->second->isOlderThan(cacheLastModified))
2193 isCacheUpToDate =
false;
2202 if (isCacheUpToDate)
2206 isModuleCacheAvailable =
true;
2212 dispatch_async(moduleCacheBuildingQueue, ^{
2213 VDebugLog(
"Rebuilding %s…", cacheDescription.c_str());
2215 set<Module *> modulesToLink;
2216 set<string> librariesToLink;
2217 set<string> frameworksToLink;
2219 compiler->getLinkerInputs(cacheableModulesAndDependencies, Optimization_SmallBinary, modulesToLink, librariesToLink, frameworksToLink);
2221 librariesToLink.insert(dylibsNeededToLinkToCaches.begin(), dylibsNeededToLinkToCaches.end());
2222 set<string>::iterator iter = librariesToLink.find(dylibPath);
2223 if (iter != librariesToLink.end())
2224 librariesToLink.erase(iter);
2226 frameworksToLink.insert(frameworksNeededToLinkToCaches.begin(), frameworksNeededToLinkToCaches.end());
2229 bool gotLockForWriting =
false;
2234 if (! gotLockForWriting)
2235 throw VuoException(
"The cache file is being used by another process. "
2236 "If any composition windows are open from previous Vuo sessions, quit them. "
2237 "If any processes whose names start with \"VuoComposition\" or one of your composition file names appear in Activity Monitor, force-quit them.",
2241 string dir, file, ext;
2244 compiler->link(tmpPath, modulesToLink, librariesToLink, frameworksToLink,
true);
2252 getVuoFrameworkPath() +
"/Helpers/install_name_tool",
2259 vector<string> expectedContents(cacheableModulesAndDependencies.begin(), cacheableModulesAndDependencies.end());
2265 VDebugLog(
"\tWarning: Couldn't downgrade the lock back to reading.");
2267 dispatch_sync(environmentQueue, ^{
2268 moduleCacheContents = cacheableModulesAndDependencies;
2269 isModuleCacheAvailable =
true;
2275 if (gotLockForWriting)
2277 VDebugLog(
"\tWarning: Couldn't downgrade the lock back to reading.");
2279 VUserLog(
"Warning: Couldn't rebuild %s for the \"faster build\" optimization: %s", cacheDescription.c_str(), e.
what());
2287 VUserLog(
"Warning: Couldn't use %s for the \"faster build\" optimization: %s", cacheDescription.c_str(), e.
what());
2294 void VuoCompiler::Environment::waitForModuleCachesToBuild(
void)
2296 dispatch_sync(moduleCacheBuildingQueue, ^{});
2308 bool VuoCompiler::Environment::findInModuleCache(
const string &moduleOrDependency,
string &cachePath)
2310 if (isModuleCacheAvailable && moduleCacheContents.find(moduleOrDependency) != moduleCacheContents.end())
2312 cachePath = moduleCachePath +
"/libVuoModuleCache-" + moduleCacheSuffix +
".dylib";
2325 void VuoCompiler::Environment::modulesChanged(
void)
2327 isModuleCacheableDataDirty =
true;
2328 isModuleCacheAvailable =
false;
2334 bool VuoCompiler::Environment::isBuiltIn()
2336 return this == sharedEnvironments[0][0];
2342 string VuoCompiler::Environment::getName()
2346 else if (
this == sharedEnvironments[0][1])
2347 return "builtin (generated)";
2348 else if (
this == sharedEnvironments[1][0])
2350 else if (
this == sharedEnvironments[1][1])
2351 return "system (generated)";
2352 else if (
this == sharedEnvironments[2][0])
2354 else if (
this == sharedEnvironments[2][1])
2355 return "user (generated)";
2356 return "composition-local";
2362 void VuoCompiler::applyToInstalledEnvironments(
void (^doForEnvironment)(Environment *))
2364 dispatch_sync(environmentQueue, ^{
2365 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i) {
2366 doForEnvironment((*i)[0]);
2374 void VuoCompiler::applyToInstalledEnvironments(
void (^doForEnvironment)(Environment *,
bool *,
string),
bool *result,
string arg)
2376 dispatch_sync(environmentQueue, ^{
2377 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i) {
2378 doForEnvironment((*i)[0], result, arg);
2386 void VuoCompiler::applyToAllEnvironments(
void (^doForEnvironment)(Environment *environment))
2388 dispatch_sync(environmentQueue, ^{
2389 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i) {
2390 for (vector<Environment *>::iterator j = i->begin(); j != i->end(); ++j) {
2391 doForEnvironment(*j);
2411 shouldLoadAllModules =
true;
2412 hasLoadedAllModules =
false;
2413 modulesToLoadQueue = dispatch_queue_create(
"org.vuo.compiler.modules", NULL);
2414 moduleCacheBuilding = dispatch_group_create();
2415 dependencyGraph = NULL;
2416 compositionDependencyGraph = NULL;
2418 _shouldShowSplashWindow =
false;
2420 delegateQueue = dispatch_queue_create(
"org.vuo.compiler.delegate", NULL);
2422 string vuoFrameworkPath = getVuoFrameworkPath();
2423 if (! vuoFrameworkPath.empty())
2424 clangPath = vuoFrameworkPath +
"/Helpers/clang";
2426 clangPath = llvm::sys::Path(StringRef(LLVM_ROOT
"/bin/clang"));
2428 dispatch_sync(environmentQueue, ^{
2429 if (sharedEnvironments.empty())
2431 sharedEnvironments = vector< vector<Environment *> >(3, vector<Environment *>(2, NULL));
2432 for (vector< vector<Environment *> >::iterator i = sharedEnvironments.begin(); i != sharedEnvironments.end(); ++i) {
2433 for (vector<Environment *>::iterator j = i->begin(); j != i->end(); ++j) {
2434 *j =
new Environment();
2438 vector<string> builtInModuleSearchPaths = Environment::getBuiltInModuleSearchPaths();
2439 for (vector<string>::iterator i = builtInModuleSearchPaths.begin(); i != builtInModuleSearchPaths.end(); ++i) {
2440 sharedEnvironments[0][0]->addModuleSearchPath(*i,
false);
2443 vector<string> builtInHeaderSearchPaths = Environment::getBuiltInHeaderSearchPaths();
2444 for (vector<string>::iterator i = builtInHeaderSearchPaths.begin(); i != builtInHeaderSearchPaths.end(); ++i) {
2445 sharedEnvironments[0][0]->addHeaderSearchPath(*i);
2448 vector<string> builtInLibrarySearchPaths = Environment::getBuiltInLibrarySearchPaths();
2449 for (vector<string>::iterator i = builtInLibrarySearchPaths.begin(); i != builtInLibrarySearchPaths.end(); ++i) {
2450 sharedEnvironments[0][0]->addLibrarySearchPath(*i);
2453 vector<string> builtInFrameworkSearchPaths = Environment::getBuiltInFrameworkSearchPaths();
2454 for (vector<string>::iterator i = builtInFrameworkSearchPaths.begin(); i != builtInFrameworkSearchPaths.end(); ++i) {
2455 sharedEnvironments[0][0]->addFrameworkSearchPath(*i);
2469 string vuoFrameworkPath = getVuoFrameworkPath();
2470 if (! vuoFrameworkPath.empty())
2472 vector<string> moduleCachePaths(3);
2473 moduleCachePaths[0] = vuoFrameworkPath +
"/Modules/Builtin";
2477 for (
size_t i = 0; i < moduleCachePaths.size(); ++i)
2479 string moduleCachePath = moduleCachePaths[i];
2481 sharedEnvironments[i][0]->setModuleCachePath(moduleCachePath);
2482 sharedEnvironments[i][0]->addModuleSearchPath(moduleCachePath +
"/Modules",
false);
2484 sharedEnvironments[i][1]->setModuleCachePath(moduleCachePath);
2502 dispatch_group_wait(moduleCacheBuilding, DISPATCH_TIME_FOREVER);
2503 dispatch_release(moduleCacheBuilding);
2505 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
2506 (*i)[0]->removeCompilerToNotify(
this);
2508 dispatch_sync(delegateQueue, ^{});
2510 dispatch_release(modulesToLoadQueue);
2511 dispatch_release(delegateQueue);
2513 delete dependencyGraph;
2514 delete compositionDependencyGraph;
2520 void VuoCompiler::reset(
void)
2522 dispatch_group_wait(moduleSourceCompilersExist, DISPATCH_TIME_FOREVER);
2524 for (vector< vector<Environment *> >::iterator i = sharedEnvironments.begin(); i != sharedEnvironments.end(); ++i)
2526 (*i)[0]->stopWatchingModuleSearchPaths();
2527 dispatch_sync((*i)[0]->moduleSearchPathContentsChangedQueue, ^{});
2530 for (map<
string, vector<Environment *> >::iterator i = environmentsForCompositionFamily.begin(); i != environmentsForCompositionFamily.end(); ++i)
2532 (i->second)[0]->stopWatchingModuleSearchPaths();
2533 dispatch_sync((i->second)[0]->moduleSearchPathContentsChangedQueue, ^{});
2536 for (vector< vector<Environment *> >::iterator i = sharedEnvironments.begin(); i != sharedEnvironments.end(); ++i)
2537 for (vector<Environment *>::iterator j = i->begin(); j != i->end(); ++j)
2540 for (map<
string, vector<Environment *> >::iterator i = environmentsForCompositionFamily.begin(); i != environmentsForCompositionFamily.end(); ++i)
2541 for (vector<Environment *>::iterator j = i->second.begin(); j != i->second.end(); ++j)
2544 sharedEnvironments.clear();
2545 environmentsForCompositionFamily.clear();
2555 dispatch_async(delegateQueue, ^{
2556 this->delegate = delegate;
2571 string compositionModulesDir;
2572 string compositionBaseDir;
2573 lastCompositionIsSubcomposition =
false;
2574 if (! compositionPath.empty())
2582 string compositionDir;
2585 lastCompositionIsSubcomposition = (compositionDir == compositionModulesDir);
2590 dispatch_sync(environmentQueue, ^{
2591 if (! environments.empty() && compositionBaseDir == lastCompositionBaseDir) {
2594 lastCompositionBaseDir = compositionBaseDir;
2598 Environment *oldCompositionFamilyInstalledEnvironment =
nullptr;
2599 vector<Environment *> compositionEnvironments;
2600 if (! environments.empty())
2602 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i) {
2603 (*i)[0]->removeCompilerToNotify(
this);
2606 if (environments.size() >= 5) {
2607 oldCompositionFamilyInstalledEnvironment = environments[3][0];
2610 compositionEnvironments = environments.back();
2612 environments.clear();
2619 bool isCompositionInSharedEnvironment =
false;
2620 for (vector< vector<Environment *> >::iterator i = sharedEnvironments.begin(); i != sharedEnvironments.end(); ++i)
2622 environments.push_back(*i);
2624 vector<string> moduleSearchPaths = (*i)[0]->getModuleSearchPaths();
2625 for (vector<string>::iterator j = moduleSearchPaths.begin(); j != moduleSearchPaths.end(); ++j)
2627 string moduleSearchPath = *j;
2629 if (moduleSearchPath == compositionModulesDir)
2631 isCompositionInSharedEnvironment =
true;
2636 if (isCompositionInSharedEnvironment) {
2643 Environment *newCompositionFamilyInstalledEnvironment =
nullptr;
2644 if (! isCompositionInSharedEnvironment && ! compositionPath.empty())
2646 vector<Environment *> compositionFamilyEnvironments = environmentsForCompositionFamily[compositionBaseDir];
2647 if (compositionFamilyEnvironments.empty())
2649 compositionFamilyEnvironments = vector<Environment *>(2, NULL);
2650 compositionFamilyEnvironments[0] =
new Environment();
2651 compositionFamilyEnvironments[1] =
new Environment();
2652 environmentsForCompositionFamily[compositionBaseDir] = compositionFamilyEnvironments;
2656 compositionFamilyEnvironments[0]->addModuleSearchPath(compositionModulesDir);
2660 string moduleCachePath = getCachePathForComposition(compositionBaseDir);
2662 compositionFamilyEnvironments[0]->setModuleCachePath(moduleCachePath);
2663 compositionFamilyEnvironments[0]->addModuleSearchPath(moduleCachePath +
"/Modules",
false);
2665 compositionFamilyEnvironments[1]->setModuleCachePath(moduleCachePath);
2667 environments.push_back(compositionFamilyEnvironments);
2669 newCompositionFamilyInstalledEnvironment = compositionFamilyEnvironments[0];
2674 if (compositionEnvironments.empty())
2676 compositionEnvironments = vector<Environment *>(2, NULL);
2677 compositionEnvironments[0] =
new Environment();
2678 compositionEnvironments[1] =
new Environment();
2680 environments.push_back(compositionEnvironments);
2682 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i) {
2683 (*i)[0]->addCompilerToNotify(
this);
2686 delete dependencyGraph;
2687 delete compositionDependencyGraph;
2688 dependencyGraph = makeDependencyNetwork(environments, ^
VuoDirectedAcyclicGraph * (Environment *env) {
return env->getDependencyGraph(); });
2689 compositionDependencyGraph = makeDependencyNetwork(environments, ^
VuoDirectedAcyclicGraph * (Environment *env) {
return env->getCompositionDependencyGraph(); });
2694 if (oldCompositionFamilyInstalledEnvironment != newCompositionFamilyInstalledEnvironment)
2696 auto getModules = [] (Environment *env)
2698 map<string, VuoCompilerModule *> modules;
2701 for (
auto i : env->getNodeClasses()) {
2704 for (
auto i : env->getTypes()) {
2707 for (
auto i : env->getLibraryModules()) {
2714 map<string, VuoCompilerModule *> modulesAdded = getModules(newCompositionFamilyInstalledEnvironment);
2715 map<string, VuoCompilerModule *> modulesRemoved = getModules(oldCompositionFamilyInstalledEnvironment);
2717 map<string, pair<VuoCompilerModule *, VuoCompilerModule *> > modulesModified;
2718 for (map<string, VuoCompilerModule *>::iterator add = modulesAdded.begin(); add != modulesAdded.end(); )
2720 map<string, VuoCompilerModule *>::iterator rem = modulesRemoved.find(add->first);
2721 if (rem != modulesRemoved.end())
2723 modulesModified[add->first] = make_pair(rem->second, add->second);
2724 modulesAdded.erase(add++);
2725 modulesRemoved.erase(rem);
2733 if (! (modulesAdded.empty() && modulesModified.empty() && modulesRemoved.empty()) )
2736 VuoCompilerDelegate::LoadedModulesData *delegateData =
new VuoCompilerDelegate::LoadedModulesData(set< pair<VuoCompilerModule *, VuoCompilerModule *> >(), set<VuoCompilerModule *>(), issues);
2737 delegateData->retain();
2739 Environment *scopeEnvironment = newCompositionFamilyInstalledEnvironment;
2740 if (! scopeEnvironment) {
2741 scopeEnvironment = compositionEnvironments.at(0);
2744 loadedModules(modulesAdded, modulesModified, modulesRemoved, issues, delegateData, scopeEnvironment);
2754 if (!graphForEnvironment)
2759 for (vector< vector<Environment *> >::const_iterator i = environments.begin(); i != environments.end(); ++i)
2763 network->
addEdge(graphForEnvironment(i->at(0)), graphForEnvironment(i->at(1)));
2767 for (vector< vector<Environment *> >::const_iterator ii = environments.begin(); ii != i; ++ii)
2769 network->
addEdge(graphForEnvironment(i->at(0)), graphForEnvironment(ii->at(0)));
2770 network->
addEdge(graphForEnvironment(i->at(1)), graphForEnvironment(ii->at(0)));
2797 void VuoCompiler::loadModulesIfNeeded(
const set<string> &moduleKeys)
2799 __block
bool willLoadAllModules =
false;
2800 if (moduleKeys.empty())
2802 dispatch_sync(modulesToLoadQueue, ^{
2803 if (shouldLoadAllModules && ! hasLoadedAllModules) {
2804 willLoadAllModules =
true;
2805 hasLoadedAllModules =
true;
2810 if (! willLoadAllModules && moduleKeys.empty())
2815 __block set<dispatch_group_t> sourcesLoading;
2816 dispatch_sync(environmentQueue, ^{
2817 sourcesLoading = loadModulesAndSources(moduleKeys, set<string>(), set<string>(),
2818 moduleKeys, set<string>(), set<string>(),
2819 willLoadAllModules,
false,
nullptr,
nullptr,
nullptr,
"");
2825 for (set<dispatch_group_t>::iterator i = sourcesLoading.begin(); i != sourcesLoading.end(); ++i)
2827 dispatch_group_wait(*i, DISPATCH_TIME_FOREVER);
2828 dispatch_release(*i);
2840 set<dispatch_group_t> VuoCompiler::loadModulesAndSources(
const set<string> &modulesAddedKeys,
const set<string> &modulesModifiedKeys,
const set<string> &modulesRemovedKeys,
2841 const set<string> &sourcesAddedKeys,
const set<string> &sourcesModifiedKeys,
const set<string> &sourcesRemovedKeys,
2842 bool willLoadAllModules,
bool shouldRecompileSourcesIfUnchanged,
2843 Environment *currentEnvironment,
VuoCompilerIssues *issuesForCurrentEnvironment,
2844 std::function<
void(
void)> moduleLoadedCallback,
const string &moduleAddedOrModifiedSourceCode)
2856 map<Environment *, set<string> > modulesAdded;
2857 map<Environment *, set<string> > modulesModified;
2858 map<Environment *, set<string> > modulesRemoved;
2859 map<Environment *, set<string> > sourcesAdded;
2860 map<Environment *, set<string> > sourcesModified;
2861 map<Environment *, set<string> > sourcesRemoved;
2862 map<Environment *, set<string> > potentialSpecializedModules;
2864 if (currentEnvironment)
2866 modulesAdded[currentEnvironment] = modulesAddedKeys;
2867 modulesModified[currentEnvironment] = modulesModifiedKeys;
2868 modulesRemoved[currentEnvironment] = modulesRemovedKeys;
2869 sourcesAdded[currentEnvironment] = sourcesAddedKeys;
2870 sourcesModified[currentEnvironment] = sourcesModifiedKeys;
2871 sourcesRemoved[currentEnvironment] = sourcesRemovedKeys;
2875 Environment *genEnv =
nullptr;
2876 if (! willLoadAllModules)
2882 int scope = environments.size() - (lastCompositionIsSubcomposition ? 2 : 1);
2883 genEnv = environments.at(scope).at(1);
2884 potentialSpecializedModules[genEnv] = modulesAddedKeys;
2887 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
2889 Environment *env = (*i).at(0);
2891 ModuleInfoIterator modulesAddedIter = (willLoadAllModules ? env->listAllModules() : env->listModules(modulesAddedKeys));
2892 ModuleInfoIterator sourcesAddedIter = (willLoadAllModules ? env->listAllSourceFiles() : env->listSourceFiles(sourcesAddedKeys));
2893 ModuleInfoIterator sourcesModifiedIter = (willLoadAllModules ? env->listAllSourceFiles() : env->listSourceFiles(sourcesModifiedKeys));
2895 ModuleInfo *moduleInfo;
2896 while ((moduleInfo = modulesAddedIter.next()))
2898 string moduleKey = moduleInfo->getModuleKey();
2900 modulesAdded[env].insert(moduleKey);
2902 if (! willLoadAllModules)
2904 auto foundIter = potentialSpecializedModules[genEnv].find(moduleKey);
2905 if (foundIter != potentialSpecializedModules[genEnv].end())
2906 potentialSpecializedModules[genEnv].erase(foundIter);
2912 auto isCompiledModuleAtSameSearchPath = [&env] (ModuleInfo *sourceInfo)
2914 ModuleInfo *compiledModuleInfo = env->listModule(sourceInfo->getModuleKey());
2915 return (compiledModuleInfo && compiledModuleInfo->getSearchPath() == sourceInfo->getSearchPath());
2918 while ((moduleInfo = sourcesAddedIter.next()))
2920 if (isCompiledModuleAtSameSearchPath(moduleInfo))
2923 sourcesAdded[env].insert( moduleInfo->getModuleKey() );
2926 while ((moduleInfo = sourcesModifiedIter.next()))
2928 if (isCompiledModuleAtSameSearchPath(moduleInfo))
2931 sourcesModified[env].insert( moduleInfo->getModuleKey() );
2936 map<Environment *, VuoCompilerIssues *> issues;
2937 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
2939 Environment *env = (*i).at(0);
2940 issues[env] = (env == currentEnvironment && issuesForCurrentEnvironment ? issuesForCurrentEnvironment :
new VuoCompilerIssues());
2945 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
2947 Environment *env = (*i).at(0);
2952 set<VuoDirectedAcyclicGraph::Vertex *> circularDependencies = env->getCompositionDependencyGraph()->getCycleVertices();
2954 set<string> sourcesAddedModified;
2955 sourcesAddedModified.insert(sourcesAdded[env].begin(), sourcesAdded[env].end());
2956 sourcesAddedModified.insert(sourcesModified[env].begin(), sourcesModified[env].end());
2958 for (set<string>::iterator j = sourcesAddedModified.begin(); j != sourcesAddedModified.end(); ++j)
2960 string moduleKey = *j;
2963 for (set<VuoDirectedAcyclicGraph::Vertex *>::iterator k = circularDependencies.begin(); k != circularDependencies.end(); ++k)
2965 DependencyGraphVertex *vertex = static_cast<DependencyGraphVertex *>(*k);
2966 if (vertex->getDependency() == moduleKey)
2975 sourcesAdded[env].erase(moduleKey);
2976 sourcesModified[env].erase(moduleKey);
2979 "Subcomposition contains itself",
2980 "%moduleKey contains an instance of itself, "
2981 "or contains another subcomposition that contains an instance of %moduleKey.");
2982 issue.setModuleKey(moduleKey);
2984 ModuleInfo *sourceInfo = env->listSourceFile(moduleKey);
2986 issue.setFilePath(sourceInfo->getFile()->path());
2988 issues[env]->append(issue);
2997 map<Environment *, set<string> > modulesDepOnModulesModified;
2998 map<Environment *, set<string> > sourcesDepOnModulesModified;
2999 map<Environment *, set<string> > modulesDepOnModulesRemoved;
3000 map<Environment *, set<string> > sourcesDepOnModulesRemoved;
3003 __block map<Environment *, set<string> > modulesDepOnModulesModified_otherCompiler;
3004 __block map<Environment *, set<string> > sourcesDepOnModulesModified_otherCompiler;
3005 __block map<Environment *, set<string> > modulesDepOnModulesRemoved_otherCompiler;
3006 __block map<Environment *, set<string> > sourcesDepOnModulesRemoved_otherCompiler;
3008 vector<VuoDirectedAcyclicNetwork *> searchDependencyGraphs;
3009 searchDependencyGraphs.push_back(dependencyGraph);
3010 for (map<
string, vector<Environment *> >::iterator ii = environmentsForCompositionFamily.begin(); ii != environmentsForCompositionFamily.end(); ++ii)
3012 vector< vector<Environment *> > otherEnvs = sharedEnvironments;
3013 otherEnvs.push_back(ii->second);
3015 searchDependencyGraphs.push_back(other);
3018 VuoDirectedAcyclicGraph *currentEnvironmentDependencyGraph = (currentEnvironment ? currentEnvironment->getDependencyGraph() :
nullptr);
3020 findDependentModulesAndSources(modulesModified, searchDependencyGraphs, currentEnvironmentDependencyGraph,
3021 modulesDepOnModulesModified, modulesDepOnModulesModified_otherCompiler,
3022 sourcesDepOnModulesModified, sourcesDepOnModulesModified_otherCompiler);
3024 findDependentModulesAndSources(modulesRemoved, searchDependencyGraphs, currentEnvironmentDependencyGraph,
3025 modulesDepOnModulesRemoved, modulesDepOnModulesRemoved_otherCompiler,
3026 sourcesDepOnModulesRemoved, sourcesDepOnModulesRemoved_otherCompiler);
3028 set<Environment *> otherEnvironments;
3029 for (map<Environment *, set<string> >::iterator i = modulesDepOnModulesModified_otherCompiler.begin(); i != modulesDepOnModulesModified_otherCompiler.end(); ++i)
3030 otherEnvironments.insert(i->first);
3031 for (map<Environment *, set<string> >::iterator i = sourcesDepOnModulesModified_otherCompiler.begin(); i != sourcesDepOnModulesModified_otherCompiler.end(); ++i)
3032 otherEnvironments.insert(i->first);
3033 for (map<Environment *, set<string> >::iterator i = modulesDepOnModulesRemoved_otherCompiler.begin(); i != modulesDepOnModulesRemoved_otherCompiler.end(); ++i)
3034 otherEnvironments.insert(i->first);
3035 for (map<Environment *, set<string> >::iterator i = sourcesDepOnModulesRemoved_otherCompiler.begin(); i != sourcesDepOnModulesRemoved_otherCompiler.end(); ++i)
3036 otherEnvironments.insert(i->first);
3038 for (Environment *env : otherEnvironments)
3040 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
3041 string moduleSearchPath = env->getModuleSearchPaths().front();
3044 dispatch_sync(environmentQueue, ^{
3045 otherCompiler->loadModulesAndSources(set<string>(), modulesDepOnModulesModified_otherCompiler[env], modulesDepOnModulesRemoved_otherCompiler[env],
3046 set<string>(), sourcesDepOnModulesModified_otherCompiler[env], sourcesDepOnModulesRemoved_otherCompiler[env],
3047 false,
true, env,
nullptr,
nullptr,
"");
3050 delete otherCompiler;
3059 map<Environment *, set<VuoCompilerModule *> > actualModulesRemoved;
3060 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
3062 Environment *env = (*i).at(0);
3064 set<string> modulesToUnload;
3065 modulesToUnload.insert(modulesRemoved[env].begin(), modulesRemoved[env].end());
3066 modulesToUnload.insert(modulesModified[env].begin(), modulesModified[env].end());
3067 modulesToUnload.insert(modulesDepOnModulesRemoved[env].begin(), modulesDepOnModulesRemoved[env].end());
3068 modulesToUnload.insert(modulesDepOnModulesModified[env].begin(), modulesDepOnModulesModified[env].end());
3070 actualModulesRemoved[env] = env->unloadCompiledModules(modulesToUnload);
3072 if (!env->isBuiltIn() && !actualModulesRemoved[env].empty())
3074 set<string> actualModulesRemovedKeys;
3075 for (
auto m : actualModulesRemoved[env])
3076 actualModulesRemovedKeys.insert(m->getPseudoBase()->getModuleKey());
3088 map<Environment *, set<string> > modulesToLoad;
3089 map<Environment *, map<string, string> > modulesToLoadSourceCode;
3090 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
3092 Environment *env = (*i).at(0);
3094 if (! modulesAdded[env].empty())
3095 modulesToLoad[env].insert(modulesAdded[env].begin(), modulesAdded[env].end());
3096 if (! modulesModified[env].empty())
3097 modulesToLoad[env].insert(modulesModified[env].begin(), modulesModified[env].end());
3098 if (! modulesDepOnModulesModified[env].empty())
3099 modulesToLoad[env].insert(modulesDepOnModulesModified[env].begin(), modulesDepOnModulesModified[env].end());
3101 if (env == currentEnvironment && moduleLoadedCallback)
3103 if (modulesAdded[env].size() == 1)
3104 modulesToLoadSourceCode[env][*modulesAdded[env].begin()] = moduleAddedOrModifiedSourceCode;
3105 else if (modulesModified[env].size() == 1)
3106 modulesToLoadSourceCode[env][*modulesModified[env].begin()] = moduleAddedOrModifiedSourceCode;
3110 map<Environment *, set<VuoCompilerModule *> > actualModulesAdded;
3111 while (! modulesToLoad.empty())
3113 set<string> dependenciesToLoad;
3114 map<Environment *, set<string> > potentialSpecializedDependencies;
3115 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
3117 Environment *env = (*i).at(0);
3118 Environment *genEnv = (*i).at(1);
3120 set<VuoCompilerModule *> actualModulesLoaded = env->loadCompiledModules(modulesToLoad[env], modulesToLoadSourceCode[env]);
3122 actualModulesAdded[env].insert(actualModulesLoaded.begin(), actualModulesLoaded.end());
3123 modulesToLoad.erase(env);
3125 set<string> actualModulesLoadedKeys;
3126 for (set<VuoCompilerModule *>::iterator j = actualModulesLoaded.begin(); j != actualModulesLoaded.end(); ++j)
3128 set<string> dependencies = (*j)->getDependencies();
3129 dependenciesToLoad.insert(dependencies.begin(), dependencies.end());
3130 potentialSpecializedDependencies[genEnv].insert(dependencies.begin(), dependencies.end());
3131 actualModulesLoadedKeys.insert((*j)->getPseudoBase()->getModuleKey());
3134 if (!env->isBuiltIn() && !actualModulesLoadedKeys.empty())
3138 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
3140 Environment *env = (*i).at(0);
3142 ModuleInfoIterator dependenciesInEnv = env->listModules(dependenciesToLoad);
3143 ModuleInfo *moduleInfo;
3144 while ((moduleInfo = dependenciesInEnv.next()))
3146 modulesToLoad[env].insert( moduleInfo->getModuleKey() );
3148 for (map<Environment *, set<string> >::iterator j = potentialSpecializedDependencies.begin(); j != potentialSpecializedDependencies.end(); ++j)
3150 auto foundIter = j->second.find( moduleInfo->getModuleKey() );
3151 if (foundIter != j->second.end())
3152 j->second.erase(foundIter);
3157 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
3159 Environment *genEnv = (*i).at(1);
3160 potentialSpecializedModules[genEnv].insert(potentialSpecializedDependencies[genEnv].begin(), potentialSpecializedDependencies[genEnv].end());
3167 set<dispatch_group_t> specializedModulesLoading;
3168 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
3170 Environment *genEnv = (*i).at(1);
3171 set<dispatch_group_t> s = genEnv->loadSpecializedModules(potentialSpecializedModules[genEnv],
this,
llvmQueue);
3172 specializedModulesLoading.insert(s.begin(), s.end());
3177 if (moduleLoadedCallback)
3178 moduleLoadedCallback();
3182 map<Environment *, set< pair<VuoCompilerModule *, VuoCompilerModule *> > > actualModulesModified;
3183 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
3185 Environment *env = (*i).at(0);
3187 for (set<VuoCompilerModule *>::iterator add = actualModulesAdded[env].begin(); add != actualModulesAdded[env].end(); )
3189 set<VuoCompilerModule *>::iterator rem;
3190 for (rem = actualModulesRemoved[env].begin(); rem != actualModulesRemoved[env].end(); ++rem)
3191 if ((*rem)->getPseudoBase()->getModuleKey() == (*add)->getPseudoBase()->getModuleKey())
3194 if (rem != actualModulesRemoved[env].end())
3196 actualModulesModified[env].insert( make_pair(*rem, *add) );
3197 actualModulesRemoved[env].erase(rem);
3198 actualModulesAdded[env].erase(add++);
3207 bool wereModulesAddedOrModified =
false;
3208 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
3210 Environment *env = (*i).at(0);
3211 if (! (actualModulesAdded[env].empty() && actualModulesModified[env].empty()) )
3213 wereModulesAddedOrModified =
true;
3218 if (wereModulesAddedOrModified)
3220 map<string, VuoCompilerType *> inheritedTypes;
3221 for (
const vector<Environment *> &envs : environments)
3223 for (Environment *env : envs)
3225 env->reifyPortTypes(inheritedTypes);
3226 map<string, VuoCompilerType *> envTypes = env->getTypes();
3227 inheritedTypes.insert(envTypes.begin(), envTypes.end());
3236 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
3238 Environment *env = (*i).at(0);
3240 set<string> sourcesToUnload;
3241 sourcesToUnload.insert(sourcesRemoved[env].begin(), sourcesRemoved[env].end());
3242 sourcesToUnload.insert(sourcesDepOnModulesRemoved[env].begin(), sourcesDepOnModulesRemoved[env].end());
3243 if (! sourcesToUnload.empty())
3245 string moduleSearchPath = env->getModuleSearchPaths().front();
3247 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
3250 dispatch_sync(environmentQueue, ^{
3251 otherCompiler->loadModulesAndSources(set<string>(), set<string>(), sourcesToUnload,
3252 set<string>(), set<string>(), set<string>(),
3253 false,
false, env,
nullptr,
nullptr,
"");
3256 delete otherCompiler;
3260 if (!env->isBuiltIn() && !sourcesToUnload.empty())
3263 env->deleteModulesCompiledFromSourceCode(sourcesToUnload);
3271 map<Environment *, set<string> > sourcesDepOnModulesAdded;
3273 map<Environment *, set<string> > modulesDepOnModulesAdded;
3274 __block map<Environment *, set<string> > modulesDepOnModulesAdded_otherCompiler;
3275 __block map<Environment *, set<string> > sourcesDepOnModulesAdded_otherCompiler;
3277 map<Environment *, set<string> > actualModuleKeysAdded;
3278 for (
const vector<Environment *> &envs : environments)
3280 Environment *env = envs.at(0);
3285 vector<VuoDirectedAcyclicNetwork *> searchDependencyGraphs;
3286 searchDependencyGraphs.push_back(compositionDependencyGraph);
3287 for (map<
string, vector<Environment *> >::iterator ii = environmentsForCompositionFamily.begin(); ii != environmentsForCompositionFamily.end(); ++ii)
3289 vector< vector<Environment *> > otherEnvs = sharedEnvironments;
3290 otherEnvs.push_back(ii->second);
3292 searchDependencyGraphs.push_back(other);
3295 VuoDirectedAcyclicGraph *currentEnvironmentDependencyGraph = (currentEnvironment ? currentEnvironment->getCompositionDependencyGraph() :
nullptr);
3297 findDependentModulesAndSources(actualModuleKeysAdded, searchDependencyGraphs, currentEnvironmentDependencyGraph,
3298 modulesDepOnModulesAdded, modulesDepOnModulesAdded_otherCompiler,
3299 sourcesDepOnModulesAdded, sourcesDepOnModulesAdded_otherCompiler);
3301 set<Environment *> otherEnvironments;
3302 for (map<Environment *, set<string> >::iterator i = sourcesDepOnModulesAdded_otherCompiler.begin(); i != sourcesDepOnModulesAdded_otherCompiler.end(); ++i)
3303 otherEnvironments.insert(i->first);
3305 for (Environment *env : otherEnvironments)
3307 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
3308 string moduleSearchPath = env->getModuleSearchPaths().front();
3311 dispatch_sync(environmentQueue, ^{
3312 otherCompiler->loadModulesAndSources(set<string>(), set<string>(), set<string>(),
3313 sourcesDepOnModulesAdded_otherCompiler[env], set<string>(), set<string>(),
3314 false,
true, env,
nullptr,
nullptr,
"");
3317 delete otherCompiler;
3322 set<dispatch_group_t> sourcesLoading;
3323 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
3325 Environment *env = (*i).at(0);
3327 set<string> sourcesToCompile;
3328 sourcesToCompile.insert(sourcesAdded[env].begin(), sourcesAdded[env].end());
3329 sourcesToCompile.insert(sourcesModified[env].begin(), sourcesModified[env].end());
3331 if (sourcesToCompile.size() == 0)
3334 set<dispatch_group_t> s = env->compileModulesFromSourceCode(sourcesToCompile, shouldRecompileSourcesIfUnchanged);
3335 sourcesLoading.insert(s.begin(), s.end());
3338 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
3340 Environment *env = (*i).at(0);
3342 set<string> sourcesToCompile;
3343 sourcesToCompile.insert(sourcesDepOnModulesAdded[env].begin(), sourcesDepOnModulesAdded[env].end());
3344 sourcesToCompile.insert(sourcesDepOnModulesModified[env].begin(), sourcesDepOnModulesModified[env].end());
3346 if (sourcesToCompile.size() == 0)
3349 env->compileModulesFromSourceCode(sourcesToCompile,
true);
3354 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
3356 Environment *env = (*i).at(0);
3357 env->notifyCompilers(actualModulesAdded[env], actualModulesModified[env], actualModulesRemoved[env], issues[env]);
3364 for (
const dispatch_group_t &group : sourcesLoading)
3365 dispatch_retain(group);
3367 set<dispatch_group_t> loadingGroups;
3368 loadingGroups.insert(specializedModulesLoading.begin(), specializedModulesLoading.end());
3369 loadingGroups.insert(sourcesLoading.begin(), sourcesLoading.end());
3370 return loadingGroups;
3384 void VuoCompiler::findDependentModulesAndSources(map<Environment *, set<string> > &changedModules,
3385 const vector<VuoDirectedAcyclicNetwork *> &searchDependencyGraphs,
3387 map<Environment *, set<string> > &modulesDepOnChangedModules_this,
3388 map<Environment *, set<string> > &modulesDepOnChangedModules_other,
3389 map<Environment *, set<string> > &sourcesDepOnChangedModules_this,
3390 map<Environment *, set<string> > &sourcesDepOnChangedModules_other)
3392 for (
const vector<Environment *> &envs : environments)
3394 Environment *env = envs.at(0);
3396 for (
const string &module : changedModules[env])
3398 set<VuoDirectedAcyclicGraph::Vertex *> dependents;
3401 vector<VuoDirectedAcyclicGraph::Vertex *> moduleVertices;
3402 if (currentEnvironmentDependencyGraph)
3408 moduleVertices.push_back(mv);
3411 moduleVertices = searchDependencyGraph->findVertex(module);
3415 DependencyGraphVertex *moduleVertex = static_cast<DependencyGraphVertex *>(moduleVertexRaw);
3416 if (moduleVertex->getEnvironment())
3418 vector<VuoDirectedAcyclicGraph::Vertex *> upstream = searchDependencyGraph->getUpstreamVertices(moduleVertex);
3419 dependents.insert(upstream.begin(), upstream.end());
3426 DependencyGraphVertex *v = static_cast<DependencyGraphVertex *>(dependentVertexRaw);
3427 Environment *dependentEnv = v->getEnvironment();
3431 string dependent = v->getDependency();
3435 if (changedModules[dependentEnv].find(dependent) != changedModules[dependentEnv].end())
3438 ModuleInfo *foundSourceInfo = dependentEnv->listSourceFile(dependent);
3439 ModuleInfo *foundModuleInfo = dependentEnv->listModule(dependent);
3441 bool belongsToCurrentCompiler =
false;
3442 for (
const vector<Environment *> &envs2 : environments)
3444 if (find(envs2.begin(), envs2.end(), dependentEnv) != envs2.end())
3446 belongsToCurrentCompiler =
true;
3451 map<Environment *, set<string> > *whicheverDependents =
nullptr;
3452 ModuleInfo *moduleInfo =
nullptr;
3453 if (foundSourceInfo)
3455 moduleInfo = foundSourceInfo;
3456 whicheverDependents = (belongsToCurrentCompiler ? &sourcesDepOnChangedModules_this : &sourcesDepOnChangedModules_other);
3458 else if (foundModuleInfo)
3460 moduleInfo = foundModuleInfo;
3461 whicheverDependents = (belongsToCurrentCompiler ? &modulesDepOnChangedModules_this : &modulesDepOnChangedModules_other);
3464 (*whicheverDependents)[dependentEnv].insert(dependent);
3465 moduleInfo->setAttempted(
false);
3474 void VuoCompiler::loadedModules(map<string, VuoCompilerModule *> modulesAdded,
3475 map<
string, pair<VuoCompilerModule *, VuoCompilerModule *> > modulesModified,
3476 map<string, VuoCompilerModule *> modulesRemoved,
3477 VuoCompilerIssues *issues,
void *delegateDataV, Environment *currentEnvironment)
3489 auto findVersionsOfModule = [
this, currentEnvironment] (
const string &moduleKey)
3491 vector< pair<Environment *, VuoCompilerModule *> > moduleVersions;
3492 for (
const vector<Environment *> &envs : environments)
3494 Environment *env = envs.at(0);
3496 if (module || env == currentEnvironment)
3497 moduleVersions.push_back( make_pair(env, module) );
3499 return moduleVersions;
3502 for (map<string, VuoCompilerModule *>::iterator i = modulesAdded.begin(); i != modulesAdded.end(); )
3504 string moduleKey = i->first;
3507 vector< pair<Environment *, VuoCompilerModule *> > moduleVersions = findVersionsOfModule(moduleKey);
3509 if (moduleVersions.size() > 1)
3511 modulesAdded.erase(i++);
3513 if (moduleVersions.back().second == moduleAdded)
3515 VuoCompilerModule *moduleSuperseded = moduleVersions.at(moduleVersions.size()-2).second;
3516 modulesModified[moduleKey] = make_pair(moduleSuperseded, moduleAdded);
3523 for (map<
string, pair<VuoCompilerModule *, VuoCompilerModule *> >::iterator i = modulesModified.begin(); i != modulesModified.end(); )
3525 string moduleKey = i->first;
3528 vector< pair<Environment *, VuoCompilerModule *> > moduleVersions = findVersionsOfModule(moduleKey);
3530 if (moduleVersions.size() > 1 && moduleVersions.back().second != moduleModified)
3531 modulesModified.erase(i++);
3536 for (map<string, VuoCompilerModule *>::iterator i = modulesRemoved.begin(); i != modulesRemoved.end(); )
3538 string moduleKey = i->first;
3541 vector< pair<Environment *, VuoCompilerModule *> > moduleVersions = findVersionsOfModule(moduleKey);
3543 if (moduleVersions.size() > 1)
3545 modulesRemoved.erase(i++);
3547 if (moduleVersions.back().first == currentEnvironment)
3549 VuoCompilerModule *moduleUnsuperseded = moduleVersions.at(moduleVersions.size()-2).second;
3550 modulesModified[moduleKey] = make_pair(moduleRemoved, moduleUnsuperseded);
3557 dispatch_async(delegateQueue, ^{
3558 VuoCompilerDelegate::LoadedModulesData *delegateData = static_cast<VuoCompilerDelegate::LoadedModulesData *>(delegateDataV);
3560 if (delegate && ! (modulesAdded.empty() && modulesModified.empty() && modulesRemoved.empty() && issues->
isEmpty()))
3562 delegate->enqueueData(delegateData);
3563 delegate->
loadedModules(modulesAdded, modulesModified, modulesRemoved, issues);
3567 delegateData->release();
3577 void VuoCompiler::loadNodeClassGeneratedAtRuntime(
VuoCompilerNodeClass *nodeClass, Environment *env)
3579 Module *module = nodeClass->
getModule();
3583 setTargetForModule(nodeClass->
getModule());
3587 dispatch_sync(environmentQueue, ^{
3588 env->replaceNodeClass(nodeClass);
3591 __block map<string, VuoCompilerType *> inheritedTypes;
3592 void (^envReifyPortTypes)(Environment *) = ^
void (Environment *env) {
3593 env->reifyPortTypes(inheritedTypes);
3594 map<string, VuoCompilerType *> currentTypes = env->getTypes();
3595 inheritedTypes.insert(currentTypes.begin(), currentTypes.end());
3597 applyToAllEnvironments(envReifyPortTypes);
3606 reifyGenericPortTypes(node->getBase());
3614 void VuoCompiler::reifyGenericPortTypes(
VuoNode *node)
3624 vector<VuoPort *> ports;
3625 ports.insert(ports.end(), inputPorts.begin(), inputPorts.end());
3626 ports.insert(ports.end(), outputPorts.begin(), outputPorts.end());
3628 for (vector<VuoPort *>::iterator j = ports.begin(); j != ports.end(); ++j)
3630 VuoCompilerPort *port = static_cast<VuoCompilerPort *>((*j)->getCompiler());
3635 if (! genericType->hasCompiler())
3675 vector<string> allIncludePaths = includePaths;
3676 string preprocessedInputPath = inputPath;
3678 string tmpPreprocessedInputDir;
3679 string dir, file, ext;
3684 string preprocessedInputContents = inputContents;
3686 if (inputContents != preprocessedInputContents)
3689 allIncludePaths.push_back(dir.empty() ?
"." : dir);
3691 preprocessedInputPath = tmpPreprocessedInputDir +
"/" + file +
"." + ext;
3696 else if (ext ==
"fs")
3702 auto getType = [
this] (
const string &moduleKey) {
return this->
getType(moduleKey); };
3707 writeModuleToBitcode(module, outputPath);
3717 vector<string> extraArgs;
3718 for (vector<string>::iterator i = allIncludePaths.begin(); i != allIncludePaths.end(); ++i)
3720 extraArgs.push_back(
"-I");
3721 extraArgs.push_back(*i);
3724 string macosxSdkFolder =
"/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/";
3727 extraArgs.push_back(
"-isysroot");
3728 extraArgs.push_back(macosxSdkFolder +
"MacOSX10.10.sdk");
3731 __block vector<string> headerSearchPaths;
3732 void (^envGetHeaderSearchPaths)(Environment *) = ^
void (Environment *env) {
3733 vector<string> result = env->getHeaderSearchPaths();
3734 headerSearchPaths.insert(headerSearchPaths.end(), result.begin(), result.end());
3736 applyToInstalledEnvironments(envGetHeaderSearchPaths);
3738 __block Module *module;
3740 module = readModuleFromC(preprocessedInputPath, headerSearchPaths, extraArgs);
3743 if (! tmpPreprocessedInputDir.empty())
3744 remove(tmpPreprocessedInputDir.c_str());
3748 "",
"%moduleKey couldn't be compiled as a node class, type, or library. Check the macOS Console for details.");
3755 if (! compilerModule)
3757 VUserLog(
"Error: Didn't recognize '%s' as a node class, type, or library.", inputPath.c_str());
3761 setTargetForModule(module, target);
3762 writeModuleToBitcode(module, outputPath);
3771 Module * VuoCompiler::compileCompositionToModule(
VuoCompilerComposition *composition,
const string &moduleKey,
bool isTopLevelComposition,
3774 composition->
check(issues);
3776 reifyGenericPortTypes(composition);
3779 isTopLevelComposition,
3781 if (telemetry ==
"console")
3784 __block Module *module;
3787 setTargetForModule(module, target);
3809 Module *module = compileCompositionToModule(composition, moduleKey, isTopLevelComposition, issues);
3812 writeModuleToBitcode(module, outputPath);
3829 VDebugLog(
"Compiling '%s'…", inputPath.c_str());
3836 "",
"The composition file couldn't be read or was empty.");
3872 delete baseComposition;
3878 void VuoCompiler::compileSubcompositionString(
const string &compositionString,
const string &outputPath,
3879 std::function<
void(
void)> moduleLoadedCallback, Environment *environment,
3885 bool compilationSucceeded =
false;
3889 compilationSucceeded =
true;
3897 if (! compilationSucceeded)
3903 string outputDir, file, ext;
3907 environment->moduleSearchPathContentsChanged(outputDir, outputPath, compositionString, moduleLoadedCallback,
this, issues);
3925 linkCompositionToCreateExecutableOrDynamicLibrary(inputPath, outputPath, optimization,
false, rPath);
3946 linkCompositionToCreateExecutableOrDynamicLibrary(inputPath, outputPath, optimization,
true);
3963 void VuoCompiler::linkCompositionToCreateExecutableOrDynamicLibrary(
string compiledCompositionPath,
string linkedCompositionPath,
3964 Optimization optimization,
bool isDylib,
string rPath)
3970 shouldLoadAllModules =
false;
3972 set<string> dependencies = getDependenciesForComposition(compiledCompositionPath);
3973 dependencies.insert(getRuntimeDependency());
3975 dependencies.insert(getRuntimeMainDependency());
3977 set<Module *> modules;
3978 set<string> libraries;
3979 set<string> frameworks;
3980 getLinkerInputs(dependencies, optimization, modules, libraries, frameworks);
3982 libraries.insert(compiledCompositionPath);
3984 link(linkedCompositionPath, modules, libraries, frameworks, isDylib, rPath);
4010 set<string> allDependencies = getDependenciesForComposition(compiledCompositionPath);
4011 set<string> addedDependencies;
4012 std::set_difference(allDependencies.begin(), allDependencies.end(),
4013 carriedOverDependencies.begin(), carriedOverDependencies.end(),
4014 std::inserter(addedDependencies, addedDependencies.end()));
4020 set<string> carriedOverExternalLibraries = runningCompositionLibraries->
getExternalLibraries();
4025 string nonUnloadableResourcePath;
4026 string unloadableResourcePath;
4027 set<string> nonUnloadableDependencies;
4028 set<string> unloadableDependencies;
4029 map<string, set<string> > builtInCacheDependencies;
4030 map<string, set<string> > userCacheDependencies;
4031 set<string> builtInLibraries;
4032 set<string> userLibraries;
4033 set<string> addedExternalLibraries;
4034 set<string> addedFrameworks;
4035 set<string> allFrameworks;
4036 if (! addedDependencies.empty())
4038 set<string> builtInModuleAndLibraryDependencies;
4039 set<string> userModuleAndLibraryDependencies;
4040 set<Module *> builtInModules;
4041 set<Module *> userModules;
4044 builtInModuleAndLibraryDependencies, userModuleAndLibraryDependencies, builtInCacheDependencies, userCacheDependencies,
4045 builtInModules, userModules, builtInLibraries, userLibraries, addedExternalLibraries, addedFrameworks);
4047 allFrameworks.insert(carriedOverFrameworks.begin(), carriedOverFrameworks.end());
4048 allFrameworks.insert(addedFrameworks.begin(), addedFrameworks.end());
4050 string dir, linkedCompositionFile, ext;
4053 if (! builtInModules.empty() || builtInLibraries.size() > builtInCacheDependencies.size())
4056 nonUnloadableDependencies = builtInModuleAndLibraryDependencies;
4058 set<string> librariesForNonUnloadableResource = builtInLibraries;
4059 librariesForNonUnloadableResource.insert(carriedOverNonUnloadableLibraries.begin(), carriedOverNonUnloadableLibraries.end());
4060 librariesForNonUnloadableResource.insert(carriedOverExternalLibraries.begin(), carriedOverExternalLibraries.end());
4061 librariesForNonUnloadableResource.insert(addedExternalLibraries.begin(), addedExternalLibraries.end());
4063 link(nonUnloadableResourcePath, builtInModules, librariesForNonUnloadableResource, allFrameworks,
true);\
4065 for (set<string>::iterator i = builtInLibraries.begin(); i != builtInLibraries.end(); )
4068 builtInLibraries.erase(i++);
4073 for (set<string>::iterator i = addedExternalLibraries.begin(); i != addedExternalLibraries.end(); )
4076 addedExternalLibraries.erase(i++);
4082 if (! userModules.empty() || userLibraries.size() > userCacheDependencies.size())
4085 unloadableDependencies = userModuleAndLibraryDependencies;
4087 set<string> librariesForUnloadableResource = userLibraries;
4088 librariesForUnloadableResource.insert(builtInLibraries.begin(), builtInLibraries.end());
4089 librariesForUnloadableResource.insert(carriedOverUnloadableLibraries.begin(), carriedOverUnloadableLibraries.end());
4090 librariesForUnloadableResource.insert(carriedOverNonUnloadableLibraries.begin(), carriedOverNonUnloadableLibraries.end());
4091 librariesForUnloadableResource.insert(carriedOverExternalLibraries.begin(), carriedOverExternalLibraries.end());
4092 librariesForUnloadableResource.insert(addedExternalLibraries.begin(), addedExternalLibraries.end());
4093 if (! nonUnloadableResourcePath.empty())
4094 librariesForUnloadableResource.insert(nonUnloadableResourcePath);
4096 link(unloadableResourcePath, userModules, librariesForUnloadableResource, allFrameworks,
true);
4098 for (set<string>::iterator i = userLibraries.begin(); i != userLibraries.end(); )
4101 userLibraries.erase(i++);
4110 set<string> vuoRuntimePaths;
4112 set<Module *> modules;
4113 set<string> libraries;
4114 set<string> frameworks;
4116 set<string> dependencies;
4117 dependencies.insert(getRuntimeDependency());
4119 vuoRuntimePaths = libraries;
4125 set<Module *> modules;
4126 set<string> libraries;
4128 libraries.insert(compiledCompositionPath);
4129 libraries.insert(carriedOverExternalLibraries.begin(), carriedOverExternalLibraries.end());
4130 libraries.insert(addedExternalLibraries.begin(), addedExternalLibraries.end());
4131 libraries.insert(carriedOverNonUnloadableLibraries.begin(), carriedOverNonUnloadableLibraries.end());
4132 libraries.insert(carriedOverUnloadableLibraries.begin(), carriedOverUnloadableLibraries.end());
4133 libraries.insert(builtInLibraries.begin(), builtInLibraries.end());
4134 libraries.insert(userLibraries.begin(), userLibraries.end());
4135 if (! nonUnloadableResourcePath.empty())
4136 libraries.insert(nonUnloadableResourcePath);
4137 if (! unloadableResourcePath.empty())
4138 libraries.insert(unloadableResourcePath);
4139 libraries.insert(vuoRuntimePaths.begin(), vuoRuntimePaths.end());
4140 link(linkedCompositionPath, modules, libraries, allFrameworks,
true);
4145 if (! nonUnloadableResourcePath.empty())
4148 if (! unloadableResourcePath.empty())
4151 for (map<
string, set<string> >::iterator i = builtInCacheDependencies.begin(); i != builtInCacheDependencies.end(); ++i)
4154 for (map<
string, set<string> >::iterator i = userCacheDependencies.begin(); i != userCacheDependencies.end(); ++i)
4167 set<string> VuoCompiler::getDependenciesForComposition(
const string &compiledCompositionPath)
4169 VDebugLog(
"Gathering dependencies for '%s'…", compiledCompositionPath.c_str());
4172 __block set<string> directDependencies;
4174 Module *module = readModuleFromBitcode(compiledCompositionPath);
4178 delete compilerModule;
4184 auto deps = getDependenciesForComposition(directDependencies,
true);
4203 set<string> directDependencies;
4212 vector<VuoPublishedPort *> publishedPorts;
4213 publishedPorts.insert(publishedPorts.end(), publishedInputPorts.begin(), publishedInputPorts.end());
4214 publishedPorts.insert(publishedPorts.end(), publishedOutputPorts.begin(), publishedOutputPorts.end());
4217 if (publishedPort->getClass()->hasCompiler())
4219 VuoType *portType = static_cast<VuoCompilerPortClass *>( publishedPort->getClass()->getCompiler() )->getDataVuoType();
4223 VuoGenericType *genericType = dynamic_cast<VuoGenericType *>(portType);
4233 directDependencies.insert(dependency);
4238 return directDependencies;
4250 return getDependenciesForComposition(directDependencies,
false);
4260 __block vector<string> librarySearchPaths;
4261 applyToInstalledEnvironments(^
void (Environment *env) {
4262 vector<string> result = env->getLibrarySearchPaths();
4263 librarySearchPaths.insert(librarySearchPaths.end(), result.begin(), result.end());
4266 set<string> dylibDeps;
4267 for (
string dep : getDependenciesForComposition(composition))
4269 string path = getLibraryPath(dep, librarySearchPaths);
4271 dylibDeps.insert(path);
4290 set<string> VuoCompiler::getDependenciesForComposition(
const set<string> &directDependencies,
bool checkCompatibility)
4293 for (set<string>::const_iterator i = directDependencies.begin(); i != directDependencies.end(); ++i)
4296 set<string> dependencies;
4297 for (set<string>::iterator i = directDependencies.begin(); i != directDependencies.end(); ++i)
4299 string moduleKey = *i;
4302 vector<VuoDirectedAcyclicGraph::Vertex *> firstPassVertices = dependencyGraph->
findVertex(moduleKey);
4303 set<VuoDirectedAcyclicGraph::Vertex *> firstPassDependencies(firstPassVertices.begin(), firstPassVertices.end());
4304 for (vector<VuoDirectedAcyclicGraph::Vertex *>::iterator j = firstPassVertices.begin(); j != firstPassVertices.end(); ++j)
4307 firstPassDependencies.insert(downstream.begin(), downstream.end());
4311 for (set<VuoDirectedAcyclicGraph::Vertex *>::iterator j = firstPassDependencies.begin(); j != firstPassDependencies.end(); ++j)
4313 DependencyGraphVertex *v = static_cast<DependencyGraphVertex *>(*j);
4318 vector<VuoDirectedAcyclicGraph::Vertex *> moduleVertices = dependencyGraph->
findVertex(moduleKey);
4319 set<VuoDirectedAcyclicGraph::Vertex *> moduleDependencies(moduleVertices.begin(), moduleVertices.end());
4320 for (vector<VuoDirectedAcyclicGraph::Vertex *>::iterator j = moduleVertices.begin(); j != moduleVertices.end(); ++j)
4323 moduleDependencies.insert(downstream.begin(), downstream.end());
4327 set<string> dependenciesToAdd;
4328 set<string> incompatibleDependencies;
4329 for (set<VuoDirectedAcyclicGraph::Vertex *>::iterator j = moduleDependencies.begin(); j != moduleDependencies.end(); ++j)
4331 DependencyGraphVertex *v = static_cast<DependencyGraphVertex *>(*j);
4332 if (! checkCompatibility || ! v->getEnvironment() || v->isCompatible())
4333 dependenciesToAdd.insert(v->getDependency());
4335 incompatibleDependencies.insert(v->getDependency());
4338 if (! checkCompatibility || incompatibleDependencies.empty())
4340 dependencies.insert(dependenciesToAdd.begin(), dependenciesToAdd.end());
4347 string dependencyTargetString;
4352 for (set<string>::iterator i = incompatibleDependencies.begin(); i != incompatibleDependencies.end(); ++i)
4361 dependencyTargetString = dependencyTargets.
toString();
4364 dependencyTargetString =
"(unknown operating systems)";
4366 string modulePlaceholder = (module ?
"%module" :
"%moduleKey");
4368 "Node incompatible with operating system",
4369 modulePlaceholder +
" is only compatible with " + dependencyTargetString +
4370 ", so this composition can't run on your macOS version (" + compositionTargets.
toString() +
").");
4372 issue.setModuleKey(moduleKey);
4378 vector<string> coreDependencies = getCoreVuoDependencies();
4379 dependencies.insert(coreDependencies.begin(), coreDependencies.end());
4381 return dependencies;
4388 void VuoCompiler::getLinkerInputs(
const set<string> &dependencies, Optimization optimization,
4389 set<Module *> &modules, set<string> &libraries, set<string> &frameworks)
4391 set<string> builtInModuleAndLibraryDependencies;
4392 set<string> userModuleAndLibraryDependencies;
4393 map<string, set<string> > builtInCacheDependencies;
4394 map<string, set<string> > userCacheDependencies;
4395 set<Module *> builtInModules;
4396 set<Module *> userModules;
4397 set<string> builtInLibraries;
4398 set<string> userLibraries;
4399 set<string> externalLibraries;
4401 getLinkerInputs(dependencies, optimization,
4402 builtInModuleAndLibraryDependencies, userModuleAndLibraryDependencies, builtInCacheDependencies, userCacheDependencies,
4403 builtInModules, userModules, builtInLibraries, userLibraries, externalLibraries, frameworks);
4405 modules.insert(builtInModules.begin(), builtInModules.end());
4406 modules.insert(userModules.begin(), userModules.end());
4407 libraries.insert(builtInLibraries.begin(), builtInLibraries.end());
4408 libraries.insert(userLibraries.begin(), userLibraries.end());
4409 libraries.insert(externalLibraries.begin(), externalLibraries.end());
4425 void VuoCompiler::getLinkerInputs(
const set<string> &dependencies, Optimization optimization,
4426 set<string> &builtInModuleAndLibraryDependencies, set<string> &userModuleAndLibraryDependencies,
4427 map<
string, set<string> > &builtInCacheDependencies, map<
string, set<string> > &userCacheDependencies,
4428 set<Module *> &builtInModules, set<Module *> &userModules,
4429 set<string> &builtInLibraries, set<string> &userLibraries,
4430 set<string> &externalLibraries, set<string> &externalFrameworks)
4433 if (shouldUseModuleCache)
4436 __block vector<string> librarySearchPaths;
4437 void (^envGetLibrarySearchPaths)(Environment *) = ^
void (Environment *env) {
4438 vector<string> result = env->getLibrarySearchPaths();
4439 librarySearchPaths.insert(librarySearchPaths.end(), result.begin(), result.end());
4441 applyToInstalledEnvironments(envGetLibrarySearchPaths);
4443 for (set<string>::iterator i = dependencies.begin(); i != dependencies.end(); ++i)
4445 string dependency = *i;
4447 bool foundInCache =
false;
4448 string moduleCachePath;
4449 bool isInBuiltInModuleCache =
false;
4450 if (shouldUseModuleCache)
4451 foundInCache = findInModuleCache(dependency, moduleCachePath, isInBuiltInModuleCache);
4455 if (isInBuiltInModuleCache)
4457 builtInLibraries.insert(moduleCachePath);
4458 builtInCacheDependencies[moduleCachePath].insert(dependency);
4462 userLibraries.insert(moduleCachePath);
4463 userCacheDependencies[moduleCachePath].insert(dependency);
4469 void (^envFindModule)(Environment *) = ^
void (Environment *env) {
4474 applyToAllEnvironments(envFindModule);
4478 if (module->getModule())
4480 string modulePath = module->getModulePath();
4481 if (! modulePath.empty() && dynamic_cast<VuoCompilerType *>(module))
4483 if (module->isBuiltIn())
4484 builtInLibraries.insert(modulePath);
4486 userLibraries.insert(modulePath);
4490 if (module->isBuiltIn())
4491 builtInModules.insert(module->getModule());
4493 userModules.insert(module->getModule());
4496 if (module->isBuiltIn())
4497 builtInModuleAndLibraryDependencies.insert(dependency);
4499 userModuleAndLibraryDependencies.insert(dependency);
4505 externalFrameworks.insert(dependency);
4508 string dependencyPath = getLibraryPath(dependency, librarySearchPaths);
4509 if (! dependencyPath.empty())
4510 externalLibraries.insert(dependencyPath);
4512 VUserLog(
"Warning: Could not locate dependency '%s'.", dependency.c_str());
4524 string VuoCompiler::getLibraryPath(
const string &dependency, vector<string> librarySearchPaths)
4531 if (dependency !=
"crypto"
4532 && dependency !=
"ssl")
4533 librarySearchPaths.push_back(
"/usr/lib");
4535 for (
auto &path : librarySearchPaths)
4537 vector<string> variations;
4538 variations.push_back(path +
"/" + dependency);
4539 variations.push_back(path +
"/lib" + dependency);
4540 variations.push_back(path +
"/lib" + dependency +
".dylib");
4541 variations.push_back(path +
"/lib" + dependency +
".a");
4542 for (
auto &variation : variations)
4557 void VuoCompiler::useModuleCache(
bool shouldUseExistingBuiltInCaches,
bool shouldUseExistingOtherCaches)
4559 loadModulesIfNeeded();
4563 dispatch_sync(environmentQueue, ^{
4564 set<string> dylibsForCachesOfInstalledModules;
4565 set<string> frameworksForCachesOfInstalledModules;
4566 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
4568 bool builtin = (i == environments.begin());
4569 set<string> dylibsForCacheOfGeneratedModules;
4570 set<string> frameworksForCacheOfGeneratedModules;
4572 for (
int j = i->size() - 1; j >= 0; --j)
4574 Environment *env = i->at(j);
4575 bool installed = (j == 0);
4577 set<string> cacheableModulesAndDependencies;
4578 set<string> dylibsNeededToLinkToThisCache;
4579 set<string> frameworksNeededToLinkToThisCache;
4580 env->getCacheableModulesAndDependencies(builtin, installed, cacheableModulesAndDependencies,
4581 dylibsNeededToLinkToThisCache, frameworksNeededToLinkToThisCache);
4583 set<string> accumulatedDylibs;
4584 accumulatedDylibs.insert(dylibsNeededToLinkToThisCache.begin(), dylibsNeededToLinkToThisCache.end());
4585 accumulatedDylibs.insert(dylibsForCachesOfInstalledModules.begin(), dylibsForCachesOfInstalledModules.end());
4586 accumulatedDylibs.insert(dylibsForCacheOfGeneratedModules.begin(), dylibsForCacheOfGeneratedModules.end());
4588 set<string> accumulatedFrameworks;
4589 accumulatedFrameworks.insert(frameworksNeededToLinkToThisCache.begin(), frameworksNeededToLinkToThisCache.end());
4590 accumulatedFrameworks.insert(frameworksForCachesOfInstalledModules.begin(), frameworksForCachesOfInstalledModules.end());
4591 accumulatedFrameworks.insert(frameworksForCacheOfGeneratedModules.begin(), frameworksForCacheOfGeneratedModules.end());
4593 bool shouldUseExistingCache = (builtin ? shouldUseExistingBuiltInCaches : shouldUseExistingOtherCaches);
4594 env->useModuleCache(shouldUseExistingCache,
this, cacheableModulesAndDependencies,
4595 accumulatedDylibs, accumulatedFrameworks);
4599 dylibsForCachesOfInstalledModules.insert(dylibsNeededToLinkToThisCache.begin(), dylibsNeededToLinkToThisCache.end());
4600 frameworksForCachesOfInstalledModules.insert(frameworksNeededToLinkToThisCache.begin(), frameworksNeededToLinkToThisCache.end());
4604 dylibsForCacheOfGeneratedModules.insert(dylibsNeededToLinkToThisCache.begin(), dylibsNeededToLinkToThisCache.end());
4605 frameworksForCacheOfGeneratedModules.insert(frameworksNeededToLinkToThisCache.begin(), frameworksNeededToLinkToThisCache.end());
4611 Environment::waitForModuleCachesToBuild();
4622 bool VuoCompiler::findInModuleCache(
const string &moduleOrDependency,
string &cachePath,
bool &isBuiltinCache)
4624 __block
bool found =
false;
4625 __block
string outPath;
4626 __block
bool outBuiltin;
4627 dispatch_sync(environmentQueue, ^{
4628 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
4630 bool builtin = (i == environments.begin());
4632 for (
int j = i->size() - 1; j >= 0; --j)
4634 Environment *env = i->at(j);
4637 bool resultFound = env->findInModuleCache(moduleOrDependency, resultPath);
4641 outPath = resultPath;
4642 outBuiltin = builtin;
4648 cachePath = outPath;
4649 isBuiltinCache = outBuiltin;
4662 dispatch_group_async(moduleCacheBuilding, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
4663 useModuleCache(
true,
false);
4681 vuoFrameworkInProgressPath = vuoFrameworkPath;
4684 compiler.useModuleCache(
false,
true);
4696 unsigned long maxSeconds = 30 * 24 * 60 * 60;
4699 for (set<VuoFileUtilities::File *>::iterator i = cacheDirs.begin(); i != cacheDirs.end(); ++i)
4701 string path = (*i)->path();
4703 string file = (*i)->basename();
4704 if (file !=
"Builtin" && file !=
"System" && file !=
"User")
4707 if (fileSeconds > maxSeconds)
4713 string pidAsString = file.substr(Environment::pidCacheDirPrefix.length());
4714 int pid = atoi(pidAsString.c_str());
4715 if (kill(pid, 0) != 0)
4729 dispatch_sync(modulesToLoadQueue, ^{
4730 this->shouldLoadAllModules = shouldLoadAllModules;
4745 void VuoCompiler::link(
string outputPath,
const set<Module *> &modules,
const set<string> &libraries,
const set<string> &frameworks,
bool isDylib,
string rPath)
4747 VDebugLog(
"Linking '%s'…", outputPath.c_str());
4755 Module *compositeModule =
new Module(
"composite", getGlobalContext());
4756 setTargetForModule(compositeModule);
4757 for (set<Module *>::const_iterator i = modules.begin(); i != modules.end(); ++i)
4760 if (Linker::LinkModules(compositeModule, *i, Linker::PreserveSource, &error))
4761 VUserLog(
"Error: Failed to link compositeModule: %s", error.c_str());
4763 writeModuleToBitcode(compositeModule, compositeModulePath);
4764 delete compositeModule;
4771 llvm::sys::Path clangPath = getClangPath();
4773 vector<const char *> args;
4774 vector<char *> argsToFree;
4775 args.push_back(clangPath.c_str());
4777 args.push_back(compositeModulePath.c_str());
4779 vector<string> coreDependencies = getCoreVuoDependencies();
4780 for (set<string>::const_iterator i = libraries.begin(); i != libraries.end(); ++i)
4782 string library = *i;
4784 for (vector<string>::iterator j = coreDependencies.begin(); j != coreDependencies.end(); ++j)
4786 string coreDependency = *j;
4788 args.push_back(
"-force_load");
4796 library = libraryObject;
4799 char *libraryZ = strdup(library.c_str());
4800 args.push_back(libraryZ);
4801 argsToFree.push_back(libraryZ);
4805 vector<string> frameworkArguments;
4807 __block vector<string> frameworkSearchPaths;
4808 void (^envGetFrameworkSearchPaths)(Environment *) = ^
void (Environment *env) {
4809 vector<string> result = env->getFrameworkSearchPaths();
4810 frameworkSearchPaths.insert(frameworkSearchPaths.end(), result.begin(), result.end());
4812 applyToInstalledEnvironments(envGetFrameworkSearchPaths);
4814 for (vector<string>::const_iterator i = frameworkSearchPaths.begin(); i != frameworkSearchPaths.end(); ++i)
4818 frameworkArguments.push_back(a);
4819 char *frameworkArgument = strdup(a.c_str());
4820 args.push_back(frameworkArgument);
4821 argsToFree.push_back(frameworkArgument);
4824 for (set<string>::const_iterator i = frameworks.begin(); i != frameworks.end(); ++i)
4826 args.push_back(
"-framework");
4828 string frameworkName = *i;
4829 frameworkName = frameworkName.substr(0, frameworkName.length() - string(
".framework").length());
4830 char *frameworkNameZ = strdup(frameworkName.c_str());
4831 args.push_back(frameworkNameZ);
4832 argsToFree.push_back(frameworkNameZ);
4836 llvm::sys::Path cRuntimePath;
4837 llvm::sys::Path crt1Path;
4838 string vuoFrameworkPath = getVuoFrameworkPath();
4839 string vuoFrameworkContainingFolder = vuoFrameworkPath +
"/..";
4840 if (! vuoFrameworkPath.empty())
4842 cRuntimePath = vuoFrameworkPath +
"/Modules/";
4843 crt1Path = cRuntimePath;
4844 crt1Path.appendComponent(
"crt1.o");
4849 if (!isDylib && crt1Path.canRead())
4851 args.push_back(
"-nostartfiles");
4852 args.push_back(crt1Path.c_str());
4856 args.push_back(
"-Xlinker");
4857 args.push_back(
"--no-demangle");
4860 args.push_back(
"-v");
4863 args.push_back(
"-dynamiclib");
4865 args.push_back(
"-Xlinker");
4866 args.push_back(
"-headerpad_max_install_names");
4870 args.push_back(
"-rpath");
4871 string rPathArg = (rPath.empty() ? vuoFrameworkContainingFolder : rPath);
4872 args.push_back(rPathArg.c_str());
4875 args.push_back(
"-rpath");
4876 args.push_back(LLVM_ROOT
"/lib");
4879 args.push_back(
"-std=c++11");
4880 args.push_back(
"-stdlib=libc++");
4883 clang::DiagnosticOptions *diagOptions =
new clang::DiagnosticOptions();
4884 clang::TextDiagnosticPrinter *diagClient =
new clang::TextDiagnosticPrinter(llvm::errs(), diagOptions);
4885 diagClient->setPrefix(clangPath.str());
4886 IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID(
new clang::DiagnosticIDs());
4887 clang::DiagnosticsEngine Diags(DiagID, diagOptions, diagClient);
4889 clang::driver::Driver TheDriver(args[0],
"x86_64-apple-macosx10.10.0", outputPath, Diags);
4891 TheDriver.CCCIsCXX =
true;
4896 for (vector<const char *>::iterator i = args.begin(); i != args.end(); ++i)
4901 OwningPtr<clang::driver::Compilation> C(TheDriver.BuildCompilation(args));
4906 SmallVector<std::pair<int, const clang::driver::Command *>, 4> FailingCommands;
4908 Res = TheDriver.ExecuteCompilation(*C, FailingCommands);
4911 for (
auto i : argsToFree)
4915 remove(compositeModulePath.c_str());
4921 chmod(outputPath.c_str(), 0755);
4925 __block vector<string> thirdPartyNodeClasses;
4926 dispatch_sync(environmentQueue, ^{
4927 for (
size_t i = 1; i < environments.size(); ++i)
4929 map<string, VuoCompilerNodeClass *> envNodeClasses = environments[i].at(0)->getNodeClasses();
4930 for (map<string, VuoCompilerNodeClass *>::iterator j = envNodeClasses.begin(); j != envNodeClasses.end(); ++j)
4931 thirdPartyNodeClasses.push_back(j->first);
4935 string details =
"One or more nodes in this composition can't be used by this version of Vuo. ";
4936 if (! thirdPartyNodeClasses.empty())
4938 details +=
"Make sure you're using the latest version of all the extra Vuo nodes you've installed:\n";
4939 sort(thirdPartyNodeClasses.begin(), thirdPartyNodeClasses.end());
4940 for (vector<string>::iterator i = thirdPartyNodeClasses.begin(); i != thirdPartyNodeClasses.end(); ++i)
4941 details +=
" • " + *i +
"\n";
4943 details +=
"Check the macOS Console for more information about the problem.";
4946 "Node broken or outdated", details);
4957 Module * VuoCompiler::readModuleFromC(
string inputPath,
const vector<string> &headerSearchPaths,
const vector<string> &extraArgs)
4961 vector<const char *> args;
4962 args.push_back(inputPath.c_str());
4963 args.push_back(
"-DVUO_COMPILER");
4964 args.push_back(
"-fblocks");
4967 args.push_back(
"-Wall");
4968 args.push_back(
"-Wextra");
4969 args.push_back(
"-Wimplicit-fallthrough");
4970 args.push_back(
"-Wno-unused-parameter");
4971 args.push_back(
"-Wno-c++11-extensions");
4972 args.push_back(
"-Wno-sign-compare");
4973 args.push_back(
"-Werror=implicit");
4977 args.push_back(
"-std=c++11");
4978 args.push_back(
"-stdlib=libc++");
4981 for (vector<string>::const_iterator i = headerSearchPaths.begin(); i != headerSearchPaths.end(); ++i)
4983 args.push_back(
"-I");
4984 args.push_back(i->c_str());
4988 args.push_back(
"-v");
4990 for (vector<string>::const_iterator i = extraArgs.begin(); i != extraArgs.end(); ++i)
4991 args.push_back(i->c_str());
4993 clang::DiagnosticOptions * diagOptions =
new clang::DiagnosticOptions();
4994 IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID(
new clang::DiagnosticIDs());
4995 clang::DiagnosticsEngine Diags(DiagID, diagOptions);
4997 OwningPtr<clang::CompilerInvocation> CI(
new clang::CompilerInvocation);
4998 clang::CompilerInvocation::CreateFromArgs(*CI, &args[0], &args[0] + args.size(), Diags);
5000 clang::CompilerInstance Clang;
5001 Clang.setInvocation(CI.take());
5003 Clang.createDiagnostics();
5004 if (!Clang.hasDiagnostics())
5008 llvm::sys::Path builtinHeaderSearchPath;
5009 string vuoFrameworkPath = getVuoFrameworkPath();
5010 if (vuoFrameworkPath.empty())
5012 llvm::sys::Path clangPath = getClangPath();
5013 builtinHeaderSearchPath = clangPath;
5014 builtinHeaderSearchPath.eraseComponent();
5015 builtinHeaderSearchPath.eraseComponent();
5016 builtinHeaderSearchPath.appendComponent(
"lib");
5017 builtinHeaderSearchPath.appendComponent(
"clang");
5018 builtinHeaderSearchPath.appendComponent(CLANG_VERSION_STRING);
5022 builtinHeaderSearchPath = vuoFrameworkPath;
5023 builtinHeaderSearchPath.appendComponent(
"Frameworks");
5024 builtinHeaderSearchPath.appendComponent(
"llvm.framework");
5025 builtinHeaderSearchPath.appendComponent(
"Versions");
5026 builtinHeaderSearchPath.appendComponent(
"A");
5027 builtinHeaderSearchPath.appendComponent(
"lib");
5028 builtinHeaderSearchPath.appendComponent(
"clang");
5029 builtinHeaderSearchPath.appendComponent(CLANG_VERSION_STRING);
5031 Clang.getHeaderSearchOpts().ResourceDir = builtinHeaderSearchPath.str();
5034 clang::CodeGenAction *Act =
new clang::EmitLLVMOnlyAction();
5035 if (!Clang.ExecuteAction(*Act))
5038 return Act->takeModule();
5046 Module * VuoCompiler::readModuleFromBitcode(
string inputPath)
5048 string dir, file, ext;
5051 return readModuleFromBitcode(&inputFile);
5063 size_t inputDataBytes;
5068 Module *module = readModuleFromBitcodeData(inputData, inputDataBytes, error);
5083 Module * VuoCompiler::readModuleFromBitcodeData(
char *inputData,
size_t inputDataBytes,
string &error)
5085 __block Module *module;
5087 StringRef inputDataAsStringRef(inputData, inputDataBytes);
5088 MemoryBuffer *mb = MemoryBuffer::getMemBuffer(inputDataAsStringRef,
"",
false);
5089 module = ParseBitcodeFile(&(*mb), getGlobalContext(), &error);
5102 bool VuoCompiler::writeModuleToBitcode(Module *module,
string outputPath)
5104 if (verifyModule(*module, PrintMessageAction))
5106 VUserLog(
"Error: Module verification failed.");
5111 raw_fd_ostream out(outputPath.c_str(), err);
5114 VUserLog(
"Error: Couldn't open file '%s' for writing: %s", outputPath.c_str(), err.c_str());
5117 WriteBitcodeToFile(module, out);
5127 void VuoCompiler::setTargetForModule(Module *module,
string target)
5154 module->setTargetTriple(
"x86_64-apple-macosx10.10.0");
5165 Module *llvmModule = module->
getModule();
5178 baseNodeClass = dynamic_cast<VuoNodeClass *>(nodeClass->
getBase());
5181 if (dynamic_cast<VuoCompilerSpecializedNodeClass *>(module))
5188 baseType = dynamic_cast<VuoType *>(type->
getBase());
5194 delete baseNodeClass;
5227 return nodeClassForNode->
newNode(title, x, y);
5236 return createPublishedNode(nodeClassName, publishedInputPorts);
5245 return createPublishedNode(nodeClassName, publishedOutputPorts);
5251 VuoNode * VuoCompiler::createPublishedNode(
const string &nodeClassName,
const vector<VuoPublishedPort *> &publishedPorts)
5259 for (
size_t i = 0; i < publishedPorts.size(); ++i)
5261 VuoType *publishedPortType = static_cast<VuoCompilerPort *>(publishedPorts[i]->getCompiler())->getDataVuoType();
5262 if (! dynamic_cast<VuoGenericType *>(publishedPortType))
5265 set<VuoPort *> nodePorts;
5269 nodePorts.insert(inputPort);
5272 nodePorts.insert(outputPort);
5277 nodePorts.insert(inputPort);
5280 for (
VuoPort *port : nodePorts)
5282 VuoCompilerPort *compilerPort = static_cast<VuoCompilerPort *>(port->getCompiler());
5287 reifyGenericPortTypes(node);
5298 dispatch_sync(environmentQueue, ^{
5299 if (environments.size() >= 5)
5300 environments.at(3).at(0)->addExpatriateSourceFile(sourcePath);
5310 dispatch_sync(environmentQueue, ^{
5311 if (environments.size() >= 5)
5313 environments.at(3).at(0)->removeExpatriateSourceFile(sourcePath);
5315 set<string> sourcesRemoved;
5317 loadModulesAndSources(set<string>(), set<string>(), set<string>(), set<string>(), set<string>(), sourcesRemoved,
5318 false,
false, environments.at(3).at(0),
nullptr,
nullptr,
"");
5341 string sourcePathCopy = sourcePath;
5342 string sourceCodeCopy = sourceCode;
5344 dispatch_async(environmentQueue, ^{
5346 ModuleInfo *sourceInfo = NULL;
5348 for (
const vector<Environment *> &envs : environments)
5350 for (Environment *env : envs)
5352 ModuleInfo *potentialSourceInfo = env->listSourceFile(nodeClassName);
5355 sourceInfo = potentialSourceInfo;
5364 bool shouldRecompileSourcesIfUnchanged;
5365 if (! sourceCodeCopy.empty())
5367 sourceInfo->setSourceCode(sourceCodeCopy);
5368 sourceInfo->setSourceCodeOverridden(
true);
5370 shouldRecompileSourcesIfUnchanged =
false;
5374 sourceInfo->revertSourceCode();
5375 sourceInfo->setSourceCodeOverridden(
false);
5377 shouldRecompileSourcesIfUnchanged =
true;
5379 sourceInfo->setAttempted(
false);
5380 sourceInfo->setLastModifiedToNow();
5382 set<string> sourcesModified;
5383 sourcesModified.insert(nodeClassName);
5385 loadModulesAndSources(set<string>(), set<string>(), set<string>(), set<string>(), sourcesModified, set<string>(),
5386 false, shouldRecompileSourcesIfUnchanged,
nullptr,
nullptr,
nullptr,
"");
5425 set<string> nodeClassNameSet;
5426 nodeClassNameSet.insert(nodeClassName);
5427 loadModulesIfNeeded(nodeClassNameSet);
5432 void (^envGetNodeClass)(Environment *) = ^
void (Environment *env) {
5437 applyToAllEnvironments(envGetNodeClass);
5448 loadModulesIfNeeded();
5450 __block map<string, VuoCompilerNodeClass *> nodeClasses;
5451 void (^envGetNodeClasses)(Environment *) = ^
void (Environment *env) {
5452 map<string, VuoCompilerNodeClass *> result = env->getNodeClasses();
5453 nodeClasses.insert(result.begin(), result.end());
5455 applyToInstalledEnvironments(envGetNodeClasses);
5466 set<string> typeNameSet;
5467 typeNameSet.insert(typeName);
5468 loadModulesIfNeeded(typeNameSet);
5471 void (^envGetType)(Environment *) = ^
void (Environment *env) {
5476 applyToInstalledEnvironments(envGetType);
5498 loadModulesIfNeeded();
5500 __block map<string, VuoCompilerType *> types;
5501 void (^envGetTypes)(Environment *) = ^
void (Environment *env) {
5502 map<string, VuoCompilerType *> result = env->getTypes();
5503 types.insert(result.begin(), result.end());
5505 applyToInstalledEnvironments(envGetTypes);
5516 loadModulesIfNeeded();
5518 __block map<string, VuoCompilerModule *> libraryModules;
5519 void (^envGetLibraryModules)(Environment *) = ^
void (Environment *env) {
5520 map<string, VuoCompilerModule *> result = env->getLibraryModules();
5521 libraryModules.insert(result.begin(), result.end());
5523 applyToInstalledEnvironments(envGetLibraryModules);
5524 return libraryModules;
5534 loadModulesIfNeeded();
5536 __block map<string, VuoNodeSet *> nodeSets;
5537 void (^envGetNodeSets)(Environment *) = ^
void (Environment *env) {
5538 map<string, VuoNodeSet *> result = env->getNodeSets();
5539 nodeSets.insert(result.begin(), result.end());
5541 applyToInstalledEnvironments(envGetNodeSets);
5552 loadModulesIfNeeded();
5555 void (^envFindNodeSet)(Environment *) = ^
void (Environment *env) {
5560 applyToInstalledEnvironments(envFindNodeSet);
5570 void (^envFindModule)(Environment *) = ^
void (Environment *env) {
5575 applyToAllEnvironments(envFindModule);
5592 map<string, VuoCompilerNodeClass *> nodeClasses =
getNodeClasses();
5593 for (map<string, VuoCompilerNodeClass *>::const_iterator i = nodeClasses.begin(); i != nodeClasses.end(); ++i)
5600 else if (format ==
"path")
5604 else if (format ==
"dot")
5622 vector<string> VuoCompiler::getCoreVuoDependencies(
void)
5624 vector<string> dependencies;
5625 dependencies.push_back(
"VuoCompositionDiff.o");
5626 dependencies.push_back(
"VuoHeap");
5627 dependencies.push_back(
"VuoException.o");
5628 dependencies.push_back(
"VuoNodeRegistry.o");
5629 dependencies.push_back(
"VuoRuntimeCommunicator.o");
5630 dependencies.push_back(
"VuoRuntimeContext.o");
5631 dependencies.push_back(
"VuoRuntimePersistentState.o");
5632 dependencies.push_back(
"VuoRuntimeState.o");
5633 dependencies.push_back(
"VuoTelemetry.o");
5634 dependencies.push_back(
"VuoThreadManager.o");
5635 dependencies.push_back(
"VuoApp");
5636 dependencies.push_back(
"zmq");
5637 dependencies.push_back(
"json-c");
5638 dependencies.push_back(
"objc");
5639 dependencies.push_back(
"c");
5640 dependencies.push_back(
"AppKit.framework");
5643 dependencies.push_back(LLVM_ROOT
"/lib/libprofile_rt.dylib");
5645 return dependencies;
5651 string VuoCompiler::getRuntimeMainDependency(
void)
5653 return "VuoRuntimeMain.o";
5663 string VuoCompiler::getRuntimeDependency(
void)
5665 return "VuoRuntime.o";
5674 string VuoCompiler::getVuoFrameworkPath(
void)
5676 if (! vuoFrameworkInProgressPath.empty())
5677 return vuoFrameworkInProgressPath;
5685 llvm::sys::Path VuoCompiler::getClangPath(
void)
5696 string dir, moduleKey, ext;
5704 while (nodeClassNameParts.size() > 1 && nodeClassNameParts.back() == ext)
5705 nodeClassNameParts.pop_back();
5708 for (
string &part : nodeClassNameParts)
5712 if (nodeClassNameParts.size() == 1)
5713 nodeClassNameParts.insert(nodeClassNameParts.begin(),
"isf");
5727 __block
bool isLocal =
false;
5729 dispatch_sync(environmentQueue, ^{
5730 if (environments.size() >= 5)
5731 isLocal = environments.at(3).at(0)->findModule(moduleKey);
5745 return lastCompositionBaseDir.empty() ?
"" : lastCompositionBaseDir +
"/Modules";
5760 return lastCompositionBaseDir;
5766 void VuoCompiler::addModuleSearchPath(
string path)
5768 dispatch_sync(environmentQueue, ^{
5769 environments.back().at(0)->addModuleSearchPath(path);
5770 environments.back().at(0)->addLibrarySearchPath(path);
5779 dispatch_sync(environmentQueue, ^{
5780 environments.back().at(0)->addHeaderSearchPath(path);
5789 dispatch_sync(environmentQueue, ^{
5790 environments.back().at(0)->addLibrarySearchPath(path);
5799 dispatch_sync(environmentQueue, ^{
5800 environments.back().at(0)->addFrameworkSearchPath(path);
5809 this->telemetry = telemetry;
5817 this->target = target;
5825 this->isVerbose = isVerbose;
5835 if (VuoPro::getProAccess())
5837 _shouldShowSplashWindow =
false;
5842 _shouldShowSplashWindow = potentiallyShow;
5850 return _shouldShowSplashWindow;
5856 void VuoCompiler::setClangPath(
const string &clangPath)
5858 this->clangPath = llvm::sys::Path(StringRef(clangPath));
5866 string vuoFrameworkPath = getVuoFrameworkPath();
5867 return (vuoFrameworkPath.empty() ?
5868 VUO_BUILD_DIR
"/bin/VuoCompositionLoader.app/Contents/MacOS/VuoCompositionLoader" :
5869 vuoFrameworkPath +
"/Helpers/VuoCompositionLoader.app/Contents/MacOS/VuoCompositionLoader");
5875 string VuoCompiler::getCompositionStubPath(
void)
5877 string vuoFrameworkPath = getVuoFrameworkPath();
5878 return (vuoFrameworkPath.empty() ?
5879 VUO_BUILD_DIR
"/lib/libVuoCompositionStub.dylib" :
5880 vuoFrameworkPath +
"/Modules/libVuoCompositionStub.dylib");
5886 string VuoCompiler::getCachePathForComposition(
const string compositionDir)
5888 string modifierLetterColon(
"꞉");
5889 string cachedModulesName = compositionDir;
5899 __block vector<string> moduleSearchPaths;
5900 void (^envGetModuleSearchPaths)(Environment *) = ^
void (Environment *env) {
5901 vector<string> result = env->getModuleSearchPaths();
5902 moduleSearchPaths.insert(moduleSearchPaths.end(), result.begin(), result.end());
5904 applyToInstalledEnvironments(envGetModuleSearchPaths);
5906 __block vector<string> headerSearchPaths;
5907 void (^envGetHeaderSearchPaths)(Environment *) = ^
void (Environment *env) {
5908 vector<string> result = env->getHeaderSearchPaths();
5909 headerSearchPaths.insert(headerSearchPaths.end(), result.begin(), result.end());
5911 applyToInstalledEnvironments(envGetHeaderSearchPaths);
5913 __block vector<string> librarySearchPaths;
5914 void (^envGetLibrarySearchPaths)(Environment *) = ^
void (Environment *env) {
5915 vector<string> result = env->getLibrarySearchPaths();
5916 librarySearchPaths.insert(librarySearchPaths.end(), result.begin(), result.end());
5918 applyToInstalledEnvironments(envGetLibrarySearchPaths);
5920 __block vector<string> frameworkSearchPaths;
5921 void (^envGetFrameworkSearchPaths)(Environment *) = ^
void (Environment *env) {
5922 vector<string> result = env->getFrameworkSearchPaths();
5923 frameworkSearchPaths.insert(frameworkSearchPaths.end(), result.begin(), result.end());
5925 applyToInstalledEnvironments(envGetFrameworkSearchPaths);
5927 fprintf(stderr,
"Module (node class, type, library) search paths:\n");
5928 for (vector<string>::iterator i = moduleSearchPaths.begin(); i != moduleSearchPaths.end(); ++i)
5929 fprintf(stderr,
" %s\n", (*i).c_str());
5930 fprintf(stderr,
"Header search paths:\n");
5931 for (vector<string>::iterator i = headerSearchPaths.begin(); i != headerSearchPaths.end(); ++i)
5932 fprintf(stderr,
" %s\n", (*i).c_str());
5933 fprintf(stderr,
"Other library search paths:\n");
5934 for (vector<string>::iterator i = librarySearchPaths.begin(); i != librarySearchPaths.end(); ++i)
5935 fprintf(stderr,
" %s\n", (*i).c_str());
5936 fprintf(stderr,
"Other framework search paths:\n");
5937 for (vector<string>::iterator i = frameworkSearchPaths.begin(); i != frameworkSearchPaths.end(); ++i)
5938 fprintf(stderr,
" %s\n", (*i).c_str());
5939 fprintf(stderr,
"Framework path:\n");
5940 if (! getVuoFrameworkPath().empty())
5941 fprintf(stderr,
" %s\n", getVuoFrameworkPath().c_str());
5942 fprintf(stderr,
"Clang path:\n");
5943 if (! getClangPath().str().empty())
5944 fprintf(stderr,
" %s\n", getClangPath().c_str());
5960 string directory, file, extension;
5964 compiler.
compileComposition(compositionFilePath, compiledCompositionPath,
true, issues);
5966 remove(compiledCompositionPath.c_str());
5995 string compositionPath = (workingDirectory.empty() ?
"." : workingDirectory) +
"/" + processName +
".vuo";
6001 remove(compiledCompositionPath.c_str());
6025 string directory, file, extension;
6028 compiler.
compileComposition(compositionFilePath, compiledCompositionPath,
true, issues);
6031 remove(compiledCompositionPath.c_str());
6060 string compositionPath = (workingDirectory.empty() ?
"." : workingDirectory) +
"/UntitledComposition.vuo";
6066 remove(compiledCompositionPath.c_str());
6079 pendingDataQueue = dispatch_queue_create(
"org.vuo.compiler.delegate.pending", 0);
6084 LoadedModulesData *data = dequeueData();
6091 void VuoCompilerDelegate::enqueueData(LoadedModulesData *data)
6093 dispatch_sync(pendingDataQueue, ^{
6094 pendingData.push_back(data);
6101 VuoCompilerDelegate::LoadedModulesData * VuoCompilerDelegate::dequeueData(
void)
6103 __block LoadedModulesData *ret;
6104 dispatch_sync(pendingDataQueue, ^{
6105 ret = pendingData.front();
6106 pendingData.pop_front();
6115 VuoCompilerDelegate::LoadedModulesData::LoadedModulesData(
const set< pair<VuoCompilerModule *, VuoCompilerModule *> > &modulesModified,
6118 referenceCountQueue = dispatch_queue_create(
"org.vuo.compiler.delegate.reference", 0);
6121 this->modulesModified = modulesModified;
6122 this->modulesRemoved = modulesRemoved;
6123 this->issues = issues;
6129 VuoCompilerDelegate::LoadedModulesData::~LoadedModulesData(
void)
6133 for (set< pair<VuoCompilerModule *, VuoCompilerModule *> >::iterator i = modulesModified.begin(); i != modulesModified.end(); ++i)
6136 for (set<VuoCompilerModule *>::iterator i = modulesRemoved.begin(); i != modulesRemoved.end(); ++i)
6143 void VuoCompilerDelegate::LoadedModulesData::retain(
void)
6145 dispatch_sync(referenceCountQueue, ^{
6153 void VuoCompilerDelegate::LoadedModulesData::release(
void)
6155 dispatch_sync(referenceCountQueue, ^{
6157 if (referenceCount == 0) {