From 4ff152797d033bee3fcff746b5a5146b3d783aee Mon Sep 17 00:00:00 2001 From: Stephen Webb Date: Mon, 14 Aug 2023 09:43:57 +1000 Subject: [PATCH 1/3] Simplify CMake build configuration (#254) --- CMakeLists.txt | 10 -- src/cmake/boost-fallback/boost-fallback.cmake | 136 +----------------- .../boost-std-configuration.h.cmake | 18 --- src/main/cpp/CMakeLists.txt | 1 - 4 files changed, 6 insertions(+), 159 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7fce97b3b..a30364896 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -230,11 +230,6 @@ endif(LOG4CXX_QT_SUPPORT) # get_directory_property( HAS_LIBESMTP DIRECTORY src/main/include DEFINITION HAS_LIBESMTP ) get_directory_property( HAS_SYSLOG DIRECTORY src/main/include DEFINITION HAS_SYSLOG ) -get_directory_property( THREAD_IMPL DIRECTORY src DEFINITION THREAD_IMPL ) -get_directory_property( SMART_PTR_IMPL DIRECTORY src DEFINITION SMART_PTR_IMPL ) -get_directory_property( MUTEX_IMPL DIRECTORY src DEFINITION MUTEX_IMPL ) -get_directory_property( SHARED_MUTEX_IMPL DIRECTORY src DEFINITION SHARED_MUTEX_IMPL ) -get_directory_property( ATOMIC_IMPL DIRECTORY src DEFINITION ATOMIC_IMPL ) get_directory_property( FILESYSTEM_IMPL DIRECTORY src DEFINITION FILESYSTEM_IMPL ) get_directory_property( STD_MAKE_UNIQUE_IMPL DIRECTORY src DEFINITION STD_MAKE_UNIQUE_IMPL ) get_directory_property( STD_LIB_HAS_UNICODE_STRING DIRECTORY src DEFINITION STD_LIB_HAS_UNICODE_STRING ) @@ -310,12 +305,7 @@ message(STATUS " Qt support ...................... : ${LOG4CXX_QT_SUPPORT}") message(STATUS "C++ version and Boost settings:") message(STATUS " Prefer boost: ................... : ${PREFER_BOOST}") message(STATUS " make_unique implementation :..... : ${STD_MAKE_UNIQUE_IMPL}") -message(STATUS " thread implementation ........... : ${THREAD_IMPL}") message(STATUS " thread_local support? ........... : ${HAS_THREAD_LOCAL}") -message(STATUS " mutex implementation ............ : ${MUTEX_IMPL}") -message(STATUS " shared_ptr implementation ....... : ${SMART_PTR_IMPL}") -message(STATUS " shared_mutex implementation ..... : ${SHARED_MUTEX_IMPL}") -message(STATUS " atomic implementation ........... : ${ATOMIC_IMPL}") message(STATUS " filesystem implementation ....... : ${FILESYSTEM_IMPL}") if(BUILD_TESTING) diff --git a/src/cmake/boost-fallback/boost-fallback.cmake b/src/cmake/boost-fallback/boost-fallback.cmake index 1a0a8493c..93952a926 100644 --- a/src/cmake/boost-fallback/boost-fallback.cmake +++ b/src/cmake/boost-fallback/boost-fallback.cmake @@ -1,48 +1,4 @@ -#include(${CMAKE_MODULE_PATH}/FindPackageHandleStandardArgs.cmake) - -# Checks for classes in std::, falling back to boost if the requested -# classes are not available -# -# Available classes to check for: -# thread -# mutex -# shared_mutex -# filesystem -# -# Variables set: -# ${prefix}_ - -#function(_boost_fallback_thread) -# try_compile(HAS_STD_THREAD "${CMAKE_BINARY_DIR}/boost-fallback-compile-tests" -# "${CMAKE_CURRENT_LIST_DIR}/test-stdthread.cpp") - - -# find_package(boost_thread COMPONENTS thread) -#endfunction() - -## check for boost fallback instead of std:: classes -## arg1: prefix for variables to set -## arg2: list of classes to check for -#function(boost_fallback prefix classes) -#endfunction() - -# # This module checks for C++ standard classes and their boost counterparts -# -# Thread variables set: -# STD_THREAD_FOUND - if std::thread is found -# Boost_THREAD_FOUND - if boost::thread is found -# -# Mutex variables set: -# STD_MUTEX_FOUND - if std::mutex is found -# STD_SHARED_MUTEX_FOUND - if std::shared_mutex is found -# Boost_MUTEX_FOUND - if boost::mutex is found -# Boost_SHARED_MUTEX_FOUND - if boost::shared_mutex is found -# -# Smart pointer variables set: -# STD_SHARED_PTR_FOUND - if std::shared_ptr is found -# Boost_SHARED_PTR_FOUND - if boost::shared_ptr is found -# # Filesystem variables set: # STD_FILESYSTEM_FOUND - if std::filesystem is found # STD_EXPERIMENTAL_FILESYSTEM_FOUND - if std::experimental::filesystem is found @@ -50,101 +6,21 @@ include(FindThreads) -try_compile(STD_THREAD_FOUND "${CMAKE_BINARY_DIR}/boost-fallback-compile-tests" - "${CMAKE_CURRENT_LIST_DIR}/test-stdthread.cpp") -try_compile(STD_MUTEX_FOUND "${CMAKE_BINARY_DIR}/boost-fallback-compile-tests" - "${CMAKE_CURRENT_LIST_DIR}/test-stdmutex.cpp") -try_compile(STD_SHARED_MUTEX_FOUND "${CMAKE_BINARY_DIR}/boost-fallback-compile-tests" - "${CMAKE_CURRENT_LIST_DIR}/test-stdsharedmutex.cpp") -try_compile(STD_SHARED_PTR_FOUND "${CMAKE_BINARY_DIR}/boost-fallback-compile-tests" - "${CMAKE_CURRENT_LIST_DIR}/test-stdsharedptr.cpp") -try_compile(STD_ATOMIC_FOUND "${CMAKE_BINARY_DIR}/boost-fallback-compile-tests" - "${CMAKE_CURRENT_LIST_DIR}/test-stdatomic.cpp") try_compile(STD_FILESYSTEM_FOUND "${CMAKE_BINARY_DIR}/boost-fallback-compile-tests" "${CMAKE_CURRENT_LIST_DIR}/test-stdfilesystem.cpp") try_compile(STD_EXPERIMENTAL_FILESYSTEM_FOUND "${CMAKE_BINARY_DIR}/boost-fallback-compile-tests" "${CMAKE_CURRENT_LIST_DIR}/test-stdexpfilesystem.cpp") -# We need to have all three boost components in order to run our tests -# Boost thread requires chrono and atomic to work -find_package(Boost COMPONENTS thread chrono atomic) -if( ${Boost_FOUND} ) - try_compile(Boost_SHARED_PTR_FOUND "${CMAKE_BINARY_DIR}/boost-fallback-compile-tests" - "${CMAKE_CURRENT_LIST_DIR}/test-boostsharedptr.cpp") - try_compile(Boost_MUTEX_FOUND "${CMAKE_BINARY_DIR}/boost-fallback-compile-tests" - "${CMAKE_CURRENT_LIST_DIR}/test-boostmutex.cpp") - try_compile(Boost_SHARED_MUTEX_FOUND "${CMAKE_BINARY_DIR}/boost-fallback-compile-tests" - "${CMAKE_CURRENT_LIST_DIR}/test-boostsharedmutex.cpp" - LINK_LIBRARIES Threads::Threads Boost::thread) - try_compile(Boost_ATOMIC_FOUND "${CMAKE_BINARY_DIR}/boost-fallback-compile-tests" - "${CMAKE_CURRENT_LIST_DIR}/test-boostatomic.cpp") -endif( ${Boost_FOUND} ) - -find_package(Boost COMPONENTS filesystem) -if( ${Boost_FOUND} ) - try_compile(Boost_FILESYSTEM_FOUND "${CMAKE_BINARY_DIR}/boost-fallback-compile-tests" - "${CMAKE_CURRENT_LIST_DIR}/test-boostfilesystem.cpp") -endif( ${Boost_FOUND} ) - - -# Link the target with the appropriate boost libraries(if required) -function(boostfallback_link target) - if(NOT ${STD_THREAD_FOUND}) - if(${Boost_THREAD_FOUND}) - find_package(Boost COMPONENTS thread) - target_link_libraries( ${target} PUBLIC Boost::thread) - endif() - endif() - if(NOT ${STD_SHARED_MUTEX_FOUND}) - if(${Boost_SHARED_MUTEX_FOUND}) - find_package(Boost COMPONENTS thread) - target_link_libraries( ${target} PUBLIC Boost::thread) - endif() - endif() -endfunction() - # Check for standard headers that we need, fall back to boost if they're not found set(NAMESPACE_ALIAS log4cxx) option(PREFER_BOOST "Prefer Boost over std:: equivalents" OFF) -if( ${STD_THREAD_FOUND} AND NOT ${PREFER_BOOST} ) - set( THREAD_IMPL "std::thread" ) -elseif( ${Boost_THREAD_FOUND} ) - set( THREAD_IMPL "boost::thread" ) -else() - set( THREAD_IMPL "NONE" ) -endif() - -if( ${STD_MUTEX_FOUND} AND NOT ${PREFER_BOOST} ) - set( MUTEX_IMPL "std::mutex" ) -elseif( ${Boost_MUTEX_FOUND} ) - set( MUTEX_IMPL "boost::mutex" ) -else() - set( MUTEX_IMPL "NONE" ) -endif() - -if( ${STD_SHARED_PTR_FOUND} AND NOT ${PREFER_BOOST} ) - set( SMART_PTR_IMPL "std::shared_ptr" ) -elseif( ${Boost_SHARED_PTR_FOUND} ) - set( SMART_PTR_IMPL "boost::shared_ptr" ) -else() - set( SMART_PTR_IMPL "NONE" ) -endif() - -if( ${STD_SHARED_MUTEX_FOUND} AND NOT ${PREFER_BOOST} ) - set( SHARED_MUTEX_IMPL "std::shared_mutex" ) -elseif( ${Boost_SHARED_MUTEX_FOUND} ) - set( SHARED_MUTEX_IMPL "boost::shared_mutex" ) -else() - set( SHARED_MUTEX_IMPL "NONE" ) -endif() - -if( ${STD_ATOMIC_FOUND} AND NOT ${PREFER_BOOST} ) - set( ATOMIC_IMPL "std::atomic" ) -elseif( ${Boost_ATOMIC_FOUND} ) - set( ATOMIC_IMPL "boost::atomic" ) -else() - set( ATOMIC_IMPL "NONE" ) +if( ${PREFER_BOOST} OR NOT ( ${STD_FILESYSTEM_FOUND} OR ${STD_EXPERIMENTAL_FILESYSTEM_FOUND} ) ) + find_package(Boost COMPONENTS filesystem) + if( ${Boost_FOUND} ) + try_compile(Boost_FILESYSTEM_FOUND "${CMAKE_BINARY_DIR}/boost-fallback-compile-tests" + "${CMAKE_CURRENT_LIST_DIR}/test-boostfilesystem.cpp") + endif( ${Boost_FOUND} ) endif() if( ${STD_FILESYSTEM_FOUND} AND NOT ${PREFER_BOOST} ) diff --git a/src/cmake/boost-fallback/boost-std-configuration.h.cmake b/src/cmake/boost-fallback/boost-std-configuration.h.cmake index 9ccf8fd90..a56b21ff4 100644 --- a/src/cmake/boost-fallback/boost-std-configuration.h.cmake +++ b/src/cmake/boost-fallback/boost-std-configuration.h.cmake @@ -1,28 +1,10 @@ #ifndef BOOST_STD_CONFIGURATION_H #define BOOST_STD_CONFIGURATION_H -#cmakedefine01 STD_SHARED_MUTEX_FOUND -#cmakedefine01 Boost_SHARED_MUTEX_FOUND #cmakedefine01 STD_FILESYSTEM_FOUND #cmakedefine01 Boost_FILESYSTEM_FOUND #cmakedefine01 STD_EXPERIMENTAL_FILESYSTEM_FOUND -#if STD_SHARED_MUTEX_FOUND -#include -namespace ${NAMESPACE_ALIAS} { - typedef std::shared_mutex shared_mutex; - template - using shared_lock = std::shared_lock; -} -#elif Boost_SHARED_MUTEX_FOUND -#include -namespace ${NAMESPACE_ALIAS} { - typedef boost::shared_mutex shared_mutex; - template - using shared_lock = boost::shared_lock; -} -#endif - #if STD_FILESYSTEM_FOUND #include namespace ${NAMESPACE_ALIAS} { diff --git a/src/main/cpp/CMakeLists.txt b/src/main/cpp/CMakeLists.txt index e4aa0ce17..be2dc4e00 100644 --- a/src/main/cpp/CMakeLists.txt +++ b/src/main/cpp/CMakeLists.txt @@ -206,7 +206,6 @@ set_target_properties(log4cxx PROPERTIES VERSION ${LIBLOG4CXX_LIB_VERSION} SOVERSION ${LIBLOG4CXX_LIB_SOVERSION} ) -boostfallback_link(log4cxx) get_directory_property( FILESYSTEM_IMPL DIRECTORY "${LOG4CXX_SOURCE_DIR}/src/main/include" DEFINITION FILESYSTEM_IMPL ) if("${FILESYSTEM_IMPL}" STREQUAL "std::filesystem" OR "${FILESYSTEM_IMPL}" STREQUAL "std::experimental::filesystem" ) From 002bf0408fc3074537e36d34ba85405f6ae73849 Mon Sep 17 00:00:00 2001 From: Stephen Webb Date: Mon, 14 Aug 2023 15:05:05 +1000 Subject: [PATCH 2/3] Create a 'Build' top level nav-panel documentation section (#255) * Create a 'Build' top level nav-panel documentation section * Update environments used in testing * 'Usage' -> 'Use', matching other verbs in the nav-panel --- src/site/markdown/1-usage.md | 2 +- src/site/markdown/4-build.md | 29 ++++++++++ .../{3-development.md => 6-development.md} | 6 +- src/site/markdown/development/build-cmake.md | 34 +++-------- src/site/markdown/development/building.md | 14 ++++- src/site/markdown/development/dependencies.md | 56 +++++++++++++------ src/site/markdown/library-design.md | 2 +- 7 files changed, 92 insertions(+), 51 deletions(-) create mode 100644 src/site/markdown/4-build.md rename src/site/markdown/{3-development.md => 6-development.md} (88%) diff --git a/src/site/markdown/1-usage.md b/src/site/markdown/1-usage.md index ee88b2e29..76098f432 100644 --- a/src/site/markdown/1-usage.md +++ b/src/site/markdown/1-usage.md @@ -1,4 +1,4 @@ -Usage {#usage-overview} +Use {#usage-overview} === + + +See the following pages for information on building Log4cxx: + +* @subpage building +* @subpage dependencies +* @subpage build-cmake +* @subpage build-vcpkg diff --git a/src/site/markdown/3-development.md b/src/site/markdown/6-development.md similarity index 88% rename from src/site/markdown/3-development.md rename to src/site/markdown/6-development.md index 989943367..a1bf9a8d3 100644 --- a/src/site/markdown/3-development.md +++ b/src/site/markdown/6-development.md @@ -1,4 +1,4 @@ -Development {#development-overview} +Develop {#development-overview} === - -# Building Apache Log4cxx with CMake +[TOC] ## Quick start: @@ -43,22 +42,22 @@ $ sudo make install Windows Example: Building and testing Log4cxx on a Microsoft Windows with APR, Expat and APR-Util built from source -extracted into apr-1.7.0, libexpat(from github) and apr-util-1.6.1 in %HOMEPATH%/Libraries. +extracted into apr-1.7.4, libexpat(from github) and apr-util-1.6.3 in %HOMEPATH%/Libraries. ~~~ $ cd %HOMEPATH%/Libraries $ cmake -S libexpat/expat -B buildtrees/expat -DCMAKE_INSTALL_PREFIX=%HOMEPATH%/Libraries/installed $ cmake --build buildtrees/expat --target install --config Release -$ cmake -S apr-1.7.0 -B buildtrees/apr -DCMAKE_INSTALL_PREFIX=%HOMEPATH%/Libraries/installed +$ cmake -S apr-1.7.4 -B buildtrees/apr -DCMAKE_INSTALL_PREFIX=%HOMEPATH%/Libraries/installed $ cmake --build buildtrees/apr --target install --config Release $ set CMAKE_PREFIX_PATH=%HOMEPATH%/Libraries/installed -$ cmake -S apr-util-1.6.1 -B buildtrees/apr-util -DCMAKE_INSTALL_PREFIX=%HOMEPATH%/Libraries/installed +$ cmake -S apr-util-1.6.3 -B buildtrees/apr-util -DCMAKE_INSTALL_PREFIX=%HOMEPATH%/Libraries/installed $ cmake --build buildtrees/apr-util --target install --config Release $ cmake -S apache-Log4cxx-x.x.x -B buildtrees/Log4cxx -DCMAKE_INSTALL_PREFIX=%HOMEPATH%/Libraries/installed $ cmake --build buildtrees/Log4cxx --target install --config Release ~~~ -## ccmake options +## CMake options | Option | Usage | |------------------------|-------| @@ -73,21 +72,6 @@ $ cmake --build buildtrees/Log4cxx --target install --config Release | -DPREFER_BOOST=on | Prefer the Boost version of dependent libraries over standard library | | -DLOG4CXX_QT_SUPPORT=ON | Enable QString API and log4cxx::qt namespace methods, requires QtCore, choice of ON, OFF (default). | -## A note on C++ version and Boost - -By default, Log4cxx attempts to use at least C++17 to compile. This is to -avoid 3rd party dependencies as much as possible. If C++17 is not -available, a search for Boost will be taken and those libaries will be used -instead. If you would prefer to use Boost, there are two options you have: - -1. Pass `-DPREFER_BOOST=ON` to CMake when compiling. This will ignore the - results of the tests that check for the standard version of components that - are required. Note that this will switch all components, regardless of the - C++ version in effect at compile time. -2. Revert to an earlier standard using `-DCMAKE_CXX_STANDARD=11` for example. - This will still to check for standard versions of required components, but - it will fall back to using Boost for newer components added in C++17. - # Platform specific notes: ## Mac OS/X: @@ -107,9 +91,9 @@ $ sudo apt-get install libssl-dev libapr1-dev libaprutil1-dev gzip zip CMake can be built from source by typing: ~~~ -$ wget https://github.com/Kitware/CMake/releases/download/v3.16.4/cmake-3.16.4.tar.gz -$ tar xf cmake-3.16.4.tar.gz -$ cd cmake-3.16.4 +$ wget https://github.com/Kitware/CMake/releases/download/v3.27.2/cmake-3.27.2.tar.gz +$ tar xf cmake-3.27.2.tar.gz +$ cd cmake-3.27.2 $ ./bootstrap $ make $ sudo make install diff --git a/src/site/markdown/development/building.md b/src/site/markdown/development/building.md index abc696c6e..6aab32c77 100644 --- a/src/site/markdown/development/building.md +++ b/src/site/markdown/development/building.md @@ -29,6 +29,17 @@ information. If you have trouble building, either create an issue in [Jira](https://issues.apache.org/jira/projects/LOGCXX/issues) or send a message to the [users mailing list]. +## Covered by Github + +These Github provided environments are +used in continuous integration and unit testing: + +* Windows - Visual Studio 2019 and 2022 +* Ubuntu 20.04 - GNU g++ 9.4.0, Clang 11.0.0 +* Ubuntu 22.04 - GNU g++ 11.4.0, Clang 14.0.0 +* MacOS 11 - AppleClang 13.0 +* MacOS 12 - AppleClang 14.0 + ## Covered by the team The following list provides an overview about the environments some of the @@ -38,8 +49,9 @@ something about how good the support on each platform is, it's just a guide. The following platforms/compilers are expected to work correctly: -* Windows 10(32 and 64-bit) - MSVC +* Windows 10(32 and 64-bit) - MSVC 2017, 2019 * Windows 10(32-bit) - Embarcadero C++ Builder XE 4 +* Windows 11(64-bit) - MSVC 2019, 2022 * Debian 10(32 and 64-bit) - gcc 8.3.0, clang-7 * Ubuntu 20.04(32 and 64-bit) - gcc, clang * Mac OSX - clang diff --git a/src/site/markdown/development/dependencies.md b/src/site/markdown/development/dependencies.md index 3b6641f0e..acf980e56 100644 --- a/src/site/markdown/development/dependencies.md +++ b/src/site/markdown/development/dependencies.md @@ -1,4 +1,4 @@ -Dependencies {#dependencies} +Log4cxx Dependencies {#dependencies} === - - -# Log4cxx Dependencies +[TOC] As of version 0.12.0, Log4cxx requires a minimum C++ version of C++11. -If C++17 is not available, then Log4cxx requires Boost Thread in order -to build, which in turn requires chrono and date\_time. -log4cxx requires the following software to build and/or run correctly: +Log4cxx requires the following software to build and/or run correctly: |Dependency Name|Version|Dependency Type|Homepage| |---------------|-------|---------------|--------| |Apache Portable Runtime(APR)|>=1.5.4|Compile/Runtime|https://apr.apache.org |APR-Util |>=1.5.4|Compile/Runtime|https://apr.apache.org -|Boost |any? |Compile/runtime. Not required if your compiler supports C++17|https://boost.org |gzip |any |Test/Runtime(optional)|https://gzip.org |sed |any |Test|N/A |zip |any |Test/Runtime(optional)|N/A -|log4j |1.2.14 |Test |https://http://logging.apache.org/log4j/2.x/ -|java |>=6 |Test |https://adoptopenjdk.net ## APR+APR-Util @@ -58,15 +51,42 @@ MinGW, cygwin, or MSYS2. `gzip` and `zip` only needed during runtime if you are compressing the log files, for example by setting a rollover policy which ends in `.gz` or `.zip`. -## log4j+Java +# Optional Dependencies + +The following table lists CMake options that require additional dependencies. + +|CMake option |Dependency Name|Version| Dependency Type | Homepage| +|---------------|---------------| :---: |---------------|--------| +|LOG4CXX_MULTIPROCESS_ROLLING_FILE_APPENDER |Boost | any | Compile/runtime. Not required if your compiler supports C++17 | https://boost.org | +|ENABLE_FMT_LAYOUT | {fmt} | 9+ | Compile/runtime | https://github.com/fmtlib/fmt | +|LOG4CXX_ENABLE_ODBC | unixodbc | any | Compile/runtime (not on Windows) | https://www.unixodbc.org/ | +|LOG4CXX_ENABLE_ESMTP | libesmtp | any | Compile/runtime (not on Windows) | https://github.com/libesmtp/libESMTP | +|LOG4CXX_QT_SUPPORT |Qt | 5 | Compile/runtime | https://www.qt.io/download | +|LOG4CXX_CFSTRING | Mac OS/X Core Foundation | any | Compile/runtime | https://developer.apple.com/documentation/corefoundation | + +## A note on C++ version and Boost + +By default, Log4cxx requests C++20 features. This is to +avoid 3rd party dependencies as much as possible. If C++17 is not +available, a search for Boost will be taken and those libraries will be used +instead. If you would prefer to use Boost, there are two options you have: -log4j and Java are needed to run some tests to ensure that log4cxx has binary compatability with -log4j. Note that the correct binary for log4j will be downloaded and used automatically if CMAKE is -used to build the project, otherwise one needs to get that manually. Java needs to be installed on -the system already in all cases, but with CMAKE again, if it's not, the corresponding tests are -skipped entirely automatically. +1. Pass `-DPREFER_BOOST=ON` to CMake when compiling. This will ignore the + results of the tests that check for the standard version of components that + are required. Note that this will switch all components, regardless of the + C++ version in effect at compile time. +2. Revert to an earlier standard using `-DCMAKE_CXX_STANDARD=11` for example. + This will still to check for standard versions of required components, but + it will fall back to using Boost for newer components added in C++17. # Licenses(direct dependencies only) -**Apache License, Version 2.0**: log4cxx, APR, APR-util -**Boost License, Version 1.0**: boost +| Dependency | License | +|------------|---------| +| APR, APR-util | **Apache License, Version 2.0** | +| Boost | **Boost License, Version 1.0** | +| {fmt} | **MIT** | +| unixodbc | **LGPL** | +| libesmtp | **LGPL** | +| Qt | Refer https://www.qt.io/licensing/ | +| Mac OS/X Core Foundation | **APSL 2.0** | \ No newline at end of file diff --git a/src/site/markdown/library-design.md b/src/site/markdown/library-design.md index 9d673c5f2..5f4649e99 100644 --- a/src/site/markdown/library-design.md +++ b/src/site/markdown/library-design.md @@ -1,4 +1,4 @@ -# Library Design Notes {#library-design} +Library Design Notes {#library-design} ===