| 214 | } |
| 215 | |
| 216 | bool require_dynamic_modules(FileAccessPtr file_access, |
| 217 | const das::string &das_root, |
| 218 | const das::string &project_root, |
| 219 | const das::vector<das::string> &load_modules, |
| 220 | das::TextWriter &tout) { |
| 221 | bool has_project = !project_root.empty() && |
| 222 | normalizeFileName(das_root.c_str()) != |
| 223 | normalizeFileName(project_root.c_str()); |
| 224 | // Collect local module names so we can skip shadows in das_root: |
| 225 | // both project_root scans and explicit -load_module paths take precedence |
| 226 | // over das_root entries with matching basenames. |
| 227 | das_hash_set<das::string> dasroot_skip; |
| 228 | if (has_project) { |
| 229 | dasroot_skip = collect_module_names(project_root); |
| 230 | } |
| 231 | // Basenames are normalized for case-insensitive filesystems (Windows, macOS) |
| 232 | // so e.g. `-load_module D:/mods/dasimgui` shadows `modules/dasImgui`. |
| 233 | das_hash_set<das::string> load_module_names; |
| 234 | for (const auto &p : load_modules) { |
| 235 | load_module_names.insert(normalize_module_name(path_basename(p))); |
| 236 | } |
| 237 | for (const auto &name : load_module_names) { |
| 238 | dasroot_skip.insert(name); |
| 239 | } |
| 240 | bool all_good = das::init_modules_for_folder(file_access, das_root, tout, |
| 241 | dasroot_skip.empty() ? nullptr : &dasroot_skip); |
| 242 | if (has_project) { |
| 243 | // Init for project_root, skipping anything an explicit -load_module |
| 244 | // already covers (load_module wins over project_root/modules/<name>). |
| 245 | all_good &= das::init_modules_for_folder(file_access, project_root, tout, |
| 246 | load_module_names.empty() ? nullptr : &load_module_names); |
| 247 | } |
| 248 | // Finally, init each explicit -load_module path directly. |
| 249 | for (const auto &p : load_modules) { |
| 250 | all_good &= (Result::OK == init_dyn_modules(file_access, p, tout)); |
| 251 | } |
| 252 | // Module .so's may carry DT_NEEDED on sibling-module .so's (e.g. node-editor -> |
| 253 | // dasModuleImgui) that live in modules/<dep>/ and aren't on RUNPATH. Directory |
| 254 | // enumeration order is unsorted on Linux (readdir), so a dependent can be visited |
| 255 | // before its dependency — its register_dynamic_module dlopen then fails and is |
| 256 | // deferred. Retry the deferred set in fixed-point passes so order stops mattering. |
| 257 | retry_pending_dynamic_modules(); |
| 258 | return all_good; |
| 259 | } |
| 260 | |
| 261 | } |
no test coverage detected