-
Notifications
You must be signed in to change notification settings - Fork 946
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
[question] How to I model private (lib-only) component dependencies? #16190
Comments
Hi @paulharris I am not sure if I understand the issue.
Then, those headers cannot be "private". This is not how headers inclusion works in C++. If the The only way that headers won't be visible to downstream consumers is when they are an internal implementation detail of the package, that is, when they are included exclusively by In your case of your code, I don't see any such self.cpp_info.components["private_function"].includedirs = [] Please try that and let me know. |
I guess the confusion comes from me saying "public" and "private". I will adjust my example project to suit. Notes:
Also note that component-a's public headers do NOT include component-b's headers, it is an internal dependency. So if component-a is required, component-b's header dir should not also be added to the argument list. The library has many parts, with the headers in different subfolders. The goal is to ensure that if a consumer did NOT do The reason is that you can get "hidden dependencies" that way. For example, consumer does BUT, if a conan-library-option changes, or the code changes, and component-b no longer links to component-a, then the headers will still #include but the linker will fail. This problem is solved at the package level, with the transitive headers and default 'private' dependencies. But this same problem also occurs at the component level, and I don't see a mechanism to model this. |
There, hopefully the example project demonstrates this nicely. I see this behaviour on a much bigger scale, in a much bigger library/recipe I'm packaging. |
I was thinking about this a little more.
And cmake would handle adding the libraries to the linker. This doesn't seem possible to model with conan? As a workaround, I could add componentB's libs to the list of libs for componentA in the And the libraries would then be repeated in the linker command line quite a lot, as it is common to depend on half a dozen components, each one of those depending on a tree of components. There would be a lot of common components between them eg a "MathCore" component, for example. |
This should be possible to model it with Conan:
So, in short, unless I have understood it incorrectly, it is just a mistake in the Please, let me know if this clarifies the issue. |
I don't think you are understanding correctly. I'll try again. The consumer may want to use compa, OR, compb, OR both compa and compb. CompB must also be packaged. The goal is that if your consumer's cmake target asks for CompA only, you do not get accidental access to CompB's headers. And the consumer can ask for both. So for example, my project is cmake.
In this case, if ModuleX's source code has this: And, in the same project, I have another module, ModuleY.
In this case, if ModuleY's source code has this: And, in the same project, I have another module, ModuleZ.
In this case, if ModuleZ's source code can #include both compa_function.h and compb_function.h successfully. |
I see now what you mean. No, I am afraid it is not possible. Header visibility is not defined at the component level. If the headers of |
So then conan can't fully model what cmake can do with its target_link_libraries() ?
and "thecode.cpp" wouldn't get access to compb's headers. Perhaps put this on the radar for the future? As a workaround, all I need is to add compb's libs to compa. For example
I would have to be careful to append all the libs to all the dependent modules, but I think it can be done in my case. There is a whole tree of component dependencies, so it isn't so simple as this example. Is the 'libs' a simple python list? Perhaps I could do:
So then if a consumer requires/links to both compa and compb, then the |
Conan can model the visibility with even more control than cmake at the package level. But it is true that
So far, it doesn't seem possible. That would imply to extend the traits model to the
I think that for most modern linkers it shouldn't be a big issue, but this is not guaranteed.
The question is: is it really worth it? Conan 1 has served well for many years without any protection/hiding of transitive headers at all. All headers of all packages were always visible to the consumers.
No, Conan does not simplify/collapse or remove duplicates from those lists. Sometimes, when there are circular dependencies, some linkers might actually need the repetition of some libraries. |
Ok thanks, will accept the limitations and hope for the future. |
What is your question?
I have made an example project
https://github.com/paulharris/conan-test-private-components
Two scripts:
test_fails_include.sh
-- adds the component-requirement, but consumer can see headertest_fails_link.sh
-- does NOT add the requirement, and the consumer cannot successfully linkHow do I add a "libs only" component-requirement on another component in package_info() ?
I have a recipe with two components. Component
public_component
links to componentprivate_component
.My consumer depends on
public_component
only, and SHOULD NOT have access to the headers from the private component (this is the key point).In package_info() of the recipe, I should normally have a line that says:
self.cpp_info.components["public_component"].requires = ["private_component"]
But if I add that,
because I noticed that if I do that, my consumer then depends on PRIVATE too, and has access to PRIVATE's header files.
Skipping the 'requires' line works fine for DLL/shared lib builds.
But for the static lib, PRIVATE is not added to the final link lib list.
Have you read the CONTRIBUTING guide?
The text was updated successfully, but these errors were encountered: