Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
dcbe7ac
Initial unified binary work
alexanderrichards Mar 4, 2026
626dcca
Fixup
alexanderrichards Apr 21, 2026
56c798e
Adding Diag
alexanderrichards Apr 28, 2026
c74285c
fixup
alexanderrichards Apr 28, 2026
9949b93
Implement the GetPenaltyTerm binary
alexanderrichards May 1, 2026
0de2a2d
adding MACH3_ERR
alexanderrichards May 5, 2026
8435352
allow MACH3_PLUGINS directory
alexanderrichards May 6, 2026
6399a50
fix link time optimisation removing vtable
alexanderrichards May 7, 2026
9248744
update
alexanderrichards May 13, 2026
c8648ec
refactoring
alexanderrichards May 13, 2026
f8e52cb
remane core library
alexanderrichards May 13, 2026
7028897
Fix namespace and shared library install
alexanderrichards May 15, 2026
7c9a741
implement the explicit options flags
alexanderrichards May 18, 2026
353c4a6
fixing the diag app
alexanderrichards May 27, 2026
06fbd7c
Adding tab completion
alexanderrichards Jun 1, 2026
cd4bb7d
Moving api into cli
alexanderrichards Jun 3, 2026
5ddbade
rename core plugins to modules
alexanderrichards Jun 3, 2026
603bbd6
Move core binaries from plugin to module naming convention
alexanderrichards Jun 3, 2026
c110f98
Add specific argparse tag
alexanderrichards Jun 16, 2026
39592fa
moving to upppercase directories
alexanderrichards Jun 16, 2026
84cc8a7
Adding Doxygen comments
alexanderrichards Jun 18, 2026
d8121f8
Pull completions for now
alexanderrichards Jun 19, 2026
c539201
migrate run -> Run as per Kamils suggestion
alexanderrichards Jun 23, 2026
5b97a69
reinstating missing comments
alexanderrichards Jun 23, 2026
24fe017
restore author info
alexanderrichards Jun 25, 2026
d8b72e8
Move Doxygen comments to triple slash format
alexanderrichards Jun 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions CLI/API/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
include(FetchContent)
FetchContent_Declare(
argparse
GIT_REPOSITORY https://github.com/p-ranav/argparse.git
GIT_TAG d924b84eba1f0f0adf38b20b7b4829f6f65b6570
)
FetchContent_MakeAvailable(argparse)
Comment thread
alexanderrichards marked this conversation as resolved.

set(HEADERS
plugin.hpp
argparse.hpp
)


add_library(CLIApi INTERFACE)

target_include_directories(CLIApi INTERFACE ${argparse_SOURCE_DIR}/include)

target_include_directories(CLIApi
INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:include/CLI/API>
)

set_target_properties(CLIApi PROPERTIES
PUBLIC_HEADER "${HEADERS}"
EXPORT_NAME CLIApi)


install(TARGETS CLIApi
EXPORT MaCh3-targets
LIBRARY DESTINATION lib/
PUBLIC_HEADER DESTINATION include/CLI/API)

#install(FILES ${HEADERS} DESTINATION include/api)
add_library(MaCh3::CLIApi ALIAS CLIApi)
49 changes: 49 additions & 0 deletions CLI/API/argparse.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/// @file argparse.hpp
/// @brief MaCh3 wrapper for argparse library with additional functionality

#pragma once
#include <argparse/argparse.hpp>

using argparse::ArgumentParser;

namespace M3 {

/// @class MaCh3ArgumentParser
/// @brief Extended ArgumentParser with MaCh3-specific functionality
///
/// This class extends the standard ArgumentParser to provide additional
/// methods for accessing parser name, subparsers, and tracking which
/// subcommand was used.
class MaCh3ArgumentParser: public ArgumentParser{
public:
using ArgumentParser::ArgumentParser;
virtual ~MaCh3ArgumentParser() = default;

/// @brief Get the name of this parser/subcommand
/// @return The program or subcommand name
const std::string name() const{
return this->m_program_name;
}

/// @brief Get the list of registered subparsers
/// @return Reference to the list of subparsers
const std::list<std::reference_wrapper<ArgumentParser>>& subparsers() const{
return this->m_subparsers;
}

/// @brief Get the subcommand that was used in parsing
///
/// Recursively traverses the subparser hierarchy to find the
/// deepest subcommand that was actually invoked.
///
/// @return Reference to the MaCh3ArgumentParser of the used subcommand
const MaCh3ArgumentParser& get_subcommand_used() const{
for (const std::reference_wrapper<ArgumentParser>& subparser : this->m_subparsers) {
if (this->is_subcommand_used(subparser.get())) {
return static_cast<MaCh3ArgumentParser*>(&(subparser.get()))->get_subcommand_used();
}
}
return (*this);
}
};
};
65 changes: 65 additions & 0 deletions CLI/API/plugin.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/// @file plugin.hpp
/// @brief Plugin interface and registration macros for MaCh3

