Skip to content

docs: one-liner installation instructions #934

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jul 18, 2025
Merged
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
15 changes: 6 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@ jobs:
contents: write

steps:
# We install git if we are using a container because
# containers don't always include git.
# We need git to ensure actions/checkout@v4 will use git and
# for the next steps that need to clone repositories
- name: Install Git
uses: alandefreitas/cpp-actions/[email protected]
if: matrix.container != ''
Expand All @@ -133,22 +137,14 @@ jobs:
with:
apt-get: git

# Set up the repository ownership to avoid issues with git commands
- name: Configure Git Safe Directory
if: matrix.container != ''
run: git config --global --add safe.directory "$(pwd)"

- name: Clone MrDocs
uses: actions/checkout@v4

- name: Install Git
uses: alandefreitas/cpp-actions/[email protected]
if: matrix.container != ''
env:
DEBIAN_FRONTEND: 'noninteractive'
TZ: 'Etc/UTC'
with:
apt-get: git

- name: Setup CMake
uses: alandefreitas/cpp-actions/[email protected]
id: setup-cmake
Expand Down Expand Up @@ -324,6 +320,7 @@ jobs:
ccflags: ${{ matrix.ccflags }}
cxxflags: ${{ matrix.cxxflags }}
build-type: Release
shared: false
extra-args: |
-D LIBXML2_WITH_PROGRAMS=ON
-D LIBXML2_WITH_FTP=OFF
Expand Down
70 changes: 47 additions & 23 deletions bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,17 @@
import tarfile
import json
import re
from functools import lru_cache

@lru_cache(maxsize=1)
def running_from_mrdocs_source_dir():
"""
Checks if the current working directory is the same as the script directory.
:return:
"""
script_dir = os.path.dirname(os.path.abspath(__file__))
cwd = os.getcwd()
return cwd == script_dir

@dataclass
class InstallOptions:
Expand All @@ -39,16 +50,16 @@ class InstallOptions:
cmake_path: str = ''

# MrDocs
mrdocs_src_dir: str = field(default_factory=lambda: os.getcwd())
mrdocs_src_dir: str = field(default_factory=lambda: os.getcwd() if running_from_mrdocs_source_dir() else os.path.join(os.getcwd(), "mrdocs"))
mrdocs_build_type: str = "Release"
mrdocs_repo: str = "https://github.com/cppalliance/mrdocs"
mrdocs_branch: str = "develop"
mrdocs_use_user_presets: bool = True
mrdocs_preset_name: str = "<mrdocs-build-type:lower>-<os:lower>"
mrdocs_build_dir: str = "<mrdocs-src-dir>/build/<mrdocs-build-type:lower>-<os:lower>"
mrdocs_build_tests: bool = True
mrdocs_install_dir: str = "<mrdocs-src-dir>/install/<mrdocs-build-type:lower>-<os:lower>"
mrdocs_system_install: bool = False
mrdocs_system_install: bool = field(default_factory=lambda: not running_from_mrdocs_source_dir())
mrdocs_install_dir: str = field(default_factory=lambda: "<mrdocs-src-dir>/install/<mrdocs-build-type:lower>-<os:lower>" if running_from_mrdocs_source_dir() else "")
mrdocs_run_tests: bool = True

