2016-01-25 5 views
3

Я использую инструменты компилятора Launchpad Arm. В частности,ссылка удалась с помощью arm-none-eabi-g ++, но не arm-none-eabi-gcc

рука-ни-EABI-г ++ и рука-ни-EABI-GCC от:

(ГНУ Инструменты для ARM встраиваемых процессоров) 5.2.1 20151202 (выпуск) [ARM/встроен-5-ветви ревизия 231848]

У меня есть простая программа, ориентированная на процессор STM32F103, которая не имеет никакой цели, кроме как доказать, что я могу написать аппаратное обеспечение и вызвать функцию из математической библиотеки. Это все это:

#include <stdio.h> 
#include <stdlib.h> 
#include <math.h> 
#include "stm32f10x.h" 

void hardwareTest(void){ 
    // Turn on the clock for PortB 
    RCC->APB2ENR = RCC_APB2ENR_IOPBEN; // Turn on IO Port B 
    // Put PB0 into push pull 50 MHz mode 
    GPIOB->CRL = 0x03; 
    // Turn PB0 on 
    GPIOB->ODR = 1; 
} 

volatile int x; // force call to sqrt() later 

int main(void) { 
    x = sqrt(100.0f); 
    x = sqrt(x); 
    hardwareTest(); 
    return (x); 
} 

Когда я попытался построить это, я получил сообщение об ошибке компоновщика говорил мне, что есть неопределенная ссылка на SQRT. Сборка была выполнена с помощью arm-none-eabi-gcc. Случайно я обнаружил, что если сборка выполняется с помощью arm-none-eabi-g ++, используя те же аргументы командной строки, соединение выполняется успешно.

Я написал Makefile, чтобы продемонстрировать разницу:

PROJECT = minimal 
SOURCES = src/startup_stm32f10x_hd.s \ 
      src/system_stm32f10x.c \ 
      src/main.c 
OUTPUT = ./out 
print-%: 
    @echo '$*=$($*)' 

TOOLCHAIN = arm-none-eabi- 

CXX = $(TOOLCHAIN)g++ 
CC = $(TOOLCHAIN)gcc 
AR = $(TOOLCHAIN)ar 
AS = $(TOOLCHAIN)gcc -c -x assembler-with-cpp 
LD = $(TOOLCHAIN)gcc 
OBJCOPY = $(TOOLCHAIN)objcopy 
OBJDUMP = $(TOOLCHAIN)objdump 
SIZE = $(TOOLCHAIN)size 
RM = rm -f 

CFLAGS = -O 
CFLAGS += -nostartfiles 

CXXFLAGS = -O 
CXXFLAGS += -nostartfiles 

ARCH = -mcpu=cortex-m3 -mthumb -DSTM32F10X_HD 
LDFLAGS = 

all: clean $(PROJECT).elf $(PROJECT).gcc $(PROJECT).bin 

$(PROJECT).bin: $(PROJECT).elf 
    @echo ' ======== ' 
    @echo ' Generating binaries' 
    $(OBJCOPY) -O binary $(OUTPUT)/$< $(OUTPUT)/$(PROJECT).bin 
    $(OBJCOPY) -O ihex $(OUTPUT)/$< $(OUTPUT)/$(PROJECT).hex 
    @echo ' ======== ' 

$(PROJECT).elf: $(SOURCES) 
    @echo ' ======== ' 
    @echo ' Successful build uses g++' 
    @echo ' CXXFLAGS = $(CXXFLAGS)' 
    @echo ' LDFLAGS = $(LDFLAGS)' 
    @echo ' ARCH = $(ARCH)' 
    $(CXX) -o $(OUTPUT)/[email protected] $(ARCH) $(CXXFLAGS) $(LDFLAGS) -Wl,-Tld_script/stm32.ld,-lm $^ 
    @echo ' ======== ' 

$(PROJECT).gcc: $(SOURCES) 
    @echo ' ======== ' 
    @echo ' Broken build uses gcc' 
    @echo ' CFLAGS = $(CFLAGS)' 
    @echo ' LDFLAGS = $(LDFLAGS)' 
    @echo ' ARCH = $(ARCH)' 
    $(CC) -o $(OUTPUT)/[email protected] $(ARCH) $(CFLAGS) $(LDFLAGS) -Wl,-Tld_script/stm32.ld,-lm $^ 
    @echo ' ======== ' 

