]> git.tdb.fi Git - builder.git/blob - source/component.cpp
Adapt to changes in msppath
[builder.git] / source / component.cpp
1 /* $Id$
2
3 This file is part of builder
4 Copyright © 2006-2007 Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
6 */
7
8 #include <msp/core/error.h>
9 #include <msp/path/utils.h>
10 #include <msp/strings/lexicalcast.h>
11 #include "builder.h"
12 #include "component.h"
13 #include "header.h"
14 #include "install.h"
15 #include "objectfile.h"
16 #include "sharedlibrary.h"
17 #include "sourcepackage.h"
18 #include "staticlibrary.h"
19 #include "target.h"
20
21 using namespace std;
22 using namespace Msp;
23
24 Component::Component(SourcePackage &p, Type t, const string &n):
25         pkg(p),
26         type(t),
27         name(n),
28         install(false),
29         module_host(0),
30         modular(false),
31         deflt(true)
32 { }
33
34 /**
35 Prepares the build information for building.
36 */
37 void Component::create_build_info()
38 {
39         build_info.add(pkg.get_build_info());
40
41         for(PackageList::iterator i=requires.begin(); i!=requires.end(); ++i)
42                 build_info.add((*i)->get_exported_binfo());
43
44         if(type==PROGRAM)
45         {
46                 string strip=pkg.get_config().get_option("strip").value;
47                 if(lexical_cast<bool>(strip))
48                         build_info.ldflags.push_back("-s");
49         }
50
51         if(modular)
52         {
53                 build_info.ldflags.push_back("-rdynamic");
54                 build_info.libs.push_back("dl");
55         }
56         else if(module_host)
57         {
58                 const PathList &host_src=module_host->get_sources();
59                 for(PathList::const_iterator i=host_src.begin(); i!=host_src.end(); ++i)
60                         build_info.incpath.push_back(i->str());
61         }
62
63         build_info.unique();
64 }
65
66 /**
67 Creates all targets needed for building this component.
68 */
69 void Component::create_targets() const
70 {
71         Builder &builder=pkg.get_builder();
72         Target *world=builder.get_target("world");
73         Target *def_tgt=builder.get_target("default");
74
75         PathList files=collect_source_files();
76
77         bool build_exe=(type!=HEADERS);
78
79         list<ObjectFile *> objs;
80         list<Target *> inst_tgts;
81         for(PathList::const_iterator i=files.begin(); i!=files.end(); ++i)
82         {
83                 string basename=(*i)[-1];
84                 string ext=splitext(basename).ext;
85                 if((ext==".cpp" || ext==".c") && build_exe)
86                 {
87                         SourceFile *src=new SourceFile(builder, this, i->str());
88
89                         // Compile sources
90                         ObjectFile *obj=new ObjectFile(builder, *this, *src);
91                         objs.push_back(obj);
92                 }
93                 else if(ext==".h")
94                 {
95                         Target *hdr=builder.get_target(i->str());
96                         if(!hdr)
97                                 hdr=new Header(builder, this, i->str());
98
99                         // Install headers if requested
100                         if(!install_headers.empty())
101                                 inst_tgts.push_back(hdr);
102                 }
103         }
104
105         if(build_exe)
106         {
107                 Executable    *exe=0;
108                 StaticLibrary *slib=0;
109                 if(type==LIBRARY)
110                 {
111                         exe=new SharedLibrary(builder, *this, objs);
112                         slib=new StaticLibrary(builder, *this, objs);
113                 }
114                 else
115                         exe=new Executable(builder, *this, objs);
116
117                 if(&pkg==builder.get_main_package() && deflt)
118                 {
119                         def_tgt->add_depend(exe);
120                         if(slib) def_tgt->add_depend(slib);
121                 }
122                 else
123                 {
124                         world->add_depend(exe);
125                         if(slib) world->add_depend(slib);
126                 }
127
128                 if(install)
129                 {
130                         inst_tgts.push_back(exe);
131                         if(slib)
132                                 inst_tgts.push_back(slib);
133                 }
134         }
135
136         Target *inst_tgt=builder.get_target("install");
137         for(TargetList::const_iterator i=inst_tgts.begin(); i!=inst_tgts.end(); ++i)
138                 inst_tgt->add_depend(new Install(builder, pkg, **i));
139 }
140
141 /**
142 Collects all files belonging to the component.
143 */
144 PathList Component::collect_source_files() const
145 {
146         PathList files;
147         for(PathList::const_iterator i=sources.begin(); i!=sources.end(); ++i)
148         {
149                 struct stat st=stat(*i);
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         Package *req=comp.pkg.get_builder().get_package(n);
185         if(req)
186                 comp.requires.push_back(req);
187 }
188
189 void Component::Loader::modular()
190 {
191         if(comp.type!=PROGRAM)
192                 throw Msp::Exception("Only programs can be modular");
193         comp.modular=true;
194 }
195
196 void Component::Loader::host(const string &n)
197 {
198         const ComponentList &comps=comp.pkg.get_components();
199         for(ComponentList::const_iterator i=comps.begin(); i!=comps.end(); ++i)
200                 if(i->get_name()==n)
201                 {
202                         if(i->get_type()!=PROGRAM || !i->get_modular())
203                                 throw Msp::Exception("Module host must be a modular program");
204                         comp.module_host=&*i;
205                         return;
206                 }
207
208         throw Msp::Exception("Unknown component");
209 }
210
211 void Component::Loader::build_info()
212 {
213         load_sub(comp.build_info);
214 }