Search code examples
c++cmakeconan

macosx + conan + cmake build resulting in undefined symbols for architecture x86_64?


I've been packaging a few conan recipes with varied success.. but now getting stuck on one package in particular

https://github.com/smasherprog/screen_capture_lite/issues/115

conanfile.py

from conans import ConanFile, CMake, tools


class ScreenCapLiteConan(ConanFile):
    name = "ScreenCaptureLite"
    version = "11.0.0"
    license = "MIT"
    author = "smasherprog@gmail.com"
    url = "https://github.com/smasherprog/screen_capture_lite/"
    description = "Capture screen grabs in C++"
    topics = ("screengrab", "capture")
    settings = "os", "compiler", "build_type", "arch"
    options = {"shared": [True, False]}
    default_options = {"shared": False}
    generators = "cmake"

    def source(self):
        self.run("git clone --depth 1 --branch v11.0.0 git@github.com:smasherprog/screen_capture_lite.git")

    def build(self):
        cmake = CMake(self)
        cmake.configure(source_folder="screen_capture_lite")
        cmake.build()

    def package(self):
        self.copy("*.h", dst="include", src="screen_capture_lite/include", keep_path=False)
        self.copy("*hello.lib", dst="lib", keep_path=False)
        self.copy("*.dll", dst="bin", keep_path=False)
        self.copy("*.so", dst="lib", keep_path=False)
        self.copy("*.dylib", dst="lib", keep_path=False)
        self.copy("*.a", dst="lib", keep_path=False)

    def package_info(self):
        self.cpp_info.libs = ["ScreenCaptureLite"]

this uploads to my registry just fine and I can see indeed there is a libscreen_cab.a of some sort saved

but when I goto try and use this library to create the libraries example in a new project.. it errors

CMakeLists.txt (of the consuming project)

cmake_minimum_required(VERSION 2.8.12)
project(scl_app_server)
add_compile_options(-std=c++17)

# Using the "cmake" generator
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup(TARGETS)

