vs中编译并运行cURL googletest 等第三方库

637 阅读5分钟

[TOC]

第三方库 为 curl 与 googletest 以及我们 自定义的 一个 库 A.dll

为了 达到 多端【windows 、linux】 一致的效果,所以 采用cmake 的方式进行编译

以下的代码必须需要您的 vs 2019 有 cmake 的组件

这里不细说 【可自行查看】:blog.csdn.net/shulianghan…(为啥我要把 路径贴出来 因为微信公众号 不支持 外链,真难)

编写 我们自己的动态库

A.h

#pragma once
//TESTDEPEND_EXPORTS 这个宏名称可以自由定义,
#ifdef TESTDEPEND_EXPORTS  
#define TESTDEPEND_API __declspec(dllexport)   
#else  
#define TESTDEPEND_API __declspec(dllimport)   
#endif

TESTDEPEND_API int testA();

A.c

#include <stdio.h>
#include "A.h"


int testA(){
	printf("helloABC\n");
	return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.7)

project(A)

add_Library(${PROJECT_NAME} SHARED A.c B.cpp)

target_compile_definitions(${PROJECT_NAME} PUBLIC TESTDEPEND_EXPORTS)

然后 可以 采用 单独的cmake.exe【可通过官网下载最新版的windows 】 这个工具,也可以通过 VS 子带的cmake 来执行。

然后右键 重新 生成 即可 根据 编译的输出日志找到 库的位置。

这里要说下, 由于我们是导出符号,所以 需要 需要加 宏定义 TESTDEPEND_EXPORTS (相当于 __declspec(dllexport)) 这样 生成的库就会有我们 的 所需要的符号,默认是不导出哦。

然后可以查看输出的目录是不是有个 A.dll 以及 A.lib 这两个东西。

引用工程

接下来我们再来个我们的 引用 这个库 的工程 test

#include <stdio.h>
#include <Windows.h>
#define CURL_ENABLE
#define ENABLE_A
#define USE_DYNAMIC_LOAD_A
#define GTEST

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

#ifdef ENABLE_A
#include "A.h"
#endif

#ifdef CURL_ENABLE
#include "curl/curl.h"
#include "curl/easy.h"
#endif

#ifdef __cplusplus
}
#endif // __cplusplus

#ifdef GTEST
#include "gtest/gtest.h" 
#endif

int hello(int arg) {
	return arg;
}
bool isTrue(int arg) {
	return !!arg;
}

#ifdef GTEST
TEST(IsPrimeTest, Trivial) {
	EXPECT_FALSE(isTrue(0));
}
#endif

typedef int(*HA_GetVersion_t)(); //定义函数指针类型
int main(int argc, char** argv) {
#ifdef USE_DYNAMIC_LOAD_A
	HMODULE hDll = GetModuleHandle("A.dll");
	if (hDll != NULL) {
		printf("hello Module\n");
	}
	else {
		printf("WOW!!!\n");
		hDll = LoadLibrary("A.dll");
	}
	if (hDll != NULL)
	{
		HA_GetVersion_t HA_GetVersion_p = NULL;

		HA_GetVersion_p = (HA_GetVersion_t)GetProcAddress(hDll, "testA");


		if (HA_GetVersion_p != NULL)
		{
			int version = HA_GetVersion_p();
			printf("version = %d\n", version);
		}
		else
		{
			printf("the calling is error\n");
		}
	}

#endif
#ifdef GTEST
	::testing::InitGoogleTest(&argc, argv);
	RUN_ALL_TESTS();
#endif
#ifdef CURL_ENABLE
	CURL* curl = curl_easy_init();
	if (curl)
	{
		curl_easy_setopt(curl, CURLOPT_URL, "https://www.baidu.com");
        //curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1);
		//curl_easy_setopt(curl, CURLOPT_CAINFO, "ca.pem");//导入证书
		//curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);//不需要证书
		int res = curl_easy_perform(curl);
		printf("request = %d\n",res);
	}
	//
	//curl_easy_cleanup(NULL);
#endif // CURL_ENABLE



	printf("hello\n");
#ifdef ENABLE_A
	testA();
#endif
	return 0;
}

