Correct way of passing paths in the REPL for a project containing sub folders

Hi all, I’ve been using Atom for a while and now I am trying to run my codes directly from the REPL without using Atom, that is, I write the *.jl files using an external text editor and then invoke julia.exe to run the code. My project contains sub folders where *.jl files reside. When I run this code from the REPL I get some errors because (I think) Julia can’t find the sub folders in the julia path. I’ve prepared a small sample project to show the problem I am facing. I describe it next.

There is a folder named “julia_test” in the root directory (C:) that contains sub folders and files:
folders

The *jl files are the following:

main.jl

include("..\\setpaths.jl")
setpaths()

using VectorOperations: dotproduct

v1 = [1.0,2.0,3.0]
v2 = [2.0,2.0,2.0]

p = dotproduct(v1,v2)

println("v1 * v2 = $p")

setpaths.jl

function setpaths()
  rootdir = pwd()
  testdir = joinpath(rootdir,"test")
  sourcedir = joinpath(rootdir,"src")
  sourcedir1 = joinpath(rootdir,"src\\VectorOperations")
  push!(LOAD_PATH, rootdir, testdir, sourcedir, sourcedir1)
end

VectorOperations.jl

module VectorOperations

using LinearAlgebra: dot

# VectorOperations functions
include("VectorOperationsFunctions.jl")
export dotproduct

end

VectorOperationsFunctions.jl

function dotproduct(v1,v2)
  return dot(v1,v2)
end

The file I run is “main.jl”. To this end, I make sure julia.exe is started inside folder “test”:

Then, in the REPL I execute the following:

include("main.jl")

However, I get the following error:

julia> include("main.jl")
ERROR: LoadError: ArgumentError: Package VectorOperations not found in current path:
- Run `import Pkg; Pkg.add("VectorOperations")` to install the VectorOperations package.

Stacktrace:
 [1] require(::Module, ::Symbol) at .\loading.jl:823
 [2] include at .\boot.jl:326 [inlined]
 [3] include_relative(::Module, ::String) at .\loading.jl:1038
 [4] include(::Module, ::String) at .\sysimg.jl:29
 [5] include(::String) at .\client.jl:403
 [6] top-level scope at none:0
in expression starting at C:\julia_test\test\main.jl:4

This means that Julia can’t find the definition of VectorOperations module that I defined. The folder where this module resides is “source/VectorOperations” and is specified inside function “setpaths”. I suppose Julia can’t find this sub folder. By the way, this code runs without any problems in Atom. Am I missing something?

In similar situations, I usually include something like

project_path(parts...) = normpath(joinpath(@__DIR__, "..", parts...))

in the main module file (eg src/Foo.jl). Then in the REPL I can do

using Foo
include(project_path("setpaths.jl"))

etc.

For the record joinpath is redundant here. Documentation PR: https://github.com/JuliaLang/julia/pull/33700.

Thanks @Tamas_Papp. I will try that. Anyway, I found what the problem is. LOAD_PATH is not set correctly after setpaths() is executed. See what I get:

julia> pwd()                                    
"C:\\julia_test\\test"                          
                                                
julia> include("main.jl")                       
ERROR: LoadError: ArgumentError: Package VectorOperations not found in current path:            
- Run `import Pkg; Pkg.add("VectorOperations")` 
to install the VectorOperations package.        
                                                
Stacktrace:                                     
 [1] require(::Module, ::Symbol) at .\loading.jl:823                                            
 [2] include at .\boot.jl:326 [inlined]         
 [3] include_relative(::Module, ::String) at .\loading.jl:1038                                  
 [4] include(::Module, ::String) at .\sysimg.jl:29                                              
 [5] include(::String) at .\client.jl:403       
 [6] top-level scope at none:0                  
in expression starting at C:\julia_test\test\main.jl:4                                          
                                                
julia> LOAD_PATH                                
7-element Array{String,1}:                      
 "@"                                            
 "@v#.#"                                        
 "@stdlib"                                      
 "C:\\julia_test\\test"                         
 "C:\\julia_test\\test\\test"                   
 "C:\\julia_test\\test\\src"                    
 "C:\\julia_test\\test\\src\\VectorOperations"                                                 

There is an extra “test” folder in the path. However, in Atom it is set OK and that is why it works in Atom:

julia> LOAD_PATH
7-element Array{String,1}:
 "@"
 "@v#.#"
 "@stdlib"
 "C:\\julia_test\\"
 "C:\\julia_test\\test"
 "C:\\julia_test\\src"
 "C:\\julia_test\\src\\VectorOperations"

I am trying to figure out why the problem happens in pure REPL and not in Run All Atom button. I will come back if I fix the problem.

Clearly Atom runs it with a different working directory than you expect. Just replacing rootdir = pwd() with rootdir = @__DIR__ should make your code insensitive to working directories.

2 Likes

Thanks @GunnarFarneback. That solved the issue.