31 Commits

Author SHA1 Message Date
c8ef38a99b release: bump version to 0.7.2 and update changelog 2026-06-07 21:41:02 +08:00
8e0c535cfd fix: improve default target triple generation for various OS environments 2026-06-07 21:29:55 +08:00
de88c160ad Merge pull request #16 from XiaoPengYouCode/codex/fix-macos-host-target-link 2026-06-07 21:21:53 +08:00
595b7ac105 Merge pull request #15 from XiaoPengYouCode/codex/fix-readme-badges 2026-06-07 21:13:10 +08:00
XiaoPengYouCode
11ae3762d0 fix: use host macOS target for default builds 2026-06-07 05:41:07 +08:00
XiaoPengYouCode
4c439317e3 docs: fix README badge rendering 2026-06-07 05:09:38 +08:00
0aa3f87f99 feat: temporarily disable Snap Store publishing and update README instructions 2026-06-06 22:18:03 +08:00
a6ce0a3332 feat: enhance release notes extraction and include release name in GitHub release 2026-06-06 21:41:50 +08:00
cea43e99c8 feat: add Windows target dependencies and update README for MinGW 2026-06-06 21:39:17 +08:00
de4fb0bc29 feat: add .SRCINFO for AUR package metadata 2026-06-06 21:33:34 +08:00
59e27b6f5d Merge pull request #14 from dexoron/dev
v0.7.1 The Multi-Arch Expansion
2026-06-06 21:28:24 +08:00
c8cb155e5a feat: update help flag 2026-06-06 21:22:46 +08:00
6424aab69d feet: add license to docs and updated Cargo.toml to add build with no features flag 2026-06-06 21:19:04 +08:00
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
23c4f4ca87 Merge pull request #11 from dexoron/dev
Release v0.7.0
2026-06-02 01:10:33 +08:00
45 changed files with 1630 additions and 238 deletions

View File

