]> git.tdb.fi Git - builder.git/blob - source/virtualfilesystem.cpp
Better logging system
[builder.git] / source / virtualfilesystem.cpp
1 #include <msp/fs/stat.h>
2 #include <msp/fs/utils.h>
3 #include <msp/io/print.h>
4 #include <msp/strings/utils.h>
5 #include "builder.h"
6 #include "csourcefile.h"
7 #include "misc.h"
8 #include "sharedlibrary.h"
9 #include "staticlibrary.h"
10 #include "tool.h"
11 #include "virtualfilesystem.h"
12
13 using namespace std;
14 using namespace Msp;
15
16 namespace {
17
18 void update_hash(string &hash, const string &value)
19 {
20         for(unsigned i=0; i<value.size(); ++i)
21                 hash[i%hash.size()] ^= value[i];
22 }
23
24 }
25
26
27 VirtualFileSystem::VirtualFileSystem(Builder &b):
28         builder(b)
29 {
30 }
31
32 FileTarget *VirtualFileSystem::get_target(const FS::Path &p) const
33 {
34         TargetMap::const_iterator i = targets.find(p.str());
35         if(i!=targets.end())
36                 return static_cast<FileTarget *>(i->second);
37         return 0;
38 }
39
40 void VirtualFileSystem::register_path(const FS::Path &path, FileTarget *t)
41 {
42         targets.insert(TargetMap::value_type(path.str(), t));
43 }
44
45 FileTarget *VirtualFileSystem::find_header(const string &name, const SearchPath &path)
46 {
47         string hash(8, 0);
48         for(list<string>::const_iterator i=path.begin(); i!=path.end(); ++i)
49                 update_hash(hash, *i);
50
51         string id = hash+name;
52         TargetMap::iterator i = include_cache.find(id);
53         if(i!=include_cache.end())
54                 return i->second;
55
56         builder.get_logger().log("vfs", format("Looking for header %s with path %s", name, join(path.begin(), path.end())));
57
58         // XXX This will cause trouble with multiple architectures in a single build
59         const Tool *tool = builder.get_toolchain().get_tool_for_suffix(FS::extpart(FS::basename(name)), true);
60         if(!tool)
61                 return 0;
62         const Tool::SearchPath &syspath = tool->get_system_path();
63
64         FileTarget *tgt = 0;
65         for(SearchPath::const_iterator j=path.begin(); (!tgt && j!=path.end()); ++j)
66                 tgt = get_header(FS::Path(*j)/name, *tool);
67         for(Tool::SearchPath::const_iterator j=syspath.begin(); (!tgt && j!=syspath.end()); ++j)
68                 tgt = get_header(FS::Path(*j)/name, *tool);
69
70         include_cache.insert(TargetMap::value_type(id, tgt));
71
72         return tgt;
73 }
74
75 FileTarget *VirtualFileSystem::find_library(const string &lib, const SearchPath &path, LibMode mode)
76 {
77         string hash(8, 0);
78         for(list<string>::const_iterator i=path.begin(); i!=path.end(); ++i)
79                 update_hash(hash, *i);
80
81         string id = hash+string(1, mode)+lib;
82         TargetMap::iterator i = library_cache.find(id);
83         if(i!=library_cache.end())
84                 return i->second;
85
86         const Tool &linker = builder.get_toolchain().get_tool("LINK");
87         const Tool::SearchPath &syspath = linker.get_system_path();
88
89         builder.get_logger().log("vfs", format("Looking for library %s with path %s", lib, join(path.begin(), path.end())));
90
91         FileTarget *tgt = 0;
92         for(SearchPath::const_iterator j=path.begin(); (!tgt && j!=path.end()); ++j)
93                 tgt = get_library(lib, *j, mode);
94         for(Tool::SearchPath::const_iterator j=syspath.begin(); (!tgt && j!=syspath.end()); ++j)
95                 tgt = get_library(lib, *j, mode);
96
97         library_cache.insert(TargetMap::value_type(id, tgt));
98
99         return tgt;
100 }
101
102 FileTarget *VirtualFileSystem::get_header(const FS::Path &fn, const Tool &tool)
103 {
104         if(FileTarget *tgt = get_target(fn))
105                 return tgt;
106
107         if(FS::is_reg(fn))
108                 return dynamic_cast<FileTarget *>(tool.create_source(fn));
109
110         return 0;
111 }
112
113 FileTarget *VirtualFileSystem::get_library(const string &lib, const FS::Path &path, LibMode mode)
114 {
115         const Architecture &arch = builder.get_current_arch();
116
117         /* Try dynamic libraries only if library mode permits it */
118         if(mode!=ALL_STATIC)
119         {
120                 FS::Path fn = try_patterns(path, arch.get_shared_library_patterns(), lib);
121                 if(!fn.empty())
122                 {
123                         FileTarget *tgt = get_target(fn);
124                         if(!tgt)
125                                 return new SharedLibrary(builder, fn);
126                         else if(mode==DYNAMIC || !tgt->get_package())
127                                 return tgt;
128                 }
129         }
130
131         /* Static libraries are always considered, since sometimes shared versions
132         may not be available */
133         FS::Path fn = try_patterns(path, arch.get_static_library_patterns(), lib);
134         if(!fn.empty())
135         {
136                 if(FileTarget *tgt = get_target(fn))
137                         return tgt;
138                 else
139                         return new StaticLibrary(builder, fn);
140         }
141
142         return 0;
143 }
144
145 FS::Path VirtualFileSystem::try_patterns(const FS::Path &dir, const list<Pattern> &patterns, const string &base)
146 {
147         for(list<Pattern>::const_iterator i=patterns.begin(); i!=patterns.end(); ++i)
148         {
149                 FS::Path full = dir/i->apply(base);
150                 if(get_target(full) || FS::is_reg(full))
151                         return full;
152         }
153
154         return FS::Path();
155 }