Distributing c++ software macOS. Static, Dynamic, Installers - c++

My project uses OpenCV installed via homebrew
I've tried static linking via my cmakelists, but it doesn't seem to work and still looks for the dylibs.
I've tried to build my own OpenCV but I can't get the project to link to it.
The project is a terminal utility, how can I package it and the dylibs so that they can be installed on a client system? Where the user doesn't have Homebrew/OpenCV installed or any knowledge and desire to do it manually.
I've managed to get self built openCV linking with. I think previously there were several versions floating around on my system where I have been trying to get this to work. I cleaned them all up and started from the beginning.
add opencv to project libs subfolder
configure in cmake gui and generate unix make files. Some tinkering here, had to turn zlib off and eigen otherwise i'd get build errors later down the line.
run make install
updated project cmake as below
cmake_minimum_required(VERSION 3.24)
set(BUILD_SHARED_LIBS OFF)
if(APPLE)
set (CMAKE_OSX_DEPLOYMENT_TARGET "11" CACHE STRING "Minimum OS X deployment version" FORCE)
set (CMAKE_OSX_ARCHITECTURES "arm64" CACHE STRING "Architectures" FORCE)
set (CMAKE_XCODE_ATTRIBUTE_MACOSX_DEPLOYMENT_TARGET[arch=arm64] "11.0" CACHE STRING "arm 64 minimum deployment target" FORCE)
endif()
project(watermark)
set(CMAKE_CXX_STANDARD 17)
add_subdirectory(libs/cargs)
find_package(OpenCV REQUIRED)
add_executable(watermark main.cpp watermark.h watermark.cpp)
target_link_libraries(watermark LINK_PUBLIC cargs ${OpenCV_LIBS})
The release binary is around 4MB so seems to be working.
However when trying to run on client systems I now get:
dyld: Symbol not found: __ZTTNSt3__114basic_ifstreamIcNS_11char_traitsIcEEEE
Referenced from: /Users/howardcolin/Desktop/./watermark
Expected in: /usr/lib/libc++.1.dylib
Is there anything else to add to the linker section for a fully statically linked independent binary that will run on any MacOS11+
When adding this target to cmake I get linker warnings that OpenCV was built for MacOS 12.5, so probs need to rebuild openCV again...

Related

How to set up OpenCV with cmake to enable dynamic and static builds?

I've built and make installed opencv on my mac with SHARED_LIBS.
I want to be able to choose for each project if I built with or without shared libs.
When I compile an additional OpenCV build with -DBUILD_SHARED_LIBS=OFF how can I reference it in my project's CMakeLists and chose the build type I want?
I have the source with shared libs in my ~/opencv and I've already compiled it in ~/opencv/build followed by make install.
When I create another dir like ~/opencv/static_build how would I have to adapt my CMakeLists in order to make a static build app? So far I've used:
find_package( OpenCV REQUIRED )
include_directories(${OpenCV_INCLUDE_DIRS})
target_link_libraries(test ${OpenCV_LIBS})
But if I'm not mistaken, these lines all depend variables which have been added to cmake during my inital make install.
It works by configuring a different install location with the cmake flag -D CMAKE_INSTALL_PREFIX for each build and make install will then install them to their respective locations.
In order to distinguish between the specific builds and to allow cmake to find the library if it not in its path, one has to add the following line to the project's CMakeLists.txt:
set(OpenCV_DIR /path/to/build/lib/cmake)
before:
find_package( OpenCV REQUIRED )

How do I use cmake to build external libraries as well as my own application?

