视觉SLAM十四讲作业练习(1)

4 CMake 练习

书写一个由 cmake 组织的 C++ 工程,要求如下:

  1. include/hello.h 和 src/hello.c 构成了 libhello.so 库。hello.c 中提供一个函数 sayHello(),调用此 函数时往屏幕输出一行“Hello SLAM”。我们已经为你准备了 hello.h 和 hello.c 这两个文件,见 “code/”目录下。
  2. 文件 useHello.c 中含有一个 main 函数,它可以编译成一个可执行文件,名为“sayhello”
  3. 默认用 Release 模式编译这个工程。
  4. 如果用户使用 sudo make install,那么将 hello.h 放至/usr/local/include/下,将 libhello.so 放 至/usr/local/lib/下。
  5. 为你的库提供 FindHello.cmake 文件,让其他用户可以通过 find_package 命令找到你的库,并实际测试你的程序确实可以这样做。
1.建立共享库(hello_lib)

在hello_lib文件夹下创建三个文件夹:build存放编译临时文件,include存放hello.h,src存放hello.cpp。

hello.h

#pragma once
void sayHello();

hello.cpp

#include "hello.h"
#include <iostream>
using namespace std;
void sayHello(){
	cout << "Hello World!"<< endl;
	
}

hello_lib/CMakeLists.txt

cmake_minimum_required(VERSION 3.16)
project(hello_lib)

include_directories(${PROJECT_SOURCE_DIR}/include)
add_subdirectory(src)

hello_lib/src/CMakeLists.txt

add_library(hello SHARED hello.cpp)
install(FILES ${PROJECT_SOURCE_DIR}/include/hello.h DESTINATION /usr/local/include)
install(TARGETS hello LIBRARY DESTINATION /usr/local/lib)

此段代码目的是将hello.h(头文件)与hello(共享库)安装到本机。

可以在build目录下运行cmake … 编译并调用sudo make install安装

2.使用共享库(say_hello)

在say_hello文件夹下创建两个个文件夹:build存放编译临时文件,src存放useHello.cpp。

useHello.cpp

#include "hello.h"
using namespace std;

int main(int agrc,char **argv){
	sayHello();
	return 0;
}

say_hello/CMakeLists.txt

cmake_minimum_required(VERSION 3.16)
project(sayHello)
add_subdirectory(src)

say_hello/src/CMakeLists.txt

include_directories(/usr/local/include)
link_directories(/usr/local/lib)

add_executable(sayHello useHello.cpp)
target_link_libraries(sayHello hello)

5 gflags, glog, gtest 的使用

​ glog 是日志打印工具,gflags 是参数管理工具,而 gtest 是单元测试工具。当我们在开发自己的应用时,可以灵活地使用这些三方库,加快算法的开发效率。

  1. 请自行寻找这三个库的说明文档,并在系统中安装它们。请说明你是如何安装的。

    (1)进入clone后的目录,在此目录中创建build目录:mkdir build

    (2)在build目录下执行cmake …

    (3)执行make 编译

    (4)执行安装命令:make install(可能需要root权限,su root即可进入root)

    PS:需要先安装glog再安装gflags,否则glog将无法安装。

  2. 将上一题中的打印改为使用 glog 的打印方式,以替代 std::cout 的输出方式。

    1.共享库文件修改

    hello.h

    #pragma once
    
    #include <glog/logging.h>
    void sayHello();
    

    hello.cpp

    #include "hello.h"
    #include <iostream>
    #include <glog/logging.h>
    using namespace std;
    void sayHello(){
    	LOG(INFO) << "Hello World!";
    	
    }
    

    hello_lib/src/CMakeLists.txt

    add_library(hello SHARED hello.cpp)
    include_directories(/usr/local/include/glog)
    
    link_directories(/usr/local/lib)
    target_link_libraries(hello glog)
    
    install(FILES ${PROJECT_SOURCE_DIR}/include/hello.h DESTINATION /usr/local/include)
    install(TARGETS hello LIBRARY DESTINATION /usr/local/lib/lib)
    

    useHello.cpp

    #include "hello.h"
    
    using namespace std;
    
    int main(int argc,char **argv){
    	sayHello();
    	return 0;
    	
    }
    

    2.运行结果

    WARNING: Logging before InitGoogleLogging() is written to STDERR
    I20220423 16:14:39.055696 10549 hello.cpp:6] Hello World!
    

    3.解决WARNING

    根据警告提示修改useHello.cpp

    #include "hello.h"
    #include <glog/logging.h>
    using namespace std;
    
    int main(int agrc,char **argv){
    	google::InitGoogleLogging(argv[0]);
    	google::SetStderrLogging(google::GLOG_INFO);
    	sayHello();
    	return 0;
    	
    }
    

    修改say_hello/src/CMakeLists.txt文件

    include_directories(/usr/local/include)
    include_directories(/usr/local/include/glog)
    
    link_directories(/usr/local/lib)
    link_directories(/usr/local/lib/lib)
    
    add_executable(sayHello useHello.cpp)
    target_link_libraries(sayHello hello glog)
    

    编译运行:

    I20220423 16:55:50.654726 13485 hello.cpp:6] Hello World!
    

    sayHello的链接情况:

    ldd src/sayHello

    libhello.so => /usr/local/lib/lib/libhello.so 
    libglog.so.1 => /usr/local/lib/libglog.so.1
    

    注:使用glog之前必须先初始化库,要生成日志文件只需在开始log之前调用一次:

    google::InitGoogleLogging(argv[0]);  //括号内是程序名
    

    ​ 当要结束glog时必须关闭库,否则会内存溢出:

    google::ShutdownGoogleLogging();
    

