Skip to content

Commit

Permalink
Standard library incompatibility fix by packaging libc++
Browse files Browse the repository at this point in the history
  • Loading branch information
fpelliccioni committed Aug 9, 2024
1 parent 05400c3 commit 5d28646
Show file tree
Hide file tree
Showing 15 changed files with 295 additions and 34 deletions.
100 changes: 83 additions & 17 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down Expand Up @@ -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')
Expand All @@ -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')
Expand All @@ -173,6 +173,7 @@ jobs:
fi
echo -E "libxml2-root=$libxml2_root" >> $GITHUB_OUTPUT
- name: LLVM Parameters
id: llvm-parameters
run: |
Expand All @@ -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
Expand All @@ -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
Expand All @@ -218,15 +227,15 @@ 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)
cmake --version
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)
if [ ${{ runner.os }} != 'Windows' ]; then
cmake --build ./build --config Release --parallel $N_CORES
Expand All @@ -253,6 +262,63 @@ jobs:
fi
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:
Expand All @@ -278,7 +344,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
Expand Down Expand Up @@ -419,7 +485,7 @@ jobs:
export CXX
CC="${{ steps.setup-cpp.outputs.cc }}"
export CC
declare -a generators=(
"adoc"
"html"
Expand Down Expand Up @@ -461,15 +527,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
Expand All @@ -487,7 +553,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}"
Expand All @@ -498,7 +564,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."
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@
/test-files/**/*.adoc
/test-files/**/*.bad.xml
docs/node_modules
docs/build
docs/build
share/mrdocs/libcxx/
share/mrdocs/clang/
17 changes: 15 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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}/../libcxx/include/c++/v1/")
set(CLANG_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})
Expand Down Expand Up @@ -284,11 +290,11 @@ if (MRDOCS_BUILD_TESTS)
endif ()
target_compile_definitions(mrdocs-test PRIVATE -DMRDOCS_TEST_FILES_DIR="${CMAKE_CURRENT_SOURCE_DIR}/test-files")
add_test(NAME mrdocs-unit-tests COMMAND mrdocs-test --unit=true)
add_test(NAME mrdocs-golden-tests COMMAND mrdocs-test --unit=false --action=test "${PROJECT_SOURCE_DIR}/test-files/golden-tests" --addons="${CMAKE_SOURCE_DIR}/share/mrdocs/addons")
add_test(NAME mrdocs-golden-tests COMMAND mrdocs-test --unit=false --action=test "${PROJECT_SOURCE_DIR}/test-files/golden-tests" --addons="${CMAKE_SOURCE_DIR}/share/mrdocs/addons" --system-includes="${LIBCXX_DIR}")
foreach (action IN ITEMS create update)
add_custom_target(
mrdocs-${action}-test-fixtures
COMMAND mrdocs-test --unit=false --action=${action} "${PROJECT_SOURCE_DIR}/test-files/golden-tests" --addons="${CMAKE_SOURCE_DIR}/share/mrdocs/addons"
COMMAND mrdocs-test --unit=false --action=${action} "${PROJECT_SOURCE_DIR}/test-files/golden-tests" --addons="${CMAKE_SOURCE_DIR}/share/mrdocs/addons" --system-includes="${LIBCXX_DIR}"
DEPENDS mrdocs-test
)
endforeach ()
Expand Down Expand Up @@ -442,6 +448,13 @@ if (MRDOCS_INSTALL)
#-------------------------------------------------
# share
#-------------------------------------------------
install(DIRECTORY ${LIBCXX_DIR}
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/mrdocs/libcxx
FILES_MATCHING PATTERN "*")
install(DIRECTORY ${CLANG_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
Expand Down
4 changes: 3 additions & 1 deletion docs/website/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,16 @@ 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')
const mrdocsInput = cmakeListsPath
const mrdocsOutput = path.join(absSnippetsDir, 'output')
const command = `${mrdocsExecutable} --config=${mrdocsConfig} ${mrdocsInput} --output=${mrdocsOutput} --multipage=true --generate=adoc`
console.log(`Running command: ${command}`)
console.log(`for: ${cmakeListsContent}`)
execSync(command, {encoding: 'utf8'});

// Look for documentation file somewhere in the output directory
Expand Down
9 changes: 9 additions & 0 deletions include/mrdocs/Config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,15 @@ class MRDOCS_DECL
/// from CMakeLists.txt
std::string cmake;

/// True if the compiler has to use just the system's standard library
bool useSystemStdLib = false;

/// Standard Library include paths
std::vector<std::string> systemIncludes;

/// Additional include paths
std::vector<std::string> includes;

/// Additional defines passed to the compiler
std::vector<std::string> defines;

Expand Down
3 changes: 3 additions & 0 deletions include/mrdocs/ConfigOptions.inc
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ COMMON_OPTION (compilationDatabase , compilation-database , Path to the c
// Build options
COMMON_OPTION (cmake , cmake , CMake arguments when generating the compilation database from CMakeLists.txt)
COMMON_OPTION (defines , defines , Additional defines passed to the compiler)
COMMON_OPTION (useSystemStdLib , use-system-stdlib , True if the compiler has to use just the system standard library)
COMMON_OPTION (systemIncludes , system-includes , Standard Library include paths)
COMMON_OPTION (includes , includes , Additional include paths)

// Generators
COMMON_OPTION (generate , generate , Documentation generator. Supported generators are: adoc/html/xml)
Expand Down
55 changes: 42 additions & 13 deletions src/lib/Lib/MrDocsCompilationDatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,10 @@ std::vector<std::string>
adjustCommandLine(
const std::vector<std::string>& cmdline,
const std::vector<std::string>& additional_defines,
std::unordered_map<std::string, std::vector<std::string>> const& implicitIncludeDirectories)
std::unordered_map<std::string, std::vector<std::string>> const& implicitIncludeDirectories,
std::vector<std::string> const& systemIncludes,
std::vector<std::string> const& includes,
bool useSystemStdLib)
{
if (cmdline.empty())
{
Expand Down Expand Up @@ -274,19 +277,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));
}

// ------------------------------------------------------
Expand Down Expand Up @@ -366,7 +392,10 @@ MrDocsCompilationDatabase(
cmd.CommandLine = adjustCommandLine(
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))
Expand Down
1 change: 1 addition & 0 deletions src/lib/Metadata/Finalize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "lib/Lib/Info.hpp"
#include "lib/Support/NameParser.hpp"
#include <mrdocs/Metadata.hpp>
#include <algorithm>
#include <ranges>
#include <span>

Expand Down
Loading

0 comments on commit 5d28646

Please sign in to comment.