How do I link dynamically built cmake files on Windows? - c++

I have been struggling for the last 8 hours to find information on how to reference a library in a C project on Windows built with CMake, specifically cURL.
I have downloaded version 7.67 cURL source from the website, and then went used the visual studio developer command prompt to compile the CMake project into a build folder using the standard method of:
cd winbuild
nmake /f Makefile.vc mode=dll
Which outputs three curl folders, one of them called "libcurl-vc-x86-release-dll-ipv6-sspi-winssl".
In that folder contains a lib, a bin, and an include folder.
I built my C project with CLion and this is the CMake file that is generated.
cmake_minimum_required(VERSION 3.15)
project(hello_world C)
set(CMAKE_C_STANDARD 99)
add_executable(hello_world main.c)
How do I use my compiled CURL in my C project with CMake properly?

I finally solved this issue by creating a cmake folder at the C: directory, and copying in the built curl CMake project folder.
The issue was that there weren't any specific tutorials that I found on how to reference projects on Windows for CMake, specifically the curl project.
Fortunately, I found this post which specified an issue I had in referencing the include folder and .lib directory separately.
How to link shared library *dll with CMake in Windows
cmake_minimum_required(VERSION 3.15)
project(hello_world C)
set(CMAKE_C_STANDARD 99)
include_directories("C:/cmake/libcurl-vc-x86-release-dll-ipv6-sspi-winssl/include")
link_directories("C:/cmake/libcurl-vc-x86-release-dll-ipv6-sspi-winssl/lib")
add_executable(hello_world main.c)
set( LIBS libcurl )
target_link_libraries(hello_world ${LIBS} )
Now the code compiles and runs succesfully.
I don't believe this is the proper method of doing this though, any help would be appreciated.

Related

Binaries missing after successful build?

I have a CMake project that I use to generate a Visual Studio solution, which I then try to compile. For some reason, the library file after compilation is nonexistent. I've searched my entire project folder, and cannot find any library files. Here's my CMake setup:
Project root:
cmake_minimum_required(VERSION 3.22)
project(ShadowContainers)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
include_directories(include/)
add_subdirectory(library)
...
library subdirectory:
add_library(libShadows shadows.tpp ../include/shadows.hpp)
set_target_properties(libShadows PROPERTIES LINKER_LANGUAGE CXX) # a tpp and an hpp aren't enough to make the system certain it's c++
target_compile_features(libShadows PRIVATE cxx_std_23)
The MSbuild output contains these lines:
Done Building Project "C:\Users\[..]\projects\Shadow Array\library\libShadows.vcxproj" (default targets).
Done Building Project "C:\Users\[..]\projects\Shadow Array\library\libShadows.vcxproj.metaproj" (default targets).
Even if libShadows is the only target in my project, it's nowhere in my project directory.
Has anybody else had this experience? Any help is appreciated. Thanks!
Edit:
To compile the project, I have tried:
My typical process (working directory = the project root):
cmake .
msbuild ShadowContainers.sln
An alternate process (working directory also project root):
mkdir build
cd build
cmake ..
cmake --build .
Both have produced the same result, albeit with VS and CMake files in different places. No library is outputted either way.
I was able to find the issue. CMake (and conventions for that matter) do not see a .tpp as a code file (similarly to how they treat header files). Thus, I was trying to compile a target with no legitimate code files. Template-only libraries are not libraries at all, so I should not be attempting to compile this standalone, and should instead put the .hpp and .tpp as the include in my projects!

CMake : add_executable not generating an executable under windows OS

