C++ “如何修复”;找不到包配置文件…“;CMake中的错误?

C++ “如何修复”;找不到包配置文件…“;CMake中的错误?,c++,linux,makefile,cmake,C++,Linux,Makefile,Cmake,我一直在从事一个使用的项目,一开始,我面临的问题是: 基本上,SDK在其本地目录中生成库,在其Makefile中,它没有install规则。我的意思是我可以运行make,但是在那之后,如果我运行sudomakeinstall,那么它会给出make:**没有规则让目标“安装”。停止。错误 因此,在&answer的帮助下,我能够构建我的本地项目。到目前为止还不错 然而,主要问题是我必须在回购协议的CMakeLists.txt中硬编码RPLidar SDK路径。现在,每当我的团队中的其他人开始处理回

我一直在从事一个使用的项目,一开始,我面临的问题是:

<如何在我的C++项目中链接本地安装的SDK静态库?< /P> 基本上,SDK在其本地目录中生成库,在其
Makefile
中,它没有
install
规则。我的意思是我可以运行
make
,但是在那之后,如果我运行
sudomakeinstall
,那么它会给出
make:**没有规则让目标“安装”。停止。
错误

因此,在&answer的帮助下,我能够构建我的本地项目。到目前为止还不错

然而,主要问题是我必须在回购协议的
CMakeLists.txt
中硬编码RPLidar SDK路径。现在,每当我的团队中的其他人开始处理回购协议(这很明显),他/她就必须首先更新
CMakeLists.txt
。这不是一个好主意/做法

为了解决这个问题,我更新了RPLidar SDK的版本,如下所示:

.
.
.

RPLIDAR_RELEASE_LIB := $(HOME_TREE)/output/Linux/Release/librplidar_sdk.a

install: $(RPLIDAR_RELEASE_LIB)
    install -d $(DESTDIR)/usr/local/lib/rplidar/Release/
    install -m 644 $(RPLIDAR_RELEASE_LIB) $(DESTDIR)/usr/local/lib/rplidar/Release/


RPLIDAR_DEBUG_LIB := $(HOME_TREE)/output/Linux/Debug/librplidar_sdk.a

install: $(RPLIDAR_DEBUG_LIB)
    install -d $(DESTDIR)/usr/local/lib/rplidar/Debug/
    install -m 644 $(RPLIDAR_DEBUG_LIB) $(DESTDIR)/usr/local/lib/rplidar/Debug/


RPLIDAR_HEADERS := $(HOME_TREE)/sdk/include

