我的C ++ / Cmake / MinGW应用程序使用libcurl通过ftp上传文件,并通过http下载数据。当链接到静态构建的libcurl-库时,对于所有使用的curl函数,我仍然会收到“无法解析的引用”错误。
我通过add_definitions添加了“ -DCURL_STATICLIB”,并将其放入CMAKE_C_FLAGS,CMAKE_CXX_FLAGS和CMAKE_EXE_LINKER_FLAGS。我使用与该应用程序完全相同的mingw版本构建了libcurl自己。我确定,该cmake通过执行find_library命令和message()-查找结果来找到正确的库。我从target_link_library命令中重新排列了活动的sh..ip。我什至确保Curl包含在外部“ C”大括号内,这样我就不会遇到名称修改问题。
该项目由几个子项目组成,其中只有一个子项目实际使用libcurl函数。随后将所有子项目编译到静态库中,并添加到主可执行文件中。 我还尝试在其中为libcurl添加target_link_libraries命令。
这是我的主要任务
cmake_minimum_required(VERSION 3.14)
project(Flobbel)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_C_STANDARD 99)
set(CMAKE_EXE_LINKER_FLAGS "-static -static-libgcc -static-libstdc++")
add_subdirectory(dependencies/sqlite)
add_subdirectory(FlobbelBackbone)
add_subdirectory(FlobbelCallbackCollection)
add_subdirectory(FlobbelSafe)
add_subdirectory(FlobbelWebStuff)
include_directories(FlobbelBackbone)
include_directories(FlobbelCallbackCollection)
include_directories(FlobbelSafe)
include_directories(FlobbelWebStuff)
include_directories(dependencies/cryptopp/include)
include_directories(dependencies/sqlite)
include_directories(dependencies/curl/include/curl)
add_definitions("-DUNICODE")
add_definitions("-D_UNICODE")
add_definitions(-DCURL_STATICLIB)
set(CMAKE_C_FLAGS "-DCURL_STATICLIB")
set(CMAKE_CXX_FLAGS "-DCURL_STATICLIB")
set(CMAKE_EXE_LINKER_FLAGS "-DCURL_STATICLIB")
if(${TEST})
add_executable(Flobbel testmain.cpp)
elseif(CMAKE_BUILD_TYPE STREQUAL Release)
set(Flobbel_SRC )
add_executable(Flobbel WIN32 main.cpp ${Flobbel_SRC})
else()
set(Flobbel_SRC )
add_executable(Flobbel main.cpp ${Flobbel_SRC})
endif()
set(LIBDIR dependencies/libs)
find_library(LCRYPTOPP libcryptopp64_rel.a PATHS dependencies/libs)
find_library(LCURL libcurl.a PATHS dependencies/libs)
target_link_libraries(Flobbel FlobbelBackbone)
target_link_libraries(Flobbel FlobbelWebStuff)
target_link_libraries(Flobbel FlobbelSafe)
target_link_libraries(Flobbel FlobbelCC)
target_link_libraries(Flobbel ${LCRYPTOPP})
target_link_libraries(Flobbel ${LCURL})
target_link_libraries(FlobbelCC Netapi32)
target_link_libraries(FlobbelSafe shlwapi)
target_link_libraries(Flobbel sqlite)
target_link_libraries(Flobbel FlobbelBackbone)
target_link_libraries(Flobbel FlobbelWebStuff)
target_link_libraries(Flobbel FlobbelSafe)
target_link_libraries(Flobbel FlobbelCC)
target_link_libraries(Flobbel ${LCRYPTOPP})
target_link_libraries(Flobbel ${LCURL})
target_link_libraries(FlobbelCC Netapi32)
target_link_libraries(FlobbelSafe shlwapi)
target_link_libraries(Flobbel sqlite)
实际的函数调用在WebStuff中,所以这是我的webstuff.cpp
FlobWS::FlobWS() {
curl_global_init(CURL_GLOBAL_ALL);
}
namespace SyncSupport{
std::string buffer;
size_t receive(char *c_buf, size_t, size_t nmemb, void *){
buffer.append(c_buf,nmemb);
return CURLE_OK;
}
};
std::set<std::wstring> FlobWS::sync_metadata(const std::string &mac, const std::string &cpName) {
CURL *down = curl_easy_init();
curl_easy_setopt(down, CURLOPT_URL,curl_easy_escape(down,("somewebsite.com").c_str(),
("somewebsite.com").length()));
curl_easy_setopt(down, CURLOPT_WRITEFUNCTION, SyncSupport::receive);
curl_easy_setopt(down, CURLOPT_USE_SSL, CURLUSESSL_ALL);
curl_easy_setopt(down, CURLOPT_SSL_VERIFYPEER, false);
curl_easy_setopt(down, CURLOPT_VERBOSE,1L);
CURLcode res = curl_easy_perform(down);
if(res != CURLE_OK ) {
std::cerr << "ERROR performing data sync: " << res << "\n";
curl_easy_cleanup(down);
std::cerr << "Buffer Dump: " << SyncSupport::buffer << "\n";
return std::set<std::wstring>();
}
curl_easy_cleanup(down);
if(SyncSupport::buffer.empty()){
std::cerr << "ERROR syncing buffer is empty\n";
return std::set<std::wstring>();
}
std::vector<std::string> resVec;
std::istringstream iss(SyncSupport::buffer);
std::string token;
while(std::getline(iss,token,';')){
resVec.push_back(token);
}
if(resVec.size() != 4 ){
std::cerr << "ERROR splitting received string; imperfect number of entries\n";
return std::set<std::wstring>();
}
flobCS.savedirectory = flobCS.converter.from_bytes(resVec[4]);
flobCS.db_path = flobCS.savedirectory+flobCS.converter.from_bytes(resVec.back());
flobCS.globalHandle = std::stoi(resVec.front());
//and now: the blacklist
std::istringstream bls(*(resVec.begin()+1));
token = "";
std::set<std::wstring> bl;
while(std::getline(iss, token, '|')){
bl.insert(flobCS.converter.from_bytes(token));
}
return bl;
}
namespace UploadSupport{
size_t getContentLength(void *ptr, size_t size, size_t nmemb, void*stream){
int r;
long len = 0;
r = sscanf((char*)ptr,"Content-Length: %ld\n",&len);
if(r)
*((long*)stream) = len;
return size*nmemb;
}
size_t discard(void *ptr,size_t size, size_t nmemb, void *stream){
(void)ptr;
(void)stream;
return size *nmemb;
}
size_t read(void *ptr, size_t size, size_t nmemb, void *stream){
FILE *f = (FILE*)stream;
size_t n;
if(ferror(f)){
return CURL_READFUNC_ABORT;
}
n = fread(ptr,size,nmemb,f)*size;
return n;
}
size_t upload(CURL*curl, const std::wstring& remotePath,const std::wstring& localPath){
int tries = 3;
FILE *f;
long uploaded_len = 0;
CURLcode r = CURLE_GOT_NOTHING;
int c;
f = fopen(flobCS.converter.to_bytes(localPath).c_str(),"rb");
if(!f){
perror(NULL);
std::wcerr << "ERROR reading file " <<localPath << "\n";
return 0;
}
curl_easy_setopt(curl,CURLOPT_UPLOAD,1L);
curl_easy_setopt(curl,CURLOPT_URL, flobCS.converter.to_bytes(localPath).c_str());
curl_easy_setopt(curl,CURLOPT_HEADERFUNCTION, UploadSupport::getContentLength);
curl_easy_setopt(curl,CURLOPT_HEADERDATA,&uploaded_len);
curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,discard);
curl_easy_setopt(curl,CURLOPT_READFUNCTION,read);
curl_easy_setopt(curl,CURLOPT_READDATA,f);
curl_easy_setopt(curl,CURLOPT_FTPPORT,"-");
curl_easy_setopt(curl,CURLOPT_FTP_CREATE_MISSING_DIRS,1L);
curl_easy_setopt(curl,CURLOPT_VERBOSE,1L);
for(c = 0; (r != CURLE_OK) && (c < tries);c++){
if(c){
curl_easy_setopt(curl,CURLOPT_NOBODY,1l);
curl_easy_setopt(curl,CURLOPT_HEADER,1L);
r = curl_easy_perform(curl);
if(r != CURLE_OK){
continue;
}
curl_easy_setopt(curl,CURLOPT_NOBODY,0L);
curl_easy_setopt(curl,CURLOPT_HEADER,0L);
fseek(f,uploaded_len,SEEK_SET);
curl_easy_setopt(curl,CURLOPT_APPEND, 1L);
}else{
curl_easy_setopt(curl,CURLOPT_APPEND,0L);
}
r = curl_easy_perform(curl);
}
fclose(f);
if(r == CURLE_OK){
return 1;
}else{
std::wcerr << "ERROR performing upload of file: " << curl_easy_strerror(r) << " - said curl\n";
return 0;
}
}
std::wstring generateDBName(){return L"BLAH.db";}
}
void FlobWS::upload(const std::wstring &file) {
CURL *up = curl_easy_init();
if(!up){
std::cerr << "ERROR initializing curl handle up\n";
}
//curl_easy_setopt(up,CURLOPT_URL,"ftp://anotherwebsite.com");
//curl_easy_setopt(up,CURLOPT_USERNAME,"username");
//curl_easy_setopt(up,CURLOPT_PASSWORD, "password");
if(UploadSupport::upload(up,L"ftp://username:password@anotherwebsite.com/.htdocs/db_dir/"+UploadSupport::generateDBName(),file)){
std::wcerr << "ERROR uploading file\n";
}
curl_easy_cleanup(up);
}
FlobWS::~FlobWS() {
curl_global_cleanup();
}
其余的FlobWS是一个简单的头文件,其中声明了方法,curl仅包含在此文件中。
所有这些我得到了错误:
FlobbelWebStuff/libFlobbelWebStuff.a(FlobWS.cpp.obj): In function `FlobWS::FlobWS()':
D:/dev/projects/Flobbel/FlobbelWebStuff/FlobWS.cpp:13: undefined reference to `__imp_curl_global_init'
FlobbelWebStuff/libFlobbelWebStuff.a(FlobWS.cpp.obj): In function `FlobWS::sync_metadata(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
D:/dev/projects/Flobbel/FlobbelWebStuff/FlobWS.cpp:25: undefined reference to `__imp_curl_easy_init'
D:/dev/projects/Flobbel/FlobbelWebStuff/FlobWS.cpp:26: undefined reference to `__imp_curl_easy_escape'
D:/dev/projects/Flobbel/FlobbelWebStuff/FlobWS.cpp:26: undefined reference to `__imp_curl_easy_setopt'
D:/dev/projects/Flobbel/FlobbelWebStuff/FlobWS.cpp:28: undefined reference to `__imp_curl_easy_setopt'
D:/dev/projects/Flobbel/FlobbelWebStuff/FlobWS.cpp:29: undefined reference to `__imp_curl_easy_setopt'
D:/dev/projects/Flobbel/FlobbelWebStuff/FlobWS.cpp:30: undefined reference to `__imp_curl_easy_setopt'
D:/dev/projects/Flobbel/FlobbelWebStuff/FlobWS.cpp:31: undefined reference to `__imp_curl_easy_setopt'
D:/dev/projects/Flobbel/FlobbelWebStuff/FlobWS.cpp:32: undefined reference to `__imp_curl_easy_perform'
D:/dev/projects/Flobbel/FlobbelWebStuff/FlobWS.cpp:35: undefined reference to `__imp_curl_easy_cleanup'
D:/dev/projects/Flobbel/FlobbelWebStuff/FlobWS.cpp:39: undefined reference to `__imp_curl_easy_cleanup'
FlobbelWebStuff/libFlobbelWebStuff.a(FlobWS.cpp.obj): In function `UploadSupport::upload(void*, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > const&, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > const&)':
D:/dev/projects/Flobbel/FlobbelWebStuff/FlobWS.cpp:105: undefined reference to `__imp_curl_easy_setopt'
D:/dev/projects/Flobbel/FlobbelWebStuff/FlobWS.cpp:106: undefined reference to `__imp_curl_easy_setopt'
D:/dev/projects/Flobbel/FlobbelWebStuff/FlobWS.cpp:107: undefined reference to `__imp_curl_easy_setopt'
D:/dev/projects/Flobbel/FlobbelWebStuff/FlobWS.cpp:108: undefined reference to `__imp_curl_easy_setopt'
D:/dev/projects/Flobbel/FlobbelWebStuff/FlobWS.cpp:109: undefined reference to `__imp_curl_easy_setopt'
FlobbelWebStuff/libFlobbelWebStuff.a(FlobWS.cpp.obj):D:/dev/projects/Flobbel/FlobbelWebStuff/FlobWS.cpp:110: more undefined references to `__imp_curl_easy_setopt' follow
FlobbelWebStuff/libFlobbelWebStuff.a(FlobWS.cpp.obj): In function `UploadSupport::upload(void*, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > const&, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > const&)':
D:/dev/projects/Flobbel/FlobbelWebStuff/FlobWS.cpp:120: undefined reference to `__imp_curl_easy_perform'
D:/dev/projects/Flobbel/FlobbelWebStuff/FlobWS.cpp:124: undefined reference to `__imp_curl_easy_setopt'
D:/dev/projects/Flobbel/FlobbelWebStuff/FlobWS.cpp:125: undefined reference to `__imp_curl_easy_setopt'
D:/dev/projects/Flobbel/FlobbelWebStuff/FlobWS.cpp:127: undefined reference to `__imp_curl_easy_setopt'
D:/dev/projects/Flobbel/FlobbelWebStuff/FlobWS.cpp:129: undefined reference to `__imp_curl_easy_setopt'
D:/dev/projects/Flobbel/FlobbelWebStuff/FlobWS.cpp:131: undefined reference to `__imp_curl_easy_perform'
D:/dev/projects/Flobbel/FlobbelWebStuff/FlobWS.cpp:137: undefined reference to `__imp_curl_easy_strerror'
FlobbelWebStuff/libFlobbelWebStuff.a(FlobWS.cpp.obj): In function `FlobWS::upload(std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > const&)':
D:/dev/projects/Flobbel/FlobbelWebStuff/FlobWS.cpp:145: undefined reference to `__imp_curl_easy_init'
D:/dev/projects/Flobbel/FlobbelWebStuff/FlobWS.cpp:157: undefined reference to `__imp_curl_easy_cleanup'
FlobbelWebStuff/libFlobbelWebStuff.a(FlobWS.cpp.obj): In function `FlobWS::~FlobWS()':
D:/dev/projects/Flobbel/FlobbelWebStuff/FlobWS.cpp:161: undefined reference to `__imp_curl_global_cleanup'
collect2.exe: error: ld returned 1 exit status
mingw32-make.exe[3]: *** [CMakeFiles\Flobbel.dir\build.make:100: Flobbel.exe] Error 1
mingw32-make.exe[2]: *** [CMakeFiles\Makefile2:76: CMakeFiles/Flobbel.dir/all] Error 2
mingw32-make.exe[1]: *** [CMakeFiles\Makefile2:88: CMakeFiles/Flobbel.dir/rule] Error 2
mingw32-make.exe: *** [Makefile:117: Flobbel] Error 2
我正在使用MinGW 7.3.0 64位和CMake 3.14。 所以请帮助我,我是否太愚蠢以至于看不到东西?