CMake BUILD undefined reference (findpng) - c++

I'm still very new to CMake so feedback is definitely welcome. So, I'm trying to build a simple application that should eventually create a pdf using the library libharu.
I think i figured it out how to link the library. But I still receive build errors for the findpng module (I suppose libharu depends on it)
CMakeLists.txt:
cmake_minimum_required(VERSION 3.2.0 FATAL_ERROR) # current latest stable version (if lower give FATAL_ERROR)
project(pdf_generator VERSION 0.1.0) # name of the project, version.
file(GLOB TARGET_SRC "./src/*.cpp") # Creates variable, using globbing.
include_directories(${PROJECT_SOURCE_DIR}/include) # list of directories to be used as header search paths.
add_executable(main ${TARGET_SRC}) # Create an executable of set of source files [exe name files to bundle].
find_library(libhpdf_location NAMES libhpdf.a) # find the location of libhpdf.a and save the value in the variable libhpdf_location.
message(STATUS ${libhpdf_location}) # print status of variable.
add_library(libhpdf STATIC IMPORTED) # Add library via a static import.
set_target_properties(
libhpdf PROPERTIES
IMPORTED_LOCATION ${libhpdf_location}
)
target_link_libraries(main libhpdf)

I've never worked with that particular library before, but skimming their CMakeLists.txt on GitHub it seems like libharu has optional dependencies on libpdf and zlib. Without knowing how you built your version of libharu I'm going to assume that both are needed.
Luckily, CMake comes with find-modules for both libpng and zlib, so adding the following should work:
find_package(PNG REQUIRED)
find_package(ZLIB REQUIRED)
set_target_properties(libhpdf
PROPERTIES
INTERFACE_LINK_LIBRARIES "ZLIB::ZLIB;PNG::PNG"
)

Looks like all you need to do is tell cmake to link libpng.

Related

How to import package in cmake from vcpkg?

When I vcpkg install simdjson , it returns :
The package simdjson:x64-linux provides CMake targets:
find_package(simdjson CONFIG REQUIRED)
target_link_libraries(main PRIVATE simdjson::simdjson simdjson::simdjson-flags simdjson::simdjson-headers)
So I add
find_package(simdjson CONFIG REQUIRED)
target_link_libraries(main PRIVATE simdjson::simdjson simdjson::simdjson-flags simdjson::simdjson-headers)
to CMakeLists.txt to use the package simdjson
But when I vcpkg install redis-plus-plus[cxx17] , it returns nothing . What should I do to let cmake use this package ?
Unfortunately, redis-plus-plus doesn't supply CMake config files. Someone should open an issue with upstream. It's honestly pretty unacceptable to not support find_package for your library. Thus, thanks to the authors' negligence, you will have to create an imported target for their library yourself. Here's an example CMakeLists.txt, step by step. We'll start with the standard boilerplate:
cmake_minimum_required(VERSION 3.19)
project(test-redis)
Then we need to find hiredis, which is one of Redis++'s dependencies:
find_package(hiredis REQUIRED)
This will create a target called hiredis::hiredis we'll link to later. Now we'll create a target to hold the Redis++ usage information.
add_library(redis++::redis++ UNKNOWN IMPORTED)
Now we need to actually find the header path and redis++ libraries:
find_path(REDIS_PP_HEADER sw REQUIRED)
find_library(REDIS_PP_LIB redis++ REQUIRED)
And now we can tell CMake that the target we just created manages the library we just found:
set_target_properties(redis++::redis++ PROPERTIES IMPORTED_LOCATION "${REDIS_PP_LIB}")
And finally we can set up the include paths and dependency on Hiredis.
target_include_directories(redis++::redis++ INTERFACE "${REDIS_PP_HEADER}")
target_link_libraries(redis++::redis++ INTERFACE hiredis::hiredis)
We're now ready to use the library like we ought to be able to expect to.
add_executable(main main.cpp)
target_link_libraries(main PRIVATE redis++::redis++)

Visual studio project for header only library

