Oracle® Solaris 11.2 链接程序和库指南

退出打印视图

更新时间: 2014 年 7 月
 
 

条件输入

mapfile 中的行可以设置条件以只应用于特定 ELFCLASS(32 或 64 位)或计算机类型。

        $if expr
        ....
        [$elif expr]
        ....
        [$else]
        ....
        $endif

条件输入表达式将计算得出一个逻辑 truefalse 值。每个指令($if$elif$else$endif)都单独出现在一行中。$if 和后续 $elif 行中的表达式将依序计算,直至找到计算结果为 true 的表达式。值为 false 的行后面的文本将被放弃。成功指令行后面的文本将得到正常处理。这里的文本是指不属于条件结构的任何内容。找到成功的 $if$elif 并处理了其文本后,后续的 $elif$else 行及其文本将被放弃。如果所有表达式都为零,并且有一个 $else,则会正常处理该 $else 之后的文本。

$if 指令的作用域不能跨越多个 mapfile。$if 指令必须由使用该 $if 指令的 mapfile 中的匹配 $endif 终止,否则链接编辑器将发出错误。

链接编辑器会维护一个内部名称表,这些名称可用在由 $if$elif 计算的逻辑表达式中。启动时,该表将使用下表中适用于要创建的输出目标文件的每个名称进行初始化。

表 8-4  预定义的条件表达式名称
名称
含义
_ELF32
32 位目标文件
_ELF64
64 位目标文件
_ET_DYN
共享目标文件
_ET_EXEC
可执行目标文件
_ET_REL
可重定位目标文件
_sparc
Sparc 计算机(32 或 64 位)
_x86
x86 计算机(32 或 64 位)
true
始终定义

名称区分大小写,并且必须完全按照所示形式使用。例如,定义了 true,但未定义 TRUE。其中的任何名称都可以由自身用作逻辑表达式。例如:

        $if _ELF64
        ....
        $endif

该示例的计算结果为 true,并且在输出目标文件为 64 位时允许链接编辑器处理所含的文本。虽然这些逻辑表达式中不允许使用数字值,但值 10 例外,它们的计算结果分别为 truefalse

任何未定义的名称计算结果将为 false。使用未定义的名称 false 标记应无条件跳过的输入行是一种常见做法。

        $if false
        ....
        $endif

使用下表中所示的运算符可以编写更复杂的逻辑表达式。

表 8-5  条件表达式运算符
运算符
含义
&&
逻辑 AND
||
逻辑 OR
( expr )
子表达式
!
对后面表达式的布尔值求反

表达式从左至右计算。子表达式先于外围表达式进行计算。

例如,在为 x86 平台生成 64 位目标文件时,将计算以下构造中的行。

        $if _ELF64 && _x86
        ....
        $endif

$add 指令可用于向链接编辑器的已知名称表中添加新名称。在上述示例中,定义名称 amd64 以表示 64 位 x86 目标文件可能会便于简化 $if 指令。

        $if _ELF64 && _x86
        $add amd64
        $endif

这可用于简化上述示例。

        $if amd64
        ....
        $endif

使用链接编辑器的 –z mapfile-add 选项,还可以将新的名称添加到链接编辑器的已知名称表。当 mapfile 输入需要基于外部环境属性(例如正在使用的编译器)有条件启用时,该选项非常有用。

$clear 指令是 $add 指令的逆操作。它用于从内部表中删除名称。

        $clear amd64

$add 指令的作用一直持续到使用该 $addmapfile 的最后,并且对于由相同链接操作中的链接编辑器处理的任何后续 mapfile 均可见。如果不希望这样,可在包含 $addmapfile 的最后使用 $clear 删除该定义。

最后,$error 指令会导致链接编辑器将行中的所有剩余文本打印为致命错误,并停止链接操作。$error 指令可用于确保将目标文件移植到新计算机类型的程序员将无法在无提示的情况下生成缺少必要 mapfile 定义的错误目标文件。

        $if _sparc
        ....
        $elif _x86
        ....
        $else
        $error unknown machine type
        $endif

C 语言程序员会发现用于 mapfile 条件输入的语法与 C 预处理程序宏语言类似。这种相似性是有意为之的。不过,mapfile 条件输入指令远不如 C 预处理程序提供的指令强大,这也是有意如此的。它们只能提供支持跨平台环境中的链接操作所需的最基本的功能。

这两种语言之间存在显著差异,其中包括:

  • C 预处理程序可定义完整的宏语言,并且这些宏适用于源文本以及由 #if#elif 预处理程序语句计算的表达式。链接编辑器 mapfile 不实现宏功能。

  • C 预处理程序计算的表达式涉及各种数字类型以及一组丰富的运算符。Mapfile 逻辑表达式涉及布尔值 truefalse,以及一组有限的运算符。

  • C 预处理程序表达式涉及任意数字值,可能定义为宏,并使用 defined() 计算是否定义了给定宏,同时生成 true(非零)或 false(零)值。mapfile 逻辑表达式只处理布尔值,并且直接使用名称而不含 defined() 运算。如果指定的名称存在于链接编辑器的已知名称表中,则视为 true,否则视为 false

如果需要进行更复杂的宏处理,则应考虑使用外部宏处理程序,例如 m4 (1)。