Ghasem Ramezani
Ghasem Ramezani

Reputation: 2888

How To Package Binary Projects Using Conan?

The Problem:

The package's consumer couldn't load the package's binary's shared libraries.

find_package(MyThirdParty REQUIRED) # MyThirdParty is installed using Conan
find_program(binary_paty MyThirdParty REQUIRED)
execute_process(COMMAND ${binary_path} COMMAND_ERROR_IS_FATAL ANY)

The execute_process command will fail because the MyThirdParty's shared libraries are missing.

How could I package the third-party binary projects?

The Minimal Reproducible Example:

Third-party project:

file(WRITE Library.hh "void Func();")
file(WRITE Library.cc "void Func() {}")
add_library(Library SHARED Library.hh Library.cc)

file(WRITE Main.cc "#include \"Library.hh\"\nint main() { Func(); }")
add_executable(MyThirdParty Main.cc)
target_link_libraries(MyThirdParty PRIVATE Library)

install(TARGETS MyThirdParty Library EXPORT MyThirdPartyConfig)
install(EXPORT MyThirdPartyConfig
  NAMESPACE MyThirdParty::
  DESTINATION lib/cmake/MyThirdParty
)

My attempt for packaging the third-party with Conan:

from conans import ConanFile, CMake, tools

class MyThirdPartyConan(ConanFile):
  name = "MyThirdParty"
  version = "1.0.0"
  settings = "os", "compiler", "build_type", "arch"

  def source(self):
    tools.download(
      filename = "CMakeLists.txt",
      url = "https://gist.githubusercontent.com/gccore/9007084e1b307592ae040ceb5745bf5f/raw/419a96712145e8d24d4c9982ab3b7fd31d44b9f0/CMakeLists.txt")

  def build(self):
    cmake = CMake(self)
    cmake.configure()
    cmake.build()

  def package(self):
    cmake = CMake(self)
    cmake.install()

The consumer:

find_package(MyThirdParty REQUIRED)
find_program(binary_paty MyThirdParty REQUIRED)
execute_process(COMMAND ${binary_path} COMMAND_ERROR_IS_FATAL ANY)

And finally the conanfile.txt:

[requires]
MyThirdParty/1.0.0@Ghasem/Test

[generators]
cmake_find_package

But the consumer's CMake with the Conan package fails because of the third-party's shared library. When the consumer's CMake tries to execute the MyThirdParty binary it will fail because it couldn't find the libLibrary.so file.


My Environment:

  • OS: Fedora 35
  • Kernel: Linux 5.18.9-100.fc35.x86_64
  • Compiler: GCC 11.3.1 20220421
  • CMake: 3.22.2
  • Conan: 1.47.0

Upvotes: 0

Views: 407

Answers (1)

Ghasem Ramezani
Ghasem Ramezani

Reputation: 2888

On Linux we could use patchelf and change the binary RPATH during the packaging state:

def package(self):
  cmake = CMake(self);
  cmake.install();
  self.run("patchelf --set-rpath '$ORIGIN/../lib' " +
    self.package_folder + "/bin/MyThirdParty");

And for Windows just put the shared libraries files besides the binary, the Windows Linker/Loader doesn't try hard to be smart(like Linux's Linker/Loader does).

Upvotes: 2

Related Questions