MantisBT - CMake
View Issue Details
0010342CMakeCMakepublic2010-02-26 10:472016-06-10 14:31
Manuel Massing 
Kitware Robot 
normalmajoralways
closedmoved 
CMake-2-8 
 
0010342: Mac OsX: Common symbols of c static librarties are not exported
On MacOSX, ranlib does not export common symbols, in contrast to the behaviour on other platforms.

This leads to link errors when linking against a static C library with common symbols (e.g. variables declared via the extern keyword will result in unresolved symbols). Attached is a minimal testcase to illustrate this.

This bug was already reported by Bob Tanner
(see http://www.cmake.org/pipermail/cmake/2009-June/029943.html [^]). The workaround,
also reported by Bob Tanner, is to invoke ranlib with a "-c" flag when building the library.
MacOS 10.6.2, ranlib version: "Apple Computer, Inc. version cctools-750"
Affects all tested cmake versions (2.8.0, 2.6.4 and cmake 2.9.0)
No tags attached.
gz testcase.tar.gz (635) 2010-02-26 10:47
https://public.kitware.com/Bug/file/2908/testcase.tar.gz
Issue History
2010-02-26 10:47Manuel MassingNew Issue
2010-02-26 10:47Manuel MassingFile Added: testcase.tar.gz
2010-02-26 10:58Bill HoffmanStatusnew => assigned
2010-02-26 10:58Bill HoffmanAssigned To => Brad King
2010-02-26 16:57Brad KingNote Added: 0019653
2010-03-02 08:30Manuel MassingNote Added: 0019683
2010-06-10 14:01Brad KingNote Added: 0020975
2010-06-10 14:28Brad KingNote Added: 0020976
2010-12-07 11:52K. Noel BelcourtNote Added: 0023756
2010-12-07 12:17Brad KingNote Added: 0023757
2010-12-07 12:32K. Noel BelcourtNote Added: 0023758
2010-12-07 12:46K. Noel BelcourtNote Added: 0023759
2012-03-02 10:40Nick BrownNote Added: 0028791
2012-03-02 11:47Brad KingNote Added: 0028794
2012-03-02 11:47Brad KingAssigned ToBrad King =>
2012-03-02 11:47Brad KingStatusassigned => backlog
2016-06-10 14:27Kitware RobotNote Added: 0041658
2016-06-10 14:27Kitware RobotStatusbacklog => resolved
2016-06-10 14:27Kitware RobotResolutionopen => moved
2016-06-10 14:27Kitware RobotAssigned To => Kitware Robot
2016-06-10 14:31Kitware RobotStatusresolved => closed

Notes
(0019653)
Brad King   
2010-02-26 16:57   
I've seen at least one project use "-fno-common" to avoid this problem.

From "man ranlib":

       -c Include common symbols as definitions with respect to the table
              of contents. This is seldom the intended behavior for linking
              from a library, as it forces the linking of a library member
              just because it uses an uninitialized global that is undefined
              at that point in the linking. This option is included only
              because this was the original behavior of ranlib. This option
              is not the default.

This seems to say it is not the preferred behavior on Mac. Any idea why? I'm not against adding the flag but I wonder why it is not default.
(0019683)
Manuel Massing   
2010-03-02 08:30   
Hi Brad, thanks for looking into this.
I do not have much experience on the platform, so unfortunately I am unsure why
this is not the default option. The man-page to ranlib seems to indicate
that libtool ( http://developer.apple.com/mac/library/documentation/Darwin [^]
/Reference/ManPages/man1/libtool.1.html ) is preferred over ranlib altogether, so
maybe this is the reason for the depreciation note?
(0020975)
Brad King   
2010-06-10 14:01   
You can probably work around this problem by adding

  SET(CMAKE_C_ARCHIVE_FINISH "<CMAKE_RANLIB> -c <TARGET>")

after your project() command.
(0020976)
Brad King   
2010-06-10 14:28   
Building your test case in Xcode also fails. It creates the archive using libtool:

/Developer/usr/bin/libtool -static -arch_only x86_64 -syslibroot /Developer/SDKs/MacOSX10.6.sdk "-L/.../Debug" -filelist "/.../Project.build/Debug/staticlib.build/Objects-normal/x86_64/staticlib.LinkFileList" -o "/.../Debug/libstaticlib.a"

Adding "-c" to the OTHER_LDFLAGS option in the Xcode IDE solves the problem.
(0023756)
K. Noel Belcourt   
2010-12-07 11:52   
Hi,

I gave your work around mentioned above a try, it doesn't seem to work. Note that I'm on OSX 10.5.8 and not using Xcode and am using Intel compilers. Is there any other way to pass -c to ranlib?

Here's what gcc has to say about -fno-common.

-fno-common
    In C, allocate even uninitialized global variables in the data section of the object file, rather than generating them as common blocks. This has the effect that if the same variable is declared (without "extern") in two different compilations, you will get an error when you link them. The only reason this might be useful is if you wish to verify that the program will work on other systems which always work this way.

So given that -fno-common isn't an option and your workaround doesn't seem to work, is there any CMAKE_RANLIB_FLAGS option we can use or add so I can pass -c to ranlib? I'm more or less dead unless I start making code changes (which I can't do to QA'd code).

Is there a way to create static libraries on the Mac using libtool rather than usnig the ar / ranlib shuffle? Perhaps an option to select which approach to use?

-- Noel
(0023757)
Brad King   
2010-12-07 12:17   
I disagree with gcc's case against -fno-common. I've never seen a C compiler other than on Mac that uses the common block for this case. It's bad behavior IMO, and -fno-common disables it. Does it avoid your problem or not?

> is there any CMAKE_RANLIB_FLAGS option
[snip]
> create static libraries on the Mac using libtool

No to both. That's why a workaround is needed.

The CMAKE_C_ARCHIVE_FINISH workaround may need to be set for CMAKE_CXX_ARCHIVE_FINISH and CMAKE_Fortran_ARCHIVE_FINISH too.

Is CMAKE_C_CREATE_STATIC_LIBRARY set to anything? If so that will be used instead of the ARCHIVE rules and the workaround will do nothing.


Anyway, the full fix here is to teach the CMake platform information files to add -c to ranlib calls, and to fix the Xcode generator too.
(0023758)
K. Noel Belcourt   
2010-12-07 12:32   
Hi Brad,

It'll take a while for a clean rebuild so I'll let you know if -fno-common passed to ifort fixes it. I didn't realize Intel supported gcc's -fno-common since they don't document it. I do notice the symbol type changed from C to S which is a step in the right direction.

"C" The symbol is common. Common symbols are uninitialized data. When linking, multiple common symbols may appear with the same name. If the symbol is defined anywhere, the common symbols are treated as undefined references.

"S" The symbol is in an uninitialized data section for small objects.

Also, if I have C, CXX and Fortran all setting the CMAKE_<LANG>_ARCHIVE_FINISH rule, then -c is passed to ranlib. Not sure why it isn't if I only set CMAKE_Fortran_ARCHIVE_FINISH.

Thanks for the help Brad, I'm running so consider this issue closed for me.

-- Noel
(0023759)
K. Noel Belcourt   
2010-12-07 12:46   
Yes, passing -fno-common to ifort works.

Thanks again Brad!

-- Noel
(0028791)
Nick Brown   
2012-03-02 10:40   
Has this been taken any further?
I don't think OSX will change it's behaviour, and and it's still necessary to add -c to ranlib or use -fno-common.
It would be nice if cmake was smart enough to do this by default on OSX and not require adding manually to project files.
(0028794)
Brad King   
2012-03-02 11:47   
Moving to backlog as I have no time to investigate this further.

How does one decide if "ranlib -c" or "--no-common" is the desired solution for a particular project? Adding either by default could pollute existing projects that do not need them.

If someone wants to work on this the patch will need to address both Makefile and Xcode generators.
(0041658)
Kitware Robot   
2016-06-10 14:27   
Resolving issue as `moved`.

This issue tracker is no longer used. Further discussion of this issue may take place in the current CMake Issues page linked in the banner at the top of this page.