Using Clang to compile for RISC-V - compilation

I am trying to build a hello world program using Clang (version 12.0.1) for RISC-V architecture. I have installed it with LLVM (version 12.0.1) with the following setup:
cmake -G "Unix Makefiles" \
-DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;libcxx;libcxxabi;libunwind;lldb;compiler-rt;lld;polly;debuginfo-tests" \
-DCMAKE_BUILD_TYPE=Debug \
-DLLVM_ENABLE_ASSERTIONS=On \
../llvm
According to here, default LLVM_TARGETS_TO_BUILD is LLVM_ALL_TARGETS, which includes RISC-V.
So I try to compile it with clang --target=riscv64 -march=rv64gc hello_world.c -o hello_world and I am getting the error:
hello_world.c:1:10: fatal error: 'stdio.h' file not found
#include <stdio.h>
^~~~~~~~~
1 error generated.
At the same time, /opt/risv/, where I have installed the riscv-gnu-toolchain, is in my path, and I can run riscv64-unknown-linux-gnu-gcc hello_world.c -o hello_world without issues.
I am trying on an Ubuntu machine with kernel 5.8.0-63-generic.
Any idea how can I solve this issue and be able to compile RISC-V programs through Clang?

Foreknowledge:
I had same delusion about this: "If llvm is targeting for all backends including riscv, we should be able to compile our codes just giving a clang flag like --target=riscv32, -target riscv64 etc. without doing extra operation" and I had similar question, but it is not like that. Although LLVM supports riscv target, you need to specify sysroot and gcc toolchain for using riscv headers and libraries, in the other words you need cross compilation. (because you are currently operating a system like x86-64 different from riscv and your default libraries are different) That's why you need to link your riscv-gnu-toolchain paths. Here I assume that you built your riscv-gnu-toolchain from github clone.
Note: Some people have problems with first option (1) and please try to use other options (2) (3) (4) firstly. (Look into comments.)
Solution:
1-) You can add these lines as your cmake configuration flags before building your llvm library:
For 32 bit riscv:
-DDEFAULT_SYSROOT="{your-riscv-gnu-toolchain-install-or-build-path}/riscv32-unknown-elf"
-DGCC_INSTALL_PREFIX="{your-riscv-gnu-toolchain-install-or-build-path}"
For 64 bit riscv:
-DDEFAULT_SYSROOT="{your-riscv-gnu-toolchain-install-or-build-path}/riscv64-unknown-elf"
-DGCC_INSTALL_PREFIX="{your-riscv-gnu-toolchain-install-or-build-path}"
and then build llvm library again. Probably as you know, in your llvm build directory:
cmake --build .
Here is an example in my case according to your cmake configuration for clearance:
cmake -G "Unix Makefiles" \
-DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;libcxx;libcxxabi;libunwind;lldb;compiler-rt;lld;polly;debuginfo-tests" \
-DCMAKE_BUILD_TYPE=Debug \
-DLLVM_ENABLE_ASSERTIONS=On \
-DDEFAULT_SYSROOT="/home/shc/riscv/install/riscv64-unknown-elf" \
-DGCC_INSTALL_PREFIX="/home/shc/riscv/install" \
../llvm
cmake --build .
Also you can set default target triple as riscv with another cmake configuration flag:
For 32 bit riscv:
-DLLVM_DEFAULT_TARGET_TRIPLE="riscv32-unknown-elf"
For 64 bit riscv:
-DLLVM_DEFAULT_TARGET_TRIPLE="riscv64-unknown-elf"
After this you should be able to compile your codes like these examples:
For C:
/home/shc/llvm/llvm-project/build/bin/clang -march=rv64gc hello_world.c -o hello_world
For C++:
/home/shc/llvm/llvm-project/build/bin/clang++ -march=rv64gc hello_world.cpp -o hello_world
If you didn't set default target triple with cmake flag, target option should remain:
For C:
/home/shc/llvm/llvm-project/build/bin/clang --target=riscv64 -march=rv64gc hello_world.c -o hello_world
For C++:
/home/shc/llvm/llvm-project/build/bin/clang++ --target=riscv64 -march=rv64gc hello_world.cpp -o hello_world
2-) You can pass sysroot and gcc toolchain as flags(as in cmake configurations above) while compiling your code without building your library again. However, if you will use this, you need to give these flags in every compilation:
For 32 bit riscv:
--sysroot="{your-riscv-gnu-toolchain-install-or-build-path}/riscv32-unknown-elf"
--gcc-toolchain="{your-riscv-gnu-toolchain-install-or-build-path}"
For 64 bit riscv:
--sysroot="{your-riscv-gnu-toolchain-install-or-build-path}/riscv64-unknown-elf"
--gcc-toolchain="{your-riscv-gnu-toolchain-install-or-build-path}"
Usage of Flags For C:
/home/shc/llvm/llvm-project/build/bin/clang --sysroot=/home/shc/riscv/install/riscv64-unknown-elf --gcc-toolchain=/home/shc/riscv/install --target=riscv64 -march=rv64gc hello_world.c -o hello_world
Usage of Flags For C++:
/home/shc/llvm/llvm-project/build/bin/clang++ --sysroot=/home/shc/riscv/install/riscv64-unknown-elf --gcc-toolchain=/home/shc/riscv/install --target=riscv64 -march=rv64gc hello_world.cpp -o hello_world
3-) You can try to pass these flags while compiling (instead of your --target=riscv64 flag) although it is not more healthy than above options. (Attention: difference is only linux keyword, normally it was -target riscv32-unknown-elf):
For 32 bit riscv:
-target riscv32-unknown-linux-elf
For 64 bit riscv:
-target riscv64-unknown-linux-elf
4-) You can use riscv-llvm repo by following given instructions, although it is outdated.
Note: I adapted my file locations to your examples to better understanding.
Further information you can look here: https://github.com/lowRISC/riscv-llvm#how-can-i-build-upstream-llvmclang-and-use-it-to-cross-compile-for-a-riscv32-target

