projectroot/
|
+------------------------------+----------------------------+
| | |
include/ libs/ helloworld/
| | |
shader_utils.h shader_utils.c triangle.c
there are three directories under project root directory. helloworld directory contains triangle.c which depends on shader_utils.h(under projectroot/include) whose definition is under projectroot/libs.and here is my make file. whats is wrong with that.
#!bin/sh
CC=gcc
LDLIBS=-lglut -lGLEW -lGL
ROOT=/media/programming/experiments/projectroot
VPATH=../libs:../include
INC=-I$(ROOT)/include
all: triangle
triangle: triangle.o shader_utils.o
cc -c $(CFLAGS) $< -o $# $(INC)
shader_utils.o: shader_utils.h
cc -c $(CFLAGS) $< -o $# $(INC)
clean:
rm -f *.o triangle
.PHONY: all clean
when try to make. it tell this
cc -c ../include/shader_utils.h -o shader_utils.o -I/media/programming/experiments/projectroot/include
cc -c triangle.o -o triangle -I/media/programming/experiments/projectroot/include
cc: warning: triangle.o: linker input file unused because linking not done
This rule makes no sense:
triangle: triangle.o shader_utils.o
cc -c $(CFLAGS) $< -o $# $(INC)
You are telling Make to construct an executable, but asking it to use -c. Just remove all of your rules and let the defaults work for you. Rewrite the Makefile:
CC=gcc
LDLIBS=-lglut -lGLEW -lGL
ROOT=/media/programming/experiments/projectroot
VPATH=../libs:../include
CFLAGS=-I$(ROOT)/include
all: triangle
triangle: triangle.o shader_utils.o
shader_utils.o: shader_utils.h
clean:
rm -f *.o triangle
.PHONY: all clean
Related
As showed in first screenshot, my ideal AVR project structure is that:
*.o, *.elf and *.hex files are in build folder.
PomoScheler.c and pinDefines.h as main files are in root folder, while other *.c and *.h are in src folder.
But *.o are always generated at the same folder as *.c like showed in second screenshot, no matter how.
(I attached my endeavors and whole Makefile below the screenshots)
Firstly, I tried build/ before $#, in vain. The terminal still the same.
# My first Makefile endeavor
%.o: %.c $(HEADERS)
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o build/$#
# Terminal command generated by Makefile (Look at the end: *.o path still same as *.c)
avr-gcc -Os -g -std=gnu99 -Wall -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -ffunction-sections -fdata-sections -DF_CPU=1000000UL -DBAUD=9600UL -I. -I~/Developer/bin/avr8-gnu-toolchain-darwin_x86_64/avr/include -mmcu=atmega328p -c -o src/RotaryEncoder.o src/RotaryEncoder.c
Secondly, I tried to add mv $# build to explicitly move it to build folder. But nothing happened. Even echo are not displayed in Terminal.
# My second Makefile endeavor
%.o: %.c $(HEADERS)
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $#
mv $# build
echo ---------Hello---------
Thirdly, I delete $(HEADERS) and replace $< with $^ just to have a try. The mv is executed. But it cannot find *.o file this time even though I have VPATH = src:build in Makefile.
# My third Makefile endeavor
%.o: %.c
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $^ -o $#
mv $# build
# Terminal error
Assembler messages:
Fatal error: can't create build/src/RotaryEncoder.o: No such file or directory
And my whole Makefile is here. Please help me out.
# My whole Makefile
MCU = atmega328p
F_CPU = 1000000UL
BAUD = 9600UL
LIBDIR = ~/Developer/bin/avr8-gnu-toolchain-darwin_x86_64/avr/include
PROGRAMMER_TYPE = usbtiny
PROGRAMMER_ARGS =
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
AVRSIZE = avr-size
AVRDUDE = avrdude
##########------------------------------------------------------##########
VPATH = ./src:./build
TARGET = $(lastword $(subst /, ,$(CURDIR)))
SOURCES=$(wildcard *.c src/*.c $(LIBDIR)/*.c)
OBJECTS=$(SOURCES:.c=.o)
HEADERS=$(SOURCES:.c=.h)
CPPFLAGS = -DF_CPU=$(F_CPU) -DBAUD=$(BAUD) -I. -I$(LIBDIR)
CFLAGS = -Os -g -std=gnu99 -Wall
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
CFLAGS += -ffunction-sections -fdata-sections
LDFLAGS = -Wl,-Map,build/$(TARGET).map
LDFLAGS += -Wl,--gc-sections
TARGET_ARCH = -mmcu=$(MCU)
%.o: %.c $(HEADERS)
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o build/$#
$(TARGET).elf: $(OBJECTS)
$(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LDLIBS) -o build/$#
%.hex: %.elf
$(OBJCOPY) -j .text -j .data -O ihex build/$< build/$#
all: $(TARGET).hex
size: $(TARGET).elf
$(AVRSIZE) -C --mcu=$(MCU) $(TARGET).elf
clean:
rm -f $(TARGET).elf $(TARGET).hex $(TARGET).obj \
$(TARGET).o $(TARGET).d $(TARGET).eep $(TARGET).lst \
$(TARGET).lss $(TARGET).sym $(TARGET).map $(TARGET)~ \
$(TARGET).eeprom
flash: $(TARGET).hex
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$<
This is clearly not right:
OBJECTS = $(SOURCES:.c=.o)
because the object files you want to create are not foo.o etc. which is what this will expand to; the object files are build/foo.o etc. So this has to be:
OBJECTS = $(patsubst %.c,build/%.o)
All of your attempts to trick make by telling it your recipe will build one target (foo.o) but actually building a totally different target (build/foo.o) are doomed to fail, regardless of whether you have the compiler do it directly, you use mv, or any other method.
If you just tell make what your recipe actually does, you will have a much simpler time of it:
build/%.o: %.c
mkdir -p $(#D)
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $^ -o $#
Probably you have similar issues with the other rules that you want to put into other directories.
You can't do this by trying to hide it from make. Make has to know where the files actually are.
BTW, VPATH cannot help here. VPATH is for finding source files, it cannot be used for finding generated files. So you could use VPATH to find your .c files but not your .o files.
I have source files in several directories and I want to compile them in a one unique temporary directory, currently I use this target to create my object files :
$(BUILD_DIR)/%.o :
#echo "Compiling $#"
$(VERBOSE) $(CC) $(CFLAGS) -c $(DEFINES) $(INCLUDES) -o $# $(shell echo "$(SOURCES)" | sed 's/ /\n/g' | sed -nr '/\/$(*F)\.c/p')
It is working well but when I modify a source file, the object one is not recompiled. So I have to add the source file to the dependencies.
But this target doesn't work :
$(BUILD_DIR)/%.o : $(shell echo "$(SOURCES)" | sed 's/ /\n/g' | sed -nr '/\/$(*F)\.c/p')
#echo "Compiling $#"
$(VERBOSE) $(CC) $(CFLAGS) -c $(DEFINES) $(INCLUDES) -o $# $^
Is there any way to use target name in dependencies ?
Assuming you are using GNU Make...
Use a pattern rule like:
obj/%.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $# $<
to tell make that an object file obj/<name>.o is to be compiled from a source file
<name>.c
In conjunction with this, use the VPATH special variable
to inform make of directories in which it should look for any <name>.c, if it is not
in the current directory.
Also, add an order-only prerequisite
to the pattern rule to ensure that the directory (obj) to which your object files are compiled
exists when needed:
obj/%.o: %.c | obj
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $# $<
So for example, with project structure:
./
-- Makefile
-- aa/
-- main.c
-- bb/
-- foo.c
-- obj/ #<-- Compile object files in here
-- prog #<- program to be built
And:
Makefile
VPATH := aa:bb
SRCS := foo.c main.c
OBJS := $(addprefix obj/, $(SRCS:.c=.o))
.PHONY: all clean
all: prog
prog: $(OBJS)
$(CC) $(LDFLAGS) -o $# $^ $(LDLIBS)
obj/%.o: %.c | obj
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $# $<
obj:
mkdir $#
clean:
$(RM) $(OBJS) prog
the build runs like:
$ make
cc -c -o obj/foo.o bb/foo.c
cc -c -o obj/main.o aa/main.c
cc -o prog obj/foo.o obj/main.o
I have the following structure for a project and I am just starting to introduce a Makefile to build the software:
├── Makefile
├── README.md
├── cg
│ └── cg.c
└── utilities
├── utilities.c
└── utilities.h
I am trying to put object files in a directory called obj yet I can't seem to get it working.
My makefile looks like:
CC=mpicc
CFLAGS=-O3 -std=c99
LIBS=
MKDIR_P = mkdir -p
make_build_dir:
#mkdir -p obj/
utilities.o: utilities/utilities.c
$(CC) $(CFLAGS) -o ./obj/$# -c $<
cg.o: cg/cg.c
$(CC) $(CFLAGS) -o ./obj/$# -c $<
.PHONY: make_build_dir
cg.exe: make_build_dir utilities.o cg.o
$(CC) $(CFLAGS) -o $# $<
clean:
rm -fr obj
rm cg.exe
Yet this generates the following error:
a#a:b/b ‹master*›$ make cg.exe
mpicc -O3 -std=c99 -o ./obj/utilities.o -c utilities/utilities.c
mpicc -O3 -std=c99 -o ./obj/cg.o -c cg/cg.c
cg/cg.c:133:3: warning: implicit declaration of function 'decompose' is invalid in C99
[-Wimplicit-function-declaration]
decompose(num_chunks, chunks_per_rank,me, &settings);
^
1 warning generated.
mpicc -O3 -std=c99 -o cg.exe make_build_dir
clang: error: no such file or directory: 'make_build_dir'
make: *** [cg.exe] Error 1
How can I get it to generate the object files in the obj directory and then an executable in the top-level directory?
This linking part of the makefile
cg.exe: make_build_dir utilities.o cg.o
$(CC) $(CFLAGS) -o $# $<
has two issues. First, $< refers to the first prerequesite of the target cg.exe, and that is make_build_dir. Declaring it as .PHONY doesn't help here, it's simply passed to $(CC). Second, utilities.o cg.o both don't exist at this location. You can change the rule to
cg.exe: obj/utilities.o obj/cg.o
$(CC) $(CFLAGS) -o $# $^
Note the automatic variable $^ which refers to all prerequisites. Additionally, the object file targets should be
obj/cg.o: cg/cg.c
$(CC) $(CFLAGS) -o $# -c $<
(identical for utilities.o).
First of all, you need to make_build_dir before making any *.o or make won't have a place to put them.
And you can make the Makefile more generic.
.PHONY: all clean info
.DEFAULT_GOAL := all
SRC_DIRS = cg utilities
OBJ_DIR = obj
EXE = cg.exe
SOURCES = $(foreach path, $(SRC_DIRS), $(wildcard $(path)/*.c))
OBJECTS = $(addprefix $(OBJ_DIR)/, $(notdir $(SOURCES:%.c=%.o)))
$(OBJ_DIR)/%.o: */%.c
$(CC) $(CFLAGS) -o $# -c $<
all: make_build_dir $(EXE)
info:
$(info SOURCES=$(SOURCES))
$(info OBJECTS=$(OBJECTS))
make_build_dir:
#mkdir -p $(OBJ_DIR)
$(EXE): $(OBJECTS)
$(CC) $(CFLAGS) -o $# $^
With this Makefile, you can add more source directories to SRC_DIRS and it will automatically compile sources in them.
What does it do? Run make with the -n option to see:
$ make -n
mkdir -p obj
cc -o obj/cg.o -c cg/cg.c
cc -o obj/utilities.o -c utilities/utilities.c
cc -o cg.exe obj/cg.o obj/utilities.o
You can also display the info on the variables by:
$ make info
SOURCES= cg/cg.c utilities/utilities.c
OBJECTS=obj/cg.o obj/utilities.o
I have the following directory structure:
root-----Makefile
|-----src #all source files here.
|-----obj #all object files here.
|-----bin #the final target.
The contents of Makefile is given below:
TARGET = exec
CC = gcc
CFLAGS = -g -I.
LINKER = gcc -o
LFLAGS = -I. -lm -lpthread
BINDIR = bin
OBJDIR = obj
SRCDIR = src
INTERFACE = interface
STD = -std=c99
PROGRAMSOURCES := $(wildcard $(SRCDIR)/*.c)
PROGRAMINTERFACE:= $(wildcard $(INTERFACE)/*.h)
OBJECTS := $(PROGRAMSOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
$(BINDIR)/$(TARGET) : $(OBJECTS)
$(LINKER) $# $(LFLAGS) $(OBJECTS) $(STD)
#pull the dependencies to the .o files
-include $(OBJECTS:.o=.d)
$(OBJECTS) : $(OBJDIR)/%.o :$(SRCDIR)/%.c
$(CC) $(CFLAGS) -c $< -o $# $(STD)
$(CC) $(CFLAGS) -MM $< > $*.d
#mv -f $*.d $*.d.tmp
#sed -e 's|.*:|$(OBJDIR)/$*.o:|' < $*.d.tmp > $*.d
#sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | \
sed -e 's/^ *//' -e 's/$$/:/' >> $*.d`
#rm -f $*.d.tmp`
.PHONY : run
run :`
./$(BINDIR)/$(TARGET) ${TYPE} ${INP_FILE}
I have used the tutorial here have been modified to suit the corresponding directory structure. But something has got wrong in the modification and I cannot understand what. The dependency list generated in the .d files is not taken into account i.e. if I change a .h the rules are not compiling.
You appear to be producing the dependency files in root/, but looking for them in obj/.
Try changing this:
-include $(OBJECTS:.o=.d)
to this:
-include *.d
There are other improvements you can make, once the makefile is working.
EDIT: further improvements
1) The choice of where to put the dependency files is mainly arbitrary, but if we put them in obj/, we can simplify the $(OBJECTS) rule quite a lot:
-include $(OBJDIR)/*.d
$(OBJECTS): $(OBJDIR)/%.o :$(SRCDIR)/%.c
$(CC) $(CFLAGS) -MMD -MP -c $< -o $# $(STD)
2) PROGRAMINTERFACE and INTERFACE aren't used, so we can remove them.
3) Putting -o in LINKER like that is dangerous. And don't forget the automatic variable $^:
LINKER = gcc
$(BINDIR)/$(TARGET) : $(OBJECTS)
$(LINKER) $# $(LFLAGS) $^ $(STD)
4) It would be wise to give run a prerequisite:
run: $(BINDIR)/$(TARGET)
./$< ${TYPE} ${INP_FILE}
There is a given r-tree code by Toni Guttman(it's been modified for my homework), however, if I change an parameter(the dimension of the node), then "make" will cause such errors:
yacc y.spec
make: yacc:command not found
make: *** [y.tab.c] error 127
I've installed bison and flex, and "which yacc" shows that
alias yacc='bison'
/usr/bin/bison
What should I do to solve the problem?
Here is the "Makefile":
# %W% %G%
# use flag -O for optimized code, slower compile
FLAGS=
SRC= main.c index.c newtid.c node.c rectangle.c \
printstats.c clock.c y.spec allocate.c error.c\
split.l.c \
split.q.c \
split.e.c
HEADERS= options.h macros.h index.h assert.h
ALL= $(SRC) $(HEADERS) split.l.h split.q.h split.e.h
OBJ= main.o index.o newtid.o node.o rectangle.o \
printstats.o clock.o y.tab.o allocate.o error.o
OBJLIN= split.l.o
OBJQ= split.q.o
OBJEXP= split.e.o
$(OBJ): $(HEADERS)
$(OBJLIN): $(HEADERS) split.l.h
$(OBJQ): $(HEADERS) split.q.h
$(OBJEXP): $(HEADERS) split.e.h
# assembler chokes if graphics.c is compiled with -g option, do it without.
# graphics.o: graphics.c $(HEADERS)
# cc -c graphics.c
# assembler chokes if y.tab.c is compiled with -g option, do it without.
# y.tab.o: y.tab.c $(HEADERS)
# cc -c y.tab.c
.c.o: $(HEADERS)
cc -c $(FLAGS) $*.c
linear: $(OBJ) $(OBJLIN)
cc $(FLAGS) $(OBJ) $(OBJLIN) -lm -o linear
quad: $(OBJ) $(OBJQ)
cc $(FLAGS) $(OBJ) $(OBJQ) -lm -o quad
exp: $(OBJ) $(OBJEXP)
cc $(FLAGS) $(OBJ) $(OBJEXP) -lm -o exp
y.tab.c: y.spec $(HEADERS)
yacc y.spec
edit:
sccs edit $(SRC) $(HEADERS) split.l.h split.q.h split.o.h
unedit:
sccs unedit $(ALL)
rm -f tags
delta:
sccs delta $(ALL)
rm -f tags
get:
sccs get $(ALL)
clean:
rm -f *.o core y.tab.c tags
tags: $(SRC)
ctags *.c
lint:
rm -f lint.out
lint *.c > lint.out
You don't have yacc installed, as you've seen. Changing an alias in your shell won't help, because it's make that is trying to run the yacc command, not the shell. You have to edit your makefile, and add a line like:
YACC = bison -y
(the -y flag makes bison behave like yacc)
Since you didn't show your actual makefile we can't be sure that this will do it, but it's likely.
EDIT:
I your makefile above, change the reference to yacc to say bison -y instead.
Your makefile is not following many best practices but that's for another day.
manually add this script /usr/bin/yacc is simply a script containing:
#! /bin/sh
exec '/usr/bin/bison' -y "$#"