Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,7 @@ docker-compose.override.yml
*word-case-api.sln

*DotNetAPI.Tests.csproj.lscache
*DotNetAPI.csproj.lscache
*DotNetAPI.csproj.lscache

*KT_Cache/

64 changes: 46 additions & 18 deletions Backend/CaseConversionAPI/CppLib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,25 @@ if(POLICY CMP0135)
cmake_policy(SET CMP0135 NEW)
endif()

# Add this near the top, after project()
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR NOT CMAKE_BUILD_TYPE)
# 1. Initialize the project profile first so system variables exist
project(StringConversion)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
enable_testing()

# 2. Apply explicit static linking constraints globally for cross-compilation
if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Windows")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static -static-libgcc -static-libstdc++")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static -static-libgcc -static-libstdc++")
# Force underlying components to compile with matching runtime definitions
set(gtest_force_shared_crt OFF CACHE BOOL "" FORCE)
else()
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
endif()

# 3. Restrict AddressSanitizer strictly to native explicit Debug builds
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
message(STATUS "Enabling AddressSanitizer for Debug build")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer -g")
Expand All @@ -14,17 +31,10 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR NOT CMAKE_BUILD_TYPE)
endif()
endif()

project(StringConversion)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
enable_testing()

# ---------------------------
# Global Settings
# ---------------------------
include_directories(include)
# Required for linking static code into a shared library on some platforms
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

# ---------------------------
Expand Down Expand Up @@ -54,20 +64,14 @@ target_include_directories(StringConversionLib PUBLIC include)
# ---------------------------
# 2. The Bridge DLL: ProcessStringDLL (SHARED)
# ---------------------------
# This creates the actual file (libProcessStringDLL.dylib / .so) for .NET
add_library(ProcessStringDLL SHARED src/ProcessStringDLL.cpp)

# This tells the compiler "We are BUILDING the DLL, not using it"
target_compile_definitions(ProcessStringDLL PRIVATE PROCESSSTRING_EXPORTS)

# This silences the 'strcpy' warning (C4996) seen in your logs
if(WIN32)
target_compile_definitions(ProcessStringDLL PRIVATE _CRT_SECURE_NO_WARNINGS)
endif()

target_link_libraries(ProcessStringDLL PRIVATE StringConversionLib)

# Ensure the "lib" prefix is consistent for your scripts
set_target_properties(ProcessStringDLL PROPERTIES PREFIX "lib")

# ---------------------------
Expand All @@ -80,8 +84,6 @@ target_link_libraries(app StringConversionLib)
# 4. GoogleTest Setup
# ---------------------------
include(FetchContent)
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)

FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/main.zip
Expand All @@ -97,4 +99,30 @@ add_executable(runTests
)
target_link_libraries(runTests StringConversionLib gtest gtest_main)

add_test(NAME AllTests COMMAND runTests)
# Force the test runner to link dependencies statically under MinGW
if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Windows")
target_link_options(runTests PRIVATE "-static" "-static-libgcc" "-static-libstdc++")
endif()

add_test(NAME AllTests COMMAND runTests)

# ---------------------------
# 6. Code Formatting (Clang-Format Automation)
# ---------------------------
find_program(CLANG_FORMAT_EXE
NAMES clang-format
HINTS /opt/homebrew/bin /usr/local/bin
)

if(CLANG_FORMAT_EXE)
message(STATUS "Found clang-format: ${CLANG_FORMAT_EXE}")
file(GLOB_RECURSE ALL_FORMAT_FILES
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp"
"${PROJECT_SOURCE_DIR}/../Tests/CppTests/*.cpp"
)
add_custom_target(format
COMMAND ${CLANG_FORMAT_EXE} -i -style=LLVM ${ALL_FORMAT_FILES}
COMMENT "Auto-formatting all C++ engine source..."
)
endif()
23 changes: 23 additions & 0 deletions Backend/CaseConversionAPI/CppLib/CMakeListsLocalApp.txt
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,27 @@ target_link_libraries(runTests StringConversionLib gtest gtest_main)
# ---------------------------
add_test(NAME AllTests COMMAND runTests)

# ===================================================================
# 6. Code Formatting (Clang-Format Automation)
# ===================================================================
find_program(CLANG_FORMAT_EXE
NAMES clang-format
HINTS /opt/homebrew/bin /usr/local/bin
)

if(CLANG_FORMAT_EXE)
message(STATUS "Found clang-format: ${CLANG_FORMAT_EXE}")

file(GLOB_RECURSE ALL_FORMAT_FILES
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp"
"${PROJECT_SOURCE_DIR}/../Tests/CppTests/*.cpp"
)

add_custom_target(format
COMMAND ${CLANG_FORMAT_EXE} -i -style=LLVM ${ALL_FORMAT_FILES}
COMMENT "Auto-formatting C++ engine, application, and test suites..."
)
else()
message(WARNING "clang-format executable not found. 'format' target will not be available.")
endif()
43 changes: 36 additions & 7 deletions Backend/CaseConversionAPI/CppLib/Scripts/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,24 @@
# * Artifact Extraction: Exposes the build directory for host-side consumption.
# -----------------------------------------------------------------------------

# --- STAGE 1: Build Environment (Native Toolchains Only) ---
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build-env
ARG TARGET_PLATFORM=linux/amd64
FROM --platform=${TARGET_PLATFORM} mcr.microsoft.com/dotnet/sdk:8.0 AS build-env

# Install C++ Native Toolchains (GCC for Linux, MinGW for Windows)
RUN apt-get update && apt-get install -y \
# Install C++ Native Toolchains, Wine, and Xvfb for testing
RUN dpkg --add-architecture i386 && \
apt-get update && apt-get install -y \
build-essential \
cmake \
mingw-w64 \
wine \
wine32 \
wine64 \
xvfb \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /src

# Copy the entire repo context to preserve script and source paths
# Copy the entire repo context
COPY . .

# Ensure orchestrator script is executable
Expand All @@ -40,14 +45,38 @@ RUN ./Backend/CaseConversionAPI/CppLib/Scripts/orchestrate-native.sh ubuntu-late
# --- STEP 2: Build Windows Artifacts (.dll via MinGW) ---
RUN ./Backend/CaseConversionAPI/CppLib/Scripts/orchestrate-native.sh windows-latest

# --- STEP 3: Verification Layer (Internal Tests) ---
WORKDIR /src/Backend/CaseConversionAPI/CppLib/build/windows-latest

ENV WINEPREFIX=/root/.wine
ENV WINEARCH=win64
ENV WINEDEBUG=-all
ENV WINEDLLOVERRIDES="mscoree,mshtml="

# Run Windows test suite via Wine
# Using absolute path to /usr/bin/xvfb-run ensures command execution
RUN echo "===== Running Windows GoogleTests via Wine =====" && \
/usr/bin/xvfb-run --server-args="-screen 0 1024x768x24" \
/usr/lib/wine/wine64 ./runTests.exe --gtest_color=yes 2>&1 | tee gtest_internal.log && \
echo "===== Windows GoogleTests Passed =====" \
|| { \
echo "=== WINDOWS GOOGLETEST CRASH LOG ==="; \
cat gtest_internal.log; \
exit 1; \
}

# Reset context for artifact extraction
WORKDIR /src

# -----------------------------------------------------------------------------
# STAGE 2: Export Layer (Minimal Delivery Vessel)
# -----------------------------------------------------------------------------
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
# Re-import target architecture variable for the final runtime stage context
ARG TARGET_PLATFORM=linux/amd64
FROM --platform=${TARGET_PLATFORM} mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
WORKDIR /app

# Export the raw C++ build artifacts for the host to extract via 'docker cp'
# This bypasses managed code publish to focus on native binary delivery.
COPY --from=build-env /src/Backend/CaseConversionAPI/CppLib/build /src/Backend/CaseConversionAPI/CppLib/build

