Makefile not finding the include file - makefile

I Have a folder structure like this.
Gif_Utility
-> Makefile
-> include ( all .h files are over here)
-> Src ( all .c files are over here).
I am writing a makefile.
Makefile
VPATH = src:include
INC = -I ./include
gif_objects = gif_display.o \
gif_lzw.o \
gif_read.o \
sysm.o \
x86_main.o
gif_display.0 : gif_display.c
gcc -I /export/home/joshis1/MakeTutorial/GIF_Utility/include -c $<
#gif_lzw.0 : gif_lzw.c
# gcc $(INC) -c src/gif_lzw.c
#gif_read.0 : gif_read.c
# gcc -I ./include/ -c $<
#sysm_main.0 : sysm_main.c
# gcc -I ./include/ -c $<
#x86_main.0 : x86_main.c
# gcc -I ./include/ -c $<
On command prompt:
$ make gif_display.o
cc -c -o gif_display.o src/gif_display.c
src/gif_display.c:2:17: fatal error: sysm.h: No such file or directory
compilation terminated.
make: *** [gif_display.o] Error 1
On the other hand, If i do like this it compiles fine
$make
-> this creates the gif_display.o
I don't know why it is throwing error on specifying the rule. Am I missing something, please help.
I am using Ubuntu machine to build my code.

Your makefile has a .0 (zero) suffix instead of the correct .o (letter oh).
When you run just make it attempts to build the first target in the Makefile, and so runs the recipe which contains the correct -I include path. The fact that it produces an .o file, not a .0 file, is acceptable to make, although I suppose it could at least print a warning in this scenario.
When you run make gif_display.o it uses Make's built-in productions for .o files, which do not contain your include path.
Given that make already has built-in rules for .o files, your rules are basically superfluous. It would be better to just add the -I include parameter to the default rules, with something like
CFLAGS += -I include
So the entire Makefile could be as simple as this:
VPATH = src:include
CFLAGS += -I ./include
gif_objects = gif_display.o \
gif_lzw.o \
gif_read.o \
sysm.o \
x86_main.o
I don't see anything to alert your Makefile to changes in .h files, so you might want to add a separate dependency for that. If you just have a few shared header files between all your object files, maybe this will be all you need:
$(gif_objects): $(wildcard include/*.h)
This basically makes the include component of the VPATH superfluous.

Related

Compile error - Make error: *** multiple target patterns. Stop

I have a problem with a makefile that's part of a repository. I already posted this question but don't know how to add some code lines after, so I'm trying it here.There is a problem with the makefile that has the common make rules. When I run make, I get the following error: C:\Mios32/include/makefile/common.mk:143: *** multiple target patterns. Stop.
Here's the code from common.mk file from line 142 to 144:
# rule to create .elf file
$(PROJECT_OUT)/$(PROJECT).elf: $(ALL_OBJS)
#$(CC) $(CFLAGS) $(ALL_OBJS) $(LIBS) $(LDFLAGS) -o$#
I'm guessing it's a problem with all_objs, cause these lines right before seem to work:
# rule to create a .hex and .bin file
%.bin : $(PROJECT_OUT)/$(PROJECT).elf
#$(OBJCOPY) $< -O binary $#
%.hex : $(PROJECT_OUT)/$(PROJECT).elf
#$(OBJCOPY) $< -O ihex $#
# rule to create a listing file from .elf
%.lss: $(PROJECT_OUT)/$(PROJECT).elf
#$(OBJDUMP) -w -h -S -C $< > $#
# rule to create a symbol table from .elf
%.sym: $(PROJECT_OUT)/$(PROJECT).elf
#$(NM) -n $< > $#
Here's some additional lines with all_objs:
# list of all objects
ALL_OBJS = $(addprefix $(PROJECT_OUT)/, $(THUMB_OBJS) $(THUMB_CPP_OBJS) $(THUMB_AS_OBJS)
$(ARM_OBJS) $(ARM_CPP_OBJS) $(ARM_AS_OBJS))
# list of all dependency files
ALL_DFILES = $(ALL_OBJS:.o=.d)
And here's some additional lines with Project_out and project:
# where should the output files be located
PROJECT_OUT ?= $(PROJECT)_build
# default linker flags
LDFLAGS += -T $(LD_FILE) -mthumb -u _start -Wl,--gc-section -Xlinker -M -Xlinker -
Map=$(PROJECT_OUT)/$(PROJECT).map -nostartfiles -lstdc++
# default rule
all: dirs cleanhex $(PROJECT).hex $(PROJECT_OUT)/$(PROJECT).bin
$(PROJECT_OUT)/$(PROJECT).lss $(PROJECT_OUT)/$(PROJECT).sym projectinfo
# create the output directories
dirs:
#-if [ ! -e $(PROJECT_OUT) ]; then mkdir $(PROJECT_OUT); fi;
#-$(foreach DIR,$(DIRS), if [ ! -e $(PROJECT_OUT)/$(DIR) ]; \
then mkdir -p $(PROJECT_OUT)/$(DIR); fi; )
I'm pretty new to the whole Make and Makefile topic, so I'm having a hard time figuring out the problem. I appreciate every help.
You should be clear in your question what OS you're working on. It seems from the error message above you're working on Windows. The makefile you're trying to use is very clearly targeted at a UNIX system like GNU/Linux or possibly MacOS.
If you are not familiar with the differences between Windows and UNIX (which are vast and deep) you will definitely have a lot of learning to do before you can even start to get this working.
To use UNIX environments on Windows you need to use something like WSL, or Cygwin, or at least install a MinGW shell environment. When you do that you need to be using UNIX paths, not Windows paths. Windows paths use backslashes (which are escape sequences in UNIX) and drive letters (which have no equivalent in UNIX) and in makefiles in particular the : character is special to make so using paths with drive letters is a problem.
You can debug your makefile by adding $(info ...) functions to show you the value of variables:
# rule to create .elf file
$(info PROJECT_OUT = $(PROJECT_OUT))
$(info PROJECT = $(PROJECT))
$(info ALL_OBJS = $(ALL_OBJS))
$(PROJECT_OUT)/$(PROJECT).elf: $(ALL_OBJS)
#$(CC) $(CFLAGS) $(ALL_OBJS) $(LIBS) $(LDFLAGS) -o$#

Makefile 'missing separator' for ifneq

I know there are other issues with similar titles, but they don't seem to hold the solution.
Heres my makefile:
# Compiler Command
CC = mpiCC
CFLAGS = -c -I./header
# collecting object file names
src = $(wildcard source/*.cpp)
src1 = $(src:.cpp=.o)
objects := $(src1:source/%=bin/%)
# Compile object files into binary
all : $(objects)
$(CC) -o run $(objects)
ifneq($(n),) // <- error location , line 15
mpirun -np $(n) run
endif
# Generate object files by compiling .cpp and .h files
bin/%.o : source/%.cpp
$(CC) $(CFLAGS) $?
mv *.o bin
# Clean Recipe
.PHONY : clean
clean :
rm -rf all $(objects)
The goal of the ifneq is to have the binary run whenever it finishes compiling.
for example, a user runs the command:
make <- builds without running
make n=5 <- builds and runs on 5 processes
Whenever I use either of these, I get the error:
makefile:15: *** missing separator. Stop.
I've used cat -e -t -v to verify everything is tabbed instead of spaced. according to (https://www.gnu.org/software/make/manual/make.html#Conditional-Example) this conditional should function.
#MadScientist solved it. You need to put a space in between ifneq and its argument. For example:
ifneq($(n),0) is invalid.
ifneq ($(n),0) is valid.

What is causing the error `make: Nothing to be done for 'x.o'.` for some x?

I added a new target (main.o) to an existing project:
DATS_FILES = main.dats
HFILES = config.h es.h gc.h input.h prim.h print.h sigmsgs.h \
stdenv.h syntax.h term.h var.h
CFILES = access.c closure.c conv.c dict.c eval.c except.c fd.c gc.c glob.c \
glom.c input.c heredoc.c list.c c_main.c match.c open.c opt.c \
prim-ctl.c prim-etc.c prim-io.c prim-sys.c prim.c print.c proc.c \
sigmsgs.c signal.c split.c status.c str.c syntax.c term.c token.c \
tree.c util.c var.c vec.c version.c y.tab.c dump.c
src :
#echo ${OTHER} ${CFILES} ${HFILES} ${DATS_FILES}
list.o : list.c es.h config.h stdenv.h gc.h
main.o : main.dats
match.o : match.c es.h config.h stdenv.h
As can be seen above, I have tried to give the new source .dats file the same status as the .c files in the project, which have no problems building.
If I try to build the target directly I get:
make main.o
make: Nothing to be done for 'main.o'.
This happens even if I run touch main.dats. If I compile main.dats manually after make fails, then run make again, the project finishes building and the output executable runs without issue. Here is the complete Makefile.in.
you need to add a rule to specify to make how to re-create main.o starting from main.dats. For C files make knows what to do, but for .dats files it doesn't. In particular, you have to change:
main.o : main.dats
with
main.o : main.dats
(your-compiler) (your-compiler-options) -o main.o main.dats
(assuming that is the syntax in your compiler for specifying input and output files)
IMPORTANT: indentation of the second (and the following) lines have to be done with tabs and not spaces, because that's how make works.
In your case (assuming .dats is the extension for dynamic ATS language) I think it should be
main.o : main.dats
patscc -c -o main.o main.dats
edit: if you have more than one .dats file to compile you can add a generic rule that teach make to invoke the right compiler for them (thanks to Toby for the syntax)
%.o : %.dats
patscc -c -o $# $<
I am not sure what is the priority for application when both a main.c and main.dats are present.

How to write Makefile to include multi directories

I have the following setup. Two folders named /driverlib and /inc on the main folder and on the same folder I have a linker file and two c files, startup_gcc and blink.c.
I followed a template I found online for STM32F4. I modified it and tried to include both directories on my folder. However I am getting the following error:
C:\Users\D\Documents\ARM-Tiva\blinky3>make
driverlib/adc.c:49:24: fatal error: inc/hw_adc.h: No such file or directory
compilation terminated.
make: *** [driverlib/adc.o] Error 1
Can somebody explain to me how to include both directories so that the /inc folder is visible to the /driverlib folder.
Here's the makefile:
OBJCOPY = $(TC)-objcopy
OBJDUMP = $(TC)-objdump
SIZE = $(TC)-size
###################################################
# Set Include Paths
INCLUDES = -I /inc
INCLUDES = -I /driverlib
# Set Sources
LIB_SRCS = $(wildcard driverlib/*.c)
USER_SRCS = $(wildcard src/*.c)
# Set Objects
LIB_OBJS = $(LIB_SRCS:.c=.o)
USER_OBJS = $(USER_SRCS:.c=.o) startup_gcc.o
# Set Libraries
LIBS = -lm -lc
###################################################
# Set Board
MCU = -mthumb -mcpu=cortex-m4
DEFINES = -DPART_LM4F120H5QR -DTARGET_IS_BLIZZARD_RA1
# Set Compilation and Linking Flags
CFLAGS = $(MCU) $(FPU) $(DEFINES) $(INCLUDES) \
-g -Wall -std=gnu90 -O0 -ffunction-sections -fdata-sections
ASFLAGS = $(MCU) $(FPU) -g -Wa,--warn -x assembler-with-cpp
LDFLAGS = $(MCU) $(FPU) -g -gdwarf-2 \
-Ttivalinker.ld \
-Xlinker --gc-sections -Wl,-Map=$(PROJ_NAME).map \
$(LIBS) \
-o $(PROJ_NAME).elf
###################################################
# Default Target
all: $(PROJ_NAME).bin info
# elf Target
$(PROJ_NAME).elf: $(LIB_OBJS) $(USER_OBJS)
#$(CC) $(LIB_OBJS) $(USER_OBJS) $(LDFLAGS)
#echo $#
# bin Target
$(PROJ_NAME).bin: $(PROJ_NAME).elf
#$(OBJCOPY) -O binary $(PROJ_NAME).elf $(PROJ_NAME).bin
#echo $#
#$(PROJ_NAME).hex: $(PROJ_NAME).elf
# #$(OBJCOPY) -O ihex $(PROJ_NAME).elf $(PROJ_NAME).hex
# #echo $#
#$(PROJ_NAME).lst: $(PROJ_NAME).elf
# #$(OBJDUMP) -h -S $(PROJ_NAME).elf > $(PROJ_NAME).lst
# #echo $#
# Display Memory Usage Info
info: $(PROJ_NAME).elf
#$(SIZE) --format=berkeley $(PROJ_NAME).elf
# Rule for .c files
.c.o:
#$(CC) $(CFLAGS) -c -o $# $<
#echo $#
# Rule for .s files
.s.o:
#$(CC) $(ASFLAGS) -c -o $# $<
#echo $#
# Clean Target
clean:
$(RM) $(LIB_OBJS)
$(RM) $(USER_OBJS)
$(RM) $(PROJ_NAME).elf
$(RM) $(PROJ_NAME).bin
$(RM) $(PROJ_NAME).map
The issue is obviously at this paragraph:
###################################################
# Set Include Paths
INCLUDES = -I /inc
INCLUDES = -I /driverlib
# Set Sources
LIB_SRCS = $(wildcard driverlib/*.c)
USER_SRCS = $(wildcard src/*.c)
# Set Objects
LIB_OBJS = $(LIB_SRCS:.c=.o)
USER_OBJS = $(USER_SRCS:.c=.o) startup_gcc.o
I cannot understand why driverlib does not include the inc directory files.
EDIT
I wanted to clarify my setup for future reference: On the main folder called blinky I have three folders : driverlib, inc and src. The driverlib and inc folders are taken from the TivaWARE folder while the src folder contains the blinky.c and startup_gcc.c file. Given the following if you use make you obtain the following :
C:\Users\D\Documents\ARM-Tiva\blinky>make
driverlib/adc.c:49:24: fatal error: inc/hw_adc.h: No such file or directory
compilation terminated.
make: *** [driverlib/adc.o] Error 1
This shows that the file adc.c in the driverlib folder cannot include the file hw_adc.h in
I modified the Makefile following the suggestions below:
# Set Sources
LIB_SRCS = $(wildcard driverlib/*.c)
USER_SRCS = $(wildcard src/*.c)
# Set Objects
LIB_OBJS = $(LIB_SRCS:.c=.o)
USER_OBJS = $(USER_SRCS:.c=.o) src/startup_gcc.o
# Set Include Paths
INCLUDES = -Idriverlib/ \
-Iinc \
-Isrc/
Betas solution was helpful , the only issue was that I did not want to edit all the files in the driverlib folder. The naming convention of the directories was not my decision. If you can see all the files in the driverlib folder you'll find out that each driver file , CAN driver for example or ADC) follows this convention :
#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/can.h"
#include "driverlib/debug.h"
#include "driverlib/interrupt.h"
So right now I understand where the issue is but I lack the understanding to edit the Makefile.
Normally if files can.c and can.h are in folder driverlib using #include "can.h" would suffice so I do not understand what's the point of using #include "driverlib/can.h" if all .h and .c files are in the same driverlib folder . If I edit all the inc/ header then I can get a working binary file. The aim however was not to modify the default stock driver files and folders obtained from TI but to use the Makefile.
So to clarify if you follow Betas solution and edit all the files , or if you put all the files in one big directory then you can get a working binary file. Also for future reference I found I could use Energia for what I am doing since it uses the same compiler and TIVA includes the complete peripheral library burned on ROM.
I don't know the cause of the error exactly, but this is not correct:
INCLUDES = -I /inc
# Now INCLUDES is "-I /inc"
INCLUDES = -I /driverlib
# Now INCLUDES is "-I /driverlib", and inc has been forgotten.
I think you mean this:
INCLUDES = -I /inc
INCLUDES += -I /driverlib
EDIT:
It's generally a bad idea to spell out paths in the #include directives. In adc.c, change this:
#include "inc/hw_adc.h"
to this:
#include "hw_adc.h"
and in the makefile remove the leading slashes (since you won't always be in the root directory):
INCLUDES = -I inc
INCLUDES += -I driverlib
The most helpful thing would have been if you had provided the actual complete path of one of the header files which is not being found, in your question, and an example compile line run by make in addition to the error message. Given that information it's trivial to see what's wrong.
It looks like some miscommunication is happening. You write two folders named /driverlib and /inc on the main folder. A folder name that begins with a / is by definition at the root of the directory structure, not within any other folder. I don't know what you mean by on the main folder.
The first thing I'll say is that you're using Windows (as can be seen by your command line prompt), and so you need to be sure that the version of make you're using will do the right thing converting Windows pathnames to UNIX pathnames. For example if you're using Cygwin version of GNU make, then I think the paths you're using are not correct.
Second, I note that you are using -I /inc; that is, the inc directory is at the root of your filesystem. Is that what you intended? Beta's answers have changed that to -I inc, which means the directory inc as a subdirectory of the current working directory, which could be quite different.
Third, if the pathname to the headers is /inc/hw_adc.h and you have -I /inc on your command line and #include "inc/hw_adc.h", I'm sure you can see how this will absolutely not work. The compiler will be looking for header files named /inc/inc/hw_adc.h. If you want to keep the relative pathname inc/hw_adc.h in your #include line, and the path to the header file is /inc/hw_adc.h, then you should use just -I / (the root directory) on the compile command line.
Lastly, I'll say that I actually don't agree with Beta's suggestion that it's a bad idea to spell out paths in include lines. This is common: if you are using a library that contains a lot of header files then typically the header files are collected in a subdirectory (consider things like Boost, or X11, etc.) and it's, IMO, good practice to use the name of the subdirectory in your #include lines in the source code.
On the other hand, though, I will agree with Beta that a directory name like inc is utterly lame and is of pretty much no use whatever. That directory should have a name which is somehow evocative of the kinds of headers that can be found inside it, not something uselessly generic like "inc".

makefile pathing issues on OSX

OK, I thought I would try one last update and see if it gets me anywhere. I've created a very small test case. This should not build anything, it just tests the path settings. Also I've setup the path so there are no spaces. The is the smallest, simplest test case I could come up with.
This makefile will set the path, echo the path, run avr-gcc -v with the full path specified and then try to run it without the full path specified. It should find avr-gcc in the path on the second try, but does not.
makefile
TOOLCHAIN := /Users/justinzaun/Desktop/AVRBuilder.app/Contents/Resources/avrchain
PATH := ${TOOLCHAIN}/bin:${PATH}
export PATH
all:
#echo ${PATH}
#echo --------
"${TOOLCHAIN}/bin/avr-gcc" -v
#echo --------
avr-gcc -v
output
JUSTINs-MacBook-Air:Untitled justinzaun$ make
/Users/justinzaun/Desktop/AVRBuilder.app/Contents/Resources/avrchain/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin
--------
"/Users/justinzaun/Desktop/AVRBuilder.app/Contents/Resources/avrchain/bin/avr-gcc" -v
Using built-in specs.
COLLECT_GCC=/Users/justinzaun/Desktop/AVRBuilder.app/Contents/Resources/avrchain/bin/avr-gcc
COLLECT_LTO_WRAPPER=/Users/justinzaun/Desktop/AVRBuilder.app/Contents/Resources/avrchain/bin/../libexec/gcc/avr/4.6.3/lto-wrapper
Target: avr
Configured with: /Users/justinzaun/Development/AVRBuilder/Packages/gccobj/../gcc/configure --prefix=/Users/justinzaun/Development/AVRBuilder/Packages/gccobj/../build/ --exec-prefix=/Users/justinzaun/Development/AVRBuilder/Packages/gccobj/../build/ --datadir=/Users/justinzaun/Development/AVRBuilder/Packages/gccobj/../build/ --target=avr --enable-languages=c,objc,c++ --disable-libssp --disable-lto --disable-nls --disable-libgomp --disable-gdbtk --disable-threads --enable-poison-system-directories
Thread model: single
gcc version 4.6.3 (GCC)
--------
avr-gcc -v
make: avr-gcc: No such file or directory
make: *** [all] Error 1
JUSTINs-MacBook-Air:Untitled justinzaun$
Original Question
I'm trying to set the path from within the makefile. I can't seem to do this on OSX. Setting the path with PATH := /new/bin/:$(PATH) does not work. See my makefile below.
makefile
PROJECTNAME = Untitled
# Name of target controller
# (e.g. 'at90s8515', see the available avr-gcc mmcu
# options for possible values)
MCU = atmega640
# id to use with programmer
# default: PROGRAMMER_MCU=$(MCU)
# In case the programer used, e.g avrdude, doesn't
# accept the same MCU name as avr-gcc (for example
# for ATmega8s, avr-gcc expects 'atmega8' and
# avrdude requires 'm8')
PROGRAMMER_MCU = $(MCU)
# Source files
# List C/C++/Assembly source files:
# (list all files to compile, e.g. 'a.c b.cpp as.S'):
# Use .cc, .cpp or .C suffix for C++ files, use .S
# (NOT .s !!!) for assembly source code files.
PRJSRC = main.c \
utils.c
# additional includes (e.g. -I/path/to/mydir)
INC =
# libraries to link in (e.g. -lmylib)
LIBS =
# Optimization level,
# use s (size opt), 1, 2, 3 or 0 (off)
OPTLEVEL = s
### You should not have to touch anything below this line ###
PATH := /Users/justinzaun/Library/Developer/Xcode/DerivedData/AVR_Builder-gxiykwiwjywvoagykxvmotvncbyd/Build/Products/Debug/AVR\ Builder.app/Contents/Resources/avrchain/bin:/usr/bin:/bin:$(PATH)
CPATH := /Users/justinzaun/Library/Developer/Xcode/DerivedData/AVR_Builder-gxiykwiwjywvoagykxvmotvncbyd/Build/Products/Debug/AVR\ Builder.app/Contents/Resources/avrchain/include
# HEXFORMAT -- format for .hex file output
HEXFORMAT = ihex
# compiler
CFLAGS = -I. $(INC) -g -mmcu=$(MCU) -O$(OPTLEVEL) \
-fpack-struct -fshort-enums \
-funsigned-bitfields -funsigned-char \
-Wall -Wstrict-prototypes \
-Wa,-ahlms=$(firstword \
$(filter %.lst, $(<:.c=.lst)))
# c++ specific flags
CPPFLAGS = -fno-exceptions \
-Wa,-ahlms=$(firstword \
$(filter %.lst, $(<:.cpp=.lst)) \
$(filter %.lst, $(<:.cc=.lst)) \
$(filter %.lst, $(<:.C=.lst)))
# assembler
ASMFLAGS = -I. $(INC) -mmcu=$(MCU) \
-x assembler-with-cpp \
-Wa,-gstabs,-ahlms=$(firstword \
$(<:.S=.lst) $(<.s=.lst))
# linker
LDFLAGS = -Wl,-Map,$(TRG).map -mmcu=$(MCU) \
-lm $(LIBS)
##### executables ####
CC=avr-gcc
OBJCOPY=avr-objcopy
OBJDUMP=avr-objdump
SIZE=avr-size
AVRDUDE=avrdude
REMOVE=rm -f
##### automatic target names ####
TRG=$(PROJECTNAME).out
DUMPTRG=$(PROJECTNAME).s
HEXROMTRG=$(PROJECTNAME).hex
HEXTRG=$(HEXROMTRG) $(PROJECTNAME).ee.hex
# Start by splitting source files by type
# C++
CPPFILES=$(filter %.cpp, $(PRJSRC))
CCFILES=$(filter %.cc, $(PRJSRC))
BIGCFILES=$(filter %.C, $(PRJSRC))
# C
CFILES=$(filter %.c, $(PRJSRC))
# Assembly
ASMFILES=$(filter %.S, $(PRJSRC))
# List all object files we need to create
OBJDEPS=$(CFILES:.c=.o) \
$(CPPFILES:.cpp=.o) \
$(BIGCFILES:.C=.o) \
$(CCFILES:.cc=.o) \
$(ASMFILES:.S=.o)
# Define all lst files.
LST=$(filter %.lst, $(OBJDEPS:.o=.lst))
# All the possible generated assembly
# files (.s files)
GENASMFILES=$(filter %.s, $(OBJDEPS:.o=.s))
.SUFFIXES : .c .cc .cpp .C .o .out .s .S \
.hex .ee.hex .h .hh .hpp
# Make targets:
# all, disasm, stats, hex, writeflash/install, clean
all: $(TRG)
$(TRG): $(OBJDEPS)
$(CC) $(LDFLAGS) -o $(TRG) $(OBJDEPS)
#### Generating assembly ####
# asm from C
%.s: %.c
$(CC) -S $(CFLAGS) $< -o $#
# asm from (hand coded) asm
%.s: %.S
$(CC) -S $(ASMFLAGS) $< > $#
# asm from C++
.cpp.s .cc.s .C.s :
$(CC) -S $(CFLAGS) $(CPPFLAGS) $< -o $#
#### Generating object files ####
# object from C
.c.o:
$(CC) $(CFLAGS) -c $< -o $#
# object from C++ (.cc, .cpp, .C files)
.cc.o .cpp.o .C.o :
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $#
# object from asm
.S.o :
$(CC) $(ASMFLAGS) -c $< -o $#
#### Generating hex files ####
# hex files from elf
.out.hex:
$(OBJCOPY) -j .text \
-j .data \
-O $(HEXFORMAT) $< $#
.out.ee.hex:
$(OBJCOPY) -j .eeprom \
--change-section-lma .eeprom=0 \
-O $(HEXFORMAT) $< $#
#### Information ####
info:
#echo PATH:
#echo "$(PATH)"
$(CC) -v
which $(CC)
#### Cleanup ####
clean:
$(REMOVE) $(TRG) $(TRG).map $(DUMPTRG)
$(REMOVE) $(OBJDEPS)
$(REMOVE) $(LST)
$(REMOVE) $(GENASMFILES)
$(REMOVE) $(HEXTRG)
error
JUSTINs-MacBook-Air:Untitled justinzaun$ make
avr-gcc -I. -g -mmcu=atmega640 -Os -fpack-struct -fshort-enums -funsigned-bitfields -funsigned-char -Wall -Wstrict-prototypes -Wa,-ahlms=main.lst -c main.c -o main.o
make: avr-gcc: No such file or directory
make: *** [main.o] Error 1
JUSTINs-MacBook-Air:Untitled justinzaun$
If I change my CC= to include the full path:
CC=/Users/justinzaun/Library/Developer/Xcode/DerivedData/AVR_Builder-gxiykwiwjywvoagykxvmotvncbyd/Build/Products/Debug/AVR\ Builder.app/Contents/Resources/avrchain/bin/avr-gcc
then it finds it, but this doesn't seem the correct way to do things. For instance its trying to use the system as not the one in the correct path.
update - Just to be sure, I'm adding the output of my ls command too so everyone knows the file exist. Also I've added a make info target to the makefile and showing that output as well.
JUSTINs-MacBook-Air:Untitled justinzaun$ ls /Users/justinzaun/Library/Developer/Xcode/DerivedData/AVR_Builder-gxiykwiwjywvoagykxvmotvncbyd/Build/Products/Debug/AVR\ Builder.app/Contents/Resources/avrchain/bin
ar avr-elfedit avr-man avr-strip objcopy
as avr-g++ avr-nm avrdude objdump
avr-addr2line avr-gcc avr-objcopy c++ ranlib
avr-ar avr-gcc-4.6.3 avr-objdump g++ strip
avr-as avr-gcov avr-ranlib gcc
avr-c++ avr-gprof avr-readelf ld
avr-c++filt avr-ld avr-size ld.bfd
avr-cpp avr-ld.bfd avr-strings nm
JUSTINs-MacBook-Air:Untitled justinzaun$
Output of make info with the \ in my path
JUSTINs-MacBook-Air:Untitled justinzaun$ make info
PATH:
/Users/justinzaun/Library/Developer/Xcode/DerivedData/AVR_Builder-gxiykwiwjywvoagykxvmotvncbyd/Build/Products/Debug/AVR\ Builder.app/Contents/Resources/avrchain/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin
avr-gcc -v
make: avr-gcc: No such file or directory
make: *** [info] Error 1
JUSTINs-MacBook-Air:Untitled justinzaun$
Output of make info with the \ not in my path
JUSTINs-MacBook-Air:Untitled justinzaun$ make info
PATH:
/Users/justinzaun/Library/Developer/Xcode/DerivedData/AVR_Builder-gxiykwiwjywvoagykxvmotvncbyd/Build/Products/Debug/AVR Builder.app/Contents/Resources/avrchain/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin
avr-gcc -v
make: avr-gcc: No such file or directory
make: *** [info] Error 1
JUSTINs-MacBook-Air:Untitled justinzaun$
update - When I have my CC set to include the full path as described above, this is the result of make info.
JUSTINs-MacBook-Air:Untitled justinzaun$ make info
PATH:
/Users/justinzaun/Library/Developer/Xcode/DerivedData/AVR_Builder-gxiykwiwjywvoagykxvmotvncbyd/Build/Products/Debug/AVR Builder.app/Contents/Resources/avrchain/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin
/Users/justinzaun/Library/Developer/Xcode/DerivedData/AVR_Builder-gxiykwiwjywvoagykxvmotvncbyd/Build/Products/Debug/AVR\ Builder.app/Contents/Resources/avrchain/bin/avr-gcc -v
Using built-in specs.
COLLECT_GCC=/Users/justinzaun/Library/Developer/Xcode/DerivedData/AVR_Builder-gxiykwiwjywvoagykxvmotvncbyd/Build/Products/Debug/AVR Builder.app/Contents/Resources/avrchain/bin/avr-gcc
COLLECT_LTO_WRAPPER=/Users/justinzaun/Library/Developer/Xcode/DerivedData/AVR_Builder-gxiykwiwjywvoagykxvmotvncbyd/Build/Products/Debug/AVR Builder.app/Contents/Resources/avrchain/bin/../libexec/gcc/avr/4.6.3/lto-wrapper
Target: avr
Configured with: /Users/justinzaun/Development/AVRBuilder/Packages/gccobj/../gcc/configure --prefix=/Users/justinzaun/Development/AVRBuilder/Packages/gccobj/../build/ --exec-prefix=/Users/justinzaun/Development/AVRBuilder/Packages/gccobj/../build/ --datadir=/Users/justinzaun/Development/AVRBuilder/Packages/gccobj/../build/ --target=avr --enable-languages=c,objc,c++ --disable-libssp --disable-lto --disable-nls --disable-libgomp --disable-gdbtk --disable-threads --enable-poison-system-directories
Thread model: single
gcc version 4.6.3 (GCC)
which /Users/justinzaun/Library/Developer/Xcode/DerivedData/AVR_Builder-gxiykwiwjywvoagykxvmotvncbyd/Build/Products/Debug/AVR\ Builder.app/Contents/Resources/avrchain/bin/avr-gcc
/Users/justinzaun/Library/Developer/Xcode/DerivedData/AVR_Builder-gxiykwiwjywvoagykxvmotvncbyd/Build/Products/Debug/AVR Builder.app/Contents/Resources/avrchain/bin/avr-gcc
JUSTINs-MacBook-Air:Untitled justinzaun$
I tried your example on OSX and Linux, and got the same results that you did. I don't quite understand why that isn't working (and would love to know), but I do have two workarounds that might help.
export SHELL
Instead of setting the PATH in your Makefile, override the SHELL like this:
export SHELL=/Users/whatever/avr-dir/wrapper
Here's a possible version of that wrapper:
#!/bin/bash
PATH="/Users/whatever/avr-dir:${PATH}"
/bin/bash "$#"
Make will invoke this wrapper to run each line of yoru recipes. This is a little ugly, but it did work for me on OSX.
Outside
Fix the PATH outside of make. Perhaps create a script that you run once per login that fixes the PATH in your shell, or create a small script (I usually call it mk) that fixes the PATH and then invokes make passing along any parameters. Here's an exmaple:
#!/bin/bash
PATH="/Users/whatever/avr-dir:${PATH}" exec make "$#"
I know you asked for a Makefile solution, but I thought I would mention this option anyway. It is just my opinion, but things like PATHs tend to be machine specific (and not project specific), and I prefer to keep them separate from source code.
Your problem is not that make failed to find avr-gcc. Your problem is in this line:
$(CC) $(CFLAGS) -mmcu=$(MCU) -c $(input) -o $(output)
Since $(input) and $(output) have not been defined your avr-gcc command-line is incomplete. Try changing that line to this instead:
$(CC) $(CFLAGS) -mmcu=$(MCU) -c $< -o $#
$< and $# are automatic variables defined to mean "the first prerequisite" and "the output target", respectively.
The problem is that make is failing to find avr-gcc, and it's due to the \ in your PATH= line.
$ mkdir /tmp/foo\ bar
$ cd /tmp/foo\ bar
$ (echo "#! /bin/sh"; echo "echo this got run") > execable
$ chmod +x execable
$ mkdir /tmp/tstmake; cd /tmp/tstmake
(now make a Makefile with contents as shown)
$ cat Makefile
PATH := /tmp/foo\ bar:$(PATH)
all:
#echo path is "$(PATH)"
execable
$ make
path is /tmp/foo\ bar:/Users/torek/bin.i386:/Users/torek/scripts:[snipped lots]
execable
make: execable: Command not found
make: *** [all] Error 127
$ ed Makefile
71
1s/\\//p
PATH := /tmp/foo bar:$(PATH)
w
70
q
$ make
path is /tmp/foo bar:/Users/torek/bin.i386:/Users/torek/scripts:[snipped lots]
execable
this got run
Update: this is not the only problem, at least when I use my MBP to simulate the issue. The remaining two are:
CPATH also needs the backslash removed (this is a general rule about these := settings)
CPATH needs to be explicitly exported, by adding the line
export CPATH
to the Makefile.
(The reason you need the backslash sometimes, but not other times, has to do with how many times the string gets passed expliclty to the shell: once when it's in $(CC) but zero times when it is an environment variable or part of $(PATH).)
Seeing as this page didn't have a proper answer, I'll link to this page that does:
How I could add dir to $PATH in Makefile?
For whatever reason OS X does not export PATH unless you set the SHELL variable too.
So:
SHELL=/bin/bash
export PATH:=/foo/bar:$(PATH)
..would work.
I just recently ran into this issue. As other comments suggest, the version of make shipped with MacOS has some issues. Build (as #MadScientist suggests above) or install GNU make from Homebrew. The installed version of make on my system is 3.81 and exhibits the same problem. The version provided from Homebrew (version 4.3) works as expected.
I presume you're using OSX. Figuring out an elegant solution may take a few iterations.
In the meantime try this kludge, and tell us the result:
CC=`avr-gcc`
If what you want is to update your PATH variable, then do:
export PATH=$(shell echo $${PATH}):<paths to add>
Example I did:
File : ./c/luckme.sh
echo "Hello Lucky Me ! "
Makefile :
export PATH=$(shell echo $${PATH}):c:.
all:
#luckyme.sh
output of make:
~$ make
Hello Lucky Me !

Resources