Ваш Makefile немного странный. Основные правила make выглядят примерно так:
file-to-build: files-it-depends-on
command-to-build
Пока вы писали такие вещи, как:
.ds_test: ds.o ds_test.o
$(CXX) $(CXXFLAGS) -o ds_test ds.o ds_test.o
где целью является не файл, созданный по рецепту. Более того, вы переименовываете вещи без правильных расширений (data_structure
против ds.o
). И, наконец, вы используете разные имена для одной и той же вещи (снова data_structure
против ds.o
). Если вы начинаете с C ++ и делаете make, вам, вероятно, следует избегать всех этих причудливых вещей.
Основная причина сбоя вашего Makefile в том, что make пытается создать файл с именем ds_test
(это то, что вы запрашиваете при вводе make ds_test
). И make знает много способов для создания файлов. В этом конкретном случае он использует свое правило по умолчанию, которое заключается в использовании $(CC)
для связи вместе ds_test.o
, а все остальные файлы ds_test
зависят от, то есть data_structure
, .ds_test.o
и .ds_test
.
Если вы новичок в создании, я предлагаю вам сначала придерживаться его самых фундаментальных принципов. Что-то вроде:
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
Пояснения:
$@
, $<
и $^
- это , создающие автоматические переменные , которые соответственно расширяются как цель, первая предпосылка и список всех предпосылок. Они не просто удобны, они намного менее подвержены ошибкам, чем перепечатывание одинаковых имен файлов в целях, предпосылках и рецептах.
.PHONY
- это специальная цель , с помощью которой вы указываете, что цели не являются реальными файлами.
EDIT : добавлено LDLIBS
для связывания объектных файлов C ++ с gcc
и альтернативным правилом связывания.
Примечание: поскольку make действительно умный и по умолчанию знает, как компилировать и связывать файлы C ++, вы можете упростить все это. Особенно если вы также используете 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)
Примечание: поскольку make будет использовать gcc
для связи, мы должны добавить -lstdc++
к флагам компоновщика (LDLIBS
). Другой вариант - указать правило связывания вместо того, чтобы позволить make использовать значение по умолчанию:
$(EXEC):
$(CXX) $(CXXFLAGS) -o $@ $^
Обратите внимание, что в этом последнем случае правило, указывающее предварительные условия, и правило, указывающее рецепт, различаются.