Linking error -- openSSL to libcurl - cmake

I'm doing C++ using libcURL. I got the task to test functions in Travis CI. So I used .travis.yml to get libcurl-dev and libssl-dev to connect to the project. I installed them and checked cURL configuration:
SSL support: enabled (OpenSSL)
But as I was trying to make main test file i got list of errors (example)
`Linking CXX executable ../bin/TechProject_example
/usr/local/lib/libcurl.a(libcurl_la-openssl.o): In function ossl_recv:
openssl.c:(.text+0xf3): undefined reference to ERR_clear_error
openssl.c:(.text+0x11c): undefined reference to SSL_read
openssl.c:(.text+0x163): undefined reference to SSL_get_error`
and so on...
The only thing I was able to check is that libcurl is working properly. I placed
--without-ssl flag and got protocol error.
Also I used
`- sudo ln -fs /usr/lib/libcurl.so.4 /usr/local/lib/`
to avoid cmake error. (I'm not very good at UNIX command, so this can be a problem)
So how should properly connect openSSL to C++ project that has <curl/curl.h> ?
EDIT:
Here is CMakeLists.txt:
cmake_minimum_required(VERSION 2.8)
project (TechProject)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(HEADERS ${PROJECT_SOURCE_DIR}/include/testclass.h)
set(HEADERS ${PROJECT_SOURCE_DIR}/include/catch.hpp)
set(SOURCES ${PROJECT_SOURCE_DIR}/sources/testclass.cpp)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
include_directories(${PROJECT_SOURCE_DIR}/include)
add_library (${PROJECT_NAME} STATIC ${SOURCES})
add_subdirectory(example)
add_subdirectory(tests)
find_library(FOO_LIB libcurl.a)
target_link_libraries(TechProject "${FOO_LIB}")
And CMakeLists.txt in tests subdir:
cmake_minimum_required(VERSION 2.8)
set(TESTS_FOR_PROJECT TechProject)
project(${TESTS_FOR_PROJECT}_tests)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
option(BUILD_SHARED_LIBS "Build shared instead of static library" OFF)
file(GLOB ${PROJECT_NAME}_sources "${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp")
find_package(${TESTS_FOR_PROJECT})
include_directories(${${TESTS_FOR_PROJECT}_INCLUDE_DIRS}})
include_directories(${CPM_INCLUDE_DIRS})
add_executable(${PROJECT_NAME} ${${PROJECT_NAME}_sources} ${${PROJECT_NAME}_headers})
target_link_libraries(${PROJECT_NAME} ${TESTS_FOR_PROJECT})
add_custom_command(TARGET ${PROJECT_NAME} PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_CURRENT_SOURCE_DIR}/fixtures $<TARGET_FILE_DIR:${PROJECT_NAME}>)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${PROJECT_NAME} -s -r compact WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

Related

How to copy linked and mingw libs to output dir of executable?

