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

interpreter: add a new function add_project_dependencies() #10206

Merged
merged 4 commits into from May 3, 2022

Conversation

bonzini
Copy link
Contributor

@bonzini bonzini commented Mar 29, 2022

This function can be used to add fundamental dependencies such as libm, dependency('threads') or glib to all build products in one fell swoop. This can be useful whenever, due to a project's coding conventions, it is not really possible to compile any source file without including the dependency.

This function also makes it possible to add an include_directories() object to the project, removing the need to list both source and global directories. An example from QEMU is this:

  add_project_arguments('-isystem', meson.current_source_dir() / 'linux-headers',
                        '-isystem', 'linux-headers',
                        language: ['c', 'cpp'])

which might become:

   linux_headers = declare_dependency(include_directories: 'linux-headers').as_system('system')
   add_project_dependencies(linux_headers, language: ['c', 'cpp'])

@bonzini bonzini requested a review from jpakkane as a code owner March 29, 2022 12:53
@eli-schwartz
Copy link
Member

This would also spare @rgommers the need to check if find_library('m') is found and then add -lm as project link args.

Seems reasonable enough, anyway.

@eli-schwartz
Copy link
Member

add_project_arguments and suchlike cannot be used after build targets have been defined, IIRC.

@bonzini
Copy link
Contributor Author

bonzini commented Mar 29, 2022

add_project_arguments and suchlike cannot be used after build targets have been defined, IIRC.

I think you could use override_dependency on a superproject and add_project_dependency() on a subproject, so I preferred to reuse the check on is_built().

@codecov
Copy link

codecov bot commented Mar 29, 2022

Codecov Report

Merging #10206 (55a3c08) into master (bba588d) will decrease coverage by 18.18%.
The diff coverage is n/a.

❗ Current head 55a3c08 differs from pull request most recent head 8d437e2. Consider uploading reports for the commit 8d437e2 to get more accurate results

@@             Coverage Diff             @@
##           master   #10206       +/-   ##
===========================================
- Coverage   68.48%   50.30%   -18.19%     
===========================================
  Files         406      203      -203     
  Lines       87400    43590    -43810     
  Branches    19422     9664     -9758     
===========================================
- Hits        59854    21926    -37928     
+ Misses      23044    19688     -3356     
+ Partials     4502     1976     -2526     
Impacted Files Coverage Δ
modules/qt5.py 0.00% <0.00%> (-100.00%) ⬇️
modules/modtest.py 0.00% <0.00%> (-100.00%) ⬇️
scripts/msgfmthelper.py 0.00% <0.00%> (-100.00%) ⬇️
modules/keyval.py 0.00% <0.00%> (-95.24%) ⬇️
scripts/vcstagger.py 0.00% <0.00%> (-91.67%) ⬇️
modules/sourceset.py 0.00% <0.00%> (-87.58%) ⬇️
scripts/depscan.py 0.00% <0.00%> (-83.92%) ⬇️
scripts/hotdochelper.py 0.00% <0.00%> (-81.49%) ⬇️
modules/i18n.py 0.00% <0.00%> (-80.16%) ⬇️
modules/unstable_wayland.py 0.00% <0.00%> (-79.67%) ⬇️
... and 321 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 5c0145c...8d437e2. Read the comment docs.

@eli-schwartz
Copy link
Member

eli-schwartz commented Mar 29, 2022

No, I mean this:

def _add_project_arguments(self, node: mparser.FunctionNode, argsdict: T.Dict[str, T.Dict[str, T.List[str]]],
args: T.List[str], kwargs: 'kwargs.FuncAddProjectArgs') -> None:
if self.subproject not in argsdict:
argsdict[self.subproject] = {}
self._add_arguments(node, argsdict[self.subproject],
self.project_args_frozen, args, kwargs)
def _add_arguments(self, node: mparser.FunctionNode, argsdict: T.Dict[str, T.List[str]],
args_frozen: bool, args: T.List[str], kwargs: 'kwargs.FuncAddProjectArgs') -> None:
if args_frozen:
msg = f'Tried to use \'{node.func_name}\' after a build target has been declared.\n' \
'This is not permitted. Please declare all arguments before your targets.'
raise InvalidCode(msg)

It's forbidden to add global/project compile/link arguments if that would override the immutability of a previously declared build target. This isn't about the one you just created. Any build target at all.

@bonzini
Copy link
Contributor Author

bonzini commented Mar 29, 2022

It's forbidden to add global/project compile/link arguments if that would override the immutability of a previously declared build target. This isn't about the one you just created. Any build target at all.

I understand, but I don't understand why it's relevant. I'm sure it is, but I am missing the link.

@eli-schwartz
Copy link
Member

eli-schwartz commented Mar 29, 2022

EDIT: I now see it shares implementation with add_project_arguments.

