From 21ca3e98081c0dc0430d8e5301591aa71ec4fca2 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Mon, 10 Nov 2014 20:50:35 +0200 Subject: [PATCH] Deal with static build flags for binary packages Some libraries have internal dependencies to other libraries, which are automatically pulled in with dynamic linking, but need to be manually specified to the linker when linking statically. --- source/binary.cpp | 28 ++++++++++++++++++--------- source/binarypackage.cpp | 40 ++++++++++++++++++++++++++++++++++----- source/binarypackage.h | 8 +++++++- source/packagemanager.cpp | 10 +++++++--- 4 files changed, 68 insertions(+), 18 deletions(-) diff --git a/source/binary.cpp b/source/binary.cpp index 448292c..55e517a 100644 --- a/source/binary.cpp +++ b/source/binary.cpp @@ -61,8 +61,7 @@ void Binary::find_dependencies() static_binfo.keep_symbols.insert(static_binfo.keep_symbols.end(), binfo.keep_symbols.begin(), binfo.keep_symbols.end()); } - list::iterator insert_pos = j; - ++insert_pos; + list libs_to_process; for(BuildInfo::WordList::const_iterator i=binfo.libs.begin(); i!=binfo.libs.end(); ++i) { if(i->size()>10 && !i->compare(i->size()-10, 10, ".framework")) @@ -71,16 +70,27 @@ void Binary::find_dependencies() BuildInfo::LibraryMode libmode = component->get_build_info().get_libmode_for(*i); Target *lib = builder.get_vfs().find_library(*i, binfo.libpath, libmode); if(lib) - { - Target *real = lib->get_real_target(); - if(StaticLibrary *stlib = dynamic_cast(real)) - queue.insert(insert_pos, stlib); - else - dep_libs.push_back(lib); - } + libs_to_process.push_back(lib); else if(missing_libs.insert(*i).second) problems.push_back(format("Required library %s not found", *i)); } + + if(tgt!=this) + { + const Target::Dependencies &tdeps = tgt->get_transitive_dependencies(); + libs_to_process.insert(libs_to_process.end(), tdeps.begin(), tdeps.end()); + } + + list::iterator insert_pos = j; + ++insert_pos; + for(list::const_iterator i=libs_to_process.begin(); i!=libs_to_process.end(); ++i) + { + Target *real = (*i)->get_real_target(); + if(StaticLibrary *stlib = dynamic_cast(real)) + queue.insert(insert_pos, stlib); + else + dep_libs.push_back(*i); + } } queue.pop_front(); diff --git a/source/binarypackage.cpp b/source/binarypackage.cpp index 94667c9..679fb63 100644 --- a/source/binarypackage.cpp +++ b/source/binarypackage.cpp @@ -1,7 +1,9 @@ +#include #include #include #include "binarypackage.h" #include "builder.h" +#include "filetarget.h" using namespace std; using namespace Msp; @@ -91,15 +93,45 @@ void BinaryPackage::do_prepare() for(BuildInfo::PathList::iterator i=export_binfo.libpath.begin(); i!=export_binfo.libpath.end(); ++i) *i = base_path/ *i; } + + if(!static_binfo.libs.empty()) + { + BuildInfo::PathList combined_libpath = static_binfo.libpath; + combined_libpath.insert(combined_libpath.end(), export_binfo.libpath.begin(), export_binfo.libpath.end()); + + Target::Dependencies static_dep_libs; + for(BuildInfo::WordList::const_iterator i=static_binfo.libs.begin(); i!=static_binfo.libs.end(); ++i) + if(Target *lib = builder.get_vfs().find_library(*i, combined_libpath, BuildInfo::STATIC, system)) + static_dep_libs.push_back(lib); + + for(BuildInfo::WordList::const_iterator i=export_binfo.libs.begin(); i!=export_binfo.libs.end(); ++i) + if(Target *lib = builder.get_vfs().find_library(*i, export_binfo.libpath, BuildInfo::FORCE_STATIC, system)) + { + for(Target::Dependencies::const_iterator j=static_dep_libs.begin(); j!=static_dep_libs.end(); ++j) + lib->add_transitive_dependency(**j); + } + } } -BinaryPackage *BinaryPackage::from_flags(Builder &builder, const string &name, const vector &flags) +BinaryPackage *BinaryPackage::from_flags(Builder &builder, const string &name, const Flags &flags, const Flags &static_flags) { BinaryPackage *pkg = new BinaryPackage(builder, name); pkg->use_pkgconfig = true; - BuildInfo &binfo = pkg->export_binfo; - for(vector::const_iterator i=flags.begin(); i!=flags.end(); ++i) + process_flags(flags, pkg->export_binfo); + + Flags exclusive_static_flags; + for(Flags::const_iterator i=static_flags.begin(); i!=static_flags.end(); ++i) + if(find(flags.begin(), flags.end(), *i)==flags.end()) + exclusive_static_flags.push_back(*i); + process_flags(exclusive_static_flags, pkg->static_binfo); + + return pkg; +} + +void BinaryPackage::process_flags(const Flags &flags, BuildInfo &binfo) +{ + for(Flags::const_iterator i=flags.begin(); i!=flags.end(); ++i) { if(!i->compare(0, 2, "-I")) binfo.incpath.push_back(i->substr(2)); @@ -118,8 +150,6 @@ BinaryPackage *BinaryPackage::from_flags(Builder &builder, const string &name, c else if(*i=="-pthread") binfo.threads = true; } - - return pkg; } diff --git a/source/binarypackage.h b/source/binarypackage.h index 13e2fd8..b8c29de 100644 --- a/source/binarypackage.h +++ b/source/binarypackage.h @@ -19,17 +19,23 @@ public: void header(const std::string &); }; + typedef std::vector Flags; + private: typedef std::list HeaderList; Msp::FS::Path base_path; HeaderList headers; + BuildInfo static_binfo; public: BinaryPackage(Builder &, const std::string &); - static BinaryPackage *from_flags(Builder &, const std::string &, const std::vector &); + const BuildInfo &get_static_build_info() const { return static_binfo; } + + static BinaryPackage *from_flags(Builder &, const std::string &, const Flags &, const Flags & = Flags()); private: + static void process_flags(const Flags &, BuildInfo &); virtual void do_prepare(); }; diff --git a/source/packagemanager.cpp b/source/packagemanager.cpp index ee07987..2319c5a 100644 --- a/source/packagemanager.cpp +++ b/source/packagemanager.cpp @@ -109,8 +109,10 @@ Package *PackageManager::find_package(const string &name) { // Package source not found - create a binary package string flags_str = run_pkgconfig(name, "flags"); - vector flags = split(flags_str); - Package *pkg = BinaryPackage::from_flags(builder, name, flags); + BinaryPackage::Flags flags = split(flags_str); + flags_str = run_pkgconfig(name, "staticflags"); + BinaryPackage::Flags static_flags = split(flags_str); + Package *pkg = BinaryPackage::from_flags(builder, name, flags, static_flags); packages.insert(PackageMap::value_type(name, pkg)); return pkg; } @@ -150,10 +152,12 @@ string PackageManager::run_pkgconfig(const string &pkg, const string &what) argv.push_back("pkg-config"); if(what=="cflags" || what=="libs") argv.push_back("--"+what); - else if(what=="flags") + else if(what=="flags" || what=="staticflags") { argv.push_back("--cflags"); argv.push_back("--libs"); + if(what=="staticflags") + argv.push_back("--static"); } else argv.push_back("--variable="+what); -- 2.43.0