SRC, OBJ 및 BIN 하위 디렉토리가있는 C 프로젝트 용 Makefile을 어떻게 만들 수 있습니까?
몇 달 전에 저는 Makefile
학교 과제를 위해 다음과 같은 일반 사항 을 생각해 냈습니다 .
# ------------------------------------------------
# Generic Makefile
#
# Author: yanick.rochon@gmail.com
# Date : 2010-11-05
#
# Changelog :
# 0.01 - first version
# ------------------------------------------------
# project name (generate executable with this name)
TARGET = projectname
CC = gcc -std=c99 -c
# compiling flags here
CFLAGS = -Wall -I.
LINKER = gcc -o
# linking flags here
LFLAGS = -Wall
SOURCES := $(wildcard *.c)
INCLUDES := $(wildcard *.h)
OBJECTS := $(SOURCES:.c=*.o)
rm = rm -f
$(TARGET): obj
@$(LINKER) $(TARGET) $(LFLAGS) $(OBJECTS)
@echo "Linking complete!"
obj: $(SOURCES) $(INCLUDES)
@$(CC) $(CFLAGS) $(SOURCES)
@echo "Compilation complete!"
clean:
@$(rm) $(TARGET) $(OBJECTS)
@echo "Cleanup complete!"
이것은 기본적으로 모든 컴파일 .c
하고 .h
생성하는 파일을 .o
파일 및 실행 파일 projectname
과 같은 폴더에있는 모든합니다.
자, 이것을 조금 밀고 싶습니다. 다음 디렉토리 구조로 C 프로젝트를 컴파일하기 위해 Makefile을 어떻게 작성할 수 있습니까?
./
./Makefile
./src/*.c;*.h
./obj/*.o
./bin/<executable>
즉, C 소스를 ./src/
로 컴파일 ./obj/
한 다음 모든 것을 링크하여 .NET에서 실행 파일을 생성 하는 Makefile을 갖고 싶습니다 ./bin/
.
다른 Makefile을 읽으려고했지만 위의 프로젝트 구조에서 작동하도록 만들 수는 없습니다. 대신 프로젝트가 모든 종류의 오류로 컴파일되지 않습니다. 물론 완전한 IDE (Monodevelop, Anjuta 등)를 사용할 수 있지만 솔직히 gEdit와 좋은 터미널을 선호합니다.
저에게 작업 솔루션을 제공 할 수있는 전문가가 있습니까? 또는 이것이 어떻게 수행 될 수 있는지에 대한 명확한 정보를 제공합니까? 감사합니다!
** 업데이트 (v4) **
최종 솔루션 :
# ------------------------------------------------
# Generic Makefile
#
# Author: yanick.rochon@gmail.com
# Date : 2011-08-10
#
# Changelog :
# 2010-11-05 - first version
# 2011-08-10 - added structure : sources, objects, binaries
# thanks to http://stackoverflow.com/users/128940/beta
# 2017-04-24 - changed order of linker params
# ------------------------------------------------
# project name (generate executable with this name)
TARGET = projectname
CC = gcc
# compiling flags here
CFLAGS = -std=c99 -Wall -I.
LINKER = gcc
# linking flags here
LFLAGS = -Wall -I. -lm
# change these to proper directories where each file should be
SRCDIR = src
OBJDIR = obj
BINDIR = bin
SOURCES := $(wildcard $(SRCDIR)/*.c)
INCLUDES := $(wildcard $(SRCDIR)/*.h)
OBJECTS := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
rm = rm -f
$(BINDIR)/$(TARGET): $(OBJECTS)
@$(LINKER) $(OBJECTS) $(LFLAGS) -o $@
@echo "Linking complete!"
$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
@$(CC) $(CFLAGS) -c $< -o $@
@echo "Compiled "$<" successfully!"
.PHONY: clean
clean:
@$(rm) $(OBJECTS)
@echo "Cleanup complete!"
.PHONY: remove
remove: clean
@$(rm) $(BINDIR)/$(TARGET)
@echo "Executable removed!"
첫째, 다음 $(OBJECTS)
과 같은 이유로 규칙에 문제가 있습니다.
- 그것은 일종의 무차별 적 이며 모든 개체의 모든 소스를 전제 조건으로 만듭니다.
- 종종 잘못된 소스를 사용 합니다 (
file1.o
및에서 발견 한대로file2.o
) - 개체에서 중지하는 대신 실행 파일을 빌드하려고합니다.
- the name of the target (
foo.o
) is not what the rule will actually produce (obj/foo.o
).
I suggest the following:
OBJECTS := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
$(CC) $(CFLAGS) -c $< -o $@
@echo "Compiled "$<" successfully!"
The $(TARGET)
rule has the same problem that the target name does not actually describe what the rule builds. For that reason, if you type make
several times, Make will rebuild the target each time, even though there is no reason to. A small change fixes that:
$(BINDIR)/$(TARGET): $(OBJECTS)
$(LINKER) $@ $(LFLAGS) $(OBJECTS)
@echo "Linking complete!"
Once that's all in order, you might consider more sophisticated dependency handling; if you modify one of the header files, this makefile will not know which objects/executables must be rebuilt. But that can wait for another day.
EDIT:
Sorry, I omitted part of the $(OBJECTS)
rule above; I've corrected it. (I wish I could use "strike" inside a code sample.)
You can add the -I
flag to the compiler flags (CFLAGS) to indicate where the compiler should look for source files , and the -o flag to indicate where the binary should be left:
CFLAGS = -Wall -I./src
TARGETPATH = ./bin
$(TARGET): obj
@$(LINKER) $(TARGETPATH)/$(TARGET) $(LFLAGS) $(OBJECTS)
@echo "Linking complete!"
In order to drop the object files into the obj
directory, use the -o
option when compiling. Also, look at the $@
and $<
automatic variables.
For example, consider this simple Makefile
CFLAGS= -g -Wall -O3
OBJDIR= ./obj
SRCS=$(wildcard *.c)
OBJS=$(SRCS:.c=.o )
all:$(OBJS)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $(OBJDIR)/$@
Update>
By looking at your makefile, I realize you are using the -o
flag. Good. Continue using it, but add a target directory variable to indicate where the output file should be written.
I have stopped writing makefiles these days, if your intention is to learn go ahead, else you have good makefile generator that comes with eclipse CDT. If you want some maintainability / multiple project support with in your build tree, have a look at the following -
https://github.com/dmoulding/boilermake I found this pretty good..!
'code' 카테고리의 다른 글
SWIG의 새로운 내장 기능과 함께 pythonappend를 사용하는 방법이 있습니까? (0) | 2020.10.15 |
---|---|
"효과보다 더 강력한 모나드 트랜스포머"-예? (0) | 2020.10.15 |
Mavericks로 느린 IOS 시뮬레이터 (0) | 2020.10.15 |
실행 중 셸 스크립트 편집 (0) | 2020.10.15 |
Android Studio의 "res"폴더로 이미지를 가져 오거나 복사하는 방법은 무엇입니까? (0) | 2020.10.14 |