I have just started learning make and I am having some trouble. I want to create an executable called sortfile. Here are the relevant files: sortfile.c fileio.c fileio.h
Both sortfile.c and fileio.c use fileio.h.
Here is my makefile:
1 CC = gcc
2 CFLAGS = -g -Wall
3
4 default: sortfile
5
6 sortfile: sortfile.o fileio.o $(CC) $(CFLAGS) -o sortfile sortfile.o fileio.o
7
8 sortfile.o: sortfile.c fileio.h $(CC) $(CFLAGS) -c sortfile.c
9
10 fileio.o: fileio.c fileio.h $(CC) $(CFLAGS) -c fileio.c
11
12 clean:
13 $(RM) sortfile *.o*~
I am getting the following error:
make: *** No rule to make target `gcc', needed by `sortfile.o'. Stop.
Makefiles are of the format:
target: dependency1 dependency2
rule (command to build)
You listed the command as the set of dependencies, so make wants to try to build gcc before it can expect sortfile.o to be satisfied.
Instead of:
sortfile.o: sortfile.c fileio.h $(CC) $(CFLAGS) -c sortfile.c
you need:
sortfile.o: sortfile.c fileio.h
$(CC) $(CFLAGS) -c sortfile.c
Note that normally all you really want here is something much simpler:
CFLAGS+=-g -Wall
all: sortfile
sortfile: sortfile.o fileio.o
This brief Makefile will work as expected with GNU Make because of implicit rules (see also).
Related
Iam working with gcc and MinGW on a Windows platform. I have a directory containing two *.c files:
main.c and funcs.c
I am using the following makefile:
CC=gcc
CFLAGS=-c
LDFLAGS=
SOURCEDIR = src
BUILDDIR = build
SOURCES=$(wildcard $(SOURCEDIR)/*.c)
OBJECTS=$(patsubst $(SOURCEDIR)/%.c,$(BUILDDIR)/%.o,$(SOURCES))
LIBRARIES=-L/mingw64/lib
INC= -I./include
EXECUTABLE=testLink
VPATH = src include build
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) $(LIBRARIES) -o ./dist/$#
$(OBJECTS): $(SOURCES)
$(CC) $(INC) $(CFLAGS) $< -o $#
Which should take the *.c files and generate *.o files with the same name. However I get the following output on make -
$ make
gcc -I./include -c src/funcs.c -o build/funcs.o
gcc -I./include -c src/funcs.c -o build/main.o
gcc build/funcs.o build/main.o -L/mingw64/lib -o ./dist/testLink
followed of course by a bunch of multiple definition errors. As you can see from the first two lines it is taking the same *.c file and compiling it twice into two different *.o files.
I am new to makefiles but I assume it is something wrong with my $(OBJECTS) rule and I'm pretty sure it's the $< which is causing the problem. I'm trying to create a generic makefile which will always work on my projects which have the same directory structure and take .c files turn them into .o files and link. Am I going about this entirely the wrong way or is there a simple fix to my makefile?
Thanks!
James
This rule:
$(OBJECTS): $(SOURCES)
$(CC) $(INC) $(CFLAGS) $< -o $#
expands to:
funcs.o main.c: funcs.c main.c
$(CC) $(INC) $(CFLAGS) $< -o $#
which is equivalent to:
funcs.o: funcs.c main.c
$(CC) $(INC) $(CFLAGS) $< -o $#
main.o: funcs.c main.c
$(CC) $(INC) $(CFLAGS) $< -o $#
$< refers to the first dependency (funcs.c) so your Makefile is trying to generate both funcs.o and main.o from the same source.
You just want a generic rule using % wildcard matching:
%.o: %.c
$(CC) $(INC) $(CFLAGS) $< -o $#
See https://www.gnu.org/software/make/manual/html_node/Pattern-Rules.html
Jeff pointed the mistake in his answer (all objects depend on all sources: that isn't a generic compilation rule for c sources).
However, the generic rule must have source & object paths. To sum it up, just replace
$(OBJECTS): $(SOURCES)
$(CC) $(INC) $(CFLAGS) $< -o $#
by
$(BUILDDIR)/%.o : $(SOURCEDIR)/%.c
$(CC) $(INC) $(CFLAGS) $< -o $#
(as explained in How to generate a Makefile with source in sub-directories using just one makefile)
note that this kind of dependency test doesn't take included .h files into account, so it's only intended for first builds. Modifying .h files afterwards doesn't trigger a compilation since the header files are not listed as dependencies.
I have a project with the following structure:
- main1.c
- main2.c
- main3.c
- lib.h
- lib.c
All the mains use the import lib.
How can I write a Makefile that creates 3 executables (one per each main)?
First Approach
I created a Makefile that does that, but you'd need to append the name of the executable after calling the make command (i.e. make main1, make main2, etc), However if I try using only make (without arguments), it only makes the first main (main1).
CC=gcc
CFLAGS=-g -O2 -Wall
LDFLAGS=-framework OpenCL
DEPS=lib.h
OBJS=main1.o main2.o main3.o
%.o: %.c $(DEPS)
$(CC) $(CFLAGS) -c -o $# $<
main1: lib.o main1.o
$(CC) $(CFLAGS) -o $# $^
main2: lib.o main2.o
$(CC) $(CFLAGS) -o $# $^
main3: lib.o main3.o
$(CC) $(CFLAGS) -o $# $^ $(LDFLAGS)
clean:
rm -f *.o main1 main2 main3
Makefile
https://www.gnu.org/software/make/manual/html_node/Goals.html
By default, the goal is the first target in the makefile (not counting
targets that start with a period). Therefore, makefiles are usually
written so that the first target is for compiling the entire program
or programs they describe.
So just add the below line as the first target in your makefile:
all: main1 main2 main3
so I have finished a big C project in eclipse and I did this by right clicking my C project folder -> properties -> C/C++ Build -> Settings -> GCC C Compiler and putting the flags
-c -std=c99
And everything is passing when I build and run my program in ECLIPSE.
Now when I move my project over to linux version:
[ubuntu#ip-172-31-25-10:~/Desktop/Fall_2013/MIPSAssembler]$gcc --version
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
and run the following Makefile:
#
# Makefile to build the MIPS assembler
#
# DIRECTIONS: In the same folder that this folder is
# in type to the command line "Makefile"
CC = gcc
CFLAGS = -O -std=c99
OBJECTS = CUnit.o VariableVector.o preprocessor.o utilities.o parser.o assembler.o \
variableVectorTest.o preprocessorTest.o utilitiesTest.o parserTest.o assemblerTest.o
# Build for full program
assembler: $(OBJECTS)
$(CC) $(CFLAGS) -o assemble $(OBJECTS)
# Rules for components
CUnit.o: CUnit.c CUnit.h
$(CC) $(CFLAGS) -c CUnit.c
VariableVector.o: VariableVector.c VariableVector.h
$(CC) $(CFLAGS) -c VariableVector.c
preprocessor.o: preprocessor.c preprocessor.h
$(CC) $(CFLAGS) -c preprocessor.c
utilities.o: utilities.c utilities.h VariableVector.o
$(CC) $(CFLAGS) -c utilities.c
parser.o: parser.c parser.h utilities.o
$(CC) $(CFLAGS) -c parser.c
assembler.o: assembler.c assembler.h VariableVector.o
$(CC) $(CFLAGS) -c assembler.c
variableVectorTest.o: variableVectorTest.c variableVectorTest.h
$(CC) $(CFLAGS) -c variableVectorTest.c
preprocessorTest.o: preprocessorTest.c preprocessorTest.h CUnit.o
$(CC) $(CFLAGS) -c preprocessorTest.c
utilitiesTest.o: utilitiesTest.c utilitiesTest.h utilities.o
$(CC) $(CFLAGS) -c utilitiesTest.c
parserTest.o: parserTest.c parserTest.h VariableVector.o
$(CC) $(CFLAGS) -c parserTest.c
assemblerTest.o: assemblerTest.c assemblerTest.h
$(CC) $(CFLAGS) -c assemblerTest.c
clean:
rm -rf *.o
everything compiles but when I run my tests by typing
./assemble // I get some seg faults!!!
I was wondering why is my code working in ECLIPSE but not working in LINUX running gcc and how can I make it so that my eclipse compiling matches how I am compiling my files using gcc on linux? Thanks!
I have a root directory and a child directory. I am planning to put the functions in child directory under libfunc.o
This libfunc.o should be merged along with other object files in top directory. But I am getting error:
$make all
cd folder; make libfunc.o
make[1]: Entering directory `/home/Work/test_makefile/folder'
cc -c -o func2.o func2.c
cc -c -o func3.o func3.c
func3.c: In function ‘set’:
func3.c:3:25: warning: initialization makes pointer from integer without a cast [enabled by default]
ld -r -o libfunc.o func2.o func3.o
make[1]: Leaving directory `/home/Work/test_makefile/folder'
arm-linux-gnueabi-gcc -c -o hellofun.o hellofun.c -I. -I./include
arm-linux-gnueabi-gcc -c -o hellomake.o hellomake.c -I. -I./include
arm-linux-gnueabi-gcc hellofun.o hellomake.o folder/libfunc.o -o hm
folder/libfunc.o: file not recognized: File format not recognized
collect2: ld returned 1 exit status
make: *** [hm] Error 1
Makefiles: toplevel
1 CC=arm-linux-gnueabi-gcc
2 LD=arm-linux-gnueabi-ld
3 AR=arm-linux-gnueabi-ar
4 CFLAGS=-I. -I./include
5 SOURCES=hellofun.c hellomake.c
6 OBJECTS=$(SOURCES:.c=.o)
7 SUBDIR_OBJS=folder/libfunc.o
8 TARGET=hm
9 DEPS = hellomake.h
10
11 %.o: %.c $(DEPS) $(SUBDIR_OBJS)
12 $(CC) -c -o $# $< $(CFLAGS)
13
14 folder/libfunc.o:
15 cd folder; $(MAKE) libfunc.o
16
17 clean:
18 rm -rf *.o hellomake folder/*.o
19
20 all: $(SOURCES) $(TARGET)
21
22 $(TARGET): $(OBJECTS)
23 $(CC) $(OBJECTS) $(SUBDIR_OBJS) -o $#
24
Makefile : Child
1 SOURCES=$(wildcard *.c)
2 OBJECTS=$(SOURCES:.c=.o)
3 TARGET=libfunc.o
4 %.o: %.c
5 $(CC) -c -o $# $< $(CFLAGS)
6
7 clean:
8 rm -rf *.o
9
10
11 $(TARGET): $(OBJECTS)
12 $(if $(strip $(OBJECTS)),\
13 $(LD) $(LDFLAGS) -r -o $# $(OBJECTS),\
14 rm -f $#; $(AR) rcs $# )
~
~
~
There's more than one error here. First, when asking questions please always provide the complete error message. The no rule to make target error will print out which target it's trying to make; that's critical information for helping you.
Second, you reference a variable SUBDIR_OBJS, but that's never defined. Plus you list that as a prerequisite for building other object files in the %.o : %.c rule: it's virtually never correct to list object files as prerequisites of other object files.
The top-level makefile does not run make in the folder directory, so no commands in that directory will be run automatically. You'll have to go there and run make yourself by hand.
Also in config.mk you create a variable merge_object but in folder/Makefile you refer to a variable merge_objects, which is not the same variable.
I missed export CC in root makefile
I would suggest put on the -Wall option in your compiler options, so that you can have a better debug view of your compiling process.
The output ld -r -o libfunc.o func2.o func3.o seems suspicious to me. Looks like The system used default linker rather than your cross-compile linker, which is arm-linux-gnueabi-ld. That might be a reason for the file not recognized.
As the error was file format not recognized, maybe you can check file libfunc.o output?
If you are having with LD, why not skip it and try other methods, like just gcc -o hm with all object files, or use ar to package the objects in subfolder.
gcc 4.7.2
c89
GNU Make 3.82
I am trying compile this program I have using this Makefile. I have only 1 src file at the moment, but I will have more later to include.
I am trying to get the Makefile to create the bin directory if it doesn't exist and put the binary executable in there.
INC_PATH=-I/home/dev_tools/apr/include/apr-1
LIB_PATH=-L/home/dev_tools/apr/lib
LIBS=-lapr-1
RUNTIME_PATH=/home/dev_tools/apr/lib
CC=gcc
CFLAGS=-Wall -Wextra -g -m32 -D_DEBUG -D_THREAD_SAFE -D_REENTRANT -D_LARGEFILE64_SOURCE -O2 $(INC_PATH)
OBJECTS=timeout.o
EXECUTABLE=bin/to
all: build $(EXECUTABLE)
$(EXECUTABLE):
$(CC) -m32 -o $# -Wl,-rpath,$(RUNTIME_PATH), $(LIB_PATH) $(OBJECTS) $(LIBS)
build:
#mkdir -p bin
clean:
rm -rf *~ timeout *.o
I am getting this error:
make
gcc -m32 -o bin/to -Wl,-rpath,/home/dev_tools/apr/lib, -L/home/dev_tools/apr/lib timeout.o -lapr-1
gcc: error: timeout.o: No such file or directory
make: *** [bin/to] Error 1
When I remove the $(OBJECTS) I get the following:
gcc -m32 -o bin/to -Wl,-rpath,/home/dev_tools/apr/lib, -L/home/dev_tools/apr/lib -lapr-1
/usr/bin/ld: cannot find : No such file or directory
collect2: error: ld returned 1 exit status
make: *** [bin/to] Error 1
Not sure where I am going wrong with this.
You have not specified how to build the target timeout.o.
You need to add the following code:
timeout.o: timeout.c
$(CC) $(CFLAGS) -c -o $# $<
If you end up with more source file that you need compiled, you can use a pattern matching rule like this:
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
Makefiles can be a bit tricky. Because you want to continue adding more objects to your OBJECT variable, I would actually add a prerequisite to EXECUTABLE to make sure all of your objects are compiled. From there, the automatic rule inference should take care of the rest.
Basically replace the line with:
$(EXECUTABLE): $(OBJECTS)
$(CC) -m32 -o $# -Wl,-rpath,$(RUNTIME_PATH), $(LIB_PATH) $(OBJECTS) $(LIBS)
Its showing error because make is not able to find timeout.o file in the current directory.
If you have timeout.c file then add the following to your makefile
OBJECTS: timeout.c
$(CC) -c timeout.c