为什么尽管使用了正确的工具链文件,但在交叉编译Net-SNMP代理时,CMake显然还是引用了主机系统文件? [英] Why is CMake apparently referring to host system files while cross-compiling a Net-SNMP agent despite a proper toolchain file is being used?

查看:153
本文介绍了为什么尽管使用了正确的工具链文件,但在交叉编译Net-SNMP代理时,CMake显然还是引用了主机系统文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发 Net-SNMP 子代理,其最终目标是ARM板,因此我正在使用 CMake 来简化构建本机版本和交叉编译版本的过程.我开始在主机平台(x86_64)上对其进行测试,并且该文件可以与此 CMakeLists.txt 文件一起构建并正常工作:

 cmake_minimum_required (VERSION 2.6)

project (snmp_agent C)

set(snmp_agent_VERSION_MAJOR 1)
set(snmp_agent_VERSION_MINOR 0)

# Defines path to the net-snmp-config script
set(NETSNMPCONFIG "${CMAKE_FIND_ROOT_PATH}/usr/bin/net-snmp-config")

# Gets compiling flags and libs linked to Net-SNMP
execute_process(COMMAND "${NETSNMPCONFIG}" "--base-cflags" OUTPUT_VARIABLE NETSNMPCFLAGS)
execute_process(COMMAND "${NETSNMPCONFIG}" "--agent-libs" OUTPUT_VARIABLE NETSNMPLIBS)

# Removes leading/trailing spaces from net-snmp-config output
string(STRIP ${NETSNMPCFLAGS} NETSNMPCFLAGS)
string(STRIP ${NETSNMPLIBS} NETSNMPLIBS)

# Prints compilation and linker flags used in Net-SNMP package
message("Net-SNMP package CFLAGS: ${NETSNMPCFLAGS}")
message("Net-SNMP package LIBS: ${NETSNMPLIBS}")

# Setting libs and compilation flags variables
set(LIBS "${NETSNMPLIBS}")
set(STRICT_FLAGS "-Wall -Wstrict-prototypes")
set(CFLAGS "-I. ${STRICT_FLAGS} ${NETSNMPCFLAGS}")

# Sets prefix for files created by 'mib2c' for the wanted MIB
set(ENT_PHYSICAL_ENTRY "scalars/entPhysicalEntry")

# Source files created by 'mib2c' and then user customized
set(USER_SRCS
    ${ENT_PHYSICAL_ENTRY}.c
  )

# Setting subagent sources
set(SRCS ${USER_SRCS}
    ${CMAKE_PROJECT_NAME}.c
  )

# Finds the required Net-SNMP lib paths and assigns them to variables
find_library(NETSNMPAGENT "netsnmpagent")
message("Found ${NETSNMPAGENT}")
find_library(NETSNMPMIBS "netsnmpmibs")
message("Found ${NETSNMPMIBS}")
find_library(NETSNMP "netsnmp")
message("Found ${NETSNMP}")

# Sets the flags to be used for compiling and linking the executable
set_source_files_properties(${SRCS} COMPILE_FLAGS ${CFLAGS})
add_executable(${CMAKE_PROJECT_NAME} ${SRCS})
target_link_libraries(${CMAKE_PROJECT_NAME} ${NETSNMPAGENT} ${NETSNMPMIBS} ${NETSNMP})
 

我使用单独的生成目录,因此我不会混合使用生成文件和源文件,这些文件与 CMakeLists.txt 文件一起保留,因此这些命令的输出...

 cd ~/git/snmp_agent # CMakeLists.txt is in here along with source files
mkdir build
cd build
cmake ..
 

...如下:

 claudio@slackdev:~/git/snmp_agent/build$ cmake ..
