title: linking succeeds with arm-none-eabi-g++ but not arm-none-eabi-gcc
body: <p>I am using the Launchpad Arm compiler tools. Specifically, </p>
  
  <p>arm-none-eabi-g++ and arm-none-eabi-gcc from:</p>
  
  <p>(GNU Tools for ARM Embedded Processors) 5.2.1 20151202 (release) [ARM/embedded-5-branch revision 231848]</p>
  
  <p>I have a simple program targeted at an STM32F103 processor that has no purpose except to prove that I can write the hardware and call a function from the math library. This is all it is:</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;math.h&gt;
  #include "stm32f10x.h"
  
  void hardwareTest(void){
     // Turn on the clock for PortB
     RCC-&gt;APB2ENR = RCC_APB2ENR_IOPBEN; // Turn on IO Port B
     // Put PB0 into push pull 50 MHz mode
     GPIOB-&gt;CRL = 0x03;
     // Turn PB0 on
     GPIOB-&gt;ODR = 1;
  }
  
  volatile int x; // force call to sqrt() later
  
  int main(void) {
     x = sqrt(100.0f);
     x = sqrt(x);
     hardwareTest();
     return (x);
  }
  </code></pre>
  
  <p>When I tried to build this, I got a linker error telling me that there is an undefined reference to sqrt. The build was done with arm-none-eabi-gcc. By chance I discovered that, if the build is done with arm-none-eabi-g++, using the same command line arguments, the linking is performed successfully.</p>
  
  <p>I wrote a Makefile to demonstrate the difference:</p>
  
  <pre><code>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)/$&lt; $(OUTPUT)/$(PROJECT).bin
      $(OBJCOPY) -O ihex   $(OUTPUT)/$&lt; $(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)/$@ $(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)/$@ $(ARCH)   $(CFLAGS) $(LDFLAGS) -Wl,-Tld_script/stm32.ld,-lm  $^
      @echo ' ======== '
  
  $(PROJECT).gxx: $(SOURCES)
      @echo ' ======== '
      @echo ' build with g++'
      $(CXX) -o $(OUTPUT)/$@ $(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 ' ======== '
  </code></pre>
  
  <p>It give the following results:</p>
  
  <pre><code>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.
  </code></pre>
  
  <p>So can anyone tell me why the two compilers behave differently? What simple thing have I overlooked? How should I ensure proper linking with libm and others if I want to use arm-none-eabi-gcc?</p>
  
  <p>I have looked at Freddie Chopin's makefiles but they are too complicated for me to unravel.</p>