Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feature] require the same thing twice with different options #13521

Closed
1 task done
smoofra opened this issue Mar 23, 2023 · 11 comments · Fixed by #13529
Closed
1 task done

[feature] require the same thing twice with different options #13521

smoofra opened this issue Mar 23, 2023 · 11 comments · Fixed by #13529
Assignees

Comments

@smoofra
Copy link

smoofra commented Mar 23, 2023

What is your suggestion?

I would like to require the same package twice, or more with different options.

I have a package called gcc/9.1.0, which takes the options os_target and arch_target.

I have a recipe called wine and what I really want to do with that one is

 def build_requirements(self):
    self.build_requries("gcc/11.3.0"). # provides x86_64-linux-gnu-gcc, options set automatically from settins_target
    self.build_requires("gcc/9.1.0", options={os_target="Windows", arch_target="x86") # provides i686-w64-mingw32-gcc
    self.build_requires("gcc/9.1.0", options={os_target="Windows", arch_target="x86_64") # provides x86_64-w64-mingw32-gcc

I tried wrapper recipes that require gcc, with every option of direct, visible, run, and build that i can think of, but nothing does what i want.

Whats blocking this from working is two things. First is the requires have the same package name and that's not allowed.
possible solution...

 def build_requirements(self):
    self.build_requries("gcc/11.3.0").
    self.build_requires("gcc/9.1.0", options={os_target="Windows", arch_target="x86", as="gcc-win32")
    self.build_requires("gcc/9.1.0", options={os_target="Windows", arch_target="x86_64", as="gcc-win64") 

then the windows compiler could appear in self.dependencies["gcc-win32"]

The second issue is that even if I create wrapper packages to require gcc, I can't get them to do what i wnat.
If the wrapper requires gcc with visible=Fasle, then the graph looks right, but the gcc packages have binary=Skip set, so they can't be used

If visible=True, then the graph only gets one node for gcc, which isn't what we want.

Have you read the CONTRIBUTING guide?

  • I've read the CONTRIBUTING guide
@memsharded
Copy link
Member

Hi @smoofra

Thanks for your suggestion.

I'd like to understand better what is the use that wine will do with the several dependencies defined as build_requires, and how wine is intended to be used. Is it possible that what you want is to create a wine package that basically re-packages and does a copy of all those things? We have an open ticket to investigate this use case in 2.X roadmap in #13171

@smoofra
Copy link
Author

smoofra commented Mar 24, 2023

In this case, wine isn't repackaging anything -- although I have encountered other cases where repackaging is necessary.

It is possible that repackaging could be used by a helper package to solve this problem. mingw-gcc-x86_64 could repackage gcc with the appropriate options and wine could require mingw-gcc-x86_64

What wine does with these three gcc packages is just run the compiler to build binaries in the build() method. The reason it needs compilers for three different platforms is because wine is a program that runs on linux which emulates windows and allows you to run windows programs on linux. Wine is ultimately a linux program, but it contains a mix of linux and windows binaries. For example it has a program loader which is a linux program that knows how to load PE files. So we need the regular linux gcc to build those. But it also has a bunch of DLLs that implement various windows operating system APIs. So we need the mingw compiler to build those. And it supports both 32 and 64 bit programs, so we need both.

@memsharded
Copy link
Member

And it supports both 32 and 64 bit programs, so we need both.

The different architectures could maybe be different binaries, with different package_ids, that would be the recommended approach in general.

So, if I understood correctly wine needs to build 3 different flavors of the gcc compiler, all for the same build, that is to build just 1 wine binary, we need these 3 flavors in the same build.
What is the mechanism to use one gcc and not the other from the wine consumer side? Because if they are all called gcc, and lets say the recipe adds itself to the PATH env-var, then only the first gcc will be ever used.

@smoofra
Copy link
Author

smoofra commented Mar 24, 2023

The different architectures could maybe be different binaries, with different package_ids, that would be the recommended approach in general

In an ideal world, maybe. But have you seen wine's build system? It's a world unto itself and this is the way they do things.

And even if i did split wine into 32 and 64 bit package ids, I'd probably just end up with some consumer further up the graph that wants to run both 32 and 64 bit windows programs as tools, so the same issue would re-occur there, with some other package wanting tool_require two different wine packages.

And even if that didn't happen wine still needs at least two gcc packages.

What is the mechanism to use one gcc and not the other from the wine consumer side?

Wine doesn't look for gcc in the PATH, it looks for x86_64-w64-mingw32-gcc and x86_64-linux-gnu-gcc, so there's no conflict.

@prince-chrismc
Copy link
Contributor

Perhaps this is a packaging question? Would it make sense to have 1 package with both 64 and 32 bit versions? Are they always both expected to be together?

@memsharded
Copy link
Member

memsharded commented Mar 24, 2023

Thanks for the feedback, now I think I understood it better.
I have added a test in #13529 that will tentatively close this issue.

I think it captures the use case that you are describing here, please have a look:

  • The trick is setting run=False trait for tool_requires(). It means "I know these could be conflicting in build runtime (which would happen for gcc.exe), but I'll manage"
  • The binaries in the packages will be added to the environment, so they can be called in the consumer build() method by different name

I am also investigating the use case of requiring same version with different options. This could be way more challenging, but lets see...

@smoofra
Copy link
Author

smoofra commented Mar 24, 2023

ah, yea I can confirm that it behaves exactly like I need if run=False and the required versions of gcc are different.

looks good:

(Pdb) p [v.cpp_info.bindirs for k,v  in self.dependencies.build.items() if 'gcc' == k.ref.name]
[['/Volumes/build/conan2/gcc0b2c18cb1ea08/p/bin'], ['/Volumes/build/conan2/gcc92c136d09892a/p/bin']]

If the versions are the same, i get the error ConanException: Duplicated requirement: gcc/9.1.0

@smoofra
Copy link
Author

smoofra commented Mar 24, 2023

I'm pretty confused as to why run=False does it. I thought this only controlled whether things were put into the virtualrunenv. What's the actual rule that controls whether you get one or two gcc nodes in the graph?

@memsharded
Copy link
Member

Added some minor change necessary to make the options case work too, lets see how it goes, this kind of change is a bit risky.

I'm pretty confused as to why run=False does it. I thought this only controlled whether things were put into the virtualrunenv. What's the actual rule that controls whether you get one or two gcc nodes in the graph?

Not really, the run=True indicates that tings will be put in the conanrun if existing, and that if the package name is the same, it is expected that putting both in the environment will make it conflicting, and there will be no way to dissambiguate it. But it doesn't really control if things are put in the conanrun environment, once we tell run=False = we don't care about the potential conflicts, it still knows how to put things in the environment.

@smoofra
Copy link
Author

smoofra commented Mar 24, 2023

@memsharded I tried your branch, it works!

@memsharded
Copy link
Member

Implemented in #13529, will be released next 2.0.5. Thanks for the feedback!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants