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

unclear if using (via -fplugin) a gcc plugin in the same meson.build that builds the plugin is possible #5090

Open
codyps opened this issue Mar 15, 2019 · 10 comments

Comments

@codyps
Copy link
Contributor

codyps commented Mar 15, 2019

I'm trying to build a gcc compiler plugin with meson, and use that same gcc compiler plugin within the meson project. (Here's a git repo for reference, but I'll try to reproduce most relevent content here).

Right now, I've got the following meson.build:

project('gcc-plugin-test', ['cpp', 'c'])

cc = meson.get_compiler('c')
plugin_dev_path_result = run_command(cc.cmd_array(), '-print-file-name=plugin')
plugin_dev_path = plugin_dev_path_result.stdout().strip()
plugin_inc = include_directories([join_paths(plugin_dev_path, 'include')])

myplugin = shared_module('myplugin',
        'myplugin.cc',
        include_directories: plugin_inc
)

test_1 = executable('test-1', 'test-1.c',
        c_args: [ '-fplugin=' + myplugin.full_path() ],
        native: true,
)
test('test_1', test_1)

Unfortunately, using myplugin.full_path() and string formatting is not sufficient to create a dependency like test_1.c.o: myplugin.

I've attempted a few methods of creating this dependency, without much luck:

  1. direct dependencies: myplugin => meson.build:13:0: ERROR: Tried to use a build target as a dependency.
  2. dependencies: files(myplugin.full_path()) => meson.build:13:0: ERROR: File /home/x/meson-gcc-plugin/_b/libmyplugin.so does not exist.
  3. link_with: myplugin => well, I don't actually want to link it. But this doesn't work because the dependency only shows up for the link step, not the compile step.
  4. try using an custom target as the final generate step for the plugin => nope, can't depend on custom targets.

Any input here on the intended mechanism for doing this (if there is one) would be appreciated.

@nirbheek
Copy link
Member

How do you normally tell gcc to load a plugin from a custom location? Is there a command-line argument to gcc for it? An env var?

@codyps
Copy link
Contributor Author

codyps commented Mar 15, 2019

Normally, you'd pass the path to -fplugin=. Note that the meson.build snippet I have above does actually work... eventually. After a few build failures (due to lack of the plugin being fully built), the plugin does get built and test_1 (the executable) is successfully built.

The key issue is that I need some way to represent the dependency between compilation within the executable() and the creation of the shared_module().

@nirbheek
Copy link
Member

nirbheek commented Mar 15, 2019

The reason why adding it to link_with: doesn't work is because link targets are not required when the compilation is done, so the dependency is actually in the link stage, not the compile stage.

What you want to do is use a custom_target() as an intermediary. Something like:

myplugin = shared_module('myplugin',
        'myplugin.cc',
        include_directories: plugin_inc
)

dummy = custom_target(input : myplugin,
        output : 'dummy.h',
        command : ['echo'],
        capture: true)

test_1 = executable('test-1', 'test-1.c', dummy,
        c_args: [ '-fplugin=' + myplugin.full_path() ],
        native: true,
)

This will make meson think that the executable requires a header generated by that custom target, and the header depends on that plugin library being built.

codyps pushed a commit to codyps/meson-gcc-plugin that referenced this issue Mar 15, 2019
@codyps
Copy link
Contributor Author

codyps commented Mar 15, 2019

Yep, that pattern does allow me to get this working. For reference, here's the meson.build I've used:

project('gcc-plugin-test', ['cpp', 'c'])

cc = meson.get_compiler('c')
plugin_dev_path_result = run_command(cc.cmd_array(), '-print-file-name=plugin')
plugin_dev_path = plugin_dev_path_result.stdout().strip()
plugin_inc = include_directories([join_paths(plugin_dev_path, 'include')])

myplugin = shared_module('myplugin',
	'myplugin.cc',
	include_directories: plugin_inc
)

myplugin_dep = custom_target('myplugin',
	input: myplugin,
        output: 'myplugin_dep.h',
        command: ['echo'],
        capture: true
)

test_1 = executable('test-1', 'test-1.c', myplugin_dep,
	c_args: [ '-fplugin=' + myplugin.full_path() ],
	native: true,
)
test('test_1', test_1)

codyps added a commit to codyps/meson-gcc-plugin that referenced this issue Mar 15, 2019
@nirbheek
Copy link
Member

I think we could add a kwarg depends: on build targets that adds a 'conservative' dependency on that target and requires it to be built before anything from that target is done. I've encountered other use-cases for that in the past.

@jpakkane
Copy link
Member

Yes.

Enlightenment-bot pushed a commit to Enlightenment/efl that referenced this issue Jun 10, 2020
Ideas and some code from mesonbuild/meson#5090

This is just an example plugin that cold be used as a starting point.
Right now we find efl_super() with GIMPLE and add a efl_super2 call when
it was defined and in code before to allow linking.
Enlightenment-bot pushed a commit to Enlightenment/efl that referenced this issue Jun 30, 2020
Ideas and some code from mesonbuild/meson#5090

This is just an example plugin that cold be used as a starting point.
Right now we find efl_super() with GIMPLE and add a efl_super2 call when
it was defined and in code before to allow linking.
Enlightenment-bot pushed a commit to Enlightenment/efl that referenced this issue Jul 8, 2020
Ideas and some code from mesonbuild/meson#5090

This is just an example plugin that cold be used as a starting point.
Right now we find efl_super() with GIMPLE and add a efl_super2 call when
it was defined and in code before to allow linking.
@eli-schwartz
Copy link
Member

@anarazel you recently asked about this.

@eli-schwartz
Copy link
Member

The very specialized way to do this is by adding a gcc_plugin / clang_plugin kwarg which handles this internally and manages the c/cpp _args for you as well.

Allowing arbitrary file dependencies is a lot more flexible... possibly "too" flexible as it would allow people to do stuff like "depends: my_generated_c" and then do #include "foo.c", which is gross. Though how important is it to actually stop this...

OTOH it may not be so bad if it can be used for that. In order to properly handle stuff like gcc -fplugin, we would need to rebuild every source file if the depends target is updated. That also means if you do odd things like depending on a .c file which is included where it should be named as a header... you end up rebuilding every single source file pointlessly. So header sources still win out as the proper solution, yay.

So I'm inclined to think this does indeed make sense anyway.

@anarazel
Copy link
Contributor

anarazel commented Jul 5, 2022

The very specialized way to do this is by adding a gcc_plugin / clang_plugin kwarg which handles this internally and manages the c/cpp _args for you as well.

That seems too specialized to me. Another case is e.g. profiles for profile-guided-optimization that need to be generated first? What if somebody wants to parse a spec file to the compiler? To me adding special-case options for these kinds of things to the buildsystem just requires accumulating too much special magic that more often than not will still not suffice.

Allowing arbitrary file dependencies is a lot more flexible... possibly "too" flexible as it would allow people to do stuff like "depends: my_generated_c" and then do #include "foo.c", which is gross. Though how important is it to actually stop this...

It's imo an anti-goal to stop stuff like that. I'd avoid it for new projects, but for people migrating it's just completely unnecessary pain.

@eli-schwartz
Copy link
Member

The spec file example actually works as gcc -spec foo.spec, so it would be viable to support c_args taking non-string values that resolve to a filename, and automatically set up dependencies that way. (Just like custom_target command elements.) Obviously, this does not always work, for example -fplugin...

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

No branches or pull requests

5 participants