View Issue Details [ Jump to Notes ] | [ Print ] | ||||||||
ID | Project | Category | View Status | Date Submitted | Last Update | ||||
0014874 | CMake | CMake | public | 2014-04-14 11:50 | 2015-01-05 08:38 | ||||
Reporter | zub | ||||||||
Assigned To | Brad King | ||||||||
Priority | normal | Severity | minor | Reproducibility | always | ||||
Status | closed | Resolution | fixed | ||||||
Platform | x86_64 | OS | Linux | OS Version | Debian sid | ||||
Product Version | CMake 2.8.12.1 | ||||||||
Target Version | CMake 3.1 | Fixed in Version | CMake 3.1 | ||||||
Summary | 0014874: Static library can miss some object files | ||||||||
Description | When creating a static library using binutils (ar) and there exist a duplicate object name (e.g. a/Foo.cpp.o, b/Foo.cpp.o), the resulting static library can end up having only one of the duplicate objects. My reading of ar man page implies ar in general is OK with duplicate object names. Also, creating a simple CMake project (just a/foo.cpp, b/foo.cpp, add_library(test STATIC a/foo.cpp b/foo.cpp) results in a correct libtest.a. This bug only happens if there are many objects. This affects how CMake invokes ar. By default CMake invokes ar for the first time for a library like this: ar cr libtest.a path/to/a/foo.cpp.o path/to/b/foo.cpp.o ... and if this is the only invocation, it produces a correct libtest.a. But if there are many objects, CMake invokes ar several times, using the following for subsequent calls: ar r libtest.a other objects... Now if it happens that the first duplicate object is added in one invocation of ar, and then CMake invokes ar again to add another, ar just replaces the previous object. When I set: set(CMAKE_CXX_ARCHIVE_APPEND "<CMAKE_AR> <LINK_FLAGS> q <TARGET> <OBJECTS>") to use "q" instead of "r", the issue is resolved for me, so the fix could be just using "q" when adding objects (CMAKE_CXX_ARCHIVE_APPEND, CMAKE_C_ARCHIVE_APPEND and perhaps also CMAKE_CXX_ARCHIVE_CREATE and CMAKE_C_ARCHIVE_CREATE, though this probably won't make a difference). But I'm not sure how do other ar's handle this. I tested this using "GNU ar (GNU Binutils for Debian) 2.24". | ||||||||
Steps To Reproduce | The issue is deterministic, but it does not occur for every project with duplicate object names - it depends on the project. To trigger this a project with many objects is required so that CMake in fact does invoke ar multiple times. Also, the duplicate objects must find their way into multiple invocations of ar, e.g.: ar cr libtest.a objects... a/foo.cpp.o objects... ar r libtest.a objects... b/foo.cpp.o objects... Then ar removes the previous foo.cpp.o. Creating a standalone testcase seems not so trivial; I run into this on a real project. If necessary, I can try to create one. | ||||||||
Tags | No tags attached. | ||||||||
Attached Files | |||||||||
Relationships | |||||||||||
|
Relationships |
Notes | |
(0035695) Brad King (manager) 2014-04-14 14:03 |
Good catch, thanks. I think "q" will work because the only platform information file that uses the separate create/append steps is Windows-GNU.cmake where we know we have the GNU archiver. |
(0035702) Marcel Loose (developer) 2014-04-15 03:26 |
Well, there's one problem. `ar` doesn't record path names (see, e.g. https://stackoverflow.com/questions/4907121/static-library-having-object-files-with-same-name-ar [^]). How are you going to distinguish the two identically named object files? $ touch a.o b.o $ ar cr foo.a a.o b.o $ ar tv foo.a rw-r--r-- 1000/1000 0 Apr 15 09:23 2014 a.o rw-r--r-- 1000/1000 0 Apr 15 09:23 2014 b.o $ mkdir a b $ touch a/a.o b/b.o $ ar q foo.a a/a.o b/b.o $ ar tv foo.a rw-r--r-- 1000/1000 0 Apr 15 09:23 2014 a.o rw-r--r-- 1000/1000 0 Apr 15 09:23 2014 b.o rw-r--r-- 1000/1000 0 Apr 15 09:24 2014 a.o rw-r--r-- 1000/1000 0 Apr 15 09:24 2014 b.o |
(0035703) zub (reporter) 2014-04-15 03:52 |
Yes, the archive ends up with duplicate file names but when I look into binutils ar man page I think this is a supported usecase. binutils ar supports this modifier: N Uses the count parameter. This is used if there are multiple entries in the archive with the same name. Extract or delete instance count of the given name from the archive. so it is possible to selectively extract individual objects: $ mkdir a b $ echo a > a/foo.o $ echo b > b/foo.o $ ar q foo.a a/foo.o b/foo.o ar: creating foo.a $ ar xvN 1 foo.a foo.o && cat foo.o x - foo.o a $ ar xvN 2 foo.a foo.o && cat foo.o x - foo.o b Indeed, one has to be careful when extracting the objects. But simply using the static library for linking seems to work OK. I think linker doesn't care about the object names. |
(0035707) Brad King (manager) 2014-04-15 09:02 |
Patch applied: Windows-GNU: Support duplicate object names in large archives http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=39d0ade0 [^] |
(0035721) zub (reporter) 2014-04-15 17:05 |
Unfortunately the issue is not yet resolved. I can still reproduce it with 8472ef243ffc9988ea8fb83cbc7acdf3f0daa239. I didn't fully understand Brad King's original comment. The bug happens not only on MinGW, but also on Linux. I experienced the issue in Debian. There seem to be several places where the ar options are set. Grepping in Modules/ brings up: * CMakeCInformation.cmake, CMakeCXXInformation.cmake and CMakeFortranInformation.cmake - these set CMAKE_lang_ARCHIVE_... to some default value if not set elsewhere * Platform/Windows-GNU.cmake - this has been resolved by http://cmake.org/gitweb?p=cmake.git;a=commit;h=39d0ade0 [^] * Compiler/TI-C.cmake and Compiler/TI-CXX.cmake - for a TI compiler If I replace the "r" with "q" in the CMakeC/CXX/FotranInformation.cmake I can no longer reproduce the issue, so I believe that fixes it with GCC on Linux. This is the patch I used and tested on my box: http://linux.fjfi.cvut.cz/~zub/0001-GNU-Support-duplicate-object-names-in-large-archives.patch [^] (TBH I tested CXX only, but I think it's reasonable to assume the same behavior with C and Fortran.) As for the TI compiler - it might be good to change it there too but I don't have the TI toolchain and I have no idea about their ar, so I can't test it. |
(0035722) Brad King (manager) 2014-04-16 08:12 |
Re 0014874:0035721: Ugh, I don't know how I missed those. We need only to grep for every place that sets the append rule: $ git grep -l ARCHIVE_APPEND v3.0.0-rc3 -- Modules v3.0.0-rc3:Modules/CMakeCInformation.cmake v3.0.0-rc3:Modules/CMakeCXXInformation.cmake v3.0.0-rc3:Modules/CMakeFortranInformation.cmake v3.0.0-rc3:Modules/Platform/Windows-GNU.cmake |
(0035723) Brad King (manager) 2014-04-16 08:14 |
I think "q" is a POSIX ar option. It appears in "man ar" on several old UNIX machines too. Here is the more general fix: Support duplicate object names in large archives http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f54be6c0 [^] |
(0035724) zub (reporter) 2014-04-16 08:27 |
That fix will solve the issue for me. What about Compiler/TI-C.cmake and Compiler/TI-CXX.cmake? |
(0035725) Brad King (manager) 2014-04-16 08:34 |
Re 0014874:0035724: The TI modules do not add any append rules, and I don't have the toolchain to test it. See 0014876 for dicussion on a rewrite of the TI modules. |
(0035730) Brad King (manager) 2014-04-16 14:07 |
Re 0014874:0035723: I rebased the fix back on the commit it generalizes: Support duplicate object names in large archives http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1ec6485c [^] |
(0035735) Brad King (manager) 2014-04-17 10:08 |
The more general fix in 0014874:0035730 is now in 'master' and will be in 3.1. |
(0037571) Robert Maynard (manager) 2015-01-05 08:38 |
Closing resolved issues that have not been updated in more than 4 months. |
Notes |
Issue History | |||
Date Modified | Username | Field | Change |
2014-04-14 11:50 | zub | New Issue | |
2014-04-14 14:02 | Brad King | Relationship added | related to 0006284 |
2014-04-14 14:03 | Brad King | Note Added: 0035695 | |
2014-04-15 03:26 | Marcel Loose | Note Added: 0035702 | |
2014-04-15 03:52 | zub | Note Added: 0035703 | |
2014-04-15 09:02 | Brad King | Note Added: 0035707 | |
2014-04-15 09:03 | Brad King | Assigned To | => Brad King |
2014-04-15 09:03 | Brad King | Status | new => resolved |
2014-04-15 09:03 | Brad King | Resolution | open => fixed |
2014-04-15 09:03 | Brad King | Fixed in Version | => CMake 3.1 |
2014-04-15 09:03 | Brad King | Target Version | => CMake 3.1 |
2014-04-15 17:05 | zub | Note Added: 0035721 | |
2014-04-15 17:05 | zub | Status | resolved => feedback |
2014-04-15 17:05 | zub | Resolution | fixed => reopened |
2014-04-16 07:40 | Brad King | Status | feedback => assigned |
2014-04-16 07:40 | Brad King | Resolution | reopened => open |
2014-04-16 07:40 | Brad King | Fixed in Version | CMake 3.1 => |
2014-04-16 08:12 | Brad King | Note Added: 0035722 | |
2014-04-16 08:14 | Brad King | Note Added: 0035723 | |
2014-04-16 08:27 | zub | Note Added: 0035724 | |
2014-04-16 08:34 | Brad King | Note Added: 0035725 | |
2014-04-16 14:07 | Brad King | Note Added: 0035730 | |
2014-04-17 10:08 | Brad King | Note Added: 0035735 | |
2014-04-17 10:08 | Brad King | Status | assigned => resolved |
2014-04-17 10:08 | Brad King | Resolution | open => fixed |
2014-04-17 10:08 | Brad King | Fixed in Version | => CMake 3.1 |
2014-06-26 09:16 | Nils Gladitz | Relationship added | has duplicate 0014994 |
2015-01-05 08:38 | Robert Maynard | Note Added: 0037571 | |
2015-01-05 08:38 | Robert Maynard | Status | resolved => closed |
Issue History |
Copyright © 2000 - 2018 MantisBT Team |