MantisBT - CMake
View Issue Details
0011844CMakeCMakepublic2011-02-11 05:142011-11-11 10:45
Matthew Bentham 
Brad King 
normalmajoralways
closedfixed 
Apple MacOS X10.4.10
CMake 2.8.3 
CMake 2.8.5CMake 2.8.5 
0011844: Xcode universal binary build interacts badly with Xcode depends helper
CMake Xcode projects contain rules to delete out-of-date files during the build.

When building more than one architecture, the rules are incorrect and, depending on timing and number of Xcode processes, delete up-to-date files as well, which causes build failures as Xcode tries to use them as inputs into later build stages.

Xcode reports errors similar to this:

CreateUniversalBinary Debug/prog4 normal "i386 x86_64"
cd /Users/mjb67local/Documents/foo/xcode-depends-bug
/usr/bin/lipo -create /Users/mjb67local/Documents/foo/xcode-depends-bug/test_xcode_depends.build/Debug/prog4.build/Objects-normal/i386/prog4 /Users/mjb67local/Documents/foo/xcode-depends-bug/test_xcode_depends.build/Debug/prog4.build/Objects-normal/x86_64/prog4 -output /Users/mjb67local/Documents/foo/xcode-depends-bug/Debug/prog4

/usr/bin/lipo: can't open input file: /Users/mjb67local/Documents/foo/xcode-depends-bug/test_xcode_depends.build/Debug/prog4.build/Objects-normal/i386/prog4 (No such file or directory)
Command /usr/bin/lipo failed with exit code 1

It seems that the XCODE_DEPENDS_HELPER.make script contains rules like this:


/Users/mjb67local/Documents/foo/xcode-depends-bug/RelWithDebInfo/prog4:
    /bin/rm -f /Users/mjb67local/Documents/foo/xcode-depends-bug/RelWithDebInfo/prog4
    /bin/rm -f /Users/mjb67local/Documents/foo/xcode-depends-bug/test_xcode_depends.build/RelWithDebInfo/prog4.build/Objects-normal/i386/prog4
    /bin/rm -f /Users/mjb67local/Documents/foo/xcode-depends-bug/test_xcode_depends.build/RelWithDebInfo/prog4.build/Objects-normal/x86_64/prog4

Which will delete both architecture-specific files during an Xcode IDE build (or an xcodebuild -parllelizeTargets build) if lipo has not yet written to the universal binary file.
This CMakeLists file:

cmake_minimum_required(VERSION 2.8)
project("test_xcode_depends")
set(CMAKE_OSX_ARCHITECTURES "i386;x86_64")
add_executable("prog1" foo1.c)
add_executable("prog2" foo1.c)
add_executable("prog3" foo1.c)
add_executable("prog4" foo1.c)
add_executable("prog5" foo1.c)
add_executable("prog6" foo1.c)

With commands:

cmake -G Xcode
cmake --build . --clean-first -- -parallelizeTargets

Will produce the error pretty reliably. On machines with lots of cores a larger number of independent targets might be necessary. Basically the error occurs when the post-build steps of one of the targets gets run during the compilation steps of one of the other targets.
I suspect it would be fixed if XCODE_DEPENDS_HELPER.make looked something like this instead:

xcode-depends-bug/RelWithDebInfo/prog4: xcode-depends-bug/test_xcode_depends.build/RelWithDebInfo/prog4.build/Objects-normal/i386/prog4 xcode-depends-bug/test_xcode_depends.build/RelWithDebInfo/prog4.build/Objects-normal/x86_64/prog4
    /bin/rm -f xcode-depends-bug/RelWithDebInfo/prog4

xcode-depends-bug/test_xcode_depends.build/RelWithDebInfo/prog4.build/Objects-normal/i386/prog4:
    /bin/rm -f xcode-depends-bug/test_xcode_depends.build/RelWithDebInfo/prog4.build/Objects-normal/i386/prog4

xcode-depends-bug/test_xcode_depends.build/RelWithDebInfo/prog4.build/Objects-normal/x86_64/prog4:
    /bin/rm -f xcode-depends-bug/test_xcode_depends.build/RelWithDebInfo/prog4.build/Objects-normal/x86_64/prog4
No tags attached.
zip xcode-depends-bug.zip (750) 2011-02-11 05:14
https://public.kitware.com/Bug/file/3691/xcode-depends-bug.zip
Issue History
2011-02-11 05:14Matthew BenthamNew Issue
2011-02-11 05:14Matthew BenthamFile Added: xcode-depends-bug.zip
2011-02-11 06:31Johan BjörkNote Added: 0025389
2011-04-14 14:38David ColeAssigned To => David Cole
2011-04-14 14:38David ColeStatusnew => assigned
2011-04-14 14:38David ColeTarget Version => CMake 2.8.5
2011-06-06 16:19Brad KingNote Added: 0026680
2011-06-06 18:06Brad KingAssigned ToDavid Cole => Brad King
2011-06-06 18:06Brad KingNote Added: 0026681
2011-06-07 08:20Brad KingStatusassigned => resolved
2011-06-07 08:20Brad KingFixed in Version => CMake 2.8.5
2011-06-07 08:20Brad KingResolutionopen => fixed
2011-11-11 10:45David ColeNote Added: 0027763
2011-11-11 10:45David ColeStatusresolved => closed

Notes
(0025389)
Johan Björk   
2011-02-11 06:31   
seen same issue. thanks for tracking down the cause, now hoping for a fix :)
(0026680)
Brad King   
2011-06-06 16:19   
I do not think the proposed fix is enough. There is still a race condition. Between when the make tool determines that a file is out of date and when it actually removes the file a parallel build step may create it.

The XCODE_DEPEND_HELPER was written originally with the assumption that only one target builds at a time. It runs during a post-build phase after a target completes building with the goal of wiping out any files that depend on the target just completed. This can work in parallel if the set of targets considered during the depend helper phase of a given target is only those targets that depend on it (i.e. its dependents). The dependents cannot possibly be building because they cannot start until the original target finishes.

In order to fix this we need to generate a separate entry point into the XCODE_DEPEND_HELPER makefile for each target that simply lists its dependents. The post-build phase for a given target must use the corresponding entry point. With this approach there is no need to evaluate each architecture separately.
(0026681)
Brad King   
2011-06-06 18:06   
This should do it:

  http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=44cdae92 [^]
(0027763)
David Cole   
2011-11-11 10:45   
Closing resolved issues that have not been updated in more than 4 months.