以上为这个项目的所有代码, 可以通过不同的宏开关来 选择性的测试 相应的集成是否 ok。

此处我们 只要打开 ENABLE_A 即可.

然后是 CMakeLists.txt

cmake_minimum_required(VERSION 3.7)

project(test)

set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")

#[==[
	set(CompilerFlags
        CMAKE_CXX_FLAGS
        CMAKE_CXX_FLAGS_DEBUG
        CMAKE_CXX_FLAGS_RELEASE
        CMAKE_C_FLAGS
        CMAKE_C_FLAGS_DEBUG
        CMAKE_C_FLAGS_RELEASE
        )
foreach(CompilerFlag ${CompilerFlags})
  string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}")
endforeach()
#]==]

add_executable(${PROJECT_NAME} test.cpp)
target_include_directories(${PROJECT_NAME} PUBLIC ../../github/googletest/googletest/include/)
target_include_directories(${PROJECT_NAME} PUBLIC lib)
target_include_directories(${PROJECT_NAME} PUBLIC D:/softwarefiles/chrome/curl-7.71.1/include)
#link_directories(../build/lib)

macro(addLIB LIBNAME LIBPATH)
message(WARNING "whar you are input LIBNAME:${LIBNAME} LIBPATH:${LIBPATH}")
	add_library(${LIBNAME} STATIC IMPORTED)
	set_target_properties(${LIBNAME} 
		PROPERTIES IMPORTED_LOCATION
		${LIBPATH}
	)
endmacro()

addLIB(crypto "D:/softwarefiles/chrome/openssl-OpenSSL_1_1_1g/build/Win64/VC14.2/DLL Release/libcrypto.lib")
addLIB(ssl "D:/softwarefiles/chrome/openssl-OpenSSL_1_1_1g/build/Win64/VC14.2/DLL Release/libssl.lib")
addLIB(AT "${CMAKE_SOURCE_DIR}/lib/Debug/A.lib")
addLIB(GT "gtest.lib")
addLIB(CURL "libcurl.lib")

target_compile_definitions(${PROJECT_NAME} PUBLIC BUILDING_LIBCURL )


message(STATUS "WHAT ${CMAKE_CURRENT_SOURCE_DIR}")
#add_subdirectory(lib)
target_link_libraries(${PROJECT_NAME} PUBLIC 
	#gtest_dlld
	AT
	GT
	CURL
	crypto
	ssl
	crypt32
	Wldap32.lib
	ws2_32.lib
	
	#winmm.lib
	#pthread	
	)

注意上面是我将所有的库导入的结果,我们可以 慢慢的一步一步的进行。

这里要说下,在windows 里面如果我用 link_directories 是找不到的, 最终改用 add_library 的方式才可以找到

如果 嫌上面的 太多太复杂,先来个简单的。

cmake_minimum_required(VERSION 3.7)

project(test)
add_executable(${PROJECT_NAME} test.cpp)
target_include_directories(${PROJECT_NAME} PUBLIC lib)

macro(addLIB LIBNAME LIBPATH)
	add_library(${LIBNAME} STATIC IMPORTED)
	set_target_properties(${LIBNAME} 
		PROPERTIES IMPORTED_LOCATION
		${LIBPATH}
	)
endmacro()

addLIB(AT "${CMAKE_SOURCE_DIR}/lib/Debug/A.lib")
target_link_libraries(${PROJECT_NAME} PUBLIC 
	AT
	)

这里要说下 我的目录结构如下[已将 额外的删除]

tree /F
│  A.dll
│  CMakeLists.txt
│  test.cpp
│  test.sln
├─lib
│  │  A.c
│  │  A.h
│  │  A.sln
│  │  B.cpp
│  │  CMakeLists.txt
│  ├─Debug
│  │      A.dll
│  │      A.exp
│  │      A.ilk
│  │      A.lib
│  │      A.pdb

