Refactor project structure: remove MyModule, implement ConfigManager, and enhance CMake/Makefile for multiple build types

This commit is contained in:
whaffman 2025-09-11 12:36:31 +02:00
parent 0d4bbe53b0
commit f7bc063227
12 changed files with 477 additions and 94 deletions

69
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,69 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug webserv",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/webserv",
"args": ["${workspaceFolder}/config/default.conf"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "Build Debug",
"miDebuggerPath": "/usr/bin/gdb",
"internalConsoleOptions": "openOnSessionStart"
},
{
"name": "Debug webserv (ASAN)",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/webserv",
"args": ["${workspaceFolder}/config/default.conf"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{
"name": "ASAN_OPTIONS",
"value": "abort_on_error=1:detect_leaks=1:check_initialization_order=1"
}
],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "Build ASAN",
"miDebuggerPath": "/usr/bin/gdb",
"internalConsoleOptions": "openOnSessionStart"
},
{
"name": "Launch Release",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/webserv",
"args": ["${workspaceFolder}/config/default.conf"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"preLaunchTask": "Build Release",
"miDebuggerPath": "/usr/bin/gdb",
"internalConsoleOptions": "openOnSessionStart"
}
]
}

45
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,45 @@
{
"cmake.buildTypes": [
{
"name": "Debug",
"displayName": "Debug",
"description": "Debug build with symbols and no optimization",
"buildType": "Debug"
},
{
"name": "Release",
"displayName": "Release",
"description": "Optimized release build",
"buildType": "Release"
},
{
"name": "ASAN",
"displayName": "AddressSanitizer",
"description": "Debug build with AddressSanitizer",
"buildType": "ASAN"
}
],
"cmake.defaultVariants": {
"buildType": {
"default": "Release",
"description": "The build type",
"choices": {
"debug": {
"short": "Debug",
"long": "Debug build with symbols",
"buildType": "Debug"
},
"release": {
"short": "Release",
"long": "Optimized release build",
"buildType": "Release"
},
"asan": {
"short": "ASAN",
"long": "AddressSanitizer build",
"buildType": "ASAN"
}
}
}
}
}

95
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,95 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Build All",
"type": "shell",
"command": "make",
"args": ["all"],
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": ["$gcc"],
"detail": "Build all targets (release, debug, asan)"
},
{
"label": "Build Release",
"type": "shell",
"command": "make",
"args": ["release"],
"group": "build",
"problemMatcher": ["$gcc"],
"detail": "Build release target"
},
{
"label": "Build Debug",
"type": "shell",
"command": "make",
"args": ["debug"],
"group": "build",
"problemMatcher": ["$gcc"],
"detail": "Build debug target"
},
{
"label": "Build ASAN",
"type": "shell",
"command": "make",
"args": ["asan"],
"group": "build",
"problemMatcher": ["$gcc"],
"detail": "Build AddressSanitizer target"
},
{
"label": "Run Release",
"type": "shell",
"command": "make",
"args": ["run_release"],
"group": "test",
"dependsOn": "Build Release",
"detail": "Build and run release version"
},
{
"label": "Run Debug",
"type": "shell",
"command": "make",
"args": ["run_debug"],
"group": "test",
"dependsOn": "Build Debug",
"detail": "Build and run debug version"
},
{
"label": "Run ASAN",
"type": "shell",
"command": "make",
"args": ["run_asan"],
"group": "test",
"dependsOn": "Build ASAN",
"detail": "Build and run AddressSanitizer version"
},
{
"label": "Clean",
"type": "shell",
"command": "make",
"args": ["clean"],
"group": "build",
"detail": "Clean build artifacts"
},
{
"label": "Full Clean",
"type": "shell",
"command": "make",
"args": ["fclean"],
"group": "build",
"detail": "Remove build directory completely"
},
{
"label": "Rebuild",
"type": "shell",
"command": "make",
"args": ["re"],
"group": "build",
"detail": "Full clean and rebuild"
}
]
}

View File

@ -21,6 +21,15 @@ if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
# Define available build types for IDE
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
"Debug"
"Release"
"ASAN"
"RelWithDebInfo"
"MinSizeRel"
)
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
# Set build flags for different build types

116
Makefile
View File

