2015-06-01 3 views
0

После этого урока:путь включает и ЦСИ каталог Makefile

http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/

Он имеет 3 файлы 2 из которых являются .c файлами и 1 .h файла. Учебник посвящен настройке make-файлов, и первые несколько шагов работают. Последний шаг включает настройку путей каталога для файлов .h и .c. Я поместил файлы .c в файл src и файлы .h в файл include.

Похоже, что это /home/bob/testcode/src < - содержит файлы .c.

И /home/bob/testcode/include < - содержит файлы .h.

Код:

IDIR =../include 
CC=gcc 
CFLAGS=-I$(IDIR) 

ODIR=obj 
LDIR =../lib 

_DEPS = hellomake.h 
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS)) 

_OBJ = hellomake.o hellofunc.o 
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ)) 


$(ODIR)/%.o: %.c $(DEPS) 
    $(CC) -c -o [email protected] $< $(CFLAGS) 

hellomake: $(OBJ) 
    gcc -o [email protected] $^ $(CFLAGS) 

.PHONY: clean 

clean: 
    rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~ 

Я хочу, чтобы понять, как это работает, и затем использовать его в библиотеке, которые я работаю. Может ли кто-нибудь указать мне, как настроить этот код? Я пробовал множество опций: "/home/bob/testcode/include/" с w/o " и /, и я до сих пор не работаю.

Цель состоит в том, чтобы получить работу с библиотекой, которая содержит более 60 файлов заголовков и 30 исходных файлов, из этих файлов мне нужно будет запустить 1 главный, поэтому мне действительно нужно заставить эту основную работу makefile работать, чтобы я мог расширить Это.

Общая задача эти линии Wich остаются открытыми:

IDIR =../include 
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS)) 

и

OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ)) 

За что я перепробовала множество различных заменителей пути но я об ошибке генерировать говорит:

gcc -o hellomake -I../include 
gcc: fatal error: no input files 
compilation terminated. 
make: *** [hellomake] Error 4 

Пожалуйста, помогите, спасибо заранее.

+1

Добро пожаловать в StackOverflow! Пожалуйста, используйте реальные слова с реальным значением о вашей реальной проблеме, а не о вещах типа «*, чтобы заставить его работать». Также, пожалуйста, напишите, что вы пробовали здесь. – Eregrith

+0

Надеюсь, теперь ясно, что это просто проблема синтаксиса, который, как мне кажется, «pathsubst» нуждается в правильном пути, который я предоставил, но я все еще получаю фатальную ошибку. – iBeyondPower

+0

Ваша ошибка довольно ясна. Вы не передали файл gcc, чтобы связать их с 'hellomake' – Eregrith

ответ

0

Простые определения Makefile кажутся мне в порядке, поскольку они появляются в вашем вопросе. Попробуйте указать параметры компилятора перед именами файлов:

$(ODIR)/%.o: %.c $(DEPS) 
    $(CC) $(CFLAGS) -c -o [email protected] $< 

hellomake: $(OBJ) 
    gcc $(CFLAGS) -o [email protected] $^ 

Вам необходимо запустить make из исходного каталога.

+0

Переключение порядка флагов не поможет ... проблема в том, что объектные файлы фактически отсутствуют в командной строке. – MadScientist

+0

@MadScientist: переключение параметров не является решением, но это целесообразно. Что касается того, почему '$ (OBJ)' пусто, либо OP не использует Gnu make, либо что-то не хватает в этом вопросе. – chqrlie

0

утилита make, без конкретной «цели», сделает первую цель в файле.

Первая цель обычно называется «все»

Для публикуемую файла, сделает объектные файлы и не будет продолжать делать исполняемым, когда цель не дано в командной строке

Предложить следующее:

SHELL := /bin/sh 

# following so could define executable name on command line 
# using the '-D' parameter 
#ifndef $(NAME) 
    NAME := hellomake 
#endif 

# use ':=' so macros only evaluated once 


MAKE := /usr/bin/make 
CC  := /usr/bin/gcc 

CFLAGS := -g -Wall -Wextra -pedantic 
LFLAGS := 

ODIR := obj 
IDIR := ../include 
LIBS := 
LIBPATH := ../lib 

