示例解析 --as-needed 和 --no-as-needed 的作用和区别

文章讲述了在编译PyTorch时,--as-needed和--no-as-needed链接选项的作用。--as-needed只在使用动态库符号时标记,而--no-as-needed总是标记,可能导致不必要的库在运行时被加载。实际问题提到,不使用--no-as-needed可能导致未使用的库引发运行时找不到接口的错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景及解释

在编译 pytorch 时,注意到参数 -Wl,–no-as-needed,便查询这两个指令的具体意义:

--as-needed
    Only set DT_NEEDED for shared libraries if used.
--no-as-needed
    Always set DT_NEEDED for shared libraries.

可以看出,

  • –as-needed,只有在使用到动态库的符号时,才将动态库打上 DT_NEEDED 的标签。
  • –no-as-needed,只要在命令行中链接,就将动态库打上 DT_NEEDED 的标签,用于在编译时不需要,但是在执行时需要的情况。

示例

使用到动态库符号

// main.cpp
#include <stdio.h>
extern int add(int, int);
int main()
{
    int a = 1, b = 2;
    printf("%d\n", add(a, b));
    return 0;
}
// helper.cpp
int add(int a, int b) { return a + b; }

将 helper.cpp 编译成动态库

g++ -c -fPIC helper.cpp
g++ -shared -o libhelper.so helper.o

使用 该动态库

g++ main.cpp -L. -lhelper

然后使用 readelf 查看 dynamic section, 可以看到 libhelper.so 被标记为 NEEDED,这时因为 main.cpp 中使用到了动态库中的 add 函数。

