Create your first Conan package with Meson

In the Create your first Conan package tutorial CMake was used as the build system. If you haven’t read that section, read it first to familiarize yourself with the conanfile.py and test_package concepts, then come back to read about the specifics of the Meson package creation.

Use the conan new command to create a “Hello World” C++ library example project:

  1. $ conan new meson_lib -d name=hello -d version=1.0

This will create a Conan package project with the following structure.

  1. ├── conanfile.py
  2. ├── meson.build
  3. ├── hello.vcxproj
  4. ├── src
  5. ├── hello.h
  6. └── hello.cpp
  7. └── test_package
  8. ├── conanfile.py
  9. ├── meson.build
  10. └── src
  11. └── example.cpp

The structure and files are very similar to the previous CMake example:

  • conanfile.py: On the root folder, there is a conanfile.py which is the main recipe file, responsible for defining how the package is built and consumed.

  • meson.build: A Meson build script. This script doesn’t need to contain anything Conan-specific, it is completely agnostic of Conan, because the integration is transparent.

  • src folder: the folder that contains the simple C++ “hello” library.

  • test_package folder: contains an example application that will require and link with the created package. In this case the test_package also contains a meson.build, but it is possible to have the test_package using other build system as CMake if desired. It is not mandatory that the test_package is using the same build system as the package.

Let’s have a look at the package recipe conanfile.py (only the relevant new parts):

  1. exports_sources = "meson.build", "src/*"
  2. def layout(self):
  3. basic_layout(self)
  4. def generate(self):
  5. tc = MesonToolchain(self)
  6. tc.generate()
  7. def build(self):
  8. meson = Meson(self)
  9. meson.configure()
  10. meson.build()
  11. def package(self):
  12. meson = Meson(self)
  13. meson.install()

Let’s explain the different sections of the recipe briefly:

  • The layout() defines a basic_layout(), this is less flexible than a CMake one, so it doesn’t allow any parametrization.

  • The generate() method calls MesonToolchain that can generate conan_meson_native.ini and conan_meson_cross.ini Meson toolchain files for cross builds. If the project had dependencies with Conan requires, it should add PkgConfigDeps too

  • The build() method uses the Meson() helper to drive the build

  • The package() method uses the Meson install functionality to define and copy to the package folder the final artifacts.

The test_package folder also contains a meson.build file that declares a dependency to the tested package, and links an application, to verify the package was correctly created and contains that library:

test_package/meson.build

  1. project('Testhello', 'cpp')
  2. hello = dependency('hello', version : '>=0.1')
  3. executable('example', 'src/example.cpp', dependencies: hello)

Note the test_package/conanfile.py contains also a generators = "PkgConfigDeps", "MesonToolchain", because the test_package has the “hello” package as dependency, and PkgConfigDeps is necessary to locate it.

Note

This example assumes Meson, Ninja and PkgConfig are installed in the system, which might not always be the case. If they are not, you can create a profile myprofile with:

  1. include(default)
  2. [tool_requires]
  3. meson/[*]
  4. pkgconf/[*]

We added Meson and pkg-config as tool requirements to the profile. By executing conan create . -pr=myprofile, those tools will be installed and made available during the package’s build process.

Let’s build the package from sources with the current default configuration, and then let the test_package folder test the package:

  1. $ conan create .
  2. ...
  3. ======== Testing the package: Executing test ========
  4. hello/1.0 (test package): Running test()
  5. hello/1.0 (test package): RUN: .\example
  6. hello/1.0: Hello World Release!
  7. hello/1.0: _M_X64 defined
  8. hello/1.0: MSVC runtime: MultiThreadedDLL
  9. hello/1.0: _MSC_VER1939
  10. hello/1.0: _MSVC_LANG201402
  11. hello/1.0: __cplusplus201402
  12. hello/1.0 test_package

We can now validate that the recipe and the package binary are in the cache:

  1. $ conan list "hello/1.0:*"
  2. Local Cache:
  3. hello
  4. hello/1.0
  5. revisions
  6. 856c535669f78da11502a119b7d8a6c9 (2024-03-04 17:52:39 UTC)
  7. packages
  8. c13a22a41ecd72caf9e556f68b406569547e0861
  9. info
  10. settings
  11. arch: x86_64
  12. build_type: Release
  13. compiler: msvc
  14. compiler.cppstd: 14
  15. compiler.runtime: dynamic
  16. compiler.runtime_type: Release
  17. compiler.version: 193
  18. os: Windows

See also