libtool: warning: 'Foo.o' has no symbols on Xcode 26.4

I've recently installed Xcode 26.4, and it seems like all of our libraries now give multiple linker error when building of the format libtool: warning: 'Foo.o' has no symbols

Most of these errors come from extensions over objc types written in objc. (for instance we have some extensions over NSArray in the file NSArray+NSSet.mm)

Is that a new feature of some stricter libtool invocation? or a bug? should I do anything about it?

Answered by DTS Engineer in 885263022

Thanks for confirming. And it turns out that this is easy to reproduce:

  1. Using Xcode 26.4, create a new project from the macOS > Library template, and choose to create a Cocoa static library.

  2. In the resulting .h file, remove the whole @interface block.

  3. And in the .m file, convert the @implementation block to a category. For example:

    @implementation NSUUID (Foo)
    
    - (void)test {
    }
    
    @end
    
  4. Choose Product > Build. This issues the following warning:

libtool: warning: 'Foo.o' has no symbols

This actually makes some degree of sense:

  • Xcode has run libtool to convert the various object (.o) files in the target into a static library (.a).
  • There’s only one object file.
  • It only contains a category.
  • Objective-C categories don’t publish any symbols.

Consider this:

% nm …/Foo.o
0000000000000000 t -[NSUUID(Foo) test]
                 U _OBJC_CLASS_$_NSUUID
0000000000000028 s __OBJC_$_CATEGORY_INSTANCE_METHODS_NSUUID_$_Foo
0000000000000048 s __OBJC_$_CATEGORY_NSUUID_$_Foo
0000000000000014 s l_OBJC_CLASS_NAME_
0000000000000088 s l_OBJC_LABEL_CATEGORY_$
0000000000000018 s l_OBJC_METH_VAR_NAME_
000000000000001d s l_OBJC_METH_VAR_TYPE_
0000000000000000 t ltmp0
0000000000000014 s ltmp1
0000000000000018 s ltmp2
000000000000001d s ltmp3
0000000000000028 s ltmp4
0000000000000088 s ltmp5
0000000000000090 s ltmp6
0000000000000630 s ltmp7

All the symbols are private (so t rather than T), except _OBJC_CLASS_$_NSUUID, which is an import.

This lack of symbols is the reason why the static linker has the -ObjC flag, to force it to include Objective-C stuff even though it doesn’t look like it’s being referenced anywhere.

Looking at the libtool man page, I see it has a -no_warning_for_no_symbols option. Adding that to the the target’s Other Librarian Flags build setting eliminates this warning.

So, this warning is reasonable enough — under normal circumstances a .o file that exports no symbols is nonsense — but in the case of an Objective-C static library that contains just categories it makes sense to suppress it.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

it seems like all of our libraries

These are static libraries, right?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Hi, I'm having the same issue. Yes, mine are in a static library.

Thanks for confirming. And it turns out that this is easy to reproduce:

  1. Using Xcode 26.4, create a new project from the macOS > Library template, and choose to create a Cocoa static library.

  2. In the resulting .h file, remove the whole @interface block.

  3. And in the .m file, convert the @implementation block to a category. For example:

    @implementation NSUUID (Foo)
    
    - (void)test {
    }
    
    @end
    
  4. Choose Product > Build. This issues the following warning:

libtool: warning: 'Foo.o' has no symbols

This actually makes some degree of sense:

  • Xcode has run libtool to convert the various object (.o) files in the target into a static library (.a).
  • There’s only one object file.
  • It only contains a category.
  • Objective-C categories don’t publish any symbols.

Consider this:

% nm …/Foo.o
0000000000000000 t -[NSUUID(Foo) test]
                 U _OBJC_CLASS_$_NSUUID
0000000000000028 s __OBJC_$_CATEGORY_INSTANCE_METHODS_NSUUID_$_Foo
0000000000000048 s __OBJC_$_CATEGORY_NSUUID_$_Foo
0000000000000014 s l_OBJC_CLASS_NAME_
0000000000000088 s l_OBJC_LABEL_CATEGORY_$
0000000000000018 s l_OBJC_METH_VAR_NAME_
000000000000001d s l_OBJC_METH_VAR_TYPE_
0000000000000000 t ltmp0
0000000000000014 s ltmp1
0000000000000018 s ltmp2
000000000000001d s ltmp3
0000000000000028 s ltmp4
0000000000000088 s ltmp5
0000000000000090 s ltmp6
0000000000000630 s ltmp7

All the symbols are private (so t rather than T), except _OBJC_CLASS_$_NSUUID, which is an import.

This lack of symbols is the reason why the static linker has the -ObjC flag, to force it to include Objective-C stuff even though it doesn’t look like it’s being referenced anywhere.

Looking at the libtool man page, I see it has a -no_warning_for_no_symbols option. Adding that to the the target’s Other Librarian Flags build setting eliminates this warning.

So, this warning is reasonable enough — under normal circumstances a .o file that exports no symbols is nonsense — but in the case of an Objective-C static library that contains just categories it makes sense to suppress it.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

libtool: warning: 'Foo.o' has no symbols on Xcode 26.4
 
 
Q