diff options
Diffstat (limited to 'project2/ice/iceCompile.cpp')
-rw-r--r-- | project2/ice/iceCompile.cpp | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/project2/ice/iceCompile.cpp b/project2/ice/iceCompile.cpp new file mode 100644 index 0000000..d9287f4 --- /dev/null +++ b/project2/ice/iceCompile.cpp @@ -0,0 +1,115 @@ +#include <pch.hpp> +#include "iceCompile.h" +#include <boost/filesystem/operations.hpp> +#include <logger.h> +#include <misc.h> +#include <dlfcn.h> + +namespace fs = boost::filesystem; + +std::string IceCompile::slice2cpp; +std::string IceCompile::cxx; +std::string IceCompile::linker; +std::string IceCompile::cxxopts; +std::string IceCompile::linkeropts; +fs::path IceCompile::tmpdir; +fs::path IceCompile::headerdir; + +DECLARE_OPTIONS(IceCompile, "ICE Compile Options") +("ice.compile.cxx", Options::value(&cxx, "g++"), + "The C++ compiler to use") +("ice.compile.cxxopts", Options::value(&cxxopts, "-Wall -Werror -std=c++11 -O3 -march=native -fPIC"), + "The extra arguments to pass to the C++ compiler") +("ice.compile.linker", Options::value(&linker, "g++"), + "The linker to use") +("ice.compile.linkeropts", Options::value(&linkeropts, ""), + "The extra arguments to pass to linker") +("ice.compile.slice2cpp", Options::value(&slice2cpp, "slice2cpp"), + "The ICE Slice to CPP processor to use") +("ice.compile.tmpdir", Options::value(&tmpdir, "/tmp/project2.slice"), + "The temporary directory used when compiling") +("ice.compile.headers", Options::value(&headerdir, "/usr/include/project2"), + "The root folder where Project2 header files are found") +END_OPTIONS(IceCompile); + +IceCompile::IceCompile(const boost::filesystem::path & s) : + slice(s) +{ +} + +IceCompile::IceCompile(const boost::filesystem::path & s, const Deps & d) : + slice(s), + deps(d) +{ +} + +void +IceCompile::Update() const +{ + fs::create_directories(IceCompile::tmpdir); + BOOST_FOREACH(const auto & dep, deps) { + dep->Update(); + } + const fs::path cpp(tmpdir / OutputName(".cpp")); + update(InputPath(), cpp, &IceCompile::Build); + const fs::path o(tmpdir / OutputName(".o")); + update(cpp, o, &IceCompile::Compile); + const fs::path so(tmpdir / OutputName(".so")); + update(o, so, &IceCompile::Link); +} + +void +IceCompile::update(const fs::path & in, const fs::path & out, UpdateFunc func) const +{ + if (!fs::exists(out) || std::max(fs::last_write_time(in), fs::last_write_time("/proc/self/exe")) > fs::last_write_time(out)) { + Logger()->messagebf(LOG_DEBUG, "updating %s from %s", out, in); + (this->*func)(in, out); + } + else { + Logger()->messagebf(LOG_DEBUG, "%s already up to date", out); + } +} + +void +IceCompile::Compile(const fs::path & in, const fs::path & out) const +{ + const auto compile = stringbf( + "%s %s -o %s -x c++ -c -I %s -I %s -I ../libmisc/ -I %s -I %s -I %s `pkg-config --cflags glibmm-2.4` %s", + cxx, cxxopts, out, tmpdir, + headerdir / "lib", + headerdir / "common", + headerdir / "ice", + headerdir / "daemon" / "lib", + in); + Logger()->messagebf(LOG_DEBUG, "compile command: %s", compile); + if (system(compile.c_str())) { + throw std::runtime_error("compile failed"); + } +} + +void +IceCompile::Link(const fs::path & in, const fs::path & out) const +{ + auto link = stringbf("%s %s -o %s -shared %s", linker, linkeropts, out, in); + BOOST_FOREACH(const auto & dep, deps) { + link += " " + (tmpdir / dep->OutputName(".so")).string(); + } + Logger()->messagebf(LOG_DEBUG, "link command: %s", link); + if (system(link.c_str())) { + throw std::runtime_error("link failed"); + } +} + +IceCompile::LibHandle +IceCompile::Open() const +{ + void * handle = dlopen((IceCompile::tmpdir / OutputName(".so")).string().c_str(), RTLD_GLOBAL | RTLD_NOW); + if (!handle) { + std::string msg(dlerror()); + Logger()->messagebf(LOG_ERR, "Failed to load compiled module (%s)", msg); + throw std::runtime_error(msg); + } + return LibHandle(handle, &dlclose); +} + + |