共享库在运行时加载。 应用程序可执行文件在运行时需要知道在哪里可以找到所需的共享库。
根据操作系统的不同,我们可以使用环境变量来帮助动态链接器查找共享库:
操作系统 | 环境变量 |
---|---|
WINDOWS | PATH |
LINUX | LD_LIBRARY_PATH |
OSX | DYLD_LIBRARY_PATH |
如果您的软件包配方(A)正在生成共享库,则可以声明指向软件包目录的所需环境变量。 这样,依赖于(A)的任何其他软件包都将自动设置正确的环境变量,因此他们将能够找到(A)共享库。
同样,如果您使用virtualenv生成器并将其激活,则将获得在终端中定位共享库所需的路径。
例子
我们正在将一个名为toolA的工具与一个库和一个可执行文件打包在一起,例如,它将压缩数据。
该软件包提供了两种形式,共享库或静态库(嵌入在该工具的可执行文件中,可与之链接)。 您可以使用toolA软件包库来开发另一个可执行文件或库,也可以只使用软件包提供的可执行文件。 在这两种情况下,如果您选择安装工具A的共享软件包,则将需要使共享库可用。
import os
from conans import tools, ConanFile
class ToolA(ConanFile):
....
name = "tool_a"
version = "1.0"
options = {"shared": [True, False]}
default_options = {"shared": False}
def build(self):
# build your shared library
def package(self):
# Copy the executable
self.copy(pattern="tool_a*", dst="bin", keep_path=False)
# Copy the libraries
if self.options.shared:
self.copy(pattern="*.dll", dst="bin", keep_path=False)
self.copy(pattern="*.dylib", dst="lib", keep_path=False)
self.copy(pattern="*.so*", dst="lib", keep_path=False)
else:
...
使用其他套件中的工具
如果现在正在创建一个使用tool_a可执行文件压缩某些数据的包,则可以使用RunEnvironment构建助手直接执行tool_a来相应地设置环境变量:
import os
from conans import tools, ConanFile
class PackageB(ConanFile):
name = "package_b"
version = "1.0"
requires = "tool_a/1.0@myuser/stable"
def build(self):
exe_name = "tool_a.exe" if self.settings.os == "Windows" else "tool_a"
self.run([exe_name, "--someparams"], run_environment=True)
...
使用来自tool_a的共享库构建应用程序
在构建最终应用程序时,我们可能希望将其与来自tool_a的共享库一起分发,因此我们可以使用Imports将所需的共享库导入到我们的用户空间。
conanfile.txt
[requires]
tool_a/1.0@myuser/stable
[generators]
cmake
[options]
tool_a:shared=True
[imports]
bin, *.dll -> ./bin # Copies all dll files from packages bin folder to my "bin" folder
lib, *.dylib* -> ./bin # Copies all dylib files from packages lib folder to my "bin" folder
lib, *.so* -> ./bin # Copies all so files from packages lib folder to my "bin" folder
现在您可以构建项目:
$ mkdir build && cd build
$ conan install ..
$ cmake .. -G "Visual Studio 14 Win64"
$ cmake --build . --config Release
$ cd bin && mytool
前面的示例仅在Windows和OSX(更改CMake生成器)中有效,因为动态链接器将在我们也复制共享库的当前目录(二进制目录)中查找。
在Linux中,您仍然需要设置LD_LIBRARY_PATH,在OSX中,则需要设置DYLD_LIBRARY_PATH:
$ cd bin && LD_LIBRARY_PATH=$(pwd) && ./mytool
从依赖项使用共享库
如果您要执行依赖于属于您的依赖项的共享库的内容,则必须在运行时找到这些共享库。 在Windows中,如果程序包将其二进制文件夹添加到系统PATH中就足够了。 在Linux和OSX中,必须使用LD_LIBRARY_PATH和DYLD_LIBRARY_PATH环境变量。
安全限制可能适用于OSX(请阅读此线程),因此DYLD_LIBRARY_PATH和DYLD_FRAMEWORK_PATH环境变量不会直接传输到子进程。 在这种情况下,您必须在conanfile.py中显式使用它:
def build(self):
env_build = RunEnvironment(self)
with tools.environment_append(env_build.vars):
# self.run("./myexetool") # won't work, even if 'DYLD_LIBRARY_PATH' and 'DYLD_FRAMEWORK_PATH' are in the env
self.run("DYLD_LIBRARY_PATH=%s DYLD_FRAMEWORK_PATH=%s ./myexetool" % (os.environ['DYLD_LIBRARY_PATH'], os.environ['DYLD_FRAMEWORK_PATH']))
或者,您可以使用上述RunEnvironment帮助程序。
使用virtualrunenv生成器
virtualrunenv生成器将自动设置指向lib和bin文件夹的环境变量PATH,LD_LIBRARY_PATH,DYLD_LIBRARY_PATH。
conanfile.txt
[requires]
tool_a/1.0@myuser/stable
[options]
tool_a:shared=True
[generators]
virtualrunenv
在终端窗口中:
$ conan install .
$ source activate_run
$ tool_a --someparams
# Only For Mac OS users to avoid restrictions:
$ DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH toolA --someparams