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 "csourcefile.h"
8 #include "executable.h"
9 #include "importlibrary.h"
10 #include "sharedlibrary.h"
11 #include "staticlibrary.h"
13 #include "virtualfilesystem.h"
18 VirtualFileSystem::VirtualFileSystem(Builder &b):
23 FileTarget *VirtualFileSystem::get_target(const FS::Path &p) const
25 auto i = targets.find(p.str());
27 return static_cast<FileTarget *>(i->second);
31 void VirtualFileSystem::register_path(const FS::Path &path, FileTarget *t)
33 targets.insert({ path, t });
34 nonexistent.erase(path);
35 builder.get_logger().log("vfs", format("Path %s registered to %s", path, t->get_name()));
38 FileTarget *VirtualFileSystem::find_header(const string &name, Tool *tool, const SearchPath &path, bool use_syspath)
41 tool = builder.get_toolchain().get_tool_for_suffix(FS::extpart(FS::basename(name)), true);
47 SearchPath combined_path = path;
50 const SearchPath &syspath = tool->get_system_path();
51 combined_path.insert(combined_path.end(), syspath.begin(), syspath.end());
54 for(const FS::Path &p: combined_path)
56 FS::Path filename = p/name;
57 if(FileTarget *tgt = get_target(filename))
59 builder.get_logger().log("vfs", format("Header %s found in %s as existing %s", name, p.str(), tgt->get_type()));
62 else if(file_exists(filename))
64 builder.get_logger().log("vfs", format("Header %s found in %s", name, p.str()));
65 return dynamic_cast<FileTarget *>(tool->create_source(filename));
68 builder.get_logger().log("vfs", format("Header %s not found in %s", name, p.str()));
74 FileTarget *VirtualFileSystem::find_library(const string &lib, const SearchPath &path, BuildInfo::LibraryMode mode, bool use_syspath)
76 SearchPath combined_path = path;
79 Tool &linker = builder.get_toolchain().get_tool("LINK");
81 const SearchPath &syspath = linker.get_system_path();
82 combined_path.insert(combined_path.end(), syspath.begin(), syspath.end());
85 const Architecture &arch = builder.get_current_arch();
87 vector<string> shared_names;
88 bool use_import_lib = false;
89 if(mode!=BuildInfo::FORCE_STATIC)
91 shared_names = Pattern::apply_list(arch.get_patterns<ImportLibrary>(), lib);
92 if(!(use_import_lib = !shared_names.empty()))
93 shared_names = Pattern::apply_list(arch.get_patterns<SharedLibrary>(), lib);
96 vector<string> static_names;
97 if(mode!=BuildInfo::FORCE_DYNAMIC)
98 static_names = Pattern::apply_list(arch.get_patterns<StaticLibrary>(), lib);
100 for(const FS::Path &p: combined_path)
102 const vector<string> *cur_names = (mode>=BuildInfo::DYNAMIC ? &shared_names : &static_names);
103 for(auto j=cur_names->begin(); j!=cur_names->end(); )
105 FS::Path filename = p / *j;
106 if(FileTarget *tgt = get_target(filename))
108 builder.get_logger().log("vfs", format("Library %s (%s) found in %s as existing %s", lib, *j, p.str(), tgt->get_type()));
111 else if(file_exists(filename))
113 builder.get_logger().log("vfs", format("Library %s (%s) found in %s", lib, *j, p.str()));
114 if(cur_names==&shared_names)
117 return new ImportLibrary(builder, filename);
118 return new SharedLibrary(builder, filename);
121 return new StaticLibrary(builder, filename);
124 if(++j==cur_names->end())
126 if(mode==BuildInfo::DYNAMIC && cur_names==&shared_names)
127 cur_names = &static_names;
128 else if(mode==BuildInfo::STATIC && cur_names==&static_names)
129 cur_names = &shared_names;
132 j = cur_names->begin();
136 builder.get_logger().log("vfs", format("Library %s not found in %s", lib, p.str()));
142 FileTarget *VirtualFileSystem::find_binary(const string &name)
145 if(FS::Path(name).is_absolute())
149 if(sys_bin_path.empty())
151 string env_path = Msp::getenv("PATH");
152 if(!env_path.empty())
154 for(const string &p: split(env_path, ':'))
155 sys_bin_path.push_back(p);
159 sys_bin_path.push_back("/bin");
160 sys_bin_path.push_back("/usr/bin");
166 for(const FS::Path &p: path)
168 FS::Path filename = p/name;
169 if(FileTarget *tgt = get_target(filename))
171 builder.get_logger().log("vfs", format("Binary %s found in %s as existing %s", name, p, tgt->get_type()));
174 else if(file_exists(filename))
176 builder.get_logger().log("vfs", format("Binary %s found in %s", name, p));
177 return new Executable(builder, filename);
180 builder.get_logger().log("vfs", format("Binary %s not found in %s", name, p));
186 bool VirtualFileSystem::file_exists(const FS::Path &filename)
188 if(nonexistent.count(filename))
190 if(FS::is_reg(filename))
192 nonexistent.insert(filename);