$(PROJECT).gxx: $(SOURCES) 
    @echo ' ======== ' 
    @echo ' build with g++' 
    $(CXX) -o $(OUTPUT)/[email protected] $(ARCH) $(CXXFLAGS) $(LDFLAGS) -Wl,-Tld_script/stm32.ld $^ 
    @echo ' ======== ' 

# Program the binary to the board using the builtin serial bootloader 
program: 
    stm32loader.py -p /dev/ttyUSB0 -ewv $(OUTPUT)/$(PROJECT).bin 

# Remove the temporary files 
clean: 
    @echo ' ' 
    @echo ' Cleaning up: ' 
    $(RM) $(OUTPUT)/* *.o *.elf *.bin *.hex *.gcc *.gxx *.g++ 
    @echo ' ======== ' 

Это даст следующие результаты:

Cleaning up: 
rm -f ./out/* *.o *.elf *.bin *.hex *.gcc *.gxx *.g++ 
======== 
======== 
Successful build uses g++ 
CXXFLAGS = -O -nostartfiles 
LDFLAGS = 
ARCH = -mcpu=cortex-m3 -mthumb -DSTM32F10X_HD 
arm-none-eabi-g++ -o ./out/minimal.elf -mcpu=cortex-m3 -mthumb -DSTM32F10X_HD -O -nostartfiles -Wl,-Tld_script/stm32.ld,-lm src/startup_stm32f10x_hd.s src/system_stm32f10x.c src/main.c 
======== 
======== 
Broken build uses gcc 
CFLAGS = -O -nostartfiles 
LDFLAGS = 
ARCH = -mcpu=cortex-m3 -mthumb -DSTM32F10X_HD 
arm-none-eabi-gcc -o ./out/minimal.gcc -mcpu=cortex-m3 -mthumb -DSTM32F10X_HD -O -nostartfiles -Wl,-Tld_script/stm32.ld,-lm src/startup_stm32f10x_hd.s src/system_stm32f10x.c src/main.c 
/var/folders/t4/dv7b46055cjgknp4nndn1_zr0000gn/T//ccbl4swG.o: In function `main': 
main.c:(.text+0x28): undefined reference to `sqrt' 
collect2: error: ld returned 1 exit status 
make: *** [minimal.gcc] Error 1 
======== 
Generating binaries 
arm-none-eabi-objcopy -O binary ./out/minimal.elf ./out/minimal.bin 
arm-none-eabi-objcopy -O ihex ./out/minimal.elf ./out/minimal.hex 
make: Target `all' not remade because of errors. 

Так может кто-нибудь сказать мне, почему два компиляторы ведут себя по-разному? Какую простую вещь я упустил? Как я должен обеспечить правильную связь с libm и другими, если я хочу использовать arm-none-eabi-gcc?

Я посмотрел на make-файлы Фредди Шопена, но они слишком сложны для меня, чтобы разгадать.

+0

C и C++ - разные языки. Ожидаете ли вы, что компилятор Java будет вести себя одинаково? Идентичный синтаксис и грамматика не подразумевают идентичную семантику. – Olaf

+0

Где проблема, указывающая '-lm' как флаг компоновщика для gcc? Поведение такое, как ожидалось, afaics. – Ctx

+0

с использованием флага -lm не имеет значения для результата здесь –

ответ

2

C++ требует, чтобы математические функции были частью основной среды выполнения, в то время как C позволяет им находиться в библиотеке. Реализация GCC достигла этого, автоматически связав libm в сборке C++.

Есть много других отличий в фазе связи; Связывание C++ будет постоянно терпеть неудачу, если используется C-компоновщик.

Для ссылки C используйте ссылку C linker и укажите -lm, чтобы сделать libm.

+0

с использованием -lm не имеет никакого отношения к результату –

+0

Порядок важен. '-lm' должен появиться в аргументах gcc * после * всех объектных файлов, которые требуют библиотеки. Кстати, gcc принимает '-lm' в качестве опции; вам не нужно скрывать его в '-Wl' – rici

+0

Отлично! Я уверен, что я кое-что прочитал о расположении линкерных объектов до этого, но он не утонул. В этом примере я просто переместил список объектов до записи LDFLAGS, а затем добавил -lm в LDFLAGS, и все это сработало. –