]> git.tdb.fi Git - builder.git/blob - source/component.cpp
Move the logic for creating targets into the Component class
[builder.git] / source / component.cpp
1 #include <msp/core/error.h>
2 #include <msp/path/utils.h>
3 #include "builder.h"
4 #include "component.h"
5 #include "header.h"
6 #include "install.h"
7 #include "objectfile.h"
8 #include "package.h"
9 #include "sharedlibrary.h"
10 #include "staticlibrary.h"
11 #include "target.h"
12
13 using namespace std;
14 using namespace Msp;
15
16 Component::Component(Package &p, Type t, const string &n):
17         pkg(p),
18         type(t),
19         name(n),
20         install(false),
21         module_host(0),
22         modular(false),
23         deflt(true)
24 { }
25
26 /**
27 Tries to resolve all references to packages.
28 */
29 void Component::resolve_refs()
30 {
31         for(PkgRefList::iterator i=requires.begin(); i!=requires.end(); ++i)
32                 i->resolve();
33 }
34
35 /**
36 Prepares the build information for building.
37 */
38 void Component::create_build_info()
39 {
40         build_info.add(pkg.get_build_info());
41
42         for(PkgRefList::iterator i=requires.begin(); i!=requires.end(); ++i)
43         {
44                 if(!i->get_package())
45                         continue;
46                 //i->get_package()->create_build_info();
47                 build_info.add(i->get_package()->get_exported_binfo());
48         }
49
50         if(modular)
51         {
52                 build_info.ldflags.push_back("-rdynamic");
53                 build_info.libs.push_back("dl");
54         }
55         else if(module_host)
56         {
57                 const PathList &host_src=module_host->get_sources();
58                 for(PathList::const_iterator i=host_src.begin(); i!=host_src.end(); ++i)
59                         build_info.incpath.push_back(i->str());
60         }
61
62         build_info.unique();
63 }
64
65 /**
66 Creates all targets needed for building this component.
67 */
68 void Component::create_targets() const
69 {
70         Builder &builder=pkg.get_builder();
71         Target *world=builder.get_target("world");
72         Target *def_tgt=builder.get_target("default");
73
74         PathList files=collect_source_files();
75
76         bool build_exe=(type!=Component::HEADERS);
77
78         list<ObjectFile *> objs;
79         list<Target *> inst_tgts;
80         for(PathList::const_iterator i=files.begin(); i!=files.end(); ++i)
81         {
82                 string basename=(*i)[-1];
83                 string ext=Path::splitext(basename).ext;
84                 if((ext==".cpp" || ext==".c") && build_exe)
85                 {
86                         SourceFile *src=new SourceFile(builder, this, i->str());
87
88                         // Compile sources
89                         ObjectFile *obj=new ObjectFile(builder, *this, *src);
90                         objs.push_back(obj);
91                 }
92                 else if(ext==".h")
93                 {
94                         Target *hdr=builder.get_target(i->str());
95                         if(!hdr)
96                                 hdr=new Header(builder, this, i->str());
97
98                         // Install headers if requested
99                         if(!install_headers.empty())
100                                 inst_tgts.push_back(hdr);
101                 }
102         }
103
104         if(build_exe)
105         {
106                 Executable    *exe=0;
107                 StaticLibrary *slib=0;
108                 if(type==Component::LIBRARY)
109                 {
110                         exe=new SharedLibrary(builder, *this, objs);
111                         slib=new StaticLibrary(builder, *this, objs);
112                 }
113                 else
114                         exe=new Executable(builder, *this, objs);
115
116                 if(&pkg==builder.get_default_package() && deflt)
117                 {
118                         def_tgt->add_depend(exe);
119                         if(slib) def_tgt->add_depend(slib);
120                 }
121                 else
122                 {
123                         world->add_depend(exe);
124                         if(slib) world->add_depend(slib);
125                 }
126
127                 if(install)
128                 {
129                         inst_tgts.push_back(exe);
130                         if(slib)
131                                 inst_tgts.push_back(slib);
132                 }
133         }
134
135         Target *inst_tgt=builder.get_target("install");
136         for(TargetList::const_iterator i=inst_tgts.begin(); i!=inst_tgts.end(); ++i)
137                 inst_tgt->add_depend(new Install(builder, pkg, **i));
138 }
139
140 /**
141 Collects all files belonging to the component.
142 */
143 PathList Component::collect_source_files() const
144 {
145         PathList files;
146         for(PathList::const_iterator i=sources.begin(); i!=sources.end(); ++i)
147         {
148                 struct stat st;
149                 stat(*i, st);
150                 if(S_ISDIR(st.st_mode))
151                 {
152                         list<string> sfiles=list_files(*i);
153                         for(list<string>::iterator j=sfiles.begin(); j!=sfiles.end(); ++j)
154                                 files.push_back(*i / *j);
155                 }
156                 else
157                         files.push_back(*i);
158         }
159
160         return files;
161 }
162
163
164 Component::Loader::Loader(Component &c):
165         comp(c)
166 {
167         add("source",          &Loader::source);
168         add("install",         &Component::install);
169         add("install_headers", &Component::install_headers);
170         add("build_info",      &Loader::build_info);
171         add("require",         &Loader::require);
172         add("modular",         &Loader::modular);
173         add("host",            &Loader::host);
174         add("default",         &Component::deflt);
175 }
176
177 void Component::Loader::source(const string &s)
178 {
179         comp.sources.push_back(comp.pkg.get_source()/s);
180 }
181
182 void Component::Loader::require(const string &n)
183 {
184         comp.requires.push_back(PackageRef(comp.pkg.get_builder(), n));
185 }
186
187 void Component::Loader::modular()
188 {
189         if(comp.type!=PROGRAM)
190                 throw Msp::Exception("Only programs can be modular");
191         comp.modular=true;
192 }
193
194 void Component::Loader::host(const string &n)
195 {
196         const ComponentList &comps=comp.pkg.get_components();
197         for(ComponentList::const_iterator i=comps.begin(); i!=comps.end(); ++i)
198                 if(i->get_name()==n)
199                 {
200                         if(i->get_type()!=PROGRAM || !i->get_modular())
201                                 throw Msp::Exception("Module host must be a modular program");
202                         comp.module_host=&*i;
203                         return;
204                 }
205
206         throw Msp::Exception("Unknown component");
207 }
208
209 void Component::Loader::build_info()
210 {
211         load_sub(comp.build_info);
212 }