17 Commits

Author SHA1 Message Date
peoplemiau1
dabeb411d3 docs: update changelog for 0.7.1 (bilingual & multi-arch) 2026-06-02 16:22:57 +03:00
peoplemiau1
b8338c752b chore: remove i686-pc-windows-gnu from build matrix 2026-06-02 16:00:08 +03:00
b70438b16d feat: update README 2026-06-02 19:38:16 +08:00
0597b5ddb2 feat: add --help for all commands, man pages 2026-06-02 19:27:44 +08:00
peoplemiau1
8866fb0796 Bump version to 0.7.1 2026-06-02 13:55:54 +03:00
peoplemiau1
7d853482aa feat: build deb and rpm packages for all linux architectures 2026-06-02 13:50:57 +03:00
peoplemiau1
ef9ca57295 Add multi-arch support to release workflows and installation scripts 2026-06-02 13:38:42 +03:00
peoplemiau1
8e1fb60692 Add Linux i686, armv7, and riscv64 architectures support to release workflow and installation script 2026-06-02 13:25:38 +03:00
peoplemiau1
d6ddb5da3d Merge origin/master into dev and resolve conflicts in release.yml 2026-06-02 13:06:15 +03:00
peoplemiau1
d26e93dd47 Optimize release binary size and parse_d_file dependency parsing 2026-06-02 12:58:06 +03:00
97d2970727 feat: add dcr-dev and dcr-dev-bin publishing to AUR 2026-06-02 17:34:17 +08:00
kie
35f9b6be94 Update README.md 2026-06-02 11:27:09 +03:00
6885a82be7 feat: add package name validation to init and new commands 2026-06-02 16:26:11 +08:00
5d587db227 fix: update AUR publishing process to handle git initialization and improve build flags 2026-06-02 16:08:58 +08:00
424f4f6929 feat: add support for publishing Snap packages with dynamic file resolution 2026-06-02 16:08:58 +08:00
443306aa5f fix: update AUR publishing process to handle git initialization and improve build flags 2026-06-02 15:17:20 +08:00
f21f50facb feat: add support for publishing Snap packages with dynamic file resolution 2026-06-02 01:27:04 +08:00
42 changed files with 1369 additions and 118 deletions

View File

