]> git.tdb.fi Git - builder.git/blobdiff - source/msvclinker.cpp
Add drivers for the MSVC toolchain
[builder.git] / source / msvclinker.cpp
diff --git a/source/msvclinker.cpp b/source/msvclinker.cpp
new file mode 100644 (file)
index 0000000..46d89f7
--- /dev/null
@@ -0,0 +1,134 @@
+#include <msp/core/environ.h>
+#include <msp/fs/utils.h>
+#include <msp/strings/format.h>
+#include <msp/strings/utils.h>
+#include "builder.h"
+#include "component.h"
+#include "executable.h"
+#include "externaltask.h"
+#include "importlibrary.h"
+#include "microsofttools.h"
+#include "msvclinker.h"
+#include "objectfile.h"
+#include "sharedlibrary.h"
+#include "sourcepackage.h"
+#include "staticlibrary.h"
+
+using namespace std;
+using namespace Msp;
+
+MsvcLinker::MsvcLinker(Builder &b, const Architecture &a, const MicrosoftTools &m):
+       Tool(b, a, "LINK"),
+       ms_tools(m)
+{
+       input_suffixes.push_back(".o");
+       input_suffixes.push_back(".a");
+
+       processing_unit = COMPONENT;
+
+       set_command((ms_tools.get_vc_bin_dir()/"link.exe").str(), false);
+}
+
+Target *MsvcLinker::create_target(const list<Target *> &sources, const string &arg)
+{
+       if(sources.empty())
+               throw invalid_argument("MsvcLinker::create_target");
+
+       list<ObjectFile *> objs;
+       for(list<Target *>::const_iterator i=sources.begin(); i!=sources.end(); ++i)
+       {
+               if(ObjectFile *obj = dynamic_cast<ObjectFile *>(*i))
+                       objs.push_back(obj);
+               else
+                       throw invalid_argument("MsvcLinker::create_target");
+       }
+
+       const Component &comp = *objs.front()->get_component();
+       Binary *bin = 0;
+       if(arg=="shared")
+               bin = new SharedLibrary(builder, comp, objs);
+       else
+               bin = new Executable(builder, comp, objs);
+       bin->set_tool(*this);
+       return bin;
+}
+
+string MsvcLinker::create_build_signature(const BuildInfo &binfo) const
+{
+       string result = FS::basename(executable->get_path());
+       result += ',';
+       if(binfo.strip)
+               result += 's';
+       if(!binfo.libs.empty())
+       {
+               result += ",l";
+               result += join(binfo.libs.begin(), binfo.libs.end(), ",l");
+       }
+       return result;
+}
+
+void MsvcLinker::do_prepare()
+{
+       string arch_dir = (architecture->get_bits()==64 ? "x64" : "x86");
+
+       const FS::Path &vc_base_dir = ms_tools.get_vc_base_dir();
+       system_path.push_back(vc_base_dir/"lib"/arch_dir);
+
+       const FS::Path &win_sdk_dir = ms_tools.get_windows_sdk_dir();
+       const string &win_sdk_ver = ms_tools.get_windows_sdk_version();
+       system_path.push_back(win_sdk_dir/"lib"/win_sdk_ver/"ucrt"/arch_dir);
+       system_path.push_back(win_sdk_dir/"lib"/win_sdk_ver/"um"/arch_dir);
+
+       string path;
+       for(SearchPath::const_iterator i=system_path.begin(); i!=system_path.end(); ++i)
+       {
+               append(path, ";", i->str());
+               builder.get_logger().log("tools", format("Got %s system path: %s", tag, *i));
+       }
+
+       setenv("LIB", path);
+}
+
+Task *MsvcLinker::run(const Target &target) const
+{
+       const Binary &bin = dynamic_cast<const Binary &>(target);
+
+       vector<string> argv;
+       argv.push_back(executable->get_path().str());
+       argv.push_back("/NOLOGO");
+
+       FS::Path work_dir = bin.get_component()->get_package().get_source_directory();
+
+       if(dynamic_cast<const SharedLibrary *>(&bin))
+               argv.push_back("/DLL");
+
+       BuildInfo binfo;
+       target.collect_build_info(binfo);
+
+       /*for(BuildInfo::PathList::const_iterator i=binfo.libpath.begin(); i!=binfo.libpath.end(); ++i)
+               argv.push_back("/LIBPATH:"+i->str());*/
+       if(binfo.strip)
+               argv.push_back("/INCREMENTAL:NO");
+       else
+               argv.push_back("/DEBUG:FULL");
+
+       argv.push_back("/OUT:"+relative(bin.get_path(), work_dir).str());
+
+       const Target::Dependencies &depends = target.get_dependencies();
+       for(Target::Dependencies::const_iterator i=depends.begin(); i!=depends.end(); ++i)
+       {
+               FileTarget *file = dynamic_cast<FileTarget *>(*i);
+               Target *tgt = (*i)->get_real_target();
+
+               if(ObjectFile *obj = dynamic_cast<ObjectFile *>(tgt))
+                       argv.push_back(relative(obj->get_path(), work_dir).str());
+               else if(StaticLibrary *stlib = dynamic_cast<StaticLibrary *>(tgt))
+                       argv.push_back((file?file:stlib)->get_path().str());
+               else if(ImportLibrary *imp = dynamic_cast<ImportLibrary *>(tgt))
+                       argv.push_back((file?file:imp)->get_path().str());
+       }
+
+       argv.push_back("/SUBSYSTEM:CONSOLE");
+
+       return new ExternalTask(argv, work_dir);
+}