Создать linux make / build file - PullRequest
       10

Создать linux make / build file

9 голосов
/ 26 августа 2010

Я перемещаю проект C ++ из Windows в Linux, и теперь мне нужно создать файл build / make. Я никогда не создавал файл build / make раньше. Мне также нужно включить библиотеки Boost, чтобы сделать его более сложным. Это также должен быть make-файл, и мне все равно нужно научиться создавать make-файл, поэтому CMake и SCON отсутствуют. IDE также отсутствуют из-за использования Boost, и все мои IDE (Eclipse, VS и т. Д.) Работают только в Windows. Я должен создать make-файл с нуля.

Итак, каковы основы создания make-файла Linux c ++ и как включить в него библиотеки Boost, чтобы правильно связать его?

Пока что мой make-файл выглядит так. Я думаю, CFLAGS и LDFLAGS являются опциями компилятора и оптимизации, но не совсем уверены.

CC = g++
CFLAGS = -wall -o3 - c
LDFLAGS = -03 -mfp-rounding-mode=n

Я предлагаю щедрость, потому что я все еще очень потерян. В случае, если кто-то чувствует себя авантюрным, мне нужно собрать следующее в linux

  • simple_ls.h
  • simple_ls.cpp
  • 2dquicksort.h
  • rawr.h
  • rawr.cpp
  • converter.cpp

Заголовки в simple_ls.h:

#include "boost/filesystem/operations.hpp"
#include "boost/filesystem/path.hpp"
#include "boost/lexical_cast.hpp"

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

Заголовки в 2dquicksort.h:

#include <stdio.h>
#include <ctype.h>
#include <iostream>

Заголовки в rawr.h:

#include <iostream> // not required by most systems
#include <fstream>
#include <iomanip>
#include <cstdlib> // or (stdlib.h) for exit()

#include <cmath> 
#include <vector>
#include <limits>
#include <string>

Приемлемым ответом будет пошаговое объяснение того, как работают make-файлы и как их создавать с помощью Boost в Linux без IDE.

Ответы [ 10 ]

19 голосов
/ 26 августа 2010

Ниже приведен очень простой сборочный файл GNU:

CPPFLAGS += -Isome_include_path
CXXFLAGS += -O3
LDFLAGS  += -Lsome_link_path -lsome_lib -lboost_filesystem

all: binary_name
binary_name: foo.o bar.o john.o
  • CPPFLAGS - это флаги, которые применяются к препроцессору Си. Такие вещи, как включают в себя пути.
  • CXXFLAGS - это флаги, которые применяются к компилятору C ++. Такие вещи, как уровни оптимизации.
  • LDFLAGS - это флаги, которые применяются к компоновщику. Такие вещи, как внешние библиотеки (boost_filesystem) и другие библиотеки. Кроме того, пути к этим библиотекам.
  • Конвенция гласит, что должно быть правило make all, которое используется по умолчанию. В make первое правило используется по умолчанию.
  • binary_name - это имя вашего двоичного файла.
  • binary_name зависит от 3 файлов: foo.o, bar.o, john.o.
  • Мы не включаем правила для *.o, потому что у gnu make есть неявное правило для них.

Чтобы использовать make, вы должны создать файл с именем Makefile с содержимым, перечисленным выше. Для сборки вы должны запустить make в этом каталоге.

В качестве отступления (и, как уже упоминали другие), я бы порекомендовал отойти от make, если это возможно. Есть лучшие системы там. Главное преимущество make в том, что оно везде. Однако если этого требует руководство, то руководство требует этого.

(Обратите внимание, что нотация GNU Make += не всегда переносима на другие версии Make. Однако make в Linux - это GNU Make.)


Учитывая ваше редактирование, вот пример с файлами, которые вы отметили. Единственное предупреждение: строка, начинающаяся с $ (CXX), должна начинаться с символа табуляции!

LDFLAGS  := -lboost_filesystem
CXXFLAGS := -O3 -Wall
CPPFLAGS :=

all: program
program: simple_ls.o converter.o rawr.o
    $(CXX) -o $< $^ $(LDFLAGS)

simple_ls.o: simple_ls.cpp rawr.h simple_ls.h 2dquicksort.h
converter.o: converter.cpp rawr.h simple_ls.h 2dquicksort.h
rawr.o: rawr.cpp rawr.h simple_ls.h 2dquicksort.h
19 голосов
/ 05 сентября 2010