@@ -21,6 +21,10 @@ on:
description: "Update AUR packages (dcr & dcr-bin)"
type: boolean
default: false
run_aur_dev:
description: "Update Dev AUR packages (dcr-dev, dcr-dev-bin)"
type: boolean
default: false
run_bsd:
description: "Build BSD"
type: boolean
@@ -37,10 +41,6 @@ on:
description: "Publish to crates.io"
type: boolean
default: false
run_snap:
description: "Publish to Snap Store (dcrup)"
type: boolean
default: false
run_brew:
description: "Update Homebrew tap"
type: boolean
@@ -56,6 +56,7 @@ jobs:
outputs:
tag: ${{ steps.tag.outputs.value }}
version: ${{ steps.tag.outputs.version }}
clean_version: ${{ steps.tag.outputs.clean_version }}
prerelease: ${{ steps.tag.outputs.prerelease }}
steps:
- name: Resolve tag
@@ -67,33 +68,51 @@ jobs:
TAG="${GITHUB_REF_NAME}"
fi
VERSION="${TAG#v}"
CLEAN_VERSION="${VERSION%-dev}"
[[ "$TAG" == *"-"* ]] && PRERELEASE="true" || PRERELEASE="false"
echo "value=${TAG}" >> "$GITHUB_OUTPUT"
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "clean_version=${CLEAN_VERSION}" >> "$GITHUB_OUTPUT"
echo "prerelease=${PRERELEASE}" >> "$GITHUB_OUTPUT"
# ── Release Notes ──────────────────────────────────────────────────────────
notes:
needs: setup
runs-on: ubuntu-latest
outputs:
release_name: ${{ steps.extract.outputs.release_name }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.setup.outputs.tag }}
- name: Prepare Release Notes
id: extract
shell: bash
run: |
set -euo pipefail
tag="${{ needs.setup.outputs.version }}"
notes_file=".github/release-notes.md"
if grep -q "^## \\[${tag}\\]" CHANGELOG.md; then
# Extract release name from header: ## [0.7.1] - 2026-06-02 "Title"
release_name=$(awk -v ver="$tag" '
$0 ~ "^## \\[" ver "\\]" {
match($0, /"([^"]+)"/, arr)
if (arr[1] != "") {
print "v" ver " - " arr[1]
} else {
print "v" ver
}
}
' CHANGELOG.md)
echo "release_name=${release_name}" >> "$GITHUB_OUTPUT"
awk -v ver="$tag" '
$0 ~ "^## \\[" ver "\\]" {found=1; next}
found && $0 ~ "^## \\[" {exit}
found {print}
' CHANGELOG.md | sed -e '${/^$/d;}' > "$notes_file"
else
echo "release_name=v${tag}" >> "$GITHUB_OUTPUT"
echo "No CHANGELOG section for $tag." > "$notes_file"
git log -1 --pretty=format:"%s%n%n%b" >> "$notes_file"
fi
@@ -119,6 +138,37 @@ jobs:
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ needs.setup.outputs.tag }}
name: ${{ needs.notes.outputs.release_name }}
body_path: .github/release-notes.md
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' }}
@@ -135,6 +185,12 @@ jobs:
- target: aarch64-unknown-linux-gnu
- target: x86_64-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:
- uses: actions/checkout@v4
with:
@@ -192,41 +248,73 @@ jobs:
strategy:
fail-fast: false
matrix:
include:
- package_type: deb
artifact_name: debian-package
- package_type: rpm
artifact_name: rpm-package
package_type: [deb, rpm, arch, snap]
target: [x86_64-unknown-linux-gnu, aarch64-unknown-linux-gnu, i686-unknown-linux-gnu, armv7-unknown-linux-gnueabihf, riscv64gc-unknown-linux-gnu]
exclude:
- 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
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:
- uses: actions/checkout@v4
with:
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'
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
# ── DEB Build ──
- name: Build Debian Package
if: matrix.package_type == 'deb'
run: |
cargo install cargo-deb
cargo build --release
cargo deb --no-build
mkdir -p dist-packages && cp target/debian/*.deb dist-packages/
if [ "${{ matrix.target }}" != "x86_64-unknown-linux-gnu" ]; then
cargo zigbuild --release --target ${{ matrix.target }}
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 ──
- name: Build RPM Package
if: matrix.package_type == 'rpm'
run: |
cargo install cargo-generate-rpm
cargo build --release
cargo generate-rpm
mkdir -p dist-packages && cp target/generate-rpm/*.rpm dist-packages/
if [ "${{ matrix.target }}" != "x86_64-unknown-linux-gnu" ]; then
cargo zigbuild --release --target ${{ matrix.target }}
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 ──
- name: Build Snap Package
@@ -235,6 +323,7 @@ jobs:
cargo build --release
mkdir -p packaging/snap/dist/bin
cp target/release/dcr packaging/snap/dist/bin/
cp -r man packaging/snap/dist/man
- name: Snapcraft Build Action
if: matrix.package_type == 'snap'
@@ -271,12 +360,17 @@ jobs:
sha256sums=('${SHA256}')
build() {
cd "\$srcdir/\$pkgname-${PKGVER_ORIG}"
unset CFLAGS CXXFLAGS LDFLAGS
export RUSTFLAGS="-C linker=cc"
cargo build --release --locked
}
package() {
cd "\$srcdir/\$pkgname-${PKGVER_ORIG}"
cd "\$srcdir/dcr-${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
docker run --rm \
@@ -296,7 +390,7 @@ jobs:
- name: Upload Package Artifact
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact_name }}
name: ${{ matrix.package_type }}-package-${{ matrix.target }}
path: dist-packages/*
if-no-files-found: ignore
@@ -321,10 +415,10 @@ jobs:
with:
tag_name: ${{ needs.setup.outputs.tag }}
files: |
collected-packages/debian-package/*
collected-packages/rpm-package/*
collected-packages/arch-package/*
collected-packages/snap-package/*
collected-packages/deb-package-*/*
collected-packages/rpm-package-*/*
collected-packages/arch-package-*/*
collected-packages/snap-package-*/*
body_path: .github/release-notes.md
prerelease: ${{ needs.setup.outputs.prerelease == 'true' }}
@@ -450,8 +544,6 @@ jobs:
cp target/release/dcr "$ASSET"
echo "BSD_ASSET=${ASSET}" >> "$GITHUB_ENV"
# --- UPLOAD TARGET ---
- name: Upload BSD Asset to Release
uses: softprops/action-gh-release@v2
@@ -472,6 +564,7 @@ jobs:
include:
- target: x86_64-pc-windows-msvc
- target: aarch64-pc-windows-msvc
- target: i686-pc-windows-msvc
- target: x86_64-pc-windows-gnu
steps:
- uses: actions/checkout@v4
@@ -552,14 +645,13 @@ jobs:
'gcc: build C/C++ projects with GCC'
'clang: build C/C++ projects with Clang'
)
source=("\$pkgname-\$pkgver.tar.gz::\${SRC_URL}")
source=("\$pkgname-\$pkgver.tar.gz::${SRC_URL}")
sha256sums=('${SHA256}')
build() {
cd "\$srcdir/\$pkgname-${PKGVER_ORIG}"
export CARGO_PROFILE_RELEASE_LTO=false
export RUSTFLAGS="\${RUSTFLAGS:-}"
export RUSTFLAGS="\${RUSTFLAGS/-C link-arg=-fuse-ld=lld/}"
unset CFLAGS CXXFLAGS LDFLAGS
export RUSTFLAGS="-C linker=cc"
cargo build --release --locked
}
@@ -567,6 +659,9 @@ jobs:
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
@@ -603,22 +698,31 @@ jobs:
ssh-keyscan aur.archlinux.org >> ~/.ssh/known_hosts
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
cp packages/aur/dcr/.SRCINFO aur-repo/.SRCINFO
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/PKGBUILD .
cp ../packages/aur/dcr/.SRCINFO .
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
if git diff --quiet; then
echo "No AUR changes"
exit 0
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 ${{ needs.setup.outputs.version }}"
git push
git push -u origin master
# ── Arch User Repository (dcr-bin) ────────────────────────────────
publish-aur-bin:
@@ -635,10 +739,22 @@ jobs:
shell: bash
run: |
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 }}"
SHA256="$(curl -fsSL "$BIN_URL" | sha256sum | awk '{print $1}')"
echo "bin_url=$BIN_URL" >> "$GITHUB_OUTPUT"
echo "sha256=$SHA256" >> "$GITHUB_OUTPUT"
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
@@ -646,16 +762,13 @@ jobs:
set -euo pipefail
PKGVER_ORIG='${{ needs.setup.outputs.version }}'
PKGVER_CLEAN="${PKGVER_ORIG//-/.}"
BIN_URL='${{ steps.meta.outputs.bin_url }}'
SHA256='${{ steps.meta.outputs.sha256 }}'
mkdir -p packages/aur/dcr-bin
cat > packages/aur/dcr-bin/PKGBUILD <<PKG
pkgname=dcr-bin
pkgver=${PKGVER_CLEAN}
pkgrel=1
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"
license=('GPL-3.0-or-later')
provides=('dcr')
@@ -664,8 +777,16 @@ jobs:
'gcc: build C/C++ projects with GCC'
'clang: build C/C++ projects with Clang'
)
source_x86_64=("dcr-\$pkgver::${BIN_URL}")
sha256sums_x86_64=('${SHA256}')
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"
@@ -679,13 +800,25 @@ jobs:
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}::${BIN_URL}
sha256sums_x86_64 = ${SHA256}
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-bin
SRC
@@ -703,22 +836,299 @@ jobs:
ssh-keyscan aur.archlinux.org >> ~/.ssh/known_hosts
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
cp packages/aur/dcr-bin/.SRCINFO aur-repo/.SRCINFO
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-bin/PKGBUILD .
cp ../packages/aur/dcr-bin/.SRCINFO .
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
if git diff --quiet; then
echo "No AUR changes"
exit 0
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-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 ──────────────────────────────────────────────────────────────
publish-crates:
@@ -738,6 +1148,8 @@ jobs:
- uses: dtolnay/rust-toolchain@stable
- name: Publish to crates.io
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: cargo publish
# ── Homebrew tap ───────────────────────────────────────────────────────────
@@ -762,6 +1174,7 @@ jobs:
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_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
uses: actions/checkout@v4
@@ -804,6 +1217,18 @@ jobs:
bin.install Dir["dcr*"].first => "dcr"
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
system "#{bin}/dcr", "--version"
end
@@ -819,24 +1244,11 @@ jobs:
git commit -m "dcr ${{ needs.setup.outputs.version }}"
git push
# ── Snap Store (dcrup) ─────────────────────────────────────────────────────
publish-snap:
if: |
(github.event_name == 'push' && needs.setup.outputs.prerelease == 'false') ||
(github.event_name == 'workflow_dispatch' && github.event.inputs.run_snap == 'true')
needs: [setup, build-linux-packages]
runs-on: ubuntu-latest
steps:
- name: Download Built Packages
uses: actions/download-artifact@v4
with:
name: snap-package
path: dist-packages
- name: Publish to Snap Store
uses: snapcore/action-publish@v1
env:
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }}
with:
snap: dist-packages/*.snap
release: stable
# ── Snap Store (dcrup) — temporarily disabled ────────────────────────────
# Classic confinement was denied for this project (too new).
# Snap artifact is still built and attached to the release via
# publish-dexoron-packages. Users can install manually:
# sudo snap install --classic --dangerous dcrup_*.snap
#
# publish-snap:
# if: ...

1
.gitignore vendored
View File

@@ -2,6 +2,7 @@ target/
sandbox/**
.idea/
.vscode/
.cargo/
.env
personal/

View File

@@ -1,5 +1,89 @@
# Changelog
## [0.7.2] - 2026-06-07 "Исправление Таргетов и Линковки / Target & Linker Fixes"
### RU
**Добавлено:**
- Учтён `target_env` в `default_target_triple()` — Linux (gnu/musl) и Windows (msvc/gnu) теперь используют правильное окружение, а не хардкод.
**Исправлено:**
- **Сборка на macOS Apple Silicon падала с `_main` undefined** — `--target=` теперь передаётся и в ldflags, не только в cflags. `default_target_triple()` на macOS использует `std::env::consts::ARCH` вместо хардкода `x86_64`.
- **Бейджи GitHub Stars и GPL-3.0 не рендерились в README** — блок бейджей переведён на чистый HTML.
**Изменено:**
- Вычисление таргета по умолчанию вынесено в общую функцию `default_target_triple()` — устранено дублирование в build, run, clean.
### EN
**Added:**
- `default_target_triple()` now respects `target_env` — Linux (gnu/musl) and Windows (msvc/gnu) use the correct environment instead of hardcoded values.
**Fixed:**
- **macOS Apple Silicon builds failed with `_main` undefined** — `--target=` is now passed to ldflags, not just cflags. `default_target_triple()` uses `std::env::consts::ARCH` on macOS instead of hardcoded `x86_64`.
- **GitHub Stars and GPL-3.0 badges not rendering in README** — badge block converted to pure HTML.
**Changed:**
- Default target resolution extracted into shared `default_target_triple()` — removed duplication across build, run, clean.
## [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) из-за проблем со сборкой.
**Исправлено:**
- **`dcr new <invalid-name>` создаёт директорию, затем падает** — валидация теперь происходит до операций с файлами.
- **`dcr init` создаёт dcr.toml, затем падает при невалидном имени директории** — то же исправление.
- **Man-страницы отсутствовали после установки** — теперь устанавливаются через скрипты установки, пакетные менеджеры и Homebrew.
- **Ложное срабатывание на букву диска в Windows** — в парсинге файлов зависимостей.
- **CRLF `\r\n` ломает парсер зависимостей** — теперь обрабатываются смешанные окончания строк.
- **Новая строка после обратного слеша не поглощалась** — в обработке escape-последовательностей `parse_d_file`.
### 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 Snap build 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
Added:

2
Cargo.lock generated
View File

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

View File

@@ -1,11 +1,13 @@
[package]
name = "dcr"
version = "0.7.0"
version = "0.7.2"
edition = "2024"
build = "build.rs"
description = "DCR is a utility for managing C/C++ projects in a Cargo-like style."
license = "GPL-3.0-or-later"
repository = "https://github.com/dexoron/dcr"
documentation = "https://dcr.dexoron.su/docs"
homepage = "https://dcr.dexoron.su"
[package.metadata.binstall]
pkg-fmt = "bin"
@@ -21,6 +23,18 @@ section = "devel"
priority = "optional"
assets = [
["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]
@@ -30,7 +44,19 @@ Cargo-like utility to manage C/C++ projects.
"""
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]
@@ -43,9 +69,32 @@ toml = "1.0.3"
serde_json = "1"
ctrlc = "3"
[features]
default = ["vendored"]
vendored = [
"git2/vendored-libgit2",
"git2/vendored-openssl",
"openssl/vendored",
]
[target.'cfg(not(windows))'.dependencies]
git2 = { version = "0.20.4", features = ["vendored-libgit2", "vendored-openssl"] }
openssl = { version = "0.10", features = ["vendored"] }
git2 = "0.20.4"
openssl = "0.10"
[target.'cfg(windows)'.dependencies]
git2 = { version = "0.20.4", features = ["vendored-libgit2"] }
git2 = "0.20.4"
[profile.release]
opt-level = "z"
lto = "thin"
codegen-units = 1
panic = "abort"
strip = true
[profile.fast]
inherits = "release"
opt-level = 1
lto = false
codegen-units = 16
panic = "abort"
strip = true

View File

@@ -1,31 +1,32 @@
<div align="center">
<h1 align="center">DCR — Dexoron Cargo Realization</h1>
# DCR — Dexoron Cargo Realization
<p align="center"><strong>A Cargo-style build tool for C/C++ projects</strong></p>
**A Cargo-style build tool for C/C++ projects**
<p align="center">
<a href="https://github.com/dexoron/dcr/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/dexoron/dcr/actions/workflows/ci.yml/badge.svg"></a>
<a href="https://github.com/dexoron/dcr/releases/latest"><img alt="GitHub Release" src="https://img.shields.io/github/v/release/dexoron/dcr"></a>
<a href="https://github.com/dexoron/dcr/releases"><img alt="Platform" src="https://img.shields.io/badge/platform-linux%20%7C%20macos%20%7C%20windows-lightgrey"></a>
<br>
<a href="https://aur.archlinux.org/packages/dcr"><img alt="AUR" src="https://img.shields.io/aur/version/dcr"></a>
<a href="https://crates.io/crates/dcr"><img alt="Crates.io" src="https://img.shields.io/crates/v/dcr"></a>
<a href="https://github.com/dexoron/homebrew-dexoron"><img alt="Homebrew" src="https://img.shields.io/badge/homebrew-dexoron%2Fdexoron-orange"></a>
<br>
<a href="https://github.com/dexoron/dcr/stargazers"><img alt="GitHub Stars" src="https://img.shields.io/github/stars/dexoron/dcr?style=flat"></a>
<a href="LICENSE"><img alt="License: GPL-3.0" src="https://img.shields.io/badge/License-GPL--3.0-blue.svg"></a>
</p>
[![CI](https://github.com/dexoron/dcr/actions/workflows/ci.yml/badge.svg)](https://github.com/dexoron/dcr/actions/workflows/ci.yml)
[![GitHub Release](https://img.shields.io/github/v/release/dexoron/dcr)](https://github.com/dexoron/dcr/releases/latest)
[![Platform](https://img.shields.io/badge/platform-linux%20%7C%20macos%20%7C%20windows-lightgrey)](https://github.com/dexoron/dcr/releases)
<br/>
[![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)
[![Homebrew](https://img.shields.io/badge/homebrew-dexoron%2Fdexoron-orange)](https://github.com/dexoron/homebrew-dexoron)
<br/>
[![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)
</div>
<!-- Snap badge removed: classic confinement was denied for this project. -->
---
## Why DCR?
- **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
- **IDE integration** — VS Code, CLion, `compile_commands.json` out of the box
- **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 +107,7 @@ cargo install dcr
<td>
```sh
curl -fsSL https://dcr.dexoron.su/install.sh | bash
curl -fsSL https://dcr.dexoron.su/install.sh | sh
```
</td>
@@ -116,7 +117,20 @@ curl -fsSL https://dcr.dexoron.su/install.sh | bash
<td>
```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>
> Snap Store publishing temporarily disabled — see [#51671](https://forum.snapcraft.io/t/classic-confinement-request-for-dcrup/51671).
> Download the `.snap` from [GitHub Releases](https://github.com/dexoron/dcr/releases/latest) and install manually:
```sh
sudo snap install --classic --dangerous dcrup_*.snap
```
</td>
@@ -200,24 +214,26 @@ kind = "bin"
| `dcr gen <vscode\|clion\|compile-commands>` | Generate IDE integration |
| `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">
| OS | x86_64 | aarch64 | armv7 | i686 | riscv64 | GNU | Musl | MSVC | MinGW |
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
| Linux | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ |
| macOS | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Windows | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ |
| FreeBSD | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ |
| OpenBSD | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ |
| NetBSD | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ |
| OS | x86_64 | aarch64 | armv7 | i686 | riscv64 |
|:---:|:---:|:---:|:---:|:---:|:---:|
| Linux (GNU) | ✅ | ✅ | ✅ | ✅ | ✅ |
| Linux (Musl) | ✅ | ✅ | ✅ | ✅ | 🚧 |
| macOS | ✅ | ✅ | ❌ | ❌ | ❌ |
| Windows (MSVC) | ✅ | ✅ | ❌ | ✅ | ❌ |
| Windows (MinGW) | ✅ | 🚧 | ❌ | ❌ | ❌ |
| FreeBSD | ✅ | 🚧 | ❌ | ❌ | ❌ |
| OpenBSD | ✅ | 🚧 | ❌ | ❌ | ❌ |
| NetBSD | ✅ | 🚧 | ❌ | ❌ | ❌ |
✅ officially supported · ⚠️ community / best-effort · ❌ not supported
✅ pre-built binary · 🚧 planned · ❌ not supported by platform or CI
</div>
@@ -257,6 +273,7 @@ cargo test
<div align="center">
GPL-3.0 — see [LICENSE](LICENSE)<br/>
DCR is a build tool, not a library. The GPL applies only to DCR's own source code, not to projects built with it.<br/>
Made with ❤️ by [Dexoron](https://github.com/dexoron) and contributors.
</div>
</div>

View File

@@ -44,6 +44,7 @@ dcr gen vscode
| [Self Update](/docs/self-update) | Auto-update |
| [FAQ](/docs/faq) | Frequently asked questions |
| [Changelog](/docs/changelog) | Version history |
| [License](/docs/license) | DCR and vendored library licenses |
| [Contributing](/docs/contributing) | DCR development |
## Features
@@ -58,3 +59,5 @@ dcr gen vscode
- **Registry + Git + Path** — three dependency mechanisms
- **IDE generation** — VS Code, CLion, compile_commands.json, JSON metadata
- **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
## 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)
### 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.
Only ASCII letters, digits, underscores `_` and hyphens `-` are allowed in the project name.
```bash
dcr new my-app
```
@@ -25,4 +27,4 @@ mkdir app && cd app
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
```
## Snap (Linux)
```sh
sudo snap install dcrup
```
## Nix (flake)
```sh
@@ -53,13 +59,13 @@ cargo install dcr
## Linux / macOS (script)
```sh
curl -fsSL https://dcr.dexoron.su/install.sh | bash
curl -fsSL https://dcr.dexoron.su/install.sh | sh
```
## BSD (script)
```sh
curl -fsSL https://dcr.dexoron.su/install_bsd.sh | bash
curl -fsSL https://dcr.dexoron.su/install_bsd.sh | sh
```
## Windows (PowerShell)
@@ -84,6 +90,13 @@ Verify the installation:
dcr --version
```
Man pages are available after installation:
```bash
man dcr
man dcr-build
```
To use the registry, create `~/.dcr/config.toml`:
```toml

46
docs/license.mdx Normal file
View File

@@ -0,0 +1,46 @@
---
sidebar_label: License
---
# License
## DCR
DCR itself is [GPL-3.0-or-later](https://spdx.org/licenses/GPL-3.0-or-later.html) licensed.
> **Note:** DCR is a build tool, not a library. The GPL applies only to DCR's own source code. Projects built with DCR are not subject to DCR's license — their licensing is determined solely by their own code and dependencies.
## Vendored libraries
DCR statically links the following C libraries through its vendored Rust dependencies:
| Library | License | Bundled by |
|---|---|---|
| [libgit2](https://libgit2.org) | MIT OR Apache-2.0 | `git2` / `libgit2-sys` |
| [libssh2](https://libssh2.org) | MIT OR Apache-2.0 | `libgit2-sys` |
| [zlib](https://zlib.net) | MIT OR Apache-2.0 | `libgit2-sys` |
| [OpenSSL](https://openssl.org) | Apache-2.0 | `openssl-sys` / `openssl-src` |
| [ring](https://github.com/briansmith/ring) | Apache-2.0 AND ISC | `rustls` |
## Rust dependencies
DCR is written in Rust. The following notable Rust crates are statically linked:
| Crate | License |
|---|---|
| [`reqwest`](https://crates.io/crates/reqwest) | MIT OR Apache-2.0 |
| [`rustls`](https://crates.io/crates/rustls) | Apache-2.0 OR ISC OR MIT |
| [`serde`](https://crates.io/crates/serde) | MIT OR Apache-2.0 |
| [`toml`](https://crates.io/crates/toml) | MIT OR Apache-2.0 |
| [`sha2`](https://crates.io/crates/sha2) | MIT OR Apache-2.0 |
| [`git2`](https://crates.io/crates/git2) | MIT OR Apache-2.0 |
| [`openssl`](https://crates.io/crates/openssl) | Apache-2.0 |
| [`tokio`](https://crates.io/crates/tokio) | MIT |
| [`hyper`](https://crates.io/crates/hyper) | MIT |
| [`ctrlc`](https://crates.io/crates/ctrlc) | MIT OR Apache-2.0 |
Full dependency tree (143 packages) is available in [`Cargo.lock`](https://github.com/dexoron/dcr/blob/main/Cargo.lock). The overwhelming majority are dual-licensed under MIT OR Apache-2.0.
## Additional credits
- DCR's CLI design and project model are inspired by [Cargo](https://doc.rust-lang.org/cargo/).

View File

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

View File

@@ -47,10 +47,16 @@ function Select-Mode {
}
function Get-Target {
if ($env:PROCESSOR_ARCHITECTURE -ne 'AMD64') {
Fail "Only x86_64 Windows is supported, current architecture: $env:PROCESSOR_ARCHITECTURE"
$arch = $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) {

View File

@@ -4,6 +4,7 @@ set -Eeuo pipefail
TMPDIR="/tmp/dcr-install"
INSTALL_PATH="$HOME/.local/share/dcr"
BINPATH="$HOME/.local/bin"
MANPATH="${XDG_DATA_HOME:-$HOME/.local/share}/man"
LOGFILE="$HOME/.cache/dcr-install.log"
REPO_URL="https://github.com/dexoron/dcr"
GITHUB_API_LATEST="https://api.github.com/repos/dexoron/dcr/releases/latest"
@@ -43,11 +44,20 @@ detect_target() {
case "$os:$arch" in
Linux:x86_64) TARGET_TRIPLE="x86_64-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:arm64|Darwin:aarch64) TARGET_TRIPLE="aarch64-apple-darwin" ;;
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: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:aarch64|NetBSD:arm64) TARGET_TRIPLE="aarch64-unknown-netbsd" ;;
NetBSD:i686|NetBSD:i386) TARGET_TRIPLE="i686-unknown-netbsd" ;;
*) error "Unsupported platform: $os/$arch"; exit 1 ;;
esac
@@ -190,6 +200,16 @@ install_link() {
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() {
if ! echo "$PATH" | grep -q "$BINPATH"; then
warn "Directory $BINPATH not found in PATH"
@@ -222,6 +242,7 @@ main() {
fi
install_link
install_man
check_path
cleanup

View File

@@ -4,6 +4,7 @@ set -eu
TMPDIR="/tmp/dcr-install"
INSTALL_PATH="$HOME/.local/share/dcr"
BINPATH="$HOME/.local/bin"
MANPATH="${XDG_DATA_HOME:-$HOME/.local/share}/man"
LOGFILE="$HOME/.cache/dcr-install.log"
REPO_URL="https://github.com/dexoron/dcr"
GITHUB_API_LATEST="https://api.github.com/repos/dexoron/dcr/releases/latest"
@@ -39,8 +40,14 @@ detect_target() {
case "$os:$arch" in
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: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: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" ;;
*) error "Unsupported BSD platform: $os/$arch"; exit 1 ;;
esac
@@ -181,6 +188,16 @@ install_link() {
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() {
if ! echo "$PATH" | grep -q "$BINPATH"; then
warn "Directory $BINPATH not found in PATH"
@@ -213,6 +230,7 @@ main() {
fi
install_link
install_man
check_path
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"
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
}

View File

@@ -19,7 +19,7 @@ use crate::core::config::Config;
use crate::core::deps::register;
use crate::utils::fs::find_project_root;
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::map::Map;
@@ -34,6 +34,31 @@ pub struct AddArgs {
}
pub fn add(args: &[String]) -> i32 {
if args.first().is_some_and(|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) {
Ok(a) => a,
Err(code) => return code,

View File

@@ -23,13 +23,13 @@ use crate::core::config::Config;
use crate::core::deps::{register, resolve_deps};
use crate::core::workspace::parse_workspace;
use crate::utils::build::{
get_bool_with_profile, get_config_opt, get_config_str, get_language_with_profile,
normalize_target_os, parse_version_info, profile_table, resolve_compiler,
resolve_pkg_config_flags, resolve_tool,
default_target_triple, get_bool_with_profile, get_config_opt, get_config_str,
get_language_with_profile, normalize_target_os, parse_version_info, prepend_clang_target_flag,
profile_table, resolve_compiler, resolve_pkg_config_flags, resolve_tool,
};
use crate::utils::fs::{check_dir, find_project_root, with_dir};
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 sha2::{Digest, Sha256};
use std::fs;
@@ -42,6 +42,27 @@ static BUILD_INTERRUPTED: AtomicBool = AtomicBool::new(false);
static SIGNAL_HANDLER: Once = Once::new();
pub fn build(args: &[String]) -> i32 {
if args.first().is_some_and(|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();
BUILD_INTERRUPTED.store(false, Ordering::SeqCst);
let start_dir = match std::env::current_dir() {
@@ -79,27 +100,7 @@ pub fn build(args: &[String]) -> i32 {
}
}
if flags.target.is_none() {
let default_target = if cfg!(target_os = "linux") {
format!("{}-unknown-linux-gnu", std::env::consts::ARCH)
} else if cfg!(target_os = "macos") {
"x86_64-apple-darwin".to_string()
} else if cfg!(target_os = "windows") {
"x86_64-pc-windows-msvc".to_string()
} else if cfg!(any(
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
target_os = "dragonfly"
)) {
format!(
"{}-unknown-{}",
std::env::consts::ARCH,
std::env::consts::OS
)
} else {
"unknown".to_string()
};
flags.target = Some(default_target);
flags.target = Some(default_target_triple());
}
if flags.clean {
let mut clean_args = Vec::new();
@@ -697,19 +698,13 @@ fn build_project_at(
tc_cxx.as_deref(),
tc_as.as_deref(),
);
if let Some(t) = build_target
&& !t.trim().is_empty()
&& resolved_compiler.to_lowercase().contains("clang")
{
let target_flag = format!("--target={}", t.trim());
if !build_cflags
.iter()
.any(|f| f == &target_flag || f.starts_with("--target="))
{
build_cflags.insert(0, target_flag);
}
}
let resolved_linker = resolve_tool("DCR_LD", tc_ld.as_deref());
prepend_clang_target_flag(&mut build_cflags, build_target, &resolved_compiler);
prepend_clang_target_flag(
&mut build_ldflags,
build_target,
resolved_linker.as_deref().unwrap_or(&resolved_compiler),
);
let resolved_archiver = resolve_tool("DCR_AR", tc_ar.as_deref());
let out_dir_config = get_build_string_with_profile(&config, "out_dir", profile);

View File

@@ -18,15 +18,33 @@
use crate::config::flags;
use crate::core::config::Config;
use crate::core::workspace::parse_workspace;
use crate::utils::build::parse_version_info;
use crate::utils::build::{default_target_triple, parse_version_info};
use crate::utils::fs::{check_dir, find_project_root, with_dir};
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 std::fs;
use std::path::Path;
pub fn clean(args: &[String]) -> i32 {
if args.first().is_some_and(|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() {
Ok(dir) => dir,
Err(_) => {
@@ -118,28 +136,7 @@ fn clean_from_root(root: &Path, flags: &CleanFlags) -> Result<(), String> {
.map(|s| s.trim().to_string())
.filter(|s| !s.is_empty())
})
.or_else(|| {
Some(if cfg!(target_os = "linux") {
format!("{}-unknown-linux-gnu", std::env::consts::ARCH)
} else if cfg!(target_os = "macos") {
"x86_64-apple-darwin".to_string()
} else if cfg!(target_os = "windows") {
"x86_64-pc-windows-msvc".to_string()
} else if cfg!(any(
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
target_os = "dragonfly"
)) {
format!(
"{}-unknown-{}",
std::env::consts::ARCH,
std::env::consts::OS
)
} else {
"unknown".to_string()
})
});
.or_else(|| Some(default_target_triple()));
if flags.all
&& let Some(workspace) = parse_workspace(

View File

@@ -16,6 +16,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
use crate::utils::log::{error, warn};
use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, printc};
use reqwest::blocking::Client;
use serde::Deserialize;
use std::fs;
@@ -39,6 +40,15 @@ struct ReleaseAsset {
}
pub fn flag_update(args: &[String]) -> i32 {
if args.first().is_some_and(|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() {
warn("Command does not support additional arguments");
return 1;

View File

@@ -16,11 +16,21 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
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 std::process::Command;
pub fn fmt(_args: &[String]) -> i32 {
pub fn fmt(args: &[String]) -> i32 {
if args.first().is_some_and(|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 = [
"src/**/*.c",
"src/**/*.cpp",

