summaryrefslogtreecommitdiff
path: root/project2/ice/iceCompile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'project2/ice/iceCompile.cpp')
-rw-r--r--project2/ice/iceCompile.cpp115
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);
+}
+
+