Refactor all documentation

big ass scary commit but it's mostly we moving around docs.
main
Joca 2025-11-23 23:32:52 -03:00
parent 4347a882a2
commit b8c2099892
Signed by: jocadbz
GPG Key ID: B1836DCE2F50BDF7
17 changed files with 351 additions and 604 deletions

View File

@ -1,92 +1,29 @@
# Lana - V C++ Build System
A simple, fast C++ build tool designed for modern C++ projects.
A simple, fast C++ build tool designed for modern C++ projects. Lana compiles itself with V and targets portable C++ workflows without relying on heavyweight generators.
## Features
## Documentation
- **Automatic dependency tracking** for efficient rebuilds
- **Simple configuration** with `config.ini` files
- **Cross-platform** support
- **Clean, minimal interface**
## Installation
1. Install V: https://vlang.io/
2. Build Lana:
```bash
v . -o lana
```
3. Add to PATH or use from current directory
- 📚 **Canonical guide:** [`docs/guide.md`](docs/guide.md) now hosts the full documentation (installation, configuration, directives, troubleshooting).
- 🧩 **Reusable snippets:** Shared markdown/JSON data lives under [`docs/snippets`](docs/snippets) and [`docs/commands.json`](docs/commands.json). The CLI help output and initializer templates consume these files directly.
## Quick Start
### Initialize a new project
```bash
lana init myproject
cd myproject
```
### Build the project
```bash
lana build
```
### Run the project
```bash
lana run
```
### Clean build files
```bash
lana clean
```
See [`docs/snippets/quickstart.md`](docs/snippets/quickstart.md) for the exact commands surfaced by `lana init`, the README template, and `lana --help`.
## Project Structure
```
myproject/
├── src/ # Source files (.cpp, .cc, .cxx)
├── include/ # Header files (.h, .hpp)
├── build/ # Object files and intermediates
├── bin/ # Executable output
├── config.ini # Build configuration
├── README.md # Project documentation
└── .gitignore # Git ignore file
```
[`docs/snippets/project_structure.md`](docs/snippets/project_structure.md) is the single source for structure diagrams used across the README, guide, and generated projects.
## Commands
## Commands & Options
- `lana build` - Compile the project
- `lana run` - Build and execute
- `lana clean` - Remove build files
- `lana init <name>` - Create new project
## Configuration
Edit `config.ini` to customize your build:
```ini
# Project settings
project_name = myproject
src_dir = src
build_dir = build
bin_dir = bin
debug = true
optimize = false
verbose = false
include_dirs = include
libraries =
cflags =
ldflags =
```
## License
MIT License - see LICENSE file for details.
The CLI help text is generated from [`docs/commands.json`](docs/commands.json). Update that file to add or modify commands/options once, and every consumer (help output, initializer docs, website) stays in sync.
## Contributing
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Submit a pull request
- Fork the repository, create a feature branch, hack away, and open a PR.
- Please keep user-facing documentation changes inside `docs/` whenever possible—other surfaces will pull from there automatically.
## License
MIT License - see [LICENSE](LICENSE) for details.

1
deps/deps.v vendored
View File

