groundwork for standalone elfs of modules for debugging purposes

master
Chris Punches 2025-03-09 19:02:39 -04:00
parent df041574ae
commit e28afc2d77
9 changed files with 606 additions and 19 deletions

View File

@ -3,8 +3,10 @@ project(dpm)
set(CMAKE_CXX_STANDARD 20)
# Create modules directory
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/modules)
# Set binary output directories
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/modules)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
# Main DPM executable
add_executable(
@ -28,10 +30,13 @@ target_link_libraries(dpm dl)
target_link_options(dpm PRIVATE -rdynamic)
# Add the info module by including its CMakeLists.txt
add_subdirectory(modules/info)
add_subdirectory(modules/info ${CMAKE_BINARY_DIR}/build-modules/info)
# add the build module by including that
add_subdirectory(modules/build ${CMAKE_BINARY_DIR}/build-modules/build)
# Create a custom target for building all modules
add_custom_target(modules DEPENDS info)
add_custom_target(modules DEPENDS info build)
# Installation rules
install(TARGETS dpm DESTINATION bin)
@ -45,7 +50,7 @@ install(
# Install modules
install(
DIRECTORY ${CMAKE_BINARY_DIR}/modules/
DIRECTORY ${CMAKE_BINARY_DIR}/bin/modules/
DESTINATION /usr/lib/dpm/modules
FILES_MATCHING PATTERN "*.so"
)

View File

@ -29,6 +29,9 @@
#pragma once
#include <iostream>
#include <string>
/**
* @brief Fatal log level constant
*
@ -134,4 +137,53 @@ extern "C" {
*
* Defines the version string for the DPM core system.
*/
#define DPM_VERSION "0.1.0"
#define DPM_VERSION "0.1.0"
// If we're building in standalone mode, add support for standalone execution
#ifdef BUILD_STANDALONE
// Declare, but don't define the standalone implementations
// These will be defined in the main file through the DPM_STANDALONE_IMPL macro
/**
* @brief Helper macro to create a standalone main function for modules
*
* This macro defines a main() function that initializes the module and
* processes command-line arguments to execute commands directly.
*/
#define DPM_MODULE_STANDALONE_MAIN() \
extern "C" void dpm_log(int level, const char* message) { \
const char* level_str; \
switch (level) { \
case 0: level_str = "FATAL"; break; \
case 1: level_str = "ERROR"; break; \
case 2: level_str = "WARN"; break; \
case 3: level_str = "INFO"; break; \
case 4: level_str = "DEBUG"; break; \
default: level_str = "UNKNOWN"; break; \
} \
std::cout << "[" << level_str << "] " << message << std::endl; \
} \
extern "C" const char* dpm_get_config(const char* section, const char* key) { \
return nullptr; \
} \
int main(int argc, char** argv) { \
std::cout << "Module version: " << dpm_module_get_version() << std::endl; \
std::cout << "Description: " << dpm_get_description() << std::endl; \
\
/* Default to "help" if no command is provided */ \
const char* command = "help"; \
\
/* If arguments are provided, use the first as command */ \
if (argc > 1) { \
command = argv[1]; \
/* Shift the argument array for the command handler */ \
argv++; \
argc--; \
} \
\
std::cout << "Executing command: " << command << std::endl; \
return dpm_module_execute(command, argc - 1, argv + 1); \
}
#endif // BUILD_STANDALONE

View File

@ -29,9 +29,4 @@
* mailing list at: https://lists.darkhorselinux.org/mailman/listinfo/dhlp-contributors
*/
#include "module.hpp"
/**
* @note The implementation of dpm_get_config and dpm_log are provided by the DPM core.
* Each module must implement dpm_module_execute, dpm_module_get_version, and dpm_get_description.
*/
#include "CommonModuleAPI.hpp"

View File

@ -0,0 +1,57 @@
cmake_minimum_required(VERSION 3.22)
project(build_module)
set(CMAKE_CXX_STANDARD 20)
# Set DPM_ROOT_DIR based on whether this is a standalone build or part of the main build
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
set(DPM_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../..")
else()
set(DPM_ROOT_DIR "${CMAKE_SOURCE_DIR}")
endif()
# Module version - used by DPM
add_library(build MODULE
build.cpp
src/buildFuncs.cpp
)
# Set output properties
set_target_properties(
build PROPERTIES
PREFIX ""
SUFFIX ".so"
)
# Include directories
target_include_directories(build PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
${DPM_ROOT_DIR}
)
# Link with filesystem library
target_link_libraries(build stdc++fs)
# Standalone version - used for debugging
add_executable(build_standalone
build.cpp
src/buildFuncs.cpp
)
# Define the BUILD_STANDALONE macro for the standalone build
target_compile_definitions(build_standalone PRIVATE BUILD_STANDALONE)
# Include directories for standalone
target_include_directories(build_standalone PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
${DPM_ROOT_DIR}
)
# Link with filesystem library for standalone
target_link_libraries(build_standalone stdc++fs)
# Set the output name for the standalone executable
set_target_properties(
build_standalone PROPERTIES
OUTPUT_NAME "build_debug"
)

102
modules/build/build.cpp Normal file
View File

@ -0,0 +1,102 @@
/**
* @file build.cpp
* @brief DPM build module implementation
*
* Implements a DPM module that creates DPM packages according to specification.
* This module handles the package creation process.
*
* @copyright Copyright (c) 2025 SILO GROUP LLC
* @author Chris Punches <chris.punches@silogroup.org>
*
* Part of the Dark Horse Linux Package Manager (DPM)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* For bug reports or contributions, please contact the dhlp-contributors
* mailing list at: https://lists.darkhorselinux.org/mailman/listinfo/dhlp-contributors
*/
#include <string>
#include <cstring>
#include <vector>
#include <iostream>
#include "include/buildFuncs.hpp"
/**
* @def MODULE_VERSION
* @brief Version information for the build module
*
* Defines the version string that will be returned by dpm_module_get_version()
*/
#define MODULE_VERSION "0.1.0"
/**
* @brief Returns the module version string
*
* Required implementation of the DPM module interface that provides
* version information for the build module.
*
* @return Const char pointer to the module version string
*/
extern "C" const char* dpm_module_get_version(void) {
return MODULE_VERSION;
}
/**
* @brief Returns the module description string
*
* Required implementation of the DPM module interface that provides
* a human-readable description of the build module and its functionality.
*
* @return Const char pointer to the module description string
*/
extern "C" const char* dpm_get_description(void) {
return "DPM Build Module - Creates DPM packages according to specification";
}
/**
* @brief Main entry point for the build module
*
* Required implementation of the DPM module interface that serves as the
* primary execution point for the module. Parses the command and routes
* execution to the appropriate handler function.
*
* @param command The command string to execute
* @param argc Number of arguments
* @param argv Array of argument strings
* @return 0 on success, non-zero on failure
*/
extern "C" int dpm_module_execute(const char* command, int argc, char** argv) {
// Parse the command
Command cmd = parse_command(command);
// Route to the appropriate command handler
switch (cmd) {
case CMD_CREATE:
return cmd_create(argc, argv);
case CMD_HELP:
return cmd_help(argc, argv);
case CMD_UNKNOWN:
default:
return cmd_unknown(command, argc, argv);
}
}
// If we're building in standalone mode, include the main function
#ifdef BUILD_STANDALONE
DPM_MODULE_STANDALONE_MAIN()
#endif // BUILD_STANDALONE

View File

@ -0,0 +1,122 @@
/**
* @file buildFuncs.hpp
* @brief Header file for the build module support functions
*
* Defines functions and enumerations for the build module which creates
* DPM packages according to specification.
*
* @copyright Copyright (c) 2025 SILO GROUP LLC
* @author Chris Punches <chris.punches@silogroup.org>
*
* Part of the Dark Horse Linux Package Manager (DPM)
*/
#pragma once
#include <string>
#include <cstring>
#include <vector>
#include <getopt.h>
#include <dpmdk/include/CommonModuleAPI.hpp>
/**
* @enum Command
* @brief Enumeration of supported commands for the build module
*/
enum Command {
CMD_UNKNOWN, /**< Unknown or unsupported command */
CMD_HELP, /**< Display help information */
CMD_CREATE /**< Create a new DPM package */
};
/**
* @struct BuildOptions
* @brief Structure to store parsed command-line options for the build module
*/
struct BuildOptions {
std::string output_dir; /**< Directory where to save the built package */
std::string contents_dir; /**< Directory with package contents */
std::string metadata_dir; /**< Directory with package metadata */
std::string hooks_dir; /**< Directory with package hooks */
std::string package_name; /**< Name of the package to build */
std::string signature_key; /**< Path to the GPG key for signing the package */
bool force; /**< Flag to force package creation even if warnings occur */
bool verbose; /**< Flag for verbose output */
// Constructor with default values
BuildOptions() :
output_dir("."),
contents_dir(""),
metadata_dir(""),
hooks_dir(""),
package_name(""),
signature_key(""),
force(false),
verbose(false) {}
};
/**
* @brief Handler for the help command
*
* Displays information about available commands in the build module.
*
* @param argc Number of arguments
* @param argv Array of arguments
* @return 0 on success, non-zero on failure
*/
int cmd_help(int argc, char** argv);
/**
* @brief Handler for the create command
*
* Processes arguments and creates a DPM package.
*
* @param argc Number of arguments
* @param argv Array of arguments
* @return 0 on success, non-zero on failure
*/
int cmd_create(int argc, char** argv);
/**
* @brief Handler for unknown commands
*
* Displays an error message for unrecognized commands.
*
* @param command The unrecognized command string
* @param argc Number of arguments
* @param argv Array of arguments
* @return 1 to indicate failure
*/
int cmd_unknown(const char* command, int argc, char** argv);
/**
* @brief Parses a command string into a Command enum value
*
* Converts a command string to the appropriate Command enum value
* for internal routing.
*
* @param cmd_str The command string to parse
* @return The corresponding Command enum value
*/
Command parse_command(const char* cmd_str);
/**
* @brief Parses command-line arguments for the create command
*
* Processes command-line arguments and populates a BuildOptions structure.
*
* @param argc Number of arguments
* @param argv Array of arguments
* @param options Reference to BuildOptions structure to populate
* @return 0 on success, non-zero on failure
*/
int parse_create_options(int argc, char** argv, BuildOptions& options);
/**
* @brief Validates the build options
*
* Ensures that all required options are provided and valid.
*
* @param options The BuildOptions structure to validate
* @return 0 if options are valid, non-zero otherwise
*/
int validate_build_options(const BuildOptions& options);

View File

@ -0,0 +1,234 @@
/**
* @file buildFuncs.cpp
* @brief Implementation of the build module support functions
*
* Implements functions for the build module that create DPM packages
* according to the specification.
*
* @copyright Copyright (c) 2025 SILO GROUP LLC
* @author Chris Punches <chris.punches@silogroup.org>
*
* Part of the Dark Horse Linux Package Manager (DPM)
*/
#include "buildFuncs.hpp"
#include <iostream>
#include <filesystem>
/**
* @brief Handler for the help command
*/
int cmd_help(int argc, char** argv) {
dpm_log(LOG_INFO, "DPM Build Module - Creates DPM packages according to specification");
dpm_log(LOG_INFO, "Available commands:");
dpm_log(LOG_INFO, " create - Create a new DPM package");
dpm_log(LOG_INFO, " help - Display this help message");
dpm_log(LOG_INFO, "");
dpm_log(LOG_INFO, "Usage: dpm build create [options]");
dpm_log(LOG_INFO, "Options:");
dpm_log(LOG_INFO, " -o, --output-dir DIR Directory to save the built package (default: current directory)");
dpm_log(LOG_INFO, " -c, --contents DIR Directory with package contents (required)");
dpm_log(LOG_INFO, " -m, --metadata DIR Directory with package metadata (required)");
dpm_log(LOG_INFO, " -H, --hooks DIR Directory with package hooks (optional)");
dpm_log(LOG_INFO, " -n, --name NAME Package name (required if not in metadata)");
dpm_log(LOG_INFO, " -s, --sign KEY Path to GPG key for signing the package (optional)");
dpm_log(LOG_INFO, " -f, --force Force package creation even if warnings occur");
dpm_log(LOG_INFO, " -v, --verbose Enable verbose output");
dpm_log(LOG_INFO, " -h, --help Display this help message");
return 0;
}
/**
* @brief Handler for unknown commands
*/
int cmd_unknown(const char* command, int argc, char** argv) {
std::string msg = "Unknown command: ";
msg += (command ? command : "");
dpm_log(LOG_WARN, msg.c_str());
dpm_log(LOG_WARN, "Run 'dpm build help' for a list of available commands");
return 1;
}
/**
* @brief Parses a command string to Command enum
*/
Command parse_command(const char* cmd_str) {
if (cmd_str == nullptr || strlen(cmd_str) == 0) {
return CMD_HELP;
}
if (strcmp(cmd_str, "help") == 0) {
return CMD_HELP;
}
else if (strcmp(cmd_str, "create") == 0) {
return CMD_CREATE;
}
return CMD_UNKNOWN;
}
/**
* @brief Handler for the create command
*/
int cmd_create(int argc, char** argv) {
BuildOptions options;
// Parse command-line options
int parse_result = parse_create_options(argc, argv, options);
if (parse_result != 0) {
return parse_result;
}
// Validate options
int validate_result = validate_build_options(options);
if (validate_result != 0) {
return validate_result;
}
// Log the operation
if (options.verbose) {
dpm_log(LOG_INFO, "Creating DPM package with the following options:");
dpm_log(LOG_INFO, (" Output directory: " + options.output_dir).c_str());
dpm_log(LOG_INFO, (" Contents directory: " + options.contents_dir).c_str());
dpm_log(LOG_INFO, (" Metadata directory: " + options.metadata_dir).c_str());
if (!options.hooks_dir.empty()) {
dpm_log(LOG_INFO, (" Hooks directory: " + options.hooks_dir).c_str());
}
if (!options.package_name.empty()) {
dpm_log(LOG_INFO, (" Package name: " + options.package_name).c_str());
}
if (!options.signature_key.empty()) {
dpm_log(LOG_INFO, (" Signature key: " + options.signature_key).c_str());
}
if (options.force) {
dpm_log(LOG_INFO, " Force: Yes");
}
}
// For now, just log that we would create the package
dpm_log(LOG_INFO, "Package creation functionality not yet implemented");
dpm_log(LOG_INFO, "Would create package using the provided options");
return 0;
}
/**
* @brief Parses command-line arguments for the create command
*/
int parse_create_options(int argc, char** argv, BuildOptions& options) {
static struct option long_options[] = {
{"output-dir", required_argument, 0, 'o'},
{"contents", required_argument, 0, 'c'},
{"metadata", required_argument, 0, 'm'},
{"hooks", required_argument, 0, 'H'},
{"name", required_argument, 0, 'n'},
{"sign", required_argument, 0, 's'},
{"force", no_argument, 0, 'f'},
{"verbose", no_argument, 0, 'v'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
};
// Skip program name and module name
int adjusted_argc = argc;
char** adjusted_argv = argv;
// Reset getopt
optind = 0;
opterr = 1;
int opt;
int option_index = 0;
while ((opt = getopt_long(adjusted_argc, adjusted_argv, "o:c:m:H:n:s:fvh", long_options, &option_index)) != -1) {
switch (opt) {
case 'o':
options.output_dir = optarg;
break;
case 'c':
options.contents_dir = optarg;
break;
case 'm':
options.metadata_dir = optarg;
break;
case 'H':
options.hooks_dir = optarg;
break;
case 'n':
options.package_name = optarg;
break;
case 's':
options.signature_key = optarg;
break;
case 'f':
options.force = true;
break;
case 'v':
options.verbose = true;
break;
case 'h':
cmd_help(0, nullptr);
return 1;
case '?':
// Error message is printed by getopt
dpm_log(LOG_ERROR, "Run 'dpm build create --help' for usage information");
return 1;
default:
dpm_log(LOG_ERROR, "Unknown option");
return 1;
}
}
return 0;
}
/**
* @brief Validates the build options
*/
int validate_build_options(const BuildOptions& options) {
// Check if contents directory is provided and exists
if (options.contents_dir.empty()) {
dpm_log(LOG_ERROR, "Contents directory is required (--contents)");
return 1;
}
if (!std::filesystem::exists(options.contents_dir)) {
dpm_log(LOG_ERROR, ("Contents directory does not exist: " + options.contents_dir).c_str());
return 1;
}
// Check if metadata directory is provided and exists
if (options.metadata_dir.empty()) {
dpm_log(LOG_ERROR, "Metadata directory is required (--metadata)");
return 1;
}
if (!std::filesystem::exists(options.metadata_dir)) {
dpm_log(LOG_ERROR, ("Metadata directory does not exist: " + options.metadata_dir).c_str());
return 1;
}
// Check if hooks directory exists if provided
if (!options.hooks_dir.empty() && !std::filesystem::exists(options.hooks_dir)) {
dpm_log(LOG_ERROR, ("Hooks directory does not exist: " + options.hooks_dir).c_str());
return 1;
}
// Check if output directory exists
if (!std::filesystem::exists(options.output_dir)) {
dpm_log(LOG_ERROR, ("Output directory does not exist: " + options.output_dir).c_str());
return 1;
}
// Check if signature key exists if provided
if (!options.signature_key.empty() && !std::filesystem::exists(options.signature_key)) {
dpm_log(LOG_ERROR, ("Signature key file does not exist: " + options.signature_key).c_str());
return 1;
}
return 0;
}

View File

@ -3,18 +3,13 @@ project(info_module)
set(CMAKE_CXX_STANDARD 20)
# Set output directory for standalone builds
# Set DPM_ROOT_DIR based on whether this is a standalone build or part of the main build
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
set(MODULE_OUTPUT_DIR "${CMAKE_BINARY_DIR}/modules")
set(DPM_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../..")
else()
set(MODULE_OUTPUT_DIR "${CMAKE_BINARY_DIR}/modules")
set(DPM_ROOT_DIR "${CMAKE_SOURCE_DIR}")
endif()
# Create output directory
file(MAKE_DIRECTORY ${MODULE_OUTPUT_DIR})
# Create shared library
add_library(info MODULE
info.cpp
@ -26,11 +21,31 @@ set_target_properties(
info PROPERTIES
PREFIX ""
SUFFIX ".so"
LIBRARY_OUTPUT_DIRECTORY "${MODULE_OUTPUT_DIR}"
)
# Include directories
target_include_directories(info PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
${DPM_ROOT_DIR}
)
# Standalone version - used for debugging
add_executable(info_standalone
info.cpp
src/infoFuncs.cpp
)
# Define the BUILD_STANDALONE macro for the standalone build
target_compile_definitions(info_standalone PRIVATE BUILD_STANDALONE)
# Include directories for standalone
target_include_directories(info_standalone PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
${DPM_ROOT_DIR}
)
# Set the output name for the standalone executable
set_target_properties(
info_standalone PROPERTIES
OUTPUT_NAME "info_debug"
)

View File

@ -108,3 +108,8 @@ extern "C" int dpm_module_execute(const char* command, int argc, char** argv) {
return cmd_unknown(command, argc, argv);
}
}
// If we're building in standalone mode, include the main function
#ifdef BUILD_STANDALONE
DPM_MODULE_STANDALONE_MAIN()
#endif // BUILD_STANDALONE