Cmake Project not linking correctly

I have been trying to link a test file (TestIntstantiator.cpp) to a library for a while, i’ve tried using add_subdirectories and multiple libraries but this just confused me (and the compiler). I am now trying to do it in the simplest way possible, but still coming across problems.

This is my CmakeLists file:

cmake_minimum_required(VERSION 3.9.1)

project(Icicle)

set(CMAKE_CXX_FLAGS "-Wall")

# check OS
# UNIX, WIN32, WINRT, CYGWIN, APPLE are environment variables as flags set by default system
if(UNIX)
    message("This is a ${CMAKE_SYSTEM_NAME} system")
elseif(WIN32)
    message("This is a Windows System")
endif()


if (NOT CMAKE_BUILD_TYPE)
  # CMake defaults to leaving CMAKE_BUILD_TYPE empty. This screws up
  # differentiation between debug and release builds.
  set(CMAKE_BUILD_TYPE "None" CACHE STRING "Choose the type of build, options are: None (CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release" FORCE)
endif ()


# Specify build paths
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin")

#cmake_policy(SET CMP0079 NEW)

add_executable(TestInstantiator Tests/Main/TestInstantiator.cpp )

file(GLOB HEADER_FILES $(CMAKE_SOURCE_DIR)/Main/src/*.h)
list(APPEND HEADER_FILES 
    "${CMAKE_SOURCE_DIR}/Main/Math/IcicleMath.h"
    "${CMAKE_SOURCE_DIR}/Main/Memory/Allocator.h"
    "${CMAKE_SOURCE_DIR}/Main/Memory/StackAllocator.h"
    "${CMAKE_SOURCE_DIR}/Main/Memory/MemoryManager.h"
    "${CMAKE_SOURCE_DIR}/Main/Resources/Resource.h"
)

file(GLOB SOURCE_FILES $(CMAKE_SOURCE_DIR)/Main/src/*.cpp)
list(APPEND SOURCE_FILES
"${CMAKE_SOURCE_DIR}/Main/Math/IcicleMath.cpp"
"${CMAKE_SOURCE_DIR}/Main/Memory/Allocator.cpp"
"${CMAKE_SOURCE_DIR}/Main/Memory/StackAllocator.cpp"
"${CMAKE_SOURCE_DIR}/Main/Memory/MemoryManager.cpp"
)


add_library(IcicleMain SHARED ${HEADER_FILES} ${SOURCE_FILES})

install(FILES ${HEADER_FILES} DESTINATION include/Icicle)


add_executable(Test "Tests/Main/TestInstantiator.cpp")
target_include_directories(Test PRIVATE 
"${CMAKE_SOURCE_DIR}/Main/src" 
"${CMAKE_SOURCE_DIR}/Main/Math" 
"${CMAKE_SOURCE_DIR}/Main/Memory" 
"${CMAKE_SOURCE_DIR}/Main/Resources")

link_directories(Test)

target_link_libraries(Test IcicleMain)
# target_link_libraries(TestInstantiator vtkCommon)


add_test(NAME TestInstantiator
         COMMAND TestInstantiator)

And the project structure looks like this:

├── Main
│   ├── Src
│   │   ├── **/*.cpp/.h
│   ├── Math
│   │   ├── **/*.cpp/.h
│   ├── Memory
│   │   ├── **/*.cpp/.h
│   ├── Resources
│   │   ├── **/*.cpp/.h
├── Tests
│   ├── Main
│   │   ├── TestInstantiator.cpp
├──CmakeLists.txt

The errors I’m getting:
Icicle/Tests/Main/TestInstantiator.cpp:34: undefined reference to S
tackAllocator::StackAllocator(unsigned long long, void*)’
undefined reference to Math::ptr_add(void*, unsigned long long)' /Icicle/Main/Memory/MemoryManager.h:53: undefined reference to Icicle::MemoryManager::~MemoryManager()’
Icicle/Main/Memory/MemoryManager.h:53: undefined reference to `Icicle::MemoryManager::MemoryManager()’
collect2.exe: error: ld returned 1 exit status
make[2]: *** [bin/TestInstantiator.exe] Error 1
make[1]: *** [CMakeFiles/TestInstantiator.dir/all] Error 2
make: *** [all] Error 2

There is not enough information in this to help you. You need to figure out where StackAllocator::StackAllocator and Icicle::MemoryManager::~MemoryManager are defined in the source code. This could be a C++ issue and not a build system issue.

My includes in TestInstantiator.cpp look like this:

#include "../doctest.h"
#include "../../Main/src/IceRoot.h" 
#include "../../Main/Memory/StackAllocator.h"
#include "../../Main/Memory/Allocator.h"
#include "../../Main/Math/IcicleMath.h"

Is this what you mean?

Also what doesn’t make sense to me is this error:
/Main/Memory/MemoryManager.h:53: undefined reference to `Icicle::MemoryManager::~MemoryManager()’

Where line 53 is this:
MemoryManager IceMemoryManager;

A static instance will need the destructor; it seems that it is not defined anywhere (it is probably in the library).

This should not be needed at all for intra-project target usages.

The TestInstantiator target needs to link to IcicleMain at least.

Okay I added both recomended, but cmake is generating makefiles that don’t compile anything (i searched for g++, gcc). All i see are rules like this:

# target to build an object file

Tests/Main/TestInstantiator.cpp.o:

$(MAKE) $(MAKESILENT) -f CMakeFiles/TestInstantiator.dir/build.make CMakeFiles/TestInstantiator.dir/Tests/Main/TestInstantiator.cpp.o

.PHONY : Tests/Main/TestInstantiator.cpp.o

The structure of the makefiles is not obvious (see the build.make file referenced there for the “real” commands). Does it build if you run make?

It builds the library but I don’t know if the individual files in the library are being linked to eachother, i get this error message now:

[ 27%] Linking CXX shared library lib/libIcicleMain.so
[ 81%] Built target IcicleMain
[ 90%] Linking CXX executable bin/TestInstantiator
/usr/bin/ld: CMakeFiles/TestInstantiator.dir/Tests/Main/TestInstantiator.cpp.o: in function `DOCTEST_ANON_FUNC_21()':
/home/work/Projects/Icicle/Tests/Main/TestInstantiator.cpp:63: undefined reference to `Icicle::ptr_add(void*, unsigned long)'
/usr/bin/ld: lib/libIcicleMain.so: undefined reference to `Icicle::ptr_subtract(void*, unsigned long)'
/usr/bin/ld: lib/libIcicleMain.so: undefined reference to `Icicle::alignForwardAdjustmentWithHeader(void*, unsigned char)'
/usr/bin/ld: lib/libIcicleMain.so: undefined reference to `Icicle::MemoryManager::instancePtr'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/TestInstantiator.dir/build.make:98: bin/TestInstantiator] Error 1
make[1]: *** [CMakeFiles/Makefile2:111: CMakeFiles/TestInstantiator.dir/all] Error 2
make: *** [Makefile:136: all] Error 2

I noticed a couple brackets meant to be squiggly brackets but otherwise my cmakelists is similar to before:

file(GLOB HEADER_FILES "${CMAKE_SOURCE_DIR}/Main/src/*.h")
list(APPEND HEADER_FILES 
    "${CMAKE_SOURCE_DIR}/Main/Math/IcicleMath.h"
    "${CMAKE_SOURCE_DIR}/Main/Memory/Allocator.h"
    "${CMAKE_SOURCE_DIR}/Main/Memory/StackAllocator.h"
    "${CMAKE_SOURCE_DIR}/Main/Memory/MemoryManager.h"
    "${CMAKE_SOURCE_DIR}/Main/Resources/Resource.h"
)

file(GLOB SOURCE_FILES "${CMAKE_SOURCE_DIR}/Main/src/*.cpp")
list(APPEND SOURCE_FILES
"${CMAKE_SOURCE_DIR}/Main/Math/IcicleMath.cpp"
"${CMAKE_SOURCE_DIR}/Main/Memory/Allocator.cpp"
"${CMAKE_SOURCE_DIR}/Main/Memory/StackAllocator.cpp"
"${CMAKE_SOURCE_DIR}/Main/Memory/MemoryManager.cpp"
)


add_library(IcicleMain SHARED ${HEADER_FILES} ${SOURCE_FILES})


target_include_directories(IcicleMain PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}/Main/src" 
"${CMAKE_CURRENT_SOURCE_DIR}/Main/Math" 
"${CMAKE_CURRENT_SOURCE_DIR}/Main/Memory" 
"${CMAKE_CURRENT_SOURCE_DIR}/Main/Resources")

install(FILES ${HEADER_FILES} DESTINATION include/Icicle)

add_executable(TestInstantiator Tests/Main/TestInstantiator.cpp )




target_link_libraries(TestInstantiator IcicleMain)
# target_link_libraries(TestInstantiator vtkCommon)


add_test(NAME TestInstantiator
         COMMAND TestInstantiator)

These seem to just be unimplemented functions. Do you really have implementations of these in the sources? If so, are they added to the library?