From 0458f28243708342cfc690e9b02a2c08022926b8 Mon Sep 17 00:00:00 2001
From: alandefreitas <alandefreitas@gmail.com>
Date: Thu, 8 Jun 2023 14:58:26 -0300
Subject: [PATCH] build: extend fmt integration options

---
 .github/workflows/ci.yml             |  8 ++-
 CMakeLists.txt                       | 93 +++++++++++++++++++---------
 docs/modules/ROOT/pages/install.adoc | 44 ++++++++++++-
 3 files changed, 113 insertions(+), 32 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index cdb9fc062..4d17b9329 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -37,8 +37,10 @@ jobs:
             msvc 14.34
           standards: '>=20'
           max-standards: 1
-          latest-factors: gcc
-          factors: clang # Don't include Asan because `clang/AST/Decl.h` fails
+          latest-factors: ''
+          factors: | 
+            gcc Fetch-Content
+          trace-commands: true
 
   build:
     needs: cpp-matrix
@@ -92,7 +94,7 @@ jobs:
         id: package-install
         with:
           apt-get: ${{ matrix.install }} openjdk-11-jdk ninja-build
-          vcpkg: fmt libxml2[tools]
+          vcpkg: ${{ ( !matrix.fetch-content && 'fmt' ) || '' }} libxml2[tools]
           cc: ${{ steps.setup-cpp.outputs.cc || matrix.cc }}
           ccflags: ${{ matrix.ccflags }}
           cxx: ${{ steps.setup-cpp.outputs.cxx || matrix.cxx }}
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f6cd197df..f4661de75 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -85,36 +85,65 @@ add_definitions(${LLVM_DEFINITIONS})
 llvm_map_components_to_libnames(llvm_libs all)
 
 # Duktape
-if(NOT DEFINED DUKTAPE_SOURCE_ROOT)
-    set(DUKTAPE_SOURCE_ROOT $ENV{DUKTAPE_SOURCE_ROOT})
-endif()
-if (NOT DUKTAPE_SOURCE_ROOT)
-    include(FetchContent)
-    if (POLICY CMP0135)
-        cmake_policy(SET CMP0135 NEW)
-    endif()
-    FetchContent_Declare(
-            duktape
-            URL https://github.com/svaarala/duktape/releases/download/v2.7.0/duktape-2.7.0.tar.xz
-    )
-    FetchContent_GetProperties(duktape)
-    if(NOT duktape_POPULATED)
-        FetchContent_Populate(duktape)
-        set(DUKTAPE_SOURCE_ROOT ${duktape_SOURCE_DIR})
+find_package(duktape CONFIG)
+if (duktape_FOUND)
+    if (NOT TARGET duktape::duktape)
+        add_library(duktape INTERFACE)
+        target_link_libraries(duktape main ${DUKTAPE_LIBRARY})
+        target_include_directories(duktape INTERFACE ${DUKTAPE_INCLUDE_DIRS})
+        target_include_directories(duktape PUBLIC ${DUKTAPE_SOURCE_ROOT}/src)
+        add_library(duktape::duktape ALIAS duktape)
     endif()
