Makefile executed unexpected behavior
I used the following Makefile to compile C++ files but some unexpected behavior happened. The environment is MacOS X Mojave. The Makefile is as:
CC=gcc
CXX=g++
CXXFLAGS=-std=c++11
RM=rm -f
all: clean sort_test ds_test
sort_test: data_structure sort .sort_test.o .sort_test
.sort_test: sort_test.o sort.o ds.o
$(CXX) $(CXXFLAGS) -o sort_test sort_test.o sort.o ds.o
.sort_test.o: sort_test.cpp ../include/io.hpp
$(CXX) $(CXXFLAGS) -c -o sort_test.o sort_test.cpp
sort: ../include/sort.hpp ../include/data_structure.hpp ../src/sort.cpp
$(CXX) $(CXXFLAGS) -c -o sort.o ../src/sort.cpp
data_structure: ../include/data_structure.hpp ../src/data_structure.cpp ../include/io.hpp
$(CXX) $(CXXFLAGS) -c -o ds.o ../src/data_structure.cpp
ds_test: data_structure .ds_test.o .ds_test
.ds_test: ds.o ds_test.o
$(CXX) $(CXXFLAGS) -o ds_test ds.o ds_test.o
.ds_test.o: ds_test.cpp ../include/io.hpp ../include/data_structure.hpp
$(CXX) $(CXXFLAGS) -c -o ds_test.o ds_test.cpp
clean:
$(RM) *.o sort_test ds_test
When I run "make ds_test" in the same directory, something weird happens:
g++ -std=c++11 -c -o ds_test.o ds_test.cpp
g++ -std=c++11 -c -o ds.o ../src/data_structure.cpp
g++ -std=c++11 -c -o ds_test.o ds_test.cpp
g++ -std=c++11 -o ds_test ds.o ds_test.o
gcc ds_test.o data_structure .ds_test.o .ds_test -o ds_test
clang: error: no such file or directory: 'data_structure'
clang: error: no such file or directory: '.ds_test.o'
clang: error: no such file or directory: '.ds_test'
make: *** [ds_test] Error 1
The first and fifth line in this output are never expected for command "make ds_test" since it should only invoke "data_structure", ".ds_test.o" and ".ds_test".
Anybody, please explain why these extra unexpected behaviors would happen and how to avoid it? Thanks!
makefile g++ gnu-make
add a comment |
I used the following Makefile to compile C++ files but some unexpected behavior happened. The environment is MacOS X Mojave. The Makefile is as:
CC=gcc
CXX=g++
CXXFLAGS=-std=c++11
RM=rm -f
all: clean sort_test ds_test
sort_test: data_structure sort .sort_test.o .sort_test
.sort_test: sort_test.o sort.o ds.o
$(CXX) $(CXXFLAGS) -o sort_test sort_test.o sort.o ds.o
.sort_test.o: sort_test.cpp ../include/io.hpp
$(CXX) $(CXXFLAGS) -c -o sort_test.o sort_test.cpp
sort: ../include/sort.hpp ../include/data_structure.hpp ../src/sort.cpp
$(CXX) $(CXXFLAGS) -c -o sort.o ../src/sort.cpp
data_structure: ../include/data_structure.hpp ../src/data_structure.cpp ../include/io.hpp
$(CXX) $(CXXFLAGS) -c -o ds.o ../src/data_structure.cpp
ds_test: data_structure .ds_test.o .ds_test
.ds_test: ds.o ds_test.o
$(CXX) $(CXXFLAGS) -o ds_test ds.o ds_test.o
.ds_test.o: ds_test.cpp ../include/io.hpp ../include/data_structure.hpp
$(CXX) $(CXXFLAGS) -c -o ds_test.o ds_test.cpp
clean:
$(RM) *.o sort_test ds_test
When I run "make ds_test" in the same directory, something weird happens:
g++ -std=c++11 -c -o ds_test.o ds_test.cpp
g++ -std=c++11 -c -o ds.o ../src/data_structure.cpp
g++ -std=c++11 -c -o ds_test.o ds_test.cpp
g++ -std=c++11 -o ds_test ds.o ds_test.o
gcc ds_test.o data_structure .ds_test.o .ds_test -o ds_test
clang: error: no such file or directory: 'data_structure'
clang: error: no such file or directory: '.ds_test.o'
clang: error: no such file or directory: '.ds_test'
make: *** [ds_test] Error 1
The first and fifth line in this output are never expected for command "make ds_test" since it should only invoke "data_structure", ".ds_test.o" and ".ds_test".
Anybody, please explain why these extra unexpected behaviors would happen and how to avoid it? Thanks!
makefile g++ gnu-make
add a comment |
I used the following Makefile to compile C++ files but some unexpected behavior happened. The environment is MacOS X Mojave. The Makefile is as:
CC=gcc
CXX=g++
CXXFLAGS=-std=c++11
RM=rm -f
all: clean sort_test ds_test
sort_test: data_structure sort .sort_test.o .sort_test
.sort_test: sort_test.o sort.o ds.o
$(CXX) $(CXXFLAGS) -o sort_test sort_test.o sort.o ds.o
.sort_test.o: sort_test.cpp ../include/io.hpp
$(CXX) $(CXXFLAGS) -c -o sort_test.o sort_test.cpp
sort: ../include/sort.hpp ../include/data_structure.hpp ../src/sort.cpp
$(CXX) $(CXXFLAGS) -c -o sort.o ../src/sort.cpp
data_structure: ../include/data_structure.hpp ../src/data_structure.cpp ../include/io.hpp
$(CXX) $(CXXFLAGS) -c -o ds.o ../src/data_structure.cpp
ds_test: data_structure .ds_test.o .ds_test
.ds_test: ds.o ds_test.o
$(CXX) $(CXXFLAGS) -o ds_test ds.o ds_test.o
.ds_test.o: ds_test.cpp ../include/io.hpp ../include/data_structure.hpp
$(CXX) $(CXXFLAGS) -c -o ds_test.o ds_test.cpp
clean:
$(RM) *.o sort_test ds_test
When I run "make ds_test" in the same directory, something weird happens:
g++ -std=c++11 -c -o ds_test.o ds_test.cpp
g++ -std=c++11 -c -o ds.o ../src/data_structure.cpp
g++ -std=c++11 -c -o ds_test.o ds_test.cpp
g++ -std=c++11 -o ds_test ds.o ds_test.o
gcc ds_test.o data_structure .ds_test.o .ds_test -o ds_test
clang: error: no such file or directory: 'data_structure'
clang: error: no such file or directory: '.ds_test.o'
clang: error: no such file or directory: '.ds_test'
make: *** [ds_test] Error 1
The first and fifth line in this output are never expected for command "make ds_test" since it should only invoke "data_structure", ".ds_test.o" and ".ds_test".
Anybody, please explain why these extra unexpected behaviors would happen and how to avoid it? Thanks!
makefile g++ gnu-make
I used the following Makefile to compile C++ files but some unexpected behavior happened. The environment is MacOS X Mojave. The Makefile is as:
CC=gcc
CXX=g++
CXXFLAGS=-std=c++11
RM=rm -f
all: clean sort_test ds_test
sort_test: data_structure sort .sort_test.o .sort_test
.sort_test: sort_test.o sort.o ds.o
$(CXX) $(CXXFLAGS) -o sort_test sort_test.o sort.o ds.o
.sort_test.o: sort_test.cpp ../include/io.hpp
$(CXX) $(CXXFLAGS) -c -o sort_test.o sort_test.cpp
sort: ../include/sort.hpp ../include/data_structure.hpp ../src/sort.cpp
$(CXX) $(CXXFLAGS) -c -o sort.o ../src/sort.cpp
data_structure: ../include/data_structure.hpp ../src/data_structure.cpp ../include/io.hpp
$(CXX) $(CXXFLAGS) -c -o ds.o ../src/data_structure.cpp
ds_test: data_structure .ds_test.o .ds_test
.ds_test: ds.o ds_test.o
$(CXX) $(CXXFLAGS) -o ds_test ds.o ds_test.o
.ds_test.o: ds_test.cpp ../include/io.hpp ../include/data_structure.hpp
$(CXX) $(CXXFLAGS) -c -o ds_test.o ds_test.cpp
clean:
$(RM) *.o sort_test ds_test
When I run "make ds_test" in the same directory, something weird happens:
g++ -std=c++11 -c -o ds_test.o ds_test.cpp
g++ -std=c++11 -c -o ds.o ../src/data_structure.cpp
g++ -std=c++11 -c -o ds_test.o ds_test.cpp
g++ -std=c++11 -o ds_test ds.o ds_test.o
gcc ds_test.o data_structure .ds_test.o .ds_test -o ds_test
clang: error: no such file or directory: 'data_structure'
clang: error: no such file or directory: '.ds_test.o'
clang: error: no such file or directory: '.ds_test'
make: *** [ds_test] Error 1
The first and fifth line in this output are never expected for command "make ds_test" since it should only invoke "data_structure", ".ds_test.o" and ".ds_test".
Anybody, please explain why these extra unexpected behaviors would happen and how to avoid it? Thanks!
makefile g++ gnu-make
makefile g++ gnu-make
edited Nov 13 '18 at 4:41
Andrew Wang
asked Nov 13 '18 at 4:18
Andrew WangAndrew Wang
33
33
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
Your Makefile is a bit weird. The basic make rules are something like:
file-to-build: files-it-depends-on
command-to-build
While you wrote things like:
.ds_test: ds.o ds_test.o
$(CXX) $(CXXFLAGS) -o ds_test ds.o ds_test.o
where the target is not the file produced by the recipe. Moreover, you rename things, without the proper extensions (data_structure
versus ds.o
). And finally you use different names for the same thing (again data_structure
versus ds.o
). If you are beginning with C++ and make, you should probably avoid all these fancy things.
The main reason why your Makefile fails is because make is trying to build a file named ds_test
(this what you ask for when typing make ds_test
). And make knows a lot of ways to build files. In this specific case it uses its default rule which consists in using $(CC)
to link together ds_test.o
and all other files ds_test
depends on, that is, data_structure
, .ds_test.o
and .ds_test
.
If you are new to make I suggest that you first stick with its most fundamental principles. Something like:
CC := gcc
CXX := g++
CXXFLAGS := -std=c++11
RM := rm -f
.PHONY: all clean
all: clean sort_test ds_test
sort_test: sort_test.o sort.o data_structure.o
$(CXX) $(CXXFLAGS) -o $@ $^
sort_test.o: sort_test.cpp ../include/io.hpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
sort.o: ../src/sort.cpp ../include/sort.hpp ../include/data_structure.hpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
data_structure.o: ../src/data_structure.cpp ../include/data_structure.hpp ../include/io.hpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
ds_test: data_structure.o ds_test.o
$(CXX) $(CXXFLAGS) -o $@ $^
ds_test.o: ds_test.cpp ../include/io.hpp ../include/data_structure.hpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
clean:
$(RM) *.o sort_test ds_test
Explanations:
$@
,$<
and$^
are make automatic variables that expand respectively as the target, the first prerequisite and the list of all prerequisites. They are not just convenient, they are much less error prone than retyping the same file names in targets, prerequisites and recipes..PHONY
is a special target with which you signal to make which targets are not real files.
EDIT: added LDLIBS
to link C++ object files with gcc
and an alternate linking rule.
Note: as make is really smart and knows by default how to compile and link C++ files, you could simplify all this. Especially if you also use the VPATH
make variable:
CC := gcc
CXX := g++
CXXFLAGS := -std=c++11
LDLIBS := -lstdc++
RM := rm -f
EXEC := sort_test ds_test
.PHONY: all clean
all: clean sort_test ds_test
VPATH := ../src:../include
sort_test.o: io.hpp
sort.o: sort.hpp data_structure.hpp
data_structure.o: data_structure.hpp io.hpp
ds_test.o: io.hpp data_structure.hpp
sort_test: sort_test.o sort.o data_structure.o
ds_test: data_structure.o ds_test.o
clean:
$(RM) *.o $(EXEC)
Note: as make will use gcc
to link, we must add -lstdc++
to the linker flags (LDLIBS
). Another option is to specify the linking rule instead of letting make use the default:
$(EXEC):
$(CXX) $(CXXFLAGS) -o $@ $^
Note that, in this last case, the rule specifying of the prerequisites and the rule specifying the recipe are different.
Hi Renaud, this answer helped me a lot, thank you very much! BTW, it seems like for "sort_test" & "ds_test", I have to manually add the command to use $(CXX), otherwise they would use gcc by default to link *.o files, which causes some linking troubles.
– Andrew Wang
Nov 14 '18 at 1:37
You're right. I edited my answer and added two possibilities to fix this.
– Renaud Pacalet
Nov 14 '18 at 6:41
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53273739%2fmakefile-executed-unexpected-behavior%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Your Makefile is a bit weird. The basic make rules are something like:
file-to-build: files-it-depends-on
command-to-build
While you wrote things like:
.ds_test: ds.o ds_test.o
$(CXX) $(CXXFLAGS) -o ds_test ds.o ds_test.o
where the target is not the file produced by the recipe. Moreover, you rename things, without the proper extensions (data_structure
versus ds.o
). And finally you use different names for the same thing (again data_structure
versus ds.o
). If you are beginning with C++ and make, you should probably avoid all these fancy things.
The main reason why your Makefile fails is because make is trying to build a file named ds_test
(this what you ask for when typing make ds_test
). And make knows a lot of ways to build files. In this specific case it uses its default rule which consists in using $(CC)
to link together ds_test.o
and all other files ds_test
depends on, that is, data_structure
, .ds_test.o
and .ds_test
.
If you are new to make I suggest that you first stick with its most fundamental principles. Something like:
CC := gcc
CXX := g++
CXXFLAGS := -std=c++11
RM := rm -f
.PHONY: all clean
all: clean sort_test ds_test
sort_test: sort_test.o sort.o data_structure.o
$(CXX) $(CXXFLAGS) -o $@ $^
sort_test.o: sort_test.cpp ../include/io.hpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
sort.o: ../src/sort.cpp ../include/sort.hpp ../include/data_structure.hpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
data_structure.o: ../src/data_structure.cpp ../include/data_structure.hpp ../include/io.hpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
ds_test: data_structure.o ds_test.o
$(CXX) $(CXXFLAGS) -o $@ $^
ds_test.o: ds_test.cpp ../include/io.hpp ../include/data_structure.hpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
clean:
$(RM) *.o sort_test ds_test
Explanations:
$@
,$<
and$^
are make automatic variables that expand respectively as the target, the first prerequisite and the list of all prerequisites. They are not just convenient, they are much less error prone than retyping the same file names in targets, prerequisites and recipes..PHONY
is a special target with which you signal to make which targets are not real files.
EDIT: added LDLIBS
to link C++ object files with gcc
and an alternate linking rule.
Note: as make is really smart and knows by default how to compile and link C++ files, you could simplify all this. Especially if you also use the VPATH
make variable:
CC := gcc
CXX := g++
CXXFLAGS := -std=c++11
LDLIBS := -lstdc++
RM := rm -f
EXEC := sort_test ds_test
.PHONY: all clean
all: clean sort_test ds_test
VPATH := ../src:../include
sort_test.o: io.hpp
sort.o: sort.hpp data_structure.hpp
data_structure.o: data_structure.hpp io.hpp
ds_test.o: io.hpp data_structure.hpp
sort_test: sort_test.o sort.o data_structure.o
ds_test: data_structure.o ds_test.o
clean:
$(RM) *.o $(EXEC)
Note: as make will use gcc
to link, we must add -lstdc++
to the linker flags (LDLIBS
). Another option is to specify the linking rule instead of letting make use the default:
$(EXEC):
$(CXX) $(CXXFLAGS) -o $@ $^
Note that, in this last case, the rule specifying of the prerequisites and the rule specifying the recipe are different.
Hi Renaud, this answer helped me a lot, thank you very much! BTW, it seems like for "sort_test" & "ds_test", I have to manually add the command to use $(CXX), otherwise they would use gcc by default to link *.o files, which causes some linking troubles.
– Andrew Wang
Nov 14 '18 at 1:37
You're right. I edited my answer and added two possibilities to fix this.
– Renaud Pacalet
Nov 14 '18 at 6:41
add a comment |
Your Makefile is a bit weird. The basic make rules are something like:
file-to-build: files-it-depends-on
command-to-build
While you wrote things like:
.ds_test: ds.o ds_test.o
$(CXX) $(CXXFLAGS) -o ds_test ds.o ds_test.o
where the target is not the file produced by the recipe. Moreover, you rename things, without the proper extensions (data_structure
versus ds.o
). And finally you use different names for the same thing (again data_structure
versus ds.o
). If you are beginning with C++ and make, you should probably avoid all these fancy things.
The main reason why your Makefile fails is because make is trying to build a file named ds_test
(this what you ask for when typing make ds_test
). And make knows a lot of ways to build files. In this specific case it uses its default rule which consists in using $(CC)
to link together ds_test.o
and all other files ds_test
depends on, that is, data_structure
, .ds_test.o
and .ds_test
.
If you are new to make I suggest that you first stick with its most fundamental principles. Something like:
CC := gcc
CXX := g++
CXXFLAGS := -std=c++11
RM := rm -f
.PHONY: all clean
all: clean sort_test ds_test
sort_test: sort_test.o sort.o data_structure.o
$(CXX) $(CXXFLAGS) -o $@ $^
sort_test.o: sort_test.cpp ../include/io.hpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
sort.o: ../src/sort.cpp ../include/sort.hpp ../include/data_structure.hpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
data_structure.o: ../src/data_structure.cpp ../include/data_structure.hpp ../include/io.hpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
ds_test: data_structure.o ds_test.o
$(CXX) $(CXXFLAGS) -o $@ $^
ds_test.o: ds_test.cpp ../include/io.hpp ../include/data_structure.hpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
clean:
$(RM) *.o sort_test ds_test
Explanations:
$@
,$<
and$^
are make automatic variables that expand respectively as the target, the first prerequisite and the list of all prerequisites. They are not just convenient, they are much less error prone than retyping the same file names in targets, prerequisites and recipes..PHONY
is a special target with which you signal to make which targets are not real files.
EDIT: added LDLIBS
to link C++ object files with gcc
and an alternate linking rule.
Note: as make is really smart and knows by default how to compile and link C++ files, you could simplify all this. Especially if you also use the VPATH
make variable:
CC := gcc
CXX := g++
CXXFLAGS := -std=c++11
LDLIBS := -lstdc++
RM := rm -f
EXEC := sort_test ds_test
.PHONY: all clean
all: clean sort_test ds_test
VPATH := ../src:../include
sort_test.o: io.hpp
sort.o: sort.hpp data_structure.hpp
data_structure.o: data_structure.hpp io.hpp
ds_test.o: io.hpp data_structure.hpp
sort_test: sort_test.o sort.o data_structure.o
ds_test: data_structure.o ds_test.o
clean:
$(RM) *.o $(EXEC)
Note: as make will use gcc
to link, we must add -lstdc++
to the linker flags (LDLIBS
). Another option is to specify the linking rule instead of letting make use the default:
$(EXEC):
$(CXX) $(CXXFLAGS) -o $@ $^
Note that, in this last case, the rule specifying of the prerequisites and the rule specifying the recipe are different.
Hi Renaud, this answer helped me a lot, thank you very much! BTW, it seems like for "sort_test" & "ds_test", I have to manually add the command to use $(CXX), otherwise they would use gcc by default to link *.o files, which causes some linking troubles.
– Andrew Wang
Nov 14 '18 at 1:37
You're right. I edited my answer and added two possibilities to fix this.
– Renaud Pacalet
Nov 14 '18 at 6:41
add a comment |
Your Makefile is a bit weird. The basic make rules are something like:
file-to-build: files-it-depends-on
command-to-build
While you wrote things like:
.ds_test: ds.o ds_test.o
$(CXX) $(CXXFLAGS) -o ds_test ds.o ds_test.o
where the target is not the file produced by the recipe. Moreover, you rename things, without the proper extensions (data_structure
versus ds.o
). And finally you use different names for the same thing (again data_structure
versus ds.o
). If you are beginning with C++ and make, you should probably avoid all these fancy things.
The main reason why your Makefile fails is because make is trying to build a file named ds_test
(this what you ask for when typing make ds_test
). And make knows a lot of ways to build files. In this specific case it uses its default rule which consists in using $(CC)
to link together ds_test.o
and all other files ds_test
depends on, that is, data_structure
, .ds_test.o
and .ds_test
.
If you are new to make I suggest that you first stick with its most fundamental principles. Something like:
CC := gcc
CXX := g++
CXXFLAGS := -std=c++11
RM := rm -f
.PHONY: all clean
all: clean sort_test ds_test
sort_test: sort_test.o sort.o data_structure.o
$(CXX) $(CXXFLAGS) -o $@ $^
sort_test.o: sort_test.cpp ../include/io.hpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
sort.o: ../src/sort.cpp ../include/sort.hpp ../include/data_structure.hpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
data_structure.o: ../src/data_structure.cpp ../include/data_structure.hpp ../include/io.hpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
ds_test: data_structure.o ds_test.o
$(CXX) $(CXXFLAGS) -o $@ $^
ds_test.o: ds_test.cpp ../include/io.hpp ../include/data_structure.hpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
clean:
$(RM) *.o sort_test ds_test
Explanations:
$@
,$<
and$^
are make automatic variables that expand respectively as the target, the first prerequisite and the list of all prerequisites. They are not just convenient, they are much less error prone than retyping the same file names in targets, prerequisites and recipes..PHONY
is a special target with which you signal to make which targets are not real files.
EDIT: added LDLIBS
to link C++ object files with gcc
and an alternate linking rule.
Note: as make is really smart and knows by default how to compile and link C++ files, you could simplify all this. Especially if you also use the VPATH
make variable:
CC := gcc
CXX := g++
CXXFLAGS := -std=c++11
LDLIBS := -lstdc++
RM := rm -f
EXEC := sort_test ds_test
.PHONY: all clean
all: clean sort_test ds_test
VPATH := ../src:../include
sort_test.o: io.hpp
sort.o: sort.hpp data_structure.hpp
data_structure.o: data_structure.hpp io.hpp
ds_test.o: io.hpp data_structure.hpp
sort_test: sort_test.o sort.o data_structure.o
ds_test: data_structure.o ds_test.o
clean:
$(RM) *.o $(EXEC)
Note: as make will use gcc
to link, we must add -lstdc++
to the linker flags (LDLIBS
). Another option is to specify the linking rule instead of letting make use the default:
$(EXEC):
$(CXX) $(CXXFLAGS) -o $@ $^
Note that, in this last case, the rule specifying of the prerequisites and the rule specifying the recipe are different.
Your Makefile is a bit weird. The basic make rules are something like:
file-to-build: files-it-depends-on
command-to-build
While you wrote things like:
.ds_test: ds.o ds_test.o
$(CXX) $(CXXFLAGS) -o ds_test ds.o ds_test.o
where the target is not the file produced by the recipe. Moreover, you rename things, without the proper extensions (data_structure
versus ds.o
). And finally you use different names for the same thing (again data_structure
versus ds.o
). If you are beginning with C++ and make, you should probably avoid all these fancy things.
The main reason why your Makefile fails is because make is trying to build a file named ds_test
(this what you ask for when typing make ds_test
). And make knows a lot of ways to build files. In this specific case it uses its default rule which consists in using $(CC)
to link together ds_test.o
and all other files ds_test
depends on, that is, data_structure
, .ds_test.o
and .ds_test
.
If you are new to make I suggest that you first stick with its most fundamental principles. Something like:
CC := gcc
CXX := g++
CXXFLAGS := -std=c++11
RM := rm -f
.PHONY: all clean
all: clean sort_test ds_test
sort_test: sort_test.o sort.o data_structure.o
$(CXX) $(CXXFLAGS) -o $@ $^
sort_test.o: sort_test.cpp ../include/io.hpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
sort.o: ../src/sort.cpp ../include/sort.hpp ../include/data_structure.hpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
data_structure.o: ../src/data_structure.cpp ../include/data_structure.hpp ../include/io.hpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
ds_test: data_structure.o ds_test.o
$(CXX) $(CXXFLAGS) -o $@ $^
ds_test.o: ds_test.cpp ../include/io.hpp ../include/data_structure.hpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
clean:
$(RM) *.o sort_test ds_test
Explanations:
$@
,$<
and$^
are make automatic variables that expand respectively as the target, the first prerequisite and the list of all prerequisites. They are not just convenient, they are much less error prone than retyping the same file names in targets, prerequisites and recipes..PHONY
is a special target with which you signal to make which targets are not real files.
EDIT: added LDLIBS
to link C++ object files with gcc
and an alternate linking rule.
Note: as make is really smart and knows by default how to compile and link C++ files, you could simplify all this. Especially if you also use the VPATH
make variable:
CC := gcc
CXX := g++
CXXFLAGS := -std=c++11
LDLIBS := -lstdc++
RM := rm -f
EXEC := sort_test ds_test
.PHONY: all clean
all: clean sort_test ds_test
VPATH := ../src:../include
sort_test.o: io.hpp
sort.o: sort.hpp data_structure.hpp
data_structure.o: data_structure.hpp io.hpp
ds_test.o: io.hpp data_structure.hpp
sort_test: sort_test.o sort.o data_structure.o
ds_test: data_structure.o ds_test.o
clean:
$(RM) *.o $(EXEC)
Note: as make will use gcc
to link, we must add -lstdc++
to the linker flags (LDLIBS
). Another option is to specify the linking rule instead of letting make use the default:
$(EXEC):
$(CXX) $(CXXFLAGS) -o $@ $^
Note that, in this last case, the rule specifying of the prerequisites and the rule specifying the recipe are different.
edited Nov 14 '18 at 6:43
answered Nov 13 '18 at 9:44
Renaud PacaletRenaud Pacalet
9,20821729
9,20821729
Hi Renaud, this answer helped me a lot, thank you very much! BTW, it seems like for "sort_test" & "ds_test", I have to manually add the command to use $(CXX), otherwise they would use gcc by default to link *.o files, which causes some linking troubles.
– Andrew Wang
Nov 14 '18 at 1:37
You're right. I edited my answer and added two possibilities to fix this.
– Renaud Pacalet
Nov 14 '18 at 6:41
add a comment |
Hi Renaud, this answer helped me a lot, thank you very much! BTW, it seems like for "sort_test" & "ds_test", I have to manually add the command to use $(CXX), otherwise they would use gcc by default to link *.o files, which causes some linking troubles.
– Andrew Wang
Nov 14 '18 at 1:37
You're right. I edited my answer and added two possibilities to fix this.
– Renaud Pacalet
Nov 14 '18 at 6:41
Hi Renaud, this answer helped me a lot, thank you very much! BTW, it seems like for "sort_test" & "ds_test", I have to manually add the command to use $(CXX), otherwise they would use gcc by default to link *.o files, which causes some linking troubles.
– Andrew Wang
Nov 14 '18 at 1:37
Hi Renaud, this answer helped me a lot, thank you very much! BTW, it seems like for "sort_test" & "ds_test", I have to manually add the command to use $(CXX), otherwise they would use gcc by default to link *.o files, which causes some linking troubles.
– Andrew Wang
Nov 14 '18 at 1:37
You're right. I edited my answer and added two possibilities to fix this.
– Renaud Pacalet
Nov 14 '18 at 6:41
You're right. I edited my answer and added two possibilities to fix this.
– Renaud Pacalet
Nov 14 '18 at 6:41
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53273739%2fmakefile-executed-unexpected-behavior%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown