0

I am trying to create a project folder structure based on CMake, using the gcc-arm-none-eabi toolchain, and that can use QEMU (arm) to run CppUTest.

Right now, my folder structure look like this:

project/
├── app/
│   ├── src/
│   │   └── main.cpp
│   ├── tests/
│   │   ├── CMakeLists.txt
│   │   ├── FooTest.cpp
│   │   └── main.cpp
│   ├── CMakeLists.txt
│   └── runCMake.sh
├── libraries/
│   ├── errortype/
│   │   ├── include/
│   │   ├── src/
│   │   └── CMakeLists.txt
│   ├── math/
│   │   ├── include/
│   │   ├── src/
│   │   └── CMakeLists.txt
│   └── prediction/
│       ├── include/
│       ├── src/
│       └── CMakeLists.txt
└── scripts/
    └── cmake/
        ├── PreTargetDef.cmake
        ├── PostTargetDef.cmake
        └── toolchain.cmake

The app/CMakeLists.txt:

### PROJECT INITIALIZATION
cmake_minimum_required(VERSION 3.19)
project(hello-arm)

### SET TOOLCHAIN
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/../scripts/cmake/toolchain.cmake)

### CUSTOM CMAKE SCRIPTS
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../scripts/cmake")
include(PreTargetDef)

### APPLICATION SOURCES
file(GLOB ${PROJECT_NAME}_SRC
    "src/main.cpp"
)

### CREATE EXECUTABLE
add_executable(${PROJECT_NAME} ${${PROJECT_NAME}_SRC})

### LIBRARIES TARGET INCLUDE DIRECTORIES
target_include_directories(${PROJECT_NAME} PUBLIC ${LIBERRORTYPE_INCLUDE_DIRS})

### CUSTOM CMAKE SCRIPT
include(PostTargetDef)

### OPTIONALLY COMPILE TESTS
option(COMPILE_TESTS "Compile the tests" OFF)
if(COMPILE_TESTS)
  add_subdirectory(tests)
endif(COMPILE_TESTS)

Toolchain.cmake:

cmake_minimum_required (VERSION 3.6)

#set(CMAKE_CROSSCOMPILING 1)
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)

set(TRIPLE "arm-none-eabi")

unset(TOOLCHAIN_GCC_PROGRAM CACHE)
find_program(TOOLCHAIN_GCC_PROGRAM "${TRIPLE}-gcc" NO_DEFAULT_PATH HINTS ${ARM_CORTEX_COMPILER_PATH} $ENV{ARM_CORTEX_COMPILER_PATH})

get_filename_component(TOOLCHAIN_ROOT ${TOOLCHAIN_GCC_PROGRAM} DIRECTORY)
get_filename_component(EXE_EXT ${TOOLCHAIN_GCC_PROGRAM} EXT)

# To create static libraries suitable for link-time optimization (LTO),
# use gcc-ar and gcc-ranlib instead of ar and ranlib. See gcc -flto option
set(CMAKE_C_COMPILER       "${TOOLCHAIN_ROOT}/${TRIPLE}-gcc${EXE_EXT}"         CACHE FILEPATH "gcc" FORCE)
set(CMAKE_CXX_COMPILER     "${TOOLCHAIN_ROOT}/${TRIPLE}-g++${EXE_EXT}"         CACHE FILEPATH "g++" FORCE)
set(CMAKE_OBJCOPY          "${TOOLCHAIN_ROOT}/${TRIPLE}-objcopy${EXE_EXT}"     CACHE FILEPATH "objcopy" FORCE)
set(CMAKE_OBJDUMP          "${TOOLCHAIN_ROOT}/${TRIPLE}-objdump${EXE_EXT}"     CACHE FILEPATH "objdump" FORCE)
set(CMAKE_RANLIB           "${TOOLCHAIN_ROOT}/${TRIPLE}-gcc-ranlib${EXE_EXT}"  CACHE FILEPATH "ranlib" FORCE)
set(CMAKE_STRIP            "${TOOLCHAIN_ROOT}/${TRIPLE}-strip${EXE_EXT}"       CACHE FILEPATH "strip" FORCE)
set(CMAKE_AR               "${TOOLCHAIN_ROOT}/${TRIPLE}-gcc-ar${EXE_EXT}"      CACHE FILEPATH "ar" FORCE)
set(CMAKE_AS               "${TOOLCHAIN_ROOT}/${TRIPLE}-as${EXE_EXT}"          CACHE FILEPATH "as" FORCE)