-endif()
-add_library(duktape ${DUKTAPE_SOURCE_ROOT}/src/duktape.c ${DUKTAPE_SOURCE_ROOT}/src/duktape.h)
-target_include_directories(duktape PUBLIC ${DUKTAPE_SOURCE_ROOT}/src)
-add_library(duktape::duktape ALIAS duktape)
-if (CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
-    target_compile_options(duktape PRIVATE -w)
-elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
-    target_compile_options(duktape PRIVATE /w)
-endif()
+else()
+    if (NOT DEFINED DUKTAPE_SOURCE_ROOT)
+        set(DUKTAPE_SOURCE_ROOT $ENV{DUKTAPE_SOURCE_ROOT})
+    endif ()
+    if (NOT DUKTAPE_SOURCE_ROOT)
+        include(FetchContent)
+        if (POLICY CMP0135)
+            cmake_policy(SET CMP0135 NEW)
+        endif ()
+        FetchContent_Declare(
+                duktape
+                URL https://github.com/svaarala/duktape/releases/download/v2.7.0/duktape-2.7.0.tar.xz
+        )
+        FetchContent_GetProperties(duktape)
+        if (NOT duktape_POPULATED)
+            FetchContent_Populate(duktape)
+            set(DUKTAPE_SOURCE_ROOT ${duktape_SOURCE_DIR})
+        endif ()
+    endif ()
+    add_library(duktape ${DUKTAPE_SOURCE_ROOT}/src/duktape.c ${DUKTAPE_SOURCE_ROOT}/src/duktape.h)
+    target_include_directories(duktape PUBLIC ${DUKTAPE_SOURCE_ROOT}/src)
+    add_library(duktape::duktape ALIAS duktape)
+    if (CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
+        target_compile_options(duktape PRIVATE -w)
+    elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+        target_compile_options(duktape PRIVATE /w)
+    endif ()
+endif ()
 
 # fmt
-unset(CMAKE_FOLDER)
-find_package(fmt REQUIRED CONFIG)
+find_package(fmt CONFIG)
+if (NOT fmt_FOUND)
+    if (NOT DEFINED FMT_SOURCE_ROOT)
+        set(FMT_SOURCE_ROOT $ENV{FMT_SOURCE_ROOT})
+    endif ()
+    if (NOT FMT_SOURCE_ROOT)
+        include(FetchContent)
+        FetchContent_Declare(
+                fmt
+                URL https://github.com/fmtlib/fmt/releases/download/10.0.0/fmt-10.0.0.zip
+        )
+        FetchContent_GetProperties(fmt)
+        if (NOT fmt_POPULATED)
+            FetchContent_Populate(fmt)
+            set(FMT_SOURCE_ROOT ${fmt_SOURCE_DIR})
+        endif ()
+    endif ()
+endif ()
+
+unset(CMAKE_FOLDER) # Dependencies
 
 #-------------------------------------------------
 #
@@ -164,8 +193,16 @@ else()
 endif()
 target_include_directories(mrdox SYSTEM PUBLIC ${CLANG_INCLUDE_DIRS})
 
+# duktape
+target_link_libraries(mrdox PRIVATE duktape::duktape)
+
 # fmt
-target_link_libraries(mrdox PUBLIC fmt::fmt duktape::duktape)
+if (fmt_FOUND)
+    target_link_libraries(mrdox PRIVATE fmt::fmt)
+else ()
+    target_include_directories(mrdox SYSTEM PRIVATE ${FMT_SOURCE_ROOT}/include)
+     target_compile_definitions(mrdox PRIVATE FMT_HEADER_ONLY)
+endif()
 
 # Windows, Win64
 if (WIN32)
diff --git a/docs/modules/ROOT/pages/install.adoc b/docs/modules/ROOT/pages/install.adoc
index 32ea91a64..fee22bbe5 100644
--- a/docs/modules/ROOT/pages/install.adoc
+++ b/docs/modules/ROOT/pages/install.adoc
@@ -8,6 +8,8 @@ Binaries are available from our https://github.com/cppalliance/mrdox/releases[Re
 
 === Requirements
 
+==== LLVM
+
 MrDox depends on a recent version of LLVM.
 
 Here are the instructions to clone LLVM version required by this project.
@@ -44,9 +46,49 @@ cmake --build . -j <threads>
 cmake --install .
 ----
 
+==== fmt
+
+MrDox uses the `fmt` library to format its messages. The library can be downloaded from https://vcpkg.io/en/getting-started.html[vcpkg] or installed from https://github.com/fmtlib/fmt[their official repository].
+
+When using vcpkg, its toolchain should be provided to the mrdox cmake configure command:
+
+[source,bash]
+----
+cmake -B [build directory] -S [path to mrdox] -D CMAKE_TOOLCHAIN_FILE=[path to vcpkg]/scripts/buildsystems/vcpkg.cmake
+----
+
+When the `fmt` library has been installed from their official release, the library path should be provided to the mrdox cmake configure command:
+
+[source,bash]
+----
+cmake -B [build directory] -S [path to mrdox] -D FMT_ROOT=[path to installed fmt]
+----
+
+Alternatively, when neither option is available, the mrdox configure script will attempt to automatically download the `fmt` library during configuration.
+
+==== duktape
+
+The MrDox templating system uses the duktape JS interpreter for its handlebars templating system. The library can be downloaded from https://vcpkg.io/en/getting-started.html[vcpkg] or installed from https://duktape.org/[their official repository].
+
+When using vcpkg, its toolchain should be provided to the mrdox cmake configure command:
+
+[source,bash]
+----
+cmake -B [build directory] -S [path to mrdox] -D CMAKE_TOOLCHAIN_FILE=[path to vcpkg]/scripts/buildsystems/vcpkg.cmake
+----
+
+When duktape has been installed from their https://github.com/svaarala/duktape/releases/tag/v2.7.0[official release], the duktape source path should be provided to the mrdox cmake configure command:
+
+[source,bash]
+----
+cmake -B [build directory] -S [path to mrdox] -D DUKTAPE_SOURCE_ROOT=[path to duktape source]
+----
+
+Alternatively, when neither option is available, the mrdox configure script will attempt to automatically download duktape during configuration.
+
 === MrDox
 
-Once the LLVM variants are available in `/path/to/llvm+clang`, you can download MrDox:
+Once the LLVM variants and dependencies are available in `/path/to/llvm+clang`, you can download MrDox:
 
 [source,bash]
 ----