CMAKE交叉编译库未找到。

9

我在我的cmake交叉编译项目中遇到了奇怪的问题。

我的自己的库能被找到,但是我的工具链(系统)库找不到。

之前我在Debian Squeeze机器上使用KDevelop。现在我在新的Debian Wheezy机器上配置失败了。它找不到像mpthread这样的系统库。

在我的旧机器上,以下内容完美地运行,但我不记得我有做过什么特别的事情来使其工作。

以下是我的一个CMakeLists.txt文件之一

cmake_minimum_required(VERSION 2.8)
SET(CMAKE_SYSTEM_NAME Linux)
SET(CMAKE_SYSTEM_VERSION 2.6.36.4)
SET(CMAKE_C_COMPILER arm-angstrom-linux-gnueabi-gcc)
SET(CMAKE_CXX_COMPILER arm-angstrom-linux-gnueabi-g++)
include_directories(../include
  ../../../sample/include)

project(testmain)

add_executable(testmain
   some_c-source-file.c)

set(CMAKE_LIBRARY_PATH ../lib/arm-26/lib
  ../../../sample/lib/arm-26/lib)
find_library(LIBS_TEST NAMES akku)
find_library(LIBS_M NAMES m)
find_library(LIBS_PTHREAD NAMES pthread )
target_link_libraries(akkumain
  ${LIBS_TEST}
  ${LIBS_M}
  ${LIBS_PTHREAD})

set(CMAKE_C_FLAGS "-Wall -Werror")
set(CMAKE_C_FLAGS_DEBUG "-g3 -O2 -rdynamic")
set(CMAKE_C_FLAGS_RELEASE "-g0 -O0")
set(CMAKE_CXX_FLAGS "-Wall -Werror")
set(CMAKE_CXX_FLAGS_DEBUG "-g3 -O2 -rdynamic")
set(CMAKE_CXX_FLAGS_RELEASE "-g0 -O0")

这是在使用KDevelop编译时显示的消息:(重申一下:这在我的旧机器上可以工作)
/home/user/testmain/build> /usr/bin/cmake -DCMAKE_BUILD_TYPE=Debug /home/user/testmain/
-- The C compiler identification is GNU 4.3.3
-- The CXX compiler identification is GNU 4.3.3
-- Check for working C compiler: /usr/local/angstrom/arm/bin/arm-angstrom-linux-gnueabi-gcc
-- Check for working C compiler: /usr/local/angstrom/arm/bin/arm-angstrom-linux-gnueabi-gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/local/angstrom/arm/bin/arm-angstrom-linux-gnueabi-g++
-- Check for working CXX compiler: /usr/local/angstrom/arm/bin/arm-angstrom-linux-gnueabi-g++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done

CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
LIBS_M
    linked by target "akkumain" in directory /home/user/testmain
LIBS_PTHREAD
    linked by target "akkumain" in directory /home/user/testmain

我已经发现了LIBS_TEST。但是没有找到libmlibpthread

我尝试过不同的项目:所有我的库都被找到了,但是没有找到“系统”库。

我已经尝试了不同的方法,比如

set(CMAKE_FIND_LIBRARY_PREFIXES lib )
set(CMAKE_FIND_LIBRARY_SUFFIXES .a )

还有一些我不记得的东西。

唯一有效的方法是手动指定目录:

find_library(ASTLIBS_M NAMES m PATHS /usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr/lib)