@ -1,87 +1,51 @@
# Compiler and flags
CXX = c++
CXXFLAGS = -Wall -Wextra -Werror -std=c++20 -MMD -MP
# Build type (default to debug)
BUILD_TYPE ?= debug
# Build-specific flags
ifeq ($(BUILD_TYPE), release)
CXXFLAGS += -O3 -DNDEBUG
BUILD_SUFFIX = release
else ifeq ($(BUILD_TYPE), asan)
CXXFLAGS += -g -O1 -fsanitize=address -fno-omit-frame-pointer
BUILD_SUFFIX = asan
else
CXXFLAGS += -g -O0 -DDEBUG
BUILD_SUFFIX = debug
endif
# Directories
SRCDIR = webserv
BUILDDIR = build/$(BUILD_SUFFIX)
OBJDIR = $(BUILDDIR)/obj
# Target executable
NAME = $(BUILDDIR)/webserv
# Source files
SOURCES = $(wildcard $(SRCDIR)/*.cpp) \
$(wildcard $(SRCDIR)/*/*.cpp)
# Object files
OBJECTS = $(SOURCES:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o)
# Dependency files
DEPENDS = $(OBJECTS:.o=.d)
# Include directories
INCLUDES = -I.
# Variables
BUILD_DIR = build
CMAKE = cmake
CMAKE_BUILD = cmake --build
CMAKE_FLAGS = -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
CONFIG_FILE = config/default.conf
# Default target
all: $(NAME)
all: release debug asan
# Create executable
$(NAME): $(OBJECTS)
@mkdir -p $(BUILDDIR)
$(CXX) $(CXXFLAGS) $(OBJECTS) -o $(NAME)
# Configure CMake if build directory doesn't exist
$(BUILD_DIR):
$(CMAKE) -B $(BUILD_DIR) $(CMAKE_FLAGS)
# Compile source files to object files
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp Makefile
@mkdir -p $(dir $@)
$(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@
# Build targets with specific build types
release: $(BUILD_DIR)
$(CMAKE) -B $(BUILD_DIR) $(CMAKE_FLAGS) -DCMAKE_BUILD_TYPE=Release
$(CMAKE_BUILD) $(BUILD_DIR) --target webserv
# Clean object files
debug: $(BUILD_DIR)
$(CMAKE) -B $(BUILD_DIR) $(CMAKE_FLAGS) -DCMAKE_BUILD_TYPE=Debug
$(CMAKE_BUILD) $(BUILD_DIR) --target webserv
asan: $(BUILD_DIR)
$(CMAKE) -B $(BUILD_DIR) $(CMAKE_FLAGS) -DCMAKE_BUILD_TYPE=ASAN
$(CMAKE_BUILD) $(BUILD_DIR) --target webserv
# Run targets
run_release: release
./$(BUILD_DIR)/webserv $(CONFIG_FILE)
run_debug: debug
./$(BUILD_DIR)/webserv $(CONFIG_FILE)
run_asan: asan
./$(BUILD_DIR)/webserv $(CONFIG_FILE)
# Clean targets
clean:
rm -rf $(OBJDIR)
@if [ -d "$(BUILD_DIR)" ]; then \
$(CMAKE_BUILD) $(BUILD_DIR) --target clean; \
fi
# Clean everything (object files, executable, and build directory)
fclean: clean
rm -rf $(BUILDDIR)
# Clean all build types
fclean-all:
rm -rf build
fclean:
rm -rf $(BUILD_DIR)
# Rebuild everything
re: fclean all
# Run the executable (rebuild first)
run: re
./$(NAME)
# Build type targets
debug:
$(MAKE) BUILD_TYPE=debug
release:
$(MAKE) BUILD_TYPE=release
asan:
$(MAKE) BUILD_TYPE=asan
# Phony targets
.PHONY: all clean fclean fclean-all re run debug release asan
# Include dependency files
-include $(DEPENDS)
# Mark targets as phony
.PHONY: all release debug asan run_release run_debug run_asan clean fclean re

87
Makefile.old Normal file
View File

@ -0,0 +1,87 @@
# Compiler and flags
CXX = c++
CXXFLAGS = -Wall -Wextra -Werror -std=c++20 -MMD -MP
# Build type (default to debug)
BUILD_TYPE ?= debug
# Build-specific flags
ifeq ($(BUILD_TYPE), release)
CXXFLAGS += -O3 -DNDEBUG
BUILD_SUFFIX = release
else ifeq ($(BUILD_TYPE), asan)
CXXFLAGS += -g -O1 -fsanitize=address -fno-omit-frame-pointer
BUILD_SUFFIX = asan
else
CXXFLAGS += -g -O0 -DDEBUG
BUILD_SUFFIX = debug
endif
# Directories
SRCDIR = webserv
BUILDDIR = build/$(BUILD_SUFFIX)
OBJDIR = $(BUILDDIR)/obj
# Target executable
NAME = $(BUILDDIR)/webserv
# Source files
SOURCES = $(wildcard $(SRCDIR)/*.cpp) \
$(wildcard $(SRCDIR)/*/*.cpp)
# Object files
OBJECTS = $(SOURCES:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o)
# Dependency files
DEPENDS = $(OBJECTS:.o=.d)
# Include directories
INCLUDES = -I.
# Default target
all: $(NAME)
# Create executable
$(NAME): $(OBJECTS)
@mkdir -p $(BUILDDIR)
$(CXX) $(CXXFLAGS) $(OBJECTS) -o $(NAME)
# Compile source files to object files
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp Makefile
@mkdir -p $(dir $@)
$(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@
# Clean object files
clean:
rm -rf $(OBJDIR)
# Clean everything (object files, executable, and build directory)
fclean: clean
rm -rf $(BUILDDIR)
# Clean all build types
fclean-all:
rm -rf build
# Rebuild everything
re: fclean all
# Run the executable (rebuild first)
run: re
./$(NAME)
# Build type targets
debug:
$(MAKE) BUILD_TYPE=debug
release:
$(MAKE) BUILD_TYPE=release
asan:
$(MAKE) BUILD_TYPE=asan
# Phony targets
.PHONY: all clean fclean fclean-all re run debug release asan
# Include dependency files
-include $(DEPENDS)

40
config/default.conf Normal file
View File

@ -0,0 +1,40 @@
server {
listen 80;
server_name localhost;
root /var/www/html;
index index.html index.htm;
error_page 400 /400.html;
error_page 403 /403.html;
error_page 404 /404.html;
error_page 405 /405.html;
error_page 413 /413.html;
error_page 500 /500.html;
error_page 502 /502.html;
error_page 504 /504.html;
client_max_body_size 1M;
location / {
autoindex off;
index index.html;
allow_methods GET POST DELETE;
}
location /uploads {
root /var/www/uploads;
autoindex on;
allow_methods GET POST;
}
location /images {
root /var/www/images;
autoindex off;
index index.jpg;
allow_methods GET;
}
cgi_pass /cgi-bin/;
cgi_ext .py .php;
}

View File

@ -0,0 +1,28 @@
#include <iostream>
#include <webserv/ConfigManager/ConfigManager.hpp>
ConfigManager::ConfigManager() : _initialized(false)
{
}
ConfigManager::~ConfigManager()
{
}
ConfigManager &ConfigManager::getInstance()
{
static ConfigManager instance;
std::cout << "ConfigManager instance" << '\n';
return instance;
}
void ConfigManager::init(const std::string &filePath)
{
if (_initialized)
{
throw std::runtime_error("ConfigManager is already initialized.");
}
std::cout << "Initializing ConfigManager with file: " << filePath << '\n';
// parseConfigFile(filePath);
_initialized = true;
}

View File

@ -0,0 +1,45 @@
#pragma once
#include <map>
#include <memory>
#include <string>
#include <vector>
struct LocationConfig
{
std::string path;
bool autoIndex;
std::string indexFile;
// Add other location-specific configurations as needed
};
struct ServerConfig
{
std::string host;
int port;
std::string root;
// Add other server-specific configurations as needed
std::unique_ptr<std::map<std::string, LocationConfig>> locations;
};
class ConfigManager
{
public:
ConfigManager &operator=(const ConfigManager &other) = delete;
ConfigManager &&operator=(const ConfigManager &&other) = delete;
ConfigManager(const ConfigManager &other) = delete;
ConfigManager(const ConfigManager &&other) = delete;
void init(const std::string &filePath);
static ConfigManager &getInstance();
private:
bool _initialized;
ConfigManager();
~ConfigManager();
std::vector<ServerConfig> serverConfigs;
// void parseConfigFile(const std::string &filePath);
// void parseServerBlock(const std::string &block);
// void parseLocationBlock(const std::string &block, ServerConfig &serverConfig);
};

View File

@ -1,7 +1,23 @@
#include <webserv/mymodule/MyModule.hpp>
#include <webserv/ConfigManager/ConfigManager.hpp>
int main()
#include <iostream>
#include <string>
#include <vector>
int main(int argc, char **argv)
{
MyModule::doSomething();
std::vector<std::string> args;
args.reserve(static_cast<size_t>(argc));
for (int i = 0; i < argc; ++i)
{
args.emplace_back(argv[i]);
}
if (args.size() < 2)
{
std::cerr << "Usage: " << args[0] << " <config_file_path>\n";
return 1;
}
ConfigManager::getInstance().init(args[1]);
return 0;
}

View File

@ -1,8 +0,0 @@
#include <webserv/mymodule/MyModule.hpp>
#include <iostream>
void MyModule::doSomething()
{
std::cout << "Doing really something!\n";
}

View File

@ -1,7 +0,0 @@
#pragma once
class MyModule
{
public:
static void doSomething();
};