You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Conan 2.0中构建GCC交叉编译器的依赖模型?

问题描述

我希望为GCC交叉编译器制作一个Conan包。从头构建GCC交叉工具链需执行以下步骤:

  1. 使用--without-headers参数构建GCC版本,生成的编译器无法创建普通二进制文件,但足以构建glibc;
  2. 使用该受限GCC构建glibc;
  3. 通过--sysroot=参数指定glibc安装路径,构建完整GCC。

我希望将整个构建过程建模为Conan依赖图。目前实现的情况:

  • conan install cc --build=missing可正常运行,会构建一个目标平台与运行平台一致的常规编译器;
  • conan install cc --build=missing pr:macos-x86_64 -o os_target=Linux -o arch_target=x86_64无法运行,报错ConanException: Tried to define 'os' setting inside recipe。

请问是否有办法让cc包依赖于为完全不同的profile构建的libc包?

相关代码

cc/conanfile.py

import os
from typing import Any

from conan import ConanFile


class CompilerConanfile(ConanFile):
    name : Any = "cc"
    version : Any = "1.0"
    description : Any = "c compiler"
    license : Any = "TBD"
    homepage : Any = "TBD"
    options : Any = {
        "os_target": ["Windows", "Linux", "Macos"], 
        "arch_target": ["x86", "x86_64"],
        "libc":[True, False]}
    default_options : Any = {"libc": True, "os_target": "Macos", "arch_target": "x86_64"}
    build_requires: Any
    requires: Any

    def configure(self):
        # record target information in options
        if settings_target := getattr(self, "settings_target", None):
            self.options.os_target = self.options.os_target or settings_target.os
            self.options.arch_target = self.options.arch_target or settings_target.os

    def requirements(self):
        if self.options.libc:
            self.requires("sysroot/1.0", options={
                "os_target": self.options.os_target,
                "arch_target": self.options.arch_target,
            })

    def generate(self):
        if self.options.libc:
            sysroot = self.dependencies.get('sysroot').conf_info.get('user.sysroot.root')
            self.output.highlight(f"sysroot is at {sysroot}")

sysroot/conanfile.py

import os
from typing import Any

from conan import ConanFile

class SysrootConanfile(ConanFile):
    name : Any = "sysroot"
    version : Any = "1.0"
    description : Any = "sysroot files for a cross compiler"
    license : Any = "TBD"
    homepage : Any = "TBD"
    options : Any = {
        "os_target": ["Windows", "Linux", "Macos"], 
        "arch_target": ["x86", "x86_64"]
    }
    default_options : Any = {"os_target": "Macos", "arch_target": "x86_64"}
    settings : Any = ("os", "arch")
    build_requires: Any
    requires: Any
    conf_info: Any
    
    def configure(self):
        if self.settings.os != self.options.os_target:
            self.settings.os = self.options.os_target
        if self.settings.arch != self.options.arch_target:
            self.settings.arch = self.options.arch_target

    def requirements(self):
        self.requires('libc/1.0', visible=True)

    def package_info(self):
        sysroot = self.dependencies["libc"].package_folder
        self.output.highlight(f"sysroot exporting path at {sysroot}")
        self.conf_info.define("user.sysroot.root", sysroot)

libc/conanfile.py

import os
from typing import Any
from conan import ConanFile

class RuntimeConanfile(ConanFile):
    name : Any = "libc"
    version : Any = "1.0"
    description : Any = "c runtime library"
    license : Any = "TBD"
    homepage : Any = "TBD"
    settings : Any = ("os", "arch")
    tool_requires : Any

    def build_requirements(self):
        # require the version of the compiler that does not have a libc baked in, 
        # since this recipe is for building libc
        self.tool_requires("cc/1.0", options={"libc": False})
    
解决方案

报错原因是sysroot/conanfile.py的configure方法中直接修改了self.settings——Conan不允许在配方内部修改settings,settings由profile或命令行参数决定,属于只读属性。

要实现交叉编译场景下的依赖管理,需利用Conan的交叉编译profile机制,通过settings_target区分构建主机和目标平台,调整方案如下:

1. 重构sysroot包

去掉修改settings的逻辑,改用settings_target同步目标平台,同时指定libc依赖使用目标平台构建:

import os
from typing import Any
from conan import ConanFile

class SysrootConanfile(ConanFile):
    name : Any = "sysroot"
    version : Any = "1.0"
    description : Any = "sysroot files for a cross compiler"
    license : Any = "TBD"
    homepage : Any = "TBD"
    options : Any = {
        "os_target": ["Windows", "Linux", "Macos"], 
        "arch_target": ["x86", "x86_64"]
    }
    default_options : Any = {"os_target": "Macos", "arch_target": "x86_64"}
    settings : Any = ("os", "arch")
    # 声明使用settings_target处理交叉编译
    settings_target : Any = ("os", "arch")
    build_requires: Any
    requires: Any
    conf_info: Any
    
    def configure(self):
        # 用settings_target同步目标平台选项
        if self.settings_target:
            self.options.os_target = self.settings_target.os
            self.options.arch_target = self.settings_target.arch

    def requirements(self):
        # 强制libc使用目标平台的settings构建
        self.requires("libc/1.0", target=self.settings_target)

    def package_info(self):
        sysroot = self.dependencies["libc"].package_folder
        self.output.highlight(f"sysroot exporting path at {sysroot}")
        self.conf_info.define("user.sysroot.root", sysroot)

2. 修正cc包的configure方法

修复原代码中settings_target赋值错误(误将settings_target.os赋值给arch_target):

def configure(self):
    # record target information in options
    if settings_target := getattr(self, "settings_target", None):
        self.options.os_target = self.options.os_target or settings_target.os
        self.options.arch_target = self.options.arch_target or settings_target.arch

3. 使用交叉编译profile调用

创建交叉编译profile文件(例如cross-linux-x86_64):

[settings]
os=Macos
arch=x86_64
[settings_target]
os=Linux
arch=x86_64

执行命令:

conan install cc --build=missing --profile:build=macos-x86_64 --profile:host=cross-linux-x86_64

关键原理

  • Conan的settings_target(或--profile:host)专门用于交叉编译,区分构建主机和目标平台;
  • 依赖声明时使用target=self.settings_target,可强制依赖包使用目标平台的settings构建;
  • 绝对不要在配方内部修改self.settings,所有settings调整需通过profile或命令行参数传递。

内容的提问来源于stack exchange,提问作者Lawrence D'Anna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 15:30:04