如何在Windows上与cmake + arm-none-eabi交叉编译?

我喜欢在Windows生成服务器上自动交叉编译多个项目。 我用arm交叉编译器有一些问题。 设置它似乎有点困难。 cmake编译器检查失败,出现链接错误(见下文)。

我的实验项目如下所示:

main.cpp - a test programm CMakeLists.txt - the cmake build script cmake/STM32F2xx.cmake - the special settings for the ARM STM32F2xx-series 

我正在使用3个软件包:

 cmake-3.8.0-win64-x64.msi -cmake for windows mingw-w64-install.exe - mingw 64 for windows gcc-arm-none-eabi-6-2017-q1-update-win32.exe - arm x compiler 

main.cpp包含:

 int main(void) { return 0; } 

CMakeLists.txt包含:

 cmake_minimum_required (VERSION 3.0) # module name set(PrjName testPrj) project (${PrjName}) # module version set(PCK_MAJOR 1) set(PCK_MINOR 0) set(PCK_REVISION 0) ##################### # Features switches ##################### ##################### # architecture ##################### # possible values: # NATIVE # STM32F2xx SET(Arch NATIVE CACHE STRING "Architecture") ############################# # software stack search path ############################ SET(SWstackPath NONE CACHE STRING "software stack search path") ############################# # software stack handling ############################ if (${SWstackPath} STREQUAL NONE) else () include_directories(${SWstackPath}) endif() ############################# # package creation ############################# SET(PackageFormat "DEFAULT" CACHE STRING "the format of the installation package") ######################## # define module content ######################## # MetaData header set(testApp "testApp") set(${testApp}_VERSION_MAJOR 1) set(${testApp}_VERSION_MINOR 2) set(${testApp}_VERSION_REVISION 3) set(${testApp}_SOVERSION 4) ######################## # architecture handling ######################## if(${Arch} STREQUAL NATIVE) MESSAGE("Architecture is set to NATIVE") else() include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/${Arch}.cmake) endif() if (${PackageFormat} STREQUAL "DEFAULT") if (UNIX) include(GNUInstallDirs) set(CPACK_GENERATOR "DEB") else () set(CPACK_GENERATOR "ZIP") set(CMAKE_INSTALL_FULL_BINDIR "bin") set(CMAKE_INSTALL_FULL_LIBDIR "lib") set(CMAKE_INSTALL_FULL_LIBDIRSTATIC "lib") set(CMAKE_INSTALL_FULL_INCLUDEDIR "include") set(CMAKE_INSTALL_FULL_MANDIR "doc") endif() elseif(${PackageFormat} STREQUAL "ZIP") set(CPACK_GENERATOR "ZIP") set(CMAKE_INSTALL_FULL_BINDIR "bin") set(CMAKE_INSTALL_FULL_LIBDIR "lib") set(CMAKE_INSTALL_FULL_LIBDIRSTATIC "lib") set(CMAKE_INSTALL_FULL_INCLUDEDIR "include") set(CMAKE_INSTALL_FULL_MANDIR "doc") else() message( FATAL_ERROR "The PackageFormat is unknown") endif() ################################ # compile of the module content ################################ list(APPEND testApp_sources ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp ) add_executable(${testApp} ${testApp_sources} ) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") set_target_properties(${testApp} PROPERTIES LINKER_LANGUAGE CXX ) ################################ # installation ################################ if(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake") # install app install( TARGETS ${testApp} RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}/static ) set(CPACK_PACKAGE_DESCRIPTION "test") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "test") set(CPACK_PACKAGE_VENDOR "xxx") set(CPACK_PACKAGE_CONTACT "xxx") set(CPACK_PACKAGE_VERSION_MAJOR "${PCK_MAJOR}") set(CPACK_PACKAGE_VERSION_MINOR "${PCK_MINOR}") set(CPACK_PACKAGE_VERSION_PATCH "${PCK_REVISION}") set(CPACK_PACKAGE_FILE_NAME "${PrjName}_${PCK_MAJOR}.${PCK_MINOR}.${PCK_REVISION}") set(CPACK_SOURCE_PACKAGE_FILE_NAME "${PrjName}_${PCK_MAJOR}.${PCK_MINOR}.${PCK_REVISION}") include(CPack) endif() 