#SET(CMAKE_EXE_LINKER_FLAGS_INIT   "--specs=nosys.specs -Wl,-gc-sections -nostdlib -static-libgcc -static-libstdc++ -nostartfiles")
set(CMAKE_EXE_LINKER_FLAGS_INIT   " --specs=nosys.specs ")
string(APPEND CMAKE_C_FLAGS_INIT   " ")
string(APPEND CMAKE_C_FLAGS_INIT_DEBUG   " ")
string(APPEND CMAKE_CXX_FLAGS_INIT   " ")
string(APPEND CMAKE_CXX_FLAGS_INIT_DEBUG   " ")

set(SHARED_LIBS OFF)
set(STATIC_LIBS ON)

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH )
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH )

PreTargetDef.cmake:

### ENABLE LANGUAGES
enable_language(C)
enable_language(CXX)
enable_language(ASM)

### COMPILE TARGET TYPE
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

### CREATE BUILD DIRECTORY IF NOT ALREADY DONE
file(MAKE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../build)

### OPTIONS
set(APP_ROOT ${CMAKE_SOURCE_DIR}/src)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_C_STANDARD 99)
set(CMAKE_EXE_LINKER_FLAGS --specs=rdimon.specs)

### COMPILE OPTIONS
list(APPEND COMPILE_OPTIONS
    -mthumb
    -mcpu=cortex-a9
    -mfloat-abi=softfp
    -mfpu=fpv4-sp-d16
    -flto
    -lm
    -lc
    -lrdimon
    -Wall
    $<$<CONFIG:RELEASE>:-g3>
    $<$<CONFIG:RELEASE>:-Os>
)

add_compile_options(
  ${COMPILE_OPTIONS}
)

### ADD SUBDIRECTORIES FOR LIBRARIES
get_filename_component(COMMON_LIBRARIES_ROOT "${CMAKE_SOURCE_DIR}/../libraries/" ABSOLUTE)
get_filename_component(COMMON_LIBRARIES_BUILD_ROOT "${CMAKE_BINARY_DIR}/common_libraries/" ABSOLUTE)

add_subdirectory(${COMMON_LIBRARIES_ROOT}/errortype/src     ${COMMON_LIBRARIES_BUILD_ROOT}/errortype)
add_subdirectory(${COMMON_LIBRARIES_ROOT}/math/src      ${COMMON_LIBRARIES_BUILD_ROOT}/math)
add_subdirectory(${COMMON_LIBRARIES_ROOT}/prediction/src ${COMMON_LIBRARIES_BUILD_ROOT}/prediction)

set( LIBS
    prediction
    errortype
)

PostTargetDef.cmake:

### TARGET LINK LIBRARY
target_link_libraries(
    ${PROJECT_NAME}
    ${COMPILE_OPTIONS}
    -Wl,-static
    -Wl,--start-group
    ${LIBS}
    -Wl,--end-group
)

And, tests/ CMakeLists.txt:

# (1) Look for installed version of CppUTest
if(DEFINED ENV{CPPUTEST_HOME})
    message(STATUS "Using CppUTest home: $ENV{CPPUTEST_HOME}")
    set(CPPUTEST_INCLUDE_DIRS $ENV{CPPUTEST_HOME}/include)
    set(CPPUTEST_LIBRARIES $ENV{CPPUTEST_HOME}/lib)
    set(CPPUTEST_LDFLAGS CppUTest CppUTestExt)
else()
    find_package(PkgConfig REQUIRED)
    pkg_search_module(CPPUTEST REQUIRED cpputest>=3.8)
    message(STATUS "Found CppUTest version ${CPPUTEST_VERSION}")
endif()

# (2) Our unit tests sources
set(TEST_APP_NAME ${PROJECT_NAME}_tests)
set(TEST_SOURCES
    mocks/IFooMock.cpp
    FooTest.cpp
    main.cpp
)

# (3) Take care of include directories
include_directories(${CPPUTEST_INCLUDE_DIRS} ../src/)
link_directories(${CPPUTEST_LIBRARIES})

# (4) Build the unit tests objects and link then with the app library
add_executable(${TEST_APP_NAME} ${TEST_SOURCES})
target_link_libraries(${TEST_APP_NAME}
    ${CPPUTEST_LDFLAGS}
    ${COMPILE_OPTIONS}
    -Wl,-static
    -Wl,--start-group
    ${LIBS}
    -Wl,--end-group
)

Doing cmake -DARM_CORTEX_COMPILER_PATH="/path/to/gcc-arm-bin/" -DCOMPILE_TESTS=ON $PROJECT_PATH creates a Makefile in the build folder for the main application and a second one under the build/tests folder. Running make produces a hello-arm file for the main app that runs under qemu-arm hello-arm just fine. But come time to make the tests/ part, I get the following error (make VERBOSE=1):

