Sane C++ Libraries
C++ Platform Abstraction Libraries
Loading...
Searching...
No Matches
Plugin.h
1// Copyright (c) Stefano Cristiano
2// SPDX-License-Identifier: MIT
3#pragma once
4#include "../Foundation/Compiler.h"
5#ifndef SC_EXPORT_LIBRARY_PLUGIN
6#define SC_EXPORT_LIBRARY_PLUGIN 0
7#endif
8#define SC_PLUGIN_LIBRARY_EXPORT SC_COMPILER_LIBRARY_EXPORT(SC_EXPORT_LIBRARY_PLUGIN)
9
10#include "../Foundation/Function.h"
11#include "../Foundation/Platform.h"
12#include "../Foundation/PrimitiveTypes.h"
13#include "../Foundation/StringPath.h"
14#include "Internal/DynamicLibrary.h"
15namespace SC
16{
17
18struct PluginDefinition;
19struct PluginScanner;
20struct PluginFile;
21struct PluginIdentity;
22struct PluginDynamicLibrary;
23struct PluginCompiler;
24struct PluginCompilerEnvironment;
25struct PluginSysroot;
26struct PluginRegistry;
27template <int N>
28using FixedString = detail::StringNativeFixed<N>;
29using PluginIdentifier = FixedString<64>;
30using PluginBuildOption = FixedString<32>;
31
32template <typename T, size_t N>
34{
35 constexpr size_t size() const { return numValues; }
36 constexpr void clear() { numValues = 0; }
37
38 operator Span<const T>() const { return {values, numValues}; }
39
40 template <typename U>
41 [[nodiscard]] constexpr bool contains(const U& value, size_t* outIndex = nullptr) const
42 {
43 for (size_t idx = 0; idx < numValues; ++idx)
44 {
45 if (values[idx] == value)
46 {
47 if (outIndex)
48 *outIndex = idx;
49 return true;
50 }
51 }
52 return false;
53 }
54
55 [[nodiscard]] constexpr bool isEmpty() const { return numValues == 0; }
56
57 [[nodiscard]] constexpr bool push_back(const T& value)
58 {
59 if (numValues < N)
60 {
61 values[numValues++] = value;
62 return true;
63 }
64 return false;
65 }
66
67 constexpr T* begin() { return values; }
68 constexpr T* end() { return values + numValues; }
69 constexpr T& operator[](size_t idx) { return values[idx]; }
70 constexpr const T* begin() const { return values; }
71 constexpr const T* end() const { return values + numValues; }
72 constexpr const T& operator[](size_t idx) const { return values[idx]; }
73
74 private:
75 T values[N];
76 size_t numValues = 0;
77};
78
83
86
92
95{
96 PluginIdentifier identifier;
97 FixedString<64> name;
98 FixedString<16> version;
99
103 bool operator==(const PluginIdentity& other) const { return identifier.view() == other.identifier.view(); }
104};
105
108{
110
111 FixedString<256> description;
112 FixedString<64> category;
114
118
121 PluginFile& getMainPluginFile() { return files[pluginFileIndex]; }
122
125 const PluginFile& getMainPluginFile() const { return files[pluginFileIndex]; }
126
131 [[nodiscard]] static bool find(const StringView text, StringView& extracted);
132
137 [[nodiscard]] static bool parse(StringView text, PluginDefinition& pluginDefinition);
138
143
148
149 private:
150 [[nodiscard]] static bool parseLine(StringIteratorASCII& iterator, StringView& key, StringView& value);
151
152 size_t pluginFileIndex = 0;
153 friend struct PluginScanner;
154};
155
158{
165 template <typename T>
166 static Result scanDirectory(const StringView directory, Span<PluginDefinition> definitionsStorage,
167 T& tempFileBuffer, Span<PluginDefinition>& foundDefinitions)
168 {
169 return scanDirectory(directory, definitionsStorage, GrowableBuffer<T>{tempFileBuffer}, foundDefinitions);
170 }
171
172 private:
173 static Result scanDirectory(const StringView directory, Span<PluginDefinition> definitionsStorage,
174 IGrowableBuffer&& tempFileBuffer, Span<PluginDefinition>& foundDefinitions);
175 struct ScannerState;
176};
177
180{
187 Result compile(const PluginDefinition& definition, const PluginSysroot& sysroot,
188 const PluginCompilerEnvironment& environment, Span<char>& compilerLog) const;
189
197 Result link(const PluginDefinition& definition, const PluginSysroot& sysroot,
198 const PluginCompilerEnvironment& environment, StringView executablePath, Span<char>& linkerLog) const;
199
201 enum class Type
202 {
203 ClangCompiler,
204 GnuCompiler,
205 MicrosoftCompiler
206 };
207 Type type = Type::ClangCompiler;
210
212
215
219 [[nodiscard]] static Result findBestCompiler(PluginCompiler& compiler);
220
221 private:
222 mutable native_char_t buffer[4096];
223
224 Result compileFile(const PluginDefinition& definition, const PluginSysroot& sysroot,
225 const PluginCompilerEnvironment& compilerEnvironment, StringView sourceFile,
226 StringView objectFile, Span<char>& compilerLog) const;
227 struct CompilerFinder;
228};
229
244
247{
248 StringView cFlags;
249 StringView ldFlags;
250
251 private:
252 struct Internal;
253 friend struct PluginCompiler;
254};
257{
259 SystemDynamicLibrary dynamicLibrary;
262
263 char errorStorage[1024 * 8] = {};
265
269 template <typename T>
270 [[nodiscard]] bool queryInterface(T*& outInterface) const
271 {
272 if (pluginQueryInterface and instance != nullptr)
273 {
274 return pluginQueryInterface(instance, T::InterfaceHash, reinterpret_cast<void**>(&outInterface));
275 }
276 return false;
277 }
278
280
281 private:
282 void* instance = nullptr;
283 bool (*pluginInit)(void*& instance) = nullptr;
284 bool (*pluginClose)(void* instance) = nullptr;
285
286 bool (*pluginQueryInterface)(void* instance, uint32_t hash, void** instanceInterface) = nullptr;
287
288 friend struct PluginRegistry;
289 Result load(const PluginCompiler& compiler, const PluginSysroot& sysroot, StringView executablePath);
290 Result unload();
291};
292
295{
297 void init(Span<PluginDynamicLibrary> librariesStorage);
298
301
306
308 enum class LoadMode
309 {
310 Load = 0,
311 Reload = 1,
312 };
313
321 Result loadPlugin(const StringView identifier, const PluginCompiler& compiler, const PluginSysroot& sysroot,
322 StringView executablePath, LoadMode loadMode = LoadMode::Load);
323
327 Result unloadPlugin(const StringView identifier);
328
333
337 [[nodiscard]] PluginDynamicLibrary* findPlugin(const StringView identifier);
338
340 [[nodiscard]] size_t getNumberOfEntries() const { return libraries.sizeInElements(); }
341
343 [[nodiscard]] const PluginIdentifier& getIdentifierAt(size_t index) const
344 {
345 return libraries[index].definition.identity.identifier;
346 }
347
349 [[nodiscard]] const PluginDynamicLibrary& getPluginDynamicLibraryAt(size_t index) { return libraries[index]; }
350
355 void getPluginsToReloadBecauseOf(StringView relativePath, TimeMs tolerance,
356 Function<void(const PluginIdentifier&)> onPlugin);
357
358 private:
361};
362
364} // namespace SC
struct SC_FOUNDATION_EXPORT Function
Wraps function pointers, member functions and lambdas without ever allocating.
Definition Function.h:19
unsigned int uint32_t
Platform independent (4) bytes unsigned int.
Definition PrimitiveTypes.h:29
char native_char_t
The native char for the platform (wchar_t (4 bytes) on Windows, char (1 byte) everywhere else )
Definition PrimitiveTypes.h:25
Definition Plugin.h:34
Reads and holds CFLAGS and LDFLAGS environment variables, mainly to pass down sysroot location.
Definition Plugin.h:247
Compiles a plugin to a dynamic library.
Definition Plugin.h:180
StringPath linkerPath
Path to the linker.
Definition Plugin.h:209
Result link(const PluginDefinition &definition, const PluginSysroot &sysroot, const PluginCompilerEnvironment &environment, StringView executablePath, Span< char > &linkerLog) const
Links a Definition into a dynamic library, with symbols from executablePath
FixedVector< StringPath, 8 > includePaths
Path to include directories used to compile plugin.
Definition Plugin.h:211
Type type
Compile Type.
Definition Plugin.h:207
FixedVector< StringPath, 8 > compilerLibraryPaths
Path to compiler library directories.
Definition Plugin.h:214
Type
Compiler type (clang/gcc/msvc)
Definition Plugin.h:202
static Result findBestCompiler(PluginCompiler &compiler)
Look for best compiler on current system.
FixedVector< StringPath, 8 > compilerIncludePaths
Path to compiler include directories.
Definition Plugin.h:213
Result compile(const PluginDefinition &definition, const PluginSysroot &sysroot, const PluginCompilerEnvironment &environment, Span< char > &compilerLog) const
Compiles a Definition to an object file.
StringPath compilerPath
Path to the compiler.
Definition Plugin.h:208
Plugin description, category, dependencies, files and directory location.
Definition Plugin.h:108
StringPath directory
Path to the directory holding the plugin.
Definition Plugin.h:113
FixedVector< PluginFile, 10 > files
Source files that compose this plugin.
Definition Plugin.h:117
PluginIdentity identity
Uniquely identifier a plugin.
Definition Plugin.h:109
static bool find(const StringView text, StringView &extracted)
Extracts the plugin definition (SC_BEGIN_PLUGIN / SC_END_PLUGIN) comment from a .cpp file.
FixedString< 256 > description
Long description of plugin.
Definition Plugin.h:111
const PluginFile & getMainPluginFile() const
Get main plugin file, holding plugin definition.
Definition Plugin.h:125
FixedVector< PluginIdentifier, 8 > dependencies
Dependencies necessary to load this plugin.
Definition Plugin.h:115
static bool parse(StringView text, PluginDefinition &pluginDefinition)
Parses an extracted plugin definition text.
Result getDynamicLibraryAbsolutePath(StringPath &fullDynamicPath) const
Gets absolute path of where compiled dynamic library will exist after plugin is compiled.
FixedString< 64 > category
Category where plugin belongs to.
Definition Plugin.h:112
Result getDynamicLibraryPDBAbsolutePath(StringPath &fullDynamicPath) const
Gets absolute path of where compiled Program Database File will exist after plugin is compiled.
PluginFile & getMainPluginFile()
Get main plugin file, holding plugin definition.
Definition Plugin.h:121
FixedVector< PluginBuildOption, 8 > build
Build options.
Definition Plugin.h:116
A plugin dynamic library loaded from a SC::PluginRegistry.
Definition Plugin.h:257
SystemDynamicLibrary dynamicLibrary
System handle of plugin's dynamic library.
Definition Plugin.h:259
TimeMs lastLoadTime
Last time when this plugin was last loaded.
Definition Plugin.h:260
PluginDefinition definition
Definition of the loaded plugin.
Definition Plugin.h:258
StringView lastErrorLog
Last error log of compiler / linker (if any)
Definition Plugin.h:264
uint32_t numReloads
Number of times that the plugin has been hot-reloaded.
Definition Plugin.h:261
bool queryInterface(T *&outInterface) const
Try to obtain a given interface as exported by a plugin through SC_PLUGIN_EXPORT_INTERFACES macro.
Definition Plugin.h:270
char errorStorage[1024 *8]
Storage for last error log (below)
Definition Plugin.h:263
Holds path to a given plugin source file.
Definition Plugin.h:89
StringPath absolutePath
Absolute path to a plugin source file.
Definition Plugin.h:90
Represents the unique signature / identity of a Plugin.
Definition Plugin.h:95
bool operator==(const PluginIdentity &other) const
Compares two plugins on Identity::identifier.
Definition Plugin.h:103
PluginIdentifier identifier
Unique string identifying the plugin.
Definition Plugin.h:96
FixedString< 64 > name
Plugin name.
Definition Plugin.h:97
FixedString< 16 > version
Plugin version (x.y.z)
Definition Plugin.h:98
Holds a registry of plugins, loading and compiling them on the fly.
Definition Plugin.h:295
void getPluginsToReloadBecauseOf(StringView relativePath, TimeMs tolerance, Function< void(const PluginIdentifier &)> onPlugin)
Enumerates all plugins that must be reloaded when relativePath is modified.
LoadMode
Instructs loadPlugin to Load or Reload the plugin.
Definition Plugin.h:309
void init(Span< PluginDynamicLibrary > librariesStorage)
Init a PluginRegistry with some given storage.
Result unloadPlugin(const StringView identifier)
Unloads an already loaded plugin by its identifier.
Result loadPlugin(const StringView identifier, const PluginCompiler &compiler, const PluginSysroot &sysroot, StringView executablePath, LoadMode loadMode=LoadMode::Load)
Loads a plugin with given identifier, compiling it with given PluginCompiler.
size_t getNumberOfEntries() const
Returns the total number of registry entries (counting both loaded and unloaded plugins)
Definition Plugin.h:340
Result removeAllBuildProducts(const StringView identifier)
Removes all temporary build products of the Plugin with given identifier.
const PluginDynamicLibrary & getPluginDynamicLibraryAt(size_t index)
Returns the PluginIdentifier corresponding to the index entry of the registry.
Definition Plugin.h:349
Result close()
Unregisters all plugins.
const PluginIdentifier & getIdentifierAt(size_t index) const
Returns the PluginIdentifier corresponding to the index entry of the registry.
Definition Plugin.h:343
Result replaceDefinitions(Span< PluginDefinition > &&definitions)
Appends the definitions to registry.
PluginDynamicLibrary * findPlugin(const StringView identifier)
Find a PluginDynamicLibrary in the registry with a given identifier.
Scans a directory for PluginDefinition.
Definition Plugin.h:158
static Result scanDirectory(const StringView directory, Span< PluginDefinition > definitionsStorage, T &tempFileBuffer, Span< PluginDefinition > &foundDefinitions)
Scans a directory for PluginDefinition.
Definition Plugin.h:166
Holds include and library paths for a system toolchain, used to let plugins link to libc and libc++.
Definition Plugin.h:232
FixedVector< StringPath, 8 > includePaths
Path to system include directories.
Definition Plugin.h:233
StringPath isysroot
Path to sysroot include (optional)
Definition Plugin.h:236
static Result findBestSysroot(PluginCompiler::Type compiler, PluginSysroot &sysroot)
Finds a reasonable sysroot for the given compiler.
FixedVector< StringPath, 8 > libraryPaths
Path to system library directories.
Definition Plugin.h:234
An ascii string used as boolean result. SC_TRY macro forwards errors to caller.
Definition Result.h:13
View over a contiguous sequence of items (pointer + size in elements).
Definition Span.h:29
A string iterator for ASCII strings.
Definition StringIterator.h:240
Pre-sized char array holding enough space to represent a file system path.
Definition StringPath.h:42
Non-owning view over a range of characters with UTF Encoding.
Definition StringView.h:47
A vocabulary type representing a time interval in milliseconds since epoch.
Definition PrimitiveTypes.h:50