@@ -21,6 +21,10 @@ on:
description: "Update AUR packages (dcr & dcr-bin)" description: "Update AUR packages (dcr & dcr-bin)"
type: boolean type: boolean
default: false default: false
run_aur_dev:
description: "Update Dev AUR packages (dcr-dev, dcr-dev-bin)"
type: boolean
default: false
run_bsd: run_bsd:
description: "Build BSD" description: "Build BSD"
type: boolean type: boolean
@@ -56,6 +60,7 @@ jobs:
outputs: outputs:
tag: ${{ steps.tag.outputs.value }} tag: ${{ steps.tag.outputs.value }}
version: ${{ steps.tag.outputs.version }} version: ${{ steps.tag.outputs.version }}
clean_version: ${{ steps.tag.outputs.clean_version }}
prerelease: ${{ steps.tag.outputs.prerelease }} prerelease: ${{ steps.tag.outputs.prerelease }}
steps: steps:
- name: Resolve tag - name: Resolve tag
@@ -67,9 +72,11 @@ jobs:
TAG="${GITHUB_REF_NAME}" TAG="${GITHUB_REF_NAME}"
fi fi
VERSION="${TAG#v}" VERSION="${TAG#v}"
CLEAN_VERSION="${VERSION%-dev}"
[[ "$TAG" == *"-"* ]] && PRERELEASE="true" || PRERELEASE="false" [[ "$TAG" == *"-"* ]] && PRERELEASE="true" || PRERELEASE="false"
echo "value=${TAG}" >> "$GITHUB_OUTPUT" echo "value=${TAG}" >> "$GITHUB_OUTPUT"
echo "version=${VERSION}" >> "$GITHUB_OUTPUT" echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "clean_version=${CLEAN_VERSION}" >> "$GITHUB_OUTPUT"
echo "prerelease=${PRERELEASE}" >> "$GITHUB_OUTPUT" echo "prerelease=${PRERELEASE}" >> "$GITHUB_OUTPUT"
# ── Release Notes ────────────────────────────────────────────────────────── # ── Release Notes ──────────────────────────────────────────────────────────
@@ -122,6 +129,36 @@ jobs:
body_path: .github/release-notes.md body_path: .github/release-notes.md
prerelease: ${{ needs.setup.outputs.prerelease == 'true' }} prerelease: ${{ needs.setup.outputs.prerelease == 'true' }}
# ── Man Pages Archive ──────────────────────────────────────────────────────
man-pages:
if: ${{ github.event_name == 'push' || github.event.inputs.run_linux == 'true' }}
needs: [setup, notes, create-release]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.setup.outputs.tag }}
- name: Download Release Notes
uses: actions/download-artifact@v4
with:
name: release-notes
path: .github
- name: Create Man Pages Archive
run: |
tar czf "dcr-man-pages-${{ needs.setup.outputs.version }}.tar.gz" \
--transform 's/^man\/man1\//usr\/share\/man\/man1\//' \
man/man1/*.1
- name: Upload Man Pages to Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ needs.setup.outputs.tag }}
files: dcr-man-pages-${{ needs.setup.outputs.version }}.tar.gz
body_path: .github/release-notes.md
prerelease: ${{ needs.setup.outputs.prerelease == 'true' }}
# ── Linux Binaries Matrix ────────────────────────────────────────────────── # ── Linux Binaries Matrix ──────────────────────────────────────────────────
build-linux: build-linux:
if: ${{ github.event_name == 'push' || github.event.inputs.run_linux == 'true' }} if: ${{ github.event_name == 'push' || github.event.inputs.run_linux == 'true' }}
@@ -135,6 +172,12 @@ jobs:
- target: aarch64-unknown-linux-gnu - target: aarch64-unknown-linux-gnu
- target: x86_64-unknown-linux-musl - target: x86_64-unknown-linux-musl
- target: aarch64-unknown-linux-musl - target: aarch64-unknown-linux-musl
- target: i686-unknown-linux-gnu
- target: i686-unknown-linux-musl
- target: armv7-unknown-linux-gnueabihf
- target: armv7-unknown-linux-musleabihf
- target: riscv64gc-unknown-linux-gnu
- target: riscv64gc-unknown-linux-musl
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
@@ -192,41 +235,73 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
include: package_type: [deb, rpm, arch, snap]
- package_type: deb target: [x86_64-unknown-linux-gnu, aarch64-unknown-linux-gnu, i686-unknown-linux-gnu, armv7-unknown-linux-gnueabihf, riscv64gc-unknown-linux-gnu]
artifact_name: debian-package exclude:
- package_type: rpm
artifact_name: rpm-package
- package_type: arch - package_type: arch
artifact_name: arch-package target: aarch64-unknown-linux-gnu
- package_type: arch
target: i686-unknown-linux-gnu
- package_type: arch
target: armv7-unknown-linux-gnueabihf
- package_type: arch
target: riscv64gc-unknown-linux-gnu
- package_type: snap - package_type: snap
artifact_name: snap-package target: aarch64-unknown-linux-gnu
- package_type: snap
target: i686-unknown-linux-gnu
- package_type: snap
target: armv7-unknown-linux-gnueabihf
- package_type: snap
target: riscv64gc-unknown-linux-gnu
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
ref: ${{ needs.setup.outputs.tag }} ref: ${{ needs.setup.outputs.tag }}
- name: Setup Rust (For non-container builds) - name: Install cargo-zigbuild
if: matrix.package_type == 'deb' || matrix.package_type == 'rpm'
run: |
pip install cargo-zigbuild
echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: Setup Zig
if: (matrix.package_type == 'deb' || matrix.package_type == 'rpm') && matrix.target != 'x86_64-unknown-linux-gnu'
uses: mlugg/setup-zig@v1
with:
version: 0.13.0
- name: Setup Rust
if: matrix.package_type != 'arch' if: matrix.package_type != 'arch'
uses: dtolnay/rust-toolchain@stable uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
# ── DEB Build ── # ── DEB Build ──
- name: Build Debian Package - name: Build Debian Package
if: matrix.package_type == 'deb' if: matrix.package_type == 'deb'
run: | run: |
cargo install cargo-deb cargo install cargo-deb
cargo build --release if [ "${{ matrix.target }}" != "x86_64-unknown-linux-gnu" ]; then
cargo deb --no-build cargo zigbuild --release --target ${{ matrix.target }}
mkdir -p dist-packages && cp target/debian/*.deb dist-packages/ else
cargo build --release --target ${{ matrix.target }}
fi
cargo deb --no-build --target ${{ matrix.target }}
mkdir -p dist-packages && cp target/${{ matrix.target }}/debian/*.deb dist-packages/
# ── RPM Build ── # ── RPM Build ──
- name: Build RPM Package - name: Build RPM Package
if: matrix.package_type == 'rpm' if: matrix.package_type == 'rpm'
run: | run: |
cargo install cargo-generate-rpm cargo install cargo-generate-rpm
cargo build --release if [ "${{ matrix.target }}" != "x86_64-unknown-linux-gnu" ]; then
cargo generate-rpm cargo zigbuild --release --target ${{ matrix.target }}
mkdir -p dist-packages && cp target/generate-rpm/*.rpm dist-packages/ else
cargo build --release --target ${{ matrix.target }}
fi
cargo generate-rpm --target ${{ matrix.target }}
mkdir -p dist-packages && cp target/${{ matrix.target }}/generate-rpm/*.rpm dist-packages/
# ── Snap Build ── # ── Snap Build ──
- name: Build Snap Package - name: Build Snap Package
@@ -235,6 +310,7 @@ jobs:
cargo build --release cargo build --release
mkdir -p packaging/snap/dist/bin mkdir -p packaging/snap/dist/bin
cp target/release/dcr packaging/snap/dist/bin/ cp target/release/dcr packaging/snap/dist/bin/
cp -r man packaging/snap/dist/man
- name: Snapcraft Build Action - name: Snapcraft Build Action
if: matrix.package_type == 'snap' if: matrix.package_type == 'snap'
@@ -271,12 +347,17 @@ jobs:
sha256sums=('${SHA256}') sha256sums=('${SHA256}')
build() { build() {
cd "\$srcdir/\$pkgname-${PKGVER_ORIG}" cd "\$srcdir/\$pkgname-${PKGVER_ORIG}"
unset CFLAGS CXXFLAGS LDFLAGS
export RUSTFLAGS="-C linker=cc"
cargo build --release --locked cargo build --release --locked
} }
package() { package() {
cd "\$srcdir/\$pkgname-${PKGVER_ORIG}" cd "\$srcdir/dcr-${PKGVER_ORIG}"
install -Dm755 "target/release/dcr" "\$pkgdir/usr/bin/dcr" install -Dm755 "target/release/dcr" "\$pkgdir/usr/bin/dcr"
install -Dm644 LICENSE "\$pkgdir/usr/share/licenses/\$pkgname/LICENSE" install -Dm644 LICENSE "\$pkgdir/usr/share/licenses/\$pkgname/LICENSE"
for manpage in man/man1/*.1; do
install -Dm644 "\$manpage" "\$pkgdir/usr/share/man/man1/\$(basename "\$manpage")"
done
} }
PKG PKG
docker run --rm \ docker run --rm \
@@ -296,7 +377,7 @@ jobs:
- name: Upload Package Artifact - name: Upload Package Artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: ${{ matrix.artifact_name }} name: ${{ matrix.package_type }}-package-${{ matrix.target }}
path: dist-packages/* path: dist-packages/*
if-no-files-found: ignore if-no-files-found: ignore
@@ -321,10 +402,10 @@ jobs:
with: with:
tag_name: ${{ needs.setup.outputs.tag }} tag_name: ${{ needs.setup.outputs.tag }}
files: | files: |
collected-packages/debian-package/* collected-packages/deb-package-*/*
collected-packages/rpm-package/* collected-packages/rpm-package-*/*
collected-packages/arch-package/* collected-packages/arch-package-*/*
collected-packages/snap-package/* collected-packages/snap-package-*/*
body_path: .github/release-notes.md body_path: .github/release-notes.md
prerelease: ${{ needs.setup.outputs.prerelease == 'true' }} prerelease: ${{ needs.setup.outputs.prerelease == 'true' }}
@@ -450,8 +531,6 @@ jobs:
cp target/release/dcr "$ASSET" cp target/release/dcr "$ASSET"
echo "BSD_ASSET=${ASSET}" >> "$GITHUB_ENV" echo "BSD_ASSET=${ASSET}" >> "$GITHUB_ENV"
# --- UPLOAD TARGET --- # --- UPLOAD TARGET ---
- name: Upload BSD Asset to Release - name: Upload BSD Asset to Release
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v2
@@ -472,6 +551,7 @@ jobs:
include: include:
- target: x86_64-pc-windows-msvc - target: x86_64-pc-windows-msvc
- target: aarch64-pc-windows-msvc - target: aarch64-pc-windows-msvc
- target: i686-pc-windows-msvc
- target: x86_64-pc-windows-gnu - target: x86_64-pc-windows-gnu
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@@ -552,14 +632,13 @@ jobs:
'gcc: build C/C++ projects with GCC' 'gcc: build C/C++ projects with GCC'
'clang: build C/C++ projects with Clang' 'clang: build C/C++ projects with Clang'
) )
source=("\$pkgname-\$pkgver.tar.gz::\${SRC_URL}") source=("\$pkgname-\$pkgver.tar.gz::${SRC_URL}")
sha256sums=('${SHA256}') sha256sums=('${SHA256}')
build() { build() {
cd "\$srcdir/\$pkgname-${PKGVER_ORIG}" cd "\$srcdir/\$pkgname-${PKGVER_ORIG}"
export CARGO_PROFILE_RELEASE_LTO=false unset CFLAGS CXXFLAGS LDFLAGS
export RUSTFLAGS="\${RUSTFLAGS:-}" export RUSTFLAGS="-C linker=cc"
export RUSTFLAGS="\${RUSTFLAGS/-C link-arg=-fuse-ld=lld/}"
cargo build --release --locked cargo build --release --locked
} }
@@ -567,10 +646,11 @@ jobs:
cd "\$srcdir/\$pkgname-${PKGVER_ORIG}" cd "\$srcdir/\$pkgname-${PKGVER_ORIG}"
install -Dm755 "target/release/dcr" "\$pkgdir/usr/bin/dcr" install -Dm755 "target/release/dcr" "\$pkgdir/usr/bin/dcr"
install -Dm644 LICENSE "\$pkgdir/usr/share/licenses/\$pkgname/LICENSE" install -Dm644 LICENSE "\$pkgdir/usr/share/licenses/\$pkgname/LICENSE"
for manpage in man/man1/*.1; do
install -Dm644 "\$manpage" "\$pkgdir/usr/share/man/man1/\$(basename "\$manpage")"
done
} }
PKG PKG
cat > packages/aur/dcr/.SRCINFO <<SRC
pkgbase = dcr pkgbase = dcr
pkgdesc = Cargo-like utility to manage C/C++ projects pkgdesc = Cargo-like utility to manage C/C++ projects
pkgver = ${PKGVER_CLEAN} pkgver = ${PKGVER_CLEAN}
@@ -603,22 +683,31 @@ jobs:
ssh-keyscan aur.archlinux.org >> ~/.ssh/known_hosts ssh-keyscan aur.archlinux.org >> ~/.ssh/known_hosts
export GIT_SSH_COMMAND='ssh -i ~/.ssh/aur -o IdentitiesOnly=yes' export GIT_SSH_COMMAND='ssh -i ~/.ssh/aur -o IdentitiesOnly=yes'
git clone "ssh://aur@aur.archlinux.org/${AUR_PACKAGE}.git" aur-repo
cp packages/aur/dcr/PKGBUILD aur-repo/PKGBUILD mkdir -p aur-repo
cp packages/aur/dcr/.SRCINFO aur-repo/.SRCINFO
cd aur-repo cd aur-repo
git init
git remote add origin "ssh://aur@aur.archlinux.org/${AUR_PACKAGE}.git"
git fetch origin master || true
git checkout master || git checkout -b master
cp ../packages/aur/dcr/PKGBUILD .
cp ../packages/aur/dcr/.SRCINFO .
git config user.name "github-actions[bot]" git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com" git config user.email "github-actions[bot]@users.noreply.github.com"
if git diff --quiet; then if git rev-parse --verify HEAD >/dev/null 2>&1; then
echo "No AUR changes" if git diff --quiet; then
exit 0 echo "No AUR changes"
exit 0
fi
fi fi
git add PKGBUILD .SRCINFO git add PKGBUILD .SRCINFO
git commit -m "dcr ${{ needs.setup.outputs.version }}" git commit -m "dcr ${{ needs.setup.outputs.version }}"
git push git push -u origin master
# ── Arch User Repository (dcr-bin) ──────────────────────────────── # ── Arch User Repository (dcr-bin) ────────────────────────────────
publish-aur-bin: publish-aur-bin:
@@ -635,10 +724,22 @@ jobs:
shell: bash shell: bash
run: | run: |
set -euo pipefail set -euo pipefail
BIN_URL="https://github.com/dexoron/dcr/releases/download/${{ needs.setup.outputs.tag }}/dcr-x86_64-unknown-linux-musl-${{ needs.setup.outputs.version }}" TAG="${{ needs.setup.outputs.tag }}"
SHA256="$(curl -fsSL "$BIN_URL" | sha256sum | awk '{print $1}')" VER="${{ needs.setup.outputs.version }}"
echo "bin_url=$BIN_URL" >> "$GITHUB_OUTPUT" BASE_URL="https://github.com/dexoron/dcr/releases/download/${TAG}"
echo "sha256=$SHA256" >> "$GITHUB_OUTPUT" for arch in x86_64 aarch64 i686 armv7h riscv64; do
case "$arch" in
x86_64) triple="x86_64-unknown-linux-musl" ;;
aarch64) triple="aarch64-unknown-linux-musl" ;;
i686) triple="i686-unknown-linux-musl" ;;
armv7h) triple="armv7-unknown-linux-musleabihf" ;;
riscv64) triple="riscv64gc-unknown-linux-musl" ;;
esac
url="${BASE_URL}/dcr-${triple}-${VER}"
sha256="$(curl -fsSL "$url" | sha256sum | awk '{print $1}')"
echo "${arch}_url=${url}" >> "$GITHUB_OUTPUT"
echo "${arch}_sha256=${sha256}" >> "$GITHUB_OUTPUT"
done
- name: Render AUR Metadata - name: Render AUR Metadata
shell: bash shell: bash
@@ -646,16 +747,13 @@ jobs:
set -euo pipefail set -euo pipefail
PKGVER_ORIG='${{ needs.setup.outputs.version }}' PKGVER_ORIG='${{ needs.setup.outputs.version }}'
PKGVER_CLEAN="${PKGVER_ORIG//-/.}" PKGVER_CLEAN="${PKGVER_ORIG//-/.}"
BIN_URL='${{ steps.meta.outputs.bin_url }}'
SHA256='${{ steps.meta.outputs.sha256 }}'
mkdir -p packages/aur/dcr-bin mkdir -p packages/aur/dcr-bin
cat > packages/aur/dcr-bin/PKGBUILD <<PKG cat > packages/aur/dcr-bin/PKGBUILD <<PKG
pkgname=dcr-bin pkgname=dcr-bin
pkgver=${PKGVER_CLEAN} pkgver=${PKGVER_CLEAN}
pkgrel=1 pkgrel=1
pkgdesc="Cargo-like utility to manage C/C++ projects (pre-compiled musl binary)" pkgdesc="Cargo-like utility to manage C/C++ projects (pre-compiled musl binary)"
arch=('x86_64') arch=('x86_64' 'aarch64' 'i686' 'armv7h' 'riscv64')
url="https://github.com/dexoron/dcr" url="https://github.com/dexoron/dcr"
license=('GPL-3.0-or-later') license=('GPL-3.0-or-later')
provides=('dcr') provides=('dcr')
@@ -664,8 +762,16 @@ jobs:
'gcc: build C/C++ projects with GCC' 'gcc: build C/C++ projects with GCC'
'clang: build C/C++ projects with Clang' 'clang: build C/C++ projects with Clang'
) )
source_x86_64=("dcr-\$pkgver::${BIN_URL}") source_x86_64=("dcr-\$pkgver::${{ steps.meta.outputs.x86_64_url }}")
sha256sums_x86_64=('${SHA256}') sha256sums_x86_64=('${{ steps.meta.outputs.x86_64_sha256 }}')
source_aarch64=("dcr-\$pkgver::${{ steps.meta.outputs.aarch64_url }}")
sha256sums_aarch64=('${{ steps.meta.outputs.aarch64_sha256 }}')
source_i686=("dcr-\$pkgver::${{ steps.meta.outputs.i686_url }}")
sha256sums_i686=('${{ steps.meta.outputs.i686_sha256 }}')
source_armv7h=("dcr-\$pkgver::${{ steps.meta.outputs.armv7h_url }}")
sha256sums_armv7h=('${{ steps.meta.outputs.armv7h_sha256 }}')
source_riscv64=("dcr-\$pkgver::${{ steps.meta.outputs.riscv64_url }}")
sha256sums_riscv64=('${{ steps.meta.outputs.riscv64_sha256 }}')
package() { package() {
install -Dm755 "\$srcdir/dcr-\$pkgver" "\$pkgdir/usr/bin/dcr" install -Dm755 "\$srcdir/dcr-\$pkgver" "\$pkgdir/usr/bin/dcr"
@@ -679,13 +785,25 @@ jobs:
pkgrel = 1 pkgrel = 1
url = https://github.com/dexoron/dcr url = https://github.com/dexoron/dcr
arch = x86_64 arch = x86_64
arch = aarch64
arch = i686
arch = armv7h
arch = riscv64
license = GPL-3.0-or-later license = GPL-3.0-or-later
provides = dcr provides = dcr
conflicts = dcr conflicts = dcr
optdepends = gcc: build C/C++ projects with GCC optdepends = gcc: build C/C++ projects with GCC
optdepends = clang: build C/C++ projects with Clang optdepends = clang: build C/C++ projects with Clang
source_x86_64 = dcr-${PKGVER_CLEAN}::${BIN_URL} source_x86_64 = dcr-${PKGVER_CLEAN}::${{ steps.meta.outputs.x86_64_url }}
sha256sums_x86_64 = ${SHA256} sha256sums_x86_64 = ${{ steps.meta.outputs.x86_64_sha256 }}
source_aarch64 = dcr-${PKGVER_CLEAN}::${{ steps.meta.outputs.aarch64_url }}
sha256sums_aarch64 = ${{ steps.meta.outputs.aarch64_sha256 }}
source_i686 = dcr-${PKGVER_CLEAN}::${{ steps.meta.outputs.i686_url }}
sha256sums_i686 = ${{ steps.meta.outputs.i686_sha256 }}
source_armv7h = dcr-${PKGVER_CLEAN}::${{ steps.meta.outputs.armv7h_url }}
sha256sums_armv7h = ${{ steps.meta.outputs.armv7h_sha256 }}
source_riscv64 = dcr-${PKGVER_CLEAN}::${{ steps.meta.outputs.riscv64_url }}
sha256sums_riscv64 = ${{ steps.meta.outputs.riscv64_sha256 }}
pkgname = dcr-bin pkgname = dcr-bin
SRC SRC
@@ -703,22 +821,299 @@ jobs:
ssh-keyscan aur.archlinux.org >> ~/.ssh/known_hosts ssh-keyscan aur.archlinux.org >> ~/.ssh/known_hosts
export GIT_SSH_COMMAND='ssh -i ~/.ssh/aur -o IdentitiesOnly=yes' export GIT_SSH_COMMAND='ssh -i ~/.ssh/aur -o IdentitiesOnly=yes'
git clone "ssh://aur@aur.archlinux.org/${AUR_PACKAGE}.git" aur-repo
cp packages/aur/dcr-bin/PKGBUILD aur-repo/PKGBUILD mkdir -p aur-repo
cp packages/aur/dcr-bin/.SRCINFO aur-repo/.SRCINFO
cd aur-repo cd aur-repo
git init
git remote add origin "ssh://aur@aur.archlinux.org/${AUR_PACKAGE}.git"
git fetch origin master || true
git checkout master || git checkout -b master
cp ../packages/aur/dcr-bin/PKGBUILD .
cp ../packages/aur/dcr-bin/.SRCINFO .
git config user.name "github-actions[bot]" git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com" git config user.email "github-actions[bot]@users.noreply.github.com"
if git diff --quiet; then if git rev-parse --verify HEAD >/dev/null 2>&1; then
echo "No AUR changes" if git diff --quiet; then
exit 0 echo "No AUR changes"
exit 0
fi
fi fi
git add PKGBUILD .SRCINFO git add PKGBUILD .SRCINFO
git commit -m "dcr-bin ${{ needs.setup.outputs.version }}" git commit -m "dcr-bin ${{ needs.setup.outputs.version }}"
git push git push -u origin master
# ── Arch User Repository (dcr-dev) ────────────────────────────────
publish-aur-dev:
if: ${{ (github.event_name == 'push' && needs.setup.outputs.prerelease == 'true') || github.event.inputs.run_aur_dev == 'true' }}
needs: [setup]
runs-on: ubuntu-latest
environment: aur
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Derive checksum
id: meta
shell: bash
run: |
set -euo pipefail
SRC_URL="https://github.com/dexoron/dcr/archive/refs/tags/${{ needs.setup.outputs.tag }}.tar.gz"
SHA256="$(curl -fsSL "$SRC_URL" | sha256sum | awk '{print $1}')"
echo "source_url=$SRC_URL" >> "$GITHUB_OUTPUT"
echo "sha256=$SHA256" >> "$GITHUB_OUTPUT"
- name: Render AUR metadata
shell: bash
run: |
set -euo pipefail
PKGVER_ORIG='${{ needs.setup.outputs.version }}'
PKGVER_CLEAN='${{ needs.setup.outputs.clean_version }}'
SRC_URL='${{ steps.meta.outputs.source_url }}'
SHA256='${{ steps.meta.outputs.sha256 }}'
mkdir -p packages/aur/dcr-dev
cat > packages/aur/dcr-dev/PKGBUILD <<PKG
pkgname=dcr-dev
pkgver=${PKGVER_CLEAN}
pkgrel=1
pkgdesc="Cargo-like utility to manage C/C++ projects (development release)"
arch=('x86_64' 'aarch64')
url="https://github.com/dexoron/dcr"
license=('GPL-3.0-or-later')
depends=('gcc-libs')
makedepends=('cargo')
options=('!lto')
provides=('dcr')
conflicts=('dcr')
optdepends=(
'gcc: build C/C++ projects with GCC'
'clang: build C/C++ projects with Clang'
)
source=("\$pkgname-\$pkgver.tar.gz::${SRC_URL}")
sha256sums=('${SHA256}')
build() {
cd "\$srcdir/dcr-${PKGVER_ORIG}"
unset CFLAGS CXXFLAGS LDFLAGS
export RUSTFLAGS="-C linker=cc"
cargo build --release --locked
}
package() {
cd "\$srcdir/\$pkgname-${PKGVER_ORIG}"
install -Dm755 "target/release/dcr" "\$pkgdir/usr/bin/dcr"
install -Dm644 LICENSE "\$pkgdir/usr/share/licenses/\$pkgname/LICENSE"
for manpage in man/man1/*.1; do
install -Dm644 "\$manpage" "\$pkgdir/usr/share/man/man1/\$(basename "\$manpage")"
done
}
PKG
cat > packages/aur/dcr-dev/.SRCINFO <<SRC
pkgbase = dcr-dev
pkgdesc = Cargo-like utility to manage C/C++ projects (development release)
pkgver = ${PKGVER_CLEAN}
pkgrel = 1
url = https://github.com/dexoron/dcr
arch = x86_64
arch = aarch64
license = GPL-3.0-or-later
makedepends = cargo
depends = gcc-libs
provides = dcr
conflicts = dcr
optdepends = gcc: build C/C++ projects with GCC
optdepends = clang: build C/C++ projects with Clang
options = !lto
source = dcr-${PKGVER_CLEAN}.tar.gz::${SRC_URL}
sha256sums = ${SHA256}
pkgname = dcr-dev
SRC
- name: Push to AUR
env:
AUR_SSH_PRIVATE_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
AUR_PACKAGE: dcr-dev
shell: bash
run: |
set -euo pipefail
install -d -m 700 ~/.ssh
printf '%s\n' "$AUR_SSH_PRIVATE_KEY" > ~/.ssh/aur
chmod 600 ~/.ssh/aur
ssh-keyscan aur.archlinux.org >> ~/.ssh/known_hosts
export GIT_SSH_COMMAND='ssh -i ~/.ssh/aur -o IdentitiesOnly=yes'
mkdir -p aur-repo
cd aur-repo
git init
git remote add origin "ssh://aur@aur.archlinux.org/${AUR_PACKAGE}.git"
git fetch origin master || true
git checkout master || git checkout -b master
cp ../packages/aur/dcr-dev/PKGBUILD .
cp ../packages/aur/dcr-dev/.SRCINFO .
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
if git rev-parse --verify HEAD >/dev/null 2>&1; then
if git diff --quiet; then
echo "No AUR changes"
exit 0
fi
fi
git add PKGBUILD .SRCINFO
git commit -m "dcr-dev ${{ needs.setup.outputs.version }}"
git push -u origin master
# ── Arch User Repository (dcr-dev-bin) ────────────────────────────
publish-aur-dev-bin:
if: ${{ (github.event_name == 'push' && needs.setup.outputs.prerelease == 'true') || github.event.inputs.run_aur_dev == 'true' }}
needs: [setup, build-linux]
runs-on: ubuntu-latest
environment: aur
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Derive checksum
id: meta
shell: bash
run: |
set -euo pipefail
TAG="${{ needs.setup.outputs.tag }}"
VER="${{ needs.setup.outputs.version }}"
BASE_URL="https://github.com/dexoron/dcr/releases/download/${TAG}"
for arch in x86_64 aarch64 i686 armv7h riscv64; do
case "$arch" in
x86_64) triple="x86_64-unknown-linux-musl" ;;
aarch64) triple="aarch64-unknown-linux-musl" ;;
i686) triple="i686-unknown-linux-musl" ;;
armv7h) triple="armv7-unknown-linux-musleabihf" ;;
riscv64) triple="riscv64gc-unknown-linux-musl" ;;
esac
url="${BASE_URL}/dcr-${triple}-${VER}"
sha256="$(curl -fsSL "$url" | sha256sum | awk '{print $1}')"
echo "${arch}_url=${url}" >> "$GITHUB_OUTPUT"
echo "${arch}_sha256=${sha256}" >> "$GITHUB_OUTPUT"
done
- name: Render AUR Metadata
shell: bash
run: |
set -euo pipefail
PKGVER_ORIG='${{ needs.setup.outputs.version }}'
PKGVER_CLEAN='${{ needs.setup.outputs.clean_version }}'
mkdir -p packages/aur/dcr-dev-bin
cat > packages/aur/dcr-dev-bin/PKGBUILD <<PKG
pkgname=dcr-dev-bin
pkgver=${PKGVER_CLEAN}
pkgrel=1
pkgdesc="Cargo-like utility to manage C/C++ projects (pre-compiled musl binary dev release)"
arch=('x86_64' 'aarch64' 'i686' 'armv7h' 'riscv64')
url="https://github.com/dexoron/dcr"
license=('GPL-3.0-or-later')
provides=('dcr')
conflicts=('dcr')
optdepends=(
'gcc: build C/C++ projects with GCC'
'clang: build C/C++ projects with Clang'
)
source_x86_64=("dcr-\$pkgver::${{ steps.meta.outputs.x86_64_url }}")
sha256sums_x86_64=('${{ steps.meta.outputs.x86_64_sha256 }}')
source_aarch64=("dcr-\$pkgver::${{ steps.meta.outputs.aarch64_url }}")
sha256sums_aarch64=('${{ steps.meta.outputs.aarch64_sha256 }}')
source_i686=("dcr-\$pkgver::${{ steps.meta.outputs.i686_url }}")
sha256sums_i686=('${{ steps.meta.outputs.i686_sha256 }}')
source_armv7h=("dcr-\$pkgver::${{ steps.meta.outputs.armv7h_url }}")
sha256sums_armv7h=('${{ steps.meta.outputs.armv7h_sha256 }}')
source_riscv64=("dcr-\$pkgver::${{ steps.meta.outputs.riscv64_url }}")
sha256sums_riscv64=('${{ steps.meta.outputs.riscv64_sha256 }}')
package() {
install -Dm755 "\$srcdir/dcr-\$pkgver" "\$pkgdir/usr/bin/dcr"
}
PKG
cat > packages/aur/dcr-dev-bin/.SRCINFO <<SRC
pkgbase = dcr-dev-bin
pkgdesc = Cargo-like utility to manage C/C++ projects (pre-compiled musl binary dev release)
pkgver = ${PKGVER_CLEAN}
pkgrel = 1
url = https://github.com/dexoron/dcr
arch = x86_64
arch = aarch64
arch = i686
arch = armv7h
arch = riscv64
license = GPL-3.0-or-later
provides = dcr
conflicts = dcr
optdepends = gcc: build C/C++ projects with GCC
optdepends = clang: build C/C++ projects with Clang
source_x86_64 = dcr-${PKGVER_CLEAN}::${{ steps.meta.outputs.x86_64_url }}
sha256sums_x86_64 = ${{ steps.meta.outputs.x86_64_sha256 }}
source_aarch64 = dcr-${PKGVER_CLEAN}::${{ steps.meta.outputs.aarch64_url }}
sha256sums_aarch64 = ${{ steps.meta.outputs.aarch64_sha256 }}
source_i686 = dcr-${PKGVER_CLEAN}::${{ steps.meta.outputs.i686_url }}
sha256sums_i686 = ${{ steps.meta.outputs.i686_sha256 }}
source_armv7h = dcr-${PKGVER_CLEAN}::${{ steps.meta.outputs.armv7h_url }}
sha256sums_armv7h = ${{ steps.meta.outputs.armv7h_sha256 }}
source_riscv64 = dcr-${PKGVER_CLEAN}::${{ steps.meta.outputs.riscv64_url }}
sha256sums_riscv64 = ${{ steps.meta.outputs.riscv64_sha256 }}
pkgname = dcr-dev-bin
SRC
- name: Push to AUR
env:
AUR_SSH_PRIVATE_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
AUR_PACKAGE: dcr-dev-bin
shell: bash
run: |
set -euo pipefail
install -d -m 700 ~/.ssh
printf '%s\n' "$AUR_SSH_PRIVATE_KEY" > ~/.ssh/aur
chmod 600 ~/.ssh/aur
ssh-keyscan aur.archlinux.org >> ~/.ssh/known_hosts
export GIT_SSH_COMMAND='ssh -i ~/.ssh/aur -o IdentitiesOnly=yes'
mkdir -p aur-repo
cd aur-repo
git init
git remote add origin "ssh://aur@aur.archlinux.org/${AUR_PACKAGE}.git"
git fetch origin master || true
git checkout master || git checkout -b master
cp ../packages/aur/dcr-dev-bin/PKGBUILD .
cp ../packages/aur/dcr-dev-bin/.SRCINFO .
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
if git rev-parse --verify HEAD >/dev/null 2>&1; then
if git diff --quiet; then
echo "No AUR changes"
exit 0
fi
fi
git add PKGBUILD .SRCINFO
git commit -m "dcr-dev-bin ${{ needs.setup.outputs.version }}"
git push -u origin master
# ── crates.io ────────────────────────────────────────────────────────────── # ── crates.io ──────────────────────────────────────────────────────────────
publish-crates: publish-crates:
@@ -738,6 +1133,8 @@ jobs:
- uses: dtolnay/rust-toolchain@stable - uses: dtolnay/rust-toolchain@stable
- name: Publish to crates.io - name: Publish to crates.io
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: cargo publish run: cargo publish
# ── Homebrew tap ─────────────────────────────────────────────────────────── # ── Homebrew tap ───────────────────────────────────────────────────────────
@@ -762,6 +1159,7 @@ jobs:
echo "linux_arm=$(download_sha "dcr-aarch64-unknown-linux-gnu-${VERSION}")" >> "$GITHUB_OUTPUT" echo "linux_arm=$(download_sha "dcr-aarch64-unknown-linux-gnu-${VERSION}")" >> "$GITHUB_OUTPUT"
echo "macos_x86=$(download_sha "dcr-x86_64-apple-darwin-${VERSION}")" >> "$GITHUB_OUTPUT" echo "macos_x86=$(download_sha "dcr-x86_64-apple-darwin-${VERSION}")" >> "$GITHUB_OUTPUT"
echo "macos_arm=$(download_sha "dcr-aarch64-apple-darwin-${VERSION}")" >> "$GITHUB_OUTPUT" echo "macos_arm=$(download_sha "dcr-aarch64-apple-darwin-${VERSION}")" >> "$GITHUB_OUTPUT"
echo "man_pages=$(download_sha "dcr-man-pages-${VERSION}.tar.gz")" >> "$GITHUB_OUTPUT"
- name: Checkout homebrew-dexoron - name: Checkout homebrew-dexoron
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -804,6 +1202,18 @@ jobs:
bin.install Dir["dcr*"].first => "dcr" bin.install Dir["dcr*"].first => "dcr"
end end
resource "man-pages" do
url "https://github.com/dexoron/dcr/releases/download/v#{version}/dcr-man-pages-#{version}.tar.gz"
sha256 "${{ steps.sha.outputs.man_pages }}"
end
def install
bin.install Dir["dcr*"].first => "dcr"
resource("man-pages").stage do
man1.install Dir["usr/share/man/man1/*.1"]
end
end
test do test do
system "#{bin}/dcr", "--version" system "#{bin}/dcr", "--version"
end end
@@ -833,10 +1243,20 @@ jobs:
name: snap-package name: snap-package
path: dist-packages path: dist-packages
- name: Resolve Snap File
id: snap-file
run: |
snap_file=$(ls dist-packages/*.snap 2>/dev/null | head -1)
if [ -z "$snap_file" ]; then
echo "No .snap file found in dist-packages/"
exit 1
fi
echo "snap=$snap_file" >> "$GITHUB_OUTPUT"
- name: Publish to Snap Store - name: Publish to Snap Store
uses: snapcore/action-publish@v1 uses: snapcore/action-publish@v1
env: env:
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }} SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }}
with: with:
snap: dist-packages/*.snap snap: ${{ steps.snap-file.outputs.snap }}
release: stable release: stable

View File

@@ -1,5 +1,54 @@
# Changelog # Changelog
## [0.7.1] - 2026-06-02 "Мультиархитектурное расширение / The Multi-Arch Expansion"
### RU
**Добавлено:**
- Вывод `--help` для всех команд с цветным форматированием.
- man-страницы (12 штук в `man/man1/`) и их установка во всех пакетах.
- Валидация имен проектов в `dcr init` и `dcr new` (только ASCII буквы, цифры, `_` и `-`).
- Метаданные `documentation` и `homepage` в `Cargo.toml`.
- Оптимизация сборки: `opt-level = "z"`, LTO, `codegen-units = 1`, `panic = "abort"`, `strip = true`.
- Поддержка новых архитектур (i686, armv7, riscv64gc, aarch64) в рабочих процессах и установочных скриптах.
- Сборка пакетов `deb` и `rpm` для всех 5 архитектур Linux через `cargo-zigbuild`.
- Пакеты AUR (`dcr-dev`, `dcr-dev-bin`) и публикация Snap в CI.
**Изменено:**
- Функция `validate_package_name` стала публичной.
- Команды `gen`, `tree`, `fmt`, `setup` больше не игнорируют аргументы и используют цветной вывод.
- Инструкция в README изменена с `| bash` на `| sh` для POSIX.
- Отключена архитектура Windows 32-bit (GNU) из-за проблем со сборкой.
### EN
**Added:**
- `--help` for all commands with styled headers and usage lines.
- Man pages (12 troff man pages in `man/man1/`) and their installation across all packaging formats.
- Project name validation in `dcr init` and `dcr new` (ASCII letters, digits, `_`, `-` only).
- `documentation` and `homepage` metadata in `Cargo.toml`.
- Release profile optimizations (`opt-level = "z"`, LTO, `codegen-units = 1`, `panic = "abort"`, `strip = true`).
- Linux i686, armv7, riscv64gc, aarch64 architecture support in release workflows and installation scripts.
- Multi-arch `deb` and `rpm` package builds for all 5 Linux architectures via `cargo-zigbuild`.
- AUR packages (`dcr-dev`, `dcr-dev-bin`) and automated Snapcraft publishing in CI.
**Changed:**
- `validate_package_name` made public and callable from CLI commands directly.
- `gen.rs`, `tree.rs`, `fmt.rs`, `setup.rs` no longer ignore arguments and use styled output.
- README install instructions changed from `| bash` to `| sh` for POSIX compatibility.
- Disabled Windows 32-bit (GNU) target due to build issues.
Fixed:
- **`dcr new <invalid-name>` creates directory then fails** — validation now happens
before any file operations.
- **`dcr init` creates dcr.toml then fails on invalid directory name** — same fix.
- **Man pages missing after installation** — now installed via install scripts,
package managers, and Homebrew.
- **Windows drive letter false positive** — in dependency file parsing.
- **CRLF `\r\n` breaks dependency parser** — now handles mixed line endings.
- **Newline after backslash not consumed** — in `parse_d_file` escape handling.
## [0.7.0] - 2026-06-02 ## [0.7.0] - 2026-06-02
Added: Added:

2
Cargo.lock generated
View File

@@ -112,7 +112,7 @@ dependencies = [
[[package]] [[package]]
name = "dcr" name = "dcr"
version = "0.7.0" version = "0.7.1"
dependencies = [ dependencies = [
"ctrlc", "ctrlc",
"git2", "git2",

View File

@@ -1,11 +1,13 @@
[package] [package]
name = "dcr" name = "dcr"
version = "0.7.0" version = "0.7.1"
edition = "2024" edition = "2024"
build = "build.rs" build = "build.rs"
description = "DCR is a utility for managing C/C++ projects in a Cargo-like style." description = "DCR is a utility for managing C/C++ projects in a Cargo-like style."
license = "GPL-3.0-or-later" license = "GPL-3.0-or-later"
repository = "https://github.com/dexoron/dcr" repository = "https://github.com/dexoron/dcr"
documentation = "https://dcr.dexoron.su/docs"
homepage = "https://dcr.dexoron.su"
[package.metadata.binstall] [package.metadata.binstall]
pkg-fmt = "bin" pkg-fmt = "bin"
@@ -21,6 +23,18 @@ section = "devel"
priority = "optional" priority = "optional"
assets = [ assets = [
["target/release/dcr", "usr/bin/dcr", "755"], ["target/release/dcr", "usr/bin/dcr", "755"],
["man/man1/dcr.1", "usr/share/man/man1/dcr.1", "644"],
["man/man1/dcr-add.1", "usr/share/man/man1/dcr-add.1", "644"],
["man/man1/dcr-build.1", "usr/share/man/man1/dcr-build.1", "644"],
["man/man1/dcr-clean.1", "usr/share/man/man1/dcr-clean.1", "644"],
["man/man1/dcr-fmt.1", "usr/share/man/man1/dcr-fmt.1", "644"],
["man/man1/dcr-gen.1", "usr/share/man/man1/dcr-gen.1", "644"],
["man/man1/dcr-init.1", "usr/share/man/man1/dcr-init.1", "644"],
["man/man1/dcr-new.1", "usr/share/man/man1/dcr-new.1", "644"],
["man/man1/dcr-run.1", "usr/share/man/man1/dcr-run.1", "644"],
["man/man1/dcr-setup.1", "usr/share/man/man1/dcr-setup.1", "644"],
["man/man1/dcr-test.1", "usr/share/man/man1/dcr-test.1", "644"],
["man/man1/dcr-tree.1", "usr/share/man/man1/dcr-tree.1", "644"],
] ]
[package.metadata.generate-rpm] [package.metadata.generate-rpm]
@@ -30,7 +44,19 @@ Cargo-like utility to manage C/C++ projects.
""" """
assets = [ assets = [
{ source = "target/release/dcr", dest = "/usr/bin/dcr", mode = "755" } { source = "target/release/dcr", dest = "/usr/bin/dcr", mode = "755" },
{ source = "man/man1/dcr.1", dest = "/usr/share/man/man1/dcr.1", mode = "644" },
{ source = "man/man1/dcr-add.1", dest = "/usr/share/man/man1/dcr-add.1", mode = "644" },
{ source = "man/man1/dcr-build.1", dest = "/usr/share/man/man1/dcr-build.1", mode = "644" },
{ source = "man/man1/dcr-clean.1", dest = "/usr/share/man/man1/dcr-clean.1", mode = "644" },
{ source = "man/man1/dcr-fmt.1", dest = "/usr/share/man/man1/dcr-fmt.1", mode = "644" },
{ source = "man/man1/dcr-gen.1", dest = "/usr/share/man/man1/dcr-gen.1", mode = "644" },
{ source = "man/man1/dcr-init.1", dest = "/usr/share/man/man1/dcr-init.1", mode = "644" },
{ source = "man/man1/dcr-new.1", dest = "/usr/share/man/man1/dcr-new.1", mode = "644" },
{ source = "man/man1/dcr-run.1", dest = "/usr/share/man/man1/dcr-run.1", mode = "644" },
{ source = "man/man1/dcr-setup.1", dest = "/usr/share/man/man1/dcr-setup.1", mode = "644" },
{ source = "man/man1/dcr-test.1", dest = "/usr/share/man/man1/dcr-test.1", mode = "644" },
{ source = "man/man1/dcr-tree.1", dest = "/usr/share/man/man1/dcr-tree.1", mode = "644" },
] ]
[dependencies] [dependencies]
@@ -48,4 +74,11 @@ git2 = { version = "0.20.4", features = ["vendored-libgit2", "vendored-openssl"]
openssl = { version = "0.10", features = ["vendored"] } openssl = { version = "0.10", features = ["vendored"] }
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
git2 = { version = "0.20.4", features = ["vendored-libgit2"] } git2 = { version = "0.20.4", features = ["vendored-libgit2"] }
[profile.release]
opt-level = "z"
lto = true
codegen-units = 1
panic = "abort"
strip = true

View File

@@ -11,6 +11,7 @@
[![AUR](https://img.shields.io/aur/version/dcr)](https://aur.archlinux.org/packages/dcr) [![AUR](https://img.shields.io/aur/version/dcr)](https://aur.archlinux.org/packages/dcr)
[![Crates.io](https://img.shields.io/crates/v/dcr)](https://crates.io/crates/dcr) [![Crates.io](https://img.shields.io/crates/v/dcr)](https://crates.io/crates/dcr)
[![Homebrew](https://img.shields.io/badge/homebrew-dexoron%2Fdexoron-orange)](https://github.com/dexoron/homebrew-dexoron) [![Homebrew](https://img.shields.io/badge/homebrew-dexoron%2Fdexoron-orange)](https://github.com/dexoron/homebrew-dexoron)
[![Snap](https://img.shields.io/badge/snap-dcrup-orange)](https://snapcraft.io/dcrup)
<br/> <br/>
[![GitHub Stars](https://img.shields.io/github/stars/dexoron/dcr?style=flat)](https://github.com/dexoron/dcr/stargazers) [![GitHub Stars](https://img.shields.io/github/stars/dexoron/dcr?style=flat)](https://github.com/dexoron/dcr/stargazers)
[![License: GPL-3.0](https://img.shields.io/badge/License-GPL--3.0-blue.svg)](LICENSE) [![License: GPL-3.0](https://img.shields.io/badge/License-GPL--3.0-blue.svg)](LICENSE)
@@ -22,10 +23,11 @@
## Why DCR? ## Why DCR?
- **No boilerplate** — one config file, predictable structure - **No boilerplate** — one config file, predictable structure
- **Cargo-like workflow** — `build`, `run`, `clean`, `test`, `add` - **Cargo-like workflow** — `build`, `run`, `clean`, `test`, `add`, `fmt`
- **Cross-compilation** — full target triple support with short names - **Cross-compilation** — full target triple support with short names
- **IDE integration** — VS Code, CLion, `compile_commands.json` out of the box - **IDE integration** — VS Code, CLion, `compile_commands.json` out of the box
- **Dependencies** — path, git, and registry-based with lock file - **Dependencies** — path, git, and registry-based with lock file
- **Man pages** — `man dcr` and per-command pages (`man dcr-build`, `man dcr-new`, etc.)
--- ---
@@ -106,7 +108,7 @@ cargo install dcr
<td> <td>
```sh ```sh
curl -fsSL https://dcr.dexoron.su/install.sh | bash curl -fsSL https://dcr.dexoron.su/install.sh | sh
``` ```
</td> </td>
@@ -116,7 +118,17 @@ curl -fsSL https://dcr.dexoron.su/install.sh | bash
<td> <td>
```sh ```sh
curl -fsSL https://dcr.dexoron.su/install_bsd.sh | bash curl -fsSL https://dcr.dexoron.su/install_bsd.sh | sh
```
</td>
</tr>
<tr>
<td><b>Snap (Linux)</b></td>
<td>
```sh
sudo snap install dcrup
``` ```
</td> </td>
@@ -200,24 +212,26 @@ kind = "bin"
| `dcr gen <vscode\|clion\|compile-commands>` | Generate IDE integration | | `dcr gen <vscode\|clion\|compile-commands>` | Generate IDE integration |
| `dcr setup` | Initialize DCR registry | | `dcr setup` | Initialize DCR registry |
other in [docs/](docs/) and `dcr --help` other in [docs/](docs/), `dcr --help` and `dcr <command> --help`
--- ---
## Platforms(pre-build source) ## Platforms (pre-built binary)
<div align="center"> <div align="center">
| OS | x86_64 | aarch64 | armv7 | i686 | riscv64 | GNU | Musl | MSVC | MinGW | | OS | x86_64 | aarch64 | armv7 | i686 | riscv64 |
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:| |:---:|:---:|:---:|:---:|:---:|:---:|
| Linux | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | | Linux (GNU) | ✅ | ✅ | ✅ | ✅ | ✅ |
| macOS | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | Linux (Musl) | ✅ | ✅ | ✅ | ✅ | 🚧 |
| Windows | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | | macOS | ✅ | ✅ | ❌ | ❌ | ❌ |
| FreeBSD | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | | Windows (MSVC) | ✅ | ✅ | ❌ | ✅ | ❌ |
| OpenBSD | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | | Windows (MinGW) | ✅ | 🚧 | ❌ | ✅ | ❌ |
| NetBSD | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | | FreeBSD | ✅ | 🚧 | ❌ | ❌ | ❌ |
| OpenBSD | ✅ | 🚧 | ❌ | ❌ | ❌ |
| NetBSD | ✅ | 🚧 | ❌ | ❌ | ❌ |
✅ officially supported · ⚠️ community / best-effort · ❌ not supported ✅ pre-built binary · 🚧 planned · ❌ not supported by platform or CI
</div> </div>
@@ -259,4 +273,4 @@ cargo test
GPL-3.0 — see [LICENSE](LICENSE)<br/> GPL-3.0 — see [LICENSE](LICENSE)<br/>
Made with ❤️ by [Dexoron](https://github.com/dexoron) and contributors. Made with ❤️ by [Dexoron](https://github.com/dexoron) and contributors.
</div> </div>

View File

@@ -58,3 +58,5 @@ dcr gen vscode
- **Registry + Git + Path** — three dependency mechanisms - **Registry + Git + Path** — three dependency mechanisms
- **IDE generation** — VS Code, CLion, compile_commands.json, JSON metadata - **IDE generation** — VS Code, CLion, compile_commands.json, JSON metadata
- **pkg-config** — automatic system library discovery - **pkg-config** — automatic system library discovery
- **Per-command `--help`** — `dcr build --help`, `dcr new --help`, etc.
- **Man pages** — `man dcr`, `man dcr-build`, `man dcr-new`

View File

@@ -4,6 +4,50 @@ sidebar_label: Changelog
# Changelog # Changelog
## 0.7.1 (2026-06-02)
### Added
- **`--help` for all commands** — `dcr build --help`, `dcr run --help`, `dcr new --help`,
`dcr init --help`, `dcr clean --help`, `dcr add --help`, `dcr fmt --help`,
`dcr setup --help`, `dcr tree --help`, `dcr gen --help`, `dcr --update --help`,
`dcr test --help`. All output uses styled headers (green) and usage lines (cyan).
- **Man pages** — 12 troff pages in `man/man1/`: `dcr.1`, `dcr-build.1`,
`dcr-run.1`, `dcr-new.1`, `dcr-init.1`, `dcr-clean.1`, `dcr-add.1`, `dcr-test.1`,
`dcr-gen.1`, `dcr-fmt.1`, `dcr-tree.1`, `dcr-setup.1`.
- **Man pages in all packaging** — install.sh, install_bsd.sh, AUR PKGBUILD,
Debian (cargo-deb), RPM (cargo-generate-rpm), Nix (postInstall), Homebrew
(resource), Snap, GitHub Release assets.
- **Project name validation** — `dcr init` and `dcr new` now validate names before
creating files. Only ASCII letters, digits, `_` and `-` are allowed.
- **`documentation` and `homepage` fields** — added to `Cargo.toml`.
- **Release profile optimizations** — `opt-level = "z"`, LTO, `codegen-units = 1`,
`panic = "abort"`, `strip = true` for smaller binaries.
- **Linux i686, armv7, riscv64 targets** — added to release workflow and install scripts.
- **Linux musl i686, armv7 targets** — cross-compiled via zigbuild in CI.
- **AUR packages** — `dcr-dev`, `dcr-dev-bin` publishing workflow.
- **Snap publishing** — automated Snapcraft publishing in CI.
- **Snap badge** — in README.
### Changed
- **`validate_package_name` made public** — callable from CLI commands.
- **README platform table** — reorganized: libc variants as separate OS rows,
removed extra columns. Linux architecture list updated.
- **`gen.rs` no-args output** — now uses styled output instead of raw `eprintln!`.
- **`tree.rs`, `fmt.rs`, and `setup.rs`** — now accept arguments for `--help`.
- **README install commands** — `| bash` → `| sh` for POSIX compatibility.
### Fixed
- **`dcr new <invalid-name>` creates directory then fails** — validation now
happens before any file operations.
- **`dcr init` on invalid directory name** — same fix.
- **Man pages missing in installed packages** — now shipped in all formats.
- **Windows drive letter false positive** — in dependency file parser.
- **CRLF (`\r\n`) breaks dependency parser** — now handles mixed line endings.
- **Newline after backslash not consumed** — in `parse_d_file` escape handling.
## 0.7.0 (2026-06-01) ## 0.7.0 (2026-06-01)
### Added ### Added

View File

@@ -8,6 +8,8 @@ sidebar_label: Project commands (new, init)
Creates a new project with a standard structure and `dcr.toml`. The `name` argument is required. Creates a new project with a standard structure and `dcr.toml`. The `name` argument is required.
Only ASCII letters, digits, underscores `_` and hyphens `-` are allowed in the project name.
```bash ```bash
dcr new my-app dcr new my-app
``` ```
@@ -25,4 +27,4 @@ mkdir app && cd app
dcr init dcr init
``` ```
The project name is taken from the current directory name. The project name is taken from the current directory name. The directory name must follow the same naming rules as `dcr new`.

View File

@@ -36,6 +36,12 @@ brew tap dexoron/dexoron
brew install dcr brew install dcr
``` ```
## Snap (Linux)
```sh
sudo snap install dcrup
```
## Nix (flake) ## Nix (flake)
```sh ```sh
@@ -53,13 +59,13 @@ cargo install dcr
## Linux / macOS (script) ## Linux / macOS (script)
```sh ```sh
curl -fsSL https://dcr.dexoron.su/install.sh | bash curl -fsSL https://dcr.dexoron.su/install.sh | sh
``` ```
## BSD (script) ## BSD (script)
```sh ```sh
curl -fsSL https://dcr.dexoron.su/install_bsd.sh | bash curl -fsSL https://dcr.dexoron.su/install_bsd.sh | sh
``` ```
## Windows (PowerShell) ## Windows (PowerShell)
@@ -84,6 +90,13 @@ Verify the installation:
dcr --version dcr --version
``` ```
Man pages are available after installation:
```bash
man dcr
man dcr-build
```
To use the registry, create `~/.dcr/config.toml`: To use the registry, create `~/.dcr/config.toml`:
```toml ```toml

View File

@@ -64,6 +64,10 @@
pkgs.darwin.apple_sdk.frameworks.SystemConfiguration pkgs.darwin.apple_sdk.frameworks.SystemConfiguration
]; ];
postInstall = ''
install -Dm644 man/man1/*.1 -t $out/share/man/man1/
'';
# Tests require external services; run separately. # Tests require external services; run separately.
doCheck = false; doCheck = false;
}; };

View File

@@ -47,10 +47,16 @@ function Select-Mode {
} }
function Get-Target { function Get-Target {
if ($env:PROCESSOR_ARCHITECTURE -ne 'AMD64') { $arch = $env:PROCESSOR_ARCHITECTURE
Fail "Only x86_64 Windows is supported, current architecture: $env:PROCESSOR_ARCHITECTURE" if ($env:PROCESSOR_ARCHITEW6432) {
$arch = $env:PROCESSOR_ARCHITEW6432
}
switch ($arch) {
'AMD64' { return 'x86_64-pc-windows-msvc' }
'ARM64' { return 'aarch64-pc-windows-msvc' }
'x86' { return 'i686-pc-windows-msvc' }
default { Fail "Unsupported Windows architecture: $arch" }
} }
return 'x86_64-pc-windows-msvc'
} }
function Fetch-ReleaseJson($channel) { function Fetch-ReleaseJson($channel) {

View File

@@ -4,6 +4,7 @@ set -Eeuo pipefail
TMPDIR="/tmp/dcr-install" TMPDIR="/tmp/dcr-install"
INSTALL_PATH="$HOME/.local/share/dcr" INSTALL_PATH="$HOME/.local/share/dcr"
BINPATH="$HOME/.local/bin" BINPATH="$HOME/.local/bin"
MANPATH="${XDG_DATA_HOME:-$HOME/.local/share}/man"
LOGFILE="$HOME/.cache/dcr-install.log" LOGFILE="$HOME/.cache/dcr-install.log"
REPO_URL="https://github.com/dexoron/dcr" REPO_URL="https://github.com/dexoron/dcr"
GITHUB_API_LATEST="https://api.github.com/repos/dexoron/dcr/releases/latest" GITHUB_API_LATEST="https://api.github.com/repos/dexoron/dcr/releases/latest"
@@ -43,11 +44,20 @@ detect_target() {
case "$os:$arch" in case "$os:$arch" in
Linux:x86_64) TARGET_TRIPLE="x86_64-unknown-linux-gnu" ;; Linux:x86_64) TARGET_TRIPLE="x86_64-unknown-linux-gnu" ;;
Linux:aarch64|Linux:arm64) TARGET_TRIPLE="aarch64-unknown-linux-gnu" ;; Linux:aarch64|Linux:arm64) TARGET_TRIPLE="aarch64-unknown-linux-gnu" ;;
Linux:i686|Linux:i386) TARGET_TRIPLE="i686-unknown-linux-gnu" ;;
Linux:armv7l|Linux:armv7) TARGET_TRIPLE="armv7-unknown-linux-gnueabihf" ;;
Linux:riscv64) TARGET_TRIPLE="riscv64gc-unknown-linux-gnu" ;;
Darwin:x86_64) TARGET_TRIPLE="x86_64-apple-darwin" ;; Darwin:x86_64) TARGET_TRIPLE="x86_64-apple-darwin" ;;
Darwin:arm64|Darwin:aarch64) TARGET_TRIPLE="aarch64-apple-darwin" ;; Darwin:arm64|Darwin:aarch64) TARGET_TRIPLE="aarch64-apple-darwin" ;;
FreeBSD:x86_64|FreeBSD:amd64) TARGET_TRIPLE="x86_64-unknown-freebsd" ;; FreeBSD:x86_64|FreeBSD:amd64) TARGET_TRIPLE="x86_64-unknown-freebsd" ;;
FreeBSD:aarch64|FreeBSD:arm64) TARGET_TRIPLE="aarch64-unknown-freebsd" ;;
FreeBSD:i686|FreeBSD:i386) TARGET_TRIPLE="i686-unknown-freebsd" ;;
OpenBSD:x86_64|OpenBSD:amd64) TARGET_TRIPLE="x86_64-unknown-openbsd" ;; OpenBSD:x86_64|OpenBSD:amd64) TARGET_TRIPLE="x86_64-unknown-openbsd" ;;
OpenBSD:aarch64|OpenBSD:arm64) TARGET_TRIPLE="aarch64-unknown-openbsd" ;;
OpenBSD:i686|OpenBSD:i386) TARGET_TRIPLE="i686-unknown-openbsd" ;;
NetBSD:x86_64|NetBSD:amd64) TARGET_TRIPLE="x86_64-unknown-netbsd" ;; NetBSD:x86_64|NetBSD:amd64) TARGET_TRIPLE="x86_64-unknown-netbsd" ;;
NetBSD:aarch64|NetBSD:arm64) TARGET_TRIPLE="aarch64-unknown-netbsd" ;;
NetBSD:i686|NetBSD:i386) TARGET_TRIPLE="i686-unknown-netbsd" ;;
*) error "Unsupported platform: $os/$arch"; exit 1 ;; *) error "Unsupported platform: $os/$arch"; exit 1 ;;
esac esac
@@ -190,6 +200,16 @@ install_link() {
success "Command 'dcr' added to $BINPATH" success "Command 'dcr' added to $BINPATH"
} }
install_man() {
log "Installing man pages..."
local man_src="$TMPDIR/man/man1"
if [[ -d "$man_src" ]]; then
mkdir -p "$MANPATH/man1"
cp "$man_src"/*.1 "$MANPATH/man1/"
success "Man pages installed to $MANPATH/man1"
fi
}
check_path() { check_path() {
if ! echo "$PATH" | grep -q "$BINPATH"; then if ! echo "$PATH" | grep -q "$BINPATH"; then
warn "Directory $BINPATH not found in PATH" warn "Directory $BINPATH not found in PATH"
@@ -222,6 +242,7 @@ main() {
fi fi
install_link install_link
install_man
check_path check_path
cleanup cleanup

View File

@@ -4,6 +4,7 @@ set -eu
TMPDIR="/tmp/dcr-install" TMPDIR="/tmp/dcr-install"
INSTALL_PATH="$HOME/.local/share/dcr" INSTALL_PATH="$HOME/.local/share/dcr"
BINPATH="$HOME/.local/bin" BINPATH="$HOME/.local/bin"
MANPATH="${XDG_DATA_HOME:-$HOME/.local/share}/man"
LOGFILE="$HOME/.cache/dcr-install.log" LOGFILE="$HOME/.cache/dcr-install.log"
REPO_URL="https://github.com/dexoron/dcr" REPO_URL="https://github.com/dexoron/dcr"
GITHUB_API_LATEST="https://api.github.com/repos/dexoron/dcr/releases/latest" GITHUB_API_LATEST="https://api.github.com/repos/dexoron/dcr/releases/latest"
@@ -39,8 +40,14 @@ detect_target() {
case "$os:$arch" in case "$os:$arch" in
FreeBSD:x86_64|FreeBSD:amd64) TARGET_TRIPLE="x86_64-unknown-freebsd" ;; FreeBSD:x86_64|FreeBSD:amd64) TARGET_TRIPLE="x86_64-unknown-freebsd" ;;
FreeBSD:aarch64|FreeBSD:arm64) TARGET_TRIPLE="aarch64-unknown-freebsd" ;;
FreeBSD:i686|FreeBSD:i386) TARGET_TRIPLE="i686-unknown-freebsd" ;;
OpenBSD:x86_64|OpenBSD:amd64) TARGET_TRIPLE="x86_64-unknown-openbsd" ;; OpenBSD:x86_64|OpenBSD:amd64) TARGET_TRIPLE="x86_64-unknown-openbsd" ;;
OpenBSD:aarch64|OpenBSD:arm64) TARGET_TRIPLE="aarch64-unknown-openbsd" ;;
OpenBSD:i686|OpenBSD:i386) TARGET_TRIPLE="i686-unknown-openbsd" ;;
NetBSD:x86_64|NetBSD:amd64) TARGET_TRIPLE="x86_64-unknown-netbsd" ;; NetBSD:x86_64|NetBSD:amd64) TARGET_TRIPLE="x86_64-unknown-netbsd" ;;
NetBSD:aarch64|NetBSD:arm64) TARGET_TRIPLE="aarch64-unknown-netbsd" ;;
NetBSD:i686|NetBSD:i386) TARGET_TRIPLE="i686-unknown-netbsd" ;;
DragonFly:x86_64|DragonFly:amd64) TARGET_TRIPLE="x86_64-unknown-dragonfly" ;; DragonFly:x86_64|DragonFly:amd64) TARGET_TRIPLE="x86_64-unknown-dragonfly" ;;
*) error "Unsupported BSD platform: $os/$arch"; exit 1 ;; *) error "Unsupported BSD platform: $os/$arch"; exit 1 ;;
esac esac
@@ -181,6 +188,16 @@ install_link() {
success "Command 'dcr' added to $BINPATH" success "Command 'dcr' added to $BINPATH"
} }
install_man() {
log "Installing man pages..."
man_src="$TMPDIR/man/man1"
if [ -d "$man_src" ]; then
mkdir -p "$MANPATH/man1"
cp "$man_src"/*.1 "$MANPATH/man1/"
success "Man pages installed to $MANPATH/man1"
fi
}
check_path() { check_path() {
if ! echo "$PATH" | grep -q "$BINPATH"; then if ! echo "$PATH" | grep -q "$BINPATH"; then
warn "Directory $BINPATH not found in PATH" warn "Directory $BINPATH not found in PATH"
@@ -213,6 +230,7 @@ main() {
fi fi
install_link install_link
install_man
check_path check_path
cleanup cleanup

42
man/man1/dcr-add.1 Normal file
View File

@@ -0,0 +1,42 @@
.TH DCR-ADD 1 "2026-06-02" "dcr 0.7.0" "DCR Manual"
.SH NAME
dcr-add \- Add a dependency to a DCR project
.SH SYNOPSIS
.B dcr add \fI<name>\fR \fI<source>\fR
[\fB\-\-branch\fR \fI<b>\fR]
[\fB\-\-tag\fR \fI<t>\fR]
[\fB\-\-rev\fR \fI<r>\fR]
.SH DESCRIPTION
Adds a dependency to the project.
.SH SOURCES
.TP
.B user/repo
GitHub shorthand.
.TP
.B github:user/repo
Full GitHub repository.
.TP
.B gitlab:user/repo
GitLab repository.
.TP
.B git:host.com/user/repo
Generic git repository.
.TP
.B path:./path/to/lib
Local path dependency.
.TP
.B <version>
Version from registry.
.SH OPTIONS
.TP
.B \-\-branch \fI<name>\fR
Use a specific branch.
.TP
.B \-\-tag \fI<name>\fR
Use a specific tag.
.TP
.B \-\-rev \fI<hash>\fR
Use a specific commit hash.
.SH SEE ALSO
.BR dcr (1),
.BR dcr-tree (1)

37
man/man1/dcr-build.1 Normal file
View File

@@ -0,0 +1,37 @@
.TH DCR-BUILD 1 "2026-06-02" "dcr 0.7.0" "DCR Manual"
.SH NAME
dcr-build \- Compile a DCR project
.SH SYNOPSIS
.B dcr build
[\fB\-\-debug\fR | \fB\-\-release\fR]
[\fB\-\-target\fR \fI<triple>\fR]
[\fB\-\-force\fR]
[\fB\-\-clean\fR]
[\fB\-\-verbose\fR]
[\fB\-\-workspace\fR \fI<name>\fR]
.SH DESCRIPTION
Compiles the project. Default profile is \fB\-\-debug\fR.
.SH OPTIONS
.TP
.B \-\-debug
Build with debug profile (default). Enables debug symbols.
.TP
.B \-\-release
Build with release profile. Enables full optimization.
.TP
.B \-\-target \fI<triple>\fR
Cross-compile for the given target.
.TP
.B \-\-force
Force a full rebuild, ignoring cached artifacts.
.TP
.B \-\-clean
Clean before building.
.TP
.B \-\-verbose
Print detailed build output including compiler commands.
.TP
.B \-\-workspace \fI<name>\fR
Build a specific workspace member.
.SH SEE ALSO
.BR dcr (1)

26
man/man1/dcr-clean.1 Normal file
View File

@@ -0,0 +1,26 @@
.TH DCR-CLEAN 1 "2026-06-02" "dcr 0.7.0" "DCR Manual"
.SH NAME
dcr-clean \- Remove build artifacts
.SH SYNOPSIS
.B dcr clean
[\fB\-\-debug\fR | \fB\-\-release\fR]
[\fB\-\-target\fR \fI<triple>\fR]
[\fB\-\-all\fR]
.SH DESCRIPTION
Removes build artifacts from the target directory.
.SH OPTIONS
.TP
.B \-\-debug
Clean debug artifacts (default).
.TP
.B \-\-release
Clean release artifacts.
.TP
.B \-\-target \fI<triple>\fR
Clean artifacts for a specific target.
.TP
.B \-\-all
Clean all workspace members.
.SH SEE ALSO
.BR dcr (1),
.BR dcr-build (1)

10
man/man1/dcr-fmt.1 Normal file
View File

@@ -0,0 +1,10 @@
.TH DCR-FMT 1 "2026-06-02" "dcr 0.7.0" "DCR Manual"
.SH NAME
dcr-fmt \- Format C/C++ source files
.SH SYNOPSIS
.B dcr fmt
.SH DESCRIPTION
Formats all C/C++ source files using clang-format. Scans \fBsrc/\fR
and \fBtests/\fR directories recursively.
.SH SEE ALSO
.BR dcr (1)

23
man/man1/dcr-gen.1 Normal file
View File

@@ -0,0 +1,23 @@
.TH DCR-GEN 1 "2026-06-02" "dcr 0.7.0" "DCR Manual"
.SH NAME
dcr-gen \- Generate IDE and tooling integration files
.SH SYNOPSIS
.B dcr gen \fI<subcommand>\fR
.SH DESCRIPTION
Generates IDE and tooling integration files for DCR projects.
.SH SUBCOMMANDS
.TP
.B project-info
Print project metadata as JSON to stdout.
.TP
.B compile-commands
Generate \fBcompile_commands.json\fR for IDE tooling.
.TP
.B vscode
Generate \fB.vscode/\fR integration files (tasks, launch configurations).
.TP
.B clion
Generate \fB.idea/\fR integration files for CLion.
.SH SEE ALSO
.BR dcr (1),
.BR dcr-build (1)

11
man/man1/dcr-init.1 Normal file
View File

@@ -0,0 +1,11 @@
.TH DCR-INIT 1 "2026-06-02" "dcr 0.7.0" "DCR Manual"
.SH NAME
dcr-init \- Initialize a directory as a DCR project
.SH SYNOPSIS
.B dcr init
.SH DESCRIPTION
Initializes the current directory as a DCR project. The directory must
be empty.
.SH SEE ALSO
.BR dcr (1),
.BR dcr-new (1)

13
man/man1/dcr-new.1 Normal file
View File

@@ -0,0 +1,13 @@
.TH DCR-NEW 1 "2026-06-02" "dcr 0.7.0" "DCR Manual"
.SH NAME
dcr-new \- Create a new DCR project
.SH SYNOPSIS
.B dcr new \fI<name>\fR
.SH DESCRIPTION
Creates a new C/C++ project with the given name. The name may only
contain ASCII letters, digits, underscores and hyphens.
.SH EXAMPLE
.B dcr new my-project
.SH SEE ALSO
.BR dcr (1),
.BR dcr-init (1)

35
man/man1/dcr-run.1 Normal file
View File

@@ -0,0 +1,35 @@
.TH DCR-RUN 1 "2026-06-02" "dcr 0.7.0" "DCR Manual"
.SH NAME
dcr-run \- Build and run a DCR project
.SH SYNOPSIS
.B dcr run
[\fB\-\-debug\fR | \fB\-\-release\fR]
[\fB\-\-target\fR \fI<triple>\fR]
[\fB\-\-force\fR]
[\fB\-\-clean\fR]
[\fB\-\-verbose\fR]
.SH DESCRIPTION
Builds and runs the project. Only available for projects with
\fBkind = "bin"\fR.
.SH OPTIONS
.TP
.B \-\-debug
Run with debug profile (default).
.TP
.B \-\-release
Run with release profile.
.TP
.B \-\-target \fI<triple>\fR
Cross-compile for the given target.
.TP
.B \-\-force
Force a full rebuild.
.TP
.B \-\-clean
Clean before building.
.TP
.B \-\-verbose
Print detailed build output.
.SH SEE ALSO
.BR dcr (1),
.BR dcr-build (1)

11
man/man1/dcr-setup.1 Normal file
View File

@@ -0,0 +1,11 @@
.TH DCR-SETUP 1 "2026-06-02" "dcr 0.7.0" "DCR Manual"
.SH NAME
dcr-setup \- Set up DCR registries
.SH SYNOPSIS
.B dcr setup
.SH DESCRIPTION
Sets up DCR registries. Downloads and indexes package registries
for dependency resolution.
.SH SEE ALSO
.BR dcr (1),
.BR dcr-add (1)

24
man/man1/dcr-test.1 Normal file
View File

@@ -0,0 +1,24 @@
.TH DCR-TEST 1 "2026-06-02" "dcr 0.7.0" "DCR Manual"
.SH NAME
dcr-test \- Run project tests
.SH SYNOPSIS
.B dcr test
[\fB\-\-init\fR]
[\fB\-\-debug\fR | \fB\-\-release\fR]
.SH ALIASES
.B dcr tests
.SH DESCRIPTION
Runs project tests and prints a unified testsuite report.
.SH OPTIONS
.TP
.B \-\-init
Create \fBtests/dcr_test.h\fR in the current project.
.TP
.B \-\-debug
Build and run tests with debug profile (default).
.TP
.B \-\-release
Build and run tests with release profile.
.SH SEE ALSO
.BR dcr (1),
.BR dcr-build (1)

11
man/man1/dcr-tree.1 Normal file
View File

@@ -0,0 +1,11 @@
.TH DCR-TREE 1 "2026-06-02" "dcr 0.7.0" "DCR Manual"
.SH NAME
dcr-tree \- Display the dependency tree
.SH SYNOPSIS
.B dcr tree
.SH DESCRIPTION
Displays the dependency tree of the current project, showing all
transitive dependencies and their versions.
.SH SEE ALSO
.BR dcr (1),
.BR dcr-add (1)

204
man/man1/dcr.1 Normal file
View File

@@ -0,0 +1,204 @@
.TH DCR 1 "2026-06-02" "dcr 0.7.0" "DCR Manual"
.SH NAME
dcr \- Cargo\-like build tool and package manager for C/C++ projects
.SH SYNOPSIS
.B dcr
[\fIcommand\fR] [\fIoptions\fR]
.SH DESCRIPTION
DCR is a comprehensive build tool and package manager for C and C++ projects,
inspired by Cargo from the Rust ecosystem. It handles project creation,
building, dependency management, testing, formatting, and IDE integration.
.SH COMMANDS
.TP
.B new \fI<name>\fR
Create a new C/C++ project with the given name. Only ASCII letters, digits,
underscores and hyphens are allowed.
.TP
.B init
Initialize the current (empty) directory as a DCR project.
.TP
.B build [\fIoptions\fR]
Compile the project. Default profile is \fB\-\-debug\fR.
.TP
.B run [\fIoptions\fR]
Build and run the project. Only available for binary projects.
.TP
.B clean [\fIoptions\fR]
Remove build artifacts from the target directory.
.TP
.B test [\fI\-\-init\fR] [\fI\-\-debug\fR|\fI\-\-release\fR]
Run project tests (alias: \fBdcr tests\fR).
.TP
.B add \fI<name>\fR \fI<source>\fR [\fIoptions\fR]
Add a dependency to the project.
.TP
.B tree
Display the dependency tree of the current project.
.TP
.B fmt
Format all C/C++ source files using clang-format.
.TP
.B gen \fI<subcommand>\fR
Generate IDE integration files (vscode, clion, compile-commands, project-info).
.TP
.B setup
Set up DCR registries for dependency resolution.
.SH GLOBAL FLAGS
.TP
.B \-\-help
Show this help message and exit.
.TP
.B \-\-version
Print version information and exit.
.TP
.B \-\-update
Update DCR to the latest version from GitHub Releases.
.SH BUILD OPTIONS
The following options apply to \fBbuild\fR and \fBrun\fR commands:
.TP
.B \-\-debug
Build with debug profile (default). Enables debug symbols and minimal optimization.
.TP
.B \-\-release
Build with release profile. Enables full optimization without debug symbols.
.TP
.B \-\-target \fI<triple>\fR
Cross-compile for the given target (e.g. \fBaarch64-linux-gnu\fR, \fBx86_64-w64-mingw32\fR).
Short names like \fBlinux\fR, \fBmacos\fR, \fBwindows\fR are also supported.
.TP
.B \-\-force
Force a full rebuild, ignoring cached build artifacts.
.TP
.B \-\-clean
Clean build artifacts before building.
.TP
.B \-\-verbose
Print detailed build output including compiler commands.
.TP
.B \-\-workspace \fI<name>\fR
Build a specific workspace member.
.SH CLEAN OPTIONS
.TP
.B \-\-debug
Clean debug artifacts (default).
.TP
.B \-\-release
Clean release artifacts.
.TP
.B \-\-target \fI<triple>\fR
Clean artifacts for a specific target.
.TP
.B \-\-all
Clean all workspace members.
.SH ADD OPTIONS
.TP
.B \-\-branch \fI<name>\fR
Use a specific branch when adding a git dependency.
.TP
.B \-\-tag \fI<name>\fR
Use a specific tag when adding a git dependency.
.TP
.B \-\-rev \fI<hash>\fR
Use a specific commit hash when adding a git dependency.
.SH DEPENDENCY SOURCES
.TP
.B user/repo
GitHub shorthand (e.g. \fBuser/repo\fR).
.TP
.B github:user/repo
Full GitHub repository URL shorthand.
.TP
.B gitlab:user/repo
GitLab repository URL shorthand.
.TP
.B git:host.com/user/repo
Generic git repository.
.TP
.B path:./path/to/lib
Local path dependency.
.TP
.B \fI<version>\fR
Version from registry (e.g. \fB1.2.3\fR).
.SH GEN SUBCOMMANDS
.TP
.B project-info
Print project metadata as JSON to stdout.
.TP
.B compile-commands
Generate \fBcompile_commands.json\fR for IDE tooling.
.TP
.B vscode
Generate \fB.vscode/\fR integration files (tasks, launch configurations).
.TP
.B clion
Generate \fB.idea/\fR integration files for CLion.
.SH TEST OPTIONS
.TP
.B \-\-init
Create \fBtests/dcr_test.h\fR in the current project.
.TP
.B \-\-debug
Build and run tests with debug profile (default).
.TP
.B \-\-release
Build and run tests with release profile.
.SH PROJECT CONFIGURATION
DCR uses \fBdcr.toml\fR for project configuration. Key settings include:
.TP
.B package.name
Project name (required).
.TP
.B package.version
Project version (default: \fB0.1.0\fR).
.TP
.B build.language
Programming language: \fBc\fR or \fBc++\fR (default: \fBc\fR).
.TP
.B build.standard
Language standard (e.g. \fBc11\fR, \fBc17\fR, \fBc++20\fR; default: \fBc11\fR).
.TP
.B build.compiler
Compiler to use: \fBclang\fR, \fBgcc\fR, \fBcl\fR, \fBclang-cl\fR (default: \fBclang\fR).
.TP
.B build.kind
Output type: \fBbin\fR, \fBlib\fR (static or dynamic), \fBstaticlib\fR, \fBsharedlib\fR (default: \fBbin\fR).
.SH FILES
.TP
.I dcr.toml
Project manifest file.
.TP
.I ~/.dcr/config.toml
User-level DCR configuration.
.TP
.I ~/.dcr/index.json
Local registry index.
.SH ENVIRONMENT
.TP
.B DCR_COMPILER
Override the compiler used for building.
.TP
.B DCR_CC
Alternative way to override the compiler.
.SH EXAMPLES
.TP
Create a new project:
.B dcr new hello
.TP
Initialize from current directory:
.B dcr init
.TP
Build with release profile:
.B dcr build \-\-release
.TP
Cross-compile for Windows:
.B dcr build \-\-target windows
.TP
Add a dependency:
.BR "dcr add curl git:https://github.com/curl/curl" .
.TP
Generate VS Code integration:
.B dcr gen vscode
.SH SEE ALSO
.IR https://dcr.dexoron.su ", " https://github.com/dexoron/dcr
.SH AUTHORS
Dexoron (Bezotechestvo Vladimir) <main@dexoron.su>

Submodule packaging/aur/dcr-dev-git added at 93bdce858b

Submodule packaging/aur/dcr-git updated: 12038a613e...2c5743a456

View File

@@ -27,4 +27,7 @@ package() {
cd "$srcdir/$pkgname-$pkgver" cd "$srcdir/$pkgname-$pkgver"
install -Dm755 "target/release/dcr" "$pkgdir/usr/bin/dcr" install -Dm755 "target/release/dcr" "$pkgdir/usr/bin/dcr"
install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE" install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
for manpage in man/man1/*.1; do
install -Dm644 "$manpage" "$pkgdir/usr/share/man/man1/$(basename "$manpage")"
done
} }

View File

@@ -19,7 +19,7 @@ use crate::core::config::Config;
use crate::core::deps::register; use crate::core::deps::register;
use crate::utils::fs::find_project_root; use crate::utils::fs::find_project_root;
use crate::utils::log::error; use crate::utils::log::error;
use crate::utils::text::{BOLD_GREEN, colored}; use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, colored, printc};
use toml::Value; use toml::Value;
use toml::map::Map; use toml::map::Map;
@@ -34,6 +34,28 @@ pub struct AddArgs {
} }
pub fn add(args: &[String]) -> i32 { pub fn add(args: &[String]) -> i32 {
if args.first().map_or(false, |a| a == "--help") {
printc("USAGE:", BOLD_GREEN);
printc(" dcr add <name> <source> [--branch <b>] [--tag <t>] [--rev <r>]", BOLD_CYAN);
println!();
printc("DESCRIPTION:", BOLD_GREEN);
println!(" Adds a dependency to the project.");
println!();
printc("SOURCES:", BOLD_GREEN);
println!(" user/repo GitHub shorthand");
println!(" github:user/repo GitHub repository");
println!(" gitlab:user/repo GitLab repository");
println!(" git:host.com/user/repo Generic git repository");
println!(" path:./path/to/lib Local path dependency");
println!(" <version> Version from registry");
println!();
printc("OPTIONS:", BOLD_GREEN);
println!(" --branch <b> Use a specific branch");
println!(" --tag <t> Use a specific tag");
println!(" --rev <r> Use a specific commit hash");
return 0;
}
let add_args = match parse_add_args(args) { let add_args = match parse_add_args(args) {
Ok(a) => a, Ok(a) => a,
Err(code) => return code, Err(code) => return code,

View File

@@ -29,7 +29,7 @@ use crate::utils::build::{
}; };
use crate::utils::fs::{check_dir, find_project_root, with_dir}; use crate::utils::fs::{check_dir, find_project_root, with_dir};
use crate::utils::log::error; use crate::utils::log::error;
use crate::utils::text::{BOLD_GREEN, colored}; use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, colored, printc};
use glob::glob; use glob::glob;
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};
use std::fs; use std::fs;
@@ -42,6 +42,24 @@ static BUILD_INTERRUPTED: AtomicBool = AtomicBool::new(false);
static SIGNAL_HANDLER: Once = Once::new(); static SIGNAL_HANDLER: Once = Once::new();
pub fn build(args: &[String]) -> i32 { pub fn build(args: &[String]) -> i32 {
if args.first().map_or(false, |a| a == "--help") {
printc("USAGE:", BOLD_GREEN);
printc(" dcr build [--debug | --release] [--target <triple>] [--force] [--clean] [--verbose]", BOLD_CYAN);
println!();
printc("DESCRIPTION:", BOLD_GREEN);
println!(" Compiles the project. Default profile is --debug.");
println!();
printc("OPTIONS:", BOLD_GREEN);
println!(" --debug Build with debug profile (default)");
println!(" --release Build with release profile");
println!(" --target <triple> Cross-compile for the given target");
println!(" --force Force a full rebuild");
println!(" --clean Clean before building");
println!(" --verbose Print detailed build output");
println!(" --workspace <name> Build a specific workspace member");
return 0;
}
install_signal_handler(); install_signal_handler();
BUILD_INTERRUPTED.store(false, Ordering::SeqCst); BUILD_INTERRUPTED.store(false, Ordering::SeqCst);
let start_dir = match std::env::current_dir() { let start_dir = match std::env::current_dir() {

View File

@@ -21,12 +21,27 @@ use crate::core::workspace::parse_workspace;
use crate::utils::build::parse_version_info; use crate::utils::build::parse_version_info;
use crate::utils::fs::{check_dir, find_project_root, with_dir}; use crate::utils::fs::{check_dir, find_project_root, with_dir};
use crate::utils::log::{error, warn}; use crate::utils::log::{error, warn};
use crate::utils::text::{BOLD_GREEN, colored}; use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, colored, printc};
use glob::glob; use glob::glob;
use std::fs; use std::fs;
use std::path::Path; use std::path::Path;
pub fn clean(args: &[String]) -> i32 { pub fn clean(args: &[String]) -> i32 {
if args.first().map_or(false, |a| a == "--help") {
printc("USAGE:", BOLD_GREEN);
printc(" dcr clean [--debug | --release] [--target <triple>] [--all]", BOLD_CYAN);
println!();
printc("DESCRIPTION:", BOLD_GREEN);
println!(" Removes build artifacts from the target directory.");
println!();
printc("OPTIONS:", BOLD_GREEN);
println!(" --debug Clean debug artifacts (default)");
println!(" --release Clean release artifacts");
println!(" --target <triple> Clean artifacts for a specific target");
println!(" --all Clean all workspace members");
return 0;
}
let start_dir = match std::env::current_dir() { let start_dir = match std::env::current_dir() {
Ok(dir) => dir, Ok(dir) => dir,
Err(_) => { Err(_) => {

View File

@@ -16,6 +16,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
use crate::utils::log::{error, warn}; use crate::utils::log::{error, warn};
use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, printc};
use reqwest::blocking::Client; use reqwest::blocking::Client;
use serde::Deserialize; use serde::Deserialize;
use std::fs; use std::fs;
@@ -39,6 +40,15 @@ struct ReleaseAsset {
} }
pub fn flag_update(args: &[String]) -> i32 { pub fn flag_update(args: &[String]) -> i32 {
if args.first().map_or(false, |a| a == "--help") {
printc("USAGE:", BOLD_GREEN);
printc(" dcr --update", BOLD_CYAN);
println!();
printc("DESCRIPTION:", BOLD_GREEN);
println!(" Updates DCR to the latest version from GitHub Releases.");
return 0;
}
if !args.is_empty() { if !args.is_empty() {
warn("Command does not support additional arguments"); warn("Command does not support additional arguments");
return 1; return 1;

View File

@@ -16,11 +16,21 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
use crate::utils::log::error; use crate::utils::log::error;
use crate::utils::text::{BOLD_GREEN, colored}; use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, colored, printc};
use glob::glob; use glob::glob;
use std::process::Command; use std::process::Command;
pub fn fmt(_args: &[String]) -> i32 { pub fn fmt(args: &[String]) -> i32 {
if args.first().map_or(false, |a| a == "--help") {
printc("USAGE:", BOLD_GREEN);
printc(" dcr fmt", BOLD_CYAN);
println!();
printc("DESCRIPTION:", BOLD_GREEN);
println!(" Formats all C/C++ source files using clang-format.");
println!(" Scans src/ and tests/ directories recursively.");
return 0;
}
let patterns = [ let patterns = [
"src/**/*.c", "src/**/*.c",
"src/**/*.cpp", "src/**/*.cpp",

