Victor Paléologue
Victor Paléologue

Reputation: 2342

Build and run an executable locally with Conan

Say I have a simple hello world project in CMake that creates a binary under bin. I build it with Conan using the latest CMake module.

In the conanfile.py, is this package method enough to announce the executable?

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

Then, if I want to build the project and run the executable locally, but in Conan's context, which commands should I type?

Upvotes: 1

Views: 2800

Answers (1)

samuel-emrys
samuel-emrys

Reputation: 81

The package method you've defined will use the installation structure defined by cmake.install() to define the package structure. For example, if your cmake.install() method installs binaries to the bin directory, the bin directory will be present in the package folder in your conan cache, i.e. ~/.conan/data/<package>/<version>/<user>/<channel>/package/<package_id>/bin.

This alone is enough to run the executable locally - you can execute it from the above path, put it onto your PATH - whatever you need. It's not convenient though. To add some convenience, you can use the VirtualRunEnv generator to consume executables. To illustrate with cmake:

$ conan install cmake/3.22.4@ --build=missing -g VirtualRunEnv

This will install cmake 3.22.4 into your local cache, and generate the following files in your cwd:

.
├── conanrunenv-release-x86_64.sh
├── conanrun.sh
├── deactivate_conanrunenv-release-x86_64.sh
└── deactivate_conanrun.sh

You can use this in the same way you would a python virtual environment:

$ source conanrun.sh
$ which cmake
/home/user/.conan/data/cmake/3.22.4/_/_/package/5c09c752508b674ca5cb1f2d327b5a2d582866c8/bin/cmake

And to restore the environment:

$ source deactivate_conanrun.sh
Restoring environment
$ which cmake
/usr/bin/cmake

The second method is to use the deploy generator:

$ conan install cmake/3.22.4@ --build=missing -g deploy

This will grab cmake and all of it's dependencies from the conan cache and dump them to your cwd. After running this command, the directory looks like the following:

.
├── cmake
│   ├── bin
│   │   ├── ccmake
│   │   ├── cmake
│   │   ├── cpack
│   │   └── ctest
│   ├── licenses
│   │   └── Copyright.txt
│   └── share
│       ├── aclocal
│       ├── bash-completion
│       ├── cmake-3.22
│       ├── emacs
│       └── vim
├── deploy_manifest.txt
└── openssl
    ├── bin
    │   ├── c_rehash
    │   └── openssl
    ├── include
    │   └── openssl
    ├── lib
    │   ├── cmake
    │   ├── libcrypto.a
    │   └── libssl.a
    └── licenses
        └── LICENSE

You can then move this wherever you need to and put it on your system PATH if you so desire. The same principle would apply to your package - create the recipe in the local cache, and use generators to consume it.

To illustrate:

  1. Place your package in the conan cache
$ conan create .
  1. Consume it using VirtualRunEnv
$ conan install mypkg/0.1.0@user/channel --build=missing -g VirtualRunEnv
  1. Consume it using deploy
$ conan install mypkg/0.1.0@user/channel --build=missing -g deploy

Instead of issuing conan install commands above, you can also list your package as a requirement in a conanfile.txt or conanfile.py for a consumer package, i.e. for a conanfile.py:

def requirements(self):
    self.requires(mypkg/0.1.0)
    self.requires(someotherpkg/1.2.0)

And then you can use the virtual environment generators to collect environment information for all dependencies. In the directory containing the conanfile.py:

$ conan install . -g VirtualRunEnv

Hope this helps.

References:

Upvotes: 3

Related Questions