Skip to content
Open
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
98 changes: 83 additions & 15 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#----------------------- PROJECT CONFIGURATION --------------------------------
cmake_minimum_required(VERSION 3.10)
cmake_minimum_required(VERSION 3.16)
project(cpp-dotenv VERSION 1.0.0)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

if ("${CMAKE_BUILD_TYPE}" STREQUAL "")
Expand All @@ -12,36 +12,104 @@ 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)

# 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()

# 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)
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 - handle MSVC vs GCC/Clang
if (MSVC)
# MSVC-specific flags
if ("${CMAKE_BUILD_TYPE}" STREQUAL "DEBUG")
set(CPP_DOTENV_COMPILE_OPTIONS /W4 /Od)
else()
set(CPP_DOTENV_COMPILE_OPTIONS /W4 /O2)
endif()
else()
# GCC/Clang and other compilers using Unix-style flags
if ("${CMAKE_BUILD_TYPE}" STREQUAL "DEBUG")
set(CPP_DOTENV_COMPILE_OPTIONS -g -Wall -O0)
else()
set(CPP_DOTENV_COMPILE_OPTIONS -O3)
endif()
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})
# Set output name to libcpp_dotenv.a (instead of libcpp_dotenv_static.a)
set_target_properties(cpp_dotenv_static PROPERTIES OUTPUT_NAME cpp_dotenv)

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})
# Set output name. On non-MSVC platforms, both static and shared libraries use
# the same base name "cpp_dotenv". On MSVC, give the shared library a distinct
# base name to avoid conflicts between the static library (.lib) and the
# import library for the shared library (also .lib).
if(MSVC)
set_target_properties(cpp_dotenv_shared PROPERTIES OUTPUT_NAME cpp_dotenv_shared)
else()
set_target_properties(cpp_dotenv_shared PROPERTIES OUTPUT_NAME cpp_dotenv)
endif()

# 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)
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()
40 changes: 38 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ C++ implementation of NodeJS [dotenv](https://github.com/motdotla/dotenv) projec

Supported build methods are:

- [CMake](#cmake) (>=3.10)
- [CMake](#cmake) (>=3.16)

### 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)
Expand All @@ -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:
Expand Down
4 changes: 2 additions & 2 deletions common/libs/antlr4-cpp-runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.0.2)
cmake_minimum_required(VERSION 3.16)
project(antlr4-cpp-runtime VERSION 4.8)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

if ("${CMAKE_BUILD_TYPE}" STREQUAL "")
Expand Down
13 changes: 11 additions & 2 deletions include/dotenv.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace dotenv

public:

dotenv& load_dotenv(const std::string& dotenv_path = env_filename,
dotenv& load_dotenv(const std::string& dotenv_path = ".env",
const bool overwrite = false,
const bool interpolate = true);

Expand All @@ -28,18 +28,27 @@ namespace dotenv
void operator=(const dotenv&) = delete;

static dotenv& instance();

private:

dotenv() = default;

private:

// Declare static members (definitions are inline after the class)
// NOTE: env_filename is kept for backward compatibility; external code
// may reference dotenv::dotenv::env_filename directly.
static const std::string env_filename;
static dotenv _instance;

};


// C++17 inline variable definitions after class is complete
// Note: _instance cannot be inline inside the class due to incomplete type
inline const std::string dotenv::env_filename = ".env";
inline dotenv dotenv::_instance;


extern dotenv& env;
}
2 changes: 1 addition & 1 deletion src/common/logger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ bool logger::position::operator<(const position& p) const
}


bool logger::position::less::operator()(const position& p1, const position& p2)
bool logger::position::less::operator()(const position& p1, const position& p2) const
{
return p1 < p2;
}
Expand Down
2 changes: 1 addition & 1 deletion src/common/logger.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ namespace dotenv

struct less
{
bool operator()(const position& p1, const position& p2);
bool operator()(const position& p1, const position& p2) const;
};

public:
Expand Down
18 changes: 10 additions & 8 deletions src/dotenv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@


using namespace std;
using namespace dotenv;


dotenv::dotenv& dotenv::dotenv::load_dotenv(const string& dotenv_path, const bool overwrite, const bool interpolate)
// Type alias to work around the fact that class name matches namespace name
// This is a known C++ limitation when defining out-of-line members
typedef class ::dotenv::dotenv DotenvClass;


DotenvClass& ::dotenv::dotenv::load_dotenv(const string& dotenv_path, const bool overwrite, const bool interpolate)
{
ifstream env_file;
env_file.open(dotenv_path);
Expand All @@ -27,19 +31,17 @@ dotenv::dotenv& dotenv::dotenv::load_dotenv(const string& dotenv_path, const boo
}


const dotenv::dotenv::value_type dotenv::dotenv::operator[](const key_type& k) const
const string DotenvClass::operator[](const key_type& k) const
{
return getenv(k).second;
}


dotenv::dotenv& dotenv::dotenv::instance()
DotenvClass& ::dotenv::dotenv::instance()
{
return _instance;
}


const string dotenv::dotenv::env_filename = ".env";
dotenv::dotenv dotenv::dotenv::_instance;

dotenv::dotenv& dotenv::env = dotenv::instance();
// Define the global 'env' reference. Static members are inline in the header (C++17).
::dotenv::dotenv& ::dotenv::env = ::dotenv::dotenv::instance();