Modifying CMAKE_<LANG>_LINK_EXECUTABLE in toolchain file

Hello!

I’m having quite some trouble finding a way to modify CMAKE_C_LINK_EXECUTABLE/CMAKE_CXX_LINK_EXECUTABLE for my embedded cross-compilation project. The compiler ID resolves correctly to “TI” and subsequencly TI-C.cmake and TI-CXX.cmake are loaded. However there is an issue with the order of arguments in those files with the newer version of the vendor toolchain. Specifically, some of the linker options need to come before the --run-linker command.

I tried asking in the “Usage” category here Chaging order of options in the link command of a cross-compilation project via CMAKE_CXX_LINK_EXECUTABLE but have not received any feedback.

I’ve also tried by creating the file cmake/Platform/Generic-TI-C.cmake and modifying CMAKE_C_LINK_EXECUTABLE there (as suggested here). This was on the root of my project and I also added ${CMAKE_CURRENT_SOURCE_DIR}/cmake/ to the front of CMAKE_MODULE_PATH but that didn’t yield results. It didn’t appear like the file was being loaded at all.

Any ideas?

Thanks!

I think you want to use CMAKE_TOOLCHAIN_FILE instead of making your own compiler module directory. See https://cmake.org/cmake/help/v3.6/manual/cmake-toolchains.7.html. I suspect you might not be setting the module path before project() as well.

Hi @ben.boeckel, sorry, I neglected to say that I do have a toolchain file in my project. It looks like this

cmake_minimum_required(VERSION 3.5)

if(NOT DEFINED TOOLCHAIN_DIR)
    if(WIN32)
        set(TOOLCHAIN_DIR "C:/ti/ccs1000/ccs/tools/compiler/ti-cgt-c2000_20.2.0.LTS/")
    elseif(UNIX)
        set(TOOLCHAIN_DIR "/opt/ti/ccs1000/ccs/tools/compiler/ti-cgt-c2000_20.2.0.LTS")
    endif()
endif()

if(NOT DEFINED C2000WARE_DIR)
    if(WIN32)
        set(C2000WARE_DIR "C:/ti/c2000/C2000Ware_3_01_00_00/")
    elseif(UNIX)
        set(C2000WARE_DIR "/opt/ti/c2000/C2000Ware_3_01_00_00/")
    endif()
endif()

# set target system
set(CMAKE_SYSTEM_NAME "Generic")
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

if(WIN32)
    # disable "response files" for cross-compiling on windows
    # see https://stackoverflow.com/a/43188057/570414
    SET(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS OFF)
    SET(CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS OFF)
endif()

# toolchain paths
find_program(TI_CC          NAMES cl2000 PATHS ${TOOLCHAIN_DIR}/bin NO_DEFAULT_PATH)
find_program(TI_CXX         NAMES cl2000 PATHS ${TOOLCHAIN_DIR}/bin NO_DEFAULT_PATH)
find_program(TI_ASM         NAMES cl2000 PATHS ${TOOLCHAIN_DIR}/bin NO_DEFAULT_PATH)

find_program(TI_AR          NAMES ar2000 PATHS ${TOOLCHAIN_DIR}/bin NO_DEFAULT_PATH)
find_program(TI_OBJCOPY     NAMES ofd2000 PATHS ${TOOLCHAIN_DIR}/bin NO_DEFAULT_PATH)
find_program(TI_OBJDUMP     NAMES hex2000 PATHS ${TOOLCHAIN_DIR}/bin NO_DEFAULT_PATH)
find_program(TI_SIZE        NAMES size2000 PATHS ${TOOLCHAIN_DIR}/bin NO_DEFAULT_PATH)
find_program(TI_LD          NAMES cl2000 PATHS ${TOOLCHAIN_DIR}/bin NO_DEFAULT_PATH)

set(CMAKE_C_COMPILER    ${TI_CC})
set(CMAKE_CXX_COMPILER  ${TI_CXX})
set(CMAKE_ASM_COMPILER  ${TI_ASM})

include_directories(${TOOLCHAIN_DIR}/include)
link_directories(${TOOLCHAIN_DIR}/lib)

set(CMAKE_FIND_ROOT_PATH ${TOOLCHAIN_DIR})

# Search for programs in the build host directories
# Search for libraries and headers in the target directories
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

The issue I have is with the CMAKE_CXX_LINK_EXECUTABLE defined here as

set(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_CXX_COMPILER> --run_linker --output_file=<TARGET> --map_file=<TARGET>.map <CMAKE_CXX_LINK_FLAGS> <LINK_LIBRARIES> <LINK_FLAGS> <OBJECTS>")

Per the compiler errors and warnings, some of the flags need to come before the --run_linker command. So, I’d like this rule variable to look a little different, something like this (with LINK_FLAGS before --run_linker:

set(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_CXX_COMPILER> <LINK_FLAGS> --run_linker --output_file=<TARGET> --map_file=<TARGET>.map <CMAKE_CXX_LINK_FLAGS> <LINK_LIBRARIES> <OBJECTS>")

My current approach is to define my own “Platform” (as linked above) so I can set this variable there, but I’m not having luck loading the platform’s .cmake file

I have found a fix to my problem. It was actually much easier than I was making it out to be. The variable CMAKE_<LANG>_LINK_EXECUTABLE does not need to be defined before calling project() as I was attempting to do by defining it as a Platform/ or in the toolchain file. It can actually be defined in the CMakeLists.txt file, after the call to project().

Defining this rule variable before the call to project() might be possible in a Platform/ file or some other way, but I had no luck with that approach.

Did you try to use CMAKE_USER_MAKE_RULES_OVERRIDE to include a file that changes CMAKE_<LANG>_LINK_EXECUTABLE before it is ever used?