9fans/plan9port

Build fails with LTO

eli-schwartz opened this issue · 3 comments

I tried to build with these *FLAGS set: -flto=4 -Werror=odr -Werror=lto-type-mismatch -Werror=strict-aliasing

I got this compiler error:

/var/tmp/portage/dev-util/plan9port-0_pre20230331-r1/work/plan9port-cc4571fec67407652b03d6603ada6580de2194dc/bin/9c: 58: which: not found
9l -o o.acmeevent acmeevent.o $LDFLAGS
/var/tmp/portage/dev-util/plan9port-0_pre20230331-r1/work/plan9port-cc4571fec67407652b03d6603ada6580de2194dc/bin/9c: 58: which: not found
9l -o o.9import 9import.o $LDFLAGS
9l -o o.9p 9p.o $LDFLAGS
/var/tmp/portage/dev-util/plan9port-0_pre20230331-r1/work/plan9port-cc4571fec67407652b03d6603ada6580de2194dc/bin/9c: 58: which: not found
/var/tmp/portage/dev-util/plan9port-0_pre20230331-r1/work/plan9port-cc4571fec67407652b03d6603ada6580de2194dc/bin/9c: 58: which: not found
9l -o o.cat cat.o $LDFLAGS
9l -o o.cleanname cleanname.o $LDFLAGS
../lib9/main.c:5:13: error: type of ‘p9main’ does not match original declaration [-Werror=lto-type-mismatch]
    5 | extern void p9main(int, char**);
      |             ^
acmeevent.c:66:1: note: type mismatch in parameter 1
   66 | main(void)
      | ^
acmeevent.c:66:1: note: type ‘void’ should match type ‘int’
acmeevent.c:66:1: note: ‘p9main’ was previously declared here
lto1: some warnings being treated as errors
lto-wrapper: fatal error: x86_64-pc-linux-gnu-gcc returned 1 exit status
compilation terminated.
/usr/lib/gcc/x86_64-pc-linux-gnu/13/../../../../x86_64-pc-linux-gnu/bin/ld: error: lto-wrapper failed
collect2: error: ld returned 1 exit status
mk: 9l -o o.acmeevent ...  : exit status=exit(1)
mk: for i in ...  : exit status=exit(1)

Downstream report: https://bugs.gentoo.org/858452

Presumably this is due to, -Werror=lto-type-mismatch, but it's unclear how to address it (at least, unclear to me). p9main here must (unfortunately?) emulate the behavior of main in ignoring its arguments if they are not specified; hence the void p9main(void) formulation. Short of doing a major revision to the source code, this is something that we'll have to figure out how to convince the compiler (or, rather, linker) of being explicitly acceptable.

p9main here must (unfortunately?) emulate the behavior of main in ignoring its arguments if they are not specified; hence the void p9main(void) formulation.

Do you mean accepting arguments and then just silently never using their values for any purposes?

Not precisely.

In standard C, main is special in that it can be declared several different ways. Notably, int main(int argc, char *argv[]) and int main(void) are both legal; to my knowledge, no other C function is special-cased in the same way (variadic functions are different). The linker must obviously support this as a special case when warning about type mismatches.

The issue with Plan 9 C is that main was declared to return void (that is, have no return value); instead, main is expected to call exits() with a pointer to some status string (or nil, usually just written as 0). For plan9port, p9main is basically a wrapper function that emulates the difference between main in standard and Plan 9 C. However, plan 9 C continued to support the void main(void) vs void main(int argc, char *argv[]) for the benefit of programs that take or do not take command line arguments. But the special case for "real" main doesn't exist for p9main, hence this error.

One wonders if there's a magic flag that would tell the linker, "ignore type mismatches for this particular function." If so, that's the simplest fix.