1 #include <msp/strings/lexicalcast.h>
2 #include <msp/strings/utils.h>
13 Creates a buildable package.
15 Package::Package(Builder &b, const string &n, const Path::Path &s):
25 if(builder.get_verbose()>=4)
26 cout<<"Created buildable package "<<n<<" at "<<s<<'\n';
30 Sets the path where the package files were installed. This is only useful for
31 non-buildable packages that don't use pkg-config.
33 void Package::set_path(const Msp::Path::Path &p)
35 path=builder.get_cwd()/p;
38 Msp::Path::Path Package::get_temp_dir() const
40 return source/config.get_option("tempdir").value/config.get_option("profile").value;
43 Msp::Path::Path Package::get_out_dir() const
45 return source/config.get_option("outdir").value;
49 Checks which kinds of things the components of this package install.
51 @return A bitmask of installed things
53 unsigned Package::get_install_flags()
56 for(ComponentList::iterator i=components.begin(); i!=components.end(); ++i)
60 if(i->get_type()==Component::PROGRAM)
62 else if(i->get_type()==Component::LIBRARY || i->get_type()==Component::MODULE)
65 if(!i->get_install_headers().empty())
72 LibMode Package::get_library_mode() const
74 const string &mode=config.get_option("staticlibs").value;
77 else if(mode=="local")
82 throw Exception("Unknown library mode");
86 Tries to resolve all references to dependency packages.
88 void Package::resolve_refs()
90 for(PkgRefList::iterator i=requires.begin(); i!=requires.end(); ++i)
92 Package *pkg=i->resolve();
93 if(pkg) all_reqs.push_back(pkg);
96 for(ComponentList::iterator i=components.begin(); i!=components.end(); ++i)
99 const PkgRefList &creqs=i->get_requires();
100 for(PkgRefList::const_iterator j=creqs.begin(); j!=creqs.end(); ++j)
102 all_reqs.push_back(j->get_package());
105 for(ConditionList::iterator i=conditions.begin(); i!=conditions.end(); ++i)
108 const PkgRefList &creqs=i->get_requires();
109 for(PkgRefList::const_iterator j=creqs.begin(); j!=creqs.end(); ++j)
111 all_reqs.push_back(j->get_package());
116 Processes configuration options that were most likely obtained from the command
119 void Package::configure(const StringMap &opts, unsigned flag)
124 if(builder.get_verbose()>=3)
125 cout<<"Configuring "<<name<<'\n';
131 StringMap::const_iterator prof=opts.find("profile");
132 if(prof!=opts.end() && flag)
133 config.select_profile(prof->second);
135 config.select_last_profile();
137 if(flag && config.update(opts))
139 if(builder.get_verbose()>=2)
140 cout<<"Configuration of "<<name<<" changed\n";
141 if(!builder.get_dry_run())
147 for(ConditionList::iterator i=conditions.begin(); i!=conditions.end(); ++i)
150 const PkgRefList &reqs=i->get_requires();
151 requires.insert(requires.end(), reqs.begin(), reqs.end());
152 build_info.add(i->get_build_info());
155 for(PackageList::iterator i=all_reqs.begin(); i!=all_reqs.end(); ++i)
157 if((*i)->get_need_path())
158 (*i)->set_path(config.get_option((*i)->get_name()+"_path").value);
159 (*i)->configure(opts, flag&2);
169 Creates a non-buildable package with the given name. Pkg-config is tried first
170 to get build information. If it fails, a built-in list of known packages is
173 Package *Package::create(Builder &b, const string &name)
176 argv.push_back("pkg-config");
177 argv.push_back("--silence-errors");
178 argv.push_back("--cflags");
179 argv.push_back("--libs");
180 argv.push_back(name);
181 vector<string> info=split(run_command(argv));
183 bool need_path=false;
184 bool use_pkgconfig=true;
189 //XXX Put these in an external file
191 info.push_back("-lGL");
192 else if(name=="pthread")
193 info.push_back("-lpthread");
194 else if(name=="gmpxx")
195 info.push_back("-lgmpxx");
196 else if(name=="fmod4")
198 else if(name=="devil")
199 info.push_back("-lIL");
200 else if(name=="Xlib")
201 info.push_back("-lX11");
206 Package *pkg=new Package(b, name, info);
207 pkg->need_path=need_path;
208 pkg->use_pkgconfig=use_pkgconfig;
214 Package::Package(Builder &b, const string &n, const vector<string> &info):
221 for(vector<string>::const_iterator i=info.begin(); i!=info.end(); ++i)
223 if(!i->compare(0, 2, "-I"))
224 export_binfo.incpath.push_back(i->substr(2));
225 else if(!i->compare(0, 2, "-D"))
226 export_binfo.defines.push_back(i->substr(2));
227 else if(!i->compare(0, 2, "-L"))
228 export_binfo.libpath.push_back(i->substr(2));
229 else if(!i->compare(0, 2, "-l"))
230 export_binfo.libs.push_back(i->substr(2));
233 if(builder.get_verbose()>=4)
235 cout<<"Created non-buildable package "<<name<<" with";
236 for(vector<string>::const_iterator i=info.begin(); i!=info.end(); ++i)
243 Initializes configuration options and loads cached values.
245 void Package::init_config()
247 config.add_option("profile", "default", "Configuration profile");
248 config.add_option("tempdir", "temp", "Directory for storing temporary files");
249 config.add_option("outdir", ".", "Directory to put build results in");
250 config.add_option("optimize", "0", "Apply compiler optimizations");
251 config.add_option("debug", "0", "Produce debugging symbols");
252 config.add_option("cpu", "auto", "CPU type to optimize for");
253 config.add_option("arch", "native", "Architecture for cross-compiling");
254 config.add_option("staticlibs", "local", "Use static libraries");
256 unsigned flags=get_install_flags();
258 config.add_option("prefix", "$HOME/local", "Installation prefix");
260 config.add_option("includedir", "$prefix/include", "Header installation directory");
262 config.add_option("includedir", "$prefix/bin", "Binary installation directory");
264 config.add_option("includedir", "$prefix/lib", "Library installation directory");
266 config.add_option("includedir", "$prefix/share", "Data installation directory");*/
268 for(FeatureList::iterator i=features.begin(); i!=features.end(); ++i)
269 config.add_option("with_"+i->name, "0", i->descr);
271 for(PackageList::const_iterator i=all_reqs.begin(); i!=all_reqs.end(); ++i)
272 if((*i)->get_need_path())
273 config.add_option((*i)->get_name()+"_path", "", "Path for "+(*i)->get_name());
277 Fills in build info based on configuration. All required packages must be
278 configured when this is called.
280 void Package::create_build_info()
284 for(PkgRefList::iterator i=requires.begin(); i!=requires.end(); ++i)
286 Package *pkg=i->get_package();
289 const BuildInfo &ebi=pkg->get_exported_binfo();
292 export_binfo.cflags.insert(export_binfo.cflags.end(), ebi.cflags.begin(), ebi.cflags.end());
293 export_binfo.incpath.insert(export_binfo.incpath.end(), ebi.incpath.begin(), ebi.incpath.end());
294 export_binfo.defines.insert(export_binfo.defines.end(), ebi.defines.begin(), ebi.defines.end());
297 build_info.cflags.push_back("-Wall");
298 build_info.cflags.push_back("-Wshadow");
299 build_info.cflags.push_back("-Wextra");
300 build_info.cflags.push_back("-Wpointer-arith");
301 build_info.cflags.push_back("-Wconversion");
302 build_info.cflags.push_back("-Werror");
304 unsigned flags=get_install_flags();
307 export_binfo.incpath.push_back((Path::Path(config.get_option("prefix").value)/"include").str());
309 export_binfo.libpath.push_back((Path::Path(config.get_option("prefix").value)/"lib").str());
311 string optimize=config.get_option("optimize").value;
312 if(lexical_cast<unsigned>(optimize))
314 build_info.cflags.push_back("-O"+optimize);
315 build_info.ldflags.push_back("-O"+optimize);
316 string cpu=config.get_option("cpu").value;
318 build_info.cflags.push_back("-march="+cpu);
321 if(lexical_cast<bool>(config.get_option("debug").value))
323 build_info.cflags.push_back("-ggdb");
324 build_info.defines.push_back("DEBUG");
327 for(FeatureList::iterator i=features.begin(); i!=features.end(); ++i)
328 if(lexical_cast<bool>(config.get_option("with_"+i->name).value))
329 build_info.cflags.push_back("-DWITH_"+toupper(i->name));
333 for(list<Component>::iterator i=components.begin(); i!=components.end(); ++i)
335 i->create_build_info();
336 if(i->get_type()==Component::LIBRARY)
337 export_binfo.libs.push_back(i->get_name());
340 else if(name=="fmod4")
342 export_binfo.libs.push_back("fmodex");
345 export_binfo.libpath.push_back((path/"api"/"lib").str());
346 export_binfo.incpath.push_back((path/"api"/"inc").str());
349 export_binfo.unique();
352 Package::Loader::Loader(Package &p):
355 add("version", &Package::version);
356 add("description", &Package::description);
357 add("require", &Loader::require);
358 add("feature", &Loader::feature);
359 add("if", &Loader::condition);
360 add("program", &Loader::program);
361 add("library", &Loader::library);
362 add("module", &Loader::module);
363 add("headers", &Loader::headers);
364 add("build_info", &Loader::build_info);
367 void Package::Loader::require(const string &n)
369 pkg.requires.push_back(PackageRef(pkg.builder, n));
372 void Package::Loader::feature(const string &n, const string &d)
374 pkg.features.push_back(Feature(n, d));
377 void Package::Loader::condition(const string &c)
379 Condition cond(pkg, c);
381 pkg.conditions.push_back(cond);
384 void Package::Loader::program(const string &n)
386 Component prog(pkg, Component::PROGRAM, n);
388 pkg.components.push_back(prog);
391 void Package::Loader::library(const string &n)
393 Component prog(pkg, Component::LIBRARY, n);
395 pkg.components.push_back(prog);
398 void Package::Loader::module(const string &n)
400 Component prog(pkg, Component::MODULE, n);
402 pkg.components.push_back(prog);
405 void Package::Loader::headers(const string &n)
407 Component prog(pkg, Component::HEADERS, n);
409 pkg.components.push_back(prog);
412 void Package::Loader::build_info()
414 load_sub(pkg.build_info);