3
votes

My goal is to cross-compile an application which exists on Windows using an external SDK toolchain being build on Linux machine in order to have an executable code for my ARM platform

I am using VisualStudio CMake project on Windows machine.

I am using an external SDK in order to cross-compile my C++ program for Linux arm architecture.

I have build this SDK using Yocto project on my Linux machine ( NOT THE ARM PLATFORM ! )

My CMake toolchain file path on my Linux machine is :

/opt/poky-atmel/2.5.3/sysroots/x86_64-pokysdk-linux/usr/share/cmake/OEToolchainConfig.cmake

I can see that there are multiple cross-compilers that may be used by my SDK under this path :

/opt/poky-atmel/2.5.3/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi

I can mention arm-poky-linux-gnueabi-gcc compiler which I want to use to cross-compile my application and execute it on my ARM platform.

Before including the path of this cross-compiler to my VisualStudio CMakeSettings file, I have tried to use it on my Linux machine ( which hosts my SDK ) in order to compile a simple code and execute it on the ARM platform. I have succeded to do that!

A little remarque that I must source and setup the environment in order to export the important paths and variables of the SDK toolchain so I can compile my code.

Now, after I have been sure about the good work of my SDK cross compiler, I have to use it in VisualStudio on my windows machine and that's for the same purpose ( cross compiling my code in order to use it on my ARM architecture ).

After opening a CMake project on VisualStudio and connecting to my Linux system following these steps :

Remote Connection

I have modified all the settings I need in order to achieve my goal.

You can see here my c++ .cpp file code which is using the Boost library :

#include "CMakeProject4.h"
#include <boost/lambda/lambda.hpp>
#include <iostream>
#include <iterator>
#include <algorithm>

using namespace std;

int main()
{
    typedef std::istream_iterator<int> in;

    std::cout << "Type in any number: ";

    std::for_each(
        in(std::cin), in(), std::cout
        << (boost::lambda::_1 * 10)
        << "\nType in another number: ");
}

This is my CMakeList.txt :

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)

set(Boost_USE_STATIC_LIBS ON) 
set(Boost_USE_MULTITHREADED OFF)  
set(Boost_USE_STATIC_RUNTIME OFF)

list(APPEND CMAKE_PREFIX_PATH /opt/poky-atmel/2.5.3/sysroots/cortexa5hf-neon-poky-linux-gnueabi/usr/include)
set(Boost_NO_BOOST_CMAKE ON)

message(STATUS "CMAKE_TOOLCHAIN_FILE='${CMAKE_TOOLCHAIN_FILE}'")
set(CROSS_COMPILER_DIR /opt/poky-atmel/2.5.3/sysroots/x86_64-pokysdk-linux/usr)
set(CMAKE_C_COMPILER ${CROSS_COMPILER_DIR}/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-gcc)
set(CMAKE_CXX_COMPILER ${CROSS_COMPILER_DIR}/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-gcc)


message(STATUS "CMAKE_C_COMPILER='${CMAKE_C_COMPILER}'")
message(STATUS "CMAKE_CXX_COMPILER='${CMAKE_CXX_COMPILER}'")

find_package(Boost 1.66.0) 

if(Boost_FOUND)

    message (STATUS "success!")
    add_executable (CMakeProject4 "CMakeProject4.cpp" "CMakeProject4.h") 
    include_directories(${Boost_INCLUDE_DIRS})  
    target_link_libraries(CMakeProject4 ${Boost_LIBRARIES})

endif()

This is my CMakeSettings.json file :

{
  "configurations": [
    {
      "addressSanitizerRuntimeFlags": "detect_leaks=0",
      "buildCommandArgs": "",
      "cmakeCommandArgs": "cmake -DBoost_DEBUG=ON -DCMAKE_CXX_COMPILER=/opt/poky-atmel/2.5.3/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-gcc",
      "cmakeExecutable": "/home/ubuntu/CMake/Executable",
      "cmakeToolchain": "/opt/poky-atmel/2.5.3/sysroots/x86_64-pokysdk-linux/usr/share/cmake/OEToolchainConfig.cmake",
      "configurationType": "RelWithDebInfo",
      "ctestCommandArgs": "",
      "generator": "Unix Makefiles",
      "inheritEnvironments": [ "linux_arm" ],
      "name": "Linux-Release",
      "remoteBuildRoot": "/home/ubuntu/CMake/RemoteBR",
      "remoteCMakeListsRoot": "/home/ubuntu/CMake/RemoteCML",
      "remoteCopyBuildOutput": false,
      "remoteCopySources": true,
      "remoteCopySourcesExclusionList": [ ".vs", ".git", "out" ],
      "remoteCopySourcesMethod": "rsync",
      "remoteInstallRoot": "/home/ubuntu/CMake/RemoteIL",
      "remoteMachineName": "867574967;192.168.1.12 (username=ubuntu, port=22, authentication=PrivateKey)",
      "rsyncCommandArgs": "-t --delete --delete-excluded",
      "variables": [
        {
          "name": "Boost_INCLUDE_DIRS",
          "value": "/opt/poky-atmel/2.5.3/sysroots/cortexa5hf-neon-poky-linux-gnueabi/usr/include",
          "type": "PATH"
        },
        {
          "name": "Boost_LIBRARIES",
          "value": "/opt/poky-atmel/2.5.3/sysroots/cortexa5hf-neon-poky-linux-gnueabi/usr/lib",
          "type": "PATH"
        },
        {
          "name": "Boost_INCLUDE_DIR",
          "value": "/opt/poky-atmel/2.5.3/sysroots/cortexa5hf-neon-poky-linux-gnueabi/usr/include",
          "type": "PATH"
        }

      ]
    }
  ]
}