I am trying to build a cross platform OpenGL application, which means building and including multiple libraries (glfw, glbinding, glm, etc.) Because my application is cross platform, it makes sense to use cmake to generate all the build scripts and not have to muck about with them myself. I am attempting to target Windows and Linux specifically.
A main feature that I need is that the libraries I need are not installed on the host system. Furthermore, they cannot be installed (due to administrative reasons). What I need is to build these libraries and then build my application.
I am mostly working on Windows using Visual Studio 2017, which has cmake support included. Currently, I have attempted to build these libraries myself, however I am having many issues getting find_package to do the right thing.
My directory structure looks like this:
project/
|-src/
|- my sources for my application
|-include/
|- my header files
|-external/
|-glfw-3.2.1/
|-glbinding-2.1.4/
|-glfw-build/
|-glbinidng-build/
So I am attempting to build the external libraries and use them in my application. I am also attempting to follow cmake best practices. My CMakeLists.txt currently looks like this:
cmake_minimum_required(VERSION 3.5)
project(glTestProj)
set(CMAKE_PREFIX_PATH "external/")
find_package(glfw3 3.2 REQUIRED)
find_package(glbinding REQUIRED)
add_executable(glTest src/main.cpp)
target_compile_features(glTest PRIVATE cxx_std_17)
target_compile_options(glTest PRIVATE -Wall -Wextra)
target_link_libraries(
glTest
glfw
glbinding::glbinding
)
The libraries in question (glfw and glbinding) both have instructions on including them via cmake, however I am running into this issue:
CMake Error at CMakeLists.txt:6 (find_package):
By not providing "Findglfw3.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "glfw3", but
CMake did not find one.
Could not find a package configuration file provided by "glfw3" (requested
version 3.2) with any of the following names:
glfw3Config.cmake
glfw3-config.cmake
Add the installation prefix of "glfw3" to CMAKE_PREFIX_PATH or set
"glfw3_DIR" to a directory containing one of the above files. If "glfw3"
provides a separate development package or SDK, be sure it has been
installed.

C++ How to run programs in Clion when you need to include OpenGL libraries?

Hello I need to work with OpenGL and want to create my project in Clion. But Clion cannot compile and run my projects because of the libraries I need to include. I can create my own makefile and run the program in terminal, but I want to do it in the IDE. How can I make this happen?
First make sure you installed all libraries correctly using the compiler you configured in clion/cmake. Assuminf you have a fresh CMakeLists.txt like
cmake_minimum_required(VERSION 3.3.2)
project(MyGL CPP)
add_executable(demo-run main.cpp)
For linking your libraries you need two things. First tell the compiler where to find the include files and second which libraries to link. You could just hard code you local installation like
target_link_libraries(demo-run path/to/glfw.lib path/to/opengl.lib path/to/jpeg.lib ...)
target_include_directories(demo-run PRIVATE path/to/glfw/include path/to/opengl/include path/to/jpeg/include ...)
however this is not very portable and if you want to work with another compiler or on another machine your project file will fail. Instead you can use the package system of cmake
find_package(PkgConfig REQUIRED)
pkg_search_module(GLFW REQUIRED glfw3)
find_package(JPEG REQUIRED)
find_package(GLEW REQUIRED)
find_package (OpenGL REQUIRED)
find_package (GLM REQUIRED)
target_link_libraries(demo-run ${GLFW_LIBRARIES} ${GLEW_LIBRARIES} ${JPEG_LIBRARIES} ${OPENGL_LIBRARIES})
target_include_directories(demo-run PRIVATE ${GLFW_INCLUDE_DIRS} ${GLEW_INCLUDE_DIR} ${JPEG_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR} ${GLM_INCLUDE_DIR})
The glfw part is a bit tricky and works only on linux i guess see http://www.glfw.org/docs/3.0/build.html.
This code is not tested at all and you may need to specify some enviroment variables so cmake can find the packages or provide additional find scripts like https://github.com/lighttransport/nanogi/blob/master/cmake/FindGLM.cmake.
I would recommend to use the CMake build tool which does the work generating Makefiles for you and is also directly supported by clion. When you open the directory containing a CMakeLists.txt (CMake Project File) with clion, it should be automatically be loaded and compiled (if not just hit build)
A very simple example CMake project would look like this
cmake_minimum_required (VERSION 2.8.9)
project (OpenGl-Stuff)
include_directories(src)
add_executable(your-binary src/your-code.c src/your-code.h)
target_link_libraries(your-binary opengl)
# target_link_libraries will search for libopengl on standard system paths,
# maybe the library is not called libopengl, then you have to adjust the name above
this cmake project will generate the binary for you and link it against opengl

Setup CMake with SFML in VS2017

