Undefined symbols for architecture arm64

Kenneth Wolcott kennethwolcott at gmail.com
Sat Mar 15 04:26:57 UTC 2025


Thank you, Ryan, an very nice elaboration!

On Fri, Mar 14, 2025 at 8:56 PM Ryan Carsten Schmidt <
ryandesign at macports.org> wrote:

> I see you already received a reply while I was writing my response but I
> may as well send it in case it explains anything in a way that is more
> understandable.
>
> On Mar 14, 2025, at 17:14, Kenneth Wolcott wrote:
>
> > I was compiling a C example of a Rosetta Code task recently..
> >
> > https://rosettacode.org/wiki/Vampire_number#C
> >
> > Here's my clang error(s):
> > clang -lm -o ./vampire_number ./vampire_number.c
> > Undefined symbols for architecture arm64:
> >   "_dtally", referenced from:
> >       _fangs in vampire_number-2cd7e6.o
> >       _fangs in vampire_number-2cd7e6.o
> >       _fangs in vampire_number-2cd7e6.o
> >   "_max", referenced from:
> >       _fangs in vampire_number-2cd7e6.o
> >   "_min", referenced from:
> >       _fangs in vampire_number-2cd7e6.o
> >   "_ndigits", referenced from:
> >       _fangs in vampire_number-2cd7e6.o
> > ld: symbol(s) not found for architecture arm64
> > clang: error: linker command failed with exit code 1 (use -v to see
> invocation)
>
> All of the undefined symbols are for functions that use the "inline"
> keyword:
>
> > inline xint max(xint a, xint b) { return a > b ? a : b; }
> > inline xint min(xint a, xint b) { return a < b ? a : b; }
> > inline int ndigits(xint x)
> > {
> >       int n = 0;
> >       while (x) n++, x /= 10;
> >       return n;
> > }
> >
> > inline xint dtally(xint x)
> > {
> >       xint t = 0;
> >       while (x) t += 1<<((x%10) * 6), x /= 10;
> >
> >       return t;
> > }
>
> The "inline" keyword was introduced to the C language standard in c99. In
> c99 and later, it tells the compiler what code to use *if* it chooses to
> inline the function, but it *does not* tell the compiler *to* inline the
> function. Some compilers treat it as a *suggestion* to inline the function
> but they might ignore that suggestion. If the compiler chooses *not* to
> inline the function, then it will look for a non-inline definition of the
> function. Since this code doesn't contain a non-inline definition of the
> function, the result is an undefined symbol error.
>
> One solution is to remove the "inline" keyword, e.g.:
>
> xint max(xint a, xint b) { return a > b ? a : b; }
> xint min(xint a, xint b) { return a < b ? a : b; }
>
> etc. The compiler can still choose to inline the function.
>
> Another solution is to keep the "inline" keyword (because you want to make
> the suggestion) and to tell the compiler that you want the same code to be
> used if the function is not inlined. There are two ways to do that: one is
> to precede "inline" with the keyword "extern" (meaning you want the
> function to be reachable from outside this translation unit (i.e. outside
> of this source code file)) and the other is to precede it with the keyword
> "static" (meaning you will only be using this function within this
> translation unit / source code file). There are some caveats to both
> "extern" and "static" when a project consists of more than one translation
> unit, as discussed more in the wikipedia article linked below. Since this
> project is only a single source code file, "static" is probably the best
> choice, e.g.:
>
> static inline xint max(xint a, xint b) { return a > b ? a : b; }
> static inline xint min(xint a, xint b) { return a < b ? a : b; }
>
> etc. It would also be reasonable to precede all of the other functions
> other than main with "static" since they are not being called from other
> translation units either.
>
> Another solution that doesn't require any changes to the code is to
> compile in gnu89 mode. Although "inline" was added to the standard in c99,
> it appeared as an extension in gcc compilers in gnu89 mode, which was the
> default mode along time ago, but per the wikipedia article below "inline"
> behaves differently in gnu89 than it does in c99 and later. In gnu89,
> "inline" is equivalent to c99's "extern inline". You can downgrade to this
> mode by adding the compiler flag "-std=gnu89", e.g.:
>
> clang -std=gnu89 -o vampire_number vampire_number.c
>
> Another "solution" that doesn't require any changes to the code but which
> is fragile is to tell the compiler to inline functions, for example by
> using an optimization flag:
>
> clang -O3 -o vampire_number vampire_number.c
>
> This (by itself) is fragile because if the compiler still chooses not to
> inline the function, you'll be back to an undefined symbol error. Different
> compilers, or different versions of a compiler, might make different
> choices about whether to inline functions at a particular optimization
> level. Adding an optimization flag in addition to one of the other fixes
> suggested above is fine.
>
> There's a lot of good information about inline functions here:
>
> https://en.wikipedia.org/wiki/Inline_function
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macports.org/pipermail/macports-users/attachments/20250314/d72bc908/attachment.htm>


More information about the macports-users mailing list