Skip to content
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ $ ./setup.sh

The script creates `.env` and installs the Python dependencies listed in `pyproject.toml`.
If `uv` is available, it uses `uv venv` and `uv pip install`; otherwise it uses the standard `venv` module and `pip`.
It also builds a local precompiled header under `.env/pch/` to speed up repeated C++ compilations.

Add `bin/` to your `PATH` so the tools can be invoked with short command names:

Expand Down
77 changes: 77 additions & 0 deletions bin/build_pch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#!/usr/bin/env python3

import hashlib
import json
from pathlib import Path
import shutil
import subprocess

from run import COMPILER, COMPILE_FLAGS, PCH_BUILD_FLAGS, PCH_CONTENT, PCH_GCH, PCH_HEADER


def compiler_identity() -> dict[str, str | int]:
compiler_path = shutil.which(COMPILER)
if compiler_path is None:
raise FileNotFoundError(f"Compiler not found: {COMPILER}")

resolved_compiler = Path(compiler_path).resolve()
cc1plus = subprocess.check_output(
[COMPILER, "-print-prog-name=cc1plus"], text=True
).strip()
cc1plus_path = Path(cc1plus).resolve()

return {
"path": str(resolved_compiler),
"mtime_ns": resolved_compiler.stat().st_mtime_ns,
"cc1plus_path": str(cc1plus_path),
"cc1plus_mtime_ns": cc1plus_path.stat().st_mtime_ns,
"version": subprocess.check_output(
[COMPILER, "-dumpfullversion", "-dumpversion"], text=True
).strip(),
}


def pch_signature() -> str:
payload = {
"compiler": compiler_identity(),
"compile_flags": COMPILE_FLAGS,
"pch_build_flags": PCH_BUILD_FLAGS,
"content": PCH_CONTENT,
}
encoded = json.dumps(payload, sort_keys=True).encode()
return hashlib.sha256(encoded).hexdigest()


def main() -> int:
PCH_HEADER.parent.mkdir(parents=True, exist_ok=True)
if not PCH_HEADER.exists() or PCH_HEADER.read_text(encoding="utf8") != PCH_CONTENT:
PCH_HEADER.write_text(PCH_CONTENT, encoding="utf8")

stamp_path = PCH_HEADER.with_suffix(PCH_HEADER.suffix + ".sha256")
signature = pch_signature()

if PCH_GCH.exists() and stamp_path.exists() and stamp_path.read_text().strip() == signature:
print(f"PCH is up to date: {PCH_GCH}")
return 0

command = [
COMPILER,
*PCH_BUILD_FLAGS,
"-x",
"c++-header",
str(PCH_HEADER),
"-o",
str(PCH_GCH),
]

print(f"Building PCH: {PCH_GCH}")
PCH_GCH.unlink(missing_ok=True)
subprocess.run(command, check=True)
if not PCH_GCH.is_file():
raise RuntimeError(f"Compiler did not create PCH: {PCH_GCH}")
stamp_path.write_text(signature + "\n", encoding="utf8")
return 0


if __name__ == "__main__":
raise SystemExit(main())
50 changes: 32 additions & 18 deletions bin/run.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,36 @@
import os
import subprocess
from pathlib import Path

from message import debug_print
from path import BIN_PATH
from path import BIN_PATH, PROJ_PATH

import time

COMPILER = "g++-15"
COMPILE_FLAGS = [
"-std=gnu++23",
"-O2",
"-Wall",
"-Wextra",
"-march=native",
# "-flto=auto",
"-fopenmp",
"-pthread",
"-ftrivial-auto-var-init=zero",
"-fconstexpr-depth=1024",
"-fconstexpr-loop-limit=524288",
"-fconstexpr-ops-limit=2097152",
"-DYSN_DEBUG",
]
PCH_BUILD_FLAGS = COMPILE_FLAGS.copy()
LINK_FLAGS = [
"-lstdc++exp",
]
PCH_CONTENT = "#include <bits/stdc++.h>\n"
PCH_HEADER = Path(PROJ_PATH) / ".env" / "pch" / "stdcxx_all.hpp"
PCH_GCH = Path(str(PCH_HEADER) + ".gch")

def exec_path_of(source_path):
return os.path.splitext(source_path)[0] + ".exe"

Expand Down Expand Up @@ -36,25 +61,14 @@ def compile(source_path):

debug_print(f"Compiling {source_path} ...")
start_time = time.time()
pch_flags = ["-I", str(PCH_HEADER.parent), "-include", PCH_HEADER.name] if PCH_GCH.exists() else []
compilation = subprocess.run([
"g++-15",
"-std=gnu++23",
"-O2",
"-Wall",
"-Wextra",
"-march=native",
"-flto=auto",
"-fmodules",
"-fopenmp",
"-pthread",
"-lstdc++exp",
"-ftrivial-auto-var-init=zero",
"-fconstexpr-depth=1024",
"-fconstexpr-loop-limit=524288",
"-fconstexpr-ops-limit=2097152",
"-DYSN_DEBUG",
COMPILER,
*COMPILE_FLAGS,
*pch_flags,
source_path,
"-o", exec_path
"-o", exec_path,
*LINK_FLAGS,
])
end_time = time.time()
duration = end_time - start_time
Expand Down
1 change: 1 addition & 0 deletions documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ ly

`setup.sh` は `.env` を作成し、`pyproject.toml` に記述された Python 依存を導入します。
`uv` が使える環境では `uv venv` と `uv pip install` を使い、なければ標準の `venv` と `pip` にフォールバックします。
セットアップ時には `.env/pch/` に `bits/stdc++.h` 用のローカル PCH も作成し、以後の C++ コンパイルで利用します。
`ly` や Graphviz 出力で使う `tree` と `dot` コマンドが見つからない場合は、追加で必要なシステムコマンドとして案内します。

C++ 側のテストは `CMakeLists.txt` と `vcpkg.json` で管理されます。
Expand Down
18 changes: 18 additions & 0 deletions fixg++-15.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/bash

set -euo pipefail

# https://github.com/orgs/Homebrew/discussions/6229#discussioncomment-14079111

brew update
brew upgrade
brew install binutils
brew reinstall binutils
sudo update-alternatives \
--install /usr/bin/as as /home/linuxbrew/.linuxbrew/opt/binutils/bin/as 100 \
--slave /usr/bin/ld ld /home/linuxbrew/.linuxbrew/opt/binutils/bin/ld \
--slave /usr/bin/nm nm /home/linuxbrew/.linuxbrew/opt/binutils/bin/nm \
--slave /usr/bin/objdump objdump /home/linuxbrew/.linuxbrew/opt/binutils/bin/objdump \
--slave /usr/bin/objcopy objcopy /home/linuxbrew/.linuxbrew/opt/binutils/bin/objcopy \
--slave /usr/bin/strip strip /home/linuxbrew/.linuxbrew/opt/binutils/bin/strip
sudo update-alternatives --config as
2 changes: 2 additions & 0 deletions setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ else
python -m pip install "${python_dependencies[@]}"
fi

.env/bin/python bin/build_pch.py

missing_commands=()

if ! command -v tree >/dev/null 2>&1; then
Expand Down
Loading