From 433f9ef196b6f5af6bb38447b650f5afaa5a783a Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Fri, 5 Feb 2010 09:23:05 +0000 Subject: [PATCH 1/1] Rewrite the architecture system CPU is now be specified as a part of the architecture Cross-compiling between 32/64-bit variants is supported --- builderrc | 17 ++-- source/architecture.cpp | 179 ++++++++++++++++++++++++++++++++++++--- source/architecture.h | 28 ++++-- source/binary.cpp | 8 +- source/builder.cpp | 74 ++++++++-------- source/builder.h | 13 ++- source/condition.cpp | 11 +-- source/sourcepackage.cpp | 11 ++- 8 files changed, 252 insertions(+), 89 deletions(-) diff --git a/builderrc b/builderrc index 22f29f3..9e624e3 100644 --- a/builderrc +++ b/builderrc @@ -8,7 +8,7 @@ binary_package "opengl" }; }; -binary_package "opengl/win32" +binary_package "opengl/windows" { build_info { @@ -51,7 +51,7 @@ binary_package "devil" }; }; -binary_package "devil/win32" +binary_package "devil/windows" { build_info { @@ -59,7 +59,7 @@ binary_package "devil/win32" }; }; -binary_package "openal/win32" +binary_package "openal/windows" { build_info { @@ -67,15 +67,8 @@ binary_package "openal/win32" }; }; -architecture "arm" -{ - prefix "arm-linux-gnueabi"; -}; - -architecture "win32" -{ - prefix "i586-mingw32msvc"; -}; +cross_prefix "arm" "arm-linux-gnueabi"; +cross_prefix "windows" "i586-mingw32msvc"; profile "debug" { diff --git a/source/architecture.cpp b/source/architecture.cpp index 65a7577..436a45a 100644 --- a/source/architecture.cpp +++ b/source/architecture.cpp @@ -1,52 +1,209 @@ /* $Id$ This file is part of builder -Copyright © 2007-2009 Mikko Rasa, Mikkosoft Productions +Copyright © 2007-2010 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ +#include +#ifndef WIN32 +#include +#endif +#include +#include #include "architecture.h" #include "builder.h" using namespace std; using namespace Msp; -Architecture::Architecture(Builder &b, const string &n, bool a): +namespace { + +const char *types[] = +{ + "pc", + "arm", + 0 +}; + +const char *cpus[] = +{ + "i386", "pc", 0, + "i486", "pc", 0, + "pentium", "pc", 0, + "i586", "pc", "pentium", + "pentiumpro", "pc", 0, + "i686", "pc", "pentiumpro", + "pentium2", "pc", 0, + "pentium3", "pc", 0, + "pentium4", "pc", 0, + "core2", "pc", 0, + "k6", "pc", 0, + "athlon", "pc", 0, + "athlonxp", "pc", 0, + "athlon64", "pc", 0, + "armv5", "arm", 0, + 0 +}; + +const char *systems[] = +{ + "linux", + "freebsd", + "windows", + 0 +}; + +} + +Architecture::Architecture(Builder &b, const string &spec): builder(b), - name(n), - native(a) -{ } + bits(0), + native(false) +{ + if(spec.empty()) + { +#ifdef WIN32 + system = "windows"; +#else + utsname un; + if(uname(&un)==0) + { + system = tolower(un.sysname); + parse_specification(tolower(un.machine)); + // We really only want to set type for the default arch + cpu.clear(); + } +#endif + bits = sizeof(void *)*numeric_limits::digits; + native = true; + } + else + { + parse_specification(spec); + const Architecture &native_arch = builder.get_native_arch(); + if(type.empty()) + type = native_arch.type; + if(cpu.empty()) + cpu = native_arch.cpu; + if(system.empty()) + system = native_arch.system; + if(!bits) + { + if(type==native_arch.type) + bits = native_arch.bits; + else + bits = 32; + } + + if(type!=native_arch.type || system!=native_arch.system) + cross_prefix = format("%s-%s", type, system); + else if(bits!=native_arch.bits) + { + build_info.cflags.push_back(format("-m%d", bits)); + build_info.ldflags.push_back(format("-m%d", bits)); + } + else + native = true; + + if(!cpu.empty()) + build_info.cflags.push_back(format("-march=%s", cpu)); + } + name = type; + if(!cpu.empty()) + name += format("-%s", cpu); + name += format("-%d-%s", bits, system); +} void Architecture::set_tool(const string &t, const string &p) { tools[t] = p; } +void Architecture::set_cross_prefix(const string &p) +{ + cross_prefix = p; +} + std::string Architecture::get_tool(const string &t) const { StringMap::const_iterator i = tools.find(t); if(i!=tools.end()) { if(i->second[0]=='-') - return prefix+i->second; + return cross_prefix+i->second; else return i->second; } - if(!native) + const Architecture &native_arch = builder.get_native_arch(); + if(this!=&native_arch) { - const Architecture &native_arch = builder.get_native_arch(); - return prefix+"-"+native_arch.get_tool(t); + if(!cross_prefix.empty()) + return cross_prefix+"-"+native_arch.get_tool(t); + else + return native_arch.get_tool(t); } else - throw KeyError("Unknown tool"); + throw KeyError("Unknown tool", t); +} + +bool Architecture::match_name(const string &pattern) const +{ + vector parts = split(pattern, "-"); + for(vector::const_iterator i=parts.begin(); i!=parts.end(); ++i) + { + if(*i!=type && *i!=cpu && *i!=system) + return false; + } + return true; +} + +void Architecture::parse_specification(const string &spec) +{ + vector parts = split(spec, "-"); + for(vector::const_iterator i=parts.begin(); i!=parts.end(); ++i) + { + bool ok = false; + for(unsigned j=0; (!ok && types[j]); ++j) + if(*i==types[j]) + { + if(!type.empty() && *i!=type) + throw InvalidParameterValue("Conflicting type specification"); + type = *i; + ok = true; + } + for(unsigned j=0; (!ok && cpus[j]); j+=3) + if(*i==cpus[j]) + { + if(type.empty()) + type = cpus[j+1]; + else if(cpus[j+1]!=type) + throw InvalidParameterValue("Conflicting CPU specification"); + cpu = (cpus[j+2] ? cpus[j+2] : *i); + ok = true; + } + for(unsigned j=0; (!ok && systems[j]); ++j) + if(*i==systems[j]) + { + system = *i; + ok = true; + } + if(!ok && (*i=="32" || *i=="64")) + { + bits = lexical_cast(*i); + ok = true; + } + if(!ok) + throw InvalidParameterValue("Unrecognized part in arch specification: "+*i); + } } Architecture::Loader::Loader(Architecture &a): arch(a) { - add("prefix", &Architecture::prefix); + add("prefix", &Architecture::cross_prefix); add("tool", &Loader::tool); } diff --git a/source/architecture.h b/source/architecture.h index aa5f865..a638834 100644 --- a/source/architecture.h +++ b/source/architecture.h @@ -1,7 +1,7 @@ /* $Id$ This file is part of builder -Copyright © 2007-2009 Mikko Rasa, Mikkosoft Productions +Copyright © 2007-2010 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ @@ -9,6 +9,7 @@ Distributed under the LGPL #define ARCHITECTURE_H_ #include +#include "buildinfo.h" #include "misc.h" class Builder; @@ -31,18 +32,33 @@ public: private: Builder &builder; + std::string type; + std::string cpu; + std::string system; + unsigned bits; std::string name; bool native; - std::string prefix; + std::string cross_prefix; StringMap tools; + BuildInfo build_info; public: - Architecture(Builder &b, const std::string &n, bool a = false); - void set_tool(const std::string &t, const std::string &p); - std::string get_tool(const std::string &t) const; + Architecture(Builder &b, const std::string &spec); + const std::string &get_name() const { return name; } + const std::string &get_system() const { return system; } + bool match_name(const std::string &) const; bool is_native() const { return native; } - const std::string &get_prefix() const { return prefix; } + + void set_tool(const std::string &t, const std::string &p); + void set_cross_prefix(const std::string &); + std::string get_tool(const std::string &t) const; + const std::string &get_cross_prefix() const { return cross_prefix; } + + const BuildInfo &get_build_info() const { return build_info; } + +private: + void parse_specification(const std::string &); }; typedef std::map ArchMap; diff --git a/source/binary.cpp b/source/binary.cpp index 08da59a..e82b65a 100644 --- a/source/binary.cpp +++ b/source/binary.cpp @@ -1,7 +1,7 @@ /* $Id$ This file is part of builder -Copyright © 2006-2009 Mikko Rasa, Mikkosoft Productions +Copyright © 2006-2010 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ @@ -86,12 +86,12 @@ FS::Path Binary::generate_target_path(const Component &c) { const SourcePackage &pkg = c.get_package(); string prefix, suffix; - const string &arch = pkg.get_builder().get_current_arch().get_name(); + const string &sys = pkg.get_builder().get_current_arch().get_system(); if(c.get_type()==Component::LIBRARY) { prefix = "lib"; - if(arch=="win32") + if(sys=="windows") suffix = ".dll"; else suffix = ".so"; @@ -100,7 +100,7 @@ FS::Path Binary::generate_target_path(const Component &c) suffix = ".m"; else if(c.get_type()==Component::PROGRAM) { - if(arch=="win32") + if(sys=="windows") suffix = ".exe"; } diff --git a/source/builder.cpp b/source/builder.cpp index 76522ad..77579ea 100644 --- a/source/builder.cpp +++ b/source/builder.cpp @@ -1,13 +1,12 @@ /* $Id$ This file is part of builder -Copyright © 2006-2009 Mikko Rasa, Mikkosoft Productions +Copyright © 2006-2010 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ #include #include -#include #include #include #include @@ -54,6 +53,7 @@ void update_hash(string &hash, const string &value) Builder::Builder(int argc, char **argv): main_pkg(0), + native_arch(*this, string()), analyzer(0), build(false), clean(0), @@ -139,25 +139,29 @@ Builder::Builder(int argc, char **argv): cwd = FS::getcwd(); - utsname un; - string sysname = "native"; - if(uname(&un)==0) - sysname = tolower(un.sysname); - - native_arch = &archs.insert(ArchMap::value_type(sysname, Architecture(*this, sysname, true))).first->second; - native_arch->set_tool("CC", "gcc"); - native_arch->set_tool("CXX", "g++"); - native_arch->set_tool("LD", "gcc"); - native_arch->set_tool("LXX", "g++"); - native_arch->set_tool("AR", "ar"); + native_arch.set_tool("CC", "gcc"); + native_arch.set_tool("CXX", "g++"); + native_arch.set_tool("LD", "gcc"); + native_arch.set_tool("LXX", "g++"); + native_arch.set_tool("AR", "ar"); load_build_file((FS::get_sys_data_dir(argv[0], "builder")/"builderrc").str()); load_build_file((FS::get_user_data_dir("builder")/"rc").str()); if(arch.empty()) - current_arch = native_arch; + current_arch = &native_arch; else - current_arch = &get_architecture(arch); + current_arch = new Architecture(*this, arch); + + if(!current_arch->is_native()) + { + for(StringMap::const_iterator i=cross_prefixes.begin(); i!=cross_prefixes.end(); ++i) + if(current_arch->match_name(i->first)) + { + current_arch->set_cross_prefix(i->second); + break; + } + } if(prfx.empty()) { @@ -247,7 +251,11 @@ int Builder::main() return 0; if(verbose>=2) - IO::print("Building on %s, for %s\n", native_arch->get_name(), current_arch->get_name()); + { + IO::print("Building on %s, for %s%s\n", native_arch.get_name(), + current_arch->get_name(), (current_arch->is_native() ? " (native)" : "")); + IO::print("Prefix is %s\n", prefix); + } if(verbose>=1) IO::print("%d active packages, %d targets\n", all_reqs.size(), targets.size()); if(verbose>=2) @@ -326,7 +334,7 @@ string Builder::run_pkgconfig(const string &pkg, const string &what) Package *Builder::get_package(const string &name) { - PackageMap::iterator i = packages.find(format("%s/%s", name, current_arch->get_name())); + PackageMap::iterator i = packages.find(format("%s/%s", name, current_arch->get_system())); if(i==packages.end()) i = packages.find(name); if(i!=packages.end()) @@ -409,7 +417,7 @@ Target *Builder::get_header(const string &include, const FS::Path &from, const l if(current_arch->is_native()) syspath.push_back("/usr/include"); else - syspath.push_back("/usr/"+current_arch->get_prefix()+"/include"); + syspath.push_back("/usr/"+current_arch->get_cross_prefix()+"/include"); if(cxx_ver!="-") syspath.push_back((FS::Path("/usr/include/c++/")/cxx_ver).str()); @@ -444,7 +452,7 @@ Target *Builder::get_library(const string &lib, const list &path, LibMod syspath.push_back("/usr/lib"); } else - syspath.push_back("/usr/"+current_arch->get_prefix()+"/lib"); + syspath.push_back("/usr/"+current_arch->get_cross_prefix()+"/lib"); if(verbose>=5) IO::print("Looking for library %s with path %s\n", lib, join(path.begin(), path.end())); @@ -460,15 +468,6 @@ Target *Builder::get_library(const string &lib, const list &path, LibMod return tgt; } -const Architecture &Builder::get_architecture(const string &arch) const -{ - ArchMap::const_iterator i = archs.find(arch); - if(i==archs.end()) - throw KeyError("Unknown architecture", arch); - - return i->second; -} - void Builder::apply_profile_template(Config &config, const string &pt) const { vector parts = split(pt, '-'); @@ -677,7 +676,8 @@ Target *Builder::get_library(const string &lib, const FS::Path &path, LibMode mo if(mode!=ALL_STATIC) { - if(current_arch->get_name()=="win32") + // XXX Should probably let the Architecture populate the list + if(current_arch->get_system()=="windows") { candidates.push_back("lib"+lib+".dll"); candidates.push_back(lib+".dll"); @@ -689,7 +689,7 @@ Target *Builder::get_library(const string &lib, const FS::Path &path, LibMode mo /* Static libraries are always considered, since sometimes shared versions may not be available */ candidates.push_back("lib"+lib+".a"); - if(current_arch->get_name()=="win32") + if(current_arch->get_system()=="windows") candidates.push_back("lib"+lib+".dll.a"); for(StringList::iterator i=candidates.begin(); i!=candidates.end(); ++i) @@ -859,19 +859,12 @@ Builder::Loader::Loader(Builder &b, const FS::Path &s): bld(b), src(s) { - add("architecture", &Loader::architecture); add("binary_package", &Loader::binpkg); + add("cross_prefix", &Loader::cross_prefix); add("profile", &Loader::profile); add("package", &Loader::package); } -void Builder::Loader::architecture(const string &n) -{ - Architecture arch(bld, n); - load_sub(arch); - bld.archs.insert(ArchMap::value_type(n, arch)); -} - void Builder::Loader::binpkg(const string &n) { BinaryPackage *pkg = new BinaryPackage(bld, n); @@ -879,6 +872,11 @@ void Builder::Loader::binpkg(const string &n) bld.packages.insert(PackageMap::value_type(n, pkg)); } +void Builder::Loader::cross_prefix(const string &a, const string &p) +{ + bld.cross_prefixes[a] = p; +} + void Builder::Loader::profile(const string &n) { StringMap prf; diff --git a/source/builder.h b/source/builder.h index 977785c..653a81a 100644 --- a/source/builder.h +++ b/source/builder.h @@ -1,7 +1,7 @@ /* $Id$ This file is part of builder -Copyright © 2006-2009 Mikko Rasa, Mikkosoft Productions +Copyright © 2006-2010 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ @@ -40,8 +40,8 @@ private: public: Loader(Builder &, const Msp::FS::Path &); private: - void architecture(const std::string &); void binpkg(const std::string &); + void cross_prefix(const std::string &, const std::string &); void profile(const std::string &); void package(const std::string &); }; @@ -75,9 +75,9 @@ private: TargetMap includes; TargetMap libraries; - ArchMap archs; - Architecture *native_arch; - const Architecture *current_arch; + Architecture native_arch; + Architecture *current_arch; + StringMap cross_prefixes; ProfileTemplateMap profile_tmpl; ProblemList problems; @@ -138,9 +138,8 @@ public: Target *get_library(const std::string &, const StringList &, LibMode); const Msp::FS::Path &get_cwd() const { return cwd; } - const Architecture &get_architecture(const std::string &) const; const Architecture &get_current_arch() const { return *current_arch; } - const Architecture &get_native_arch() const { return *native_arch; } + const Architecture &get_native_arch() const { return native_arch; } const Msp::FS::Path &get_prefix() const { return prefix; } const StringList &get_warnings() const { return warnings; } void apply_profile_template(Config &, const std::string &) const; diff --git a/source/condition.cpp b/source/condition.cpp index 314d9c9..4c7b5ed 100644 --- a/source/condition.cpp +++ b/source/condition.cpp @@ -1,7 +1,7 @@ /* $Id$ This file is part of builder -Copyright © 2007-2009 Mikko Rasa, Mikkosoft Productions +Copyright © 2007-2010 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ @@ -44,14 +44,15 @@ bool Condition::eval() unsigned start = 1; if(i->second[1]=='=') ++start; + string value = i->second.substr(start); - string value; + bool match = false; if(conf.is_option(i->first)) - value = conf.get_option(i->first).value; + match = (conf.get_option(i->first).value==value); else if(i->first=="arch") - value = pkg.get_builder().get_current_arch().get_name(); + match = pkg.get_builder().get_current_arch().match_name(value); - if((value==i->second.substr(start))==neg) + if(match==neg) result = false; } diff --git a/source/sourcepackage.cpp b/source/sourcepackage.cpp index 838ab16..5209be4 100644 --- a/source/sourcepackage.cpp +++ b/source/sourcepackage.cpp @@ -1,7 +1,7 @@ /* $Id$ This file is part of builder -Copyright © 2007-2009 Mikko Rasa, Mikkosoft Productions +Copyright © 2007-2010 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ @@ -35,7 +35,8 @@ SourcePackage::SourcePackage(Builder &b, const string &n, const FS::Path &s): FS::Path SourcePackage::get_temp_dir() const { - return source/config.get_option("tempdir").value/builder.get_current_arch().get_name()/config.get_option("profile").value; + string subdir = format("%s.%s", builder.get_current_arch().get_name(), config.get_option("profile").value); + return source/config.get_option("tempdir").value/subdir; } FS::Path SourcePackage::get_out_dir() const @@ -132,7 +133,6 @@ void SourcePackage::init_config() config.add_option("optimize", "0", "Apply compiler optimizations"); config.add_option("strip", "no", "Strip symbols from programs"); config.add_option("debug", "no", "Produce debugging symbols"); - config.add_option("cpu", "none", "CPU type to optimize for"); config.add_option("staticlibs", "local", "Use static libraries"); for(FeatureList::iterator i=features.begin(); i!=features.end(); ++i) @@ -148,6 +148,8 @@ void SourcePackage::init_config() void SourcePackage::create_build_info() { + build_info.add(builder.get_current_arch().get_build_info()); + for(PackageList::iterator i=base_reqs.begin(); i!=base_reqs.end(); ++i) { const BuildInfo &ebi = (*i)->get_exported_binfo(); @@ -177,9 +179,6 @@ void SourcePackage::create_build_info() { build_info.cflags.push_back("-O"+optimize); build_info.ldflags.push_back("-O"+optimize); - string cpu = config.get_option("cpu").value; - if(cpu!="none") - build_info.cflags.push_back("-march="+cpu); } if(lexical_cast(config.get_option("debug").value)) -- 2.43.0