This official GitHub app is trash and makes diffs practically unreadable. Back to the website it is.

Copy link
Member

@dcbaker dcbaker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've only looked at the implementation, not at whether this is a good idea. I'm leaving that up to @jpakkane

mesonbuild/dependencies/base.py Show resolved Hide resolved
mesonbuild/interpreter/interpreter.py Show resolved Hide resolved
@rgommers
Copy link
Contributor

This would also spare @rgommers the need to check if find_library('m') is found and then add -lm as project link args.

For context, that code can be found here and looks like:

# We need -lm for all C code (assuming it uses math functions, which is safe to
# assume for SciPy). For C++ it isn't needed, because libstdc++/libc++ is
# guaranteed to depend on it. For Fortran code, Meson already adds `-lm`.
m_dep = cc.find_library('m', required : false)
if m_dep.found()
  add_project_link_arguments('-lm', language : 'c')
endif

That is't too bad in the end, but figuring out the details and how every language treats mlib differently was a little nontrivial. So I guess it's the code comment rather than the add_project_link_arguments above that took the work here; if that logic could be built in I think that would make sense.

@tristan957
Copy link
Contributor

Would be pretty interesting to see an add_project_include_directories() too.

@xclaesse
Copy link
Member

xclaesse commented Apr 7, 2022

Would be pretty interesting to see an add_project_include_directories() too.

Could be nice, but that could already be done easily with this PR:

incdir = include_directories('include')
dep = declare_dependency(include_directories: incdir)
add_project_dependency(dep)

Implementation looks good to me and I like the idea as well. LGTM.

@xclaesse
Copy link
Member

xclaesse commented Apr 7, 2022

add_project_arguments and suchlike cannot be used after build targets have been defined, IIRC.

I think you could use override_dependency on a superproject and add_project_dependency() on a subproject, so I preferred to reuse the check on is_built().

Using is_built() is stricter that relying on add_project_arguments() that checks we have no built targets in current project, because we also want to forbid using built targets from other subprojects. So I think we are all good on this.

@tristan957
Copy link
Contributor

Would be pretty interesting to see an add_project_include_directories() too.

Could be nice, but that could already be done easily with this PR:

incdir = include_directories('include')
dep = declare_dependency(include_directories: incdir)
add_project_dependency(dep)

Implementation looks good to me and I like the idea as well. LGTM.

Yep good point. My motivation for making that comment was essentially that we now have global options for all the important kwargs in build_target(): add_project_link_args(), add_project_args(), add_project_dependencies(). So adding add_project_include_directories() would finish it out in my opinion.

@bonzini
Copy link
Contributor Author

bonzini commented Apr 15, 2022

@dcbaker, does it look good now?

@bonzini
Copy link
Contributor Author

bonzini commented Apr 16, 2022

Also ping @jpakkane.

@jpakkane
Copy link
Member

There needs to be a test that you can't call this function after any build targets have been defined.

project(...)
executable(...)
add_project_dependencies(...) # <- Must error out.

This is in line with how other such functions work.

@eli-schwartz
Copy link
Member

This does dispatch to self._add_project_arguments() so it should be enforcing that rule, although I guess in theory a refactoring could break that.

@bonzini
Copy link
Contributor Author

bonzini commented Apr 19, 2022

This does dispatch to self._add_project_arguments() so it should be enforcing that rule

On top of that, it is also enforced by the fact that the dependency cannot be a "built" one. See also the new test cases/failing/124 override and add_project_dependency.

@eli-schwartz
Copy link
Member

That doesn't really assert anything as the restriction jpakkane mentioned is about forbidding any dependencies at all, not built ones specifically.

@bonzini
Copy link
Contributor Author

bonzini commented Apr 30, 2022

Ping.

@xclaesse
Copy link
Member

xclaesse commented May 2, 2022

@bonzini it conflicts now, but looks good to me.

Both dependencies.ExternalLibrary and dependencies.InternalDependency are
subclasses of dependencies.Dependency, no need to list them separately.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Extract to a separate function the code that resolves dependencies
for compiler methods.  We will reuse it for add_project_dependencies().

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This function can be used to add fundamental dependencies such as glib
to all build products in one fell swoop.  This can be useful whenever,
due to a project's coding conventions, it is not really possible to
compile any source file without including the dependency.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Test that add_project_dependencies() can only be used before build targets
have been declared.  Also test that one cannot use override_dependency
on a superproject to inject a superproject's build products into the
subproject.  This would violate the rule that build products cannot be used
with add_project_dependencies() (similar to e.g. compiler.has_function),
so check that meson detects the situation correctly.
@xclaesse
Copy link
Member

xclaesse commented May 2, 2022

LGTM when CI is green, thanks!

@eli-schwartz eli-schwartz merged commit 2f68aa2 into mesonbuild:master May 3, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants