26 #include "shell_compiler.hpp"
27 #include "casadi/core/casadi_misc.hpp"
28 #include "casadi/core/casadi_meta.hpp"
29 #include "casadi/core/casadi_logger.hpp"
33 #ifndef OBJECT_FILE_SUFFIX
34 #define OBJECT_FILE_SUFFIX CasadiMeta::object_file_suffix()
42 int CASADI_IMPORTER_SHELL_EXPORT
45 plugin->name =
"shell";
47 plugin->version = CASADI_VERSION;
85 "Directory to put temporary objects in. Must end with a file separator."}},
88 "Compiler setup command. Intended to be fixed."
89 " The 'flag' option is the prefered way to set"
93 "Linker setup command. Intended to be fixed."
94 " The 'flag' option is the prefered way to set"
98 "Alias for 'compiler_flags'"}},
101 "Compile flags for the JIT compiler. Default: None"}},
104 "Linker flags for the JIT compiler. Default: None"}},
107 "Cleanup temporary files when unloading. Default: true"}},
108 {
"compiler_output_flag",
110 "Compiler flag to denote object output. Default: '-o '"}},
111 {
"compiler_include_flag",
113 "Compiler flag to add an include directory. Default: '-I' ('/I' on MSVC)"}},
116 "List of include directories, each passed to the compiler prefixed with "
117 "'compiler_include_flag'. OS-agnostic alternative to passing '-I...' via 'flags'. "
119 {
"linker_output_flag",
121 "Linker flag to denote shared library output. Default: '-o '"}},
124 "List of suffixes for extra files that the compiler may generate. Default: None"}},
127 "The file name used to write out compiled objects/libraries. "
128 "The actual file names used depend on 'temp_suffix' and include extensions. "
129 "Default: 'tmp_casadi_compiler_shell'"}},
132 "Use a temporary (seemingly random) filename suffix for file names. "
133 "This is desired for thread-safety. "
134 "This behaviour may defeat caching compiler wrappers. "
146 bool temp_suffix =
true;
147 std::string bare_name =
"tmp_casadi_compiler_shell";
150 std::vector<std::string> compiler_flags;
151 std::vector<std::string> linker_flags;
152 std::vector<std::string> include_dirs;
153 std::string suffix = OBJECT_FILE_SUFFIX;
156 std::string compiler =
"cl.exe";
157 std::string linker =
"link.exe";
158 std::string compiler_setup =
"/c";
159 std::string linker_setup =
"/DLL";
160 std::string compiler_output_flag =
"/Fo";
161 std::string linker_output_flag =
"/out:";
162 std::string compiler_include_flag =
"/I";
164 #elif defined(__APPLE__)
165 std::string compiler =
"clang";
166 std::string linker =
"clang";
167 std::string compiler_setup =
"-fPIC -c";
168 std::string linker_setup =
"-shared";
169 std::string compiler_output_flag =
"-o ";
170 std::string linker_output_flag =
"-o ";
171 std::string compiler_include_flag =
"-I";
173 std::string compiler =
"gcc";
174 std::string linker =
"gcc";
175 std::string compiler_setup =
"-fPIC -c";
176 std::string linker_setup =
"-shared";
177 std::string compiler_output_flag =
"-o ";
178 std::string linker_output_flag =
"-o ";
179 std::string compiler_include_flag =
"-I";
183 for (
auto&& op : opts) {
184 if (op.first==
"compiler") {
185 compiler = op.second.to_string();
186 }
else if (op.first==
"linker") {
187 linker = op.second.to_string();
188 }
else if (op.first==
"compiler_setup") {
189 compiler_setup = op.second.to_string();
190 }
else if (op.first==
"cleanup") {
192 }
else if (op.first==
"linker_setup") {
193 linker_setup = op.second.to_string();
194 }
else if (op.first==
"compiler_flags" || op.first==
"flags") {
195 compiler_flags = op.second;
196 }
else if (op.first==
"linker_flags") {
197 linker_flags = op.second;
198 }
else if (op.first==
"compiler_output_flag") {
199 compiler_output_flag = op.second.to_string();
200 }
else if (op.first==
"linker_output_flag") {
201 linker_output_flag = op.second.to_string();
202 }
else if (op.first==
"compiler_include_flag") {
203 compiler_include_flag = op.second.to_string();
204 }
else if (op.first==
"include_dirs") {
205 include_dirs = op.second.to_string_vector();
206 }
else if (op.first==
"extra_suffixes") {
208 }
else if (op.first==
"name") {
209 bare_name = op.second.to_string();
210 }
else if (op.first==
"temp_suffix") {
211 temp_suffix = op.second;
219 obj_name_ = directory + bare_name + suffix;
225 std::stringstream cccmd;
227 for (
auto i=compiler_flags.begin(); i!=compiler_flags.end(); ++i) {
231 for (
const std::string& dir : include_dirs) {
232 cccmd <<
" " << compiler_include_flag << dir;
234 cccmd <<
" " << compiler_setup;
237 cccmd <<
" " <<
name_;
240 cccmd <<
" " + compiler_output_flag <<
obj_name_;
243 if (
verbose_) casadi_message(
"calling \"" + cccmd.str() +
"\"");
244 if (system(cccmd.str().c_str())) {
245 casadi_error(
"Compilation failed. Tried \"" + cccmd.str() +
"\"");
249 std::stringstream ldcmd;
256 for (
auto i=linker_flags.begin(); i!=linker_flags.end(); ++i) {
259 ldcmd <<
" " << linker_setup;
262 if (
verbose_) casadi_message(
"calling \"" + ldcmd.str() +
"\"");
263 if (system(ldcmd.str().c_str())) {
264 casadi_error(
"Linking failed. Tried \"" + ldcmd.str() +
"\"");
268 handle_ = open_shared_library(
bin_name_, search_paths,
"ShellCompiler::init");
static std::string get_jit_directory(const Dict &jit_options)
Get JIT directory from options.
bool verbose_
Verbose – for debugging purposes.
virtual void init(const Dict &opts)
Initialize.
static const Options options_
Options.
std::string name_
C filename.
static void registerPlugin(const Plugin &plugin, bool needs_lock=true)
Register an integrator in the factory.
std::string bin_name_
Temporary file.
std::string obj_name_
Temporary file.
static const Options options_
Options.
static ImporterInternal * creator(const std::string &name)
Create a new JIT function.
ShellCompiler(const std::string &name)
Constructor.
std::vector< std::string > extra_suffixes_
Extra files.
static const std::string meta_doc
A documentation string.
~ShellCompiler() override
Destructor.
bool cleanup_
Cleanup temporary files when unloading.
signal_t get_function(const std::string &symname) override
Get a function pointer for numerical evaluation.
void init(const Dict &opts) override
Initialize.
std::string library() const override
Get library name.
int CASADI_IMPORTER_SHELL_EXPORT casadi_register_importer_shell(ImporterInternal::Plugin *plugin)
std::vector< std::string > get_search_paths()
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
void(* signal_t)(void)
Function pointer types for the C API.
bool remove(const std::string &path)
void CASADI_IMPORTER_SHELL_EXPORT casadi_load_importer_shell()
std::string temporary_file(const std::string &prefix, const std::string &suffix, const std::string &directory)
Options metadata for a class.