Finally i deal with that! i`m used next keys:
cmake -G "Unix Makefiles" \
-DCMAKE_BUILD_TYPE="Release" \
-DBUILD_SHARED_LIBS=True \
-DCMAKE_INSTALL_PREFIX="/home/username/llvm-install" \
-DLLVM_OPTIMIZED_TABLEGEN=ON -DLLVM_BUILD_TESTS=False \
-DDEFAULT_SYSROOT="/home/username/esp-toolchain-install/riscv64-unknown-elf" \
-DGCC_INSTALL_PREFIX="/home/username/esp-toolchain-install" \
-DLLVM_ENABLE_PROJECTS="clang;lld" \
-DLLVM_DEFAULT_TARGET_TRIPLE="riscv64-unknown-elf" \
-DLLVM_TARGETS_TO_BUILD="RISCV" ../llvm
and i copied content of esp-toolchain-install/* into llvm-install/*. And clang finally saw all of GCC files:
clang -v -print-search-dirs
clang version 12.0.1 (https://github.com/llvm/llvm-project.git fed41342a82f5a3a9201819a82bf7a48313e296b)
Target: riscv64-unknown-unknown-elf
Thread model: posix
InstalledDir: /home/username/llvm-install/bin
Found candidate GCC installation: /home/username/llvm-install/bin/../lib/gcc/riscv64-unknown-elf/9.2.0
Selected GCC installation: /home/username/llvm-install/bin/../lib/gcc/riscv64-unknown-elf/9.2.0
Candidate multilib: rv32i/ilp32;#march=rv32i#mabi=ilp32
Candidate multilib: rv32im/ilp32;#march=rv32im#mabi=ilp32
Candidate multilib: rv32iac/ilp32;#march=rv32iac#mabi=ilp32
Candidate multilib: rv32imac/ilp32;#march=rv32imac#mabi=ilp32
Candidate multilib: rv32imafc/ilp32f;#march=rv32imafc#mabi=ilp32f
Candidate multilib: rv64imac/lp64;#march=rv64imac#mabi=lp64
Candidate multilib: rv64imafdc/lp64d;#march=rv64imafdc#mabi=lp64d
Selected multilib: rv64imac/lp64;#march=rv64imac#mabi=lp64
programs: =/home/username/llvm-install/bin:/home/username/llvm-install/bin/../lib/gcc/riscv64-unknown-elf/9.2.0/../../../../riscv64-unknown-elf/bin:/home/username/llvm-install/bin/../lib/gcc/riscv64-unknown-elf/9.2.0/../../../../bin
libraries: =/home/username/llvm-install/lib/clang/12.0.1:/home/username/llvm-install/bin/../lib/gcc/riscv64-unknown-elf/9.2.0/rv64imac/lp64:/home/username/llvm-install/bin/../lib/gcc/riscv64-unknown-elf/9.2.0/../../../../riscv64-unknown-elf/lib/rv64imac/lp64:/home/username/llvm-install/bin/../lib/gcc/riscv64-unknown-elf/9.2.0:/home/username/esp-toolchain-install/riscv64-unknown-elf/lib

Related

How can I compile with LLVM/Clang to RISC-V target?

I want to compile a simple program "int main(){return 0;}" to RISC-V processor.
LLVM/Clang version is 9.0 and I want to run the compiled program with a RISC-V simulator like this https://github.com/riscv/riscv-tools
My problem is that I can't list the clang supported targets only the LLC-s whith these commands:
llc --version
llc -march=xxARCHTYPExx -mattr=help
And there is no any type of riscv processor listed.
So I tried to look the triple file: llvm-project\llvm\include\llvm\ADT\Triple.h
and try a command like: clang hello.c -target riscv32 -march=rv32imafd
But I get the following error:
error: unable to create target: 'No available targets are compatible
with triple "riscv32"'
Can somebody help me to how get a valid RISC-V target? I just simple can't compile the program but I know LLVM has a RISC-V support.
LLVM 9 release notes explicitly state that RISC-V support was promoted from experimental to official.
And indeed, on my Fedora 31 machine, the LLVM 9 Fedora package does support RISC-V:
$ llvm-objdump --version | grep riscv
riscv32 - 32-bit RISC-V
riscv64 - 64-bit RISC-V
Also, I can create RISC-V binary code with the LLVM toolchain:
$ clang --target=riscv64 -march=rv64gc rotate.s -c -o rotate.o
$ file rotate.o
rotate.o: ELF 64-bit LSB relocatable, UCB RISC-V, version 1 (SYSV), not stripped
Although it doesn't include a libc for RISC-V targets:
$ clang --target=riscv64 -march=rv64gc hello-world.c -o hello-world
hello-world.c:1:10: fatal error: 'stdio.h' file not found
#include <stdio.h>
^~~~~~~~~
1 error generated.
However, you don't really need one - you could directly call syscalls for your hello world, e.g.:
$ clang --target=riscv64 -march=rv64gc hello.s -c -o hello.o
$ ld.lld hello.o -o hello
$ spike --isa=RV64gc ~/local/riscv/pk/riscv64-unknown-elf/bin/pk ./hello
bbl loader
Hello World
I don't use clang for linking because it seems that I can't convince clang with -fuse-ld to use another linker besides /usr/bin/ld.

How do I tell gcc to use a specific instantiation of glibc?

For "reasons", I need to build an x86 toolchain that emits no SIMD instructions (trying to use -march isn't enough because glibc will include functions that are built to use SIMD instructions, etc.).
I have built my own gcc 5.3 using the following configure flags:
../src/gcc/configure --prefix=/scratch/install --enable-languages=c,c++ \
--with-cpu=ivybridge \
--with-arch=ivybridge \
CFLAGS="-march=ivybridge" \
CXXFLAGS="-march=ivybridge"
I then built my own glibc using the following configure flags:
../src/glibc/configure --prefix=/scratch/install --with-arch=ivybridge \
CC="/scratch/install/bin/gcc" \
CXX="/scratch/install/bin/g++" \
CFLAGS="-O2 -march=ivybridge" \
CXXFLAGS="-O2 -march=ivybridge -Wa,-march=corei7+nommx+nosse+noavx"`
I verified that my gcc is NOT using my glibc.
$ /scratch/install/bin/gcc -print-file-name=libc.so
/usr/lib/x86_64-linux-gnu/libc.so
Question:
How do I link in my newly compiled glibc? I'm only interested in compiling -static binaries, if that helps.
I verified that my gcc is NOT using my glibc.
Why would it?
You need to rebuild gcc again, adding --with-sysroot=/scratch/install (and possibly other flags).
In general, building correct linux-to-linux cross-compilers is quite tricky, and you may find that using crosstool-ng will save you quite a bit of trial and error.