cmake / STM32F2xx.cmake包含:

 set(CMAKE_C_FLAGS_INIT "--cpu Cortex-M3") set(CMAKE_CXX_FLAGS_INIT "--cpu Cortex-M3") set(CMAKE_C_LINK_FLAGS_INIT "--zt") 

我为arm编译器创build了一个工具链文件:

 # generated cmake toolchain file for include (CMakeForceCompiler) # We are cross compiling so we don't want compiler tests to run, as they will fail set(CMAKE_SYSTEM_NAME Generic) # Set processor type set(CMAKE_SYSTEM_PROCESSOR arm) SET(CMAKE_CROSSCOMPILING 1) set(CMAKE_ASM_COMPILER "arm-none-eabi-as.exe") set(CMAKE_C_COMPILER "arm-none-eabi-gcc.exe") set(CMAKE_CXX_COMPILER "arm-none-eabi-g++.exe") set(CMAKE_LINKER "arm-none-eabi-gcc.exe") set(CMAKE_MAKE_PROGRAM "mingw32-make.exe") set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --specs=nosys.specs") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --specs=nosys.specs") 

在cmd上编译时用:

 cd D:\git\myTestBuild\build PATH=C:\Program Files\CMake\bin;C:\Program Files (x86)\GNU Tools ARM Embedded\6 2017-q1-update\bin;C:\Program Files\mingw-w64\x86_64-6.3.0-posix-seh-rt_v5-rev2\mingw64\bin;%PATH% "C:\Program Files\CMake\bin\cmake.exe" -DArch="STM32F2xx" -G"MinGW Makefiles" -DPackageFormat=ZIP -DSWstackPath="D:\git\myTestBuild\SWstack" -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE="D:\git\myTestBuild\dump\toolchain.cmake" .. CMake Error at C:/Program Files/CMake/share/cmake-3.8/Modules/CMakeTestCCompiler.cmake:51 (message): The C compiler "C:/Program Files (x86)/GNU Tools ARM Embedded/6 2017-q1-update/bin/arm-none-eabi-gcc.exe" is not able to compile a simple test program. It fails with the following output: Change Dir: D:/git/myTestBuild/build/CMakeFiles/CMakeTmp Run Build Command:"C:/Program Files/mingw-w64/x86_64-6.3.0-posix-seh-rt_v5-rev2/mingw64/bin/mingw32-make.exe" "cmTC_8c052/fast" C:/Program Files/mingw-w64/x86_64-6.3.0-posix-seh-rt_v5-rev2/mingw64/bin/mingw32-make.exe -f CMakeFiles\cmTC_8c052.dir\build.make CMakeFiles/cmTC_8c052.dir/build mingw32-make.exe[1]: Entering directory 'D:/git/myTestBuild/build/CMakeFiles/CMakeTmp' Building C object CMakeFiles/cmTC_8c052.dir/testCCompiler.c.obj "C:\Program Files (x86)\GNU Tools ARM Embedded\6 2017-q1-update\bin\arm-none-eabi-gcc.exe" -o CMakeFiles\cmTC_8c052.dir\testCCompiler.c.obj -c D:\git\myTestBuild\build\CMakeFiles\CMakeTmp\testCCompiler.c Linking C executable cmTC_8c052 "C:\Program Files\CMake\bin\cmake.exe" -E cmake_link_script CMakeFiles\cmTC_8c052.dir\link.txt --verbose=1 "C:\Program Files (x86)\GNU Tools ARM Embedded\6 2017-q1-update\bin\arm-none-eabi-gcc.exe" CMakeFiles/cmTC_8c052.dir/testCCompiler.c.obj -o cmTC_8c052 c:/program files (x86)/gnu tools arm embedded/6 2017-q1-update/bin/../lib/gcc/arm-none-eabi/6.3.1/../../../../arm-none-eabi/lib\libc.a(lib_a-exit.o): In function `exit': exit.c:(.text.exit+0x2c): undefined reference to `_exit' collect2.exe: error: ld returned 1 exit status CMakeFiles\cmTC_8c052.dir\build.make:96: recipe for target 'cmTC_8c052' failed mingw32-make.exe[1]: *** [cmTC_8c052] Error 1 mingw32-make.exe[1]: Leaving directory 'D:/git/myTestBuild/build/CMakeFiles/CMakeTmp' Makefile:125: recipe for target 'cmTC_8c052/fast' failed mingw32-make.exe: *** [cmTC_8c052/fast] Error 2 CMake will not be able to correctly generate this project. Call Stack (most recent call first): CMakeLists.txt:5 (project) 

