title: Makefile linking: undefined reference to _exit
body: <p>I have been trying to create a neatly-organized makefile project template utilizing the ARM mbed library. I have already solved a few of the problems (<a href="https://stackoverflow.com/questions/37106184/library-include-not-detecting-header-in-include-path">see this post)</a> related to header file paths. However, now I am having problems with the linker. My goal is to have sources and headers in <em>src</em>, object files in <em>obj</em>, and the final binaries in either <em>debug</em> or <em>release</em>.</p>
  
  <p>Here is the error I am getting...</p>
  
  <pre><code>make
  arm-none-eabi-g++  -DTARGET_M4 -DMBED_BUILD_TIMESTAMP=1453683815.81 -DTOOLCHAIN_GCC_ARM -DTOOLCHAIN_GCC -DTARGET_RTOS_M4_M7 -DTARGET_FF_MORPHO -DTARGET_CORTEX_M -D__FPU_PRESENT=1 -DTARGET_FF_ARDUINO -DTARGET_STM32F446RE -DTARGET_NUCLEO_F446RE -D__MBED__=1 -DTARGET_STM -DTARGET_STM32F4 -D__CORTEX_M4 -DARM_MATH_CM4 -std=c++98 -fno-rtti -I lib/ -I lib/mbed/ -I lib/mbed/TARGET_NUCLEO_F446RE/ -I lib/mbed/TARGET_NUCLEO_F446RE/TARGET_STM/ -I lib/mbed/TARGET_NUCLEO_F446RE/TARGET_STM/TARGET_STM32F4/ -I lib/mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM/ -I lib/mbed/TARGET_NUCLEO_F446RE/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F446RE/ -o obj/main.o src/main.cc
  /usr/lib/gcc/arm-none-eabi/6.1.1/../../../../arm-none-eabi/lib/libc.a(lib_a-exit.o): In function `exit':
  exit.c:(.text.exit+0x2c): undefined reference to `_exit'
  collect2: error: ld returned 1 exit status
  make: *** [makefile:54: obj/main.o] Error 1
  </code></pre>
  
  <p>This is my makefile. I have denoted where the problem(s) might be, but I am not sure.
      #Project parameters
      PROJECT = Nucleo_blink
      OBJECTS = obj/main.o
      DEST    = debug
      VPATH   = src lib $DEST
      TARGET  = NUCLEO_F446RE</p>
  
  <pre><code>#Compilation options
  DEBUG = 1
  
  #Tools
  AS      = $(GCC_BIN)arm-none-eabi-as
  CC      = $(GCC_BIN)arm-none-eabi-gcc
  CXX     = $(GCC_BIN)arm-none-eabi-g++
  LD      = $(GCC_BIN)arm-none-eabi-gcc
  OBJCOPY = $(GCC_BIN)arm-none-eabi-objcopy
  OBJDUMP = $(GCC_BIN)arm-none-eabi-objdump
  SIZE    = $(GCC_BIN)arm-none-eabi-size 
  
  include $(TARGET).mk
  
  CFLAGS = $(INCLUDE_PATHS) $(CC_SYMBOLS) $(CPU) -c -g -fno-common -fmessage-length=0 -Wall -Wextra -fno-exceptions -ffunction-sections -fdata-sections -fomit-frame-pointer -MMD -MP
  
  ifeq ($(HARDFP),1)
          FLOAT_ABI = hard
  else
          FLOAT_ABI = softfp
  endif
  
  ifeq ($(DEBUG), 1)
          CFLAGS += -DDEBUG -O0
  else
          CFLAGS += -DNDEBUG -Os
  endif
  
  #MY PROBLEM MAY BE HERE
  LD_FLAGS = $(CPU) -Wl,--gc-sections --specs=nano.specs -Wl,--wrap,main -Wl,-Map=$(PROJECT).map,--cref
  #`-u _printf_float -u _scanf_float` after -specs for floating point I/O
  
  LD_SYS_LIBS = -lstdc++ -lsupc++ -lm -lc -lgcc -lnosys 
  
  LIBRARIES = -lmbed 
  
  .PHONY: all clean lst size
  
  all: $(PROJECT).bin $(PROJECT).hex
  
  clean:
      rm -f debug/* obj/* asm/* $(DEPS)
  
  obj/%.o: %.c
          $(CC)  $(CC_FLAGS) $(CC_SYMBOLS) -std=c99 $(INCLUDE_PATHS) -o $@ $&lt;
  
  obj/%.o: %.cc
          $(CXX) $(CC_FLAGS) $(CC_SYMBOLS) -std=c++98 -fno-rtti $(INCLUDE_PATHS) -o $@ $&lt;
  
  obj/%.o: %.cpp
          $(CXX) $(CC_FLAGS) $(CC_SYMBOLS) -std=c++98 -fno-rtti $(INCLUDE_PATHS) -o $@ $&lt;
  
  obj/%.o: %.asm
          $(CC) $(CPU) -c -x assembler-with-cpp -o asm/$@ $&lt;
  
  #OR HERE
  $(PROJECT).elf: $(OBJECTS) $(SYS_OBJECTS)
          $(LD) $(LD_FLAGS) -T$(LINKER_SCRIPT) $(LIBRARY_PATHS) -o $(DEST)/$@ $^ $(LIBRARIES) $(LD_SYS_LIBS) $(LIBRARIES) $(LD_SYS_LIBS)
  
  $(PROJECT).bin: $(PROJECT).elf
          $(OBJCOPY) -O binary $&lt; $@
  
  $(PROJECT).hex: $(PROJECT).elf
          @$(OBJCOPY) -O ihex $&lt; $@
  
  $(PROJECT).lst: $(PROJECT).elf
          @$(OBJDUMP) -Sdh $&lt; &gt; $@
  
  lst: $(PROJECT).lst
  
  size: $(PROJECT).elf
          $(SIZE) $(PROJECT).elf
  
  DEPS = $(OBJECTS:.o=.d) $(SYS_OBJECTS:.o=.d)
  -include $(DEPS)
  </code></pre>
  
  <p>Before you ask, I have already tried changing <code>--specs=nano.specs</code> to <code>--specs=nosys.specs</code>. It does nothing. The strange part is that the linker settings above work fine for the automatically generated mbed makefile.</p>
  
  <p>Here is the working makefile. It compiles without errors...</p>
  
  <pre><code># This file was automagically generated by mbed.org. For more information, 
  # see http://mbed.org/handbook/Exporting-to-GCC-ARM-Embedded
  
  GCC_BIN = 
  PROJECT = Nucleo_blink
  OBJECTS = ./source/main.o 
  SYS_OBJECTS = #Long list of object files
  INCLUDE_PATHS = -I. -I./source -I./mbed -I./mbed/TARGET_NUCLEO_F446RE -I./mbed/TARGET_NUCLEO_F446RE/TARGET_STM -I./mbed/TARGET_NUCLEO_F446RE/TARGET_STM/TARGET_STM32F4 -I./mbed/TARGET_NUCLEO_F446RE/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F446RE -I./mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM 
  LIBRARY_PATHS = -L./mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM 
  LIBRARIES = -lmbed 
  LINKER_SCRIPT = ./mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM/STM32F446XE.ld
  
  ############################################################################### 
  AS      = $(GCC_BIN)arm-none-eabi-as
  CC      = $(GCC_BIN)arm-none-eabi-gcc
  CPP     = $(GCC_BIN)arm-none-eabi-g++
  LD      = $(GCC_BIN)arm-none-eabi-gcc
  OBJCOPY = $(GCC_BIN)arm-none-eabi-objcopy
  OBJDUMP = $(GCC_BIN)arm-none-eabi-objdump
  SIZE    = $(GCC_BIN)arm-none-eabi-size 
  
  ifeq ($(HARDFP),1)
          FLOAT_ABI = hard
  else
          FLOAT_ABI = softfp
  endif
  
  
  CPU = -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=$(FLOAT_ABI) 
  CC_FLAGS = $(CPU) -c -g -fno-common -fmessage-length=0 -Wall -Wextra -fno-exceptions -ffunction-sections -fdata-sections -fomit-frame-pointer -MMD -MP
  CC_SYMBOLS = -DTARGET_M4 -DTARGET_FF_ARDUINO -DTOOLCHAIN_GCC_ARM -DTOOLCHAIN_GCC -DTARGET_RTOS_M4_M7 -DTARGET_FF_MORPHO -DTARGET_LIKE_MBED -DTARGET_CORTEX_M -D__FPU_PRESENT=1 -DTARGET_LIKE_CORTEX_M4 -DTARGET_NUCLEO_F446RE -D__MBED__=1 -DTARGET_STM -DMBED_BUILD_TIMESTAMP=1468213384.59 -DTARGET_STM32F446RE -DTARGET_STM32F4 -D__CORTEX_M4 -DARM_MATH_CM4 
  
  #My makefile above copies these two lines
  LD_FLAGS = $(CPU) -Wl,--gc-sections --specs=nano.specs -u _printf_float -u _scanf_float -Wl,--wrap,main -Wl,-Map=$(PROJECT).map,--cref
  LD_SYS_LIBS = -lstdc++ -lsupc++ -lm -lc -lgcc -lnosys
  
  
  ifeq ($(DEBUG), 1)
  CC_FLAGS += -DDEBUG -O0
  else
  CC_FLAGS += -DNDEBUG -Os
  endif
  
  .PHONY: all clean lst size
  
  all: $(PROJECT).bin $(PROJECT).hex size
  
  
  clean:
          rm -f $(PROJECT).bin $(PROJECT).elf $(PROJECT).hex $(PROJECT).map $(PROJECT).lst $(OBJECTS) $(DEPS)
  
  
  .asm.o:
          $(CC) $(CPU) -c -x assembler-with-cpp -o $@ $&lt;
  .s.o:
          $(CC) $(CPU) -c -x assembler-with-cpp -o $@ $&lt;
  .S.o:
          $(CC) $(CPU) -c -x assembler-with-cpp -o $@ $&lt;
  
  .c.o:
          $(CC)  $(CC_FLAGS) $(CC_SYMBOLS) -std=gnu99   $(INCLUDE_PATHS) -o $@ $&lt;
  
  .cpp.o:
          $(CPP) $(CC_FLAGS) $(CC_SYMBOLS) -std=gnu++98 -fno-rtti $(INCLUDE_PATHS) -o $@ $&lt;
  
  
  
  $(PROJECT).elf: $(OBJECTS) $(SYS_OBJECTS)
          $(LD) $(LD_FLAGS) -T$(LINKER_SCRIPT) $(LIBRARY_PATHS) -o $@ $^ -Wl,--start-group $(LIBRARIES) $(LD_SYS_LIBS) -Wl,--end-group
  
  
  $(PROJECT).bin: $(PROJECT).elf
          $(OBJCOPY) -O binary $&lt; $@
  
  $(PROJECT).hex: $(PROJECT).elf
          @$(OBJCOPY) -O ihex $&lt; $@
  
  $(PROJECT).lst: $(PROJECT).elf
          @$(OBJDUMP) -Sdh $&lt; &gt; $@
  
  lst: $(PROJECT).lst
  
  size: $(PROJECT).elf
          $(SIZE) $(PROJECT).elf
  
  DEPS = $(OBJECTS:.o=.d) $(SYS_OBJECTS:.o=.d)
  -include $(DEPS)
  </code></pre>
  
  <p>I think my problem is some sort of path error...
  - The <code>_exit</code> symbol may be defined, but inaccessible by <em>main.o</em>
  - There may be some major error in the makefile I'm missing
  - Something totally different?</p>
  
  <p>Feel free to comment any suggested changes to this question.</p>
  
  <p><strong>EDIT: All I had to do to fix the error was change <code>CFLAGS</code> to <code>CCFLAGS</code>. The answer I marked as the solution explained what was happening, and a potential way to fix it. Although I didn't need to use the suggested solution, the explanation of why it wasn't working is useful, and the information provided by both answers is useful.</strong></p>