This document gathers all the relevant information regarding the general lines to follow while creating new recipes that will eventually be part of this repository.
Origin of sources:
-
Library sources should come from an official origin like the library source code repository or the official release/download webpage.
-
If an official source archive is available, it should be preferred over an auto-generated archive.
Source immutability: Downloaded source code stored under source
folder should not be modified. Any patch should be applied to the copy of this source code when a build is executed (basically in build()
method).
Building from sources: Recipes should always build packages from library sources.
Sources not accessible:
-
Library sources that are not publicly available will not be allowed in this repository even if the license allows their redistribution.
-
If library sources cannot be downloaded from their official origin or cannot be consumed directly due to their format, the recommendation is to contact the publisher and ask them to provide the sources in a way/format that can be consumed programmatically.
-
In case of needing those binaries to use them as a "build require" for some library, we will consider following the approach of adding it as a system recipe (
<build_require>/system
) and making those binaries available in the CI machines (if the license allows it).
-
Version range is not allowed.
-
Specify explicit RREV (recipe revision) of dependencies is not allowed.
-
Vendoring in library source code should be removed (best effort) to avoid potential ODR violations. If upstream takes care to rename symbols, it may be acceptable.
-
Only other conan-center recipes are allowed in
requires
/requirements()
andbuild_requires
/build_requirements()
of a conan-center recipe. -
If a requirement is conditional, this condition must not depend on build context. Build requirements don't have this constraint.
-
Forcing options of dependencies inside a conan-center recipe should be avoided, except if it is mandatory for the library.
-
build()
method should focus on build only, not installation. During the build, nothing should be written inpackage
folder. Installation step should only occur inpackage()
method. -
The build itself should only rely on local files. Nothing should be downloaded from internet during this step. If external files are required, they should come from
requirements
orbuild_requirements
, in addition to source files downloaded insource()
or coming from recipe itself. -
Except CMake and a working build toolchain (compiler, linker, archiver etc), the recipe should not assume that any other build tool is installed on user build machine (like Meson, autotools or pkg-config). On Windows, recipe should not assume that a shell is available (like MSYS2). Therefore, if the buid requires additional build tools, they should be added to
build_requirements()
. -
It is forbidden to run other conan client commands during build. In other words, if upstream build files call conan under the hood (through
cmake-conan
for example or any other logic), this logic must be neutralized. -
Settings from profile should be honored (
build_type
,compiler.libcxx
,compiler.cppstd
,compiler.runtime
etc). -
These env vars from profile should be honored and properly propagated to underlying build system during the build:
CC
,CXX
,CFLAGS
,CXXFLAGS
,LDFLAGS
.
-
CMake config files must be removed (they will be generated for consumers by
cmake_find_package
,cmake_find_package_multi
orCMakeDeps
generators). -
pkg-config files must be removed (they will be generated for consumers by
pkg_config
orPkgConfigDeps
generators). -
On *nix systems, executables and shared libraries should have empty
RPATH
/RUNPATH
/LC_RPATH
. -
On macOS, install name in
LC_ID_DYLIB
section of shared libs must be@rpath/<libfilename>
. -
Installed files must not contain absolute paths specific to build machine. Relative paths to other packages is also forbidden since relative paths of dependencies during build may not be the same for consumers. Hardcoded relative paths pointing to a location in the package itself are allowed.
All recipes should list the four settings os
, arch
, compiler
and build_type
so Conan will compute a different package ID
for each combination. There are some particular cases for this general rule:
-
Recipes for header only libraries might omit the
settings
attibute, but in any case they should adddef package_id(self): self.info.header_only()
-
Recipes that provide applications (
b2
,cmake
,make
,...) that are generally used as a build requires, must list all the settings as well, but they should remove thecompiler
one in the corresponding method unless the recipe provides also libraries that are consumed by other packages:def package_id(self): del self.settings.compiler
Removing the
compiler
setting reduces the number of configurations generated by the CI, reducing the time and workload and, at the same time, demonstrates the power of Conan behind the package ID logic.Note.- Intentionally, the
build_type
setting should not be removed from the package ID in this case. Preserving this setting will ensure that the package ID for Debug and Release configurations will be different and both binaries can be available in the Conan cache at the same time. This enable consumers to switch from one configuration to the other in the case they want to run or to debug those executables.
Recipes can list any number of options with any meaning, and defaults are up to the recipe itself. The CI cannot enforce anything in this direction. However, there are a couple of options that have a special meaning for the CI:
-
shared
(with valuesTrue
orFalse
). The CI inspects the recipe looking for this option. If it is found, it will generate all the configurations with valuesshared=True
andshared=False
.Note.- The CI applies
shared=True
only to the package being built, while every other requirement will use their defaults (typicallyshared=False
). It's important to keep this in mind when trying to consume shared packages from ConanCenter as their requirements were linked inside the shared library. See FAQs for more information. -
header_only
(with valuesTrue
orFalse
). If the CI detects this option, it will generate all the configurations for the valueheader_only=False
and add one more configuration withheader_only=True
. Only one package will be generated forheader_only=True
, so it is crucial that the package is actually a header only library, with header files only (no libraries or executables inside).Recipes with such option should include the following in their
package_id
methoddef package_id(self): if self.options.header_only: self.info.header_only()
ensuring that, when the option is active, the recipe ignores all the settings and only one package ID is generated.