mirror of
https://github.com/nasa/trick.git
synced 2025-06-17 06:38:27 +00:00
Standardize directory names
Reorganized. Created a new top level include directory that will hold all of Trick's header files. Moved all of the Trick headers to this directory. Created a libexec directory that holds all of the executables that users don't need to execute directly. Changed all of the executables remaining in bin to start with "trick-". In the sim_services directories changed all source files to find the Trick headers in their new location. Since all of the include files are gone in sim_services, removed the src directories as well, moving all of the source files up a level. Moved the makefiles, docs, man, and other architecture independent files into a top level share directory. Renamed lib_${TRICK_HOST_CPU} to lib64 or lib depending on the platform we're currently on. refs #63
This commit is contained in:
282
trick_source/sim_services/JITInputFile/JITInputFile.cpp
Normal file
282
trick_source/sim_services/JITInputFile/JITInputFile.cpp
Normal file
@ -0,0 +1,282 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include <string.h>
|
||||
#include <dlfcn.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
#include "trick/JITInputFile.hh"
|
||||
#include "trick/command_line_protos.h"
|
||||
#include "trick/message_type.h"
|
||||
#include "trick/message_proto.h"
|
||||
#include "trick/env_proto.h"
|
||||
#include "trick/exec_proto.h"
|
||||
#include "trick/exec_proto.hh"
|
||||
#include "trick/TrickConstant.hh"
|
||||
|
||||
Trick::JITInputFile * the_jit = NULL ;
|
||||
|
||||
//TODO: Move JITLibInfo code into the JITLibInfo object.
|
||||
|
||||
Trick::JITInputFile::JITInputFile() {
|
||||
the_jit = this ;
|
||||
|
||||
JITLibInfo li ;
|
||||
li.library_name = "S_main" ;
|
||||
li.handle = dlopen( NULL , RTLD_LAZY ) ;
|
||||
file_to_libinfo_map["S_main"] = li ;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@details
|
||||
-# Test if the input file on the command line ends in .cpp or .cc
|
||||
-# If it does save the input file locally and clear the command line argument so
|
||||
the cpp input file will not go through the input processor.
|
||||
*/
|
||||
int Trick::JITInputFile::process_sim_args() {
|
||||
|
||||
std::string cpp = ".cpp" ;
|
||||
std::string cc = ".cc" ;
|
||||
|
||||
std::string & ifr = command_line_args_get_input_file_ref() ;
|
||||
if ( ! ifr.empty() ) {
|
||||
if (! ifr.compare( ifr.length() - cpp.length() , cpp.length(), cpp) or
|
||||
! ifr.compare( ifr.length() - cc.length() , cc.length(), cc) ) {
|
||||
input_file = ifr ;
|
||||
ifr.clear() ;
|
||||
}
|
||||
}
|
||||
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
/**
|
||||
@details
|
||||
-# If the incoming file name has already been successfully compiled, return 0
|
||||
-# Get the basename of the input file
|
||||
-# Get the root name of the input file (no extension)
|
||||
-# Set all of the output file names based on the output directory and the input file root name
|
||||
-# Make the output directory
|
||||
-# Open the makefile for writing
|
||||
-# Create a makefile that will compile the input file to a shared library
|
||||
-# Call make to compile the library file.
|
||||
-# Extract the return status from the system call.
|
||||
-# If the compilation was unsuccessful, exec_terminate
|
||||
-# The library compile successfully. Add library name to map
|
||||
*/
|
||||
int Trick::JITInputFile::compile(std::string file_name) {
|
||||
|
||||
std::ofstream outfile ;
|
||||
std::ostringstream ss ;
|
||||
|
||||
std::string output_directory ;
|
||||
std::string object_fullpath_name ;
|
||||
std::string library_fullpath_name ;
|
||||
std::string makefile_fullpath_name ;
|
||||
std::string input_file_rootname ;
|
||||
std::string input_file_basename ;
|
||||
std::string dep_file_name ;
|
||||
struct stat output_dir_stat ;
|
||||
int ret ;
|
||||
size_t pos ;
|
||||
|
||||
// If the incoming file name has already been successfully compiled, return now.
|
||||
if ( file_to_libinfo_map.find(file_name) != file_to_libinfo_map.end() ) {
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
// get the basename of the input file
|
||||
if ( (pos = file_name.find_last_of("/")) != std::string::npos ) {
|
||||
input_file_basename = file_name.substr(pos + 1 ) ;
|
||||
} else {
|
||||
input_file_basename = file_name ;
|
||||
}
|
||||
|
||||
// get the root name of the input file (no extension)
|
||||
if ( (pos = input_file_basename.find_last_of(".")) != std::string::npos ) {
|
||||
input_file_rootname = input_file_basename.substr(0, pos) ;
|
||||
} else {
|
||||
input_file_rootname = input_file_basename ;
|
||||
}
|
||||
|
||||
// set all of the output file names based on the output directory and the input file root name
|
||||
output_directory = std::string(command_line_args_get_output_dir()) + "/jitlib" ;
|
||||
makefile_fullpath_name = output_directory + "/Makefile." + input_file_rootname ;
|
||||
object_fullpath_name = output_directory + "/" + input_file_rootname + ".o" ;
|
||||
library_fullpath_name = output_directory + "/lib" + input_file_rootname + ".so" ;
|
||||
dep_file_name = output_directory + "/" + input_file_rootname + ".d" ;
|
||||
|
||||
// make the output directory
|
||||
ret = stat( output_directory.c_str(), &output_dir_stat) ;
|
||||
if ( ret == -1 and errno == ENOENT ) {
|
||||
mkdir(output_directory.c_str(), 0775) ;
|
||||
} else if ( ret == 0 and ! S_ISDIR(output_dir_stat.st_mode)) {
|
||||
std::string error_message = "JITInputfile could not create directory " + output_directory ;
|
||||
exec_terminate_with_return(-1 , __FILE__ , __LINE__ , error_message.c_str() ) ;
|
||||
}
|
||||
|
||||
// open the makefile for writing
|
||||
outfile.open(makefile_fullpath_name.c_str()) ;
|
||||
|
||||
// create a makefile that will compile the input file to a shared library
|
||||
outfile << "# JITInputFile auto generated Makefile. Paths are relative to the simulation directory" << std::endl ;
|
||||
outfile << "# To manually use this file go to sim directory and use \"make -f " << makefile_fullpath_name << " <makefile_target>\"" ;
|
||||
outfile << std::endl << std::endl ;
|
||||
// rule to link shared library
|
||||
outfile << library_fullpath_name << ": " << object_fullpath_name << std::endl ;
|
||||
outfile << "\t" << get_trick_env((char *)"TRICK_CPPC") << " -shared -o $@ $<" << std::endl << std::endl ;
|
||||
// rule to compile cpp file
|
||||
outfile << object_fullpath_name << ": " << file_name << std::endl ;
|
||||
outfile << "\t" << get_trick_env((char *)"TRICK_CPPC") << " " << get_trick_env((char *)"TRICK_CXXFLAGS") ;
|
||||
outfile << " -MMD -c -fPIC -o $@ $<" << std::endl << std::endl ;
|
||||
// rule to clean
|
||||
outfile << "clean:" << std::endl ;
|
||||
outfile << "\t rm -f " << object_fullpath_name << " " << library_fullpath_name ;
|
||||
outfile << " " << command_line_args_get_output_dir() << "/" << dep_file_name << std::endl << std::endl ;
|
||||
// dependency file
|
||||
outfile << "-include " << dep_file_name << std::endl ;
|
||||
|
||||
outfile.close() ;
|
||||
|
||||
// call make to compile the library file.
|
||||
ss << "make -s -f " << makefile_fullpath_name << std::endl ;
|
||||
ret = system(ss.str().c_str()) ;
|
||||
|
||||
// extract the return status from the system call.
|
||||
ret = WEXITSTATUS(ret) ;
|
||||
|
||||
// If the compilation was unsuccessful, exec_terminate
|
||||
if ( ret != 0 ) {
|
||||
std::string error_message = "JITInputfile shared library creation failed" ;
|
||||
exec_terminate_with_return(-1 , __FILE__ , __LINE__ , error_message.c_str() ) ;
|
||||
}
|
||||
|
||||
// The library compile successfully. Add library name to map
|
||||
JITLibInfo li ;
|
||||
li.library_name = library_fullpath_name ;
|
||||
file_to_libinfo_map[file_name] = li ;
|
||||
|
||||
return 0 ;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@details
|
||||
-# Check if we have compiled this library yet
|
||||
-# If we have not compiled the library then exec_terminate
|
||||
-# If the library handle is NULL, try and open the library
|
||||
-# If the library open fails, exec_terminate
|
||||
-# Look up the symbol run_function
|
||||
-# If the symbol is not found exec_terminate.
|
||||
-# Call the function
|
||||
*/
|
||||
int Trick::JITInputFile::run(std::string file_name , std::string run_function ) {
|
||||
int (*call_me)(void) = NULL ;
|
||||
int ret = 0 ;
|
||||
|
||||
// Check if we have compiled this library yet.
|
||||
if ( file_to_libinfo_map.find(file_name) == file_to_libinfo_map.end() ) {
|
||||
// If we have not compiled the library then exec_terminate
|
||||
std::string error_message = "JITInputfile library not found for " + file_name ;
|
||||
exec_terminate_with_return(-1 , __FILE__ , __LINE__ , error_message.c_str() ) ;
|
||||
}
|
||||
|
||||
JITLibInfo & li = file_to_libinfo_map.find(file_name)->second ;
|
||||
// if the library handle is NULL, try and open the library.
|
||||
if ( li.handle == NULL ) {
|
||||
li.handle = dlopen( li.library_name.c_str() , RTLD_LAZY ) ;
|
||||
// if the library open fails, exec_terminate
|
||||
if ( li.handle == NULL ) {
|
||||
std::string error_message = "JITInputfile dlopen failed on " + li.library_name ;
|
||||
exec_terminate_with_return(-1 , __FILE__ , __LINE__ , error_message.c_str() ) ;
|
||||
}
|
||||
}
|
||||
|
||||
// Look up the symbol name
|
||||
call_me = (int (*)(void))dlsym( li.handle , run_function.c_str()) ;
|
||||
if ( call_me == NULL ) {
|
||||
std::string error_message = "JITInputfile could not find function " + run_function ;
|
||||
exec_terminate_with_return(-1 , __FILE__ , __LINE__ , error_message.c_str() ) ;
|
||||
}
|
||||
|
||||
// We found the function, call it!
|
||||
ret = (*call_me)() ;
|
||||
|
||||
return ret ;
|
||||
}
|
||||
|
||||
/**
|
||||
@details
|
||||
-# If the file_name is not empty
|
||||
-# Compile the file_name
|
||||
-# If the file compiled successfully
|
||||
-# Execute the run_function
|
||||
*/
|
||||
int Trick::JITInputFile::compile_and_run(std::string file_name, std::string run_function) {
|
||||
|
||||
int ret = 0 ;
|
||||
|
||||
// If the file name is not empty
|
||||
if ( ! file_name.empty() ) {
|
||||
// Attempt to compile the library.
|
||||
ret = compile(file_name) ;
|
||||
if ( ret == 0 ) {
|
||||
// If the compilation was successful execute run_function.
|
||||
ret = run( file_name , run_function ) ;
|
||||
}
|
||||
}
|
||||
|
||||
// Return 0 or the return value of compile/run.
|
||||
return ret ;
|
||||
}
|
||||
|
||||
/**
|
||||
@details
|
||||
-# If the incoming file name has already been added, return 0
|
||||
-# Add library name to map
|
||||
*/
|
||||
int Trick::JITInputFile::add_library(std::string lib_name) {
|
||||
|
||||
// If the incoming file name has already been added, return 0
|
||||
if ( file_to_libinfo_map.find(lib_name) != file_to_libinfo_map.end() ) {
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
// Add library name to map
|
||||
JITLibInfo li ;
|
||||
li.library_name = lib_name ;
|
||||
li.handle = dlopen( li.library_name.c_str() , RTLD_LAZY ) ;
|
||||
file_to_libinfo_map[lib_name] = li ;
|
||||
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
void * Trick::JITInputFile::find_symbol(std::string sym) {
|
||||
std::map< std::string , JITLibInfo >::iterator it ;
|
||||
for ( it = file_to_libinfo_map.begin() ; it != file_to_libinfo_map.end() ; it++ ) {
|
||||
void * ret = (*it).second.find_symbol(sym) ;
|
||||
if (ret != NULL) {
|
||||
return ret ;
|
||||
}
|
||||
}
|
||||
return NULL ;
|
||||
}
|
||||
|
||||
/**
|
||||
@details
|
||||
-# Call compile_and_run with the input_file from the command line
|
||||
*/
|
||||
int Trick::JITInputFile::init() {
|
||||
// Compile and run the input file. It's ok if input_file is empty.
|
||||
return compile_and_run(input_file) ;
|
||||
}
|
||||
|
Reference in New Issue
Block a user