I wrote a Makefile to compile the files and output the file "main", which I will eventually execute by "./main". Below is my Makefile:
CXX=clang++
CXXFLAGS=-g -std=c++11 -Wall -pedantic
BIN=prog
SRC=$(wildcard *.cpp)
OBJ=$(SRC:%.cpp=%.o)
all: Student_info median grade main
main: main.cpp
$(CXX) $(CXXFLAGS) main.cpp -o main grade.o median.o Student_info.o
grade: grade.h grade.cpp
$(CXX) $(CXXFLAGS) grade.cpp -o grade.o
median: median.h median.cpp
$(CXX) $(CXXFLAGS) median.cpp -o median.o
Student_info: Student_info.h Student_info.cpp
$(CXX) $(CXXFLAGS) Student_info.cpp -o Student_info.o
clean:
rm -f *.o
rm -f main
However, it says
clang++ -g -std=c++11 -Wall -pedantic Student_info.cpp -o Student_info.o
Undefined symbols for architecture x86_64:
"_main", referenced from:
implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [Student_info] Error 1
What is wrong with my Makefile?
Student_info: Student_info.h Student_info.cpp
$(CXX) $(CXXFLAGS) Student_info.cpp -o Student_info.o
Looks like you want this to compile to an object file - without linking. To do this, you need to pass -c. Also, the name of the target should be Student_info.o:
Student_info.o: Student_info.h Student_info.cpp
$(CXX) $(CXXFLAGS) -c Student_info.cpp -o Student_info.o
Ditto for grade and median.
main should depend on not only main.cpp but also the object files you are linking it with:
main: main.cpp Student_info.o grade.o median.o
$(CXX) $(CXXFLAGS) main.cpp -o main grade.o median.o Student_info.o
Related
I use this Makefile to build a small C++ application:
BIN_CPP=Main
CPP=g++
INCLUDES_APR=/usr/local/apr/include/apr-1
LIB_SRC = $(wildcard My*.cpp)
LIB_OBJ = $(LIB_SRC:.cpp=.o)
RM=rm
all: Main
MyClass.o: MyClass.cpp
$(CPP) -I$(INCLUDES_APR) -c $< -o $#
MyModel.o: MyModel.cpp
$(CPP) -I$(INCLUDES_APR) -c $< -o $#
libMyLibrary.so: $(LIB_OBJ)
$(CPP) -fPIC -shared -o $# $^
Main.o: Main.cpp
$(CPP) -o $# -c $^ -I$(INCLUDES_APR)
Main: libMyLibrary.so Main.o
$(CPP) $^ -o $# -L/usr/local/apr/lib -L. -lapr-1 -lMyLibrary
.PHONY: clean
clean:
$(RM) -f *.o *.so $(BIN_CPP)
When I remove then first two targets and extend the libMyLibrary.so one, it fails:
# MyClass.o: MyClass.cpp
# $(CPP) -I$(INCLUDES_APR) -c $< -o $#
# MyModel.o: MyModel.cpp
# $(CPP) -I$(INCLUDES_APR) -c $< -o $#
libMyLibrary.so: $(LIB_OBJ)
$(CPP) -fPIC -shared -o $# $^ -I$(INCLUDES_APR)
and the error message is this:
g++ -c -o MyClass.o MyClass.cpp
In file included from MyClass.cpp:1:
MyClass.hpp:3:10: fatal error: apr_general.h: No such file or directory
3 | #include <apr_general.h>
| ^~~~~~~~~~~~~~~
compilation terminated.
make: *** [<builtin>: MyClass.o] Error 1
The -I$(INCLUDES_APR) is missing from the automake output. What is wrong with this build file?
By removing the explicit rules, you are relying on GNU make's built-in rules to compile your files, which is good. But GNU make's built-in rules can't possibly know about your local variable INCLUDES_APR, so when it compiles the source files that variable is not used.
You should add the -I flag to the standard variable CPPFLAGS (the "CPP" here stands for "C preprocessor", not "C++"), which is what make uses to compile in its built-in rules.
Example:
BIN_CPP=Main
CPP=g++
INCLUDES_APR=/usr/local/apr/include/apr-1
CPPFLAGS=-I$(INCLUDES_APR)
LIB_SRC = $(wildcard My*.cpp)
LIB_OBJ = $(LIB_SRC:.cpp=.o)
RM=rm
all: Main
libMyLibrary.so: $(LIB_OBJ)
$(CPP) -fPIC -shared -o $# $^
Main: Main.o libMyLibrary.so
$(CPP) $< -o $# -L/usr/local/apr/lib -L. -lapr-1 -lMyLibrary
.PHONY: clean
clean:
$(RM) -f *.o *.so $(BIN_CPP)
Possible make output
g++ -I/usr/local/apr/include/apr-1 -c -o Main.o Main.cpp
g++ -I/usr/local/apr/include/apr-1 -c -o MyClass.o MyClass.cpp
g++ -I/usr/local/apr/include/apr-1 -c -o MyModel.o MyModel.cpp
g++ -fPIC -shared -o libMyLibrary.so MyClass.o MyModel.o
g++ Main.o -o Main -L/usr/local/apr/lib -L. -lapr-1 -lMyLibrary
I received this sample makefile from my professor and I'm trying to run it on Ubuntu but the commands I'm typing won't run it. All the files in the makefile already exist and when I type make, it makes the files but the actual program doesn't run. I have tried to type ./a.out but that doesn't run it either. Please help me with what command to type for the program to run.
# Makefile for Library Management System
CXXFLAGS += --std=c++11
all: div main
rebuild: div clean main
debug: CXXFLAGS += -g
debug: rebuild
main: main.o controller.o view.o library.o publication.o
$(CXX) $(CXXFLAGS) -o lms main.o controller.o view.o library.o publication.o
main.o: main.cpp *.h
$(CXX) $(CXXFLAGS) -c main.cpp
controller.o: controller.cpp *.h
$(CXX) $(CXXFLAGS) -c controller.cpp
test_view: test_view.o controller.o view.o library.o publication.o
$(CXX) $(CXXFLAGS) -o test_view test_view.o controller.o view.o library.o publication.o
test_view.o: test_view.cpp view.h publication.h library.h
$(CXX) $(CXXFLAGS) -c test_view.cpp
test_library: test_library.o library.o publication.o
$(CXX) $(CXXFLAGS) -o test_library test_library.cpp library.o publication.o
test_library.o: test_library.cpp *.h
$(CXX) $(CXXFLAGS) -c test_library.cpp
library.o: library.cpp *.h
$(CXX) $(CXXFLAGS) -c library.cpp
test_publication: test_publication.o publication.o
$(CXX) $(CXXFLAGS) -o test_publication test_publication.o publication.o
test_publication.o: test_publication.cpp *.h
$(CXX) $(CXXFLAGS) -c test_publication.cpp
publication.o: publication.cpp *.h
$(CXX) $(CXXFLAGS) -c publication.cpp
clean:
-rm -f *.o lms test_age test_genre test_media test_publication test_library test_view test_view_actual.txt
div:
#echo
#echo 'X-X-X-X-X-X-X-X-X-X-X-X-X-X-X-X-'
#echo '-X-X-X-X-X-X-X-X-X-X-X-X-X-X-X-X'
#echo 'X-X-X-X-X-X-X-X-X-X-X-X-X-X-X-X-'
#echo '-X-X-X-X-X-X-X-X-X-X-X-X-X-X-X-X'
#echo
Is there a file called 'lms'? Try running: ./lms
The things in the makefile after '-o' specify the output filenames. These are the programs you can run.
The job of make is to build the program, not run it, so the makefile is probably working just fine.
You can see from the line:
all: div main
that the makefile will try to build div and main by default.
There is a rule for div that just prints things to the console:
div:
#echo
#echo 'X-X-X-X-X-X-X-X-X-X-X-X-X-X-X-X-'
#echo '-X-X-X-X-X-X-X-X-X-X-X-X-X-X-X-X'
#echo 'X-X-X-X-X-X-X-X-X-X-X-X-X-X-X-X-'
#echo '-X-X-X-X-X-X-X-X-X-X-X-X-X-X-X-X'
#echo
as noted in the comments of the other answer, the rule for main has the flag to gcc -o lms so the actual output executable name will be lms.
You should really tell your professor that is is bad form, since a makefile is supposed to build a file with the same name as it's rule. (ie make main should build a file called main) Feel free to point him here if he disagrees.
When I try this;
VPATH= ./src
CXXFLAGS= -I "./include"
program: ListNode.o LinkedList.o TreeNode.o Tree.o Test.o
g++ lib\ListNode.o lib\LinkedList.o lib\TreeNode.o lib\Tree.o lib\Test.o -o bin\program
ListNode.o: ListNode.cpp
g++ -c $(CXXFLAGS) $< -o lib\ListNode.o
LinkedList.o: LinkedList.cpp
g++ -c $(CXXFLAGS) $< -o lib\LinkedList.o
TreeNode.o: TreeNode.cpp
g++ -c $(CXXFLAGS) $< -o lib\TreeNode.o
Tree.o: Tree.cpp
g++ -c $(CXXFLAGS) $< -o lib\Tree.o
Test.o: Test.cpp
g++ -c $(CXXFLAGS) $< -o lib\Test.o
clean:
del *.exe
del *.o
It all works without any problem.But for my homework I have to create a static library.Anyway when I add this command to the makefile;
VPATH= ./src
CXXFLAGS= -I "./include"
program: ListNode.o LinkedList.o TreeNode.o Tree.o Test.o
g++ lib\ListNode.o lib\LinkedList.o lib\TreeNode.o lib\Tree.o lib\Test.o -o bin\program
ListNode.o: ListNode.cpp
g++ -c $(CXXFLAGS) $< -o lib\ListNode.o
LinkedList.o: LinkedList.cpp
g++ -c $(CXXFLAGS) $< -o lib\LinkedList.o
TreeNode.o: TreeNode.cpp
g++ -c $(CXXFLAGS) $< -o lib\TreeNode.o
Tree.o: Tree.cpp
g++ -c $(CXXFLAGS) $< -o lib\Tree.o
Test.o: Test.cpp
g++ -c $(CXXFLAGS) $< -o lib\Test.o
clean:
del *.exe
del *.o
libclass.a: ListNode.o LinkedList.o
ar -rcs libclass.a lib\ListNode.o lib\LinkedList.o
It doesn't do anything.There is no file or there is no error.Its like it doesn't exist :/
By the way I think it'd be good to mention about that if I use first makefile and then I put this code on terminal;
ar -rcs libclass.a lib\*.o
It works like magic i mean perfectly.So I need a little bit help cuz I'm about to go insane.Any help would be appreciated.
Add:
all: program libclass.a
to the beginning of your makefile. By default, make builds only the first target it finds in your makefile. This declares a fake target named "all" that depends on "program" and "libclass.a", so make ends up building both.
i have a simple Makefile:
CC=g++
CFLAGS= -Wall -std=c++11 -M -MF dependencyFileName.d -c
objects = Table.o LimitedTable.o aDimension.o test.o
edit: $(objects)
g++ -o edit $(objects)
test.o: LimitedTable.o Table.o aDimension.o test.cpp
$(CC) $(CFLAGS) test.cpp -o test.o
LimitedTable.o: LimitedTable.cpp LimitedTable.hpp Table.o aDimension.o
$(CC) $(CFLAGS) LimitedTable.cpp -o LimitedTable.o
aDimension.o: aDimension.cpp aDimension.cpp Table.o
$(CC) $(CFLAGS) aDimension.cpp -o aDimension.o
Table.o: Table.cpp Table.hpp
$(CC) $(CFLAGS) Table.cpp -o Table.o
clean:
rm -f *.o
and I get this error:
marius#marius-Lenovo-Y50-70 ~/Documents $ make clean
rm -f *.o
marius#marius-Lenovo-Y50-70 ~/Documents $ make edit
g++ -Wall -std=c++11 -M -MF dependencyFileName.d -c Table.cpp -o Table.o
g++ -Wall -std=c++11 -M -MF dependencyFileName.d -c aDimension.cpp -o aDimension.o
g++ -Wall -std=c++11 -M -MF dependencyFileName.d -c LimitedTable.cpp -o LimitedTable.o
g++ -Wall -std=c++11 -M -MF dependencyFileName.d -c test.cpp -o test.o
g++ -o edit Table.o LimitedTable.o aDimension.o test.o
Table.o: file not recognized: File truncated
collect2: error: ld returned 1 exit status
make: *** [edit] Error 1
Can anyone tell me what is wrong ?
Could a wrong include in one of the files be a reason for this error ?
There are some problems with the way you handle your dependency file, but first:
I have a simple Makefile
No you don't. The amount of boilerplate code is way too high, and adding any file to your projet will require you to manually edit that makefile again.
Your Makefile should be boiled down to this:
SRC := $(wildcard *.cpp)
OBJ := $(SRC:.cpp=.o)
DEP := $(OBJ:.o=.d)
CPPFLAGS := -MMD -MP
CXXFLAGS := -std=c++11 -Wall
edit: $(OBJ)
$(CXX) $^ -o $#
-include $(DEP)
clean:
$(RM) $(OBJ) $(DEP)
Here you :
avoid repeating yourself too much,
make good use of make's implicit rules to save time,
use the right built-in variables instead of overriding the wrong ones,
correctly handle dependency files creation and actually use them to prevent manual recompilation,
won't need to edit the makefile when adding a .cpp or .hpp file to your project.
Also, that should fix your problem. Don't forget to clean before trying to compile again after such an error ("file truncated") occurred.
I have 4 '.cpp' files and 1 header files:
Tools.cpp
Code1.cpp
Code2.cpp
Code3.cpp
and Tools.hh
Now all Code1.cpp, Code2.cpp, Code3.cpp
use functions stored in Tools.cpp.
Currently, what I do to compile all of them is using
this simple shell script:
#!/bin/bash
echo "compiling Code1.cpp";
g++ Code1.cpp Tools.cpp -o Code1
echo "compiling Code2.cpp";
g++ Code2.cpp Tools.cpp -o Code2
echo "compiling Code3.cpp";
g++ Code3.cpp Tools.cpp -o Code3
It all works fine.
Now I want to do that using a standard makefile.
But why this doesnt' work:
CXX = g++
TOOLSRC = Tools.cpp Code1.cpp Code2.cpp \
Code3.cpp
TOOLSINC = Tools.hh
all: Code1 Code2 Code3
Code1: $(TOOLSRC) $(TOOLSINC) makefile
$(CXX) $^ -o $#
Code2: $(TOOLSRC) $(TOOLSINC) makefile
$(CXX) $^ -o $#
Code3: $(TOOLSRC) $(TOOLSINC) makefile
$(CXX) $^ -o $#
The error I got is this:
ld: warning in makefile, file is not of required architecture
ld: duplicate symbol neighbors(std::vector<int, std::allocator<int> >&, int, int)in /var/folders/Yx/YxKmmyVPGpakdPL4St7X6++++TI/-Tmp-//ccQCrGHe.o and /var/folders/Yx/YxKmmyVPGpakdPL4St7X6++++TI/-Tmp-//ccreq9YU.o
collect2: ld returned 1 exit status
make: *** [FindNeighbours] Error 1
How can I correct the mistakes?
In these targets:
Code1: $(TOOLSRC) $(TOOLSINC) makefile
$(CXX) $^ -o $#
The resulting command will be:
g++ Tools.cpp Code1.cpp Code2.cpp Code3.cpp Tools.hh makefile -o Code1
This is clearly not what you want. g++ is attempting to compile both the header file and the makefile and doesn't know what to do with the makefile. You're also declaring dependencies on all three of your main units for each unit. So if Code3.cpp changes, Code1 will require recompilation. This is also undesirable.
Try something like this instead:
CXX = g++
all: Code1 Code2 Code3
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c -o $# $^
Code1: Code1.o Tools.o
$(CXX) -o $# $^
Code2: Code1.o Tools.o
$(CXX) -o $# $^
Code3: Code1.o Tools.o
$(CXX) -o $# $^
In short, $^ isn't what you want here. It evaluates to the "names of all the prerequisites, with spaces between them." In the problem Makefile, that causes all three targets to use almost identical command lines, that each look like
g++ Tools.cpp Code1.cpp Code2.cpp Code3.cpp Tools.hh makefile -o Code1
From the error message quoted, g++ has decided that makefile should be passed to the linker as if it were an object. It isn't. Without makefile on the line, you would still be compiling and linking all four of your source files, and quite likely leaving the linker to decide which of four main() functions to use.
You probably want to leverage the fact that make has a huge number of builtin rules for common cases. Compiling two source files and linking the result fits neatly into those common cases. Its untested, but the following should do all you want (assuming a recent build of gnu make, at least), and have the advantage of only compiling each object once.
all: Code1 Code2 Code3
Code1: Code1.o Tools.o
Code2: Code2.o Tools.o
Code3: Code3.o Tools.o
Code1.o Code2.o Code3.o Tools.o: Tools.hh
If you needed to set some compiler options you could add a definition for CXXFLAGS, traditionally near the top of the file.
Hm. Normally you'd specify dependencies on object files, with ".o" extensions. It might be that Make is being confused, since it has built-in rules for files of various types.
The error is because you're trying to link the makefile into the program, by passing $^ to the compiler.
On the right hand side of a rule you should put only the files that are usefull.
Code1: Code1.cpp Tools.cpp
$(CXX) $^ -o $#
Code1: Code2.cpp Tools.cpp
$(CXX) $^ -o $#
Code3: Code3.cpp Tools.cpp
$(CXX) $^ -o $#
While this solves your problem you should definitely read Grayfade’s answer on how to do things the "Right Way".
I am no expert at makefiles, but this is how I usually do it, and it works well.
COMPILER = g++
CXXFLAGS =
EXECUTABLE = code
all: code
code: Code1.o Code2.o Code3.o Tools.o
${COMPILER} ${CXXFLAGS} -o ${EXECUTABLE} Code1.o Code2.o Code3.o Tools.o
Code1.o: Code1.cpp Tools.o
${COMPILER} ${CXXFLAGS} -c Code1.cpp
Code2.o: Code2.cpp Tools.o
${COMPILER} ${CXXFLAGS} -c Code2.cpp
Code3.o: Code3.cpp Tools.o
${COMPILER} ${CXXFLAGS} -c Code3.cpp
Tools.o: Tools.cpp Tools.hh
${COMPILER} ${CXXFLAGS} -c Tools.cpp
clean:
rm *.o
rm ${EXECUTABLE}