<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Jun 10, 2022 at 10:26 PM Rob Landley <<a href="mailto:rob@landley.net" target="_blank">rob@landley.net</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On 6/10/22 14:47, enh via Toybox wrote:<br>
> i haven't updated in a week or two, but trying to update today, i hit this:<br>
> <br>
> enh-p920.mtv:/new-ssd/aosp-master-with-phones/external/toybox$ ./post_update.sh .<br>
> <br>
> -------- device<br>
> <br>
> warning: using unfinished code from toys/pending<br>
> Library probe<br>
> generated/{Config.in<br>
> Config.probed changed, run 'make oldconfig'<br>
<br>
Sigh. I think I need to lobotomize it again for now... (Pushed a commit to turn<br>
it into a warning.)<br></blockquote><div><br></div><div>thanks!</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Previously the dependencies weren't recalculating a lot of stuff unless you did<br>
a "make distclean" (or "make clean" and "make oldconfig"), but this caused build<br>
breaks when I switched between the host, musl, and NDK toolchains. So I tried to<br>
fix it.<br>
<br>
The problem I got to is, when it updates Config.probed I can easily-ish adjust<br>
the .config file for the changes, but there are a bunch of dependencies on those<br>
symbols that won't get adjusted unless I make a tool that can parse config<br>
syntax and resolve dependencies:<br>
<br>
<a href="https://landley.net/notes-2022.html#28-05-2022" rel="noreferrer" target="_blank">https://landley.net/notes-2022.html#28-05-2022</a><br>
<br>
And THAT is half the "write a kconfig replacement" todo item. (The rest is<br>
writing a menuconfig replacement with all the ansi escapes.) Which is a can of<br>
worms I don't want to open right now.<br>
<br>
But I ALSO don't want anything in scripts/make.sh to call the old kconfig<br>
because the layering is part of the license isolation: .config is consumed<br>
read-only by scripts/make.sh and friends. You can "rm -rf kconfig", and should<br>
still be able to drop a .config file into the top level and call scripts/make.sh<br>
and scripts/install.sh and they should work.<br>
<br>
So my header dependency work stopped at an awkward place where it detects "this<br>
thing should be done" but refuses to do it for you.<br>
<br>
> if i do that though...<br>
> <br>
> rm -rf .config generated/ android/<br>
> <br>
> function generate() {<br>
>   which=$1<br>
>   echo -e "\n-------- $1\n"<br>
> <br>
>   # These are the only generated files we actually need.<br>
>   files="config.h flags.h globals.h help.h newtoys.h tags.h"<br>
> <br>
>   cp .config-$which .config<br>
> <br>
>   make oldconfig # added here<br>
> <br>
>   NOBUILD=1 scripts/make.sh<br>
<br>
You didn't set CROSS_COMPILE there, so it's querying the cc in your $PATH, which<br>
is probably glibc.<br></blockquote><div><br></div><div>yeah, since none of that stuff is likely to work for me anyway i've always just assumed those things need to be manually configured. (see later for a specific example...)</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
>   out=android/$which/generated/<br>
>   mkdir -p $out<br>
>   for f in $files; do cp generated/$f $out/$f ; done<br>
>   rm -rf .config generated/<br>
> <br>
>   make allnoconfig KCONFIG_ALLCONFIG=.config-$which<br>
<br>
Didn't set CROSS_COMPILE there either.<br>
<br>
The Config.probed symbols aren't selectable (the "bool" hasn't got a string<br>
after it so doesn't show up in menuconfig), which means they take their default<br>
value even in allyesconfig/allnoconfig unless acted upon by a dependency or a<br>
"selects" statement. (Allyesconfig and allnoconfig just affect the selectable<br>
symbols.)<br>
<br>
> }<br>
> <br>
> generate "device"<br>
> generate "linux"<br>
> generate "mac"<br>
> <br>
> ...i end up with incorrect configs. for example, despite<br>
> <br>
> enh-p920.mtv:/new-ssd/aosp-master-with-phones/external/toybox$ grep -r SHADOW<br>
> .config-*<br>
> .config-device:# CONFIG_TOYBOX_SHADOW is not set<br>
> .config-linux:# CONFIG_TOYBOX_SHADOW is not set<br>
> .config-mac:# CONFIG_TOYBOX_SHADOW is not set<br>
> <br>
> i end up with the wrong definition in my generated config.h files:<br>
> <br>
> android/device/generated/config.h:#define CFG_TOYBOX_SHADOW 1<br>
> android/device/generated/config.h:#define USE_TOYBOX_SHADOW(...) __VA_ARGS__<br>
> android/mac/generated/config.h:#define CFG_TOYBOX_SHADOW 1<br>
> android/mac/generated/config.h:#define USE_TOYBOX_SHADOW(...) __VA_ARGS__<br>
> android/linux/generated/config.h:#define CFG_TOYBOX_SHADOW 1<br>
> android/linux/generated/config.h:#define USE_TOYBOX_SHADOW(...) __VA_ARGS__<br>
<br>
Sigh, this is another reason I use miniconfigs. These symbols would drop out in<br>
a miniconfig because they're constant within a toolchain. :P<br></blockquote><div><br></div><div>is this also why i need the "is not set" comment lines? i've never understood why i can't just miss out the irrelevant stuff...</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
(SO much backstory...)<br>
<br>
> on the other hand, if i disable the new check in scripts/make.sh<br>
> <br>
> #[ "$A" != "$B" ] &&<br>
> #  { echo -e "\nConfig.probed changed, run 'make oldconfig'" >&2; exit 1;}<br>
> <br>
> everything works again... what am i missing?<br>
<br>
Just because the dependencies say .config should have its dependencies<br>
recalculated (because the generated/Config.probed it includes changed) doesn't<br>
mean NOT doing it will necessarily cause a build break. If stuff that "depends<br>
on" a symbol that went away already wasn't selected, you're probably fine.<br>
That's "working by coincidence", but it's probably also your use case with a<br>
known .config that already works in your bionic toolchain. You've manually<br>
selected options that work on your toolchain, and are not running something like<br>
defconfig to figure out what's supported and enable it. Also, your toolchain is<br>
stable so features aren't appearing and disappearing like they do when you swap<br>
toolchains out from under an existing .config, which is what I do in testing a<br>
lot. (You have 3 potted configs already.)<br>
<br>
The Config.probed symbols mostly control what _can_ be selected, hiding<br>
commands/options that aren't available in this build environment.<br>
<br>
But only mostly: TOYBOX_SHADOW specifically controls whether #include <shadow.h><br>
happens in portability.h, that's a build break in _either_ direction if you get<br>
it wrong.<br>
<br>
That said, gcc 5 introduced __has_include so in theory I could use that if clang<br>
also supports it these days. (gcc 5.1 was April 2015, 7 year time horizon...)<br></blockquote><div><br></div><div>yes, clang's supported __has_include() for as long as we've been using clang. (annoyingly, their documentation really sucks -- far worse than gcc -- so i couldn't find a reference to what version it was introduced in.)</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Any compile time probes I can turn into build-time probes, I'm all for it.<br></blockquote><div><br></div><div>certainly __has_include(), yes, though see later for why syscalls are hairy...</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Figuring out how that impacts the dependency resolution is a design issue<br>
though. What's the right thing to do when this command depends on a feature<br>
that's not available in this build environment? Before menuconfig hid them, but<br>
now it wouldn't test it until compile time. I can probably figure out how to<br>
make commands drop out of the list (define HAS_BLAH() macros inside the<br>
__has_include stanzas maybe) and get --gc-sections to dead-code-eliminate<br>
them... but is that the right thing to do? Avoids a build break, at the cost of<br>
"I built this command and it's not in the resulting toybox binary". Is a build<br>
break better? A #warning output?<br></blockquote><div><br></div><div>(+1 to build break. your practice of "you don't have this constant from the future? here you go then..." [and then a possible runtime failure because you really are on too old a kernel] is also fine. but see later for my problem...)</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
It's always the aesthetic issues that are particularly terrible, because they<br>
don't have a definitive correct answer.<br>
<br>
> (i also don't understand why `make oldconfig` hassled me about<br>
> TOYBOX_FORCE_NOMMU until i added it to the .config files --- it doesn't look<br>
> like that actually does anything in practice?)<br>
<br>
scripts/genconfig.sh:<br>
<br>
  # nommu support<br>
  probesymbol TOYBOX_FORK << EOF<br>
    #include <unistd.h><br>
    int main(int argc, char *argv[]) { return fork(); }<br>
EOF<br>
  echo -e '\tdepends on !TOYBOX_FORCE_NOMMU'<br>
<br>
I.E. in generated/Config.probed:<br>
<br>
config TOYBOX_FORK<br>
        bool<br>
        default y<br>
<br>
        depends on !TOYBOX_FORCE_NOMMU<br>
<br>
It disables TOYBOX_FORK even if the compile-time probe succeeded.<br>
<br>
(You can't fork() on nommu because there's no address translation, so if you<br>
make a copy all the pointers in your new copy of the memory would point into the<br>
old process's memory. Adjusting them is an AI-complete problem, equivalent to<br>
doing reliable garbage collection in C. You _must_ vfork() and then exec a new<br>
process setting up new memory segments and populating them with your own<br>
pointers. In uclibc fork() wasn't there on nommu targets, but musl provides a<br>
broken fork() that always returns -ENOSYS, </blockquote><div><br></div><div>this doesn't apply to fork(), but the trouble with ENOSYS on Android is that you have to ask yourself "was there a hole punched in the seccomp() filter for this syscall?". this is my concern with copy_file_range(), for example. although that's in really old kernels at this point, you can't call it on Android without getting SIGSYS courtesy of seccomp until <checks notes> next year in Android U. which is "fine" in a sense --- AOSP is "U" at this point, so this version of toybox is being built with a version of the OS that has a seccomp filter that will allow you to probe for copy_file_range(). but it's "bad" in that it means that you can't run even a static toybox binary from U on pre-U (at least not for a codepath that actually uses copy_file_range()).</div><div><br></div><div>my initial plan (and the reason i don't think i even mentioned this when the recent copy_file_range() changes went in) was to just keep it disabled for the next 7 years... but that's trickier if it's `#ifdef __NR_foo`ed like copy_file_range() now is, rather than a regular "config" item. obviously we can just add ` && !defined(__ANDROID__)` and a comment explaining why, but i'm tempted to wait until someone actually notices and complains? i'm _trying_ to persuade people to use a static toybox for hermetic testing on old android releases, but i'm not sure i've actually succeeded yet... ugh, no, i don't want to leave a known roadblock for those folks (_especially_ because i keep telling people to drive down that road!), so i'll send you a patch.</div><div><br></div><div>(before you complain, no, i wasn't a huge fan of the whole seccomp thing either, but if nothing else it's prevented kernels from shipping with "random" syscalls occupying the next few syscall numbers. which was a thing that happened: given a sufficiently large ecosystem, for anything you can imagine, someone's done it.)</div><div><br></div><div>anyway, looking at the full list:</div><div><br></div><div>* TOYBOX_CONTAINER seems years out of date, at least as a "does this compile?" probe? everyone should have setns()/unshare() by now?</div><div><br></div><div>* TOYBOX_FIFREEZE seems years out of date? everyone should have that constant by now, and your usual way of doing that today would be to manually #define it anyway.</div><div><br></div><div>* TOYBOX_UTMPX can be __has_include(<utmpx.h>)?</div><div><br></div><div>* TOYBOX_SHADOW can be __has_include(<shadow.h>)?</div><div><br></div><div>* TOYBOX_ANDROID_SCHEDPOLICY isn't used?</div><div><br></div><div>* TOYBOX_PRLIMIT is uclibc only? does uclibc have a __UCLIBC__ or something?</div><div><br></div><div>* TOYBOX_GETRANDOM can be __has_include(<sys/random.h>)?</div><div><br></div><div>* TOYBOX_HASTIMERS is actually a workaround for a gcc issue, and should probably test the gcc version macros instead?</div><div><br></div><div>i won't send a patch/patches in case you're already doing stuff in there, but let me know if you'd like any/all of those...</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">which makes it hard to detect "I'm<br>
running on nommu and need to do nommu things" at compile time. As with refusing<br>
to have an #ifdef __MUSL__ this is basically a religious conviction on Rich's<br>
part and we've all given up trying to convince him he's wrong after YEARS of<br>
trying. I run "sed" against the musl source in the toolchains I build to fix it,<br>
but if you're using somebody else's musl toolchain on a nommu system you need an<br>
manual indicator....)<br>
<br>
Rob<br>
</blockquote></div></div>