Thread: Linking multiple source files: Undefiled Reference to...

  1. #1

    Linking multiple source files: Undefiled Reference to...

    I have about 9 .o files, and make compiles quickly and quietly until it gets to the part where it links them all together... here are the errors and makefile. I won't post the code unless i need to, one of the source files is >500 lines long.

    Code:
    typescript.ts
    -------------
    (ethereal@linbox:~/c++/nemoserv)$ make clean ; make
    rm -f *.o
    g++ -ggdb -pthread -c nemoserv.cpp
    g++ -ggdb -pthread -c nemoirc.cpp
    g++ -ggdb -pthread -c logger.cpp
    g++ -ggdb -pthread -c ircfunc.cpp
    g++ -ggdb -pthread -c sockfunc.cpp
    g++ -ggdb -pthread -c ircserver.cpp
    g++ -ggdb -pthread -c blackjack.cpp
    g++ -ggdb -pthread -c cards.cpp
    g++ -ggdb -pthread nemoserv.o nemoirc.o logger.o ircfunc.o sockfunc.o ircserver.o cards.o blackjack.o -o nemoserv
    blackjack.o: In function `blackjackgame::dealTo(char *, char *, ircserver, bool)':
    /home/ethereal/c++/nemoserv/blackjack.cpp:45: undefined reference to `deck::deal(card &)'
    /home/ethereal/c++/nemoserv/blackjack.cpp:47: undefined reference to `card::suitText(void)'
    /home/ethereal/c++/nemoserv/blackjack.cpp:47: undefined reference to `card::rankText(void)'
    /home/ethereal/c++/nemoserv/blackjack.cpp:48: undefined reference to `deck::deal(card &)'
    /home/ethereal/c++/nemoserv/blackjack.cpp:50: undefined reference to `card::suitText(void)'
    /home/ethereal/c++/nemoserv/blackjack.cpp:50: undefined reference to `card::rankText(void)'
    collect2: ld returned 1 exit status
    make: *** [nemoserv] Error 1
    (ethereal@linbox:~/c++/nemoserv)$ 
    -------------
    Code:
    makefile
    --------
    # Makefile for nemoserv.
    
    CC = g++
    CFLAGS = -ggdb -pthread
    
    nemoserv : nemoserv.o nemoirc.o logger.o ircfunc.o sockfunc.o ircserver.o blackjack.o cards.o
    	$(CC) $(CFLAGS) nemoserv.o nemoirc.o logger.o ircfunc.o sockfunc.o cards.o blackjack.o ircserver.o -o nemoserv
    
    nemoserv.o : nemoserv.cpp sockfunc.h ircfunc.h nemoirc.h logger.h ircserver.h
    	$(CC) $(CFLAGS) -c nemoserv.cpp
    
    nemoirc.o : nemoirc.cpp sockfunc.h ircfunc.h nemoirc.h logger.h ircserver.h
    	$(CC) $(CFLAGS) -c nemoirc.cpp
    
    ircserver.o : ircserver.cpp sockfunc.h ircfunc.h nemoirc.h logger.h ircserver.h
    	$(CC) $(CFLAGS) -c ircserver.cpp
    
    logger.o : logger.cpp logger.h
    	$(CC) $(CFLAGS) -c logger.cpp
    
    ircfunc.o : ircfunc.cpp ircfunc.h
    	$(CC) $(CFLAGS) -c ircfunc.cpp
    
    sockfunc.o : sockfunc.cpp sockfunc.h
    	$(CC) $(CFLAGS) -c sockfunc.cpp
    
    blackjack.o : blackjack.cpp cards.cpp blackjack.h cards.hpp
    	$(CC) $(CFLAGS) -c blackjack.cpp
    
    cards.o : cards.cpp cards.hpp
    	$(CC) $(CFLAGS) -c cards.cpp
    
    clean :
    	rm -f *.o
    --------
    Compilers:
    GCC on Red Hat 8.1 (Primary)
    GCC on Mac OS X 10.2.4 (Secondary)

    Others:
    MinGW on XP

  2. #2
    cards.cpp
    Code:
    // +++Date last modified: 05-Jul-1997
    /*
    **  CARDS.CPP - Playing card classes
    **
    **  public domain by Bob Stout
    */
    
    #include <stddef.h>
    #include <stdlib.h>
    #include <time.h>
    #include <string.h>
    #include "cards.h"
    
    const char *suits[] = {"Diamonds", "Clubs", "Hearts", "Spades"};
    const char *cards[] = {"Ace", "Deuce", "3", "4", "5", "6", "7", "8", "9",
                           "10", "Jack", "Queen", "King"};
    
    
    inline card::card(void)
    {
          rank_ = Rank_Error;
          suit_ = Suit_Error;
    }
    
    inline card::card(cardSuit s, cardRank r)
    {
          rank_ = r;
          suit_ = s;
    }
    
    inline cardRank card::rank(void)
    {
          return rank_;
    }
    
    inline cardSuit card::suit(void)
    {
          return suit_;
    }
    
    inline char * card::rankText(void)
    {
          return (char *)cards[(int)rank_ - 1];
    }
    
    inline char * card::suitText(void)
    {
          return (char *)suits[(int)suit_];
    }
    
    inline void card::set_rank(cardRank r)
    {
          rank_ = r;
    }
    inline void card::set_suit(cardSuit s)
    {
         suit_ = s;
    }
    
    inline void card::set_card(cardSuit s, cardRank r)
    {
          rank_ = r;
          suit_ = s;
    }
    
    inline void card::get_card(cardSuit &s, cardRank &r)
    {
          r = rank_;
          s = suit_;
    }
    
    
    deck::deck(void)
    {
          int n = 0;
    
          for (int s = int(Diamond); s <= int(Spade); ++s)
          {
                for (int c = int(Ace); c <= int(King); ++c)
                {
                      card_[n].set_rank(cardRank(c));
                      card_[n].set_suit(cardSuit(s));
                      ++n;
                }
          }
          top = 0;
    }
    
    inline void deck::deal(class card &c)
    {
          if (top < Deck_Size)
                c = card_[top++];
    }
    
    inline int deck::cards_left(void)
    
    {
          return int(Deck_Size - top);
    }
    
    void deck::shuffle(void)
    {
          int used[Deck_Size], posn = 0;
    
          srand((unsigned)time(NULL) | 1);
          memset(used, 0, Deck_Size * sizeof(int));
    
          for (int s = int(Diamond); s <= int(Spade); ++s)
          {
                for (int c = int(Ace); c <= int(King); ++c)
                {
                      posn = (posn + rand()) % Deck_Size;
                      while (used[posn])
                            posn = ++posn % Deck_Size;
                      card_[posn].set_rank(cardRank(c));
                      card_[posn].set_suit(cardSuit(s));
                      used[posn] = -1;
                }
          }
          top = 0;
    }
    cards.hpp
    Code:
    // +++Date last modified: 05-Jul-1997
    /*
    **  CARDS.HPP - Declare card classes
    **
    **  public domain by Bob Stout
    */
    
    #ifndef CARDS__HPP
    #define CARDS__HPP
    
    const int Card_Error = -1;
    const int Deck_Size  = 52;
    
    typedef enum {Rank_Error = Card_Error, Ace = 1, Deuce, Trey, Spot_4, Spot_5,
                  Spot_6, Spot_7, Spot_8, Spot_9, Spot_10, Jack = 11, Queen = 12,
                  King = 13} cardRank;
    
    typedef enum {Suit_Error = Card_Error, Diamond, Club, Heart, Spade} cardSuit;
    
    
    class card
    {
    private:
          cardRank rank_;
          cardSuit suit_;
    
    public:
          card(void);
          card(cardSuit s, cardRank r);
          cardRank rank(void);
          cardSuit suit(void);
          void get_card(cardSuit &s, cardRank &r);
          char *rankText(void);
          char *suitText(void);
          void set_rank(cardRank r);
          void set_suit(cardSuit s);
          void set_card(cardSuit s, cardRank r);
    };
    
    class deck
    {
    private:
          class card card_[Deck_Size];
          unsigned top;
    
    public:
          deck(void);
          void shuffle(void);
          void deal(class card &c);
          int cards_left(void);
    };
    
    #endif // CARDS__HPP
    ~Inquirer
    Compilers:
    GCC on Red Hat 8.1 (Primary)
    GCC on Mac OS X 10.2.4 (Secondary)

    Others:
    MinGW on XP

  3. #3
    And here is the only part of blackjack.cpp that actually deals with the blackjack game/cards/deck.

    blackjack.cpp
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string.h>
    #include <netdb.h>
    //#include <regex.h>		// Regular Expression (POSIX) Matching
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <sys/socket.h>
    #include <iostream>
    #include <fstream>		// For cout redirecting
    #include <string>
    #include "ircserver.h"
    #include "nemoirc.h"
    #include "blackjack.h"		// My header!
    #include "cards.h"		// For the blackjack game
    
    
    #define MAX_HAND 15
    
    //External variables
    //extern ircserver serv;
    //extern ircserver srvr;
    //extern parsedArgs opts;
    
    void blackjackgame::shuffle() {
    	dDeck.shuffle();
    	nPlayers = 0;
    	memset(cPlayers, '\0', 30*30);
    }
    void blackjackgame::dealTo(char *nick, char *chan, ircserver serv, bool welc) {
    	card temp;
    	if (welc) {
    		serv << "NOTICE " << nick << " :Welcome to IRC BlackJack v0.0" << serv.endl;
    		serv << "NOTICE " << nick << " :I am going to deal you two cards," << serv.endl;
    		serv << "NOTICE " << nick << " :one publicly, and one privately." << serv.endl;
    		serv << "NOTICE " << nick << " :\"hit\" gets you a new card," << serv.endl;
    		serv << "NOTICE " << nick << " :\"stay\" goes to the next person." << serv.endl;
    		serv << "NOTICE " << nick << " :Please only go when you are asked." << serv.endl;
    	}
    	nPlayers++;
    	//Players[nPlayers] = nick;
    	//Hands[nPlayers].clear();
    	dDeck.deal(temp);
    	//Hands[nPlayers].addCard(temp);
    	serv << "NOTICE " << nick << " :" << nick << ": " << temp.rankText() << " of " << temp.suitText() << serv.endl;
    	dDeck.deal(temp);
    	//Hands[nPlayers].addCard(temp);
    	serv << "PRIVMSG " << chan << " :" << nick << ": " << temp.rankText() << " of " << temp.suitText() << serv.endl;
    }
    and blackjack.h
    Code:
    #ifndef BLACKJACK_H
    #define BLACKJACK_H
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string.h>
    #include <netdb.h>
    //#include <regex.h>		// Regular Expression (POSIX) Matching
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <sys/socket.h>
    #include <iostream>
    #include <fstream>		// For cout redirecting
    #include <string>
    #include "ircserver.h"
    #include "nemoirc.h"
    #include "cards.hpp"		// For the blackjack game
    
    #define MAX_HAND 15
    
    // Forward Declarations
    class hand;
    class blackjackgame;
    
    // External variables
    //extern ircserver serv;
    //extern ircserver srvr;
    //extern parsedArgs opts;
    
    class hand {
    	private:
    		card	cHand[MAX_HAND];
    		bool	bShow[MAX_HAND];
    		int	iTotal;
    
    		int	addUp();
    
    	public:
    		card	getCard(int);	// Get the CARD of hand[int]
    		char*	getName(int);	// i.e. "(11) Ace of Spades"
    		int	addCard(card);	// add the card to the hand
    		int	getTotal();
    };
    
    class blackjackgame {
    	private:
    		int	nPlayers;
    		char	cPlayers[30][30];
    		hand	hHands[30];
    		deck	dDeck;
    
    	public:
    		void	shuffle();
    		void	dealTo(char*, char*, ircserver, bool welc = true);
    };
    
    #endif
    Compilers:
    GCC on Red Hat 8.1 (Primary)
    GCC on Mac OS X 10.2.4 (Secondary)

    Others:
    MinGW on XP

  4. #4
    Wow! it worked! What, exactly, does inline do that would make it unable to be "referenced" from another source file?

    ~Inquirer
    Compilers:
    GCC on Red Hat 8.1 (Primary)
    GCC on Mac OS X 10.2.4 (Secondary)

    Others:
    MinGW on XP

  5. #5
    Aaah. Thats interesting. Thanks for the explanation. I'll remember that.

    Thanks
    ~Inquirer
    Compilers:
    GCC on Red Hat 8.1 (Primary)
    GCC on Mac OS X 10.2.4 (Secondary)

    Others:
    MinGW on XP

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 05-13-2011, 08:28 AM
  2. Mutex across multiple source files
    By Quasar in forum Linux Programming
    Replies: 7
    Last Post: 12-04-2007, 08:25 AM
  3. added start menu crashes game
    By avgprogamerjoe in forum Game Programming
    Replies: 6
    Last Post: 08-29-2007, 01:30 PM
  4. Beginner Question: Multiple source files
    By ironfistchamp in forum C++ Programming
    Replies: 8
    Last Post: 07-16-2006, 02:19 PM
  5. Linking multiple .c/pp files together
    By Enstavv in forum Game Programming
    Replies: 1
    Last Post: 10-29-2001, 10:14 PM