make: implicit rule to link c++ project

后端 未结 7 1024
礼貌的吻别
礼貌的吻别 2020-12-31 04:52

I am working my way through a make tutorial. Very simple test projects I am trying to build has only 3 files: ./src/main.cpp ./src/implementation.cpp and

相关标签:
7条回答
  • 2020-12-31 05:28

    My answer (a neat solution): add

    LDLIBS = -lstdc++
    

    to the Makefile. According to the manual:

    Libraries (-lfoo) should be added to the LDLIBS variable instead.

    LDFLAGS are designed for library directory flags such as -L. On my Linux (Ubuntu 14.04), LDFLAGS = -lstdc++ produces

    cc -lstdc++ main.o -o main
    

    which does not work, while LDLIBS = -lstdc++ produces

    cc main.o -lstdc++ -o main
    

    which works. I have no idea why the order matters, but it makes sense according to the roles of the two built-in variables. I do not like to alias CC to CXX which seems like hacking, as well as confusing for readers.

    LDFLAGS v.s. LDLIBS

    I just tried and found that this compiler does not work for LDFLAGS = -lstdc++:

    • GCC 4.8.5 on Ubuntu 14.04

    but the following compilers accept LDFLAGS = -lstdc++:

    • Clang 3.4 on Ubuntu 14.04
    • GCC 4.7.2 on Debian Wheezy
    • Clang 7.3.0 (703.0.31) on OS X

    So it works most of the time, but is not guaranteed. If you want your makefile to be more portable, use LDLIBS which works on all the above environments.

    Why not other solutions above?

    1. Hasturkun: having main.o in the rule

      main: main.o implementation.o
      

      does not lead to an error. The main.o is not necessary, but it will still make.

    2. Simon Richter: the solution remove the need to track the header (which is really great), but OP wants an implicit rule. We can actually get the best of both:

      VPATH = src include
      CPPFLAGS = -I include -MMD -MP
      CXXFLAGS = -g -W -Wall -Werror
      LDLIBS = -lstdc++
      
      target = main
      lib = implementation.cpp
      objects = $(target:=.o) $(lib:.cpp=.o)
      
      $(target): $(objects)
      %.o: %.cpp %.d
      %.d: ;
      
      -include $(objects:.o=.d)
      
      clean::
          $(RM) $(target) $(objects) $(objects:.o=.d)
      

      which does what he did, as well as taking advantage of implicit rules. However, this complete solution should not be here, since it is not what the OP desire: OP just want to know why his Makefile does not work, and why. "Auto-Dependency Generation" is yet another huge topic deserving an entire tutorial (like this one). So I'm sorry, but his answer did not actually answer the question.

    3. Jerome: I used to change LINK.o from $(CC) $(LDFLAGS) $(TARGET_ARCH) to $(CXX) $(LDFLAGS) $(TARGET_ARCH) and it worked, but I prefer editing LDLIBS since LINK.o is not documented (and possibly not part of the public API) and not future-proof. I would call that a hack.

    0 讨论(0)
提交回复
热议问题