FILE ( GLOB SCL_APP_SRC src/*.cpp )

add_executable(scl_app_server ${SCL_APP_SRC} )
target_link_libraries(scl_app_server pthread CONAN_PKG::ScreenCaptureLite)

The following is what happens after I conan install the following

[requires]
ScreenCaptureLite/11.0.0@namespace/prod

[generators]
cmake

The commands executed emitting the error

cmake .. -DCMAKE_BUILD_TYPE=Release
cmake --build .
-- The C compiler identification is AppleClang 13.0.0.13000029
-- The CXX compiler identification is AppleClang 13.0.0.13000029
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Conan: Adjusting output directories
-- Conan: Using cmake targets configuration
-- Library libscreen_capture found /Users/emcp/.conan/data/libscreen_capture/11.0.0/prod/package/2cd20192e71f56e1115fbdc2ebf2871bb61152e4/lib/liblibscreen_capture.a
-- Conan: Adjusting default RPATHs Conan policies
-- Conan: Adjusting language standard
-- Current conanbuildinfo.cmake directory: /Users/emcp/Dev/git/screen-cap-lite-server/build
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/emcp/Dev/git/screen-cap-lite-server/build
[ 33%] Building CXX object CMakeFiles/scl_app_server.dir/src/Screen_Capture_Example.cpp.o
[ 66%] Building CXX object CMakeFiles/scl_app_server.dir/src/lodepng.cpp.o
[100%] Linking CXX executable bin/scl_app_server
Undefined symbols for architecture x86_64:
  "_CFDataGetBytePtr", referenced from:
      SL::Screen_Capture::CGFrameProcessor::ProcessFrame(SL::Screen_Capture::Monitor const&) in liblibscreen_capture.a(CGFrameProcessor.cpp.o)
      SL::Screen_Capture::NSMouseProcessor::ProcessFrame() in liblibscreen_capture.a(NSMouseProcessor.cpp.o)
  "_CFDataGetLength", referenced from:
      SL::Screen_Capture::NSMouseProcessor::ProcessFrame() in liblibscreen_capture.a(NSMouseProcessor.cpp.o)
  "_CFRelease", referenced from:
      SL::Screen_Capture::CGFrameProcessor::ProcessFrame(SL::Screen_Capture::Monitor const&) in liblibscreen_capture.a(CGFrameProcessor.cpp.o)
      SL::Screen_Capture::NSMouseProcessor::ProcessFrame() in liblibscreen_capture.a(NSMouseProcessor.cpp.o)
      _SLScreen_Capture_GetCurrentMouseImage in liblibscreen_capture.a(NSMouseCapture.m.o)
  "_CGDataProviderCopyData", referenced from:
      SL::Screen_Capture::CGFrameProcessor::ProcessFrame(SL::Screen_Capture::Monitor const&) in liblibscreen_capture.a(CGFrameProcessor.cpp.o)
      SL::Screen_Capture::NSMouseProcessor::ProcessFrame() in liblibscreen_capture.a(NSMouseProcessor.cpp.o)
  "_CGDisplayBounds", referenced from:
      SL::Screen_Capture::GetMonitors() in liblibscreen_capture.a(GetMonitors.cpp.o)
  "_CGDisplayCopyDisplayMode", referenced from:
      SL::Screen_Capture::GetMonitors() in liblibscreen_capture.a(GetMonitors.cpp.o)
  "_CGDisplayCreateImage", referenced from:
      SL::Screen_Capture::CGFrameProcessor::ProcessFrame(SL::Screen_Capture::Monitor const&) in liblibscreen_capture.a(CGFrameProcessor.cpp.o)
  "_CGDisplayCreateImageForRect", referenced from:
      SL::Screen_Capture::CGFrameProcessor::ProcessFrame(SL::Screen_Capture::Monitor const&) in liblibscreen_capture.a(CGFrameProcessor.cpp.o)
  "_CGDisplayMirrorsDisplay", referenced from:
      SL::Screen_Capture::GetMonitors() in liblibscreen_capture.a(GetMonitors.cpp.o)
  "_CGDisplayModeGetPixelHeight", referenced from:
      SL::Screen_Capture::GetMonitors() in liblibscreen_capture.a(GetMonitors.cpp.o)
  "_CGDisplayModeGetPixelWidth", referenced from:
      SL::Screen_Capture::GetMonitors() in liblibscreen_capture.a(GetMonitors.cpp.o)
  "_CGDisplayModeRelease", referenced from:
      SL::Screen_Capture::GetMonitors() in liblibscreen_capture.a(GetMonitors.cpp.o)
  "_CGEventCreate", referenced from:
      SL::Screen_Capture::NSMouseProcessor::ProcessFrame() in liblibscreen_capture.a(NSMouseProcessor.cpp.o)
  "_CGEventGetLocation", referenced from:
      SL::Screen_Capture::NSMouseProcessor::ProcessFrame() in liblibscreen_capture.a(NSMouseProcessor.cpp.o)
  "_CGGetActiveDisplayList", referenced from:
      SL::Screen_Capture::GetMonitors() in liblibscreen_capture.a(GetMonitors.cpp.o)
  "_CGImageGetBitsPerPixel", referenced from:
      SL::Screen_Capture::CGFrameProcessor::ProcessFrame(SL::Screen_Capture::Monitor const&) in liblibscreen_capture.a(CGFrameProcessor.cpp.o)
  "_CGImageGetBytesPerRow", referenced from:
      SL::Screen_Capture::CGFrameProcessor::ProcessFrame(SL::Screen_Capture::Monitor const&) in liblibscreen_capture.a(CGFrameProcessor.cpp.o)
  "_CGImageGetDataProvider", referenced from:
      SL::Screen_Capture::CGFrameProcessor::ProcessFrame(SL::Screen_Capture::Monitor const&) in liblibscreen_capture.a(CGFrameProcessor.cpp.o)
      SL::Screen_Capture::NSMouseProcessor::ProcessFrame() in liblibscreen_capture.a(NSMouseProcessor.cpp.o)
  "_CGImageGetHeight", referenced from:
      SL::Screen_Capture::CGFrameProcessor::ProcessFrame(SL::Screen_Capture::Monitor const&) in liblibscreen_capture.a(CGFrameProcessor.cpp.o)
      SL::Screen_Capture::NSMouseProcessor::ProcessFrame() in liblibscreen_capture.a(NSMouseProcessor.cpp.o)
  "_CGImageGetWidth", referenced from:
      SL::Screen_Capture::CGFrameProcessor::ProcessFrame(SL::Screen_Capture::Monitor const&) in liblibscreen_capture.a(CGFrameProcessor.cpp.o)
      SL::Screen_Capture::NSMouseProcessor::ProcessFrame() in liblibscreen_capture.a(NSMouseProcessor.cpp.o)
  "_CGImageRelease", referenced from:
      SL::Screen_Capture::CGFrameProcessor::ProcessFrame(SL::Screen_Capture::Monitor const&) in liblibscreen_capture.a(CGFrameProcessor.cpp.o)
      SL::Screen_Capture::NSMouseProcessor::ProcessFrame() in liblibscreen_capture.a(NSMouseProcessor.cpp.o)
  "_CGImageSourceCreateImageAtIndex", referenced from:
      _SLScreen_Capture_GetCurrentMouseImage in liblibscreen_capture.a(NSMouseCapture.m.o)
  "_CGImageSourceCreateWithData", referenced from:
      _SLScreen_Capture_GetCurrentMouseImage in liblibscreen_capture.a(NSMouseCapture.m.o)
  "_OBJC_CLASS_$_NSApplication", referenced from:
      objc-class-ref in liblibscreen_capture.a(NSMouseCapture.m.o)
  "_OBJC_CLASS_$_NSCursor", referenced from:
      objc-class-ref in liblibscreen_capture.a(NSMouseCapture.m.o)
  "_objc_autoreleasePoolPop", referenced from:
      _SLScreen_Capture_GetCurrentMouseImage in liblibscreen_capture.a(NSMouseCapture.m.o)
  "_objc_autoreleasePoolPush", referenced from:
      _SLScreen_Capture_GetCurrentMouseImage in liblibscreen_capture.a(NSMouseCapture.m.o)
  "_objc_msgSend", referenced from:
      _SLScreen_Capture_InitMouseCapture in liblibscreen_capture.a(NSMouseCapture.m.o)
      _SLScreen_Capture_GetCurrentMouseImage in liblibscreen_capture.a(NSMouseCapture.m.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [bin/scl_app_server] Error 1
make[1]: *** [CMakeFiles/scl_app_server.dir/all] Error 2
make: *** [all] Error 2

Edit:

seems the author got back to me and showed me I need to add some things.. I am unsure how to add it to a conan based CMakeLists.txt but it's all the apple things

https://github.com/smasherprog/screen_capture_lite/blob/master/Example_CPP/CMakeLists.txt

project(screen_capture_example_cpp)

if(WIN32)
    set(${PROJECT_NAME}_PLATFORM_LIBS Dwmapi)
    add_definitions(-DNOMINMAX)
elseif(APPLE)
    find_package(Threads REQUIRED)
    find_library(corefoundation_lib CoreFoundation REQUIRED)
    find_library(cocoa_lib Cocoa REQUIRED)
    find_library(coremedia_lib CoreMedia REQUIRED)
    find_library(avfoundation_lib AVFoundation REQUIRED)
    find_library(coregraphics_lib CoreGraphics REQUIRED)
    find_library(corevideo_lib CoreVideo REQUIRED)
   
    set(${PROJECT_NAME}_PLATFORM_LIBS
        ${CMAKE_THREAD_LIBS_INIT}
        ${corefoundation_lib}
        ${cocoa_lib}
        ${coremedia_lib}
        ${avfoundation_lib}
        ${coregraphics_lib}  
        ${corevideo_lib}
    ) 
else()
    find_package(X11 REQUIRED)
    if(!X11_XTest_FOUND)
        message(FATAL_ERROR "X11 extensions are required, but not found!")
    endif()
    if(!X11_Xfixes_LIB)
        message(FATAL_ERROR "X11 fixes extension is required, but not found!")
    endif()
    find_package(Threads REQUIRED)
    set(${PROJECT_NAME}_PLATFORM_LIBS
        ${X11_LIBRARIES}
        ${X11_Xfixes_LIB}
        ${X11_XTest_LIB}
        ${X11_Xinerama_LIB}
        ${CMAKE_THREAD_LIBS_INIT}
    )
endif()

include_directories(
    ../include 
) 

add_executable(${PROJECT_NAME}_static
    lodepng.cpp
    Screen_Capture_Example.cpp
)
target_link_libraries(${PROJECT_NAME}_static screen_capture_lite_static ${${PROJECT_NAME}_PLATFORM_LIBS})  

add_executable(${PROJECT_NAME}_shared  
    lodepng.cpp
    Screen_Capture_Example.cpp
)

target_link_libraries(${PROJECT_NAME}_shared screen_capture_lite_shared ${${PROJECT_NAME}_PLATFORM_LIBS}) 

install (TARGETS ${PROJECT_NAME}_static ${PROJECT_NAME}_shared screen_capture_lite_shared
    RUNTIME DESTINATION Examples
) 

do I just add these lines to my CMakeLists.txt the same?


Solution

  • it turned out the version I had pulled from github was super ancient.. once I updated my recipe to pull from the latest.. it was apparent that my consuming CMakeLists.txt was missing all sorts of apple libraries..

    I modified slightly the authors original.. added the conan logic.. and most importantly learned how to add logic so that conan can make sense if you want static or dynamic libraries

    my conanfile.py

    from conans import ConanFile, CMake, tools
    
    
    class ScreenCapLiteConan(ConanFile):
        name = "screen_capture_lite"
        version = "17.1.439"
        license = "MIT"
        author = "smasherprog@gmail.com"
        url = "https://github.com/smasherprog/screen_capture_lite"
        description = "Capture screen grabs in Mac OSX"
        topics = ("screengrab", "capture")
        settings = "os", "compiler", "build_type", "arch"
        options = {"shared": [True, False]}
        default_options = {"shared": False}
        generators = "cmake"
    
        def source(self):
            self.run("git clone --depth 1 --branch 17.1.439 git@github.com:smasherprog/screen_capture_lite.git")
    
        def build(self):
            cmake = CMake(self)
            cmake.configure(source_folder="screen_capture_lite")
            cmake.build()
    
        def package(self):
            self.copy("*.h", dst="include", src="screen_capture_lite/include")
            self.copy("*hello.lib", dst="lib", keep_path=False)
            self.copy("*.dll", dst="bin", keep_path=False)
            self.copy("*.so", dst="lib", keep_path=False)
            self.copy("*.dylib", dst="lib", keep_path=False)
            self.copy("*.a", dst="lib", keep_path=False)
    
        def package_info(self):
            if self.settings.os == "Macos":
                self.cpp_info.libs = ["libscreen_capture_lite_static.a"] if not self.options.shared else ["libscreen_capture_lite_shared.dylib"]
            elif self.settings.os == "Linux":
                self.cpp_info.libs = ["libscreen_capture_lite_static.a"] if not self.options.shared else ["libscreen_capture_lite_shared.so"]  
    
    

    notice the last lines where I have to add the logic for the different libraries

    then my consuming project just needs the following

    conanfile.txt

    [requires]
    screen_capture_lite/17.1.439@emcp/prod
    
    [generators]
    cmake
    
    [options]
    screen_capture_lite:shared=False
    
    

    CMakeLists.txt

    cmake_minimum_required(VERSION 2.8.12)
    project(osx_screengrabber)
    add_compile_options(-std=c++17)
    
    # Using the "cmake" generator
    include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
    conan_basic_setup(TARGETS)
    
    if(WIN32)
        set(${PROJECT_NAME}_PLATFORM_LIBS Dwmapi)
        add_definitions(-DNOMINMAX)
    elseif(APPLE)
        find_package(Threads REQUIRED)
        find_library(corefoundation_lib CoreFoundation REQUIRED)
        find_library(cocoa_lib Cocoa REQUIRED)
        find_library(coremedia_lib CoreMedia REQUIRED)
        find_library(avfoundation_lib AVFoundation REQUIRED)
        find_library(coregraphics_lib CoreGraphics REQUIRED)
        find_library(corevideo_lib CoreVideo REQUIRED)
       
        set(${PROJECT_NAME}_PLATFORM_LIBS
            ${CMAKE_THREAD_LIBS_INIT}
            ${corefoundation_lib}
            ${cocoa_lib}
            ${coremedia_lib}
            ${avfoundation_lib}
            ${coregraphics_lib}  
            ${corevideo_lib}
        ) 
    else()
        find_package(X11 REQUIRED)
        if(!X11_XTest_FOUND)
            message(FATAL_ERROR "X11 extensions are required, but not found!")
        endif()
        if(!X11_Xfixes_LIB)
            message(FATAL_ERROR "X11 fixes extension is required, but not found!")
        endif()
        find_package(Threads REQUIRED)
        set(${PROJECT_NAME}_PLATFORM_LIBS
            ${X11_LIBRARIES}
            ${X11_Xfixes_LIB}
            ${X11_XTest_LIB}
            ${X11_Xinerama_LIB}
            ${CMAKE_THREAD_LIBS_INIT}
        )
    endif()
    
    add_executable(${PROJECT_NAME}_static
        src/lodepng.cpp
        src/osx_screengrabber.cpp
    )
    target_link_libraries(${PROJECT_NAME}_static CONAN_PKG::screen_capture_lite ${${PROJECT_NAME}_PLATFORM_LIBS} )
    
    

    this fixed everything and I copied the original authors example project of the same git tag v17.1.439 into it's own repo.. fired up conan and cmake.. and it's all working now

    thanks Conan! and screen_capture_lite!