install: $(RPLIDAR_HEADERS)
    install -d $(DESTDIR)/usr/local/include/rplidar/
    cp -r $(RPLIDAR_HEADERS)/* $(DESTDIR)/usr/local/include/rplidar/

RPLIDAR_HEADERS_HAL := $(HOME_TREE)/sdk/src/hal

install: $(RPLIDAR_HEADERS_HAL)
    install -d $(DESTDIR)/usr/local/include/rplidar/
    cp -r $(RPLIDAR_HEADERS_HAL) $(DESTDIR)/usr/local/include/rplidar/
cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR)

project(<project_name>)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
SET(CMAKE_CXX_FLAGS -pthread)

include_directories(include)
add_executable(${PROJECT_NAME} src/main.cpp src/another_src_file.cpp)

find_package(rplidar REQUIRED)
include_directories(${rplidar_INCLUDE_DIRS})
link_directories(${rplidar_LIBRARY_DIRS})
target_link_libraries(${PROJECT_NAME} ${rplidar_LIBRARY})
由于这次更新,现在我可以运行
sudomakeinstall
,它基本上将rplidarsdk的头文件从本地目录复制到
/usr/local/RPLidar/
目录。它还将lib文件复制到
/usr/local/lib/rplidar/或/
目录

现在,在我的本地项目中,我将
CMakeLists.txt
更新如下:

.
.
.

RPLIDAR_RELEASE_LIB := $(HOME_TREE)/output/Linux/Release/librplidar_sdk.a

install: $(RPLIDAR_RELEASE_LIB)
    install -d $(DESTDIR)/usr/local/lib/rplidar/Release/
    install -m 644 $(RPLIDAR_RELEASE_LIB) $(DESTDIR)/usr/local/lib/rplidar/Release/


RPLIDAR_DEBUG_LIB := $(HOME_TREE)/output/Linux/Debug/librplidar_sdk.a

install: $(RPLIDAR_DEBUG_LIB)
    install -d $(DESTDIR)/usr/local/lib/rplidar/Debug/
    install -m 644 $(RPLIDAR_DEBUG_LIB) $(DESTDIR)/usr/local/lib/rplidar/Debug/


RPLIDAR_HEADERS := $(HOME_TREE)/sdk/include

install: $(RPLIDAR_HEADERS)
    install -d $(DESTDIR)/usr/local/include/rplidar/
    cp -r $(RPLIDAR_HEADERS)/* $(DESTDIR)/usr/local/include/rplidar/

RPLIDAR_HEADERS_HAL := $(HOME_TREE)/sdk/src/hal

install: $(RPLIDAR_HEADERS_HAL)
    install -d $(DESTDIR)/usr/local/include/rplidar/
    cp -r $(RPLIDAR_HEADERS_HAL) $(DESTDIR)/usr/local/include/rplidar/
cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR)

project(<project_name>)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
SET(CMAKE_CXX_FLAGS -pthread)

include_directories(include)
add_executable(${PROJECT_NAME} src/main.cpp src/another_src_file.cpp)

find_package(rplidar REQUIRED)
include_directories(${rplidar_INCLUDE_DIRS})
link_directories(${rplidar_LIBRARY_DIRS})
target_link_libraries(${PROJECT_NAME} ${rplidar_LIBRARY})
据我所知,rplidarsdk没有
rplidarConfig.cmake
RPLidar config.cmake
文件

我怎样才能纠正这个错误?

我的灵魂在咆哮:

当作者无法通过调用
find\u package(foo)
为您提供一个
foo config.cmake
以方便使用时,如果您必须使用任何库
foo
,那么它就很糟糕。当一个相当现代的项目仍然使用手工编写的makefile作为其构建系统时,这绝对是不可容忍的。我自己现在被一个比你更糟糕的SDK所困扰


简短答复:

由于SDK的作者未能提供一个配置文件来支持您的cmake使用,如果您仍然坚持调用库中的
find_package
(您应该这么做!),您需要编写自己的
模块
文件来清理它们的混乱。(是的,你在为图书馆的作者工作)

为了真正实现跨平台使用,您应该编写一个
Findrplidar.cmake
模块文件来查找库

为了编写一个合理的模块文件,您最有可能对头文件使用API
find_path
,对libs使用
find_library
。你应该看看它的文档,试着使用它们,也许可以在谷歌上搜索一些教程

这是我的
Findglog.cmake
版本,供您参考。(glog作者已经更新并支持
Config
模式。不幸的是,Ubuntu build没有使用它,所以我仍然需要编写自己的文件)

您可以这样使用它:

find_package(glog)
target_link_libraries(main PRIVATE glog::glog)
find_package(foo)
target_link_libraries(your_exe ... foo::foo)

长答覆:

开发人员使用cmake的历史绝对是一场噩梦。互联网上充斥着关于如何在项目中不使用cmake的错误实践/示例,包括旧的官方cmake教程(可能仍然存在)。主要是因为没有人真正给出****(如果我可以构建我的项目,谁会在乎它是否是跨平台的)。另一个合理的原因是,cmake文档对于初学者来说确实令人望而生畏

这就是为什么我在这里写我自己的答案,以免你被谷歌的其他地方误导

噩梦不再。等待已经结束。克马克()的“救世主”来了。他给2020年及以后编写的asm/C/C++/CUDA项目带来了希望。这是

上面的链接指向了编写cmake项目并真正实现一次性跨平台的唯一方法。注意,对于初学者来说,这些材料一点也不容易理解。我自己花了整整一周的时间来完全理解这个词所涵盖的内容,当时我对cmake的概念有些熟悉(但迷失在我过去罪恶的方式中)

所谓的“长答案”实际上更短。这只是一个指向真正答案的指针。祝你读单词好运。拥抱这个词,因为任何反对它的东西都是纯粹的异端


对评论1-5的答复: 好问题。其中很多可以从这个词中获得。但是当你更加熟悉CMake时,这个词会被更好地理解。让我以与你手头的问题相关性降低的方式来回答这些问题

为了便于讨论,我将以libfoo为例

假设您总是希望像这样使用libfoo:

find_package(glog)
target_link_libraries(main PRIVATE glog::glog)
find_package(foo)
target_link_libraries(your_exe ... foo::foo)
假装foo安装在以下位置:

- /home/dev/libfoo-dev/
  - include
    - foo
      - foo.h
      - bar.h
      - ...
  - lib
    - libfoo.so
  - share
    - foo/foo-config.cmake   # This may or may not exist. See discussion.

Q:只有一个
.h
文件。为什么?

答:因为在
libfoo
的情况下(对于
glog
),只需要搜索一次标题位置。就像
libfoo
中的示例一样, 其中
foo/foo.h
foo/bar.h
位于同一位置。因此,它们的
find_path
输出将是相同的:
/home/dev/libfoo-dev/include


问:为什么我的头文件和lib会出现
NOTFOUND

答:功能
find_path
find_library
仅在文档中指定搜索位置。默认情况下,它们搜索系统位置, 分别与
/usr/include
/usr/lib
类似。有关系统位置的详细信息,请参阅官方文档。但是,在
libfoo
的情况下, 它们位于
/home/dev/libfoo-dev
中。因此,必须在cmake变量
cmake_PREFIX_PATH
中指定这些位置。这是一个
分隔字符串。
可以在命令行上执行
cmake-dcmake_PREFIX_PATH=“/home/dev/libfoo dev;/more/PATH/for/other/libs/;…;/event/more/PATH”。…

一个非常重要的注意事项:与Unix命令
find
不同,
find\u path
将只搜索特定路径