Stefan Falk
Stefan Falk

Reputation: 25555

Getting "undefined reference to"

I tried several things to resolve this issue, but I just can't get my head around CMake apparently...

The following is basically the entire project:

.
├── CMakeLists.txt
└── src
    ├── CMakeLists.txt
    ├── main.cpp
    ├── SubwordEncoder.cpp
    └── SubwordEncoder.h

The first (./CMakeLists.txt) contains:

    cmake_minimum_required(VERSION 3.5)
    project(xlib)
    set(CMAKE_CXX_STANDARD 11)        
    add_subdirectory(./src)        
    add_executable(main src/main.cpp)

and the second (src/MakeLists.txt)

file(GLOB_RECURSE xlib_SOURCES "*.cpp")
file(GLOB_RECURSE xlib_SURCES "*.h")

main.cpp only contains this:

#include <string>
#include <iostream>
#include <stdio.h>
#include "SubwordEncoder.h"

int main() {
    std::cout << "Hello World!" << std::endl;
    auto encoder = new SubwordEncoder();

    auto encoded = encoder->encode("Hello World!");

    for (auto i : encoded) {
        std::cout << i << std::endl;
    }

    return 0;
}

SubwordEncoder.h

#ifndef XLIB_SUBWORDENCODER_H
#define XLIB_SUBWORDENCODER_H

#include <string>
#include <vector>

class SubwordEncoder {
public:
    std::vector<int> encode(std::string decoded);
};

#endif //XLIB_SUBWORDENCODER_H

and SubwordEncoder.cpp

#include "SubwordEncoder.h"

std::vector<int> SubwordEncoder::encode(std::string decoded) {
    std::vector<int> vect;
    vect.push_back(10);
    vect.push_back(20);
    vect.push_back(30);
    return vect;
}

Yet I keep getting this error:

/tmp/tmp.KYl9HEcObN/src/main.cpp:13: undefined reference to `SubwordEncoder::encode(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)'

What am I doing wrong?


Note:

I know I could do this:

add_executable(main src/main.cpp src/SubwordEncoder.cpp src/SubwordEncoder.h)

but I don't want to add every single file here. I want all files in src/ to be used for the compilation.

Upvotes: 0

Views: 391

Answers (2)

rdowell
rdowell

Reputation: 729

The only line in either of your CMake files that actually causes files to be compiled is add_executable(main src/main.cpp) and the only file it adds is main.cpp. There is nothing in either CMake file that actually tells it to compile the other source files.

These lines

file(GLOB_RECURSE xlib_SOURCES "*.cpp")
file(GLOB_RECURSE xlib_HEADERS "*.h")

only set up variables containing lists of file names. There is nothing that then includes those files in any compilation. Your options are either add those files to your compilation of the main target as in squareskittles answer, or compile them as a separate library and then link it into main:

src/CMakeLists.txt:

add_library(SubwordEncoder ${xlib_SOURCES})

./CMakeLists.txt:

target_link_libraries(main SubwordEncoder)

Upvotes: 0

Kevin
Kevin

Reputation: 18396

When you call add_executable(), you are only including main.cpp and not the others, so SubwordEncoder::encode is undefined when you try to use it in main(). Try changing your CMake files to something like this:

./CMakeLists.txt

cmake_minimum_required(VERSION 3.5)
project(xlib)
set(CMAKE_CXX_STANDARD 11)        
add_subdirectory(src)  

./src/CMakeLists.txt

file(GLOB_RECURSE xlib_SOURCES "*.cpp")
file(GLOB_RECURSE xlib_HEADERS "*.h")

add_executable(main ${xlib_SOURCES} ${xlib_HEADERS}) 
# Include the current folder for including headers.
target_include_directories(main PRIVATE ${CMAKE_CURRENT_LIST_DIR})

Upvotes: 1

Related Questions