I'm creating a CMake project whose two main files are:
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(CPP_Algorithms_and_Data_Structures)
set( CMAKE_CXX_STANDARD 11 )
#add_subdirectory(./ElementaryAlgorithms)
add_subdirectory(./ElementaryDataStructures)
#add_subdirectory(./AdvancedDataStructures)
#add_subdirectory(./GraphAlgorithms)
#set(INCLUDE_FOLDERS
# ./
# ./ElementaryAlgorithms
# ./ElementaryDataStructures
# ./AdvancedDataStructures
# ./GraphAlgorithms)
set(INCLUDE_FOLDERS ./ ./ElementaryDataStructures)
set(HEADER_FILES alg-and-ds.h)
set(SRC_FILES main.cpp alg-and-ds.cpp)
add_executable(alg-and-ds ${SRC_FILES} ${HEADER_FILES})
target_include_directories(alg-and-ds PUBLIC ${INCLUDE_FOLDERS})
target_link_libraries(alg-and-ds elementary-data-structures)
#target_link_libraries(alg-and-ds
# graph-algorithms
# elementary-data-structures
# elementary-algorithms
# advanced-data-structures)
and
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(ElementaryDataStructures)
set( CMAKE_CXX_STANDARD 11 )
if(WIN32)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS YES CACHE BOOL "Export all symbols")
endif()
add_library(elementary-data-structures INTERFACE)
target_include_directories(elementary-data-structures INTERFACE ./)
target_sources(elementary-data-structures INTERFACE
"${CMAKE_CURRENT_LIST_DIR}/list.h"
"${CMAKE_CURRENT_LIST_DIR}/list.tcc")
#set_target_properties(elementary-data-structures PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
I'm using these to generate a visual studio solution, however what I would like to do is to generate a separate project for the header only library.
Basically I had a small list library that I converted to an header only library, by using templates, before such change I was able to generate separate visual studio projects but in the same solution, in this case instead I can see something like this:
But what I'd like to see, assuming this is possible is a separate project for the ElementaryDataStructures.
I'm not an expert in CMake and all the setups, but I would be great if you could help me to figure out how to do it.
Update:
Following suggestion on the comment I got a new project in VS, however there's still a tiny bit that bothers me.
In the picture below I can see both alg-and-ds and ElementaryDataStructures_ referencing the same sources. Is there a way to avoid the alg-and-ds project to show such files?
The update CMakeLists.txt
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(ElementaryDataStructures)
set( CMAKE_CXX_STANDARD 11 )
if(WIN32)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS YES CACHE BOOL "Export all symbols")
endif()
add_library(elementary-data-structures INTERFACE)
target_include_directories(elementary-data-structures INTERFACE ./)
target_sources(elementary-data-structures INTERFACE
"${CMAKE_CURRENT_LIST_DIR}/list.h"
"${CMAKE_CURRENT_LIST_DIR}/list.tcc")
add_custom_target(ElementaryDataStructures_ SOURCES ${CMAKE_CURRENT_LIST_DIR}/list.h ${CMAKE_CURRENT_LIST_DIR}/list.tcc)
As far as I know there is no normal way to do it. Only a hackish one. So you create a custom target which will force MSVC to show the project in the solution tree. Something like this:
add_custom_target(${PROJECT_NAME}_ SOURCES ${PROJECT_SOURCES})
Note the underscore in the name: it is there to differentiate it from the name in the add_library command. Of course you need to replace the variables in my example to yours actual ones.
Another solution is to declare static library with stub source file:
file(TOUCH ${CMAKE_BINARY_DIR}/stub.cpp)
add_library(elementary-data-structures STATIC
"${CMAKE_BINARY_DIR}/stub.cpp"
"${CMAKE_CURRENT_LIST_DIR}/list.h"
"${CMAKE_CURRENT_LIST_DIR}/list.tcc"
)
target_include_directories(elementary-data-structures INTERFACE ./)

Using SDL2 with CMake in CLion

After hours of scouring the web and SO for a solution I'm at a standstill. Nothing has worked so far for me...
I'm on Windows, using CLion IDE which uses CMake. My goal is to correctly link SDL2 to my project and use it through #include "SDL.h" which is the correct way.
The format of my CMakeLists.txt file
Specifics regarding the directory where I should have put the MingW development library of SDL2
Any requirements regarding windows ENV variables that I might have to set.
My CMakeLists.txt looks like this:
cmake_minimum_required(VERSION 3.6)
project(sdl2Project)
set(CMAKE_CXX_STANDARD 11)
#This is where sdl2-config.cmake is located
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "C:/Users/MyUserName/CLibraries/SDL2-2.0.5/x86_64-w64-mingw32/lib/cmake/SDL2")
set(SOURCE_FILES main.cpp)
add_executable(sdl2Project ${SOURCE_FILES})
find_package(sdl2 REQUIRED)
target_include_directories(sdl2Project PUBLIC ${SDL2_INCLUDE_DIRS})
target_link_libraries(sdl2Project ${SDL2_LIBRARIES})
There is no FindSDL2.cmake file used.
The SDL2 library I downloaded from libsdl.org is located in:
C:/Users/MyUserName/CLibraries/SDL2-2.0.5/x86_64-w64-mingw32
I have no experience with CMake so I'm unable to truly understand where the problem stems from. What are the steps I need to take in order for it to find the library and link it correctly??
EDIT:
My Project structure is the following:
sdl2Project
cmake-build-debug
CMakeLists.txt
main.cpp
Looking in your FindSDL2.cmake, you need to provide an hint to CMake about where the library is installed. You could do this by setting an environment variable SDLDIR, but you shouldn't. General advice: you shouldn't use a CMake package that wasn't provided with the sources you're using.
Looking in sources of SDL2, root directory contains a file sdl2-config.cmake.in that should have been configured and installed in your install directory as sdl2-config.cmake: that's the package file you should use.
Am I right guessing the file C:/Users/MyUserName/CLibraries/SDL2-2.0.5/sdl2-config.cmake exists?
If yes, to allow CMake to find it, add your install directory to CMAKE_PREFIX_PATH, before calling find_package:
set(CMAKE_PREFIX_PATH
${CMAKE_PREFIX_PATH}
"C:/Users/MyUserName/CLibraries/SDL2-2.0.5"
)
find_package(sdl2 REQUIRED)
Note the use of "/" in the path instead of "\" which could be interpreted as escaping character. Quotes around the path are only necessary if the path contains whitespaces.
EDIT:
Moreover, you misused target_link_libraries with a wrong target: SDL2 which you don't build in your project, instead of sdl2Project.
You also used a wrong variable: SDL2_LIBRARY instead of SDL2_LIBRARIES; you can see the good variable name by looking in sdl2-config.cmake.
You may consider target_include_directories instead of include_directories, but again the variable name you used is wrong: SDL2_INCLUDE_DIR instead of SDL2_INCLUDE_DIRS.
Try:
target_include_directories(sdl2Project PUBLIC ${SDL2_INCLUDE_DIRS})
target_link_libraries(sdl2Project ${SDL2_LIBRARIES})