$ readelf -d a.out
 0x0000000000000001 (NEEDED)             Shared library: [libhelper.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

未使用到动态库的符号

// main.cpp
int main()
{
    return 0;
}

如果去掉对 add 函数的使用,再次按照上述流程进行处理的时候, 这时候就发现已经没有了 libhelper.so 库了。

 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

但是如果使用 no-as-needed 参数, 可以发现即使没有使用到libhelper.so,该库也会被打上 NEEDED 的标签。

$ g++ main.cpp -L. -Wl,--no-as-needed -lhelper
$ readelf -d a.out
 0x0000000000000001 (NEEDED)             Shared library: [libhelper.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

实际问题

如这个帖子C++ 链接一个不需要的库(–no-as-needed)所描述的,如果程序没有使用到 libtorch 的接口,且不使用 --no-as-needed 参数链接 libtorch.so,就会在运行时出现找不到接口的问题。

参考:

/** ****************************************************************************** * @file lan8742.c * @author MCD Application Team * @brief This file provides a set of functions needed to manage the LAN742 * PHY devices. ****************************************************************************** * @attention * * Copyright (c) 2017 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "lan8742.h" /** @addtogroup BSP * @{ */ /** @addtogroup Component * @{ */ /** @defgroup LAN8742 LAN8742 * @{ */ /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /** @defgroup LAN8742_Private_Defines LAN8742 Private Defines * @{ */ #define LAN8742_MAX_DEV_ADDR ((uint32_t)31U) /** * @} */ /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ /* Private functions ---------------------------------------------------------*/ /** @defgroup LAN8742_Private_Functions LAN8742 Private Functions * @{ */ /** * @brief Register IO functions to component object * @param pObj: device object of LAN8742_Object_t. * @param ioctx: holds device IO functions. * @retval LAN8742_STATUS_OK if OK * LAN8742_STATUS_ERROR if missing mandatory function */ int32_t LAN8742_RegisterBusIO(lan8742_Object_t *pObj, lan8742_IOCtx_t *ioctx) { if(!pObj || !ioctx
03-20
<think>好的,我现在要解决用户关于LAN8742_RegisterBusIO函数用法及参数说明的问题。首先,我需要回顾一下STM32中LAN8742的驱动相关代码,尤其是PHY芯片的初始化配置部分。 用户提供的代码片段显示,在low_level_init函数中调用了LAN8742_RegisterBusIO,并传入了&LAN8742&LAN8742_IOCtx两个参数。这说明用户可能是在使用STM32的HAL库或者CubeMX生成的代码,需要正确配置PHY的接口函数。 首先,LAN8742_RegisterBusIO函数的作用应该是注册PHY芯片所需的底层I/O操作,比如读写寄存器。在STM32的HAL库中,通常需要为PHY芯片提供这些底层函数,以便上层驱动能够通过MDIO接口与PHY通信。 接下来,我需要确定参数的结构。第一个参数是&LAN8742,这应该是指向LAN8742_Object结构体的指针,包含PHY的状态信息。第二个参数是&LAN8742_IOCtx,类型可能是LAN8742_IOCtx_t,这个结构体应该包含了读写寄存器的函数指针,比如ReadRegWriteReg。 用户的问题可能在于如何正确初始化配置这两个参数。例如,需要确保LAN8742_IOCtx中的ReadRegWriteReg函数已经正确实现,能够通过STM32的MAC外设(如ETH)进行MDIO通信。此外,还需要注意这些函数的参数是否符合要求,比如寄存器地址、数据等。 另外,用户可能在调用该函数时遇到问题,例如初始化失败或者PHY无法正确响应。这时候需要检查I/O函数是否正确注册,以及硬件连接是否正确,比如复位引脚、MDIOMDC线路是否正常。 最后,需要确保在调用LAN8742_Init之前已经正确调用了LAN8742_RegisterBusIO,这样PHY的初始化才能顺利进行。同时,用户可能需要参考ST提供的驱动库文档或示例代码,确保参数传递正确无误。</think>### LAN8742_RegisterBusIO 函数用法及参数说明 在STM32以太网驱动开发中,`LAN8742_RegisterBusIO` 函数用于为PHY芯片(如LAN8742A)注册底层总线I/O操作函数,使驱动能够通过MDIO接口与PHY通信。以下是详细说明: --- #### **函数原型** ```c int32_t LAN8742_RegisterBusIO(lan8742_Object_t *pObj, lan8742_IOCtx_t *ioctx); ``` --- #### **参数解析** 1. **`pObj`** - 类型:`lan8742_Object_t *` - 作用:指向PHY设备对象的结构体指针,用于存储PHY状态配置信息。 - 示例: ```c lan8742_Object_t LAN8742; // 全局PHY对象 ``` 2. **`ioctx`** - 类型:`lan8742_IOCtx_t *` - 作用:包含底层I/O操作函数的结构体指针,需用户实现以下两个关键函数: - **`ReadReg(uint16_t devAddr, uint16_t regAddr, uint32_t *pData)`** 读取PHY寄存器的值。 - `devAddr`:PHY地址(通常由硬件引脚决定,例如0x01)。 - `regAddr`:寄存器地址(如状态寄存器、控制寄存器等)。 - `pData`:用于存储读取结果的指针。 - **`WriteReg(uint16_t devAddr, uint16_t regAddr, uint32_t data)`** 向PHY寄存器写入数据。 - 参数同上,`data`为待写入的值。 - 示例: ```c lan8742_IOCtx_t LAN8742_IOCtx = { .ReadReg = ETH_ReadPHYRegister, // STM32 HAL库提供的MDIO读函数 .WriteReg = ETH_WritePHYRegister // STM32 HAL库提供的MDIO写函数 }; ``` --- #### **典型调用流程** 1. **初始化I/O上下文** 绑定MDIO读写函数(通常使用HAL库的`ETH_ReadPHYRegister``ETH_WritePHYRegister`): ```c lan8742_IOCtx_t LAN8742_IOCtx = { .ReadReg = ETH_ReadPHYRegister, .WriteReg = ETH_WritePHYRegister }; ``` 2. **注册总线函数** 调用`LAN8742_RegisterBusIO`关联PHY对象与I/O操作: ```c LAN8742_RegisterBusIO(&LAN8742, &LAN8742_IOCtx); ``` 3. **初始化PHY芯片** 后续通过`LAN8742_Init`完成PHY配置: ```c while (LAN8742_Init(&LAN8742) != LAN8742_STATUS_OK); // 确保初始化成功[^1] ``` --- #### **注意事项** 1. **硬件依赖** - 需确保ETH外设的时钟引脚已正确配置(如RMII或MII接口)。 - PHY地址(`devAddr`)需与硬件设计匹配(通过PHY芯片的配置引脚设定)。 2. **错误排查** - 若初始化失败,可检查MDIO总线时序或尝试读取PHY ID寄存器(地址0x02)验证通信是否正常。 - 复位PHY时需操作硬件复位引脚(如示例中的`HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, ...)`)。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lylhw13_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值