-- The C compiler identification is GNU 5.3.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
Net-SNMP package CFLAGS: -DNETSNMP_ENABLE_IPV6 -fno-strict-aliasing -O2 -fPIC -Ulinux -Dlinux=linux -D_REENTRANT -D_GNU_SOURCE -fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2 -I/usr/lib64/perl5/CORE -I/usr/include/libnl3 -I/usr/include
Net-SNMP package LIBS: -L/usr/lib64 -lnetsnmpmibs -lsensors -lpci -ldl -lnetsnmpagent -lwrap -lnsl -Wl,-E -Wl,-rpath,/usr/lib64/perl5/CORE -lnetsnmp -lcrypto -lnl-3 -lm
Found /usr/lib64/libnetsnmpagent.so
Found /usr/lib64/libnetsnmpmibs.so
Found /usr/lib64/libnetsnmp.so
-- Configuring done
-- Generating done
-- Build files have been written to: /home/claudio/git/snmp_agent/build
 

运行make,它可以很好地构建:

 claudio@slackdev:~/git/snmp_agent/build$ make
Scanning dependencies of target snmp_agent
[ 25%] Building C object CMakeFiles/snmp_agent.dir/scalars/entPhysicalEntry.c.o
[ 50%] Building C object CMakeFiles/snmp_agent.dir/snmp_agent.c.o
[100%] Linking C executable snmp_agent
[100%] Built target snmp_agent
 

snmp_agent作为agentX子代理运行,连接到主snmpd主代理,并正确响应entPhysicalEntry标量对象的SNMP请求.

好的,到目前为止很好.问题是,当我尝试对其进行交叉编译时,它会对最终目标ARMv7 Allwinner A20开发板执行相同的操作.我已经有了一个跨工具链,它是使用 Crosstool-NG 创建的.它位于搜索路径中,其工具以前缀armv7-a20_allwinner-linux-gnueabihf开头.为了使用它,我设置了以下工具链文件,其名为armv7-a20_allwinner-linux-gnueabihf.cmake :

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

# which C and C++ compiler to use
SET(CMAKE_C_COMPILER   armv7-a20_allwinner-linux-gnueabihf-gcc)
SET(CMAKE_CXX_COMPILER armv7-a20_allwinner-linux-gnueabihf-g++) 

