cmake link to macOS pre-compiled binaries at custom path - cmake

I want to link to the GLFW library using the binaries provided when downloading from the website at a custom path in my project:
include_directories(PROJECT_SOURCE_DIR/third_party/glfw/lib-arm64)
add_executable(rpg main.cpp)
target_include_directories(rpg PRIVATE ${PROJECT_SOURCE_DIR}/third_party/glad/include ${PROJECT_SOURCE_DIR}/third_party/glfw/include)
find_library(GLFW_LIB NAMES glfw3 PATHS PROJECT_SOURCE_DIR/third_party/glfw PATH_SUFFIXES lib-arm64 lib-universal lib-x86_64)
target_link_libraries(rpg PRIVATE ${GLFW_LIB})
I've tried finding both glfw and glfw3 but this fails to find the GLFW library:
CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
GLFW_LIB
linked by target "rpg" in directory /Users/ashley/Personal/rpg/src
How should I specify the path to link to these rather than use a globally installed version or building from source myself?
Edit
Correcting the use of find_library as per #Tsyvarev suggestion solved this. The prior update to say it still didn't work was in haste - I wasn't correctly expanding the path variable.

Related

CMake importing both shared and static library versions, but I only want one

I would like to use the Antlr framework in a project. I'm using CMake to build the project.
I would like to use the SHARED library version of Antlr, not the STATIC one. Its CMake file contains targets for both.
Antlr's github site explicity tells me to use the following code:
find_package(antlr4-runtime REQUIRED)
# add runtime include directories on this project.
include_directories( ${ANTLR4_INCLUDE_DIR} )
# add runtime to project dependencies
add_dependencies( Parsertest antlr4_shared )
# add runtime to project link libraries
target_link_libraries( Parsertest PRIVATE
antlr4_shared)
(another target, antlr4_static, exists, but shouldn´t be used.)
I copied it exactly like this and am getting the following error:
CMake Error at /usr/lib64/cmake/antlr4-runtime/antlr4-targets.cmake:82 (message):
The imported target "antlr4_static" references the file
"/usr/lib/libantlr4-runtime.a"
but this file does not exist.
I dont have the static library installed in my system as I have no intention of using it. Still, how do I make CMake stop looking for the wrong target in the first place? I use it nowhere in my CMakeLists.txt file and am puzzled by this behavior.

CMake package configuration files for upstream projects using Qt5 problems

