Как скомпилировать несколько простых проектов с помощью GNU make - PullRequest
0 голосов
/ 21 июня 2020

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

.
├── Makefile
├── bin
│   ├── prog1
│   ├── prog2
│   └── prog3
└── src
    ├── prog1
    │   ├── Makefile
    │   └── main.c
    ├── prog2
    │   ├── Makefile
    │   └── main.c
    └── prog3
        ├── Makefile
        └── main.c

Я хотел бы узнать, как создать такую ​​структуру. В частности, часть, где верхний make-файл обращается ко всем папкам в src, вызывает там make, а затем копирует и переименовывает исполняемый файл в папки bin.

Ответы [ 2 ]

1 голос
/ 21 июня 2020

Ваша схема макета c показывает make-файл для каждого упражнения, а также make-файл верхнего уровня, о котором вы, кажется, действительно спрашиваете. Было бы лучше, если бы make-файл верхнего уровня избегал дублирования поведения make-файлов для каждого упражнения, так как такое дублирование создало бы для вас дополнительную нагрузку на обслуживание. Кроме того, вероятно, что вы в конечном итоге перейдете к упражнениям с несколькими исходными файлами и, возможно, к тем, у которых есть несколько артефактов, которые нужно создать. Это еще одна причина для того, чтобы каждый make-файл для каждого упражнения содержал все необходимое для создания упражнения, с которым он связан (в каталоге + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1001 *

Следуя этой схеме, make-файл верхнего уровня оставит четко определенную роль: выполнять сборки для каждого упражнения (путем рекурсивного запуска make) и копировать полученные двоичные файлы в bin/. Это не единственный способ настроить систему взаимодействующих make-файлов, но он довольно прост и позволит вам сосредоточиться на упражнениях, а не на системе сборки.

Итак, давайте предположим, что каждое отдельное упражнение можно создать, перейдя в его каталог и запустив make, в результате чего будет исполняемый файл в том же каталоге с тем же именем, что и каталог. То есть из каталога верхнего уровня выполнение cd src/prog2; make приведет к созданию желаемого исполняемого файла как src/prog2/prog2. В этом случае для make-файла верхнего уровня требуется немного больше, чем имена всех упражнений и пара правил:

EXERCISES = prog1 prog2 prog3
BINARIES =  $(EXERCISES:%=bin/%)

all: $(BINARIES)

$(BINARIES):
        make -C src/$$(basename $@)
        cp src/$$(basename $@)/$$(basename $@) $@

Примечание: в нем используется особенность c для GNU. реализация make для вычисления имен требуемых двоичных файлов из имен упражнений. Я считаю это приемлемым, поскольку вы отметили [gnu-make], но в любом случае это удобная функция, а не необходимость.

0 голосов
/ 21 июня 2020

Существуют разные способы решения этой проблемы, но в вашем примере должно работать что-то вроде этого:

PROGS := bin/prog1 bin/prog2 bin/prog3

all: $(PROGS)

$(PROGS):
    $(MAKE) -C src/$(@F)
    mkdir -p $(@D)
    cp src/$(@F)/main $@

.PHONY: clean

clean:
    rm -f $(PROGS)
    for t in $(PROGS); do make -C src/`basename $$t` clean; done

Мы определяем список целей (PROGS), которые мы должны построить. Мы говорим, что эти цели являются предпосылками all, а затем мы go вперед и определяем, как они должны быть построены, то есть: мы рекурсивно спускаемся в src/ плюс имя файла цели, чтобы запустить там make. Мы создаем каталог цели, чтобы быть уверенным, что она есть, и копируем main из каталога, по которому мы спустились, на путь к цели.

Для хорошей меры существует также цель clean который удаляет все PROGS и рекурсивно запускает make clean в src/.

...