]> git.tdb.fi Git - builder.git/blob - source/component.cpp
2bfa736e14ea2dc7663fcae75b5f6f8c3329395a
[builder.git] / source / component.cpp
1 #include <algorithm>
2 #include <msp/fs/dir.h>
3 #include <msp/fs/stat.h>
4 #include <msp/fs/utils.h>
5 #include <msp/io/print.h>
6 #include <msp/strings/lexicalcast.h>
7 #include "builder.h"
8 #include "component.h"
9 #include "sourcepackage.h"
10
11 using namespace std;
12 using namespace Msp;
13
14 Component::Component(SourcePackage &p, const string &n):
15         package(p),
16         name(n),
17         install(false),
18         deflt(true)
19 { }
20
21 void Component::prepare()
22 {
23         for(Package::Requirements::const_iterator i=requires.begin(); i!=requires.end(); ++i)
24                 (*i)->prepare();
25 }
26
27 void Component::create_build_info()
28 {
29         BuildInfo final_build_info;
30
31         const Package::Requirements &pkg_reqs = package.get_required_packages();
32         Package::Requirements direct_reqs = requires;
33         direct_reqs.insert(direct_reqs.end(), pkg_reqs.begin(), pkg_reqs.end());
34
35         Package::Requirements all_reqs = direct_reqs;
36         for(Package::Requirements::iterator i=all_reqs.begin(); i!=all_reqs.end(); ++i)
37         {
38                 BuildInfo::UpdateLevel level = BuildInfo::CHAINED;
39                 if(find(direct_reqs.begin(), direct_reqs.end(), *i)!=direct_reqs.end())
40                         level = BuildInfo::DEPENDENCY;
41                 final_build_info.update_from((*i)->get_exported_build_info(), level);
42
43                 const Package::Requirements &reqs = (*i)->get_required_packages();
44                 for(Package::Requirements::const_iterator j=reqs.begin(); j!=reqs.end(); ++j)
45                         if(find(all_reqs.begin(), all_reqs.end(), *j)==all_reqs.end())
46                                 all_reqs.push_back(*j);
47         }
48
49         final_build_info.update_from(package.get_build_info());
50         final_build_info.update_from(build_info);
51         build_info = final_build_info;
52
53         for(BuildInfo::PathList::iterator i=build_info.incpath.begin(); i!=build_info.incpath.end(); ++i)
54                 *i = (package.get_source_directory() / *i).str();
55         for(BuildInfo::PathList::iterator i=build_info.libpath.begin(); i!=build_info.libpath.end(); ++i)
56                 *i = (package.get_source_directory() / *i).str();
57 }
58
59 BuildInfo Component::get_build_info_for_path(const FS::Path &path) const
60 {
61         // XXX Cache these and check that the directories actually exist before adding them
62         BuildInfo binfo = build_info;
63         if(!overlays.empty())
64         {
65                 FS::Path dir = FS::dirname(path);
66                 string last = FS::basename(dir);
67                 for(OverlayList::const_iterator i=overlays.begin(); i!=overlays.end(); ++i)
68                         if(last==*i)
69                         {
70                                 dir = FS::dirname(dir);
71                                 break;
72                         }
73
74                 for(SourceList::const_iterator i=sources.begin(); i!=sources.end(); ++i)
75                         if(dir==*i)
76                         {
77                                 binfo.local_incpath.push_back(dir);
78                                 for(OverlayList::const_iterator j=overlays.begin(); j!=overlays.end(); ++j)
79                                         binfo.local_incpath.push_back(*i/ *j);
80                         }
81         }
82         return binfo;
83 }
84
85 Component::SourceList Component::collect_source_files() const
86 {
87         SourceList files;
88         for(SourceList::const_iterator i=sources.begin(); i!=sources.end(); ++i)
89         {
90                 FS::Path path(*i);
91                 if(FS::is_dir(path))
92                 {
93                         SourceList dirs;
94                         dirs.push_back(path);
95                         for(OverlayList::const_iterator j=overlays.begin(); j!=overlays.end(); ++j)
96                         {
97                                 FS::Path opath = path / *j;
98                                 if(FS::is_dir(opath))
99                                         dirs.push_back(opath);
100                         }
101                         set<string> overlay_files;
102                         for(SourceList::const_iterator j=dirs.begin(); j!=dirs.end(); ++j)
103                         {
104                                 package.get_builder().get_logger().log("files", format("Traversing %s", *j));
105                                 list<string> sfiles = list_files(*j);
106                                 for(list<string>::iterator k=sfiles.begin(); k!=sfiles.end(); ++k)
107                                 {
108                                         if(j!=dirs.begin())
109                                         {
110                                                 if(overlay_files.count(*k))
111                                                         continue;
112                                                 overlay_files.insert(*k);
113                                         }
114                                         files.push_back(*j / *k);
115                                 }
116                         }
117                 }
118                 else
119                 {
120                         files.push_back(path);
121                         for(OverlayList::const_iterator j=overlays.begin(); j!=overlays.end(); ++j)
122                         {
123                                 FS::Path opath = FS::dirname(path)/ *j/FS::basename(path);
124                                 if(FS::is_reg(opath))
125                                         files.push_back(opath);
126                         }
127                 }
128         }
129
130         return files;
131 }
132
133
134 Component::Loader::Loader(Component &c):
135         DataFile::ObjectLoader<Component>(c),
136         ConditionalLoader(c.package, format("%s/%s", c.package.get_name(), c.name))
137 {
138         add("overlay",         &Loader::overlay);
139         add("source",          &Loader::source);
140         add("install",         &Component::install);
141         add("install_map",     &Loader::install_map);
142         add("build_info",      &Loader::build_info);
143         add("require",         &Loader::require);
144         add("default",         &Component::deflt);
145 }
146
147 void Component::Loader::build_info()
148 {
149         load_sub(obj.build_info);
150 }
151
152 void Component::Loader::install_map()
153 {
154         load_sub(obj.install_map, obj.package.get_source_directory());
155 }
156
157 void Component::Loader::overlay(const string &o)
158 {
159         obj.overlays.push_back(o);
160 }
161
162 void Component::Loader::require(const string &n)
163 {
164         Package *req = obj.package.get_builder().get_package_manager().find_package(n);
165         if(req)
166                 obj.requires.push_back(req);
167         else
168                 obj.problems.push_back(format("Required package %s not found", n));
169 }
170
171 void Component::Loader::source(const string &s)
172 {
173         obj.sources.push_back((obj.package.get_source_directory()/s).str());
174 }