Skip to content

[bug] The bundled version of conan (from PyInstaller) should automatically bundle all tools #18041

@ymeine

Description

@ymeine

Describe the bug

Quite some time ago, I wanted to use the bundled conan version (the one made with PyInstaller) since I’m using scoop on Windows to install most of my software.

At that time, I had an issue with the missing tool conan.tools.scons. I didn’t report the bug back then, and as I was finally about to do it today, I realized it was fixed by PR #17809 as an answer to issue #17808.

Now, while I’m glad it’s finally fixed, there are a few concerns regarding that topic of bundling:

Still, since the bundled version exists and can be more practical for some, I guess a couple of improvements could be made.

I wonder if you could automatically add all tools, using the --collect-modules=conan.tools option, knowing that you already use that option for something else. I tried it and, at the time of writing, seemed to only bundle one more set of modules, all related to the conan.tools.cps tool, which is a good sign that it may be the right solution.

But if you want more fine grained control, since you are already using a Python script to invoke PyInstaller, you could maybe even loop over your existing conan/tools folder and add all the --hidden-import=conan.tools.xxx options.

First solution looks like this:

               # Modules that can be imported in ConanFile conan.tools and errors
               "--collect-submodules=conan.cli.commands "
               "--hidden-import=conan.errors "
-              "--hidden-import=conan.tools.android "
-              "--hidden-import=conan.tools.apple "
-              "--hidden-import=conan.tools.build "
-              "--hidden-import=conan.tools.cmake "
-              "--hidden-import=conan.tools.env "
-              "--hidden-import=conan.tools.files "
-              "--hidden-import=conan.tools.gnu "
-              "--hidden-import=conan.tools.google "
-              "--hidden-import=conan.tools.intel "
-              "--hidden-import=conan.tools.layout "
-              "--hidden-import=conan.tools.meson "
-              "--hidden-import=conan.tools.microsoft "
-              "--hidden-import=conan.tools.premake "
-              "--hidden-import=conan.tools.qbs "
-              "--hidden-import=conan.tools.ros "
-              "--hidden-import=conan.tools.sbom "
-              "--hidden-import=conan.tools.scm "
-              "--hidden-import=conan.tools.scons "
-              "--hidden-import=conan.tools.system "
-              "--hidden-import=conan.tools.system.package_manager")
+              "--collect-submodules=conan.tools")

and at the time being adds the following modules: conan.cps, conan.cps.cps, conan.tools.cps, conan.tools.cps.cps_deps.

Second solution would be:

+from pathlib import Path

+    tools = (
+        f'--hidden-import=conan.tools.{child.name}'
+        for child in Path(source_folder, 'conan', 'tools').iterdir()
+        if child.is_dir() and child.name != '__pycache__'
+    )
     hidden = ("--hidden-import=glob "  # core stdlib
               "--hidden-import=pathlib "
               # Modules that can be imported in ConanFile conan.tools and errors
               "--collect-submodules=conan.cli.commands "
               "--hidden-import=conan.errors "
-              "--hidden-import=conan.tools.android "
-              "--hidden-import=conan.tools.apple "
-              "--hidden-import=conan.tools.build "
-              "--hidden-import=conan.tools.cmake "
-              "--hidden-import=conan.tools.env "
-              "--hidden-import=conan.tools.files "
-              "--hidden-import=conan.tools.gnu "
-              "--hidden-import=conan.tools.google "
-              "--hidden-import=conan.tools.intel "
-              "--hidden-import=conan.tools.layout "
-              "--hidden-import=conan.tools.meson "
-              "--hidden-import=conan.tools.microsoft "
-              "--hidden-import=conan.tools.premake "
-              "--hidden-import=conan.tools.qbs "
-              "--hidden-import=conan.tools.ros "
-              "--hidden-import=conan.tools.sbom "
-              "--hidden-import=conan.tools.scm "
-              "--hidden-import=conan.tools.scons "
-              "--hidden-import=conan.tools.system "
-              "--hidden-import=conan.tools.system.package_manager")
+              + ' '.join(tools))

and at the time being adds the same modules as solution 1, but as a difference removes module conan.tools.system.package_manager. Indeed, the manual looping over tools needs to handle nested tools if any (like that one) and is harder to maintain.

Btw, I know you have a comment about it in the code, but you are not tying to a specific PyInstaller version and therefore you are relying on the developer to install it, which could be problematic in some situations.

How to reproduce it

Well, there’s not really one scenario, it all depends on whether you want to use a given tool and if it has been bundled or not.

Here’s what I did though to check my changes:

  • in the conan repository, run the pyinstaller.py script
  • after that, use pyi-archive_viewer --list --recursive --brief $pathToTheConanBin and check in the output what tools/modules are being bundled or not

I did that multiple times with the 3 different versions (untouched, solution 1 and solution 2) and then output the list to different files that I could diff.

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions