How to set global path?

in startup.jl:

if Sys.isapple()
    const ROOT_PATH = "/Users/Tom/Documents/Julia/"
else
    const ROOT_PATH = "/home/Tom/Documents/Julia/"
end

import Abc

then in Abc.jl:

module Abc

include(joinpath(ROOT_PATH, "extension.jl") )

end

and I got the error:

ERROR: LoadError: UndefVarError: `ROOT_PATH` not defined

what should I do so that module Abc could see ROOT_PATH? Thanks

This isn’t special to the startup.jl, but to how modules work, isn’t it?

If I do

x = 10

module M
    println(x)
end

it gives ERROR: LoadError: UndefVarError: x not defined.

To my understanding, that’s because x lives in Main, but when a module is created, only Base and Core are implicitly loaded (cf. Modules · The Julia Language ). Hence anything defined “by hand” will not be available without using/importing it.


A quick way to achieve what you want is to just say Main.ROOT_PATH (because although it is not imported completely, the binding Main is available). Or I guess import Main: ROOT_PATH if you use the constant often.

No. Main.ROOT_PATH still not find the variable.

and import Main: ROOT_PATH gives the error:

ERROR: LoadError: ArgumentError: Package Main not found in current path, maybe you meant `import/using .Main`.
- Otherwise, run `import Pkg; Pkg.add("Main")` to install the Main package.

while import .Main: ROOT_PATH gives:

WARNING: could not import Main.ROOT_PATH into FXs
ERROR: LoadError: UndefVarError: `ROOT_PATH` not defined

seems like module Main is “not yet ready” for modules that are imported inside startup.jl??

Then I think I don’t understand your setup. Could you share what you are trying to achieve in the end?

In particular, how is the import Abc supposed work in the startup file? Is Abc.jl included somewhere earlier?


If I just put this in my startup file, it prints the global variable correctly upon starting a new Julia REPL…

if Sys.isapple()
    const ROOT_PATH = "testpath_apple"
else
    const ROOT_PATH = "testpath_orange"
end

module Abc
    println(Main.ROOT_PATH)
end

and same if I replace the module with this

module Abc
    import Main: ROOT_PATH
    println(ROOT_PATH)
end

EDIT: My best guess is that you include the module definition before the definition of the constants. This doesn’t work (using a variable before it is defined).

No. I defined ROOT_PATH (inside startup.jl) before importing Abc. (just as shown on the first post). Logically, it should work.

and the strange thing is: not importing Abc inside startup.jl still not work:
startup.jl:

if Sys.isapple()
    const ROOT_PATH = "/Users/Tom/Documents/Julia/"
else
    const ROOT_PATH = "/home/Tom/Documents/Julia/"
end
# no longer import Abc here

and Abc.jl:

module Abc
    const rp = Main.ROOT_PATH
end

still gets the error:

julia> import Abc
[ Info: Precompiling Abc [top-level]
ERROR: LoadError: UndefVarError: `ROOT_PATH` not defined

I didn’t mean import, but include. The source code from Abc.jl has to somehow end up in the startup file if you want to import Abc as in your first post.

Did you perhaps change the LOAD_PATH and import Abc without the include("Abc.jl")? I am not sure how exactly the two scenarios are different, but if you include the file with the module Abc, there should be no issues (everything is under the Main module). If you rely on loading the module directly, it seems that the code in the module is in a separate parent module…

Make it simple. Now there’s only one line in startup.jl:

Thomass-MacBook-Pro:config Thomas$ cat startup.jl
const XXX = 3

and Abc.jl contains any combinations of the following 4 lines (by commenting some of the lines); all combinations failed when I import Abc:

module Abc
    import Main: XXX            # ERROR: LoadError: ArgumentError: Package Main not found in current path, maybe you meant `import/using .Main`.

    import .Main: XXX           # WARNING: could not import Main.XXX into Abc

    const YYY = XXX + 1         # ERROR: LoadError: UndefVarError: `XXX` not defined

    const YYY = Main.XXX + 1    # ERROR: LoadError: UndefVarError: `XXX` not defined
end

same situation in v1.9.1 and v1.8.1

I believe we’re not talking about the same thing.

To reproduce your problem, the code of Abc.jl needs to be available in the place where import Abc should be run.

This is the setup:

  • A startup.jl file with const XXX = 3
  • A file Abc.jl with the module Abc in some directory
  • A REPL or Julia session where import Abc is run – how are you doing this? (just running import Abc in a fresh REPL will give a LoadError that Abc is not found…)

I know these two ways:

  1. If I do the (I guess) default way of typing this in a REPL I get no errors whatsoever:
julia> include("Abc.jl")

julia> import .Abc  # not really necessary anyway, `Abc` is already a known name in this scope

# do something with `Abc.YYY`, `XXX`, etc.
  1. If I instead do this I get the same errors you mention:
julia> push!(LOAD_PATH, pwd()) # Assuming `Abc.jl` is in the current directory

julia> import Abc

Hence my question: How exactly are you making the module available to import in the first place? And is it possible to change to the first way?

I’m doing your 2nd way: push!(LOAD_PATH, with where Abc.jl locates, then import it.

The problem now is: why a constant defined in startup.jl is not visible when a module is imported???

That’s just how modules work… there is nothing special about the startup.jl as far as I can tell. If any variable is defined in a module, it is not automatically available in a child module.

1 Like

This can be taken to the extreme if you define a baremodule:

baremodule Abc
    println("not working")
end

you get

ERROR: LoadError: UndefVarError: `println` not defined

because the “built-in” functions from Core and Base are also missing.

1 Like