View File

@@ -27,6 +27,7 @@ use crate::utils::build::{
}; };
use crate::utils::fs::find_project_root; use crate::utils::fs::find_project_root;
use crate::utils::log::error; use crate::utils::log::error;
use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, printc};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
/// Like `deps::resolve_deps` but does NOT require lib directories to exist. /// Like `deps::resolve_deps` but does NOT require lib directories to exist.
@@ -186,13 +187,30 @@ pub struct ProjectInfo {
pub fn r#gen(args: &[String]) -> i32 { pub fn r#gen(args: &[String]) -> i32 {
let subcommand = match args.first() { let subcommand = match args.first() {
Some(s) if s == "--help" => {
printc("USAGE:", BOLD_GREEN);
printc(" dcr gen <subcommand>", BOLD_CYAN);
println!();
printc("DESCRIPTION:", BOLD_GREEN);
println!(" Generates IDE and tooling integration files.");
println!();
printc("SUBCOMMANDS:", BOLD_GREEN);
println!(" project-info Print project metadata as JSON");
println!(" compile-commands Generate compile_commands.json");
println!(" vscode Generate .vscode/ integration files");
println!(" clion Generate .idea/ integration files");
return 0;
}
Some(s) => s.as_str(), Some(s) => s.as_str(),
None => { None => {
eprintln!("Usage: dcr gen <subcommand>"); printc("USAGE:", BOLD_GREEN);
eprintln!(" project-info Print project metadata as JSON"); printc(" dcr gen <subcommand>", BOLD_CYAN);
eprintln!(" compile-commands Generate compile_commands.json"); println!();
eprintln!(" vscode Generate .vscode/ integration files"); printc("SUBCOMMANDS:", BOLD_GREEN);
eprintln!(" clion Generate .idea/ integration files"); println!(" project-info Print project metadata as JSON");
println!(" compile-commands Generate compile_commands.json");
println!(" vscode Generate .vscode/ integration files");
println!(" clion Generate .idea/ integration files");
return 1; return 1;
} }
}; };

View File

@@ -16,7 +16,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
use crate::config::FILE_MAIN_C; use crate::config::FILE_MAIN_C;
use crate::core::config::Config; use crate::core::config::{validate_package_name, Config};
use crate::utils::fs::check_dir; use crate::utils::fs::check_dir;
use crate::utils::log::{error, warn}; use crate::utils::log::{error, warn};
use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, colored, printc}; use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, colored, printc};
@@ -25,6 +25,16 @@ use std::io::Write;
use toml::Value; use toml::Value;
pub fn init(args: &[String]) -> i32 { pub fn init(args: &[String]) -> i32 {
if args.first().map_or(false, |a| a == "--help") {
printc("USAGE:", BOLD_GREEN);
printc(" dcr init", BOLD_CYAN);
println!();
printc("DESCRIPTION:", BOLD_GREEN);
println!(" Initializes the current directory as a DCR project.");
println!(" The directory must be empty.");
return 0;
}
if !args.is_empty() { if !args.is_empty() {
warn("Command does not support additional arguments"); warn("Command does not support additional arguments");
return 1; return 1;
@@ -41,6 +51,15 @@ pub fn init(args: &[String]) -> i32 {
return 1; return 1;
} }
if let Err(e) = validate_package_name(&project_name) {
error(&format!(
"Invalid project name `{}`: {}",
colored(&project_name, BOLD_CYAN),
e
));
return 1;
}
let cwd = std::env::current_dir() let cwd = std::env::current_dir()
.map(|v| v.to_string_lossy().to_string()) .map(|v| v.to_string_lossy().to_string())
.unwrap_or_else(|_| ".".to_string()); .unwrap_or_else(|_| ".".to_string());

View File

@@ -16,7 +16,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
use crate::config::FILE_MAIN_C; use crate::config::FILE_MAIN_C;
use crate::core::config::Config; use crate::core::config::{validate_package_name, Config};
use crate::utils::fs::check_dir; use crate::utils::fs::check_dir;
use crate::utils::log::{error, warn}; use crate::utils::log::{error, warn};
use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, colored, printc}; use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, colored, printc};
@@ -25,6 +25,16 @@ use std::io::Write;
use toml::Value; use toml::Value;
pub fn new(args: &[String]) -> i32 { pub fn new(args: &[String]) -> i32 {
if args.first().map_or(false, |a| a == "--help") {
printc("USAGE:", BOLD_GREEN);
printc(" dcr new <name>", BOLD_CYAN);
println!();
printc("DESCRIPTION:", BOLD_GREEN);
println!(" Creates a new C/C++ project with the given name.");
println!(" The name may only contain ASCII letters, digits, '_' and '-'.");
return 0;
}
let items = check_dir(None).unwrap_or_default(); let items = check_dir(None).unwrap_or_default();
if args.is_empty() { if args.is_empty() {
@@ -42,6 +52,15 @@ pub fn new(args: &[String]) -> i32 {
colored(project_name, BOLD_CYAN) colored(project_name, BOLD_CYAN)
); );
if let Err(e) = validate_package_name(project_name) {
error(&format!(
"Invalid project name `{}`: {}",
colored(project_name, BOLD_CYAN),
e
));
return 1;
}
if items.contains(project_name) { if items.contains(project_name) {
error(&format!( error(&format!(
"Directory `{}` already exists\n", "Directory `{}` already exists\n",

View File

@@ -23,7 +23,7 @@ use crate::utils::build::{normalize_target_os, parse_version_info};
use crate::utils::fs::find_project_root; use crate::utils::fs::find_project_root;
use crate::utils::fs::with_dir; use crate::utils::fs::with_dir;
use crate::utils::log::error; use crate::utils::log::error;
use crate::utils::text::{BOLD_GREEN, colored}; use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, colored, printc};
use std::path::Path; use std::path::Path;
use std::process::Command; use std::process::Command;
@@ -56,6 +56,23 @@ fn get_run_cmd(
} }
pub fn run(args: &[String]) -> i32 { pub fn run(args: &[String]) -> i32 {
if args.first().map_or(false, |a| a == "--help") {
printc("USAGE:", BOLD_GREEN);
printc(" dcr run [--debug | --release] [--target <triple>] [--force] [--clean] [--verbose]", BOLD_CYAN);
println!();
printc("DESCRIPTION:", BOLD_GREEN);
println!(" Builds and runs the project. Only available for kind = \"bin\".");
println!();
printc("OPTIONS:", BOLD_GREEN);
println!(" --debug Run with debug profile (default)");
println!(" --release Run with release profile");
println!(" --target <triple> Cross-compile for the given target");
println!(" --force Force a full rebuild");
println!(" --clean Clean before building");
println!(" --verbose Print detailed build output");
return 0;
}
let start_dir = match std::env::current_dir() { let start_dir = match std::env::current_dir() {
Ok(dir) => dir, Ok(dir) => dir,
Err(_) => { Err(_) => {

View File

@@ -15,7 +15,19 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
pub fn setup(_args: &[String]) -> i32 { use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, printc};
pub fn setup(args: &[String]) -> i32 {
if args.first().map_or(false, |a| a == "--help") {
printc("USAGE:", BOLD_GREEN);
printc(" dcr setup", BOLD_CYAN);
println!();
printc("DESCRIPTION:", BOLD_GREEN);
println!(" Sets up DCR registries. Downloads and indexes");
println!(" package registries for dependency resolution.");
return 0;
}
println!("Setting up DCR registries..."); println!("Setting up DCR registries...");
match crate::core::registry::RegistryManager::load() { match crate::core::registry::RegistryManager::load() {
Ok(manager) => { Ok(manager) => {

View File

@@ -24,7 +24,7 @@ use crate::utils::build::{
}; };
use crate::utils::fs::{find_project_root, with_dir}; use crate::utils::fs::{find_project_root, with_dir};
use crate::utils::log::error; use crate::utils::log::error;
use crate::utils::text::{BOLD_GREEN, BOLD_RED, RESET, colored}; use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, BOLD_RED, RESET, colored, printc};
use std::fs; use std::fs;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::process::Command; use std::process::Command;
@@ -36,16 +36,16 @@ pub fn test(args: &[String]) -> i32 {
let mut profile = "debug"; let mut profile = "debug";
for arg in args { for arg in args {
if arg == "--help" { if arg == "--help" {
println!("USAGE:"); printc("USAGE:", BOLD_GREEN);
println!(" dcr test [--init] [--debug | --release]"); printc(" dcr test [--init] [--debug | --release]", BOLD_CYAN);
println!(); println!();
println!("ALIASES:"); printc("ALIASES:", BOLD_GREEN);
println!(" dcr tests"); println!(" dcr tests");
println!(); println!();
println!("DESCRIPTION:"); printc("DESCRIPTION:", BOLD_GREEN);
println!(" Runs project tests and prints a unified testsuite report."); println!(" Runs project tests and prints a unified testsuite report.");
println!(); println!();
println!("OPTIONS:"); printc("OPTIONS:", BOLD_GREEN);
println!(" --init Create tests/dcr_test.h in current project"); println!(" --init Create tests/dcr_test.h in current project");
println!(" --debug Build and run tests with debug profile (default)"); println!(" --debug Build and run tests with debug profile (default)");
println!(" --release Build and run tests with release profile"); println!(" --release Build and run tests with release profile");

View File

@@ -17,12 +17,21 @@
use crate::core::config::Config; use crate::core::config::Config;
use crate::utils::log::error; use crate::utils::log::error;
use crate::utils::text::{BOLD_CYAN, printc}; use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, printc};
use std::collections::HashSet; use std::collections::HashSet;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use toml::Value; use toml::Value;
pub fn tree(_args: &[String]) -> i32 { pub fn tree(args: &[String]) -> i32 {
if args.first().map_or(false, |a| a == "--help") {
printc("USAGE:", BOLD_GREEN);
printc(" dcr tree", BOLD_CYAN);
println!();
printc("DESCRIPTION:", BOLD_GREEN);
println!(" Displays the dependency tree of the current project.");
return 0;
}
let current_dir = std::env::current_dir().unwrap_or_else(|_| PathBuf::from(".")); let current_dir = std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
let config = match Config::open("dcr.toml") { let config = match Config::open("dcr.toml") {
Ok(c) => c, Ok(c) => c,

View File

@@ -329,17 +329,16 @@ pub fn needs_link(objects: &[String], output_path: &str) -> bool {
fn parse_d_file(content: &str) -> Vec<String> { fn parse_d_file(content: &str) -> Vec<String> {
let mut deps = Vec::new(); let mut deps = Vec::new();
let text = content.replace("\\\n", " ").replace("\\\r\n", " ");
let mut target_end = 0; let mut target_end = 0;
let chars: Vec<char> = text.chars().collect(); let bytes = content.as_bytes();
for i in 0..chars.len() { for (i, &b) in bytes.iter().enumerate() {
if chars[i] == ':' { if b == b':' {
if i == 1 if i == 1
&& chars[0].is_ascii_alphabetic() && bytes[0].is_ascii_alphabetic()
&& i + 1 < chars.len() && i + 1 < bytes.len()
&& (chars[i + 1] == '\\' || chars[i + 1] == '/') && (bytes[i + 1] == b'\\' || bytes[i + 1] == b'/')
{ {
continue; // Windows drive letter continue;
} }
target_end = i + 1; target_end = i + 1;
break; break;
@@ -347,17 +346,23 @@ fn parse_d_file(content: &str) -> Vec<String> {
} }
let deps_str = if target_end > 0 { let deps_str = if target_end > 0 {
&text[target_end..] &content[target_end..]
} else { } else {
&text content
}; };
let mut current_path = String::new(); let mut current_path = String::new();
let mut in_escape = false; let mut in_escape = false;
let mut chars = deps_str.chars().peekable();
for c in deps_str.chars() { while let Some(c) = chars.next() {
if in_escape { if in_escape {
if c != '\n' && c != '\r' { if c == '\n' {
} else if c == '\r' {
if chars.peek() == Some(&'\n') {
chars.next();
}
} else {
current_path.push(c); current_path.push(c);
} }
in_escape = false; in_escape = false;

View File

@@ -447,7 +447,7 @@ fn parse_typed_config(value: &Value) -> Result<DcrConfig, ConfigError> {
value.clone().try_into().map_err(ConfigError::TomlDe) value.clone().try_into().map_err(ConfigError::TomlDe)
} }
fn validate_package_name(name: &str) -> Result<(), ConfigError> { pub fn validate_package_name(name: &str) -> Result<(), ConfigError> {
let trimmed = name.trim(); let trimmed = name.trim();
if trimmed != name { if trimmed != name {
return Err(ConfigError::Invalid( return Err(ConfigError::Invalid(