【问题标题】:Can compile from the commandline but not from a makefile可以从命令行编译,但不能从 makefile 编译
【发布时间】:2014-03-04 14:12:50
【问题描述】:

我正在尝试编译一个由一个主 C 文件和两个辅助 C++ 文件组成的程序。 Main.c 依赖于 Wrapper.cpp,而后者又依赖于 Utility.cpp。具体来说,Main.c 调用 Wrapper.cpp 中定义的函数 func()

有趣的问题是我可以从命令行编译程序,但不能从 makefile 编译。我收到一个链接错误“main.o:对 func() 的引用未定义”。这可能主要是因为我了解 makefile 的概念,但它们可能变得太复杂了!

这是我从命令行编译的方式:

g++ -c Wrapper.cpp Utility.cpp
gcc -c Main.c Wrapper.cpp 
g++ -o myProg Main.o Wrapper.o Utility.o

这是我的生成文件:

# Rules to produce the targets

all: Main

Main: Utility.o Main.o Wrapper.o
        g++ -o myProg Utility.o Main.o Wrapper.o -lstdc++

# Rules to produce the object files

Utility.o: Utility.cpp
        g++ -c Utility.cpp

Wrapper.o: Wrapper.cpp Utility.cpp
        g++ -c Wrapper.cpp Utility.cpp

Main.o: Main.c Wrapper.cpp
        gcc -c Main.c Wrapper.cpp

我知道我可能会编译 Utility.cpp 和 Wrapper.cpp 两次,但我真的不知道如何编写编译规则。有人可以给我一些有用的见解。另外请不要给我复杂的makefile,因为我对它们很陌生。

【问题讨论】:

    标签: compilation linker makefile


    【解决方案1】:

    您的主要问题是您想象源文件依赖于其他源文件。这不是真的。你不需要Utility.cpp 的内容来编译Wrapper.cpp(除非你正在做一些奇怪的事情,比如#includeing 源文件到其他源文件)。

    同样,目标文件只依赖于它们正在编译的源文件,以及源文件包含的任何头文件。

    可执行文件依赖于构建程序所需的所有目标文件和库。

    因此,在最简单的情况下,您将编写(请注意,如果您使用 g++,则无需显式链接 -lstd++

    all: Main
    
    Main: Utility.o Main.o Wrapper.o
            g++ -o myProg Utility.o Main.o Wrapper.o
    
    # Rules to produce the object files
    
    Utility.o: Utility.cpp
            g++ -c Utility.cpp
    
    Wrapper.o: Wrapper.cpp
            g++ -c Wrapper.cpp
    
    Main.o: Main.c
            gcc -c Main.c
    

    虽然这很容易理解,但它确实消除了 make 的大部分功能。您可以编写此 makefile 以获得完全相同的结果:

    CXX = g++
    CC = gcc
    
    Main: Main.o Utility.o Wrapper.o
    

    就是这样,一切都完成了。

    【讨论】:

    • 非常感谢您的反馈。在上面简洁的makefile中,我如何使用变量CXX和CC?
    • 你不需要使用它们。 Make 有许多内置规则,这些规则使用许多预定义的变量。这个简洁的makefile利用了那些内置规则,其中一个告诉make如何从.cpp构建一个.o,另一个告诉make如何从.o构建一个程序(使用相同的前缀名称)。这些内置规则使用CXXCCCPPFLAGSCXXFLAGS 等变量。因此,通过设置这些变量,您可以更改规则的工作方式,而无需重新定义规则本身。请参阅 GNU make 手册,或运行 make -pf/dev/null 以查看所有规则。
    • 非常感谢您提供了非常有用且简单的 makefile。我写了下面的makefile XX = g++ CC = gcc CFLAGS = -std=c99 CXXFLAGS = -o myProg all: Main.o Utility.o Wrapper.o ... ...当我编译时,我不再得到原始参考未定义的错误,这很好。但是,不会生成可执行文件,即仅生成目标文件且未链接。当我在命令行上链接它们时,可以愉快地生成可执行文件。请帮我解决这个问题
    • 很难确切地看到您在未格式化的 cmets 中所做的事情,但通常将 -o 标志添加到 CXXFLAGSCFLAGS 是不正确的。 -o 标志特定于给定目标,而这些变量用于构建 every(分别为 C++ / C)目标。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-30
    • 1970-01-01
    • 2013-02-27
    • 2013-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多