1 #include <msp/core/environ.h>
2 #include <msp/fs/stat.h>
3 #include <msp/fs/utils.h>
4 #include <msp/io/print.h>
5 #include <msp/strings/utils.h>
7 #include "executable.h"
8 #include "importlibrary.h"
9 #include "sharedlibrary.h"
10 #include "staticlibrary.h"
12 #include "virtualfilesystem.h"
17 FileTarget *VirtualFileSystem::get_target(const FS::Path &p) const
19 auto i = targets.find(p.str());
21 return static_cast<FileTarget *>(i->second);
25 void VirtualFileSystem::register_path(const FS::Path &path, FileTarget *t)
27 targets.insert({ path, t });
28 nonexistent.erase(path);
29 builder.get_logger().log("vfs", "Path %s registered to %s", path, t->get_name());
32 FileTarget *VirtualFileSystem::find_header(const string &name, Tool *tool, const SearchPath &path, bool use_syspath)
35 tool = builder.get_toolchain().get_tool_for_suffix(FS::extpart(FS::basename(name)), true);
41 SearchPath combined_path = path;
44 const SearchPath &syspath = tool->get_system_path();
45 combined_path.insert(combined_path.end(), syspath.begin(), syspath.end());
48 for(const FS::Path &p: combined_path)
50 FS::Path filename = p/name;
51 if(FileTarget *tgt = get_target(filename))
53 builder.get_logger().log("vfs", "Header %s found in %s as existing %s", name, p.str(), tgt->get_type());
56 else if(file_exists(filename))
58 builder.get_logger().log("vfs", "Header %s found in %s", name, p.str());
59 return dynamic_cast<FileTarget *>(tool->create_source(filename));
62 builder.get_logger().log("vfs", "Header %s not found in %s", name, p.str());
68 FileTarget *VirtualFileSystem::find_library(const string &lib, const SearchPath &path, BuildInfo::LibraryMode mode, bool use_syspath)
70 SearchPath combined_path = path;
73 Tool &linker = builder.get_toolchain().get_tool("LINK");
75 const SearchPath &syspath = linker.get_system_path();
76 combined_path.insert(combined_path.end(), syspath.begin(), syspath.end());
79 const Architecture &arch = builder.get_current_arch();
81 vector<string> shared_names;
82 bool use_import_lib = false;
83 if(mode!=BuildInfo::FORCE_STATIC)
85 shared_names = Pattern::apply_list(arch.get_patterns<ImportLibrary>(), lib);
86 if(!(use_import_lib = !shared_names.empty()))
87 shared_names = Pattern::apply_list(arch.get_patterns<SharedLibrary>(), lib);
90 vector<string> static_names;
91 if(mode!=BuildInfo::FORCE_DYNAMIC)
92 static_names = Pattern::apply_list(arch.get_patterns<StaticLibrary>(), lib);
94 for(const FS::Path &p: combined_path)
96 const vector<string> *cur_names = (mode>=BuildInfo::DYNAMIC ? &shared_names : &static_names);
97 for(auto j=cur_names->begin(); j!=cur_names->end(); )
99 FS::Path filename = p / *j;
100 if(FileTarget *tgt = get_target(filename))
102 builder.get_logger().log("vfs", "Library %s (%s) found in %s as existing %s", lib, *j, p.str(), tgt->get_type());
105 else if(file_exists(filename))
107 builder.get_logger().log("vfs", "Library %s (%s) found in %s", lib, *j, p.str());
108 if(cur_names==&shared_names)
111 return new ImportLibrary(builder, filename);
112 return new SharedLibrary(builder, filename);
115 return new StaticLibrary(builder, filename);
118 if(++j==cur_names->end())
120 if(mode==BuildInfo::DYNAMIC && cur_names==&shared_names)
121 cur_names = &static_names;
122 else if(mode==BuildInfo::STATIC && cur_names==&static_names)
123 cur_names = &shared_names;
126 j = cur_names->begin();
130 builder.get_logger().log("vfs", "Library %s not found in %s", lib, p.str());
136 FileTarget *VirtualFileSystem::find_binary(const string &name)
139 if(FS::Path(name).is_absolute())
143 if(sys_bin_path.empty())
145 string env_path = Msp::getenv("PATH");
146 if(!env_path.empty())
148 for(const string &p: split(env_path, ':'))
149 sys_bin_path.push_back(p);
153 sys_bin_path.push_back("/bin");
154 sys_bin_path.push_back("/usr/bin");
160 for(const FS::Path &p: path)
162 FS::Path filename = p/name;
163 if(FileTarget *tgt = get_target(filename))
165 builder.get_logger().log("vfs", "Binary %s found in %s as existing %s", name, p, tgt->get_type());
168 else if(file_exists(filename))
170 builder.get_logger().log("vfs", "Binary %s found in %s", name, p);
171 return new Executable(builder, filename);
174 builder.get_logger().log("vfs", "Binary %s not found in %s", name, p);
180 bool VirtualFileSystem::file_exists(const FS::Path &filename)
182 if(nonexistent.count(filename))
184 if(FS::is_reg(filename))
186 nonexistent.insert(filename);