I'm new in CMake.
Could someone please describe to me what I should write in my CMakeLists.txt to copy dependencies to the output directory of the executable file?
So, I have a CMake project:
# top-level CMakeLists.txt
cmake_minimum_required(VERSION 3.23)
project(CoolLib VERSION 0.0.1)
set(CMAKE_CXX_STANDARD 23)
add_subdirectory(mylib)
add_subdirectory(mytestconsole)
install(TARGETS mnconsole mnlib
RUNTIME DESTINATION bin COMPONENT Runtime
LIBRARY DESTINATION lib COMPONENT Runtime
ARCHIVE DESTINATION lib/myproject COMPONENT Development)
# mylib/CMakeLists.txt
cmake_minimum_required(VERSION 3.23)
project(mylib VERSION 0.0.1)
add_library(mylib SHARED mylib.cpp mylib.h)
target_include_directories(mylib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
# mytestconsole/CMakeLists.txt
cmake_minimum_required(VERSION 3.23)
project(mytestconsole VERSION 0.0.1)
add_executable(mytestconsole main.cpp)
target_link_libraries(mytestconsole LINK_PUBLIC mylib)
target_include_directories(mytestconsole PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/mylib)
As you can see, I've added an install() command, but this isn't exactly what I want.
As far as I understand, the install() command will copy my program to the Program Files directory in Windows.
GOAL:
I want to copy the mingw libraries (e.g. libgcc_s_seh-1, libstdc++-6, libwinpthread-1, etc.) and mylib to the output directory of the mytestconsole.exe file.
PS: I saw this answer, but GetPrerequesites is deprecated. And I didn't understand how to use it.
I tried to do this:
add_custom_command(
TARGET mnconsole POST_BUILD
COMMAND LIST_PREREQUISITES($<TARGET_FILE:mnconsole>)
VERBATIM)
But got an error:
D:\Programs\JetBrains\CLion\bin\cmake\win\bin\cmake.exe --build D:\Projects\MethaneNumber\_builds\debug --target mnconsole -j 9
[1/1] Linking CXX executable mnconsole\mnconsole.exe
FAILED: mnconsole/mnconsole.exe
cmd.exe /C "cd . && D:\Programs\mingw64\12.2.0\x64\posix-seh\bin\c++.exe -g mnconsole/CMakeFiles/mnconsole.dir/main.cpp.obj -o mnconsole\mnconsole.exe -Wl,--out-implib,mnconsole\libmnconsole.dll.a -Wl,--major-image-version,0,--minor-image-version,0 mnlib/libmnlib.a -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 && cmd.exe /C "cd /D D:\Projects\MethaneNumber\_builds\debug\mnconsole && LIST_PREREQUISITES ( D:/Projects/MethaneNumber/_builds/debug/mnconsole/mnconsole.exe )""
"LIST_PREREQUISITES" is ­not recognized as an internal command.
ninja: build stopped: subcommand failed.
PS2: It should work like windeployqt.exe with Qt, but I'm not using Qt in this project right now.

CMake - How to get include directories of external project?

I tried to used https://github.com/julianxhokaxhiu/SteamworksSDKCI to use steam api on a simple SFML application (helloworld).
I wanted to use cmake to learn it, but I am struggling to understand how the provided CMakeLists and Find*.cmake file are expected to be used.
Currently, I have modified the CMakeLists to change the INSTALL_DIR
INSTALL_DIR "${CMAKE_BINARY_DIR}/../../vendor"
and my CMakeLists is :
cmake_minimum_required(VERSION 3.19)
project(SfmlWithCMake VERSION 1.0)
include(FetchContent)
set (CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}/cmake_steam")
# Configure external project
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/cmake_steam)
execute_process(
COMMAND ${CMAKE_COMMAND} ${CMAKE_SOURCE_DIR}/cmake_steam
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/cmake_steam
)
# Build external project
execute_process(
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR}/cmake_steam
)
set(BUILD_SHARED_LIBS OFF)
FetchContent_Declare(
SFML
GIT_REPOSITORY https://github.com/SFML/SFML.git
GIT_TAG 2.5.1
)
FetchContent_MakeAvailable(SFML)
find_package(STEAMWORKSSDK REQUIRED)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED true)
# Generate config.h
configure_file(config.h.in config.h)
add_executable(
SfmlWithCMake
main.cpp
)
get_target_property(STEAMSDK STEAMWORKSSDK::STEAMWORKSSDK INCLUDE_DIRECTORIES)
target_include_directories(
SfmlWithCMake
PRIVATE
"${PROJECT_BINARY_DIR}"
"${STEAMSDK}"
)
target_link_libraries(
SfmlWithCMake
sfml-graphics
STEAMWORKSSDK::STEAMWORKSSDK
-static gcc stdc++ winpthread -dynamic
)
install(TARGETS SfmlWithCMake DESTINATION bin)
How to get include directories?
I do not succeed to add the steam include to the target_include_directories.
Here the ${STEAMSDK} is my last attempt to get the directory.
If I replace this by ${PROJECT_BINARY_DIR}/vendor/include, everything works.
Also, why does the SFML include are automatically added to my target include directories and not the steam one?
Am I using the Find*.cmake file the right way?
I understood that ExternalProject_Add was performed at build time and thus, as the find_package is needed at configue time, I added the two "execute_process". But, the readme on github only says to do the find package and add the target to target_link_libraries...
Thanks.

