项目的环境配置一般由项目文件和清单文件Manifest.toml体现。全局环境配置针对的是 REPL 环境中的代码和独立的 Julia 程序。该环境配置的文件通常会在~/.julia/environments目录的特性版本子目录(如v1.3)中。

    我们已经学会了在全局环境中怎样安装和导入程序包。这对于编写和部署一些脚本程序来说已经足够了。不过,我们在正式开发 Julia 项目的时候往往还需要专属的环境配置文件。这样才能与全局环境区别开。这么做有 3 个好处:

    1. 一旦有了专属的环境配置文件,我们的项目就可以独立地管理依赖包了。
    2. 针对某个 Julia 项目的程序包管理操作不会影响到全局的环境配置。反之亦然。
    3. 拥有环境配置文件的 Julia 项目可以为项目的分发(以供他人使用)做好准备。

    换句话说,我们的 Julia 项目可以因此成为独立的、可重用的以及对分发友好的项目。

    创建一个 Julia 项目很容易,在 REPL 环境中就可以办到。我们先在命令行中通过输入julia命令进入到 REPL 环境。然后,我们在它的 shell 模式中进入某个专用的目录(比如~/Projects),就像这样:

    这时,我们可以再确认一下当前的目录:

    1. julia> pwd()
    2. "/Users/haolin/Projects"
    3. julia>

    这里的pwd是 Print Working Directory 的缩写。所以,pwd函数的含义就是打印当前的工作目录。这与在命令行中输入pwd命令的作用是类似的。只不过调用表达式pwd()的求值结果是一个字符串。

    在确认了工作目录之后,我们就可以切换到 REPL 环境的 pkg 模式,然后输入generate命令,并后跟一个空格和项目的名称Programs(你也可以用别的名字):

    1. (v1.3) pkg> generate Programs
    2. Generating project Programs:
    3. Programs/Project.toml
    4. Programs/src/Programs.jl
    5. (v1.3) pkg>

    我们先来看项目文件,它的内容如下:

    这里有 4 个条目,分别代表项目的名称、UUID、作者信息和初始版本号。其中的 UUID 是 Julia 的程序包管理器自动生成的。而项目作者信息是从当前操作系统中的 Git 配置信息复制过来的。

    我们再来看源码文件Programs.jl的内容:

    1. greet() = print("Hello World!")
    2. end # module

    其中只定义了一个名为Programs的模块。并且,该模块仅包含了一个可以向计算机的标准输出打印Hello World!的函数greet。这显然只是一个简单的程序模板。不过,它为我们后续的编码开了个头。

    注意,这个源码文件是有重要意义的:

    1. 该文件可以被称为Programs项目的源码入口。或者说,它是这个项目的主源码文件。这是由于该文件的主文件名与项目的(主)名称是一致的。
    2. 该文件中定义的(最外层的)模块Programs将会是其所属项目的主模块(或者说默认模块)。这是由于该模块的名称与项目的(主)名称是一致的。

    正因为有了这样的一个源码文件,使得Programs项目可以被 Julia 视为一个程序包。更明确地讲,如果存在一个名为XX.jl的 Julia 项目,只要该项目包含一个相对路径为src/X.jl的源码文件,并且在该文件中定义的最外层模块名为X,那么它就是一个有效的程序包。

    最后,一个可选的操作是,我们可以把这个项目的名称变更为Programs.jl。如此可以让它更具 Julia 项目的特色。由前述内容可知,这样做并不会妨碍此项目成为一个有效的程序包。注意,项目Programs.jl所代表的程序包的名称依然是Programs,同时它的主模块的名称也依然是Programs

    2.3.2 程序包的引入

    当我们试图在全局环境中导入该程序包的时候,Julia 会提示找不到这个程序包:

    1. julia> import Programs
    2. ERROR: ArgumentError: Package Programs not found in current path:
    3. - Run `import Pkg; Pkg.add("Programs")` to install the Programs package.
    4. Stacktrace:
    5. [1] require(::Module, ::Symbol) at ./loading.jl:887
    6. julia>

    为了解决这个问题,我们可以先在 REPL 环境下进入到Programs.jl项目所在的目录,然后切换到 pkg 模式,并输入命令activate .。注意,这里的输入是activate加一个空格`,再加一个英文点号.`。示例如下:

    我们可以看到,在使用activate命令之后,REPL 环境的提示符再次改变了,变成了当前程序包的名称,也就是在当前目录下的Project.toml文件中记录的那个名称。命令activate .的作用正是把程序包管理器的操作目录切换到当前项目所在的目录,即:~/Projects/Programs.jl。还记得吗?它原先的(或者说默认的)操作目录是~/.julia/environments/v1.3,对应于 Julia 的v1.3版本的全局环境。顺便说一下,如果你想切换回全局环境,那么只需要再次输入命令activate(不加任何参数)就可以了。

    在这之后,我们再在当前的 REPL 环境中导入Programs就不会有问题了:

    1. julia> import Programs
    2. julia> Programs.greet()
    3. Hello World!

    如果我们确实需要在全局环境中引入Programs,那么可以先把这个项目上传到一个代码托管仓库(比如 GitHub)中,然后再使用 Julia 的程序包管理器把它安装到本地的仓库目录。

    比如,我们的这个Programs.jl项目已经在 GitHub 上了,它的 git 地址是git@github.com:hyper0x/Programs.jl.git。所以,我们现在就可以直接在 REPL 环境中进行如下操作:

    1. (Programs) pkg> activate
    2. (v1.3) pkg> add git@github.com:hyper0x/Programs.jl.git
    3. Updating registry at `~/.julia/registries/General`
    4. Updating git-repo `https://github.com/JuliaRegistries/General.git`
    5. Cloning git-repo `git@github.com:hyper0x/Programs.jl.git`
    6. Updating git-repo `git@github.com:hyper0x/Programs.jl.git`
    7. Resolving package versions...
    8. Updating `~/.julia/environments/v1.3/Project.toml`
    9. [d2b7efac] + Programs v0.1.0 #master (git@github.com:hyper0x/Programs.jl.git)
    10. Updating `~/.julia/environments/v1.3/Manifest.toml`
    11. [d2b7efac] + Programs v0.1.0 #master (git@github.com:hyper0x/Programs.jl.git)
    12. (v1.3) pkg>

    一旦Programs程序包被记录在了全局环境的项目文件中,我们在该环境下引入它也就不会有问题了。