# here is the target environment located
SET(CMAKE_FIND_ROOT_PATH  "$ENV{HOME}/arm_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 ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
 

对于ARM版本,使用不同的构建目录,CMake应该选择指向ARM根文件系统的正确路径,该路径是目标板SD卡上内容的副本:

 cd ~/git/snmp_agent # CMakeLists.txt and armv7-a20_allwinner-linux-gnueabihf.cmake are here
mkdir build-arm
cd build-arm
cmake -DCMAKE_TOOLCHAIN_FILE=../armv7-a20_allwinner-linux-gnueabihf.cmake ..
 

请注意,显然CMake运行良好,因为找到的路径都相对于ARM根文件系统:

 claudio@slackdev:~/git/snmp_agent/build-arm$ cmake -DCMAKE_TOOLCHAIN_FILE=../cmake_defs/armv7-a20_allwinner-linux-gnueabihf.cmake ..
-- The C compiler identification is GNU 6.3.0
-- Check for working C compiler: /home/claudio/x-tools/armv7-a20_allwinner-linux-gnueabihf/bin/armv7-a20_allwinner-linux-gnueabihf-gcc
-- Check for working C compiler: /home/claudio/x-tools/armv7-a20_allwinner-linux-gnueabihf/bin/armv7-a20_allwinner-linux-gnueabihf-gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
Net-SNMP package CFLAGS: -DNETSNMP_ENABLE_IPV6 -fno-strict-aliasing -O2 -march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=hard -Ulinux -Dlinux=linux -D_REENTRANT -D_GNU_SOURCE -fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2 -I/usr/lib/perl5/CORE -I/usr/include/libnl3 -I/usr/include
Net-SNMP package LIBS: -L/usr/lib -lnetsnmpmibs -lsensors -lpci -ldl -lnetsnmpagent -lwrap -lnsl -Wl,-E -Wl,-rpath,/usr/lib/perl5/CORE -lnetsnmp -lcrypto -lnl-3 -lm
Found /home/claudio/arm_rootfs/usr/lib/libnetsnmpagent.so
Found /home/claudio/arm_rootfs/usr/lib/libnetsnmpmibs.so
Found /home/claudio/arm_rootfs/usr/lib/libnetsnmp.so
-- Configuring done
-- Generating done
-- Build files have been written to: /home/claudio/git/snmp_agent/build-arm
 

但是在运行make时,它在寻找/usr/include/gnu/stubs.h时会分崩离析.如果我们尝试用VERBOSE=1重复make,我们可以看到gcc调用正在使用相对于主机的路径:

 claudio@slackdev:~/git/snmp_agent/build-arm$ make VERBOSE=1
/usr/bin/cmake -H/home/claudio/git/snmp_agent -B/home/claudio/git/snmp_agent/build-arm --check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake -E cmake_progress_start /home/claudio/git/snmp_agent/build-arm/CMakeFiles /home/claudio/git/snmp_agent/build-arm/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory 'snmp_agent/build-arm'
make -f CMakeFiles/snmp_agent.dir/build.make CMakeFiles/snmp_agent.dir/depend
make[2]: Entering directory 'snmp_agent/build-arm'
cd /home/claudio/git/snmp_agent/build-arm && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/claudio/git/snmp_agent /home/claudio/git/snmp_agent /home/claudio/git/snmp_agent/build-arm /home/claudio/git/snmp_agent/build-arm /home/claudio/git/snmp_agent/build-arm/CMakeFiles/snmp_agent.dir/DependInfo.cmake --color=
make[2]: Leaving directory 'snmp_agent/build-arm'
make -f CMakeFiles/snmp_agent.dir/build.make CMakeFiles/snmp_agent.dir/build
make[2]: Entering directory 'snmp_agent/build-arm'
[ 25%] Building C object CMakeFiles/snmp_agent.dir/scalars/entPhysicalEntry.c.o
/home/claudio/x-tools/armv7-a20_allwinner-linux-gnueabihf/bin/armv7-a20_allwinner-linux-gnueabihf-gcc     -I. -Wall -Wstrict-prototypes -DNETSNMP_ENABLE_IPV6 -fno-strict-aliasing -O2 -march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=hard -Ulinux -Dlinux=linux -D_REENTRANT -D_GNU_SOURCE -fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2 -I/usr/lib/perl5/CORE -I/usr/include/libnl3 -I/usr/include -o CMakeFiles/snmp_agent.dir/scalars/entPhysicalEntry.c.o   -c /home/claudio/git/snmp_agent/scalars/entPhysicalEntry.c
In file included from /usr/include/features.h:392:0,
                 from /usr/include/stdio.h:27,
                 from /usr/include/net-snmp/net-snmp-includes.h:14,
                 from /home/claudio/git/snmp_agent/scalars/entPhysicalEntry.c:7:
/usr/include/gnu/stubs.h:7:27: fatal error: gnu/stubs-32.h: No such file or directory
 # include <gnu/stubs-32.h>
                           ^
compilation terminated.
CMakeFiles/snmp_agent.dir/build.make:62: recipe for target 'CMakeFiles/snmp_agent.dir/scalars/entPhysicalEntry.c.o' failed
make[2]: *** [CMakeFiles/snmp_agent.dir/scalars/entPhysicalEntry.c.o] Error 1
make[2]: Leaving directory 'snmp_agent/build-arm'
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/snmp_agent.dir/all' failed
make[1]: *** [CMakeFiles/snmp_agent.dir/all] Error 2
make[1]: Leaving directory 'snmp_agent/build-arm'
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
 

奇怪的是,ARM根文件系统中的/usr/include/gnu/stubs.hstubs-32.h无关:

 /* This file is automatically generated.
   This file selects the right generated file of `__stub_FUNCTION' macros
   based on the architecture being compiled for.  */


#if !defined __ARM_PCS_VFP
# include <gnu/stubs-soft.h>
#endif
#if defined __ARM_PCS_VFP
# include <gnu/stubs-hard.h>
#endif
 

但是,如果您从主机系统(这是一台x86_64机器)上查看相同的文件,我们可以猜测为什么它试图找到stubs-32.h(记住我们试图为ARM编译,所以找不到) __x86_64__符号定义):

 /* This file is automatically generated.
   This file selects the right generated file of `__stub_FUNCTION' macros
   based on the architecture being compiled for.  */