DEPS := $(wildcard $(IDIR)/*.h) 
SRCS := $(wildcard *.c) 
OBJS := $(SRCS:.c=.o) 

.PHONY: all 
all: $(NAME) $(OBJS) 

$(ODIR)/%.o: %.c $(DEPS) 
    $(CC) $(CFLAGS) -c -o [email protected] $< -I$(DEPS) 

$(NAME): $(OBJS) 
    $(CC) $(LFLAGS) -o [email protected] $^ -L$(LIBPATH) -l$(LIBS) 

.PHONY: clean 
clean: 
    rm -f $(ODIR)/*.o 
    rm -f $(NAME) 


however, in your proposed project, 
not every source file needs every header file 
so should use either gcc or sed to generate the dependency files 
then use makefile rules similar to the following, 
which may need a little 'tweaking' for your project 
because the include files are not in the same directory 
as the source files: 

DEP := $(SRCS:.c=.d) 

# 
#create dependency files 
# 
%.d: %.c 
    # 
    # ========= START $< TO [email protected] ========= 
    $(CC) -M $(CPPFLAGS) $< > [email protected]$$$$;      \ 
    sed 's,\($*\)\.o[ :]*,\1.o [email protected] : ,g' < [email protected]$$$$ > [email protected];  \ 
    rm -f [email protected]$$$$ 
    # ========= END $< TO [email protected] ========= 

# 
# compile the .c files into .o files using the compiler flags 
# 
%.o: %.c %.d 
    # 
    # ========= START $< TO [email protected] ========= 
    $(CC) $(CCFLAGS) -c $< -o [email protected] -I$(IDIR) 
    # ========= END $< TO [email protected] ========= 
    # 

# include the contents of all the .d files 
# note: the .d files contain: 
# <filename>.o:<filename>.c plus all the dependencies for that .c file 
# I.E. the #include'd header files 
# wrap with ifneg... so will not rebuild *.d files when goal is 'clean' 
# 
ifneq "$(MAKECMDGOALS)" "clean" 
-include $(DEP) 
endif 
+0

Ваш отзыв. Правила шаблонов и правила суффиксов (неявные правила) не могут считаться объектами по умолчанию. Первое явное правило в make-файле выше - 'helloworld', и это цель, которая будет создана, если в командной строке не будет указана другая цель. Хотя добавление цели «все» - неплохая идея, она не нужна. Кроме того, ваш комментарий об использовании '-D' неверен: make не использует' -D' для определения переменных. И вы не можете писать инструкции препроцессора типа '# ifdef' в make-файле (это просто комментарий, чтобы сделать). Здесь есть и другие проблематичные вещи. – MadScientist

9

Ваш учебник пропагандирует плохие практики, вы должны избегать его ИМХО.

В правиле здесь:

$(ODIR)/%.o: %.c $(DEPS) 

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


Убедитесь, что вы организовать свой каталог проекта, как это:

+ include/ 
|-- all .h files here 
+ lib/ 
|-- all thirdparty library files (.a files) here 
+ obj/ 
|-- all .o files will be placed here 
+ src/ 
|-- all .c files here 
+ Makefile 

Тогда давайте рассмотрим процесс шаг за шагом, используя передовой опыт.

Во-первых, не определяйте ничего, если вам это не нужно. У Make есть много предопределенных переменных и функций, которые вы должны использовать, прежде чем пытаться сделать это вручную. На самом деле у него так много, что вы можете скомпилировать простой проект, даже не имея Makefile в каталоге вообще!

  1. Имя ваша конечная цель, то есть, ваш исполняемый файл:

    EXE = hellomake 
    
  2. Список ваш источник и построить выходные каталоги:

    SRC_DIR = src 
    OBJ_DIR = obj 
    
  3. Список ваши исходные файлы:

    SRC = $(wildcard $(SRC_DIR)/*.c) 
    
  4. Из исходных файлов, список объектных файлов:

    OBJ = $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o) # patsubst is far less readable 
    # You can also do it like that 
    OBJ = $(addprefix $(OBJ_DIR)/, $(notdir $(SRC))) 
    
  5. Got некоторые препроцессора флаги пройти? Продолжай.

    CPPFLAGS += -Iinclude # -I is a preprocessor flag, not a compiler flag 
    
  6. Есть некоторые флагов компилятора для добавления? Ну вот.

    CFLAGS += -Wall # some warnings about bad code 
    
  7. Есть несколько флагов-линкеров?

    LDFLAGS += -Llib # -L is a linker flag 
    
  8. У вас есть библиотеки третьих сторон, на которые нужно ссылаться?

    LDLIBS += -lm # Left empty if no libs are needed 
    

Ok, время свернуть некоторые рецепты теперь, когда наши переменные правильно заполнены.

Широко распространено, что цель по умолчанию должна быть вызвана all. Для простоты, она должна быть первой мишенью в вашем Makefile, и его предпосылка должна быть целью вы хотите построить при написании make в командной строке:

all: $(EXE) 

Перечислят предпосылки для построения исполняемого файла, и заполнить его рецепт, чтобы сказать, сделать то, что делать с этим:

$(EXE): $(OBJ) 
    $(CC) $(LDFLAGS) $^ $(LDLIBS) -o [email protected] 

некоторых быстрыми ноты:

  • $(CC) является встроенным переменным уже содером нин, что вам нужно при компиляции и компоновке в C,
  • Чтобы избежать ошибки компоновщика, вы должны ставить $(LDFLAGS)перед тем ваших объектных файлов и $(LDLIBS)после.
  • $(CPPFLAGS) и $(CFLAGS) являются бесполезным здесь, фаза компиляции уже завершена, здесь фаза связи.

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

$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c 
    $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o [email protected] 

Ok, теперь исполняемый файл должен строить красиво, мы можем очистить каталог сборки, если мы хотим:

clean: 
    $(RM) $(OBJ) 

Последняя вещь. Вы должны указать, когда правило не приводит к какой-либо целевой выход с .PHONY Sepcial правило:

.PHONY: all clean 

Конечный результат:

EXE = hellomake 

SRC_DIR = src 
OBJ_DIR = obj 

SRC = $(wildcard $(SRC_DIR)/*.c) 
OBJ = $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o) 

CPPFLAGS += -Iinclude 
CFLAGS += -Wall 
LDFLAGS += -Llib 
LDLIBS += -lm 

.PHONY: all clean 

all: $(EXE) 

$(EXE): $(OBJ) 
    $(CC) $(LDFLAGS) $^ $(LDLIBS) -o [email protected] 

$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c 
    $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o [email protected] 

clean: 
    $(RM) $(OBJ) 
+0

Спасибо! Хорошо написанное введение о том, как писать make-файлы :-) –

+0

Спасибо, человек, вы рок! – route

Смежные вопросы