Skip to content

[question] Packaging cross toolchain with relocation and settings_target #17928

@snickl

Description

@snickl

What is your question?

Hey, I'm trying to put https://github.com/conan-io/conan/blob/develop2/test/integration/build_requires/test_relocatable_toolchain.py together with https://docs.conan.io/2/examples/cross_build/toolchain_packages.html and just can't seem to make it work.
This is for a buildroot SDK, but stripped down:

base/conanfile.py:

import os

from conan import ConanFile
from conan.tools.files import mkdir


class Base(ConanFile):
    name = "base"
    version = "1.0"
    package_type = "shared-library"
    settings = ("os", "arch", "sdk_build_type")
    _resource_folder = "data"
    no_copy_source = True

    def build(self):
        arch = str(self.settings_target.arch)
        os_lc = str(self.settings_target.os).lower()
        if arch == "armv8":
            arch = "aarch64"
        toolchain_prefix = "-".join([arch, os_lc, "gnu"])
        sdk_build_type = self.settings_target.get_safe("sdk_build_type")
        self.output.info(f"sdk_build_type: {sdk_build_type}")
        sdk_file_name_extra = (
            "-" + sdk_build_type.lower()
            if sdk_build_type and sdk_build_type != "Release"
            else ""
        )
        sdk_file_name = f"{toolchain_prefix}_sdk-buildroot{sdk_file_name_extra}.tar.gz"
        sdk_url = os.path.join("https://artifactserver", sdk_file_name)
        mkdir(self, self._resource_folder)
        self.output.info(f"Retrieving {sdk_url} into {self._resource_folder}")

    def package_id(self):
        self.info.settings_target = self.settings_target
        self.info.settings_target.rm_safe("build_type")
        self.info.settings_target.rm_safe("compiler")

sdk/conanfile.py:

import os

from conan import ConanFile
from conan.tools.files import copy


class Sdk(ConanFile):
    name = "sdk"
    version = "1.0"
    package_type = "shared-library"
    settings = ("os", "arch", "sdk_build_type")
    _resource_folder = "data"
    no_copy_source = True
    build_policy = "missing"
    upload_policy = "skip"

    def build_requirements(self):
        self.tool_requires("base/1.0")

    def configure(self):
        arch = str(self.settings_target.arch)
        os_lc = str(self.settings_target.os).lower()
        if arch == "armv8":
            arch = "aarch64"
        self._toolchain_prefix = "-".join([arch, os_lc, "gnu"])

    def package_id(self):
        self.info.settings_target = self.settings_target
        self.info.settings_target.rm_safe("build_type")
        self.info.settings_target.rm_safe("compiler")

    def package(self):
        base_folder = self.dependencies.build["base"].package_folder
        copy(
            self,
            "*",
            os.path.join(base_folder, self._resource_folder),
            os.path.join(self.package_folder),
        )
        self.output.info(f"Running ./relocate-sdk.sh in cwd={self.package_folder}")

app/conanfile.py:

from conan import ConanFile


class App(ConanFile):
    name = "app"
    version = "1.0"
    package_type = "application"
    settings = ("os", "arch", "compiler", "build_type")

    def build_requirements(self):
        self.tool_requires("sdk/1.0")

    def package_id(self):
        self.info.settings.rm_safe("compiler")

target:

[settings]
os=Linux
arch=armv8
sdk_build_type=Release

workstation:

[settings]
os=Linux
arch=x86_64
sdk_build_type=Release

~/.conan2/settings_user.yml:

sdk_build_type: ["Release", "Debug"]

test.sh:

#!/bin/sh

set -x

conan remove -c "*"
conan create --no-remote --build-require -pr:h=target -pr:b=workstation base/
conan export --no-remote --build-require sdk/
conan create --no-remote -pr:h=target -pr:b=workstation app/
conan list "*#*:*"
conan graph explain --no-remote -pr:h=target -pr:b=workstation app/

Which ends with

======== Closest binaries ========
base/1.0
  base/1.0#8112ee662df1a2967e3b8c12c87d3160%1741642041.4603093 (2025-03-10 21:27:21 UTC)
    base/1.0#8112ee662df1a2967e3b8c12c87d3160:6dade31be6e3e0a864ef0db4f21ac90d653c844f
      remote: Local Cache
      settings: Linux, x86_64, Release
      settings_target: arch=armv8, os=Linux, sdk_build_type=Release
      diff
        settings_target
          expected: arch=x86_64
          existing: arch=armv8
        explanation: This binary was built with different settings_target.

I think the problem is somehow that since the sdk package is built implicitly per dependency, the requested settings (-pr:h=target) don't transfer to settings_target (expected: arch=x86_64).
I've tried more things than bear mentioning and hope you can give me a hint.

The sdk_build_type setting isn't core to this but an adjacent issue, the intent being that the SDK can itself be built in debug mode and I want to be able to select this, but when users of the toolchain apply -s build_type=Debug, that is not what they usually want.

Have you read the CONTRIBUTING guide?

  • I've read the CONTRIBUTING guide

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions