• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nasa / trick / 15910387694

26 Jun 2025 07:07PM UTC coverage: 55.948% (+0.001%) from 55.947%
15910387694

push

github

web-flow
JIT compile call should load resulting library #1912 (#1913)

The compile command would track the resulting library, but didn't load the
symbols.  This makes it impossible to do anything with the code.  Changed it
so after successful compilation the library symbols are loaded.

0 of 1 new or added line in 1 file covered. (0.0%)

1 existing line in 1 file now uncovered.

12332 of 22042 relevant lines covered (55.95%)

257116.52 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

19.27
/trick_source/sim_services/JITInputFile/JITInputFile.cpp
1

2
#include <iostream>
3
#include <fstream>
4
#include <sstream>
5
#include <cstring>
6
#include <string>
7

8
#include <string.h>
9
#include <dlfcn.h>
10
#include <stdlib.h>
11
#include <sys/types.h>
12
#include <sys/stat.h>
13
#include <unistd.h>
14
#include <errno.h>
15

16

17
#include "trick/JITInputFile.hh"
18
#include "trick/command_line_protos.h"
19
#include "trick/message_type.h"
20
#include "trick/message_proto.h"
21
#include "trick/env_proto.h"
22
#include "trick/exec_proto.h"
23
#include "trick/exec_proto.hh"
24
#include "trick/TrickConstant.hh"
25

26
Trick::JITInputFile * the_jit = NULL ;
27

28
//TODO: Move JITLibInfo code into the JITLibInfo object.
29

30
Trick::JITInputFile::JITInputFile() {
182✔
31
    the_jit = this ;
182✔
32

33
    JITLibInfo li ;
182✔
34
    li.library_name = "S_main" ;
182✔
35
    li.handle = dlopen( NULL , RTLD_LAZY ) ;
182✔
36
    file_to_libinfo_map["S_main"] = li ;
182✔
37

38
}
182✔
39

40
/**
41
@details
42
-# Test if the input file on the command line ends in .cpp or .cc
43
-# If it does save the input file locally and clear the command line argument so
44
   the cpp input file will not go through the input processor.
45
*/
46
int Trick::JITInputFile::process_sim_args() {
182✔
47

48
    std::string cpp = ".cpp" ;
364✔
49
    std::string cc = ".cc" ;
182✔
50

51
    std::string & ifr = command_line_args_get_input_file_ref() ;
182✔
52
    if ( ! ifr.empty() ) {
182✔
53
        if (! ifr.compare( ifr.length() - cpp.length() , cpp.length(), cpp) or
364✔
54
            ! ifr.compare( ifr.length() -  cc.length() ,  cc.length(),  cc) ) {
182✔
55
            input_file = ifr ;
×
56
            ifr.clear() ;
×
57
        }
58
    }
59

60
    return 0 ;
364✔
61
}
62

