CMake cross-compile with specific linker doesn't pass arguments to armlink

后端 未结 3 612
一整个雨季
一整个雨季 2020-12-02 00:36

I am trying to cross-compile a project for embedded ARM Cortex builds, but I am unable to get the linker working. I want to use armlink, but no files are passed to armlink a

相关标签:
3条回答
  • 2020-12-02 00:45

    A toolchain file may be a good idea. Here is what I've came up the last time I tried CMake 2.8.10 with the DS-5 toolchain (it could still be optimized, but it should give you a starting point):

    INCLUDE(CMakeForceCompiler)
    
    # This one is important
    SET(CMAKE_SYSTEM_NAME Generic)
    SET(CMAKE_SYSTEM_PROCESSOR arm)
    
    # Specify the cross compiler
    SET(CMAKE_C_COMPILER "C:/Program Files (x86)/DS-5/bin/armcc.exe")
    SET(CMAKE_CXX_COMPILER "C:/Program Files (x86)/DS-5/bin/armcc.exe")
    SET(CMAKE_AR "C:/Program Files (x86)/DS-5/bin/armar.exe" CACHE FILEPATH "Archiver")
    
    #CMAKE_FORCE_C_COMPILER("C:/Program Files (x86)/DS-5/sw/gcc/bin/arm-linux-gnueabihf-gcc.exe" GNU)
    #CMAKE_FORCE_CXX_COMPILER("C:/Program Files (x86)/DS-5/sw/gcc/bin/arm-linux-gnueabihf-g++.exe" GNU)
    
    UNSET(CMAKE_C_FLAGS CACHE)
    SET(CMAKE_C_FLAGS "--cpu=Cortex-A9 --thumb -Ospace" CACHE STRING "" FORCE)
    UNSET(CMAKE_CXX_FLAGS CACHE)
    SET(CMAKE_CXX_FLAGS ${CMAKE_C_FLAGS} CACHE STRING "" FORCE)
    UNSET(CMAKE_EXE_LINKER_FLAGS CACHE)
    SET(CMAKE_EXE_LINKER_FLAGS "" CACHE STRING "" FORCE)
    UNSET(CMAKE_AR_FLAGS CACHE)
    SET(CMAKE_AR_FLAGS "-p -armcc,-Ospace" CACHE STRING "" FORCE)
    
    # set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> cr <TARGET> <LINK_FLAGS> <OBJECTS>")
    SET(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> ${CMAKE_AR_FLAGS} -o <TARGET> <OBJECTS>" CACHE STRING "C Archive Create")
    # set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> cr <TARGET> <LINK_FLAGS> <OBJECTS>")
    SET(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> ${CMAKE_AR_FLAGS} -o <TARGET> <OBJECTS>" CACHE STRING "CXX Archive Create")
    
    include_directories("C:/Program Files (x86)/DS-5/include")
    #include_directories("C:/Program Files (x86)/DS-5/sw/gcc/arm-linux-gnueabihf/libc/usr/include/arm-linux-gnueabi")
    
    # Where is the target environment
    SET(CMAKE_FIND_ROOT_PATH "C:/Program Files (x86)/DS-5")
    
    # Search for programs in the build host directories
    SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
    
    # For libraries and headers in the target directories
    SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
    SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
    

    Regarding your question

    Some failure analysis

    What you have tried should work (see also e.g. How do I add a linker or compile flag in a CMake file?). But it seems something goes wrong during the configuration step.

    I don't know your command line call for CMake's configuration/generation steps, so some general tips to find the root cause:

    You could try calling

    cmake.exe --trace ...
    

    to see what went wrong with your CMAKE_EXE_LINKER_FLAGS variable. This will generate a lot of output, so here are some basics on what CMake does:

    • The project() command will trigger the compiler evaluation
    • This will write CMAKE_EXE_LINKER_FLAGS into your CMakeCache.txt
    • You are overwriting it with a local variable (see variable scope docu here)

    If you look into share\cmake-2.8\Modules\CMakeCommonLanguageInclude.cmake:

    set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS_INIT} $ENV{LDFLAGS}"
         CACHE STRING "Flags used by the linker.")
    

    You could use CMAKE_EXE_LINKER_FLAGS_INIT, but you have to set it before the project() command or in the toolchain file.

    Because you set the link language to C take a look into share\cmake-2.8\Modules\CMakeCInformation.cmake:

    if(NOT CMAKE_C_LINK_EXECUTABLE)
      set(CMAKE_C_LINK_EXECUTABLE
        "<CMAKE_C_COMPILER> <FLAGS> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS>  -o <TARGET> <LINK_LIBRARIES>")
    endif()
    

    So you can use CMAKE_C_LINK_EXECUTABLE to overwrite the complete linker call or you could use CMAKE_C_LINK_FLAGS to set additional flags.

    The "official" way

    The official way to set the target's linker and compiler flags would be (before CMake 2.8.12):

    set_property(TARGET blinky APPEND_STRING PROPERTY COMPILE_FLAGS "--cpu=Cortex-M3")
    set_property(TARGET blinky APPEND_STRING PROPERTIES LINK_FLAGS "--map --ro-base=0x0 --rw-base=0x0008000 --first='boot.o(RESET)' --datacompressor=off")
    

    Starting with CMake 2.8.12 it would be something like:

    add_compile_options("--cpu=Cortex-M3")
    
    0 讨论(0)
  • 2020-12-02 00:48

    Starting with CMake v3.5 you don't need a toolchain anymore for Keil ARM C/C++ compilation tools:

    Support was added for the ARM Compiler (arm.com) with compiler id ARMCC.

    Just set your C/CXX compiler variables accordingly

    cmake -DCMAKE_C_COMPILER:PATH="C:\Program Files (x86)\DS-5\bin\armcc.exe"
          -DCMAKE_CXX_COMPILER:PATH="C:\Program Files (x86)\DS-5\bin\armcc.exe"
          ...
    

    References

    • ARMCC toolchain support
    • Add support for the ARM Compiler (arm.com)
    • CMake Error at CMakeLists.txt:30 (project): No CMAKE_C_COMPILER could be found
    0 讨论(0)
  • 2020-12-02 00:51

    From my experience, you cannot set CMAKE_EXE_LINKER_FLAGS in a CMakeLists.txt file. It has to be passed via a CMAKE_TOOLCHAIN_FILE when CMake is invoked the very first time in a build directory.

    I don't find any documentation regarding this problem, but there is the cross-compilation with CMake page which you should use it if you do cross-compilation.

    For a start, just put your set-calls in a toolchain file and run

    cmake -DCMAKE_TOOLCHAIN_FILE=<yourfile.toolchain>
    

    in a clean build directory.

    0 讨论(0)
提交回复
热议问题