Что такое Makefile ? (применяется к проекту Boost )
Корень рекурсивный идея, стоящая за Makefile:
Для построения цели нам необходимы предпосылки (другие цели!) И инструкции для построения
Предпосылки
Они естьфайлы, папки или поддельные цели (обычно в .PHONY
).Файлы / папки проверяются на наличие и дату модификации.
Цель должна быть перестроена, если у нее нет предварительных условий или если она старше, чем любая из предпосылок.
Инструкция
Инструкция: Команды оболочки , начиная с одной вкладки.Каждая строка инструкций является одним экземпляром оболочки.Команда оболочки может быть продолжена на следующей строке, когда текущая строка заканчивается обратной косой чертой \
.
Определение цели
Цель - либо зависимость , либо rule .
Зависимость:
target : prerequisite1 prerequisite2 prerequisiteN
Правило:
target : prerequisite1 prerequisite2 prerequisiteN
instructions1
@hidden_batch1 ; \
hidden_batch2
С вкладками перед началом инструкции.
Debug
Отладка Makefile может стать настоящей головной болью.Попробуйте следующее в вашем Makefile, чтобы показать трассировки (с расположением файла и строки для warning
):
$(info Shell: $(SHELL))
$(warning CXX: $(CXX))
Это полезно, когда ваш Makefile содержит много вложенных if/else/endif
, и вы больше не увереныкаков текущий путь.
Структура make-файла
Идеальная структура make-файла:
- настройка переменной
- объявления цели / зависимости
Реальная обработка целевых инструкций начинается, как только весь Makefile и его включаемые файлы были поняты (хранятся во внутренней базе данных make
).
Пример
Наконец, примените теорию к этому конкретному примеру, используя Boost, и создайте поддельные исходные файлы для иллюстрации.
rawr.cpp
#include "rawr.h"
simple_ls.cpp
#include "rawr.h"
converter.cpp
#include <iostream>
#include "rawr.h"
#include "simple_ls.h"
#include "2dquicksort.h"
#include <boost/array.hpp> // Boost!
int main(int argc, char **argv)
{
boost::array<int,4> a = { { 1, 2, 3, 4} };
std::cout << a[1] << std::endl;
return 0;
}
Makefile
Не забудьте заменить пробелы реальными вкладками, если копируете Makefile
исходник из * стека*** переполнение **:
sed -i~ -e 's/^ /\t/' Makefile
Источник файла Makefile:
## Makefile for C++ project using Boost
#
# @author Cedric "levif" Le Dillau
#
# Some notes:
# - Using ':=' instead of '=' assign the value at Makefile parsing time,
# others are evaluated at usage time. This discards
# - Use ':set list' in Vi/Vim to show tabs (Ctrl-v-i force tab insertion)
#
# List to '.PHONY' all fake targets, those that are neither files nor folders.
# "all" and "clean" are good candidates.
.PHONY: all, clean
# Define the final program name
PROGNAME := converter
# Pre-processor flags to be used for includes (-I) and defines (-D)
CPPFLAGS := -DUSE_BOOST
# CFLAGS is used for C compilation options.
CFLAGS := -Wall -O0
# CXXFLAGS is used for C++ compilation options.
CXXFLAGS += -Wall -O0
# LDFLAGS is used for linker (-g enables debug symbols)
LDFLAGS += -g
# Which Boost modules to use (all)
BOOST_MODULES = \
date_time \
filesystem \
graph \
iostreams \
math_c99 \
system \
serialization \
regex
# Boost libraries' type (a suffix)
BOOST_MODULES_TYPE := -mt
# Define library names with their type
BOOST_MODULES_LIBS := $(addsuffix $(BOOT_MODULES_TYPE),$(BOOST_MODULES))
# Define the linker argument to use the Boost libraries.
BOOST_LDFLAGS := $(addprefix -lboost_,$(BOOST_MODULES_LIBS))
# Feed compiler/linker flags with Boost's
CPPFLAGS += $(BOOST_CPPFLAGS)
LDFLAGS += $(BOOST_LDFLAGS)
# List the project' sources to compile or let the Makefile recognize
# them for you using 'wildcard' function.
#
#SOURCES = simple_ls.cpp rawr.cpp converter.cpp
SOURCES = $(wildcard *.cpp)
# List the project' headers or let the Makefile recognize
# them for you using 'wildcard' function.
#
#HEADERS = simple_ls.h 2dquicksort.h rawr.h
HEADERS = $(wildcard %.h)
# Construct the list of object files based on source files using
# simple extension substitution.
OBJECTS = $(SOURCES:%.cpp=%.o)
#
# Now declare the dependencies rules and targets
#
# Starting with 'all' make it becomes the default target when none
# is specified on 'make' command line.
all : $(PROGNAME)
# Declare that the final program depends on all objects and the Makfile
$(PROGNAME) : $(OBJECTS) Makefile
$(CXX) -o $@ $(LDFLAGS) $(OBJECTS)
# Now the choice of using implicit rules or not (my choice)...
#
# Choice 1: use implicit rules and then we only need to add some dependencies
# to each object.
#
## Tells make that each object file depends on all headers and this Makefile.
#$(OBJECTS) : $(HEADERS) Makefile
#
# Choice 2: don't use implicit rules and specify our will
%.o: %.cpp $(HEADERS) Makefile
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(OUTPUT_OPTION) $<
# Simple clean-up target
# notes:
# - the '@' before 'echo' informs make to hide command invocation.
# - the '-' before 'rm' command to informs make to ignore errors.
clean :
@echo "Clean."
-rm -f *.o $(PROGNAME)
Список файлов
2dquicksort.h
converter.cpp
Makefile
rawr.cpp
rawr.h
simple_ls.cpp
simple_ls.h
Компиляция
make clean all
Clean.
rm -f *.o converter
g++ -Wall -O0 -DUSE_BOOST -c -o converter.o converter.cpp
g++ -Wall -O0 -DUSE_BOOST -c -o rawr.o rawr.cpp
g++ -Wall -O0 -DUSE_BOOST -c -o simple_ls.o simple_ls.cpp
g++ -o converter -g -lboost_date_time -lboost_filesystem -lboost_graph -lboost_iostreams -lboost_math_c99 -lboost_system -lboost_serialization -lboost_regex converter.o rawr.o simple_ls.o
Результат
И вот, результат почти крошечной программы Boost:
./converter
2
Нет оправдания, чтобы не использовать его! Повышение - это действительно набор инструментов C ++ :)