conan-io / conan

Conan - The open-source C and C++ package manager
https://conan.io
MIT License
7.96k stars 952 forks source link

[question] How to debug when different package IDs are generated #16464

Closed Todiq closed 2 weeks ago

Todiq commented 3 weeks ago

What is your question?

Hello,

I am encountering a weird behaviour. Although using the same docker image, I am getting an entirely different package ID from the same sources on CI/CD vs locally.

In fact, when building my project locally in Release & Debug, the package ID remains the same, and a new revision is created with the different settings, as expected.

It does not behave this way on CI for some reason. Not only package ID/revisions are different from what I get locally, but also between the Release and Debug versions that are concurrently built on CI (independent caches).

Would there be a way to inspect that more deeply? In general, what are the variables that would impact the creation of a new package ID / revision?

Thanks in advance!

Have you read the CONTRIBUTING guide?

memsharded commented 3 weeks ago

Hi @Todiq

Thanks for your question.

Would there be a way to inspect that more deeply? In general, what are the variables that would impact the creation of a new package ID / revision?

yes, the new conan list pkg/version#revision:* command will list exactly the binaries of that recipe-revision, with the factors that generate that package_id. By listing the different created binaries you should be able to see there what is different, if settings, options, or dependencies.

Note this section https://docs.conan.io/2/reference/binary_model.html, specially the effects of dependencies in the package_id (see https://docs.conan.io/2/reference/binary_model/dependencies.html) can explain why you might be getting different package_ids, if there are some older revisions stored in the cache for the dependencies, or if retrieving different ones from the server.

The conan list command will give you the differences and details between those package-ids

In fact, when building my project locally in Release & Debug, the package ID remains the same, and a new revision is created with the different settings, as expected.

This doesn't make much sense. Different settings do not create a new revision, different settings create a new package_id. Please check https://docs.conan.io/2/tutorial/versioning/revisions.html if necessary.

Please let me know if this helps.

Todiq commented 2 weeks ago

Thanks for the links @memsharded

I don't know why it would be properly locally while not at all on CI.

Here is the result for the Debug job:

conan list castdbconnectivity/0.1#*:*
Local Cache
  castdbconnectivity
    castdbconnectivity/0.1
      revisions
        264b28cbdad5033d1c7feb7f576344bf (2024-06-14 14:28:45 UTC)
          packages
            200fb98aa4ab4533929f6093cb3ec7e22cb84ff2
              info
                settings
                  arch: x86_64
                  build_type: Debug
                  compiler: gcc
                  compiler.cppstd: 17
                  compiler.libcxx: libstdc++11
                  compiler.version: 12
                  os: Linux
                options
                  fPIC: False
                  shared: True
                requires
                  boost/1.81.Z
                  castcore/0.1.Z
                  libpq/14.5.Z
                  rapidjson/1.1.Z

And the one from the Release job:

$ conan list castdbconnectivity/0.1#*:*
Local Cache
  castdbconnectivity
    castdbconnectivity/0.1
      revisions
        9dd934b1c257245ec2484529a6d1fc64 (2024-06-14 14:28:48 UTC)
          packages
            e80e73027344801fb4e070c1cbfc7cfe04c9262e
              info
                settings
                  arch: x86_64
                  build_type: Release
                  compiler: gcc
                  compiler.cppstd: 17
                  compiler.libcxx: libstdc++11
                  compiler.version: 12
                  os: Linux
                options
                  fPIC: False
                  shared: True
                requires
                  boost/1.81.Z
                  castcore/0.1.Z
                  libpq/14.5.Z
                  rapidjson/1.1.Z

The only thing that changed is the build_type setting and yet, it would create a new revision. The docker image used is the same for local testing and on CI. Do you have any ideas? I am very confused.

memsharded commented 2 weeks ago

The problem indeed seems that you are creating 2 different recipe revisions from the same sources (in theory, the same commit in source code?)

There could be a couple of reasons:

Please try that and let me know.

Todiq commented 2 weeks ago

Hello @memsharded,

There is actually a difference between the two conanmanifest.txt.

In fact, the Debug version of castdbconnectivity/0.1 builds with the Debug version of another package. Let's call that package alpha.

The Release version of castdbconnectivity/0.1 builds with the Release version of alpha. However, alpha was built successfully and its Debug & Release versions are under the same revision.

Is it expected to have alpha located in different paths in the Release & Debug jobs of castdbconnectivity? I guess it does, since the location is composed of the hash of the revision & package ID, if I understood properly.

Then, is there a way to have my tree (meaning only my dependencies, not the external ones --> castdbconnectivity & alpha in this case) fully in Debug, but keep the same revision for castdbconnectivity, whether it was build in Release or Debug?

Thanks in advance!

Todiq commented 2 weeks ago

Something weird:

When building locally, the conanmanifest.txt only contains the sources from castdbconnectivity while on CI, it also contains sources from the dependencies. I may have an issue with the export_sources() method. Which is strange because everything has been working fine on our previous CI system:

def export_sources(self):
    to_exclude = ["build*", "test"]
    copy(self, "*.cpp", src=self.recipe_folder, dst=self.export_sources_folder, excludes=to_exclude)
    copy(self, "*.h", src=self.recipe_folder, dst=self.export_sources_folder, excludes=to_exclude)
    copy(self, "*.hpp", src=self.recipe_folder, dst=self.export_sources_folder, excludes=to_exclude)
    copy(self, "*CMakeLists.txt", src=self.recipe_folder, dst=self.export_sources_folder, excludes=to_exclude)
    copy(self, "*.inl", src=self.recipe_folder, dst=self.export_sources_folder, excludes=to_exclude)
memsharded commented 2 weeks ago

Thanks for the feedback.

There is actually a difference between the two conanmanifest.txt.

Good, that explains the issue. If you want to share the especific differences, that could help relating that to the export_sources.

When building locally, the conanmanifest.txt only contains the sources from castdbconnectivity while on CI, it also contains sources from the dependencies.

That could happen if reusing folders, not cleaning something from the previous job, etc. The conanmanifest.txt differences should help identifying the files that are being export_sources that shouldn't have been.

Todiq commented 2 weeks ago

I found the issue.

I forgot that, in gitlab CI, you have everything living in the same folder as your source code. The CONAN_HOME was there as well, which implied everything inside it was copied in export_sources.

Adding it to the list of exclusions of the copy method fixed the issue. Many thanks!

memsharded commented 2 weeks ago

Great, happy that you found the issue, thanks for the feedback!