casadi_os.cpp
1 /*
2  * This file is part of CasADi.
3  *
4  * CasADi -- A symbolic framework for dynamic optimization.
5  * Copyright (C) 2010 by Joel Andersson, Moritz Diehl, K.U.Leuven. All rights reserved.
6  *
7  * CasADi is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 3 of the License, or (at your option) any later version.
11  *
12  * CasADi is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with CasADi; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  *
21  */
22 
23 #include "casadi_os.hpp"
24 #include "exception.hpp"
25 #include "global_options.hpp"
26 
27 namespace casadi {
28 
29 // http://stackoverflow.com/questions/303562/c-format-macro-inline-ostringstream
30 #define STRING(ITEMS) \
31  ((dynamic_cast<std::ostringstream &>(std::ostringstream() \
32  . seekp(0, std::ios_base::cur) << ITEMS)) . str())
33 
34 char pathsep() {
35  #ifdef _WIN32
36  return ';';
37  #else
38  return ':';
39  #endif
40 }
41 std::string filesep() {
42  #ifdef _WIN32
43  return "\\";
44  #else
45  return "/";
46  #endif
47 }
48 
49 std::vector<std::string> get_search_paths() {
50 
51  // Build up search paths;
52  std::vector<std::string> search_paths;
53 
54  // Search path: global casadipath option
55  std::stringstream casadipaths(GlobalOptions::getCasadiPath());
56  std::string casadipath;
57  while (std::getline(casadipaths, casadipath, pathsep())) {
58  search_paths.push_back(casadipath);
59  }
60 
61  // Search path: CASADIPATH env variable
62  char* pLIBDIR;
63  pLIBDIR = getenv("CASADIPATH");
64 
65  if (pLIBDIR!=nullptr) {
66  std::stringstream casadipaths(pLIBDIR);
67  std::string casadipath;
68  while (std::getline(casadipaths, casadipath, pathsep())) {
69  search_paths.push_back(casadipath);
70  }
71  }
72 
73  // Search path: bare
74  search_paths.push_back("");
75 
76  // Search path : PLUGIN_EXTRA_SEARCH_PATH
77  #ifdef PLUGIN_EXTRA_SEARCH_PATH
78  search_paths.push_back(
79  std::string("") + PLUGIN_EXTRA_SEARCH_PATH);
80  #endif // PLUGIN_EXTRA_SEARCH_PATH
81 
82  // Search path : current directory
83  search_paths.push_back(".");
84 
85  return search_paths;
86 }
87 
88 #ifdef WITH_DL
89 
90 handle_t open_shared_library(const std::string& lib, const std::vector<std::string> &search_paths,
91  const std::string& caller, bool global) {
92  std::string resultpath;
93  return open_shared_library(lib, search_paths, resultpath, caller, global);
94 }
95 
96 int close_shared_library(handle_t handle) {
97  #ifdef _WIN32
98  return !FreeLibrary(handle);
99  #else // _WIN32
100  return dlclose(handle);
101  #endif // _WIN32
102 }
103 
104 handle_t open_shared_library(const std::string& lib, const std::vector<std::string> &search_paths,
105  std::string& resultpath, const std::string& caller, bool global) {
106  // Alocate a handle
107  handle_t handle = 0;
108 
109  // Alocate a handle pointer
110  #ifndef _WIN32
111  int flag;
112  if (global) {
113  flag = RTLD_NOW | RTLD_GLOBAL;
114  } else {
115  flag = RTLD_LAZY | RTLD_LOCAL;
116  }
117  #ifdef WITH_DEEPBIND
118  #if !defined(__APPLE__) && !defined(__EMSCRIPTEN__)
119  flag |= RTLD_DEEPBIND;
120  #endif
121  #endif
122  #endif
123 
124 
125  // Prepare error string
126  std::stringstream errors;
127  errors << caller << ": Cannot load shared library '"
128  << lib << "': " << std::endl;
129  errors << " (\n"
130  << " Searched directories: 1. casadipath from GlobalOptions\n"
131  << " 2. CASADIPATH env var\n"
132  << " 3. PATH env var (Windows)\n"
133  << " 4. LD_LIBRARY_PATH env var (Linux)\n"
134  << " 5. DYLD_LIBRARY_PATH env var (osx)\n"
135  << " A library may be 'not found' even if the file exists:\n"
136  << " * library is not compatible (different compiler/bitness)\n"
137  << " * the dependencies are not found\n"
138  << " )";
139 
140  std::string searchpath;
141 
142  // Try getting a handle
143  for (casadi_int i=0;i<search_paths.size();++i) {
144  searchpath = search_paths[i];
145 #ifdef _WIN32
146  SetDllDirectory(TEXT(searchpath.c_str()));
147  handle = LoadLibrary(TEXT(lib.c_str()));
148  SetDllDirectory(NULL);
149 #else // _WIN32
150  std::string libname = searchpath.empty() ? lib : searchpath + filesep() + lib;
151  handle = dlopen(libname.c_str(), flag);
152 #endif // _WIN32
153  if (handle) {
154  resultpath = searchpath;
155  break;
156  } else {
157  errors << std::endl << " Tried '" << searchpath << "' :";
158 #ifdef _WIN32
159  errors << std::endl << " Error code (WIN32): " << STRING(GetLastError());
160 #else // _WIN32
161  errors << std::endl << " Error code: " << dlerror();
162 #endif // _WIN32
163  }
164  }
165 
166  casadi_assert(handle!=nullptr, errors.str());
167 
168  return handle;
169 }
170 
171 #endif // WITH_DL
172 
173 } // namespace casadi
static std::string getCasadiPath()
The casadi namespace.
Definition: archiver.cpp:28
std::string filesep()
Definition: casadi_os.cpp:41
std::vector< std::string > get_search_paths()
Definition: casadi_os.cpp:49
char pathsep()
Definition: casadi_os.cpp:34