# Note: No ENTRYPOINT defined as this container is utilized as an artifact source.
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,21 @@
# Version : 1.0 */
# */
# Purpose : Coordinates Local (macOS) and Dockerized (Linux/Win) */
# builds to generate a unified multi-platform binary set.*/
# Location : backend/CaseConversionAPI/CppLib/Scripts/master-build.sh*/
# builds to generate a unified multi-platform binary */
# set. */
# Location : Backend/CaseConversionAPI/CppLib/Scripts/ */
# orchestrate-native-docker.sh */
# */
# Revision History: */
# ------------------------------------------------------------------ */
# Version Date Author Description */
# ------------------------------------------------------------------ */
# 1.0 2026-05-14 Nitish Singh Initial Master Orchestrator*/
# with Docker extraction. */
# 1.1 2026-05-16 Nitish Singh Added changed backend root */
# path handling. */
# 1.2 2026-05-20 Nitish Singh Aded google test execution */
# inside the docker container*/
#*********************************************************************/

set -euo pipefail
Expand All @@ -25,7 +31,7 @@ REPO_ROOT=$(realpath "$BACKEND_ROOT/..")
# Configuration
DOCKERFILE_PATH="$BACKEND_ROOT/CaseConversionAPI/CppLib/Scripts/Dockerfile"
DIST_DIR="$BACKEND_ROOT/CaseConversionAPI/CppLib/build"
NATIVE_SCRIPT_REL="backend/CaseConversionAPI/CppLib/Scripts/orchestrate-native.sh"
NATIVE_SCRIPT_REL="Backend/CaseConversionAPI/CppLib/Scripts/orchestrate-native.sh"

log_info() { echo -e "\033[0;34m[$(date +'%T')] [INFO]\033[0m $1"; }
log_success() { echo -e "\033[0;32m[$(date +'%T')] [SUCCESS]\033[0m $1"; }
Expand All @@ -38,7 +44,6 @@ cd "$REPO_ROOT"
if [[ "$(uname)" == "Darwin" ]]; then
log_info "MacOS detected. Running local native build & tests..."

# Execute native script with the macos-latest target
if bash "$NATIVE_SCRIPT_REL" macos-latest; then
log_success "MacOS Local Build & Testing Complete."
else
Expand All @@ -52,41 +57,49 @@ fi
# --- STEP 2: DOCKER CROSS-BUILD (LINUX & WINDOWS) ---
log_info "Initiating Docker Build for Linux (.so) and Windows (.dll)..."

# Build the native-only Docker image
if docker build -t cpp-native-cross -f "$DOCKERFILE_PATH" .; then
if docker build \
--progress=plain \
--platform linux/amd64 \
-t cpp-native-cross \
-f "$DOCKERFILE_PATH" .; then

# 1. Run Linux Tests
log_info "Running C++ Core GoogleTest suite inside Linux Container Environment..."
if docker run --rm cpp-native-cross /src/Backend/CaseConversionAPI/CppLib/build/ubuntu-latest/runTests; then
log_success "Linux (Ubuntu) Container Core Tests Passed Successfully."
else
log_error "Linux Core Tests Failed within the container context."
exit 1
fi

# 3. Extract and Sync Artifacts
log_info "Extracting virtual artifacts from Docker..."

CONTAINER_ID=$(docker create cpp-native-cross)
TEMP_EXTRACT="$DIST_DIR/docker_temp"
mkdir -p "$TEMP_EXTRACT"

# Copy the internal build directory to local temp
# The dot at the end ensures we copy contents of 'build'
docker cp "$CONTAINER_ID:/src/backend/CaseConversionAPI/CppLib/build/." "$TEMP_EXTRACT/"

# Cleanup Docker immediately

docker cp "$CONTAINER_ID:/src/Backend/CaseConversionAPI/CppLib/build/." "$TEMP_EXTRACT/"
docker rm "$CONTAINER_ID"
docker rmi cpp-native-cross

# --- STEP 3: SYNC VIRTUAL ARTIFACTS ---
log_info "Syncing cross-platform target folders..."

# Target: ubuntu-latest
# Sync Linux
if [ -d "$TEMP_EXTRACT/ubuntu-latest" ]; then
mkdir -p "$DIST_DIR/ubuntu-latest"
cp "$TEMP_EXTRACT/ubuntu-latest/libProcessStringDLL.so" "$DIST_DIR/ubuntu-latest/"
log_success "Artifact Secured: ubuntu-latest/libProcessStringDLL.so"
fi

