Добавить команду очистки сборки и обновить документацию, включая новые шаблоны и инструкции

This commit is contained in:
2026-02-11 23:54:41 +08:00
parent 491666b63e
commit 8ef1ab7fec
14 changed files with 163 additions and 56 deletions

4
.gitignore vendored
View File

@@ -4,4 +4,6 @@ dist/
wheels/ wheels/
*.egg-info *.egg-info
.venv .venv
sandbox/* sandbox/*
.ruff_cache/
.vscode/

View File

@@ -1,3 +0,0 @@
{
"kiroAgent.configureMCP": "Disabled"
}

10
CHANGELOG.md Normal file
View File

@@ -0,0 +1,10 @@
# Changelog
## [0.1.0] - 2026-02-11
Первый публичный релиз.
Добавлено:
- Базовые команды `new`, `init`, `build`, `run`, `clean`
- Профили сборки `debug` и `release`
- Шаблоны `dcr.toml` и `src/main.c`

View File

@@ -13,6 +13,7 @@ DCR — это утилита для управления проектами н
- Создание нового проекта или инициализация текущей директории - Создание нового проекта или инициализация текущей директории
- Сборка проекта в профилях `debug` и `release` - Сборка проекта в профилях `debug` и `release`
- Запуск собранного бинарника - Запуск собранного бинарника
- Очистка результатов сборки
- Генерация минимального шаблона C-проекта - Генерация минимального шаблона C-проекта
## Быстрый старт ## Быстрый старт
@@ -47,6 +48,9 @@ hello/
Запуск вручную: Запуск вручную:
`./target/<profile>/main` `./target/<profile>/main`
### `dcr clean`
Удаляет папку `target` в корне проекта.
## Профили сборки ## Профили сборки
Поддерживаются два профиля: Поддерживаются два профиля:
- `--debug` (по умолчанию) — флаги: `-O0 -g -Wall -Wextra -fno-omit-frame-pointer -DDEBUG` - `--debug` (по умолчанию) — флаги: `-O0 -g -Wall -Wextra -fno-omit-frame-pointer -DDEBUG`
@@ -55,6 +59,24 @@ hello/
## Конфигурация ## Конфигурация
Основной файл проекта — `dcr.toml`. Сейчас он создается автоматически и служит точкой входа для будущих настроек. Основной файл проекта — `dcr.toml`. Сейчас он создается автоматически и служит точкой входа для будущих настроек.
Пример `dcr.toml`:
```
[package]
name = "hello"
version = "0.1.0"
language = "c"
compiler = "clang"
[dependencies]
```
## Установка в PATH
Чтобы вызывать `dcr` из любой директории, можно сделать symlink в `~/.local/bin`:
```sh
ln -s "$PWD/dcr" ~/.local/bin/dcr
```
Убедитесь, что `~/.local/bin` находится в `PATH`.
## Пример проекта ## Пример проекта
`src/main.c` содержит минимальный `Hello, World!`: `src/main.c` содержит минимальный `Hello, World!`:
```c ```c

3
dcr Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/sh
uv run run "$@"

View File

@@ -3,6 +3,8 @@ from .init import init
from .new import new from .new import new
from .run import run from .run import run
from .build import build from .build import build
from .clean import clean
__all__ = [ __all__ = [
"help", "help",
@@ -10,4 +12,5 @@ __all__ = [
"new", "new",
"run", "run",
"build", "build",
"clean",
] ]

View File

@@ -1,13 +1,8 @@
import time
import os import os
import subprocess import subprocess
from ..config import flags, profile, c_comp from ..config import flags, profile, c_comp
from dcr.utils.fs import check_dir
def check_dir(dir: str | None = None) -> list[str]:
if dir in (None, ".", "./"):
return os.listdir(os.getcwd())
else:
return os.listdir(os.getcwd() + "/" + dir)
def build(args: list[str] | None = None) -> int: def build(args: list[str] | None = None) -> int:
@@ -22,7 +17,7 @@ def build(args: list[str] | None = None) -> int:
if len(args) >= 1 and args[0].startswith("--"): if len(args) >= 1 and args[0].startswith("--"):
candidate: str = args[0][2:] candidate: str = args[0][2:]
if candidate in flags: if candidate in flags:
active_profile = candidate active_profile: str = candidate
else: else:
print("Ошибка: неверный флаг сборки") print("Ошибка: неверный флаг сборки")
return 1 return 1
@@ -33,8 +28,9 @@ def build(args: list[str] | None = None) -> int:
if active_profile not in check_dir("target"): if active_profile not in check_dir("target"):
os.mkdir(f"./target/{active_profile}") os.mkdir(f"./target/{active_profile}")
if "main.c" in check_dir("src"): if "main.c" in check_dir("src"):
print(f"Run build project as profiles {active_profile}") print(f"Запуск сборки с профилем {active_profile}")
compile_flags = flags[active_profile] compile_flags = flags[active_profile]
start_time: float = time.time()
subprocess.run( subprocess.run(
[ [
c_comp, c_comp,
@@ -45,5 +41,8 @@ def build(args: list[str] | None = None) -> int:
], ],
check=True, check=True,
) )
print("Build complite") end_time: float = time.time()
times: float = end_time - start_time
times: float = int(times * 100) / 100
print(f"Сборка завершена, за {times} секунд")
return 0 return 0

20
src/dcr/cli/clean.py Normal file
View File

@@ -0,0 +1,20 @@
from dcr.utils.fs import check_dir
import os
import shutil
def clean(args: list[str]) -> int:
items: list[str] = check_dir()
if len(args) >= 1:
print("Ошибка: команда не поддежривает аргументы")
return 1
if "dcr.toml" not in items:
print("Ошибка: вы находитесь не в корне проекта")
return 1
if "target" not in items:
print("Вы уже очистили сборки")
return 0
shutil.rmtree("target")
print("Сборки очишены")
return 0

View File

@@ -1,32 +1,37 @@
from dcr.config import (
file_dcr_toml,
file_main_c,
project_version,
project_language,
project_compiler,
)
import os import os
from dcr.utils.fs import check_dir
def init(args: list[str] | None = None) -> int:
def init(args) -> int: if args:
items = os.listdir(os.getcwd()) print("Ошибка: команда init не поддерживает аргументы")
return 1
items = check_dir()
project_name = os.path.basename(os.getcwd()) project_name = os.path.basename(os.getcwd())
if items: if items:
print("ERROR: directory is not empty") print("Ошибка: директория не пустая")
return 1 return 1
os.mkdir("src") os.mkdir("src")
with open("./src/main.c", "w") as file: with open("./src/main.c", "w") as file:
file.write( file.write(file_main_c)
"#include <stdio.h>\n\n"
"int main(void) {\n"
' printf("Hello World!\\n");\n'
" return 0;\n"
"}\n"
)
with open("./dcr.toml", "w") as file: with open("./dcr.toml", "w") as file:
file.write( file.write(
"[package]\n" file_dcr_toml.format(
f'name = "{project_name}"\n' project_name=project_name,
'version = "0.1.0"\n' project_version=project_version,
'edition = "2026"\n\n' project_language=project_language,
"[dependencies]\n" project_compiler=project_compiler,
)
) )
return 0 return 0

View File

@@ -1,34 +1,40 @@
from dcr.config import (
file_dcr_toml,
file_main_c,
project_version,
project_language,
project_compiler,
)
import os import os
from dcr.utils.fs import check_dir
def new(args: list[str]) -> int: def new(args: list[str]) -> int:
items: list[str] = os.listdir(os.getcwd()) items: list[str] = check_dir()
if len(args) == 0 or len(args) > 1: if len(args) == 0:
print("ERROR") print("Ошибка: не указано название проекта")
return 1
if len(args) > 1:
print("Ошибка: команда не поддежривает аргументы")
return 1 return 1
project_name: str = args[0] project_name: str = args[0]
if project_name in items: if project_name in items:
print("ERROR") print(f"Ошибка: директория {project_name} занята")
return 1 return 1
os.makedirs(f"./{project_name}/src") os.makedirs(f"./{project_name}/src")
with open(f"./{project_name}/src/main.c", "w") as file: with open(f"./{project_name}/src/main.c", "w") as file:
file.write( file.write(file_main_c)
"#include <stdio.h>\n\n"
"int main(void) {\n"
' printf("Hello World!\\n");\n'
" return 0;\n"
"}\n"
)
with open(f"./{project_name}/dcr.toml", "w") as file: with open(f"./{project_name}/dcr.toml", "w") as file:
file.write( file.write(
"[package]\n" file_dcr_toml.format(
f'name = "{project_name}"\n' project_name=project_name,
'version = "0.1.0"\n' project_version=project_version,
'edition = "2026"\n\n' project_language=project_language,
"[dependencies]\n" project_compiler=project_compiler,
)
) )
return 0 return 0

View File

@@ -1,20 +1,14 @@
import os import os
import subprocess import subprocess
from dcr.utils.fs import check_dir
from ..config import flags, profile from ..config import flags, profile
from .build import build from .build import build
def check_dir(dir: str | None = None) -> list[str]:
if dir in (None, ".", "./"):
return os.listdir(os.getcwd())
else:
return os.listdir(os.getcwd() + "/" + dir)
def run(args: list[str] | None = None) -> int: def run(args: list[str] | None = None) -> int:
active_profile: str = profile active_profile: str = profile
if "dcr.toml" not in os.listdir(os.getcwd()): if "dcr.toml" not in check_dir():
print("Ошибка: не найден файл dcr.toml") print("Ошибка: не найден файл dcr.toml")
return 1 return 1
@@ -22,7 +16,7 @@ def run(args: list[str] | None = None) -> int:
if len(args) >= 1 and args[0].startswith("--"): if len(args) >= 1 and args[0].startswith("--"):
candidate: str = args[0][2:] candidate: str = args[0][2:]
if candidate in flags: if candidate in flags:
active_profile = candidate active_profile: str = candidate
else: else:
print("Ошибка: неверный флаг сборки") print("Ошибка: неверный флаг сборки")
return 1 return 1
@@ -31,5 +25,5 @@ def run(args: list[str] | None = None) -> int:
return 1 return 1
build(args) build(args)
print("Run project") print("Запуск проекта")
return subprocess.run([f"./target/{active_profile}/main"]).returncode return subprocess.run([f"./target/{active_profile}/main"]).returncode

View File

@@ -1,3 +1,39 @@
file_dcr_toml: str = """[package]
name = "{project_name}"
version = "{project_version}"
language = "{project_language}"
compiler = "{project_compiler}"
[dependencies]
"""
file_main_c: str = """#include <stdio.h>
int main(void) {
printf("Hello World!\n");
return 0;
}
"""
file_dcr_lock: str = """# This file is automatically @generated by dcr.
# It is not intended for manual editing.
version = 1
[[package]]
name = "{project_name}"
version = "{project_version}"
"""
"""[[package]]
name = "{package_name}"
version = "{package_version}"
source = "{{package_source}"
checksum = "{package_checksum}"
dependencies = [{package_dependencies}]"""
project_version: str = "0.1.0"
project_language: str = "c"
project_compiler: str = "clang"
profile: str = "debug" profile: str = "debug"
c_comp: str = "clang" c_comp: str = "clang"
flags: dict[str, list[str]] = { flags: dict[str, list[str]] = {

View File

@@ -19,6 +19,8 @@ def main() -> int:
cli.build(args) cli.build(args)
case "run": case "run":
cli.run(args) cli.run(args)
case "clean":
cli.clean(args)
case _: case _:
print("Unknown command") print("Unknown command")

8
src/dcr/utils/fs.py Normal file
View File

@@ -0,0 +1,8 @@
import os
def check_dir(dir: str | None = None) -> list[str]:
if dir in (None, ".", "./"):
return os.listdir(os.getcwd())
else:
return os.listdir(os.getcwd() + "/" + dir)