Qt w/ Cmake: set(QT_USE_QTWEBKIT TRUE) not working

I'm attempting to build a Qt-based application using cmake (It's what Kdevelop gave me). I tried to use a QWebView;
QWebView *webView = new QWebView( this );
webView->load(QUrl("http://google.ca"));
But it failed with Undefined Reference errors...
undefined reference to `QWebView::QWebView(QWidget*)'
undefined reference to `QWebView::load(QUrl const&)'
I looked it up and I needed to add QTWEBKIT to my project, but all the solutions said to add it to my .pro file... And I'm not using .pro. In the QT documentation it said to add "set(QT_USE_QTWEBKIT TRUE)" to my CMAKE file, this is my CMakeLists.txt file now:
#-------------------------------------------------------------------------------
# Corrections Tool CMAKE list
#-------------------------------------------------------------------------------
project(corrections)
# Versioning Requirements
#-------------------------------------------------------------------------------
cmake_minimum_required(VERSION 2.6)
find_package(Qt4 REQUIRED)
# Include QT Librtaries
#-------------------------------------------------------------------------------
set(QT_USE_QTWEBKIT TRUE)
# Set Sources
#-------------------------------------------------------------------------------
set(corrections_SRCS corrections.cpp main.cpp utilities.cpp prettySplash.cpp)
#The Rest
#-------------------------------------------------------------------------------
include_directories(${QT_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR})
qt4_automoc(${corrections_SRCS})
add_executable(corrections ${corrections_SRCS})
target_link_libraries(corrections ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY})
install(TARGETS corrections RUNTIME DESTINATION bin)
But I'm still getting the errors, so either I did it wrong, in the wrong place, etc. I've also cleaned out and reconfigured my project several times making sure I wasn't using a bad generated makefile.
How would I either fix my cmake config to actually work, or convert my project to using .pro (with minimum stress & heartache)?
Thank you.
The canonical way to select Qt components in CMake is to specify the them in the find_package call and then to include ${QT_USE_FILE}
FIND_PACKAGE( Qt4 COMPONENTS QtWebKit REQUIRED )
INCLUDE( ${QT_USE_FILE} )
...
TARGET_LINK_LIBRARIES( corrections ${QT_LIBRARIES} )
This already configures the include directories and sets ${QT_LIBRARIES} to contain all relevant Qt libraries (i.e. your selected component and all Qt libraries it depends on).
So you don't need to manually add the libraries by listing them individually as you did in your example.
Edit:
Additional explaination:
The COMPONENTparameter to FIND_PACKAGE actually does the same as your manual call to set QT_USE_WEBKIT. But this variable is only evaluated/used in UseQt4.cmake which is included (and "executed") by the INCLUDEcommand. See CMake documentation of FindQt4 for details.
You do not appear to be linking against all of the Qt libraries. Use ${QT_LIBRARIES} instead of ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} in your target_link_libraries
target_link_libraries(corrections ${QT_LIBRARIES} )

cmake + sdl - disable sdlmain

I"m linking SDL with my application using cmake (winxp sp3, cmake 2.8.4).
cmake_minimum_required(VERSION 2.8)
find_package(SDL REQUIRED)
set(src WIN32 main.cpp)
include_directories(${QT_INCLUDE_DIR} ${QT_QTGUI_INCLUDE_DIR} ${SDL_INCLUDE_DIR})
add_executable(test ${src})
target_link_libraries(test ${SDL_LIBRARY})
Problem: SDL_LIBRARY contains SDLmain.lib, and I need to avoid linking with it (I already have one other library that contains main but isn't mentioned in this cmakelists.txt example).
I need to remove SDLmain entry from SDL_LIBRARY. This must be done without using hard-coded paths to the library - basically I need to keep using find_package to set up sdl-related variables, but I must ensure that SDLmain is not within SDL_LIBRARY. Also, I'm using cmake 2.8.4 which doesn't have string(FIND).
How can I do that?
Does that help?
FindSDL.cmake:
# This module responds to the the flag:
# SDL_BUILDING_LIBRARY
# If this is defined, then no SDL_main will be linked in because
# only applications need main().
# Otherwise, it is assumed you are building an application and this
# module will attempt to locate and set the the proper link flags
# as part of the returned SDL_LIBRARY variable.