Qt6+Cmake bad linking MacOS - c++

I am trying to do a C++ project using CMake, Conan and Qt6.
At first, I was able to add Qt Core in the project (hello world at the time) and call qDebug() instead of std::cout but then I added a lib with Conan (libgphoto2) and now I can't use Qt in the project.
The build does not fail, but running the app gives this error :
dyld[68458]: Library not loaded: '#rpath/QtCore.framework/Versions/A/QtCore'
Referenced from: '/Users/chell/code/skytracker/cmake-build-debug/bin/skytracker'
Reason: tried: '/Library/Frameworks/QtCore.framework/Versions/A/QtCore' (no such file), '/System/Library/Frameworks/QtCore.framework/Versions/A/QtCore' (no such file)
If I understand correctly what I read on internet when trying to find a solution, is that at runtime, the linker will replace #rpath with a list of path to look for the lib. Here, it fails because it doesn't have ~/Qt/6.4.2/macos/lib where the QtCore.framework folder is ?
I'm not using Qt Creator at all, I'm using CLion, I'll just need some Qt libs.
Here's the CMakeLists.txt :
cmake_minimum_required(VERSION 3.22)
project(skytracker)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
#Conan integration
if(NOT EXISTS "${CMAKE_BINARY_DIR}/conan.cmake")
message(STATUS "Downloading conan.cmake from https://github.com/conan-io/cmake-conan")
file(DOWNLOAD "https://raw.githubusercontent.com/conan-io/cmake-conan/0.18.1/conan.cmake"
"${CMAKE_BINARY_DIR}/conan.cmake"
TLS_VERIFY ON)
endif()
include(${CMAKE_BINARY_DIR}/conan.cmake)
set(CI false CACHE BOOL "Set true if CI build")
if(${CI})
message("Using CI profile")
set(CMAKE_C_COMPILER /usr/bin/gcc)
set(CMAKE_CXX_COMPILER /usr/bin/g++)
set(CONANPROFILE ../CI.conanprofile)
endif()
conan_cmake_install(PATH_OR_REFERENCE ..
BUILD missing
REMOTE conancenter
PROFILE ${CONANPROFILE})
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup(TARGETS)
set(sources src/cpp/main.cpp
src/cpp/services/PhotoService.cpp src/cpp/services/PhotoService.h
# src/cpp/entities/Camera.h src/cpp/entities/Camera.cpp
# src/cpp/entities/NikonCamera.cpp src/cpp/entities/NikonCamera.h
)
set(CMAKE_AUTOMOC ON) #Qt C++ extensions
set(CMAKE_AUTOUIC OFF) #Enable GUI compile
set(CMAKE_AUTORCC OFF) #Enable QRC files
if(APPLE)
set(Qt6_DIR ~/Qt/6.4.2/macos/lib/cmake/Qt6/)
set(CONANPROFILE macos.conanprofile)
set(CMAKE_MACOSX_RPATH 1)
elseif(UNIX)
set(Qt6_DIR ~/Qt/6.4.2/gcc_64/lib/cmake/Qt6/)
set(CONANPROFILE unix.conanprofile)
elseif(WIN32)
set(Qt6_DIR C:/Qt/6.4.2/mingw_64/lib/cmake/Qt6/)
set(CONANPROFILE windows.conanprofile)
endif()
#find the Qt libs used by the project
find_package(Qt6 6.4.2 REQUIRED COMPONENTS Core)
include(${CMAKE_BINARY_DIR}/conan_paths.cmake)
# give the compiler the path to the libs
link_directories("${CONAN_LIB_DIRS}")
# and to the headers
include_directories("${CONAN_INCLUDE_DIRS}")
add_executable(skytracker ${sources})
#link all Qt libs to the executable
target_link_libraries(skytracker PRIVATE Qt6::Core)
target_link_libraries(skytracker PRIVATE ${CONAN_LIBS})
Running otool -L skytracker gives me this :
skytracker:
#rpath/QtCore.framework/Versions/A/QtCore (compatibility version 6.0.0, current version 6.4.2)
/Users/chell/.conan/data/libgphoto2/2.5.27/_/_/package/8880a3412c5909fb46130c128d3ff83f4602ce9e/lib/libgphoto2.6.dylib (compatibility version 8.0.0, current version 8.0.0)
/Users/chell/.conan/data/libgphoto2/2.5.27/_/_/package/8880a3412c5909fb46130c128d3ff83f4602ce9e/lib/libgphoto2_port.12.dylib (compatibility version 13.0.0, current version 13.0.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit (compatibility version 1.0.0, current version 275.0.0)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1953.255.0)
/System/Library/Frameworks/Security.framework/Versions/A/Security (compatibility version 1.0.0, current version 60420.60.24)
/System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1300.36.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1319.0.0)
The logs of CMake loading the project contains this -- Conan: Adjusting default RPATHs Conan policies which makes me believe maybe Conan erases the default value that worked before ?
Here are some more details of my system :
MacOS 12.6.3 (but I'll be crosscompiling later to raspberry and I created a github action CI)
Qt6 v6.4.2 installed in home folder
Conan 1.58.0
Cmake 3.25.1
Thank you very much for your help.
Benjamin

Related

After `libigl` update to ver 2.4.0 I can't build anymore

My CMakeLists.txt file for my old libigl testing project contains the piece below:
project(libigl)
set(LIBIGL_HOME $ENV{HOME}/apps/libigl)
set(CMAKE_PREFIX_PATH ${LIBIGL_HOME})
set(CMAKE_MODULE_PATH ${LIBIGL_HOME}/cmake)
find_package(${PROJECT_NAME} CONFIGS libigl.cmake REQUIRED)
if(${PROJECT_NAME}_FOUND)
message("-- Found ${PROJECT_NAME}")
else()
message(FATAL_ERROR "${PROJECT_NAME} is not found")
endif()
I tried to build this project with the new version 2.4.0 of the libigl library and got this message:
CMake Error at /home/hekto/apps/libigl/cmake/libigl.cmake:5 (message):
You included libigl.cmake directly from your own project. This behavior is
not supported anymore. Please add libigl to your project via
add_subdirectory(<path_to_libigl>). See the libigl example project for
more information: https://github.com/libigl/libigl-example-project/
Call Stack (most recent call first):
CMakeLists.txt:43 (find_package)
So, they recommend to use the add_subdirectory command for client projects. I looked at the CMakeLists.txt file from the recommended GitHub example project and couldn't find the add_subdirectory command:
cmake_minimum_required(VERSION 3.16)
project(example)
list(PREPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
# Libigl
include(libigl)
# Enable the target igl::glfw
igl_include(glfw)
# Add your project files
file(GLOB SRC_FILES *.cpp)
add_executable(${PROJECT_NAME} ${SRC_FILES})
target_link_libraries(${PROJECT_NAME} PUBLIC igl::glfw)
How should I build with the new version 2.4.0 of the libigl?
OS: Ubuntu 20.04.5 LTS
Compiler: g++ (Ubuntu 10.3.0-1ubuntu1~20.04) 10.3.0

Build cmake library without RPATH (use executable_path instead)

I am using CMake to build a library. Here is my CMakeLists.txt:
cmake_minimum_required(VERSION 3.11)
project(simpleLibrary)
set(CMAKE_CXX_STANDARD 17)
add_library(simpleLibrary SHARED main.cpp)
It is very simple and clear. It builds a library in cmake-build-debug. I use otool to check shared library id:
➜ cmake-build-debug git:(master) ✗ otool -L libsimpleLibrary.dylib
libsimpleLibrary.dylib:
#rpath/libsimpleLibrary.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 904.4.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1292.60.1)
➜ cmake-build-debug git:(master) ✗
It builds with #rpath by default. In my case I need to use #executable_path because I am facing linkage problems in the Mac OS without Xcode installed. Is there a way to change it in CMake build? I could change it using install_name_tool but I have to make that on build stage. Thanks in advance.

TypeError: __init__() should return None, not 'NoneType' with Python Boost

cmake file
cmake_minimum_required(VERSION 3.13)
project(p1)
set(CMAKE_CXX_STANDARD 11)
FIND_PACKAGE(PythonInterp)
if (PYTHONINTERP_FOUND)
if (UNIX AND NOT APPLE)
if (PYTHON_VERSION_MAJOR EQUAL 3)
FIND_PACKAGE(Boost COMPONENTS python${PYTHON_VERSION_SUFFIX})
FIND_PACKAGE(PythonInterp 3)
FIND_PACKAGE(PythonLibs 3 REQUIRED)
else()
FIND_PACKAGE(Boost COMPONENTS python)
FIND_PACKAGE(PythonInterp)
FIND_PACKAGE(PythonLibs REQUIRED)
endif()
else()
if (PYTHON_VERSION_MAJOR EQUAL 3)
FIND_PACKAGE(Boost COMPONENTS
python${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR})
FIND_PACKAGE(PythonInterp 3)
FIND_PACKAGE(PythonLibs 3 REQUIRED)
else()
FIND_PACKAGE(Boost COMPONENTS
python${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR})
FIND_PACKAGE(PythonInterp)
FIND_PACKAGE(PythonLibs REQUIRED)
endif()
endif()
else()
message("Python not found")
endif()
message(STATUS "PYTHON_LIBRARIES = ${PYTHON_LIBRARIES}")
message(STATUS "PYTHON_EXECUTABLE = ${PYTHON_EXECUTABLE}")
message(STATUS "PYTHON_INCLUDE_DIRS = ${PYTHON_INCLUDE_DIRS}")
message(STATUS "Boost_LIBRARIES = ${Boost_LIBRARIES}")
#ENABLE_TESTING()
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS})
add_library(pylib SHARED pylib.cpp)
target_link_libraries(pylib ${Boost_LIBRARIES} ${PYTHON_LIBRARIES})
#
# Tweaks the name of the library to match what Python expects
set_target_properties(pylib PROPERTIES SUFFIX .so)
set_target_properties(pylib PROPERTIES PREFIX "")
cmake output:
/Applications/CLion.app/Contents/bin/cmake/mac/bin/cmake -
DCMAKE_BUILD_TYPE=Debug -G "CodeBlocks - Unix Makefiles"
/Users/studentuser/CLionProjects/sbmlPythonAPI
-- Found PythonInterp: /usr/local/bin/python (found version "2.7.16")
-- Boost version: 1.68.0
-- Found the following Boost libraries:
-- python27
-- PYTHON_LIBRARIES = /usr/lib/libpython2.7.dylib
-- PYTHON_EXECUTABLE = /usr/local/bin/python
-- PYTHON_INCLUDE_DIRS =
/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr
/include/python2.7
-- Boost_LIBRARIES = /usr/local/lib/libboost_python27-mt.dylib
-- Configuring done
-- Generating done
-- Build files have been written to:
/Users/studentuser/CLionProjects/sbmlPythonAPI/cmake-build-debug
Bonjour.hpp
#include <iostream>
#include <string>
using namespace std;
class Bonjour
{
// Private attribute
string m_msg;
public:
// Constructor
Bonjour(string msg):m_msg(msg) { }
// Methods
void greet() { std::cout << m_msg << std::endl; }
void check_func() {cout<<"Hello! I am working"; }
// Getter/Setter functions for the attribute
void set_msg(std::string msg) { this->m_msg = msg; }
std::string get_msg() const { return m_msg; }
};
pylib.cpp
#include <boost/python.hpp>
#include "Bonjour.hpp"
using namespace boost::python;
BOOST_PYTHON_MODULE(pylib)
{
class_< Bonjour >("Bonjour", init<std::string>())
.def("greet", &Bonjour::greet)
.add_property("msg", &Bonjour::get_msg, &Bonjour::set_msg);
}
I get the error message stated in the tile when I try running
from pylib import Bonjour
b = Bonjour("He")
Error:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-2-a019b42ef03f> in <module>()
----> 1 b = Bonjour("He")
TypeError: __init__() should return None, not 'NoneType'
I am using macOS, and I also encounter this TypeError recently! It is probably caused by linking the built .so file to a different Python interpreter's lib/libpython2.7.dylib file.
1. First checkout your .so file by using otool -L command:
$ otool -L libh264decoder.so
libh264decoder.so:
/somepath/build/libh264decoder.so (compatibility version 0.0.0, current version 0.0.0)
/usr/local/opt/ffmpeg/lib/libavcodec.58.dylib (compatibility version 58.0.0, current version 58.35.100)
/usr/local/opt/ffmpeg/lib/libswscale.5.dylib (compatibility version 5.0.0, current version 5.3.100)
/usr/local/opt/ffmpeg/lib/libavutil.56.dylib (compatibility version 56.0.0, current version 56.22.100)
/usr/local/opt/boost-python/lib/libboost_python27-mt.dylib (compatibility version 0.0.0, current version 0.0.0)
/opt/local/Library/Frameworks/Python.framework/Versions/2.7/Python (compatibility version 2.7.0, current version 2.7.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.4)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.200.5)
Note that this .so file is linked to the Python installed by MacPort, which is located at: /opt/local/Library/Frameworks/Python.framework/Versions/2.7/Python
2. But the Python interpreter I am running is a different one.
It's located at: /Users/name/anaconda3/envs/py27/ (which apparently is installed by Anaconda).
3. So the solution is to let cmake link to the right Python library by setting DPYTHON_LIBRARY varible:
$ cd build/
$ cmake -DPYTHON_LIBRARY="/Users/name/anaconda3/envs/py27/lib/libpython2.7.dylib" ..
$ make
4. Finally, check the result:
$ otool -L libh264decoder.so
libh264decoder.so:
/somepath/build/libh264decoder.so (compatibility version 0.0.0, current version 0.0.0)
/usr/local/opt/ffmpeg/lib/libavcodec.58.dylib (compatibility version 58.0.0, current version 58.35.100)
/usr/local/opt/ffmpeg/lib/libswscale.5.dylib (compatibility version 5.0.0, current version 5.3.100)
/usr/local/opt/ffmpeg/lib/libavutil.56.dylib (compatibility version 56.0.0, current version 56.22.100)
/usr/local/opt/boost-python/lib/libboost_python27-mt.dylib (compatibility version 0.0.0, current version 0.0.0)
#rpath/libpython2.7.dylib (compatibility version 2.7.0, current version 2.7.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.4)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.200.5)
Note that the libpython2.7.dylib's linking path is changed.