63
/**
64
@details
65
-# If the incoming file name has already been successfully compiled, return 0
66
-# Get the basename of the input file
67
-# Get the root name of the input file (no extension)
68
-# Set all of the output file names based on the output directory and the input file root name
69
-# Make the output directory
70
-# Open the makefile for writing
71
-# Create a makefile that will compile the input file to a shared library
72
-# Call make to compile the library file.
73
-# Extract the return status from the system call.
74
-# If the compilation was unsuccessful, exec_terminate
75
-# The library compile successfully.  Add library name to map
76
*/
77
int Trick::JITInputFile::compile(std::string file_name) {
×
78

79
    std::ofstream outfile ;
×
80
    std::ostringstream ss ;
×
81

82
    std::string output_directory ;
×
83
    std::string object_fullpath_name ;
×
84
    std::string library_fullpath_name ;
×
85
    std::string makefile_fullpath_name ;
×
86
    std::string input_file_rootname ;
×
87
    std::string input_file_basename ;
×
88
    std::string dep_file_name ;
×
89
    struct stat output_dir_stat ;
90
    int ret ;
91
    size_t pos ;
92

93
    // If the incoming file name has already been successfully compiled, return now.
94
    if ( file_to_libinfo_map.find(file_name) != file_to_libinfo_map.end() ) {
×
95
        return 0 ;
×
96
    }
97

98
    // get the basename of the input file
99
    if ( (pos = file_name.find_last_of("/")) != std::string::npos ) {
×
100
        input_file_basename = file_name.substr(pos + 1 ) ;
×
101
    } else {
102
        input_file_basename = file_name ;
×
103
    }
104

105
    // get the root name of the input file (no extension)
106
    if ( (pos = input_file_basename.find_last_of(".")) != std::string::npos ) {
×
107
        input_file_rootname = input_file_basename.substr(0, pos) ;
×
108
    } else {
109
        input_file_rootname = input_file_basename ;
×
110
    }
111

112
    // set all of the output file names based on the output directory and the input file root name
113
    output_directory = std::string(command_line_args_get_output_dir()) + "/jitlib" ;
×
114
    makefile_fullpath_name = output_directory + "/Makefile." + input_file_rootname ;
×
115
    object_fullpath_name = output_directory + "/" + input_file_rootname + ".o" ;
×
116
    library_fullpath_name = output_directory + "/lib" + input_file_rootname + ".so" ;
×
117
    dep_file_name = output_directory + "/" + input_file_rootname + ".d" ;
×
118

119
    // make the output directory
120
    ret = stat( output_directory.c_str(), &output_dir_stat) ;
×
121
    if ( ret == -1 and errno == ENOENT ) {
×
122
        mkdir(output_directory.c_str(), 0775) ;
×
123
    } else if ( ret == 0 and ! S_ISDIR(output_dir_stat.st_mode)) {
×
124
        std::string error_message = "JITInputfile could not create directory " + output_directory ;
×
125
        exec_terminate_with_return(-1 , __FILE__ , __LINE__ , error_message.c_str() ) ;
×
126
    }
127

128
    // open the makefile for writing
129
    outfile.open(makefile_fullpath_name.c_str()) ;
×
130

131
    // create a makefile that will compile the input file to a shared library
132
    outfile << "# JITInputFile auto generated Makefile.  Paths are relative to the simulation directory" << std::endl ;
×
133
    outfile << "# To manually use this file go to sim directory and use \"make -f " << makefile_fullpath_name << " <makefile_target>\"" ;
×
134
    outfile << std::endl << std::endl ;
×
135
    // rule to link shared library
136
    outfile << library_fullpath_name << ": " << object_fullpath_name << std::endl ;
×
137
#ifdef __APPLE__
138
    outfile << "\t" << get_trick_env((char *)"TRICK_CXX") << " " << get_trick_env((char *)"TRICK_LDFLAGS") << " -shared -undefined dynamic_lookup -o $@ $< " << std::endl << std::endl ;
139
#else
140
    outfile << "\t" << get_trick_env((char *)"TRICK_CXX") << " " << get_trick_env((char *)"TRICK_LDFLAGS") << " -shared -o $@ $< " << std::endl << std::endl ;
×
141
#endif
142
    // rule to compile cpp file
143
    outfile << object_fullpath_name << ": " << file_name << std::endl ;
×
144
    outfile << "\t" << get_trick_env((char *)"TRICK_CXX") << " " << get_trick_env((char *)"TRICK_CXXFLAGS") ;
×
145
    outfile << " " << get_trick_env((char *)"TRICK_SYSTEM_CXXFLAGS") ;
×
146
    outfile << " -MMD -c -fPIC -o $@ $<" << std::endl << std::endl ;
×
147
    // rule to clean
148
    outfile << "clean:" << std::endl ;
×
149
    outfile << "\t rm -f " << object_fullpath_name << " " << library_fullpath_name ;
×
150
    outfile << " " << dep_file_name << std::endl << std::endl ;
×
151
    // dependency file
152
    outfile << "-include " << dep_file_name << std::endl ;
×
153

154
    outfile.close() ;
×
155

156
    // call make to compile the library file.
157
    ss << "make -s -f " << makefile_fullpath_name << std::endl ;
×
158
    ret = system(ss.str().c_str()) ;
×
159

160
    // extract the return status from the system call.
161
    ret = WEXITSTATUS(ret) ;
×
162

163
    // If the compilation was unsuccessful, exec_terminate
164
    if ( ret != 0 ) {
×
165
        std::string error_message = std::string("JITInputFile shared library creation failed: ")
×
166
                                  + std::strerror(errno);
×
167
        exec_terminate_with_return(-1 , __FILE__ , __LINE__ , error_message.c_str());
×
168
    }
169

170
    // The library compile successfully.  Add library name to map
NEW
171
    add_library(library_fullpath_name);
×
172

173
    return 0 ;
×
174

175
}
176

