Skip to content

Don't set LD_LIBRARY_PATH on package load#28354

Merged
tgamblin merged 1 commit intospack:developfrom
haampie:fix/dont-set-LD_LIBRARY_PATH-on-load
Aug 11, 2022
Merged

Don't set LD_LIBRARY_PATH on package load#28354
tgamblin merged 1 commit intospack:developfrom
haampie:fix/dont-set-LD_LIBRARY_PATH-on-load

Conversation

@haampie
Copy link
Copy Markdown
Member

@haampie haampie commented Jan 11, 2022

For me this has been mostly just annoying, cause if I do
spack env activate ... and it sets LD_LIBRARY_PATH, system executables that don't
use rpath will now consider spack-built libs first, and are sometimes
incompatible.

And executables built by Spack already use rpath anyways, so they know
where there libs are.

The only case is maybe when libs are dlopen'ed by say Python, but even
then, I think the libs are generally located because of Python's own
rpaths set by Spack.

Closes #3955 #31731

@spackbot-app spackbot-app bot added defaults documentation Improvements or additions to documentation shell-support labels Jan 11, 2022
@haampie haampie force-pushed the fix/dont-set-LD_LIBRARY_PATH-on-load branch from 9bb89ca to 7ebdff6 Compare January 11, 2022 13:46
Copy link
Copy Markdown
Member

@adamjstewart adamjstewart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR will break most Python/SCons packages with external dependencies. Python does not properly support RPATHs.

- LD_LIBRARY_PATH
lib64:
- LD_LIBRARY_PATH
modules: {}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If these files are no longer being used they can just be removed

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That made the tests fail :( didn't check why, but then I thought it wouldn't hurt as a blueprint

@haampie
Copy link
Copy Markdown
Member Author

haampie commented Jan 11, 2022

Can't PythonPackage set LD_LIBRARY_PATH for link type deps that are meant to be dlopen'ed? Just like PYTHONPATH

@adamjstewart
Copy link
Copy Markdown
Member

It can, although that will make it even harder to get rid of setup_dependent_*_environment.

lib:
- DYLD_FALLBACK_LIBRARY_PATH
lib64:
- DYLD_FALLBACK_LIBRARY_PATH
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand your concern with LD_LIBRARY_PATH, but this issue does not arise with DYLD_FALLBACK_LIBRARY_PATH. On macOS, there are two env vars that control library selection at load-time: DYLD_LIBRARY_PATH and DYLD_FALLBACK_LIBRARY_PATH. The former acts just like LD_LIBRARY_PATH and can break system exes that aren't RPATHed. The latter acts more like RUNPATH and provides libraries to use only when the libraries aren't found in normal search locations. So I think it's safe to keep these here.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, reverted that, it's just about linux now.

@haampie
Copy link
Copy Markdown
Member Author

haampie commented Mar 7, 2022

This PR will break most Python packages with external dependencies. Python does not properly support RPATHs.

Is this really true @adamjstewart? Don't python packages usually call C functions through a generated wrapper library that does have rpaths already?

For instance when running ./bin/python directly without activating an environment, and running import numpy, I get:

$ cat /proc/451559/maps | grep openblas
7f7218ad1000-7f7218b40000 r--p 00000000 103:04 40283657                  /home/harmen/spack/opt/spack/linux-ubuntu20.04-zen2/gcc-10.3.0/openblas-0.3.19-ixyrqkwedhttcxokzzczho4zefy7b3ji/lib/libopenblas_zen-r0.3.19.so

so it manages to load libraries without LD_LIBRARY_PATH just fine.

And can you explain what you mean with SCons given that LD_LIBRARY_PATH is runtime.

@haampie haampie force-pushed the fix/dont-set-LD_LIBRARY_PATH-on-load branch from 8453847 to ed38dad Compare March 7, 2022 13:46
@salotz-sitx
Copy link
Copy Markdown

When I load an environment and LD_LIBRARY_PATH is set this sometimes conflicts with the distro installed packages that depend on dynamic linking via that variable. This can cause segfaults to occur depending on the versions. I haven't experienced a segfault myself (Ubuntu 18.04) but a coworker has with Ubuntu 21.04 with nano.

E.g.:

--> ldd /usr/bin/python3
	linux-vdso.so.1 (0x00007ffc9603d000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fce3ef58000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fce3ed39000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fce3eb35000)
	libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007fce3e932000)
	libexpat.so.1 => /home/salotz/scratch/mdutil/.spack-env/view/lib/libexpat.so.1 (0x00007fce3e6fe000)
	libz.so.1 => /home/salotz/scratch/mdutil/.spack-env/view/lib/libz.so.1 (0x00007fce3e4e7000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fce3e149000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fce3f349000)
	libbsd.so.0 => /home/salotz/spack/opt/spack/linux-ubuntu18.04-skylake/gcc-7.5.0/libbsd-0.11.3-rkyd4ndtgypgsbhazhd4dwbflwskzf36/lib/libbsd.so.0 (0x00007fce3df34000)
	libmd.so.0 => /home/salotz/spack/opt/spack/linux-ubuntu18.04-skylake/gcc-7.5.0/libmd-1.0.3-fwt4srl6qp7veimuan65dc23zzobjkpr/lib/libmd.so.0 (0x00007fce3dd28000)

