Developing your Julia package
We’ll show step-by-step how to develop your first package in Julia. To do this, we use the very useful PkgTemplate.jl, and we base our Tutorial on this guide by Quantecon and this video by Chris Rackauckas.
First things first. Start by creating the folder to store your package. In our case, we’ll be creating a package named “VegaGraphs”, which is a package that I’m developing. So, inside this folder, open your Julia REPL and install PkgTemplate.jl.
1. Creating your Package Template
First, we need to create a template for our package. This template will include things like Licensing, Plugins, Authors, etc. For our example, we’ll be using a simple template with the MIT License. The plugins used will be GitHub Actions and Codecov. I’ll not be diving into these plugins, but just for the sake of clarity, I’ll briefly explain what they do.
- GitHub Actions is a plugin that automatically builds a virtual machine and tests your code, hence, you can control the machine configurations necessary to running your package.
- Codecov is a plugin that analysis your code, and evaluates how much of it is covered in your tests. So, for example, suppose that you wrote 3 different functions, but forgot to write a test for one of them. Then, Codecov will point out that there is no tests for such function.
Still inside the REPL, run the following commands:
t = Template(;user="YourUserNameOnGithub", plugins = [GitHubActions(), Codecov()], manifest = true)generate("VegaGraphs.jl",t)
The first line of code defines the template, while the second one will generate your package. Note that I didn’t specify a folder, so the package will be created in a default location, which will be
~/.julia/dev (for Linux).
Now, just copy the files from the
~/.julia/dev/VegaGraphs to the folder where you will be working from, and then setup your git repository by running the following commands in the terminal:
# inside the VegaGraphs working folder
git add -A
git commit -m "first commit"
git branch -M master
git remote add origin email@example.com:YOURUSERNAME/VegaGraphs.git
git push -u origin master
Taking a look inside the generated folder, you’ll have two folders and four files:
/src: This folder is where you will write the code for your package per se;
/test: Here is for storing your tests;
Project.toml: This is where you will store information such as the author, dependencies, julia version, etc;
Manifest.toml: This is a machine generated file, and you should just leave it be;
The other files are self explanatory.
2. Writing Code
We are ready to start coding our package. Note that inside the
/src folder we already have a file named
VegaGraphs.jl , which is the main file of our package. We can do all our coding directly inside
VegaGraphs.jl , but as our code gets large, this might become messy.
Instead, we can write many different files for organizing our code, and then use
VegaGraphs.jl to join everything together. Let’s do an example. We’ll code a very simple function, which we’ll store in another file, called
graph_functions.jl , that will also be inside the
Here is some example code:
# code inside graph_functions.jl
The code above is a simple implementation of a function. Below I show how to actually make this function available to users. One just needs to “include” the
graph_functions.jl file, and to export the
plot_scatter . Once exported, the function is now available to anyone who imports our package.
# code inside VegaGraphs.jl
module VegaGraphsusing VegaLiteexport sum_values
Note that, besides including our function, I’ve also imported the VegaLite package. Hence, I need to specify VegaLite.jl as a dependency. We’ll do this by using the REPL again.
Go to the root of your package and open the REPL by running the command
julia in the terminal.Now, press
] . This will put you on “package mode”. Next, write
activate . , which will activate the Julia environment to your current folder. Finally, write
add VegaLite , and this will add VegaLite.jl to your dependencies inside the
3. Creating and running tests
So we’ve implemented a function and added a dependency to our package. The following step is to write a test, to guarantee that our code is indeed working. The code is self-explanatory, we just write our test inside a testset. You can write as many as you like to guarantee that your function is working properly.
# code inside ./test/runtests.jl
using Test@testset "VegaGraphs.jl" begin
x = 2
y = 2
@test VegaGraphs.sum_values(x,y) == 4
Once the test is written, we have to run it and see if everything is working. Again, go to the root of the project and open your REPL. Guarantee that your environment is activated and run the tests as shown in the image below:
This will run your tests and see if everything passes. Once everything passes, we can trust that our code is working properly, and we can move on to more implementations.
4. Workflow - Text editor + Jupyter Notebook
With everything shown up until now, you are already ready to develop your package in Julia. Still, you might be interested on how to develop an efficient workflow. There are many possibilities here, such as using IDEs such as Juno and VsCode. I prefer to use Jupyter Notebooks with Vim (my text editor of choice), and doing everything from the terminal.
To use your developing package in your Notebook, you will need to activate your environment in a similar way that we’ve been doing up until now. As you open a new Notebook, run the following code in the very first cell.
Note here that besides activating the environment, we also imported a package called Revise. This package is very helpful, and it should be imported right in the beginning of your notebook, before you actually import your own package, otherwise it won’t work properly!
Every time you modify the code in your package, to load the changes to your notebook you would have to restart the kernel. But when you use Revise.jl, you don’t need to restart your kernel, just import your package again, and the modifications will be applied.
Now, my workflow is very simple. I use Vim to modify the code in my package, and use the Notebook for trying things out. Once I get everything working as it should, I write down some tests, and test the whole thing.
5. Registering/Publishing your Package
Finally, suppose that you’ve finished writing your package, and you are ready to share it with the Julia community. Like with other packages, you want users to be able to write a simple
Pkg.add("MyPackage") and install it. This process is called registering.
To do this, first go to Registrator.jl and install the app to your Github account.
Next, go to your package Github’s page and enter the Issues tab. Create a new issue, an write
@JuliaRegistrator register() , as shown in the image below.
Once you’ve done this, the JuliaRegistrator bot will open a pull request for your package to be registered. Unless you actually want your package to be registered, don’t actually submit the issue.
And that’s all.