Makefile对每个目标文件使用相同的源

时间:2014-05-27 07:05:49

标签: linux makefile

我有一个makefile,它应该将大量源文件编译成单个目标文件,然后将它们链接到一个共享库中。

源文件列表存储在变量SOURCES中。在编译目标文件的$(OBJECTS)目标期间,make运行命令$(CC)$(CFLAGS)-c $< -o $ @,其中$<是$(addprefix $(SRCPATH),$(SOURCES))。

这使命令对每个目标文件使用相同的源文件,给我一堆由Time.cpp制作的目标文件,并使链接器给我一堆已经在每个其他对象中定义的函数错误文件。如何让这个makefile工作?

# Variable setup
# BUILD - Either Debug or Release, specify when running make
# ARCH - Either 32 or 64, specify when running make
# CC - The compiler
# INC - The include directories
# CFLAGS - Compiler flags to use
# LDFLAGS - Linker flags to use
# OBJDIR - Directory for .o files
# BINARY - Output file path
# SOURCES - Path to each individual source file
# OBJECTS - Object files

ifeq ($(and $(ARCH),$(BUILD)),)
    $(error You have either not defined an architecture or build or both, please run "make BUILD=(DEBUG/RELEASE) ARCH=(32/64)")
endif

CC  = g++
INC = -I../../include -I../../extlibs/headers -I../../extlibs/headers/libfreetype/linux
LDFLAGS = -lX11 -lGL -lGLEW -lfreetype -ljpeg -lopenal -lsndfile
CFLAGS  = $(INC) -std=c++0x -fPIC -pthread -m$(ARCH)
OBJDIR  = ./obj/$(BUILD)/$(ARCH)-bit
BINPATH = ./bin/$(BUILD)/$(ARCH)-bit
BINARY  = $(BINPATH)/libTyrant$(ARCH).so
SRCPATH = ../../src/
SOURCES = System/Time.cpp System/Mutex.cpp System/Log.cpp System/Clock.cpp System/Sleep.cpp System/Unix/ClockImpl.cpp System/Unix/MutexImpl.cpp System/Unix/SleepImpl.cpp System/Unix/ThreadImpl.cpp System/Unix/ThreadLocalImpl.cpp System/Lock.cpp System/String.cpp System/ThreadLocal.cpp System/Thread.cpp Audio/SoundRecorder.cpp Audio/SoundBuffer.cpp Audio/SoundSource.cpp Audio/AudioDevice.cpp Audio/ALCheck.cpp Audio/Sound.cpp Audio/Music.cpp Audio/SoundFile.cpp Audio/SoundStream.cpp Audio/SoundBufferRecorder.cpp Audio/Listener.cpp Graphics/RectangleShape.cpp Graphics/VertexArray.cpp Graphics/Shader.cpp Graphics/ConvexShape.cpp Graphics/ImageLoader.cpp Graphics/Sprite.cpp Graphics/RenderTexture.cpp Graphics/BlendMode.cpp Graphics/Shape.cpp Graphics/CircleShape.cpp Graphics/TextureSaver.cpp Graphics/Vertex.cpp Graphics/RenderTextureImpl.cpp Graphics/Texture.cpp Graphics/Text.cpp Graphics/GLExtensions.cpp Graphics/Image.cpp Graphics/RenderTextureImplFBO.cpp Graphics/GLCheck.cpp Graphics/RenderTextureImplDefault.cpp Graphics/Color.cpp Graphics/Transformable.cpp Graphics/RenderTarget.cpp Graphics/Transform.cpp Graphics/View.cpp Graphics/RenderStates.cpp Graphics/RenderWindow.cpp Graphics/Font.cpp Window/JoystickManager.cpp Window/Joystick.cpp Window/Window.cpp Window/Keyboard.cpp Window/GlResource.cpp Window/Unix/JoystickImpl.cpp Window/Unix/WindowImplX11.cpp Window/Unix/GlxContext.cpp Window/Unix/Display.cpp Window/Unix/VideoModeImpl.cpp Window/Unix/InputImpl.cpp Window/VideoMode.cpp Window/Mouse.cpp Window/GlContext.cpp Window/Context.cpp Window/WindowImpl.cpp Network/Ftp.cpp Network/TcpListener.cpp Network/Packet.cpp Network/IpAddress.cpp Network/TcpSocket.cpp Network/Socket.cpp Network/Unix/SocketImpl.cpp Network/UdpSocket.cpp Network/SocketSelector.cpp Network/Http.cpp
OBJECTS = $(addprefix $(OBJDIR)/,$(SOURCES:.cpp=.o))

ifeq ($(BUILD),DEBUG)
    CFLAGS := $(CFLAGS) -g -pg -Og
endif

ifeq ($(BUILD),RELEASE)
    CFLAGS := $(CFLAGS) -s -O3
endif

all: clean $(addprefix $(SRCPATH),$(SOURCES)) $(BINARY)

$(BINARY): $(OBJECTS) $(BINPATH)
    $(CC) $(LDFLAGS) $(OBJECTS) -shared -o $@

$(OBJECTS): $(addprefix $(SRCPATH),$(SOURCES)) $(OBJDIR)
    $(CC) $(CFLAGS) -c $< -o $@

$(OBJDIR):
    mkdir ./obj
    mkdir ./obj/$(BUILD)
    mkdir $@
    mkdir $@/Audio
    mkdir $@/Graphics
    mkdir $@/Network
    mkdir $@/Network/Unix
    mkdir $@/System
    mkdir $@/System/Unix
    mkdir $@/Window
    mkdir $@/Window/Unix

$(BINPATH):
    mkdir ./bin
    mkdir ./bin/$(BUILD)
    mkdir $@

clean:
    rm -rf bin
    rm -rf obj

2 个答案:

答案 0 :(得分:3)

这里有几个问题。

假设所有源文件都在工作目录中,并且目标文件也属于该目录。您可以使用模式规则单独构建每个对象,而不是尝试使用一个命令构建所有对象:

%.o: %.cpp
    $(CC) $(CFLAGS) -c $< -o $@

然后你可以创建库的OBJECTS先决条件,而Make会处理它:

$(BINARY): $(OBJECTS)
    $(CC) $(LDFLAGS) $^ -shared -o $@

(一旦你有了这个工作,你可能还记得,Make已经有了内置规则,比如从foo.o构建foo.cpp,但暂时不介意。)

但是在你的构建方案中,你将它与其他问题结合起来:1)你有几个不同目录中的源文件,2)你想在其他地方构建对象,即3)在镜像源树的目录树中, 4)你在飞行中建立。

解决所有这些问题将会产生相当大的答案。你已经习惯了哪一个?

答案 1 :(得分:0)

我已经成功了,尽管它可能不是最佳的。我的解决方案:

$(BINARY): $(SOURCES) $(BINPATH)
    $(CC) $(LDFLAGS) $(OBJECTS) -shared -o $@

$(SOURCES): $(OBJDIR)
    $(CC) $(CFLAGS) -c $(SRCPATH)$@ -o $(patsubst %.cpp,%.o,$(OBJDIR)/$@)

基本上,我只是将目标从Object文件切换到源文件,将源路径附加到输入文件的目标名称,并将对象目录附加到目标名称,同时还使用patsubst更改文件扩展名从.cpp到.o。整个makefile很糟糕,我已经意识到了这一点,但是它起作用了,这对我的第一个makefile来说已经足够了。