Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
183 lines (131 sloc) 6.55 KB

Recipe and Sources in the Same Repo

Sometimes it is more convenient to have the recipe and source code together in the same repository. This is true especially if you are developing and packaging your own library, and not one from a third-party.

There are two different approaches:

Exporting the Sources with the Recipe: exports_sources

This could be an appropriate approach if we want the package recipe to live in the same repository as the source code it is packaging.

First, let's get the initial source code and create the basic package recipe:

$ conan new Hello/0.1 -t -s

A src folder will be created with the same "hello" source code as in the previous example. You can have a look at it and see that the code is straightforward.

Now let's have a look at conanfile.py:

from conans import ConanFile, CMake

class HelloConan(ConanFile):
    name = "Hello"
    version = "0.1"
    license = "<Put the package license here>"
    url = "<Package recipe repository url here, for issues about the package>"
    description = "<Description of Hello here>"
    settings = "os", "compiler", "build_type", "arch"
    options = {"shared": [True, False]}
    default_options = {"shared": False}
    generators = "cmake"
    exports_sources = "src/*"

    def build(self):
        cmake = CMake(self)
        cmake.configure(source_folder="src")
        cmake.build()

        # Explicit way:
        # self.run('cmake "%s/src" %s' % (self.source_folder, cmake.command_line))
        # self.run("cmake --build . %s" % cmake.build_config)

    def package(self):
        self.copy("*.h", dst="include", src="src")
        self.copy("*.lib", dst="lib", keep_path=False)
        self.copy("*.dll", dst="bin", keep_path=False)
        self.copy("*.dylib*", dst="lib", keep_path=False)
        self.copy("*.so", dst="lib", keep_path=False)
        self.copy("*.a", dst="lib", keep_path=False)

    def package_info(self):
        self.cpp_info.libs = ["hello"]

There are two important changes:

  • Added the exports_sources field, indicating to Conan to copy all the files from the local src folder into the package recipe.
  • Removed the source() method, since it is no longer necessary to retrieve external sources.

Also, you can notice the two CMake lines:

include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()

They are not added in the package recipe, as they can be directly added to the src/CMakeLists.txt file.

And simply create the package for user and channel demo/testing as described previously:

$ conan create . demo/testing
...
Hello/0.1@demo/testing test package: Running test()
Hello world!

Capturing the Remote and Commit: scm

Warning

This is an experimental feature subject to breaking changes in future releases.

You can use the :ref:`scm attribute <scm_attribute>` with the url and revision field set to auto. When you export the recipe (or when :command:`conan create` is called) the exported recipe will capture the remote and commit of the local repository:

You can commit and push the conanfile.py to your origin repository, which will always preserve the auto values. But when the file is exported to the Conan local cache, the copied recipe in the local cache will point to the captured remote and commit:

So when you :ref:`upload the recipe <uploading_packages>` to a Conan remote, the recipe will contain the "resolved" URL and commit.

When you are requiring your HelloConan, the :command:`conan install` will retrieve the recipe from the remote. If you are building the package, the source code will be fetched from the captured url/commit.

As SCM attributes are evaluated in the workspace context (see :ref:`scm attribute <scm_attribute>`), you can write more complex functions to retrieve the proper values, this source conanfile.py will be valid too:

Tip

When doing a :command:`conan create` of a recipe using scm, Conan will save the path to the local source repository. Every time the :command:`conan create` command is invoked, the sources will not be downloaded from the remote repository but copied from the local directory.

This allows to build packages making changes to the source code without the need of committing them and pushing them to the remote repository. This convenient to speed up the development of your packages when cloning from a local repository.

Warning: This optimization can lead to non-reproducible packages if changes in the source code are not committed and the recipe is uploaded with its packages to a remote.

You can’t perform that action at this time.