C/C++环境配置

欢迎访问我的博客首页


  本文旨在配置跨平台的 C/C++ 环境,主要是配置 linux 系统上的 C/C++ 环境和工具,编与 linux 和 windows 系统无关的代码。

1. C++ 环境配置


1.1 CMake


  CMake 是一个编译工具,它不是编译器但提供一套能控制所有编译器的语言,否则我们只能针对不同编译器在命令行输入不同编译参数。CMake 有专门的配置文件 CMakeLists.txt 存放描述编译过程的语句。CMake 语言不区分大小写,后面会讲 CMake 语法。

  安装 CMake 很简单,到官网下载安装文件就可以安装。

1.2 MinGW


  GNU 是一个公司。它的产品之一 GCC 全称 GNU Compiler Collection(GNU 编译器套件),包含编译 C 语言的 gcc 编译器、编译 C++ 语言的 g++ 编译器等。GCC 用于 Linux 操作系统,在 Windows 操作系统上使用 GCC 需要借助 MinGW。

  MinGW 全称 Minimalist GUN for Windows,是 GUN 产品在 windows 上的移植。MSYS 全称 Minimal GNU(POSIX)system on Windows,是一个小型的GNU环境,包括基本的bash,make等,更新不及时,功能不全。MSVC 全称 Microsoft Visual C++,是 Microsoft Visual Studio 等微软 IDE 内的编译器,移植性差。

  MinGW 可以从 OSDN 下载。MinGW-w64 可以从 sourceforge下载。TDM-GCC 衍生自 MinGW 和 MinGW-w64 的项目,分为 32 位与 64 位两个版本。

  以 MinGW-w64 为例,它有 win32 和 posix 这两个版本,下载并解压其二进制压缩包,复制 bin 文件夹中的 mingw32-make.exe 命名副本为 make.exe,并把 bin 文件夹路径添加到环境变量即可供 CMake 使用。因为 win32 有自己的多线程,win32 版的 MinGW 支持 win32 的多线程而不支持 C++ 的多线程。此外 MinGW 的版本还有 sjlj 和 seh 之分。这是两种异常处理机制,sjlj 使用两个函数 setjump 和 longjump 在异常时实现跳转,seh 是 windows 提供的结构化异常处理(structured exception handing)机制。综上所述,所以一般选择 posix-seh。测试安装是否正确:

// 'std::once_flag' is defined in header '<mutex>'; did you forget to '#include <mutex>'?
#include <iostream>
#include <thread>
#include <mutex>
std::once_flag flag1;
void simple_do_once() {
    std::call_once(flag1, [](){ std::cout << "Simple example: called once\n"; });
}
int main() {
    std::thread st1(simple_do_once);
    std::thread st2(simple_do_once);
    st1.join();
    st2.join();
}

add_executable(main main.cpp)
target_link_libraries(main PRIVATE pthread)

2. 常用库


2.1 Boost


  在 linux 和 windows 编译 boost 出错都是大概率事件。比如会出现缺少 .\build.bat 的问题,最好通过 boost 官网到 sourceForge 下载而不在 github 下载。

  先点击 bootstrap.bat 生成 b2.exe,再使用下面的命令编译。注意出现路径中的反斜杠可能引起错误,可以试试正斜杠。

# The value of the --build-type option should be either 'complete' or 'minimal
b2.exe install --toolset=msvc-14.1 --prefix="D:\boost" --without-python threading=multi --build-type=complete address-model=64

  测试 boost 安装是否成功:

#include <iostream>
#include <boost/lexical_cast.hpp>
int main() {
        using boost::lexical_cast;
        int a = lexical_cast<int>("123");
        double b = lexical_cast<double>("123.12");
        std::cout<<a<<std::endl;
        std::cout<<b<<std::endl;
        return 0;
}

set(BOOST_PATH D:\\software\\boost\\include\\boost-1_76)
include_directories(${BOOST_PATH})
add_executable(boost boost.cpp)

3. CMake 语法


3.1 基础


  CMake 不区分大小写,字符串和路径加不加双引号都一样。

1. 开头

  project 后面的括号中是项目名称,使用 cmake 生成的 vs 项目名称也是由这个名称决定的。

# 对CMake版本的最低要求,小于将报错。
cmake_minimum_required(VERSION 3.2)
# 指定项目名。
project(test)

2. 变量

# 定义变量、获取变量的值。
set(A_PATH path/to/a/dir)
${A_PATH}
# 固有变量。
${PROJECT_NAME} # 指定的项目名。
${CMAKE_SOURCE_DIR} # 最外层CMakeLists.txt所在目录。
${CMAKE_CURRENT_SOURCE_DIR} # 该CMakeLists.txt所在目录。
${PROJECT_SOURCE_DIR}
# 修改变量。
string(TOLOWER ${PROJECT_NAME} LIBRARY_NAME) # 把${PROJECT_NAME}变量值的全小写赋值给变量LIBRARY_NAME。
list(APPEND A_PATH newpath/to/a/dir) # 向A_PATH添加值。
# 比较
if (${PROJECT_NAME} STREQUAL test)
    ...
endif()
# 输出语句。
message("-- project name: ${PROJECT_NAME}.")

3. 指定头文件和第三方库目录

include_directories(${PROJECT_SOURCE_DIR}/include)
link_directories(${PROJECT_SOURCE_DIR}/libs) # 相当于在linux中设置环境变量LD_LIBRARY_PATH。

4. 指定次级CMakeLists.txt目录

set(CMAKE_MODULE_PATH ./)
add_subdirectory(./)

5. 指定生成库和可执行程序的目录

set(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/build/libs)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/build/bin)

6. 搜索文件存放在变量SRC和HEADER

aux_source_directory(".cpp" ".cc" SRC)
file(GLOB_RECURSE HEADER *.cc) # GLOB:不递归

7. 生成库

add_library(${PROJECT_NAME} # STATIC | SHARED | MODULE
	${SRC}
)
target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS})
  1. STATIC:生成静态链接库。
  2. SHARED:生成动态链接库。
  3. MODULE:在使用 dyld 的系统有效,如果不支持 dyld,则被当做 SHARED。

8. 生成可执行程序

add_executable(run main.cc)
target_link_libraries(run ${OpenCV_LIBS})
add_dependencies(run ${${PROJECT_NAME}_EXPORTED_TARGETS})

9. 设置

# 设置编译选项。
add_definitions("-DXXX")
# 设置编译模式。
set(CMAKE_BUILD_TYPE Debug)
if(not CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE Release)
endif()
# 设置输出位数。
set(BUILD_USE_64BITS on)
# 设置gcc和g++路径。
set(gcc_DIR /path/to/GCC)
set(CMAKE_C_COMPILER ${gcc_DIR}/bin/gcc)
set(CMAKE_CXX_COMPILER ${gcc_DIR}/bin/g++)
# 多个libstdc++.so时选最新的。
add_definitions(-D_GLIBCXX_USE_CXX11_ABI=1)
# 使用C++11。
add_compile_options(-std=c++11)
set(CMAKE_CXX_FLAGS -std=c++11)
set(CMAKE_CXX_STANDARD 11)
# 使用C++17。
set(STDCXXFS stdc++fs)
link_directories(${gcc_DIR}/lib64)
# 其它。
add_compile_options(-Wthread-safety)

10. 优化与调试

set(CMAKE_CXX_FLAGS_DEBUG $ENV{CXXFLAGS} -O0 -Wall -g -ggdb)
set(CMAKE_CXX_FLAGS_RELEASE $ENV{CXXFLAGS} -O3 -Wall)
  1. -O0:0 表示不优化,1、2、3 表示优化程度递增。
  2. -Wall:显示所有警告。
  3. -g:利用操作系统的原生格式(native format)生成调试信息。
  4. -ggdb:使GCC为GDB生成专用的更为丰富的调试信息。

3.2 CMake 生成配置文件


  可以把参数写在 CMakeLists.txt 里面,然后传到代码里面。注意是传到代码里面而不是程序里面,这意味着改变参数要重新编译。通过 CMakeLists.txt 传参数分为 3 步:

1. 在 CMakeLists.txt 中配置

# 1.设置变量:传数字、布尔和字符串。
set(VALUE_1 0)
set(VALUE_2 1)
set(VALUE_3 false)
set(VALUE_4 ${CMAKE_SOURCE_DIR}/dataset/test.mp4)
# 2.指明配置文件名和生成的配置头文件名及它们的位置。
configure_file (
	${PROJECT_SOURCE_DIR}/Config.h.in
	${PROJECT_BINARY_DIR}/Config.h
)
# 3.指明配置头文件路径。
include_directories(${PROJECT_BINARY_DIR})
  1. 设置变量:传数字、布尔和字符串。
  2. 指定创建的配置文件位置,和生成的配置头文件位置:Config.h.in 是需要我们手动创建的配置文件,而 Config.h 是生成的配置头文件。文件名任意,后缀固定。
  3. 因为要通过 include 配置头文件获取参数,所以要指明配置头文件路径。配置头文件路径由上面 configure_file 命令的第二个参数决定,也就是第 12 行和第 9 行要一致。

2. 编写配置文件 Config.h.in