As you can see I am setting my SDK compilers bin paths to CMAKE_CXX_COMPILER variable.

This is also OEToolchainConfig.cmake file which I find on my Linux machine :

set( CMAKE_SYSTEM_NAME Linux )
set( CMAKE_C_FLAGS $ENV{CFLAGS} CACHE STRING "" FORCE )
set( CMAKE_CXX_FLAGS $ENV{CXXFLAGS}  CACHE STRING "" FORCE )
set( CMAKE_ASM_FLAGS ${CMAKE_C_FLAGS} CACHE STRING "" FORCE )
set( CMAKE_LDFLAGS_FLAGS ${CMAKE_CXX_FLAGS} CACHE STRING "" FORCE )

set( CMAKE_FIND_ROOT_PATH $ENV{OECORE_TARGET_SYSROOT} $ENV{OECORE_NATIVE_SYSROOT} )
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_SYSTEM_PROCESSOR from the sysroot name (assuming processor-distro-os).
if ($ENV{SDKTARGETSYSROOT} MATCHES "/sysroots/([a-zA-Z0-9_-]+)-.+-.+")
  set(CMAKE_SYSTEM_PROCESSOR ${CMAKE_MATCH_1})
endif()

# Include the toolchain configuration subscripts
file( GLOB toolchain_config_files "${CMAKE_TOOLCHAIN_FILE}.d/*.cmake" )
foreach(config ${toolchain_config_files})
    include(${config})
endforeach()

I have sourced the environment on my Linux machine and then I try to compile.

This is the command I use to compile my code :

cmake -DBoost_DEBUG=ON -DCMAKE_CXX_COMPILER=/opt/poky-atmel/2.5.3/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-gcc

But, this message occurs from CMake saying that the compiler is broken and some other things that CMake can not find :

CMake message

This is my CMakeCache file where you can see what variables ( compilers and other things .. ) used by my project :

CMakeCache

The first thing I guess, the environment was not setup correctly or VisualStudio is not seeing the environment variable after sourcing the environment from my Linux machine. This is just an opinion. I don't know realy what is the problem here and why I can not compile my code.

I will appreciate your help!

Thank you!

EDIT

I add the log files :

Here is the CMakeError.log file :

CMakeError.log

Here is CMakeOutput.log file :

CMakeOutput.log

1
The answer to your previous question said that you should NOT set the compiler manually when you set a toolchain file. Why do you insist on your setting of the compiler? If the compiler isn't set by a toolchain, then the problem in the toolchain or in the environment settings. The file OEToolchainConfig.cmake you show use contains a little information: it include()-s other files which seem to perform detailed settings, but we don't know content of these files.Tsyvarev
@Tsyvarev When I made what was described in the previous answer, the CMake project did not recognize the compiler at all and CMAKE_CXX_COMPILER was using the default VS compiler : CMAKE_CXX_COMPILER=/usr/bin/c++ that's why I did not accept the answer. I think that the problem is in environment settings but I'm not able to understand what's written in the OEToolchainConfig.cmake that's why I don't know what to do and what to modifyGonn

1 Answers

0
votes

My guess here would be that the OEToolchainConfig.cmake file uses environment variables to find e.g. the target sysroot, the $ENV{OECORE_TARGET_SYSROOT} part, and that is why it's not working.

You write that you have sourced the environment-setup script on your linux machine, but that won't have any effect on the environment when you're trying to build from VS from Windows.

Either see if there's a way that you can make the build via VS use the environment script, or simply see what values the environment variables used in OEToolchainConfig.cmake have on the linux machine after sourcing the setup script, and replace the $ENV{} parts of OEToolchainConfig.cmake with the actual values instead.