#if !defined __x86_64__
# include <gnu/stubs-32.h>
#endif
#if defined __x86_64__ && defined __LP64__
# include <gnu/stubs-64.h>
#endif
#if defined __x86_64__ && defined __ILP32__
# include <gnu/stubs-x32.h>
#endif
 

为什么会这样,因为工具链文件明确指定仅在CMAKE_FIND_ROOT_PATH设置的路径中搜索库和包含项?

更新(问题尚未完全解决!):

我接受了@Tsyvarev的回答后,我仔细检查了我的 CMakeLists.txt 文件,发现在试图使其工作时,我通过手动将CMAKE_FIND_ROOT_PATH设置为每个文件的前缀而遭到黑客入侵编译器包含 net-snmp-config 返回的开关(-I),这显然不是理想的选择.这样,它与CMAKE_SYSROOT一起工作,但是仅CMAKE_SYSROOT本身并不能为包含路径加上前缀:

 # This is the manually hacked line:
set(NETSNMPCFLAGS "-DNETSNMP_ENABLE_IPV6 -fno-strict-aliasing -O2 -march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=hard -Ulinux -Dlinux=linux -D_REENTRANT -D_GNU_SOURCE -fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I${CMAKE_FIND_ROOT_PATH}/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2 -I${CMAKE_FIND_ROOT_PATH}/usr/lib/perl5/CORE -I${CMAKE_FIND_ROOT_PATH}/usr/include/libnl3 -I${CMAKE_FIND_ROOT_PATH}/usr/include")

set(LIBS "${NETSNMPLIBS}")

set(STRICT_FLAGS "-Wall -Wstrict-prototypes")
set(CFLAGS "-I. ${STRICT_FLAGS} ${NETSNMPCFLAGS}")
 

解决方案

最终解决方案:

就像对问题 UPDATE 的解释一样,@ Tsyvarev的答案通过提供指向编译器的--sysroot开关来指向ARM的根文件系统,从而解决了链接部分的问题,但是找到了从主机系统不被固定.尽管这是解决方案的一部分,但重要的是要注意到主要的观察结果还有另一个原因:include -I开关被直接用作编译器的CFLAGS,从而使其可以有效地查看主机系统,因为它们位于不能以ARM板的根文件系统路径为前缀(请记住标志是由 net-snmp-config 脚本直接输出的,该脚本正在报告 native ARM构建的标志,因此改为使用常规"路径).为了解决这个问题,我使用了CMake字符串命令从NETSNMPCFLAGS变量中删除了所有-I开关:

 # Gets compiling flags and libs linked to Net-SNMP
execute_process(COMMAND "${NETSNMPCONFIG}" "--base-cflags" OUTPUT_VARIABLE NETSNMPCFLAGS)
execute_process(COMMAND "${NETSNMPCONFIG}" "--agent-libs" OUTPUT_VARIABLE NETSNMPLIBS)
# removes the include dir switches "-I" from the NETSNMPCFLAGS, since we don't want
# the compiler to include paths relative to the host system in the compilation
string(REGEX REPLACE "-I[a-zA-Z0-9/]*" "" NETSNMPCFLAGS ${NETSNMPCFLAGS})

set(STRICT_FLAGS "-Wall -Wstrict-prototypes")
set(CFLAGS "-I. ${STRICT_FLAGS} ${NETSNMPCFLAGS}")
 

并将根文件系统放在 include_directories 指令中:

 # Sets the flags to be used for compiling and linking the executable
set_source_files_properties(${SRCS} COMPILE_FLAGS ${CFLAGS})
include_directories(${CMAKE_FIND_ROOT_PATH}/usr/include)
add_executable(${CMAKE_PROJECT_NAME} ${SRCS})
target_link_libraries(${CMAKE_PROJECT_NAME} ${NETSNMPAGENT} ${NETSNMPMIBS} ${NETSNMP})
 

I am developing a Net-SNMP subagent whose final target will be an ARM board, so I'm using CMake to make it easier to manage building the native and cross-compiled versions. I started testing it on my host platform (x86_64) and it builds and works fine with this CMakeLists.txt file:

cmake_minimum_required (VERSION 2.6)

project (snmp_agent C)

set(snmp_agent_VERSION_MAJOR 1)
set(snmp_agent_VERSION_MINOR 0)

# Defines path to the net-snmp-config script
set(NETSNMPCONFIG "${CMAKE_FIND_ROOT_PATH}/usr/bin/net-snmp-config")

# Gets compiling flags and libs linked to Net-SNMP
execute_process(COMMAND "${NETSNMPCONFIG}" "--base-cflags" OUTPUT_VARIABLE NETSNMPCFLAGS)
execute_process(COMMAND "${NETSNMPCONFIG}" "--agent-libs" OUTPUT_VARIABLE NETSNMPLIBS)

# Removes leading/trailing spaces from net-snmp-config output
string(STRIP ${NETSNMPCFLAGS} NETSNMPCFLAGS)
string(STRIP ${NETSNMPLIBS} NETSNMPLIBS)

# Prints compilation and linker flags used in Net-SNMP package
message("Net-SNMP package CFLAGS: ${NETSNMPCFLAGS}")
message("Net-SNMP package LIBS: ${NETSNMPLIBS}")

# Setting libs and compilation flags variables
set(LIBS "${NETSNMPLIBS}")
set(STRICT_FLAGS "-Wall -Wstrict-prototypes")
set(CFLAGS "-I. ${STRICT_FLAGS} ${NETSNMPCFLAGS}")

# Sets prefix for files created by 'mib2c' for the wanted MIB
set(ENT_PHYSICAL_ENTRY "scalars/entPhysicalEntry")

# Source files created by 'mib2c' and then user customized
set(USER_SRCS
    ${ENT_PHYSICAL_ENTRY}.c
  )

# Setting subagent sources
set(SRCS ${USER_SRCS}
    ${CMAKE_PROJECT_NAME}.c
  )

# Finds the required Net-SNMP lib paths and assigns them to variables
find_library(NETSNMPAGENT "netsnmpagent")
message("Found ${NETSNMPAGENT}")
find_library(NETSNMPMIBS "netsnmpmibs")
message("Found ${NETSNMPMIBS}")
find_library(NETSNMP "netsnmp")
message("Found ${NETSNMP}")

# Sets the flags to be used for compiling and linking the executable
set_source_files_properties(${SRCS} COMPILE_FLAGS ${CFLAGS})
add_executable(${CMAKE_PROJECT_NAME} ${SRCS})
target_link_libraries(${CMAKE_PROJECT_NAME} ${NETSNMPAGENT} ${NETSNMPMIBS} ${NETSNMP})

I use a separate build dir so I don't mix build and source files, which stay along with the CMakeLists.txt file, so the the output of these commands...

cd ~/git/snmp_agent # CMakeLists.txt is in here along with source files
mkdir build
cd build
cmake ..

...is as follows:

claudio@slackdev:~/git/snmp_agent/build$ cmake ..
-- The C compiler identification is GNU 5.3.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
Net-SNMP package CFLAGS: -DNETSNMP_ENABLE_IPV6 -fno-strict-aliasing -O2 -fPIC -Ulinux -Dlinux=linux -D_REENTRANT -D_GNU_SOURCE -fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2 -I/usr/lib64/perl5/CORE -I/usr/include/libnl3 -I/usr/include
Net-SNMP package LIBS: -L/usr/lib64 -lnetsnmpmibs -lsensors -lpci -ldl -lnetsnmpagent -lwrap -lnsl -Wl,-E -Wl,-rpath,/usr/lib64/perl5/CORE -lnetsnmp -lcrypto -lnl-3 -lm
Found /usr/lib64/libnetsnmpagent.so
Found /usr/lib64/libnetsnmpmibs.so
Found /usr/lib64/libnetsnmp.so
-- Configuring done
-- Generating done
-- Build files have been written to: /home/claudio/git/snmp_agent/build

Running make, it builds just fine:

claudio@slackdev:~/git/snmp_agent/build$ make
Scanning dependencies of target snmp_agent
[ 25%] Building C object CMakeFiles/snmp_agent.dir/scalars/entPhysicalEntry.c.o
[ 50%] Building C object CMakeFiles/snmp_agent.dir/snmp_agent.c.o
[100%] Linking C executable snmp_agent
[100%] Built target snmp_agent

This snmp_agent runs as an agentX subagent, connecting to the main snmpd master agent and properly answering SNMP requests against entPhysicalEntry scalar objects.

Ok, so far so good. The problem is when I try to cross-compile this so it does the same thing on my final target, which is an ARMv7 Allwinner A20 board. I already have a cross-toolchain available for it - which I created using Crosstool-NG. It is in the search PATH and its tools begin with the prefix armv7-a20_allwinner-linux-gnueabihf. In order to use it, I set up the following toolchain file, which was named armv7-a20_allwinner-linux-gnueabihf.cmake:

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

# which C and C++ compiler to use
SET(CMAKE_C_COMPILER   armv7-a20_allwinner-linux-gnueabihf-gcc)
SET(CMAKE_CXX_COMPILER armv7-a20_allwinner-linux-gnueabihf-g++) 

# here is the target environment located
SET(CMAKE_FIND_ROOT_PATH  "$ENV{HOME}/arm_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 ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

Using a different build dir for the ARM version, CMake should pick up the right paths pointing to the ARM root filesystem, which is a copy of what will be on the target board's SDcard:

cd ~/git/snmp_agent # CMakeLists.txt and armv7-a20_allwinner-linux-gnueabihf.cmake are here
mkdir build-arm
cd build-arm
cmake -DCMAKE_TOOLCHAIN_FILE=../armv7-a20_allwinner-linux-gnueabihf.cmake ..

Note that apparently CMake runs fine, as the paths found are all relative to the ARM root filesystem:

claudio@slackdev:~/git/snmp_agent/build-arm$ cmake -DCMAKE_TOOLCHAIN_FILE=../cmake_defs/armv7-a20_allwinner-linux-gnueabihf.cmake ..
-- The C compiler identification is GNU 6.3.0
-- Check for working C compiler: /home/claudio/x-tools/armv7-a20_allwinner-linux-gnueabihf/bin/armv7-a20_allwinner-linux-gnueabihf-gcc
-- Check for working C compiler: /home/claudio/x-tools/armv7-a20_allwinner-linux-gnueabihf/bin/armv7-a20_allwinner-linux-gnueabihf-gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
Net-SNMP package CFLAGS: -DNETSNMP_ENABLE_IPV6 -fno-strict-aliasing -O2 -march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=hard -Ulinux -Dlinux=linux -D_REENTRANT -D_GNU_SOURCE -fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2 -I/usr/lib/perl5/CORE -I/usr/include/libnl3 -I/usr/include
Net-SNMP package LIBS: -L/usr/lib -lnetsnmpmibs -lsensors -lpci -ldl -lnetsnmpagent -lwrap -lnsl -Wl,-E -Wl,-rpath,/usr/lib/perl5/CORE -lnetsnmp -lcrypto -lnl-3 -lm
Found /home/claudio/arm_rootfs/usr/lib/libnetsnmpagent.so
Found /home/claudio/arm_rootfs/usr/lib/libnetsnmpmibs.so
Found /home/claudio/arm_rootfs/usr/lib/libnetsnmp.so
-- Configuring done
-- Generating done
-- Build files have been written to: /home/claudio/git/snmp_agent/build-arm

But when running make it falls apart while looking for /usr/include/gnu/stubs.h. If we try to repeat make with VERBOSE=1, we can see the gcc invocation is using paths relative to the host machine:

claudio@slackdev:~/git/snmp_agent/build-arm$ make VERBOSE=1
/usr/bin/cmake -H/home/claudio/git/snmp_agent -B/home/claudio/git/snmp_agent/build-arm --check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake -E cmake_progress_start /home/claudio/git/snmp_agent/build-arm/CMakeFiles /home/claudio/git/snmp_agent/build-arm/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory 'snmp_agent/build-arm'
make -f CMakeFiles/snmp_agent.dir/build.make CMakeFiles/snmp_agent.dir/depend
make[2]: Entering directory 'snmp_agent/build-arm'
cd /home/claudio/git/snmp_agent/build-arm && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/claudio/git/snmp_agent /home/claudio/git/snmp_agent /home/claudio/git/snmp_agent/build-arm /home/claudio/git/snmp_agent/build-arm /home/claudio/git/snmp_agent/build-arm/CMakeFiles/snmp_agent.dir/DependInfo.cmake --color=
make[2]: Leaving directory 'snmp_agent/build-arm'
make -f CMakeFiles/snmp_agent.dir/build.make CMakeFiles/snmp_agent.dir/build
make[2]: Entering directory 'snmp_agent/build-arm'
[ 25%] Building C object CMakeFiles/snmp_agent.dir/scalars/entPhysicalEntry.c.o
/home/claudio/x-tools/armv7-a20_allwinner-linux-gnueabihf/bin/armv7-a20_allwinner-linux-gnueabihf-gcc     -I. -Wall -Wstrict-prototypes -DNETSNMP_ENABLE_IPV6 -fno-strict-aliasing -O2 -march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=hard -Ulinux -Dlinux=linux -D_REENTRANT -D_GNU_SOURCE -fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2 -I/usr/lib/perl5/CORE -I/usr/include/libnl3 -I/usr/include -o CMakeFiles/snmp_agent.dir/scalars/entPhysicalEntry.c.o   -c /home/claudio/git/snmp_agent/scalars/entPhysicalEntry.c
In file included from /usr/include/features.h:392:0,
                 from /usr/include/stdio.h:27,
                 from /usr/include/net-snmp/net-snmp-includes.h:14,
                 from /home/claudio/git/snmp_agent/scalars/entPhysicalEntry.c:7:
/usr/include/gnu/stubs.h:7:27: fatal error: gnu/stubs-32.h: No such file or directory
 # include <gnu/stubs-32.h>
                           ^
compilation terminated.
CMakeFiles/snmp_agent.dir/build.make:62: recipe for target 'CMakeFiles/snmp_agent.dir/scalars/entPhysicalEntry.c.o' failed
make[2]: *** [CMakeFiles/snmp_agent.dir/scalars/entPhysicalEntry.c.o] Error 1
make[2]: Leaving directory 'snmp_agent/build-arm'
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/snmp_agent.dir/all' failed
make[1]: *** [CMakeFiles/snmp_agent.dir/all] Error 2
make[1]: Leaving directory 'snmp_agent/build-arm'
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2

The strange thing here is the /usr/include/gnu/stubs.h from the ARM root filesystem has nothing to do with stubs-32.h:

/* This file is automatically generated.
   This file selects the right generated file of `__stub_FUNCTION' macros
   based on the architecture being compiled for.  */


#if !defined __ARM_PCS_VFP
# include <gnu/stubs-soft.h>
#endif
#if defined __ARM_PCS_VFP
# include <gnu/stubs-hard.h>
#endif

But if you look at the same file from the host system - which is a x86_64 machine - we can guess why it tried to find stubs-32.h (remember we are trying to compile for ARM, so it won't find the __x86_64__ symbol definition):

/* This file is automatically generated.
   This file selects the right generated file of `__stub_FUNCTION' macros
   based on the architecture being compiled for.  */


#if !defined __x86_64__
# include <gnu/stubs-32.h>
#endif
#if defined __x86_64__ && defined __LP64__
# include <gnu/stubs-64.h>
#endif
#if defined __x86_64__ && defined __ILP32__
# include <gnu/stubs-x32.h>
#endif

Why is that happening, since the toolchain file clearly specifies that libraries and includes are to be searched ONLY in the path set by CMAKE_FIND_ROOT_PATH?

UPDATE (problem not totally solved yet!):

After I had accepted the answer from @Tsyvarev I was double checking my CMakeLists.txt file and I found while trying to make it work I had made a hack by manually setting CMAKE_FIND_ROOT_PATH as prefix of each compiler include switches (-I) returned by net-snmp-config, which obviously is not the ideal thing to do. That, along with CMAKE_SYSROOT, makes it work, but CMAKE_SYSROOT alone doesn't prefix the include paths by itself:

# This is the manually hacked line:
set(NETSNMPCFLAGS "-DNETSNMP_ENABLE_IPV6 -fno-strict-aliasing -O2 -march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=hard -Ulinux -Dlinux=linux -D_REENTRANT -D_GNU_SOURCE -fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I${CMAKE_FIND_ROOT_PATH}/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2 -I${CMAKE_FIND_ROOT_PATH}/usr/lib/perl5/CORE -I${CMAKE_FIND_ROOT_PATH}/usr/include/libnl3 -I${CMAKE_FIND_ROOT_PATH}/usr/include")

set(LIBS "${NETSNMPLIBS}")

set(STRICT_FLAGS "-Wall -Wstrict-prototypes")
set(CFLAGS "-I. ${STRICT_FLAGS} ${NETSNMPCFLAGS}")

解决方案

FINAL SOLUTION:

Like explained on the question UPDATE, @Tsyvarev's answer fixed the linking part by providing the --sysroot switch to the compiler pointing to the root filesystem for ARM, but the problem of finding a stubs-32.h from the host system isn't fixed by that. Although it was part of the solution, it is important to note the primary observation had another cause: the include -I switches were being used directly as CFLAGS to the compiler, making it effectively look at the host system, since they where not prefixed with the root filesystem path for the ARM board (remember the flags were output directly by the net-snmp-config script, which was reporting flags for the native ARM build, so with "normal" paths instead). To fix that I used a CMake string command to remove all the -I switches from the NETSNMPCFLAGS variable:

# Gets compiling flags and libs linked to Net-SNMP
execute_process(COMMAND "${NETSNMPCONFIG}" "--base-cflags" OUTPUT_VARIABLE NETSNMPCFLAGS)
execute_process(COMMAND "${NETSNMPCONFIG}" "--agent-libs" OUTPUT_VARIABLE NETSNMPLIBS)
# removes the include dir switches "-I" from the NETSNMPCFLAGS, since we don't want
# the compiler to include paths relative to the host system in the compilation
string(REGEX REPLACE "-I[a-zA-Z0-9/]*" "" NETSNMPCFLAGS ${NETSNMPCFLAGS})

set(STRICT_FLAGS "-Wall -Wstrict-prototypes")
set(CFLAGS "-I. ${STRICT_FLAGS} ${NETSNMPCFLAGS}")

and put the root filesystem in an include_directories directive:

# Sets the flags to be used for compiling and linking the executable
set_source_files_properties(${SRCS} COMPILE_FLAGS ${CFLAGS})
include_directories(${CMAKE_FIND_ROOT_PATH}/usr/include)
add_executable(${CMAKE_PROJECT_NAME} ${SRCS})
target_link_libraries(${CMAKE_PROJECT_NAME} ${NETSNMPAGENT} ${NETSNMPMIBS} ${NETSNMP})

这篇关于为什么尽管使用了正确的工具链文件,但在交叉编译Net-SNMP代理时,CMake显然还是引用了主机系统文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