-
-
Notifications
You must be signed in to change notification settings - Fork 632
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
Split conan resolve product by target to enforce declared dependencies #6492
Split conan resolve product by target to enforce declared dependencies #6492
Conversation
|
||
def _make_compile_request(self, versioned_target, dependencies, external_libs_product): | ||
target = versioned_target.target | ||
|
||
include_dirs = [self._include_dirs_for_target(dep_tgt) for dep_tgt in dependencies] | ||
include_dirs.extend(self._get_third_party_include_dirs(external_libs_product)) | ||
include_dirs.extend(self._get_third_party_include_dirs(external_libs_product, dependencies)) | ||
print('>>> include_dirs: {}'.format(include_dirs)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO.
This is reviewable. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A test would be nice.
def cache_target_dirs(self): | ||
def create_target_dirs(self): | ||
# We create per-target directories in order to act as isolated collections of fetched files. | ||
# But do not attempt to automatically cache then (cache_target_dirs), because the entire resolve |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/then/them/
|
||
native_external_libs_product = self._collect_external_libs(vts_results_dir) | ||
native_external_libs_product = self._collect_external_libs(invalidation_check.all_vts) | ||
self.context.products.register_data(NativeExternalLibraryFiles, | ||
native_external_libs_product) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is confusion waiting to happen. The type is declared as NativeExternalLibraryFiles
but the instance is a UnionProducts
. Maybe s/NativeExternalLibraryFiles
/NativeExternalLibrary
/ and then subclass UnionProducts
as NativeExternalLibraries
which now contains a union of NativeExternalLibrary
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the above sounds like a good idea -- unsure if we would need to override the copy()
method to return a NativeExternalLibrary
instead of a UnionProducts
, because I think the UnionProducts
method would take precedence over the datatype version.
all_compiled_object_files.extend(object_file_paths) | ||
|
||
return LinkSharedLibraryRequest.with_external_libs_product( | ||
if compiled_objects_product.get(dep_tgt): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unsure whether we should accept the lack of a product for that target and not error out -- I think we should be able to assume the product for the compiled output exists in the mapping (even if the product contains no files), unless there's some polymorphism happening here I'm missing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, that actually makes sense. Maybe a comment on the fact that dep_tgt
could be either an external library or a source library could be useful, as that spooky action happens at a distance in NativeCompile
and isn't immediately evident in this file.
|
||
for vt in invalidation_check.all_vts: | ||
object_files = self.collect_cached_objects(vt) | ||
self._add_product_at_target_base(object_files_product, vt.target, object_files) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The execute method is easier to follow now, thanks.
|
||
native_external_libs_product = self._collect_external_libs(vts_results_dir) | ||
native_external_libs_product = self._collect_external_libs(invalidation_check.all_vts) | ||
self.context.products.register_data(NativeExternalLibraryFiles, | ||
native_external_libs_product) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the above sounds like a good idea -- unsure if we would need to override the copy()
method to return a NativeExternalLibrary
instead of a UnionProducts
, because I think the UnionProducts
method would take precedence over the datatype version.
lib_names = external_libs_product.lib_names | ||
|
||
return cls(*args, external_lib_dirs=lib_dirs, external_lib_names=lib_names, **kwargs) | ||
pass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This factory method is definitely unnecessary thanks to this PR, I neglected to mention that, thanks for reading my mind.
A very simple test for this could be in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Thanks for taking care of this! One simple way of integration testing could be to have two separate ctyes_compatible_cpp_library
targets that both include cereal.h
,and then assert that the build/run fails with the correct compilation error. This should be green on master due to the lack of target-based partitioning.
Also while reviewing this, it occurred to be that there might be static and dynamic object files flying around in various use cases, and there is not a whole lot of differentiation or option declarations around these. Afaict, a static archive might make it into a LinkSharedLibrariesRequest
via NativeExternalLibrary
. As I understand it, we can link both types when depending on a Conan package, so it may be worth it at some point in the future to refactor the class/method names to convey this flexibility.
Totally agree on specifically noting the difference between static and shared libs -- we'll find a way to do that cleanly (as you describe) in #6486 after this is merged, I think (because we don't have any examples of using 3rdparty shared libs in this PR yet). But I'm 100% with you on making these easily differentiable -- not munging together different types of native build products haphazardly is something I think is super important to maintain. I mentioned the use of |
I made this into #6630 because all the work/review here was done and it unblocks landing each of these in parallel since I can fix any merge conflicts. |
Thanks... sorry about that! |
…6630) Takeover of #6492 (which has completely passed review) as it was blocked by progress on two other PRs I have up (#6486, #6628) due to potential merge conflicts, which I can resolve when they come up for each of these PRs to unblock landing them in parallel. The body of #6492 was: ### Problem As described in #6178, the `NativeExternalLibraryFiles` products of a `conan` resolve are not currently partitioned by target, which means it isn't possible to expose individual 3rdparty deps to only their declared dependents. ### Solution Partition the `NativeExternalLibraryFiles` product using `UnionProduct` while producing it in `NativeExternalLibraryFetch` (and switch to using isolated `vt.results_dir` directories per `external_native_library` target), and consume the split product in `NativeCompile` and `LinkSharedLibraries`. ### Result Only declared dependents have access to 3rdparty libraries. Fixes #6178.
… design mistake (#6628) ### Problem *This probably blocks #6486 and #6492.* As @CMLivingston and I realized sometime this week (to my *immense* dismay), we had no tests of native library targets depending on each other. When making these examples, I realized two things: 1. `--strict-deps` doesn't really make sense as two separate options for C and C++ targets which can depend on each other. 2. The implementation of `--strict-deps` in the native backend ("caching" native target interdependencies in a product from the compiler tasks) was absurd and unnecessary. I think I vaguely recall that the fact that `LinkSharedLibraries` previously did not have a subsystem dependency on the `CCompileSettings` or `CppCompileSettings` subsystems may have led to a subtle caching bug in the link task when options in those subsystems were modified, but I don't remember all the details right now. Regardless, that bug would have been fixed with this PR -- see the below: ### Solution - Move dependency calculation into a single `NativeBuildSettings` subsystem which is consumed by compile and link tasks, and use it to calculate the dependencies in both tasks. - Drop the very unnecessary `NativeTargetDependencies` product. - Move a ton of logic into `NativeTask` that really should have been there instead of `NativeCompile`, but couldn't because of the hacked together dependency calculation. - Add a testproject with C and C++ targets depending on each other, and an integration test showing the above all works. ### Result We have a working example of C and C++ targets depending on each other, resulting in idiomatic enough C and C++, which also work extremely effectively in a `python_dist()` target.
Problem
As described in #6178, the
NativeExternalLibraryFiles
products of aconan
resolve are not currently partitioned by target, which means it isn't possible to expose individual 3rdparty deps to only their declared dependents.Solution
Partition the
NativeExternalLibraryFiles
product usingUnionProduct
while producing it inNativeExternalLibraryFetch
(and switch to using isolatedvt.results_dir
directories perexternal_native_library
target), and consume the split product inNativeCompile
andLinkSharedLibraries
.Result
Only declared dependents have access to 3rdparty libraries. Fixes #6178.