Генерация объектного файла Makefile, подстановка переменных и другие вопросы

В настоящее время я пытаюсь создать Makefile для проекта университета C, но чтение руководств мне не очень помогло (к тому же makefile не является частью процесса оценки, и нас не учат, как это делать)

Моя цель — сделать make-файл автоматическим, чтобы он автоматически создавал объектные файлы из файлов .c в src (src/*.c), помещал объектные файлы в папку bin и связывал их с исполняемым файлом в основном каталоге.

project/
    bin/
        (object files)
    src/
        (source files)
    executable
    Makefile

На данный момент я примерно собрал этот make-файл и протестировал исходный код, но он работает не так, как я предполагал, и я объясню, как это делается ниже:

#compiler used
COMPILER = gcc

#flags for individual object file compilation
FLAGS = -Wall -ansi -g
#RELEASE
# -Wall -ansi -O3
#DEVELOPMENT
# -Wall -ansi -g

#source .c files
SOURCE = $(wildcard src/*.c)
#object files created
OBJECTS = $(SOURCE:.c=.o)
OBJECTS = $(SOURCE: src/=bin/)

#executable name
EXECUTABLE = app

############################################################

all: $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS)
    $(COMPILER) $(FLAGS) -o $(EXECUTABLE) $(OBJECTS)

%.o: %.c
    $(COMPILER) $(FLAGS) -c %< -o %@

Результатом является следующая команда:

user@user-lenovo:~/Desktop/C Projects/AED/project$ make
gcc -Wall -ansi -g -o app src/main.c src/test.c

Как ни странно, это работает, но на самом деле не должно. Это также противоречит цели наличия make-файла, поскольку все компилируется снова после обнаружения одного изменения.

Прежде всего, я заметил, что OBJECTS напрямую копирует SOURCE и не заменяет .c на .o или src/ на bin/. Я пытался заменить '=' на ':=', но результат тот же, и я не совсем понимаю, в чем разница между ними. Моя идея заключалась бы в том, чтобы, например, src/main.c превратился в bin/main.o.

%.o: %.c
    $(COMPILER) $(FLAGS) -c %< -o %@

Эта часть также является моей неудачной попыткой сгенерировать все объектные файлы по отдельности с одной целью. Я пытался читать об этом, но не мог понять, как они работают: '%‹', '%@' или '%.o' и '%.c'.

Я действительно считаю, что он вообще не запускается, так как никаких объектных файлов не появилось.

Я надеюсь, что вы можете помочь мне исправить этот беспорядок, спасибо заранее!


person Alexandre Rodrigues    schedule 17.10.2018    source источник
comment
Пожалуйста, задайте только один вопрос и выберите соответствующий ему заголовок.   -  person Yunnosch    schedule 17.10.2018


Ответы (2)


OBJECTS = $(SOURCE:.c=.o)
OBJECTS = $(SOURCE: src/=bin/)

Вы дважды назначаете OBJECTS - первый результат перезаписывается вторым, который не работает. Вы хотите объединить их в одно утверждение, подобное этому

OBJECTS=$(SOURCE:src/%.c=bin/%.o)

Ваша следующая проблема заключается в том, что вам нужно сообщить make, что "bin/whatever.o" построен из "src/whatever.c". В настоящее время он ищет «whatever.c» в «bin/».

Итак, ваш рецепт создания файлов .o требует добавления каталогов.

bin/%.o: src/%.c
    $(COMPILER) $(FLAGS) -c $< -o $@

У вас также должно быть $@ вместо %@ и $< вместо %<

person Chris Turner    schedule 17.10.2018

  1. Автоматические переменные расширяются с помощью префикса $, как и любая другая переменная, а не %.
  2. Поскольку ваши объектные и исходные файлы находятся в разных каталогах, вы не можете просто %.o: %.c.

Пытаться:

CC = gcc
CFLAGS = -Wall -ansi -g

OBJECTS = $(patsubst src/%.c,bin/%.o,$(SOURCE))

bin/%.o: src/%.c
    $(CC) $(CFLAGS) -c $< -o $@

Примечание: стандартная переменная make для компилятора C — CCи CFLAGS для флагов. Их лучше использовать.

person Renaud Pacalet    schedule 17.10.2018