Creating a New Project
If you want to keep you code well organized, the first step is to create a project.
Basic Directory Structure
Let’s begin by creating a basic directory structure to store our project’s files. We will use (at least) the following folders:
src/
which will contain our main code, structured with modules and multiple files.test/
to assess the functionality of our code.docs/
, most of which will be generated automatically from comments on the code.
Of course, this is a basic setup. Having tests and documentation is considered mandatory for good programming practices, but nothing stops you from adding additional folders.
Two common choices are:
examples/
, to store simple scripts that demonstrate how to use the core project’s functionality.benchmarks/
, in case we need to keep track of performance of several cases, and/or to compare with competing alternatives.
Create the Source Tree and TOML files
Now let’s create the basic source tree, and the project’s TOML files
]
pkg > generate MyProject
This will create the following source tree:
MyProject/
├── Project.toml
└── src
└── MyProject.jl
MyProject.jl
will contain a Hello World function named greet()
:
module MyProject
greet() = print("Hello World!")
end # module
The Project.toml and Manifest.toml are central to a project. While Project.toml can be edited manually, the Manifest.toml file is generated and maintained by Pkg, so should never be modified manually.
Enter the shell mode by typing ;
in the REPL and create the remainder folders you need using mkdir
.
;
shell> mkdir -p MyProject/{docs,test}
Activating the Project Environment
To activate the project environment, cd
into project’s folder in shell mode, switch to pkg
mode and type activate .
:
shell> cd MyProject
]
pkg > activate .
You can also type activate MyProject
if you are on the parent folder. Your prompt should change into something of the form
(MyProject) pkg >
Equivalently, from the terminal, start Julia with the following command
julia --project=.
Adding dependencies
After activating the current environment, you can also add dependencies. For example, let’s add the Plots package.
]
(MyProject) pkg > add Plots
Our Project.toml should now look like something
name = "MyProject"
uuid = "a5927f71-4e94-4484-9e8d-767c56d7f0c4"
authors = ["yourname <[email protected]>"]
version = "0.1.0"
[deps]
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
Using your project
Once activated you activate the project environment, you can now call your greet function with the following code:
using MyProject
MyProject.greet()
Did you modify MyProject.jl? If you are working interactively, testing things and adding them to your project’s module, you might notice that calling using MyProject
again doesn’t do anything. This can be annoying.
In order to force the recompilation of your project’s files every time you call using MyProject
from the REPL, you need to include the Revise.jl package to your working environment.
Simply start Julia, and install the Revise package in the global environment (that is, there is no need to install it as a project dependency), then activate the project environment and do:
using Revise
using MyProject
MyProject.greet()
###
### Introduce modifications in the file MyProject.jl
###
using MyProject
MyProject.greet()
Now, the second time you call the function, the changes you’ve made in MyProject.jl will be reflected properly.
Export
You might have noticed that, when we want to call our function greet()
defined in MyProject, we need to reference it using MyProject.greet()
.
This happens by default to keep the global namespace clean. But we might want to change that.
In order to do it, we need to explicitly export a symbol, using the export
keyword. So our project should look like this:
module MyProject
greet() = print("Hello World!")
export greet
end # module
And now, from any other scope, we can do
using MyProject
greet()
Conclusion
Ok, we’ve got the basics covered. In subsequent posts we will go about structuring our code into modules, and cover some good programming practices like writing tests and relying on automatically-generated documentation. So stay tuned!