# Third-party dependencies
Expand Down Expand Up @@ -96,7 +107,7 @@ class InstallOptions:
"mrdocs_src_dir": "MrDocs source directory.",
"mrdocs_repo": "URL of the MrDocs repository to clone.",
"mrdocs_branch": "Branch or tag of the MrDocs repository to use.",
"mrdocs_build_type": "CMake build type for MrDocs (e.g., Release, Debug).",
"mrdocs_build_type": "CMake build type for MrDocs (Release, Debug, RelWithDebInfo, MilRelSize, DebWithOpt).",
"mrdocs_use_user_presets": "Whether to use CMake User Presets for building MrDocs.",
"mrdocs_preset_name": "Name of the CMake User Preset to use for MrDocs.",
"mrdocs_build_dir": "Directory where MrDocs will be built.",
Expand All @@ -106,24 +117,24 @@ class InstallOptions:
"mrdocs_run_tests": "Whether to run tests after building MrDocs.",
"third_party_src_dir": "Directory for all third-party source dependencies.",
"fmt_src_dir": "Directory for the fmt library source code.",
"fmt_build_type": "CMake build type for the fmt library.",
"fmt_build_type": "CMake build type for the fmt library. (Release, Debug, RelWithDebInfo, MilRelSize, DebWithOpt)",
"fmt_build_dir": "Directory where the fmt library will be built.",
"fmt_install_dir": "Directory where the fmt library will be installed.",
"fmt_repo": "URL of the fmt library repository to clone.",
"fmt_branch": "Branch or tag of the fmt library to use.",
"duktape_src_dir": "Directory for the Duktape source code.",
"duktape_url": "Download URL for the Duktape source archive.",
"duktape_build_type": "CMake build type for Duktape.",
"duktape_build_type": "CMake build type for Duktape. (Release, Debug, RelWithDebInfo, MilRelSize, DebWithOpt)",
"duktape_build_dir": "Directory where Duktape will be built.",
"duktape_install_dir": "Directory where Duktape will be installed.",
"libxml2_src_dir": "Directory for the libxml2 source code.",
"libxml2_build_type": "CMake build type for libxml2.",
"libxml2_build_type": "CMake build type for libxml2. (Release, Debug, RelWithDebInfo, MilRelSize, DebWithOpt)",
"libxml2_build_dir": "Directory where libxml2 will be built.",
"libxml2_install_dir": "Directory where libxml2 will be installed.",
"libxml2_repo": "URL of the libxml2 repository to clone.",
"libxml2_branch": "Branch or tag of libxml2 to use.",
"llvm_src_dir": "Directory for the LLVM project source code.",
"llvm_build_type": "CMake build type for LLVM.",
"llvm_build_type": "CMake build type for LLVM. (Release, Debug, RelWithDebInfo, MilRelSize, DebWithOpt)",
"llvm_build_dir": "Directory where LLVM will be built.",
"llvm_install_dir": "Directory where LLVM will be installed.",
"llvm_repo": "URL of the LLVM project repository to clone.",
Expand Down Expand Up @@ -161,6 +172,14 @@ def prompt_string(self, prompt, default):
: param default: The default value to use if the user does not provide input.
:return:
"""
prompt = prompt.strip()
if prompt.endswith('.'):
prompt = prompt[:-1]
prompt = prompt.strip()
BLUE = "\033[94m"
RESET = "\033[0m"
if self.supports_ansi():
prompt = f"{BLUE}{prompt}{RESET}"
inp = input(f"{prompt} ({default}): ")
result = inp.strip() or default
return result
Expand All @@ -173,6 +192,14 @@ def prompt_boolean(self, prompt, default = None):
:param default: The default value to return if the user does not provide input.
:return: bool: True if the user answers yes, False otherwise.
"""
prompt = prompt.strip()
if prompt.endswith('.'):
prompt = prompt[:-1]
prompt = prompt.strip()
BLUE = "\033[94m"
RESET = "\033[0m"
if self.supports_ansi():
prompt = f"{BLUE}{prompt}{RESET}"
while True:
answer = input(f"{prompt} ({'y/n' if default is None else 'yes' if default else 'no'}): ").strip().lower()
if answer in ('y', 'yes'):
Expand Down Expand Up @@ -310,17 +337,10 @@ def run_cmd(self, cmd, cwd=None):
"""
BLUE = "\033[94m"
RESET = "\033[0m"
def supports_ansi():
if os.name == "posix":
return True
if os.name == "nt":
return "WT_SESSION" in os.environ or sys.stdout.isatty()
return False

if cwd is None:
cwd = os.getcwd()
color = BLUE if supports_ansi() else ""
reset = RESET if supports_ansi() else ""
color = BLUE if self.supports_ansi() else ""
reset = RESET if self.supports_ansi() else ""
if isinstance(cmd, list):
print(f"{color}{cwd}> {' '.join(cmd)}{reset}")
else:
Expand Down Expand Up @@ -404,10 +424,8 @@ def cmake_workflow(self, src_dir, build_type, build_dir, install_dir, extra_args
if build_type_is_debwithopt:
if self.is_windows():
config_args.extend(["-DCMAKE_CXX_FLAGS=/DWIN32 /D_WINDOWS /Ob1 /O2 /Zi", "-DCMAKE_C_FLAGS=/DWIN32 /D_WINDOWS /Ob1 /O2 /Zi"])
config_args.extend(["-DCMAKE_CXX_FLAGS=/Ob1 /O2 /Zi", "-DCMAKE_C_FLAGS=/Ob1 /O2 /Zi"])
else:
config_args.extend(["-DCMAKE_CXX_FLAGS=-Og -g", "-DCMAKE_C_FLAGS=-Og -g"])
config_args.extend(["-DCMAKE_CXX_FLAGS_DEBUG=-Og -g", "-DCMAKE_C_FLAGS_DEBUG=-Og -g"])
if isinstance(extra_args, str):
config_args.extend(extra_args.split())
elif isinstance(extra_args, list):
Expand Down Expand Up @@ -736,8 +754,9 @@ def install_mrdocs(self):
self.prompt_option("mrdocs_install_dir")

extra_args = []
if self.options.mrdocs_system_install and self.options.mrdocs_install_dir:
if not self.options.mrdocs_system_install and self.options.mrdocs_install_dir:
extra_args.extend(["-D", f"CMAKE_INSTALL_PREFIX={self.options.mrdocs_install_dir}"])

if self.options.mrdocs_use_user_presets:
extra_args.append(f"--preset={self.options.mrdocs_preset_name}")
else:
Expand All @@ -763,11 +782,16 @@ def install_mrdocs(self):
ctest_path = os.path.join(os.path.dirname(self.options.cmake_path), "ctest")
if not os.path.exists(ctest_path):
raise FileNotFoundError(f"ctest executable not found at {ctest_path}. Please ensure CMake is installed correctly.")
# --parallel 4 --no-tests=error --progress --output-on-failure
test_args = [ctest_path, "--test-dir", self.options.mrdocs_build_dir, "--output-on-failure", "--progress", "--no-tests=error", "--output-on-failure"]
test_args = [ctest_path, "--test-dir", self.options.mrdocs_build_dir, "--output-on-failure", "--progress",
"--no-tests=error", "--output-on-failure", "--parallel", str(os.cpu_count() or 1)]
self.run_cmd(test_args)

print(f"\nMrDocs has been successfully installed in {self.options.mrdocs_install_dir}.\n")
YELLOW = "\033[93m"
RESET = "\033[0m"
if self.supports_ansi():
print(f"{YELLOW}MrDocs has been successfully installed in {self.options.mrdocs_install_dir}.{RESET}")
else:
print(f"\nMrDocs has been successfully installed in {self.options.mrdocs_install_dir}.\n")

def install_all(self):
self.check_tools()
Expand Down
Loading
Loading