# Target: windows-latest
# Sync Windows
if [ -d "$TEMP_EXTRACT/windows-latest" ]; then
mkdir -p "$DIST_DIR/windows-latest"
cp "$TEMP_EXTRACT/windows-latest/libProcessStringDLL.dll" "$DIST_DIR/windows-latest/"
log_success "Artifact Secured: windows-latest/libProcessStringDLL.dll"
fi

# Final Cleanup
# 4. Final Cleanup
rm -rf "$TEMP_EXTRACT"
docker rmi cpp-native-cross
else
log_error "Docker build failed. Check Dockerfile and native toolchains."
exit 1
Expand Down
13 changes: 13 additions & 0 deletions Backend/CaseConversionAPI/CppLib/Scripts/orchestrate-native.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
# 1.5 2026-05-16 Nitish Singh Standardized logging, */
# execution context validation*/
# and dynamic path handling. */
# 1.6 2026-05-28 Nitish Singh Injected pre-build format */
# automation with set +e. */
#*********************************************************************/

set -euo pipefail
Expand Down Expand Up @@ -124,6 +126,17 @@ fi
# Modern CMake build
cmake -S "$CPP_ROOT" -B "$BUILD_DIR" "${CMAKE_ARGS[@]}"

# Temporarily drop strict exit tracking to execute target code formatting safely
set +e
log_info "Executing shared framework auto-formatting via clang-format..."
cmake --build "$BUILD_DIR" --target format
if [ $? -eq 0 ]; then
log_success "Workspace formatting complete."
else
log_warn "Formatting target encountered an initialization anomaly or was skipped; proceeding."
fi
set -e # Re-engage strict execution tracking for compilation safety

log_info "Utilizing $NUM_CORES cores for parallel build..."
cmake --build "$BUILD_DIR" --config Release --parallel "$NUM_CORES"

Expand Down
25 changes: 19 additions & 6 deletions Backend/CaseConversionAPI/CppLib/Scripts/run-local-context.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@
# ------------------------------------------------------------------ */
# Version Date Author Description */
# ------------------------------------------------------------------ */
# 1.0 2026-04-16 Nitish Singh Initial Swap Logic Script */
# 1.1 2026-04-16 Nitish Singh Added Absolute Path Trap */
# 1.2 2026-05-09 Nitish Singh Optimized for M2 P-Cores */
# and enhanced error cleanup. *
# 1.3 2026-05-16 Nitish Singh Added execution context */
# validation and dynamic path */
# 1.0 2026-04-16 Nitish Singh Initial Swap Logic Script */
# 1.1 2026-04-16 Nitish Singh Added Absolute Path Trap */
# 1.2 2026-05-09 Nitish Singh Optimized for M2 P-Cores */
# and enhanced error cleanup. */
# 1.3 2026-05-16 Nitish Singh Added execution context */
# validation and dynamic path */
# 1.4 2026-05-28 Nitish Singh Automated clang-format via */
# set +e error isolation. */
#*********************************************************************/

set -euo pipefail
Expand Down Expand Up @@ -94,6 +96,17 @@ cmake -S "$CPP_ROOT" -B "$BUILD_DIR" \
-DUSE_PCORES=ON \
-DCMAKE_OSX_ARCHITECTURES=arm64

# Temporarily disable strict exit-on-error for the formatter target
set +e
log_info "Executing source workspace auto-formatting via clang-format..."
cmake --build "$BUILD_DIR" --target format
if [ $? -eq 0 ]; then
log_success "Workspace formatting complete."
else
log_warn "Formatting target encountered an initialization anomaly; proceeding to compilation."
fi
set -e # Re-enable strict error tracking for compilation safety

log_info "Utilizing $NUM_CORES cores for parallel compilation..."
cmake --build "$BUILD_DIR" --config Release --parallel "$NUM_CORES"

Expand Down
Loading
Loading