当然,你可以看到 我们 链接的时候是链接的 A.lib 这个库,但是我们运行的时候像linux 一样 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH;xxx

当然如果你想直接 通过 IDE 进行 运行 也是可以 。两种方式 将 A.dll 放到 根目录底下【就是上面我的目录结构】 还有一种就是 设置环境变量 将路径加进去即可,然后重启IDE即可,看到效果。

ok 运行即可,看到想要的效果咯。

动态加载动态库

当然 可以 按照 linux 的 dlopen 的方式打开某个动态库,这里 需要将上述的 USE_DYNAMIC_LOAD_A 打开即可。你就可以看到 动态导入的效果了。有两个问题注意下 1. 路径 2. 导出符号必须有才可以。

也许你会问:怎么看导出符号有没有呢。 其实每个平台都提供给我们 相应的 反汇编的工具,比方说 :linux 有 objdump nm windows 相应的也有 dumpbin.exe 这个工具

dumpbin /exports a.dll

如果你找不到你的 dumpbin.exe 在哪里,建议安装个 Listary 这个文件便利工具,贼好用。

导入三方库 googletest

github.com/google/goog…

这是 googletest 的地址

打开后可以清楚的看到 竟然后cmake 那我们就可以直接使用cmake.exe 这个工具进行生成了

按照上述步骤 即可 生成 相应的属性,然后 点击Generate open Project 你就可以看到正常生成了。 当然 必须依赖于你已经配置好 windows的编译环境 cl.exe 了。【这里 正常安装好 就可以了?】

然后又击 重新生成

没错你就可以看到上面的输出日志了。

接下来 就是 按照上面的方式进行导入即可。

以下便是输出了,当然 如果一开始不是用 最全的CmakeList.txt 这里需要把 googletest这个也加下

导入三方库 curl

首先去官网 下载 curl 库: curl.haxx.se/download.ht…

下载解压后,可以看到 curl-7.71.1\projects\Windows\VC15 这里面是直接就可以在VS中打开的工程,你说牛不牛

右键 重新生成 你就会得到 libcurl.lib 将其导入,打开宏定义 然后运行,看效果

报错 ,curl 返回 1 ,通过查看错误码定义: curl.haxx.se/libcurl/c/l…

CURLE_UNSUPPORTED_PROTOCOL (1)

The URL you passed to libcurl used a protocol that this libcurl does not support. The support might be a compile-time option that you didn't use, it can be a misspelled protocol string or just a protocol libcurl has no code for.

不支持的类型,因为我们上面用了 https 的方式,我们先改成 http 试下

一切成功。

那怎么支持 https 呢?

支持 https

首先下载 一个 openssl 的源码 地址 github.com/openssl/ope… 随便下载一个,我这里下载了 OpenSSL 1.1.1g 这个包

如果你之前细心的话,你会发现 curl 的 目录底下竟然有 build-openssl.bat

运行之后我们发现 需要指定 openssl 源码的路径, perl的可执行文件的路径。我们还需要下载一个perl工具才可以。 下载即可 strawberryperl.com/releases.ht…

下载解压之后,指定路径即可,成功编译了。

build-openssl.bat vc14.2 x64 release [openssl的源码路径] -perlpath=[perl的路径]

大概需要等待十多分钟,就可以成功在目录 openssl-OpenSSL_1_1_1g\build\Win64\VC14.2\DLL Release 成功生成 了

导入到我们的项目里面,如果导入动态库的方式,则需要将 上述的两个动态库 复制到相应的根目录下才可以,【上面已经讲了】。

运行也会发现可以了。接下里将 http 改成https

你会发现 报错了。

CURLE_PEER_FAILED_VERIFICATION (60)

The remote server's SSL certificate or SSH md5 fingerprint was deemed not OK. This error code has been unified with CURLE_SSL_CACERT since 7.62.0. Its previous value was 51.

原来 https 请求还需要 安全证书才可以的。

安全证书

在这里下载然后导入即可,至于怎么自己生成,后面有时间再写吧。

curl.haxx.se/docs/caextr…

预留坑位1

预留坑位2