From 9d3f65ba8b20afe0a490a860f8263c84e1c46e07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Wed, 21 Jan 2026 03:11:47 +0100 Subject: [PATCH 1/4] Add BUILD_BOTH_LIBRARIES option to build static and shared libs Add a new CMake option BUILD_BOTH_LIBRARIES that allows building both static and shared libraries in a single build directory. This provides an alternative to the existing approach of building in separate directories with BUILD_SHARED_LIBS=ON/OFF, while maintaining backward compatibility with existing build scripts. Usage: cmake .. -DBUILD_BOTH_LIBRARIES=ON Produces: - libcpp_dotenv_static.a - libcpp_dotenv_shared.so (or .dylib on macOS) --- CMakeLists.txt | 58 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9fb67a4..092378c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,9 @@ else() endif() message(STATUS "Building CPP-DOTENV in ${CMAKE_BUILD_TYPE} mode") +# Option to build both static and shared libraries +option(BUILD_BOTH_LIBRARIES "Build both static and shared libraries" OFF) + #------------------- SUBDIRECTORY ADDITION ------------------------------------ add_subdirectory(common) @@ -19,29 +22,58 @@ add_subdirectory(src) #----------------------- LIBRARY CONFIGURATION -------------------------------- -set(CPP_DOTENV cpp_dotenv CACHE INTERNAL "") set(CPP_DOTENV_SRC src/dotenv.cpp include/dotenv.h ) -add_library(${CPP_DOTENV} ${CPP_DOTENV_SRC}) +# Common include directories +set(CPP_DOTENV_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include) -target_link_libraries(${CPP_DOTENV} - ${ENVIRON_LIB} - ${PARSER_LIB} -) +# Common compile options +if ("${CMAKE_BUILD_TYPE}" STREQUAL "DEBUG") + set(CPP_DOTENV_COMPILE_OPTIONS -g -Wall -O0) +else() + set(CPP_DOTENV_COMPILE_OPTIONS -O3) +endif() -target_include_directories(${CPP_DOTENV} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/include -) +# Build both static and shared libraries if requested +if(BUILD_BOTH_LIBRARIES) + # Static library + add_library(cpp_dotenv_static STATIC ${CPP_DOTENV_SRC}) + target_link_libraries(cpp_dotenv_static + ${ENVIRON_LIB} + ${PARSER_LIB} + ) + target_include_directories(cpp_dotenv_static PUBLIC ${CPP_DOTENV_INCLUDE_DIRS}) + target_compile_options(cpp_dotenv_static PRIVATE ${CPP_DOTENV_COMPILE_OPTIONS}) -if ("${CMAKE_BUILD_TYPE}" STREQUAL "DEBUG") - target_compile_options(${CPP_DOTENV} PRIVATE - -g -Wall -O0 + # Shared library + add_library(cpp_dotenv_shared SHARED ${CPP_DOTENV_SRC}) + target_link_libraries(cpp_dotenv_shared + ${ENVIRON_LIB} + ${PARSER_LIB} ) + target_include_directories(cpp_dotenv_shared PUBLIC ${CPP_DOTENV_INCLUDE_DIRS}) + target_compile_options(cpp_dotenv_shared PRIVATE ${CPP_DOTENV_COMPILE_OPTIONS}) + + # Alias for compatibility - default to static + add_library(cpp_dotenv ALIAS cpp_dotenv_static) else() + # Single library (type determined by BUILD_SHARED_LIBS) + set(CPP_DOTENV cpp_dotenv CACHE INTERNAL "") + add_library(${CPP_DOTENV} ${CPP_DOTENV_SRC}) + + target_link_libraries(${CPP_DOTENV} + ${ENVIRON_LIB} + ${PARSER_LIB} + ) + + target_include_directories(${CPP_DOTENV} PUBLIC + ${CPP_DOTENV_INCLUDE_DIRS} + ) + target_compile_options(${CPP_DOTENV} PRIVATE - -O3 + ${CPP_DOTENV_COMPILE_OPTIONS} ) endif() From 5222c9951344a6db3693af5cd70148343651cca7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Wed, 21 Jan 2026 09:16:56 +0100 Subject: [PATCH 2/4] Address Copilot review feedback for BUILD_BOTH_LIBRARIES - Add validation to prevent BUILD_BOTH_LIBRARIES and BUILD_SHARED_LIBS from being used together (with warning message) - Improve documentation for the cpp_dotenv alias, explaining that it points to cpp_dotenv_static when BUILD_BOTH_LIBRARIES is ON --- CMakeLists.txt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 092378c..802ad6b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,12 @@ message(STATUS "Building CPP-DOTENV in ${CMAKE_BUILD_TYPE} mode") # Option to build both static and shared libraries option(BUILD_BOTH_LIBRARIES "Build both static and shared libraries" OFF) +# Validate that BUILD_BOTH_LIBRARIES and BUILD_SHARED_LIBS are not used together +if(BUILD_BOTH_LIBRARIES AND BUILD_SHARED_LIBS) + message(WARNING "BUILD_BOTH_LIBRARIES and BUILD_SHARED_LIBS should not be used together. BUILD_SHARED_LIBS will be ignored.") + set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared libraries" FORCE) +endif() + #------------------- SUBDIRECTORY ADDITION ------------------------------------ add_subdirectory(common) @@ -57,7 +63,10 @@ if(BUILD_BOTH_LIBRARIES) target_include_directories(cpp_dotenv_shared PUBLIC ${CPP_DOTENV_INCLUDE_DIRS}) target_compile_options(cpp_dotenv_shared PRIVATE ${CPP_DOTENV_COMPILE_OPTIONS}) - # Alias for compatibility - default to static + # Alias for backward compatibility: + # When BUILD_BOTH_LIBRARIES is ON, the cpp_dotenv target is an alias to + # cpp_dotenv_static. Projects that need the shared library must explicitly + # link against cpp_dotenv_shared instead of cpp_dotenv. add_library(cpp_dotenv ALIAS cpp_dotenv_static) else() # Single library (type determined by BUILD_SHARED_LIBS) From 7bed243a738f3704585c4b862a5af7ea2f23c34c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Wed, 21 Jan 2026 09:52:00 +0100 Subject: [PATCH 3/4] Address remaining Copilot review feedback - Add OUTPUT_NAME property so libraries are named correctly: * libcpp_dotenv.a (static) instead of libcpp_dotenv_static.a * libcpp_dotenv.so/.dylib (shared) instead of libcpp_dotenv_shared.so - Enable CMAKE_POSITION_INDEPENDENT_CODE when building shared libraries to ensure static dependencies are compiled with -fPIC - Document BUILD_BOTH_LIBRARIES option in README.md with usage examples The OUTPUT_NAME property sets only the base name; CMake automatically adds the correct platform-specific extension (.so on Linux, .dylib on macOS). --- CMakeLists.txt | 10 ++++++++++ README.md | 38 +++++++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 802ad6b..2624a29 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,12 @@ if(BUILD_BOTH_LIBRARIES AND BUILD_SHARED_LIBS) set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared libraries" FORCE) endif() +# When building shared libraries that link against static libraries, +# we need position-independent code for the static libraries +if(BUILD_SHARED_LIBS OR BUILD_BOTH_LIBRARIES) + set(CMAKE_POSITION_INDEPENDENT_CODE ON) +endif() + #------------------- SUBDIRECTORY ADDITION ------------------------------------ add_subdirectory(common) @@ -53,6 +59,8 @@ if(BUILD_BOTH_LIBRARIES) ) target_include_directories(cpp_dotenv_static PUBLIC ${CPP_DOTENV_INCLUDE_DIRS}) target_compile_options(cpp_dotenv_static PRIVATE ${CPP_DOTENV_COMPILE_OPTIONS}) + # Set output name to libcpp_dotenv.a (instead of libcpp_dotenv_static.a) + set_target_properties(cpp_dotenv_static PROPERTIES OUTPUT_NAME cpp_dotenv) # Shared library add_library(cpp_dotenv_shared SHARED ${CPP_DOTENV_SRC}) @@ -62,6 +70,8 @@ if(BUILD_BOTH_LIBRARIES) ) target_include_directories(cpp_dotenv_shared PUBLIC ${CPP_DOTENV_INCLUDE_DIRS}) target_compile_options(cpp_dotenv_shared PRIVATE ${CPP_DOTENV_COMPILE_OPTIONS}) + # Set output name to libcpp_dotenv.so/.dylib (instead of libcpp_dotenv_shared.so) + set_target_properties(cpp_dotenv_shared PROPERTIES OUTPUT_NAME cpp_dotenv) # Alias for backward compatibility: # When BUILD_BOTH_LIBRARIES is ON, the cpp_dotenv target is an alias to diff --git a/README.md b/README.md index aad33c5..198f6f1 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ Supported build methods are: ### CMake -**cpp-dotenv** comes with support for `CMake` right out of the box. In order to use it, simply include this repository's directory and link the `cpp_dotenv` target to your own targets where needed: +**cpp-dotenv** comes with support for `CMake` right out of the box (>=3.16). In order to use it, simply include this repository's directory and link the `cpp_dotenv` target to your own targets where needed: ```cmake add_subdirectory(cpp-dotenv) @@ -55,6 +55,42 @@ target_link_libraries(YOUR_TARGET cpp_dotenv) After this, you might use the library as described in [usage](#usage); no extra scoping, no need to worry about the project's directory structure. +#### Build Options + +By default, only one library target named `cpp_dotenv` is built. The type of library (static or shared) is controlled by CMake's standard `BUILD_SHARED_LIBS` option: + +```bash +# Build static library (default) +cmake -DBUILD_SHARED_LIBS=OFF .. + +# Build shared library +cmake -DBUILD_SHARED_LIBS=ON .. +``` + +#### Building Both Static and Shared Libraries + +To build both static and shared libraries in a single build directory, use the `BUILD_BOTH_LIBRARIES` option: + +```bash +cmake -DBUILD_BOTH_LIBRARIES=ON .. +``` + +This creates two separate library targets: +- `cpp_dotenv_static` - outputs as `libcpp_dotenv.a` +- `cpp_dotenv_shared` - outputs as `libcpp_dotenv.so` (or `.dylib` on macOS) + +For backward compatibility, the `cpp_dotenv` target remains available as an alias to `cpp_dotenv_static`. If you need to link against the shared library, explicitly specify `cpp_dotenv_shared`: + +```cmake +# Link against static library (default) +target_link_libraries(YOUR_TARGET cpp_dotenv) + +# Link against shared library +target_link_libraries(YOUR_TARGET cpp_dotenv_shared) +``` + +**Note:** When `BUILD_BOTH_LIBRARIES` is enabled, `BUILD_SHARED_LIBS` is ignored. Do not use both options simultaneously. + ## Usage To be able to use the dotenv classes, simply include the main header file: From 9cf61b18fcd925a990be0b997829ed253fc823cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Wed, 21 Jan 2026 10:14:09 +0100 Subject: [PATCH 4/4] Address CodeRabbit AI review feedback - Fix README CMake version mismatch: update from >=3.10 to >=3.16 to match CMakeLists.txt requirement - Fix Windows MSVC import library conflict: when BUILD_BOTH_LIBRARIES is ON, both static and shared libraries would produce cpp_dotenv.lib on Windows. Add IMPORT_SUFFIX "_shared.lib" to the shared library's import library to avoid this conflict on Windows/MSVC. --- CMakeLists.txt | 5 +++++ README.md | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2624a29..49e0468 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,6 +72,11 @@ if(BUILD_BOTH_LIBRARIES) target_compile_options(cpp_dotenv_shared PRIVATE ${CPP_DOTENV_COMPILE_OPTIONS}) # Set output name to libcpp_dotenv.so/.dylib (instead of libcpp_dotenv_shared.so) set_target_properties(cpp_dotenv_shared PROPERTIES OUTPUT_NAME cpp_dotenv) + # On Windows (MSVC), the import library would conflict with the static library. + # Add a suffix to the import library name to avoid this conflict. + if(MSVC) + set_target_properties(cpp_dotenv_shared PROPERTIES IMPORT_SUFFIX "_shared.lib") + endif() # Alias for backward compatibility: # When BUILD_BOTH_LIBRARIES is ON, the cpp_dotenv target is an alias to diff --git a/README.md b/README.md index 198f6f1..24a0a63 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ C++ implementation of NodeJS [dotenv](https://github.com/motdotla/dotenv) projec Supported build methods are: -- [CMake](#cmake) (>=3.10) +- [CMake](#cmake) (>=3.16) ### CMake