### Build Examples with CMake Source: https://github.com/ph3at/libenvpp/blob/main/CMakeLists.txt Automatically discovers and builds all C++ files in the examples directory when LIBENVPP_EXAMPLES is enabled. ```cmake if(LIBENVPP_EXAMPLES) file(GLOB_RECURSE LIBENVPP_EXAMPLES_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/examples/*.cpp") foreach(LIBENVPP_EXAMPLE_SOURCE ${LIBENVPP_EXAMPLES_SOURCES}) get_filename_component(LIBENVPP_EXAMPLE_TARGET ${LIBENVPP_EXAMPLE_SOURCE} NAME_WE) add_executable(${LIBENVPP_EXAMPLE_TARGET} "${LIBENVPP_EXAMPLE_SOURCE}") libenvpp_set_compiler_parameters(${LIBENVPP_EXAMPLE_TARGET}) target_link_libraries(${LIBENVPP_EXAMPLE_TARGET} PRIVATE libenvpp) endforeach() endif() ``` -------------------------------- ### Configure Installation Targets Source: https://github.com/ph3at/libenvpp/blob/main/CMakeLists.txt Sets up installation rules for headers, libraries, and CMake package configuration files. ```cmake if(LIBENVPP_INSTALL) # Libenvpp installation. include(CMakePackageConfigHelpers) set(LIBENVPP_PROJECT_CONFIG_OUT "${CMAKE_CURRENT_BINARY_DIR}/libenvpp-config.cmake") set(LIBENVPP_VERSION_CONFIG_FILE "${CMAKE_CURRENT_BINARY_DIR}/libenvpp-config-version.cmake") install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/ DESTINATION include ) install(TARGETS libenvpp EXPORT libenvpp LIBRARY DESTINATION lib ARCHIVE DESTINATION lib INCLUDES DESTINATION include ) install(EXPORT libenvpp DESTINATION lib/cmake/libenvpp NAMESPACE libenvpp:: FILE libenvpp-config-targets.cmake ) configure_package_config_file(cmake/libenvpp-config.cmake.in "${LIBENVPP_PROJECT_CONFIG_OUT}" INSTALL_DESTINATION lib/cmake/libenvpp ) write_basic_package_version_file("${LIBENVPP_VERSION_CONFIG_FILE}" VERSION ${LIBENVPP_VERSION} COMPATIBILITY SameMajorVersion ) install(FILES "${LIBENVPP_PROJECT_CONFIG_OUT}" "${LIBENVPP_VERSION_CONFIG_FILE}" DESTINATION lib/cmake/libenvpp ) endif() ``` -------------------------------- ### Integrate Libenvpp with CMake FetchContent Source: https://github.com/ph3at/libenvpp/blob/main/README.md Integrates libenvpp into a CMake project using the FetchContent mechanism. Ensure LIBENVPP_INSTALL is set if installation is desired. ```cmake set(LIBENVPP_INSTALL ON CACHE BOOL "" FORCE) # If installation is desired. FetchContent_Declare(libenvpp GIT_REPOSITORY https://github.com/ph3at/libenvpp.git GIT_TAG v1.5.2 ) FetchContent_MakeAvailable(libenvpp) # ... target_link_libraries(myproject PUBLIC libenvpp::libenvpp ) ``` -------------------------------- ### Handling Deprecated Variables in C++ Source: https://context7.com/ph3at/libenvpp/llms.txt Register deprecated environment variables to guide users during migration. Provide a clear message indicating the replacement variable. ```cpp #include #include #include #include int main() { auto pre = env::prefix("MYPROG"); // Register deprecated variable with migration message pre.register_deprecated( "LOG_FILE_PATH", "has been deprecated since v2.0, use 'MYPROG_LOG_FILE' instead" ); // Register the new replacement variable const auto log_file_id = pre.register_variable("LOG_FILE"); const auto parsed_and_validated_pre = pre.parse_and_validate(); if (parsed_and_validated_pre.ok()) { const auto log_file = parsed_and_validated_pre.get_or(log_file_id, "/default/log/file"); std::cout << "Log file: " << log_file << std::endl; } else { std::cout << parsed_and_validated_pre.warning_message(); std::cout << parsed_and_validated_pre.error_message(); } return EXIT_SUCCESS; } // Using deprecated variable: // $ MYPROG_LOG_FILE_PATH=/var/log/old.log ./example // Error : Validation error for environment variable 'MYPROG_LOG_FILE_PATH': has been deprecated since v2.0, use 'MYPROG_LOG_FILE' instead // Using new variable: // $ MYPROG_LOG_FILE=/var/log/app.log ./example // Log file: /var/log/app.log ``` -------------------------------- ### Configure CMake for Libenvpp Dependency Source: https://github.com/ph3at/libenvpp/blob/main/README.md Configures a CMake project to find and use libenvpp as a dependency. This is typically used in a myproject-config.cmake.in file when installation is desired. ```cmake # ... include(CMakeFindDependencyMacro) find_dependency(libenvpp REQUIRED) # ... ``` -------------------------------- ### Basic Environment Variable Parsing Source: https://github.com/ph3at/libenvpp/blob/main/README.md Demonstrates registering, parsing, and validating environment variables with a prefix. Use this for standard environment variable management. ```cpp #include #include #include #include int main() { auto pre = env::prefix("MYPROG"); const auto log_path_id = pre.register_variable("LOG_FILE_PATH"); const auto num_threads_id = pre.register_required_variable("NUM_THREADS"); const auto parsed_and_validated_pre = pre.parse_and_validate(); if (parsed_and_validated_pre.ok()) { const auto log_path = parsed_and_validated_pre.get_or(log_path_id, "/default/log/path"); const auto num_threads = parsed_and_validated_pre.get(num_threads_id); std::cout << "Log path : " << log_path << std::endl; std::cout << "Num threads: " << num_threads << std::endl; } else { std::cout << parsed_and_validated_pre.warning_message(); std::cout << parsed_and_validated_pre.error_message(); } return EXIT_SUCCESS; } ``` -------------------------------- ### Console Output With Both Variables Set Source: https://github.com/ph3at/libenvpp/blob/main/README.md Shows the successful output when both environment variables are correctly set. ```console $ MYPROG_LOG_FILE_PATH=/var/log/file MYPROG_NUM_THREADS=4 ./libenvpp_simple_usage_example Log path : "/var/log/file" Num threads: 4 ``` -------------------------------- ### Generate Help Message for Environment Variables Source: https://github.com/ph3at/libenvpp/blob/main/README.md Generates a formatted help message for environment variables registered under a specific prefix. It lists each variable, indicating whether it is required or optional. ```cpp auto pre = env::prefix("MYPROG"); const auto log_path_id = pre.register_variable("LOG_FILE_PATH"); const auto num_threads_id = pre.register_required_variable("NUM_THREADS"); std::cout << pre.help_message(); ``` -------------------------------- ### Register environment variables Source: https://github.com/ph3at/libenvpp/blob/main/README.md Define a prefix and register variables as optional or required. ```cpp auto pre = env::prefix("MYPROG"); const auto log_path_id = pre.register_variable("LOG_FILE_PATH"); const auto num_threads_id = pre.register_required_variable("NUM_THREADS"); ``` -------------------------------- ### Parse and validate environment variables Source: https://github.com/ph3at/libenvpp/blob/main/README.md Execute the parsing and validation process after registration. ```cpp const auto parsed_and_validated_pre = pre.parse_and_validate(); ``` -------------------------------- ### Console Output With Required Variable Set Source: https://github.com/ph3at/libenvpp/blob/main/README.md Demonstrates the output when only the required environment variable is provided. ```console $ MYPROG_NUM_THREADS=4 ./libenvpp_simple_usage_example Log path : "/default/log/path" Num threads: 4 ``` -------------------------------- ### Generate Help Messages in C++ Source: https://context7.com/ph3at/libenvpp/llms.txt Automatically generate formatted help messages for your application's environment variables. This includes listing all registered variables and their status (required/optional). ```cpp #include #include #include #include int main(int argc, char* argv[]) { auto pre = env::prefix("MYAPP"); const auto log_path_id = pre.register_variable("LOG_PATH"); const auto num_threads_id = pre.register_required_variable("NUM_THREADS"); const auto debug_id = pre.register_variable("DEBUG"); const auto timeout_id = pre.register_range("TIMEOUT_MS", 100, 30000); // Print help if requested if (argc > 1 && std::string(argv[1]) == "--help") { std::cout << pre.help_message(); return EXIT_SUCCESS; } const auto parsed_and_validated_pre = pre.parse_and_validate(); if (!parsed_and_validated_pre.ok()) { std::cout << parsed_and_validated_pre.error_message(); std::cout << "\nUsage:" std::cout << parsed_and_validated_pre.help_message(); return EXIT_FAILURE; } return EXIT_SUCCESS; } // $ ./example --help // Prefix 'MYAPP_' supports the following 4 environment variable(s): // 'MYAPP_LOG_PATH' optional // 'MYAPP_NUM_THREADS' required // 'MYAPP_DEBUG' optional // 'MYAPP_TIMEOUT_MS' optional ``` -------------------------------- ### Configure Unit Tests with CMake Source: https://github.com/ph3at/libenvpp/blob/main/CMakeLists.txt Defines the test executable and links necessary dependencies when LIBENVPP_TESTS is enabled. ```cmake if(LIBENVPP_TESTS) include(CTest) include(Catch) add_executable(libenvpp_tests "test/levenshtein_test.cpp" "test/libenvpp_environment_test.cpp" "test/libenvpp_parser_test.cpp" "test/libenvpp_test.cpp" "test/libenvpp_testing_test.cpp" ) libenvpp_set_compiler_parameters(libenvpp_tests) target_link_libraries(libenvpp_tests PRIVATE libenvpp Catch2::Catch2WithMain) # Set test as VS startup if libenvpp is master project. if(LIBENVPP_MASTER_PROJECT) set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT libenvpp_tests) endif() catch_discover_tests(libenvpp_tests) endif() ``` -------------------------------- ### Handle Errors and Warnings with Parsed Prefix Source: https://context7.com/ph3at/libenvpp/llms.txt Access detailed error and warning information programmatically after parsing environment variables. This is useful for implementing robust error handling in your application. ```cpp #include #include #include int main() { auto pre = env::prefix("CONFIG"); const auto port_id = pre.register_required_range("PORT", 1, 65535); const auto timeout_id = pre.register_range("TIMEOUT", 1, 3600); const auto parsed_pre = pre.parse_and_validate(); // Check if there are any errors or warnings if (!parsed_pre.ok()) { // Get formatted messages std::cout << parsed_pre.warning_message(); std::cout << parsed_pre.error_message(); // Access individual errors programmatically for (const auto& err : parsed_pre.errors()) { std::cerr << "Error ID: " << err.get_id() << std::endl; std::cerr << "Variable: " << err.get_name() << std::endl; std::cerr << "Message: " << err.what() << std::endl; } // Access individual warnings for (const auto& warn : parsed_pre.warnings()) { std::cerr << "Warning for: " << warn.get_name() << std::endl; std::cerr << "Message: " << warn.what() << std::endl; } return EXIT_FAILURE; } const auto port = parsed_pre.get(port_id); const auto timeout = parsed_pre.get_or(timeout_id, 30); std::cout << "Port: " << port << ", Timeout: " << timeout << std::endl; return EXIT_SUCCESS; } // $ CONFIG_PROT=8080 ./example // Warning: Unrecognized environment variable 'CONFIG_PROT' set, did you mean 'CONFIG_PORT'? // Error : Environment variable 'CONFIG_PORT' not set ``` -------------------------------- ### Include libenvpp header Source: https://github.com/ph3at/libenvpp/blob/main/README.md Include the main header file to access the library functionality. ```cpp #include ``` -------------------------------- ### Accessing Prefixless Environment Variables in C++ Source: https://context7.com/ph3at/libenvpp/llms.txt Use standalone env::get and env::get_or functions for direct access to environment variables without prefix registration. ```cpp #include #include #include #include int main() { // Get optional variable with default value const auto log_path = env::get_or("LOG_FILE_PATH", "/default/log/path"); // Get required variable - returns expected const auto num_threads = env::get("NUM_THREADS"); if (num_threads.has_value()) { std::cout << "Log path : " << log_path << std::endl; std::cout << "Num threads: " << num_threads.value() << std::endl; } else { // Access error information std::cout << num_threads.error().what() << std::endl; } return EXIT_SUCCESS; } ``` -------------------------------- ### Custom Environment Source: https://github.com/ph3at/libenvpp/blob/main/README.md Passing a custom map to override system environment variables during parsing. ```APIDOC ## Custom Environment ### Description Allows passing a `std::unordered_map` to `prefix::parse_and_validate` to act as the source for environment variables instead of the system environment. ``` -------------------------------- ### Registering Variables with a Prefix in C++ Source: https://context7.com/ph3at/libenvpp/llms.txt Use env::prefix to group variables under a common namespace, enabling automatic validation and typo detection. ```cpp #include #include #include #include int main() { // Create a prefix - all variables will start with "MYPROG_" auto pre = env::prefix("MYPROG"); // Register an optional variable (no error if not set) const auto log_path_id = pre.register_variable("LOG_FILE_PATH"); // Register a required variable (error if not set) const auto num_threads_id = pre.register_required_variable("NUM_THREADS"); // Parse and validate all registered variables const auto parsed_and_validated_pre = pre.parse_and_validate(); if (parsed_and_validated_pre.ok()) { // Get optional variable with default value const auto log_path = parsed_and_validated_pre.get_or(log_path_id, "/default/log/path"); // Get required variable (returns value directly) const auto num_threads = parsed_and_validated_pre.get(num_threads_id); std::cout << "Log path : " << log_path << std::endl; std::cout << "Num threads: " << num_threads << std::endl; } else { std::cout << parsed_and_validated_pre.warning_message(); std::cout << parsed_and_validated_pre.error_message(); } return EXIT_SUCCESS; } ``` -------------------------------- ### Console Output Without Environment Variables Source: https://github.com/ph3at/libenvpp/blob/main/README.md Shows the error output when required environment variables are not set. ```console $ ./libenvpp_simple_usage_example Error : Environment variable 'MYPROG_NUM_THREADS' not set ``` -------------------------------- ### Console Output With Typo in Environment Variable Source: https://github.com/ph3at/libenvpp/blob/main/README.md Illustrates the warning and error messages when an unrecognized environment variable is set, along with a missing required variable. ```console $ MYPROG_LOG_FILEPATH=/var/log/file ./libenvpp_simple_usage_example Warning: Unrecognized environment variable 'MYPROG_LOG_FILEPATH' set, did you mean 'MYPROG_LOG_FILE_PATH'? Error : Environment variable 'MYPROG_NUM_THREADS' not set ``` -------------------------------- ### Specialize env::default_parser for custom types Source: https://context7.com/ph3at/libenvpp/llms.txt Implement a custom parser by specializing env::default_parser. Throw env::parser_error if parsing fails. ```cpp #include #include #include #include #include #include #include static std::vector split(const std::string_view str, const char delimiter) { auto result = std::vector{}; auto sstream = std::istringstream(std::string(str)); auto item = std::string{}; while (std::getline(sstream, item, delimiter)) { result.push_back(std::move(item)); } return result; } struct server_config { std::string host; int port; }; // Specialize default_parser for custom type namespace env { template <> struct default_parser { server_config operator()(const std::string_view str) const { const auto parts = split(str, ':'); if (parts.size() != 2) { throw parser_error{"Expected format 'host:port'"}; } server_config config; config.host = parts[0]; // Delegate primitive parsing to built-in parser config.port = default_parser{}(parts[1]); if (config.port <= 0 || config.port > 65535) { throw parser_error{"Port must be between 1 and 65535"}; } return config; } }; } // namespace env int main() { auto pre = env::prefix("SERVER"); const auto config_id = pre.register_required_variable("CONFIG"); const auto parsed_and_validated_pre = pre.parse_and_validate(); if (parsed_and_validated_pre.ok()) { const auto config = parsed_and_validated_pre.get(config_id); std::cout << "Host: " << config.host << std::endl; std::cout << "Port: " << config.port << std::endl; } else { std::cout << parsed_and_validated_pre.error_message(); } return EXIT_SUCCESS; } ``` -------------------------------- ### Test with Custom Environment Map Source: https://context7.com/ph3at/libenvpp/llms.txt Use a custom environment map with `parse_and_validate()` for complete isolation from system environment variables during testing. This allows for precise control over the environment your code interacts with. ```cpp #include #include #include #include int main() { auto pre = env::prefix("APP"); const auto host_id = pre.register_required_variable("HOST"); const auto port_id = pre.register_required_variable("PORT"); // Custom environment - completely isolated from system std::unordered_map test_environment = { {"APP_HOST", "localhost"}, {"APP_PORT", "3000"}, }; // Parse using custom environment instead of system environment const auto parsed_pre = pre.parse_and_validate(test_environment); if (parsed_pre.ok()) { const auto host = parsed_pre.get(host_id); const auto port = parsed_pre.get(port_id); std::cout << "Connecting to " << host << ":" << port << std::endl; } return EXIT_SUCCESS; } // Output: Connecting to localhost:3000 ``` -------------------------------- ### Global Testing Environment Source: https://github.com/ph3at/libenvpp/blob/main/README.md Utility for mocking environment variables during unit tests using a scoped environment. ```APIDOC ## Global Testing Environment ### Description Allows temporary injection of key/value pairs into the environment. Variables are automatically removed when the `env::scoped_test_environment` object goes out of scope. ### Usage ```cpp const auto _ = env::scoped_test_environment({ {"MYPROG_LOG_FILE_PATH", "/dev/null"}, {"MYPROG_NUM_THREADS", "8"}, }); ``` ``` -------------------------------- ### Specialize env::default_validator for custom validation Source: https://context7.com/ph3at/libenvpp/llms.txt Implement custom validation by specializing env::default_validator. Throw env::validation_error on failure. ```cpp #include #include #include #include // Validate that paths must exist on the filesystem namespace env { template <> struct default_validator { void operator()(const std::filesystem::path& path) const { if (!std::filesystem::exists(path)) { throw validation_error{path.string() + " path does not exist"}; } } }; } // namespace env int main() { auto pre = env::prefix("APP"); // This path will be validated to exist const auto config_path_id = pre.register_variable("CONFIG_PATH"); const auto parsed_and_validated_pre = pre.parse_and_validate(); if (parsed_and_validated_pre.ok()) { auto path = parsed_and_validated_pre.get(config_path_id); if (path.has_value()) { std::cout << "Config path: " << *path << std::endl; } else { std::cout << "Using default config" << std::endl; } } else { std::cout << parsed_and_validated_pre.error_message(); } return EXIT_SUCCESS; } ``` -------------------------------- ### Register Option Variables with libenvpp Source: https://context7.com/ph3at/libenvpp/llms.txt Register variables that must match one of a predefined set of options. Supports both string-mapped options and parsed enum values. Use `register_option` for optional variables and `register_required_option` for mandatory ones. ```cpp #include #include #include #include #include enum class log_level { debug, info, warning, error, }; // Option with string mapping - no parser needed enum class output_format { json, xml, text, }; int main() { auto pre = env::prefix("APP"); // Option with explicit string-to-value mapping const auto format_id = pre.register_option( "OUTPUT_FORMAT", {{"json", output_format::json}, {"xml", output_format::xml}, {"text", output_format::text}} ); // Required option with string mapping const auto level_id = pre.register_required_option( "LOG_LEVEL", {{"debug", log_level::debug}, {"info", log_level::info}, {"warning", log_level::warning}, {"error", log_level::error}} ); const auto parsed_and_validated_pre = pre.parse_and_validate(); if (parsed_and_validated_pre.ok()) { const auto format = parsed_and_validated_pre.get_or(format_id, output_format::text); const auto level = parsed_and_validated_pre.get(level_id); std::cout << "Output format: " << static_cast(format) << std::endl; std::cout << "Log level: " << static_cast(level) << std::endl; } else { std::cout << parsed_and_validated_pre.warning_message(); std::cout << parsed_and_validated_pre.error_message(); } return EXIT_SUCCESS; } // $ APP_LOG_LEVEL=info ./example // Output format: 2 // Log level: 1 // $ APP_OUTPUT_FORMAT=yaml APP_LOG_LEVEL=info ./example // Error : Option error for environment variable 'APP_OUTPUT_FORMAT': Unrecognized option 'yaml', should be one of [json, xml, text] ``` -------------------------------- ### Handle parsing and validation errors Source: https://github.com/ph3at/libenvpp/blob/main/README.md Check the status of the parsed environment and retrieve error or warning messages. ```cpp if (!parsed_and_validated_pre.ok()) { std::cout << parsed_and_validated_pre.warning_message(); std::cout << parsed_and_validated_pre.error_message(); } ``` -------------------------------- ### Parse Prefixless Environment Variables Source: https://github.com/ph3at/libenvpp/blob/main/README.md Parses environment variables directly without a namespace prefix. Supports required variables using `env::get` and optional variables with a default value using `env::get_or`. ```cpp #include #include #include #include int main() { const auto log_path = env::get_or("LOG_FILE_PATH", "/default/log/path"); const auto num_threads = env::get("NUM_THREADS"); if (num_threads.has_value()) { std::cout << "Log path : " << log_path << std::endl; std::cout << "Num threads: " << num_threads.value() << std::endl; } else { std::cout << num_threads.error().what() << std::endl; } return EXIT_SUCCESS; } ``` -------------------------------- ### Bypass Parsing with set_for_testing Source: https://context7.com/ph3at/libenvpp/llms.txt Use set_for_testing to manually inject values into a prefix, bypassing standard environment parsing and validation for unit testing. ```cpp #include #include #include #include int main() { auto pre = env::prefix("MYPROG"); const auto log_path_id = pre.register_variable("LOG_FILE_PATH"); const auto num_threads_id = pre.register_required_variable("NUM_THREADS"); // Directly set values - bypasses parsing and validation pre.set_for_testing(log_path_id, std::filesystem::path{"/test/log/path"}); pre.set_for_testing(num_threads_id, 16u); const auto parsed_and_validated_pre = pre.parse_and_validate(); // Values are already set, parsing is skipped for these variables const auto log_path = parsed_and_validated_pre.get_or(log_path_id, "/default"); const auto num_threads = parsed_and_validated_pre.get(num_threads_id); std::cout << "Log path : " << log_path << std::endl; // /test/log/path std::cout << "Num threads: " << num_threads << std::endl; // 16 return EXIT_SUCCESS; } ``` -------------------------------- ### Register Enum Option Variable Source: https://github.com/ph3at/libenvpp/blob/main/README.md Registers an environment variable with a predefined set of string options that map to an enum class. A fallback option can be provided for when the variable is not set. ```cpp enum class option { first, second, fallback, }; int main() { auto pre = env::prefix("OPTION"); const auto option_id = pre.register_option