Search code examples
c++cmakelinkerlinker-errorscmake-language

Why does my CMakeLists file compile a library, but fail to link it to an executable?


I've been working on a hobby project of mine programmed in C++ on macOS, and as a beginner in CMake, I tried to move away from find_package due to issues with getting it to prioritize vendored libraries.

I re-wrote my CMake script to try to streamline the process of adding subdirectories, and I didn't get any errors when I generated the makefiles. When I tried to actually compile the program, however, my first library (SDL) compiled successfully, but failed to link to my executable with the following error:

[ 49%] Linking C shared library libSDL2-2.0.dylib
Undefined symbols for architecture x86_64:
  "_CHHapticDynamicParameterIDHapticIntensityControl", referenced from:
      -[SDL_RumbleMotor setIntensity:] in SDL_mfijoystick.m.o
  "_CHHapticEventParameterIDHapticIntensity", referenced from:
      -[SDL_RumbleMotor setIntensity:] in SDL_mfijoystick.m.o
  "_CHHapticEventTypeHapticContinuous", referenced from:
      -[SDL_RumbleMotor setIntensity:] in SDL_mfijoystick.m.o
  "_GCControllerDidConnectNotification", referenced from:
      _IOS_JoystickInit in SDL_mfijoystick.m.o
      _IOS_JoystickQuit in SDL_mfijoystick.m.o

  ...

  "_OBJC_CLASS_$_CHHapticDynamicParameter", referenced from:
      objc-class-ref in SDL_mfijoystick.m.o
  "_OBJC_CLASS_$_CHHapticEvent", referenced from:
      objc-class-ref in SDL_mfijoystick.m.o
  "_OBJC_CLASS_$_CHHapticEventParameter", referenced from:
      objc-class-ref in SDL_mfijoystick.m.o
  "_OBJC_CLASS_$_CHHapticPattern", referenced from:
      objc-class-ref in SDL_mfijoystick.m.o
  "_OBJC_CLASS_$_GCColor", referenced from:
      objc-class-ref in SDL_mfijoystick.m.o
  "_OBJC_CLASS_$_GCController", referenced from:
      objc-class-ref in SDL_mfijoystick.m.o
  "_OBJC_CLASS_$_GCControllerAxisInput", referenced from:
      objc-class-ref in SDL_mfijoystick.m.o
  "_OBJC_CLASS_$_GCControllerButtonInput", referenced from:
      objc-class-ref in SDL_mfijoystick.m.o
ld: symbol(s) not found for architecture x86_64

This appears to be a list of the first twenty or so functions in alphabetical order, leading me to believe that it's somehow unable to find any of the functions. I did notice that most of the "referenced from" locations mention iOS, though, so it's also possible that I'm accidentally including iOS-related functions somehow. My CMake script is as follows:

cmake_minimum_required(VERSION 3.10)

set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64")
set(CMAKE_MACOSX_RPATH 1)

set(OutputPath "${CMAKE_SOURCE_DIR}/bin/${CMAKE_SYSTEM_NAME}")

set(CMAKE_ARCHIVE_OUTPUT_DIR "${OutputPath}/staticlibs")
set(CMAKE_LIBRARY_OUTPUT_DIR "${OutputPath}")
set(CMAKE_RUNTIME_OUTPUT_DIR "${OutputPath}")

set(CMAKE_FIND_FRAMEWORK NEVER)

set(TGUI_BACKEND SDL_RENDERER)
set(TGUI_BUILD_FRAMEWORK FALSE)

project(Tutorial VERSION 1.1
        DESCRIPTION "Project" 
        LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

#
# Setting lists for convenience:
#

set(SourceList
    src/main.cpp
    src/graphics.cpp
    src/main.h
    src/graphics.h
    src/version.h
    src/files.cpp
    src/files.h
    src/mainExclusive.h
    src/include/tinyfiledialogs.cpp
    src/include/tinyfiledialogs.h
)

set (Libraries
    src/include/SDL2
    src/include/SDL2_image
    src/include/SDL2_ttf
    src/include/TGUI-1.3.0
) 

set (LibraryNames
    SDL2
    SDL2_image
    SDL2_ttf
    TGUI
)

add_executable(${PROJECT_NAME} MACOSX_BUNDLE ${SourceList})

# Read the Libraries list to determine subdirectories to add

foreach(Project IN LISTS Libraries)
    #include_directories(${Project})
    if(NOT TARGET ${Project})
        add_subdirectory(${Project})
    endif()
endforeach()

# Read LibraryNames to link the libraries by their actual name

foreach(Name IN LISTS LibraryNames)
    target_link_libraries(${PROJECT_NAME} ${Name})
endforeach()

Never mind it being generally messy from being referenced from several tutorials, and also me naming my dependencies folder "include" for whatever reason, I'm completely lost as to what causes it to fail at linking.

I tried including the library directories prior to adding the subdirectory, but it didn't seem to make a difference. I also tried to link the libraries in the "for each project in Libraries" loop instead of the LibraryNames loop, but that just completely skips over the dependencies (probably it's looking for libraries that are named "src/include/[library directory]").

If anyone can help me, it would be much appreciated, as I've been stuck on this for days.


Solution

  • Sorry for ghosting the topic for so long! I tried descherjm's suggestion of using find_package with the package source under PATH and while setting NO_CMAKE_SYSTEM_PATH. Surprise, it works. I swore I looked over the CMake docs multiple times, how did I not notice these useful parameters?!

    I guess at least other people with similarly low reading retention now have this question to be pointed to...