C++ 如何使用main()构造支持多个目标的makefile

C++ 如何使用main()构造支持多个目标的makefile,c++,ubuntu,makefile,g++,C++,Ubuntu,Makefile,G++,我有一个makefile,在过去的几周里一直工作得非常好。然而,现在我用“main”为我的项目添加了另一个目标,它开始有点失控 CC=g++ CCOPTS=-g -w OBJS = $(BINDIR)/manager.o $(BINDIR)/rtngnode.o TARGETS = $(BINDIR)/manager $(BINDIR)/rtngnode BINDIR = build all: $(TARGETS) $(OBJS) clean: rm -f $(TARGETS) $

我有一个makefile,在过去的几周里一直工作得非常好。然而,现在我用“main”为我的项目添加了另一个目标,它开始有点失控

CC=g++
CCOPTS=-g -w

OBJS = $(BINDIR)/manager.o $(BINDIR)/rtngnode.o
TARGETS = $(BINDIR)/manager $(BINDIR)/rtngnode
BINDIR = build

all: $(TARGETS) $(OBJS)

clean:
    rm -f $(TARGETS) $(OBJS)

.PHONY: all clean

$(TARGETS): $(OBJS)
    $(CC) -o $@ $^ $(CFLAGS) $(LIBS)

$(BINDIR)/%.o: %.cpp
    $(CC) -c $(CCOPTS) -o $@ $<
CC=g++
CCOPTS=-g-w
OBJS=$(BINDIR)/manager.o$(BINDIR)/rtngnode.o
目标=$(BINDIR)/manager$(BINDIR)/rtngnode
BINDIR=build
全部:$(目标)$(OBJS)
清洁:
rm-f$(目标)$(OBJS)
.骗子:都是干净的
$(目标):$(OBJS)
$(CC)-o$@$^$(CFLAGS)$(LIBS)
$(BINDIR)/%.o:%.cpp
$(抄送)-c$(抄送)-o$@$<
我还是不太懂makefile。。。所以我不确定发生了什么。我有两个错误:

build/rtngnode.o: In function `__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<int const, Node> > >::new_allocator()':
/home/caleb/Documents/dev/tote2/mp2/rtngnode.cpp:5: multiple definition of `main'
build/manager.o:/home/caleb/Documents/dev/tote2/mp2/manager.cpp:161: first defined here
build/manager.o: In function `main':

manager.cpp:(.text+0xefb): undefined reference to `NetworkConnection::NetworkConnection(char const*, char const*)'
build/rtngnode.o:在函数“\uu gnu\u cxx::new\u allocator::new\u allocator()”中:
/home/caleb/Documents/dev/tote2/mp2/rtngnode.cpp:5:main的多重定义
build/manager.o:/home/caleb/Documents/dev/tote2/mp2/manager.cpp:161:首先在这里定义
build/manager.o:在函数“main”中:
manager.cpp:(.text+0xefb):对“NetworkConnection::NetworkConnection(char const*,char const*)”的未定义引用
在我的
rtngnode
目标中,我依赖于
tcpcon
类。。。我的
manager
目标也有一个
main()
引用。我很困惑。。。所以我甚至不确定我问的问题是否正确

我想我的问题是:

  • 对于OBJ和目标,会出现什么情况?我所有的.cpp文件?我所有的可执行文件
  • 我觉得这两个人在一起怎么样

    • 这里最重要的事情与您的Makefile无关(它看起来相当不错,只是缺少使用编译器警告):


      在所有源文件中,您的项目中可能只有一个
      main()

      您应该将可执行文件与包含“main”函数的一个源文件绑定

      正如链接器告诉您的,manager.cpp和rtngnode.cpp都有main函数的定义。您可能不想将它们组合在一起。我建议您从使用gcc命令手动构建代码开始(使用gcc-c生成对象文件,使用gcc-o生成可执行文件)。一旦理解了其中的逻辑,就继续编写makefile


      顺便说一句,如果你可以选择你的构建环境——从一个比makefile更不神秘的环境开始。

      因此,基本上,目标应该包含你的源文件(.cpp),然后编译这些源文件来创建对象文件,对象文件应该在OBJS变量中,然后将它们传递给链接器来创建可执行文件

      到目前为止,您的Makefile似乎是正确的,错误告诉您声明了两个main()函数,一个在rtngnode.cpp文件中,另一个在manager.cpp中,这是不可能发生的,否则机器将不知道在执行程序时调用哪个函数

      另外,未定义的引用错误通常是由链接器错误引起的,大多数情况下,当您使用#include将库包括到编译器中,而不是通常使用makefile中的LIBS变量将库包括到链接器中时,会发生此错误


      这是一本关于Makefiles的小教程,也是一本很好的读物。

      其他答案都是准确的,但我认为要理解的关键是这条规则:

      $(TARGETS): $(OBJS)
              $(CC) -o $@ $^ $(CFLAGS) $(LIBS)
      
      不是你想象的那样。这扩展到:

      $(BINDIR)/manager $(BINDIR)/rtngnode : $(BINDIR)/manager.o $(BINDIR)/rtngnode.o
              $(CC) -o $@ $^ $(CFLAGS) $(LIBS)
      
      Make不会试图推断目标与先决条件之间的神奇匹配;相反,make会对每个目标重复整个规则,但必须满足所有先决条件。上述规则与以下内容相同:

      $(BINDIR)/manager : $(OBJS)
              $(CC) -o $@ $^ $(CFLAGS) $(LIBS)
      
      $(BINDIR)/rtngnode : $(OBJS)
              $(CC) -o $@ $^ $(CFLAGS) $(LIBS)
      
      鉴于此,您可以看到问题所在:您正试图将所有对象链接到每个可执行文件中


      由于您的程序是从一个具有与程序名相同前缀的单一对象文件构建的,因此实际上根本不需要为它们编写规则;您可以依赖make的内置规则来构建程序。只要完全排除上述规则,它就会起作用。

      感谢您的回复;我认为对其他答案的误解是,我希望在我的项目中有多个共享公共类的可执行文件。我相信这并不罕见。我在atm机上工作,但是你相信上面的这个改变会解决我在多个可执行文件/多个电源上的问题吗?是的。您必须使用
      main
      指定哪个对象进入哪个可执行文件。不能将多个带有
      main
      (或任何其他重复符号)的对象放入同一个可执行文件中。