#include "gnucxxcompiler.h"
#include "gnulinker.h"
#include "installedfile.h"
+#include "mingwdlltool.h"
#include "package.h"
#include "pkgconfiggenerator.h"
#include "sharedlibrary.h"
toolchain.add_tool(new Copy(*this));
toolchain.add_tool(new Tar(*this));
toolchain.add_tool(new PkgConfigGenerator(*this));
+ if(current_arch->get_system()=="windows")
+ toolchain.add_tool(new MingwDllTool(*this, *current_arch));
}
Builder::~Builder()
--- /dev/null
+#include "component.h"
+#include "exportdefinitions.h"
+#include "sourcepackage.h"
+
+using namespace Msp;
+
+ExportDefinitions::ExportDefinitions(Builder &b, const Component &c, SharedLibrary &l):
+ FileTarget(b, c.get_package(), generate_target_path(c)),
+ lib(l)
+{
+ component = &c;
+}
+
+FS::Path ExportDefinitions::generate_target_path(const Component &comp)
+{
+ return comp.get_package().get_temp_dir()/comp.get_name()/(comp.get_name()+".def");
+}
--- /dev/null
+#ifndef EXPORTDEFINITIONS_H_
+#define EXPORTDEFINITIONS_H_
+
+#include "filetarget.h"
+
+class SharedLibrary;
+
+/**
+An export definition file for a shared library. Only used on Windows.
+*/
+class ExportDefinitions: public FileTarget
+{
+private:
+ SharedLibrary &lib;
+
+public:
+ ExportDefinitions(Builder &, const Component &, SharedLibrary &);
+private:
+ static Msp::FS::Path generate_target_path(const Component &);
+
+public:
+ virtual const char *get_type() const { return "ExportDefinitions"; }
+
+ SharedLibrary &get_library() const { return lib; }
+};
+
+#endif
#include "builder.h"
#include "component.h"
#include "executable.h"
+#include "exportdefinitions.h"
#include "externaltask.h"
#include "gnucompiler.h"
#include "gnulinker.h"
const Component &comp = *objs.front()->get_component();
Binary *bin = 0;
if(arg=="shared")
- bin = new SharedLibrary(builder, comp, objs);
+ {
+ SharedLibrary *shlib = new SharedLibrary(builder, comp, objs);
+ if(architecture->get_system()=="windows")
+ {
+ ExportDefinitions *exp = new ExportDefinitions(builder, comp, *shlib);
+ shlib->add_side_effect(*exp);
+ const Tool &dlltool = builder.get_toolchain().get_tool("DLL");
+ ImportLibrary *imp = dynamic_cast<ImportLibrary *>(dlltool.create_target(*exp));
+ shlib->set_import_library(imp);
+ }
+ bin = shlib;
+ }
else
bin = new Executable(builder, comp, objs);
bin->set_tool(*linker);
{
const Tool © = builder.get_toolchain().get_tool("CP");
InstalledFile *inst_tgt = dynamic_cast<InstalledFile *>(copy.create_target(target));
- const Pattern &pattern = architecture->get_shared_library_patterns().front();
- inst_tgt->set_symlink(pattern.apply(shlib->get_libname()));
+ if(architecture->get_system()=="windows")
+ builder.add_installed_target(*shlib->get_import_library());
+ else
+ {
+ const Pattern &pattern = architecture->get_shared_library_patterns().front();
+ inst_tgt->set_symlink(pattern.apply(shlib->get_libname()));
+ }
return inst_tgt;
}
else
const Component &comp = *bin.get_component();
+ FS::Path work_dir = comp.get_package().get_source_directory();
+
if(const SharedLibrary *shlib = dynamic_cast<const SharedLibrary *>(&bin))
{
argv.push_back("-shared");
argv.push_back("-fPIC");
- if(!shlib->get_soname().empty())
+ const Target::Dependencies &side_eff = target.get_side_effects();
+ for(Target::Dependencies::const_iterator i=side_eff.begin(); i!=side_eff.end(); ++i)
+ {
+ if(ExportDefinitions *exp = dynamic_cast<ExportDefinitions *>(*i))
+ argv.push_back("-Wl,--output-def,"+relative(exp->get_path(), work_dir).str());
+ }
+ if(architecture->get_system()!="windows" && !shlib->get_soname().empty())
argv.push_back("-Wl,-soname,"+shlib->get_soname());
}
if(architecture->get_bits()!=native_arch.get_bits())
argv.push_back(format("-m%d", architecture->get_bits()));
- FS::Path work_dir = comp.get_package().get_source_directory();
-
argv.push_back("-o");
argv.push_back(relative(bin.get_path(), work_dir).str());
}
else if(ImportLibrary *imp = dynamic_cast<ImportLibrary *>(tgt))
{
- argv.push_back(imp->get_path().str());
+ shlib = imp->get_shared_library();
+ if(shlib)
+ argv.push_back("-l"+shlib->get_libname());
+ else
+ argv.push_back(imp->get_path().str());
static_link_ok = false;
}
}
#include <msp/strings/format.h>
+#include "component.h"
+#include "exportdefinitions.h"
#include "importlibrary.h"
+#include "sourcepackage.h"
+using namespace std;
using namespace Msp;
ImportLibrary::ImportLibrary(Builder &b, const FS::Path &p):
- FileTarget(b, p)
+ FileTarget(b, p),
+ shared_lib(0)
{ }
+
+ImportLibrary::ImportLibrary(Builder &b, const Component &c, ExportDefinitions &exp):
+ FileTarget(b, c.get_package(), c.get_package().get_out_dir()/format("lib%s.dll.a", c.get_name())),
+ shared_lib(&exp.get_library())
+{
+ component = &c;
+ add_dependency(exp);
+
+ install_location = "lib";
+
+ const string &version = component->get_package().get_interface_version();
+ if(!version.empty())
+ install_filename = format("lib%s-%s.dll.a", c.get_name(), version);
+}
#include "filetarget.h"
+class ExportDefinitions;
+class SharedLibrary;
+
/**
A special case of static library which pulls in a shared library. Used on
platforms with no true dynamic linking support.
*/
class ImportLibrary: public FileTarget
{
+private:
+ SharedLibrary *shared_lib;
+
public:
ImportLibrary(Builder &, const Msp::FS::Path &);
+ ImportLibrary(Builder &, const Component &, ExportDefinitions &);
virtual const char *get_type() const { return "ImportLibrary"; }
+
+ SharedLibrary *get_shared_library() const { return shared_lib; }
};
#endif
--- /dev/null
+#include <cstdlib>
+#include <msp/fs/utils.h>
+#include <msp/strings/format.h>
+#include "architecture.h"
+#include "builder.h"
+#include "component.h"
+#include "exportdefinitions.h"
+#include "externaltask.h"
+#include "importlibrary.h"
+#include "installedfile.h"
+#include "mingwdlltool.h"
+#include "sharedlibrary.h"
+#include "sourcepackage.h"
+
+using namespace std;
+using namespace Msp;
+
+MingwDllTool::MingwDllTool(Builder &b, const Architecture &a):
+ Tool(b, a, "DLL")
+{
+ string command = "dlltool";
+ if(architecture->is_cross())
+ command = format("%s-%s", architecture->get_cross_prefix(), command);
+ executable = builder.get_vfs().find_binary(command);
+}
+
+Target *MingwDllTool::create_target(const list<Target *> &sources, const string &) const
+{
+ if(sources.size()!=1)
+ throw invalid_argument("MingwDllTool::create_target");
+ ExportDefinitions &def = dynamic_cast<ExportDefinitions &>(*sources.front());
+ ImportLibrary *imp = new ImportLibrary(builder, *def.get_component(), def);
+ imp->set_tool(*this);
+ return imp;
+}
+
+Target *MingwDllTool::create_install(Target &target) const
+{
+ if(ImportLibrary *imp = dynamic_cast<ImportLibrary *>(&target))
+ {
+ const Tool © = builder.get_toolchain().get_tool("CP");
+ InstalledFile *inst_tgt = dynamic_cast<InstalledFile *>(copy.create_target(target));
+ string link_name = format("lib%s.dll.a", imp->get_shared_library()->get_libname());
+ inst_tgt->set_symlink(link_name);
+ return inst_tgt;
+ }
+ else
+ return 0;
+}
+
+Task *MingwDllTool::run(const Target &target) const
+{
+ const ImportLibrary &imp = dynamic_cast<const ImportLibrary &>(target);
+ const ExportDefinitions &exp = dynamic_cast<const ExportDefinitions &>(*imp.get_dependencies().front());
+ const SharedLibrary &shlib = exp.get_library();
+
+ vector<string> argv;
+ argv.push_back(executable->get_path().str());
+
+ /* dlltool is stupid and puts temporary files in the working directory by
+ default */
+ argv.push_back("--temp-prefix");
+ char random[8];
+ for(unsigned i=0; i<8; ++i)
+ random[i] = 'a'+(rand()%26);
+ argv.push_back(string("/tmp/")+string(random, 8));
+
+ const Component &comp = *imp.get_component();
+ FS::Path work_dir = comp.get_package().get_source_directory();
+
+ argv.push_back("-d");
+ argv.push_back(relative(exp.get_path(), work_dir).str());
+
+ argv.push_back("-D");
+ if(shlib.get_install_filename().empty())
+ argv.push_back(FS::basename(shlib.get_path()));
+ else
+ argv.push_back(shlib.get_install_filename());
+
+ argv.push_back("-l");
+ argv.push_back(relative(imp.get_path(), work_dir).str());
+
+ return new ExternalTask(argv, work_dir);
+}
--- /dev/null
+#ifndef DLLTOOL_H_
+#define DLLTOOL_H_
+
+#include "tool.h"
+
+class MingwDllTool: public Tool
+{
+public:
+ MingwDllTool(Builder &, const Architecture &);
+
+ virtual Target *create_target(const std::list<Target *> &, const std::string &) const;
+ virtual Target *create_install(Target &) const;
+
+ virtual Task *run(const Target &) const;
+};
+
+#endif
using namespace Msp;
SharedLibrary::SharedLibrary(Builder &b, const Msp::FS::Path &p):
- Binary(b, p)
+ Binary(b, p),
+ import_lib(0)
{
libname = FS::basepart(FS::basename(path));
if(!libname.compare(0, 3, "lib"))
SharedLibrary::SharedLibrary(Builder &b, const Component &c, const list<ObjectFile *> &objs):
Binary(b, c, generate_filename(c), objs),
- libname(c.get_name())
+ libname(c.get_name()),
+ import_lib(0)
{
install_location = "lib";
if(component->get_type()==Component::MODULE)
return arch.get_shared_library_patterns().front().apply(comp.get_name());
}
}
+
+void SharedLibrary::set_import_library(ImportLibrary *imp)
+{
+ import_lib = imp;
+}
#include "binary.h"
+class ImportLibrary;
+
/**
Represents a shared library. It has two special properties: libname and
soname. Libname is the name used by the linker. Soname is the canonical
filename of the library, including version number. If the owning package has
no version, soname will be empty.
+
+A SharedLibrary can also store a pointer to the associated ImportLibrary, for
+platforms that need one.
*/
class SharedLibrary: public Binary
{
private:
std::string libname;
std::string soname;
+ ImportLibrary *import_lib;
public:
SharedLibrary(Builder &, const Msp::FS::Path &);
virtual const char *get_type() const { return "SharedLibrary"; }
const std::string &get_libname() const { return libname; }
const std::string &get_soname() const { return soname; }
+
+ void set_import_library(ImportLibrary *);
+ ImportLibrary *get_import_library() const { return import_lib; }
};
#endif