【问题标题】:makefile linking does not work (although no error message)makefile 链接不起作用(尽管没有错误消息)
【发布时间】:2015-06-24 13:00:15
【问题描述】:

我对我制作的 Makefile 有疑问。它由一个内部带有 main() 的 .cpp 文件组成,我想从中创建可执行文件。在输入终端 ma​​ke 命令时,我得到以下信息:

g++ STutorial.o -o MyExecutable
g++: error: STutorial.o: No such file or directory
g++: fatal error: no input files

首先 ma​​ke STutorial.o(.o 创建)然后 ma​​ke 得到这个:

g++ STutorial.o -o MyExecutable
STutorial.o: In function `main':
STutorial.cpp:(.text+0x47a): undefined reference to `alcOpenDevice'

首先,为什么ma​​ke不从头开始? 其次,为什么这个引用是未定义的,就好像我没有包含库一样,我在 Makefile 以及 STutorial.cpp 文件中都这样做了。 你能帮帮我吗?我正在阅读我会做错什么并且看不到任何线索。 (我是初学者,也许错误是菜鸟,我提前道歉但不能单独理解) 生成文件:

FLAGS += -std=c++11
CCX=g++
FLAGS +=-c -Wall #for compilation, for warning
FLAGS += -lopenal -lSDL
all: MyExecutable
MyExecutable:
    $(CXX) STutorial.o -o MyExecutable
STutorial.o: STutorial.cpp
    $(CXX) $(FLAGS) STutorial.cpp

【问题讨论】:

  • 问题是什么?我看到您正在寻求帮助,但也许可以构建您的问题以识别您要解决的任务,突出您尝试过的内容,然后寻求帮助以克服特定问题,这会帮助您获得更好的答案。

标签: c++ linux makefile linker


【解决方案1】:

你的makefile应该是这样的:

CCX=g++
FLAGS +=-c -Wall #for compilation, for warning
LINK_FLAGS += -lopenal -lSDL
all: MyExecutable
MyExecutable: Stutorial.o
    $(CXX) STutorial.o -o MyExecutable $(LINK_FLAGS) 
STutorial.o: STutorial.cpp
    $(CXX) $(FLAGS) STutorial.cpp

解释:

您的MyExecutable 依赖于Stutorial.o,而Stutorial.cpp 又依赖于Stutorial.cpp

现在-c 标志只能与.cpp 文件一起使用来创建目标文件,而不是与已经创建的.o 文件一起使用。

因此,您应该有两个标志:FLAGS 用于编译,LINK_FLAGS 用于在制作可执行文件期间链接库。

【讨论】:

  • 谢谢你的解释,我现在清楚了。在应用您的解决方案时,我得到未定义的参考错误。但是在输入控制台 g++ STutorial.cpp -lopenal -lSDL 时,一切都很好!这怎么可能(最后一个创建了我 a.out,但我也想影响名称并了解它的工作方式。)
  • 尝试在makefile中将$(LINK_FLAGS)放在MyExecutable之后。
  • 在您的库名称之前使用库位置标志-L 也是一个好习惯,否则编译器将无法找到您的库。
  • 错误(与 $(LINK_FLAGS) 一致):缺少分隔符。停止。
  • 问题解决了,留下看不见的空白,扭曲了意图
【解决方案2】:

您的可执行规则是问题所在:

MyExecutable:
    $(CXX) STutorial.o -o MyExecutable

它有一个目标 (MyExecutable) 和一个配方 ($(CXX) ...),看起来都不错。但它的先决条件是什么? MyExecutable 确实 有先决条件 - 它需要 STutorial.o 才能生成二进制文件!你需要明确告诉 make :

MyExecutable: STutorial.o
    $(CXX) STutorial.o -o MyExecutable

否则,您是在告诉 make 您要构建 allall 取决于 MyExecutableMyExecutable 不依赖任何东西,因此STutorial.o 的规则永远不会运行。

至于链接器错误,你没有在你需要的库中链接,所以你应该定义如下:

LFLAGS += -lopenal -lSDL

MyExecutable: STutorial.o
    $(CXX) STutorial.o $(LFLAGS) -o MyExecutable

【讨论】:

  • 我根据上面的 bavesh 建议创建了 makefile。我仍然得到链接器错误。但是,当简单地输入 g++ STutorial.cpp -lopenal -lSDL 时,它不会出错。区别在哪里?
  • @beginh 您在编译二进制文件时没有向 g++ 提供 -lopenal -lSDL 标志。查看更新的答案。
  • 谢谢!对于那些跟踪讨论的人:将用于链接的库放在适当的位置,以便在对象之后和之前 -o
【解决方案3】:

您的 Makefile 中存在一些问题:

FLAGS +=-c -Wall #for compilation, for warning
FLAGS += -lopenal -lSDL

您在此处重新定义 FLAGS 变量。 所以你应该为你的编译器和链接器标志设置一个不同的变量:

CFLAGS +=-c -Wall #for compilation, for warning
LDFLAGS += -lopenal -lSDL

现在,为了给出一个完整的答案,而不是仅仅解决您当前的问题,我将尝试展示如何使 Makefile 更加灵活:

  1. 从源头开始——你也应该为它们设置一个变量;在项目中添加/删除源文件时很有用:

    SOURCES = STutorial.cpp
    
  2. 为您的目标文件定义一个变量(这将在链接时派上用场):

    OBJ = $(SOURCES:.cpp=.o)
    
  3. 将所有源文件编译成目标文件:

    .cpp.o:
        $(C++) $(CFLAGS) -o $@ $<
    
  4. 使用已编译的目标文件链接您的二进制文件:

    $(MyExecutable): $(OBJ)
       $(C++) $(LDFLAGS) $(OBJ) -o $@ 
    
  5. 为完整性添加一个干净的命令(删除二进制文件和目标文件):

    clean:
        $(RM) $(EXECUTABLE) $(OBJ) 
    

现在,把它们放在一起:

CCX=g++
CFLAGS +=-c -Wall -std=c++11#for compilation, for warning
LDFLAGS += -lopenal -lSDL
SOURCES = STutorial.cpp

OBJ = $(SOURCES:.cpp=.o)

all: $(MyExecutable)

$(MyExecutable): $(OBJ)
       $(CCX) $(LDFLAGS) $(OBJ) -o $@ 

.cpp.o:
        $(CCx) $(CFLAGS) -o $@ $<

 clean:
        $(RM) $(EXECUTABLE) $(OBJ) 

这应该允许您灵活地构建、重建、清理您的项目。

【讨论】:

  • 你应该清理一些这些规则,有很多错误的输入。
【解决方案4】:

你应该这样做:

g++ -std=c++11 -Wall  -lopenal -lSDL STutorial.cpp -o MyExecutable

【讨论】:

  • 但这将 MyExecutable 创建为对象,而不是可执行文件。你能解释一下吗?
  • 删除-c标志,它将是可执行的。
猜你喜欢
  • 1970-01-01
  • 2019-11-26
  • 2019-11-13
  • 1970-01-01
  • 1970-01-01
  • 2016-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多