]> git.tdb.fi Git - builder.git/blobdiff - plugins/msvc/msvclinker.cpp
Rearrange sources into subdirectories
[builder.git] / plugins / msvc / msvclinker.cpp
diff --git a/plugins/msvc/msvclinker.cpp b/plugins/msvc/msvclinker.cpp
new file mode 100644 (file)
index 0000000..8008791
--- /dev/null
@@ -0,0 +1,128 @@
+#include <msp/builder/builder.h>
+#include <msp/builder/component.h>
+#include <msp/builder/executable.h>
+#include <msp/builder/importlibrary.h>
+#include <msp/builder/objectfile.h>
+#include <msp/builder/sharedlibrary.h>
+#include <msp/builder/sourcepackage.h>
+#include <msp/builder/staticlibrary.h>
+#include <msp/core/environ.h>
+#include <msp/fs/utils.h>
+#include <msp/strings/utils.h>
+#include "microsofttools.h"
+#include "msvclinker.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);
+       set_run_external(_run);
+}
+
+Target *MsvcLinker::create_target(const vector<Target *> &sources, const string &arg)
+{
+       if(sources.empty())
+               throw invalid_argument("MsvcLinker::create_target");
+
+       vector<ObjectFile *> objs;
+       objs.reserve(sources.size());
+       for(Target *s: sources)
+               objs.push_back(&dynamic_cast<ObjectFile &>(*s));
+
+       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 = Tool::create_build_signature(binfo);
+       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(ToolData &tool) const
+{
+       const std::string &tool_tag = static_cast<Tool &>(tool).get_tag();
+       const Architecture &arch = *static_cast<Tool &>(tool).get_architecture();
+       string arch_dir = (arch.get_bits()==64 ? "x64" : "x86");
+
+       const FS::Path &vc_base_dir = ms_tools.get_vc_base_dir();
+       tool.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();
+       tool.system_path.push_back(win_sdk_dir/"lib"/win_sdk_ver/"ucrt"/arch_dir);
+       tool.system_path.push_back(win_sdk_dir/"lib"/win_sdk_ver/"um"/arch_dir);
+
+       string path;
+       for(const FS::Path &p: tool.system_path)
+       {
+               append(path, ";", p.str());
+               builder.get_logger().log("tools", "Got %s system path: %s", tool_tag, p);
+       }
+
+       setenv("LIB", path);
+}
+
+ExternalTask::Arguments MsvcLinker::_run(const Binary &bin, FS::Path &work_dir)
+{
+       const Tool &tool = *bin.get_tool();
+
+       vector<string> argv;
+       argv.push_back(tool.get_executable()->get_path().str());
+       argv.push_back("/NOLOGO");
+
+       if(dynamic_cast<const SharedLibrary *>(&bin))
+               argv.push_back("/DLL");
+
+       BuildInfo binfo;
+       bin.collect_build_info(binfo);
+
+       /*for(const FS::Path &p: binfo.libpath)
+               argv.push_back("/LIBPATH:"+p.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());
+
+       for(Target *d: bin.get_dependencies())
+       {
+               FileTarget *file = dynamic_cast<FileTarget *>(d);
+               Target *tgt = d->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 argv;
+}