Compiler option sets for Native targets - #6665
Conversation
|
@CMLivingston talked about this offline... I had initially suggested that it would be easier to add @cosmicexplorer : If you agree that it is worthwhile to do |
|
I'll move forward with |
|
Took a first pass at option sets. @cosmicexplorer I tried to capture what you were talking about as using a mixin for shared default option set keys. Please let me know if this is at all related to what you were describing. More testing to come after I get the green light. Thanks! |
| # flags! | ||
| register('--fatal-warnings', type=bool, default=True, fingerprint=True, advanced=True, | ||
| help='The default for the "fatal_warnings" argument for targets of this language.') | ||
| register('--fatal-warnings-enabled-args', advanced=True, type=list, fingerprint=True, |
There was a problem hiding this comment.
The changes to the fatal-warnings option should not be necessary here: can leave it as is, and then it can be deprecated in a followup.
| help='Extra compiler args to use when fatal warnings are disabled.') | ||
| register('--compiler-option-sets-enabled-args', advanced=True, type=dict, fingerprint=True, | ||
| default={ | ||
| 'fatal_warnings': list(cls.get_fatal_warnings_enabled_args_default()), |
There was a problem hiding this comment.
Given that this backend is fairly young, I don't think that you should worry about attempting to preserve backwards compatibility here. So it should be fine to have the default enabled/disabled args just be empty.
| 'include_dirs', | ||
| 'sources', | ||
| ('fatal_warnings', bool), | ||
| ('ndebug', bool), |
| include_dirs=include_dirs, | ||
| sources=sources_and_headers, | ||
| fatal_warnings=self._compile_settings.get_fatal_warnings_value_for_target(target), | ||
| compiler_option_sets_options=self._compile_settings.get_merged_compiler_options_for_target(target), |
There was a problem hiding this comment.
At this point they will have been flattened, so you can probably just call this field compiler_options.
|
@stuhood regarding inheritance of |
There are a few things to think about, and I'm not sure I can recommend the appropriate thing here, but I know that @cosmicexplorer can: Using a Subsystem always means creating a new "namespace". If you scope the subsystem ( If you use inheritance, then you're just adding the options directly to some existing ( |
8eba2b6 to
6801834
Compare
|
|
||
| class NativeBuildStepSettingsBase(Subsystem, MirroredTargetOptionMixin): | ||
|
|
||
| options_scope = 'native-build-step-settings-base' |
There was a problem hiding this comment.
I think that this class is supposed to be abstract, and then mixed in to a language specific subsystem? If so, it shouldn't need an options_scope to be defined, because the subclass will handle that.
There was a problem hiding this comment.
This is here to allow for base options set definitions that can be shared between C and CPP (different from default option set keys).
There was a problem hiding this comment.
Ok. Do we think that that is a blocker? Might be easier to wait to add that flexibility if need be.
Or to go the other way? I know that in a previous revision @cosmicexplorer mentioned that he wasn't sure that the C/C++ language split was carrying its weight: #6628 (review)
There was a problem hiding this comment.
...oh, nevermind. I misinterpreted that.
| compiler_options = set() | ||
|
|
||
| # Set values for enabled options. | ||
| if compiler_option_sets: |
There was a problem hiding this comment.
Below you directly access the compiler_option_sets variable, which implies that it is not None within this method... if that's the case, it should be fine to just have this loop at the top level rather than guarded by the if.
| .get_fatal_warnings_value_for_target(target)), | ||
| compiler_options=(self._compile_settings | ||
| ._native_build_step_settings | ||
| .get_merged_compiler_options_for_target(target, |
There was a problem hiding this comment.
It looks like the get_merged_compiler_options_for_target method already includes the enabled/disabled args dicts... are the arguments here a different collection of options? If so, is there a usecase for that? It's sortof confusing.
There was a problem hiding this comment.
These arguments are to compose the dicts for the subclasses into the calculation. The dicts that are pulled from self.get_options() belong to the base class.
|
ping @stuhood, this is in a good state for review when you can. |
stuhood
left a comment
There was a problem hiding this comment.
This is very close, but there is one big open question. Thanks!
| from pants.util.memo import memoized_property | ||
|
|
||
|
|
||
| class NativeBuildStepSettings(Subsystem, MirroredTargetOptionMixin): |
There was a problem hiding this comment.
I'm not completely clear on why this is a different subsystem than NativeBuildSettings.
Rather than adding this subsystem, would it be useful to just define the new options on that subsystem? And if they need to be split for some reason, could you add docstrings to both of them explaining why?
There was a problem hiding this comment.
The difference is described in #6486 -- https://github.com/pantsbuild/pants/blob/5e320b721c234cdc6a56e5c762441a87741d85d7/src/python/pants/backend/native/subsystems/native_build_step_settings_base.py. They are named like this because that PR is still in development. The names could maybe be improved -- I don't like calling everything "settings" but want to differentiate it from e.g. the compile tasks.
cosmicexplorer
left a comment
There was a problem hiding this comment.
I would really like the implementation of compiler_option_sets to be shared with the JVM implementation for this to be merged, ideally as a mixin (something similar to e.g. MirroredTargetOptionMixin). Even getting the hang of understanding how to use compiler_option_sets has been described as difficult to me from users consuming the JVM version, and I really don't want to introduce further idiosyncracies.
The reason why I want this is because we'll never have to make any subsystems just to add a compiler option ever again, and because then every other subsystem will have a deep knowledge of which settings to apply in which scenarios, which could potentially make it extremely easy to then implement reliable and granular caching of native artifacts in a way, yet again, that no other build tool can do.
| import os | ||
|
|
||
|
|
||
| def get_generated_shared_lib(lib_name): |
There was a problem hiding this comment.
Question unrelated to this specific code -- is there a way we can package the ctypes dylibs in a way that allows us to access it like a JVM resource instead of hardcoding the relative path? Not anything to fix in this PR specifically.
There was a problem hiding this comment.
I'm not sure. I think there would need to be coherence between the compile tasks and the resource target handling. However, I think resources just pull in the same dir structure as the path you provide to the resource files themselves (I'm not too familiar with that target type).
There was a problem hiding this comment.
Made #6711 in case anyone gets any smart ideas.
| ] | ||
| pants_run = self.run_pants(command=command, config={ | ||
| 'native-build-step-settings.cpp-compile-settings': { | ||
| 'compiler_option_sets_enabled_args': { |
There was a problem hiding this comment.
This makes me pretty happy to see, we are changing the C/C++ game every step of the way.
| from pants.util.memo import memoized_property | ||
|
|
||
|
|
||
| class NativeBuildStepSettings(Subsystem, MirroredTargetOptionMixin): |
There was a problem hiding this comment.
The difference is described in #6486 -- https://github.com/pantsbuild/pants/blob/5e320b721c234cdc6a56e5c762441a87741d85d7/src/python/pants/backend/native/subsystems/native_build_step_settings_base.py. They are named like this because that PR is still in development. The names could maybe be improved -- I don't like calling everything "settings" but want to differentiate it from e.g. the compile tasks.
|
This is in a great state for a final pass @stuhood @cosmicexplorer. |
| import os | ||
|
|
||
|
|
||
| def get_generated_shared_lib(lib_name): |
There was a problem hiding this comment.
Made #6711 in case anyone gets any smart ideas.
stuhood
left a comment
There was a problem hiding this comment.
Looks good! Just a naming nit. Thanks for iterating here.
|
|
||
| class NativeBuildStepSettings(CompilerOptionSetsMixin, MirroredTargetOptionMixin, Subsystem): | ||
|
|
||
| options_scope = 'native-build-step-settings' |
There was a problem hiding this comment.
This is still pretty verbose. Putting the words "options" or "settings" in the names of options is probably superfluous.
In this case you're ending up with a subsystem instance scope named native-build-step-settings.c-compile-settings.
Problem
Native targets do not have support for compiler option sets.
Solution
Add support for compiler options sets for use in native compile tasks.
Result
Users can specify option set defaults and their corresponding default enabled values in Pants.ini. Native targets support option sets.