I am trying to generate an executable with CMake under windows by command line.
This is what I do:
I enter testprog directory then do
cd build
cmake ..
I also tried this:
cd build
cmake -G"Visual Studio 16 2019" ..
same result as earlier attempt.
This builds bunch of files in build directory but no executable is ever created.
It creates files to be opened in visual studio.
This is how my folder look like;
testprog
-build
-src
-main.cpp
-call.h
-include
-main.h
-call.h
-CMakeLists.txt
CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 17)
project(testprog)
include_directories(include)
file(GLOB SOURCES "src/*.cpp")
add_executable(testprog ${SOURCES})
This builds bunch of files in build directory but no executable is ever created. It creates files to be opened in visual studio.
That's it.
That's exactly what CMake does; CMake is a meta build system where it generates all necessary files that you can open with, say, Visual Studio on Windows since you've given:
-G "Visual Studio 16 2019"
and build the projects with Visual Studio.
add_executable does not magically build your source files. It only tells the given tool to do so.
It's all same in Unix-like platforms as well; CMake drops Makefile, and then you build with make. (Or other tools like Ninja can be a good candidate instead of make)
EDIT
I understand, but is there no way to build the executable from command line without the need of say Visual studio
Yes, you can! Microsoft provides Build Tools for Visual Studio for those who don't want the whole heavy IDE.
This is quite common when it comes to establishing a build server.
In order to build you have to call cmake --build <dir> [<options>] [-- <build-tool-options>]
Documentation is here

Error : LNK1104 cannot open file 'pthread.lib'

I am trying to compile a native Linux C++ application in Windows using Visual Studio 2017. The app uses WebRtc's Acoustic Echo Cancellation(AEC) APIs to negate echo on wav files. Following is the CmakeLists.txt file:
cmake_minimum_required(VERSION 2.8)
project(wav-aec)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
add_subdirectory(gflags)
add_definitions("-DWEBRTC_NS_FLOAT -DWEBRTC_WIN -DNOMINMAX")
#-DWEBRTC_UNTRUSTED_DELAY -DWEBRTC_LINUX -DWEBRTC_POSIX
include_directories(
webrtc
webrtc/webrtc/common_audio/signal_processing/include
webrtc/webrtc/modules/audio_coding/codecs/isac/main/include
)
set(WEBRTC_SRC_
base/buffer.cc
base/checks.cc
...
...
#system_wrappers/source/rw_lock_posix.cc
system_wrappers/source/trace_impl.cc
#system_wrappers/source/trace_posix.cc
)
function(prepend_path var prefix)
set(listVar "")
foreach(f ${ARGN})
list(APPEND listVar "${prefix}/${f}")
endforeach(f)
set(${var} "${listVar}" PARENT_SCOPE)
endfunction(prepend_path)
prepend_path(WEBRTC_SRC webrtc/webrtc ${WEBRTC_SRC_})
add_executable(webrtc-audioproc webrtc-audioproc.cpp ${WEBRTC_SRC})
target_link_libraries(webrtc-audioproc gflags pthread)
When I try to build it, I get the following errror:
Error : LNK1104 cannot open file 'pthread.lib'
Here is the link to the only linux dependent source file(cpp) of the project:
https://github.com/lschilli/wav-aec/blob/master/webrtc-audioproc.cpp
What will be the right approach to port the code from Linux to windows?
Whats is Windows equivalent of gflags and pthread? And what necessary changes needs to go to CmakeLists.txt?
P.S: I have already added pthread header, dll and libs to Visual Studio directory manually.
If 'missing pthread library' is the only error, you can use pthread-w32. We have successfully used it in some of our cross-platform apps requiring pthread.
They have libraries for both 64-bit and 32-bit. You can download and add it into your project. You haven't mentioned your toolset - their libraries are named differently depending on your toolset (MSVC or GNU) so you need to pick the right one. Check out their FAQ.
Hope it helps.
You need to us the actual lib file which is typically not "pthread.lib". It's most likely "pthreadVC3.lib" or "pthreadVC2.lib". Find the actual name by looking in the lib directory of your source package. You might see other lib files in there like "pthreadVCE3.lib" and "pthreadVSE3.lib", but you want to link "pthreadVC3.lib".
You can either add this in the project settings, or add the following code:
#pragma comment(lib,"pthreadVC3.lib")
To add it to the project settings:
Go to project properties->Configuration Properties->Linker->General and add your library path to Additional Library Directories
Go to project properties->Configuration Properties->Linker->Input and add the lib file (such as "pthreadVC3.lib") to Additional Dependencies
Make sure you have the correct version of pthread to match your compile settings, ie x86/x64.
In my case, I am using VCPkg for package management and I installed pthreads using the following commands:
vcpkg install pthread:x86-windows
vcpkg install pthread:x64-windows
And my package lib directory is "C:\vcpkg\installed\x64-windows\lib"
I additionally had to add the following to my project settings as vcpkg wasn't integrating automatically:
Go to project properties->Configuration Properties->VC++ Directories and add "C:\vcpkg\installed\x64-windows\include" to Include Directories
Go to project properties->Configuration Properties->VC++ Directories and add "C:\vcpkg\installed\x64-windows\lib" to Library Directories

