I'm trying to set up a C++ project using CMake but I think I'm missing something. When I'm trying to use my library in an executable I get the error:
Scanning dependencies of target dynamic-shadows-lib
[ 33%] Linking CXX static library libdynamic-shadows-lib.a
[ 33%] Built target dynamic-shadows-lib
Scanning dependencies of target main
[ 66%] Building CXX object CMakeFiles/main.dir/main.cpp.o
[100%] Linking CXX executable main
/usr/bin/ld: CMakeFiles/main.dir/main.cpp.o: in function `main':
main.cpp:(.text+0x83): undefined reference to `num3()'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/main.dir/build.make:85: main] Error 1
make[1]: *** [CMakeFiles/Makefile2:78: CMakeFiles/main.dir/all] Error 2
make: *** [Makefile:84: all] Error 2
My file structure looks like this:
.
├── build
├── CMakeLists.txt
├── include
│ └── vec2f.hpp
├── main.cpp
└── src
└── vec2f.cpp
3 directories, 4 files
My root (and only) CMakeLists.txt looks like this:
cmake_minimum_required(VERSION 3.16)
project(
dynamic-shadows
VERSION 1.0
LANGUAGES CXX
)
# Set C++ to version 14
set(CMAKE_CXX_STANDARD 14)
# Set a name for the target
set(TARGET_LIB ${CMAKE_PROJECT_NAME}-lib)
# Make library ${TARGET_LIB}
add_library(${TARGET_LIB} STATIC)
# Set linker language to CXX (Gets error without it)
set_target_properties(${TARGET_LIB} PROPERTIES LINKER_LANGUAGE CXX)
# Set include directory for ${TARGET_LIB}
target_include_directories(
${TARGET_LIB}
PUBLIC
${PROJECT_SOURCE_DIR}/include
)
# Set sources for ${TARGET_LIB}
target_sources(
${TARGET_LIB}
PUBLIC
${PROJECT_SOURCE_DIR}/src
)
# Add a simple test executable to test the library
add_executable(main main.cpp)
# Link the ${TARGET_LIB} to main executable
target_link_libraries(
main
PUBLIC
${TARGET_LIB}
)
I suspect the problem lies in my CMakeLists.txt since I'm new to this, but I can't figure out what it is. What am I missing? Could it be something else I'm doing wrong?
The code I'm trying to run is very simple but I'll include it for reference:
./include/vec2.hpp
#ifndef __VEC2F_HPP__
#define __VEC2F_HPP__
#include <iostream>
namespace ds {
class vec2f {
public:
float x;
float y;
vec2f(float x_value, float y_value) : x(x_value), y(y_value) {}
};
} // End of namespace ds
std::ostream & operator<<(std::ostream &out, const ds::vec2f &v);
ds::vec2f operator+(const ds::vec2f &left, const ds::vec2f &right);
float num3();
#endif
./src/vec2f.cpp
#include "../include/vec2f.hpp"
/**
* @brief Overload of << operator for ds::vec2f class to allow for printing it in std::cout.
*
* @param out std::ostream reference (&)
* @param v ds::vec2f reference (&)
* @return std::ostream& out
*/
std::ostream & operator<<(std::ostream &out, const ds::vec2f &v)
{
return out << "[" << v.x << ", " << v.y << "]";
}
/**
* @brief Overload of + operator for ds::vec2f class to allow for vector addition.
*
* @param left ds::vec2f
* @param right ds::vec2f
* @return ds::vec2f sum
*/
ds::vec2f operator+(const ds::vec2f &left, const ds::vec2f &right)
{
return ds::vec2f(
left.x + right.x,
left.y + right.y
);
}
float num3()
{
return 3;
}
./main.cpp
#include "vec2f.hpp"
int main(int argc, char* argv[])
{
std::cout << "Hello world!" << std::endl;
ds::vec2f v1 = ds::vec2f(8, -2);
ds::vec2f v2 = ds::vec2f(2, 5);
float n = num3();
std::cout << "Res: " << n << std::endl;
return 0;
}
I've tried to follow solutions to similair problems which usually seems to have something to do with linking.
Most havn't really helped since I'm required to solve this using CMake. I've tried with a variety of CMakeLists.txt configurations but ended up with this one since it looked the cleanest and seemed to be using the latest implementations of commands (target_include_directory instead of include_directories etc..)