1

I have 2 classes: a class template list.t with definition and implementation, and ticker.h and ticker.cpp, along with a driver program, main.cpp. I want to compile main.cpp to get to main.x which uses both the ticker and list class. This is my makefile so far.

# makefile for fx project

CC = g++
CFLAGS = -g -Wall -Wextra

default: main.x

main.x: main.o ticker.o list.o
    $(CC) $(CFLAGS) -o $@  main.o list.o ticker.o

list.o: list.t
    $(CC) -c list.t

ticker.o: ticker.cpp
      $(CC) -c ticker.cpp list.t

main.o: list.t ticker.cpp main.cpp
    $(CC) -c  main.cpp ticker.cpp list.t

But on executing the command make I am getting the following error:

make
g++ -c  main.cpp ticker.cpp list.t
clang: warning: list.t: 'linker' input unused
g++ -c list.t
clang: warning: list.t: 'linker' input unused
g++ -g -Wall -Wextra -o main.x  main.o list.o ticker.o
clang: error: no such file or directory: 'list.o'
make: *** [main.x] Error 1

List.t - (without implementations)

#ifndef LIST_T
#define LIST_T

#include <iostream>

template <typename T>
class List
{
public:
  // constructors
  List();
  List(T);
  List(const List&);
  ~List();

  // member functions
  List& operator = (const List&);
  void PushFront (const T&);
  void PushBack (const T&);
  T PopFront();
  T PopBack();
  T& Front();
  T& Back();
  const T& Front() const;
  const T& Back() const;
  size_t Size() const;
  bool Empty() const;
  void Clear();
  void Display (std::ostream&, char = '\0') const;

    //private vars
  private:
    class Link
    {
      Link (const T& t) : element_(t), nextLink_(0), previousLink_(0) {};
      T element_;
      Link* nextLink_;
      Link* previousLink_;
      friend class List<T>;
    };
    Link* firstLink_;
    Link* lastLink_;
  };

I am sure this is a simple error, and I have scoured google for this error message, but I either am not fully understanding their solutions, or they are not working for me. Either way, let me know if you have a solution to this problem, or any other comments on the quality and structure of this makefile. Also any knowledge on why my flags are apparently being unused would be greatly appreciated!

Thanks!

Free Url
  • 1,836
  • 2
  • 15
  • 28
  • Why the `-c` option if you try to link an executable? – πάντα ῥεῖ Jan 07 '16 at 22:28
  • Why is your clang called g++? – SergeyA Jan 07 '16 at 22:42
  • @SergeyA, not sure. Running through terminal on mac using bash. don't know enough about compilers at all to tell you. As for the -c, that is what R Sahu was explaining to me down here I believe. – Free Url Jan 07 '16 at 22:58
  • @Zroach You shouldn't pass a _template file_ directly to the compiler. Include that where needed. The implementation must appear in the included code as well. See the whole story here: [Why can templates only be implemented in the header file?](http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file). – πάντα ῥεῖ Jan 07 '16 at 23:03
  • Thanks @R Sahu, I am on to my next error! Couldn't have done it without you. Also thank to @pi(russianstuff) I think I am understanding why I can't, because template files are determined dynamically based off of what type T it is implemented with, therefore cannot be compiled beforehand. Maybe not, I am gonna read what you posted man. Thanks for the help guys. – Free Url Jan 07 '16 at 23:05
  • This line : main.o: list.t ticker.cpp main.cpp $(CC) -c main.cpp ticker.cpp list.t should be main.o: main.cpp $(CC) -c main.cpp and same for the ticker.o, you shall not specify list.t on the command line – Celine NOEL Jan 07 '16 at 23:13
  • @Zroach Note: It's not russian ... – πάντα ῥεῖ Jan 07 '16 at 23:20
  • @πάνταῥεῖ Greek?? What does it mean? – Free Url Jan 07 '16 at 23:33
  • @Zroach Check my profile, it's well explained there. – πάντα ῥεῖ Jan 07 '16 at 23:33

2 Answers2

0

You need -c in the command line only when you compile source files to create object files.

Change