@adamjstewart
Copy link
Copy Markdown
Member

Is this really true @adamjstewart? Don't python packages usually call C functions through a generated wrapper library that does have rpaths already?

Most Python libraries use ctypes.util.find_library, which searches typical system locations and environment variables only. Packages like numpy which hardcode the library location in setup.cfg are the exception, not the rule. If you want to reproduce this, try py-shapely, that's the first example that comes to mind. The same is true for most geospatial Python libs.

Can't PythonPackage set LD_LIBRARY_PATH for link type deps that are meant to be dlopen'ed? Just like PYTHONPATH

If we do push through with this PR, we'll have to do this if we don't want to break hundreds of packages.

@adamjstewart
Copy link
Copy Markdown
Member

I know I've been the main person opposing this for years, but I'm starting to warm up to this idea. I think the packages that require LD_LIBRARY_PATH are few enough that we can special case them. Now might be a good time to merge this and see what breaks since we just had a release.

@haampie
Copy link
Copy Markdown
Member Author

haampie commented Jul 25, 2022

So, should we merge it?

@adamjstewart
Copy link
Copy Markdown
Member

I'm fine with that but would like to get the opinions of a couple more core devs first.

@spackbot-app spackbot-app bot added the core PR affects Spack core functionality label Aug 9, 2022
@haampie haampie force-pushed the fix/dont-set-LD_LIBRARY_PATH-on-load branch from 39054ff to 12c0a30 Compare August 9, 2022 14:48
@haampie haampie requested a review from tgamblin August 9, 2022 14:54
@tgamblin
Copy link
Copy Markdown
Member

tgamblin commented Aug 9, 2022

I am strongly in favor of this change -- the question is what to do for people who relied on this stuff. Basically I think Spack should work and loading an environment should not affect your compiler or ld.so. So I agree with removing:

  • LD_LIBRARY_PATH
  • LIBRARY_PATH
  • CPATH

The last two AFAIK don't work on all compilers anyway, so it's at best inconsistent to set them.

@haampie: could you modify this, though, so that we set these?

  • SPACK_LIBRARY_PATH
  • SPACK_INCLUDE_PATH

to the prior values of LD_LIBRARY_PATH/LIBRARY_PATH and CPATH, respectively? And document it?

That way someone who loads an env will have something they can use to set the variables they need, but we won't be borking the user environment by default.

@tgamblin
Copy link
Copy Markdown
Member

tgamblin commented Aug 9, 2022

I added this here since it's a fairly impactful change: #30634

@haampie
Copy link
Copy Markdown
Member Author

haampie commented Aug 9, 2022

