C - Cmake compiling program with libcurl - c

I'm trying to use some curl code to test the lib but I can't compile it :(
I'm using Clion (Cmake + gcc) and I've got a libcurl.a, a libcurl.dll and a libcurl.dlla
What am I suppose to do with those 3 files ?
This is my CmakeLists.txt :
cmake_minimum_required(VERSION 3.10)
project(curl_test2 C)
set(CMAKE_C_STANDARD 99)
ADD_DEFINITIONS( -DCURL_STATICLIB )
include_directories( "include" )
set(SRCS"
srcs/main.c")
set(HEADERS
"include/curl/curl.h"
"include/curl/easy.h")
link_directories("lib")
add_executable(curl_test2 ${SRCS} ${HEADERS})
target_link_libraries(curl_test2 "curl")
this is my project:
include
--curl
--curl.h
srcs
--main.c
lib
--libcurl.a
(--dlls
--libcurl.dll
--libcurl.dlla) <- i'm not using them for now
this is my main.c (just a libcurl example, not really important - i'm just trying to compile):
#include <stdio.h>
#include "curl/curl.h"
int main(void)
{
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://postit.example.com/moo.cgi");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "name=daniel&project=curl");
res = curl_easy_perform(curl);
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
When I'm trying to build the compiler drop this error : "undefined reference to `_imp__curl_global_init'" (and all other curl function calls)
Can you help me ? I'm a bit lost - I did not really use Cmake before..
Thank you !

You link with static curl library (libcurl.a) which required CURL_STATICLIB definition. Add this in your CMakeLists.txt between "project" and "add_executable" commands:
add_definitions( -DCURL_STATICLIB )
Moreover, your file .dlla is not .dll.a ? In that case, .dll.a file is (I think) generated by MinGW toolchain and is required only if you link dynamically with curl library (as .dll file).
I downloaded the sources of cURL library here and compiled it (with Visual Compiler 2015). It produces shared libraries (libcurl.dll and libcurl_imp.lib) that I move in the lib directory (I should rename libcurl_imp.lib to curl.lib). I move also the include directory.
Then, I used this CMakeLists.txt :
cmake_minimum_required(VERSION 3.10)
project(curl_test2 C)
set(CMAKE_C_STANDARD 99)
set(SRCS "srcs/main.c")
set( CURL_LIBRARY ${CMAKE_SOURCE_DIR}/lib )
set( CURL_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/include )
find_package( CURL )
include_directories( ${CURL_INCLUDE_DIRS} )
link_directories( ${CURL_LIBRARIES} )
add_executable(curl_test2 ${SRCS})
target_link_libraries(curl_test2 curl)
With it, your project compiles and the execution works.
I also tried with cURL static library (for that, if you use CMake to compile cURL, add -DCURL_STATICLIB=ON in cmake command line). And I moved the produced library libcurl.lib to lib\curl.lib.
I used this CMakeLists.txt :
cmake_minimum_required(VERSION 3.10)
project(curl_test2 C)
set(CMAKE_C_STANDARD 99)
set(SRCS "srcs/main.c")
add_definitions( -DCURL_STATICLIB )
set( CURL_LIBRARY ${CMAKE_SOURCE_DIR}/lib )
set( CURL_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/include )
find_package( CURL )
include_directories( ${CURL_INCLUDE_DIRS} )
link_directories( ${CURL_LIBRARIES} )
add_executable(curl_test2 ${SRCS})
target_link_libraries(curl_test2 curl wldap32 ws2_32)
And it works too.

Related

compiling c language program with libcurl on windows

I am trying to compile a simple c program on windows 10 using gcc from the libcurl website I cloned vcpkg and then ran the .bat file , next I installed curl with the command vcpkg install curl and got this output
Computing installation plan...
The following packages are already installed:
curl[core,non-http,openssl,schannel,ssl,sspi]:x86-windows -> 7.80.0
Package curl:x86-windows is already installed
Restored 0 packages from C:\Users\<me>\AppData\Local\vcpkg\archives in 138.1 us. Use --debug to see more details.
Total elapsed time: 386.9 ms
The package curl provides CMake targets:
find_package(CURL CONFIG REQUIRED)
target_link_libraries(main PRIVATE CURL::libcurl)
#include <stdio.h>
#include <stdlib.h>
#include <curl/curl.h>
int report()
{
CURL* curl;
CURLcode res;
/* In windows, this will init the winsock stuff */
curl_global_init(CURL_GLOBAL_ALL);
/* get a curl handle */
curl = curl_easy_init();
if (curl) {
/* First set the URL that is about to receive our POST. This URL can
just as well be a https:// URL if that is what should receive the
data. */
curl_easy_setopt(curl, CURLOPT_URL, "http://192.168.1.12:8000");
const char* c = const_cast<char*>(output.c_str());
printf ("%s", c);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, c );
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
/* always cleanup */
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
int main()
{
report();
return 0;
}
Now when I try to compile the code above I get the error
c_example_curl.c:3:23: fatal error: curl/curl.h: No such file or directory
#include <curl/curl.h>
^
compilation terminated.
I am compiling using the command
gcc -lcurl file.c
I also tried using the command
gcc -lcurl -I F:\_C_\vcpkg\installed\x86-windows\include\curl file.c
doesn't seem to change anything
I even tried to copy the curl header file to the working directory of the above code but I was not lucky
How do you install libcurl for windows isn't there any command equivalent to the linux one
download curl for windows here.
unpack the zip and place it anywhere on the system (i personally prefer C:\curl).
then compile your script with: gcc file.c -I<path-to-curl> -L<path-to-curl>\lib -lcurl
NOTE: replace <path-to-curl> with the curl location on the system, for example C:\curl

Calling C from Rust with external headers in C file

I am trying to call C code from Rust, I succeeded! The only issue I get is when I try to take other libraries with me... the documentation says that you should include all headers in the one file you try to load in Rust, so I do this in the .c file...
#include <stdio.h>
#include <stdbool.h>
#include "dependencies/glfw-3.3.4/include/GLFW/glfw3.h"
int someFunc() {
int i = glfwInit();
glfwTerminate();
return i;
}
But when I run the Rust program, it says glfwInit and glfwTerminate are unresolved symbols... If I do this instead:
...
#include <GLFW/glfw3.h>
...
I get the error in my Rust program that there is no such directory, though the library was linked correctly using CMake... I read something about a cmake crate, so I am guessing it has something to do with that, but at the moment I am completely clueless. I must say that I am new to both Rust and C/C++ (student in Computer Science...) :slight_smile:
Note that when I remove any glfw related stuff, everything works correctly!
I am thinking if I can somehow invoke CMake from the build.rs file, that I can link everything in the C project correctly, right? I just do not understand very much CMake since I have been doing everything with an IDE (CLion by jet brains) and very limited commands in CMakeLists.txt.
This is how the project is organised...
project structure:
// generated with cargo new rust_project ...
.../rust_project/
c_project/ // This was generated with the IDE for C (CLion)...
dependecies/
glfw-3.3.4/
include/
...
CMakeLists.txt
MyCFile.c
...
src
main.rs
build.rs
cargo.toml
...
CMakeLists.txt:
cmake_minimum_required(VERSION 3.17)
project(c_project)
set(CMAKE_C_STANDARD 11)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/dependencies/glfw-3.3.4)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/dependencies/glfw-3.3.4/include)
##some more libraries... not currently included in MyCFile.c !##
add_library(c_project MyCFile.c)
target_link_libraries(c_project PRIVATE <other_libraries> glfw ${GLFW_LIBRARIES} <other_libraries>)
MyCFile.c:
#include <GLFW/glfw3.h>
int someFunc() {
int i = glfwInit();
glfwTerminate();
return i;
}
main.rs:
extern "C" {
fn someFunc() -> i32;
}
fn main() {
unsafe {
println!("{}", someFunc());
}
}
build.rs
extern crate cc;
fn main() {
cc::Build::new()
.file("c_project/MyCFile.c")
.compile("library");
/*
* I am guessing here goes something along the lines:
* "CMakeLists.txt".execute (as pseudo code...)
*/
}
cargo.toml:
[package]
name = "rust_project"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
[build-dependencies]
cc = "1.0.70"
the error message upon "cargo check":
error: failed to run custom build command for `version_zero v0.1.0 (D:\...\rust_project)`
Caused by:
process didn't exit successfully: `D:\...\rust_project\target\debug\build\rust_project-bf398c13c8af8b0c\build-script-build` (exit code: 1)
--- stdout
TARGET = Some("x86_64-pc-windows-msvc")
OPT_LEVEL = Some("0")
HOST = Some("x86_64-pc-windows-msvc")
CC_x86_64-pc-windows-msvc = None
CC_x86_64_pc_windows_msvc = None
HOST_CC = None
CC = None
CFLAGS_x86_64-pc-windows-msvc = None
CFLAGS_x86_64_pc_windows_msvc = None
HOST_CFLAGS = None
CFLAGS = None
CRATE_CC_NO_DEFAULTS = None
CARGO_CFG_TARGET_FEATURE = Some("fxsr,sse,sse2")
DEBUG = Some("true")
running: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.29.30037\\bin\\HostX64\\x64\\cl.exe" "-nologo" "-MD" "-Z7" "-Brepro" "-W4" "-FoD:\\...\\rust_project\\target\\debug\\build\\version_zero-54603a96dee57aac\\out\\c_project/MyCFile.o" "-c" "c_project/MyCFile.c"
MyCFile.c
c_project/MyCFile.c(5): fatal error C1083: Cannot open include file: 'GLFW/glfw3.h': No such file or directory
exit code: 2
--- stderr
error occurred: Command "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.29.30037\\bin\\HostX64\\x64\\cl.exe" "-nologo" "-MD" "-Z7" "-Brepro" "-W4" "-FoD:\\...\\rust_project\\target\\debug\\build\\version_zero-54603a96dee57aac\\out\\c_project/MyCFile.o" "-c" "c_project/MyCFile.c" with args "cl.exe" did not execute successfully (status code exit code: 2).
I used: https://crates.io/crates/cc, https://liufuyang.github.io/2020/02/02/call-c-in-rust.html, https://docs.rust-embedded.org/book/interoperability/c-with-rust.html
CMake was installed through: https://cmake.org/download/.
Downloaded the option: "Windows x64 Installer: Installer tool has changed. Uninstall CMake 3.4 or lower first! cmake-3.21.2-windows-x86_64.msi"
Honoustly don't know how you would do it with the zip files...
tried to uninstall the current CMake, and downloaded version 3.4 (and installed it).
Also changed the build.rs file to:
use cmake;
fn main() {
let dst = cmake::build("c_project");
println!("cargo:rustc-link-search=native={}", dst.display());
println!("cargo:rustc-link-lib=static=MyCFile");
}
cargo check compiles just fine, cargo run, will produce an error:
<lots of file paths...>
= note: LINK : fatal error LNK1181: cannot open input file 'MyCFile.lib'
Note that I do not get any indications anymore of cmake not being installed...
Cannot open include file: 'GLFW/glfw3.h': No such file or directory - the error states that the c compiler cannot find the header file glfw3.h from your build point. The cc crate provides the .include for it's builder. Find out where you have the glfw3.h file and pass its path into the include builder method:
fn main() {
cc::Build::new()
.file("c_project/MyCFile.c")
.include("path/to/glfw3.h")
.compile("library");
/*
* I am guessing here goes something along the lines:
* "CMakeLists.txt".execute (as pseudo code...)
*/
}

Trying to add SDL2_mixer and SDL2 as ExternalProject's in CMake

I am currently trying to fetch SDL2 and SDL2_mixer as external projects in my CMake project.
SDL2 seems to work fine, but I cannot make SDL2_mixer compile. It fails when trying to link the playwav binary. The problem are the CFLAGS and LDFLAGS variables in the ExternalProject_Add. The same problem occurs when adding these variables while building from the command line without CMake.
Here is my code so far:
cmake_minimum_required(VERSION 2.8)
include(ExternalProject)
project(sdl2_test)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall")
set(LIBS_DIR ${PROJECT_BINARY_DIR}/libs)
set(SDL2_VER "2.0.8")
set(SDL2_MIXER_VER "2.0.2")
# SDL library
ExternalProject_Add(sdl2_project
URL http://www.libsdl.org/release/SDL2-${SDL2_VER}.tar.gz
PREFIX ${LIBS_DIR}/SDL2
INSTALL_COMMAND ""
)
ExternalProject_Get_Property(sdl2_project SOURCE_DIR)
ExternalProject_Get_Property(sdl2_project BINARY_DIR)
set(SDL2_SRC ${SOURCE_DIR})
set(SDL2_BIN ${BINARY_DIR})
file(GLOB SDL2_INCLUDE "${SDL2_SRC}/include/*")
file(COPY ${SDL2_INCLUDE} DESTINATION ${SDL2_BIN}/include/)
# SDL_mixer library
ExternalProject_Add(sdl2_mixer_project
URL https://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-${SDL2_MIXER_VER}.tar.gz
DEPENDS sdl2_project
PREFIX ${LIBS_DIR}/SDL2_mixer
CONFIGURE_COMMAND
SDL2_CONFIG=${SDL2_BIN}/sdl2-config
CFLAGS=-I${SDL2_BIN}/include
LDFLAGS=-L${SDL2_BIN}
#LIBS=-ldl
<SOURCE_DIR>/configure
--prefix=<INSTALL_DIR>
--enable-shared=no
#--with-sdl-prefix=${SDL2_BIN}
--disable-sdltest
BUILD_COMMAND make
INSTALL_COMMAND ""
)
#file(GLOB SDL2_INCLUDE "${SDL2_SRC}/include/*")
#file(COPY ${SDL2_INCLUDE} DESTINATION ${SDL2_BIN}/include/)
ExternalProject_Get_Property(sdl2_mixer_project SOURCE_DIR)
ExternalProject_Get_Property(sdl2_mixer_project BINARY_DIR)
set(SDL2_MIXER_SRC ${SOURCE_DIR})
set(SDL2_MIXER_BIN ${BINARY_DIR})
include_directories(${SDL2_SRC}/include)
include_directories(${SDL2_MIXER_SRC}/include)
set(SOURCE sdl2test.cc)
add_executable(sdl_test ${SOURCE})
add_dependencies(sdl_test sdl2_project sdl2_mixer_project)
target_link_libraries(sdl_test ${SDL2_BIN}/libSDL2.a)
The file sdl2test.cc is just a dummy file:
#include <iostream>
int main()
{
std::cout << "Hooray" << std::endl;
return 0;
}

Why does cmake give undefined references for netcdf with cygwin on windows?

I am trying to set up some model code on multiple operating systems using clion 2016.3-1 and its bundled cmake 3.6.2.
On Windows I am using the cygwin environment but I ran into a linking issue I can not resolve. Here is a minimum example of my code:
#include <stdlib.h>
#include <stdio.h>
#include <netcdf.h>
#define ERRCODE 2
#define ERR(e) {printf("Error: %s\n", nc_strerror(e)); exit(ERRCODE);}
int main() {
int ncid, varid, dimid, retval;
size_t nlat;
char filepath[] = "minimumExample.nc";
char dimname[64];
double *latitudes;
// open nc file
if ((retval = nc_open(filepath, NC_NOWRITE, &ncid))) ERR(retval);
// find variable IDs
if ((retval = nc_inq_varid(ncid, "latitude", &varid))) ERR(retval);
// find dimension bounds
if ((retval = nc_inq_vardimid(ncid, varid, &dimid))) ERR(retval);
if ((retval = nc_inq_dim(ncid, dimid, dimname, &nlat))) ERR(retval);
// allocate data array
latitudes = malloc(sizeof(double) * nlat);
// get data
if ((retval = nc_get_var_double(ncid, varid, &latitudes[0]))) ERR(retval);
// close nc file
if ((retval = nc_close(ncid))) ERR(retval);
// free data array
free(latitudes);
return(0);
}
Here is my CMakeLists.txt:
cmake_minimum_required(VERSION 3.3)
project(test_examples)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -lnetcdf")
include_directories("/usr/include")
link_directories("/usr/lib")
set(SOURCE_FILES main.c)
add_executable(test_examples ${SOURCE_FILES})
However I get a lot of error messages similar to:
undefined reference to `nc_open'
The binaries and include files are all present in the cygwin environment at the respective folders.
What am I missing?
The errors are saying that linker could not find code for that functions: in other words the library is not reachable.
You should use the CMake target_link_libraries function to link netcdf lib.
remove
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -lnetcdf")
and add
target_link_libraries (test_examples netcdf)

Netcdf Undefined symbols for architecture x86_64

I am running into the famous while using the netcdf library
Undefined symbols for architecture x86_64:
"NcVar::get(double*, long const*) const", referenced from:
Reader<itk::Image<double, 3u> >::Read() in main.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I have installed the library using homebrew:
$brew doctor
Your system is ready to brew.
$brew info netcdf
netcdf: stable 4.3.0
http://www.unidata.ucar.edu/software/netcdf
/usr/local/Cellar/netcdf/4.3.0 (53 files, 4.5M) *
Built from source with: --enable-cxx-compat
From: https://github.com/homebrew/homebrew-science/commits/master/netcdf.rb
==> Dependencies Required: hdf5 ✔
the library is in /usr/local/lib (where it is supposed to be). and I assume this path is in the library include path.
$ls /usr/local/lib/|grep netcdf
libnetcdf.7.dylib
libnetcdf.a
libnetcdf.dylib
libnetcdf_c++.4.dylib
libnetcdf_c++.a
libnetcdf_c++.dylib
libnetcdf_c++4.1.dylib
libnetcdf_c++4.a
libnetcdf_c++4.dylib
and my code used to link, until it didn't.
#include <iostream>
#include <exception>
#include <netcdfcpp.h>
std::string _filename="blabla.nc", _varname="variableName";
int _dim;
long* _sizeArray;
long _sizeFlat;
double* _data;
// Read netCDF
void Read()
{
// Open the file.
NcFile file( _filename.c_str(), NcFile::ReadOnly, NULL, 0, NcFile::Offset64Bits);
NcVar* var = file.get_var( _varname.c_str() );
if( var->is_valid() )
{
_sizeFlat = var->num_vals();
_sizeArray = var->edges();
/*
_dim = var->num_dims();
std::cout<< _dim<<std::endl;
for (int i=0; i<_dim; i++)
std::cout<<_sizeArray[i]<<"\t";
std::cout<<"\t"<<_sizeFlat<<std::endl;
// */
_data = new PixelType[_sizeFlat];
try
{
var->get(_data, _sizeArray);
}
catch(std::exception& a)
{
a.what();
//free mem
delete[] _data;
file.close();
_sizeArray = NULL;
var = NULL;
//quit
std::cout<<"Could not read variable :"<<_varname<<std::endl;
exit(EXIT_FAILURE);
}
//free mem
file.close();
}
else
{
//free mem
file.close();
var = NULL;
//quit
std::cout<<"Could not find variable :"<<_varname<<std::endl;
exit(EXIT_FAILURE);
}
}
int main(void)
{
Read();
return 0;
}
I know that I am using old legacy code ( http://www.unidata.ucar.edu/software/netcdf/examples/programs/ ) but the methods I am using are those I found when opening the /usr/local/include/netcdfcpp.h
I am using Cmake to compile, here is the CMakeLists.txt, if it can help
cmake_minimum_required ( VERSION 2.6 )
#set project name
set( Version_Major 3 )
set( Version_Minor 0 )
set( ProjectName supercellDetection_v${Version_Major}.${Version_Minor} )
project ( ${ProjectName} )
if( COMMAND CMAKE_POLICY )
cmake_policy( SET CMP0012 NEW )
cmake_policy( SET CMP0009 NEW )
endif()
#set output path
set( EXECUTABLE_OUTPUT_PATH /absolute/path )
#generate source files list
file(
GLOB_RECURSE
source_files
src/*pp
)
#create output executable
add_executable( ${ProjectName} ${source_files} )
#look for itk
find_package( ITK REQUIRED )
include( ${ITK_USE_FILE} )
include_directories( ${ITK_INCLUDE_DIRS} )
#try for vtk
if ( ITKVtkGlue_LOADED )
find_package( VTK REQUIRED )
include( ${VTK_USE_FILE} )
endif()
#linker settings
#target_link_libraries( ${ProjectName} ITKCommon ITKIO ITKBasicFilters ITKReview )
target_link_libraries( ${ProjectName} ${ITK_LIBRARIES} )
# compilation options
add_definitions( "-Wall -std=c++11 -g" )
################################################################
#Generate list of header files
include_directories( "/opt/X11/include/" )
include_directories( "/usr/local/include/" )
#add libraries
file(
GLOB_RECURSE
x11Lib_files
/opt/X11/lib/*.dylib
)
target_link_libraries( ${ProjectName} ${x11Lib_files} )
I do not know how to solve this linker problem. Could you please help me?

Resources