#pragma once
#include "CLI/API/argparse.hpp"


namespace M3 {

/// @class IPlugin
/// @brief Interface for MaCh3 plugins and modules
///
/// All plugins and modules must implement this interface to provide
/// argument parsing and execution functionality.
class IPlugin {
public:
virtual ~IPlugin() = default;

/// @brief Execute the plugin's main functionality
/// @return Exit code (0 on success, non-zero on error)
virtual int Run() = 0;

/// @brief Get the argument parser for this plugin
/// @return Pointer to the plugin's MaCh3ArgumentParser
virtual MaCh3ArgumentParser* get_parser() = 0;
};

/// @typedef IModule
/// @brief Alias for IPlugin, used for core modules
typedef IPlugin IModule;
};

/// @typedef create_plugin_t
/// @brief Function pointer type for plugin factory function
extern "C" {
typedef M3::IPlugin* (*create_plugin_t)();

/// @typedef destroy_plugin_t
/// @brief Function pointer type for plugin destructor function
typedef void (*destroy_plugin_t)(M3::IPlugin*);
}

/// @def MACH3_REGISTER_PLUGIN
/// @brief Macro to register a plugin class with MaCh3
///
/// This macro generates the required factory and destructor functions
/// for a plugin class. Use it in your plugin implementation file.
///
/// @param PluginClass The plugin class that implements M3::IPlugin
///
/// Example usage:
/// @code
/// class MyPlugin : public M3::IPlugin {
/// // ... implementation
/// };
/// MACH3_REGISTER_PLUGIN(MyPlugin)
/// @endcode
#define MACH3_REGISTER_PLUGIN(PluginClass) \
static_assert(std::is_base_of<M3::IPlugin, PluginClass>::value, "PluginClass must derive from M3::IPlugin"); \
extern "C" M3::IPlugin* create_plugin() { \
return new PluginClass(); \
} \
extern "C" void destroy_plugin(M3::IPlugin* p) { \
delete p; \
}
12 changes: 12 additions & 0 deletions CLI/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
add_subdirectory(API)
add_subdirectory(Modules)


add_executable(mach3
mach3.cpp
MaCh3Program.cpp
)

target_link_libraries(mach3 PRIVATE MaCh3::CLIModules MaCh3::All)

install(TARGETS mach3 DESTINATION bin)
54 changes: 54 additions & 0 deletions CLI/DynamicPlugin.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/// @file DynamicPlugin.hpp
/// @brief Wrapper class for dynamically loaded plugins

#pragma once
#include <dlfcn.h>
#include "CLI/API/plugin.hpp"

namespace M3{
/// @class DynamicPlugin
/// @brief Manages the lifecycle of a dynamically loaded plugin
///
/// This class wraps a plugin loaded from a shared library, maintaining the
/// library handle and providing cleanup functionality.
class DynamicPlugin: public IPlugin{
public:
/// @brief Constructor for a dynamic plugin
/// @param handle Handle to the loaded shared library
/// @param plugin Pointer to the instantiated plugin
/// @param destroy_func Function pointer to destroy the plugin
DynamicPlugin(void* handle,
IPlugin* plugin,
destroy_plugin_t destroy_func):m_handle(handle),
m_plugin(plugin),
m_destroy_func(destroy_func){}

/// @brief Run the plugin's main functionality
/// @return Exit code from the plugin
int Run() {
return m_plugin->Run();
}

/// @brief Get the argument parser for this plugin
/// @return Pointer to the plugin's argument parser
MaCh3ArgumentParser* get_parser(){
return m_plugin->get_parser();
}

/// @brief Destroy the plugin and close the shared library
///
/// Calls the plugin's destroy function and closes the library handle.
void destroy(){
m_destroy_func(m_plugin);
m_plugin = 0;
dlclose(m_handle);
m_handle = 0;
m_destroy_func = 0;
}

private:
void* m_handle; ///< Handle to the loaded shared library
IPlugin* m_plugin; ///< Pointer to the plugin instance
destroy_plugin_t m_destroy_func; ///< Function pointer to destroy the plugin
};
};
Loading
Loading