3.在 useHello.cpp 中增加一个 gflags 以指明打印的次数 print_times,默认为 1。当用户传递该参数时, 即打印多少遍 Hello SLAM。

​ 主要修改say_hello

(1)say_hello/src/useHello.cpp修改

#include "hello.h"
#include <glog/logging.h>
#include <gflags/gflags.h>

using namespace std;

DEFINE_int32(print_times,1,"number of times for output");

int main(int argc,char **argv){
	gflags::ParseCommandLineFlags(&argc,&argv,true);
	google::InitGoogleLogging(argv[0]);
	google::SetStderrLogging(google::GLOG_INFO);
	//将输入的字符串转化为数字
	if(argv[1])
	{
		FLAGS_print_times = stoi(argv[1]);
	}
	for(int i = 0;i < FLAGS_print_times;i++)
	{
		sayHello();
	}

	return 0;
}

(2)say_hello/src/CMakeLists.txt修改

include_directories(/usr/local/include)
include_directories(/usr/local/include/glog)
include_directories(/usr/local/include/gflags)

link_directories(/usr/local/lib)
link_directories(/usr/local/lib/lib)

add_executable(sayHello useHello.cpp)
target_link_libraries(sayHello hello glog gflags)

(3)运行

在 ./sayHello 后面添加数字即可重复打印。

./sayHello 3

I20220423 20:03:10.555475 17494 hello.cpp:6] Hello World!
I20220423 20:03:10.555738 17494 hello.cpp:6] Hello World!
I20220423 20:03:10.555755 17494 hello.cpp:6] Hello World!

3.书写一个 gtest 单元测试程序来测试你的工程能够正常运行。修改你的 CMakeLists.txt 来增加这 个单元测试。

(1)创建test文件夹,在其中创建testUsehello.cpp与CMakeLists.txt

testUseHello.cpp

#include <gtest/gtest.h>
#include <glog/logging.h>
#include "hello.h"

TEST(sayHelloTest,sayHelloNoThrow)
{
    EXPECT_NO_THROW(sayHello());
}

int main(int argc, char *argv[])
{
    google::InitGoogleLogging(argv[0]);
    google::SetStderrLogging(google::GLOG_INFO);
    ::testing::InitGoogleTest(&argc,argv);

    return RUN_ALL_TESTS();
}

CMakeLists.txt

include_directories(/usr/local/include)
include_directories(/usr/local/include/glog)
include_directories(/usr/local/include/gflags)
include_directories(/usr/local/include/gtest)
include_directories(/usr/local/include/gmock)

link_directories(/usr/local/lib)
link_directories(/usr/local/lib/lib)

add_executable(testUseHello testUseHello.cpp)
target_link_libraries(testUseHello hello glog gflags gtest gmock pthread)

say_hello/CMakeLists.txt中需添加:

add_subdirectory(test)

(2)编译运行

结果如下:

[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from sayHelloTest
[ RUN      ] sayHelloTest.sayHelloNoThrow
I20220424 14:51:29.943917  8962 hello.cpp:6] Hello World!
[       OK ] sayHelloTest.sayHelloNoThrow (0 ms)
[----------] 1 test from sayHelloTest (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[  PASSED  ] 1 test.
  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值