buildat/src/server/rccpp.cpp
Perttu Ahola ec0c0b64e6 WIP
2014-09-16 21:28:54 +03:00

147 lines
4.4 KiB
C++

#if defined(RCCPP_ENABLED)
#include "rccpp.h"
// Module interface
#include "interface/core.h"
#include <c55_filesys.h>
#include <vector>
#include <string>
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include <dlfcn.h>
// linux
#if 1
static void *library_load(const char *filename) { return dlopen(filename, RTLD_NOW); }
static void library_unload(void *module) { dlclose(module); }
static void *library_get_address(void *module, const char *name) { return dlsym(module, name); }
#elif 0
static void *library_load(const char *filename) { return LoadLibrary(filename); }
static void library_unload(void *module) { FreeLibrary(module); }
static void *library_get_address(void *module, const char *name) { return GetProcAddress(module, name); }
#endif
RCCPP_Compiler::RCCPP_Compiler()
{
}
bool RCCPP_Compiler::compile(const std::string &in_path, const std::string &out_path)
{
//std::string command = "g++ -g -O0 -fPIC -fvisibility=hidden -shared";
std::string command = "g++ -DRCCPP -g -fPIC -fvisibility=hidden -shared";
command += " -std=c++11";
for(const std::string &dir : include_directories) command += " -I" + dir;
for(const std::string &dir : library_directories) command += " -L" + dir;
command += " -o" + out_path;
command += " " + in_path;
//std::cout << ">>> " << command << std::endl;
// Fork for compilation.
int f = fork();
if(f == 0) {
execl("/bin/sh", "sh", "-c", command.c_str(), (const char*)nullptr);
}
// Wait for the forked process to exit.
int exit_status;
while(wait(&exit_status) > 0);
return exit_status == 0;
}
void RCCPP_Compiler::build(const std::string &in_path, const std::string &out_path)
{
std::cout << "Building " << in_path << " -> " << out_path << "... ";
std::string out_dir = c55fs::stripFilename(out_path);
c55fs::CreateAllDirs(out_dir);
if(!compile(in_path, out_path)) {
std::cout << "Failed!" << std::endl;
return;
}
std::cout << "Success!" << std::endl;
void *new_module = library_load(out_path.c_str());
if(new_module == NULL){
std::cout<<"Failed to load compiled library: "<<dlerror()<<std::endl;
return;
}
RCCPP_GetInterface GetInterface = (RCCPP_GetInterface)library_get_address(new_module, "rccpp_GetInterface");
if(GetInterface == nullptr) {
std::cout << "GetInterface is missing from the library" << std::endl;
return;
}
RCCPP_Interface *interface = GetInterface();
assert(interface && "Interface is null");
RCCPP_Constructor fun_constructor = interface->constructor;
RCCPP_Destructor fun_destructor = interface->destructor;
RCCPP_PlacementNew fun_placementnew = interface->placementnew;
if(!(fun_constructor && fun_constructor && fun_placementnew)) {
printf("Something failed with the function pointers in the module\n");
printf(" constructor: %p (%s)\n", fun_constructor, (fun_constructor != nullptr ? "ok" : "fail"));
printf(" destructor: %p (%s)\n", fun_destructor, (fun_destructor != nullptr ? "ok" : "fail"));
printf(" placement new: %p (%s)\n", fun_placementnew, (fun_placementnew != nullptr ? "ok" : "fail"));
fflush(stdout);
return;
}
std::string classname = interface->classname;
auto it = component_info_.find(classname);
if(it != component_info_.end()) {
RCCPP_Info &funcs = it->second;
funcs.constructor = fun_constructor;
funcs.destructor = fun_destructor;
funcs.placement_new = fun_placementnew;
if(funcs.module_prev) library_unload(funcs.module_prev);
funcs.module_prev = funcs.module;
funcs.module = new_module;
} else {
RCCPP_Info funcs;
funcs.constructor = fun_constructor;
funcs.destructor = fun_destructor;
funcs.placement_new = fun_placementnew;
funcs.module_prev = nullptr;
funcs.module = new_module;
funcs.size = interface->original_size;
component_info_.emplace(classname, std::move(funcs));
}
changed_classes_.push_back(classname);
}
void *RCCPP_Compiler::construct(const char *name) {
auto component_info_it = component_info_.find(name);
if(component_info_it == component_info_.end()) {
assert(nullptr && "Failed to get class info");
return nullptr;
}
RCCPP_Info &info = component_info_it->second;
RCCPP_Constructor constructor = info.constructor;
void *result = constructor();
auto it = constructed_objects.find(std::string(name));
if(it == constructed_objects.end()) constructed_objects.insert(std::make_pair(name, std::vector<void*>{result}));
else it->second.push_back(result);
return result;
}
#endif