2

My project looks like this:

include/util/safety.h
include/opcodes/8bit_load_opcodes.h
include/CPU.h
src/util/safety.cpp
src/CPU.cpp
src/main.cpp
src/opcodes/8bit_load_opcodes.cpp
CMakeLists.txt

With the CMake script below

cmake_minimum_required(VERSION 3.17)
project(gameboy)
enable_testing()

FIND_PACKAGE(Boost 1.65.1 COMPONENTS unit_test_framework REQUIRED)

if(NOT Boost_FOUND)
    message(FATAL_ERROR "Boost Not found")
endif()
set(CMAKE_CXX_STANDARD 20)
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIR})


INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include/opcodes)
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include/util)

ADD_LIBRARY(cpu_util src/util/safety.cpp)

ADD_LIBRARY(cpu src/CPU.cpp src/opcodes/8bit_load_opcodes.cpp)

TARGET_LINK_LIBRARIES(cpu ${Boost_LIBRARIES})
TARGET_LINK_LIBRARIES(cpu cpu_util)

add_executable(gameboy src/main.cpp)

TARGET_LINK_LIBRARIES(gameboy cpu)

When I run make I get:

Scanning dependencies of target cpu_util
[ 14%] Building CXX object CMakeFiles/cpu_util.dir/src/util/safety.cpp.o
[ 28%] Linking CXX static library libcpu_util.a
[ 28%] Built target cpu_util
Scanning dependencies of target cpu
[ 42%] Building CXX object CMakeFiles/cpu.dir/src/CPU.cpp.o
[ 57%] Building CXX object CMakeFiles/cpu.dir/src/opcodes/8bit_load_opcodes.cpp.o
[ 71%] Linking CXX static library libcpu.a
[ 71%] Built target cpu
Scanning dependencies of target gameboy
[ 85%] Building CXX object CMakeFiles/gameboy.dir/src/main.cpp.o
[100%] Linking CXX executable gameboy
CMakeFiles/gameboy.dir/src/main.cpp.o: In function `main':
/home/cedric/Programming/gameboy/src/main.cpp:6: undefined reference to `unsigned short validate_argument<unsigned short>(unsigned short, unsigned short)'
collect2: error: ld returned 1 exit status
CMakeFiles/gameboy.dir/build.make:106: recipe for target 'gameboy' failed
make[2]: *** [gameboy] Error 1
CMakeFiles/Makefile2:154: recipe for target 'CMakeFiles/gameboy.dir/all' failed
make[1]: *** [CMakeFiles/gameboy.dir/all] Error 2
Makefile:114: recipe for target 'all' failed
make: *** [all] Error 2

Running nm appears to show an empty output:

$ nm libcpu_util.a 

safety.cpp.o:

Why aren't there any symbols in libcpu_util and how can I fix this make error?

For reference:

safety.cpp

#include <stdexcept>
#include "util/safety.h"

template<typename T>
T validate_argument(T value, T mask)
{
    if((value & mask) != value)
        throw std::runtime_error("Value outside of mask!");

    return value;
}

safety.h

#ifndef GAMEBOY_SAFETY_H
#define GAMEBOY_SAFETY_H

template<typename T>
T validate_argument(T value, T mask);

#endif //GAMEBOY_SAFETY_H
Cedric Martens
  • 1,139
  • 10
  • 23

1 Answers1

2

The safety.h only has one template function, and the definition part is located in safety.cpp, which is wrong. Template functions should be defined in headers, so you get an empty library here. We need to put the definition part in the header file, and remove the library libcpu_util.a

template<typename T>
T validate_argument(T value, T mask);
prehistoricpenguin
  • 6,130
  • 3
  • 25
  • 42