Note that CPATH and LIBRARY_PATH were already removed long ago. To hit the code path in prefix_inspections where you get CPATH and LIBRARY_PATH, you need to delete all modules.yaml config files including $spack/etc/defaults/modules.yaml, which seems unlikely. This PR just fixes some oversights wrt CPATH/LIBRARY_PATH.

So this PR is really about LD_LIBRARY_PATH only.

could you modify this, though, so that we set these?

Do you mean to store <prefix>/lib(64)? in SPACK_LD_LIBRARY_PATH so users can do LD_LIBRARY_PATH=$SPACK_LD_LIBRARY_PATH if they want the previous behavior? I would say users can just change the config files, right? E.g.

spack config add modules:prefix_inspections:lib64:[LD_LIBRARY_PATH]
spack config add modules:prefix_inspections:lib:[LD_LIBRARY_PATH]

Also, can we run a pipeline from scratch using this PR? It affects the builds too (note that modules:prefix_inspections is also used to set up the build environment).

@tgamblin
Copy link
Copy Markdown
Member

tgamblin commented Aug 9, 2022

Do you mean to store /lib(64)? in SPACK_LD_LIBRARY_PATH so users can do LD_LIBRARY_PATH=$SPACK_LD_LIBRARY_PATH if they want the previous behavior?

Yes.

spack config add modules:prefix_inspections:lib64:[LD_LIBRARY_PATH]
spack config add modules:prefix_inspections:lib:[LD_LIBRARY_PATH]

They could do this, but IMO it's a little clunky, and having the env vars allows you do do more -- e.g., you may want to pass the list of transitive library search directories to CMake or use it on your link line or something. I'm basically saying that we should have a convention for that and throw it in a harmless env var (as opposed to a harmful one like now).

Users will be familiar with this from module schemes like OpenHPC, where they have a similar policy. I think it's a good default.

@adamjstewart
Copy link
Copy Markdown
Member

I personally agree with @haampie, if people want to set additional env vars in module files, Spack already has a way to do that, we don't need to set SPACK_* env vars for them to use instead.

@tgamblin
Copy link
Copy Markdown
Member

tgamblin commented Aug 9, 2022

I personally agree with @haampie, if people want to set additional env vars in module files, Spack already has a way to do that, we don't need to set SPACK_* env vars for them to use instead.

Ok fair enough -- I'll relent. They can add those settings via spack config. Can that please be documented here, though?

@adamjstewart
Copy link
Copy Markdown
Member

Worth documenting in the release notes too since it's a backwards incompatible change.

@tgamblin tgamblin changed the title Don't set LD_LIBRARY_PATH on pkg load Don't set LD_LIBRARY_PATH on package load Aug 11, 2022
@tgamblin tgamblin changed the title Don't set LD_LIBRARY_PATH on package load Don't set LD_LIBRARY_PATH on package load Aug 11, 2022
@tgamblin tgamblin merged commit ceda5fb into spack:develop Aug 11, 2022
@haampie haampie deleted the fix/dont-set-LD_LIBRARY_PATH-on-load branch August 15, 2022 07:28
@h-murai
Copy link
Copy Markdown
Contributor

h-murai commented Aug 25, 2022

How about the case where you load a library by Spack and then link your objects with the library?

$ spack load fftw
$ gcc foo.c -lfftw3

Does it work after this change?

@jbigot
Copy link
Copy Markdown
Member

jbigot commented Sep 1, 2022

How about the case where you load a library by Spack and then link your objects with the library?

$ spack load fftw
$ gcc foo.c -lfftw3

Does it work after this change?

This is my exact use-case (although with en environment) we distribute a spack env that people wanting to hack on our just have to load to start working. I recently noticed LD_LIBRARY_PATH is not set by the env anymore. With cmake, deps are still found ok, but as soon as you try to run the compiled code, it doesn't work anymore.

@jbigot
Copy link
Copy Markdown
Member

jbigot commented Sep 1, 2022

could a flag be provided to explicitly ask for LD_LIBRARY_PATH to be set?

@adamjstewart
Copy link
Copy Markdown
Member

