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 "../Common/CompilerMacrosExport.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 "../Common/Assert.h"
11#include "../Common/Function.h"
12#include "../Common/IGrowableBufferStringPath.h"
13#include "../Common/PlatformMacrosType.h"
14#include "../Common/PrimitiveDefinitions.h"
15#include "Internal/DynamicLibrary.h"
16#include "PluginError.h"
17namespace SC
18{
19SC_DECLARE_ASSERT_PROVIDER(PluginAssert, SC_PLUGIN_LIBRARY_EXPORT);
20
21#define SC_PLUGIN_ASSERT_RELEASE(e) SC_ASSERT_PROVIDER_RELEASE(SC::PluginAssert, e)
22#define SC_PLUGIN_ASSERT_DEBUG(e) SC_ASSERT_PROVIDER_DEBUG(SC::PluginAssert, e)
23#define SC_PLUGIN_TRUST_RESULT(expression) SC_PLUGIN_ASSERT_RELEASE(expression)
24
25struct PluginDefinition;
26struct PluginScanner;
27struct PluginFile;
28struct PluginIdentity;
29struct PluginDynamicLibrary;
30struct PluginCompiler;
31struct PluginCompilerEnvironment;
32struct PluginSysroot;
33struct PluginRegistry;
34template <int N>
35using FixedString = detail::StringNativeFixed<N>;
36using PluginIdentifier = FixedString<64>;
37using PluginBuildOption = FixedString<32>;
38
39template <typename T, size_t N>
41{
42 constexpr size_t size() const { return numValues; }
43 constexpr void clear() { numValues = 0; }
44
45 operator Span<const T>() const { return {values, numValues}; }
46
47 template <typename U>
48 [[nodiscard]] constexpr bool contains(const U& value, size_t* outIndex = nullptr) const
49 {
50 for (size_t idx = 0; idx < numValues; ++idx)
51 {
52 if (values[idx] == value)
53 {
54 if (outIndex)
55 *outIndex = idx;
56 return true;
57 }
58 }
59 return false;
60 }
61
62 [[nodiscard]] constexpr bool isEmpty() const { return numValues == 0; }
63
64 [[nodiscard]] constexpr bool push_back(const T& value)
65 {
66 if (numValues < N)
67 {
68 values[numValues++] = value;
69 return true;
70 }
71 return false;
72 }
73
74 constexpr T* begin() { return values; }
75 constexpr T* end() { return values + numValues; }
76 constexpr T& operator[](size_t idx) { return values[idx]; }
77 constexpr const T* begin() const { return values; }
78 constexpr const T* end() const { return values + numValues; }
79 constexpr const T& operator[](size_t idx) const { return values[idx]; }
80
81 private:
82 T values[N];
83 size_t numValues = 0;
84};
85
90
93
96{
97 StringPath absolutePath;
98};
99
102{
103 PluginIdentifier identifier;
104 FixedString<64> name;
105 FixedString<16> version;
106
110 bool operator==(const PluginIdentity& other) const { return identifier.view() == other.identifier.view(); }
111};
112
115{
117
118 FixedString<256> description;
119 FixedString<64> category;
120 StringPath directory;
121
125
128 PluginFile& getMainPluginFile() { return files[pluginFileIndex]; }
129
132 const PluginFile& getMainPluginFile() const { return files[pluginFileIndex]; }
133
138 [[nodiscard]] static bool find(StringSpan text, StringSpan& extracted);
139
145 [[nodiscard]] static ResultPlugin parse(StringSpan text, PluginDefinition& pluginDefinition, bool& parsed);
146
148 [[nodiscard]] static bool parse(StringSpan text, PluginDefinition& pluginDefinition);
149
153 ResultPlugin getDynamicLibraryAbsolutePath(StringPath& fullDynamicPath) const;
154
158 ResultPlugin getDynamicLibraryPDBAbsolutePath(StringPath& fullDynamicPath) const;
159
160 private:
161 size_t pluginFileIndex = 0;
162 friend struct PluginScanner;
163};
164
167{
174 template <typename T>
175 static ResultPlugin scanDirectory(StringSpan directory, Span<PluginDefinition> definitionsStorage,
176 T& tempFileBuffer, Span<PluginDefinition>& foundDefinitions)
177 {
178 return scanDirectory(directory, definitionsStorage, GrowableBuffer<T>{tempFileBuffer}, foundDefinitions);
179 }
180
181 private:
182 static ResultPlugin scanDirectory(StringSpan directory, Span<PluginDefinition> definitionsStorage,
183 IGrowableBuffer&& tempFileBuffer, Span<PluginDefinition>& foundDefinitions);
184 struct ScannerState;
185};
186
189{
196 ResultPlugin compile(const PluginDefinition& definition, const PluginSysroot& sysroot,
197 const PluginCompilerEnvironment& environment, Span<char>& compilerLog) const;
198
206 ResultPlugin link(const PluginDefinition& definition, const PluginSysroot& sysroot,
207 const PluginCompilerEnvironment& environment, StringSpan executablePath,
208 Span<char>& linkerLog) const;
209
211 enum class Type
212 {
213 ClangCompiler,
214 GnuCompiler,
215 MicrosoftCompiler
216 };
217 Type type = Type::ClangCompiler;
218 StringPath compilerPath;
219 StringPath linkerPath;
220
222
225
231 [[nodiscard]] static ResultPlugin findBestCompiler(PluginCompiler& compiler);
232
233 private:
234 mutable native_char_t buffer[4096];
235
236 ResultPlugin compileFile(const PluginDefinition& definition, const PluginSysroot& sysroot,
237 const PluginCompilerEnvironment& compilerEnvironment, StringSpan sourceFile,
238 StringSpan objectFile, Span<char>& compilerLog) const;
239 struct CompilerFinder;
240};
241
256
259{
260 StringSpan cFlags;
261 StringSpan ldFlags;
262
263 private:
264 struct Internal;
265 friend struct PluginCompiler;
266};
269{
271 SystemDynamicLibrary dynamicLibrary;
273 uint32_t numReloads;
274
275 char errorStorage[1024 * 8] = {};
276 StringSpan lastErrorLog;
277
281 template <typename T>
282 [[nodiscard]] bool queryInterface(T*& outInterface) const
283 {
284 if (pluginQueryInterface and instance != nullptr)
285 {
286 return pluginQueryInterface(instance, T::InterfaceHash, reinterpret_cast<void**>(&outInterface));
287 }
288 return false;
289 }
290
292
293 private:
294 void* instance = nullptr;
295 bool (*pluginInit)(void*& instance) = nullptr;
296 bool (*pluginClose)(void* instance) = nullptr;
297
298 bool (*pluginQueryInterface)(void* instance, uint32_t hash, void** instanceInterface) = nullptr;
299
300 friend struct PluginRegistry;
301 ResultPlugin load(const PluginCompiler& compiler, const PluginSysroot& sysroot, StringSpan executablePath);
302 ResultPlugin unload(bool releaseDebuggerFiles);
303};
304
307{
309 void init(Span<PluginDynamicLibrary> librariesStorage);
310
313
317 ResultPlugin replaceDefinitions(Span<PluginDefinition>&& definitions);
318
320 enum class LoadMode
321 {
322 Load = 0,
323 Reload = 1,
324 };
325
335 ResultPlugin loadPlugin(StringSpan identifier, const PluginCompiler& compiler, const PluginSysroot& sysroot,
336 StringSpan executablePath, LoadMode loadMode = LoadMode::Load);
337
341 ResultPlugin unloadPlugin(StringSpan identifier);
342
346 ResultPlugin removeAllBuildProducts(StringSpan identifier);
347
351 [[nodiscard]] PluginDynamicLibrary* findPlugin(StringSpan identifier);
352
354 [[nodiscard]] size_t getNumberOfEntries() const { return libraries.sizeInElements(); }
355
357 [[nodiscard]] const PluginIdentifier& getIdentifierAt(size_t index) const
358 {
359 return libraries[index].definition.identity.identifier;
360 }
361
363 [[nodiscard]] const PluginDynamicLibrary& getPluginDynamicLibraryAt(size_t index) { return libraries[index]; }
364
369 void getPluginsToReloadBecauseOf(StringSpan relativePath, TimeMs tolerance,
370 Function<void(const PluginIdentifier&)> onPlugin);
371
372 private:
373 ResultPlugin unloadPlugin(StringSpan identifier, bool releaseDebuggerFiles);
374
375 Span<PluginDynamicLibrary> storage;
376 Span<PluginDynamicLibrary> libraries;
377};
378
380} // namespace SC
Definition Plugin.h:41
Reads and holds CFLAGS and LDFLAGS environment variables, mainly to pass down sysroot location.
Definition Plugin.h:259
Compiles a plugin to a dynamic library.
Definition Plugin.h:189
StringPath linkerPath
Path to the linker.
Definition Plugin.h:219
ResultPlugin compile(const PluginDefinition &definition, const PluginSysroot &sysroot, const PluginCompilerEnvironment &environment, Span< char > &compilerLog) const
Compiles a Definition to an object file.
FixedVector< StringPath, 8 > includePaths
Path to include directories used to compile plugin.
Definition Plugin.h:221
static ResultPlugin findBestCompiler(PluginCompiler &compiler)
Look for best compiler on current system.
Type type
Compile Type.
Definition Plugin.h:217
ResultPlugin link(const PluginDefinition &definition, const PluginSysroot &sysroot, const PluginCompilerEnvironment &environment, StringSpan executablePath, Span< char > &linkerLog) const
Links a Definition into a dynamic library, with symbols from executablePath
FixedVector< StringPath, 8 > compilerLibraryPaths
Path to compiler library directories.
Definition Plugin.h:224
Type
Compiler type (clang/gcc/msvc)
Definition Plugin.h:212
FixedVector< StringPath, 8 > compilerIncludePaths
Path to compiler include directories.
Definition Plugin.h:223
StringPath compilerPath
Path to the compiler.
Definition Plugin.h:218
Plugin description, category, dependencies, files and directory location.
Definition Plugin.h:115
StringPath directory
Path to the directory holding the plugin.
Definition Plugin.h:120
FixedVector< PluginFile, 10 > files
Source files that compose this plugin.
Definition Plugin.h:124
static bool find(StringSpan text, StringSpan &extracted)
Extracts the plugin definition (SC_BEGIN_PLUGIN / SC_END_PLUGIN) comment from a .cpp file.
PluginIdentity identity
Uniquely identifier a plugin.
Definition Plugin.h:116
ResultPlugin getDynamicLibraryAbsolutePath(StringPath &fullDynamicPath) const
Gets absolute path of where compiled dynamic library will exist after plugin is compiled.
FixedString< 256 > description
Long description of plugin.
Definition Plugin.h:118
const PluginFile & getMainPluginFile() const
Get main plugin file, holding plugin definition.
Definition Plugin.h:132
FixedVector< PluginIdentifier, 8 > dependencies
Dependencies necessary to load this plugin.
Definition Plugin.h:122
static ResultPlugin parse(StringSpan text, PluginDefinition &pluginDefinition, bool &parsed)
Parses an extracted plugin definition text.
FixedString< 64 > category
Category where plugin belongs to.
Definition Plugin.h:119
static bool parse(StringSpan text, PluginDefinition &pluginDefinition)
Compatibility helper that returns false for either normal absence or a parsing storage failure.
PluginFile & getMainPluginFile()
Get main plugin file, holding plugin definition.
Definition Plugin.h:128
FixedVector< PluginBuildOption, 8 > build
Build options.
Definition Plugin.h:123
ResultPlugin getDynamicLibraryPDBAbsolutePath(StringPath &fullDynamicPath) const
Gets absolute path of where compiled Program Database File will exist after plugin is compiled.
A plugin dynamic library loaded from a SC::PluginRegistry.
Definition Plugin.h:269
SystemDynamicLibrary dynamicLibrary
System handle of plugin's dynamic library.
Definition Plugin.h:271
TimeMs lastLoadTime
Last time when this plugin was last loaded.
Definition Plugin.h:272
StringSpan lastErrorLog
Last error log of compiler / linker (if any)
Definition Plugin.h:276
PluginDefinition definition
Definition of the loaded plugin.
Definition Plugin.h:270
uint32_t numReloads
Number of times that the plugin has been hot-reloaded.
Definition Plugin.h:273
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:282
char errorStorage[1024 *8]
Storage for last error log (below)
Definition Plugin.h:275
Holds path to a given plugin source file.
Definition Plugin.h:96
StringPath absolutePath
Absolute path to a plugin source file.
Definition Plugin.h:97
Represents the unique signature / identity of a Plugin.
Definition Plugin.h:102
bool operator==(const PluginIdentity &other) const
Compares two plugins on Identity::identifier.
Definition Plugin.h:110
PluginIdentifier identifier
Unique string identifying the plugin.
Definition Plugin.h:103
FixedString< 64 > name
Plugin name.
Definition Plugin.h:104
FixedString< 16 > version
Plugin version (x.y.z)
Definition Plugin.h:105
Holds a registry of plugins, loading and compiling them on the fly.
Definition Plugin.h:307
LoadMode
Instructs loadPlugin to Load or Reload the plugin.
Definition Plugin.h:321
PluginDynamicLibrary * findPlugin(StringSpan identifier)
Find a PluginDynamicLibrary in the registry with a given identifier.
void init(Span< PluginDynamicLibrary > librariesStorage)
Init a PluginRegistry with some given storage.
ResultPlugin close()
Unregisters all plugins.
size_t getNumberOfEntries() const
Returns the total number of registry entries (counting both loaded and unloaded plugins)
Definition Plugin.h:354
ResultPlugin replaceDefinitions(Span< PluginDefinition > &&definitions)
Appends the definitions to registry.
void getPluginsToReloadBecauseOf(StringSpan relativePath, TimeMs tolerance, Function< void(const PluginIdentifier &)> onPlugin)
Enumerates all plugins that must be reloaded when relativePath is modified.
ResultPlugin removeAllBuildProducts(StringSpan 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:363
const PluginIdentifier & getIdentifierAt(size_t index) const
Returns the PluginIdentifier corresponding to the index entry of the registry.
Definition Plugin.h:357
ResultPlugin loadPlugin(StringSpan identifier, const PluginCompiler &compiler, const PluginSysroot &sysroot, StringSpan executablePath, LoadMode loadMode=LoadMode::Load)
Loads a plugin with given identifier, compiling it with given PluginCompiler.
ResultPlugin unloadPlugin(StringSpan identifier)
Unloads an already loaded plugin by its identifier.
Scans a directory for PluginDefinition.
Definition Plugin.h:167
static ResultPlugin scanDirectory(StringSpan directory, Span< PluginDefinition > definitionsStorage, T &tempFileBuffer, Span< PluginDefinition > &foundDefinitions)
Scans a directory for PluginDefinition.
Definition Plugin.h:175
Holds include and library paths for a system toolchain, used to let plugins link to libc and libc++.
Definition Plugin.h:244
static ResultPlugin findBestSysroot(PluginCompiler::Type compiler, PluginSysroot &sysroot)
Finds a reasonable sysroot for the given compiler.
FixedVector< StringPath, 8 > includePaths
Path to system include directories.
Definition Plugin.h:245
StringPath isysroot
Path to sysroot include (optional)
Definition Plugin.h:248
FixedVector< StringPath, 8 > libraryPaths
Path to system library directories.
Definition Plugin.h:246
Plugin result retaining a stable operation detail and one scalar diagnostic context.
Definition PluginError.h:151