@ -2,7 +2,6 @@ module deps
import os
import config
import os.cmdline
pub fn extract_dependencies(source_file string) ![]string {
mut dependencies := []string{}

View File

@ -1,5 +1,7 @@
# Lana Documentation
> This is the canonical source of project documentation. `README.md`, the CLI help text, and the project initializer templates all reference the content in this directory.
## Table of Contents
1. [Overview](#overview)
@ -57,7 +59,7 @@ Lana parses `// build-directive:` comments in your C++ files to handle project-s
chmod +x lana
```
4. Add to PATH (optional):
4. (Optional) Add to PATH:
```bash
sudo mv lana /usr/local/bin/
```
@ -82,7 +84,7 @@ project/
│ ├── tools/ # Tool executables
├── config.ini # Global build configuration
├── README.md # Project docs (auto-generated with directive examples)
└── .gitignore # Ignores build artifacts
└── .gitignore # Git ignore file
```
- **Build Directives**: Add `// build-directive:` comments at the top of C++ files for per-file settings (see [Build Directives](#build-directives)).
@ -111,8 +113,6 @@ lana build [options]
```
Compiles sources, processes directives, builds dependency graph, and links outputs. Incremental: only rebuilds changed files.
**Options:** See [Command Line Options](#command-line-options).
**Example:**
```bash
lana build -d -v # Debug build with verbose output (shows directive parsing)
@ -124,22 +124,12 @@ lana run [options]
```
Builds (if needed) and runs the main executable (first tool or `project_name` from config/directives).
**Example:**
```bash
lana run -O # Optimized run
```
### Clean Project
```bash
lana clean
```
Removes `build/`, `bin/`, and intermediates.
**Example:**
```bash
lana clean
```
### Help
```bash
lana --help
@ -160,21 +150,10 @@ Fetches and extracts external dependencies declared in `config.ini` under `[depe
- `build_cmds` - optional semicolon-separated shell commands to build/install the dependency
Notes:
- Only `name` is required. If `url` is omitted Lana will skip any download/clone and extraction steps — this is useful for dependencies that are generated locally or that only require running project-local commands.
- If `url` points to a git repository (ends with `.git`), `lana setup` will perform a shallow clone into `dependencies/<extract_to>`.
- For archive URLs `lana setup` will try `curl` then `wget` to download, will verify checksum if provided, and will extract common archive types (`.tar.gz`, `.tar.xz`, `.zip`).
- When `build_cmds` are present they are executed either inside `dependencies/<extract_to>` (if `extract_to` is set or a clone/extract was performed) or in the project root (if no extract directory is available).
- The current implementation performs a best-effort download/extract and prints warnings/errors; it is intentionally simple and can be extended or replaced by a more robust script if needed.
Example (only `name` + `build_cmds`):
```ini
[dependencies]
name = generate_headers
build_cmds = tools/gen_headers.sh; cp -r generated/include ../../include/
```
In this example `lana setup` will not try to download anything — it will run the `build_cmds` from the project root, allowing you to run arbitrary local build or generation steps.
- Only `name` is required. If `url` is omitted Lana will skip any download/clone and extraction steps — useful for dependencies generated locally or that only require running project-local commands.
- If `url` points to a git repository (ends with `.git`), `lana setup` performs a shallow clone into `dependencies/<extract_to>`.
- For archive URLs `lana setup` tries `curl` then `wget` to download, verifies checksum if provided, and extracts common archive types (`.tar.gz`, `.tar.xz`, `.zip`).
- When `build_cmds` are present they run either inside `dependencies/<extract_to>` (if available) or in the project root.
## Configuration
@ -190,7 +169,7 @@ src_dir = src
build_dir = build
bin_dir = bin
# Build modes (mutually exclusive; CLI overrides)
# Build modes (CLI overrides)
debug = true
optimize = false
@ -235,12 +214,12 @@ Lana's killer feature: Embed build instructions **directly in C++ source files**
### Supported Directives
- **`unit-name(<name>)`**: Unique unit ID (e.g., `"lib/cli"`, `"tools/mytool"`). Required for custom builds. Defaults to file path if omitted.
- **`depends-units(<unit1>,<unit2>,...)`**: Dependencies (other units, e.g., `"lib/utils,lib/file"`). Builds them first.
- **`link(<lib1>,<lib2>,...)`**: Libraries to link (e.g., `"utils.so,pthread,boost_system"`). Internal (Lana-built) or external.
- **`depends-units(<unit1>,<unit2>,...)`**: Dependencies (other units). Builds them first.
- **`link(<lib1>,<lib2>,...)`**: Libraries to link (internal or external).
- **`out(<path>)`**: Output relative to `bin/` (e.g., `"tools/mytool"`, `"lib/mylib"`). Defaults to unit name.
- **`cflags(<flag1> <flag2> ...)`**: Per-file compiler flags (e.g., `"-std=c++20 -fPIC"`). Appends to global `cflags`.
- **`ldflags(<flag1> <flag2> ...)`**: Per-file linker flags (e.g., `"-static -pthread"`). Appends to global `ldflags`.
- **`shared(<true|false>)`**: Build as shared lib (`.so`/`.dll`, true) or executable (false, default).
- **`cflags(<flag1> <flag2> ...)`**: Per-file compiler flags. Appends to global `cflags`.
- **`ldflags(<flag1> <flag2> ...)`**: Per-file linker flags.
- **`shared(<true|false>)`**: Build as shared lib (`.so`/`.dll`, true) or executable (false).
### Examples
@ -258,7 +237,6 @@ int main() {
return 0;
}
```
- Builds `bin/tools/main` executable. No deps.
**Shared Library (`src/lib/cli.cpp`)**:
```cpp
@ -276,7 +254,6 @@ namespace lana {
void print_help() { std::cout << "CLI help" << std::endl; }
}
```
- Builds `bin/lib/cli.so`. PIC for shared lib.
**Tool Depending on Shared Lib (`src/tools/mytool.cpp`)**:
```cpp
@ -296,14 +273,6 @@ int main() {
return 0;
}
```
- Depends on/builds `lib/cli` first; links `cli.so`; outputs `bin/tools/mytool`.
### Tips
- **Order**: Directives before `#include` or code.
- **Empty Values**: Use `()` for none (e.g., `depends-units()`).
- **Global Interaction**: Directives add to `config.ini` settings (e.g., global `-Wall` + per-file `-std=c++20`).
- **Assets**: Use `[dependencies]` hooks for non-C++ steps (e.g., shader compilation).
- **Legacy**: Use `[shared_libs]`/`[tools]` in config for manual lists (overrides auto-parsing).
## Build Process
@ -387,12 +356,12 @@ libraries = pthread,boost_system
cflags = -Wall -Wextra -std=c++17
ldflags = -static
[shared_libs] # Legacy/manual (directives preferred)
[shared_libs]
name = cli
sources = src/lib/cli.cpp
libraries =
[tools] # Legacy/manual
[tools]
name = main
sources = src/main.cpp
libraries = cli
@ -400,13 +369,11 @@ libraries = cli
## Troubleshooting
### Common Issues
- **"No source files found"**: Check `src_dir` in config; ensure `.cpp` files exist.
- **"Failed to parse directive"**: Verify syntax (e.g., `unit-name(lib/cli)`); use `-v` for details.
- **"Dependency not found"**: Add missing `depends-units()` or build order in directives.
- **Linking errors**: Check `link()` for libs; install dev packages (e.g., `sudo apt install libpthread-dev`).
- **Asset build fails**: Verify commands in `[dependencies]` hook scripts (e.g., shader toolchain).
- **Asset build fails**: Verify commands in `[dependencies]` hook scripts.
- **Permission denied**: `chmod +x bin/tools/mytool`.
### Debugging Tips
@ -422,10 +389,4 @@ See the source code structure in the repo. To extend:
- Add directives: Update `config.BuildDirective` and `builder.build_from_directives()`.
- New features: Modify `config.v` for parsing, `builder.v` for logic.
For contributing, see [GitHub](https://github.com/yourusername/lana) (fork, branch, PR).
---
*Documentation for Lana v1.0.0*
*Last updated: 2025-09-17*
*Issues: [Issues](https://lostcave.ddnss.de/git/jocadbz/lana)*
*Contribute: [Repo](https://lostcave.ddnss.de/git/jocadbz/lana)*
For contributing, see Gitea (fork, branch, PR).

30
docs/help.txt Normal file
View File

@ -0,0 +1,30 @@
lana - Vlang C++ Build System
Usage: lana [command] [options]
Commands:
build Compile all shared libraries and tools according to build directives.
run Build (if needed) and run the main tool (project_name or first tool).
clean Remove build artifacts under build/ and bin/.
init <name> Scaffold a new Lana-ready C++ project.
setup Fetch/build external dependencies declared in config.ini.
help Display this help text.
Global Options:
-d, --debug Enable debug mode (-g -O0).
-O, --optimize Enable optimization (-O3, disables debug).
-v, --verbose Verbose logging (graph + compiler commands).
-p, --parallel Force parallel compilation worker pool.
-o, --output <name> Override project/output name.
-I <dir> Add include directory (repeatable).
-L <dir> Add library search path (repeatable).
-l <lib> Add global link library (repeatable).
-c, --compiler <bin> Set compiler binary explicitly.
--toolchain <name> Choose toolchain adapter (gcc/clang).
--config <file> Use alternate config file.
--shared-lib <name> <source> Add legacy shared lib entry (no directives).
--tool <name> <source> Add legacy tool entry (no directives).
Docs:
Canonical Guide docs/guide.md
Project Structure docs/snippets/project_structure.md
Quick Start docs/snippets/quickstart.md

View File

@ -0,0 +1,12 @@
## Project Structure
- `src/` — Source files (.cpp, .cc, .cxx)
- `lib/` — Shared library sources (mark with `shared(true)` when needed)
- `tools/` — Tool/executable sources
- `include/` — Public headers
- `build/` — Intermediate object files and dependency dumps
- `bin/` — Final outputs
- `lib/` — Shared libraries (.so/.dll)
- `tools/` — Executables
- `config.ini` — Global build configuration
- `README.md` — Project overview (generated by Lana)
- `.gitignore` — Generated ignore file tuned for Lana projects

View File

@ -0,0 +1,18 @@
## Quick Start
1. Initialize a project:
```bash
lana init myproject
cd myproject
```
2. Build it:
```bash
lana build
```
3. Run the main tool:
```bash
lana run
```
4. Clean artifacts:
```bash
lana clean
```

15
docs/templates/cli.cpp.tpl vendored Normal file
View File

@ -0,0 +1,15 @@
// build-directive: unit-name(lib/cli)
// build-directive: depends-units()
// build-directive: link()
// build-directive: out(lib/cli)
// build-directive: shared(true)
// build-directive: cflags(-fPIC)
#include <iostream>
#include "cli.h"
namespace lana {
void print_help() {
std::cout << "Lana CLI help" << std::endl;
}
}

8
docs/templates/cli.h.tpl vendored Normal file
View File

@ -0,0 +1,8 @@
#ifndef LANA_CLI_H
#define LANA_CLI_H
namespace lana {
void print_help();
}
#endif

24
docs/templates/config.ini.tpl vendored Normal file
View File

@ -0,0 +1,24 @@
# {{project_name}} lana build configuration
[global]
project_name = {{project_name}}
src_dir = src
build_dir = build
bin_dir = bin
compiler = g++
debug = true
optimize = false
verbose = false
parallel_compilation = true
include_dirs = include
lib_search_paths =
cflags = -Wall -Wextra
ldflags =
dependencies_dir = dependencies
[shared_libs]
# legacy/manual entries go here when you don't want build directives
[tools]
# legacy/manual entries go here when you don't want build directives

13
docs/templates/example_tool.cpp.tpl vendored Normal file
View File

@ -0,0 +1,13 @@
#include <iostream>
#include "cli.h"
// build-directive: unit-name(tools/example_tool)
// build-directive: depends-units(lib/cli)
// build-directive: link(cli.so)
// build-directive: out(tools/example_tool)
int main() {
std::cout << "Tool example" << std::endl;
lana::print_help();
return 0;
}

23
docs/templates/gitignore.tpl vendored Normal file
View File

@ -0,0 +1,23 @@
# Build files
build/
bin/
*.o
*.exe
*.dSYM
*.d
*.so
*.dll
*.dylib
# IDE files
.vscode/
.idea/
*.swp
*.swo
# OS files
.DS_Store
Thumbs.db
# Dependencies
dependencies/

11
docs/templates/main.cpp.tpl vendored Normal file
View File

@ -0,0 +1,11 @@
#include <iostream>
// build-directive: unit-name(tools/main)
// build-directive: depends-units()
// build-directive: link()
// build-directive: out(tools/main)
int main() {
std::cout << "Hello, {{project_name}}!" << std::endl;
return 0;
}

13
docs/templates/readme.md.tpl vendored Normal file
View File

@ -0,0 +1,13 @@
# {{project_name}}
A C++ project built with the [Lana build system](https://github.com/lana-build/lana/blob/main/docs/guide.md).
{{quickstart}}
{{project_structure}}
## Build Directives
Lana reads build instructions directly from your source files. Add `// build-directive:` comments near the top of a translation unit to specify unit names, dependencies, and custom flags. See `docs/guide.md#build-directives` for the full catalog.
## Configuration
Global build settings live in `config.ini`. Command-line flags override config values, which override built-in defaults. Consult `docs/guide.md#configuration` for details and advanced examples.

43
docstore/docstore.v Normal file
View File

@ -0,0 +1,43 @@
module docstore
const snippet_project_structure_embedded = $embed_file('../docs/snippets/project_structure.md')
const snippet_quickstart_embedded = $embed_file('../docs/snippets/quickstart.md')
const template_main_embedded = $embed_file('../docs/templates/main.cpp.tpl')
const template_cli_embedded = $embed_file('../docs/templates/cli.cpp.tpl')
const template_example_tool_embedded = $embed_file('../docs/templates/example_tool.cpp.tpl')
const template_cli_header_embedded = $embed_file('../docs/templates/cli.h.tpl')
const template_gitignore_embedded = $embed_file('../docs/templates/gitignore.tpl')
const template_config_embedded = $embed_file('../docs/templates/config.ini.tpl')
const template_readme_embedded = $embed_file('../docs/templates/readme.md.tpl')
const guide_embedded = $embed_file('../docs/guide.md')
const help_text_embedded = $embed_file('../docs/help.txt')
pub fn snippet(name string) !string {
return match name {
'project_structure' { snippet_project_structure_embedded.to_string() }
'quickstart' { snippet_quickstart_embedded.to_string() }
else { error('snippet ${name} not found') }
}
}
pub fn template(name string) !string {
return match name {
'main.cpp.tpl' { template_main_embedded.to_string() }
'cli.cpp.tpl' { template_cli_embedded.to_string() }
'example_tool.cpp.tpl' { template_example_tool_embedded.to_string() }
'cli.h.tpl' { template_cli_header_embedded.to_string() }
'gitignore.tpl' { template_gitignore_embedded.to_string() }
'.gitignore.tpl' { template_gitignore_embedded.to_string() }
'config.ini.tpl' { template_config_embedded.to_string() }
'readme.md.tpl' { template_readme_embedded.to_string() }
else { error('template ${name} not found') }
}
}
pub fn guide() string {
return guide_embedded.to_string()
}
pub fn help_text() string {
return help_text_embedded.to_string()
}

View File

@ -1,57 +1,7 @@
module help
import docstore
pub fn show_help() {
println('lana - Vlang C++ Build System')
println('Usage: lana [command] [options]')
println('')
println('Commands:')
println(' build Build the project (shared libs + tools)')
println(' clean Clean build files')
println(' run Build and run the main tool')
println(' init <name> Initialize new project')
println('')
println('Options:')
println(' -d, --debug Enable debug mode')
println(' -O, --optimize Enable optimization')
println(' -v, --verbose Verbose output')
println(' -p, --parallel Enable parallel compilation')
println(' -o, --output Set output name')
println(' -I <dir> Add include directory')
println(' -l <lib> Add library')
println(' --config <file> Use config file')
println(' --shared-lib <name> <source> Add shared library')
println(' --tool <name> <source> Add tool/executable')
println('')
println('Configuration File (config.ini):')
println(' [global]')
println(' project_name = myproject')
println(' src_dir = src')
println(' debug = true')
println(' ')
println(' [shared_libs]')
println(' name = net')
println(' sources = src/lib/net/connection.cpp')
println(' libraries = cli')
println(' ')
println(' [tools]')
println(' name = dumpnbt')
println(' sources = src/tools/dumpnbt.cpp')
println(' libraries = nbt,cli')
println('')
println('Examples:')
println(' lana build -d -v -p')
println(' lana run')
println(' lana build --shared-lib cli src/lib/cli.cpp --tool dumpnbt src/tools/dumpnbt.cpp')
println(' lana init myproject')
println('')
println('Project Structure:')
println(' src/ - Source files (.cpp, .cc, .cxx)')
println(' lib/ - Shared library sources')
println(' tools/ - Tool/executable sources')
println(' include/ - Header files (.h, .hpp)')
println(' build/ - Object files and intermediates')
println(' bin/ - Output')
println(' lib/ - Shared libraries (.so/.dll)')
println(' tools/ - Executables')
println(' config.ini - Build configuration')
print(docstore.help_text())
}

View File

@ -1,11 +1,20 @@
module initializer
import os
import docstore
fn render_template(template string, replacements map[string]string) string {
mut output := template
for key, value in replacements {
placeholder := '{{${key}}}'
output = output.replace(placeholder, value)
}
return output
}
pub fn init_project(project_name string) {
println('Initializing C++ project: ${project_name}')
// Create directory structure
dirs := [
'src',
'src/lib',
@ -16,7 +25,7 @@ pub fn init_project(project_name string) {
'build',
'bin',
'bin/lib',
'bin/tools'
'bin/tools',
]
for dir in dirs {
full_path := os.join_path(project_name, dir)
@ -25,370 +34,47 @@ pub fn init_project(project_name string) {
}
}
// Create basic main.cpp with build directives
main_content := r'
#include <iostream>
// build-directive: unit-name(tools/main)
// build-directive: depends-units()
// build-directive: link()
// build-directive: out(tools/main)
int main() {
std::cout << "Hello, ${project_name}!" << std::endl;
return 0;
}
'
os.write_file(os.join_path(project_name, 'src', 'main.cpp'), main_content) or { }
// Create example shared library with build directives
cli_content := r'
// build-directive: unit-name(lib/cli)
// build-directive: depends-units()
// build-directive: link()
// build-directive: out(lib/cli)
// build-directive: shared(true)
#include <iostream>
namespace lana {
void print_help() {
std::cout << "Lana CLI help" << std::endl;
replacements := {
'project_name': project_name
}
}
'
os.write_file(os.join_path(project_name, 'src/lib', 'cli.cpp'), cli_content) or { }
// Create example tool with build directives
tool_content := r'
#include <iostream>
// build-directive: unit-name(tools/example_tool)
// build-directive: depends-units(lib/cli)
// build-directive: link(cli.so)
// build-directive: out(tools/example_tool)
quickstart := docstore.snippet('quickstart') or { 'See docs/snippets/quickstart.md in the Lana repo.' }
structure := docstore.snippet('project_structure') or { 'See docs/snippets/project_structure.md in the Lana repo.' }
int main() {
std::cout << "Tool example" << std::endl;
lana::print_help();
return 0;
}
'
os.write_file(os.join_path(project_name, 'src/tools', 'example_tool.cpp'), tool_content) or { }
write_template(project_name, 'src/main.cpp', 'main.cpp.tpl', replacements)
write_template(project_name, 'src/lib/cli.cpp', 'cli.cpp.tpl', replacements)
write_template(project_name, 'src/tools/example_tool.cpp', 'example_tool.cpp.tpl', replacements)
write_template(project_name, '.gitignore', 'gitignore.tpl', replacements)
write_template(project_name, 'config.ini', 'config.ini.tpl', replacements)
// Create .gitignore
gitignore_content := r'
# Build files
build/
bin/
*.o
*.exe
*.dSYM
*.d
*.so
*.dll
*.dylib
mut readme_map := replacements.clone()
readme_map['quickstart'] = quickstart.trim_space()
readme_map['project_structure'] = structure.trim_space()
write_template_with_map(project_name, 'README.md', 'readme.md.tpl', readme_map)
# IDE files
.vscode/
.idea/
*.swp
*.swo
# OS files
.DS_Store
Thumbs.db
# Dependencies
dependencies/
'
os.write_file(os.join_path(project_name, '.gitignore'), gitignore_content) or { }
// Create config.ini with build directive support
config_content := r'
# ${project_name} lana build configuration
[global]
project_name = ${project_name}
src_dir = src
build_dir = build
bin_dir = bin
compiler = g++
debug = true
optimize = false
verbose = false
parallel_compilation = true
include_dirs = include
lib_search_paths =
cflags = -Wall -Wextra
ldflags =
# Build directives will be automatically parsed from source files
# using // build-directive: comments
[shared_libs]
# These are for legacy support or manual configuration
# Most shared libraries should use build directives in source files
[tools]
# These are for legacy support or manual configuration
# Most tools should use build directives in source files
'
os.write_file(os.join_path(project_name, 'config.ini'), config_content) or { }
// Create README.md with build directive documentation
readme_content := r'
# ${project_name}
A C++ project built with lana (Vlang C++ Build System)
## Getting Started
### Build the project
```bash
lana build
```
### Run the main executable
```bash
lana run
```
### Run a specific tool
```bash
./bin/tools/example_tool
```
### Clean build files
```bash
lana clean
```
## Project Structure
- `src/` - Source files (.cpp, .cc, .cxx)
- `lib/` - Shared library sources
- `tools/` - Tool/executable sources
- `include/` - Header files (.h, .hpp)
- `build/` - Object files and intermediate build files
- `bin/` - Executable output
- `lib/` - Shared libraries (.so/.dll)
- `tools/` - Tool executables
- `config.ini` - Build configuration
## Build Directives
Lana reads build instructions directly from source files using special comments:
```
// build-directive: unit-name(tools/arraydump)
// build-directive: depends-units(lib/file,lib/cli)
// build-directive: link(file.so,cli.so)
// build-directive: out(tools/arraydump)
// build-directive: cflags(-Wall -Wextra)
// build-directive: ldflags()
// build-directive: shared(true)
```
### Directive Types
- **unit-name**: Name of the build unit (e.g., "tools/arraydump", "lib/file")
- **depends-units**: Dependencies for this unit (other units or libraries)
- **link**: Libraries to link against (e.g., "file.so", "cli.so")
- **out**: Output path for the binary (relative to bin/)
- **cflags**: Additional CFLAGS for this file
- **ldflags**: Additional LDFLAGS for this file
- **shared**: Whether this is a shared library (true/false)
### Example Source File
```cpp
// build-directive: unit-name(tools/dumpnbt)
// build-directive: depends-units(lib/nbt,lib/cli)
// build-directive: link(nbt.so,cli.so)
// build-directive: out(tools/dumpnbt)
// build-directive: cflags()
// build-directive: ldflags()
// build-directive: shared(false)
#include <iostream>
#include "nbt.h"
#include "cli.h"
int main() {
// Your code here
return 0;
}
```
## Configuration
Edit `config.ini` to customize global build settings:
### Global Settings
```ini
[global]
project_name = myproject
compiler = g++
debug = true
optimize = false
verbose = false
parallel_compilation = true
include_dirs = include,external/lib/include
lib_search_paths = /usr/local/lib,external/lib
cflags = -Wall -Wextra -std=c++17
ldflags = -pthread
```
### Shared Libraries (Legacy)
```ini
[shared_libs]
name = cli
sources = src/lib/cli.cpp
libraries =
include_dirs = include
cflags =
ldflags =
```
### Tools (Legacy)
```ini
[tools]
name = main
sources = src/main.cpp
libraries = cli
name = example_tool
sources = src/tools/example_tool.cpp
libraries = cli
```
## Command Line Options
```bash
lana build [options]
-d, --debug Enable debug mode
-O, --optimize Enable optimization
-v, --verbose Verbose output
-p, --parallel Parallel compilation
-c, --compiler <name> Set C++ compiler (default: g++)
-o <name> Set project name
-I <dir> Add include directory
-L <dir> Add library search path
-l <lib> Add global library
--config <file> Use custom config file
--shared-lib <name> <source> Add shared library (legacy)
--tool <name> <source> Add tool (legacy)
```
## Build Process
1. **Parse build directives** from source files
2. **Build dependency graph** based on unit dependencies
3. **Compile source files** to object files
4. **Link libraries and executables** according to directives
5. **Execute dependency hooks** declared under `[dependencies]` (ideal for assets like shaders)
The build system automatically handles:
- Dependency resolution and build ordering
- Incremental builds (only rebuild changed files)
- Shared library vs executable detection
- Custom flags per file
- Parallel compilation
## Examples
### Simple Tool
```cpp
// build-directive: unit-name(tools/calculator)
// build-directive: depends-units()
// build-directive: link()
// build-directive: out(tools/calculator)
#include <iostream>
int main() {
int a, b;
std::cin >> a >> b;
std::cout << "Sum: " << a + b << std::endl;
return 0;
}
```
### Shared Library with Dependencies
```cpp
// build-directive: unit-name(lib/math)
// build-directive: depends-units(lib/utils)
// build-directive: link(utils.so)
// build-directive: out(lib/math)
// build-directive: shared(true)
// build-directive: cflags(-fPIC)
#include "utils.h"
namespace math {
double add(double a, double b) {
return a + b;
}
}
```
### Complex Tool with Multiple Dependencies
```cpp
// build-directive: unit-name(tools/game)
// build-directive: depends-units(lib/graphics,lib/audio,lib/input)
// build-directive: link(graphics.so,audio.so,input.so,glfw,SDL2)
// build-directive: out(tools/game)
// build-directive: cflags(-DDEBUG)
// build-directive: ldflags(-pthread)
#include "graphics.h"
#include "audio.h"
#include "input.h"
int main() {
// Game loop
return 0;
}
```
## License
MIT License - see LICENSE file for details.
## Contributing
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Submit a pull request
'
os.write_file(os.join_path(project_name, 'README.md'), readme_content) or { }
// Create example header
header_content := r'
#ifndef LANA_CLI_H
#define LANA_CLI_H
namespace lana {
void print_help();
}
#endif
'
os.write_file(os.join_path(project_name, 'include', 'cli.h'), header_content) or { }
write_template(project_name, 'include/cli.h', 'cli.h.tpl', replacements)
println('Project initialized successfully!')
println('Created directory structure and template files')
println('')
println('Usage:')
println('\nNext steps:')
println(' cd ${project_name}')
println(' lana build')
println(' lana run')
println(' ./bin/tools/example_tool')
println('')
println('Build Directives:')
println(' Add // build-directive: comments to your source files')
println(' See README.md for examples and documentation')
println('Configuration:')
println(' Edit config.ini for global build settings')
println(' Add your C++ source files to src/lib/ and src/tools/')
println(' Use [dependencies] entries for extra asset steps (e.g., shader compilation)')
println('\nDocs and templates originate from docs/ in the Lana repo. Update them once to affect README/help/init output everywhere.')
}
fn write_template(root string, relative_path string, template_name string, replacements map[string]string) {
write_template_with_map(root, relative_path, template_name, replacements)
}
fn write_template_with_map(root string, relative_path string, template_name string, replacements map[string]string) {
content := docstore.template(template_name) or {
println('Warning: template ${template_name} missing (${err})')
return
}
rendered := render_template(content, replacements)
os.write_file(os.join_path(root, relative_path), rendered) or {
println('Warning: failed to write ${relative_path}: ${err}')
}
}

112
lana.v
View File

@ -8,68 +8,72 @@ import initializer
import deps
import help
const (
// For runner compatibility
bin_dir = 'bin'
tools_dir = 'bin/tools'
)
// For runner compatibility
const bin_dir = 'bin'
const tools_dir = 'bin/tools'
fn main() {
mut config_data := config.parse_args() or { config.default_config }
mut config_data := config.parse_args() or { config.default_config }
if os.args.len < 2 {
help.show_help()
return
}
if os.args.len < 2 {
help.show_help()
return
}
match os.args[1] {
'build' {
builder.build(mut config_data) or {
eprintln('Build failed: ${err}')
exit(1)
}
}
'clean' { builder.clean(config_data) }
'run' {
// For run, try to build first, then run the main tool
builder.build(mut config_data) or {
eprintln('Build failed: ${err}')
exit(1)
}
match os.args[1] {
'build' {
builder.build(mut config_data) or {
eprintln('Build failed: ${err}')
exit(1)
}
}
'clean' {
builder.clean(config_data)
}
'run' {
// For run, try to build first, then run the main tool
builder.build(mut config_data) or {
eprintln('Build failed: ${err}')
exit(1)
}
// Find and run the main executable (first tool or project_name)
main_executable := get_main_executable(config_data)
if main_executable != '' && os.is_file(main_executable) {
runner.run_executable(config_data)
} else {
println('No main executable found to run')
}
}
'init' { initializer.init_project(os.args[2] or { 'myproject' }) }
'setup' {
deps.fetch_dependencies(config_data) or {
eprintln('Failed to fetch dependencies: ${err}')
exit(1)
}
}
else { help.show_help() }
}
// Find and run the main executable (first tool or project_name)
main_executable := get_main_executable(config_data)
if main_executable != '' && os.is_file(main_executable) {
runner.run_executable(config_data)
} else {
println('No main executable found to run')
}
}
'init' {
initializer.init_project(os.args[2] or { 'myproject' })
}
'setup' {
deps.fetch_dependencies(config_data) or {
eprintln('Failed to fetch dependencies: ${err}')
exit(1)
}
}
else {
help.show_help()
}
}
}
fn get_main_executable(build_config config.BuildConfig) string {
// First try to find a tool with the project name
for tool_config in build_config.tools {
if tool_config.name == build_config.project_name {
return os.join_path(tool_config.output_dir, tool_config.name)
}
}
// First try to find a tool with the project name
for tool_config in build_config.tools {
if tool_config.name == build_config.project_name {
return os.join_path(tool_config.output_dir, tool_config.name)
}
}
// Then try the first tool
if build_config.tools.len > 0 {
tool_config := build_config.tools[0]
return os.join_path(tool_config.output_dir, tool_config.name)
}
// Then try the first tool
if build_config.tools.len > 0 {
tool_config := build_config.tools[0]
return os.join_path(tool_config.output_dir, tool_config.name)
}
// Fallback to old behavior
return os.join_path(build_config.bin_dir, build_config.project_name)
// Fallback to old behavior
return os.join_path(build_config.bin_dir, build_config.project_name)
}