程序编译安装与卸载

本文最后更新于 2025年2月19日 上午

本文主要分享了程序编译、安装与卸载的知识点。

ROS编译与运行

编写CmakeLists.txt

在CmakeLists.txt里指定第三方库所在的路径

CmakeLists.txt里指定第三方库所在的路径,即指定其编译安装后.cmake文件所在的路径,例如:

1
2
3
4
5
6
7
8
# 指定OpenCVConfig.cmake文件的目录
# 注意opencv安装目录下的/share/OpenCV
set(OpenCV_DIR /usr/local/share/OpenCV) # 默认安装在/usr/local/
set(OpenCV_DIR /usr/local/opencv/opencv345/share/OpenCV) # 自定义安装在/usr/local/opencv/opencv345的openv3.4.5
set(OpenCV_DIR /usr/local/opencv/opencv452/lib/cmake/opencv4)
# set(OpenCV_DIR /opt/ros/kinetic/share/OpenCV-3.3.1-dev)
# set(OpenCV_DIR /path/to/opencv/build)
find_package(OpenCV REQUIRED)
1
find_library(flowfilter_gpu_LIBS NAMES flowfilter_gpu PATHS /usr/local/include)

首先,set(OpenCV_DIR /usr/local/opencv/opencv345/share/OpenCV)这行代码设置了一个变量OpenCV_DIR,它指向OpenCV库的安装位置。在这个例子中,OpenCV库被安装在/usr/local/opencv/opencv345/share/OpenCV这个路径下。OpenCV_DIR这个变量通常用于指定OpenCV的cmake配置文件的位置,这个文件包含了OpenCV库的版本信息、编译选项等信息。

然后,find_package(OpenCV REQUIRED)这行代码告诉CMake去查找OpenCV库。REQUIRED关键字表示如果CMake不能找到OpenCV库,那么CMake应该停止配置过程并显示错误信息。如果CMake成功找到了OpenCV库,那么它将设置一些变量,例如OpenCV_INCLUDE_DIRSOpenCV_LIBS,这些变量分别包含了OpenCV的头文件路径和库文件路径,可以在后续的target_include_directoriestarget_link_libraries命令中使用。

