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)
166 dispatch_release(loading);
169 VuoCompiler::Environment * VuoCompiler::ModuleInfo::getEnvironment(
void)
const
174 string VuoCompiler::ModuleInfo::getSearchPath(
void)
const
179 string VuoCompiler::ModuleInfo::getModuleKey(
void)
const
189 string VuoCompiler::ModuleInfo::getSourceCode(
void)
const
194 void VuoCompiler::ModuleInfo::setSourceCode(
const string &sourceCode)
196 this->sourceCode = sourceCode;
199 void VuoCompiler::ModuleInfo::revertSourceCode(
void)
204 bool VuoCompiler::ModuleInfo::isSourceCodeOverridden(
void)
const
206 return sourceCodeOverridden;
209 void VuoCompiler::ModuleInfo::setSourceCodeOverridden(
bool overridden)
211 sourceCodeOverridden = overridden;
214 bool VuoCompiler::ModuleInfo::isNewerThan(ModuleInfo *other)
const
216 return lastModified > other->lastModified;
219 bool VuoCompiler::ModuleInfo::isNewerThan(
unsigned long ageInSeconds)
const
221 return lastModified > ageInSeconds;
224 bool VuoCompiler::ModuleInfo::isOlderThan(
unsigned long ageInSeconds)
const
226 return lastModified < ageInSeconds;
229 void VuoCompiler::ModuleInfo::setLastModifiedToNow(
void)
232 gettimeofday(&t, NULL);
233 lastModified = t.tv_sec;
236 set<string> VuoCompiler::ModuleInfo::getContainedNodeClasses(
void)
const
238 return containedNodeClasses;
241 bool VuoCompiler::ModuleInfo::getAttempted(
void)
const
246 void VuoCompiler::ModuleInfo::setAttempted(
bool attempted)
248 this->attempted = attempted;
251 dispatch_group_t VuoCompiler::ModuleInfo::getLoadingGroup(
void)
const
256 void VuoCompiler::ModuleInfo::dump()
const
258 fprintf(stderr,
"module %s:\n"
259 "\tloadingGroup=%p\n"
264 "\tsourceCodeOverridden=%d\n"
266 "\tcontainedNodeClasses:\n",
271 environment->getCompiledModuleCachePath().c_str(),
275 sourceCodeOverridden,
277 for (
auto i: containedNodeClasses)
278 fprintf(stderr,
"\t\t%s\n", i.c_str());
281 VuoCompiler::DependencyGraphVertex * VuoCompiler::DependencyGraphVertex::vertexForDependency(
const string &dependency,
VuoDirectedAcyclicGraph *graph)
285 return dynamic_cast<DependencyGraphVertex *>(v);
287 DependencyGraphVertex *vv =
new DependencyGraphVertex();
288 vv->dependency = dependency;
289 vv->environment = NULL;
290 vv->compatible =
true;
294 string VuoCompiler::DependencyGraphVertex::getDependency(
void)
299 VuoCompiler::Environment * VuoCompiler::DependencyGraphVertex::getEnvironment(
void)
304 void VuoCompiler::DependencyGraphVertex::setEnvironment(Environment *environment)
306 this->environment = environment;
309 bool VuoCompiler::DependencyGraphVertex::isCompatible(
void)
314 void VuoCompiler::DependencyGraphVertex::setCompatible(
bool compatible)
316 this->compatible = compatible;
319 string VuoCompiler::DependencyGraphVertex::key(
void)
329 VuoCompiler::ModuleInfoIterator::ModuleInfoIterator(map<
string, map<string, ModuleInfo *> > *allModuleInfos)
331 this->allModuleInfos = allModuleInfos;
332 hasSearchModuleKeys =
false;
341 VuoCompiler::ModuleInfoIterator::ModuleInfoIterator(map<
string, map<string, ModuleInfo *> > *allModuleInfos,
const set<string> &searchModuleKeys)
343 this->allModuleInfos = allModuleInfos;
344 this->searchModuleKeys = searchModuleKeys;
345 hasSearchModuleKeys =
true;
354 void VuoCompiler::ModuleInfoIterator::initialize(
void)
356 currSearchPath = allModuleInfos->begin();
357 hasCurrModuleKey =
false;
365 VuoCompiler::ModuleInfo * VuoCompiler::ModuleInfoIterator::next(
void)
367 for ( ; currSearchPath != allModuleInfos->end(); ++currSearchPath)
369 if (! hasCurrModuleKey)
371 currModuleKey = currSearchPath->second.begin();
372 hasCurrModuleKey =
true;
375 for ( ; currModuleKey != currSearchPath->second.end(); ++currModuleKey)
377 if (! hasSearchModuleKeys || searchModuleKeys.find(currModuleKey->first) != searchModuleKeys.end())
379 ModuleInfo *moduleInfo = currModuleKey->second;
385 hasCurrModuleKey =
false;
394 VuoCompiler::Environment::Environment(
void)
396 compilersToNotifyQueue = dispatch_queue_create(
"org.vuo.compiler.notify", 0);
397 moduleSearchPathContentsChangedQueue = dispatch_queue_create(
"org.vuo.compiler.watch", 0);
398 isModuleCacheableDataDirty =
false;
399 isModuleCacheInitialized =
false;
400 isModuleCacheAvailable =
false;
409 VuoCompiler::Environment::~Environment(
void)
411 stopWatchingModuleSearchPaths();
412 dispatch_sync(moduleSearchPathContentsChangedQueue, ^{});
414 dispatch_release(moduleSearchPathContentsChangedQueue);
415 dispatch_release(compilersToNotifyQueue);
417 for (map<string, VuoCompilerNodeClass *>::iterator i = nodeClasses.begin(); i != nodeClasses.end(); ++i)
418 destroyModule(i->second);
420 for (map<string, VuoCompilerType *>::iterator i = types.begin(); i != types.end(); ++i)
421 destroyModule(i->second);
423 for (map<string, VuoCompilerModule *>::iterator i = libraryModules.begin(); i != libraryModules.end(); ++i)
424 destroyModule(i->second);
426 for (set<VuoCompilerGenericType *>::iterator i = genericTypes.begin(); i != genericTypes.end(); ++i)
428 VuoType *base = (*i)->getBase();
433 for (map<string, VuoNodeSet *>::iterator i = nodeSetForName.begin(); i != nodeSetForName.end(); ++i)
436 for (map<
string, map<string, ModuleInfo *> >::iterator i = moduleFilesAtSearchPath.begin(); i != moduleFilesAtSearchPath.end(); ++i)
437 for (map<string, ModuleInfo *>::iterator j = i->second.begin(); j != i->second.end(); ++j)
440 for (map<
string, map<string, ModuleInfo *> >::iterator i = sourceFilesAtSearchPath.begin(); i != sourceFilesAtSearchPath.end(); ++i)
441 for (map<string, ModuleInfo *>::iterator j = i->second.begin(); j != i->second.end(); ++j)
444 delete dependencyGraph;
445 delete compositionDependencyGraph;
451 void VuoCompiler::Environment::addCompilerToNotify(
VuoCompiler *compiler)
453 dispatch_sync(compilersToNotifyQueue, ^{
454 compilersToNotify.insert(compiler);
461 void VuoCompiler::Environment::removeCompilerToNotify(
VuoCompiler *compiler)
463 dispatch_sync(compilersToNotifyQueue, ^{
464 compilersToNotify.erase(compiler);
473 map<string, VuoCompilerNodeClass *> VuoCompiler::Environment::getNodeClasses(
void)
485 map<string, VuoCompilerNodeClass *>::iterator nodeClassIter = nodeClasses.find(moduleKey);
486 if (nodeClassIter != nodeClasses.end())
487 return nodeClassIter->second;
500 map<string, VuoCompilerNodeClass *>::iterator nodeClassIter = nodeClasses.find(moduleKey);
501 if (nodeClassIter != nodeClasses.end())
503 nodeClass = nodeClassIter->second;
505 nodeClasses.erase(nodeClassIter);
506 removeFromDependencyGraph(nodeClass);
518 map<string, VuoCompilerType *> VuoCompiler::Environment::getTypes(
void)
528 VuoCompilerType * VuoCompiler::Environment::getType(
const string &moduleKey)
530 map<string, VuoCompilerType *>::iterator typeIter = types.find(moduleKey);
531 if (typeIter != types.end())
532 return typeIter->second;
542 map<string, VuoNodeSet *> VuoCompiler::Environment::getNodeSets(
void)
544 return nodeSetForName;
552 map<string, VuoCompilerModule *> VuoCompiler::Environment::getLibraryModules(
void)
554 return libraryModules;
563 VuoCompilerModule * VuoCompiler::Environment::findModule(
const string &moduleKey)
565 map<string, VuoCompilerNodeClass *>::iterator nodeClassIter = nodeClasses.find(moduleKey);
566 if (nodeClassIter != nodeClasses.end())
567 return nodeClassIter->second;
569 map<string, VuoCompilerType *>::iterator typeIter = types.find(moduleKey);
570 if (typeIter != types.end())
571 return typeIter->second;
573 map<string, VuoCompilerModule *>::iterator libraryIter = libraryModules.find(moduleKey);
574 if (libraryIter != libraryModules.end())
575 return libraryIter->second;
585 VuoNodeSet * VuoCompiler::Environment::findNodeSet(
const string &name)
588 map<string, VuoNodeSet *>::iterator nodeSetIter = nodeSetForName.find(name);
589 if (nodeSetIter != nodeSetForName.end())
590 return nodeSetIter->second;
601 void VuoCompiler::Environment::addModuleSearchPath(
const string &path,
bool shouldWatch)
603 moduleSearchPaths.push_back(path);
605 updateModulesAtSearchPath(path);
606 updateSourceFilesAtSearchPath(path);
609 startWatchingModuleSearchPath(path);
617 vector<string> VuoCompiler::Environment::getModuleSearchPaths(
void)
619 return moduleSearchPaths;
627 void VuoCompiler::Environment::addHeaderSearchPath(
const string &path)
629 headerSearchPaths.push_back(path);
637 vector<string> VuoCompiler::Environment::getHeaderSearchPaths(
void)
639 return headerSearchPaths;
647 void VuoCompiler::Environment::addLibrarySearchPath(
const string &path)
649 librarySearchPaths.push_back(path);
657 vector<string> VuoCompiler::Environment::getLibrarySearchPaths(
void)
659 return librarySearchPaths;
667 void VuoCompiler::Environment::addFrameworkSearchPath(
const string &path)
669 frameworkSearchPaths.push_back(path);
677 vector<string> VuoCompiler::Environment::getFrameworkSearchPaths(
void)
679 return frameworkSearchPaths;
684 return dependencyGraph;
689 return compositionDependencyGraph;
697 void VuoCompiler::Environment::setModuleCachePath(
const string &path)
699 moduleCachePath = path;
707 string VuoCompiler::Environment::getCompiledModuleCachePath(
void)
709 return (moduleCachePath.empty() ?
"" : moduleCachePath +
"/Modules");
717 string VuoCompiler::Environment::getOverriddenCompiledModuleCachePath(
void)
719 if (moduleCachePath.empty())
725 string dir, moduleCacheDirName, ext;
738 void VuoCompiler::Environment::addExpatriateSourceFile(
const string &sourcePath)
740 expatriateSourceFiles.push_back(sourcePath);
742 if (find(moduleSearchPaths.begin(), moduleSearchPaths.end(),
"") == moduleSearchPaths.end())
743 moduleSearchPaths.push_back(
"");
745 auto iter = sourceFilesAtSearchPath.find(
"");
746 if (iter != sourceFilesAtSearchPath.end())
747 sourceFilesAtSearchPath.erase(iter);
755 void VuoCompiler::Environment::removeExpatriateSourceFile(
const string &sourcePath)
757 for (
auto i = expatriateSourceFiles.begin(); i != expatriateSourceFiles.end(); ++i)
761 expatriateSourceFiles.erase(i);
763 auto iter = sourceFilesAtSearchPath.find(
"");
764 if (iter != sourceFilesAtSearchPath.end())
765 sourceFilesAtSearchPath.erase(iter);
784 void VuoCompiler::Environment::updateModulesAtSearchPath(
const string &path,
bool shouldCleanModuleCache)
786 if (moduleFilesAtSearchPath.find(path) != moduleFilesAtSearchPath.end())
789 set<string> moduleExtensions;
790 moduleExtensions.insert(
"vuonode");
791 moduleExtensions.insert(
"vuonode+");
792 moduleExtensions.insert(
"bc");
793 moduleExtensions.insert(
"bc+");
794 set<string> archiveExtensions;
795 archiveExtensions.insert(
"vuonode");
798 map<string, ModuleInfo *> fileForModuleKey;
799 for (set<VuoFileUtilities::File *>::iterator i = moduleFiles.begin(); i != moduleFiles.end(); ++i)
803 ModuleInfo *m =
new ModuleInfo(
this, path, moduleFile,
false,
false);
804 fileForModuleKey[m->getModuleKey()] = m;
807 if (shouldCleanModuleCache && path == getCompiledModuleCachePath())
809 for (map<string, ModuleInfo *>::iterator i = fileForModuleKey.begin(); i != fileForModuleKey.end(); )
811 ModuleInfo *sourceInfo = listSourceFile(i->first);
812 if (! sourceInfo || sourceInfo->isNewerThan(i->second))
814 ModuleInfo *m = i->second;
817 fileForModuleKey.erase(i++);
824 moduleFilesAtSearchPath[path] = fileForModuleKey;
834 void VuoCompiler::Environment::updateSourceFilesAtSearchPath(
const string &path)
836 map<string, map<string, ModuleInfo *> >::iterator sourceFilesIter = sourceFilesAtSearchPath.find(path);
837 if (sourceFilesIter != sourceFilesAtSearchPath.end())
840 set<VuoFileUtilities::File *> sourceFiles;
843 set<string> sourceExtensions;
844 sourceExtensions.insert(
"vuo");
845 sourceExtensions.insert(
"fs");
847 sourceExtensions.insert(cext.begin(), cext.end());
852 for (
const string &sourcePath : expatriateSourceFiles)
854 string dir, file, ext;
857 sourceFiles.insert(sourceFile);
861 map<string, ModuleInfo *> fileForModuleKey;
862 for (set<VuoFileUtilities::File *>::iterator i = sourceFiles.begin(); i != sourceFiles.end(); ++i)
866 string dir, moduleKey, ext;
868 bool isSubcomposition = (ext ==
"vuo");
871 if (path.empty() && !sourceFile->
exists())
874 ModuleInfo *m =
new ModuleInfo(
this, path, sourceFile,
true, isSubcomposition);
875 if (fileForModuleKey.find(m->getModuleKey()) != fileForModuleKey.end())
876 VUserLog(
"Warning: Conflicting source files for module %s are installed at %s", m->getModuleKey().c_str(), path.c_str());
877 fileForModuleKey[m->getModuleKey()] = m;
879 if (isSubcomposition)
881 DependencyGraphVertex *compositionVertex = DependencyGraphVertex::vertexForDependency(moduleKey, compositionDependencyGraph);
882 compositionDependencyGraph->addVertex(compositionVertex);
884 compositionVertex->setEnvironment(
this);
886 set<string> dependencies = m->getContainedNodeClasses();
887 for (set<string>::iterator j = dependencies.begin(); j != dependencies.end(); ++j)
889 DependencyGraphVertex *dependencyVertex = DependencyGraphVertex::vertexForDependency(*j, compositionDependencyGraph);
890 compositionDependencyGraph->addEdge(compositionVertex, dependencyVertex);
895 sourceFilesAtSearchPath[path] = fileForModuleKey;
903 VuoCompiler::ModuleInfo * VuoCompiler::Environment::listModule(
const string &moduleKey)
905 for (
const auto &moduleFiles : moduleFilesAtSearchPath)
907 map<string, ModuleInfo *>::const_iterator foundIter = moduleFiles.second.find(moduleKey);
908 if (foundIter != moduleFiles.second.end())
909 return foundIter->second;
920 VuoCompiler::ModuleInfoIterator VuoCompiler::Environment::listModules(
const set<string> &moduleKeys)
922 for (
const string &path : moduleSearchPaths)
923 updateModulesAtSearchPath(path);
925 return ModuleInfoIterator(&moduleFilesAtSearchPath, moduleKeys);
933 VuoCompiler::ModuleInfoIterator VuoCompiler::Environment::listAllModules(
void)
935 for (
const string &path : moduleSearchPaths)
936 updateModulesAtSearchPath(path);
938 return ModuleInfoIterator(&moduleFilesAtSearchPath);
946 VuoCompiler::ModuleInfo * VuoCompiler::Environment::listSourceFile(
const string &moduleKey)
948 for (
const auto &sourceFiles : sourceFilesAtSearchPath)
950 map<string, ModuleInfo *>::const_iterator foundIter = sourceFiles.second.find(moduleKey);
951 if (foundIter != sourceFiles.second.end())
952 return foundIter->second;
963 VuoCompiler::ModuleInfoIterator VuoCompiler::Environment::listSourceFiles(
const set<string> &moduleKeys)
965 for (
const string &path : moduleSearchPaths)
966 updateSourceFilesAtSearchPath(path);
968 return ModuleInfoIterator(&sourceFilesAtSearchPath, moduleKeys);
976 VuoCompiler::ModuleInfoIterator VuoCompiler::Environment::listAllSourceFiles(
void)
978 for (
const string &path : moduleSearchPaths)
979 updateSourceFilesAtSearchPath(path);
981 return ModuleInfoIterator(&sourceFilesAtSearchPath);
987 vector<string> VuoCompiler::Environment::getBuiltInModuleSearchPaths(
void)
989 vector<string> builtInModuleSearchPaths;
991 string vuoFrameworkPath = getVuoFrameworkPath();
992 if (! vuoFrameworkPath.empty())
994 builtInModuleSearchPaths.push_back(vuoFrameworkPath +
"/Modules");
998 builtInModuleSearchPaths.push_back(VUO_BUILD_DIR
"/library");
999 builtInModuleSearchPaths.push_back(VUO_BUILD_DIR
"/node");
1000 builtInModuleSearchPaths.push_back(VUO_BUILD_DIR
"/type");
1001 builtInModuleSearchPaths.push_back(VUO_BUILD_DIR
"/type/list");
1004 return builtInModuleSearchPaths;
1010 vector<string> VuoCompiler::Environment::getBuiltInHeaderSearchPaths(
void)
1012 vector<string> builtInHeaderSearchPaths;
1014 string vuoFrameworkPath = getVuoFrameworkPath();
1015 if (! vuoFrameworkPath.empty())
1017 builtInHeaderSearchPaths.push_back(vuoFrameworkPath +
"/Headers");
1018 builtInHeaderSearchPaths.push_back(vuoFrameworkPath +
"/Headers/macos");
1019 builtInHeaderSearchPaths.push_back(vuoFrameworkPath +
"/Frameworks/llvm.framework/Versions/A/Headers/lib/c++/v1");
1023 builtInHeaderSearchPaths.push_back(VUO_SOURCE_DIR
"/library");
1024 builtInHeaderSearchPaths.push_back(VUO_SOURCE_DIR
"/node");
1025 builtInHeaderSearchPaths.push_back(VUO_SOURCE_DIR
"/type");
1026 builtInHeaderSearchPaths.push_back(VUO_SOURCE_DIR
"/type/list");
1027 builtInHeaderSearchPaths.push_back(VUO_SOURCE_DIR
"/runtime");
1028 builtInHeaderSearchPaths.push_back(JSONC_ROOT
"/include");
1029 builtInHeaderSearchPaths.push_back(LLVM_ROOT
"/include/c++/v1");
1032 return builtInHeaderSearchPaths;
1038 vector<string> VuoCompiler::Environment::getBuiltInLibrarySearchPaths(
void)
1040 vector<string> builtInLibrarySearchPaths;
1042 string vuoFrameworkPath = getVuoFrameworkPath();
1043 if (! vuoFrameworkPath.empty())
1045 builtInLibrarySearchPaths.push_back(vuoFrameworkPath +
"/Modules");
1048 builtInLibrarySearchPaths.push_back(OPENSSL_ROOT
"/lib");
1052 builtInLibrarySearchPaths.push_back(VUO_BUILD_DIR
"/library");
1053 builtInLibrarySearchPaths.push_back(VUO_BUILD_DIR
"/node");
1054 builtInLibrarySearchPaths.push_back(VUO_BUILD_DIR
"/type");
1055 builtInLibrarySearchPaths.push_back(VUO_BUILD_DIR
"/type/list");
1056 builtInLibrarySearchPaths.push_back(VUO_BUILD_DIR
"/runtime");
1058 builtInLibrarySearchPaths.push_back(LEAP_ROOT);
1061 builtInLibrarySearchPaths.insert(builtInLibrarySearchPaths.end(), conanLibDirs.begin(), conanLibDirs.end());
1064 return builtInLibrarySearchPaths;
1070 vector<string> VuoCompiler::Environment::getBuiltInFrameworkSearchPaths(
void)
1072 vector<string> builtInFrameworkSearchPaths;
1074 string vuoFrameworkPath = getVuoFrameworkPath();
1075 if (! vuoFrameworkPath.empty())
1077 builtInFrameworkSearchPaths.push_back(vuoFrameworkPath +
"/Modules/");
1078 builtInFrameworkSearchPaths.push_back(vuoFrameworkPath +
"/Frameworks/");
1082 builtInFrameworkSearchPaths.push_back(SYPHON_ROOT);
1085 return builtInFrameworkSearchPaths;
1094 void VuoCompiler::Environment::startWatchingModuleSearchPath(
const string &moduleSearchPath)
1097 moduleSearchPathWatchers.insert(watcher);
1105 void VuoCompiler::Environment::stopWatchingModuleSearchPaths(
void)
1107 for (set<VuoFileWatcher *>::iterator i = moduleSearchPathWatchers.begin(); i != moduleSearchPathWatchers.end(); ++i)
1110 moduleSearchPathWatchers.clear();
1117 void VuoCompiler::Environment::fileChanged(
const string &moduleSearchPath)
1119 dispatch_sync(moduleSearchPathContentsChangedQueue, ^{
1120 moduleSearchPathContentsChanged(moduleSearchPath);
1131 void VuoCompiler::Environment::moduleSearchPathContentsChanged(
const string &moduleSearchPath,
const string &moduleAddedOrModifiedPath,
1132 const string &moduleAddedOrModifiedSourceCode,
1133 std::function<
void(
void)> moduleLoadedCallback,
1139 __block set<string> modulesAdded;
1140 __block set<string> modulesModifed;
1141 __block set<string> modulesRemoved;
1142 __block set<string> compositionsAdded;
1143 __block set<string> compositionsModifed;
1144 __block set<string> compositionsRemoved;
1146 dispatch_sync(environmentQueue, ^{
1150 map<string, ModuleInfo *> oldModules;
1151 map<string, ModuleInfo *> oldCompositions;
1153 map<string, map<string, ModuleInfo *> >::iterator mf = moduleFilesAtSearchPath.find(moduleSearchPath);
1154 if (mf != moduleFilesAtSearchPath.end())
1156 for (map<string, ModuleInfo *>::iterator j = mf->second.begin(); j != mf->second.end(); ++j)
1158 oldModules[j->first] = j->second;
1161 moduleFilesAtSearchPath.erase(mf);
1164 map<string, map<string, ModuleInfo *> >::iterator cf = sourceFilesAtSearchPath.find(moduleSearchPath);
1165 if (cf != sourceFilesAtSearchPath.end())
1167 for (map<string, ModuleInfo *>::iterator j = cf->second.begin(); j != cf->second.end(); ++j)
1169 oldCompositions[j->first] = j->second;
1172 compositionDependencyGraph->removeVertex(vertex);
1175 sourceFilesAtSearchPath.erase(cf);
1180 updateModulesAtSearchPath(moduleSearchPath, moduleAddedOrModifiedPath.empty());
1181 updateSourceFilesAtSearchPath(moduleSearchPath);
1183 mf = moduleFilesAtSearchPath.find(moduleSearchPath);
1184 if (mf != moduleFilesAtSearchPath.end())
1186 for (map<string, ModuleInfo *>::iterator n = mf->second.begin(); n != mf->second.end(); ++n)
1188 string moduleKey = n->first;
1190 map<string, ModuleInfo *>::iterator o = oldModules.find(moduleKey);
1191 if (o != oldModules.end())
1193 if (n->second->isNewerThan(o->second) ||
1194 (n->second->getFile() && (n->second->getFile()->isInArchive() ||
VuoFileUtilities::arePathsEqual(n->second->getFile()->path(), moduleAddedOrModifiedPath))))
1196 modulesModifed.insert(moduleKey);
1200 n->second->setAttempted(o->second->getAttempted());
1204 oldModules.erase(o);
1208 modulesModifed.insert(moduleKey);
1212 modulesAdded.insert(moduleKey);
1217 cf = sourceFilesAtSearchPath.find(moduleSearchPath);
1218 if (cf != sourceFilesAtSearchPath.end())
1220 for (map<string, ModuleInfo *>::iterator n = cf->second.begin(); n != cf->second.end(); ++n)
1222 string moduleKey = n->first;
1224 map<string, ModuleInfo *>::iterator o = oldCompositions.find(moduleKey);
1225 if (o != oldCompositions.end())
1227 if (n->second->isNewerThan(o->second))
1229 compositionsModifed.insert(moduleKey);
1233 n->second->setAttempted(o->second->getAttempted());
1234 n->second->setSourceCode(o->second->getSourceCode());
1238 oldCompositions.erase(o);
1242 compositionsAdded.insert(moduleKey);
1247 for (map<string, ModuleInfo *>::iterator o = oldModules.begin(); o != oldModules.end(); ++o)
1250 modulesRemoved.insert(o->first);
1253 for (map<string, ModuleInfo *>::iterator o = oldCompositions.begin(); o != oldCompositions.end(); ++o)
1256 compositionsRemoved.insert(o->first);
1259 compilerForLoading->loadModulesAndSources(modulesAdded, modulesModifed, modulesRemoved,
1260 compositionsAdded, compositionsModifed, compositionsRemoved,
1261 false,
false,
this, issues, moduleLoadedCallback, moduleAddedOrModifiedSourceCode);
1265 delete compilerForLoading;
1271 void VuoCompiler::Environment::notifyCompilers(
const set<VuoCompilerModule *> &modulesAdded,
1272 const set< pair<VuoCompilerModule *, VuoCompilerModule *> > &modulesModified,
1274 bool oldModulesInvalidated)
1276 if (! (modulesAdded.empty() && modulesModified.empty() && modulesRemoved.empty() && issues->
isEmpty()) )
1278 set< pair<VuoCompilerModule *, VuoCompilerModule *> > invalidatedModulesModified;
1279 set<VuoCompilerModule *> invalidatedModulesRemoved;
1280 if (oldModulesInvalidated)
1282 invalidatedModulesModified = modulesModified;
1283 invalidatedModulesRemoved = modulesRemoved;
1286 VuoCompilerDelegate::LoadedModulesData *delegateData =
new VuoCompilerDelegate::LoadedModulesData(invalidatedModulesModified, invalidatedModulesRemoved, issues);
1288 map<string, VuoCompilerModule *> modulesAddedMap;
1289 map<string, pair<VuoCompilerModule *, VuoCompilerModule *> > modulesModifiedMap;
1290 map<string, VuoCompilerModule *> modulesRemovedMap;
1292 modulesAddedMap[m->getPseudoBase()->getModuleKey()] = m;
1293 for (pair<VuoCompilerModule *, VuoCompilerModule *> m : modulesModified)
1294 modulesModifiedMap[m.first->getPseudoBase()->getModuleKey()] = m;
1296 modulesRemovedMap[m->getPseudoBase()->getModuleKey()] = m;
1298 dispatch_sync(compilersToNotifyQueue, ^{
1299 for (set<VuoCompiler *>::iterator i = compilersToNotify.begin(); i != compilersToNotify.end(); ++i) {
1300 delegateData->retain();
1302 for (set<VuoCompiler *>::iterator i = compilersToNotify.begin(); i != compilersToNotify.end(); ++i) {
1303 (*i)->loadedModules(modulesAddedMap, modulesModifiedMap, modulesRemovedMap, issues, delegateData,
this);
1323 set<VuoCompilerModule *> VuoCompiler::Environment::loadCompiledModules(
const set<string> &moduleKeys,
const map<string, string> &sourceCodeForModule)
1325 ModuleInfoIterator modulesToLoadIter = listModules(moduleKeys);
1326 set<VuoCompilerModule *> modulesLoaded;
1328 ModuleInfo *moduleInfo;
1329 while ((moduleInfo = modulesToLoadIter.next()))
1331 string moduleKey = moduleInfo->getModuleKey();
1335 if (moduleInfo->getEnvironment() !=
this || findModule(moduleKey) || moduleInfo->getAttempted())
1338 moduleInfo->setAttempted(
true);
1345 modulesLoaded.insert(module);
1346 addToDependencyGraph(module);
1350 string searchPath = moduleInfo->getSearchPath();
1357 ModuleInfo *sourceInfo = listSourceFile(moduleKey);
1361 auto sourceCodeIter = sourceCodeForModule.find(moduleKey);
1362 if (sourceCodeIter != sourceCodeForModule.end())
1369 return modulesLoaded;
1383 set<dispatch_group_t> VuoCompiler::Environment::loadSpecializedModules(
const set<string> &moduleKeys,
1386 set<dispatch_group_t > loadingGroups;
1388 for (
string moduleKey : moduleKeys)
1397 if (findModule(moduleKey))
1402 map<string, dispatch_group_t>::iterator iter = specializedModulesLoading.find(moduleKey);
1403 if (iter != specializedModulesLoading.end())
1405 loadingGroups.insert(iter->second);
1406 dispatch_retain(iter->second);
1410 dispatch_group_t loadingGroup = dispatch_group_create();
1411 specializedModulesLoading[moduleKey] = loadingGroup;
1412 loadingGroups.insert(loadingGroup);
1418 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
1419 dispatch_group_async(loadingGroup, queue, ^{
1433 compiler->loadNodeClassGeneratedAtRuntime(specNodeClass,
this);
1436 compiler->loadModulesIfNeeded(dependencies);
1439 dispatch_sync(environmentQueue, ^{
1440 specializedModulesLoading.erase(moduleKey);
1445 return loadingGroups;
1460 set<dispatch_group_t> VuoCompiler::Environment::compileModulesFromSourceCode(
const set<string> &moduleKeys,
bool shouldRecompileIfUnchanged)
1462 ModuleInfoIterator modulesToLoadIter = listSourceFiles(moduleKeys);
1464 set<dispatch_group_t> sourcesLoading;
1465 int sourcesEnqueued = 0;
1466 ModuleInfo *sourceInfo;
1467 while ((sourceInfo = modulesToLoadIter.next()))
1469 string moduleKey = sourceInfo->getModuleKey();
1471 dispatch_group_t loadingGroup = sourceInfo->getLoadingGroup();
1472 sourcesLoading.insert(loadingGroup);
1477 if (sourceInfo->getAttempted())
1482 string sourceCode = sourceInfo->getSourceCode();
1484 if (! shouldRecompileIfUnchanged)
1487 if (existingNodeClass && existingNodeClass->
getSourceCode() == sourceCode)
1493 sourceInfo->setAttempted(
true);
1495 dispatch_group_enter(loadingGroup);
1496 dispatch_group_enter(moduleSourceCompilersExist);
1500 queueItem->
sourcePath = sourceInfo->getFile()->path();
1502 queueItem->
sourceFile = sourceInfo->getFile();
1503 queueItem->
cachedModulesPath = sourceInfo->isSourceCodeOverridden() ? getOverriddenCompiledModuleCachePath() : getCompiledModuleCachePath();
1506 moduleCompilationQueue->enqueue(queueItem);
1515 for (
int i = 0; i < sourcesEnqueued; ++i)
1517 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
1518 dispatch_async(queue, ^{
1530 notifyCompilers(set<VuoCompilerModule *>(), set< pair<VuoCompilerModule *, VuoCompilerModule *> >(), set<VuoCompilerModule *>(), issues,
false);
1535 auto moduleLoadedCallback = [=](){
1537 moduleCompilationQueue->completed(queueItem);
1551 notifyCompilers(set<VuoCompilerModule *>(), set< pair<VuoCompilerModule *, VuoCompilerModule *> >(), set<VuoCompilerModule *>(), issues,
false);
1558 auto getType = [&compiler] (
const string &moduleKey) {
return compiler->
getType(moduleKey); };
1577 moduleLoadedCallback();
1591 notifyCompilers(set<VuoCompilerModule *>(), set< pair<VuoCompilerModule *, VuoCompilerModule *> >(), set<VuoCompilerModule *>(), issues,
false);
1592 moduleLoadedCallback();
1602 dispatch_group_leave(moduleSourceCompilersExist);
1606 return sourcesLoading;
1617 set<VuoCompilerModule *> VuoCompiler::Environment::unloadCompiledModules(
const set<string> &moduleKeys)
1619 set<VuoCompilerModule *> modulesUnloaded;
1621 for (set<string>::const_iterator i = moduleKeys.begin(); i != moduleKeys.end(); ++i)
1623 string moduleKey = *i;
1626 map<string, VuoCompilerNodeClass *>::iterator nodeClassIter = nodeClasses.find(moduleKey);
1627 if (nodeClassIter != nodeClasses.end())
1629 module = nodeClassIter->second;
1630 nodeClasses.erase(nodeClassIter);
1634 map<string, VuoCompilerType *>::iterator typeIter = types.find(moduleKey);
1635 if (typeIter != types.end())
1637 module = typeIter->second;
1638 types.erase(typeIter);
1642 map<string, VuoCompilerModule *>::iterator libraryModuleIter = libraryModules.find(moduleKey);
1643 if (libraryModuleIter != libraryModules.end())
1645 module = libraryModuleIter->second;
1646 libraryModules.erase(libraryModuleIter);
1653 modulesUnloaded.insert(module);
1654 removeFromDependencyGraph(module);
1659 return modulesUnloaded;
1667 void VuoCompiler::Environment::deleteModulesCompiledFromSourceCode(
const set<string> &moduleKeys)
1669 for (set<string>::const_iterator i = moduleKeys.begin(); i != moduleKeys.end(); ++i)
1671 string moduleKey = *i;
1673 map<string, ModuleInfo *>::iterator iter = moduleFilesAtSearchPath[getCompiledModuleCachePath()].find(moduleKey);
1674 if (iter != moduleFilesAtSearchPath[getCompiledModuleCachePath()].end())
1686 VuoCompilerModule * VuoCompiler::Environment::loadModule(ModuleInfo *moduleInfo)
1688 string moduleKey = moduleInfo->getModuleKey();
1695 __block
size_t inputDataBytes;
1696 __block
char *rawInputData;
1700 rawInputData = moduleInfo->getFile()->getContentsAsRawData(inputDataBytes);
1704 rawInputData = NULL;
1705 VUserLog(
"Warning: Couldn't load module '%s'. Its file may have been deleted. (%s)", moduleKey.c_str(), e.
what());
1711 char *processedInputData;
1713 processedInputData = loadModule_Pro0(moduleInfo, moduleKey, inputDataBytes, rawInputData);
1715 processedInputData = rawInputData;
1718 Module *module = NULL;
1719 bool moduleParseError = !processedInputData;
1720 if (!moduleParseError)
1722 string moduleReadError;
1724 module = readModuleFromBitcodeData(processedInputData, inputDataBytes, moduleReadError);
1726 free(processedInputData);
1730 moduleParseError =
true;
1732 string dir, file, ext;
1733 VuoFileUtilities::splitPath(moduleInfo->getFile()->isInArchive() ? moduleInfo->getFile()->getRelativePath() : moduleInfo->getFile()->path(), dir, file, ext);
1735 if (dir == getCompiledModuleCachePath())
1738 VUserLog(
"Error: Couldn't parse module '%s': %s.", moduleInfo->getFile()->getRelativePath().c_str(), moduleReadError.c_str());
1742 if (!moduleParseError)
1745 if (! moduleInfo->getFile()->isInArchive())
1746 modulePath = moduleInfo->getFile()->path();
1755 if (dynamic_cast<VuoCompilerNodeClass *>(compilerModule))
1756 nodeClasses[moduleKey] = static_cast<VuoCompilerNodeClass *>(compilerModule);
1757 else if (dynamic_cast<VuoCompilerType *>(compilerModule))
1758 types[moduleKey] = static_cast<VuoCompilerType *>(compilerModule);
1760 libraryModules[moduleKey] = compilerModule;
1765 map<string, VuoNodeSet *>::iterator nodeSetIter = nodeSetForName.find(nodeSet->
getName());
1766 if (nodeSetIter == nodeSetForName.end())
1768 nodeSetForName[nodeSet->
getName()] = nodeSet;
1773 nodeSet = nodeSetIter->second;
1775 compilerModule->getPseudoBase()->setNodeSet(nodeSet);
1779 loadModule_Pro1(rawInputData, processedInputData, compilerModule);
1782 compilerModule->setBuiltIn( isBuiltIn() );
1784 return compilerModule;
1788 destroyLlvmModule(module);
1807 removeFromDependencyGraph(oldNodeClass);
1808 destroyModule(oldNodeClass);
1811 nodeClasses[moduleKey] = newNodeClass;
1812 addToDependencyGraph(newNodeClass);
1818 DependencyGraphVertex *vertex = DependencyGraphVertex::vertexForDependency(module->
getPseudoBase()->
getModuleKey(), dependencyGraph);
1819 dependencyGraph->addVertex(vertex);
1821 vertex->setEnvironment(
this);
1828 for (set<string>::iterator i = dependencies.begin(); i != dependencies.end(); ++i)
1830 DependencyGraphVertex *depVertex = DependencyGraphVertex::vertexForDependency(*i, dependencyGraph);
1831 dependencyGraph->addEdge(vertex, depVertex);
1835 void VuoCompiler::Environment::removeFromDependencyGraph(
VuoCompilerModule *module)
1837 DependencyGraphVertex *vertex = DependencyGraphVertex::vertexForDependency(module->
getPseudoBase()->
getModuleKey(), dependencyGraph);
1838 dependencyGraph->removeVertex(vertex);
1851 void VuoCompiler::Environment::reifyPortTypes(
const map<string, VuoCompilerType *> &inheritedTypes)
1853 map<string, VuoCompilerType *> availableTypes = inheritedTypes;
1854 availableTypes.insert(types.begin(), types.end());
1856 for (map<string, VuoCompilerNodeClass *>::const_iterator i = nodeClasses.begin(); i != nodeClasses.end(); ++i)
1862 vector<VuoPortClass *> portClasses;
1863 portClasses.insert(portClasses.end(), inputPortClasses.begin(), inputPortClasses.end());
1864 portClasses.insert(portClasses.end(), outputPortClasses.begin(), outputPortClasses.end());
1866 for (vector<VuoPortClass *>::iterator j = portClasses.begin(); j != portClasses.end(); ++j)
1871 if (baseType && ! baseType->hasCompiler())
1876 VuoGenericType *genericType = dynamic_cast<VuoGenericType *>(baseType);
1881 genericTypes.insert( static_cast<VuoCompilerGenericType *>(reifiedType) );
1886 map<string, VuoCompilerType *>::iterator reifiedTypeIter = availableTypes.find(typeName);
1887 if (reifiedTypeIter != availableTypes.end())
1890 reifiedType = reifiedTypeIter->second;
1901 for (vector<VuoCompilerTriggerDescription *>::iterator j = triggers.begin(); j != triggers.end(); ++j)
1909 map<string, VuoCompilerType *>::iterator reifiedTypeIter = availableTypes.find(typeName);
1910 if (reifiedTypeIter != availableTypes.end())
1933 void VuoCompiler::Environment::getCacheableModulesAndDependencies(
bool builtIn,
bool installed, set<string> &cacheableModulesAndDependencies,
1934 set<string> &dylibsNeededToLinkToThisCache,
1935 set<string> &frameworksNeededToLinkToThisCache)
1937 if (isModuleCacheInitialized && ! isModuleCacheableDataDirty)
1939 cacheableModulesAndDependencies = moduleCacheContents;
1940 dylibsNeededToLinkToThisCache = moduleCacheDylibs;
1941 frameworksNeededToLinkToThisCache = moduleCacheFrameworks;
1949 map<string, VuoCompilerModule *> allModules;
1950 allModules.insert(nodeClasses.begin(), nodeClasses.end());
1951 allModules.insert(types.begin(), types.end());
1952 allModules.insert(libraryModules.begin(), libraryModules.end());
1954 set<string> dependencies;
1955 for (map<string, VuoCompilerModule *>::iterator i = allModules.begin(); i != allModules.end(); ++i)
1957 string moduleKey = i->first;
1962 if (module->requiresPro())
1970 cacheableModulesAndDependencies.insert(moduleKey);
1973 dependencies.insert(moduleDependencies.begin(), moduleDependencies.end());
1977 if (builtIn && installed)
1979 vector<string> coreDependencies = getCoreVuoDependencies();
1980 dependencies.insert(coreDependencies.begin(), coreDependencies.end());
1985 for (set<string>::iterator i = dependencies.begin(); i != dependencies.end(); ++i)
1987 string dependency = *i;
1988 if (allModules.find(dependency) == allModules.end())
1991 frameworksNeededToLinkToThisCache.insert(dependency);
1994 string dependencyPath = VuoCompiler::getLibraryPath(dependency, librarySearchPaths);
1995 if (! dependencyPath.empty())
1998 dylibsNeededToLinkToThisCache.insert(dependencyPath);
2000 cacheableModulesAndDependencies.insert(dependency);
2006 moduleCacheSuffix = (installed ?
"installed" :
"generated");
2007 dylibsNeededToLinkToThisCache.insert(moduleCachePath +
"/libVuoModuleCache-" + moduleCacheSuffix +
".dylib");
2009 moduleCacheDylibs = dylibsNeededToLinkToThisCache;
2010 moduleCacheFrameworks = frameworksNeededToLinkToThisCache;
2032 void VuoCompiler::Environment::useModuleCache(
bool shouldUseExistingCache,
VuoCompiler *compiler, set<string> cacheableModulesAndDependencies,
2033 set<string> dylibsNeededToLinkToCaches, set<string> frameworksNeededToLinkToCaches)
2037 static dispatch_once_t checked = 0;
2038 static bool prelinkCache =
true;
2039 dispatch_once(&checked, ^{
2041 bool result = CFPreferencesGetAppBooleanValue(CFSTR(
"prelinkCache"), CFSTR(
"org.vuo.Editor"), &valid);
2043 prelinkCache = result;
2047 VDebugLog(
"Ignoring the module cache since the 'prelinkCache' preference is false.");
2053 if (moduleCachePath.empty())
2058 string cacheDescription = string() +
"the cache of " + moduleCacheSuffix +
" modules at '" + moduleCachePath +
"'";
2059 if (isModuleCacheInitialized && ! isModuleCacheableDataDirty)
2061 VDebugLog(
"No need to recheck %s.", cacheDescription.c_str());
2067 VDebugLog(
"Checking if %s is up-to-date…", cacheDescription.c_str());
2069 bool isCacheUpToDate =
true;
2071 if (isModuleCacheInitialized && isModuleCacheableDataDirty)
2072 isCacheUpToDate =
false;
2074 isModuleCacheInitialized =
true;
2075 isModuleCacheableDataDirty =
false;
2077 const string dylibFileName =
"libVuoModuleCache-" + moduleCacheSuffix +
".dylib";
2078 const string indexFileName =
"moduleCache-" + moduleCacheSuffix +
".txt";
2079 string dylibPath = moduleCachePath +
"/" + dylibFileName;
2080 string indexPath = moduleCachePath +
"/" + indexFileName;
2084 bool dylibFileExists =
false;
2085 bool indexFileExists =
false;
2094 if (! (dirExists && dylibFileExists && indexFileExists))
2096 if (shouldUseExistingCache)
2097 throw VuoException(
"Trying to use the existing cache, but the cache doesn't exist.",
false);
2102 if (! indexFileExists)
2104 if (! dylibFileExists)
2107 isCacheUpToDate =
false;
2115 fileForLocking = moduleCacheFileForLocking[dylibPath];
2116 if (! fileForLocking)
2119 moduleCacheFileForLocking[dylibPath] = fileForLocking;
2123 VDebugLog(
"\tWarning: Couldn't lock for reading.");
2128 if (isCacheUpToDate)
2133 if (shouldUseExistingCache)
2134 throw VuoException(
"Trying to use the existing cache, but the cache doesn't contain readable data.",
false);
2136 isCacheUpToDate =
false;
2142 const char separator =
'\n';
2143 if (isCacheUpToDate || shouldUseExistingCache)
2146 string index = indexFile.getContentsAsString();
2149 moduleCacheContents.clear();
2150 moduleCacheContents.insert(actualIndex.begin(), actualIndex.end());
2152 if (shouldUseExistingCache)
2154 isModuleCacheAvailable =
true;
2161 if (isCacheUpToDate)
2163 if (moduleCacheContents.size() != cacheableModulesAndDependencies.size())
2164 isCacheUpToDate =
false;
2167 set<string> contentsInBoth;
2168 std::set_intersection(moduleCacheContents.begin(), moduleCacheContents.end(),
2169 cacheableModulesAndDependencies.begin(), cacheableModulesAndDependencies.end(),
2170 std::inserter(contentsInBoth, contentsInBoth.begin()));
2172 if (contentsInBoth.size() != cacheableModulesAndDependencies.size())
2173 isCacheUpToDate =
false;
2179 if (isCacheUpToDate)
2183 for (map<
string, map<string, ModuleInfo *> >::iterator i = moduleFilesAtSearchPath.begin(); i != moduleFilesAtSearchPath.end(); ++i)
2185 for (map<string, ModuleInfo *>::iterator j = i->second.begin(); j != i->second.end(); ++j)
2187 if (! j->second->isOlderThan(cacheLastModified))
2189 isCacheUpToDate =
false;
2198 if (isCacheUpToDate)
2202 isModuleCacheAvailable =
true;
2208 dispatch_async(moduleCacheBuildingQueue, ^{
2209 VDebugLog(
"Rebuilding %s…", cacheDescription.c_str());
2211 set<Module *> modulesToLink;
2212 set<string> librariesToLink;
2213 set<string> frameworksToLink;
2215 compiler->getLinkerInputs(cacheableModulesAndDependencies, Optimization_SmallBinary, modulesToLink, librariesToLink, frameworksToLink);
2217 librariesToLink.insert(dylibsNeededToLinkToCaches.begin(), dylibsNeededToLinkToCaches.end());
2218 set<string>::iterator iter = librariesToLink.find(dylibPath);
2219 if (iter != librariesToLink.end())
2220 librariesToLink.erase(iter);
2222 frameworksToLink.insert(frameworksNeededToLinkToCaches.begin(), frameworksNeededToLinkToCaches.end());
2225 bool gotLockForWriting =
false;
2230 if (! gotLockForWriting)
2231 throw VuoException(
"The cache file is being used by another process. "
2232 "If any composition windows are open from previous Vuo sessions, quit them. "
2233 "If any processes whose names start with \"VuoComposition\" or one of your composition file names appear in Activity Monitor, force-quit them.",
2237 string dir, file, ext;
2240 compiler->link(tmpPath, modulesToLink, librariesToLink, frameworksToLink,
true);
2248 getVuoFrameworkPath() +
"/Helpers/install_name_tool",
2255 vector<string> expectedContents(cacheableModulesAndDependencies.begin(), cacheableModulesAndDependencies.end());
2261 VDebugLog(
"\tWarning: Couldn't downgrade the lock back to reading.");
2263 dispatch_sync(environmentQueue, ^{
2264 moduleCacheContents = cacheableModulesAndDependencies;
2265 isModuleCacheAvailable =
true;
2271 if (gotLockForWriting)
2273 VDebugLog(
"\tWarning: Couldn't downgrade the lock back to reading.");
2275 VUserLog(
"Warning: Couldn't rebuild %s for the \"faster build\" optimization: %s", cacheDescription.c_str(), e.
what());
2283 VUserLog(
"Warning: Couldn't use %s for the \"faster build\" optimization: %s", cacheDescription.c_str(), e.
what());
2290 void VuoCompiler::Environment::waitForModuleCachesToBuild(
void)
2292 dispatch_sync(moduleCacheBuildingQueue, ^{});
2304 bool VuoCompiler::Environment::findInModuleCache(
const string &moduleOrDependency,
string &cachePath)
2306 if (isModuleCacheAvailable && moduleCacheContents.find(moduleOrDependency) != moduleCacheContents.end())
2308 cachePath = moduleCachePath +
"/libVuoModuleCache-" + moduleCacheSuffix +
".dylib";
2321 void VuoCompiler::Environment::modulesChanged(
void)
2323 isModuleCacheableDataDirty =
true;
2324 isModuleCacheAvailable =
false;
2330 bool VuoCompiler::Environment::isBuiltIn()
2332 return this == sharedEnvironments[0][0];
2338 string VuoCompiler::Environment::getName()
2342 else if (
this == sharedEnvironments[0][1])
2343 return "builtin (generated)";
2344 else if (
this == sharedEnvironments[1][0])
2346 else if (
this == sharedEnvironments[1][1])
2347 return "system (generated)";
2348 else if (
this == sharedEnvironments[2][0])
2350 else if (
this == sharedEnvironments[2][1])
2351 return "user (generated)";
2352 return "composition-local";
2358 void VuoCompiler::applyToInstalledEnvironments(
void (^doForEnvironment)(Environment *))
2360 dispatch_sync(environmentQueue, ^{
2361 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i) {
2362 doForEnvironment((*i)[0]);
2370 void VuoCompiler::applyToInstalledEnvironments(
void (^doForEnvironment)(Environment *,
bool *,
string),
bool *result,
string arg)
2372 dispatch_sync(environmentQueue, ^{
2373 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i) {
2374 doForEnvironment((*i)[0], result, arg);
2382 void VuoCompiler::applyToAllEnvironments(
void (^doForEnvironment)(Environment *environment))
2384 dispatch_sync(environmentQueue, ^{
2385 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i) {
2386 for (vector<Environment *>::iterator j = i->begin(); j != i->end(); ++j) {
2387 doForEnvironment(*j);
2407 shouldLoadAllModules =
true;
2408 hasLoadedAllModules =
false;
2409 modulesToLoadQueue = dispatch_queue_create(
"org.vuo.compiler.modules", NULL);
2410 moduleCacheBuilding = dispatch_group_create();
2411 dependencyGraph = NULL;
2412 compositionDependencyGraph = NULL;
2414 _shouldShowSplashWindow =
false;
2416 delegateQueue = dispatch_queue_create(
"org.vuo.compiler.delegate", NULL);
2418 string vuoFrameworkPath = getVuoFrameworkPath();
2419 if (! vuoFrameworkPath.empty())
2420 clangPath = vuoFrameworkPath +
"/Helpers/clang";
2422 clangPath = llvm::sys::Path(StringRef(LLVM_ROOT
"/bin/clang"));
2424 dispatch_sync(environmentQueue, ^{
2425 if (sharedEnvironments.empty())
2427 sharedEnvironments = vector< vector<Environment *> >(3, vector<Environment *>(2, NULL));
2428 for (vector< vector<Environment *> >::iterator i = sharedEnvironments.begin(); i != sharedEnvironments.end(); ++i) {
2429 for (vector<Environment *>::iterator j = i->begin(); j != i->end(); ++j) {
2430 *j =
new Environment();
2434 vector<string> builtInModuleSearchPaths = Environment::getBuiltInModuleSearchPaths();
2435 for (vector<string>::iterator i = builtInModuleSearchPaths.begin(); i != builtInModuleSearchPaths.end(); ++i) {
2436 sharedEnvironments[0][0]->addModuleSearchPath(*i,
false);
2439 vector<string> builtInHeaderSearchPaths = Environment::getBuiltInHeaderSearchPaths();
2440 for (vector<string>::iterator i = builtInHeaderSearchPaths.begin(); i != builtInHeaderSearchPaths.end(); ++i) {
2441 sharedEnvironments[0][0]->addHeaderSearchPath(*i);
2444 vector<string> builtInLibrarySearchPaths = Environment::getBuiltInLibrarySearchPaths();
2445 for (vector<string>::iterator i = builtInLibrarySearchPaths.begin(); i != builtInLibrarySearchPaths.end(); ++i) {
2446 sharedEnvironments[0][0]->addLibrarySearchPath(*i);
2449 vector<string> builtInFrameworkSearchPaths = Environment::getBuiltInFrameworkSearchPaths();
2450 for (vector<string>::iterator i = builtInFrameworkSearchPaths.begin(); i != builtInFrameworkSearchPaths.end(); ++i) {
2451 sharedEnvironments[0][0]->addFrameworkSearchPath(*i);
2465 string vuoFrameworkPath = getVuoFrameworkPath();
2466 if (! vuoFrameworkPath.empty())
2468 vector<string> moduleCachePaths(3);
2469 moduleCachePaths[0] = vuoFrameworkPath +
"/Modules/Builtin";
2473 for (
size_t i = 0; i < moduleCachePaths.size(); ++i)
2475 string moduleCachePath = moduleCachePaths[i];
2477 sharedEnvironments[i][0]->setModuleCachePath(moduleCachePath);
2478 sharedEnvironments[i][0]->addModuleSearchPath(moduleCachePath +
"/Modules",
false);
2480 sharedEnvironments[i][1]->setModuleCachePath(moduleCachePath);
2494 dispatch_group_wait(moduleCacheBuilding, DISPATCH_TIME_FOREVER);
2495 dispatch_release(moduleCacheBuilding);
2497 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
2498 (*i)[0]->removeCompilerToNotify(
this);
2500 dispatch_sync(delegateQueue, ^{});
2502 dispatch_release(modulesToLoadQueue);
2503 dispatch_release(delegateQueue);
2505 delete dependencyGraph;
2506 delete compositionDependencyGraph;
2512 void VuoCompiler::reset(
void)
2514 dispatch_group_wait(moduleSourceCompilersExist, DISPATCH_TIME_FOREVER);
2516 for (vector< vector<Environment *> >::iterator i = sharedEnvironments.begin(); i != sharedEnvironments.end(); ++i)
2518 (*i)[0]->stopWatchingModuleSearchPaths();
2519 dispatch_sync((*i)[0]->moduleSearchPathContentsChangedQueue, ^{});
2522 for (map<
string, vector<Environment *> >::iterator i = environmentsForCompositionFamily.begin(); i != environmentsForCompositionFamily.end(); ++i)
2524 (i->second)[0]->stopWatchingModuleSearchPaths();
2525 dispatch_sync((i->second)[0]->moduleSearchPathContentsChangedQueue, ^{});
2528 for (vector< vector<Environment *> >::iterator i = sharedEnvironments.begin(); i != sharedEnvironments.end(); ++i)
2529 for (vector<Environment *>::iterator j = i->begin(); j != i->end(); ++j)
2532 for (map<
string, vector<Environment *> >::iterator i = environmentsForCompositionFamily.begin(); i != environmentsForCompositionFamily.end(); ++i)
2533 for (vector<Environment *>::iterator j = i->second.begin(); j != i->second.end(); ++j)
2536 sharedEnvironments.clear();
2537 environmentsForCompositionFamily.clear();
2547 dispatch_async(delegateQueue, ^{
2548 this->delegate = delegate;
2563 string compositionModulesDir;
2564 string compositionBaseDir;
2565 lastCompositionIsSubcomposition =
false;
2566 if (! compositionPath.empty())
2574 string compositionDir;
2577 lastCompositionIsSubcomposition = (compositionDir == compositionModulesDir);
2582 dispatch_sync(environmentQueue, ^{
2583 if (! environments.empty() && compositionBaseDir == lastCompositionBaseDir) {
2586 lastCompositionBaseDir = compositionBaseDir;
2590 Environment *oldCompositionFamilyInstalledEnvironment =
nullptr;
2591 vector<Environment *> compositionEnvironments;
2592 if (! environments.empty())
2594 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i) {
2595 (*i)[0]->removeCompilerToNotify(
this);
2598 if (environments.size() >= 5) {
2599 oldCompositionFamilyInstalledEnvironment = environments[3][0];
2602 compositionEnvironments = environments.back();
2604 environments.clear();
2611 bool isCompositionInSharedEnvironment =
false;
2612 for (vector< vector<Environment *> >::iterator i = sharedEnvironments.begin(); i != sharedEnvironments.end(); ++i)
2614 environments.push_back(*i);
2616 vector<string> moduleSearchPaths = (*i)[0]->getModuleSearchPaths();
2617 for (vector<string>::iterator j = moduleSearchPaths.begin(); j != moduleSearchPaths.end(); ++j)
2619 string moduleSearchPath = *j;
2621 if (moduleSearchPath == compositionModulesDir)
2623 isCompositionInSharedEnvironment =
true;
2628 if (isCompositionInSharedEnvironment) {
2635 Environment *newCompositionFamilyInstalledEnvironment =
nullptr;
2636 if (! isCompositionInSharedEnvironment && ! compositionPath.empty())
2638 vector<Environment *> compositionFamilyEnvironments = environmentsForCompositionFamily[compositionBaseDir];
2639 if (compositionFamilyEnvironments.empty())
2641 compositionFamilyEnvironments = vector<Environment *>(2, NULL);
2642 compositionFamilyEnvironments[0] =
new Environment();
2643 compositionFamilyEnvironments[1] =
new Environment();
2644 environmentsForCompositionFamily[compositionBaseDir] = compositionFamilyEnvironments;
2648 compositionFamilyEnvironments[0]->addModuleSearchPath(compositionModulesDir);
2652 string moduleCachePath = getCachePathForComposition(compositionBaseDir);
2654 compositionFamilyEnvironments[0]->setModuleCachePath(moduleCachePath);
2655 compositionFamilyEnvironments[0]->addModuleSearchPath(moduleCachePath +
"/Modules",
false);
2657 compositionFamilyEnvironments[1]->setModuleCachePath(moduleCachePath);
2659 environments.push_back(compositionFamilyEnvironments);
2661 newCompositionFamilyInstalledEnvironment = compositionFamilyEnvironments[0];
2666 if (compositionEnvironments.empty())
2668 compositionEnvironments = vector<Environment *>(2, NULL);
2669 compositionEnvironments[0] =
new Environment();
2670 compositionEnvironments[1] =
new Environment();
2672 environments.push_back(compositionEnvironments);
2674 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i) {
2675 (*i)[0]->addCompilerToNotify(
this);
2678 delete dependencyGraph;
2679 delete compositionDependencyGraph;
2680 dependencyGraph = makeDependencyNetwork(environments, ^
VuoDirectedAcyclicGraph * (Environment *env) {
return env->getDependencyGraph(); });
2681 compositionDependencyGraph = makeDependencyNetwork(environments, ^
VuoDirectedAcyclicGraph * (Environment *env) {
return env->getCompositionDependencyGraph(); });
2686 if (oldCompositionFamilyInstalledEnvironment != newCompositionFamilyInstalledEnvironment)
2688 auto getModules = [] (Environment *env)
2690 map<string, VuoCompilerModule *> modules;
2693 for (
auto i : env->getNodeClasses()) {
2696 for (
auto i : env->getTypes()) {
2699 for (
auto i : env->getLibraryModules()) {
2706 map<string, VuoCompilerModule *> modulesAdded = getModules(newCompositionFamilyInstalledEnvironment);
2707 map<string, VuoCompilerModule *> modulesRemoved = getModules(oldCompositionFamilyInstalledEnvironment);
2709 map<string, pair<VuoCompilerModule *, VuoCompilerModule *> > modulesModified;
2710 for (map<string, VuoCompilerModule *>::iterator add = modulesAdded.begin(); add != modulesAdded.end(); )
2712 map<string, VuoCompilerModule *>::iterator rem = modulesRemoved.find(add->first);
2713 if (rem != modulesRemoved.end())
2715 modulesModified[add->first] = make_pair(rem->second, add->second);
2716 modulesAdded.erase(add++);
2717 modulesRemoved.erase(rem);
2725 if (! (modulesAdded.empty() && modulesModified.empty() && modulesRemoved.empty()) )
2728 VuoCompilerDelegate::LoadedModulesData *delegateData =
new VuoCompilerDelegate::LoadedModulesData(set< pair<VuoCompilerModule *, VuoCompilerModule *> >(), set<VuoCompilerModule *>(), issues);
2729 delegateData->retain();
2731 Environment *scopeEnvironment = newCompositionFamilyInstalledEnvironment;
2732 if (! scopeEnvironment) {
2733 scopeEnvironment = compositionEnvironments.at(0);
2736 loadedModules(modulesAdded, modulesModified, modulesRemoved, issues, delegateData, scopeEnvironment);
2746 if (!graphForEnvironment)
2751 for (vector< vector<Environment *> >::const_iterator i = environments.begin(); i != environments.end(); ++i)
2755 network->
addEdge(graphForEnvironment(i->at(0)), graphForEnvironment(i->at(1)));
2759 for (vector< vector<Environment *> >::const_iterator ii = environments.begin(); ii != i; ++ii)
2761 network->
addEdge(graphForEnvironment(i->at(0)), graphForEnvironment(ii->at(0)));
2762 network->
addEdge(graphForEnvironment(i->at(1)), graphForEnvironment(ii->at(0)));
2789 void VuoCompiler::loadModulesIfNeeded(
const set<string> &moduleKeys)
2791 __block
bool willLoadAllModules =
false;
2792 if (moduleKeys.empty())
2794 dispatch_sync(modulesToLoadQueue, ^{
2795 if (shouldLoadAllModules && ! hasLoadedAllModules) {
2796 willLoadAllModules =
true;
2797 hasLoadedAllModules =
true;
2802 if (! willLoadAllModules && moduleKeys.empty())
2807 __block set<dispatch_group_t> sourcesLoading;
2808 dispatch_sync(environmentQueue, ^{
2809 sourcesLoading = loadModulesAndSources(moduleKeys, set<string>(), set<string>(),
2810 moduleKeys, set<string>(), set<string>(),
2811 willLoadAllModules,
false,
nullptr,
nullptr,
nullptr,
"");
2817 for (set<dispatch_group_t>::iterator i = sourcesLoading.begin(); i != sourcesLoading.end(); ++i)
2819 dispatch_group_wait(*i, DISPATCH_TIME_FOREVER);
2820 dispatch_release(*i);
2832 set<dispatch_group_t> VuoCompiler::loadModulesAndSources(
const set<string> &modulesAddedKeys,
const set<string> &modulesModifiedKeys,
const set<string> &modulesRemovedKeys,
2833 const set<string> &sourcesAddedKeys,
const set<string> &sourcesModifiedKeys,
const set<string> &sourcesRemovedKeys,
2834 bool willLoadAllModules,
bool shouldRecompileSourcesIfUnchanged,
2835 Environment *currentEnvironment,
VuoCompilerIssues *issuesForCurrentEnvironment,
2836 std::function<
void(
void)> moduleLoadedCallback,
const string &moduleAddedOrModifiedSourceCode)
2848 map<Environment *, set<string> > modulesAdded;
2849 map<Environment *, set<string> > modulesModified;
2850 map<Environment *, set<string> > modulesRemoved;
2851 map<Environment *, set<string> > sourcesAdded;
2852 map<Environment *, set<string> > sourcesModified;
2853 map<Environment *, set<string> > sourcesRemoved;
2854 map<Environment *, set<string> > potentialSpecializedModules;
2856 if (currentEnvironment)
2858 modulesAdded[currentEnvironment] = modulesAddedKeys;
2859 modulesModified[currentEnvironment] = modulesModifiedKeys;
2860 modulesRemoved[currentEnvironment] = modulesRemovedKeys;
2861 sourcesAdded[currentEnvironment] = sourcesAddedKeys;
2862 sourcesModified[currentEnvironment] = sourcesModifiedKeys;
2863 sourcesRemoved[currentEnvironment] = sourcesRemovedKeys;
2867 Environment *genEnv =
nullptr;
2868 if (! willLoadAllModules)
2874 int scope = environments.size() - (lastCompositionIsSubcomposition ? 2 : 1);
2875 genEnv = environments.at(scope).at(1);
2876 potentialSpecializedModules[genEnv] = modulesAddedKeys;
2879 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
2881 Environment *env = (*i).at(0);
2883 ModuleInfoIterator modulesAddedIter = (willLoadAllModules ? env->listAllModules() : env->listModules(modulesAddedKeys));
2884 ModuleInfoIterator sourcesAddedIter = (willLoadAllModules ? env->listAllSourceFiles() : env->listSourceFiles(sourcesAddedKeys));
2885 ModuleInfoIterator sourcesModifiedIter = (willLoadAllModules ? env->listAllSourceFiles() : env->listSourceFiles(sourcesModifiedKeys));
2887 ModuleInfo *moduleInfo;
2888 while ((moduleInfo = modulesAddedIter.next()))
2890 string moduleKey = moduleInfo->getModuleKey();
2892 modulesAdded[env].insert(moduleKey);
2894 if (! willLoadAllModules)
2896 auto foundIter = potentialSpecializedModules[genEnv].find(moduleKey);
2897 if (foundIter != potentialSpecializedModules[genEnv].end())
2898 potentialSpecializedModules[genEnv].erase(foundIter);
2904 auto isCompiledModuleAtSameSearchPath = [&env] (ModuleInfo *sourceInfo)
2906 ModuleInfo *compiledModuleInfo = env->listModule(sourceInfo->getModuleKey());
2907 return (compiledModuleInfo && compiledModuleInfo->getSearchPath() == sourceInfo->getSearchPath());
2910 while ((moduleInfo = sourcesAddedIter.next()))
2912 if (isCompiledModuleAtSameSearchPath(moduleInfo))
2915 sourcesAdded[env].insert( moduleInfo->getModuleKey() );
2918 while ((moduleInfo = sourcesModifiedIter.next()))
2920 if (isCompiledModuleAtSameSearchPath(moduleInfo))
2923 sourcesModified[env].insert( moduleInfo->getModuleKey() );
2928 map<Environment *, VuoCompilerIssues *> issues;
2929 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
2931 Environment *env = (*i).at(0);
2932 issues[env] = (env == currentEnvironment && issuesForCurrentEnvironment ? issuesForCurrentEnvironment :
new VuoCompilerIssues());
2937 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
2939 Environment *env = (*i).at(0);
2944 set<VuoDirectedAcyclicGraph::Vertex *> circularDependencies = env->getCompositionDependencyGraph()->getCycleVertices();
2946 set<string> sourcesAddedModified;
2947 sourcesAddedModified.insert(sourcesAdded[env].begin(), sourcesAdded[env].end());
2948 sourcesAddedModified.insert(sourcesModified[env].begin(), sourcesModified[env].end());
2950 for (set<string>::iterator j = sourcesAddedModified.begin(); j != sourcesAddedModified.end(); ++j)
2952 string moduleKey = *j;
2955 for (set<VuoDirectedAcyclicGraph::Vertex *>::iterator k = circularDependencies.begin(); k != circularDependencies.end(); ++k)
2957 DependencyGraphVertex *vertex = static_cast<DependencyGraphVertex *>(*k);
2958 if (vertex->getDependency() == moduleKey)
2967 sourcesAdded[env].erase(moduleKey);
2968 sourcesModified[env].erase(moduleKey);
2971 "Subcomposition contains itself",
2972 "%moduleKey contains an instance of itself, "
2973 "or contains another subcomposition that contains an instance of %moduleKey.");
2974 issue.setModuleKey(moduleKey);
2976 ModuleInfo *sourceInfo = env->listSourceFile(moduleKey);
2978 issue.setFilePath(sourceInfo->getFile()->path());
2980 issues[env]->append(issue);
2989 map<Environment *, set<string> > modulesDepOnModulesModified;
2990 map<Environment *, set<string> > sourcesDepOnModulesModified;
2991 map<Environment *, set<string> > modulesDepOnModulesRemoved;
2992 map<Environment *, set<string> > sourcesDepOnModulesRemoved;
2995 __block map<Environment *, set<string> > modulesDepOnModulesModified_otherCompiler;
2996 __block map<Environment *, set<string> > sourcesDepOnModulesModified_otherCompiler;
2997 __block map<Environment *, set<string> > modulesDepOnModulesRemoved_otherCompiler;
2998 __block map<Environment *, set<string> > sourcesDepOnModulesRemoved_otherCompiler;
3000 vector<VuoDirectedAcyclicNetwork *> searchDependencyGraphs;
3001 searchDependencyGraphs.push_back(dependencyGraph);
3002 for (map<
string, vector<Environment *> >::iterator ii = environmentsForCompositionFamily.begin(); ii != environmentsForCompositionFamily.end(); ++ii)
3004 vector< vector<Environment *> > otherEnvs = sharedEnvironments;
3005 otherEnvs.push_back(ii->second);
3007 searchDependencyGraphs.push_back(other);
3010 VuoDirectedAcyclicGraph *currentEnvironmentDependencyGraph = (currentEnvironment ? currentEnvironment->getDependencyGraph() :
nullptr);
3012 findDependentModulesAndSources(modulesModified, searchDependencyGraphs, currentEnvironmentDependencyGraph,
3013 modulesDepOnModulesModified, modulesDepOnModulesModified_otherCompiler,
3014 sourcesDepOnModulesModified, sourcesDepOnModulesModified_otherCompiler);
3016 findDependentModulesAndSources(modulesRemoved, searchDependencyGraphs, currentEnvironmentDependencyGraph,
3017 modulesDepOnModulesRemoved, modulesDepOnModulesRemoved_otherCompiler,
3018 sourcesDepOnModulesRemoved, sourcesDepOnModulesRemoved_otherCompiler);
3020 set<Environment *> otherEnvironments;
3021 for (map<Environment *, set<string> >::iterator i = modulesDepOnModulesModified_otherCompiler.begin(); i != modulesDepOnModulesModified_otherCompiler.end(); ++i)
3022 otherEnvironments.insert(i->first);
3023 for (map<Environment *, set<string> >::iterator i = sourcesDepOnModulesModified_otherCompiler.begin(); i != sourcesDepOnModulesModified_otherCompiler.end(); ++i)
3024 otherEnvironments.insert(i->first);
3025 for (map<Environment *, set<string> >::iterator i = modulesDepOnModulesRemoved_otherCompiler.begin(); i != modulesDepOnModulesRemoved_otherCompiler.end(); ++i)
3026 otherEnvironments.insert(i->first);
3027 for (map<Environment *, set<string> >::iterator i = sourcesDepOnModulesRemoved_otherCompiler.begin(); i != sourcesDepOnModulesRemoved_otherCompiler.end(); ++i)
3028 otherEnvironments.insert(i->first);
3030 for (Environment *env : otherEnvironments)
3032 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
3033 string moduleSearchPath = env->getModuleSearchPaths().front();
3036 dispatch_sync(environmentQueue, ^{
3037 otherCompiler->loadModulesAndSources(set<string>(), modulesDepOnModulesModified_otherCompiler[env], modulesDepOnModulesRemoved_otherCompiler[env],
3038 set<string>(), sourcesDepOnModulesModified_otherCompiler[env], sourcesDepOnModulesRemoved_otherCompiler[env],
3039 false,
true, env,
nullptr,
nullptr,
"");
3042 delete otherCompiler;
3051 map<Environment *, set<VuoCompilerModule *> > actualModulesRemoved;
3052 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
3054 Environment *env = (*i).at(0);
3056 set<string> modulesToUnload;
3057 modulesToUnload.insert(modulesRemoved[env].begin(), modulesRemoved[env].end());
3058 modulesToUnload.insert(modulesModified[env].begin(), modulesModified[env].end());
3059 modulesToUnload.insert(modulesDepOnModulesRemoved[env].begin(), modulesDepOnModulesRemoved[env].end());
3060 modulesToUnload.insert(modulesDepOnModulesModified[env].begin(), modulesDepOnModulesModified[env].end());
3062 actualModulesRemoved[env] = env->unloadCompiledModules(modulesToUnload);
3064 if (!env->isBuiltIn() && !actualModulesRemoved[env].empty())
3066 set<string> actualModulesRemovedKeys;
3067 for (
auto m : actualModulesRemoved[env])
3068 actualModulesRemovedKeys.insert(m->getPseudoBase()->getModuleKey());
3080 map<Environment *, set<string> > modulesToLoad;
3081 map<Environment *, map<string, string> > modulesToLoadSourceCode;
3082 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
3084 Environment *env = (*i).at(0);
3086 if (! modulesAdded[env].empty())
3087 modulesToLoad[env].insert(modulesAdded[env].begin(), modulesAdded[env].end());
3088 if (! modulesModified[env].empty())
3089 modulesToLoad[env].insert(modulesModified[env].begin(), modulesModified[env].end());
3090 if (! modulesDepOnModulesModified[env].empty())
3091 modulesToLoad[env].insert(modulesDepOnModulesModified[env].begin(), modulesDepOnModulesModified[env].end());
3093 if (env == currentEnvironment && moduleLoadedCallback)
3095 if (modulesAdded[env].size() == 1)
3096 modulesToLoadSourceCode[env][*modulesAdded[env].begin()] = moduleAddedOrModifiedSourceCode;
3097 else if (modulesModified[env].size() == 1)
3098 modulesToLoadSourceCode[env][*modulesModified[env].begin()] = moduleAddedOrModifiedSourceCode;
3102 map<Environment *, set<VuoCompilerModule *> > actualModulesAdded;
3103 while (! modulesToLoad.empty())
3105 set<string> dependenciesToLoad;
3106 map<Environment *, set<string> > potentialSpecializedDependencies;
3107 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
3109 Environment *env = (*i).at(0);
3110 Environment *genEnv = (*i).at(1);
3112 set<VuoCompilerModule *> actualModulesLoaded = env->loadCompiledModules(modulesToLoad[env], modulesToLoadSourceCode[env]);
3114 actualModulesAdded[env].insert(actualModulesLoaded.begin(), actualModulesLoaded.end());
3115 modulesToLoad.erase(env);
3117 set<string> actualModulesLoadedKeys;
3118 for (set<VuoCompilerModule *>::iterator j = actualModulesLoaded.begin(); j != actualModulesLoaded.end(); ++j)
3120 set<string> dependencies = (*j)->getDependencies();
3121 dependenciesToLoad.insert(dependencies.begin(), dependencies.end());
3122 potentialSpecializedDependencies[genEnv].insert(dependencies.begin(), dependencies.end());
3123 actualModulesLoadedKeys.insert((*j)->getPseudoBase()->getModuleKey());
3126 if (!env->isBuiltIn() && !actualModulesLoadedKeys.empty())
3130 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
3132 Environment *env = (*i).at(0);
3134 ModuleInfoIterator dependenciesInEnv = env->listModules(dependenciesToLoad);
3135 ModuleInfo *moduleInfo;
3136 while ((moduleInfo = dependenciesInEnv.next()))
3138 modulesToLoad[env].insert( moduleInfo->getModuleKey() );
3140 for (map<Environment *, set<string> >::iterator j = potentialSpecializedDependencies.begin(); j != potentialSpecializedDependencies.end(); ++j)
3142 auto foundIter = j->second.find( moduleInfo->getModuleKey() );
3143 if (foundIter != j->second.end())
3144 j->second.erase(foundIter);
3149 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
3151 Environment *genEnv = (*i).at(1);
3152 potentialSpecializedModules[genEnv].insert(potentialSpecializedDependencies[genEnv].begin(), potentialSpecializedDependencies[genEnv].end());
3159 set<dispatch_group_t> specializedModulesLoading;
3160 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
3162 Environment *genEnv = (*i).at(1);
3163 set<dispatch_group_t> s = genEnv->loadSpecializedModules(potentialSpecializedModules[genEnv],
this,
llvmQueue);
3164 specializedModulesLoading.insert(s.begin(), s.end());
3169 if (moduleLoadedCallback)
3170 moduleLoadedCallback();
3174 map<Environment *, set< pair<VuoCompilerModule *, VuoCompilerModule *> > > actualModulesModified;
3175 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
3177 Environment *env = (*i).at(0);
3179 for (set<VuoCompilerModule *>::iterator add = actualModulesAdded[env].begin(); add != actualModulesAdded[env].end(); )
3181 set<VuoCompilerModule *>::iterator rem;
3182 for (rem = actualModulesRemoved[env].begin(); rem != actualModulesRemoved[env].end(); ++rem)
3183 if ((*rem)->getPseudoBase()->getModuleKey() == (*add)->getPseudoBase()->getModuleKey())
3186 if (rem != actualModulesRemoved[env].end())
3188 actualModulesModified[env].insert( make_pair(*rem, *add) );
3189 actualModulesRemoved[env].erase(rem);
3190 actualModulesAdded[env].erase(add++);
3199 bool wereModulesAddedOrModified =
false;
3200 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
3202 Environment *env = (*i).at(0);
3203 if (! (actualModulesAdded[env].empty() && actualModulesModified[env].empty()) )
3205 wereModulesAddedOrModified =
true;
3210 if (wereModulesAddedOrModified)
3212 map<string, VuoCompilerType *> inheritedTypes;
3213 for (
const vector<Environment *> &envs : environments)
3215 for (Environment *env : envs)
3217 env->reifyPortTypes(inheritedTypes);
3218 map<string, VuoCompilerType *> envTypes = env->getTypes();
3219 inheritedTypes.insert(envTypes.begin(), envTypes.end());
3228 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
3230 Environment *env = (*i).at(0);
3232 set<string> sourcesToUnload;
3233 sourcesToUnload.insert(sourcesRemoved[env].begin(), sourcesRemoved[env].end());
3234 sourcesToUnload.insert(sourcesDepOnModulesRemoved[env].begin(), sourcesDepOnModulesRemoved[env].end());
3235 if (! sourcesToUnload.empty())
3237 string moduleSearchPath = env->getModuleSearchPaths().front();
3239 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
3242 dispatch_sync(environmentQueue, ^{
3243 otherCompiler->loadModulesAndSources(set<string>(), set<string>(), sourcesToUnload,
3244 set<string>(), set<string>(), set<string>(),
3245 false,
false, env,
nullptr,
nullptr,
"");
3248 delete otherCompiler;
3252 if (!env->isBuiltIn() && !sourcesToUnload.empty())
3255 env->deleteModulesCompiledFromSourceCode(sourcesToUnload);
3263 map<Environment *, set<string> > sourcesDepOnModulesAdded;
3265 map<Environment *, set<string> > modulesDepOnModulesAdded;
3266 __block map<Environment *, set<string> > modulesDepOnModulesAdded_otherCompiler;
3267 __block map<Environment *, set<string> > sourcesDepOnModulesAdded_otherCompiler;
3269 map<Environment *, set<string> > actualModuleKeysAdded;
3270 for (
const vector<Environment *> &envs : environments)
3272 Environment *env = envs.at(0);
3277 vector<VuoDirectedAcyclicNetwork *> searchDependencyGraphs;
3278 searchDependencyGraphs.push_back(compositionDependencyGraph);
3279 for (map<
string, vector<Environment *> >::iterator ii = environmentsForCompositionFamily.begin(); ii != environmentsForCompositionFamily.end(); ++ii)
3281 vector< vector<Environment *> > otherEnvs = sharedEnvironments;
3282 otherEnvs.push_back(ii->second);
3284 searchDependencyGraphs.push_back(other);
3287 VuoDirectedAcyclicGraph *currentEnvironmentDependencyGraph = (currentEnvironment ? currentEnvironment->getCompositionDependencyGraph() :
nullptr);
3289 findDependentModulesAndSources(actualModuleKeysAdded, searchDependencyGraphs, currentEnvironmentDependencyGraph,
3290 modulesDepOnModulesAdded, modulesDepOnModulesAdded_otherCompiler,
3291 sourcesDepOnModulesAdded, sourcesDepOnModulesAdded_otherCompiler);
3293 set<Environment *> otherEnvironments;
3294 for (map<Environment *, set<string> >::iterator i = sourcesDepOnModulesAdded_otherCompiler.begin(); i != sourcesDepOnModulesAdded_otherCompiler.end(); ++i)
3295 otherEnvironments.insert(i->first);
3297 for (Environment *env : otherEnvironments)
3299 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
3300 string moduleSearchPath = env->getModuleSearchPaths().front();
3303 dispatch_sync(environmentQueue, ^{
3304 otherCompiler->loadModulesAndSources(set<string>(), set<string>(), set<string>(),
3305 sourcesDepOnModulesAdded_otherCompiler[env], set<string>(), set<string>(),
3306 false,
true, env,
nullptr,
nullptr,
"");
3309 delete otherCompiler;
3314 set<dispatch_group_t> sourcesLoading;
3315 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
3317 Environment *env = (*i).at(0);
3319 set<string> sourcesToCompile;
3320 sourcesToCompile.insert(sourcesAdded[env].begin(), sourcesAdded[env].end());
3321 sourcesToCompile.insert(sourcesModified[env].begin(), sourcesModified[env].end());
3323 if (sourcesToCompile.size() == 0)
3326 set<dispatch_group_t> s = env->compileModulesFromSourceCode(sourcesToCompile, shouldRecompileSourcesIfUnchanged);
3327 sourcesLoading.insert(s.begin(), s.end());
3330 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
3332 Environment *env = (*i).at(0);
3334 set<string> sourcesToCompile;
3335 sourcesToCompile.insert(sourcesDepOnModulesAdded[env].begin(), sourcesDepOnModulesAdded[env].end());
3336 sourcesToCompile.insert(sourcesDepOnModulesModified[env].begin(), sourcesDepOnModulesModified[env].end());
3338 if (sourcesToCompile.size() == 0)
3341 env->compileModulesFromSourceCode(sourcesToCompile,
true);
3346 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
3348 Environment *env = (*i).at(0);
3349 env->notifyCompilers(actualModulesAdded[env], actualModulesModified[env], actualModulesRemoved[env], issues[env]);
3356 for (
const dispatch_group_t &group : sourcesLoading)
3357 dispatch_retain(group);
3359 set<dispatch_group_t> loadingGroups;
3360 loadingGroups.insert(specializedModulesLoading.begin(), specializedModulesLoading.end());
3361 loadingGroups.insert(sourcesLoading.begin(), sourcesLoading.end());
3362 return loadingGroups;
3376 void VuoCompiler::findDependentModulesAndSources(map<Environment *, set<string> > &changedModules,
3377 const vector<VuoDirectedAcyclicNetwork *> &searchDependencyGraphs,
3379 map<Environment *, set<string> > &modulesDepOnChangedModules_this,
3380 map<Environment *, set<string> > &modulesDepOnChangedModules_other,
3381 map<Environment *, set<string> > &sourcesDepOnChangedModules_this,
3382 map<Environment *, set<string> > &sourcesDepOnChangedModules_other)
3384 for (
const vector<Environment *> &envs : environments)
3386 Environment *env = envs.at(0);
3388 for (
const string &module : changedModules[env])
3390 set<VuoDirectedAcyclicGraph::Vertex *> dependents;
3393 vector<VuoDirectedAcyclicGraph::Vertex *> moduleVertices;
3394 if (currentEnvironmentDependencyGraph)
3400 moduleVertices.push_back(mv);
3403 moduleVertices = searchDependencyGraph->findVertex(module);
3407 DependencyGraphVertex *moduleVertex = static_cast<DependencyGraphVertex *>(moduleVertexRaw);
3408 if (moduleVertex->getEnvironment())
3410 vector<VuoDirectedAcyclicGraph::Vertex *> upstream = searchDependencyGraph->getUpstreamVertices(moduleVertex);
3411 dependents.insert(upstream.begin(), upstream.end());
3418 DependencyGraphVertex *v = static_cast<DependencyGraphVertex *>(dependentVertexRaw);
3419 Environment *dependentEnv = v->getEnvironment();
3423 string dependent = v->getDependency();
3427 if (changedModules[dependentEnv].find(dependent) != changedModules[dependentEnv].end())
3430 ModuleInfo *foundSourceInfo = dependentEnv->listSourceFile(dependent);
3431 ModuleInfo *foundModuleInfo = dependentEnv->listModule(dependent);
3433 bool belongsToCurrentCompiler =
false;
3434 for (
const vector<Environment *> &envs2 : environments)
3436 if (find(envs2.begin(), envs2.end(), dependentEnv) != envs2.end())
3438 belongsToCurrentCompiler =
true;
3443 map<Environment *, set<string> > *whicheverDependents =
nullptr;
3444 ModuleInfo *moduleInfo =
nullptr;
3445 if (foundSourceInfo)
3447 moduleInfo = foundSourceInfo;
3448 whicheverDependents = (belongsToCurrentCompiler ? &sourcesDepOnChangedModules_this : &sourcesDepOnChangedModules_other);
3450 else if (foundModuleInfo)
3452 moduleInfo = foundModuleInfo;
3453 whicheverDependents = (belongsToCurrentCompiler ? &modulesDepOnChangedModules_this : &modulesDepOnChangedModules_other);
3456 (*whicheverDependents)[dependentEnv].insert(dependent);
3457 moduleInfo->setAttempted(
false);
3466 void VuoCompiler::loadedModules(map<string, VuoCompilerModule *> modulesAdded,
3467 map<
string, pair<VuoCompilerModule *, VuoCompilerModule *> > modulesModified,
3468 map<string, VuoCompilerModule *> modulesRemoved,
3469 VuoCompilerIssues *issues,
void *delegateDataV, Environment *currentEnvironment)
3481 auto findVersionsOfModule = [
this, currentEnvironment] (
const string &moduleKey)
3483 vector< pair<Environment *, VuoCompilerModule *> > moduleVersions;
3484 for (
const vector<Environment *> &envs : environments)
3486 Environment *env = envs.at(0);
3488 if (module || env == currentEnvironment)
3489 moduleVersions.push_back( make_pair(env, module) );
3491 return moduleVersions;
3494 for (map<string, VuoCompilerModule *>::iterator i = modulesAdded.begin(); i != modulesAdded.end(); )
3496 string moduleKey = i->first;
3499 vector< pair<Environment *, VuoCompilerModule *> > moduleVersions = findVersionsOfModule(moduleKey);
3501 if (moduleVersions.size() > 1)
3503 modulesAdded.erase(i++);
3505 if (moduleVersions.back().second == moduleAdded)
3507 VuoCompilerModule *moduleSuperseded = moduleVersions.at(moduleVersions.size()-2).second;
3508 modulesModified[moduleKey] = make_pair(moduleSuperseded, moduleAdded);
3515 for (map<
string, pair<VuoCompilerModule *, VuoCompilerModule *> >::iterator i = modulesModified.begin(); i != modulesModified.end(); )
3517 string moduleKey = i->first;
3520 vector< pair<Environment *, VuoCompilerModule *> > moduleVersions = findVersionsOfModule(moduleKey);
3522 if (moduleVersions.size() > 1 && moduleVersions.back().second != moduleModified)
3523 modulesModified.erase(i++);
3528 for (map<string, VuoCompilerModule *>::iterator i = modulesRemoved.begin(); i != modulesRemoved.end(); )
3530 string moduleKey = i->first;
3533 vector< pair<Environment *, VuoCompilerModule *> > moduleVersions = findVersionsOfModule(moduleKey);
3535 if (moduleVersions.size() > 1)
3537 modulesRemoved.erase(i++);
3539 if (moduleVersions.back().first == currentEnvironment)
3541 VuoCompilerModule *moduleUnsuperseded = moduleVersions.at(moduleVersions.size()-2).second;
3542 modulesModified[moduleKey] = make_pair(moduleRemoved, moduleUnsuperseded);
3549 dispatch_async(delegateQueue, ^{
3550 VuoCompilerDelegate::LoadedModulesData *delegateData = static_cast<VuoCompilerDelegate::LoadedModulesData *>(delegateDataV);
3552 if (delegate && ! (modulesAdded.empty() && modulesModified.empty() && modulesRemoved.empty() && issues->
isEmpty()))
3554 delegate->enqueueData(delegateData);
3555 delegate->
loadedModules(modulesAdded, modulesModified, modulesRemoved, issues);
3559 delegateData->release();
3569 void VuoCompiler::loadNodeClassGeneratedAtRuntime(
VuoCompilerNodeClass *nodeClass, Environment *env)
3571 Module *module = nodeClass->
getModule();
3575 setTargetForModule(nodeClass->
getModule());
3579 dispatch_sync(environmentQueue, ^{
3580 env->replaceNodeClass(nodeClass);
3583 __block map<string, VuoCompilerType *> inheritedTypes;
3584 void (^envReifyPortTypes)(Environment *) = ^
void (Environment *env) {
3585 env->reifyPortTypes(inheritedTypes);
3586 map<string, VuoCompilerType *> currentTypes = env->getTypes();
3587 inheritedTypes.insert(currentTypes.begin(), currentTypes.end());
3589 applyToAllEnvironments(envReifyPortTypes);
3598 reifyGenericPortTypes(node->getBase());
3606 void VuoCompiler::reifyGenericPortTypes(
VuoNode *node)
3616 vector<VuoPort *> ports;
3617 ports.insert(ports.end(), inputPorts.begin(), inputPorts.end());
3618 ports.insert(ports.end(), outputPorts.begin(), outputPorts.end());
3620 for (vector<VuoPort *>::iterator j = ports.begin(); j != ports.end(); ++j)
3622 VuoCompilerPort *port = static_cast<VuoCompilerPort *>((*j)->getCompiler());
3627 if (! genericType->hasCompiler())
3667 vector<string> allIncludePaths = includePaths;
3668 string preprocessedInputPath = inputPath;
3670 string tmpPreprocessedInputDir;
3671 string dir, file, ext;
3676 string preprocessedInputContents = inputContents;
3678 if (inputContents != preprocessedInputContents)
3681 allIncludePaths.push_back(dir.empty() ?
"." : dir);
3683 preprocessedInputPath = tmpPreprocessedInputDir +
"/" + file +
"." + ext;
3688 else if (ext ==
"fs")
3694 auto getType = [
this] (
const string &moduleKey) {
return this->
getType(moduleKey); };
3699 writeModuleToBitcode(module, outputPath);
3709 vector<string> extraArgs;
3710 for (vector<string>::iterator i = allIncludePaths.begin(); i != allIncludePaths.end(); ++i)
3712 extraArgs.push_back(
"-I");
3713 extraArgs.push_back(*i);
3716 string macosxSdkFolder =
"/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/";
3719 extraArgs.push_back(
"-isysroot");
3720 extraArgs.push_back(macosxSdkFolder +
"MacOSX10.10.sdk");
3723 __block vector<string> headerSearchPaths;
3724 void (^envGetHeaderSearchPaths)(Environment *) = ^
void (Environment *env) {
3725 vector<string> result = env->getHeaderSearchPaths();
3726 headerSearchPaths.insert(headerSearchPaths.end(), result.begin(), result.end());
3728 applyToInstalledEnvironments(envGetHeaderSearchPaths);
3730 __block Module *module;
3732 module = readModuleFromC(preprocessedInputPath, headerSearchPaths, extraArgs);
3735 if (! tmpPreprocessedInputDir.empty())
3736 remove(tmpPreprocessedInputDir.c_str());
3740 "",
"%moduleKey couldn't be compiled as a node class, type, or library. Check the macOS Console for details.");
3747 if (! compilerModule)
3749 VUserLog(
"Error: Didn't recognize '%s' as a node class, type, or library.", inputPath.c_str());
3753 setTargetForModule(module, target);
3754 writeModuleToBitcode(module, outputPath);
3763 Module * VuoCompiler::compileCompositionToModule(
VuoCompilerComposition *composition,
const string &moduleKey,
bool isTopLevelComposition,
3766 composition->
check(issues);
3768 reifyGenericPortTypes(composition);
3771 isTopLevelComposition,
3773 if (telemetry ==
"console")
3776 __block Module *module;
3779 setTargetForModule(module, target);
3801 Module *module = compileCompositionToModule(composition, moduleKey, isTopLevelComposition, issues);
3804 writeModuleToBitcode(module, outputPath);
3821 VDebugLog(
"Compiling '%s'…", inputPath.c_str());
3828 "",
"The composition file couldn't be read or was empty.");
3864 delete baseComposition;
3870 void VuoCompiler::compileSubcompositionString(
const string &compositionString,
const string &outputPath,
3871 std::function<
void(
void)> moduleLoadedCallback, Environment *environment,
3877 bool compilationSucceeded =
false;
3881 compilationSucceeded =
true;
3889 if (! compilationSucceeded)
3895 string outputDir, file, ext;
3899 environment->moduleSearchPathContentsChanged(outputDir, outputPath, compositionString, moduleLoadedCallback,
this, issues);
3917 linkCompositionToCreateExecutableOrDynamicLibrary(inputPath, outputPath, optimization,
false, rPath);
3938 linkCompositionToCreateExecutableOrDynamicLibrary(inputPath, outputPath, optimization,
true);
3955 void VuoCompiler::linkCompositionToCreateExecutableOrDynamicLibrary(
string compiledCompositionPath,
string linkedCompositionPath,
3956 Optimization optimization,
bool isDylib,
string rPath)
3962 shouldLoadAllModules =
false;
3964 set<string> dependencies = getDependenciesForComposition(compiledCompositionPath);
3965 dependencies.insert(getRuntimeDependency());
3967 dependencies.insert(getRuntimeMainDependency());
3969 set<Module *> modules;
3970 set<string> libraries;
3971 set<string> frameworks;
3972 getLinkerInputs(dependencies, optimization, modules, libraries, frameworks);
3974 libraries.insert(compiledCompositionPath);
3976 link(linkedCompositionPath, modules, libraries, frameworks, isDylib, rPath);
4002 set<string> allDependencies = getDependenciesForComposition(compiledCompositionPath);
4003 set<string> addedDependencies;
4004 std::set_difference(allDependencies.begin(), allDependencies.end(),
4005 carriedOverDependencies.begin(), carriedOverDependencies.end(),
4006 std::inserter(addedDependencies, addedDependencies.end()));
4012 set<string> carriedOverExternalLibraries = runningCompositionLibraries->
getExternalLibraries();
4017 string nonUnloadableResourcePath;
4018 string unloadableResourcePath;
4019 set<string> nonUnloadableDependencies;
4020 set<string> unloadableDependencies;
4021 map<string, set<string> > builtInCacheDependencies;
4022 map<string, set<string> > userCacheDependencies;
4023 set<string> builtInLibraries;
4024 set<string> userLibraries;
4025 set<string> addedExternalLibraries;
4026 set<string> addedFrameworks;
4027 set<string> allFrameworks;
4028 if (! addedDependencies.empty())
4030 set<string> builtInModuleAndLibraryDependencies;
4031 set<string> userModuleAndLibraryDependencies;
4032 set<Module *> builtInModules;
4033 set<Module *> userModules;
4036 builtInModuleAndLibraryDependencies, userModuleAndLibraryDependencies, builtInCacheDependencies, userCacheDependencies,
4037 builtInModules, userModules, builtInLibraries, userLibraries, addedExternalLibraries, addedFrameworks);
4039 allFrameworks.insert(carriedOverFrameworks.begin(), carriedOverFrameworks.end());
4040 allFrameworks.insert(addedFrameworks.begin(), addedFrameworks.end());
4042 string dir, linkedCompositionFile, ext;
4045 if (! builtInModules.empty() || builtInLibraries.size() > builtInCacheDependencies.size())
4048 nonUnloadableDependencies = builtInModuleAndLibraryDependencies;
4050 set<string> librariesForNonUnloadableResource = builtInLibraries;
4051 librariesForNonUnloadableResource.insert(carriedOverNonUnloadableLibraries.begin(), carriedOverNonUnloadableLibraries.end());
4052 librariesForNonUnloadableResource.insert(carriedOverExternalLibraries.begin(), carriedOverExternalLibraries.end());
4053 librariesForNonUnloadableResource.insert(addedExternalLibraries.begin(), addedExternalLibraries.end());
4055 link(nonUnloadableResourcePath, builtInModules, librariesForNonUnloadableResource, allFrameworks,
true);\
4057 for (set<string>::iterator i = builtInLibraries.begin(); i != builtInLibraries.end(); )
4060 builtInLibraries.erase(i++);
4065 for (set<string>::iterator i = addedExternalLibraries.begin(); i != addedExternalLibraries.end(); )
4068 addedExternalLibraries.erase(i++);
4074 if (! userModules.empty() || userLibraries.size() > userCacheDependencies.size())
4077 unloadableDependencies = userModuleAndLibraryDependencies;
4079 set<string> librariesForUnloadableResource = userLibraries;
4080 librariesForUnloadableResource.insert(builtInLibraries.begin(), builtInLibraries.end());
4081 librariesForUnloadableResource.insert(carriedOverUnloadableLibraries.begin(), carriedOverUnloadableLibraries.end());
4082 librariesForUnloadableResource.insert(carriedOverNonUnloadableLibraries.begin(), carriedOverNonUnloadableLibraries.end());
4083 librariesForUnloadableResource.insert(carriedOverExternalLibraries.begin(), carriedOverExternalLibraries.end());
4084 librariesForUnloadableResource.insert(addedExternalLibraries.begin(), addedExternalLibraries.end());
4085 if (! nonUnloadableResourcePath.empty())
4086 librariesForUnloadableResource.insert(nonUnloadableResourcePath);
4088 link(unloadableResourcePath, userModules, librariesForUnloadableResource, allFrameworks,
true);
4090 for (set<string>::iterator i = userLibraries.begin(); i != userLibraries.end(); )
4093 userLibraries.erase(i++);
4102 set<string> vuoRuntimePaths;
4104 set<Module *> modules;
4105 set<string> libraries;
4106 set<string> frameworks;
4108 set<string> dependencies;
4109 dependencies.insert(getRuntimeDependency());
4111 vuoRuntimePaths = libraries;
4117 set<Module *> modules;
4118 set<string> libraries;
4120 libraries.insert(compiledCompositionPath);
4121 libraries.insert(carriedOverExternalLibraries.begin(), carriedOverExternalLibraries.end());
4122 libraries.insert(addedExternalLibraries.begin(), addedExternalLibraries.end());
4123 libraries.insert(carriedOverNonUnloadableLibraries.begin(), carriedOverNonUnloadableLibraries.end());
4124 libraries.insert(carriedOverUnloadableLibraries.begin(), carriedOverUnloadableLibraries.end());
4125 libraries.insert(builtInLibraries.begin(), builtInLibraries.end());
4126 libraries.insert(userLibraries.begin(), userLibraries.end());
4127 if (! nonUnloadableResourcePath.empty())
4128 libraries.insert(nonUnloadableResourcePath);
4129 if (! unloadableResourcePath.empty())
4130 libraries.insert(unloadableResourcePath);
4131 libraries.insert(vuoRuntimePaths.begin(), vuoRuntimePaths.end());
4132 link(linkedCompositionPath, modules, libraries, allFrameworks,
true);
4137 if (! nonUnloadableResourcePath.empty())
4140 if (! unloadableResourcePath.empty())
4143 for (map<
string, set<string> >::iterator i = builtInCacheDependencies.begin(); i != builtInCacheDependencies.end(); ++i)
4146 for (map<
string, set<string> >::iterator i = userCacheDependencies.begin(); i != userCacheDependencies.end(); ++i)
4159 set<string> VuoCompiler::getDependenciesForComposition(
const string &compiledCompositionPath)
4161 VDebugLog(
"Gathering dependencies for '%s'…", compiledCompositionPath.c_str());
4164 __block set<string> directDependencies;
4166 Module *module = readModuleFromBitcode(compiledCompositionPath);
4170 delete compilerModule;
4176 auto deps = getDependenciesForComposition(directDependencies,
true);
4195 set<string> directDependencies;
4204 vector<VuoPublishedPort *> publishedPorts;
4205 publishedPorts.insert(publishedPorts.end(), publishedInputPorts.begin(), publishedInputPorts.end());
4206 publishedPorts.insert(publishedPorts.end(), publishedOutputPorts.begin(), publishedOutputPorts.end());
4209 if (publishedPort->getClass()->hasCompiler())
4211 VuoType *portType = static_cast<VuoCompilerPortClass *>( publishedPort->getClass()->getCompiler() )->getDataVuoType();
4215 VuoGenericType *genericType = dynamic_cast<VuoGenericType *>(portType);
4225 directDependencies.insert(dependency);
4230 return directDependencies;
4242 return getDependenciesForComposition(directDependencies,
false);
4252 __block vector<string> librarySearchPaths;
4253 applyToInstalledEnvironments(^
void (Environment *env) {
4254 vector<string> result = env->getLibrarySearchPaths();
4255 librarySearchPaths.insert(librarySearchPaths.end(), result.begin(), result.end());
4258 set<string> dylibDeps;
4259 for (
string dep : getDependenciesForComposition(composition))
4261 string path = getLibraryPath(dep, librarySearchPaths);
4263 dylibDeps.insert(path);
4282 set<string> VuoCompiler::getDependenciesForComposition(
const set<string> &directDependencies,
bool checkCompatibility)
4285 for (set<string>::const_iterator i = directDependencies.begin(); i != directDependencies.end(); ++i)
4288 set<string> dependencies;
4289 for (set<string>::iterator i = directDependencies.begin(); i != directDependencies.end(); ++i)
4291 string moduleKey = *i;
4294 vector<VuoDirectedAcyclicGraph::Vertex *> firstPassVertices = dependencyGraph->
findVertex(moduleKey);
4295 set<VuoDirectedAcyclicGraph::Vertex *> firstPassDependencies(firstPassVertices.begin(), firstPassVertices.end());
4296 for (vector<VuoDirectedAcyclicGraph::Vertex *>::iterator j = firstPassVertices.begin(); j != firstPassVertices.end(); ++j)
4299 firstPassDependencies.insert(downstream.begin(), downstream.end());
4303 for (set<VuoDirectedAcyclicGraph::Vertex *>::iterator j = firstPassDependencies.begin(); j != firstPassDependencies.end(); ++j)
4305 DependencyGraphVertex *v = static_cast<DependencyGraphVertex *>(*j);
4310 vector<VuoDirectedAcyclicGraph::Vertex *> moduleVertices = dependencyGraph->
findVertex(moduleKey);
4311 set<VuoDirectedAcyclicGraph::Vertex *> moduleDependencies(moduleVertices.begin(), moduleVertices.end());
4312 for (vector<VuoDirectedAcyclicGraph::Vertex *>::iterator j = moduleVertices.begin(); j != moduleVertices.end(); ++j)
4315 moduleDependencies.insert(downstream.begin(), downstream.end());
4319 set<string> dependenciesToAdd;
4320 set<string> incompatibleDependencies;
4321 for (set<VuoDirectedAcyclicGraph::Vertex *>::iterator j = moduleDependencies.begin(); j != moduleDependencies.end(); ++j)
4323 DependencyGraphVertex *v = static_cast<DependencyGraphVertex *>(*j);
4324 if (! checkCompatibility || ! v->getEnvironment() || v->isCompatible())
4325 dependenciesToAdd.insert(v->getDependency());
4327 incompatibleDependencies.insert(v->getDependency());
4330 if (! checkCompatibility || incompatibleDependencies.empty())
4332 dependencies.insert(dependenciesToAdd.begin(), dependenciesToAdd.end());
4339 string dependencyTargetString;
4344 for (set<string>::iterator i = incompatibleDependencies.begin(); i != incompatibleDependencies.end(); ++i)
4353 dependencyTargetString = dependencyTargets.
toString();
4356 dependencyTargetString =
"(unknown operating systems)";
4358 string modulePlaceholder = (module ?
"%module" :
"%moduleKey");
4360 "Node incompatible with operating system",
4361 modulePlaceholder +
" is only compatible with " + dependencyTargetString +
4362 ", so this composition can't run on your macOS version (" + compositionTargets.
toString() +
").");
4364 issue.setModuleKey(moduleKey);
4370 vector<string> coreDependencies = getCoreVuoDependencies();
4371 dependencies.insert(coreDependencies.begin(), coreDependencies.end());
4373 return dependencies;
4380 void VuoCompiler::getLinkerInputs(
const set<string> &dependencies, Optimization optimization,
4381 set<Module *> &modules, set<string> &libraries, set<string> &frameworks)
4383 set<string> builtInModuleAndLibraryDependencies;
4384 set<string> userModuleAndLibraryDependencies;
4385 map<string, set<string> > builtInCacheDependencies;
4386 map<string, set<string> > userCacheDependencies;
4387 set<Module *> builtInModules;
4388 set<Module *> userModules;
4389 set<string> builtInLibraries;
4390 set<string> userLibraries;
4391 set<string> externalLibraries;
4393 getLinkerInputs(dependencies, optimization,
4394 builtInModuleAndLibraryDependencies, userModuleAndLibraryDependencies, builtInCacheDependencies, userCacheDependencies,
4395 builtInModules, userModules, builtInLibraries, userLibraries, externalLibraries, frameworks);
4397 modules.insert(builtInModules.begin(), builtInModules.end());
4398 modules.insert(userModules.begin(), userModules.end());
4399 libraries.insert(builtInLibraries.begin(), builtInLibraries.end());
4400 libraries.insert(userLibraries.begin(), userLibraries.end());
4401 libraries.insert(externalLibraries.begin(), externalLibraries.end());
4417 void VuoCompiler::getLinkerInputs(
const set<string> &dependencies, Optimization optimization,
4418 set<string> &builtInModuleAndLibraryDependencies, set<string> &userModuleAndLibraryDependencies,
4419 map<
string, set<string> > &builtInCacheDependencies, map<
string, set<string> > &userCacheDependencies,
4420 set<Module *> &builtInModules, set<Module *> &userModules,
4421 set<string> &builtInLibraries, set<string> &userLibraries,
4422 set<string> &externalLibraries, set<string> &externalFrameworks)
4425 if (shouldUseModuleCache)
4428 __block vector<string> librarySearchPaths;
4429 void (^envGetLibrarySearchPaths)(Environment *) = ^
void (Environment *env) {
4430 vector<string> result = env->getLibrarySearchPaths();
4431 librarySearchPaths.insert(librarySearchPaths.end(), result.begin(), result.end());
4433 applyToInstalledEnvironments(envGetLibrarySearchPaths);
4435 for (set<string>::iterator i = dependencies.begin(); i != dependencies.end(); ++i)
4437 string dependency = *i;
4439 bool foundInCache =
false;
4440 string moduleCachePath;
4441 bool isInBuiltInModuleCache =
false;
4442 if (shouldUseModuleCache)
4443 foundInCache = findInModuleCache(dependency, moduleCachePath, isInBuiltInModuleCache);
4447 if (isInBuiltInModuleCache)
4449 builtInLibraries.insert(moduleCachePath);
4450 builtInCacheDependencies[moduleCachePath].insert(dependency);
4454 userLibraries.insert(moduleCachePath);
4455 userCacheDependencies[moduleCachePath].insert(dependency);
4461 void (^envFindModule)(Environment *) = ^
void (Environment *env) {
4466 applyToAllEnvironments(envFindModule);
4470 if (module->getModule())
4472 string modulePath = module->getModulePath();
4473 if (! modulePath.empty() && dynamic_cast<VuoCompilerType *>(module))
4475 if (module->isBuiltIn())
4476 builtInLibraries.insert(modulePath);
4478 userLibraries.insert(modulePath);
4482 if (module->isBuiltIn())
4483 builtInModules.insert(module->getModule());
4485 userModules.insert(module->getModule());
4488 if (module->isBuiltIn())
4489 builtInModuleAndLibraryDependencies.insert(dependency);
4491 userModuleAndLibraryDependencies.insert(dependency);
4497 externalFrameworks.insert(dependency);
4500 string dependencyPath = getLibraryPath(dependency, librarySearchPaths);
4501 if (! dependencyPath.empty())
4502 externalLibraries.insert(dependencyPath);
4504 VUserLog(
"Warning: Could not locate dependency '%s'.", dependency.c_str());
4516 string VuoCompiler::getLibraryPath(
const string &dependency, vector<string> librarySearchPaths)
4523 if (dependency !=
"crypto"
4524 && dependency !=
"ssl")
4525 librarySearchPaths.push_back(
"/usr/lib");
4527 for (
auto &path : librarySearchPaths)
4529 vector<string> variations;
4530 variations.push_back(path +
"/" + dependency);
4531 variations.push_back(path +
"/lib" + dependency);
4532 variations.push_back(path +
"/lib" + dependency +
".dylib");
4533 variations.push_back(path +
"/lib" + dependency +
".a");
4534 for (
auto &variation : variations)
4549 void VuoCompiler::useModuleCache(
bool shouldUseExistingBuiltInCaches,
bool shouldUseExistingOtherCaches)
4551 loadModulesIfNeeded();
4555 dispatch_sync(environmentQueue, ^{
4556 set<string> dylibsForCachesOfInstalledModules;
4557 set<string> frameworksForCachesOfInstalledModules;
4558 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
4560 bool builtin = (i == environments.begin());
4561 set<string> dylibsForCacheOfGeneratedModules;
4562 set<string> frameworksForCacheOfGeneratedModules;
4564 for (
int j = i->size() - 1; j >= 0; --j)
4566 Environment *env = i->at(j);
4567 bool installed = (j == 0);
4569 set<string> cacheableModulesAndDependencies;
4570 set<string> dylibsNeededToLinkToThisCache;
4571 set<string> frameworksNeededToLinkToThisCache;
4572 env->getCacheableModulesAndDependencies(builtin, installed, cacheableModulesAndDependencies,
4573 dylibsNeededToLinkToThisCache, frameworksNeededToLinkToThisCache);
4575 set<string> accumulatedDylibs;
4576 accumulatedDylibs.insert(dylibsNeededToLinkToThisCache.begin(), dylibsNeededToLinkToThisCache.end());
4577 accumulatedDylibs.insert(dylibsForCachesOfInstalledModules.begin(), dylibsForCachesOfInstalledModules.end());
4578 accumulatedDylibs.insert(dylibsForCacheOfGeneratedModules.begin(), dylibsForCacheOfGeneratedModules.end());
4580 set<string> accumulatedFrameworks;
4581 accumulatedFrameworks.insert(frameworksNeededToLinkToThisCache.begin(), frameworksNeededToLinkToThisCache.end());
4582 accumulatedFrameworks.insert(frameworksForCachesOfInstalledModules.begin(), frameworksForCachesOfInstalledModules.end());
4583 accumulatedFrameworks.insert(frameworksForCacheOfGeneratedModules.begin(), frameworksForCacheOfGeneratedModules.end());
4585 bool shouldUseExistingCache = (builtin ? shouldUseExistingBuiltInCaches : shouldUseExistingOtherCaches);
4586 env->useModuleCache(shouldUseExistingCache,
this, cacheableModulesAndDependencies,
4587 accumulatedDylibs, accumulatedFrameworks);
4591 dylibsForCachesOfInstalledModules.insert(dylibsNeededToLinkToThisCache.begin(), dylibsNeededToLinkToThisCache.end());
4592 frameworksForCachesOfInstalledModules.insert(frameworksNeededToLinkToThisCache.begin(), frameworksNeededToLinkToThisCache.end());
4596 dylibsForCacheOfGeneratedModules.insert(dylibsNeededToLinkToThisCache.begin(), dylibsNeededToLinkToThisCache.end());
4597 frameworksForCacheOfGeneratedModules.insert(frameworksNeededToLinkToThisCache.begin(), frameworksNeededToLinkToThisCache.end());
4603 Environment::waitForModuleCachesToBuild();
4614 bool VuoCompiler::findInModuleCache(
const string &moduleOrDependency,
string &cachePath,
bool &isBuiltinCache)
4616 __block
bool found =
false;
4617 __block
string outPath;
4618 __block
bool outBuiltin;
4619 dispatch_sync(environmentQueue, ^{
4620 for (vector< vector<Environment *> >::iterator i = environments.begin(); i != environments.end(); ++i)
4622 bool builtin = (i == environments.begin());
4624 for (
int j = i->size() - 1; j >= 0; --j)
4626 Environment *env = i->at(j);
4629 bool resultFound = env->findInModuleCache(moduleOrDependency, resultPath);
4633 outPath = resultPath;
4634 outBuiltin = builtin;
4640 cachePath = outPath;
4641 isBuiltinCache = outBuiltin;
4654 dispatch_group_async(moduleCacheBuilding, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
4655 useModuleCache(
true,
false);
4673 vuoFrameworkInProgressPath = vuoFrameworkPath;
4676 compiler.useModuleCache(
false,
true);
4688 unsigned long maxSeconds = 30 * 24 * 60 * 60;
4691 for (set<VuoFileUtilities::File *>::iterator i = cacheDirs.begin(); i != cacheDirs.end(); ++i)
4693 string path = (*i)->path();
4695 string file = (*i)->basename();
4696 if (file !=
"Builtin" && file !=
"System" && file !=
"User")
4699 if (fileSeconds > maxSeconds)
4705 string pidAsString = file.substr(Environment::pidCacheDirPrefix.length());
4706 int pid = atoi(pidAsString.c_str());
4707 if (kill(pid, 0) != 0)
4721 dispatch_sync(modulesToLoadQueue, ^{
4722 this->shouldLoadAllModules = shouldLoadAllModules;
4737 void VuoCompiler::link(
string outputPath,
const set<Module *> &modules,
const set<string> &libraries,
const set<string> &frameworks,
bool isDylib,
string rPath)
4739 VDebugLog(
"Linking '%s'…", outputPath.c_str());
4747 Module *compositeModule =
new Module(
"composite", getGlobalContext());
4748 setTargetForModule(compositeModule);
4749 for (set<Module *>::const_iterator i = modules.begin(); i != modules.end(); ++i)
4752 if (Linker::LinkModules(compositeModule, *i, Linker::PreserveSource, &error))
4753 VUserLog(
"Error: Failed to link compositeModule: %s", error.c_str());
4755 writeModuleToBitcode(compositeModule, compositeModulePath);
4756 delete compositeModule;
4763 llvm::sys::Path clangPath = getClangPath();
4765 vector<const char *> args;
4766 vector<char *> argsToFree;
4767 args.push_back(clangPath.c_str());
4769 args.push_back(compositeModulePath.c_str());
4771 vector<string> coreDependencies = getCoreVuoDependencies();
4772 for (set<string>::const_iterator i = libraries.begin(); i != libraries.end(); ++i)
4774 string library = *i;
4776 for (vector<string>::iterator j = coreDependencies.begin(); j != coreDependencies.end(); ++j)
4778 string coreDependency = *j;
4780 args.push_back(
"-force_load");
4788 library = libraryObject;
4791 char *libraryZ = strdup(library.c_str());
4792 args.push_back(libraryZ);
4793 argsToFree.push_back(libraryZ);
4797 vector<string> frameworkArguments;
4799 __block vector<string> frameworkSearchPaths;
4800 void (^envGetFrameworkSearchPaths)(Environment *) = ^
void (Environment *env) {
4801 vector<string> result = env->getFrameworkSearchPaths();
4802 frameworkSearchPaths.insert(frameworkSearchPaths.end(), result.begin(), result.end());
4804 applyToInstalledEnvironments(envGetFrameworkSearchPaths);
4806 for (vector<string>::const_iterator i = frameworkSearchPaths.begin(); i != frameworkSearchPaths.end(); ++i)
4810 frameworkArguments.push_back(a);
4811 char *frameworkArgument = strdup(a.c_str());
4812 args.push_back(frameworkArgument);
4813 argsToFree.push_back(frameworkArgument);
4816 for (set<string>::const_iterator i = frameworks.begin(); i != frameworks.end(); ++i)
4818 args.push_back(
"-framework");
4820 string frameworkName = *i;
4821 frameworkName = frameworkName.substr(0, frameworkName.length() - string(
".framework").length());
4822 char *frameworkNameZ = strdup(frameworkName.c_str());
4823 args.push_back(frameworkNameZ);
4824 argsToFree.push_back(frameworkNameZ);
4828 llvm::sys::Path cRuntimePath;
4829 llvm::sys::Path crt1Path;
4830 string vuoFrameworkPath = getVuoFrameworkPath();
4831 string vuoFrameworkContainingFolder = vuoFrameworkPath +
"/..";
4832 if (! vuoFrameworkPath.empty())
4834 cRuntimePath = vuoFrameworkPath +
"/Modules/";
4835 crt1Path = cRuntimePath;
4836 crt1Path.appendComponent(
"crt1.o");
4841 if (!isDylib && crt1Path.canRead())
4843 args.push_back(
"-nostartfiles");
4844 args.push_back(crt1Path.c_str());
4848 args.push_back(
"-Xlinker");
4849 args.push_back(
"--no-demangle");
4852 args.push_back(
"-v");
4855 args.push_back(
"-dynamiclib");
4857 args.push_back(
"-Xlinker");
4858 args.push_back(
"-headerpad_max_install_names");
4862 args.push_back(
"-rpath");
4863 string rPathArg = (rPath.empty() ? vuoFrameworkContainingFolder : rPath);
4864 args.push_back(rPathArg.c_str());
4867 args.push_back(
"-rpath");
4868 args.push_back(LLVM_ROOT
"/lib");
4871 args.push_back(
"-std=c++11");
4872 args.push_back(
"-stdlib=libc++");
4875 clang::DiagnosticOptions *diagOptions =
new clang::DiagnosticOptions();
4876 clang::TextDiagnosticPrinter *diagClient =
new clang::TextDiagnosticPrinter(llvm::errs(), diagOptions);
4877 diagClient->setPrefix(clangPath.str());
4878 IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID(
new clang::DiagnosticIDs());
4879 clang::DiagnosticsEngine Diags(DiagID, diagOptions, diagClient);
4881 clang::driver::Driver TheDriver(args[0],
"x86_64-apple-macosx10.10.0", outputPath, Diags);
4883 TheDriver.CCCIsCXX =
true;
4888 for (vector<const char *>::iterator i = args.begin(); i != args.end(); ++i)
4893 OwningPtr<clang::driver::Compilation> C(TheDriver.BuildCompilation(args));
4898 SmallVector<std::pair<int, const clang::driver::Command *>, 4> FailingCommands;
4900 Res = TheDriver.ExecuteCompilation(*C, FailingCommands);
4903 for (
auto i : argsToFree)
4907 remove(compositeModulePath.c_str());
4913 chmod(outputPath.c_str(), 0755);
4917 __block vector<string> thirdPartyNodeClasses;
4918 dispatch_sync(environmentQueue, ^{
4919 for (
size_t i = 1; i < environments.size(); ++i)
4921 map<string, VuoCompilerNodeClass *> envNodeClasses = environments[i].at(0)->getNodeClasses();
4922 for (map<string, VuoCompilerNodeClass *>::iterator j = envNodeClasses.begin(); j != envNodeClasses.end(); ++j)
4923 thirdPartyNodeClasses.push_back(j->first);
4927 string details =
"One or more nodes in this composition can't be used by this version of Vuo. ";
4928 if (! thirdPartyNodeClasses.empty())
4930 details +=
"Make sure you're using the latest version of all the extra Vuo nodes you've installed:\n";
4931 sort(thirdPartyNodeClasses.begin(), thirdPartyNodeClasses.end());
4932 for (vector<string>::iterator i = thirdPartyNodeClasses.begin(); i != thirdPartyNodeClasses.end(); ++i)
4933 details +=
" • " + *i +
"\n";
4935 details +=
"Check the macOS Console for more information about the problem.";
4938 "Node broken or outdated", details);
4949 Module * VuoCompiler::readModuleFromC(
string inputPath,
const vector<string> &headerSearchPaths,
const vector<string> &extraArgs)
4953 vector<const char *> args;
4954 args.push_back(inputPath.c_str());
4955 args.push_back(
"-DVUO_COMPILER");
4956 args.push_back(
"-fblocks");
4959 args.push_back(
"-Wall");
4960 args.push_back(
"-Wextra");
4961 args.push_back(
"-Wimplicit-fallthrough");
4962 args.push_back(
"-Wno-unused-parameter");
4963 args.push_back(
"-Wno-c++11-extensions");
4964 args.push_back(
"-Wno-sign-compare");
4965 args.push_back(
"-Werror=implicit");
4969 args.push_back(
"-std=c++11");
4970 args.push_back(
"-stdlib=libc++");
4973 for (vector<string>::const_iterator i = headerSearchPaths.begin(); i != headerSearchPaths.end(); ++i)
4975 args.push_back(
"-I");
4976 args.push_back(i->c_str());
4980 args.push_back(
"-v");
4982 for (vector<string>::const_iterator i = extraArgs.begin(); i != extraArgs.end(); ++i)
4983 args.push_back(i->c_str());
4985 clang::DiagnosticOptions * diagOptions =
new clang::DiagnosticOptions();
4986 IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID(
new clang::DiagnosticIDs());
4987 clang::DiagnosticsEngine Diags(DiagID, diagOptions);
4989 OwningPtr<clang::CompilerInvocation> CI(
new clang::CompilerInvocation);
4990 clang::CompilerInvocation::CreateFromArgs(*CI, &args[0], &args[0] + args.size(), Diags);
4992 clang::CompilerInstance Clang;
4993 Clang.setInvocation(CI.take());
4995 Clang.createDiagnostics();
4996 if (!Clang.hasDiagnostics())
5000 llvm::sys::Path builtinHeaderSearchPath;
5001 string vuoFrameworkPath = getVuoFrameworkPath();
5002 if (vuoFrameworkPath.empty())
5004 llvm::sys::Path clangPath = getClangPath();
5005 builtinHeaderSearchPath = clangPath;
5006 builtinHeaderSearchPath.eraseComponent();
5007 builtinHeaderSearchPath.eraseComponent();
5008 builtinHeaderSearchPath.appendComponent(
"lib");
5009 builtinHeaderSearchPath.appendComponent(
"clang");
5010 builtinHeaderSearchPath.appendComponent(CLANG_VERSION_STRING);
5014 builtinHeaderSearchPath = vuoFrameworkPath;
5015 builtinHeaderSearchPath.appendComponent(
"Frameworks");
5016 builtinHeaderSearchPath.appendComponent(
"llvm.framework");
5017 builtinHeaderSearchPath.appendComponent(
"Versions");
5018 builtinHeaderSearchPath.appendComponent(
"A");
5019 builtinHeaderSearchPath.appendComponent(
"lib");
5020 builtinHeaderSearchPath.appendComponent(
"clang");
5021 builtinHeaderSearchPath.appendComponent(CLANG_VERSION_STRING);
5023 Clang.getHeaderSearchOpts().ResourceDir = builtinHeaderSearchPath.str();
5026 clang::CodeGenAction *Act =
new clang::EmitLLVMOnlyAction();
5027 if (!Clang.ExecuteAction(*Act))
5030 return Act->takeModule();
5038 Module * VuoCompiler::readModuleFromBitcode(
string inputPath)
5040 string dir, file, ext;
5043 return readModuleFromBitcode(&inputFile);
5055 size_t inputDataBytes;
5060 Module *module = readModuleFromBitcodeData(inputData, inputDataBytes, error);
5075 Module * VuoCompiler::readModuleFromBitcodeData(
char *inputData,
size_t inputDataBytes,
string &error)
5077 __block Module *module;
5079 StringRef inputDataAsStringRef(inputData, inputDataBytes);
5080 MemoryBuffer *mb = MemoryBuffer::getMemBuffer(inputDataAsStringRef,
"",
false);
5081 module = ParseBitcodeFile(&(*mb), getGlobalContext(), &error);
5094 bool VuoCompiler::writeModuleToBitcode(Module *module,
string outputPath)
5096 if (verifyModule(*module, PrintMessageAction))
5098 VUserLog(
"Error: Module verification failed.");
5103 raw_fd_ostream out(outputPath.c_str(), err);
5106 VUserLog(
"Error: Couldn't open file '%s' for writing: %s", outputPath.c_str(), err.c_str());
5109 WriteBitcodeToFile(module, out);
5119 void VuoCompiler::setTargetForModule(Module *module,
string target)
5146 module->setTargetTriple(
"x86_64-apple-macosx10.10.0");
5157 Module *llvmModule = module->
getModule();
5170 baseNodeClass = dynamic_cast<VuoNodeClass *>(nodeClass->
getBase());
5173 if (dynamic_cast<VuoCompilerSpecializedNodeClass *>(module))
5180 baseType = dynamic_cast<VuoType *>(type->
getBase());
5186 delete baseNodeClass;
5219 return nodeClassForNode->
newNode(title, x, y);
5228 return createPublishedNode(nodeClassName, publishedInputPorts);
5237 return createPublishedNode(nodeClassName, publishedOutputPorts);
5243 VuoNode * VuoCompiler::createPublishedNode(
const string &nodeClassName,
const vector<VuoPublishedPort *> &publishedPorts)
5251 for (
size_t i = 0; i < publishedPorts.size(); ++i)
5253 VuoType *publishedPortType = static_cast<VuoCompilerPort *>(publishedPorts[i]->getCompiler())->getDataVuoType();
5254 if (! dynamic_cast<VuoGenericType *>(publishedPortType))
5257 set<VuoPort *> nodePorts;
5261 nodePorts.insert(inputPort);
5264 nodePorts.insert(outputPort);
5269 nodePorts.insert(inputPort);
5272 for (
VuoPort *port : nodePorts)
5274 VuoCompilerPort *compilerPort = static_cast<VuoCompilerPort *>(port->getCompiler());
5279 reifyGenericPortTypes(node);
5290 dispatch_sync(environmentQueue, ^{
5291 if (environments.size() >= 5)
5292 environments.at(3).at(0)->addExpatriateSourceFile(sourcePath);
5302 dispatch_sync(environmentQueue, ^{
5303 if (environments.size() >= 5)
5305 environments.at(3).at(0)->removeExpatriateSourceFile(sourcePath);
5307 set<string> sourcesRemoved;
5309 loadModulesAndSources(set<string>(), set<string>(), set<string>(), set<string>(), set<string>(), sourcesRemoved,
5310 false,
false, environments.at(3).at(0),
nullptr,
nullptr,
"");
5333 string sourcePathCopy = sourcePath;
5334 string sourceCodeCopy = sourceCode;
5336 dispatch_async(environmentQueue, ^{
5338 ModuleInfo *sourceInfo = NULL;
5340 for (
const vector<Environment *> &envs : environments)
5342 for (Environment *env : envs)
5344 ModuleInfo *potentialSourceInfo = env->listSourceFile(nodeClassName);
5347 sourceInfo = potentialSourceInfo;
5356 bool shouldRecompileSourcesIfUnchanged;
5357 if (! sourceCodeCopy.empty())
5359 sourceInfo->setSourceCode(sourceCodeCopy);
5360 sourceInfo->setSourceCodeOverridden(
true);
5362 shouldRecompileSourcesIfUnchanged =
false;
5366 sourceInfo->revertSourceCode();
5367 sourceInfo->setSourceCodeOverridden(
false);
5369 shouldRecompileSourcesIfUnchanged =
true;
5371 sourceInfo->setAttempted(
false);
5372 sourceInfo->setLastModifiedToNow();
5374 set<string> sourcesModified;
5375 sourcesModified.insert(nodeClassName);
5377 loadModulesAndSources(set<string>(), set<string>(), set<string>(), set<string>(), sourcesModified, set<string>(),
5378 false, shouldRecompileSourcesIfUnchanged,
nullptr,
nullptr,
nullptr,
"");
5417 set<string> nodeClassNameSet;
5418 nodeClassNameSet.insert(nodeClassName);
5419 loadModulesIfNeeded(nodeClassNameSet);
5424 void (^envGetNodeClass)(Environment *) = ^
void (Environment *env) {
5429 applyToAllEnvironments(envGetNodeClass);
5440 loadModulesIfNeeded();
5442 __block map<string, VuoCompilerNodeClass *> nodeClasses;
5443 void (^envGetNodeClasses)(Environment *) = ^
void (Environment *env) {
5444 map<string, VuoCompilerNodeClass *> result = env->getNodeClasses();
5445 nodeClasses.insert(result.begin(), result.end());
5447 applyToInstalledEnvironments(envGetNodeClasses);
5458 set<string> typeNameSet;
5459 typeNameSet.insert(typeName);
5460 loadModulesIfNeeded(typeNameSet);
5463 void (^envGetType)(Environment *) = ^
void (Environment *env) {
5468 applyToInstalledEnvironments(envGetType);
5490 loadModulesIfNeeded();
5492 __block map<string, VuoCompilerType *> types;
5493 void (^envGetTypes)(Environment *) = ^
void (Environment *env) {
5494 map<string, VuoCompilerType *> result = env->getTypes();
5495 types.insert(result.begin(), result.end());
5497 applyToInstalledEnvironments(envGetTypes);
5508 loadModulesIfNeeded();
5510 __block map<string, VuoCompilerModule *> libraryModules;
5511 void (^envGetLibraryModules)(Environment *) = ^
void (Environment *env) {
5512 map<string, VuoCompilerModule *> result = env->getLibraryModules();
5513 libraryModules.insert(result.begin(), result.end());
5515 applyToInstalledEnvironments(envGetLibraryModules);
5516 return libraryModules;
5526 loadModulesIfNeeded();
5528 __block map<string, VuoNodeSet *> nodeSets;
5529 void (^envGetNodeSets)(Environment *) = ^
void (Environment *env) {
5530 map<string, VuoNodeSet *> result = env->getNodeSets();
5531 nodeSets.insert(result.begin(), result.end());
5533 applyToInstalledEnvironments(envGetNodeSets);
5544 loadModulesIfNeeded();
5547 void (^envFindNodeSet)(Environment *) = ^
void (Environment *env) {
5552 applyToInstalledEnvironments(envFindNodeSet);
5562 void (^envFindModule)(Environment *) = ^
void (Environment *env) {
5567 applyToAllEnvironments(envFindModule);
5584 map<string, VuoCompilerNodeClass *> nodeClasses =
getNodeClasses();
5585 for (map<string, VuoCompilerNodeClass *>::const_iterator i = nodeClasses.begin(); i != nodeClasses.end(); ++i)
5592 else if (format ==
"path")
5596 else if (format ==
"dot")
5614 vector<string> VuoCompiler::getCoreVuoDependencies(
void)
5616 vector<string> dependencies;
5617 dependencies.push_back(
"VuoCompositionDiff.o");
5618 dependencies.push_back(
"VuoHeap");
5619 dependencies.push_back(
"VuoException.o");
5620 dependencies.push_back(
"VuoNodeRegistry.o");
5621 dependencies.push_back(
"VuoRuntimeCommunicator.o");
5622 dependencies.push_back(
"VuoRuntimeContext.o");
5623 dependencies.push_back(
"VuoRuntimePersistentState.o");
5624 dependencies.push_back(
"VuoRuntimeState.o");
5625 dependencies.push_back(
"VuoTelemetry.o");
5626 dependencies.push_back(
"VuoThreadManager.o");
5627 dependencies.push_back(
"VuoApp");
5628 dependencies.push_back(
"zmq");
5629 dependencies.push_back(
"json-c");
5630 dependencies.push_back(
"objc");
5631 dependencies.push_back(
"c");
5632 dependencies.push_back(
"AppKit.framework");
5635 dependencies.push_back(LLVM_ROOT
"/lib/libprofile_rt.dylib");
5637 return dependencies;
5643 string VuoCompiler::getRuntimeMainDependency(
void)
5645 return "VuoRuntimeMain.o";
5655 string VuoCompiler::getRuntimeDependency(
void)
5657 return "VuoRuntime.o";
5666 string VuoCompiler::getVuoFrameworkPath(
void)
5668 if (! vuoFrameworkInProgressPath.empty())
5669 return vuoFrameworkInProgressPath;
5677 llvm::sys::Path VuoCompiler::getClangPath(
void)
5688 string dir, moduleKey, ext;
5696 while (nodeClassNameParts.size() > 1 && nodeClassNameParts.back() == ext)
5697 nodeClassNameParts.pop_back();
5700 for (
string &part : nodeClassNameParts)
5704 if (nodeClassNameParts.size() == 1)
5705 nodeClassNameParts.insert(nodeClassNameParts.begin(),
"isf");
5719 __block
bool isLocal =
false;
5721 dispatch_sync(environmentQueue, ^{
5722 if (environments.size() >= 5)
5723 isLocal = environments.at(3).at(0)->findModule(moduleKey);
5737 return lastCompositionBaseDir.empty() ?
"" : lastCompositionBaseDir +
"/Modules";
5752 return lastCompositionBaseDir;
5758 void VuoCompiler::addModuleSearchPath(
string path)
5760 dispatch_sync(environmentQueue, ^{
5761 environments.back().at(0)->addModuleSearchPath(path);
5762 environments.back().at(0)->addLibrarySearchPath(path);
5771 dispatch_sync(environmentQueue, ^{
5772 environments.back().at(0)->addHeaderSearchPath(path);
5781 dispatch_sync(environmentQueue, ^{
5782 environments.back().at(0)->addLibrarySearchPath(path);
5791 dispatch_sync(environmentQueue, ^{
5792 environments.back().at(0)->addFrameworkSearchPath(path);
5801 this->telemetry = telemetry;
5809 this->target = target;
5817 this->isVerbose = isVerbose;
5827 if (VuoPro::getProAccess())
5829 _shouldShowSplashWindow =
false;
5834 _shouldShowSplashWindow = potentiallyShow;
5842 return _shouldShowSplashWindow;
5848 void VuoCompiler::setClangPath(
const string &clangPath)
5850 this->clangPath = llvm::sys::Path(StringRef(clangPath));
5858 string vuoFrameworkPath = getVuoFrameworkPath();
5859 return (vuoFrameworkPath.empty() ?
5860 VUO_BUILD_DIR
"/bin/VuoCompositionLoader.app/Contents/MacOS/VuoCompositionLoader" :
5861 vuoFrameworkPath +
"/Helpers/VuoCompositionLoader.app/Contents/MacOS/VuoCompositionLoader");
5867 string VuoCompiler::getCompositionStubPath(
void)
5869 string vuoFrameworkPath = getVuoFrameworkPath();
5870 return (vuoFrameworkPath.empty() ?
5871 VUO_BUILD_DIR
"/lib/libVuoCompositionStub.dylib" :
5872 vuoFrameworkPath +
"/Modules/libVuoCompositionStub.dylib");
5878 string VuoCompiler::getCachePathForComposition(
const string compositionDir)
5880 string modifierLetterColon(
"꞉");
5881 string cachedModulesName = compositionDir;
5891 __block vector<string> moduleSearchPaths;
5892 void (^envGetModuleSearchPaths)(Environment *) = ^
void (Environment *env) {
5893 vector<string> result = env->getModuleSearchPaths();
5894 moduleSearchPaths.insert(moduleSearchPaths.end(), result.begin(), result.end());
5896 applyToInstalledEnvironments(envGetModuleSearchPaths);
5898 __block vector<string> headerSearchPaths;
5899 void (^envGetHeaderSearchPaths)(Environment *) = ^
void (Environment *env) {
5900 vector<string> result = env->getHeaderSearchPaths();
5901 headerSearchPaths.insert(headerSearchPaths.end(), result.begin(), result.end());
5903 applyToInstalledEnvironments(envGetHeaderSearchPaths);
5905 __block vector<string> librarySearchPaths;
5906 void (^envGetLibrarySearchPaths)(Environment *) = ^
void (Environment *env) {
5907 vector<string> result = env->getLibrarySearchPaths();
5908 librarySearchPaths.insert(librarySearchPaths.end(), result.begin(), result.end());
5910 applyToInstalledEnvironments(envGetLibrarySearchPaths);
5912 __block vector<string> frameworkSearchPaths;
5913 void (^envGetFrameworkSearchPaths)(Environment *) = ^
void (Environment *env) {
5914 vector<string> result = env->getFrameworkSearchPaths();
5915 frameworkSearchPaths.insert(frameworkSearchPaths.end(), result.begin(), result.end());
5917 applyToInstalledEnvironments(envGetFrameworkSearchPaths);
5919 fprintf(stderr,
"Module (node class, type, library) search paths:\n");
5920 for (vector<string>::iterator i = moduleSearchPaths.begin(); i != moduleSearchPaths.end(); ++i)
5921 fprintf(stderr,
" %s\n", (*i).c_str());
5922 fprintf(stderr,
"Header search paths:\n");
5923 for (vector<string>::iterator i = headerSearchPaths.begin(); i != headerSearchPaths.end(); ++i)
5924 fprintf(stderr,
" %s\n", (*i).c_str());
5925 fprintf(stderr,
"Other library search paths:\n");
5926 for (vector<string>::iterator i = librarySearchPaths.begin(); i != librarySearchPaths.end(); ++i)
5927 fprintf(stderr,
" %s\n", (*i).c_str());
5928 fprintf(stderr,
"Other framework search paths:\n");
5929 for (vector<string>::iterator i = frameworkSearchPaths.begin(); i != frameworkSearchPaths.end(); ++i)
5930 fprintf(stderr,
" %s\n", (*i).c_str());
5931 fprintf(stderr,
"Framework path:\n");
5932 if (! getVuoFrameworkPath().empty())
5933 fprintf(stderr,
" %s\n", getVuoFrameworkPath().c_str());
5934 fprintf(stderr,
"Clang path:\n");
5935 if (! getClangPath().str().empty())
5936 fprintf(stderr,
" %s\n", getClangPath().c_str());
5952 string directory, file, extension;
5956 compiler.
compileComposition(compositionFilePath, compiledCompositionPath,
true, issues);
5958 remove(compiledCompositionPath.c_str());
5987 string compositionPath = (workingDirectory.empty() ?
"." : workingDirectory) +
"/" + processName +
".vuo";
5993 remove(compiledCompositionPath.c_str());
6017 string directory, file, extension;
6020 compiler.
compileComposition(compositionFilePath, compiledCompositionPath,
true, issues);
6023 remove(compiledCompositionPath.c_str());
6052 string compositionPath = (workingDirectory.empty() ?
"." : workingDirectory) +
"/UntitledComposition.vuo";
6058 remove(compiledCompositionPath.c_str());
6071 pendingDataQueue = dispatch_queue_create(
"org.vuo.compiler.delegate.pending", 0);
6076 LoadedModulesData *data = dequeueData();
6083 void VuoCompilerDelegate::enqueueData(LoadedModulesData *data)
6085 dispatch_sync(pendingDataQueue, ^{
6086 pendingData.push_back(data);
6093 VuoCompilerDelegate::LoadedModulesData * VuoCompilerDelegate::dequeueData(
void)
6095 __block LoadedModulesData *ret;
6096 dispatch_sync(pendingDataQueue, ^{
6097 ret = pendingData.front();
6098 pendingData.pop_front();
6107 VuoCompilerDelegate::LoadedModulesData::LoadedModulesData(
const set< pair<VuoCompilerModule *, VuoCompilerModule *> > &modulesModified,
6110 referenceCountQueue = dispatch_queue_create(
"org.vuo.compiler.delegate.reference", 0);
6113 this->modulesModified = modulesModified;
6114 this->modulesRemoved = modulesRemoved;
6115 this->issues = issues;
6121 VuoCompilerDelegate::LoadedModulesData::~LoadedModulesData(
void)
6125 for (set< pair<VuoCompilerModule *, VuoCompilerModule *> >::iterator i = modulesModified.begin(); i != modulesModified.end(); ++i)
6128 for (set<VuoCompilerModule *>::iterator i = modulesRemoved.begin(); i != modulesRemoved.end(); ++i)
6135 void VuoCompilerDelegate::LoadedModulesData::retain(
void)
6137 dispatch_sync(referenceCountQueue, ^{
6145 void VuoCompilerDelegate::LoadedModulesData::release(
void)
6147 dispatch_sync(referenceCountQueue, ^{
6149 if (referenceCount == 0) {