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
4 changes: 4 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -227,3 +227,7 @@ IncludeCategories:
# Comments
FixNamespaceComments: true
CommentPragmas: '^ clang-format'

---
Language: Json
BasedOnStyle: llvm
61 changes: 45 additions & 16 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ jobs:
common-flags-base: {{#if (ieq compiler 'clang')}}-gz=zstd {{/if}}
common-flags: {{{ common-flags-base }}}{{#if msan }}-fsanitize-memory-track-origins {{/if}}
common-ccflags: {{{ ccflags }}} {{{ common-flags }}}
mrdocs-flags: {{{ warning-flags }}}{{#if (and (eq compiler 'gcc') (not asan)) }}-static {{/if}}
mrdocs-flags: {{{ warning-flags }}}
mrdocs-ccflags: {{{ common-ccflags }}} {{{ mrdocs-flags }}}
mrdocs-package-generators: {{#if (ieq os 'windows') }}7Z ZIP WIX{{else}}TGZ TXZ{{/if}}
mrdocs-release-package-artifact: release-packages-{{{ lowercase os }}}
Expand Down Expand Up @@ -726,6 +726,26 @@ jobs:
contents: write

steps:
# This calculates a bunch of variables, which would normally go in to the regular matrix extra-values
# section, but which depend on paths not known at that point.
- name: Resolved Matrix
id: rmatrix
run: |
set -euvx

third_party_dir="$(realpath $(pwd)/..)/third-party"
if [[ "${{ runner.os }}" == 'Windows' ]]; then
third_party_dir="$(echo "$third_party_dir" | sed 's/\\/\//g; s|^/d/|D:/|')"
fi
echo "third-party-dir=$third_party_dir" >> $GITHUB_OUTPUT

llvm_path="$third_party_dir/llvm"
echo "llvm-path=$llvm_path" >> $GITHUB_OUTPUT

llvm_cache_key="${{ matrix.llvm-archive-basename }}"
llvm_cache_key="${llvm_cache_key//:/-}"
echo "llvm-cache-key=$llvm_cache_key" >> $GITHUB_OUTPUT

- name: Ensure Node
if: matrix.container != '' && env.ACT == 'true'
run: |
Expand Down Expand Up @@ -768,6 +788,14 @@ jobs:
compiler: ${{ matrix.compiler }}
version: ${{ matrix.version }}

- name: Cached LLVM Binaries
id: llvm-cache
uses: actions/cache@v4
with:
path: ${{ steps.rmatrix.outputs.llvm-path }}
key: ${{ steps.rmatrix.outputs.llvm-cache-key }}
fail-on-cache-miss: true

- name: Download MrDocs package
uses: actions/download-artifact@v4
with:
Expand All @@ -776,28 +804,29 @@ jobs:

- name: Install MrDocs from Package
run: |
set -x
set -euvx

# Delete packages/_CPack_Packages files from previous runs
rm -rf packages/_CPack_Packages

# Print tree structure
find packages -print | sed 's;[^/]*/;|____;g;s;____|; |;g'


dest_dir="${{ steps.rmatrix.outputs.llvm-path }}"

if [[ ${{ runner.os }} != 'Windows' ]]; then
dest_dir="$HOME/local"
mkdir -p "$dest_dir"
find packages -maxdepth 1 -name 'MrDocs-*.tar.gz' -exec tar -vxzf {} -C $dest_dir --strip-components=1 \;
else
dest_dir="$GITHUB_WORKSPACE/usr/local"
dest_dir=$(echo "$dest_dir" | sed 's/\\/\//g')
find packages -maxdepth 1 -name "MrDocs-*.7z" -exec 7z x {} -o$dest_dir \;
if [[ $(ls -1 $dest_dir | wc -l) -eq 1 ]]; then
single_dir=$(ls -1 $dest_dir)
if [[ -d $dest_dir/$single_dir ]]; then
mv $dest_dir/$single_dir/* $dest_dir/
rmdir $dest_dir/$single_dir
fi
package=$(find packages -maxdepth 1 -name "MrDocs-*.7z" -print -quit)
filename=$(basename "$package")
name="${filename%.*}"
7z x "${package}" -o${dest_dir}
set +e
robocopy "${dest_dir}/${name}" "${dest_dir}" //move //e //np //nfl
exit_code=$?
set -e
if (( exit_code >= 8 )); then
exit 1
fi
fi
MRDOCS_ROOT="$dest_dir"
Expand Down
24 changes: 10 additions & 14 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -261,15 +261,6 @@ if (NOT EXISTS "${LIBCXX_DIR}")
"Please provide a LLVM with libc++ enabled\n")
endif()

set(STDLIB_INCLUDE_DIR "${LLVM_BINARY_DIR}/lib/clang/${Clang_VERSION_MAJOR}/include"
CACHE PATH "Path to the clang headers include directory")
message(STATUS "STDLIB_INCLUDE_DIR: ${STDLIB_INCLUDE_DIR}")
if (NOT EXISTS "${STDLIB_INCLUDE_DIR}")
message(FATAL_ERROR
"STDLIB_INCLUDE_DIR (${STDLIB_INCLUDE_DIR}) does not exist.\n"
"Missing clang headers\n")
endif()

list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}")
include(HandleLLVMOptions)
add_definitions(${LLVM_DEFINITIONS})
Expand Down Expand Up @@ -384,6 +375,7 @@ if (WIN32)
mrdocs-core
PUBLIC
/permissive- # strict C++
/Zc:__cplusplus # report C++ standard support
/W4 # enable all warnings
/MP # multi-processor compilation
/EHs # C++ Exception handling
Expand All @@ -407,6 +399,15 @@ if (MRDOCS_DOCUMENTATION_BUILD)
return()
endif()

# Replicate the clang resource directory structure within our own build,
# so that libclang will find it when executing directly from the build directory.
# The installed binary will use runtime path resolution to locate the resource directory
# relative to the executable, so both LLVM and MrDocs must be installed to the same prefix.
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "bin")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib/clang")
set(RESOURCE_DIR "lib/clang/${Clang_VERSION_MAJOR}")
file(CREATE_LINK "${LLVM_BINARY_DIR}/${RESOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/${RESOURCE_DIR}" SYMBOLIC)

#-------------------------------------------------
#
# Tool
Expand Down Expand Up @@ -484,7 +485,6 @@ if (MRDOCS_BUILD_TESTS)
"--addons=${CMAKE_SOURCE_DIR}/share/mrdocs/addons"
--generator=${testgenerator}
"--stdlib-includes=${LIBCXX_DIR}"
"--stdlib-includes=${STDLIB_INCLUDE_DIR}"
"--libc-includes=${CMAKE_SOURCE_DIR}/share/mrdocs/headers/libc-stubs"
--log-level=warn
)
Expand All @@ -499,7 +499,6 @@ if (MRDOCS_BUILD_TESTS)
"--addons=${CMAKE_SOURCE_DIR}/share/mrdocs/addons"
--generator=${testgenerator}
"--stdlib-includes=${LIBCXX_DIR}"
"--stdlib-includes=${STDLIB_INCLUDE_DIR}"
"--libc-includes=${CMAKE_SOURCE_DIR}/share/mrdocs/headers/libc-stubs"
--log-level=warn
DEPENDS mrdocs-test
Expand Down Expand Up @@ -697,9 +696,6 @@ if (MRDOCS_INSTALL)
install(DIRECTORY ${LIBCXX_DIR}/
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/mrdocs/headers/libcxx
FILES_MATCHING PATTERN "*")
install(DIRECTORY ${STDLIB_INCLUDE_DIR}/
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/mrdocs/headers/clang
FILES_MATCHING PATTERN "*")
install(DIRECTORY ${CMAKE_SOURCE_DIR}/share/mrdocs/headers/libc-stubs/
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/mrdocs/headers/libc-stubs
FILES_MATCHING PATTERN "*")
Expand Down
22 changes: 21 additions & 1 deletion docs/modules/ROOT/pages/install.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ manual intervention and potential errors.
This approach is recommended for developers, advanced users, or those integrating Mr.Docs
into larger projects.

[NOTE]
====
The bootstrap script automatically installs all dependencies (LLVM, Clang, etc.) to the same prefix as Mr.Docs.
This ensures that the Clang resource directory can be found at runtime without additional configuration.
====

[#mrdocs-source]
== Manually Install from Source

Expand Down Expand Up @@ -315,12 +321,19 @@ Then build and install MrDocs with:
----
cd build
cmake --build .
cmake --install .
cmake --install . --prefix /path/to/llvm/install/prefix
----

To customize the installation directory, use the `CMAKE_INSTALL_PREFIX` option or use the `--prefix` option for the `cmake --install .` command.
To customize the C and C++ compilers, use the `CMAKE_C_COMPILER` and `CMAKE_CXX_COMPILER` options.

[IMPORTANT]
====
The `--prefix` for MrDocs installation *must* match the installation prefix used for LLVM/Clang.
This is critical for proper runtime resolution of the Clang resource directory.
For example, if LLVM was installed to `/opt/llvm`, then install MrDocs with `cmake --install . --prefix /opt/llvm`.
====

[NOTE]
====
Developers should also enable `-D BUILD_TESTING=ON`.
Expand All @@ -337,3 +350,10 @@ The MrDocs installation directory follows the "Filesystem Hierarchy Standard" (F
* `lib`: the MrDocs library

The FHS layout provides a directory structure that also serves as a widely accepted convention for organizing files and directories in Unix-like systems, but that can be used in any operating system.

[IMPORTANT]
====
The MrDocs binary must be installed in the same installation prefix as the Clang library it was built from.
This is required because the Clang resource directory location is resolved relative to the MrDocs executable at runtime.
When installing both LLVM/Clang and MrDocs, ensure they share the same `CMAKE_INSTALL_PREFIX`.
====
2 changes: 1 addition & 1 deletion docs/modules/ROOT/pages/usage.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ It's also common for libraries to depend on the C++ standard library, the C stan

That means unless `-nostdinc` is defined, all systems include paths are included. This is what allows the user to also use headers like `<Windows.h>` or `<linux/version.h>` without explicitly including anything else, even though they are not part of the C standard library. This is often seen as a convenience but can lead to portability issues.

In this context, MrDocs provides the `use-system-stdlib` and `use-system-libc` options. Both are set as `false` by default, meaning MrDocs will compile the code as if the `-nostdinc&plus;&plus; -nostdlib&plus;&plus;` and `-nostdinc` flags were passed to Clang. Additionally:
In this context, MrDocs provides the `use-system-stdlib` and `use-system-libc` options. Both are set as `true` by default; setting both to `false` results in MrDocs compiling the code as if the `-nostdinc&plus;&plus; -nostdlib&plus;&plus;` and `-nostdinc` flags were passed to Clang. Additionally:

- When `use-system-stdlib` is `false`, MrDocs will use the bundled libc&plus;&plus; headers available in `<mrdocs-root>/share/mrdocs/headers/libcxx` and `<mrdocs-root>/share/mrdocs/headers/clang`. These paths can be adjusted with the `stdlib-includes` option.
- When `use-system-libc` is `false`, MrDocs will use the bundled libc stubs available in `<mrdocs-root>/share/mrdocs/headers/libc-stubs`. This path can be adjusted with the `libc-includes` option.
Expand Down
7 changes: 3 additions & 4 deletions docs/mrdocs.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -570,8 +570,7 @@
},
"stdlib-includes": {
"default": [
"<mrdocs-root>/share/mrdocs/headers/libcxx",
"<mrdocs-root>/share/mrdocs/headers/clang"
"<mrdocs-root>/share/mrdocs/headers/libcxx"
],
"description": "When `use-system-stdlib` is disabled, the C++ standard library headers are available in these paths.",
"items": {
Expand Down Expand Up @@ -611,7 +610,7 @@
"type": "string"
},
"use-system-libc": {
"default": false,
"default": true,
"description": "To achieve reproducible results, MrDocs bundles the LibC headers with its definitions. To use the C standard library available in the system instead, set this option to true.",
"enum": [
true,
Expand All @@ -621,7 +620,7 @@
"type": "boolean"
},
"use-system-stdlib": {
"default": false,
"default": true,
"description": "To achieve reproducible results, MrDocs bundles the LibC++ headers. To use the C++ standard library available in the system instead, set this option to true.",
"enum": [
true,
Expand Down
1 change: 0 additions & 1 deletion docs/website/snippets/sqrt.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include <type_traits>
#include <stdexcept>

/** Computes the square root of an integral value.

Expand Down
8 changes: 6 additions & 2 deletions include/mrdocs/Support/Concepts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,12 @@ concept range_of_tuple_like =
std::ranges::range<Range> && tuple_like<std::ranges::range_value_t<Range>>;

#ifdef __cpp_lib_reference_from_temporary
using std::reference_constructs_from_temporary_v;
using std::reference_converts_from_temporary_v;
/** True when binding `To` from `From` would require a temporary conversion.
*/
using std::reference_constructs_from_temporary_v;
/** Like `reference_converts_from_temporary_v`, but for construction.
*/
using std::reference_converts_from_temporary_v;
#else
/** True when binding `To` from `From` would require a temporary conversion.
*/
Expand Down
3 changes: 2 additions & 1 deletion src/lib/AST/ASTVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2372,7 +2372,8 @@ extractSFINAEInfo(clang::QualType const T)
Result.Type = resultType->getAsType();
for (std::size_t I = 0; I < Args.size(); ++I)
{
if (SFINAEControl->ControllingParams[I])
if (I < SFINAEControl->ControllingParams.size()
&& SFINAEControl->ControllingParams[I])
{
MRDOCS_SYMBOL_TRACE(Args[I], context_);
clang::TemplateArgument ArgsI = Args[I];
Expand Down
2 changes: 1 addition & 1 deletion src/lib/AST/ExtractDocComment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,7 @@ class DocCommentVisitor
auto compsExp = parseHTMLStartSpan(C, cur);
if (!compsExp)
{
report::error(
report::warn(
"{} at {} ({})",
compsExp.error().message(),
filename,
Expand Down
7 changes: 3 additions & 4 deletions src/lib/ConfigOptions.json
Original file line number Diff line number Diff line change
Expand Up @@ -537,16 +537,15 @@
"brief": "Use the system C++ standard library",
"details": "To achieve reproducible results, MrDocs bundles the LibC++ headers. To use the C++ standard library available in the system instead, set this option to true.",
"type": "bool",
"default": false
"default": true
},
{
"name": "stdlib-includes",
"brief": "C++ Standard Library include paths",
"details": "When `use-system-stdlib` is disabled, the C++ standard library headers are available in these paths.",
"type": "list<path>",
"default": [
"<mrdocs-root>/share/mrdocs/headers/libcxx",
"<mrdocs-root>/share/mrdocs/headers/clang"
"<mrdocs-root>/share/mrdocs/headers/libcxx"
],
"relative-to": "<config-dir>",
"must-exist": false,
Expand All @@ -557,7 +556,7 @@
"brief": "Use the system C standard library",
"details": "To achieve reproducible results, MrDocs bundles the LibC headers with its definitions. To use the C standard library available in the system instead, set this option to true.",
"type": "bool",
"default": false
"default": true
},
{
"name": "libc-includes",
Expand Down
9 changes: 6 additions & 3 deletions src/lib/MrDocsCompilationDatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,10 @@ adjustCommandLine(
cmdLineCStrs.data(),
cmdLineCStrs.data() + cmdLineCStrs.size());

auto const systemIncludeFlag = is_clang_cl ? "-external:I" : "-isystem";
char const* systemIncludeFlag = is_clang_cl ? "-external:I" : "-isystem";
// FIXME: No CL equivalent, but not really needed there?
char const* afterIncludeFlag = is_clang_cl ? "-external:I" : "-idirafter";


// ------------------------------------------------------
// Supress all warnings
Expand Down Expand Up @@ -406,10 +409,10 @@ adjustCommandLine(

if (!(*config)->useSystemLibc)
{
new_cmdline.emplace_back("-nostdinc");
new_cmdline.emplace_back(is_clang_cl ? "-X" : "-nostdlibinc");
for (auto const& inc : (*config)->libcIncludes)
{
new_cmdline.emplace_back(systemIncludeFlag);
new_cmdline.emplace_back(afterIncludeFlag);
new_cmdline.emplace_back(inc);
}
}
Expand Down
8 changes: 5 additions & 3 deletions src/lib/MrDocsSettingsDB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "MrDocsSettingsDB.hpp"
#include <mrdocs/Support/Path.hpp>
#include <llvm/Support/Program.h>


namespace mrdocs {
Expand Down Expand Up @@ -60,17 +61,18 @@ MrDocsSettingsDB::MrDocsSettingsDB(ConfigImpl const& config)
});
}

llvm::ErrorOr<std::string> clangPath = llvm::sys::findProgramByName(
"clang");

for (auto const& pathName: sourceFiles)
{
// auto fileName = files::getFileName(pathName);
auto parentDir = files::getParentDir(pathName);

std::vector<std::string> cmds;
cmds.emplace_back("clang");
cmds.emplace_back(clangPath ? *clangPath : "clang");
cmds.emplace_back("-fsyntax-only");
cmds.emplace_back("-std=c++23");
cmds.emplace_back("-pedantic-errors");
cmds.emplace_back("-Werror");
cmds.emplace_back("-x");
cmds.emplace_back("c++");
cmds.emplace_back(pathName);
Expand Down
7 changes: 6 additions & 1 deletion src/test/TestRunner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,11 +184,16 @@ handleFile(
auto runWith = [&](std::vector<std::string> command)
{
auto const db = makeSingleFileDB(filePath, std::move(command));
std::unordered_map<std::string, std::vector<std::string>>
defaultIncludePaths = {
{ "clang", { MRDOCS_TEST_FILES_DIR "/include" } },
{ "clang-cl", { MRDOCS_TEST_FILES_DIR "/include" } },
};
MrDocsCompilationDatabase compilations(
llvm::StringRef(files::getParentDir(filePath)),
db,
config,
std::unordered_map<std::string, std::vector<std::string>>{});
defaultIncludePaths);
handleCompilationDatabase(filePath, compilations, config, layout);
};

Expand Down
Loading
Loading