如果没有设置OpenCV_DIRfind_package命令会在默认的路径下查找OpenCV库。这些默认的路径包括:

  • CMake的模块路径(CMAKE_MODULE_PATH
  • CMake的安装前缀(CMAKE_PREFIX_PATH
  • 系统的环境变量路径

具体来说,find_package会查找名为OpenCVConfig.cmakeopencv-config.cmake的文件,这个文件通常位于OpenCV库的安装目录中。

如果你的OpenCV库安装在非标准的位置,或者你有多个版本的OpenCV库并且想要选择一个特定的版本,那么你可以通过设置OpenCV_DIR来指定OpenCV库的路径。如果没有设置OpenCV_DIR,CMake可能会找到错误的版本或者找不到OpenCV库。

OpenCV_DIROpenCV_INCLUDE_DIR是两个不同的变量,它们在CMake中的作用也不同。

  • OpenCV_DIR是用于指定OpenCV的cmake配置文件位置的变量。find_package命令会使用OpenCV_DIR变量的值作为查找OpenCV配置文件的起始路径。如果OpenCV_DIR被设置,find_package就会直接在这个路径下查找配置文件,而不会在其他路径下查找。

  • OpenCV_INCLUDE_DIR通常是find_package命令找到OpenCV库后设置的一个变量,它包含了OpenCV的头文件路径。这个变量通常用于target_include_directories命令,以便你的项目可以找到OpenCV的头文件。

如果你设置了OpenCV_INCLUDE_DIR,而不是OpenCV_DIR,然后调用find_package(OpenCV REQUIRED),那么find_package命令可能无法找到正确的OpenCV库,因为它不知道在哪里查找OpenCV的配置文件。在这种情况下,find_package命令可能会找到错误的OpenCV版本,或者找不到OpenCV库。find_package命令找到的结果会覆盖你设置的OpenCV_INCLUDE_DIR变量。

总的来说,如果你想要指定OpenCV库的位置,你应该设置OpenCV_DIR,而不是OpenCV_INCLUDE_DIR

(在ROS中)编译第三方开源软件需要下载的问题

注意CmakeList.txt里有没有指定具体版本。在package.xml里也可以看到指定的版本。

其实就类似于在系统中cmakemakemake install的步骤,只不过这里的第三方库是安装在了ROS工作区里被相互调用,catkin clean后也就删除掉了,而没有安装在系统环境里。也方便使用指定版本的第三方库。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# URL https://github.com/gflags/gflags/archive/v2.2.1.zip

# GIT_REPOSITORY https://github.com/jbeder/yaml-cpp
# GIT_TAG ${YAML_CPP_TAG}

# DOWNLOAD_COMMAND rm -f SuiteSparse-${VERSION}.tar.gz && wget --retry-connrefused --waitretry=1 --timeout=40 --tries 3 https://github.com/ethz-asl/thirdparty_library_binaries/raw/master/SuiteSparse-${VERSION}.tar.gz

# 对于上述的3种情况,可以替换为:
DOWNLOAD_COMMAND ""
URL "/yourfolder/gflags-2.2.1.zip" # 使用存档时,它将自动解压缩,除非设置了 DOWNLOAD_NO_EXTRACT 选项来阻止它。
# 详细示例:https://zeyulong.com/posts/6d95d81a/

# 默认解压路径为catkin_ws/build/xxx/xxx_src-prefix/src/xxx_src

# 可选
URL_MD5 4628df9eeae10ae5f0c486f1ac982fce # (可选,仅用作文件验证)与URL搭配。随便输入一个MD5码,编译时会报错当前压缩包正确的MD5码。
UPDATE_COMMAND "" # 与URL搭配。使用自定义命令覆盖下载方法的更新步骤。
DOWNLOAD_NO_EXTRACT TRUE # 允许通过为此选项传递一个布尔真值来禁用下载步骤的提取部分。
# 如果希望控制下载的归档文件的位置及其名称,可以使用以下选项
set(CMAKE_CURRENT_BINARY_DIR /yourfolder) # 放在主程序中,而不包含在ExternalProject_Add()
DOWNLOAD_DIR ${CMAKE_CURRENT_BINARY_DIR}
DOWNLOAD_NAME jsoncpp_1.8.4.tar.gz

或者,将src(这个文件是原本解压下载的第三方源码source的地方,具体名称要看CMakeLists.txt中SOURCE_DIR的设置)中的各个第三方源码都解压好,放到src对应的文件夹中。例如catkin_ws/build/xxx/xxx_src-prefix/src/xxx.tar.gz

cmake

一般流程

1
2
3
4
cd package_name
mkdir build
cd build
cmake ..

我个人推荐把第三方库安装在/usr/local文件夹下进行管理。例如,在/usr/local文件夹下新建文件夹eigen3,后在eigen3文件夹下新建文件夹eigen330eigen340

定义编译参数

可在cmake命令后加参数:

1
2
3
4
# 指定安装目录。使用该参数可以指定安装目录,使得在执行make install命令时,生成的可执行文件、库文件、头文件等可以被安装到指定的目录下。
cmake -DCMAKE_INSTALL_PREFIX=/usr/local/package_name ..
# 指定使用的gcc和g++版本
-DCMAKE_C_COMPILER=gcc-10 -DCMAKE_CXX_COMPILER=g++-10

也可以在CMakeLists.txt文件中定义,例如,启用参数EFFT_USE_FFTW3

1
cmake DEFFT_USE_FFTW3 ..

或,在CMakeLists.txt文件中:

1
target_compile_definitions(efft-unit-tests PRIVATE EFFT_USE_FFTW3)

保存cmake输出

ROS: cmake build的输出在catkin_ws/logs/your_package_name/build.cmake.log、build.make.log里。

cmake命令的输出信息通常在终端中显示,而不是保存在文件中。这些信息包括配置过程中的警告、错误以及其他重要信息。

然而,你可以将cmake命令的输出重定向到一个文件中。例如,你可以使用以下命令将输出保存到一个名为output.txt的文件中:

1
cmake .. > output.txt

在这个命令中,>操作符将cmake命令的输出重定向到output.txt文件中。如果output.txt文件已经存在,这个命令将覆盖它的内容。如果你想要追加输出到文件中,而不是覆盖它,你可以使用>>操作符,如下所示:

1
cmake .. >> output.txt

请注意,这些命令只会捕获标准输出,而不会捕获错误输出。如果你也想要捕获错误输出,你可以使用2>&1,如下所示:

1
cmake .. > output.txt 2>&1

在这个命令中,2>&1将错误输出重定向到标准输出,然后>操作符将标准输出重定向到output.txt文件中。这样,output.txt文件将包含所有的输出,包括错误信息。

make

1
2
3
4
5
# 建议在make之前先查看CPU的核心数
nproc # 你可以根据你的核心数来调整make指令的参数,比如笔者的CPU核心数为12,则可以执行:
make -j12
make # 根据Makefile编译源代码,连接,生成目标文件,可执行文件。
make install # 将编译成功的可执行文件安装到系统目录中,一般为/usr/local/bin目录。

cmake --install .make install的区别:

cmake --install .make install都是用来安装编译好的程序的命令,但它们在使用的构建系统和工作方式上有所不同。

  • make install是GNU Make的命令,它依赖于Makefile中的install目标。这个install目标通常会将编译好的二进制文件、库文件、头文件等复制到系统的指定位置,如/usr/local/bin/usr/local/lib等。这个命令通常在使用GNU Autotools或者手写Makefile的项目中使用。

  • cmake --install .是CMake的命令,它会执行CMakeLists.txt文件中定义的安装规则。这个命令在CMake 3.15及以后的版本中可用,它是cmake -P cmake_install.cmake的一个更简洁的替代。这个命令的好处是它不依赖于特定的构建系统,可以在任何CMake支持的构建系统中使用。

总的来说,这两个命令的功能是类似的,但cmake --install .更加通用,不依赖于特定的构建系统。

卸载

如果因为反复./configure xx然后make会导致安装路径混乱,sudo make install失败。所以如果路径设错了又已经make完,需要make clean来清除一下。如果想把自己刚刚make install安装的卸载掉,可以在那个目录里直接用sudo make uninstall

1
2
3
4
5
6
7
8
9
10
11
12
13
cd package_name/build

# 卸载使用make install命令安装到系统路径的文件
# `install_manifest.txt`文件里包含了所有安装的文件的路径
cat install_manifest.txt | sudo xargs rm # 或
sudo xargs rm < install_manifest.txt
# 上述命令只会删除掉文件夹里的文件,会留下空文件夹。所以可以继续对照`install_manifest.txt`文件,手动删掉多余的空文件夹。

sudo make uninstall
sudo make clean #清除上一次make命令生成的文件
sudo make distclean #清除上一次make以及configure命令生成的文件
cd ..
sudo rm -r build

make uninstall 是一个常见的 makefile 目标,它的主要作用是删除由 make install 命令安装的文件。

当你运行 make install 命令时,通常会将一些文件(例如可执行文件、库文件、头文件等)复制到系统的某些目录下(例如 /usr/local/bin/usr/local/lib 等)。make uninstall 命令就是用来删除这些文件的。

然而,需要注意的是,并不是所有的 makefile 都提供 make uninstall 目标。如果 makefile 没有提供这个目标,运行 make uninstall 命令将会导致错误。

在运行 make uninstall 命令之前,你应该查看 makefile 或者相关的文档,以确认这个命令是否可用,以及它会删除哪些文件。

cat install_manifest.txt | sudo xargs rmsudo make uninstall 都是用来删除由 make install 命令安装的文件的。然而,它们的工作方式有所不同。

  • cat install_manifest.txt | sudo xargs rm:这个命令会读取 install_manifest.txt 文件,这个文件通常由 make install 命令生成,包含了所有被安装的文件的列表。然后,它会使用 xargs rm 命令删除这些文件。这个命令不依赖于 makefile,只要 install_manifest.txt 文件存在,就可以使用。
  • sudo make uninstall:这个命令会执行 makefile 中的 uninstall 目标。这个目标通常会删除所有被 make install 命令安装的文件。然而,需要注意的是,并不是所有的 makefile 都提供 uninstall 目标。如果 makefile 没有提供这个目标,运行 sudo make uninstall 命令将会导致错误。

总的来说,这两个命令的功能是相似的,但是 cat install_manifest.txt | sudo xargs rm 命令更为直接,不依赖于 makefile。而 sudo make uninstall 命令则需要 makefile 提供 uninstall 目标。

make cleanmake distclean 是两个常见的 makefile 目标,它们的功能取决于 makefile 的编写者如何定义它们。但是,通常它们的功能如下:

  • make clean:这个命令通常用于删除所有由 makefile 生成的文件。这通常包括编译产生的对象文件(.o 或 .obj 文件)和编译器生成的中间文件。但是,它通常不会删除配置文件或者 makefile 文件。
  • make distclean:这个命令通常用于将目录恢复到初始状态。除了删除 make clean 会删除的文件,它还会删除配置文件和 makefile 文件。这个命令通常在你想要重新配置和编译一个项目时使用。

需要注意的是,这两个命令的具体行为取决于 makefile 的编写者。在使用这些命令之前,你应该查看 makefile 或者相关的文档,以了解这些命令的具体行为。


程序编译安装与卸载
http://zeyulong.com/posts/9cf8916b/
作者
龙泽雨
发布于
2025年2月19日
许可协议