177
/**
178
@details
179
-# Check if we have compiled this library yet
180
    -# If we have not compiled the library then exec_terminate
181
-# If the library handle is NULL, try and open the library
182
    -# If the library open fails, exec_terminate
183
-# Look up the symbol run_function
184
    -# If the symbol is not found exec_terminate.
185
-# Call the function
186
*/
187
int Trick::JITInputFile::run(std::string file_name , std::string run_function ) {
×
188
    // Check if we have compiled this library yet.
189
    if ( file_to_libinfo_map.find(file_name) == file_to_libinfo_map.end() ) {
×
190
        // If we have not compiled the library then exec_terminate
191
        std::string error_message = "JITInputfile library not found for " + file_name ;
×
192
        exec_terminate_with_return(-1 , __FILE__ , __LINE__ , error_message.c_str() ) ;
×
193
    }
194

195
    JITLibInfo & li = file_to_libinfo_map.find(file_name)->second ;
×
196
    // if the library handle is NULL, try and open the library.
197
    if ( li.handle == NULL ) {
×
198
        li.handle = dlopen( li.library_name.c_str() , RTLD_LAZY ) ;
×
199
        // if the library open fails, exec_terminate
200
        if ( li.handle == NULL ) {
×
201
            std::string error_message = "JITInputfile dlopen failed on " + li.library_name ;
×
202
            exec_terminate_with_return(-1 , __FILE__ , __LINE__ , error_message.c_str() ) ;
×
203
        }
204
    }
205

206
    // Look up the symbol name
207
    int (*call_me)(void) = (int (*)(void))dlsym( li.handle , run_function.c_str()) ;
×
208
    if ( call_me == NULL ) {
×
209
        std::string error_message = "JITInputfile could not find function " + run_function ;
×
210
        return exec_terminate_with_return(-1 , __FILE__ , __LINE__ , error_message.c_str() ) ;
×
211
    } else {
212
        // We found the function, call it!
213
        return (*call_me)() ;
×
214
    }
215
}
216

217
/**
218
@details
219
-# If the file_name is not empty
220
    -# Compile the file_name
221
    -# If the file compiled successfully
222
        -# Execute the run_function
223
*/
224
int Trick::JITInputFile::compile_and_run(std::string file_name, std::string run_function) {
182✔
225

226
    int ret = 0 ;
182✔
227

228
    // If the file name is not empty
229
    if ( ! file_name.empty() ) {
182✔
230
        // Attempt to compile the library.
231
        ret = compile(file_name) ;
×
232
        if ( ret == 0 ) {
×
233
            // If the compilation was successful execute run_function.
234
            ret = run( file_name , run_function ) ;
×
235
        }
236
    }
237

238
    // Return 0 or the return value of compile/run.
239
    return ret ;
182✔
240
}
241

242
/**
243
@details
244
-# If the incoming file name has already been added, return 0
245
-# Add library name to map
246
*/
247
int Trick::JITInputFile::add_library(std::string lib_name) {
×
248

249
    // If the incoming file name has already been added, return 0
250
    if ( file_to_libinfo_map.find(lib_name) != file_to_libinfo_map.end() ) {
×
251
        return 0 ;
×
252
    }
253

254
    // Add library name to map
255
    JITLibInfo li ;
×
256
    li.library_name = lib_name ;
×
257
    li.handle = dlopen( li.library_name.c_str() , RTLD_LAZY ) ;
×
258
    file_to_libinfo_map[lib_name] = li ;
×
259

260
    return 0 ;
×
261
}
262

263
void * Trick::JITInputFile::find_symbol(std::string sym) {
×
264
    std::map< std::string , JITLibInfo >::iterator it ;
×
265
    for ( it = file_to_libinfo_map.begin() ; it != file_to_libinfo_map.end() ; ++it ) {
×
266
        void * ret = (*it).second.find_symbol(sym) ;
×
267
        if (ret != NULL) {
×
268
            return ret ;
×
269
        }
270
    }
271
    return NULL ;
×
272
}
273

274
/**
275
@details
276
-# Call compile_and_run with the input_file from the command line
277
*/
278
int Trick::JITInputFile::init() {
182✔
279
    // Compile and run the input file.  It's ok if input_file is empty.
280
    return compile_and_run(input_file) ;
182✔
281
}
282

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc