私はちょうど SDL を学んでいて、twinklebear のチュートリアルを終えました。コードを複数のファイルに分割し始めた後、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つの関連ファイルがあります(問題の解決に役立つ場合を除き、これらをスキップしてください。スポイラーなどの内部でそれらを作成する方法がわかりません):makefile:
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;
}
終了.h:
#ifndef _QUIT_
#define _QUIT_
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
void quit(SDL_Window**,SDL_Renderer**);
#endif
終了.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 を適切に使用していますか?