Error: undefined reference to 'sincosf'

this code seems to cause a linker failure now, on 5.8:

extension SVG.Point<Float>
{
    @inlinable public
    init(radians:Float, radius:Float = 1.0)
    {
        self.init(radius * _cos(radians), radius * -_sin(radians))
    }
}
extension SVG.Point<Double>
{
    @inlinable public
    init(radians:Double, radius:Double = 1.0)
    {
        self.init(radius * _cos(radians), radius * -_sin(radians))
    }
}
SVG.Point.swift:4618: error: undefined reference to 'sincosf'
SVG.Point.swift:4792: error: undefined reference to 'sincos'

the fix is not difficult, we can spend some portability to use the Glibc trig functions instead:

#if canImport(Glibc)
import func Glibc.cos
import func Glibc.sin
#endif

but it seems kind of unfortunate that trig functions are no longer “included” with swift. what happened?

_cos and _sin are underscored, and as such were never really "included" with Swift. They are vestigial implementation hooks that we can't really remove. The expectation is really that you get cos and sin either from the platform libc (as you show) or from Numerics, like the rest of the C math library.

However, it is somewhat troubling that LLVM is generating a call to a function that doesn't exist (or isn't linked) in your environment. If you have just a call to _cos (no matching _sin, and no Glibc import), does the linker find cos successfully?

glibc and musl both look like they've had sincos in them for a while. Could it be that we're completely failing to link -lm at all?

2 Likes

hence, “"included”" in quotes :slight_smile:

this, by itself (with no Double-based counterpart),

extension SVG.Point<Float>
{
    @inlinable public
    init(radians:Float, radius:Float = 1.0)
    {
        self.init(radius * _cos(radians), 0)
    }
}

fails with

SVG.Point.swift:3580: error: undefined reference to 'cosf'

this, by itself (no Float),

extension SVG.Point<Double>
{
    @inlinable public
    init(radians:Double, radius:Double = 1.0)
    {
        self.init(radius * _cos(radians), 0)
    }
}

fails with

SVG.Point.swift:3552: error: undefined reference to 'cos'

by the way, the file SVG.Point.swift is less than 60 lines long, i do not know why the compiler is referencing a source location with a line number in the thousands.

if i add the

#if canImport(Glibc)
import func Glibc.cos
import func Glibc.sin
#elseif canImport(Darwin)
import func Darwin.cos
import func Darwin.sin
#endif

preamble, compilation succeeds, even though i did not change the name of the function being called from _cos to cos.

if i remove the preamble, compilation will continue to succeed until i delete the .build directory. (to me, this was the strangest part of this issue.)

2 Likes

OK, that's enough to tell us that this is just garden variety libm-not-being-linked-by-default-on-Linux, rather than LLVM doing something sneaky with sincos formation. If you use Numerics or the Glibc module, then libm will be linked for you. If you want to avoid using them, you'll have to ensure that it gets linked into your binary.

The best solution would be to use one of the modules that actually provides the feature, but if you really can't for some reason, then linking it manually ought to suffice.

3 Likes