我刚学习SDL并完成了twinklebear tutorials。在我开始将代码拆分成多个文件后,我的makefile停止工作,我不得不手动编译它。它说:
make: *** No rule to make target `main.o', needed by `ooptest'. Stop.
当我使用.cxx.o:
之类的规则时,或者,如果我为所有.cxx
制定单独的规则:
g++ main.o -L/usr/local/lib -lSDL2 -Wl,-rpath=/usr/local/lib -o ooptest
main.o: In function `main':
main.cxx:(.text+0x247): undefined reference to `init(SDL_Window**, SDL_Renderer**)'
main.cxx:(.text+0x42e): undefined reference to `quit(SDL_Window**, SDL_Renderer**)'
collect2: error: ld returned 1 exit status
make: *** [ooptest] Error 1
我知道这是因为它只链接main.o而没有其他文件,但我不知道为什么。
以下是7个相关文件(只是跳过这些文件,除非它们有助于解决问题,我不知道如何在剧透或其他内容中制作它们): 生成文件:
CXX = g++
SRCS = main.cxx init.cxx quit.cxx
SDL_LIB = -L/usr/local/lib -lSDL2 -Wl,-rpath=/usr/local/lib
SDL_INCLUDE = -I/usr/local/include
CXXFLAGS = -Wall -c -std=c++11 $(SDL_INCLUDE)
LDFLAGS = $(SDL_LIB)
OBJS = $(SRCS:.cxx=.o)
EXE = ooptest
all: $(EXE) $(SRCS)
$(EXE): $(OBJS)
$(CXX) $< $(LDFLAGS) -o $@
main.o:
$(CXX) $(CXXFLAGS) main.cxx -o $@
init.o:
$(CXX) $(CXXFLAGS) init.cxx -o $@
quit.o:
$(CXX) $(CXXFLAGS) quit.cxx -o $@
#.cxx.o:
# $(CXX) $(CXXFLAGS) $< -o $@
clean:
rm *.o && rm $(EXE)
main.h:
#ifndef _MAIN_
#define _MAIN_
#include <string>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
const int WIDTH=640;
const int HEIGHT=480;
void lgErr(std::string);
SDL_Texture*loadTex(const std::string&,SDL_Renderer*);
void renderTex(SDL_Texture*,SDL_Renderer*,int,int);
int main(void);
#endif
main.cxx:
#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include "main.h"
#include "init.h"
#include "quit.h"
using namespace std;
void lgErr(string msg){
cout<<msg<<" error: "<<SDL_GetError()<<endl;
}
SDL_Texture* loadTex(const string &file,SDL_Renderer *ren){
SDL_Texture *tex=0;
SDL_Surface *img=SDL_LoadBMP(file.c_str());
if(img){
tex=SDL_CreateTextureFromSurface(ren,img);
SDL_FreeSurface(img);
if(tex==0)lgErr("CreateTextureFromSurface");
}else
lgErr("LoadBMP");
return tex;
}
void renderTex(SDL_Texture *tex,SDL_Renderer *ren,int x,int y){
SDL_Rect dst;
dst.x=x;dst.y=y;
SDL_QueryTexture(tex,NULL,NULL,&dst.w,&dst.h);
SDL_RenderCopy(ren,tex,NULL,&dst);
}
int main(){
SDL_Window *win;
SDL_Renderer *ren;
init(&win,&ren);
SDL_Texture *bg=loadTex("bg.bmp",ren);
SDL_Texture *fg=loadTex("fg.bmp",ren);
if(bg==0 || fg==0)return 4;
int bw,bh;
SDL_QueryTexture(bg,NULL,NULL,&bw,&bh);
SDL_RenderClear(ren);
for(int i=0;i<WIDTH;i+=bw)
for(int j=0;j<HEIGHT;j+=bh)
renderTex(bg,ren,i,j);
int fw,fh;
SDL_QueryTexture(fg,NULL,NULL,&fw,&fh);
int x=WIDTH/2-fw/2;
int y=HEIGHT/2-fh/2;
renderTex(fg,ren,x,y);
SDL_RenderPresent(ren);
SDL_Delay(2000);
SDL_DestroyTexture(bg);
SDL_DestroyTexture(fg);
quit(&win,&ren);
}
init.h里:
#ifndef _INIT_
#define _INIT_
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
int init(SDL_Window**,SDL_Renderer**);
#endif
init.cxx:
#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include "main.h"
#include "quit.h"
using namespace std;
int init(SDL_Window** win,SDL_Renderer** ren){
if(SDL_Init(SDL_INIT_EVERYTHING)!=0){
lgErr("SDL_Init");
return 1;
}
*win=SDL_CreateWindow("Lesson 2",100,100,WIDTH,HEIGHT,SDL_WINDOW_SHOWN);
if(*win==0){
lgErr("CreateWindow");
return 2;
}
*ren=SDL_CreateRenderer(*win,-1,SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if(*ren==0){
lgErr("CreateRenderer");
return 3;
}
return 0;
}
quit.h:
#ifndef _QUIT_
#define _QUIT_
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
void quit(SDL_Window**,SDL_Renderer**);
#endif
quit.cxx:
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include "main.h"
#include "init.h"
void quit(SDL_Window** win,SDL_Renderer** ren){
SDL_DestroyRenderer(*ren);
SDL_DestroyWindow(*win);
SDL_Quit();
}
最后,我将GNU Make 3.81
,g++ (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3
和SDL2与图片库一起使用。
.cpp.o的makefile规则和$(EXE)的规则有什么问题?另外,我正在使用#include吗?
答案 0 :(得分:2)
我认为问题在于这一部分:
$(EXE): $(OBJS)
$(CXX) $< $(LDFLAGS) -o $@
来自Make's documentation:$<
是第一个先决条件的名称,因此这只会尝试与main.o链接。相反,请使用$^
,这应该是所有先决条件。