I am working on a larger C++ library that is using CMake and depends on Qt.
We moved from Qt4 to Qt5 and now I encounter a problem when using our lib
in an upstream project. As a minimal working example demonstrating the problem please have a look at this repo:
https://github.com/philthiel/cmake_qt5_upstream
It contains two separate CMake projects:
MyLIB: a tiny library that uses QString from Qt5::Core.
It generates and installs package configuration files
MyLIBConfig.cmake, MyLIBConfigVersion.cmake, and MyLIBTargets.cmake
in order to be searchable by CMake find_package()
MyAPP: a tiny executable depending on MyLIB
The project uses find_package(MyLIB) and creates an executable that uses MyLIB
The problem is that CMake gives me the following error message when configuring the MyAPP project:
CMake Error at CMakeLists.txt:11 (add_executable):
Target "MyAPP" links to target "Qt5::Core" but the target was not found.
Perhaps a find_package() call is missing for an IMPORTED target, or an
ALIAS target is missing?
The reason for this behaviour is that in the automatically generated MyLIBTargets.cmake file the INTERFACE_LINK_LIBRARIES entry for Qt5 Core is the Qt5::Core symbol. Using Qt4, the absolute path to the Qt core lib was specified here.
Now, I simply can resolve this by using
find_package(Qt5Core 5.X REQUIRED)
in the MyAPP project.
However, I would like to know if this is the intended/generic way to go, i.e. requesting upstream projects of our lib to search for the required transitive Qt5 dependencies themselves, or if I probably misuse CMake here and need to change my configuration procedure?
The CMake docu on package file generation
https://cmake.org/cmake/help/v3.0/manual/cmake-packages.7.html
mentions that macros can be provided by the package configuration files to upstream. Maybe this would be the correct place to search for imported targets like Qt5 and break upstream configuration runs when these dependencies are not found?
Best,
Philipp
[edit of the edit] Full Source Example
You need to deliver a CMake config file for your project, and probably the ConfigFile should be generated via CMake itself (because you cannot know for shure where the user will install your software).
Tip, use the ECM cmake modules to ease the creation of that:
find_package(ECM REQUIRED NO_MODULE)
include(CMakePackageConfigHelpers)
ecm_setup_version(${PROJECT_VERSION}
VARIABLE_PREFIX ATCORE
VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/atcore_version.h"
PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KF5AtCoreConfigVersion.cmake"
SOVERSION 1
)
configure_package_config_file("${CMAKE_CURRENT_SOURCE_DIR}/KF5AtCoreConfig.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/KF5AtCoreConfig.cmake"
INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR}
)
and the KF5AtCoreConfig.cmake.in:
#PACKAGE_INIT#
find_dependency(Qt5Widgets "#REQUIRED_QT_VERSION#")
find_dependency(Qt5SerialPort "#REQUIRED_QT_VERSION#")
find_dependency(KF5Solid "#KF5_DEP_VERSION#")
include("${CMAKE_CURRENT_LIST_DIR}/KF5AtCoreTargets.cmake")
This will generate the correct FindYourSortware.cmake with all your dependencies.
[edit] Better explanation on what's going on.
If you are providing a library that will use Qt, and that would also need to find the Qt5 library before compilling the user's source, you need to provide yourself a FindYourLibrary.cmake code, that would call
find_package(Qt5 REQUIRED COMPONENTS Core Gui Widgets Whatever)
Now, if it's your executable that needs to be linked, use the Components instead of the way you are doing it now.
find_package(Qt5 REQUIRED COMPONENTS Core)
then you link your library with
target_link_libraries(YourTarget Qt5::Core)

GLEW with CMakeLists

