# Setting ENV for a shared library in \_\_init\_\_

**URL:** <https://discourse.julialang.org/t/setting-env-for-a-shared-library-in-init/24724>\
**Category:** General Usage\
**Tags:** question\
**Created:** [May 29, 2019, 11:27am UTC](https://discourse.julialang.org/t/setting-env-for-a-shared-library-in-init/24724 "2019-05-29T11:27:55Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![visr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/visr/32/17204_2.png) [@visr](https://discourse.julialang.org/u/visr)\
**Post date:** [May 29, 2019, 11:27am UTC](https://discourse.julialang.org/t/setting-env-for-a-shared-library-in-init/24724/1 "2019-05-29T11:27:55Z")

</div>

In [this GDAL.jl PR](https://github.com/JuliaGeo/GDAL.jl/pull/66) I want to set an environment variable `PROJ_LIB` that one of the underlying shared libraries uses to find resources. If I set this environment globally, in the shell, or in `startup.jl` with `ENV["PROJ_LIB"] = ...` the shared library picks it up as expected.

However I don’t want to ask users to do this, so I wanted to set `ENV["PROJ_LIB"] = ...` in the module’s ` __init__ ` function. In this case the shared library does not pick it up and I wonder why. Julia itself does pick it up:

```julia
module A
__init__ () = ENV["ABC"] = "2"
end

using Main.A
ENV["ABC"] # => "2"

```

Any ideas for why this happens or how I can make it work? I find it particularly strange that it works from `startup.jl` but not from ` __init__ `, also when I set `ENV` before `check_deps()`, which is presumably the moment it loads the libraries.

---

<div class="post-metadata">

**Author:** ![c42f](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/c42f/32/52842_2.png) [@c42f](https://discourse.julialang.org/u/c42f)\
**Post date:** [May 31, 2019, 1:39am UTC](https://discourse.julialang.org/t/setting-env-for-a-shared-library-in-init/24724/2 "2019-05-31T01:39:47Z")

</div>

Poking around inside the current libproj, I came across `proj_context_set_search_paths` (legacy api `pj_set_searchpath`). I didn’t get to the bottom of your problem, but this should be better than using the environment variable.

For even more powerful integration with proj’s resource discovery there’s also `proj_context_set_file_finder` for custom resource search, and `pj_ctx_set_fileapi` to define how resources are loaded.

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [May 31, 2019, 4:22am UTC](https://discourse.julialang.org/t/setting-env-for-a-shared-library-in-init/24724/3 "2019-05-31T04:22:14Z")

</div>

Is this environment variable read at the time when the external library is opened? If that’s the case, I guess ` __init__ ` is too late to do this. I remember that I couldn’t change `dlopen` option if the library is `ccall`ed from the module (but I’m not super sure about this).

---

<div class="post-metadata">

**Author:** ![visr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/visr/32/17204_2.png) [@visr](https://discourse.julialang.org/u/visr)\
**Post date:** [May 31, 2019, 9:24am UTC](https://discourse.julialang.org/t/setting-env-for-a-shared-library-in-init/24724/4 "2019-05-31T09:24:14Z")

</div>

> [@tkf](#):
>
> Is this environment variable read at the time when the external library is opened? If that’s the case, I guess ` __init__ ` is too late to do this.

It seems indeed that ` __init__ ` is too late. Recently the [` __init__ ` docs were written](https://github.com/JuliaLang/julia/pull/31930/files). It is called after all statements in the module have been executed. Does having functions with `ccall` in there cause the library to be dlopened already? Seems like it. I believe in general libraries load in their copy of environment variables at that time, such that setting it later is useless. Because [it does look like](https://github.com/OSGeo/proj.4/blob/6.1.0/src/open_lib.cpp#L220-L221) PROJ just does a runtime getenv.

If this is the case that might be worth clarification in the ` __init__ ` docs.

> [@c42f](#):
>
> this should be better than using the environment variable

Yeah indeed. Currently for `GDAL_DATA` we do both methods, `CPLSetConfigOption` and `ENV`. `ENV` [was added at the time for parallel processes](https://github.com/JuliaGeo/GDAL.jl/issues/49#issuecomment-403077530). Though a quick test now shows that this works with `CPLSetConfigOption` only, and not at all with `ENV` only (which is consistent with my assumptions in the paragraph above).

I’ll focus then on trying to set it directly in PROJ with one of the functions you mentioned. Though I have not been successful so far, which is why I came back to `ENV`. I tried [`proj_context_set_search_paths`](https://github.com/JuliaGeo/GDAL.jl/pull/66/commits/54cc2e192566f808f0d30241cadf09541fcbeb25) and [`proj_context_set_file_finder`](https://github.com/JuliaGeo/GDAL.jl/commit/d9a932b9699d3d08f60f8a376963329e3e6df7d9). It’s a bit tricky to have a clear mental model of what is happening, since PROJ is only loaded indirectly by GDAL, so not sure how to work with the contexts.

---

<div class="post-metadata">

**Author:** ![c42f](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/c42f/32/52842_2.png) [@c42f](https://discourse.julialang.org/u/c42f)\
**Post date:** [May 31, 2019, 9:35am UTC](https://discourse.julialang.org/t/setting-env-for-a-shared-library-in-init/24724/5 "2019-05-31T09:35:21Z")

</div>

> [@visr](#):
>
> I’ll focus then on trying to set it directly in PROJ with one of the functions you mentioned. Though I have not been successful so far, which is why I came back to `ENV` . I tried [`proj_context_set_search_paths`](https://github.com/JuliaGeo/GDAL.jl/pull/66/commits/54cc2e192566f808f0d30241cadf09541fcbeb25) and [`proj_context_set_file_finder`](https://github.com/JuliaGeo/GDAL.jl/commit/d9a932b9699d3d08f60f8a376963329e3e6df7d9). It’s a bit tricky to have a clear mental model of what is happening, since PROJ is only loaded indirectly by GDAL, so not sure how to work with the contexts.

Oh right. Perhaps GDAL is overriding those settings itself or using a custom proj context?

---

<div class="post-metadata">

**Author:** ![visr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/visr/32/17204_2.png) [@visr](https://discourse.julialang.org/u/visr)\
**Post date:** [May 31, 2019, 11:11am UTC](https://discourse.julialang.org/t/setting-env-for-a-shared-library-in-init/24724/6 "2019-05-31T11:11:58Z")

</div>

I tried looking into this a little, and found [ogr\_proj\_p.h](https://github.com/OSGeo/gdal/blob/v3.0.0/gdal/ogr/ogr_proj_p.h) and [ogr\_proj\_p.cpp](https://github.com/OSGeo/gdal/blob/v3.0.0/gdal/ogr/ogr_proj_p.cpp).

So there is a private header that provides `OSRGetProjTLSContext`. Not sure why this is private or how to make it public, because I can’t seem to `ccall` it in `libgdal`. The cpp file also has `OSRSetPROJSearchPaths`. Perhaps I need to patch the [GDALBuilder](https://github.com/JuliaGeo/GDALBuilder) in some way? I would think this would need to be exposed in the C API.

---

<div class="post-metadata">

**Author:** ![visr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/visr/32/17204_2.png) [@visr](https://discourse.julialang.org/u/visr)\
**Post date:** [May 31, 2019, 2:23pm UTC](https://discourse.julialang.org/t/setting-env-for-a-shared-library-in-init/24724/7 "2019-05-31T14:23:31Z")

</div>

Ah great, turns out `OSRSetPROJSearchPaths` is part of the GDAL C API after all, and it works [if I call this function](https://github.com/JuliaGeo/GDAL.jl/pull/66/files#diff-f3076f21ed4e6738593ae9f3c07b5341). Thanks for the help both!