在我的CMakeLists.txt中指定后,库被找到了,并且我可以编译我的项目而没有任何错误。
但是:这不是我想要的,因为我有很多项目和许多库,我不想编辑所有的CMakeLists.txt... :(
有人知道是什么让我的旧机器在IDE/CMake文件中没有特别指定时找到了系统库吗?
编辑: 我刚刚注意到,对于我的一个可执行文件,在链接器阶段会抛出一些找不到glibc符号的错误 - 似乎我的debian wheezy系统还有其他问题。-我希望我能解决它...
编辑:
也许我应该简单总结一下:我的代码编译得很好,但是我的工具链中的所有库都找不到,但是如果我手动添加工具链库的路径,则编译通过,但在链接器阶段失败。

仍然没有解决我的问题。从工具链中链接库根本不可能。它们被设置为NOTFOUND。我一点头绪都没有.. :( - Meister Schnitzel
2个回答

21

你有没有尝试过使用工具链文件?我也经常进行ARM和AVR的交叉编译,并且使用起来非常顺利(我也使用KDevelop,它与CMake一起运行得非常好)。重点是通过CMAKE_FIND_ROOT_PATH变量指定工具链根文件系统的路径。尝试把所有这些放在一个文件中,我通常将其命名为我要交叉编译的架构名称(在本例中,我将其命名为arm-unknown-linux-gnueabi.cmake):

# the name of the target operating system
SET(CMAKE_SYSTEM_NAME Linux)

# which C and C++ compiler to use
SET(CMAKE_C_COMPILER   arm-unknown-linux-gnueabi-gcc)
SET(CMAKE_CXX_COMPILER arm-unknown-linux-gnueabi-g++) 

# here is the target environment located
SET(CMAKE_FIND_ROOT_PATH  /home/claudio/TS-7400/rootfs) 

# adjust the default behaviour of the FIND_XXX() commands:
# search headers and libraries in the target environment, search 
# programs in the host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)

请注意变量CMAKE_FIND_ROOT_PATH_MODE_xxx可以控制CMake在哪里查找二进制文件、库和头文件。我通常将PROGRAM设置为NEVER,这样它就不会使用来自跨架构根文件系统的二进制文件,因为它们无论如何都无法在主机上运行。对于库和头文件,BOTH表示它首先会搜索指定的ROOT_PATH,如果没有找到,它会继续搜索主机机器系统目录。

这样,每当您想要交叉编译项目时,您只需要创建一个构建目录(以便它不混合您的源代码和构建期间创建的文件),然后从那里运行cmake并指定您想要使用的工具链文件(假设您的CMakeLists.txt与工具链文件一起位于与源代码相同的目录中- 在我的示例中是project_sources_dir):

cd project_sources_dir
mkdir build
cd build
cmake -DCMAKE_TOOLCHAIN_FILE=../arm-unknown-linux-gnueabi.cmake ..

使用工具链文件的意义在于,如果你想要为你的主机编译完全相同的项目,你不需要在你的CMakeLists.txt中改变任何一行代码。只需运行cmake而不指定工具链文件:

cd project_sources_dir
mkdir build
cd build
cmake ..

现在您的项目已经准备好为本地主机机器编译而不是交叉编译。如果这些还不够,您可以在CMake Cross Compiling上查找更多细节。


如果您想将这些库安装到不同的目录(默认为“/usr/local/”,但您想要“/opt/cross/”),该怎么办呢?而且,您的交叉编译器也与“/usr/”不在同一个目录下。 - S.R
好的,我找到了解决方案: 在 arm-unknown-linux-gnueabi.cmake 中添加以下代码: SET(CMAKE_PREFIX_PATH /opt/cross/arm-unknown-linux-gnueabi) - S.R

2

CMake的find_library模块会在某些默认路径中搜索。如果你的旧机器上的系统库恰好位于这样的地方,它们将被找到而无需进行任何额外的工作。

然而,由于您新机器上这些库的路径似乎是“/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr/lib”,因此您需要告诉CMake这一点。

其中一种方法是像您展示的那样(显式添加路径)。但在这种情况下,该路径可能仅适用于该特定机器 - 因此最好只在调用该机器上的CMake时设置该路径。例如,您可以将其添加到CMAKE_PREFIX_PATH中:

cmake . -DCMAKE_PREFIX_PATH=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr

(注意:在这种情况下,当调用find_library时,路径会添加“lib”)。
或者,如果您只想影响find_library搜索路径,而不是所有find_xxx模块,请设置CMAKE_LIBRARY_PATH
cmake . -DCMAKE_LIBRARY_PATH=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr/lib

谢谢,这是一个好提示。但是如何将附加参数传递给KDevelop的构建命令? - Meister Schnitzel
我不了解kdevelop,但我想每个项目都有一个“配置”选项。它会在其中调用CMake,并且您应该能够在那里传递其他参数给CMake。 - Fraser
迟做总比不做好:最终在CMakeliste.txt中使用set(CMAKE_PREFIX_PATH ...)解决了问题。 - Meister Schnitzel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接