I have the following CMakeLists to include glew into my project. Compiling the project works fine but when I run the project I get an error saying that the program can't find glew32.dll. Any ideas why?? Thanks for answers!
set(CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/external/glew-1.12.0")
set(CMAKE_LIBRARY_PATH "${CMAKE_SOURCE_DIR}/external/glew-1.12.0/lib/Release/Win32/")
find_package(GLEW REQUIRED)
if(GLEW_FOUND)
message("GLEW Found!")
include_directories(${GLEW_INCLUDE_DIRS})
link_libraries(${GLEW_LIBRARIES})
add_definitions(${GLEW_DEFINITIONS})
else(GLEW_FOUND)
message(FATAL_ERROR "GLEW NOT Found")
endif(GLEW_FOUND)
add_executable(Project ${CODE})
target_link_libraries(Project ${GLEW_LIBRARIES})
You need to have the directory where glew32.dll can be found in your environment's PATH variable. If you're using MSVC set the Environment textbox in your property pages of your application:
PATH=<dir-of-glew32.dll>;%PATH%
If you're running from shell, issue the same command on the command line.
Another option is to use GLEW as a static library. In that case you will not need glew32.dll, the entire glew library will be linked into your program. Check out the GLEW github repository and study the script cmake-testbuild.sh about how to use GLEW as a static library.
Please note, that the GLEW github repository does not contain certain generated files. If you can't run make extensions on your platform, use this repository: glew-with-extensions which already contains the generated files.

CMAKE RPATH not working - could not find shared object file

I am trying to get rid of setting LD_LIBRARY_PATH everytime time I run my program. After adding in the library and targeting my executable to the library, when I run it tells me it can not open shared object library, no such file or directory.
In my CMakeLists.txt I have:
add_library(heart SHARED ${HEART_FILES})
add_executable(run ${RUN_FILES})
target_link_libraries(run heart)
set(CMAKE_SKIP_BUILD_PATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
set(CMAKE_INSTALL_RPATH "~/person/target/usr/local/lib")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
I set an absolute link to my library folder to test out whether this would create an rpath to my library and it seems like there isn't. I have checked and made sure that the shared library is indeed in lib. libheart.so is the file that is being linked. What else am I missing?
It is because you build heart and run from the same cmake project:
CMAKE_INSTALL_RPATH_USE_LINK_PATH is an interesting and very useful option. When building a target with RPATH, CMake determines the RPATH by using the directories of all libraries to which this target links. Some of these libraries may be located in the same build tree, e.g. libbar.so, these directories are also added to the RPATH.
If this option is enabled, all these directories except those which are also in the build tree will be added to the install RPATH automatically. The only directories which may then still be missing from the RPATH are the directories where the libraries from the same project (i.e. libbar.so) are installed to. If the install directory for the libraries is not one of the systems default library directories, you have to add this directory yourself to the install RPATH by setting CMAKE_INSTALL_RPATH accordingly
You can try this:
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
More documentation here cmake rpath handling
EDIT:
Only this should work:
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
add_library(heart SHARED ${HEART_FILES})
add_executable(run ${RUN_FILES})
target_link_libraries(run heart)
install(
TARGETS heart run
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
)
Clean your build directory and then:
cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=/home/person/target/usr/local ..
make install
At the end of the g++ line Linking CXX executable run you should see like -Wl,-rpath,/home/person/target/usr/local/lib
If you want a fully relocatable package:
set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib")
PS: are you sur that it is libheart.so that is not found ?
In your CMake file, set the RPATH before defining the targets. The CMAKE_INSTALL_RPATH must be defined before calling add_executable(), otherwise it has no effect.
I had a similar issue as the original post. I created executables which linked to external shared libraries. This approach compiled and executed fine from the build directory. However, the executable that was installed to a separate directory could not find a shared library at runtime:
error while loading shared libraries: libxxxx.so.1: cannot open shared object file: No such file or directory
To solve, I
1) upgraded to CMake 3.17
2) used Craig Scott's recommended:
set(CMAKE_INSTALL_RPATH $ORIGIN)
as explained in his talk
3) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) as directly mentioned to solve this error in the second common question in Kitware's documention
4) Put all this before adding the targets as mentioned in this post
5) Used the "$ORIGIN/../lib" syntax instead of Craig's Scott's mentioned $ORIGIN as mentioned by #explo91
In summary, and to my suprise, only the "$ORIGIN/../lib" before the target definition was necessary from above (I tested the other combinations which did not fix the cannot open shared object file runtime issue).
Anyway the solution I finally applied, which may be of better, fine-grained CMake style or at least may be helpful to others on their RPATH journey is:
set_target_properties(target_defined_above PROPERTIES INSTALL_RPATH "$ORIGIN/../lib")

Linking GLEW with CMake

