]> git.tdb.fi Git - builder.git/blob - source/component.cpp
Reorder class members
[builder.git] / source / component.cpp
1 /* $Id$
2
3 This file is part of builder
4 Copyright © 2006-2009  Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
6 */
7
8 #include <msp/core/except.h>
9 #include <msp/fs/dir.h>
10 #include <msp/fs/stat.h>
11 #include <msp/fs/utils.h>
12 #include <msp/strings/lexicalcast.h>
13 #include "builder.h"
14 #include "component.h"
15 #include "header.h"
16 #include "install.h"
17 #include "objectfile.h"
18 #include "sharedlibrary.h"
19 #include "sourcepackage.h"
20 #include "staticlibrary.h"
21 #include "target.h"
22
23 using namespace std;
24 using namespace Msp;
25
26 Component::Component(SourcePackage &p, Type t, const string &n):
27         pkg(p),
28         type(t),
29         name(n),
30         install(false),
31         module_host(0),
32         modular(false),
33         deflt(true)
34 { }
35
36 void Component::create_build_info()
37 {
38         build_info.add(pkg.get_build_info());
39
40         for(PackageList::iterator i=requires.begin(); i!=requires.end(); ++i)
41                 build_info.add((*i)->get_exported_binfo());
42
43         for(StringList::iterator i=build_info.incpath.begin(); i!=build_info.incpath.end(); ++i)
44                 *i=(pkg.get_source() / *i).str();
45         for(StringList::iterator i=build_info.libpath.begin(); i!=build_info.libpath.end(); ++i)
46                 *i=(pkg.get_source() / *i).str();
47
48         if(pkg.get_library_mode()!=DYNAMIC)
49         {
50                 // XXX This may pull in some unnecessary libpaths too.  More thought required.
51                 PackageList reqs=pkg.collect_requires();
52                 for(PackageList::iterator i=reqs.begin(); i!=reqs.end(); ++i)
53                 {
54                         const BuildInfo &ebi=(*i)->get_exported_binfo();
55                         build_info.libpath.insert(build_info.libpath.end(), ebi.libpath.begin(), ebi.libpath.end());
56                 }
57         }
58
59         if(type==PROGRAM)
60         {
61                 string strip=pkg.get_config().get_option("strip").value;
62                 if(lexical_cast<bool>(strip))
63                         build_info.ldflags.push_back("-s");
64         }
65
66         if(modular)
67         {
68                 build_info.ldflags.push_back("-rdynamic");
69                 build_info.libs.push_back("dl");
70         }
71         else if(module_host)
72         {
73                 const PathList &host_src=module_host->get_sources();
74                 for(PathList::const_iterator i=host_src.begin(); i!=host_src.end(); ++i)
75                         build_info.incpath.push_back(i->str());
76         }
77
78         build_info.unique();
79 }
80
81 void Component::create_targets() const
82 {
83         Builder &builder=pkg.get_builder();
84         Target *world=builder.get_target("world");
85         Target *def_tgt=builder.get_target("default");
86
87         PathList files=collect_source_files();
88
89         bool build_exe=(type!=HEADERS);
90
91         list<ObjectFile *> objs;
92         list<Target *> inst_tgts;
93         for(PathList::const_iterator i=files.begin(); i!=files.end(); ++i)
94         {
95                 string ext=FS::extpart(FS::basename(*i));
96                 if((ext==".cpp" || ext==".c") && build_exe)
97                 {
98                         SourceFile *src=new SourceFile(builder, this, i->str());
99
100                         // Compile sources
101                         ObjectFile *obj=new ObjectFile(builder, *this, *src);
102                         objs.push_back(obj);
103                 }
104                 else if(ext==".h")
105                 {
106                         Target *hdr=builder.get_target(i->str());
107                         if(!hdr)
108                                 hdr=new Header(builder, this, i->str());
109
110                         // Install headers if requested
111                         if(!install_headers.empty())
112                                 inst_tgts.push_back(hdr);
113                 }
114         }
115
116         if(build_exe)
117         {
118                 Executable *exe=0;
119                 StaticLibrary *slib=0;
120                 if(type==LIBRARY)
121                 {
122                         exe=new SharedLibrary(builder, *this, objs);
123                         slib=new StaticLibrary(builder, *this, objs);
124                 }
125                 else
126                         exe=new Executable(builder, *this, objs);
127
128                 if(&pkg==builder.get_main_package() && deflt)
129                 {
130                         def_tgt->add_depend(exe);
131                         if(slib) def_tgt->add_depend(slib);
132                 }
133                 else
134                 {
135                         world->add_depend(exe);
136                         if(slib) world->add_depend(slib);
137                 }
138
139                 if(install)
140                 {
141                         inst_tgts.push_back(exe);
142                         if(slib)
143                                 inst_tgts.push_back(slib);
144                 }
145         }
146
147         Target *inst_tgt=builder.get_target("install");
148         for(TargetList::const_iterator i=inst_tgts.begin(); i!=inst_tgts.end(); ++i)
149                 inst_tgt->add_depend(new Install(builder, pkg, **i));
150 }
151
152 PathList Component::collect_source_files() const
153 {
154         PathList files;
155         for(PathList::const_iterator i=sources.begin(); i!=sources.end(); ++i)
156         {
157                 if(FS::is_dir(*i))
158                 {
159                         list<string> sfiles=list_files(*i);
160                         for(list<string>::iterator j=sfiles.begin(); j!=sfiles.end(); ++j)
161                                 files.push_back(*i / *j);
162                 }
163                 else
164                         files.push_back(*i);
165         }
166
167         return files;
168 }
169
170
171 Component::Loader::Loader(Component &c):
172         comp(c)
173 {
174         add("source",          &Loader::source);
175         add("install",         &Component::install);
176         add("install_headers", &Component::install_headers);
177         add("build_info",      &Loader::build_info);
178         add("require",         &Loader::require);
179         add("modular",         &Loader::modular);
180         add("host",            &Loader::host);
181         add("default",         &Component::deflt);
182 }
183
184 void Component::Loader::source(const string &s)
185 {
186         comp.sources.push_back(comp.pkg.get_source()/s);
187 }
188
189 void Component::Loader::require(const string &n)
190 {
191         Package *req=comp.pkg.get_builder().get_package(n);
192         if(req)
193                 comp.requires.push_back(req);
194 }
195
196 void Component::Loader::modular()
197 {
198         if(comp.type!=PROGRAM)
199                 throw Msp::Exception("Only programs can be modular");
200         comp.modular=true;
201 }
202
203 void Component::Loader::host(const string &n)
204 {
205         const ComponentList &comps=comp.pkg.get_components();
206         for(ComponentList::const_iterator i=comps.begin(); i!=comps.end(); ++i)
207                 if(i->get_name()==n)
208                 {
209                         if(i->get_type()!=PROGRAM || !i->get_modular())
210                                 throw Msp::Exception("Module host must be a modular program");
211                         comp.module_host=&*i;
212                         return;
213                 }
214
215         throw Msp::Exception("Unknown component");
216 }
217
218 void Component::Loader::build_info()
219 {
220         load_sub(comp.build_info);
221 }