View File

@@ -27,6 +27,7 @@ use crate::utils::build::{
};
use crate::utils::fs::find_project_root;
use crate::utils::log::error;
use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, printc};
use std::path::{Path, PathBuf};
/// 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 {
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(),
None => {
eprintln!("Usage: dcr gen <subcommand>");
eprintln!(" project-info Print project metadata as JSON");
eprintln!(" compile-commands Generate compile_commands.json");
eprintln!(" vscode Generate .vscode/ integration files");
eprintln!(" clion Generate .idea/ integration files");
printc("USAGE:", BOLD_GREEN);
printc(" dcr gen <subcommand>", BOLD_CYAN);
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 1;
}
};

View File

@@ -16,7 +16,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
use crate::config::FILE_MAIN_C;
use crate::core::config::Config;
use crate::core::config::{Config, validate_package_name};
use crate::utils::fs::check_dir;
use crate::utils::log::{error, warn};
use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, colored, printc};
@@ -25,6 +25,16 @@ use std::io::Write;
use toml::Value;
pub fn init(args: &[String]) -> i32 {
if args.first().is_some_and(|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() {
warn("Command does not support additional arguments");
return 1;
@@ -41,6 +51,15 @@ pub fn init(args: &[String]) -> i32 {
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()
.map(|v| v.to_string_lossy().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/>.
use crate::config::FILE_MAIN_C;
use crate::core::config::Config;
use crate::core::config::{Config, validate_package_name};
use crate::utils::fs::check_dir;
use crate::utils::log::{error, warn};
use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, colored, printc};
@@ -25,6 +25,16 @@ use std::io::Write;
use toml::Value;
pub fn new(args: &[String]) -> i32 {
if args.first().is_some_and(|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();
if args.is_empty() {
@@ -42,6 +52,15 @@ pub fn new(args: &[String]) -> i32 {
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) {
error(&format!(
"Directory `{}` already exists\n",

View File

@@ -19,11 +19,11 @@ use crate::cli::build::build;
use crate::cli::flags::parse_build_run_flags;
use crate::core::config::Config;
use crate::core::runner::run_binary;
use crate::utils::build::{normalize_target_os, parse_version_info};
use crate::utils::build::{default_target_triple, normalize_target_os, parse_version_info};
use crate::utils::fs::find_project_root;
use crate::utils::fs::with_dir;
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::process::Command;
@@ -56,6 +56,26 @@ fn get_run_cmd(
}
pub fn run(args: &[String]) -> i32 {
if args.first().is_some_and(|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() {
Ok(dir) => dir,
Err(_) => {
@@ -158,27 +178,7 @@ fn run_project(
// If no target specified, use default host target for target-specific config
let mut target = flags.target.clone();
if target.is_none() {
let default_target = if cfg!(target_os = "linux") {
format!("{}-unknown-linux-gnu", std::env::consts::ARCH)
} else if cfg!(target_os = "macos") {
"x86_64-apple-darwin".to_string()
} else if cfg!(target_os = "windows") {
"x86_64-pc-windows-msvc".to_string()
} else if cfg!(any(
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
target_os = "dragonfly"
)) {
format!(
"{}-unknown-{}",
std::env::consts::ARCH,
std::env::consts::OS
)
} else {
"unknown".to_string()
};
target = Some(default_target);
target = Some(default_target_triple());
}
let build_kind = config

View File

@@ -15,7 +15,19 @@
// You should have received a copy of the GNU General Public License
// 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().is_some_and(|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...");
match crate::core::registry::RegistryManager::load() {
Ok(manager) => {

View File

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

View File

@@ -17,12 +17,21 @@
use crate::core::config::Config;
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::path::{Path, PathBuf};
use toml::Value;
pub fn tree(_args: &[String]) -> i32 {
pub fn tree(args: &[String]) -> i32 {
if args.first().is_some_and(|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 config = match Config::open("dcr.toml") {
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> {
let mut deps = Vec::new();
let text = content.replace("\\\n", " ").replace("\\\r\n", " ");
let mut target_end = 0;
let chars: Vec<char> = text.chars().collect();
for i in 0..chars.len() {
if chars[i] == ':' {
let bytes = content.as_bytes();
for (i, &b) in bytes.iter().enumerate() {
if b == b':' {
if i == 1
&& chars[0].is_ascii_alphabetic()
&& i + 1 < chars.len()
&& (chars[i + 1] == '\\' || chars[i + 1] == '/')
&& bytes[0].is_ascii_alphabetic()
&& i + 1 < bytes.len()
&& (bytes[i + 1] == b'\\' || bytes[i + 1] == b'/')
{
continue; // Windows drive letter
continue;
}
target_end = i + 1;
break;
@@ -347,17 +346,23 @@ fn parse_d_file(content: &str) -> Vec<String> {
}
let deps_str = if target_end > 0 {
&text[target_end..]
&content[target_end..]
} else {
&text
content
};
let mut current_path = String::new();
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 c != '\n' && c != '\r' {
if c == '\n' {
} else if c == '\r' {
if chars.peek() == Some(&'\n') {
chars.next();
}
} else {
current_path.push(c);
}
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)
}
fn validate_package_name(name: &str) -> Result<(), ConfigError> {
pub fn validate_package_name(name: &str) -> Result<(), ConfigError> {
let trimmed = name.trim();
if trimmed != name {
return Err(ConfigError::Invalid(

View File

@@ -72,6 +72,53 @@ pub fn normalize_target_os(target: &str) -> &str {
}
}
pub fn default_target_triple() -> String {
let arch = std::env::consts::ARCH;
if cfg!(target_os = "linux") {
let env = if cfg!(target_env = "musl") {
"musl"
} else {
"gnu"
};
format!("{arch}-unknown-linux-{env}")
} else if cfg!(target_os = "macos") {
format!("{arch}-apple-darwin")
} else if cfg!(target_os = "windows") {
let env = if cfg!(target_env = "gnu") {
"gnu"
} else {
"msvc"
};
format!("{arch}-pc-windows-{env}")
} else if cfg!(any(
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
target_os = "dragonfly"
)) {
format!("{arch}-unknown-{}", std::env::consts::OS)
} else {
"unknown".to_string()
}
}
pub fn prepend_clang_target_flag(flags: &mut Vec<String>, target: Option<&str>, tool: &str) {
let Some(target) = target.map(str::trim).filter(|t| !t.is_empty()) else {
return;
};
if !tool.to_lowercase().contains("clang") {
return;
}
let target_flag = format!("--target={target}");
if !flags
.iter()
.any(|f| f == &target_flag || f.starts_with("--target="))
{
flags.insert(0, target_flag);
}
}
pub fn get_config_str(config: &Config, key: &str) -> String {
config
.get(key)
@@ -380,6 +427,61 @@ mod tests {
assert_eq!(normalize_target_os("unknown"), "unknown");
}
#[test]
fn default_target_triple_uses_host_arch() {
let target = default_target_triple();
if cfg!(target_os = "linux") {
assert_eq!(
target,
format!("{}-unknown-linux-gnu", std::env::consts::ARCH)
);
} else if cfg!(target_os = "macos") {
assert_eq!(target, format!("{}-apple-darwin", std::env::consts::ARCH));
} else if cfg!(target_os = "windows") {
assert_eq!(
target,
format!("{}-pc-windows-msvc", std::env::consts::ARCH)
);
} else if cfg!(any(
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
target_os = "dragonfly"
)) {
assert_eq!(
target,
format!(
"{}-unknown-{}",
std::env::consts::ARCH,
std::env::consts::OS
)
);
} else {
assert_eq!(target, "unknown");
}
}
#[test]
fn prepend_clang_target_flag_adds_once_for_clang() {
let mut flags = vec!["-O2".to_string()];
prepend_clang_target_flag(&mut flags, Some("aarch64-apple-darwin"), "clang");
prepend_clang_target_flag(&mut flags, Some("aarch64-apple-darwin"), "clang");
assert_eq!(
flags,
vec![
"--target=aarch64-apple-darwin".to_string(),
"-O2".to_string()
]
);
}
#[test]
fn prepend_clang_target_flag_ignores_non_clang_tools() {
let mut flags = vec!["-O2".to_string()];
prepend_clang_target_flag(&mut flags, Some("aarch64-apple-darwin"), "gcc");
assert_eq!(flags, vec!["-O2".to_string()]);
}
#[test]
fn parse_version_parts() {
let info = parse_version_info("1.2.3-beta");