Caffe compilation fails due to unsupported gcc compiler version

I struggle with Caffe compilation. Unfortunately I failed to compile it.
Steps I followed:
git clone https://github.com/BVLC/caffe.git
cd caffe
mkdir build
cd build
cmake ..
make all
Running make all fails with the following error message:
[ 2%] Building NVCC (Device) object src/caffe/CMakeFiles/cuda_compile.dir/util/cuda_compile_generated_im2col.cu.o
In file included from /usr/include/cuda_runtime.h:59:0,
from <command-line>:0:
/usr/include/host_config.h:82:2: error: #error -- unsupported GNU version! gcc 4.9 and up are not supported!
#error -- unsupported GNU version! gcc 4.9 and up are not supported!
^
CMake Error at cuda_compile_generated_im2col.cu.o.cmake:207 (message):
Error generating /mydir/caffe/build/src/caffe/CMakeFiles/cuda_compile.dir/util/./cuda_compile_generated_im2col.cu.o
Software version:
OS: Debian.
gcc version: 5.3.1.
nvcc version: 6.5.12.
cat /proc/driver/nvidia/version result:
NVRM version: NVIDIA UNIX x86_64 Kernel Module 352.63 Sat Nov 7 21:25:42 PST 2015
GCC version: gcc version 4.8.5 (Debian 4.8.5-3)
Attempts to solve the problem
1st try
Simple solutions are often best ones, so (as suggested here) I tried to comment out macro checking gcc version from /usr/include/host_config.h (line 82). Unfortunately it doesn't work and compilation fails badly:
1 catastrophic error detected in the compilation of "/tmp/tmpxft_000069c2_00000000-4_im2col.cpp4.ii".
2nd try
I tried to run:
cmake -D CMAKE_CXX_COMPILER=g++-4.8 ..
make
but it fails with exactly the same error message (even though g++-4.8 should be accepted).
3rd try
I've found similar problem (though not related to Caffe) and I tried to solve it as suggested in the accepted answer.
What I did:
I've ran grep -iR "find_package(CUDA" caffe command and found Cuda.cmake file which has find_package(CUDA 5.5 QUIET) in line 225.
I added set(CUDA_HOST_COMPILER /usr/bin/gcc-4.8) to Cuda.cmake, line before line: find_package(CUDA 5.5 QUIET).
I removed everything from build directory and ran cmake and make again - with and without -D CMAKE_CXX_COMPILER=g++-4.8.
Unfortunately result is exactly the same. Caffe probably overwrites it somehow - I didn't figure it out how.
make VERBOSE=1 2>&1 | grep -i compiler-bindir returns nothing.
What's interesting, make VERBOSE=1 prints command that fails, which is:
/usr/bin/nvcc -M -D__CUDACC__ /mydir/caffe/src/caffe/util/im2col.cu -o /mydir/caffe/build/src/caffe/CMakeFiles/cuda_compile.dir/util/cuda_compile_generated_im2col.cu.o.NVCC-depend -ccbin /usr/bin/cc -m64 -DUSE_LMDB -DUSE_LEVELDB -DUSE_OPENCV -DWITH_PYTHON_LAYER -DGTEST_USE_OWN_TR1_TUPLE -Xcompiler ,\"-fPIC\",\"-Wall\",\"-Wno-sign-compare\",\"-Wno-uninitialized\",\"-O3\",\"-DNDEBUG\" -gencode arch=compute_20,code=sm_21 -Xcudafe --diag_suppress=cc_clobber_ignored -Xcudafe --diag_suppress=integer_sign_change -Xcudafe --diag_suppress=useless_using_declaration -Xcudafe --diag_suppress=set_but_not_used -Xcompiler -fPIC -DNVCC -I/usr/include -I/mydir/caffe/src -I/usr/include -I/mydir/caffe/build/include -I/usr/include/hdf5/serial -I/usr/include/opencv -I/usr/include/atlas -I/usr/include/python2.7 -I/usr/lib/python2.7/dist-packages/numpy/core/include -I/mydir/caffe/include -I/mydir/caffe/build
when I add --compiler-bindir /usr/bin/gcc-4.8 flag manually, it prints error:
nvcc fatal : redefinition of argument 'compiler-bindir'
which may be related to this bug report.
Edit: I didn't notice that --compiler-bindir and -ccbin are the same options, and the latter is already set in above command that failed. When I changed -ccbin /usr/bin/cc to -ccbin /usr/bin/gcc-4.8 in above command that failed, it completes successfully. Now I need to find option in Caffe's CMake file that overwrite -ccbin in all subsequent Caffe's CMakes. Looking at cmake/Cuda.cmake:252:list(APPEND CUDA_NVCC_FLAGS ${NVCC_FLAGS_EXTRA} seems to be good way to go.
How can I successfully complete my compilation? Any help is appreciated.
Related SO questions:
host_config.h:unsupported GNU version! gcc versions later than 4.9 are not supported.
CUDA 6.5 complains about not supporting gcc 4.9 - what to do?.
cmake -D CUDA_NVCC_FLAGS="-ccbin gcc-4.8" .. && make causes successful compilation.
Now another problem showed up: linking Google's libgflags or libprotobuf fails probably due to fact that it was compiled with newer gcc version but it's not related to asked question.
My machine runs Ubuntu 15.10, and my default compiler version is gcc 5.2.1 .
Commenting out the #error directive in line 115 of file
/usr/local/cuda-7.5/include/host_config.h
(or whatever the path on your system is) did the trick for me. Caffe compiled fine, all tests ran smoothly.
On the other hand, if one chooses to ignore this and proceed to compile part of the project with one compiler version, part of the project with another (for me it was gcc-4.8 and gcc-5.2.1), linking problems will arise. The linking problems of protobuf and libgflags another answer mentions are not unrelated to this.