Что такое 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-файла:

  1. настройка переменной
  2. объявления цели / зависимости

Реальная обработка целевых инструкций начинается, как только весь 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 ++ :)

8 голосов
/ 26 августа 2010

Я бы не рекомендовал писать свои Makefile с.Вместо этого используйте систему сборки, такую ​​как CMake или SCons .

Стоит отметить, что эти инструменты являются кроссплатформенными.Таким образом, вы можете использовать одну и ту же систему сборки в Linux и Windows.

5 голосов
/ 26 августа 2010

Конечно, вы должны прочитать The Fine Manual (в частности, gcc и make).Однако вот основы для gcc:

Чтобы скомпилировать исходный файл:

g++ -c file.cpp

Это создаст файл .o.Тогда вы, вероятно, захотите связать их:

g++ -o app_name file.o main.o other_file.o

Это создаст исполняемый файл с именем app_name .Но так как вы используете boost и заголовочные файлы могут быть расположены повсюду, вам, вероятно, понадобятся дополнительные опции.Используйте -I во время компиляции, чтобы добавить каталог к ​​пути включения:

g++ -I/usr/local/more_includes/ -c file.cpp

Возможно, вам также понадобится установить связь с некоторыми библиотеками.Во время ссылки:

g++ -L/usr/local/more_libraries/ file.o main.o other_file.o -lsome_library

Теперь на make-файлы.Основы make-файла:

target: dependencies
    command

Например:

my_app: file.o
    g++ -o my_app file.o

file.o: file.cpp file.h
    g++ -o file.cpp

clean:
    rm file.o my_app

Если вы введете «make», по умолчанию будет попытаться создать первую цель.my_app зависит от целевого file.o, поэтому он проверит, был ли file.o изменен с момента последнего изменения my_app.Если это так, он будет перекомпонован.При проверке file.o он замечает, что file.o зависит от file.cpp и file.h.Если какой-либо из этих файлов был изменен с момента последнего создания файла file.o, он перекомпилирует этот файл.

Цели также не всегда должны быть фактическими файлами.Последний называется чистым, он ни от чего не зависит и просто удаляет file.o и my_app.Если вы наберете «make clean», он запустит команду.

Есть, конечно, множество других опций, но это поможет вам начать.

4 голосов
/ 03 сентября 2010

По крайней мере, попытайтесь прочитать официальную документацию продукта, который вы пытаетесь использовать: здесь . Это объясняет почти все основы.

В частности, прочитайте главы 2 и 3, они помогут вам на 99% добраться до того места, где вы должны быть, чтобы эффективно использовать gmake. Кроме того, внимательно прочитайте Каталог неявных правил . Это скажет вам, что большинство из этих «специальных переменных».

Один совет, который я бы вам дал, это попробовать gcc -M *.cpp в каталоге вашего проекта. Это выведет список обязательных заголовков для каждого из ваших файлов .cpp в формате Makefile. Фактически, для стартового make-файла вы можете просто сделать:

gcc -M *.cpp > Makefile

Отредактируйте этот файл, более или менее предваряя ответ на него Шарта, и у вас будет работающий Makefile Вероятно, я бы посоветовал вам удалить большое количество системных заголовков, которые gcc -M будет добавлять к каждому правилу сборки, но вам это не обязательно.

FWIW, если вы начинаете работать над большим проектом (более одного исходного каталога - хорошая подсказка), пришло время использовать современный инструмент управления сборкой (фанат cmake здесь). Но для небольших проектов raw make довольно прост в использовании.

2 голосов
/ 03 сентября 2010

Прежде всего, я не эксперт по Makefiles. Я знаю основы, но Makefile в этом ответе почти наверняка будет иметь место для улучшения. Существует множество хитростей и ярлыков, которые позволят вам обрабатывать зависимости и добавлять файлы лучше, чем жесткое кодирование всего. Однако я думаю, что этот пример будет достаточным для ваших целей и, возможно, будет более образовательным.

Во-вторых, я хочу убедиться, что вы знаете основные этапы построения проекта. Возможно, вы уже знаете это, но если вы этого не сделаете, то поначалу будет немного запутанно. Существуют два основных этапа: компиляция и компоновка. Компиляция преобразует ваш код в объектный код - он преобразует файл .cpp в файл .o в случае успеха. Следующий шаг - связывание. Здесь он объединяет весь объектный код для создания исполняемого файла и связывает вызовы функции из одного файла в другой (поэтому, если file1.cpp вызывает функцию, определенную в file2.cpp, именно на этом этапе file1.cpp выясняет, где функция на самом деле). Это еще не все, но этого должно быть достаточно, чтобы прояснить следующее.