CMake search for shared libraries in relative path

Is there a way to specify the shared library path from CMakeLists.txt?
I want to make an executable which uses OpenCV but I don't want the final user to install OpenCV. Instead I would like to deliver a folder containing my executable and the shared libraries it needs. The final structure should be something like
Delivery
MyApp
OpenCV (folder containing opencv dylibs)
In the end MyApp should search for the shared libs in OpenCV folder.
I tried to use the info from https://cmake.org/Wiki/CMake_RPATH_handling but for some reason I don't seem to understand what i really have to do to achieve what I want.
I tried to set CMAKE_INSTALL_RPATH to #loader_path or #executable_path but don't see any change. It still searches for opencv libs in /lib folder.
Running otool -L MyApp results in:
lib/libopencv_imgproc.3.1.dylib (compatibility version 3.1.0, current version 3.1.0)
lib/libopencv_imgcodecs.3.1.dylib (compatibility version 3.1.0, current version 3.1.0)
lib/libopencv_highgui.3.1.dylib (compatibility version 3.1.0, current version 3.1.0)
lib/libopencv_core.3.1.dylib (compatibility version 3.1.0, current version 3.1.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.1.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)

cmake cannot detect boost multiple installation

I've previous boost installation from ubuntu repo which is 1.42 and its installed in /usr/lib Now I downloaded 1.52 and ./b2 install that installed it in /usr/local/lib. now cmake is detecting 1.52 only and using include Path from /usr/local/include (which is 1.52) and using library directory /usr/lib (which is 1.42) and giving undefined reference errors.
cmake_minimum_required(VERSION 2.6)
PROJECT(app)
set(Boost_USE_MULTITHREADED ON)
FIND_PACKAGE(Boost 1.52 COMPONENTS filesystem program_options thread system serialization REQUIRED)
ADD_EXECUTABLE(app list_of_cpp_files)
MESSAGE(STATUS "** Boost Include: ${Boost_INCLUDE_DIR}")
MESSAGE(STATUS "** Boost Libraries: ${Boost_LIBRARIES}")
TARGET_LINK_LIBRARIES(app ${Boost_LIBRARIES})
if(CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "-g -O2")
set(CMAKE_EXE_LINKER_FLAGS "-s")
endif()
even if I give a LIBRARY_PATH in CMakeLists.txt it still uses /usr/lib
What should be done now ? would I do a booststrap.sh --prefix=/usr but wont that make duplicate copies ? also Do I need change all symlinks manually ?
or I'll remove previous installation (1.42) from repo (apt-get) ? I cannot remove all because there are dependant packages.
Solved by doing a ./bjam --layout=tagged install