]> git.tdb.fi Git - builder.git/blob - source/virtualfilesystem.cpp
Use the tool to create headers
[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         if(builder.get_verbose()>=5)
57                 IO::print("Looking for header %s with path %s\n", name, join(path.begin(), path.end()));
58
59         // XXX This will cause trouble with multiple architectures in a single build
60         const Tool *tool = builder.get_toolchain().get_tool_for_suffix(FS::extpart(FS::basename(name)), true);
61         if(!tool)
62                 return 0;
63         const Tool::SearchPath &syspath = tool->get_system_path();
64
65         FileTarget *tgt = 0;
66         for(SearchPath::const_iterator j=path.begin(); (!tgt && j!=path.end()); ++j)
67                 tgt = get_header(FS::Path(*j)/name, *tool);
68         for(Tool::SearchPath::const_iterator j=syspath.begin(); (!tgt && j!=syspath.end()); ++j)
69                 tgt = get_header(FS::Path(*j)/name, *tool);
70
71         include_cache.insert(TargetMap::value_type(id, tgt));
72
73         return tgt;
74 }
75
76 FileTarget *VirtualFileSystem::find_library(const string &lib, const SearchPath &path, LibMode mode)
77 {
78         string hash(8, 0);
79         for(list<string>::const_iterator i=path.begin(); i!=path.end(); ++i)
80                 update_hash(hash, *i);
81
82         string id = hash+string(1, mode)+lib;
83         TargetMap::iterator i = library_cache.find(id);
84         if(i!=library_cache.end())
85                 return i->second;
86
87         const Tool &linker = builder.get_toolchain().get_tool("LINK");
88         const Tool::SearchPath &syspath = linker.get_system_path();
89
90         if(builder.get_verbose()>=5)
91                 IO::print("Looking for library %s with path %s\n", lib, join(path.begin(), path.end()));
92
93         FileTarget *tgt = 0;
94         for(SearchPath::const_iterator j=path.begin(); (!tgt && j!=path.end()); ++j)
95                 tgt = get_library(lib, *j, mode);
96         for(Tool::SearchPath::const_iterator j=syspath.begin(); (!tgt && j!=syspath.end()); ++j)
97                 tgt = get_library(lib, *j, mode);
98
99         library_cache.insert(TargetMap::value_type(id, tgt));
100
101         return tgt;
102 }
103
104 FileTarget *VirtualFileSystem::get_header(const FS::Path &fn, const Tool &tool)
105 {
106         if(FileTarget *tgt = get_target(fn))
107                 return tgt;
108
109         if(FS::is_reg(fn))
110                 return dynamic_cast<FileTarget *>(tool.create_source(fn));
111
112         return 0;
113 }
114
115 FileTarget *VirtualFileSystem::get_library(const string &lib, const FS::Path &path, LibMode mode)
116 {
117         const Architecture &arch = builder.get_current_arch();
118
119         /* Try dynamic libraries only if library mode permits it */
120         if(mode!=ALL_STATIC)
121         {
122                 FS::Path fn = try_patterns(path, arch.get_shared_library_patterns(), lib);
123                 if(!fn.empty())
124                 {
125                         FileTarget *tgt = get_target(fn);
126                         if(!tgt)
127                                 return new SharedLibrary(builder, fn);
128                         else if(mode==DYNAMIC || !tgt->get_package())
129                                 return tgt;
130                 }
131         }
132
133         /* Static libraries are always considered, since sometimes shared versions
134         may not be available */
135         FS::Path fn = try_patterns(path, arch.get_static_library_patterns(), lib);
136         if(!fn.empty())
137         {
138                 if(FileTarget *tgt = get_target(fn))
139                         return tgt;
140                 else
141                         return new StaticLibrary(builder, fn);
142         }
143
144         return 0;
145 }
146
147 FS::Path VirtualFileSystem::try_patterns(const FS::Path &dir, const list<Pattern> &patterns, const string &base)
148 {
149         for(list<Pattern>::const_iterator i=patterns.begin(); i!=patterns.end(); ++i)
150         {
151                 FS::Path full = dir/i->apply(base);
152                 if(get_target(full) || FS::is_reg(full))
153                         return full;
154         }
155
156         return FS::Path();
157 }