CRYSTAL_PATH not always includes the default libraries paths if user specify $CRYSTAL_PATH manually

I ask this question because this behavior not same as Ruby $RUBYLIB.

Following is my default env when not define $CRYSTAL_PATH.

 ╰─ $ cr env CRYSTAL_PATH
lib:/home/zw963/Crystal/bin/../share/crystal/src

Then when i specify $CRYSTAL_PATH manually like following, i even can’t run a hello world successful.

 ╰─ $ export CRYSTAL_PATH=~/Dropbox/common/crystal/lib

 ╰─ $ cr env CRYSTAL_PATH
/home/zw963/Dropbox/common/crystal/lib

 ╰─ $ cr 1.cr  
Showing last frame. Use --error-trace for full trace.

In 1.cr:1:1

 1 | puts "hello world"
     ^
Error: can't find file 'prelude'

If you're trying to require a shard:
- Did you remember to run `shards install`?
- Did you make sure you're running the compiler in the same directory as your shard.yml?

This behavior is unexpected for a user come from Ruby, because, when add paths into $RUBYLIB,
those paths will prepend into $LOAD_PATH array, that is, the default $LOAD_PATH always exists for avoid even a very simple hello world is broken.

 ╰─ $ ruby -e 'puts $LOAD_PATH'
/home/zw963/.rvm/rubies/ruby-3.1.0/lib/ruby/site_ruby/3.1.0
/home/zw963/.rvm/rubies/ruby-3.1.0/lib/ruby/site_ruby/3.1.0/x86_64-linux
/home/zw963/.rvm/rubies/ruby-3.1.0/lib/ruby/site_ruby
/home/zw963/.rvm/rubies/ruby-3.1.0/lib/ruby/vendor_ruby/3.1.0
/home/zw963/.rvm/rubies/ruby-3.1.0/lib/ruby/vendor_ruby/3.1.0/x86_64-linux
/home/zw963/.rvm/rubies/ruby-3.1.0/lib/ruby/vendor_ruby
/home/zw963/.rvm/rubies/ruby-3.1.0/lib/ruby/3.1.0
/home/zw963/.rvm/rubies/ruby-3.1.0/lib/ruby/3.1.0/x86_64-linux

 ╰─ $ RUBYLIB=/home/zw963/ruby/lib ruby -e 'puts $LOAD_PATH'
/home/zw963/ruby/lib
/home/zw963/.rvm/rubies/ruby-3.1.0/lib/ruby/site_ruby/3.1.0
/home/zw963/.rvm/rubies/ruby-3.1.0/lib/ruby/site_ruby/3.1.0/x86_64-linux
/home/zw963/.rvm/rubies/ruby-3.1.0/lib/ruby/site_ruby
/home/zw963/.rvm/rubies/ruby-3.1.0/lib/ruby/vendor_ruby/3.1.0
/home/zw963/.rvm/rubies/ruby-3.1.0/lib/ruby/vendor_ruby/3.1.0/x86_64-linux
/home/zw963/.rvm/rubies/ruby-3.1.0/lib/ruby/vendor_ruby
/home/zw963/.rvm/rubies/ruby-3.1.0/lib/ruby/3.1.0
/home/zw963/.rvm/rubies/ruby-3.1.0/lib/ruby/3.1.0/x86_64-linux

I’m throwing this question just want to know if this behavior is intentional, for now, the workaround is:

export CRYSTAL_PATH=~/Dropbox/common/crystal/lib:lib:"$(dirname `which crystal`)/../share/crystal/src"

But, i consider the lib:"$(dirname which crystal)/../share/crystal/src part is really not necessary.

Or, am I missing some environment variable that can just prepend path into CRYSTAL_PATH instead of override?

Thank you.

Is there a reason you can’t just treat it as like $PATH and do like export CRYSTAL_PATH="/home/zw963/Dropbox/common/crystal/lib:$CRYSTAL_PATH"?

EDIT: NVM, issue is the env var is defined via the wrapper script so that just ends up overriding it anyway.

Hi, AFAIK, use like this not work too, because the $CRYSTAL_PATH is unset by default.

export CRYSTAL_PATH="/some/path:$(crystal env CRYSTAL_PATH)" This should so it. Prepend your custom path(s) before the default path(s).

$ crystal env CRYSTAL_PATH
/some/path:lib:/usr/lib/crystal

export CRYSTAL_PATH="/some/path:$(crystal env CRYSTAL_PATH)"

This usage is really cool, I didn’t even think of it.

If the the behavior of current CRYSTAL_PATH behavior correct and expected, this is probably the best solution.

Thank you.

Although, the difference with $RUBYLIB probably confuse Rubyist.

Yes it’s intended that way and documented accordingly. It’s not really designed for end users who want to pull in a custom source directory. It’s mostly used for system configuration (for example within wrapper scripts) and for that it must override any built-in configuration.

What’s your use case for adding another code location? Perhaps we can find an easier solution for that.

My use case is, i save this really useful snippets write by @asterite to, e.g. ~/Dropbox/common/crystal/lib/meta.cr, then prepend this folder into $CRYSTAL_PATH.

now, i can use those methods defined in meta.cr, like this:

require "meta"

pp! "hello".methods
pp! String.class_methods