Clang linker reports “symbol not found”, despite &

2019-02-18 13:15发布

问题:

On OS X (clang), during linkage stage, a symbol (boost::filesystem::portable_posix_name) in my code is not being found. Here is a brief code snippet that contains the function I am calling in my code:

if (boost::filesystem::is_directory(settings.parent_path())
 && boost::filesystem::portable_posix_name(settings.filename().string()))
{ ... }

(Please let me know if more context in my code snippet is required.)

The linker command line, used when the program compiles and links, contains the following:

-L/Users/administrator/boost_1_54_0/lib -lboost_filesystem

... And the path and filename indicated (both libboost_filesystem.a and libboost_filesystem.dylib) exist at the path indicated.

The linker cannot find the Boost function boost::filesystem::portable_posix_name(std::string const &):

Undefined symbols for architecture x86_64: "boost::filesystem::portable_posix_name(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)"

However, I do see that this function exists in both the .a and .dylib files in question:

nm -m ./libboost_filesystem.a reveals 00000000000090f0 (__TEXT,__text) external __ZN5boost10filesystem19portable_posix_nameERKSs, and running the mangled function name __ZN5boost10filesystem19portable_posix_nameERKSs line through the demangler reveals:

_boost::filesystem::portable_posix_name(std::string const&)

... I trust that the underscore that precedes the name is correct, because other functions that ARE found also have the preceding underscore.

(The .dylib file also contains the same mangled string).

I have confirmed that the architecture of both the .a and .dylib files are correct: otool -hv ./libboost_filesystem.a shows 'x86_64' through-and-through (and ditto for the .dylib).

Just to be sure the library was actually being found and linked, I changed the name of the library in the compile command line as follows:

-L/Users/administrator/boost_1_54_0/lib -lboost_filesystemm

(notice the double mm at the end of the filename), just to confirm that that a "library not found" error was returned, and it was: ld: library not found for -lboost_filesystemm. I have also confirmed that the only occurrences in the file system of the libboost_filesystem.a and .dylib files are those within the given Boost directory tree (one in the /lib directory, and another one of the same size and almost identical creation date/time in the /bin.v2 subdirectory); also, changing the -L/Users/administrator/boost_1_54_0/lib line to make it junk causes a ld: library not found for -lboost_filesystem error to appear.

