-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
Better support for bare metal and low level OS targets #6434
Comments
@marc-h38, I'm sure you have some ideas. |
Besides the cyclic dependency between libc/python, what kind of issues do you have in mind? (I would love to build my libc as meson subproject, to have 0 dependencies, lol) |
@keith-packard is building a tiny libc with meson, so I figured he'd have some suggestions. |
So, I've run into a couple of minor issues. The first one is that the compiler tests which check whether you can generate and run an executable just aren't going to do very well when building the toolchain.
The second issue was in how the exe_wrapper stuff works. I need to run a shell script distribued with my source code as an exe_wrapper, but meson makes that hard. I hacked around that by adding the meson.source_root() to the environment and making my exe_wrapper a bit of shell code that uses the environment variable. I'm not worrying about bootstrapping a native build environment; that's an OS distribution problem, not a build system problem. |
If you always need |
Yes, -nostdlib in the cross file worked fine. However, -nostdlib also skips libgcc.a, so I had to re-add that when building my test applications, so I'd prefer to not include that. I think what I'd prefer is to have a configuration option that skipped the compilation tests entirely. If this seems like something you'd incorporate into meson, I can cook up a patch. |
I'd prefer if we could make the sanity check more robust instead. Having cross files that point to the wrong things is not that uncommon. |
Then the sanity check should only attempt to compile a trivial function with no headers and check that a .o file is produced. That would at least verify that the compiler path isn't completely broken. |
That is what it already does if an exe wrapper is not defined. |
The code I have attempts to build a complete executable, not just a single object file. By specifying -nostdlib on the command line, this happens to "work" (in that the compile succeeds with only warnings), but it probably shouldn't have as the resulting elf file is quite broken. I also have an exe wrapper defined as I'm building test applications and running them under qemu; my magic exe wrapper hacks can tell when meson is running the sanity check and skips actually attempting to run that file. I certainly appreciate that meson is testing the build environment so we reduce the errors seen only once you attempt to run ninja; this is a great design goal. And, of course, thanks much for thinking about how this issue might inform future meson changes; I've managed to work around all of the meson limitations so far and am really happy using it instead of the alternatives :-) |
Thanks @dcbaker for opening this.
Yes, although I'm going to ask forgiveness not permission and use it as an "umbrella" issue pointing at other github issues without repeating too much of them. Probably the main issue I met is the need for a "Main issue" = the issue requiring the most lines of extra (meson.build) code. Probably not the most time-consuming one, especially not if you just re-use my In an ideal world with a large choice of nicely designed, maintained and open-source toolchains no one should ever invoke anything but the compiler front-end which should always "know better". First, I'm afraid the world of toolchains is far from ideal. Even if it were, few toolchains seem to explicitly support "bare metal", they all seem to assume some "target" environment + an organically grown, cryptic and of course non-portable grab bag of BTW does meson assume that linkers on Unix build systems are always "dynamic"? https://mesonbuild.com/howtox.html#set-dynamic-linker Maybe not the best example but even with For other examples just add some Related to the above, the This wouldn't hurt: Explicitly disable pie when pie is false #4651 (a couple more items coming)
Saving someone a search: https://github.com/keith-packard/picolibc |
Usability issue. Meson assumes this workflow:
However toolchains suck (breaking news...) and suck even more for "bare metal", see above. So getting everything to work takes a significant amount of meson time and effort. This work requires re-running meson and ninja every time which is expected but somewhat tedious. Starting from some version (0.52?) meson supports multiple, layered Long story short I ended up with non-portable wrapper script(s) on top of meson, which is itself... already a "layer" on top of ninja? I think this user interface issue could be entirely solved with two new features and one small change:
I can create some new github issue(s) out of this comment if none yet, just let me know. See also |
This is not specific to "bare metal". It just hurts more in cross-compilation and maybe even more in "bare metal" |
This is a very interesting project using Meson and bare metal: https://github.com/pabigot/nrfcxx. @pabigot is the author. |
The plan has been to be able to set meson level settings and project level settings with cross/native files. Would that do what you need? |
Is the plan available somewhere? I don't mind searching.
Well, it wouldn't help with finding and typing the right combination of
Of course such wrapper(s) can be implemented in Python for portability, however PS: I just remembered argparse supports this "for free" as long as no future flag makes it ambiguous: |
There is an issue about it, I can't seem to find it now (I thought I assigned it to myself...) |
I think I found it, please confirm: Use native files for saving the command line #4637
Indeed https://github.com/mesonbuild/meson/issues?utf8=%E2%9C%93&q=is%3Aopen+assignee%3Adcbaker |
I think that's related, but there at least was an issue about being able to store project and meson options in a cross file (this issue predates the native file IIRC) |
@dcbaker found it and it is Generic overrider functionality #3001 UPDATE: After a discussion on IRC, it's still not clear to me whether #3001 will avoid the need for wrapper scripts like the d-xxx-configure scripts found at https://github.com/keith-packard/picolibc/tree/80528c684 |
The idea of #3001 is to be able to take anything that could be passed on the command line and put it in a cross/native (I'm going to call them machine files now) file. #4637 is about using that ability to replace the opened coded format we currently use to serialize command line options to meson and instead produce a valid native file @keith-packard, @marc-h38, you can already encode paths in the machine files, although I see there are more options that Keith is using than just extending paths: [paths]
libdir = 'picolibc/xtensa-esp32-elf/lib'
includedir = 'picolibc/xtensa-esp32-elf/include'
[binaries]
c = 'xtensa-esp32-elf-gcc'
ar = 'xtensa-esp32-elf-ar'
as = 'xtensa-esp32-elf-as'
ld = 'xtensa-esp32-elf-ld'
strip = 'xtensa-esp32-elf-strip'
[host_machine]
system = 'unknown'
cpu_family = 'esp32'
cpu = 'esp32'
endian = 'little' |
Interestingly I noticed a -nolibc which seems like a recent addition to gcc - see https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html which doesn't skip libgcc |
Maybe it will helps to someone. I build cross binaries for MCU with clang and ldc2. Clang also used as linker. [host_machine]
system = 'bare metal'
cpu_family = 'arm'
cpu = 'cortex-m3'
endian = 'little'
[binaries]
d = 'ldc2'
c = 'clang'
strip = 'llvm-strip'
[properties]
d_args = ['--mtriple=arm-none-eabi', '-mcpu=cortex-m3'] #ldc isn't understand LLVM "vendor" code
c_args = ['-target', 'arm-unknown-none-eabi', '-mcpu=cortex-m3']
c_link_args = [
'-target', 'arm-unknown-none-eabi',
'-mcpu=cortex-m3',
'--no-standard-libraries',
'-Xlinker', '-marmelf',
#'-Xlinker', '--fatal-warnings',
'-L../subprojects/libopencm3/lib/', #just to convient pick linker script below
'-Xlinker', '--script=stm32/f1/stm32f103x8.ld',
] |
Dave Murphy <[email protected]> writes:
Interestingly I noticed a -nolibc which seems like a recent addition
to gcc - see https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html
which doesn't skip libgcc
Yup. It's a recent addition though, not available in the compilers I'm
using (alas).
…--
-keith
|
Thanks @denizzzka . Great reminder that what meson (and autoconf) call "host", clang calls it "target". [host_machine]
cpu_family = 'arm'
cpu = 'cortex-m3'
[properties]
c_args = ['-target', 'arm-unknown-none-eabi', '-mcpu=cortex-m3'] Considering how popular clang is, now I feel like I should have mentioned this in my doc update #6301. @jpakkane , @dcbaker , should I? I think this is because compiling a clang /LLVM toolchain relies on a different approach that doesn't require both |
Using |
As described in one of my (too long) comments above, I'm linking with a linker script and a |
I haven't tried clang myself as it doesn't appear to ship on debian with support libraries compiled for every target architecture (I need to support 30 different RISC-V variants). |
A minor annoyance: in
in
What I'd like meson to have is instead of doing |
Errrr? Isn't that what it does already? If you have the binary in your cross file, then You might also consider doing this instead: bin = custom_target(
'bin',
capture: true,
command: [
objcopy, [
'-Obinary',
exe,
exe.full_path() + '.bin',
]
],
output: 'bin'
) If you put a build target in the command line argument array, Meson will automatically expand it and add the necessary dependencies. |
results in:
|
No. Now I need to call |
When using
For example for C programs, I would like to call the preprocessor, compiler, linker, archiver, strip etc. manually but without specifying them as external programs. Correct me, if I'm wrong, but I think, meson must know them anyway (but hides this from the user). Maybe this can be done also a step further specifying a bunch of low level targets, that can be replace the my_source = 'my_prog.cpp`
my_obj = object('objectify_source', my_source)
my_exe = link('my_exe_full', inputs: my_obj, output: 'my_program', type: 'executable')
my_exe_stripped = strip('my_exe_stripped', inputs: my_exe, output: 'my_program_stripped') |
You can compile and link separately: See also example in #6063 |
Only partially, when I get it right. You can compile further from object files and you can extract object files from an already existing linked app. But you are right, these commands go in the direction I thought of. |
I discovered another meson limitation when building components for an embedded toolchain. In that environment, the compiler is often built with 'sysroot' support. This allows specs files to include %R directives that substitute the path to the compiler bits instead of requiring absolute paths everywhere. This capability is used to allow the compiler to be installed in an arbitrary directory by the user, without requiring any reconfiguration or recompilation. What this means for meson is that the --prefix value that should be used while building should be automatically discovered by invoking the compiler with -print-sysroot. However, meson does not allow the prefix value to be set from the build script. Right now, I'm checking to make sure the --prefix value supplied to meson matches the -print-sysroot value emitted by the compiler and failing the configuration process when they don't match, but it would be a lot more convenient to allow setting the prefix value at runtime. |
I just want to say a very good goal is allowing a libc and a regular program (zlib, hello) to both be subprojects. Once Meson can understand that regular projects have an implicit libc dependency which the subproject provides instead of the ambient systems, we will be in very good shape! A lot of these questions of "when can the tests run? does linking work? etc. etc.) are best resolved on a fundamental level by materializing these implicit dependencies (crt0 for anything we can run, semi-normally; dynamic loader / runtime code for dynamic linking; etc.). By understanding these things directly, vs crossing fingers the black-box toolchains are "complete" enough, we gain a lot of power and flexibility! |
Lets have a discussion about what is needed to make meson better support bare metal targets and low level targets such as building a libc. I think it would be nice to have this all in one place so we can better keep track of it.
The text was updated successfully, but these errors were encountered: