Projects & packages
Organize source files, choose a compiler version, and add dependencies.
On this page
A single file is enough for a small program. Once features need their own files, give the project a root directory and a valk.json configuration.
Create a project#
Use this directory structure:
hello/
├── valk.json
└── src/
├── main.valk
└── greetings/
└── greeting.valk
For the following example, put this in valk.json:
{
"use": "0.6.4",
"namespaces": {
"greetings": "src/greetings"
}
}
use pins a compiler version so contributors use the same toolchain. Run vman use from the project root to install or select it. The example uses 0.6.4; choose the version your project targets.
Import a namespace#
Put the greeting function in src/greetings/greeting.valk:
fn message(name: String) String {
return "Welcome, %name."
}
Then use that namespace in src/main.valk:
use greetings
fn main() {
println(greetings.message("Ada"))
}
A namespace groups the declarations in a directory. Use a dot to access one of its declarations. An import can also introduce a shorter name, such as use greetings as hello.
Build from the project root:
vman use
valk build src --run
Control what other code can access#
An unmarked declaration is available inside its package. Add + when a library should expose a declaration to other packages; add - when a helper should stay private to its source file.
+ fn public_message() String { return "Welcome" }
- fn local_message() String { return "Internal" }
A ~ marker allows other source files to read a declaration while preventing writes from those files. These markers also apply to class properties. Visibility is based on source boundaries, so - does not mean class-private.
Add a dependency#
Use vman from the project directory to manage packages:
vman install
With no package argument, this installs the dependencies in valk.json. Use vman install package-url to install a package from its URL. To remove an installed package, use its name: vman remove package-name. Browse vpkg.dev for packages and their import instructions.
Include files in the executable#
#embed reads a file at compile time and places its contents in the program. Paths are relative to valk.json:
fn main() {
let license = #embed("LICENSE.txt")
println(license)
}
#embed_dir("public") does the same recursively for a directory, returning a map from relative filenames to file contents. Rebuild after changing an embedded file. This is useful for shipping templates or web assets with a single executable.