Módulos e pacotes
Até agora, todos os exemplos cabiam em um único arquivo. Bases de código reais crescem rapidamente além disso. Este capítulo contém tudo o que você precisa para organizar código Glide em qualquer escala — de um "CLI pequeno" a um "serviço com cinco bibliotecas".
Módulos: um arquivo, um namespace
Em Glide, um arquivo é um módulo. O nome do módulo vem do caminho dentro de src/ com o .glide removido:
hello/
glide.glide
src/
main.glide ← módulo: main
storage/
sqlite.glide ← módulo: storage::sqlite
memory.glide ← módulo: storage::memory
Para usar algo definido em outro módulo, importe-o:
import storage::sqlite::*; // traz tudo que é pub desse arquivo
import storage::memory::*;
Leia o caminho usando :: como separador. O ::* no final significa "traga todos os itens públicos para o escopo, para que eu possa usá-los pelo nome curto".
Público vs privado
Por padrão, tudo que é definido em um módulo é privado — visível apenas dentro daquele arquivo. Para exportar, use o prefixo pub:
pub struct Db {
handle: *void,
}
pub fn open(path: string) -> !Db {
// ...
}
fn _internal_helper() -> i32 {
// sem pub: permanece privado a este arquivo
return 0;
}
A partir de main.glide:
import storage::sqlite::*;
fn main() -> i32 {
let r: !Db = open("data.db"); // funciona — open é pub
return 0;
}
Formas diferentes de importar
// Importa tudo que é pub de um módulo:
import storage::sqlite::*;
// Importa o módulo pelo nome curto, acessa as coisas de forma qualificada:
import storage::sqlite; // depois: sqlite::open("data.db")
// Importa apenas um item pelo nome:
import storage::sqlite::{open};
A forma com * é a mais comum. A forma com nome qualificado é útil para resolver colisões quando dois módulos definem o mesmo nome.
O manifesto glide.glide
Todo projeto tem um manifesto na raiz. Não é um arquivo de configuração — é um valor Glide:
let manifest: Package = Package {
name: "myapp",
version: "0.1.0",
description: "Example application",
author: "Your Name",
license: "MIT",
repository: "https://github.com/you/myapp",
bin: "src/main.glide", // ponto de entrada
deps: vec_of(
Dep::git("discord_lib", "https://github.com/you/discord-lib", "v0.1.0"),
Dep::path("local_lib", "../local-lib"),
),
};
O CLI lê os campos literalmente. Os mais importantes:
- `name` — o nome do pacote. Deve coincidir com o nome do diretório e com o nome do arquivo de entrada da biblioteca (mais sobre isso abaixo).
- `version` — incrementado manualmente a cada release; consumidores fixam uma revisão específica em vez dessa versão.
- `bin` — o arquivo-fonte que contém
fn main(). Para um pacote de biblioteca, defina como"". - `deps` — uma lista
vec_of(...)de valoresDep. Dois tipos:Dep::git(name, url, rev)eDep::path(name, local_path).
Adicionando uma dependência
Você pode editar glide.glide manualmente ou usar o CLI:
glide add discord_lib github.com/you/discord-lib v0.1.0
Isso acrescenta a dependência ao seu manifesto. Em seguida, baixe-a:
glide fetch
glide fetch puxa cada dependência para um cache endereçado por conteúdo (~/.glide/cache/<sha256>) e cria um link simbólico em glide_modules/<dep-name> apontando para ela. Você commita seu glide.glide e glide.lock no git; você não commita glide_modules/ (o script de instalação o regenera).
Use a dependência importando o nome do pacote:
import discord_lib::*;
// ou, se os símbolos estão em submódulos:
import discord_lib::gateway::*;
import discord_lib::rest::*;
Publicando uma biblioteca
Quer que outros dependam do seu código? Três passos:
- Estrutura: crie o diretório com este layout (use
glide new mylib --lib):
mylib/
glide.glide # name: "mylib", bin: ""
src/
mylib.glide # ponto de entrada — mesmo nome do pacote
# ... mais arquivos aqui, importáveis como mylib::other_file
O nome do arquivo de entrada deve coincidir com o nome do pacote. É assim que import mylib; encontra o arquivo correto.
- Publicar: envie para o GitHub e crie uma tag de versão:
git tag v0.1.0
git push origin v0.1.0
- Consumir: qualquer pessoa pode agora adicionar sua biblioteca:
glide add mylib github.com/you/mylib v0.1.0
glide fetch
Compilando para produção
Quando estiver pronto para distribuir, glide build --release gera o binário otimizado:
glide build --release
# → ./build/myapp (ou myapp.exe no Windows)
Esse binário é autossuficiente: não precisa do Glide instalado na máquina de destino. Copie-o para o seu servidor, execute-o, pronto.
Para compilar para outro sistema operacional sem sair da sua máquina:
glide build --release --target=x86_64-linux-gnu # Linux
glide build --release --target=aarch64-apple-darwin # macOS ARM
glide build --release --target=x86_64-windows-gnu # Windows
O zig cc embutido cuida da compilação cruzada — nenhum toolchain adicional precisa ser instalado.
Lendo a árvore de dependências
glide.lock registra a revisão exata (SHA do commit + hash do conteúdo) de cada dependência que você baixou, de modo que um clone novo resolva para o mesmo código. Commite-o no git assim como package-lock.json ou Cargo.lock.
Inspecione o que realmente foi baixado:
ls glide_modules/ # dependências de nível superior
ls glide_modules/<dep> # código-fonte de uma dependência
glide_modules/ é uma lista plana de links simbólicos para o cache endereçado por conteúdo. Dois projetos que dependem da mesma revisão da mesma biblioteca compartilham uma única cópia no disco.
Um layout realista de projeto
Como um serviço HTTP fica depois de alguns milhares de linhas:
myservice/
glide.glide # name, version, deps
glide.lock
src/
main.glide # fn main() — conecta tudo
config.glide # parsing de env, validação
handlers/
health.glide
users.glide
posts.glide
storage/
pool.glide # pool de conexões
queries.glide # SQL
middleware/
auth.glide
logging.glide
book/ # este site, talvez
static/
tests/
glide_modules/ # não commitado; populado por glide fetch
sqlite/
redis/
auth_jwt/
build/ # não commitado; saída de glide build
Dentro de main.glide você veria:
import handlers::health::*;
import handlers::users::*;
import handlers::posts::*;
import middleware::auth::*;
import middleware::logging::*;
import sqlite::*;
fn main() -> i32 {
// ... configura rotas, inicia servidor
return 0;
}
Recap
O que vem a seguir
Esse é o núcleo da linguagem e suas ferramentas. Os capítulos seguintes colocam tudo em prática: o próximo — Um tour pela biblioteca padrão — percorre as baterias que o Glide oferece, as APIs que você vai usar no dia a dia.
Depois disso: construindo um servidor HTTP, testes e benchmarks, e FFI e escotilhas de escape.