Repository: conan-io/conan-center-index

Issue:
[bug] vulkan-validationlayers/1.3.239.0: Cannot load libVkLayer_khronos_validation.so at runtime
### Description

`libVkLayer_khronos_validation.so` is a runtime requirement of any application that consumes `vulkan-validationlayers`, which technically produces a static library (it produces both the static and dynamic libraries, but only the static library should be linked). `libVkLayer_khronos_validation.so` should not be linked with the consumer, but is instead dynamically loaded via `vulkan-loader`, which uses `$VK_LAYER_PATH` to read `libVkLayer_khronos_validation.json` to identify the library, which contains the path to `libVkLayer_khronos_validation.so`. This looks like the following:
```
{
    "file_format_version": "1.2.0",
    "layer": {
        "name": "VK_LAYER_KHRONOS_validation",
        "type": "GLOBAL",
        "library_path": "libVkLayer_khronos_validation.so",
        "api_version": "1.3.239",
...
```
Unfortunately, the recipe doesn't populate `LD_LIBRARY_PATH` on linux, and so when searching for `libVkLayer_khronos_validation.so`, the application can't find it.

There are a few potential fixes to this:

1. Manually add `self.libdirs` to `LD_LIBRARY_PATH`, `PATH`, `DYLD_LIBRARY_PATH`
2. Set `package_type="shared-library"`
3. Require consumers to depend on this with `self.requires("vulkan-validationlayers/1.3.239.0", run=True)`
4. Try to patch `libVkLayer_khronos_validation.json` after creation so that `library_path` contains a relative path to the `lib` directory in its own package

### Package and Environment Details

* Package Name/Version: **vulkan-validationlayers/1.3.239.0**
* Operating System+version: **Arch Linux**
* Compiler+version: **GCC 13.2**
* Docker image: N/A
* Conan version: **conan 2.0.10**
* Python version: **Python 3.11.1**


### Conan profile

======== Input profiles ========                                                                                                            
Profile host:                                                                                                                               
[settings]                                                                                                                                  
arch=x86_64                                                                                                                                 
build_type=Release                                                                                                                          
compiler=gcc                                                                                                                                
compiler.cppstd=20                                                                                                                          
compiler.libcxx=libstdc++11                                                                                                                 
compiler.version=12                                                                                                                         
os=Linux                                                                                                                                    
&:build_type=Debug                                                                                                                          
[conf]                                                                                                                                      
tools.build:compiler_executables={'c': '/usr/bin/gcc', 'cpp': '/usr/bin/g++'}                                                               
                                                                                                                                            
Profile build:                                                                                                                              
[settings]                                                                                                                                  
arch=x86_64                                                                                                                                 
build_type=Release                                                                                                                          
compiler=clang                                                                                                                              
compiler.cppstd=20                                                                                                                          
compiler.libcxx=libstdc++11                                                                                                                 
compiler.version=15                                                                                                                         
os=Linux                                                                                                                                    
[conf]                                                                                                                                      
tools.build:compiler_executables={'c': '/usr/bin/clang', 'cpp': '/usr/bin/clang++'}

### Steps to reproduce

1. `git clone -b bug/vulkan-validationlayers https://github.com/samuel-emrys/vulkan-tutorial.git`
2. `conan build . -s "&:build_type=Debug"` # The build type is important here
3. `source build/Debug/generators/conanrun.sh`
4. `./build/Debug/src/vulkantutorial`
5. Observe the following:

```bash
$ ./build/Debug/src/vulkantutorial
validation layer: Searching for ICD drivers named libGLX_nvidia.so.0                                                                        
validation layer: Searching for ICD drivers named /usr/lib32/amdvlk32.so                                                                    
validation layer: Build ICD instance extension list                                                                                         
validation layer: libVkLayer_khronos_validation.so: cannot open shared object file: No such file or directory                               
validation layer: Requested layer VK_LAYER_KHRONOS_validation failed to load!                                                               
failed to create instance!  
```

### Logs

<details><summary>Click to expand log</summary>

```
Put your log output here
```

</details>



Discussion:

Resolving patch:
diff --git a/recipes/vulkan-validationlayers/all/conanfile.py b/recipes/vulkan-validationlayers/all/conanfile.py
--- a/recipes/vulkan-validationlayers/all/conanfile.py
+++ b/recipes/vulkan-validationlayers/all/conanfile.py
@@ -225,5 +225,17 @@ def package_info(self):
         manifest_subfolder = "bin" if self.settings.os == "Windows" else os.path.join("res", "vulkan", "explicit_layer.d")
         vk_layer_path = os.path.join(self.package_folder, manifest_subfolder)
         self.runenv_info.prepend_path("VK_LAYER_PATH", vk_layer_path)
+
+        # Update runtime discovery paths to allow libVkLayer_khronos_validation.{so,dll,dylib} to be discovered
+        # and loaded by vulkan-loader when the consumer executes
+        # This is necessary because this package exports a static lib to link against and a dynamic lib to load at runtime
+        runtime_lib_discovery_path = "LD_LIBRARY_PATH"
+        if self.settings.os == "Windows":
+            runtime_lib_discovery_path = "PATH"
+        if self.settings.os == "Macos":
+            runtime_lib_discovery_path = "DYLD_LIBRARY_PATH"
+        for libdir in [os.path.join(self.package_folder, libdir) for libdir in self.cpp_info.libdirs]:
+            self.runenv_info.prepend_path(runtime_lib_discovery_path, libdir)
+
         # TODO: to remove after conan v2, it allows to not break consumers still relying on virtualenv generator
         self.env_info.VK_LAYER_PATH.append(vk_layer_path)


Test patch: