Linking against archictecture-specific libs using arm-none-eabi-gcc

Asked by jpc on 2016-03-09

I have installed arm-none-eabi-gcc using apt-get and am now building a simple project targeting the NXP TWR-K70. When I link my application, I have to provide the -L option with the path to the architecture-specific libraries provided with the toolchain, otherwise the linker will complain about a CPU architecture mismatch. Command:

arm-none-eabi-gcc -o targets/twr-k70f120m/none/check-core -march=armv7-m -T targets/twr-k70f120m/k70f120m.ld -mfpu=vfpv4 --specs=rdimon.specs tests/core/runner.o tests/core/tests.o targets/twr-k70f120m/none/main.o targets/twr-k70f120m/sys_init.o -L/usr/lib/arm-none-eabi/lib/armv7-m -LRTOS -Lunity -lc -lm -lgcc -lrdimon -lcommon -lcpu -lio -lbsp-twr-k70f120m -lunity

Is this the "canonical" way to do this? Is there a more portable way to do this that doesn't involve hard-coding the library path?

-Jim

Question information

Language:
English Edit question
Status:
Solved
For:
GNU Arm Embedded Toolchain Edit question
Assignee:
No assignee Edit question
Solved by:
jpc
Solved:
2016-03-09
Last query:
2016-03-09
Last reply:
2016-03-09

Hi jpc,

No it's not the canonical way. It should work without that -L. Can you show me the error output without it and adding -Wl,--trace to the command line?

Best regards.

jpc (jimcarroll21) said : #2

Thanks, Thomas.

Here's the command output with the --trace flag.

arm-none-eabi-gcc -o targets/twr-k70f120m/none/check-bus -march=armv7-m -T targets/twr-k70f120m/k70f120m.ld -mfpu=vfpv4 --specs=rdimon.specs -Wl,--trace tests/bus/runner.o tests/bus/tests.o targets/twr-k70f120m/none/main.o targets/twr-k70f120m/sys_init.o -LRTOS -Lunity -lc -lm -lgcc -lrdimon -lcommon -lcpu -lio -lbsp-twr-k70f120m -lunity
/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/bin/ld: mode armelf
/usr/lib/gcc/arm-none-eabi/4.9.3/crti.o
/usr/lib/gcc/arm-none-eabi/4.9.3/crtbegin.o
/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/rdimon-crt0.o
tests/bus/runner.o
tests/bus/tests.o
targets/twr-k70f120m/none/main.o
targets/twr-k70f120m/sys_init.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a)lib_a-atexit.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a)lib_a-exit.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a)lib_a-fini.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a)lib_a-impure.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a)lib_a-init.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a)lib_a-memset.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a)lib_a-setjmp.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a)lib_a-__atexit.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a)lib_a-__call_atexit.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/librdimon.a)rdimon-syscalls.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/librdimon.a)rdimon-_exit.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/librdimon.a)rdimon-_kill.o
(RTOS/libcommon.a)kal_no_os.o
(RTOS/libcommon.a)lib_mem.o
(RTOS/libcpu.a)cpu_core.o
(RTOS/libcpu.a)cpu_a.o
(RTOS/libio.a)spi.o
(RTOS/libio.a)spi_bus.o
(RTOS/libio.a)spi_bus_drv_null.o
(unity/libunity.a)unity.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a)lib_a-errno.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a)lib_a-findfp.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a)lib_a-fwalk.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a)lib_a-mallocr.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a)lib_a-mlock.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a)lib_a-sbrkr.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a)lib_a-stdio.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a)lib_a-strlen.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a)lib_a-wbuf.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a)lib_a-writer.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a)lib_a-wsetup.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a)lib_a-closer.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a)lib_a-fclose.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a)lib_a-fflush.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a)lib_a-freer.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a)lib_a-lseekr.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a)lib_a-makebuf.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a)lib_a-readr.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a)lib_a-reent.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a)lib_a-fstatr.o
(/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a)lib_a-isattyr.o
/usr/lib/gcc/arm-none-eabi/4.9.3/crtend.o
/usr/lib/gcc/arm-none-eabi/4.9.3/crtn.o
/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/bin/ld: error: /usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a(lib_a-setjmp.o): Conflicting CPU architectures 13/1
/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/bin/ld: failed to merge target specific data of file /usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a(lib_a-setjmp.o)
/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/bin/ld: link errors found, deleting executable `targets/twr-k70f120m/none/check-bus'
collect2: error: ld returned 1 exit status

Hi jpc,

Could you also provide us with the outcome of:
$arm-none-eabi-gcc --version

And I see you are missing -mthumb there, which the compiler should complain about. This looks like its not choosing the right multilib. --print-multi-directory, when passed with your command should yield armv7-m

jpc (jimcarroll21) said : #4

Hi Andre,

jpc@jpc-laptop:~/Development/io_tests$ arm-none-eabi-gcc --version
arm-none-eabi-gcc (15:4.9.3+svn227297-1) 4.9.3 20150529 (prerelease)
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

and

arm-none-eabi-gcc -o targets/twr-k70f120m/none/check-core --print-multi-directory -mthumb -march=armv7-m -T targets/twr-k70f120m/k70f120m.ld -mfpu=vfpv4 --specs=rdimon.specs -Wl,--trace tests/core/runner.o tests/core/tests.o targets/twr-k70f120m/none/main.o targets/twr-k70f120m/sys_init.o -LRTOS -Lunity -lc -lm -lgcc -lrdimon -lcommon -lcpu -lio -lbsp-twr-k70f120m -lunity
.

It is searching the current directory for libs?

jpc (jimcarroll21) said : #5

Hey, all.

Just found the solution.

The linker determines which libs to use based on the "-m" options passed in. You can see the options associated with each multilib using -print-multi-lib.

jpc@jpc-laptop:~/Development/io_tests$ arm-none-eabi-gcc -print-multi-lib
.;
thumb;@mthumb
fpu;@mfloat-abi=hard
armv6-m;@mthumb@march=armv6s-m
armv7-m;@mthumb@march=armv7-m
armv7e-m;@mthumb@march=armv7e-m
armv7-ar/thumb;@mthumb@march=armv7
armv7e-m/softfp;@mthumb@march=armv7e-m@mfloat-abi=softfp@mfpu=fpv4-sp-d16
armv7e-m/fpu;@mthumb@march=armv7e-m@mfloat-abi=hard@mfpu=fpv4-sp-d16
armv7-ar/thumb/softfp;@mthumb@march=armv7@mfloat-abi=softfp@mfpu=vfpv3-d16
armv7-ar/thumb/fpu;@mthumb@march=armv7@mfloat-abi=hard@mfpu=vfpv3-d16
thumb/armv7-ar/fpu/vfpv3-d16/be;@mthumb@march=armv7@mfloat-abi=hard@mfpu=vfpv3-d16@mbig-endian

Here you can see that the "armv7-m" libs will be used when "-mthumb -march=armv7-m" are passed in. My issue was that I was also passing in "-mfpu-vfpv4". This does not match any of these multilibs, so the ".;" option is selected.

I was able to resolve the issue by only passing "-mthumb -march=armv7-m".

Thanks for helping me work through this issue. Hopefully somebody else will find this helpful, too!

Best,
Jim

Hi jpc,

So I think the reason we only have floating point multilibs for armv7e-m and not armv7-m is that the two Cortex-M cores that support FPU also support DSP and thus fall under the armv7e-m architecture.

Also if you define a -mfpu you might want to pass -mfloat-abi=softfp or hard, to actually use the fpu instructions.

Furthermore, are you sure -mfpu=vfpv4 with an armv7-m? Architecturally it doesnt make much sense to me, the ARMv7-M Architecture Reference Manual only refers to FPv4-SP-D16 and FPv5. Maybe you want to use one of these?

Cheers,
Andre

jpc (jimcarroll21) said : #7

Hi Andre,

Thanks for pointing that out to me. You are correct. I should be using

-march=armv7e-m
-mfpu=fpv4-sp-d16

... since the Cortex M4 actually implements the armv7e-m architecture, and (optionally) supports the single-precision FPU.

Additionally, I will provide the -mfloat-abi=hard to use the libs in armv7e-m/fpu. Based on my understanding, this changes the way function calls are made (i.e., the ABI), so I will not be able to link with libs compiled with -mfloat-abi=soft, correct? Sorry if this is getting off-topic.

-Jim

Yes jpc, that's correct.

You can however use -mfloat-abi=softfp which allows the use of fp instructions within functions, but all parameters/return are passed in general purpose registers or stack. This way you can link it with soft libraries whilst still using fp instructions in your own code. Do realize however that this does generate a bit more code since it will have to move the floating point arguments/return variables from the fp registers to general purpose registers or stack.

Also if you are compiling for a Cortex-M4 why not use '-mcpu=cortex-m4' rather than -march=armv7e-m?

jpc (jimcarroll21) said : #10

Hi Andre,

I think I will keep it set to 'hard' for now, since I won't be linking against any pre-compiled libraries.

I suppose I could use -mcpu instead of -march, but I kind of prefer -march=armv7e-m since it is more explicit as to which libs will be used.

Thanks again to both of you for your help.

-Jim