conan-io / conan

Conan - The open-source C and C++ package manager
https://conan.io
MIT License
7.97k stars 952 forks source link

[bug] cross compilation is not properly detected #6546

Closed sct2010 closed 3 months ago

sct2010 commented 4 years ago

I was trying to cross compile from linux x86_64 to linux arm32. The toolchain and sysroot are conan packages. The two conanfiles setting the package_info:

self.env_info.path.append(os.path.join(self.package_folder, "bin"))
self.env_info.CC = os.path.join(self.package_folder, "bin", "arm-linux-gnueabihf-gcc").replace("\\", "/")
self.env_info.CXX = os.path.join(self.package_folder, "bin", "arm-linux-gnueabihf-g++").replace("\\", "/")
self.env_info.AR = os.path.join(self.package_folder, "bin", "arm-linux-gnueabihf-ar").replace("\\", "/")
self.env_info.RANLIB = os.path.join(self.package_folder, "bin", "arm-linux-gnueabihf-ranlib").replace("\\", "/")
self.env_info.STRIP = os.path.join(self.package_folder, "bin", "arm-linux-gnueabihf-strip").replace("\\", "/")
self.env_info.SYSROOT = self.package_folder
self.env_info.CMAKE_SYSROOT = self.package_folder
self.env_info.CONAN_CMAKE_FIND_ROOT_PATH = self.package_folder
self.env_info.CONAN_CMAKE_FIND_ROOT_PATH_MODE_PROGRAM = "NEVER"

I expected to get the content of the CONAN_CMAKE_FIND_ROOT_PATH variable available in the cmake file. It is not the case.

My configuration is the following:

Configuration:
[settings]
arch=armv7hf
arch_build=x86_64
build_type=Debug
compiler=gcc
compiler.cppstd=17
compiler.libcxx=libstdc++11
compiler.version=8
os=Linux
os_build=Linux
[options]
[build_requires]
*: armv7hf-linux-toolchain/2019.03-sqp1@tools/testing, am57xx-sysroot/06.02.00.81-sqp1@tools/testing
[env]

After a quick look at the conan source, I found an issue in the client/build/cmake_flags.py:

def _cmake_cross_build_defines(self):
...
        # System name and system version
        if cmake_system_name is not True:  # String not empty
            definitions["CMAKE_SYSTEM_NAME"] = cmake_system_name
        else:  # detect if we are cross building and the system name and version
            if cross_building(self._conanfile.settings):  # We are cross building
                if os_ != os_build:
                    if os_:  # the_os is the host (regular setting)
                        definitions["CMAKE_SYSTEM_NAME"] = {"iOS": "Darwin",
                                                            "tvOS": "Darwin",
                                                            "watchOS": "Darwin",
                                                            "Neutrino": "QNX"}.get(os_, os_)
                    else:
                        definitions["CMAKE_SYSTEM_NAME"] = "Generic"
...
if definitions:  # If enabled cross compile

In my case, cross_building(self._conanfile.settings) returns True. In the next line it detects host and target os is the same (if os_ != os_build:). So it is not setting the definitions["CMAKE_SYSTEM_NAME"]. Later in the code it detects if cross compilation is enabled, by if definitions:. Since it never sets a single definition above, the check if we are cross compilation fails and the definitions are empty. My sugesstion is to change the following line:

if os_ != os_build:

to something like

if os_ != os_build or arch_ != arch_build:

Currently I have a workaroung and force the cross compilation detection by setting: self.env_info.CONAN_CMAKE_SYSTEM_NAME = "Linux"

Environment Details (include every applicable attribute)

jgsogo commented 4 years ago

Hi, @sct2010

I have some doubts, I'm not sure if we should set the value of definitions["CMAKE_SYSTEM_NAME"] (it would take the value 'Generic' given the current implementation) or we should just improve the if definitions: so it checks for actual cross-compilation. I feel like the second option is better, CMAKE_SYSTEM_NAME will take the value of CMAKE_HOST_SYSTEM_NAME and we will enter the if to set the rest of CMake variables, wdyt?

sct2010 commented 4 years ago

Hi @jgsogo

You are right, setting the definitions["CMAKE_SYSTEM_NAME"] to Generic is not a proper solution. Improving the if definitions: would be better. A few lines above you already have a check if we are crosscompiling. Why not include it? if cross_building(self._conanfile.settings) or definitions:

jgsogo commented 4 years ago

Not sure if it should be just if cross_building(self._conanfile.settings):... it is an easy PR 😉

memsharded commented 3 months ago

This ticket is quite outdated, both tools, env-management and the 2 profile cross-build model has changed everything.

Closing the ticket, please report a new one against the new Conan 2 if necessary, thanks!