Can CocoaPods pod a library build by cMake with another cMake dependencies? - c++

I have a library build with cMake, and use cMake manage third party dependencies(use FetchContent);
Library has a podspec file that use framework for another proj needed use, but i wanna debug it in local, seems change the local podspec is easy:
...
spec.prepare_command = <<-CMD
mkdir -p build/ios && cd build/ios
cmake ../.. -GXcode -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_INSTALL_PREFIX=./
cmake --build . --target install -j 20
CMD
...
Unfortunately, i found out podspec files needs the spec.sources to list sources file which i already specify in cMake, is there a way CocoaPods use cmake generate xcodeproject directly, or another way that can resolve xcodeproj dependency with library build by cMake?

Related

How can I add all Boost libraries as include directories?

I'm pulling in Boost using CPM to build another dependency of my project.
CPMAddPackage(
NAME Boost
VERSION 1.77.0
GITHUB_REPOSITORY "boostorg/boost"
GIT_TAG "boost-1.77.0"
)
The issue I'm having is exposing the header files to my dependency. I dumped all of the cmake variables, and there are many variables like boost_accumulators_SOURCE_DIR, boost_algorithm_SOURCE_DIR, boost_any_SOURCE_DIR, boost_asio_SOURCE_DIR, etc. My dependency depends on many of these libraries, and it's really tedious to list them all as include directories:
target_include_directories(
nghttp2_asio
PRIVATE "${boost_system_SOURCE_DIR}/include"
PRIVATE "${boost_config_SOURCE_DIR}/include"
PRIVATE "${boost_asio_SOURCE_DIR}/include"
PRIVATE "${boost_throw_exception_SOURCE_DIR}/include"
PRIVATE "${boost_assert_SOURCE_DIR}/include"
PRIVATE "${BoostAlign_SOURCE_DIR}/include"
PRIVATE "${boost_date_time_SOURCE_DIR}/include"
)
Is there a better way to do this?
CPM is just a thin layer around FetchContent, which in turn downloads your dependency into your build folder and then attempts to add_subdirectory it, adding it to your main build.
I think this is a bad idea for a lot of reasons...
Boost is one of the most commonly packaged C++ libraries, period. Integrating your project into an existing environment (like a Linux distro, or another package manager like Conan or Vcpkg) is going to be difficult if not impossible (without patching, I mean) since it will surely want your project to use the curated build of Boost.
Adding any third party CMake code to your own build is signing up for headaches... have you noticed how hard it is to write correct CMake code? What if Boost clobbers your cache variables or defines targets that conflict with yours?
CMake has built-in and standard support for locating many versions of Boost, including the newer versions that provide first-party CMake config modules.
Boost now provides first-party CMake config modules.
I don't think any build using Boost should be any more complex than this:
cmake_minimum_required(VERSION 3.22)
project(boost-usage-example)
find_package(Boost 1.77 REQUIRED system date_time)
add_executable(nghttp2_asio main.cpp ...)
target_link_libraries(
nghttp2_asio
PRIVATE
Boost::boost # all header-only libs: config asio throw_exception assert align
Boost::date_time
Boost::system
)
See the documentation here: https://cmake.org/cmake/help/latest/module/FindBoost.html
You only list as components (after REQUIRED) the non-header-only libraries. Those are also the ones that require special addition via target_link_libraries. Link to Boost::boost to get all the header-only modules.
This will work no matter what package manager you're using.
If you want to use vcpkg, create a file called vcpkg.json in your project root with the following contents:
{
"name": "boost-usage-example",
"version-string": "0.1.0-dev",
"dependencies": [
"boost-system",
"boost-config",
"boost-asio",
"boost-throw-exception",
"boost-assert",
"boost-align",
"boost-date-time"
]
}
You can also depend on just boost and it will acquire all boost modules, not just the ones you need. Then acquire vcpkg:
$ git clone https://github.com/microsoft/vcpkg.git
$ ./vcpkg/bootstrap-vcpkg.sh
Then build with:
$ cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=$PWD/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=Release
$ cmake --build build
Done!
Suppose on the other hand that you wanted to use Conan. No big deal, just install Conan in a pip virtual environment:
$ python3 -m venv venv
$ . venv/bin/activate
$ python3 -m pip install -U pip setuptools wheel
$ python3 -m pip install conan
Then create a conanfile.txt with the following contents:
[requires]
boost/1.77.0
[generators]
cmake_paths
Install the dependencies:
$ mkdir build && pushd build && conan install .. && popd
And then build, using Conan's generated toolchain file:
$ cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=$PWD/build/conan_paths.cmake -DCMAKE_BUILD_TYPE=Release
$ cmake --build build
In fact, you can provide both a vcpkg.json and a conanfile.txt and your users will be free to use either one or neither and rely on their system package manager or a package manager you don't know about. In any case it will just work and you free yourself of a mountain of maintenance burdens.

