LICENSE.md

Bincrafters recipe files should always be MIT license, and that is what should exist in the repository in a file by the name LICENSE.md. See the section below

CMakeLists.txt

The template repository now features CMakeLists.txt template, which is listed in an export in the template conanfile.txt. This is a wrapper that should be used when building all libraries which use CMake for the build, even when it has no dependencies. You can tweak and add flags in this file, but most times it just serves to enforce the “Conan-managed” settings and attributes during the build. If the target library does not use CMake, delete this file and remote the import of the Cmake helper from the conanfile.py.

conanfile.py

We have conventions for most of the fields of conanfile.py.

url

Always use the URL of the git repo of the recipe, not the original library.

homepage

Always use the URL of the original library.

license

Always name the license of the original library. If possible, please use SPDX license identifier https://spdx.org/licenses/

short_paths

Only use if the library won’t build otherwise, OR if the library has to be built with Cygwin on Windows. Again, always use with Cygwin builds, otherwise, if there is a space in some users profile path and they choose to build from sources with –build, it will fail.

name

As of December, use only lowercase letters in package names moving forward. We will be renaming old packages to be all-lowercase.

version

Always use the version of the upstream package. There are some challenges in some cases, such as those which lack semver, or those that are currently un-released. Strategies for these cases are described below.

Packages without official releases

The notation shown below is used for publishing packages where the original library does not make official releases. Thus we use a datestamp to show when the package was created:

gsl_microsoft/20171020@bincrafters/stable

Packages without semantic versioning

The same notation is used for publishing packages where the original library does have official releases, but does not use semantic versioning. In this case, the version number is the one provided from the original library. In the case of msys2_installer, the library happens to use a datestamp:

msys2_installer/20161025@bincrafters/stable

Conan “latest” version convention

In some cases a version alias of “latest” is added to packages. Users can reference this version in requirements as shown in the example below to get the latest release without specifying a specific version or range:

msys2_installer/latest@bincrafters/stable

Note that using the latest alias will cause your projects to download and use an updated version as soon as it becomes available. Such library updates can potentially be breaking, so users should consider this before referencing the latest alias in a project.

topics

Always include conan and project name. All topics listed on the project homepage can also be included.

settings

settings.compiler

Windows does not necessarily imply Visual Studio, there are at least GCC (e.g. MinGW) and Clang for Windows. Thus, don’t write conditions like:

if self.settings.os == "Windows":
    self.run("cl")

write instead:

if self.settings.compiler == "Visual Studio":
    self.run("cl")

settings.arch

Don’t assume there are only two architectures like x86 and x64, there are at least many variations of ARM (even on Windows, yes) so don’t write conditions like:

flags = "-m32" if self.settings.arch = 'x86' else = "-m64"

write instead:

flags = {'x86': '-m32', 'x86_64': '-m64'}.get(str(self.settings.arch))

settings - restrictions

Don’t restrict operating system and arch with the following strategy, even though I think this is in the Conan documentation as a suggestion. It turns out that this prevents cross-building scenarios.

settings = {"os" : ["Windows", "Macos", "Linux"], "arch" : ["x86_64"]}

Instead, do this:

def config_options(self):
    # Checking against self.settings.* would prevent cross-building profiles from working
    if tools.detected_architecture() != "x86_64":
        raise Exception("Unsupported Architecture.  This package currently only supports x86_64.")
    if platform.system() not in ["Windows", "Darwin", "Linux"]:
        raise Exception("Unsupported System. This package currently only support Linux/Darwin/Windows")

options

options - fPIC for Linux

At a certain point, we realized we should be adding fPIC option for many packages which we did not consider before. So, please check with the team in slack if you’re not sure whether or not you need fPIC.

In order to add fPIC options, modify your conanfile.py by adding highlighted lines:

options = {"shared": [True, False], "fPIC": [True, False]}
default_options = {"shared": False, "fPIC": True}

also, you’ll need configure method to skip fPIC for Visual Studio (if your recipe supports MSVC, of course):

def configure(self):
    if self.settings.compiler == 'Visual Studio':
        del self.options.fPIC

For CMake-based projects, modify your build() method:

def build_cmake(self):
    cmake = CMake(self, generator='Ninja')
    if self.settings.compiler != 'Visual Studio':
        cmake.definitions['CMAKE_POSITION_INDEPENDENT_CODE'] = self.options.fPIC

For autotools-based project, you may just need:

if self.settings.compiler != 'Visual Studio':
    env_build.fpic = self.options.fPIC

Or alternatively, if configure provides –with-pic option:

if self.settings.compiler != 'Visual Studio' and self.options.fPIC:
    configure_args.append('--with-pic')

source() method

  • Use tools.get() and a conandata.yml file as shown in our templates. Don’t do git clones.

  • With GitHub, even if there are no github releases, use the “Download as Zip” url.

  • Most times you can use a .tar.gz file

  • Rename the directory that gets extracted or downloaded to source_subfolder. This simplifies several elements in our standard recipes. This is also part of our templates

build() method

Don’t do cmake.install() in the the build() method. The problem is that if/when users just want to try to re-run the package() method for some reason, it won’t have the desired effect.

So, don’t do this:

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

def package(self):
    pass

Do this instead:

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

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

Or, you can do this, particularly if there are any special definitions:

def _configure_cmake(self):
    cmake = CMake(self)
    cmake.definitions["BUILD_TESTS"] = False # example
    cmake.definitions['LOG4CPLUS_SINGLE_THREADED'] = self.options.single_threaded
    cmake.definitions['LOG4CPLUS_BUILD_LOGGINGSERVER'] = self.options.build_loggingserver
    cmake.configure()
    return cmake

def build(self):
    cmake = self._configure_cmake()
    cmake.build()

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

package() method

Don’t do with tools.chdir("sources"), it doesn’t do what you want it to.

If you’re building a CMake project, do cmake.install() in the package() method (see notes above under build() method).

test_package

Our standard for test_package are nice in that you only need to change test_package.cpp contents in most cases. The conanfile.py and CMakeLists.txt are made to be generic. Special circumstances might require some changes to the other files such as for C only libraries, but try to avoid if possible.

Please write the actual minimum contents of a file you can to prove that include and linking works. Do not use examples from the author, do not test that methods do the right thing. Do not use a test framework, even Catch. Just use a main() method that gets fun from the test() method in conanfile.py.