Compiling library in g++ using C++11

I'm been attempting to compile an open-source C++ library (QuantLib-1.7) on my mac for several days but I seem to be encountering some kind of C++11 compatibility issue.
When I run make && sudo make install from the terminal the compilation seems to work except for a bunch of errors of the form
Making all in BermudanSwaption
g++ -DHAVE_CONFIG_H -I. -I../../ql -I../.. -I../.. -I/opt/local/include -g -O2 -MT BermudanSwaption.o -MD -MP -MF .deps/BermudanSwaption.Tpo -c -o BermudanSwaption.o BermudanSwaption.cpp
In file included from BermudanSwaption.cpp:22:
In file included from ../../ql/quantlib.hpp:43:
In file included from ../../ql/experimental/all.hpp:25:
In file included from ../../ql/experimental/volatility/all.hpp:21:
In file included from ../../ql/experimental/volatility/zabr.hpp:31:
In file included from ../../ql/math/statistics/incrementalstatistics.hpp:35:
In file included from /opt/local/include/boost/accumulators/statistics/stats.hpp:14:
In file included from /opt/local/include/boost/accumulators/statistics_fwd.hpp:12:
/opt/local/include/boost/mpl/print.hpp:50:19: warning: in-class initialization
of non-static data member is a C++11 extension [-Wc++11-extensions]
const int m_x = 1 / (sizeof(T) - sizeof(T));
^
1 warning generated.
I'm guessing this has something to do with g++ not being correctly configured for C++11. I'm familiar with the fact that C++11 can be invoked by compiling with g++ -std=c++11. However, despite a lot of googling I can't find a way to modify the makefile such that -std=c++11 is called when I run make && sudo make install.
Any help would be greatly appreciated.
Here is the section of the makefile which I believe is relevant:
BOOST_INCLUDE = -I/opt/local/include
BOOST_LIB = -L/opt/local/lib
BOOST_THREAD_LIB =
BOOST_UNIT_TEST_DEFINE = -DQL_WORKING_BOOST_STREAMS
BOOST_UNIT_TEST_LIB = boost_unit_test_framework-mt
BOOST_UNIT_TEST_MAIN_CXXFLAGS = -DBOOST_TEST_DYN_LINK
CC = gcc
CCDEPMODE = depmode=gcc3
CFLAGS = -g -O2
CPP = gcc -E
CPPFLAGS = -I/opt/local/include
CXX = g++
CXXCPP = g++ -E
CXXDEPMODE = depmode=gcc3
CXXFLAGS = -g -O2
Here is the output from running "g++ -v":
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.0.0 (clang-700.1.76)
Target: x86_64-apple-darwin14.5.0
Thread model: posix
Makefile.am: https://www.dropbox.com/s/v5j7qohwfup81od/Makefile.am?dl=0
Makefile.in: https://www.dropbox.com/s/t92hft9ea2ar1zw/Makefile.in?dl=0
QuantLib-1.7 directory: https://www.dropbox.com/sh/ulj0y68m8x35zg8/AAA-w7L2_YWIP8_KnwURErzYa?dl=0
Full error log: https://www.dropbox.com/s/g09lcnma8skipv7/errors.txt?dl=0
Add something like
CXXFLAGS += -std=c++11
to your Makefile. This will work regardless of the Darwin-specific munging of the g++ executable---it's really clang++.
References:
https://gcc.gnu.org/onlinedocs/gcc-5.2.0/gcc/C_002b_002b-Dialect-Options.html#C_002b_002b-Dialect-Options
https://gcc.gnu.org/projects/cxx0x.html
http://clang.llvm.org/cxx_status.html
https://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html
As you already have, and are familiar with homebrew, my suggestion would be to use that to install and manage quantlib like this:
brew install quantlib
That will then build and put all the files in /usr/local/Cellar/quantlib under some version number that is not of importance. The important thing is the the tools are then linked into /usr/local/bin so all you need to do is make sure that /usr/local/bin is in your PATH.
That gives you access to the tool quantlib-config which is always linked to the latest version and it knows which version that is. So, if you run:
quantlib-config --cflags
it will tell you what the correct path is for your includes like this:
-I/usr/local/Cellar/quantlib/1.6.1/include
Likewise, if you run:
quantlib-config --libs
it will tell you the correct linking directories and libraries for your latest version.
In short, all you need to do to compile is:
g++ $(quantlib-config --cflags --libs)
and it will always pull in the version you are using.
Note that if you use a Makefile, you will need to double the dollar signs.
This is how I eventually managed to compile the Quantlib library for future reference. It is probably not the most efficient/elegant method but it appears to work.
I followed the steps given in http://quantlib.org/install/macosx.shtml and found that running make && sudo make install led to the error reported in the OP.
Create a new static library C++ project in Eclipse called 'Quantlib'
Copy the ql directory located in the .tar file to the Quantlib Eclipse workspace
Right-click Quantlib > Properties > C/C++ Build > Settings > Cross G++ Compiler: Change the Language standard to ISO C++ 11 (-std=c++0x)
Right-click Quantlib > C/C++ General > Paths and Symbols: Add the following include directories for GNU C++
opt/local/include
/Quantlib (check "Is a workspace directory")
/opt/local/include/boost.
Build the Quantlib project (around 34 min on MacBook Air 1.8 GHz Intel Core i7)
Create a new C++ executable project (e.g. BermudanSwaption) and copy the BermudanSwaption.cpp into the BermudanSwaption Eclipse workspace
Repeat steps 4. and 5. for the BermudanSwaption Eclipse project
Right-click BermudanSwaption > Properties > C/C++ General > Paths and Symbols > References: check Quantlib (the Library Paths tab should now contain the entry '/Quantlib/Debug')
Build and run the BermudanSwaption executable project
QuantLib-1.7
OSX Yosemite 10.10.5
Eclipse C/C++ Development Tools Version: 8.8.0.201509131935
Xcode Version 7.1 (7B91b)
xcode-select version 2339.

