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

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/
*.egg-info
.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`
- Запуск собранного бинарника
- Очистка результатов сборки
- Генерация минимального шаблона C-проекта
## Быстрый старт
@@ -47,6 +48,9 @@ hello/
Запуск вручную:
`./target/<profile>/main`
### `dcr clean`
Удаляет папку `target` в корне проекта.
## Профили сборки
Поддерживаются два профиля:
- `--debug` (по умолчанию) — флаги: `-O0 -g -Wall -Wextra -fno-omit-frame-pointer -DDEBUG`
@@ -55,6 +59,24 @@ hello/
## Конфигурация
Основной файл проекта — `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!`:
```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 .run import run
from .build import build
from .clean import clean
__all__ = [
"help",
@@ -10,4 +12,5 @@ __all__ = [
"new",
"run",
"build",
"clean",
]

View File

@@ -1,13 +1,8 @@
import time
import os
import subprocess
from ..config import flags, profile, c_comp
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)
from dcr.utils.fs import check_dir
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("--"):
candidate: str = args[0][2:]
if candidate in flags:
active_profile = candidate
active_profile: str = candidate
else:
print("Ошибка: неверный флаг сборки")
return 1
@@ -33,8 +28,9 @@ def build(args: list[str] | None = None) -> int:
if active_profile not in check_dir("target"):
os.mkdir(f"./target/{active_profile}")
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]
start_time: float = time.time()
subprocess.run(
[
c_comp,
@@ -45,5 +41,8 @@ def build(args: list[str] | None = None) -> int:
],
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

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

View File

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

View File

@@ -19,6 +19,8 @@ def main() -> int:
cli.build(args)
case "run":
cli.run(args)
case "clean":
cli.clean(args)
case _:
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)