File findDefaultModulesFolder (bool mustContainJuceCoreModule) { auto& windows = ProjucerApplication::getApp().mainWindowList; for (int i = windows.windows.size(); --i >= 0;) { if (auto* p = windows.windows.getUnchecked (i)->getProject()) { const File f (EnabledModuleList::findDefaultModulesFolder (*p)); if (isJuceModulesFolder (f) || (f.isDirectory() && ! mustContainJuceCoreModule)) return f; } } if (mustContainJuceCoreModule) return findDefaultModulesFolder (false); auto f = File::getSpecialLocation (File::currentApplicationFile); for (;;) { auto parent = f.getParentDirectory(); if (parent == f || ! parent.isDirectory()) break; if (isJuceFolder (parent)) return parent.getChildFile ("modules"); f = parent; } return {}; }
static Array<File> getAllPossibleModulePathsFromExporters (Project& project) { StringArray paths; for (Project::ExporterIterator exporter (project); exporter.next();) { auto& modules = project.getModules(); auto n = modules.getNumModules(); for (int i = 0; i < n; ++i) { auto id = modules.getModuleID (i); if (modules.shouldUseGlobalPath (id)) continue; const auto path = exporter->getPathForModuleString (id); if (path.isNotEmpty()) paths.addIfNotAlreadyThere (path); } String oldPath (exporter->getLegacyModulePath()); if (oldPath.isNotEmpty()) paths.addIfNotAlreadyThere (oldPath); } Array<File> files; for (auto& path : paths) { auto f = project.resolveFilename (path); if (f.isDirectory()) { files.addIfNotAlreadyThere (f); if (f.getChildFile ("modules").isDirectory()) files.addIfNotAlreadyThere (f.getChildFile ("modules")); } } return files; }
File EnabledModuleList::getModuleFolderFromPathIfItExists (const String& path, const String& moduleID, const Project& project) { if (path.isNotEmpty()) { auto moduleFolder = project.resolveFilename (path); if (moduleFolder.exists()) { if (ModuleDescription (moduleFolder).isValid()) return moduleFolder; auto f = moduleFolder.getChildFile (moduleID); if (ModuleDescription (f).isValid()) return f; } } return {}; }
//============================================================================== ProjucerAnalyticsDestination::ProjucerAnalyticsDestination() : ThreadedAnalyticsDestination ("ProjucerAnalyticsThread") { { MemoryOutputStream mo; if (Base64::convertFromBase64 (mo, BinaryData::nothingtoseehere_txt)) apiKey = mo.toString(); } auto dataDir = File::getSpecialLocation (File::userApplicationDataDirectory) #if JUCE_MAC .getChildFile ("Application Support") #endif .getChildFile ("Projucer") .getChildFile ("Analytics"); if (! dataDir.exists()) dataDir.createDirectory(); savedEventsFile = dataDir.getChildFile ("analytics_events.xml"); startAnalyticsThread (initialPeriodMs); }
void InMemoryView::crawler( const std::shared_ptr<w_root_t>& root, SyncView::LockedPtr& view, PendingCollection::LockedPtr& coll, const w_string& dir_name, struct timeval now, bool recursive) { struct watchman_file *file; const watchman_dir_ent* dirent; char path[WATCHMAN_NAME_MAX]; bool stat_all = false; if (watcher_->flags & WATCHER_HAS_PER_FILE_NOTIFICATIONS) { stat_all = watcher_->flags & WATCHER_COALESCED_RENAME; } else { // If the watcher doesn't give us per-file notifications for // watched dirs, then we'll end up explicitly tracking them // and will get updates for the files explicitly. // We don't need to look at the files again when we crawl stat_all = false; } auto dir = resolveDir(view, dir_name, true); // Detect root directory replacement. // The inode number check is handled more generally by the sister code // in stat.cpp. We need to special case it for the root because we never // generate a watchman_file node for the root and thus never call // InMemoryView::statPath (we'll fault if we do!). // Ideally the kernel would have given us a signal when we've been replaced // but some filesystems (eg: BTRFS) do not emit appropriate inotify events // for things like subvolume deletes. We've seen situations where the // root has been replaced and we got no notifications at all and this has // left the cookie sync mechanism broken forever. if (dir_name == root->root_path) { try { auto st = getFileInformation(dir_name.c_str(), root->case_sensitive); if (st.ino != view->rootInode) { // If it still exists and the inode doesn't match, then we need // to force recrawl to make sure we're in sync. // We're lazily initializing the rootInode to 0 here, so we don't // need to do this the first time through (we're already crawling // everything in that case). if (view->rootInode != 0) { root->scheduleRecrawl( "root was replaced and we didn't get notified by the kernel"); return; } recursive = true; view->rootInode = st.ino; } } catch (const std::system_error& err) { handle_open_errno(root, dir, now, "getFileInformation", err.code()); markDirDeleted(view, dir, now, true); return; } } memcpy(path, dir_name.data(), dir_name.size()); path[dir_name.size()] = 0; w_log(W_LOG_DBG, "opendir(%s) recursive=%s\n", path, recursive ? "true" : "false"); /* Start watching and open the dir for crawling. * Whether we open the dir prior to watching or after is watcher specific, * so the operations are rolled together in our abstraction */ std::unique_ptr<watchman_dir_handle> osdir; try { osdir = watcher_->startWatchDir(root, dir, path); } catch (const std::system_error& err) { handle_open_errno(root, dir, now, "opendir", err.code()); markDirDeleted(view, dir, now, true); return; } if (dir->files.empty()) { // Pre-size our hash(es) if we can, so that we can avoid collisions // and re-hashing during initial crawl uint32_t num_dirs = 0; #ifndef _WIN32 struct stat st; int dfd = osdir->getFd(); if (dfd != -1 && fstat(dfd, &st) == 0) { num_dirs = (uint32_t)st.st_nlink; } #endif // st.st_nlink is usually number of dirs + 2 (., ..). // If it is less than 2 then it doesn't follow that convention. // We just pass it through for the dir size hint and the hash // table implementation will round that up to the next power of 2 apply_dir_size_hint( dir, num_dirs, uint32_t(root->config.getInt("hint_num_files_per_dir", 64))); } /* flag for delete detection */ for (auto& it : dir->files) { auto file = it.second.get(); if (file->exists) { file->maybe_deleted = true; } } try { while ((dirent = osdir->readDir()) != nullptr) { // Don't follow parent/self links if (dirent->d_name[0] == '.' && (!strcmp(dirent->d_name, ".") || !strcmp(dirent->d_name, ".."))) { continue; } // Queue it up for analysis if the file is newly existing w_string name(dirent->d_name, W_STRING_BYTE); file = dir->getChildFile(name); if (file) { file->maybe_deleted = false; } if (!file || !file->exists || stat_all || recursive) { auto full_path = dir->getFullPathToChild(name); w_log( W_LOG_DBG, "in crawler calling process_path on %s\n", full_path.c_str()); processPath( root, view, coll, full_path, now, ((recursive || !file || !file->exists) ? W_PENDING_RECURSIVE : 0), dirent); } } } catch (const std::system_error& exc) { log(ERR, "Error while reading dir ", path, ": ", exc.what(), ", re-adding to pending list to re-assess\n"); coll->add(path, now, 0); } osdir.reset(); // Anything still in maybe_deleted is actually deleted. // Arrange to re-process it shortly for (auto& it : dir->files) { auto file = it.second.get(); if (file->exists && (file->maybe_deleted || (file->stat.isDir() && recursive))) { coll->add( dir, file->getName().data(), now, recursive ? W_PENDING_RECURSIVE : 0); } } }
void LibraryModule::addSettingsForModuleToExporter (ProjectExporter& exporter, ProjectSaver& projectSaver) const { auto& project = exporter.getProject(); const auto moduleRelativePath = exporter.getModuleFolderRelativeToProject (getID()); exporter.addToExtraSearchPaths (moduleRelativePath.getParentDirectory()); String libDirPlatform; if (exporter.isLinux()) libDirPlatform = "Linux"; else if (exporter.isCodeBlocks() && exporter.isWindows()) libDirPlatform = "MinGW"; else libDirPlatform = exporter.getTargetFolder().getFileName(); const auto libSubdirPath = String (moduleRelativePath.toUnixStyle() + "/libs/") + libDirPlatform; const auto moduleLibDir = File (project.getProjectFolder().getFullPathName() + "/" + libSubdirPath); if (moduleLibDir.exists()) exporter.addToModuleLibPaths (RelativePath (libSubdirPath, moduleRelativePath.getRoot())); const auto extraInternalSearchPaths = moduleInfo.getExtraSearchPaths().trim(); if (extraInternalSearchPaths.isNotEmpty()) { StringArray paths; paths.addTokens (extraInternalSearchPaths, true); for (int i = 0; i < paths.size(); ++i) exporter.addToExtraSearchPaths (moduleRelativePath.getChildFile (paths.getReference(i))); } { const String extraDefs (moduleInfo.getPreprocessorDefs().trim()); if (extraDefs.isNotEmpty()) exporter.getExporterPreprocessorDefs() = exporter.getExporterPreprocessorDefsString() + "\n" + extraDefs; } { Array<File> compiled; auto& modules = project.getModules(); auto id = getID(); const File localModuleFolder = modules.shouldCopyModuleFilesLocally (id).getValue() ? project.getLocalModuleFolder (id) : moduleInfo.getFolder(); findAndAddCompiledUnits (exporter, &projectSaver, compiled); if (modules.shouldShowAllModuleFilesInProject (id).getValue()) addBrowseableCode (exporter, compiled, localModuleFolder); } if (exporter.isXcode()) { auto& xcodeExporter = dynamic_cast<XcodeProjectExporter&> (exporter); if (project.isAUPluginHost()) xcodeExporter.xcodeFrameworks.addTokens (xcodeExporter.isOSX() ? "AudioUnit CoreAudioKit" : "CoreAudioKit", false); const String frameworks (moduleInfo.moduleInfo [xcodeExporter.isOSX() ? "OSXFrameworks" : "iOSFrameworks"].toString()); xcodeExporter.xcodeFrameworks.addTokens (frameworks, ", ", {}); parseAndAddLibs (xcodeExporter.xcodeLibs, moduleInfo.moduleInfo [exporter.isOSX() ? "OSXLibs" : "iOSLibs"].toString()); } else if (exporter.isLinux()) { parseAndAddLibs (exporter.linuxLibs, moduleInfo.moduleInfo ["linuxLibs"].toString()); parseAndAddLibs (exporter.linuxPackages, moduleInfo.moduleInfo ["linuxPackages"].toString()); } else if (exporter.isWindows()) { if (exporter.isCodeBlocks()) parseAndAddLibs (exporter.mingwLibs, moduleInfo.moduleInfo ["mingwLibs"].toString()); else parseAndAddLibs (exporter.windowsLibs, moduleInfo.moduleInfo ["windowsLibs"].toString()); } else if (exporter.isAndroid()) { parseAndAddLibs (exporter.androidLibs, moduleInfo.moduleInfo ["androidLibs"].toString()); } }