ITK: Can't find ITKCommon-x.xx.dll when executing HelloWorld Example

i successfully built ITK 4.13 (as 'Release') on Windows 10 with the latest Visual Studio version (Visual Studio 15 2017 Win64 compiler). Then i tried to built the ITKHelloWorld example using the following CMakeLists.txt (as shown in the example by ITK):
#CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(HelloWorld)
find_package(ITK REQUIRED)
include(${ITK_USE_FILE})
add_executable(HelloWorld HelloWorld.cxx)
target_link_libraries(HelloWorld ${ITK_LIBRARIES})
Built runs without errors or warnings. Running the generated HelloWorld.exe file result in an ITKCommon-4.13.dll not found error.
The ITKCommon-4.13.dll was built by ITK, thus, i think i have to change something in the CMakeList file, but don't know what.
Any guess or solution?
Edit: The include(${ITK_USE_FILE}) expression in CMakeLists searches for UseITK.cmake, but this file is located in the source of ITK not in the build folder. Could this be a source of the error?
Edit2: Running a VTK Example also shows errors caused by not finding required .dlls.
There is no problem with your project. Windows can use dll libraries on runtime only if they are in PATH location. So there are two options: either you add bin/Release directory of ITK library to Windows's PATH system variable (the directory that contains all the ddls), or you just copy all the dlls from that directory to the one that contains your new application.
Precisely, you don't need to copy all the dlls, you can check by e.g. Dependency Walker, which ones are really needed.

Include problems when using CMake with Gnu on Qt project

I am starting a multiplatform (Win Xp, Linux) qt project. I want to use an out of source build so my directory structure is as followed:
project/
CMakeLists.txt (global CMake file, includes other CMakeLists)
build/ (my build directory)
libA/
CMakeLists.txt
mystuff/
subprojectA/
CMakeLists.txt
subprojectB/
CMakeLists.txt
So when I use that on Windows with the Visual Studio generator everything builds fine.
If I use the same structure and CMakeLists on Linux or under Windows with the MinGW generator I get compile errors because the qt generated files (through moc and uic) lying under the build directory cannot find my header files in my subprojects. Some of the qt generated header/source files are dependent on my header/source files because I use promoted widgets in my .ui files which point to the implementation in my source. Again under Visual Studio / NMake everything compiles fine.
As a workaround I can use an in source build which runs fine or I can add the following on the global CMakeLists.txt:
include_directories(
mystuff/subprojectA
mystuff/subprojectB
)
But what is the right solution? Thank you very much!!
I have a similar problem, with includes for out of source builds on unix (although I am not using QT), and in each effected projected I added:
include_directories( . )
Not the most elegant but I worked for me.
In a project I'm working on I use this statement to handle includes in my CMakeLists.txt :
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${QT_INCLUDES} ${OPENSSL_INCLUDE_DIR})
The keyword is ${CMAKE_CURRENT_BINARY_DIR}, hope that helps.
Side note, if you are using gcc 4.4.x with exceptions enabled, you might want to use this so it wouldn't link against libgcc_s_sjlj-1.dll on windows.
SET(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "-static-libgcc")