第 13 章的项目只要一个目录就够了。一旦它依赖别处的代码,就会多一个 dawn.toml:一份
可选的清单,装目录约定说不出的东西,也就是项目的身份和它的依赖。目录结构、入口、模块路径
仍归目录管;没有这个文件的项目,行为和以前完全一样。
schema = 1 # 永远是第一个键
name = "myapp" # 项目的身份,[a-z_][a-z0-9_]*
依赖是源码包#
包本身也是一个项目,有自己的 dawn.toml 和自己的 src/。下面是一个小包 greet,
就放在 myapp 旁边:
greet/
├── dawn.toml # schema = 1, name = "greet", version = "1.0.0"
└── src/
├── hello.dawn
└── style.dawn
myapp/
├── dawn.toml
└── src/
└── main.dawn
greet/src/style.dawn:
# greet 包的每个模块都看得见,包外一概看不见
pub(pkg) fn shout(s: String) -> String = s ++ "!"
greet/src/hello.dawn:
use style.{shout}
pub fn hello(name: String) -> String = shout("hello, ${name}")
包内的模块按它在包自己的 src/ 下的路径互相引入,和第 13 章一样。dawn add 把依赖写进
myapp 的清单:
$ dawn add ../greet --dir myapp
Added greet as `greet` (path myapp/../greet)
schema = 1
name = "myapp"
[deps]
greet = "../greet"
[deps] 下的键是 myapp 对这个包的称呼:它就是 use 行的第一段。
myapp/src/main.dawn:
use greet/hello.{hello}
pub fn main() -> Unit !io = println(hello("Dawn"))
dawn run myapp 打印 hello, Dawn!。
pub(pkg):包内共享,包外不可见#
在模块私有(什么都不写)和 pub 之间还有第三级。pub(pkg) 声明对它所在包(一份
dawn.toml 描述的那个单元)的每个模块可见,对包外一概不可见。shout 是 greet 的各个
模块共用的辅助函数,myapp 够不着它:
$ dawn run myapp # main.dawn 里又加了一行:use greet/style.{shout}
error: `shout` is package-private to package `greet`
--> myapp/src/main.dawn:2:18
|
2 | use greet/style.{shout}
| ^^^^^
= hint: only modules of package `greet` may name it
pub 声明的签名里不许出现 pub(pkg) 类型,和不许模块私有类型出现在公开签名里是同一条
规则;dawn doc 也只列 pub 的条目。没有 dawn.toml 的项目是一个包,打包附带的标准库
整体也是一个包。
远程包、版本与 MVS#
路径依赖适合放在你旁边的代码。发布出来的包是某个 URL 上的一个归档,用解包后内容的哈希 钉住:
[deps.json]
url = "https://github.com/dawnop/dawn-lang/archive/refs/tags/v0.7.0.zip"
version = "1.0.0"
hash = "d1:<sha256>" # 解包后文件树的内容哈希
subdir = "packages/json" # 包在归档里的位置
这个哈希没人手算。dawn add <url> 会抓取归档、算哈希、读包自己的清单拿到名字和版本,
再把条目写进去,文件其余部分的注释和排版原样保留;--subdir 指明包在归档里的位置,
--as 换一个键。对同一个包再 add 一次会就地更新它的条目,升版本就是这么升的。
一个程序里的两个包以不同版本依赖同一个第三方包时,程序只得到它的一份:所要求的各个
最低版本里最高的那个。这就是最小版本选择(MVS),Go 用的那套算法;要求永远只是一个最低
版本,没有上界,也没有排除。对 Dawn 来说只有一份不是图省事。每个「trait × 类型」在整个
程序里恰有一个 impl(第 16 章),一个包有两份,它的每个类型就有两份,各带两个 impl。包的
身份是它自己清单里的 name,不是你给它起的键,所以一个改了名的大版本(json2)只要保留
旧键,照样可以写作 use json/...。
第三张表 [java-deps] 列的是给第 11 章 use java 用的 Maven 坐标
(sqlite = "org.xerial:sqlite-jdbc:3.36.0.3",只收精确版本)。JVM 工具链负责解析和
下载;dawnc 拒绝 use java,也就用不上它们。设计与理由见
package-design.md 和
package-visibility-design.md。
另见:spec.md §10.1、§10.4