它失败。 编译器无法链接简单的演示程序,因为它没有find“_exit”符号。 这个问题应该通过添加“–specs = nosys.specs”来解决 。 似乎它不起作用。

有任何想法吗?

把我的评论变成一个答案

我已经给你一个简单的例子一个尝试。 我可以重现您的初始错误,并可以通过将CMAKE_TRY_COMPILE_TARGET_TYPE设置为CMAKE_TRY_COMPILE_TARGET_TYPE来修复编译器检测。 但是,然后建立一个“可执行”仍然会失败。

因此,您可以将CMAKE_EXE_LINKER_FLAGS_INIT设置为--specs=nosys.specs (因为这些是链接器标志)。 只要确保从空的二进制输出目录开始,如果您正在使用..._INIT标志,因为所产生的CMAKE_EXE_LINKER_FLAGS被缓存。

我更喜欢强制结果CMAKE_EXE_LINKER_FLAGS变量( INTERNAL确实意味着FORCE )。

的CMakeLists.txt

 cmake_minimum_required(VERSION 3.6) project(testApp) file(WRITE main.cpp "int main(void) { return 0; }") set(testApp "testApp") list( APPEND testApp_sources main.cpp ) add_executable( ${testApp} ${testApp_sources} ) 

toolchain.cmake

 set(CMAKE_SYSTEM_NAME Generic) set(CMAKE_SYSTEM_PROCESSOR arm) set(CMAKE_C_COMPILER "arm-none-eabi-gcc.exe") set(CMAKE_CXX_COMPILER "arm-none-eabi-g++.exe") set(CMAKE_EXE_LINKER_FLAGS "--specs=nosys.specs" CACHE INTERNAL "") set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) 

请问:

 build> cmake -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE:PATH="..\toolchain.cmake" .. -- The C compiler identification is GNU 6.3.1 -- The CXX compiler identification is GNU 6.3.1 -- Check for working C compiler: C:/Program Files (x86)/GNU Tools ARM Embedded/6 2017-q1-update/bin/arm-none-eabi-gcc.exe -- Check for working C compiler: C:/Program Files (x86)/GNU Tools ARM Embedded/6 2017-q1-update/bin/arm-none-eabi-gcc.exe -- works -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Detecting C compile features -- Detecting C compile features - done -- Check for working CXX compiler: C:/Program Files (x86)/GNU Tools ARM Embedded/6 2017-q1-update/bin/arm-none-eabi-g++.exe -- Check for working CXX compiler: C:/Program Files (x86)/GNU Tools ARM Embedded/6 2017-q1-update/bin/arm-none-eabi-g++.exe -- works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Detecting CXX compile features -- Detecting CXX compile features - done -- Configuring done -- Generating done -- Build files have been written to: build build> cmake --build . Scanning dependencies of target testApp [ 50%] Building CXX object CMakeFiles/testApp.dir/main.obj [100%] Linking CXX executable testApp [100%] Built target testApp 

参考

  • 与特定链接器的cmake交叉编译不会将参数传递给armlink
  • 什么是CMake语法来设置和使用变量?