[ 91%] Building CXX object tests/CMakeFiles/hello-arm_tests.dir/main.cpp.obj
cd /home/tester/Documents/hello-qemu-arm/build/release/tests && /home/tester/miniconda3/envs/hello-qemu/bin/arm-none-eabi-g++  -I/home/tester/miniconda3/envs/hello-qemu/include -I/home/tester/Documents/hello-qemu-arm/application/tests/../src -I/home/tester/Documents/hello-qemu-arm/libraries/prediction/src/include -I/home/tester/Documents/hello-qemu-arm/build/release/common_libraries/prediction/src-config/include -I/home/tester/Documents/hello-qemu-arm/libraries/types/src/include -I/home/tester/Documents/hello-qemu-arm/build/release/common_libraries/types/src-config/include -I/home/tester/Documents/hello-qemu-arm/libraries/math/src/include -I/home/tester/Documents/hello-qemu-arm/build/release/common_libraries/math/src-config/include -I/home/tester/Documents/hello-qemu-arm/libraries/errortype/src/include -I/home/tester/Documents/hello-qemu-arm/build/release/common_libraries/errortype/src-config/include -I/home/tester/Documents/hello-qemu-arm/build/include -I/home/tester/Documents/hello-qemu-arm/libraries/etl/src/include -I/home/tester/Documents/hello-qemu-arm/libraries/etl/src/../config -O3 -DNDEBUG -mthumb -mcpu=cortex-a9 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -flto -lm -lc -lrdimon -Wall -g3 -Os -std=gnu++17 -MD -MT tests/CMakeFiles/hello-arm_tests.dir/main.cpp.obj -MF CMakeFiles/hello-arm_tests.dir/main.cpp.obj.d -o CMakeFiles/hello-arm_tests.dir/main.cpp.obj -c /home/tester/Documents/hello-qemu-arm/application/tests/main.cpp
[100%] Linking CXX executable hello-arm_tests
cd /home/tester/Documents/hello-qemu-arm/build/release/tests && /home/tester/miniconda3/envs/hello-qemu/bin/cmake -E cmake_link_script CMakeFiles/hello-arm_tests.dir/link.txt --verbose=1
/home/tester/miniconda3/envs/hello-qemu/bin/arm-none-eabi-g++ -O3 -DNDEBUG --specs=rdimon.specs "CMakeFiles/hello-arm_tests.dir/mocks/IFooMock.cpp.obj" "CMakeFiles/hello-arm_tests.dir/FooTest.cpp.obj" "CMakeFiles/hello-arm_tests.dir/main.cpp.obj" -o hello-arm_tests   -L/home/tester/miniconda3/envs/hello-qemu/lib  -lCppUTest -lCppUTestExt -mthumb -mcpu=cortex-a9 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -flto -lm -lc -lrdimon -Wall -g3 -Os -Wl,-static -Wl,--start-group ../common_libraries/prediction/libprediction.a ../common_libraries/errortype/liberrortype.a -Wl,--end-group 
/home/tester/miniconda3/envs/hello-qemu/arm-none-eabi/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld: /home/tester/miniconda3/envs/hello-qemu/lib/libCppUTest.a: error adding symbols: file format not recognized
collect2: error: ld returned 1 exit status
make[2]: *** [tests/CMakeFiles/hello-arm_tests.dir/build.make:131: tests/hello-arm_tests] Error 1
make[2]: Leaving directory '/home/tester/Documents/hello-qemu-arm/build/release'
make[1]: *** [CMakeFiles/Makefile2:296: tests/CMakeFiles/hello-arm_tests.dir/all] Error 2
make[1]: Leaving directory '/home/tester/Documents/hello-qemu-arm/build/release'
make: *** [Makefile:91: all] Error 2
mmnano50
  • 37
  • 6
  • The error message `file format not recognized` means that format of `libCppUTest.a` file is not recognized by the linker. E.g. this file could be build for x86, but you build your project for ARM. You could check architecture of the static library using `objdump -f`: https://stackoverflow.com/a/12262148/3440745 – Tsyvarev Sep 02 '22 at 14:18
  • 1
    You might want to move your `set()` of the toolchain to be before the call the `project()`. [According to docs](https://cmake.org/cmake/help/latest/command/project.html#code-injection), the top-level `project()` call reads the toolchain file. – starball Sep 03 '22 at 02:51
  • @Tsyvarev That's what the problem was, thank you. – mmnano50 Sep 05 '22 at 06:29

0 Answers0