From e7beee7c3891779e8c884286fc5a494ed62d5646 Mon Sep 17 00:00:00 2001 From: Fernando Pelliccioni Date: Fri, 26 Jul 2024 16:57:05 -0300 Subject: [PATCH] Standard library incompatibility fix by packaging libc++ --- .github/workflows/ci.yml | 123 +++++++++++++++------- .gitignore | 4 +- CMakeLists.txt | 19 +++- docs/modules/ROOT/pages/install.adoc | 94 ++++++++++++++++- docs/website/render.js | 3 +- src/lib/Lib/ConfigOptions.json | 22 ++++ src/lib/Lib/MrDocsCompilationDatabase.cpp | 55 +++++++--- src/lib/Metadata/Finalize.cpp | 1 + src/test/TestArgs.cpp | 10 ++ src/test/TestArgs.hpp | 2 + src/tool/Addons.cpp | 55 ---------- src/tool/Addons.hpp | 33 ------ src/tool/GenerateAction.cpp | 1 - src/tool/ToolArgs.cpp | 1 - util/generate-config-info.py | 21 +++- 15 files changed, 295 insertions(+), 149 deletions(-) delete mode 100644 src/tool/Addons.cpp delete mode 100644 src/tool/Addons.hpp diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d037b71cb..0caaec727 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -104,9 +104,9 @@ jobs: cd fmt cmake -S . -B ./build -D FMT_DOC=OFF -D FMT_TEST=OFF -DCMAKE_BUILD_TYPE=${{ matrix.build-type }} -DCMAKE_CXX_COMPILER=${{ steps.setup-cpp.outputs.cxx }} -DCMAKE_C_COMPILER=${{ steps.setup-cpp.outputs.cc }} N_CORES=$(nproc 2>/dev/null || echo 1) - cmake --build ./build --config ${{ matrix.build-type }} --parallel $N_CORES + cmake --build ./build --config ${{ matrix.build-type }} --parallel $N_CORES cmake --install ./build --prefix ./install - + fmt_root=$(pwd)/install if [[ ${{ runner.os }} == 'Windows' ]]; then fmt_root=$(echo "$fmt_root" | sed 's/\\/\//g') @@ -135,9 +135,9 @@ jobs: fi cmake -S . -B ./build -DCMAKE_BUILD_TYPE=${{ matrix.build-type }} -DCMAKE_CXX_COMPILER=${{ steps.setup-cpp.outputs.cxx }} -DCMAKE_C_COMPILER=${{ steps.setup-cpp.outputs.cc }} N_CORES=$(nproc 2>/dev/null || echo 1) - cmake --build ./build --config ${{ matrix.build-type }} --parallel $N_CORES + cmake --build ./build --config ${{ matrix.build-type }} --parallel $N_CORES cmake --install ./build --prefix ./install - + duktape_root=$(pwd)/install if [[ ${{ runner.os }} == 'Windows' ]]; then duktape_root=$(echo "$duktape_root" | sed 's/\\/\//g') @@ -159,12 +159,12 @@ jobs: git config --global advice.detachedHead false git clone https://github.com/GNOME/libxml2 --branch v2.12.6 --depth 1 cd libxml2 - + cmake -S . -B ./build -DCMAKE_BUILD_TYPE=Release -DLIBXML2_WITH_PROGRAMS=ON -DLIBXML2_WITH_FTP=OFF -DLIBXML2_WITH_HTTP=OFF -DLIBXML2_WITH_ICONV=OFF -DLIBXML2_WITH_LEGACY=OFF -DLIBXML2_WITH_LZMA=OFF -DLIBXML2_WITH_ZLIB=OFF -DLIBXML2_WITH_ICU=OFF -DLIBXML2_WITH_TESTS=OFF -DLIBXML2_WITH_HTML=ON -DLIBXML2_WITH_C14N=ON -DLIBXML2_WITH_CATALOG=ON -DLIBXML2_WITH_DEBUG=ON -DLIBXML2_WITH_ISO8859X=ON -DLIBXML2_WITH_MEM_DEBUG=OFF -DLIBXML2_WITH_MODULES=ON -DLIBXML2_WITH_OUTPUT=ON -DLIBXML2_WITH_PATTERN=ON -DLIBXML2_WITH_PUSH=ON -DLIBXML2_WITH_PYTHON=OFF -DLIBXML2_WITH_READER=ON -DLIBXML2_WITH_REGEXPS=ON -DLIBXML2_WITH_SAX1=ON -DLIBXML2_WITH_SCHEMAS=ON -DLIBXML2_WITH_SCHEMATRON=ON -DLIBXML2_WITH_THREADS=ON -DLIBXML2_WITH_THREAD_ALLOC=OFF -DLIBXML2_WITH_TREE=ON -DLIBXML2_WITH_VALID=ON -DLIBXML2_WITH_WRITER=ON -DLIBXML2_WITH_XINCLUDE=ON -DLIBXML2_WITH_XPATH=ON -DLIBXML2_WITH_XPTR=ON -DCMAKE_CXX_COMPILER=${{ steps.setup-cpp.outputs.cxx || steps.parameters.outputs.clang-bin }} -DCMAKE_C_COMPILER=${{ steps.setup-cpp.outputs.cc || steps.parameters.outputs.clang-bin }} N_CORES=$(nproc 2>/dev/null || echo 1) - cmake --build ./build --config ${{ matrix.build-type }} --parallel $N_CORES + cmake --build ./build --config ${{ matrix.build-type }} --parallel $N_CORES cmake --install ./build --prefix ./install - + libxml2_root=$(pwd)/install if [[ ${{ runner.os }} == 'Windows' ]]; then libxml2_root=$(echo "$libxml2_root" | sed 's/\\/\//g') @@ -173,6 +173,7 @@ jobs: fi echo -E "libxml2-root=$libxml2_root" >> $GITHUB_OUTPUT + - name: LLVM Parameters id: llvm-parameters run: | @@ -188,6 +189,14 @@ jobs: fi echo -E "llvm-root=$llvm_root" >> $GITHUB_OUTPUT + libcxx_root=$(pwd)/third-party/llvm-project/install + if [[ ${{ runner.os }} == 'Windows' ]]; then + libcxx_root=$(echo "$libcxx_root" | sed 's/\\/\//g') + libcxx_root=$(echo $libcxx_root | sed 's|^/d/|D:/|') + echo "$libcxx_root" + fi + echo -E "libcxx-root=$libcxx_root" >> $GITHUB_OUTPUT + - name: LLVM Binaries id: llvm-cache uses: actions/cache@v4 @@ -202,7 +211,7 @@ jobs: run: | # LLVM is be installed with the default compiler set -x - + # Shallow clone LLVM_HASH in ../third-party/llvm cd .. mkdir -p third-party/llvm-project @@ -218,7 +227,7 @@ jobs: # Copy presets cp ../../mrdocs/third-party/llvm/CMakePresets.json ./llvm cp ../../mrdocs/third-party/llvm/CMakeUserPresets.json.example ./llvm/CMakeUserPresets.json - + # Build cd llvm llvm_root=$(pwd) @@ -226,11 +235,68 @@ jobs: cmake -S . -B ./build --preset=${{ steps.llvm-parameters.outputs.llvm-build-preset }} -DCMAKE_CXX_COMPILER=${{ steps.setup-cpp.outputs.cxx }} -DCMAKE_C_COMPILER=${{ steps.setup-cpp.outputs.cc }} if [[ ${{ runner.os }} == 'Linux' ]]; then cmake --build ./build --target help - fi + fi N_CORES=$(nproc 2>/dev/null || echo 1) cmake --build ./build --config Release --parallel $N_CORES cmake --install ./build --prefix "$llvm_project_root"/install + - name: LibC++ Binaries + id: libcxx-cache + uses: actions/cache@v4 + with: + path: ${{ steps.llvm-parameters.outputs.libcxx-root }} + key: libcxx-${{ runner.os }}-${{ matrix.compiler }}-${{ matrix.version }}-${{ steps.llvm-parameters.outputs.llvm-hash }} + + - name: Install LibC++ + id: libcxx-install + if: ${{ steps.libcxx-cache.outputs.cache-hit != 'true'}} + shell: bash + run: | + set -x + + cd .. + llvm_project_root="$(pwd)/third-party/llvm-project" + if [ ! -d "$llvm_project_root/runtimes" ]; then + mkdir -p $llvm_project_root + cd $llvm_project_root + git config --global init.defaultBranch master + git config --global advice.detachedHead false + git init + git remote add origin https://github.com/llvm/llvm-project.git + git fetch --depth 1 origin ${{ steps.llvm-parameters.outputs.llvm-hash }} + git checkout FETCH_HEAD + fi + + export CXX="$llvm_project_root/install/bin/clang++" + export CC="$llvm_project_root/install/bin/clang" + + cd $llvm_project_root + + if [ ${{ runner.os }} != 'Windows' ]; then + cmake -G Ninja \ + -S runtimes \ + -B build-libcxx \ + -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind" \ + -DCMAKE_INSTALL_PREFIX="$llvm_project_root/install" + + ninja -C build-libcxx cxx cxxabi unwind + ninja -C build-libcxx install-cxx install-cxxabi install-unwind + else + cmake -G Ninja \ + -S runtimes \ + -B build-libcxx \ + -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \ + -DCMAKE_INSTALL_PREFIX="$llvm_project_root/install" \ + -DLIBCXXABI_USE_LLVM_UNWINDER=OFF \ + -DLIBCXXABI_ENABLE_SHARED=OFF \ + -DLIBCXXABI_ENABLE_STATIC=ON \ + -DLIBCXX_ENABLE_SHARED=OFF \ + -DLIBCXX_NO_VCRUNTIME=ON \ + -DCMAKE_CXX_FLAGS="-D__ORDER_LITTLE_ENDIAN__=1234 -D__ORDER_BIG_ENDIAN__=4321 -D__BYTE_ORDER__=__ORDER_LITTLE_ENDIAN__" + ninja -C build-libcxx cxx + ninja -C build-libcxx install-cxx + fi + - name: Install Node.js uses: actions/setup-node@v3 with: @@ -256,7 +322,7 @@ jobs: -D duktape_ROOT=${{ steps.duktape-install.outputs.duktape-root }} -D Duktape_ROOT=${{ steps.duktape-install.outputs.duktape-root }} -D fmt_ROOT=${{ steps.fmt-install.outputs.fmt-root }} - ${{ (steps.libxml2-install.outputs.libxml2-root && format('-D libxml2_ROOT={0}', steps.libxml2-install.outputs.libxml2-root)) || '' }} + ${{ (steps.libxml2-install.outputs.libxml2-root && format('-D libxml2_ROOT={0}', steps.libxml2-install.outputs.libxml2-root)) || '' }} ${{ (steps.libxml2-install.outputs.libxml2-root && format('-D LibXml2_ROOT={0}', steps.libxml2-install.outputs.libxml2-root)) || '' }} export-compile-commands: true run-tests: true @@ -296,27 +362,17 @@ jobs: run: shell: bash name: Website - timeout-minutes: 30 - runs-on: ubuntu-20.04 - container: ubuntu:23.04 + timeout-minutes: 30 + runs-on: ubuntu-latest + container: ubuntu:20.04 permissions: contents: write steps: - - name: Setup C++ - uses: alandefreitas/cpp-actions/setup-cpp@v1.8.3 - id: setup-cpp - with: - compiler: clang - version: 16 - check-latest: true - - name: Install packages uses: alandefreitas/cpp-actions/package-install@v1.8.3 id: package-install with: - apt-get: libstdc++-12-dev asciidoctor cmake bzip2 git - cc: ${{ steps.setup-cpp.outputs.cc }} - cxx: ${{ steps.setup-cpp.outputs.cxx }} + apt-get: build-essential asciidoctor cmake bzip2 git - name: Clone mrdocs uses: actions/checkout@v4 @@ -339,8 +395,6 @@ jobs: mrdocs --version MRDOCS_ROOT=/usr/local echo -e "MRDOCS_ROOT=$MRDOCS_ROOT" >> $GITHUB_ENV - CXX=/usr/bin/clang-16 - echo -e "CXX=$CXX" >> $GITHUB_ENV - name: Clone Boost.URL uses: alandefreitas/cpp-actions/boost-clone@v1.8.3 @@ -393,11 +447,6 @@ jobs: - name: Generate Demos run: | - CXX="${{ steps.setup-cpp.outputs.cxx }}" - export CXX - CC="${{ steps.setup-cpp.outputs.cc }}" - export CC - declare -a generators=( "adoc" "xml" @@ -438,15 +487,15 @@ jobs: id: compare-demos run: | set -x - + # Define URLs and directories LOCAL_DEMOS_DIR="./demos/" PREV_DEMOS_DIR="./demos-previous/" DIFF_DIR="./demos-diff/" - + # Create directories if they don't exist mkdir -p $PREV_DEMOS_DIR $DIFF_DIR - + # Iterate over the previous files and compare them with the corresponding local files find $PREV_DEMOS_DIR -type f | while read previous_file; do # Derive the corresponding local file path @@ -464,7 +513,7 @@ jobs: cat "$previous_file" >> "$diff_output" fi done - + # Iterate over the local files to find new files find $LOCAL_DEMOS_DIR -type f | while read local_file; do previous_file="${PREV_DEMOS_DIR}${local_file#$LOCAL_DEMOS_DIR}" @@ -475,7 +524,7 @@ jobs: echo "NEW CONTENT OF THE FILE IS:" >> "$diff_output" fi done - + # Check if the diff directory is empty if [[ -z $(ls -A $DIFF_DIR) ]]; then echo "No differences found." diff --git a/.gitignore b/.gitignore index 2a85a591d..b396488a2 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,6 @@ /test-files/**/*.adoc /test-files/**/*.bad.xml docs/node_modules -docs/build \ No newline at end of file +docs/build +share/mrdocs/libcxx/ +share/mrdocs/clang/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 760f53824..fd67d7c4d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,6 +92,12 @@ elseif (LLVM_ROOT) endif() find_package(LLVM REQUIRED CONFIG) find_package(Clang REQUIRED CONFIG) + +if (LLVM_ROOT) + set(LIBCXX_DIR "${LLVM_ROOT}/include/c++/v1/") + set(STDLIB_INCLUDE_DIR "${LLVM_ROOT}/lib/clang/${Clang_VERSION_MAJOR}/include/") +endif() + list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}") include(HandleLLVMOptions) add_definitions(${LLVM_DEFINITIONS}) @@ -337,7 +343,9 @@ if (MRDOCS_BUILD_TESTS) --unit=false --action=test "${PROJECT_SOURCE_DIR}/test-files/golden-tests" - --addons="${CMAKE_SOURCE_DIR}/share/mrdocs/addons") + --addons="${CMAKE_SOURCE_DIR}/share/mrdocs/addons" + --system-includes="${LIBCXX_DIR}" + --system-includes="${STDLIB_INCLUDE_DIR}") foreach (action IN ITEMS create update) add_custom_target( mrdocs-${action}-test-fixtures @@ -347,6 +355,8 @@ if (MRDOCS_BUILD_TESTS) --action=${action} "${PROJECT_SOURCE_DIR}/test-files/golden-tests" --addons="${CMAKE_SOURCE_DIR}/share/mrdocs/addons" + --system-includes="${LIBCXX_DIR}" + --system-includes="${STDLIB_INCLUDE_DIR}" DEPENDS mrdocs-test ) endforeach () @@ -492,6 +502,13 @@ if (MRDOCS_INSTALL) #------------------------------------------------- # share #------------------------------------------------- + install(DIRECTORY ${LIBCXX_DIR} + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/mrdocs/libcxx + FILES_MATCHING PATTERN "*") + install(DIRECTORY ${STDLIB_INCLUDE_DIR} + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/mrdocs/clang + FILES_MATCHING PATTERN "*") + foreach (share_mrdocs_dir addons) install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/share/mrdocs/${share_mrdocs_dir} DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/mrdocs diff --git a/docs/modules/ROOT/pages/install.adoc b/docs/modules/ROOT/pages/install.adoc index e71887d68..c7eba42cb 100644 --- a/docs/modules/ROOT/pages/install.adoc +++ b/docs/modules/ROOT/pages/install.adoc @@ -382,12 +382,102 @@ cmake --install ./build --prefix ../install Replace 4 with the number of cores you want to use for building LLVM. -Return from `./third-party/llvm-project/llvm` to the parent directory to build and install MrDocs: +Return from `./third-party/llvm-project/llvm` to the LLVM project directory: [source,bash] ---- -cd ../../.. +cd ../.. +---- + +=== LibC++ + +In addition to LLVM, MrDocs requires a deterministic version of the C++ standard library (LibC++) to ensure consistent behavior across various environments. This step is crucial for replicating specific compiler and library configurations. + +**Download**: + +Continue using the same LLVM project directory. + +**Configure**: + +Configure and build LibC++ using the existing structure: + +[source,bash] +---- +export CXX="./install/bin/clang++" +export CC="./install/bin/clang" +---- + +Run a command such as the following to configure LLVM: + +[tabs] +==== +Windows PowerShell:: ++ +-- +[source,bash] +---- +cmake -G Ninja \ + -S runtimes \ + -B build-libcxx \ + -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \ + -DCMAKE_INSTALL_PREFIX="$(pwd)/install" \ + -DLIBCXXABI_USE_LLVM_UNWINDER=OFF \ + -DLIBCXXABI_ENABLE_SHARED=OFF \ + -DLIBCXXABI_ENABLE_STATIC=ON \ + -DLIBCXX_ENABLE_SHARED=OFF \ + -DLIBCXX_NO_VCRUNTIME=ON \ + -DCMAKE_CXX_FLAGS="-D__ORDER_LITTLE_ENDIAN__=1234 -D__ORDER_BIG_ENDIAN__=4321 -D__BYTE_ORDER__=__ORDER_LITTLE_ENDIAN__" +---- +-- + +Unix Variants:: ++ +-- +[source,bash] +---- +cmake -G Ninja \ + -S runtimes \ + -B build-libcxx \ + -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind" \ + -DCMAKE_INSTALL_PREFIX="$(pwd)/install" ---- +-- +==== + +**Build**: + +Build and install the configured version of LibC++ with: + +[tabs] +==== +Windows PowerShell:: ++ +-- +[source,bash] +---- +ninja -C build-libcxx cxx +ninja -C build-libcxx install-cxx +---- +-- + +Unix Variants:: ++ +-- +[source,bash] +---- +ninja -C build-libcxx cxx cxxabi unwind +ninja -C build-libcxx install-cxx install-cxxabi install-unwind +---- +-- +==== + +Return from `./third-party/llvm-project` to the parent directory to build and install MrDocs: + +[source,bash] +---- +cd ../.. +---- + === MrDocs diff --git a/docs/website/render.js b/docs/website/render.js index c63400b04..f993b5c2a 100644 --- a/docs/website/render.js +++ b/docs/website/render.js @@ -57,7 +57,8 @@ for (let panel of data.panels) { // Create a CMakeLists.txt file for the snippet const cmakeListsPath = path.join(absSnippetsDir, 'CMakeLists.txt') - fs.writeFileSync(cmakeListsPath, `cmake_minimum_required(VERSION 3.13)\nproject(${sourceBasename})\nadd_executable(${sourceBasename} ${panel.source})\n`) + const cmakeListsContent = `cmake_minimum_required(VERSION 3.13)\nproject(${sourceBasename})\nadd_executable(${sourceBasename} ${panel.source})\n` + fs.writeFileSync(cmakeListsPath, cmakeListsContent) // Run mrdocs to generate documentation const mrdocsConfig = path.join(absSnippetsDir, 'mrdocs.yml') diff --git a/src/lib/Lib/ConfigOptions.json b/src/lib/Lib/ConfigOptions.json index 32cf3abb1..6f4a92d6b 100644 --- a/src/lib/Lib/ConfigOptions.json +++ b/src/lib/Lib/ConfigOptions.json @@ -79,6 +79,28 @@ "details": "Additional defines passed to the compiler when building the source code. These defines are added to the compilation database regardless of the strategy to generate it.", "type": "list", "default": [] + }, + { + "name": "use-system-stdlib", + "brief": "Use the system standard library", + "details": "True if the compiler has to use just the system standard library. When set to true, the compiler uses the system standard library instead of the standard library provided by the compiler.", + "type": "bool", + "default": false + }, + { + "name": "system-includes", + "brief": "Standard Library include paths", + "details": "Standard Library include paths.", + "type": "list", + "default": ["/share/mrdocs/libcxx", "/share/mrdocs/clang"], + "relativeto": "" + }, + { + "name": "includes", + "brief": "Additional include paths", + "details": "Additional include paths.", + "type": "list", + "default": [] } ] }, diff --git a/src/lib/Lib/MrDocsCompilationDatabase.cpp b/src/lib/Lib/MrDocsCompilationDatabase.cpp index 21d271569..0d1e17ec4 100644 --- a/src/lib/Lib/MrDocsCompilationDatabase.cpp +++ b/src/lib/Lib/MrDocsCompilationDatabase.cpp @@ -245,7 +245,10 @@ adjustCommandLine( llvm::StringRef workingDir, const std::vector& cmdline, const std::vector& additional_defines, - std::unordered_map> const& implicitIncludeDirectories) + std::unordered_map> const& implicitIncludeDirectories, + std::vector const& systemIncludes, + std::vector const& includes, + bool useSystemStdLib) { if (cmdline.empty()) { @@ -297,19 +300,42 @@ adjustCommandLine( new_cmdline.emplace_back(fmt::format("-D{}", def)); } - // ------------------------------------------------------ - // Add implicit include paths - // ------------------------------------------------------ - // Implicit include paths are those which are automatically - // added by the compiler. These will not be defined in the - // compile command, so we add them here so that clang - // can also find these headers. - if (auto it = implicitIncludeDirectories.find(progName); - it != implicitIncludeDirectories.end()) { - for (auto const& inc : it->second) + if (useSystemStdLib) + { + // ------------------------------------------------------ + // Add implicit include paths + // ------------------------------------------------------ + // Implicit include paths are those which are automatically + // added by the compiler. These will not be defined in the + // compile command, so we add them here so that clang + // can also find these headers. + if (auto const it = implicitIncludeDirectories.find(progName); + it != implicitIncludeDirectories.end()) { + for (auto const& inc : it->second) + { + new_cmdline.emplace_back(fmt::format("-isystem{}", inc)); + } + } + } + else + { + // ------------------------------------------------------ + // Add standard library include directories + // ------------------------------------------------------ + for (auto const& inc : systemIncludes) { - new_cmdline.emplace_back(fmt::format("-I{}", inc)); + new_cmdline.emplace_back(fmt::format("-isystem{}", inc)); } + new_cmdline.emplace_back("-nostdinc++"); + new_cmdline.emplace_back("-nostdlib++"); + } + + // ------------------------------------------------------ + // Add additional include directories + // ------------------------------------------------------ + for (auto const& inc : includes) + { + new_cmdline.emplace_back(fmt::format("-I{}", inc)); } // ------------------------------------------------------ @@ -390,7 +416,10 @@ MrDocsCompilationDatabase( workingDir, cmd0.CommandLine, (*config_impl)->defines, - implicitIncludeDirectories); + implicitIncludeDirectories, + (*config_impl)->systemIncludes, + (*config_impl)->includes, + (*config_impl)->useSystemStdlib); cmd.Directory = makeAbsoluteAndNative(workingDir, cmd0.Directory); cmd.Filename = makeAbsoluteAndNative(workingDir, cmd0.Filename); if (isCXXSrcFile(cmd.Filename)) diff --git a/src/lib/Metadata/Finalize.cpp b/src/lib/Metadata/Finalize.cpp index cc3daaa9f..1036e6705 100644 --- a/src/lib/Metadata/Finalize.cpp +++ b/src/lib/Metadata/Finalize.cpp @@ -12,6 +12,7 @@ #include "lib/Lib/Info.hpp" #include "lib/Support/NameParser.hpp" #include +#include #include #include diff --git a/src/test/TestArgs.cpp b/src/test/TestArgs.cpp index 7f6c6da4a..96687cb3e 100644 --- a/src/test/TestArgs.cpp +++ b/src/test/TestArgs.cpp @@ -80,6 +80,16 @@ R"( "addons", llvm::cl::desc("The directory with the addons."), llvm::cl::cat(commonCat)) + +, systemIncludes( + "system-includes", + llvm::cl::desc("A list of paths to the system headers."), + llvm::cl::cat(commonCat)) + +, includes( + "includes", + llvm::cl::desc("A list of paths to additional include directories."), + llvm::cl::cat(commonCat)) { } diff --git a/src/test/TestArgs.hpp b/src/test/TestArgs.hpp index 6a9c20288..17407761b 100644 --- a/src/test/TestArgs.hpp +++ b/src/test/TestArgs.hpp @@ -47,6 +47,8 @@ class TestArgs llvm::cl::opt unitOption; llvm::cl::list inputPaths; llvm::cl::opt addons; + llvm::cl::list systemIncludes; + llvm::cl::list includes; // Hide all options that don't belong to us void hideForeignOptions(); diff --git a/src/tool/Addons.cpp b/src/tool/Addons.cpp deleted file mode 100644 index e6d971c3a..000000000 --- a/src/tool/Addons.cpp +++ /dev/null @@ -1,55 +0,0 @@ -// -// Licensed under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com) -// -// Official repository: https://github.com/cppalliance/mrdocs -// - -#include "Addons.hpp" -#include -#include -#include -#include - -namespace clang { -namespace mrdocs { - -Expected -setupAddonsDir( - std::string& addonsDirArg, - std::string_view execPath) -{ - if (!addonsDirArg.empty()) - { - // Already set from mrdocs.yml or command line - return {}; - } - - // Set addons dir from environment variable - auto addonsEnvVar = llvm::sys::Process::GetEnv("MRDOCS_ADDONS_DIR"); - if (addonsEnvVar) - { - MRDOCS_CHECK(*addonsEnvVar, "MRDOCS_ADDONS_DIR is empty"); - std::string addonsDir = files::normalizePath(*addonsEnvVar); - MRDOCS_TRY(files::requireAbsolute(addonsDir)); - MRDOCS_TRY(files::requireDirectory(addonsDir)); - addonsDirArg = addonsDir; - return {}; - } - - // Set addons dir from process working directory - MRDOCS_CHECK(execPath, "getMainExecutable failed"); - std::string binDir = files::getParentDir(execPath); - std::string addonsDir = files::appendPath( - binDir, "..", "share", "mrdocs", "addons"); - Error err = files::requireDirectory(addonsDir); - MRDOCS_CHECK(err); - addonsDirArg = addonsDir; - return {}; -} - -} // mrdocs -} // clang diff --git a/src/tool/Addons.hpp b/src/tool/Addons.hpp deleted file mode 100644 index 15fbb31cc..000000000 --- a/src/tool/Addons.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// -// Licensed under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com) -// -// Official repository: https://github.com/cppalliance/mrdocs -// - -#ifndef MRDOCS_TOOL_ADDONS_HPP -#define MRDOCS_TOOL_ADDONS_HPP - -#include -#include -#include - -namespace clang { -namespace mrdocs { - -/** Set the addons directory using the argument as a hint. - - @return The error if any occurred. -*/ -Expected -setupAddonsDir( - std::string& addonsDirArg, - std::string_view execPath); - -} // mrdocs -} // clang - -#endif diff --git a/src/tool/GenerateAction.cpp b/src/tool/GenerateAction.cpp index 48afa49f4..30bbba398 100644 --- a/src/tool/GenerateAction.cpp +++ b/src/tool/GenerateAction.cpp @@ -9,7 +9,6 @@ // Official repository: https://github.com/cppalliance/mrdocs // -#include "Addons.hpp" #include "CompilerInfo.hpp" #include "ToolArgs.hpp" #include diff --git a/src/tool/ToolArgs.cpp b/src/tool/ToolArgs.cpp index c1d902a5a..561f141e8 100644 --- a/src/tool/ToolArgs.cpp +++ b/src/tool/ToolArgs.cpp @@ -9,7 +9,6 @@ // #include "ToolArgs.hpp" -#include "Addons.hpp" #include #include #include diff --git a/util/generate-config-info.py b/util/generate-config-info.py index 091be0d2a..f57605387 100644 --- a/util/generate-config-info.py +++ b/util/generate-config-info.py @@ -499,6 +499,15 @@ def remove_reference_dir_from_path(path): return path +def get_reference_dir_from_path(path): + if path.startswith('<'): + closing_bracket = path.find('>') + if closing_bracket == -1: + raise ValueError(f'Invalid default value {path} for option') + return path[1:closing_bracket] + return None + + def option_validation_snippet(option): camel_name = to_camel_case(option['name']) contents = '' @@ -510,6 +519,7 @@ def option_validation_snippet(option): path_is_relativeto_dir = option['relativeto'] if path_is_relativeto_dir.startswith('<') and path_is_relativeto_dir.endswith('>'): path_is_relativeto_dir = path_is_relativeto_dir[1:-1] + default_is_relativeto_dir = path_is_relativeto_dir if 'default' in option and isinstance(option['default'], str): first_path_seg_is_reference = option['default'].startswith('<') @@ -520,6 +530,7 @@ def option_validation_snippet(option): default_is_relativeto_dir = option['default'][1:closing_bracket] else: default_is_relativeto_dir = 'cwd' + same_base_paths = default_is_relativeto_dir == path_is_relativeto_dir validation_contents = '' @@ -644,16 +655,18 @@ def option_validation_snippet(option): validation_contents += f'}}\n' else: if option['default']: - validation_contents += f'// s.{camel_name} paths are not required. The default value is "{option["default"]}"\n' + validation_contents += f'// s.{camel_name} paths are not required.\n' + validation_contents += f'// The default value is "{option["default"]}"\n' validation_contents += f'if (s.{camel_name}.empty())\n' validation_contents += f'{{\n' - validation_contents += f' s.{camel_name} = {{' + validation_contents += f' s.{camel_name} = {{\n' is_first = True for default_path in option['default']: if not is_first: - validation_contents += ', ' - validation_contents += f'" files::makeAbsolute("{remove_reference_dir_from_path(default_path)}", dirs.{to_camel_case(default_is_relativeto_dir)}")' + validation_contents += ',\n' + validation_contents += f' files::makeAbsolute("{remove_reference_dir_from_path(default_path)}", dirs.{to_camel_case(get_reference_dir_from_path(default_path))})' is_first = False + validation_contents += '\n' validation_contents += ' };\n' validation_contents += f'}}\n' validation_contents += f'else\n'