1

There are two classes in my project board and generator. The project structure is like this

.
├── board
├── CMakeLists.txt
├── compile_commands.json
├── include
│   ├── board.h
│   ├── global.h
│   └── generator.h
├── Inputs
│   └── fen1.txt
├── Makefile
├── src
│   ├── board.cpp
│   └── generator.cpp

board.h defines a bunch of function in the class:

#ifndef BOARD_H
#define BOARD_H

#include <cctype>
#include <cstddef>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include "global.h"

class Board {
    // Using bitboard representation
    // a1 is the first bit, while h8 is the last bit (from right to left)
    ull whiteKing, whiteQueen, whiteRooks, whiteBishops, whiteKnights, whitePawns;
    ull blackKing, blackQueen, blackRooks, blackBishops, blackKnights, blackPawns;
    ull whitePieces, blackPieces, occupiedSquares;

    bool nextMove; // if nextMove is true, then it's white's turn
    bool viewRotated;
    int castleWhite; // if white can still castle; left bit represents king side, right bit represents queen side
    int castleBlack; // if black can still castle

    int square[9][9];
    int epSquare; // En-passant square?
    int fiftyMove; // move since the last pawn move or capture
    int material; // total material in centipawn, in white's perspective

    void helpInit();

    public:
    Board();

    Board(int input[64], bool next, int fiftyM, int castleW, int castleB, int epSq);

    Board(std::string fen, std::string fencolor, std::string fencastling, std::string fenenpessant, std::string fenhalfmoveclock, std::string fenfullmove);

    void display();
};

#endif

while board.cppp implements these functions.

Similarly, generator.h defines a bunch of functions while generator.cpp implements them.

#ifndef GENERATOR_H
#define GENERATOR_H

#include <global.h>
#include <board.h>
#include <data.h>
#include <move.h>
#include <stdexcept>
#include <vector>

class Generator {
    Board board;
    Data data;
    std::vector<Move> whiteKnighMoves;
    std::vector<Move> blackKnightMoves;

    public: 

    Generator(Board b);

    static ull lowbit(ull number) {
        if (number == 0) throw std::invalid_argument("doesn't work bro!!");
        return __builtin_ctz(number) + 1;
    }

    void generateWhiteKnightMoves(); 

    void displayWhiteKnightMoves();

    void generateBlackKnightMoves();

};

#endif

However, when I implemented generator.cpp, errors occurred.

#include <iostream>
#include <generator.h>
#include <board.h>
#include <global.h>
#include <data.h>

Generator::Generator(Board b) {
    board = b;
}

void Generator::generateWhiteKnightMoves() {
    ull whiteKnights = board.getWhiteKnights();
    while (whiteKnights) {
        int x = lowbit(whiteKnights);
        whiteKnights ^= ((ull) 1 << x);
        ull knightAttack = data.KNIGHT_ATTACK[x];
        while (knightAttack) {
            Move move;
            int y = lowbit(knightAttack);
            knightAttack ^= ((ull) 1 << y);
            move.setFrom(y);
            move.setPiece(WHITE_KNIGHT);
            move.setCapture(board.getPiece(y));
            whiteKnighMoves.push_back(move);
        }
    }
}

void Generator::displayWhiteKnightMoves() {
    for (auto m : whiteKnighMoves) {
        m.display();
    }
}

int main() {
    // std::cout << "wtf bro" << std::endl;
    return 0;
}

The following error occurred:

/usr/bin/ld: CMakeFiles/generator.dir/src/generator.cpp.o: in function `Generator::Generator(Board)':
generator.cpp:(.text+0x18): undefined reference to `Board::Board()'

I suspect that there's something wrong with my CMakeLists.txt (I'm a beginner and this is my first project). Here it is:

cmake_minimum_required(VERSION 3.10)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
project(Ophelia VERSION 1.0)

add_executable(board src/board.cpp)
target_include_directories(board PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)

add_executable(generator src/generator.cpp)
target_include_directories(generator PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)

Sorry if the error is very trivial, I just got started and didn't find anything via researching. Thanks in advance :)

Yksisarvinen
  • 18,008
  • 2
  • 24
  • 52
Harry Zhou
  • 63
  • 3
  • 2
    The source `board.cpp` is **not a part** of `generator` executable. This is why function defined in that file do not count. You probably want to make a **single executable** from `board.cpp` and `generator.cpp` sources. Single executable is achieved by single `add_executable` call. – Tsyvarev Mar 21 '22 at 22:04
  • @Tsyvarev Do you mean something like this? ```set(SOURCE_FILES src/board.cpp src/move.cpp src/data.cpp src/generator.cpp) add_executable(test ${SOURCE_FILES}) target_include_directories(test PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) ``` I tried this, but it's showing me ```multiple_definitions``` errors. Can you help me? Thanks! – Harry Zhou Mar 21 '22 at 22:08
  • Yes, it is possible way to follow. Alternatively, instead of creating a variable contained a list of source files, you could list all source files directly in the `add_executable` call. – Tsyvarev Mar 21 '22 at 22:09
  • @Tsyvarev thank you, but do you happen to know how to solve the ```multiple definitions``` errors as well? I have used header guards for the header files, so I don't know what caused it. – Harry Zhou Mar 21 '22 at 22:11
  • Does this answer your question? [What is an undefined reference/unresolved external symbol error and how do I fix it?](https://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) – fabian Mar 22 '22 at 18:24

0 Answers0