**IAIC**
Paquetes y Entornos en Julia
Cuando empieces a usar Julia, entrarás rápidamente en contacto con Pkg.jl, su gestor de paquetes. Es razonablemente fácil instalar unos pocos paquetes y empezar a usar Julia. Pero leyendo preguntas en Slack y Discourse, muchos usuarios sólo empiezan a entender relativamente tarde lo que hacen comandos como `instantiate`. Este post debería enseñarte cómo puedes ir más allá de un entorno global desordenado y hacia versiones locales bien empaquetadas que te permitan colaborar más eficazmente y hacer que tus resultados sean reproducibles.
## Empezando
Cuando instalas Julia por primera vez, no hay entornos. Digamos que has instalado Julia 1.8. Cuando inicies la REPL con el comando `julia`, verás el prompt estándar
```terminal
julia>
```
Desde ahí, se accede al modo REPL de Pkg.jl tecleando `]`. El prompt cambiará para indicarlo, mostrando el nombre del entorno activo:
```terminal
(@v1.8) pkg>
```
Pero espera, ¿no acabo de decir que todavía no hay entornos? Es cierto, no debería haber ningún archivo de entorno en tu ordenador. Puedes comprobar la carpeta `.julia/environments`, debería estar vacía. Esta carpeta contiene todos tus entornos "compartidos". Puedes decir que un entorno es compartido por el carácter `@` en el prompt del paquete REPL, en nuestro caso `@v1.8` porque usamos Julia 1.8.
(Ten en cuenta que si ya tienes una carpeta llamada `v1.8`, o cualquier versión de Julia que estés usando, puedes simplemente renombrarla a `v1.8_deactivated` o algo así y reiniciar Julia para los propósitos de este tutorial).
Si se activa un nuevo entorno, esto todavía no crea ningún archivo, y es por eso que no tenemos ningún archivo en `.julia/environments`, todavía. Sólo aparecen una vez que realmente haces algo con tu entorno.
Podemos probar esto rápidamente. Activa un nuevo entorno escribiendo `(@v1.8) pkg> activate MyEnvironment`. No verás que se crea ningún fichero nuevo en tu directorio de trabajo, como he dicho esto sólo ocurre una vez que manipulas un entorno. Pero el prompt habrá cambiado:
```terminal
(@v1.8) pkg> activate MyEnvironment
Activating new project at `~/MyEnvironment`
(MyEnvironment) pkg>
```
Volvamos al entorno "principal" `@v1.8` por ahora.
El propósito de los entornos compartidos es que puedas activarlos fácilmente desde cualquier directorio de trabajo porque empiezan por `@`, y Pkg sabe que debe buscarlos en `.julia/environments`. Para todos los demás entornos, puedes activarlos por su nombre si te encuentras en el directorio donde se crearon, o tienes que especificar la ruta completa.
Así que activamos de nuevo `@v1.8` tecleando:
```terminal
(MyEnvironment) pkg> activate @v1.8
Activating new project at `~/.julia/environments/v1.8`
(@v1.8) pkg>
```
Como ves, Pkg nos dijo que estábamos activando un nuevo proyecto (otra palabra para entorno), porque como vimos antes, ningún fichero existía realmente, todavía.
Hay otro atajo para activar el entorno principal, que es `activate` sin argumento:
```terminal
(@v1.8) pkg> activate
Activating new project at `~/.julia/environments/v1.8`
(@v1.8) pkg>
```
## Añadir un paquete
Vamos a añadir nuestro primer paquete a nuestro entorno compartido `@v1.8`. Para esto, usamos el comando `add`. Elijo el paquete `MacroTools` porque tiene pocas dependencias.
```terminal
(@v1.8) pkg> add MacroTools
Updating registry at `~/.julia/registries/General.toml`
Resolving package versions...
Updating `~/.julia/environments/v1.8/Project.toml`
[1914dd2f] + MacroTools v0.5.9
Updating `~/.julia/environments/v1.8/Manifest.toml`
[1914dd2f] + MacroTools v0.5.9
[2a0f44e3] + Base64
[d6f4376e] + Markdown
[9a3f8284] + Random
[ea8e919c] + SHA v0.7.0
[9e88b42a] + Serialization
```
Como probablemente sabrás, después de hacer esto, el código de `MacroTools` se habrá descargado en tu sistema y podrás utilizarlo en tu propio código:
```terminal
julia> using MacroTools
```
¿Qué ocurrió realmente cuando ejecutamos el comando `add`?
En la primera línea, puedes ver que se ha actualizado el registro general. El registro general ([https://github.com/JuliaRegistries/General](https://github.com/JuliaRegistries/General)) es una lista de paquetes de terceros que están disponibles al público, donde cada paquete lista todas sus dependencias y versiones. Puede haber otros registros, incluso privados, pero el registro general es el principal y el único relevante para la mayoría de los usuarios.
Pkg ha actualizado por primera vez esta lista en nuestro ordenador cuando ejecutamos `add MacroTools` para que conozca las versiones más recientes de todos los paquetes del ecosistema. Puedes echarle un vistazo en `.julia/registries/` si quieres.
Después de actualizar el registro, Pkg está `Resolviendo versiones de paquetes`. Primero, la última versión de `MacroTools` en el momento de escribir esto, `v0.5.9`, fue añadida a `~/.julia/environments/v1.8/Project.toml`. Así que en este momento, finalmente se está creando el archivo de entorno del que hablaba antes.
Podemos ver el contenido de `Project.toml`:
```toml
[deps]
MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
```
Así que esto sólo dice que nuestro entorno tiene una dependencia declarada, que es `MacroTools.jl`. La cadena UUID `1914dd2f-81c6...` está ahí porque ese es el identificador único *real* del paquete porque, por ejemplo, si otro hipotético registro tuviera un `MacroTools` diferente, entonces al menos podrías especificar el que realmente quieres a través del UUID.
Pkg también actualizó el archivo `~/.julia/environments/v1.8/Manifest.toml`. Echemos un vistazo a este:
```toml
# This file is machine-generated - editing it directly is not advised
julia_version = "1.8.0-rc3"
manifest_format = "2.0"
project_hash = "e39ab6d265da4acedccb7411db33219b8d7db4fc"
[[deps.Base64]]
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
[[deps.MacroTools]]
deps = ["Markdown", "Random"]
git-tree-sha1 = "3d3e902b31198a27340d0bf00d6ac452866021cf"
uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
version = "0.5.9"
[[deps.Markdown]]
deps = ["Base64"]
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"
[[deps.Random]]
deps = ["SHA", "Serialization"]
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
[[deps.SHA]]
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"
version = "0.7.0"
[[deps.Serialization]]
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
```
El `Manifest.toml` lista todos los paquetes que se instalaron, mientras que el `Project.toml` sólo lista la dependencia `MacroTools`.
Puedes pensar en los dos archivos de esta manera:
- `Project.toml`: Lo que quieres.
- `Manifest.toml`: Lo que obtienes.
El `Project.toml` es siempre el primer fichero que se edita cuando se hacen cambios en el entorno, ya sea a través del Pkg REPL o manualmente. El `Manifest.toml` es entonces el resultado de un cálculo que intenta encontrar versiones compatibles de todos los paquetes especificados en el `Project.toml` y sus dependencias. Ten en cuenta que `Project.toml` puede en principio especificar demandas imposibles, como dos paquetes que requieren dependencias incompatibles. Un `Manifest.toml` sin embargo debe estar siempre en un estado válido, si no se puede resolver una configuración válida de dependencias de paquetes, simplemente obtendrá un error.
Podemos ver el grafo de dependencias que Pkg resolvió en el `Manifest.toml`, si nos fijamos en los campos `deps`:
```{dot}
digraph G {
MacroTools -> Markdown
MacroTools -> Random
Markdown -> Base64
Random -> SHA
Random -> Serialization
MacroTools [label="MacroTools v0.5.9", style=filled, fillcolor="slategray2"]
SHA [label="SHA v0.7.0", style=filled, fillcolor="tomato"]
Markdown [style=filled, fillcolor="tomato"]
Random [style=filled, fillcolor="tomato"]
Serialization [style=filled, fillcolor="tomato"]
Base64 [style=filled, fillcolor="tomato"]
}
```
El nodo azul se refiere al paquete externo `MacroTools`, que tiene una versión. Los nodos rojos son bibliotecas estándar. Las bibliotecas estándar se envían con Julia, por lo que normalmente no tienen su propia versión y sólo cambian con cada versión de Julia. Puedes ver todas las bibliotecas estándar en el [repositorio de Julia en GitHub](https://github.com/JuliaLang/julia/tree/master/stdlib). Las bibliotecas estándar pueden depender de otras bibliotecas estándar. SHA es una librería estándar inusual porque está alojada externamente y tiene una versión. Pero la versión sigue siendo fija para cada versión de Julia a través de un archivo `.version` como [el de SHA](https://github.com/JuliaLang/julia/blob/master/stdlib/SHA.version), por lo que la mayoría de los usuarios pueden tratarla como una biblioteca estándar normal. En este ejemplo, MacroTools depende sólo de librerías estándar, pero la mayoría de los otros paquetes dependen también de otros paquetes externos.
Puedes comprobar las versiones de las librerías en tu `Project.toml` y `Manifest.toml` con el comando `status` o `st`. Con la opción `-m` puedes ver las entradas de `Manifest.toml`, que pueden ser importantes para comprobar qué dependencias se han resuelto.
```terminal
(@v1.8) pkg> st
Status `~/.julia/environments/v1.8/Project.toml`
[1914dd2f] MacroTools v0.5.9
(@v1.8) pkg> st -m
Status `~/.julia/environments/v1.8/Manifest.toml`
[1914dd2f] MacroTools v0.5.9
[2a0f44e3] Base64
[d6f4376e] Markdown
[9a3f8284] Random
[ea8e919c] SHA v0.7.0
[9e88b42a] Serialization
(@v1.8) pkg> st -m SHA
Status `~/.julia/environments/v1.8/Manifest.toml`
[ea8e919c] SHA v0.7.0
```
## Números de versión
Para entender cómo se resuelven las dependencias, tienes que entender [SemVer versioning](https://semver.org). SemVer significa versionado semántico, lo que significa que los números de versión deben ser significativos, no sólo etiquetas aleatorias. Las tres partes del número de versión son `major`.`minor`.`patch`. En Julia, todas las versiones más recientes con la misma versión principal deben tener APIs públicas compatibles, por lo que el código que funciona con `v1.2.3` también debería funcionar con `v1.20.5`. La excepción es la versión mayor `0`, donde cada nueva versión menor puede considerarse potencialmente rompedora. Así, el código que funciona con `v0.2.4` debería seguir funcionando con `v0.2.13` pero no necesariamente con `v0.3.0`. Esto se debe a que los desarrolladores de paquetes quieren ser capaces de hacer cambios de ruptura incluso si no han llevado su paquete a `v1.0` todavía, una versión que normalmente lleva implícita la estabilidad de la API pública y que a menudo sólo se alcanza después de que el paquete haya existido durante un tiempo.
## Añadir variantes específicas de un paquete
Hasta ahora, sólo hemos utilizado el comando `add MacroTools`, que trajo la última versión `v0.5.9` a nuestro entorno. A veces, sin embargo, quieres una variante específica de un paquete. No tiene que ser necesariamente una versión específica. También puede ser un commit o una rama de un determinado repositorio. Vamos a probar esto con `MacroTools`.
Podemos instalar la versión `v0.5.1` utilizando la sintaxis `@`:
```terminal
(@v1.8) pkg> add MacroTools@0.5.1
Resolving package versions...
Updating `~/.julia/environments/v1.8/Project.toml`
⌃ [1914dd2f] ↓ MacroTools v0.5.9 ⇒ v0.5.1
Updating `~/.julia/environments/v1.8/Manifest.toml`
⌅ [00ebfdb7] + CSTParser v2.5.0
⌅ [34da2185] + Compat v2.2.1
⌅ [864edb3b] + DataStructures v0.17.20
⌃ [1914dd2f] ↓ MacroTools v0.5.9 ⇒ v0.5.1
[bac558e1] + OrderedCollections v1.4.1
[0796e94c] + Tokenize v0.5.24
[0dad84c5] + ArgTools v1.1.1
[56f22d72] + Artifacts
[ade2ca70] + Dates
[8bb1440f] + DelimitedFiles
[8ba89e20] + Distributed
[f43a241f] + Downloads v1.6.0
[7b1f6079] + FileWatching
[b77e0a4c] + InteractiveUtils
[b27032c2] + LibCURL v0.6.3
[76f85450] + LibGit2
[8f399da3] + Libdl
[37e2e46d] + LinearAlgebra
[56ddb016] + Logging
[a63ad114] + Mmap
[ca575930] + NetworkOptions v1.2.0
[44cfe95a] + Pkg v1.8.0
[de0858da] + Printf
[3fa0cd96] + REPL
[1a1011a3] + SharedArrays
[6462fe0b] + Sockets
[2f01184e] + SparseArrays
[10745b16] + Statistics
[fa267f1f] + TOML v1.0.0
[a4e569a6] + Tar v1.10.0
[8dfed614] + Test
[cf7118a7] + UUIDs
[4ec0a83e] + Unicode
[e66e0078] + CompilerSupportLibraries_jll v0.5.2+0
[deac9b47] + LibCURL_jll v7.83.1+1
[29816b5a] + LibSSH2_jll v1.10.2+0
[c8ffd9c3] + MbedTLS_jll v2.28.0+0
[14a3606d] + MozillaCACerts_jll v2022.2.1
[4536629a] + OpenBLAS_jll v0.3.20+0
[83775a58] + Zlib_jll v1.2.12+3
[8e850b90] + libblastrampoline_jll v5.1.1+0
[8e850ede] + nghttp2_jll v1.47.0+0
[3f19e933] + p7zip_jll v17.4.0+0
Info Packages marked with ⌃ and ⌅ have new versions available, but those with ⌅ cannot be upgraded. To see why use `status --outdated -m`
```
Puedes ver que tenemos una tonelada de nuevas dependencias. Esto ocurrió porque `MacroTools` consiguió reducir mucho el número de paquetes de los que depende con el tiempo, por lo que la versión anterior tira de mucho más.
Si echamos un vistazo a la nueva entrada `Manifest.toml` para `MacroTools`, vemos:
```toml
[[deps.MacroTools]]
deps = ["CSTParser", "Compat", "DataStructures", "Test", "Tokenize"]
git-tree-sha1 = "d6e9dedb8c92c3465575442da456aec15a89ff76"
uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
version = "0.5.1"
```
Esto demuestra que incluso entre versiones de parches de un paquete, que deberían seguir la misma API pública, las dependencias pueden cambiar mucho.
Si miras `Project.toml`, verás que no ha cambiado. El requisito de versión sólo se aplicó durante la resolución de esta dependencia, y no se recordará ni se aplicará de nuevo en futuras operaciones de Pkg.
Vamos a probar otra sintaxis, que es la de elegir una confirmación o rama específica de un repositorio. En este caso, usamos el commit `639d1a6`, pero también podríamos usar algo como `master` para obtener el último commit de esa rama.
```terminal
(@v1.8) pkg> add MacroTools#639d1a6
Resolving package versions...
Updating `~/.julia/environments/v1.8/Project.toml`
[1914dd2f] ~ MacroTools v0.5.1 ⇒ v0.5.9 `https://github.com/FluxML/MacroTools.jl.git#639d1a6`
Updating `~/.julia/environments/v1.8/Manifest.toml`
[00ebfdb7] - CSTParser v2.5.0
[34da2185] - Compat v2.2.1
[864edb3b] - DataStructures v0.17.20
[1914dd2f] ~ MacroTools v0.5.1 ⇒ v0.5.9 `https://github.com/FluxML/MacroTools.jl.git#639d1a6`
[bac558e1] - OrderedCollections v1.4.1
[0796e94c] - Tokenize v0.5.24
[0dad84c5] - ArgTools v1.1.1
[56f22d72] - Artifacts
[ade2ca70] - Dates
[8bb1440f] - DelimitedFiles
[8ba89e20] - Distributed
[f43a241f] - Downloads v1.6.0
[7b1f6079] - FileWatching
[b77e0a4c] - InteractiveUtils
[b27032c2] - LibCURL v0.6.3
[76f85450] - LibGit2
[8f399da3] - Libdl
[37e2e46d] - LinearAlgebra
[56ddb016] - Logging
[a63ad114] - Mmap
[ca575930] - NetworkOptions v1.2.0
[44cfe95a] - Pkg v1.8.0
[de0858da] - Printf
[3fa0cd96] - REPL
[1a1011a3] - SharedArrays
[6462fe0b] - Sockets
[2f01184e] - SparseArrays
[10745b16] - Statistics
[fa267f1f] - TOML v1.0.0
[a4e569a6] - Tar v1.10.0
[8dfed614] - Test
[cf7118a7] - UUIDs
[4ec0a83e] - Unicode
[e66e0078] - CompilerSupportLibraries_jll v0.5.2+0
[deac9b47] - LibCURL_jll v7.83.1+1
[29816b5a] - LibSSH2_jll v1.10.2+0
[c8ffd9c3] - MbedTLS_jll v2.28.0+0
[14a3606d] - MozillaCACerts_jll v2022.2.1
[4536629a] - OpenBLAS_jll v0.3.20+0
[83775a58] - Zlib_jll v1.2.12+3
[8e850b90] - libblastrampoline_jll v5.1.1+0
[8e850ede] - nghttp2_jll v1.47.0+0
[3f19e933] - p7zip_jll v17.4.0+0
```
Ten en cuenta que aunque la versión impresa para MacroTools es de nuevo `0.5.9`, esto no significa necesariamente que estemos en el mismo commit que el apuntado por la versión `0.5.9` en el registro. Sólo significa que Pkg clonó el repositorio, comprobó el commit con el hash `639d1a6` y encontró el especificador de versión `0.5.9` en el propio fichero `Project.toml` de MacroTools. Por lo tanto, infinitas versiones de código de un paquete pueden ser tratadas como la versión `X.Y.Z` por Pkg, pero `X.Y.Z` sólo se refiere a exactamente una versión. Es importante recordar esta distinción al desarrollar y editar un paquete, pero hablaremos de ello más adelante.
Si echamos otro vistazo a nuestro `Manifest.toml`, podemos ver la siguiente entrada para MacroTools:
```toml
[[deps.MacroTools]]
deps = ["Markdown", "Random"]
git-tree-sha1 = "465a4803356bcb11f6eb97df992680f13a9ba776"
repo-rev = "639d1a6"
repo-url = "https://github.com/FluxML/MacroTools.jl.git"
uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
version = "0.5.9"
```
Esta vez, se registró la URL del repositorio, así como la revisión, que fue `639d1a6`. Esto se debe a que tan pronto como especifica una revisión en el comando `add`, Pkg sabe que está operando fuera del registro, por lo que no puede confiar en la información del repositorio almacenada allí para MacroTools.
(Ten en cuenta que también puedes instalar paquetes no registrados, o bifurcaciones de paquetes registrados de esta manera, haciendo `add https://the_url_to_the_git_repository`).
El manifiesto necesita almacenar la url y la revisión para que el proyecto pueda ser reproducido por otra persona. Veamos cómo es reproducir un entorno.
## Reproducir un entorno
Digamos que has escrito un código que depende de la versión específica de `MacroTools` que añadimos mediante `add MacroTools#639d1a6` y quieres que tu colega pueda ejecutar ese código con los paquetes exactos instalados que usamos en su momento.
¿Qué ficheros se necesitan para reproducir el estado de tu entorno? No sólo `Project.toml` contiene esta información:
```julia
[deps]
MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
```
Necesitamos enviar también el `Manifest.toml` porque registra las versiones exactas de todos los paquetes. Imaginemos que somos nuestro colega, y que acabamos de recibir un archivo `Project.toml` y `Manifest.toml`. ¿Cómo conseguimos instalar el entorno?
Vamos a copiar los archivos en una nueva carpeta que llamaremos `ColleagueEnv` en nuestro directorio de trabajo actual.
Para simular que somos el colega que acaba de usar Julia por primera vez, también borramos la carpeta `.julia/packages/MacroTools` en la que estaba almacenado el código fuente descargado de `MacroTools`.
Ten en cuenta que esto significa que el código fuente no forma parte de un entorno, sino que se almacena de forma centralizada. Sería bastante derrochador descargar los mismos fuentes una y otra vez sólo porque estás utilizando diferentes entornos locales.
Ahora reiniciemos Julia y activemos el entorno `ColleagueEnv`:
```terminal
(@v1.8) pkg> activate ./ColleagueEnv
Activating project at `~/ColleagueEnv`
```
Podemos comprobar los paquetes instalados mediante `st -m`:
```terminal
(ColleagueEnv) pkg> st -m
Status `~/ColleagueEnv/Manifest.toml`
→ [1914dd2f] MacroTools v0.5.9 `https://github.com/FluxML/MacroTools.jl.git#master`
[2a0f44e3] Base64
[d6f4376e] Markdown
[9a3f8284] Random
[ea8e919c] SHA v0.7.0
[9e88b42a] Serialization
Info Packages marked with → are not downloaded, use `instantiate` to download
```
Si ahora intentáramos ejecutar un código utilizando `MacroTools`, ocurriría lo siguiente:
```terminal
julia> using MacroTools
ERROR: ArgumentError: Package MacroTools [1914dd2f-81c6-5fcd-8719-6d5c9610ff09] is required but does not seem to be installed:
- Run `Pkg.instantiate()` to install all recorded dependencies.
Stacktrace:
[1] _require(pkg::Base.PkgId)
@ Base ./loading.jl:1306
[2] _require_prelocked(uuidkey::Base.PkgId)
@ Base ./loading.jl:1200
[3] macro expansion
@ ./loading.jl:1180 [inlined]
[4] macro expansion
@ ./lock.jl:223 [inlined]
[5] require(into::Module, mod::Symbol)
@ Base ./loading.jl:1144
```
Así que tenemos que seguir el consejo ya impreso dos veces para nosotros, y llamar a `instantiate`. Esto descargará todo lo especificado en el `Manifest.toml` exactamente como se registró allí. De hecho, puedes estar seguro de que es exactamente lo mismo porque el `Manifest.toml` almacena los hashes del árbol git de cada dependencia. A menos que alguien borre estas partes específicas del repositorio, podrás descargar el código fuente exactamente como estaba:
```terminal
(ColleagueEnv) pkg> instantiate
Precompiling project...
✓ MacroTools
1 dependency successfully precompiled in 1 seconds
(ColleagueEnv) pkg> st -m
Status `~/ColleagueEnv/Manifest.toml`
[1914dd2f] MacroTools v0.5.9 `https://github.com/FluxML/MacroTools.jl.git#master`
[2a0f44e3] Base64
[d6f4376e] Markdown
[9a3f8284] Random
[ea8e919c] SHA v0.7.0
[9e88b42a] Serialization
```
Ahora ya no recibimos una advertencia, nuestras dependencias se han descargado correctamente.
Encontrarás `MacroTools` descargado en la carpeta `.julia/packages` de nuevo.
## Paquetes y entornos
Los paquetes y los entornos normales son bastante similares.
Cada paquete debe tener un `Project.toml` que especifique su nombre, UUID, versión y dependencias.
La forma más fácil de hacer un paquete para probar esto, es usar el comando `generate` del Pkg REPL.
Reiniciemos Julia y eliminemos `MacroTools` de nuestro entorno principal para que quede vacío:
```terminal
(@v1.8) pkg> rm MacroTools
Updating `~/.julia/environments/v1.8/Project.toml`
[1914dd2f] - MacroTools v0.5.9 `https://github.com/FluxML/MacroTools.jl.git#639d1a6`
Updating `~/.julia/environments/v1.8/Manifest.toml`
[1914dd2f] - MacroTools v0.5.9 `https://github.com/FluxML/MacroTools.jl.git#639d1a6`
[2a0f44e3] - Base64
[d6f4376e] - Markdown
[9a3f8284] - Random
[ea8e919c] - SHA v0.7.0
[9e88b42a] - Serialization
```
Ahora, generamos un nuevo paquete llamado `MyPackage`:
```terminal
(@v1.8) pkg> generate MyPackage
Generating project MyPackage:
MyPackage/Project.toml
MyPackage/src/MyPackage.jl
```
Como puede ver, se generó un archivo `Project.toml` en el directorio `MyPackage`.
Echemos un vistazo a este:
```toml
name = "MyPackage"
uuid = "025f59cc-7e1c-467d-8f56-70157e1cbbbb"
authors = ["Your Name