На данный момент вы можете просто использовать g++ для компиляции и компоновки вашего проекта (вы даже можете сделать это за один шаг). Однако это довольно громоздко, особенно для любого нетривиального проекта. Это также затрудняет отслеживание файлов, которые изменились с момента последней компиляции.

Именно здесь приходят Makefile. Makefile - это список правил в форме:

target: dependencies
    command

(Обязательно используйте табуляции, а не пробелы, make, вероятно, не будет работать, если вы используете пробелы). Если вы запустите команду:

make some_target

Тогда make будет искать правило с some_target. Если целью является файл, он проверит метку времени последнего изменения файла и проверит метки времени всех зависимостей, которые вы перечислили. Если какая-либо из зависимостей имеет более позднюю отметку времени, она запустит команду.

Мне нужно будет сделать некоторые предположения о вашем проекте (а именно, какие файлы зависят от того, от каких файлов), поэтому вам, вероятно, придется изменить следующее, но вот основной Makefile для вашего проекта (и помните, вкладки не пробелы. Если вы скопируете и вставите это, оно не будет работать):

CC = g++
INCLUDE_DIRS = -I/path/to/boost

all: binary_file

clean:
    rm *.o
    rm binary_file

binary_file: simple_ls.o rawr.o converter.o
    $(CC) -o binary_file simple_ls.o rawr.o converter.o

rawr.o: rawr.h rawr.cpp 2dquicksort.h
    $(CC) -c rawr.cpp $(INCLUDE_DIRS)

simple_ls.o: simple_ls.h simple_ls.cpp 2dquicksort.h
    $(CC) -c simple_ls.cpp $(INC*emphasized text*LUDE_DIRS)

Запуск make или make all или make binary_file приведет к тому, что все ваши файлы будут скомпилированы в случае необходимости, а затем связаны для создания исполняемого файла с именем binary_file. Вы можете внести некоторые улучшения, например:

%.o: %.cpp %.h 2dquicksort.h
    $(CC) -c $<

Который найдет все файлы .cpp и скомпилирует их в файлы .o. Файлы .o будут зависеть от файла .cpp и файла .h с одинаковым именем (и 2dquicksort.h).

2 голосов
/ 03 сентября 2010

Очень хороший учебник @ ALP .

2 голосов
/ 31 августа 2010

Это не совсем то, что вы запрашивали, но я настоятельно рекомендую вам использовать систему сборки под названием premake . Преимущество и разница между premake, scons и cmake в том, что он генерирует make-файлы для вас. Это означает, что вы можете использовать premake в качестве начала, а затем просматривать файлы, которые он генерирует, чтобы узнать больше.

Помимо этого предварительного создания, это простой в освоении и интуитивно понятный инструмент, и он имеет дополнительное преимущество, заключающееся в возможности генерировать файлы проектов Visual Studio из той же конфигурации.

Мой совет - использовать premake, если вам абсолютно необходимы make-файлы, это поможет вам учиться и, в конечном счете, является гибкой заменой для непосредственного написания ваших собственных make-файлов (что является основной проблемой% * $). *

0 голосов
/ 16 октября 2018

Я предпочитаю стандартное проект описание, такое как это . Другими словами, я считаю, что фокус на make-файле слишком узок.

Достоинство этого описания проекта - простота. Его можно адаптировать к более сложным проектам с подкаталогами, используя make -C subdir -f Makefile all в цели all. subdir - это, конечно, ваш подкаталог с кодом, который должен быть собран.

Автор указывает, что создание и поддержка сред сборки не производительны, поэтому вам нужно что-то, что легко изменить и вы понимаете. Я не обязательно хотел бы быть экспертом по make-файлам. Я не думаю, что это так полезно, как думают многие.

Мне так нравится идея hiltmon, что я превращаю ее в сценарий оболочки. Я могу написать законченный проект на Python и спросить автора, могу ли я внести свой вклад в GitHub.

0 голосов
/ 31 августа 2010

Используя идею @Job, я рекомендую оставить ее для некоторой IDE. Например, создайте проект в Eclipse CDT и используйте его автоматически созданный файл make. Затем вы можете настроить его и к тому времени изменить, чтобы он точно соответствовал вашим потребностям.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...