1

我刚刚学习 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)

主.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

主.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);
}

初始化.h:

#ifndef _INIT_
#define _INIT_
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
int init(SDL_Window**,SDL_Renderer**);
#endif

初始化.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.81g++ (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3和 SDL2 与图像库一起使用。

.cpp.o 的 makefile 规则和 $(EXE) 的规则有什么问题?另外,我是否正确使用#include?

4

1 回答 1

2

我认为问题出在这部分:

$(EXE): $(OBJS)
    $(CXX) $< $(LDFLAGS) -o $@

来自Make 的文档:$<是第一个先决条件的名称,所以这只会尝试与 main.o 链接。而是使用$^,这应该是所有先决条件。

于 2013-10-05T23:17:54.357 回答