Oddly, when I grep the nm -m output for the presence of boost::filesystem::is_directory, no results appear in the symbol table for the library for the latter function, even though there is no linker error for this function. This seems awfully backwards to me (the function that does not appear in the library links fine, but the function that does appear in the library gives a linker error?) - but that question is for another day (and, perhaps, there actually would be an undefined symbol error for this function, but it's not being shown due to the first undefined symbol error).

My question is: Why is this symbol not found, despite the fact that the correct library, with the correct architecture, with the correct external symbol, is being linked?


In response to @Sebastian's answer, I am here pasting the full command line for the linker. This command line is created by Qt (this is a Qt project).

Note that the -lboost_filesystem argument appears after all object files have been listed.

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++ -headerpad_max_install_names -Wl,-syslibroot,/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk -stdlib=libc++ -mmacosx-version-min=10.7 -o NewGene.app/Contents/MacOS/NewGene main.o newgenemainwindow.o newgenecreateoutput.o newgeneselectvariables.o newgenevariablesummary.o newgenetabwidget.o newgenevariablegroup.o newgenevariables.o newgenevariablegroupsscrollarea.o newgenevariablestoolboxwrapper.o newgenevariablestoolbox.o newgenevariablesummaryscrollarea.o newgenevariablesummarygroup.o kadcolumnselectionbox.o timerangebox.o newgenewidget.o uisettingsmanager.o uimodelmanager.o uidocumentmanager.o uistatusmanager.o globals.o uimanager.o settingchangeresponseindicator.o settingchangerequestindicator.o settingchangeindicator.o projectsettingchangeindicator.o globalsettingchangeindicator.o settingchangeresponseitem.o settingchangerequestitem.o settingchangeitem.o projectsettingchangeitem.o globalsettingchangeitem.o globalsettingchangerequestindicator.o globalsettingchangeresponseindicator.o globalsettingchangerequestitem.o globalsettingchangeresponseitem.o projectsettingchangerequestindicator.o projectsettingchangeresponseindicator.o projectsettingchangerequestitem.o projectsettingchangeresponseitem.o modelchangeresponse.o modelchangerequest.o modelchangeindicator.o modelchangeresponseitem.o modelchangerequestitem.o modelchangeitem.o uiprojectmanager.o newgenefilenames.o uiloggingmanager.o newgeneapplication.o uiallsettings.o uisetting.o uimessager.o uiinputproject.o uioutputproject.o uiinputmodel.o uioutputmodel.o uiallprojectsettings.o uimodel.o uiproject.o uiinputprojectsettings.o uioutputprojectsettings.o uiallglobalsettings.o uiallglobalsettings_list.o uiinputprojectsettings_list.o uioutputprojectsettings_list.o uithreadmanager.o uitriggermanager.o uimodelsettings.o uiinputmodelsettings.o uioutputmodelsettings.o eventloopthreadmanager.o workqueuemanager.o outputprojectworkqueue_base.o inputprojectworkqueue_base.o inputprojectworkqueue.o outputprojectworkqueue.o inputmodelworkqueue_base.o outputmodelworkqueue_base.o inputmodelworkqueue.o outputmodelworkqueue.o inputprojectsettingsworkqueue_base.o outputprojectsettingsworkqueue_base.o globalsettingsworkqueue_base.o inputmodelsettingsworkqueue_base.o outputmodelsettingsworkqueue_base.o globalsettingsworkqueue.o inputmodelsettingsworkqueue.o outputmodelsettingsworkqueue.o inputprojectsettingsworkqueue.o outputprojectsettingsworkqueue.o uiuidatamanager.o uiuiactionmanager.o uimodelactionmanager.o uiprojectmanagerworkqueue_base.o uiprojectmanagerworkqueue.o uiwidgetdatarefresh.o uimessagersingleshot.o modelworkqueue.o uiaction.o variablegroupsetmemberselectionchange.o kadwidgetsscrollarea.o kadspinbox.o kadcountchange.o generateoutput.o newgenedatetimewidget.o timerangechange.o newgenegenerateoutput.o generaloptions.o qrc_NewGeneResources.o moc_newgenemainwindow.o moc_newgenecreateoutput.o moc_newgeneselectvariables.o moc_newgenevariablesummary.o moc_newgenetabwidget.o moc_newgenevariablegroup.o moc_newgenevariables.o moc_newgenevariablegroupsscrollarea.o moc_newgenevariablestoolboxwrapper.o moc_newgenevariablestoolbox.o moc_newgenevariablesummaryscrollarea.o moc_newgenevariablesummarygroup.o moc_kadcolumnselectionbox.o moc_timerangebox.o moc_uisettingsmanager.o moc_uimodelmanager.o moc_uidocumentmanager.o moc_uistatusmanager.o moc_globalsettingchangerequestindicator.o moc_globalsettingchangeresponseindicator.o moc_globalsettingchangerequestitem.o moc_globalsettingchangeresponseitem.o moc_projectsettingchangerequestindicator.o moc_projectsettingchangeresponseindicator.o moc_projectsettingchangerequestitem.o moc_projectsettingchangeresponseitem.o moc_modelchangeresponse.o moc_modelchangerequest.o moc_modelchangeindicator.o moc_modelchangeresponseitem.o moc_modelchangerequestitem.o moc_modelchangeitem.o moc_uiprojectmanager.o moc_uiloggingmanager.o moc_newgeneapplication.o moc_uimessager.o moc_uiinputproject.o moc_uioutputproject.o moc_uiinputmodel.o moc_uioutputmodel.o moc_uiinputprojectsettings.o moc_uioutputprojectsettings.o moc_uiallglobalsettings.o moc_uithreadmanager.o moc_uitriggermanager.o moc_uiinputmodelsettings.o moc_uioutputmodelsettings.o moc_workqueuemanager.o moc_uiuidatamanager.o moc_uiuiactionmanager.o moc_uimodelactionmanager.o moc_kadwidgetsscrollarea.o moc_kadspinbox.o moc_newgenedatetimewidget.o moc_newgenegenerateoutput.o
-F/Users/administrator/Qt/5.1.1/clang_64/lib -L/Users/administrator/newgene/NewGeneUI/NewGene/../../NewGeneBackEnd/OSX/NewGene/DerivedData/NewGene/Build/Products/Debug -lNewGene -L/Users/administrator/boost_1_54_0/lib -lboost_filesystem -framework QtWidgets -framework QtGui -framework QtCore -framework OpenGL -framework AGL

回答1:

In the linker commandline, you must put the library ("-l") after the object file which references the symbol. Maybe you already did, and you have another problem. But since you didn't show the whole commandline, we can't know.



回答2:

A giveaway was the std::__1 in the linker's warning message. It was an indication that libc++ internally creates a distinct namespace for standard library classes such as string specifically to force linker errors, because the C++ library that is included by default on OS X is incompatible with use of libc++.

More details, with links, are given in a question I posted while attempting to answer this question: Boost: Why is toolset listed in ~/user-config.jam not available to ./b2?

The answer is to rebuild Boost on OS X, specifying both clang as the compiler, and libc++ as the standard C++ library. (Again, see linked question for details.)