blob: 951ad10426e85bbc34bd7c5dccda3a29e377d36e [file] [log] [blame]
Brian Silverman8fce7482020-01-05 13:18:21 -08001/*----------------------------------------------------------------------------*/
2/* Copyright (c) 2017-2019 FIRST. All Rights Reserved. */
3/* Open Source Software - may be modified and shared by FRC teams. The code */
4/* must be accompanied by the FIRST BSD license file in the root directory of */
5/* the project. */
6/*----------------------------------------------------------------------------*/
7
8#include "hal/Extensions.h"
9
10#include <wpi/Path.h>
11#include <wpi/SmallString.h>
12#include <wpi/StringRef.h>
13#include <wpi/raw_ostream.h>
14
15#include "hal/HAL.h"
16
17#if defined(WIN32) || defined(_WIN32)
18#include <windows.h>
19#else
20#include <dlfcn.h>
21#endif
22
23#if defined(WIN32) || defined(_WIN32)
24#define DELIM ';'
25#define HTYPE HMODULE
26#define DLOPEN(a) LoadLibrary(a)
27#define DLSYM GetProcAddress
28#define DLCLOSE FreeLibrary
29#else
30#define DELIM ':'
31#define HTYPE void*
32#define PREFIX "lib"
33#define DLOPEN(a) dlopen(a, RTLD_LAZY)
34#define DLSYM dlsym
35#define DLCLOSE dlclose
36#endif
37
38namespace hal {
39namespace init {
40void InitializeExtensions() {}
41} // namespace init
42} // namespace hal
43
44static bool& GetShowNotFoundMessage() {
45 static bool showMsg = true;
46 return showMsg;
47}
48
49extern "C" {
50
51int HAL_LoadOneExtension(const char* library) {
52 int rc = 1; // It is expected and reasonable not to find an extra simulation
53 wpi::outs() << "HAL Extensions: Attempting to load: "
54 << wpi::sys::path::stem(library) << "\n";
55 wpi::outs().flush();
56 HTYPE handle = DLOPEN(library);
57#if !defined(WIN32) && !defined(_WIN32)
58 if (!handle) {
59 wpi::SmallString<128> libraryName("lib");
60 libraryName += library;
61#if defined(__APPLE__)
62 libraryName += ".dylib";
63#else
64 libraryName += ".so";
65#endif
66 wpi::outs() << "HAL Extensions: Trying modified name: "
67 << wpi::sys::path::stem(libraryName);
68 wpi::outs().flush();
69 handle = DLOPEN(libraryName.c_str());
70 }
71#endif
72 if (!handle) {
73 wpi::outs() << "HAL Extensions: Failed to load library\n";
74 wpi::outs().flush();
75 return rc;
76 }
77
78 auto init = reinterpret_cast<halsim_extension_init_func_t*>(
79 DLSYM(handle, "HALSIM_InitExtension"));
80
81 if (init) rc = (*init)();
82
83 if (rc != 0) {
84 wpi::outs() << "HAL Extensions: Failed to load extension\n";
85 wpi::outs().flush();
86 DLCLOSE(handle);
87 } else {
88 wpi::outs() << "HAL Extensions: Successfully loaded extension\n";
89 wpi::outs().flush();
90 }
91 return rc;
92}
93
94int HAL_LoadExtensions(void) {
95 int rc = 1;
96 wpi::SmallVector<wpi::StringRef, 2> libraries;
97 const char* e = std::getenv("HALSIM_EXTENSIONS");
98 if (!e) {
99 if (GetShowNotFoundMessage()) {
100 wpi::outs() << "HAL Extensions: No extensions found\n";
101 wpi::outs().flush();
102 }
103 return rc;
104 }
105 wpi::StringRef env{e};
106 env.split(libraries, DELIM, -1, false);
107 for (auto& libref : libraries) {
108 wpi::SmallString<128> library(libref);
109 rc = HAL_LoadOneExtension(library.c_str());
110 if (rc < 0) break;
111 }
112 return rc;
113}
114
115void HAL_SetShowExtensionsNotFoundMessages(HAL_Bool showMessage) {
116 GetShowNotFoundMessage() = showMessage;
117}
118
119} // extern "C"