Just like in CLion I want to use SFML with Visual Studio 2017, but I'm still learning cmake and I don't know the commands or the logic of how cmake works at all. I've just seen some posts and got this litle script.
Note: I downloaded the latest version of sfml in the link provided, I just taked the extrated directory and put alongside CMakeLists.txt in my folder
#sets up the minimum version of cmake
cmake_minimum_required(VERSION 3.9)
#how the project will be called
project (space_impact)
#set c++11 standard
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" -std=c++11)
#set source files
set (SOURCE_FILES main.cpp)
#we add the executable of the program
add_executable (space_impact ${SOURCE_FILES})
#taked from a mac-clion tutorial, doesn't work
set (CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/SFML/cmake-modules/")
find_package (SFML REQUIRED system window graphics network audio)
if (SFML_FOUND)
include_directories(${SFML_INCLUDE_DIR})
target_link_libraries(space_impact ${SFML_LIBRARIES})
endif()
that thing gave me errors:
Error CMake Error at SFML/cmake-modules/FindSFML.cmake:355 (message):
Could NOT find SFML (missing: SFML_SYSTEM_LIBRARY SFML_WINDOW_LIBRARY
SFML_GRAPHICS_LIBRARY SFML_NETWORK_LIBRARY SFML_AUDIO_LIBRARY) SFML/cmake-modules/FindSFML.cmake
I want everything to be dynamic, but I don't know how can I do that..
So my question is what should I do for setting up correctly SFML with Cmake in Visual Studio.
I don't want the old-fashioned method from the official website
UPDATE
Here's my location....
The thing is.. the FindSFML.cmake script it's not working...
What files should I move for make it working?
Your script is perfectly fine, except three things I'd change:
Move the whole module detection before defining targets. I'm pretty sure you also have to define your include directories before.
Your if(SFML_FOUND) bracket is pretty pointless right now, because you've set SFML to be required, which means it will never get past find_package() unless it's found.
-std=c++11 is a GCC only flag (MSVC will always use the latest standard, unless specified). As such you'll have to check the compiler here or use CMAKE_CXX_STANDARD.
So the "cleaned" CMakeLists.txt could look like this:
#sets up the minimum version of cmake
cmake_minimum_required(VERSION 3.9) # personally I'd set this version as low as required; you don't have to require the cutting edge version
#how the project will be called
project (space_impact)
#set the C++ standard to be used
set (CMAKE_CXX_STANDARD 11)
#set source files
set (SOURCE_FILES main.cpp)
#look for SFML and add it
set (CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/SFML/cmake-modules/")
find_package (SFML REQUIRED system window graphics network audio)
include_directories(${SFML_INCLUDE_DIR})
#we add the executable of the program
add_executable (space_impact ${SOURCE_FILES})
target_link_libraries(space_impact ${SFML_LIBRARIES} ${SFML_DEPENDENCIES})
Note that adding SFML_DEPENDENCIES to the library list is optional, unless you're using a static version of SFML.
But what about your SFML issue? Since you don't have the SFML files installed in any directory looked into by default, you'll have to tell CMake where it's found using the CMake variable SFML_ROOT or the environment variable of the same name.
So the first time you're invoking CMake, it could look like this:
cmake -G "Visual Studio 15 2017" -DSFML_ROOT=path/to/sfml path/to/source
This is all you need to compile sfml in your cmake project.
find_package(SFML 2.5.1 COMPONENTS system graphics audio network REQUIRED)
add_executable (AwesomeProject "AwesomeProject.cpp" "AwesomeProject.h")
target_link_libraries(AwesomeProject PRIVATE sfml-audio sfml-graphics sfml-network sfml-system)
Also set SFML_DIR var to your sfml folder.

CMake exports targets with absolute path

I am developing a static library and I am using CMake. This library needs Boost. So I did the following:
set(LIBRARY_NAME "MyLib")
set(LIBRARY_VERSION 1.0.0)
project(${LIBRARY_NAME} VERSION ${LIBRARY_VERSION})
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_MULTITHREADED ON)
find_package(Boost COMPONENTS system filesystem regex thread date_time log log_setup REQUIRED)
include_directories(${Boost_INCLUDE_DIR})
link_directories(${Boost_LIBRARY_DIR})
add_library(${LIBRARY_NAME} STATIC xx.cpp)
target_link_libraries(${LIBRARY_NAME} PUBLIC ${Boost_LIBRARIES})
Everything is fine till now.
Now, I need to make this library install-able. So, I follow this tutorial https://cmake.org/cmake/help/v3.0/manual/cmake-packages.7.html
Everything looks fine on my machine. However, when I moved the installed files (The files that are generated by calling make-install) into another machine and tried to use it using find_package(MyLib), problem raised saying that it could find boost in the in a place supposed to be on my original machine. I dig into the file MyLibTargets.cmake and I saw absolute paths of Boost library!
Why this is happining? how can I prevent this?
If you took the cmake build directory and used it from another machine, this won't work. cmake is not intended to support different platforms from the same working directory.
You need to use out of source builds for this purpose. But once you did an in place build with cmake the directory is burned and out of source builds no longer work for this source tree. You need to delete all cmake temporary files and folders to get the source tree working again in this case.