LINK_INTERFACE_MULTIPLICITY Explained: A Guide to Properties: Targets in CMake


What it is

  • It controls the minimum number of times the linker scans through a library component during the linking process.
  • It's a target property associated with linking in CMake.

Default Behavior

  • By default, CMake constructs the link line such that the linker scans the component at least twice. This is to ensure proper resolution of symbol dependencies within the library.

Purpose of Customization

  • Increasing LINK_INTERFACE_MULTIPLICITY can be useful if:
    • The linker has trouble resolving symbol dependencies within a complex library component.
    • You have a specific linker optimization strategy that benefits from additional scans.
  • In rare cases, you might want to adjust the scanning behavior.

How to Set It

  • Use the set_target_properties command:
set_target_properties(MyTarget PROPERTIES LINK_INTERFACE_MULTIPLICITY 3)
  • This sets the minimum number of scans for the target MyTarget to 3.

Important Considerations

  • CMake will use the largest value specified by any target in a component, ensuring consistency.
  • Increasing the value can potentially slow down the linking process due to additional scans.
  • Generally, it's not necessary to modify LINK_INTERFACE_MULTIPLICITY unless you encounter specific linking issues.
  • It's primarily relevant for static libraries, as dynamic libraries usually only require one scan.
  • This property has configuration-specific variants like LINK_INTERFACE_MULTIPLICITY_<CONFIG>, allowing you to set different values for different build configurations (e.g., Debug, Release).


Example 1: Basic Usage

This example defines two libraries, LibA and LibB, and sets the LINK_INTERFACE_MULTIPLICITY for LibA to 3. When an executable links against LibA, the linker will scan its components at least three times.

add_library(LibA SHARED sourceA.cpp)
add_library(LibB SHARED sourceB.cpp)

# Set LINK_INTERFACE_MULTIPLICITY for LibA (optional in most cases)
set_target_properties(LibA PROPERTIES LINK_INTERFACE_MULTIPLICITY 3)

target_link_libraries(MyExecutable PUBLIC LibA LibB)

Example 2: Configuration-Specific Setting

This example sets a higher LINK_INTERFACE_MULTIPLICITY value for the Release configuration to potentially improve linking performance:

add_library(MyLibrary SHARED source.cpp)

# Set higher value for Release configuration (optional)
set_target_properties(MyLibrary PROPERTIES
  LINK_INTERFACE_MULTIPLICITY_RELEASE 4)

target_link_libraries(MyExecutable PUBLIC MyLibrary)


Object Libraries

  • This approach involves creating an intermediate object library that both dependent libraries can link against. This breaks the cyclic dependency and avoids the need for multiple linker scans.
add_library(ObjectLibrary OBJECT source1.cpp source2.cpp)
add_library(LibA SHARED $<TARGET_OBJECTS:ObjectLibrary>)
add_library(LibB SHARED $<TARGET_OBJECTS:ObjectLibrary>)

target_link_libraries(MyExecutable PUBLIC LibA LibB)

Linker Order Optimization Flags

  • Some linkers offer options to control the order in which libraries are scanned. These flags might be named -Wl,--start-group and -Wl,--end-group (GNU ld) or /OPT:REFERENCE (Microsoft Visual Studio). However, this approach can be linker-specific and might not always be reliable.
target_link_options(MyExecutable PUBLIC INTERFACE "-Wl,--start-group")
target_link_libraries(MyExecutable PUBLIC LibA LibB)
target_link_options(MyExecutable PUBLIC INTERFACE "-Wl,--end-group")

Re-architecting Libraries

  • In rare cases, restructuring your libraries to break down circular dependencies might be necessary. This could involve introducing a new abstraction layer or refactoring code to avoid tight coupling between libraries.

CMake Policies

  • While not directly addressing linking issues, CMake provides policies like CMP0022 that can control how transitive dependencies are propagated. This could be helpful in managing complex linking scenarios. Refer to CMake documentation for details on available policies.
  • CMake policies can offer additional control but might require a deeper understanding of the build system.
  • Restructuring libraries is a more significant change and should be a last resort.
  • Only consider linker order optimization flags if the issue persists and you're comfortable with linker-specific behavior.
  • Start with simpler solutions like object libraries.