The set of environment variables added by Spack is completely customizable. Although LD_LIBRARY_PATH is no longer added by default, you can add it to your Spack installation like so:

$ spack config add modules:prefix_inspections:lib64:[LD_LIBRARY_PATH]
$ spack config add modules:prefix_inspections:lib:[LD_LIBRARY_PATH]

After this, spack load ... will work identically to the way that it used to. See https://spack.readthedocs.io/en/latest/module_file_support.html#write-a-configuration-file for examples of what this will look like, the above command just writes this file for you. Note that you may need to specify that this is added to your environment, or to a global scope so that it affects all users, not just you.

Does that address your concerns?

@jbigot
Copy link
Copy Markdown
Member

jbigot commented Sep 2, 2022

thank you for the pointer. Indeed, this should do the trick!

psychocoderHPC added a commit to psychocoderHPC/picongpu that referenced this pull request Oct 7, 2022
Add option `PIC_ADD_RPATH` to controll if picongpu is setting the rpath.
By default PIConGPU will now always use RPATH but optionally allow
disabling this and falling back to the old behaviour.

Using rpath's is motivated by the spack where `LD_LIBRARY_PATH` is not set anymore: spack/spack#28354
psychocoderHPC added a commit to psychocoderHPC/picongpu that referenced this pull request Oct 7, 2022
Add option `PIC_ADD_RPATH` to control if picongpu is setting the rpath. By default, PIConGPU will now always use RPATH but optionally allow disabling this and falling back to the old behavior.

Using rpath's is motivated by the spack where `LD_LIBRARY_PATH` is not set anymore: spack/spack#28354
psychocoderHPC added a commit to psychocoderHPC/cuda_memtest that referenced this pull request Oct 7, 2022
Add option `CUDA_MEMTEST__ADD_RPATH` to control if cuda_memtest is setting the rpath.
The new default is that RPATH will be used but optionally allow disabling this and falling back to the old behaviori.

Using rpath's is motivated by the spack where `LD_LIBRARY_PATH` is not set anymore: spack/spack#28354
pordyna pushed a commit to pordyna/picongpu that referenced this pull request Oct 19, 2022
Add option `PIC_ADD_RPATH` to control if picongpu is setting the rpath. By default, PIConGPU will now always use RPATH but optionally allow disabling this and falling back to the old behavior.

Using rpath's is motivated by the spack where `LD_LIBRARY_PATH` is not set anymore: spack/spack#28354
@fspiga
Copy link
Copy Markdown
Contributor

fspiga commented Nov 3, 2022

Today I discovered while I was doing a fresh build, I discovered generated TCL modules do not export anymore LD_LIBRARY_PATH.

Spack has been an extremely useful tool to install packages, self-build modules, expose to users these modules that can be used by users using module load in the old fashion way. Many end users do not really need to know spack exists or learning spack commands.

Please documents very visibly the workaaround

$ spack config add modules:prefix_inspections:lib64:[LD_LIBRARY_PATH]
$ spack config add modules:prefix_inspections:lib:[LD_LIBRARY_PATH]

because a lot of your users and sysadmins will likely need it.

@haampie
Copy link
Copy Markdown
Member Author

haampie commented Nov 3, 2022

Feel free to make a PR

jdenny-ornl added a commit to llvm-doe-org/llvm-project that referenced this pull request May 5, 2023
* As discussed at <spack/spack#28354>, spack
  no longer sets `LD_LIBRARY_PATH`, which makes it harder to run
  applications compiled by a spack-installed Clacc.  This patch adds
  the spack config workaround suggested there.
* Spack's Clacc recipe hasn't been updated since libcxx and libunwind
  are considered runtimes not projects in LLVM.  This patch disables
  their builds where that causes a failure.
* This patch removes the hwloc.h instructions for spack installs on
  leconte as they no longer appear to be necessary.
* This patch updates various ExCL software packages.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core PR affects Spack core functionality defaults documentation Improvements or additions to documentation shell-support

Projects

None yet

8 participants