/builder
/builder.pc
/builder-stage1
+/builtintools.dlm
/clangtools.dlm
/gnutools.dlm
/libbuilder.a
/libbuilder.so
/libandroidtools.a
-/libbuiltintools.a
/libdatatools.a
/msvctools.dlm
/temp
standard CXX "c++11";
};
- library "builtintools"
- {
- source "plugins/builtin";
- default false;
- };
-
library "androidtools"
{
source "plugins/android";
library "libbuilder"
{
source "source/lib";
- use "builtintools";
use "androidtools";
use "datatools";
build_info
install true;
};
+ module "builtintools"
+ {
+ source "plugins/builtin";
+ install true;
+ };
+
module "gnutools"
{
source "plugins/gnu";
--- /dev/null
+#include <msp/builder/builder.h>
+#include <msp/builder/tool.h>
+#include "builtinplugin.h"
+#include "builtintools.h"
+#include "compilecommandsjson.h"
+#include "pkgconfigfile.h"
+#include "vcxprojectfile.h"
+#include "vssolutionfile.h"
+
+void BuiltinPlugin::add_tools(Toolchain &toolchain, const Architecture &) const
+{
+ toolchain.add_toolchain(new BuiltinTools(builder));
+}
+
+void BuiltinPlugin::create_targets(SourcePackage &spkg) const
+{
+ const Architecture &native_arch = builder.get_native_arch();
+
+ if(!spkg.get_exported_build_info().libs.empty() && native_arch.get_system()=="linux")
+ {
+ PkgConfigFile *pc = new PkgConfigFile(builder, spkg);
+ builder.get_build_graph().get_target("install")->add_dependency(*builder.get_toolchain().get_tool("CP").create_target(*pc));
+ }
+
+ if(native_arch.get_system()=="windows")
+ {
+ new VcxProjectFile(builder, spkg);
+ new VsSolutionFile(builder, spkg);
+ }
+
+ new CompileCommandsJson(builder, spkg);
+}
+
+
+extern "C"
+Plugin *create_plugin(Builder &builder)
+{
+ return new BuiltinPlugin(builder);
+}
--- /dev/null
+#ifndef BUILTINPLUGIN_H_
+#define BUILTINPLUGIN_H_
+
+#include <msp/builder/plugin.h>
+
+class BuiltinPlugin: public Plugin
+{
+public:
+ BuiltinPlugin(Builder &b): Plugin(b) { }
+
+ void add_tools(Toolchain &, const Architecture &) const override;
+ void create_targets(SourcePackage &) const override;
+};
+
+#endif
--- /dev/null
+#include "builtintools.h"
+#include "copy.h"
+#include "compilecommandsgenerator.h"
+#include "pkgconfiggenerator.h"
+#include "tar.h"
+#include "vcxprojectgenerator.h"
+#include "vssolutiongenerator.h"
+
+BuiltinTools::BuiltinTools(Builder &builder)
+{
+ add_tool(new Copy(builder));
+ add_tool(new Tar(builder));
+ add_tool(new PkgConfigGenerator(builder));
+ add_tool(new VcxProjectGenerator(builder));
+ add_tool(new VsSolutionGenerator(builder));
+ add_tool(new CompileCommandsGenerator(builder));
+}
--- /dev/null
+#ifndef BUILTINTOOLS_H_
+#define BUILTINTOOLS_H_
+
+#include <msp/builder/toolchain.h>
+
+class Builder;
+
+class BuiltinTools: public Toolchain
+{
+public:
+ BuiltinTools(Builder &);
+};
+
+#endif
--- /dev/null
+#include <msp/builder/builder.h>
+#include <msp/builder/objectfile.h>
+#include <msp/builder/sourcefile.h>
+#include <msp/io/file.h>
+#include <msp/io/print.h>
+#include <msp/strings/utils.h>
+#include "compilecommandsgenerator.h"
+#include "compilecommandsjson.h"
+
+using namespace std;
+using namespace Msp;
+
+CompileCommandsGenerator::CompileCommandsGenerator(Builder &b):
+ Tool(b, "CCJG")
+{
+ set_run_internal(_run);
+}
+
+Target *CompileCommandsGenerator::create_target(const vector<Target *> &, const string &)
+{
+ throw logic_error("Not implemented");
+}
+
+bool CompileCommandsGenerator::_run(const CompileCommandsJson &cmds)
+{
+ Builder &builder = cmds.get_package()->get_builder();
+ const SourcePackage &spkg = *cmds.get_package();
+ string work_dir = c_escape(spkg.get_source_directory().str());
+
+ IO::BufferedFile out(cmds.get_path().str(), IO::M_WRITE);
+ IO::print(out, "[");
+
+ bool first = true;
+ for(const auto &kvp: builder.get_build_graph().get_targets())
+ if(kvp.second->is_buildable() && kvp.second->get_package()==&spkg)
+ if(ObjectFile *obj = dynamic_cast<ObjectFile *>(kvp.second))
+ {
+ FS::Path src_path = obj->get_source().get_path();
+ Task *task = kvp.second->build();
+ if(!first)
+ out.put(',');
+ IO::print(out, "\n\t{\n");
+ IO::print(out, "\t\t\"file\": \"%s\"\n", src_path);
+ IO::print(out, "\t\t\"command\": \"%s\"\n", c_escape(task->get_command()));
+ IO::print(out, "\t\t\"directory\": \"%s\"\n", work_dir);
+ IO::print(out, "\t}");
+ delete task;
+ first = false;
+ }
+
+ IO::print(out, "\n]\n");
+
+ return true;
+}
--- /dev/null
+#ifndef COMPILECOMMANDSGENERATOR_H_
+#define COMPILECOMMANDSGENERATOR_H_
+
+#include <msp/builder/tool.h>
+
+class CompileCommandsJson;
+
+class CompileCommandsGenerator: public Tool
+{
+public:
+ CompileCommandsGenerator(Builder &);
+
+ Target *create_target(const std::vector<Target *> &, const std::string &) override;
+
+private:
+ static bool _run(const CompileCommandsJson &);
+};
+
+#endif
--- /dev/null
+#include <msp/builder/builder.h>
+#include <msp/builder/package.h>
+#include <msp/builder/objectfile.h>
+#include "compilecommandsjson.h"
+
+CompileCommandsJson::CompileCommandsJson(Builder &b, const SourcePackage &p):
+ FileTarget(b, p, p.get_source_directory()/("compile_commands.json"))
+{
+ tool = &builder.get_toolchain().get_tool("CCJG");
+}
+
+void CompileCommandsJson::find_dependencies()
+{
+ for(const auto &kvp: builder.get_build_graph().get_targets())
+ if(kvp.second->is_buildable() && kvp.second->get_package()==package && dynamic_cast<ObjectFile *>(kvp.second))
+ kvp.second->prepare();
+}
--- /dev/null
+#ifndef COMPILECOMMANDSJSON_H_
+#define COMPILECOMMANDSJSON_H_
+
+#include <msp/builder/sourcepackage.h>
+#include <msp/builder/filetarget.h>
+
+class CompileCommandsJson: public FileTarget
+{
+private:
+
+public:
+ CompileCommandsJson(Builder &, const SourcePackage &);
+
+ const char *get_type() const override { return "CompileCommandsJson"; }
+
+protected:
+ void find_dependencies() override;
+};
+
+#endif
--- /dev/null
+#ifndef _WIN32
+#include <unistd.h>
+#include <sys/stat.h>
+#endif
+#include <msp/builder/builder.h>
+#include <msp/builder/installedfile.h>
+#include <msp/fs/dir.h>
+#include <msp/fs/stat.h>
+#include <msp/fs/utils.h>
+#include <msp/io/file.h>
+#include <msp/io/print.h>
+#include "copy.h"
+
+using namespace std;
+using namespace Msp;
+
+Copy::Copy(Builder &b):
+ Tool(b, "CP")
+{
+ set_run_internal(_run);
+}
+
+Target *Copy::create_target(const vector<Target *> &sources, const string &arg)
+{
+ FileTarget &file_tgt = dynamic_cast<FileTarget &>(*sources.front());
+ InstalledFile *inst = new InstalledFile(builder, *file_tgt.get_package(), file_tgt, arg);
+ inst->set_tool(*this);
+ return inst;
+}
+
+bool Copy::_run(const InstalledFile &install)
+{
+ const FileTarget &source = install.get_source();
+ const FS::Path &src_path = source.get_path();
+ const FS::Path &dst_path = install.get_path();
+
+ try
+ {
+ IO::File in(src_path.str());
+ IO::File out(dst_path.str(), IO::M_WRITE);
+
+ // Actual transfer loop
+ char buf[16384];
+ while(!in.eof())
+ {
+ unsigned len = in.read(buf, sizeof(buf));
+ out.write(buf, len);
+ }
+ }
+ catch(const exception &e)
+ {
+ IO::print(IO::cerr, "%s\n", e.what());
+ return false;
+ }
+
+#ifndef _WIN32
+ // Preserve file permissions
+ struct stat st;
+ if(stat(src_path.str().c_str(), &st)==0)
+ chmod(dst_path.str().c_str(), st.st_mode&0777);
+
+ const FS::Path &link = install.get_symlink();
+ if(!link.empty())
+ {
+ FS::Path relpath = FS::relative(dst_path, FS::dirname(link));
+ if(FS::exists(link))
+ FS::unlink(link);
+ symlink(relpath.str().c_str(), link.str().c_str());
+ }
+#endif
+
+ return true;
+}
--- /dev/null
+#ifndef COPY_H_
+#define COPY_H_
+
+#include <msp/builder/tool.h>
+
+class InstalledFile;
+
+/**
+Copies a file to another place. Used by the InstalledFile target.
+*/
+class Copy: public Tool
+{
+public:
+ Copy(Builder &);
+
+ Target *create_target(const std::vector<Target *> &, const std::string &) override;
+
+private:
+ static bool _run(const InstalledFile &);
+};
+
+#endif
--- /dev/null
+#include <msp/builder/builder.h>
+#include <msp/builder/package.h>
+#include "pkgconfigfile.h"
+
+PkgConfigFile::PkgConfigFile(Builder &b, const SourcePackage &p):
+ FileTarget(b, p, p.get_source_directory()/(p.get_name()+".pc"))
+{
+ tool = &builder.get_toolchain().get_tool("PCG");
+
+ install_location = "lib/pkgconfig";
+}
--- /dev/null
+#ifndef PKGCONFIGFILE_H_
+#define PKGCONFIGFILE_H_
+
+#include <msp/builder/sourcepackage.h>
+#include <msp/builder/filetarget.h>
+
+/**
+Creates a .pc file to enable other packages fetch build options with pkg-config.
+*/
+class PkgConfigFile: public FileTarget
+{
+public:
+ PkgConfigFile(Builder &, const SourcePackage &);
+
+ const char *get_type() const override { return "PkgConfigFile"; }
+};
+
+#endif
--- /dev/null
+#include <msp/builder/builder.h>
+#include <msp/fs/utils.h>
+#include <msp/io/file.h>
+#include <msp/io/print.h>
+#include "pkgconfigfile.h"
+#include "pkgconfiggenerator.h"
+
+using namespace std;
+using namespace Msp;
+
+PkgConfigGenerator::PkgConfigGenerator(Builder &b):
+ Tool(b, "PCG")
+{
+ set_run_internal(_run);
+}
+
+Target *PkgConfigGenerator::create_target(const vector<Target *> &, const string &)
+{
+ throw logic_error("Not implemented");
+}
+
+bool PkgConfigGenerator::_run(const PkgConfigFile &pkgc)
+{
+ Builder &builder = pkgc.get_package()->get_builder();
+ const SourcePackage &spkg = *pkgc.get_package();
+
+ IO::BufferedFile out(pkgc.get_path().str(), IO::M_WRITE);
+ IO::print(out, "prefix=%s\n", builder.get_prefix().str());
+ IO::print(out, "source=%s\n\n", spkg.get_source_directory());
+
+ IO::print(out, "Name: %s\n", spkg.get_label());
+ IO::print(out, "Description: %s\n", spkg.get_description());
+ IO::print(out, "Version: %s\n", spkg.get_version());
+
+ IO::print(out, "Requires:");
+ for(const Package *r: spkg.get_required_packages())
+ if(r->uses_pkgconfig())
+ IO::print(out, " %s", r->get_name());
+ out.put('\n');
+
+ const BuildInfo &binfo = spkg.get_exported_build_info();
+ IO::print(out, "Libs:");
+ for(const FS::Path &p: binfo.libpath)
+ IO::print(out, " -L%s", prefixify(p, builder.get_prefix()));
+ for(const string &l: binfo.libs)
+ IO::print(out, " -l%s", l);
+ if(binfo.threads)
+ out.write("-pthread");
+ out.put('\n');
+
+ IO::print(out, "Cflags:");
+ for(const FS::Path &p: binfo.incpath)
+ IO::print(out, " -I%s", prefixify(p, builder.get_prefix()));
+ for(const auto &kvp: binfo.defines)
+ if(kvp.second.empty())
+ IO::print(out, " -D%s", kvp.first);
+ else
+ IO::print(out, " -D%s=%s", kvp.first, kvp.second);
+ out.put('\n');
+
+ return true;
+}
+
+string PkgConfigGenerator::prefixify(const FS::Path &path, const FS::Path &prefix)
+{
+ if(FS::descendant_depth(path, prefix)>=0)
+ {
+ FS::Path rel_path = FS::relative(path, prefix);
+ return "${prefix}"+rel_path.str().substr(1);
+ }
+ else
+ return path.str();
+}
--- /dev/null
+#ifndef PKGCONFIGGENERATOR_H_
+#define PKGCONFIGGENERATOR_H_
+
+#include <msp/builder/tool.h>
+
+class PkgConfigFile;
+
+class PkgConfigGenerator: public Tool
+{
+public:
+ PkgConfigGenerator(Builder &);
+
+ Target *create_target(const std::vector<Target *> &, const std::string &) override;
+
+private:
+ static bool _run(const PkgConfigFile &);
+ static std::string prefixify(const Msp::FS::Path &, const Msp::FS::Path &);
+};
+
+#endif
--- /dev/null
+#include <cstring>
+#include <msp/builder/builder.h>
+#include <msp/builder/sourcepackage.h>
+#include <msp/fs/stat.h>
+#include <msp/fs/utils.h>
+#include <msp/io/file.h>
+#include <msp/io/print.h>
+#include "tar.h"
+#include "tarball.h"
+
+using namespace std;
+using namespace Msp;
+
+Tar::Tar(Builder &b):
+ Tool(b, "TAR")
+{
+ processing_unit = COMPONENT;
+ set_run_internal(&_run);
+}
+
+Target *Tar::create_target(const vector<Target *> &sources, const string &arg)
+{
+ if(sources.empty() || !sources.front()->get_package())
+ throw invalid_argument("Tar::create_target");
+
+ TarBall *tarball = new TarBall(builder, *sources.front()->get_package(), arg);
+ for(Target *s: sources)
+ tarball->add_dependency(*s);
+
+ tarball->set_tool(*this);
+
+ return tarball;
+}
+
+bool Tar::_run(const TarBall &tarball)
+{
+ const FS::Path &pkg_src = tarball.get_package()->get_source_directory();
+ FS::Path basedir = FS::basepart(FS::basename(tarball.get_path()));
+
+ IO::File out(tarball.get_path().str(), IO::M_WRITE);
+ for(Target *d: tarball.get_dependencies())
+ {
+ FileTarget *ft = dynamic_cast<FileTarget *>(d);
+ if(!ft)
+ continue;
+
+ char buf[4096];
+ memset(buf, 0, 512);
+
+ string rel_path = (basedir/relative(ft->get_path(), pkg_src)).str();
+ if(rel_path.size()>99)
+ {
+ IO::print("Can't store %s in tar archive - too long name\n", rel_path);
+ return false;
+ }
+
+ memcpy(buf, rel_path.data(), rel_path.size());
+
+ FS::Stat st = FS::stat(ft->get_path());
+ store_number(buf+100, 0666, 7);
+ store_number(buf+108, 0, 7);
+ store_number(buf+116, 0, 7);
+ store_number(buf+124, st.get_size(), 11);
+ store_number(buf+136, st.get_modify_time().to_unixtime(), 11);
+ buf[156] = '0';
+
+ memset(buf+148, ' ', 8);
+ unsigned chk = 0;
+ for(unsigned j=0; j<512; ++j)
+ chk += static_cast<unsigned char>(buf[j]);
+ store_number(buf+148, chk, 7);
+ buf[155] = 0;
+
+ out.write(buf, 512);
+ IO::File in(ft->get_path().str());
+ for(unsigned j=0; j<st.get_size(); j+=4096)
+ {
+ unsigned len = in.read(buf, 4096);
+ len += ((~len)+1)&0777;
+ out.write(buf, len);
+ }
+ }
+
+ return true;
+}
+
+void Tar::store_number(char *buf, unsigned value, unsigned length)
+{
+ for(unsigned i=length; i--;)
+ {
+ buf[i] = '0'+value%8;
+ value /= 8;
+ }
+}
--- /dev/null
+#ifndef TAR_H_
+#define TAR_H_
+
+#include <msp/builder/tool.h>
+
+class TarBall;
+
+class Tar: public Tool
+{
+public:
+ Tar(Builder &);
+
+ Target *create_target(const std::vector<Target *> &, const std::string &) override;
+
+private:
+ static bool _run(const TarBall &);
+ static void store_number(char *, unsigned, unsigned);
+};
+
+#endif
--- /dev/null
+#include <msp/builder/sourcepackage.h>
+#include "tar.h"
+#include "tarball.h"
+
+using namespace std;
+
+TarBall::TarBall(Builder &b, const SourcePackage &p, const string &n):
+ FileTarget(b, p, p.get_source_directory()/(n+".tar"))
+{ }
+
+const SourcePackage *TarBall::get_package() const
+{
+ return static_cast<const SourcePackage *>(package);
+}
--- /dev/null
+#ifndef TARBALL_H_
+#define TARBALL_H_
+
+#include <msp/builder/filetarget.h>
+
+class TarBall: public FileTarget
+{
+public:
+ TarBall(Builder &, const SourcePackage &, const std::string &);
+
+ const char *get_type() const override { return "TarBall"; }
+ const SourcePackage *get_package() const;
+};
+
+#endif
--- /dev/null
+#include <msp/builder/builder.h>
+#include <msp/builder/sourcepackage.h>
+#include <msp/crypto/md5.h>
+#include <msp/strings/format.h>
+#include "vcxprojectfile.h"
+
+using namespace Msp;
+
+VcxProjectFile::VcxProjectFile(Builder &b, const SourcePackage &p):
+ FileTarget(b, p, p.get_source_directory()/(p.get_name()+".vcxproj"))
+{
+ tool = &builder.get_toolchain().get_tool("VCXG");
+
+ char digest[16];
+ Crypto::MD5(package->get_name()).get_digest(digest, sizeof(digest));
+ digest[6] = 3;
+ digest[8] = (digest[6]&0x3F)|0x80;
+ for(unsigned j=0; j<sizeof(digest); ++j)
+ {
+ if(j==4 || j==6 || j==8 || j==10)
+ guid += '-';
+ guid += format("%02x", static_cast<unsigned char>(digest[j]));
+ }
+}
--- /dev/null
+#ifndef VCXPROJECTFILE_H_
+#define VCXPROJECTFILE_H_
+
+#include <msp/builder/filetarget.h>
+
+class VcxProjectFile: public FileTarget
+{
+private:
+ std::string guid;
+
+public:
+ VcxProjectFile(Builder &, const SourcePackage &);
+
+ const char *get_type() const override { return "VcxProjectFile"; }
+
+ const std::string &get_guid() const { return guid; }
+};
+
+#endif
--- /dev/null
+#include <msp/builder/builder.h>
+#include <msp/builder/csourcefile.h>
+#include <msp/builder/executable.h>
+#include <msp/builder/sourcepackage.h>
+#include <msp/core/application.h>
+#include <msp/fs/utils.h>
+#include <msp/io/print.h>
+#include <msp/strings/utils.h>
+#include "vcxprojectfile.h"
+#include "vcxprojectgenerator.h"
+
+using namespace std;
+using namespace Msp;
+
+VcxProjectGenerator::VcxProjectGenerator(Builder &b):
+ Tool(b, "VCXG")
+{
+ set_run_internal(_run);
+}
+
+Target *VcxProjectGenerator::create_target(const vector<Target *> &, const string &)
+{
+ throw logic_error("Not implemented");
+}
+
+bool VcxProjectGenerator::_run(const VcxProjectFile &project)
+{
+ const SourcePackage &spkg = *project.get_package();
+ Builder &builder = spkg.get_builder();
+
+ IO::BufferedFile out(project.get_path().str(), IO::M_WRITE);
+ IO::print(out, "<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n");
+
+ IO::print(out, "\t<ItemGroup Label=\"ProjectConfigurations\">\n");
+ vector<string> build_types = builder.get_build_types();
+ const char *platforms[] = { "Win32", "x64" };
+ for(const char *p: platforms)
+ for(const string &b: build_types)
+ {
+ IO::print(out, "\t\t<ProjectConfiguration Include=\"%s|%s\">\n", b, p);
+ IO::print(out, "\t\t\t<Configuration>%s</Configuration>\n", b);
+ IO::print(out, "\t\t\t<Platform>%s</Platform>\n", p);
+ IO::print(out, "\t\t</ProjectConfiguration>\n");
+ }
+ IO::print(out, "\t</ItemGroup>\n");
+
+ IO::print(out, "\t<PropertyGroup Label=\"Globals\">\n");
+ IO::print(out, "\t\t<VCProjectVersion>15.0</VCProjectVersion>\n");
+ IO::print(out, "\t\t<Keyword>MakeFileProj</Keyword>\n");
+ IO::print(out, "\t\t<ProjectGuid>{%s}</ProjectGuid>\n", project.get_guid());
+ IO::print(out, "\t</PropertyGroup>\n");
+
+ IO::print(out, "\t<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n");
+
+ const Executable *exe = 0;
+ for(const Target *t: builder.get_build_graph().get_target("world")->get_dependencies())
+ if(t->get_package()==&spkg)
+ if((exe = dynamic_cast<const Executable *>(t)))
+ break;
+
+ const char *argv0 = Application::get_argv0();
+ const string &toolchain = builder.get_current_arch().get_toolchain();
+ for(const char *p: platforms)
+ for(const string &b: build_types)
+ {
+ string base_cmd = format("%s --arch=%s-%s --build-type=%s --prefix=%s", argv0, p, toolchain, b, builder.get_prefix());
+ IO::print(out, "\t<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='%s|%s'\" Label=\"Configuration\">\n", b, p);
+ IO::print(out, "\t\t<ConfigurationType>MakeFile</ConfigurationType>\n");
+ IO::print(out, "\t\t<NMakeBuildCommandLine>%s</NMakeBuildCommandLine>\n", base_cmd);
+ IO::print(out, "\t\t<NMakeCleanCommandLine>%s -c</NMakeCleanCommandLine>\n", base_cmd);
+ IO::print(out, "\t\t<NMakeReBuildCommandLine>%s -B</NMakeReBuildCommandLine>\n", base_cmd);
+ if(exe)
+ IO::print(out, "\t\t<NMakeOutput>%s</NMakeOutput>\n", exe->get_path());
+ IO::print(out, "\t</PropertyGroup>\n");
+ }
+
+ IO::print(out, "\t<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n");
+
+ vector<const FileTarget *> sources;
+ vector<const FileTarget *> includes;
+ vector<const FileTarget *> others;
+ BuildInfo build_info;
+ for(const auto &kvp: builder.get_build_graph().get_targets())
+ if(kvp.second->get_package()==&spkg)
+ {
+ if(kvp.second->is_buildable())
+ {
+ BuildInfo tgt_binfo;
+ kvp.second->collect_build_info(tgt_binfo);
+ build_info.update_from(tgt_binfo, BuildInfo::CHAINED);
+ }
+ else if(const FileTarget *file = dynamic_cast<const FileTarget *>(kvp.second))
+ {
+ if(dynamic_cast<const CSourceFile *>(file))
+ {
+ string ext = tolower(FS::extpart(FS::basename(file->get_path())));
+ if(ext==".h" || ext==".hpp")
+ includes.push_back(file);
+ else
+ sources.push_back(file);
+ }
+ else
+ others.push_back(file);
+ }
+ }
+
+ if(!build_info.incpath.empty())
+ {
+ IO::print(out, "\t<PropertyGroup>\n");
+ string path_str;
+ for(const FS::Path &p: build_info.incpath)
+ append(path_str, ";", p.str());
+ IO::print(out, "\t\t<NMakeIncludeSearchPath>%s</NMakeIncludeSearchPath>\n", path_str);
+ IO::print(out, "\t</PropertyGroup>\n");
+ }
+
+ IO::print(out, "\t<ItemGroup>\n");
+ for(const FileTarget *s: sources)
+ IO::print(out, "\t\t<ClCompile Include=\"%s\" />\n", s->get_path());
+ IO::print(out, "\t</ItemGroup>\n");
+
+ IO::print(out, "\t<ItemGroup>\n");
+ for(const FileTarget *i: includes)
+ IO::print(out, "\t\t<ClInclude Include=\"%s\" />\n", i->get_path());
+ IO::print(out, "\t</ItemGroup>\n");
+
+ IO::print(out, "\t<ItemGroup>\n");
+ for(const FileTarget *t: others)
+ IO::print(out, "\t\t<None Include=\"%s\" />\n", t->get_path());
+ IO::print(out, "\t</ItemGroup>\n");
+
+ IO::print(out, "\t<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n");
+ IO::print(out, "</Project>\n");
+
+ return true;
+}
--- /dev/null
+#ifndef VCXPROJECTGENERATOR_H_
+#define VCXPROJECTGENERATOR_H_
+
+#include <msp/builder/tool.h>
+
+class VcxProjectFile;
+
+class VcxProjectGenerator: public Tool
+{
+public:
+ VcxProjectGenerator(Builder &);
+
+ Target *create_target(const std::vector<Target *> &, const std::string &) override;
+
+private:
+ static bool _run(const VcxProjectFile &);
+};
+
+#endif
--- /dev/null
+#include <msp/builder/builder.h>
+#include <msp/builder/sourcepackage.h>
+#include <msp/core/algorithm.h>
+#include "vssolutionfile.h"
+
+using namespace std;
+using namespace Msp;
+
+VsSolutionFile::VsSolutionFile(Builder &b, const SourcePackage &p):
+ FileTarget(b, p, p.get_source_directory()/(p.get_name()+".sln"))
+{
+ tool = &builder.get_toolchain().get_tool("VSSG");
+}
+
+void VsSolutionFile::find_dependencies()
+{
+ find_dependencies(*package);
+}
+
+void VsSolutionFile::find_dependencies(const SourcePackage &spkg)
+{
+ if(FileTarget *project = builder.get_vfs().get_target(spkg.get_source_directory()/(spkg.get_name()+".vcxproj")))
+ if(!any_equals(depends, static_cast<Target *>(project)))
+ {
+ add_dependency(*project);
+
+ for(const Package *r: spkg.get_required_packages())
+ if(const SourcePackage *s = dynamic_cast<const SourcePackage *>(r))
+ find_dependencies(*s);
+ }
+}
--- /dev/null
+#ifndef VSSOLUTIONFILE_H_
+#define VSSOLUTIONFILE_H_
+
+#include <msp/builder/filetarget.h>
+
+class VsSolutionFile: public FileTarget
+{
+public:
+ VsSolutionFile(Builder &, const SourcePackage &);
+
+ const char *get_type() const override { return "VsSolutionFile"; }
+protected:
+ void find_dependencies() override;
+ void find_dependencies(const SourcePackage &);
+};
+
+#endif
--- /dev/null
+#include <cstring>
+#include <msp/builder/builder.h>
+#include <msp/builder/sourcepackage.h>
+#include <msp/io/file.h>
+#include <msp/io/print.h>
+#include "vcxprojectfile.h"
+#include "vssolutionfile.h"
+#include "vssolutiongenerator.h"
+
+using namespace std;
+using namespace Msp;
+
+VsSolutionGenerator::VsSolutionGenerator(Builder &b):
+ Tool(b, "VSSG")
+{
+ set_run_internal(_run);
+}
+
+Target *VsSolutionGenerator::create_target(const vector<Target *> &, const string &)
+{
+ throw logic_error("Not implemented");
+}
+
+bool VsSolutionGenerator::_run(const VsSolutionFile &solution)
+{
+ const SourcePackage &spkg = *solution.get_package();
+ Builder &builder = spkg.get_builder();
+
+ IO::BufferedFile out(solution.get_path().str(), IO::M_WRITE);
+ IO::print(out, "Microsoft Visual Studio Solution File, Format Version 12.00\n");
+ IO::print(out, "MinimumVisualStudioVersion = 10.0.40219.1\n");
+
+ vector<const VcxProjectFile *> projects;
+ for(const Target *t: solution.get_dependencies())
+ if(const VcxProjectFile *project = dynamic_cast<const VcxProjectFile *>(t))
+ projects.push_back(project);
+
+ for(const VcxProjectFile *p: projects)
+ {
+ const SourcePackage *pkg = p->get_package();
+ IO::print(out, "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"%s\", \"%s\", \"{%s}\"\nEndProject\n",
+ pkg->get_name(), p->get_path(), p->get_guid());
+ }
+
+ vector<string> build_types = builder.get_build_types();
+ const char *platforms[] = { "x86", "x64" };
+
+ IO::print(out, "Global\n");
+ IO::print(out, "\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n");
+ for(const string &t: build_types)
+ for(const char *p: platforms)
+ IO::print(out, "\t\t%s|%s = %s|%s\n", t, p, t, p);
+ IO::print(out, "\tEndGlobalSection\n");
+ IO::print(out, "\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n");
+ for(const VcxProjectFile *p: projects)
+ for(const string &t: build_types)
+ for(const char *f: platforms)
+ {
+ const char *project_platform = (!strcmp(f, "x86") ? "Win32" : f);
+ IO::print(out, "\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n", p->get_guid(), t, f, t, project_platform);
+ if(p->get_package()==&spkg)
+ IO::print(out, "\t\t{%s}.%s|%s.Build.0 = %s|%s\n", p->get_guid(), t, f, t, project_platform);
+ }
+ IO::print(out, "\tEndGlobalSection\n");
+ IO::print(out, "EndGlobal\n");
+
+ return true;
+}
--- /dev/null
+#ifndef VSSOLUTIONGENERATOR_H_
+#define VSSOLUTIONGENERATOR_H_
+
+#include <msp/builder/tool.h>
+
+class VsSolutionFile;
+
+class VsSolutionGenerator: public Tool
+{
+public:
+ VsSolutionGenerator(Builder &);
+
+ Target *create_target(const std::vector<Target *> &, const std::string &) override;
+
+private:
+ static bool _run(const VsSolutionFile &);
+};
+
+#endif
+++ /dev/null
-#include "builtintools.h"
-#include "copy.h"
-#include "compilecommandsgenerator.h"
-#include "pkgconfiggenerator.h"
-#include "tar.h"
-#include "vcxprojectgenerator.h"
-#include "vssolutiongenerator.h"
-
-BuiltinTools::BuiltinTools(Builder &builder)
-{
- add_tool(new Copy(builder));
- add_tool(new Tar(builder));
- add_tool(new PkgConfigGenerator(builder));
- add_tool(new VcxProjectGenerator(builder));
- add_tool(new VsSolutionGenerator(builder));
- add_tool(new CompileCommandsGenerator(builder));
-}
+++ /dev/null
-#ifndef BUILTINTOOLS_H_
-#define BUILTINTOOLS_H_
-
-#include <msp/builder/toolchain.h>
-
-class Builder;
-
-class BuiltinTools: public Toolchain
-{
-public:
- BuiltinTools(Builder &);
-};
-
-#endif
+++ /dev/null
-#include <msp/builder/builder.h>
-#include <msp/builder/objectfile.h>
-#include <msp/builder/sourcefile.h>
-#include <msp/io/file.h>
-#include <msp/io/print.h>
-#include <msp/strings/utils.h>
-#include "compilecommandsgenerator.h"
-#include "compilecommandsjson.h"
-
-using namespace std;
-using namespace Msp;
-
-CompileCommandsGenerator::CompileCommandsGenerator(Builder &b):
- Tool(b, "CCJG")
-{
- set_run_internal(_run);
-}
-
-Target *CompileCommandsGenerator::create_target(const vector<Target *> &, const string &)
-{
- throw logic_error("Not implemented");
-}
-
-bool CompileCommandsGenerator::_run(const CompileCommandsJson &cmds)
-{
- Builder &builder = cmds.get_package()->get_builder();
- const SourcePackage &spkg = *cmds.get_package();
- string work_dir = c_escape(spkg.get_source_directory().str());
-
- IO::BufferedFile out(cmds.get_path().str(), IO::M_WRITE);
- IO::print(out, "[");
-
- bool first = true;
- for(const auto &kvp: builder.get_build_graph().get_targets())
- if(kvp.second->is_buildable() && kvp.second->get_package()==&spkg)
- if(ObjectFile *obj = dynamic_cast<ObjectFile *>(kvp.second))
- {
- FS::Path src_path = obj->get_source().get_path();
- Task *task = kvp.second->build();
- if(!first)
- out.put(',');
- IO::print(out, "\n\t{\n");
- IO::print(out, "\t\t\"file\": \"%s\"\n", src_path);
- IO::print(out, "\t\t\"command\": \"%s\"\n", c_escape(task->get_command()));
- IO::print(out, "\t\t\"directory\": \"%s\"\n", work_dir);
- IO::print(out, "\t}");
- delete task;
- first = false;
- }
-
- IO::print(out, "\n]\n");
-
- return true;
-}
+++ /dev/null
-#ifndef COMPILECOMMANDSGENERATOR_H_
-#define COMPILECOMMANDSGENERATOR_H_
-
-#include <msp/builder/tool.h>
-
-class CompileCommandsJson;
-
-class CompileCommandsGenerator: public Tool
-{
-public:
- CompileCommandsGenerator(Builder &);
-
- Target *create_target(const std::vector<Target *> &, const std::string &) override;
-
-private:
- static bool _run(const CompileCommandsJson &);
-};
-
-#endif
+++ /dev/null
-#include <msp/builder/builder.h>
-#include <msp/builder/package.h>
-#include <msp/builder/objectfile.h>
-#include "compilecommandsjson.h"
-
-CompileCommandsJson::CompileCommandsJson(Builder &b, const SourcePackage &p):
- FileTarget(b, p, p.get_source_directory()/("compile_commands.json"))
-{
- tool = &builder.get_toolchain().get_tool("CCJG");
-}
-
-void CompileCommandsJson::find_dependencies()
-{
- for(const auto &kvp: builder.get_build_graph().get_targets())
- if(kvp.second->is_buildable() && kvp.second->get_package()==package && dynamic_cast<ObjectFile *>(kvp.second))
- kvp.second->prepare();
-}
+++ /dev/null
-#ifndef COMPILECOMMANDSJSON_H_
-#define COMPILECOMMANDSJSON_H_
-
-#include <msp/builder/sourcepackage.h>
-#include <msp/builder/filetarget.h>
-
-class CompileCommandsJson: public FileTarget
-{
-private:
-
-public:
- CompileCommandsJson(Builder &, const SourcePackage &);
-
- const char *get_type() const override { return "CompileCommandsJson"; }
-
-protected:
- void find_dependencies() override;
-};
-
-#endif
+++ /dev/null
-#ifndef _WIN32
-#include <unistd.h>
-#include <sys/stat.h>
-#endif
-#include <msp/builder/builder.h>
-#include <msp/builder/installedfile.h>
-#include <msp/fs/dir.h>
-#include <msp/fs/stat.h>
-#include <msp/fs/utils.h>
-#include <msp/io/file.h>
-#include <msp/io/print.h>
-#include "copy.h"
-
-using namespace std;
-using namespace Msp;
-
-Copy::Copy(Builder &b):
- Tool(b, "CP")
-{
- set_run_internal(_run);
-}
-
-Target *Copy::create_target(const vector<Target *> &sources, const string &arg)
-{
- FileTarget &file_tgt = dynamic_cast<FileTarget &>(*sources.front());
- InstalledFile *inst = new InstalledFile(builder, *file_tgt.get_package(), file_tgt, arg);
- inst->set_tool(*this);
- return inst;
-}
-
-bool Copy::_run(const InstalledFile &install)
-{
- const FileTarget &source = install.get_source();
- const FS::Path &src_path = source.get_path();
- const FS::Path &dst_path = install.get_path();
-
- try
- {
- IO::File in(src_path.str());
- IO::File out(dst_path.str(), IO::M_WRITE);
-
- // Actual transfer loop
- char buf[16384];
- while(!in.eof())
- {
- unsigned len = in.read(buf, sizeof(buf));
- out.write(buf, len);
- }
- }
- catch(const exception &e)
- {
- IO::print(IO::cerr, "%s\n", e.what());
- return false;
- }
-
-#ifndef _WIN32
- // Preserve file permissions
- struct stat st;
- if(stat(src_path.str().c_str(), &st)==0)
- chmod(dst_path.str().c_str(), st.st_mode&0777);
-
- const FS::Path &link = install.get_symlink();
- if(!link.empty())
- {
- FS::Path relpath = FS::relative(dst_path, FS::dirname(link));
- if(FS::exists(link))
- FS::unlink(link);
- symlink(relpath.str().c_str(), link.str().c_str());
- }
-#endif
-
- return true;
-}
+++ /dev/null
-#ifndef COPY_H_
-#define COPY_H_
-
-#include <msp/builder/tool.h>
-
-class InstalledFile;
-
-/**
-Copies a file to another place. Used by the InstalledFile target.
-*/
-class Copy: public Tool
-{
-public:
- Copy(Builder &);
-
- Target *create_target(const std::vector<Target *> &, const std::string &) override;
-
-private:
- static bool _run(const InstalledFile &);
-};
-
-#endif
+++ /dev/null
-#include <msp/builder/builder.h>
-#include <msp/builder/package.h>
-#include "pkgconfigfile.h"
-
-PkgConfigFile::PkgConfigFile(Builder &b, const SourcePackage &p):
- FileTarget(b, p, p.get_source_directory()/(p.get_name()+".pc"))
-{
- tool = &builder.get_toolchain().get_tool("PCG");
-
- install_location = "lib/pkgconfig";
-}
+++ /dev/null
-#ifndef PKGCONFIGFILE_H_
-#define PKGCONFIGFILE_H_
-
-#include <msp/builder/sourcepackage.h>
-#include <msp/builder/filetarget.h>
-
-/**
-Creates a .pc file to enable other packages fetch build options with pkg-config.
-*/
-class PkgConfigFile: public FileTarget
-{
-public:
- PkgConfigFile(Builder &, const SourcePackage &);
-
- const char *get_type() const override { return "PkgConfigFile"; }
-};
-
-#endif
+++ /dev/null
-#include <msp/builder/builder.h>
-#include <msp/fs/utils.h>
-#include <msp/io/file.h>
-#include <msp/io/print.h>
-#include "pkgconfigfile.h"
-#include "pkgconfiggenerator.h"
-
-using namespace std;
-using namespace Msp;
-
-PkgConfigGenerator::PkgConfigGenerator(Builder &b):
- Tool(b, "PCG")
-{
- set_run_internal(_run);
-}
-
-Target *PkgConfigGenerator::create_target(const vector<Target *> &, const string &)
-{
- throw logic_error("Not implemented");
-}
-
-bool PkgConfigGenerator::_run(const PkgConfigFile &pkgc)
-{
- Builder &builder = pkgc.get_package()->get_builder();
- const SourcePackage &spkg = *pkgc.get_package();
-
- IO::BufferedFile out(pkgc.get_path().str(), IO::M_WRITE);
- IO::print(out, "prefix=%s\n", builder.get_prefix().str());
- IO::print(out, "source=%s\n\n", spkg.get_source_directory());
-
- IO::print(out, "Name: %s\n", spkg.get_label());
- IO::print(out, "Description: %s\n", spkg.get_description());
- IO::print(out, "Version: %s\n", spkg.get_version());
-
- IO::print(out, "Requires:");
- for(const Package *r: spkg.get_required_packages())
- if(r->uses_pkgconfig())
- IO::print(out, " %s", r->get_name());
- out.put('\n');
-
- const BuildInfo &binfo = spkg.get_exported_build_info();
- IO::print(out, "Libs:");
- for(const FS::Path &p: binfo.libpath)
- IO::print(out, " -L%s", prefixify(p, builder.get_prefix()));
- for(const string &l: binfo.libs)
- IO::print(out, " -l%s", l);
- if(binfo.threads)
- out.write("-pthread");
- out.put('\n');
-
- IO::print(out, "Cflags:");
- for(const FS::Path &p: binfo.incpath)
- IO::print(out, " -I%s", prefixify(p, builder.get_prefix()));
- for(const auto &kvp: binfo.defines)
- if(kvp.second.empty())
- IO::print(out, " -D%s", kvp.first);
- else
- IO::print(out, " -D%s=%s", kvp.first, kvp.second);
- out.put('\n');
-
- return true;
-}
-
-string PkgConfigGenerator::prefixify(const FS::Path &path, const FS::Path &prefix)
-{
- if(FS::descendant_depth(path, prefix)>=0)
- {
- FS::Path rel_path = FS::relative(path, prefix);
- return "${prefix}"+rel_path.str().substr(1);
- }
- else
- return path.str();
-}
+++ /dev/null
-#ifndef PKGCONFIGGENERATOR_H_
-#define PKGCONFIGGENERATOR_H_
-
-#include <msp/builder/tool.h>
-
-class PkgConfigFile;
-
-class PkgConfigGenerator: public Tool
-{
-public:
- PkgConfigGenerator(Builder &);
-
- Target *create_target(const std::vector<Target *> &, const std::string &) override;
-
-private:
- static bool _run(const PkgConfigFile &);
- static std::string prefixify(const Msp::FS::Path &, const Msp::FS::Path &);
-};
-
-#endif
+++ /dev/null
-#include <cstring>
-#include <msp/builder/builder.h>
-#include <msp/builder/sourcepackage.h>
-#include <msp/fs/stat.h>
-#include <msp/fs/utils.h>
-#include <msp/io/file.h>
-#include <msp/io/print.h>
-#include "tar.h"
-#include "tarball.h"
-
-using namespace std;
-using namespace Msp;
-
-Tar::Tar(Builder &b):
- Tool(b, "TAR")
-{
- processing_unit = COMPONENT;
- set_run_internal(&_run);
-}
-
-Target *Tar::create_target(const vector<Target *> &sources, const string &arg)
-{
- if(sources.empty() || !sources.front()->get_package())
- throw invalid_argument("Tar::create_target");
-
- TarBall *tarball = new TarBall(builder, *sources.front()->get_package(), arg);
- for(Target *s: sources)
- tarball->add_dependency(*s);
-
- tarball->set_tool(*this);
-
- return tarball;
-}
-
-bool Tar::_run(const TarBall &tarball)
-{
- const FS::Path &pkg_src = tarball.get_package()->get_source_directory();
- FS::Path basedir = FS::basepart(FS::basename(tarball.get_path()));
-
- IO::File out(tarball.get_path().str(), IO::M_WRITE);
- for(Target *d: tarball.get_dependencies())
- {
- FileTarget *ft = dynamic_cast<FileTarget *>(d);
- if(!ft)
- continue;
-
- char buf[4096];
- memset(buf, 0, 512);
-
- string rel_path = (basedir/relative(ft->get_path(), pkg_src)).str();
- if(rel_path.size()>99)
- {
- IO::print("Can't store %s in tar archive - too long name\n", rel_path);
- return false;
- }
-
- memcpy(buf, rel_path.data(), rel_path.size());
-
- FS::Stat st = FS::stat(ft->get_path());
- store_number(buf+100, 0666, 7);
- store_number(buf+108, 0, 7);
- store_number(buf+116, 0, 7);
- store_number(buf+124, st.get_size(), 11);
- store_number(buf+136, st.get_modify_time().to_unixtime(), 11);
- buf[156] = '0';
-
- memset(buf+148, ' ', 8);
- unsigned chk = 0;
- for(unsigned j=0; j<512; ++j)
- chk += static_cast<unsigned char>(buf[j]);
- store_number(buf+148, chk, 7);
- buf[155] = 0;
-
- out.write(buf, 512);
- IO::File in(ft->get_path().str());
- for(unsigned j=0; j<st.get_size(); j+=4096)
- {
- unsigned len = in.read(buf, 4096);
- len += ((~len)+1)&0777;
- out.write(buf, len);
- }
- }
-
- return true;
-}
-
-void Tar::store_number(char *buf, unsigned value, unsigned length)
-{
- for(unsigned i=length; i--;)
- {
- buf[i] = '0'+value%8;
- value /= 8;
- }
-}
+++ /dev/null
-#ifndef TAR_H_
-#define TAR_H_
-
-#include <msp/builder/tool.h>
-
-class TarBall;
-
-class Tar: public Tool
-{
-public:
- Tar(Builder &);
-
- Target *create_target(const std::vector<Target *> &, const std::string &) override;
-
-private:
- static bool _run(const TarBall &);
- static void store_number(char *, unsigned, unsigned);
-};
-
-#endif
+++ /dev/null
-#include <msp/builder/sourcepackage.h>
-#include "tar.h"
-#include "tarball.h"
-
-using namespace std;
-
-TarBall::TarBall(Builder &b, const SourcePackage &p, const string &n):
- FileTarget(b, p, p.get_source_directory()/(n+".tar"))
-{ }
-
-const SourcePackage *TarBall::get_package() const
-{
- return static_cast<const SourcePackage *>(package);
-}
+++ /dev/null
-#ifndef TARBALL_H_
-#define TARBALL_H_
-
-#include <msp/builder/filetarget.h>
-
-class TarBall: public FileTarget
-{
-public:
- TarBall(Builder &, const SourcePackage &, const std::string &);
-
- const char *get_type() const override { return "TarBall"; }
- const SourcePackage *get_package() const;
-};
-
-#endif
+++ /dev/null
-#include <msp/builder/builder.h>
-#include <msp/builder/sourcepackage.h>
-#include <msp/crypto/md5.h>
-#include <msp/strings/format.h>
-#include "vcxprojectfile.h"
-
-using namespace Msp;
-
-VcxProjectFile::VcxProjectFile(Builder &b, const SourcePackage &p):
- FileTarget(b, p, p.get_source_directory()/(p.get_name()+".vcxproj"))
-{
- tool = &builder.get_toolchain().get_tool("VCXG");
-
- char digest[16];
- Crypto::MD5(package->get_name()).get_digest(digest, sizeof(digest));
- digest[6] = 3;
- digest[8] = (digest[6]&0x3F)|0x80;
- for(unsigned j=0; j<sizeof(digest); ++j)
- {
- if(j==4 || j==6 || j==8 || j==10)
- guid += '-';
- guid += format("%02x", static_cast<unsigned char>(digest[j]));
- }
-}
+++ /dev/null
-#ifndef VCXPROJECTFILE_H_
-#define VCXPROJECTFILE_H_
-
-#include <msp/builder/filetarget.h>
-
-class VcxProjectFile: public FileTarget
-{
-private:
- std::string guid;
-
-public:
- VcxProjectFile(Builder &, const SourcePackage &);
-
- const char *get_type() const override { return "VcxProjectFile"; }
-
- const std::string &get_guid() const { return guid; }
-};
-
-#endif
+++ /dev/null
-#include <msp/builder/builder.h>
-#include <msp/builder/csourcefile.h>
-#include <msp/builder/executable.h>
-#include <msp/builder/sourcepackage.h>
-#include <msp/core/application.h>
-#include <msp/fs/utils.h>
-#include <msp/io/print.h>
-#include <msp/strings/utils.h>
-#include "vcxprojectfile.h"
-#include "vcxprojectgenerator.h"
-
-using namespace std;
-using namespace Msp;
-
-VcxProjectGenerator::VcxProjectGenerator(Builder &b):
- Tool(b, "VCXG")
-{
- set_run_internal(_run);
-}
-
-Target *VcxProjectGenerator::create_target(const vector<Target *> &, const string &)
-{
- throw logic_error("Not implemented");
-}
-
-bool VcxProjectGenerator::_run(const VcxProjectFile &project)
-{
- const SourcePackage &spkg = *project.get_package();
- Builder &builder = spkg.get_builder();
-
- IO::BufferedFile out(project.get_path().str(), IO::M_WRITE);
- IO::print(out, "<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n");
-
- IO::print(out, "\t<ItemGroup Label=\"ProjectConfigurations\">\n");
- vector<string> build_types = builder.get_build_types();
- const char *platforms[] = { "Win32", "x64" };
- for(const char *p: platforms)
- for(const string &b: build_types)
- {
- IO::print(out, "\t\t<ProjectConfiguration Include=\"%s|%s\">\n", b, p);
- IO::print(out, "\t\t\t<Configuration>%s</Configuration>\n", b);
- IO::print(out, "\t\t\t<Platform>%s</Platform>\n", p);
- IO::print(out, "\t\t</ProjectConfiguration>\n");
- }
- IO::print(out, "\t</ItemGroup>\n");
-
- IO::print(out, "\t<PropertyGroup Label=\"Globals\">\n");
- IO::print(out, "\t\t<VCProjectVersion>15.0</VCProjectVersion>\n");
- IO::print(out, "\t\t<Keyword>MakeFileProj</Keyword>\n");
- IO::print(out, "\t\t<ProjectGuid>{%s}</ProjectGuid>\n", project.get_guid());
- IO::print(out, "\t</PropertyGroup>\n");
-
- IO::print(out, "\t<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n");
-
- const Executable *exe = 0;
- for(const Target *t: builder.get_build_graph().get_target("world")->get_dependencies())
- if(t->get_package()==&spkg)
- if((exe = dynamic_cast<const Executable *>(t)))
- break;
-
- const char *argv0 = Application::get_argv0();
- const string &toolchain = builder.get_current_arch().get_toolchain();
- for(const char *p: platforms)
- for(const string &b: build_types)
- {
- string base_cmd = format("%s --arch=%s-%s --build-type=%s --prefix=%s", argv0, p, toolchain, b, builder.get_prefix());
- IO::print(out, "\t<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='%s|%s'\" Label=\"Configuration\">\n", b, p);
- IO::print(out, "\t\t<ConfigurationType>MakeFile</ConfigurationType>\n");
- IO::print(out, "\t\t<NMakeBuildCommandLine>%s</NMakeBuildCommandLine>\n", base_cmd);
- IO::print(out, "\t\t<NMakeCleanCommandLine>%s -c</NMakeCleanCommandLine>\n", base_cmd);
- IO::print(out, "\t\t<NMakeReBuildCommandLine>%s -B</NMakeReBuildCommandLine>\n", base_cmd);
- if(exe)
- IO::print(out, "\t\t<NMakeOutput>%s</NMakeOutput>\n", exe->get_path());
- IO::print(out, "\t</PropertyGroup>\n");
- }
-
- IO::print(out, "\t<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n");
-
- vector<const FileTarget *> sources;
- vector<const FileTarget *> includes;
- vector<const FileTarget *> others;
- BuildInfo build_info;
- for(const auto &kvp: builder.get_build_graph().get_targets())
- if(kvp.second->get_package()==&spkg)
- {
- if(kvp.second->is_buildable())
- {
- BuildInfo tgt_binfo;
- kvp.second->collect_build_info(tgt_binfo);
- build_info.update_from(tgt_binfo, BuildInfo::CHAINED);
- }
- else if(const FileTarget *file = dynamic_cast<const FileTarget *>(kvp.second))
- {
- if(dynamic_cast<const CSourceFile *>(file))
- {
- string ext = tolower(FS::extpart(FS::basename(file->get_path())));
- if(ext==".h" || ext==".hpp")
- includes.push_back(file);
- else
- sources.push_back(file);
- }
- else
- others.push_back(file);
- }
- }
-
- if(!build_info.incpath.empty())
- {
- IO::print(out, "\t<PropertyGroup>\n");
- string path_str;
- for(const FS::Path &p: build_info.incpath)
- append(path_str, ";", p.str());
- IO::print(out, "\t\t<NMakeIncludeSearchPath>%s</NMakeIncludeSearchPath>\n", path_str);
- IO::print(out, "\t</PropertyGroup>\n");
- }
-
- IO::print(out, "\t<ItemGroup>\n");
- for(const FileTarget *s: sources)
- IO::print(out, "\t\t<ClCompile Include=\"%s\" />\n", s->get_path());
- IO::print(out, "\t</ItemGroup>\n");
-
- IO::print(out, "\t<ItemGroup>\n");
- for(const FileTarget *i: includes)
- IO::print(out, "\t\t<ClInclude Include=\"%s\" />\n", i->get_path());
- IO::print(out, "\t</ItemGroup>\n");
-
- IO::print(out, "\t<ItemGroup>\n");
- for(const FileTarget *t: others)
- IO::print(out, "\t\t<None Include=\"%s\" />\n", t->get_path());
- IO::print(out, "\t</ItemGroup>\n");
-
- IO::print(out, "\t<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n");
- IO::print(out, "</Project>\n");
-
- return true;
-}
+++ /dev/null
-#ifndef VCXPROJECTGENERATOR_H_
-#define VCXPROJECTGENERATOR_H_
-
-#include <msp/builder/tool.h>
-
-class VcxProjectFile;
-
-class VcxProjectGenerator: public Tool
-{
-public:
- VcxProjectGenerator(Builder &);
-
- Target *create_target(const std::vector<Target *> &, const std::string &) override;
-
-private:
- static bool _run(const VcxProjectFile &);
-};
-
-#endif
+++ /dev/null
-#include <msp/builder/builder.h>
-#include <msp/builder/sourcepackage.h>
-#include <msp/core/algorithm.h>
-#include "vssolutionfile.h"
-
-using namespace std;
-using namespace Msp;
-
-VsSolutionFile::VsSolutionFile(Builder &b, const SourcePackage &p):
- FileTarget(b, p, p.get_source_directory()/(p.get_name()+".sln"))
-{
- tool = &builder.get_toolchain().get_tool("VSSG");
-}
-
-void VsSolutionFile::find_dependencies()
-{
- find_dependencies(*package);
-}
-
-void VsSolutionFile::find_dependencies(const SourcePackage &spkg)
-{
- if(FileTarget *project = builder.get_vfs().get_target(spkg.get_source_directory()/(spkg.get_name()+".vcxproj")))
- if(!any_equals(depends, static_cast<Target *>(project)))
- {
- add_dependency(*project);
-
- for(const Package *r: spkg.get_required_packages())
- if(const SourcePackage *s = dynamic_cast<const SourcePackage *>(r))
- find_dependencies(*s);
- }
-}
+++ /dev/null
-#ifndef VSSOLUTIONFILE_H_
-#define VSSOLUTIONFILE_H_
-
-#include <msp/builder/filetarget.h>
-
-class VsSolutionFile: public FileTarget
-{
-public:
- VsSolutionFile(Builder &, const SourcePackage &);
-
- const char *get_type() const override { return "VsSolutionFile"; }
-protected:
- void find_dependencies() override;
- void find_dependencies(const SourcePackage &);
-};
-
-#endif
+++ /dev/null
-#include <cstring>
-#include <msp/builder/builder.h>
-#include <msp/builder/sourcepackage.h>
-#include <msp/io/file.h>
-#include <msp/io/print.h>
-#include "vcxprojectfile.h"
-#include "vssolutionfile.h"
-#include "vssolutiongenerator.h"
-
-using namespace std;
-using namespace Msp;
-
-VsSolutionGenerator::VsSolutionGenerator(Builder &b):
- Tool(b, "VSSG")
-{
- set_run_internal(_run);
-}
-
-Target *VsSolutionGenerator::create_target(const vector<Target *> &, const string &)
-{
- throw logic_error("Not implemented");
-}
-
-bool VsSolutionGenerator::_run(const VsSolutionFile &solution)
-{
- const SourcePackage &spkg = *solution.get_package();
- Builder &builder = spkg.get_builder();
-
- IO::BufferedFile out(solution.get_path().str(), IO::M_WRITE);
- IO::print(out, "Microsoft Visual Studio Solution File, Format Version 12.00\n");
- IO::print(out, "MinimumVisualStudioVersion = 10.0.40219.1\n");
-
- vector<const VcxProjectFile *> projects;
- for(const Target *t: solution.get_dependencies())
- if(const VcxProjectFile *project = dynamic_cast<const VcxProjectFile *>(t))
- projects.push_back(project);
-
- for(const VcxProjectFile *p: projects)
- {
- const SourcePackage *pkg = p->get_package();
- IO::print(out, "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"%s\", \"%s\", \"{%s}\"\nEndProject\n",
- pkg->get_name(), p->get_path(), p->get_guid());
- }
-
- vector<string> build_types = builder.get_build_types();
- const char *platforms[] = { "x86", "x64" };
-
- IO::print(out, "Global\n");
- IO::print(out, "\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n");
- for(const string &t: build_types)
- for(const char *p: platforms)
- IO::print(out, "\t\t%s|%s = %s|%s\n", t, p, t, p);
- IO::print(out, "\tEndGlobalSection\n");
- IO::print(out, "\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n");
- for(const VcxProjectFile *p: projects)
- for(const string &t: build_types)
- for(const char *f: platforms)
- {
- const char *project_platform = (!strcmp(f, "x86") ? "Win32" : f);
- IO::print(out, "\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n", p->get_guid(), t, f, t, project_platform);
- if(p->get_package()==&spkg)
- IO::print(out, "\t\t{%s}.%s|%s.Build.0 = %s|%s\n", p->get_guid(), t, f, t, project_platform);
- }
- IO::print(out, "\tEndGlobalSection\n");
- IO::print(out, "EndGlobal\n");
-
- return true;
-}
+++ /dev/null
-#ifndef VSSOLUTIONGENERATOR_H_
-#define VSSOLUTIONGENERATOR_H_
-
-#include <msp/builder/tool.h>
-
-class VsSolutionFile;
-
-class VsSolutionGenerator: public Tool
-{
-public:
- VsSolutionGenerator(Builder &);
-
- Target *create_target(const std::vector<Target *> &, const std::string &) override;
-
-private:
- static bool _run(const VsSolutionFile &);
-};
-
-#endif
#include "android/androidtools.h"
#include "binarypackage.h"
#include "builder.h"
-#include "builtin/builtintools.h"
#include "datafile/datatool.h"
#include "installedfile.h"
#include "package.h"
{
if(current_arch->get_system()=="android")
toolchain.add_toolchain(new AndroidTools(*this, *current_arch));
- toolchain.add_toolchain(new BuiltinTools(*this));
toolchain.add_tool(new DataTool(*this));
for(const LoadedPlugin &p: plugins)
p.plugin->add_tools(toolchain, *current_arch);
#include "binarycomponent.h"
#include "binarypackage.h"
#include "builder.h"
-#include "builtin/compilecommandsjson.h"
#include "datafile/datapackcomponent.h"
#include "file.h"
#include "installcomponent.h"
-#include "builtin/pkgconfigfile.h"
#include "plugin.h"
#include "sourcearchivecomponent.h"
#include "sourcegenerator.h"
#include "sourcepackage.h"
#include "tool.h"
-#include "builtin/vcxprojectfile.h"
-#include "builtin/vssolutionfile.h"
using namespace std;
using namespace Msp;
for(Component *c: components)
c->create_targets();
- const Architecture &arch = builder.get_native_arch();
if(!export_binfo.libs.empty())
{
export_binfo.incpath.push_back((builder.get_prefix()/"include").str());
export_binfo.libpath.push_back((builder.get_prefix()/"lib").str());
-
- if(arch.get_system()=="linux")
- {
- PkgConfigFile *pc = new PkgConfigFile(builder, *this);
- builder.get_build_graph().get_target("install")->add_dependency(*builder.get_toolchain().get_tool("CP").create_target(*pc));
- }
}
export_binfo.standards = build_info.standards;
- if(arch.get_system()=="windows")
- {
- new VcxProjectFile(builder, *this);
- new VsSolutionFile(builder, *this);
- }
-
- new CompileCommandsJson(builder, *this);
-
builder.call_plugins([this](const Plugin &p){ p.create_targets(*this); });
}