How can you link GLEW to a project with CMake?
We've been trying to link GLEW to our project using CMake for at least 3 hours without any success so any help is accepted.
I'm using the FindGLEW.cmake which comes with CMake 3.1.0
CMakeLists.txt
find_package(GLEW REQUIRED)
if (GLEW_FOUND)
include_directories($(GLEW_INCLUDE_DIRS))
endif()
Environment Variables
I'm using MinGW w64 to compile the sources and we successfully linked GLFW and GLM just by copying the includes and libs to their respective folders, but after doing the same with GLEW, CMake still couldn't find it.
Sorry if I wasn't clear enough while formulating the question. I will provide any additional information required.
Edit: I've managed to link the header files by specifying their location in the CMake Cache file, though I'm getting undefined reference to glew functions like glewInit().
Typical CMake scripts like FindGLEW will define variables that specify the paths and files that your project needs. If the script can't automatically identify the correct paths (usually because of nonstandard install location, which is fine), then it leaves these variables up to you to fill in.
With command line CMake, you use the -D flag to define and set the value of a given variable. Other CMake interfaces, like CMake-gui or an IDE integration, give you this ability some other way.
However you do it, you can also modify the cache directly (CMakeCache.txt) and see what CMake is using in there or just clear the cache altogether. You'll have to rerun CMake for it to pick up your changes.
When it comes to linking, that's when you need to tell CMake which libs to link. Use the link_libraries command with what the automated script gives you.
find_package(GLEW REQUIRED)
include_directories(${GLEW_INCLUDE_DIRS})
link_libraries(${GLEW_LIBRARIES})
Other answers do obviously work, but the target based style of cmake makes it even easier since the GLEW find module defines the imported target GLEW::GLEW. All you need is:
find_package(GLEW REQUIRED)
target_link_libraries(YourTarget GLEW::GLEW)
YourTarget is the target that you created with add_executable or add_library. No need to explicitly add include directories, they are added automatically by linking the targets.
The secret of find_package(GLEW) is in FindGLEW.cmake file with cmake install.
find_path(GLEW_INCLUDE_DIR GL/glew.h)
find_library(GLEW_LIBRARY NAMES GLEW glew32 glew glew32s PATH_SUFFIXES lib64)
The find_path and find_library commands find paths in standard system paths. If you want them to find paths in user defined directories, you should tell them.
For example:
set(CMAKE_PREFIX_PATH "d:/libs/glew-1.10.0")
set(CMAKE_LIBRARY_PATH "d:/libs/glew-1.10.0/lib/Release/Win32/")
find_package(GLEW REQUIRED)
Reference:
http://www.cmake.org/cmake/help/v3.0/command/find_path.html
http://www.cmake.org/cmake/help/v3.0/command/find_library.html
I was struggling hard to link glew to cmake through command line on mac. This might be helpful but I am not sure :) I will walk you through step by step of what I have done.
I installed Cmake source from the web.
Then I went inside the cmake folder in terminal and typed
./bootstrap && make && make install
(this will install cmake command line tools on our OS platform)
I have some exercise files. I want cmake to generate xcode files for me for all those exercise files (ex. triangles.cpp, shader.cpp etc) So i made a directory inside exercise files folder.
$ mkdir xcode
$ cd xcode
$ cmake -G "Xcode" ..
At this point, Cmake suppose to install all xcode files that included correct libraries. But there was an error :
$ cmake -G "Xcode" ..
CMake Warning (dev) at CMakeLists.txt:3 (cmake_minimum_required):
Compatibility with CMake < 2.4 is not supported by CMake >= 3.0.
This warning is for project developers. Use -Wno-dev to suppress it.
system name is: Darwin-14.1.0
system processor is: x86_64
-- Could NOT find GLEW (missing: GLEW_INCLUDE_DIR GLEW_LIBRARY)
-- Could NOT find Doxygen (missing: DOXYGEN_EXECUTABLE)
-- Using Cocoa for window creation
-- Using NSGL for context creation
-- Building GLFW only for the native architecture
CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
GLEW_LIBRARY
linked by target "TextureLoader" in directory /Users/Mydir/Desktop/Exercise/Exercise Files
-- Configuring incomplete, errors occurred!
Then to make sure I have installed GLEW and all its libraries correctly, I ran
$brew install glew
Yes, I have installed glew already but it was NOT linked. See the Warning below:
Warning: glew-1.12.0 already installed, it's just not linked
Then I ran the following commands:
$ brew unlink glew
$ brew link glew
And I have solved the error. So just make sure that you have linked glew. Hope this helps.
Happy Coding :)
Finally I found a simple and short CMakeLists which works if you have installed everything in default paths.(openGL, glfw and glew)
cmake_minimum_required(VERSION 3.3)
project(openGL_tutorial)
find_package(OpenGL REQUIRED)
if(NOT OPENGL_FOUND)
message("ERROR: OpenGL not found")
endif(NOT OPENGL_FOUND)
set(GL_LIBRARY GL GLU X11)
add_executable(openGL_tutorial main.cpp)
target_link_libraries(openGL_tutorial glfw GLEW libGLEW.so libGLU.so libGL.so)
For what it is worth, in 2023, this works for me, on macOS, with GLEW, GLFW, and CMake installed using Homebrew:
cmake_minimum_required(VERSION 3.10)
project(Project)
add_executable(Project main.cpp)
find_package(glfw3 REQUIRED)
find_package(GLEW REQUIRED)
target_link_libraries(Project glfw GLEW::glew)