Skip to content

Commit cfcd256

Browse files
czoidoAbrilRBSdanimtb
authored
Local recipes index post (#266)
* wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * review * review * wip * wip * Update _posts/2024-04-23-Introducing-local-recipes-index-remote.markdown Co-authored-by: Rubén Rincón Blanco <[email protected]> * Update _posts/2024-04-23-Introducing-local-recipes-index-remote.markdown * Update _posts/2024-04-23-Introducing-local-recipes-index-remote.markdown * Update _posts/2024-04-23-Introducing-local-recipes-index-remote.markdown Co-authored-by: Daniel <[email protected]> * Update _posts/2024-04-23-Introducing-local-recipes-index-remote.markdown Co-authored-by: Daniel <[email protected]> * Update _posts/2024-04-23-Introducing-local-recipes-index-remote.markdown Co-authored-by: Rubén Rincón Blanco <[email protected]> * Update _posts/2024-04-23-Introducing-local-recipes-index-remote.markdown Co-authored-by: Rubén Rincón Blanco <[email protected]> * Update _posts/2024-04-23-Introducing-local-recipes-index-remote.markdown Co-authored-by: Rubén Rincón Blanco <[email protected]> * Update _posts/2024-04-23-Introducing-local-recipes-index-remote.markdown Co-authored-by: Rubén Rincón Blanco <[email protected]> * Update _posts/2024-04-23-Introducing-local-recipes-index-remote.markdown Co-authored-by: Rubén Rincón Blanco <[email protected]> --------- Co-authored-by: Rubén Rincón Blanco <[email protected]> Co-authored-by: Daniel <[email protected]>
1 parent f221508 commit cfcd256

File tree

2 files changed

+323
-0
lines changed

2 files changed

+323
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,323 @@
1+
---
2+
layout: post
3+
comments: false
4+
title: "Introducing the Local-Recipes-Index: A New Repository Type in Conan"
5+
meta_title: "Understanding Conan's Local-Recipes-Index to improve package management for C/C++ - Conan Blog"
6+
description: "Explore the capabilities of Conan's local-recipes-index feature and how it enhances dependency management for C and C++ libraries."
7+
---
8+
9+
ConanCenter, the central open-source repository for C and C++ libraries, is a success
10+
story, containing a vast collection of C and C++ open-source packages. It processes hundreds
11+
of thousands of download requests daily, building its packages [from a central GitHub
12+
repository](https://github.com/conan-io/conan-center-index), which is organized in a
13+
specific folder layout and received nearly 6,000 pull requests from contributors in
14+
2023 alone.
15+
16+
However, ConanCenter does not fit all use cases. For instance, it cannot include
17+
closed-source libraries or tools that might still be beneficial to the community.
18+
Additionally, some organizations, particularly large enterprises, prefer not to use
19+
binaries downloaded from the internet. Instead, they build their own binaries in-house
20+
using the `conan-center-index` recipes. These organizations often need to customize these
21+
recipes to meet unique requirements that are not applicable to the broader community,
22+
making such contributions unsuitable for the upstream repository. The Conan documentation
23+
[acknowledges this
24+
practice](https://docs.conan.io/2/devops/conancenter/hosting_binaries.html), recommending
25+
working from a fork of `conan-center-index` for such needs.
26+
27+
For all those reasons in version 2.2.0, Conan introduced a new repository type called
28+
`local-recipes-index`, designed to offer more flexibility by allowing a Conan remote to
29+
point to a local copy of Conan recipes with a specific layout.
30+
31+
The `local-recipes-index` allows users to maintain a local folder with the same structure
32+
as the `conan-center-index` GitHub repository, using it as a source for package recipes.
33+
This new type of repository is recipes-only, necessitating the construction of package
34+
binaries from source on each machine where the package is used. For sharing binaries
35+
across teams, we continue to recommend [using a Conan remote server like
36+
Artifactory](https://docs.conan.io/2/tutorial/conan_repositories/setting_up_conan_remotes/artifactory/artifactory_ce_cpp.html)
37+
for production purposes.
38+
39+
<p class="centered">
40+
<img src="{{ site.baseurl }}/assets/post_images/2024-04-23/general-flow-diagram.png" style="display: block; margin-left: auto; margin-right: auto;" alt="Diagram of the general workflow"/>
41+
</p>
42+
43+
In this post, we will explore how this feature facilitates the following:
44+
45+
- This feature enables contributors to share package recipes with the community for
46+
libraries that might not be suitable for ConanCenter due to various reasons, such as
47+
licensing constraints or binary distribution policies. An example of this could be CUDA
48+
or other proprietary libraries, which are distributed as precompiled closed-source
49+
binaries.
50+
51+
- It simplifies the adoption of best practices outlined [in the Conan
52+
documentation](https://docs.conan.io/2/devops/conancenter/hosting_binaries.html) for
53+
organizations requiring custom-built binaries or modified ConanCenter recipes to meet
54+
unique requirements. This approach grants users complete control over their third-party
55+
dependencies, ensuring they are both robust and fully customizable.
56+
57+
Next, we'll delve into practical examples to demonstrate these two use cases of the
58+
`local-recipes-index` repository.
59+
60+
## Using a local-recipes-index repository with your own recipes
61+
62+
In this section, we will illustrate how to use the `local-recipes-index` feature for
63+
scenarios where certain libraries or tools, due to licensing restrictions or proprietary
64+
nature, are not suitable for ConanCenter.
65+
66+
For demonstration purposes, let's create a `local-recipes-index` repository for a hypothetical
67+
`hello` closed-source library using the `local_recipes_index` template for the `conan new`
68+
command:
69+
70+
$ mkdir repo && cd repo
71+
$ conan new local_recipes_index -d name=hello -d version=0.1 \
72+
-d url=https://github.com/conan-io/libhello/archive/refs/tags/0.0.1.zip \
73+
-d sha256=1dfb66cfd1e2fb7640c88cc4798fe25853a51b628ed9372ffc0ca285fe5be16b
74+
$ cd ..
75+
76+
The `conan new local_recipes_index` command creates a template that assumes CMake as the
77+
build system alongside other heavy assumptions. In practice, it will require customizing
78+
it, but for this demo, it works as-is. It will create a folder layout equal to the
79+
`conan-center-index` GitHub repository:
80+
81+
.
82+
└── repo
83+
└── recipes
84+
└── hello
85+
├── all
86+
│ ├── conandata.yml
87+
│ ├── conanfile.py
88+
│ └── test_package
89+
│ ├── CMakeLists.txt
90+
│ ├── conanfile.py
91+
│ └── src
92+
│ └── example.cpp
93+
└── config.yml
94+
95+
After setting up the repository, we add it as a local remote to Conan:
96+
97+
$ conan remote add mylocalrepo ./repo --allowed-packages="hello/*"
98+
99+
Please pay special attention to the `--allowed-packages` argument. This argument ensures
100+
that all packages other than `hello` are discarded by Conan. This can be used to minimize
101+
the surface area for a potential supply chain attack.
102+
103+
Now you can list and install packages from this new repository:
104+
105+
$ conan list "*" -r=mylocalrepo
106+
$ conan install --requires=hello/0.1 -r=mylocalrepo --build=missing
107+
108+
At this point, you could push this repository to your GitHub account and share it with the
109+
community. Please be aware that, as we commented earlier, this feature is specifically
110+
tailored for scenarios where certain libraries are not suitable for ConanCenter. Remember,
111+
a "local-recipes-index" repository has limitations: it is not fully reproducible as it
112+
models only versions and not revisions, and it does not provide binaries. Therefore,
113+
outside of these cases, it is advised to use a remote package server such as Artifactory.
114+
115+
Now, users simply need to clone the GitHub repository and add the cloned folder as a local
116+
repository themselves.
117+
118+
## Building Binaries from a private `conan-center-index` fork
119+
120+
As outlined in [the Conan DevOps
121+
Guide](https://docs.conan.io/2/devops/using_conancenter.html), there are many cases where
122+
organizations need to operate independently of ConanCenter by building their own binaries.
123+
Being decoupled from the public upstream ConanCenter server and building your own binaries
124+
from a fork of ``conan-center-index`` as suggested in the linked documentation page can have
125+
many advantages, including absolute control and possibility to customize recipes, giving
126+
us the ability for the repository to act as a snapshot of versions, be completely robust
127+
against possible continuous changes and new releases in upstream ConanCenter, etc.
128+
129+
The `local-recipes-index` repository allows you to easily build binaries from a fork of
130+
`conan-center-index`, and then hosting them on a Conan remote repository like Artifactory.
131+
The main difference with the process explained [in the Conan DevOps
132+
guide](https://docs.conan.io/2/devops/conancenter/hosting_binaries.html) is the ability
133+
to immediately test multiple local changes without the need to export each time a recipe
134+
is modified.
135+
136+
Note that in this case, mixing binaries from ConanCenter with locally built binaries is
137+
not recommended for several reasons:
138+
139+
- Binary compatibility: There may be small differences in setup between the ConanCenter CI
140+
and the user's CI. Maintaining a consistent setup for all binaries can mitigate some issues.
141+
142+
- Full control over builds: Building all binaries yourself ensures you have complete control
143+
over the compilation environment and dependency versions.
144+
145+
Instead, it's recommended to build all your direct and transitive dependencies from the fork.
146+
To begin, remove the upstream ConanCenter as it will not be used, everything will come
147+
from our own fork:
148+
149+
$ conan remote remove conancenter
150+
151+
Then we will clone our fork (in this case, we are cloning directly the upstream for demo
152+
purposes, but you would be cloning your fork instead):
153+
154+
$ git clone https://github.com/conan-io/conan-center-index
155+
156+
Add this as our `mycenter` remote:
157+
158+
# Add the mycenter remote pointing to the local folder
159+
$ conan remote add mycenter ./conan-center-index
160+
161+
And that’s all! Now you're set to list and use packages from your `conan-center-index` local folder:
162+
163+
$ conan list "zlib/*" -r=mycenter
164+
mycenter
165+
zlib
166+
zlib/1.2.11
167+
zlib/1.2.12
168+
zlib/1.2.13
169+
zlib/1.3
170+
zlib/1.3.1
171+
172+
We can also install packages from this repo, for example we can do:
173+
174+
$ conan install --requires=zlib/1.3
175+
...
176+
======== Computing dependency graph ========
177+
zlib/1.3: Not found in local cache, looking in remotes...
178+
zlib/1.3: Checking remote: mycenter
179+
zlib/1.3: Downloaded recipe revision 5c0f3a1a222eebb6bff34980bcd3e024
180+
Graph root
181+
cli
182+
Requirements
183+
zlib/1.3#5c0f3a1a222eebb6bff34980bcd3e024 - Downloaded (mycenter)
184+
185+
======== Computing necessary packages ========
186+
Requirements
187+
zlib/1.3#5c0f3a1a222eebb6bff34980bcd3e024:72c852c5f0ae27ca0b1741e5fd7c8b8be91a590a - Missing
188+
ERROR: Missing binary: zlib/1.3:72c852c5f0ae27ca0b1741e5fd7c8b8be91a590a
189+
190+
As we can see, Conan managed to get the recipe for ``zlib/1.3`` from ``mycenter``, but
191+
then it failed because there is no binary. This is expected, **the repository only contains
192+
the recipes, but not the binaries**. We can build the binary from source with
193+
``--build=missing`` argument:
194+
195+
$ conan install --requires=zlib/1.3 --build=missing
196+
...
197+
zlib/1.3: package(): Packaged 2 '.h' files: zconf.h, zlib.h
198+
zlib/1.3: package(): Packaged 1 file: LICENSE
199+
zlib/1.3: package(): Packaged 1 '.a' file: libz.a
200+
zlib/1.3: Created package revision 0466b3475bcac5c2ce37bb5deda835c3
201+
zlib/1.3: Package '72c852c5f0ae27ca0b1741e5fd7c8b8be91a590a' created
202+
zlib/1.3: Full package reference: zlib/1.3#5c0f3a1a222eebb6bff34980bcd3e024:72c852c5f0ae27ca0b1741e5fd7c8b8be91a590a#0466b3475bcac5c2ce37bb5deda835c3
203+
zlib/1.3: Package folder /home/conan/.conan2/p/b/zlib1ed9fe13537a2/p
204+
WARN: deprecated: Usage of deprecated Conan 1.X features that will be removed in Conan 2.X:
205+
WARN: deprecated: 'cpp_info.names' used in: zlib/1.3
206+
207+
======== Finalizing install (deploy, generators) ========
208+
cli: Generating aggregated env files
209+
cli: Generated aggregated env files: ['conanbuild.sh', 'conanrun.sh']
210+
Install finished successfully
211+
212+
We can see now the binary package in our local cache:
213+
214+
$ conan list zlib:*
215+
Local Cache
216+
zlib
217+
zlib/1.3
218+
revisions
219+
5c0f3a1a222eebb6bff34980bcd3e024 (2024-04-10 11:50:34 UTC)
220+
packages
221+
72c852c5f0ae27ca0b1741e5fd7c8b8be91a590a
222+
info
223+
settings
224+
arch: x86_64
225+
build_type: Release
226+
compiler: gcc
227+
compiler.version: 9
228+
os: Linux
229+
options
230+
fPIC: True
231+
shared: False
232+
233+
Finally, upload the binary package to our Artifactory repository to make it available for
234+
our organization, users and CI jobs:
235+
236+
$ conan remote add myartifactoryrepo <artifactory_url>
237+
$ conan upload zlib* -r=myartifactoryrepo -c
238+
239+
This way, consumers of the packages will not only enjoy the pre-compiled binaries and
240+
avoid having to always re-build from source all dependencies, but that will also provide
241+
stronger guarantees that the dependencies build and work correctly, that all dependencies
242+
and transitive dependencies play well together, etc. Decoupling the binary creation
243+
process from the binary consumption process is the way to achieve faster and more reliable
244+
usage of dependencies.
245+
246+
Remember, in a production setting, the `conan upload` command should be executed by CI,
247+
not developers, following the [Conan
248+
guidelines](https://docs.conan.io/2/knowledge/guidelines.html). This approach ensures that
249+
package consumers enjoy pre-compiled binaries and consistency across dependencies.
250+
251+
### Modifying the local-recipes-index repository files
252+
253+
One of the advantages of this approach is that all the changes that we do in every single
254+
recipe are automatically available for the Conan client. For example, changes to the
255+
`recipes/zlib/config.yml` file are immediately recognized by the Conan client. If you
256+
edit that file and remove all versions but the latest and then we `list` the recipes:
257+
258+
$ conan list "zlib/*" -r=mycenter
259+
mycenter
260+
zlib
261+
zlib/1.3.1
262+
263+
When some of the recipes change, then note that the current Conan home already contains a
264+
cached copy of the package, so it will not update it unless we explicitly use the
265+
``--update``, as any other Conan remote.
266+
267+
So if we do a change in the ``zlib`` recipe in ``recipes/zlib/all/conanfile.py`` and
268+
repeat:
269+
270+
$ conan install --requires=zlib/1.3.1 -r=mycenter --update --build=missing
271+
272+
We will immediately have the new package binary locally built from source from the new
273+
modified recipe in our Conan home.
274+
275+
### Using local-recipes-index Repositories in Production
276+
277+
Several important points should be considered when using this new feature:
278+
279+
- It is designed for **third-party packages**, where recipes in one repository are creating
280+
packages with sources located elsewhere. To package your own code, the standard practice
281+
of adding `conanfile.py` recipes along with the source code and using the standard
282+
`conan create` flow is recommended.
283+
284+
- The `local-recipes-index` repositories point to **local folders in the filesystem**.
285+
While users may choose to sync that folder with a git repository or other version
286+
control mechanisms, Conan is agnostic to this, as it is only aware of the folder in the
287+
filesystem that points to the (current) state of the repository. Users may choose to run
288+
git commands directly to switch branches/commit/tags and Conan will automatically
289+
recognise the changes
290+
291+
- This approach operates at the source level and does not generate package binaries. For
292+
deployment for development and production environments, the use of a remote package
293+
server such as Artifactory is crucial. It's important to note that this feature is not a
294+
replacement for Conan's remote package servers, which play a vital role in hosting
295+
packages for regular use.
296+
297+
- Also, note that a server remote can retain a history of changes storing multiple recipe
298+
revisions. In contrast, a `local-recipes-index` remote can only represent a single
299+
snapshot at any given time.
300+
301+
Furthermore, this feature does not support placing server URLs directly in recipes; remote
302+
repositories must be explicitly added with `conan remote add`. Decoupling abstract package
303+
requirements, such as "zlib/1.3.1", from their specific origins is crucial to resolving
304+
dependencies correctly and leveraging Conan's graph capabilities, including version
305+
conflict detection and resolution, version-ranges resolution, [opting into
306+
pre-releases](https://docs.conan.io/2/devops/versioning/resolve_prereleases.html),
307+
[platform_requires](https://docs.conan.io/2/reference/config_files/profiles.html#platform-requires),
308+
[replace_requires](https://docs.conan.io/2/reference/config_files/profiles.html#replace-requires),
309+
etc. This separation also facilitates the implementation of modern DevOps practices, such
310+
as package immutability, full relocatability and package promotions.
311+
312+
## Conclusions
313+
314+
The `local-recipes-index` repository type introduces a new tool that enables workflows
315+
previously not possible with Conan 1.X:
316+
317+
- It allows the easy creation of packages from forks of the `conan-center-index` GitHub
318+
repository. Many enterprises require this due to policies necessitating private
319+
customizations in recipes that are unsuitable for merging into the upstream repository.
320+
321+
- It provides a solution for packaging closed-source libraries and tools within the C/C++
322+
ecosystem that cannot be included in ConanCenter, enabling their recipes to be shared
323+
and conveniently used within the Conan community.
Loading

0 commit comments

Comments
 (0)