#ifndef _CONFIG_H_
#define _CONFIG_H_
#include <string>
#define KEY_1 @VALUE_1@
namespace cfg {
	const int KEY_2 = @VALUE_2@;
	const bool KEY_3 = @VALUE_3@;
	const std::string KEY_4 = "@VALUE_4@";
}
#endif

  这些内容用于生成头文件。CMake 会用第1步在 CMakeLists.txt 中通过 set 设置的变量值来替换 @VALUE_1@,从而生成配置头文件。
  配置头文件就是一个普通的头文件,我们完全可以直接写一个这样的头文件。但是对于路径参数,利用 CMake 可以方便地获取绝对路径。

3. 在代码中使用参数

#include <iostream>
#include "Config.h"
using namespace std;
 
int main (int argc, char *argv[]) {
	cout << KEY_1 << endl << cfg::KEY_2 << endl << cfg::KEY_3 << endl << cfg::KEY_4 << endl;
	return 0;
}

  包含配置头文件后就可以直接使用参数了。

3.3 CMake 使用常用库


1. OpenCV

set(OpenCV_DIR /home/XXX/software/OpenCV340/share/OpenCV)
#set(CMAKE_PREFIX_PATH /home/master/local_install/)
find_package(OpenCV 3.1.0 EXACT REQUIRED)
#find_package(OpenCV REQUIRED)
MESSAGE(STATUS "opencv version: ${OpenCV_VERSION}")
include_directories(
	${OpenCV_DIRS}
	${OpenCV_INCLUDE_DIRS}
)
target_link_libraries(exe
	${OpenCV_LIBS}
)

2. OpenNI

find_package(OpenNI2 REQUIRED)
include_directories(
	${OpenNI2_INCLUDE_DIR}
)

3. Eigen

set(Eigen3_DIR /home/XXX/software/eigenunstable/share/eigen3/cmake)
find_package(Eigen3 REQUIRED)
include_directories(
	${EIGEN3_INCLUDE_DIRS}
	/usr/include/eigen3
)

4. G2O

set(CMAKE_MODULE_PATH   ${PROJECT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH}) #the location of FindG2O.cmake
set(G2O_ROOT /home/XXX/software/g2o)
set(G2O_DIR /home/XXX/software/g2o/share)
#在FindG2O.cmake中根据G2O_ROOT查找库和头文件
find_package(G2O REQUIRED) 
include_directories( 
    ${G2O_INCLUDE_DIR}
)
link_directories(${G2O_ROOT}/lib)

5. Boost

set(BOOST_ROOT "/opt/boost")
set(BOOST_ROOT /home/XXX/software/boost159)
set(BOOST_LIBRARY_DIR "" CACHE PATH " directory of the boost lib")
set(BOOST_INCLUDE_DIR "" CACHE PATH " directory of the boost headers")
SET(BOOST_LIBRARYDIR "${BOOST_LIBRARY_DIR}")
SET(BOOST_INCLUDEDIR "${BOOST_INCLUDE_DIR}")
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
find_package(Boost REQUIRED COMPONENTS
	regex
	filesystem
	system
	thread
)
if(NOT Boost_FOUND)
	message("--Failed to find Boost.")
endif()
include_directories(
	${Boost_INCLUDE_DIRS}
	/opt/boost/lib
)

6. PCL

set(PCL_DIR /home/XXX/software/pcl180/share/pcl-1.8)
find_package(PCL REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
#移除某个链接库(当它引起错误时,通过这条语句不再链接它)
list(REMOVE_ITEM PCL_LIBRARIES "vtkproj4")

3.4 使用 CMake 编译


  当有 visual studio 的 MSVC 和 MinGW 编译器共存时,可以指定编译选项指定,还可以指定安装位置。

cmake -G "MSYS Makefiles" ..
cmake -G "MinGW Makefiles" ..
cmake -G "MinGW Makefiles" -DCMAKE_INSTALL_PREFIX=D:/selfLibs ..

3.5 find_package


  make install 会把安装目录写入包注册表。如果不想编辑或查找包注册表,可以使用这些命令。如果自定义了安装目录,可以把安装目录下的 bin 和 lib 目录添加到环境变量,find_package 就可以找到。

4. 参考


  1. MinGW 的 posix 和 win32,知乎专栏,2020。
  2. MinGW 的 posix 和 win32,CSDN,2020。
  3. 如何选择 MinGW,知乎。
  4. Windows 编译安装 boost,博客园。
  5. CMake 使用总结,博客园,2017。
  6. CMake 简要教程,简书,2016。
  7. find_package 使用 <PackageName>_ROOT,CMake 官方文档。
  8. sophus 安装与使用
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值