SLAM开发过程中常会用到gflags, glog, gtest 这三件套,gflags 是参数管理工具,glog 是日志打印工具,而 gtest是单元测试工具,下面对其进行学习和初步使用。
直观的理解,就是对命令行参数中的flag进行管理的一个库,比如ls -l
中的-l
就是一个flag,后面没有跟参数。这就是最初步的理解。
先挖个坑,到时候来填:
参考1
参考2
安装:
git clone https://github.com/gflags/gflags.git
cd gflags
mkdir build && cd build
cmake -DCMAKE_INSTALL_PREFIX=/usr/local -DBUILD_SHARED_LIBS=ON -DGFLAGS_NAMESPACE=gflags ../
make -j4
sudo make install
注意上面要设置为默认生成动态库,下面会讲到。
工程/foo.cpp:
#include
#include
using namespace std;
//宏定义gflags
DEFINE_bool(big_menu, true, "Include 'advanced' options in the menu listing");
DEFINE_string(languages, "english,french,german", "comma-separated list of languages to offer in the 'lang' menu");
DEFINE_int32(tmp, 100, "This is temp test value!");
static bool ValidatePort(const char* flagname, int value) {
if (value > 0 && value < 32768) // value is ok
return true;
printf("Invalid value for --%s: %d\n", flagname, (int)value);
return false;
}
int main(int argc, char** argv)
{
DEFINE_validator(tmp, &ValidatePort);
if(tmp_validator_registered)
{
cout<<"tmp 定义成功"<<endl;
cout<<"tmp值为:"<<FLAGS_tmp<<endl;
cout<<"请输入要修改的tmp值:";
cin>>FLAGS_tmp;
cout<<endl<<"修改成功,修改后tmp为:"<<FLAGS_tmp<<endl;
}
else cout<<"tmp 定义失败"<<endl;
return 0;
}
工程/CMakeLists.txt:
PROJECT(GFLAGS_)
FIND_PACKAGE(gflags REQUIRED)
IF (GFLAGS_INCLUDE_DIR)
MESSAGE(INFO "找到了gflags库")
ENDIF (GFLAGS_INCLUDE_DIR)
ADD_EXECUTABLE(foo foo.cpp)
TARGET_LINK_LIBRARIES(foo gflags) #这里不是gflags::gflags,找不到
访问定义的FLAGS就直接可以当作正常的变量访问,只是需要加前缀FLAGS_
,如上面定义的tmp变量,访问可以直接FLAGS_tmp
:
多文件使用FLAGS需要声明,在hello.h文件中声明,然后直接#include "hello.h"就可以直接使用这个FLAGS了
ADD_EXECUTABLE(sayhello useHello.cpp)
INCLUDE_DIRECTORIES(../include) #添加一个头文件搜索路径
FIND_PACKAGE(gflags REQUIRED)
TARGET_LINK_LIBRARIES(sayhello hello gflags) #最最最重要的事情:千万不要忘记把所有的库都link到sayhello上
强调一定要把所有的库都link到sayhello上。
#pragma once
#include
DECLARE_int32(tmp); //声明FLAGS
void sayHello();
直接使用flags即可,因为是默认安装到usr/local/下的,所以也不用SET(PACKAGE_DIR)
和FIND_PACKAGE(gflags)
main
#include
#include "hello.h"
#include
DEFINE_int32(print_times, 1, "The print times");
int main( int argc, char** argv )
{
gflags::ParseCommandLineFlags(&argc, &argv, true); //用于接受命令行的flag参数并更新默认参数
for(int i=FLAGS_print_times; i>0;--i)
sayHello();
std::cout<<"FLAGS_tmp的值为:"<<FLAGS_tmp<<std::endl;
return 0;
}
gflags::ParseCommandLineFlags(&argc, &argv, true);
用于接受命令行的flag参数并更新默认参数
./sayhello -print_times 10
传入参数
先装gflags,再装glog
但是在装glog时会出现编译动态库时不能使用静态库,
/usr/bin/ld: /usr/local/lib/libgflags.a(gflags.cc.o): relocation R_X86_64_PC32 against symbol `stderr@@GLIBC_2.2.5' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: 最后的链结失败: bad value
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/glog.dir/build.make:84:libglog.so.0.6.0] 错误 1
make[1]: *** [CMakeFiles/Makefile2:1102:CMakeFiles/glog.dir/all] 错误 2
make: *** [Makefile:163:all] 错误 2
所以gflags要安装动态库.so,所以前面安装时设置了DBUILD_SHARED_LIBS=ON
cmake -DCMAKE_INSTALL_PREFIX=/usr/local -DBUILD_SHARED_LIBS=ON -DGFLAGS_NAMESPACE=gflags ../
看了半天,没发现这个glog的优势在哪,除了一些判断语句的输出,为什么不直接用cout??
先放着。
有tests,test suits, test programs
有ASSERT*
和EXPECT*
类的函数,前者如果断言错误则直接中止程序,后者不会,更倾向于后者,很严重的断言采用ASSERT*
。
test/CMakeLists.txt为:
INCLUDE_DIRECTORIES(../include) #hello.h搜索路径
FIND_PACKAGE(gflags REQUIRED) #找到gflags包
FIND_PACKAGE(glog REQUIRED) #找到glog包
set(CMAKE_CXX_STANDARD 11)
include(FetchContent) #载入模块
FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip
)
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
#后面又添加的
enable_testing()
add_executable( main_test main_test.cpp)
target_link_libraries(main_test gtest_main hello gflags glog)
#使CMake runner能够在二进制中找到测试,使用GoogleTest模块
include(GoogleTest) #用来载入 CMakeLists.txt 文件,也用于载入预定义的 cmake 模块. INCLUDE(file1 [OPTIONAL]) INCLUDE(module [OPTIONAL])
gtest_discover_tests(main_test)
test/main_test.cpp为:
#include
#include
#include
#include
TEST(FactorialTest, ZeroInput){
EXPECT_EQ(my_fac(0), 1);
}
TEST(FactorialTest, PositiveInput){
EXPECT_EQ(my_fac(1), 1);
EXPECT_EQ(my_fac(2), 2);
EXPECT_EQ(my_fac(3), 6);
}