How to install a Library for C++ like Eigen and sharkML at vs code?

I am trying to install libraries like eigen, sharkMl, xtensor, and others in VSCode for C++.
Please if anyone can help me to know the right way to do that.
All of these libraries use CMake for their build system so what I do is use CMake as my build system. My favorite way to do this is to use the libraries build systems to install them and then inlcude them with cmakes find_package function. This you can do by cloning the git repository for the library then build it and install it with cmake. On linux you do this by:
git clone https://gitlab.com/libeigen/eigen.git
cd eigen
mkdir build
cd build
cmake ..
sudo make install
VSCode has good integration for cmake so if you have the C/C++ Extension pack you will be able to build with cmake. In your project folder make a CMakeLists.txt file and add the packages you want:
add_executable(main main.cpp)
find_package(Eigen3 3.4 NO_MODULE)
target_link_libraries(main Eigen3::Eigen)
(This example assumes the main cpp file is main.cpp and creates an executable called main) Then when you press ctr+shift+p and perform CMake: Configure you can select your compiler and build the executable.

Build specific modules in Qt6 (i.e. QtMqtt)

For a project which uses MQTT, I always had to compile the QtMqtt module from source, because it wasn't included in the prebuilt windows release and couldn't be chosen for installation either. In Qt5 that was pretty easy: Download source code from official git (https://code.qt.io/cgit/qt/qtmqtt.git/), open the .pro file in QtCreator and compile the project. For installation, I just moved the .dll files to my Qt install directory.
Now in Qt6, the build process was switched from qmake to cmake, so I cannot simply load the project in QtCreator, but have to compile it manually using CMake, which I find really unintuitive and prone to errors. From what I understand, I cannot compile single modules on their own from now on, but have to get the whole Qt 6.2.0 source code instead (i.e. via installer option) and then use a --target option on CMake to build only specific module. So here is what I did so far:
Get Qt source code from installer (installed to Qt/6.2.0/Src)
Create a command line environment according to this manual
Open cmd environment, navigate to build folder (i.e. Qt/6.2.0/build)
Configure build using command: ..\Src\configure -prefix Qt\6.2.0\build
Build with cmake using command cmake --build . --target qtmqtt
Install using command cmake --install .
What happens, is that the configuration works, and the build supposedly too, but installation fails with something like:
CMake Error at qtbase/src/3rdparty/libpng/cmake_install.cmake:41 (file):
file INSTALL cannot find
"F:/DEV/prog/Qt/6.2.0/build/qtbase/mkspecs/modules/qt_ext_libpng.pri": File
exists.
Call Stack (most recent call first):
qtbase/src/3rdparty/cmake_install.cmake:42 (include)
qtbase/src/cmake_install.cmake:42 (include)
qtbase/cmake_install.cmake:244 (include)
cmake_install.cmake:42 (include)
The folder Qt/6.2.0/build then only consists of .cmake files but nothing which seems to be usable .dll files for me. I just don't understand how to properly set up everything with cmake. Why would they make it so complicated after all now, as it was fairly easy to compile modules with qmake in Qt5?
Having Qt 6.4.2 installed in ${HOME}/Qt/6.4.2/ using the Qt Installer, this is how I did it on Linux.
Detailed steps:
# Create a work directory
mkdir ~/temporal && cd ~/temporal
# Clone the repository
git clone https://github.com/qt/qtmqtt.git
# Switch to the repository
cd qtmqtt
# Checkout the branch corresponding to the target kit
git checkout 6.4.2
# Create a directory to build the module cleanly
mkdir build && cd build
# Use the qt-configure-module tool
~/Qt/6.4.2/gcc_64/bin/qt-configure-module ..
# Build it here
~/Qt/Tools/CMake/bin/cmake --build .
# Install the module in the correct location
~/Qt/Tools/CMake/bin/cmake --install . --verbose
Testing on a clean project:
Edit the project's CMakeLists.txt file
(1) Add Mqtt to the relevant find_package macro like this:
find_package(QT NAMES Qt6 COMPONENTS Widgets Network Sql Mqtt REQUIRED)
(2) Add Qt${QT_VERSION_MAJOR}::Mqtt to a target_link_libraries line like this:
target_link_libraries(MyCleanProject PRIVATE Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Network Qt${QT_VERSION_MAJOR}::Mqtt Qt${QT_VERSION_MAJOR}::Sql)
(3) Run CMake
Try actually using the module
Add relevant includes in the project source like this:
#include <QtMqtt/QtMqtt>
// and then try to use QtMqtt classes
QMqttClient client;
Rebuild the project. Should compile and link cleanly.
Addendum
It's desirable to have proper environment variables set while building Qt projects from the CLI. My preference is to have a script in my user directory with all the relevant variables.
My Qt_environment.sh:
export QT_VERSION="6.4.2"
export QT_INSTALL_DIR="${HOME}/Qt"
export CMAKE_BIN_DIR="${QT_INSTALL_DIR}/Tools/CMake/bin"
export QMAKE_BIN_DIR="${QT_INSTALL_DIR}/${QT_VERSION}/gcc_64/bin"
export CMAKE_PREFIX_PATH="${QT_INSTALL_DIR}/${QT_VERSION}/gcc_64/"
export NINJA_DIR="${QT_INSTALL_DIR}/Tools/Ninja"
export PATH="${PATH}:${CMAKE_BIN_DIR}:${QMAKE_BIN_DIR}:${NINJA_DIR}"
One can choose to load manually from the command line before building a project like this
source $HOME/Qt_environment.sh
# do some Qt stuff here, cmake, ninja, etc
or simply have it loaded from .bashrc for every new bash shell. The same can be accomplished for any other shell.
# $HOME/.bashrc
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
# ...
# rest of the .bashrc file ommited for brevity
# ...
# Relevant part here - add these two lines at the end
# Load Qt environment variables
source "$HOME/Qt_environment.sh"
From what I understand, I cannot compile single modules on their own
from now on, but have to get the whole Qt 6.2.0 source code instead
(i.e. via installer option)
That's not correct. Given a pre-built Qt, you should be still able to just build the qmqtt package from source by running e.g.
<QTDIR>\bin\qt-configure-module <mqtt_src_dir>
cmake --build .
try to replace cmake --install . with cmake --install qtmqtt

How can I use OpenCV without running 'make install'?

I am new to cmake and OpenCV.
Is there a way that I can use OpenCV on my machine by just building the source code and not installing them to /usr/local/lib on my machine, i.e. without running make install after building the binaries?
The solution would be to set CMAKE_INSTALL_PREFIX to a specific location:
# in opencv/build
cmake .. -DCMAKE_INSTALL_PREFIX=/home/user/path/to/deps/
cmake --build . --target install
Then, configure your project with the same prefix:
# in your project/build
cmake .. -DCMAKE_PREFIX_PATH=/home/user/path/to/deps/
In your cmake files, simply use find_package(OpenCV)

gRPC cmake installation doesn't generate targets file

I've been trying to build and install gRPC with cmake. Building the project went relatively smoothly with ninja after some confusion related to acquiring nuget packages and updating the git submodules.
I am having trouble installing gRPC though. After reading the cmake file I discovered that you need to manually set the gRPC_INSTALL cache variable to ON in order for cmake to generate an install target. After doing this I can invoke the install target and the libraries and headers and cmake config files are emplaced. But the cmake targets file is missing, and it isn't even being generated. The config file is simple, all it does is call the targets file:
include(${CMAKE_CURRENT_LIST_DIR}/gRPCTargets.cmake)
But it doesn't look like the CMakeLists file in gRPC is even attempting to generate this file, unless I am missing something? You can't even build the example cpp project in the gRPC repo with cmake because when it tries to find the gRPC package, the config file fails to find gRPCTargets.cmake. So what is the proper way to build, install, and link to gRPC with cmake? I am on Windows but that shouldn't matter with cmake.
on OSX:
run these command:
cd grpc
mkdir -p cmake/build
cd cmake/build
cmake -DgRPC_INSTALL=ON -DgRPC_BUILD_TESTS=OFF -DgRPC_PROTOBUF_PROVIDER=package -DgRPC_ZLIB_PROVIDER=package -DgRPC_CARES_PROVIDER=package -DgRPC_SSL_PROVIDER=package -DCMAKE_BUILD_TYPE=Release -DOPENSSL_ROOT_DIR=/usr/local/Cellar/openssl/1.0.2r -DOPENSSL_LIBRARIES=/usr/local/Cellar/openssl/1.0.2r/lib ../..
make install