What is a correct way to solve undefined reference to undefined reference to `LLVMInitializeAArch64TargetInfo'

In Clion when i build llvm project I got following message:
CMakeFiles/codegen_llvm.dir/main.cpp.o: In function `llvm::InitializeAllTargetInfos()':
/usr/lib/llvm-9/include/llvm/Config/Targets.def:26: undefined reference to `LLVMInitializeAArch64TargetInfo'
/usr/lib/llvm-9/include/llvm/Config/Targets.def:27: undefined reference to `LLVMInitializeAMDGPUTargetInfo'
/usr/lib/llvm-9/include/llvm/Config/Targets.def:28: undefined reference to `LLVMInitializeARMTargetInfo'
/usr/lib/llvm-9/include/llvm/Config/Targets.def:29: undefined reference to `LLVMInitializeBPFTargetInfo'
/usr/lib/llvm-9/include/llvm/Config/Targets.def:30: undefined reference to `LLVMInitializeHexagonTargetInfo'
/usr/lib/llvm-9/include/llvm/Config/Targets.def:31: undefined reference to `LLVMInitializeLanaiTargetInfo'
And My CmakeLists is here:
cmake_minimum_required(VERSION 3.15)
project(codegen_llvm)
find_package(LLVM REQUIRED CONFIG)
message(STATUS "Found ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
include_directories(${LLVM_INCLUDE_DIRS})
add_definitions(${LLVM_DEFINITIONS})
set(CMAKE_CXX_STANDARD 14)
add_executable(codegen_llvm main.cpp)
llvm_map_components_to_libnames(llvm_libs support core irreader executionEngine)
target_link_libraries(codegen_llvm ${llvm_libs})
...
What should I do?
cmake solution
cmake_minimum_required(VERSION 3.10)
project(project_name )
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_C_COMPILER clang)
set(CMAKE_CXX_COMPILER clang++)
link_libraries()
execute_process(COMMAND llvm-config --libs OUTPUT_VARIABLE LIBS)
execute_process(COMMAND llvm-config --system-libs OUTPUT_VARIABLE SYS_LIBS)
execute_process(COMMAND llvm-config --ldflags OUTPUT_VARIABLE LDF)
#message(STATUS "Found LLVM" ${LIBS})
string(STRIP ${LIBS} LIBS)
string(STRIP ${SYS_LIBS} SYS_LIBS)
string(STRIP ${LDF} LDF)
link_libraries(${LIBS} ${SYS_LIBS} ${LDF})
execute_process(COMMAND llvm-config --cxxflags OUTPUT_VARIABLE CMAKE_CXX_FLAGS)
string(STRIP ${CMAKE_CXX_FLAGS} CMAKE_CXX_FLAGS)
add_executable(project_name toy.cpp)
one liner
clang++ -g toy.cpp $(llvm-config --cxxflags --ldflags --system-libs --libs) -O3 -o toy
If you still do not have a solution for this error, try to add ${LLVM_TARGETS_TO_BUILD} to your link libraries.
I am using CLion too, and I solved this by changing:
llvm_map_components_to_libnames(llvm_libs support core irreader codegen mc mcparser option)
to:
llvm_map_components_to_libnames(llvm_libs ${LLVM_TARGETS_TO_BUILD} support core irreader codegen mc mcparser option)
In your last but one line config is not an llvm component, so you'd want to remove it. To see the list of official components, use the llvm-config --components command.

How to reload cmake targets

