我有一个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
答案 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来说已经足够了。