main.x: main.o ticker.o list.o
        $(CC) $(CFLAGS) -c main.o list.o ticker.o

to

main.x: main.o ticker.o list.o
        $(CC) $(CFLAGS) -o $@ main.o list.o ticker.o
                        ^^^^^

$@ is the file name of the target of the rule.

See GNU make: Automatic Variables for more such variables.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • I am still getting the error: < br/ > `g++ -c main.cpp ticker.cpp list.t clang: warning: list.t: 'linker' input unused g++ -c list.t clang: warning: list.t: 'linker' input unused g++ -g -Wall -Wextra -o main.x main.o list.o ticker.o clang: error: no such file or directory: 'list.o' make: *** [main.x] Error 1` – Free Url Jan 07 '16 at 22:43
  • `list.o` is missing. Try `make list.o` and see what you get. – R Sahu Jan 07 '16 at 22:46
  • `g++ -c list.t clang: warning: list.t: 'linker' input unused` – Free Url Jan 07 '16 at 22:47
  • could the dependencies I have within the individual files affect this? Also I wasn't 100% on how to compile a template file – Free Url Jan 07 '16 at 22:48
  • What are the contents of `list.t`? – R Sahu Jan 07 '16 at 22:49
  • I have added its contents to my original post. I can add the implementations but I didn't think that would be helpful. – Free Url Jan 07 '16 at 22:56
  • @Zroach, you don't need to compile that file. Remove the `list.o` target. Remove `list.o` from the list of files to use to build `main.x`. – R Sahu Jan 07 '16 at 22:59
0

The makefile should be the following:

CC = g++
CPPFLAGS = -g -Wall -Wextra

default: main.x

main.x: main.o ticker.o
    $(CC) -o $@  main.o ticker.o

ticker.o: ticker.cpp
    $(CC) -c ticker.cpp $(CPPFLAGS) 

main.o: list.t main.cpp
    $(CC) -c  main.cpp $(CPPFLAGS) 

You don't compile a template file. The implementation should be inside the same file as the class declaration (putting the .hpp extension would be better also). Then the template must be included in the other files. For example, in the main, put a #include "list.t" directive.

Celine NOEL
  • 155
  • 9
  • You are correct as I finally got to above that the template file isn't compiled. it is formatted correctly with implementation and definition in the same file. I made a new makefile with the code you have above and got the following output: `makefile:7: *** missing separator. Stop.` – Free Url Jan 07 '16 at 23:26
  • Missed a space actually on that line. I'm gonna edit it. – Celine NOEL Jan 07 '16 at 23:30
  • And also, replace the sequences of four spaces by a tabulation if that's not done automatically. – Celine NOEL Jan 07 '16 at 23:37
  • output was: `g++ -c main.cpp g++ -c ticker.cpp g++ -g -Wall -Wextra -o main.x main.o ticker.o Undefined symbols for architecture x86_64: "operator>>(std::__1::basic_istream >&, Ticker&)", referenced from: _main in main.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) make: *** [main.x] Error 1` with main.o and ticker.o, but no main.x – Free Url Jan 07 '16 at 23:47
  • It seems that you declared an operator looking like that somewhere, operator>>(std::__1::basic_istream >&, Ticker&), but you forgot to add the implementation into the cpp files you're compiling. Can I see your main.cpp ? – Celine NOEL Jan 07 '16 at 23:57
  • And concerning your unused flags, they need to be used when building the .o instead of the linking process. I'll reedit the post. – Celine NOEL Jan 07 '16 at 23:59
  • Ty for post re-edit, and the continued work with me. The only class with overloaded >> is ticker and that is implemented. Was thinking it was an inclusion error but header file is included in cpp. I will have to look at it more tomorrow, unfortunately. Thanks for the help – Free Url Jan 08 '16 at 00:33
  • You may have forgotten to put the implementation in ticker.cpp, or made a mistake in the prototype while coding it. Also, when it comes to error like this, it's never inclusion problems, it's a linker error. It means that something you have declared and used somewhere has not been defined (= implemented). – Celine NOEL Jan 08 '16 at 00:39