Following is the my scenario. I have one top level CMakeList.txt and another 2 internal CMakeList.txt. In top level cmake I have 3 custom targets that are copy, build, copyandbuild. As name specifies make copy copies the source directories (i.e dir1, dir2) to ${CMAKE_SOURCE_DIR}. make build creates libs and executables. make copyandbuild (copy+build).
Running cmake .. from build directory completes successfully.
If I run make copyandbuild it is copying to ${CMAKE_SOURCE_DIR} but at the time of build it is showing error that
No rule to make target `dir1/libmylib.so', needed by `CMaketargetdbuild'. Stop
MyProject
dir1
CMakeLists.txt
dir2
CMakeLists.txt
CMakeLists.txt
It is working if i execute commands in below order.
cmake ..
make copyandbuild
cmake ..
make build
My requirement is it should work with out running cmake and make build again as copyandbuild doing the same work.
Top level CMakeLists.txt:
cmake_minimum_required(VERSION 2.6)
cmake_minimum_required(VERSION 2.6)
set(RE_BUILD make rebuild_cache)
set(OUTPUT_DIR ${CMAKE_SOURCE_DIR}/../)
if(EXISTS ${CMAKE_SOURCE_DIR}/dir1)
message(WARNING "Found dir1 dir")
add_subdirectory(dir1 EXCLUDE_FROM_ALL)
else()
message(WARNING "Couldn't find dir1 directory ")
endif()
if(EXISTS ${CMAKE_SOURCE_DIR}/dir2)
add_subdirectory(dir2 EXCLUDE_FROM_ALL)
else()
message(WARNING "Couldn't find dir2 directory")
endif()
set(MOVE_LIB_COMMAND mv src/myapp . && mv dir1/mylib .)
set(COPY_COMMAND cp -r ../sourceCode1 ../dir1 && cp -r ../sourceCode2 ../dir2)
set(CLEAN_DIR1_COMMAND cmake -E remove_directory ${CMAKE_SOURCE_DIR}/dir1)
set(CLEAN_DIR2_COMMAND cmake -E remove_directory ${CMAKE_SOURCE_DIR}/dir2)
set(SET_SLEEP sync)
#Copy command
add_custom_target(
copy ${COPY_COMMAND}
COMMAND ${RE_BUILD}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
#Compilation
add_custom_target(
build
COMMAND ${MOVE_LIB_COMMAND}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
DEPENDS mylib myapp
)
#copy and compile
add_custom_target(
copyandbuild
COMMAND ${MOVE_LIB_COMMAND}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
DEPENDS copy mylib myapp
)
add_custom_command(TARGET copy POST_BUILD
COMMAND ${SET_SLEEP}
)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11")
dir1 CMake is :
cmake_minimum_required(VERSION 2.6)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11")
include_directories(
${MY_APP_INCLUDE_DIRS}
)
link_directories(
${MY_APP_LIBDIR}
)
add_library(mylib
SHARED
com/*.cpp
)
target_link_libraries(mylib myapp_lib)
dir2 CMake is :
cmake_minimum_required(VERSION 2.6)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11")
include_directories(
${MY_APP_INCLUDE_DIRS}
)
link_directories(
${MY_APP_LIBDIR}
)
You are using CMake in a way that prevents its proper function. By explicitly invoking shell commands in many places, when you could use CMake built in features, you are robbing CMake of any context that it could use to build your programs. Also, using wildcards like *.cpp in CMake is considered bad practice. And you have a number of duplicate statements--you do not need cmake_minimum_required() or setting compiler flags other than at the top level.
In short, your CMakeLists.txt at the top level should look more like this:
cmake_minimum_required(VERSION 2.6)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11")
add_subdirectory(dir1 EXCLUDE_FROM_ALL)
You should not need to copy source files around--just build them from where they are, for example your dir1/CMakeLists.txt might be:
add_library(mylib
SHARED
sourceCode1/mylib.cpp
)
Keep it simple. Get it working. Then ask questions if you need to add missing features.

Building GLFW3 Application with CMAKE - GLFW_LIBRARIES doesnt set

I'm attempting to build a small project using glfw3 but no matter what I do I can't get pkgconfig to set GLFW_LIBRARIES.
Here is my CMakeList.txt
cmake_minimum_required(VERSION 3.3)
project(LearnGLSL)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
if (CMAKE_BUILD_TYPE STREQUAL "")
set(CMAKE_BUILD_TYPE Debug)
endif()
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/build/debug")
set(PROJECT_BINARY_DIR "${CMAKE_SOURCE_DIR}/build/debug")
endif(CMAKE_BUILD_TYPE STREQUAL "Debug")
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
find_package(OpenGL REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(GLFW REQUIRED glfw3)
include_directories(
${OPENGL_INCLUDE_DIR}
${GLFW_INCLUDE_DIRS}
)
set(SOURCE_FILES main.cpp gl_core_4_3.cpp)
message(WARNING "${GLFW_LIBRARIES}")
add_executable(LearnGLSL ${SOURCE_FILES})
target_link_libraries(LearnGLSL ${OPENGL_gl_LIBRARY} ${GLFW_LIBRARIES})
add_custom_command(TARGET LearnGLSL POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_SOURCE_DIR}/assets
${PROJECT_BINARY_DIR}
COMMENT "Copy resources to build tree")
Here is where glfw3 is installed
-- Installing: /usr/local/include/GLFW
-- Installing: /usr/local/include/GLFW/glfw3native.h
-- Installing: /usr/local/include/GLFW/glfw3.h
-- Installing: /usr/local/lib/cmake/glfw/glfw3Config.cmake
-- Installing: /usr/local/lib/cmake/glfw/glfw3ConfigVersion.cmake
-- Installing: /usr/local/lib/cmake/glfw/glfwTargets.cmake
-- Installing: /usr/local/lib/cmake/glfw/glfwTargets-noconfig.cmake
-- Installing: /usr/local/lib/pkgconfig/glfw3.pc
-- Installing: /usr/local/lib/libglfw3.a
I'll be the first to admit I'm not super comfortable with CMAKE but this seems simple enough and I've done everything I can google to find. maybe its a typo i'm not noticing. Any help is appreciated thanks
Oh i forgot to mention I get undefined references to the glfw functions when building this project. I assumed this is a result of GLFW_LIBRARIES not properly getting set tho.
I don't know about finding GLFW with pkgconfig but I don't think you need pkgconfig in this case. Since GLFW itself builds with CMake it should install a native CMake config module, which it does.
Well, almost. The official GLFW CMake config-module support is a bit buggy as of v3.1.2. Instead, use shaxbee's fork or the adasworks fork (based on shaxbee's but newer)
With that GLFW all you need to find it is just 2 lines:
find_package(glfw3 REQUIRED)
...
target_link_libraries(LearnGLSL ... glfw)
I also found a few other problems in your CMakeLists.txt so I repeat the whole script, revised:
cmake_minimum_required(VERSION 3.3)
project(LearnGLSL)
set(CMAKE_CXX_STANDARD 11) # no explicit compiler flags if possible
# don't read CMAKE_BUILD_TYPE, it has no meaning with multiconfig
# generators
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_SOURCE_DIR}/build/debug")
# PROJECT_BINARY_DIR should not be set at all
# You establish the BINARY_DIR with the initial cmake command
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
find_package(OpenGL REQUIRED)
find_package(glfw3 REQUIRED)
include_directories(${OPENGL_INCLUDE_DIR})
add_executable(LearnGLSL main.cpp gl_core_4_3.cpp)
target_link_libraries(LearnGLSL ${OPENGL_gl_LIBRARY} glfw)
add_custom_command(TARGET LearnGLSL POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_SOURCE_DIR}/assets
${PROJECT_BINARY_DIR}
COMMENT "Copy resources to build tree")
Since CMake 3.1 pkg_check_modules uses additional paths from CMAKE_PREFIX_PATH variable for search .pc files. Searching is performed in similar manner as in command find_library, but additional subdirectory pkgconfig/ is added to the resulted path. Specifically, for each <prefix> in CMAKE_PREFIX_PATH, .pc file is searched in next directory:
<prefix>/lib[64]/[<arch>/]pkgconfig
(suffix 64 and arhitecture-specific subdirectory is added when appropriate).
So having file /usr/local/lib/pkgconfig/glfw3.pc, you need to set CMAKE_PREFIX_PATH to /usr/local for pkg_check_modules is able to find it. Variable can be set either:
1) In the CMakeLists.txt script itself, or
2) In the command line
cmake -DCMAKE_PREFIX_PATH=<...> <source-dir>
3) As environment one (OS-dependent).
Before CMake 3.1 (and after it) additional search directory can be specified via PKG_CONFIG_PATH environment variable.
E.g. with file /usr/local/lib/pkgconfig/glfw3.pc variable PKG_CONFIG_PATH should contain /usr/local/lib/pkgconfig.