]> git.tdb.fi Git - builder.git/blob - source/package.cpp
Allow requirements for components
[builder.git] / source / package.cpp
1 #include <msp/strconv.h>
2 #include <msp/strutils.h>
3 #include "builder.h"
4 #include "misc.h"
5 #include "package.h"
6
7 using namespace std;
8 using namespace Msp;
9
10 Package::Package(Builder &b, const string &n, const Path::Path &s):
11         builder(b),
12         name(n),
13         source(s),
14         buildable(true),
15         build_info_ready(false)
16 { }
17
18 Package::Package(Builder &b, const string &n, const vector<string> &info):
19         builder(b),
20         name(n),
21         buildable(false),
22         build_info_ready(true)
23 {
24         for(vector<string>::const_iterator i=info.begin(); i!=info.end(); ++i)
25         {
26                 if(!i->compare(0, 2, "-I"))
27                         export_binfo.incpath.push_back(i->substr(2));
28                 else if(!i->compare(0, 2, "-D"))
29                         export_binfo.defines.push_back(i->substr(2));
30                 else if(!i->compare(0, 2, "-L"))
31                         export_binfo.libpath.push_back(i->substr(2));
32                 else if(!i->compare(0, 2, "-l"))
33                         export_binfo.libs.push_back(i->substr(2));
34         }
35 }
36
37 void Package::resolve_refs()
38 {
39         for(list<PackageRef>::iterator i=requires.begin(); i!=requires.end(); ++i)
40                 i->resolve();
41         for(ComponentList::iterator i=components.begin(); i!=components.end(); ++i)
42                 i->resolve_refs();
43 }
44
45 void Package::create_build_info()
46 {
47         if(build_info_ready)
48                 return;
49         
50         for(list<PackageRef>::iterator i=requires.begin(); i!=requires.end(); ++i)
51         {
52                 if(!i->get_package())
53                         continue;
54                 i->get_package()->create_build_info();
55                 build_info.add(i->get_package()->get_exported_binfo());
56         }
57         
58         build_info.cflags.push_back("-Wall");
59         build_info.cflags.push_back("-Wshadow");
60         build_info.cflags.push_back("-Wextra");
61         build_info.cflags.push_back("-Wpointer-arith");
62         build_info.cflags.push_back("-Wconversion");
63         build_info.cflags.push_back("-Werror");
64
65         unsigned flags=get_install_flags();
66
67         if(flags&INCLUDE)
68                 export_binfo.incpath.push_back((Path::Path(config.get_option("prefix").value)/"include").str());
69         if(flags&LIB)
70                 export_binfo.libpath.push_back((Path::Path(config.get_option("prefix").value)/"lib").str());
71
72         string optimize=config.get_option("optimize").value;
73         if(strtol(optimize))
74         {
75                 build_info.cflags.push_back("-O"+optimize);
76                 string cpu=config.get_option("cpu").value;
77                 if(cpu!="auto")
78                         build_info.cflags.push_back("-march="+cpu);
79         }
80
81         if(strtobool(config.get_option("debug").value))
82         {
83                 build_info.cflags.push_back("-ggdb");
84                 build_info.defines.push_back("DEBUG");
85         }
86
87         build_info.unique();
88         export_binfo.unique();
89
90         for(list<Component>::iterator i=components.begin(); i!=components.end(); ++i)
91         {
92                 i->create_build_info();
93                 if(i->get_type()==Component::LIBRARY)
94                         export_binfo.libs.push_back(i->get_name());
95         }
96
97         build_info_ready=true;
98 }
99
100 void Package::process_options(const RawOptionMap &opts)
101 {
102         if(config.process(opts))
103                 config.save(source/".options.cache");
104 }
105
106 Package *Package::create(Builder &b, const string &name)
107 {
108         list<string> argv;
109         argv.push_back("pkg-config");
110         argv.push_back("--silence-errors");
111         argv.push_back("--cflags");
112         argv.push_back("--libs");
113         argv.push_back(name);
114         vector<string> info=split(run_command(argv));
115         
116         if(info.empty())
117         {
118                 if(name=="opengl")
119                         info.push_back("-lGL");
120                 else if(name=="pthread")
121                         info.push_back("-lpthread");
122                 else if(name=="gmpxx")
123                         info.push_back("-lgmpxx");
124                 else
125                         return 0;
126         }
127         
128         Package *pkg=new Package(b, name, info);
129         return pkg;
130 }
131
132 void Package::init_buildable()
133 {
134         buildable=true;
135
136         config.add_option("tempdir",  "temp",   "Directory for storing temporary files");
137         config.add_option("optimize", "0",      "Apply compiler optimizations");
138         config.add_option("debug",    "0",      "Produce debugging symbols");
139         config.add_option("cpu",      "auto",   "CPU type to optimize for");
140         config.add_option("arch",     "native", "Architecture for cross-compiling");
141
142         const char *home=getenv("HOME");
143         unsigned flags=get_install_flags();
144         if(flags)
145                 config.add_option("prefix",     string(home)+"/local"/*"/usr"*/,            "Installation prefix");
146         /*if(flags&INCLUDE)
147                 config.add_option("includedir", "$prefix/include", "Header installation directory");
148         if(flags&BIN)
149                 config.add_option("includedir", "$prefix/bin",     "Binary installation directory");
150         if(flags&LIB)
151                 config.add_option("includedir", "$prefix/lib",     "Library installation directory");
152         if(flags&DATA)
153                 config.add_option("includedir", "$prefix/share",   "Data installation directory");*/
154
155         config.load(source/".options.cache");
156 }
157
158 unsigned Package::get_install_flags()
159 {
160         unsigned flags=0;
161         for(ComponentList::iterator i=components.begin(); i!=components.end(); ++i)
162         {
163                 if(i->get_install())
164                 {
165                         if(i->get_type()==Component::PROGRAM)
166                                 flags|=BIN;
167                         else if(i->get_type()==Component::LIBRARY || i->get_type()==Component::MODULE)
168                                 flags|=LIB;
169                 }
170                 if(!i->get_install_headers().empty())
171                         flags|=INCLUDE;
172         }
173
174         return flags;
175 }
176
177 Package::Loader::Loader(Package &p):
178         pkg(p)
179 {
180         add("version",     &Package::version);
181         add("description", &Package::description);
182         add("require",     &Loader::require);
183         add("program",     &Loader::program);
184         add("library",     &Loader::library);
185         add("headers",     &Loader::headers);
186         add("build_info",  &Loader::build_info);
187 }
188
189 Package::Loader::~Loader()
190 {
191         pkg.init_buildable();
192 }
193
194 void Package::Loader::require(const string &n)
195 {
196         pkg.requires.push_back(PackageRef(pkg.builder, n));
197 }
198
199 void Package::Loader::program(const string &n)
200 {
201         Component prog(pkg, Component::PROGRAM, n);
202         load_sub(prog);
203         pkg.components.push_back(prog);
204 }
205
206 void Package::Loader::library(const string &n)
207 {
208         Component prog(pkg, Component::LIBRARY, n);
209         load_sub(prog);
210         pkg.components.push_back(prog);
211 }
212
213 void Package::Loader::headers(const string &n)
214 {
215         Component prog(pkg, Component::HEADERS, n);
216         load_sub(prog);
217         pkg.components.push_back(prog);
218 }
219
220 void Package::Loader::build_info()
221 {
222         load_sub(pkg.build_info);
223 }