Closed sdroege closed 1 year ago
I'm wondering if the approach of using a regular target for proc_macro was the wrong one, maybe it would make more sense to add proc_macro to the rust
module, where we can just enforce that everything is for the build target and not the host target
That would make sense, yes. Does meson have any kind of concept of a "build dependency" for something, or a "build tool" that has to be built itself during the build to produce some other target?
Yes? You just create e.g. an executable with type native: true
. You don't need anything fancier. A custom_target can use any executable, even a native one, as its command:
kwarg.
Sure but that seems extremely generic and doesn't seem specific enough for exposing proc-macros. So maybe a special custom target as part of the Rust module makes most sense after all, which then could enforce that it's only used in the right places and is always compiled natively.
It's not entirely clear to me how this all works, but I think basically you need this:
pm = shared_library(
'proc_macro_examples',
'proc.rs',
rust_crate_type : 'proc-macro',
)
to be this:
pm = shared_library(
'proc_macro_examples',
'proc.rs',
rust_crate_type : 'proc-macro',
native: true,
)
except that because it is a proc-macro crate it automatically forces native: true
and also despite that usually native and cross targets cannot be linked into the same final executable or shared library, a proc-macro can because it's actually
loaded and run by the compiler during compilation
and not in fact linked into the executable?
yeah, exactly. It's more like a compiler extension
One thing that this makes me realize we're probably going to have to solve is that currently a subproject can only be built for one machine (ie, either host or build) but not both
I guess this could be made to work with the current mechanism but would require adding a couple of special cases all over the place. Maybe it's not too bad, worth a try.
One thing that this makes me realize we're probably going to have to solve is that currently a subproject can only be built for one machine (ie, either host or build) but not both
That's a limitation of cargo too AFAIU. Either your crate is a proc-macro or it's not, but you can't make it both at once.
What situation do you imagine where this could be useful?
It's not really rust-specific, but. Imagine you have, say, a program that acts as a codegen tool. myproject-generate-sources.c
.
This program makes heavy use of glib for the general reasons that people make general use of glib. So you need to depend on a dependency('glib-2.0', native: true)
. But the produced sources are used to create "myproject", an executable that also makes heavy use of glib, and thus requires dependency('glib-2.0', native: false)
.
So this works fine in a native build, because both native: false
and native: true
are the same machine and the same *.so files. You can build glib as a subproject and this works. But it fails in cross compilation: you can get both native and cross glib from the system and from a sysroot, but what do you do about building one (cross) glib subproject for myproject.exe, and one (native) glib subproject for myproject-generate-sources.exe?
I see, I didn't get that connection. That's problematic indeed :) There will be many cases where a proc-macro crate will have a dependency that is also used by normal build targets, so that dependency would have to be built for both.
So making the main part of this issue work was actually less bad than expected. From what I could find, only 2 places needed a bit of special casing. See https://github.com/mesonbuild/meson/pull/11743
I'll create another issue for the bigger problem of requiring multiple builds of a dependency.
The PR doesn't seem to work. I pulled the patch into the meson master, and changed the proc-macro crate with native: true
, but got an error in setup time. I was trying to port the foreign-types crate which depends on foreign-types-macros crate.
../subprojects/foreign-types-macros-0.2.3/meson.build:16:23: ERROR: Tried to mix libraries for machines 0 and 1 in target 'foreign_types_macros' This is not possible in a cross build.
Why don't you comment on the PR? :)
Also can you make a testcase available? For me the PR still works with test cases/rust/18 proc-macro
and cross-compiling from Linux/x86-64 to Linux/aarch64.
Why don't you comment on the PR? :)
Sorry. I should've done that.
Also can you make a testcase available? For me the PR still works with
test cases/rust/18 proc-macro
and cross-compiling from Linux/x86-64 to Linux/aarch64.
If the proc-macro crate has no dependencies, it's fine. Perhaps I hit this issue #11744.
Yeah if it has dependencies you need to make sure that all dependencies are native: true
too (and that they're not used for anything native: false
, i.e. that they're only used for proc macros).
I think this is fixed by https://github.com/mesonbuild/meson/pull/11714. We now have rust.proc_macro()
which is always native build.
Describe the bug
meson currently always uses the host architecture for building proc-macro targets, which is wrong. proc-macro targets are loaded and run by the compiler during compilation so must be compiled for the build architecture.
Also in extension this means that all dependencies of the proc-macro target also must be compiled for the build architecture, and with this it can happen that dependencies have to be compiled for both the build and host architecture (if they're used by targets for both).
To Reproduce
Try cross-compiling
test cases/rust/18 proc-macro
and see how it fails:When running the commands manually and selecting the correct target for the proc-macro it builds fine:
CC @dcbaker