riscv-software-src / riscv-tools

RISC-V Tools (ISA Simulator and Tests)
1.13k stars 446 forks source link

Build without optimizations #227

Closed mateoconlechuga closed 5 years ago

mateoconlechuga commented 5 years ago

How can I build (specifically the riscv-gnu-toolchain and related newlib/glibc) with something other than -O2 or -Os? Ideally I would like to use -O0 to verfiy some external application. I've tried export CFLAGS=-O0, but it seems to have no effect on the compiled libraries.

Cirromulus commented 5 years ago

Noticed the same problem (compiling with -g) It seems to ignore that. Quick hack: grep -IR O2 ... and manually replacing it.

mateoconlechuga commented 5 years ago

I shouldn't have to manually replace it :P

Cirromulus commented 5 years ago

you are right :) This also applies to changing the isa, which requires a lot of using the "manual override"

jim-wilson commented 5 years ago

glibc will not work if compiled with -O0. There is some code that relies on optimization for the correct result. I don't know offhand if newlib is safe to compile at -O0.

riscv-tools is a collection of different packages, each with its own makefiles, and some packages like riscv-gcc contain multiple tools with different Makefile designs. Etc. This makes it difficult to add any easy way to specify options at the top level that will affect everything. We don't control all of the packages we are including, so we can't change how they work.

In general though, for GNU tools, such as riscv-binutils, riscv-gcc, etc, setting CFLAGS should work for host tools, and setting CFLAGS_FOR_TARGET should work for target code (i.e. cross compiled libraries). There is also a CFLAGS_FOR_BUILD if doing a canadian-cross build!=host!=target build, but few people will ever need to set that one.

CFLAGS of course is only for C code. So there are also CXXFLAGS, CXXFLAGS_FOR_TARGET, and CXXFLAGS_FOR_BUILD for C++ tools and libraries, and another set that starts with GOCFLAGS for tools and libraries written in Go.

The initial values for CFLAGS, CXXFLAGS, etc come from configure, which will use -g -O2 by default if the compiler is gcc. But it will use a value specified by the user if any. This is typically done by setting CFLAGS etc right before the configure command. E.g. CFLAGS="-g -O1" CXXFLAGS="-g -O1" ../riscv-gcc/configure ... That is usually the easiest way to get the initial CFLAGS etc values set if you want non-standard values for them.

The toplevel riscv-gnu-tools Makefile does not follow GNU rules. It sets CFLAGS, CFLAGS_FOR_TARGET, etc itself, and doesn't allow for user set values. It is probably easier to just manually edit the top level Makefile to fix that if you want different options.

And then riscv-tools is another layer on top of that. I would suggest avoiding riscv-tools as an unnecessary complication and use riscv-gnu-toolchain directly.

mateoconlechuga commented 5 years ago

I have never heard of -O0 not working with glibc... Is there a particular routine you can point me towards? I'd be rather interested. Thanks for the information though! That helps a lot.

jim-wilson commented 5 years ago

I think the main problem is some startup code written in C that tries to set up the initial stack frame for the program. If you compile without optimization, then the compiler tries to use the stack frame before it has been created, which doesn't work.

There may also be trouble with GNU C90 extern inline (aka ISO C99 static inline) functions, which are defined in header files, but no non-inline definition is provided, which can only work when optimized such that all such instances can be inlined.

But it probably has been 20 years or so since I last looked at this, so things could work differently now.