Compiling gcc with AVR options

I want to generate the assembly file of my code oriented to the AVR architecture, I am using gcc version 4.7.2 with the following arguments:
g++ -O3 -Wall -S -Wp,-mmcu=atmega8 -o "src\Compression.o" "..\src\Compression.cpp"
but I am getting the following error:
cc1plus.exe: error: unrecognized command line option '-mmcu=atmega8'
But I got the command options from the gcc website:
http://gcc.gnu.org/onlinedocs/gcc-4.7.3/gcc/AVR-Options.html#AVR-Options
There should be something that I am missing, could you help me with this please!
If gcc does not accept -mmcu, you are probably not using a gcc with support for the AVR architecture.
It's normally used like this:
avr-gcc -mmcu=atmega328p
because it's not only the preprocessor, it's actually other tools as well which require this setting (linker, assembler).
Normally the architecture gcc is compiled for is indicated by a prefix, in this case it's avr- by convention.
So the solution is to get a toolchain with AVR support. You can download it from Atmel's web site, even for Linux.
Update
If you like to check the configuration of your gcc, you can use -dumpmachine to check for the target processor
$ gcc -dumpmachine
i486-linux-gnu
$ arm-none-eabi-gcc -dumpmachine
arm-none-eabi
$ avr-gcc -dumpmachine
avr
If you look at the target specific options using --target-help
$ gcc --target-help | grep march
-march= Generate code for given CPU
you can see that the Linux gcc does accept -march as well. It probably fails later.
gcc is a very complex piece of software, because it just supports so many different architectures. From that perspective it works amazingly well.
Another interesting option is -v
$ gcc -v
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 4.4.5-8'
[...]
to see how that gcc has been built.
And there could be another trap down the road (multi-libs), as you can see here

Resources