Bug in UNITY builds combined with OBJECT libraries
Trying to convert my CMake files to use the new CMake 3.16.0 unity builds is failing, in some but not all situations where I use OBJECT libraries. It's exceedingly strange: it even fails differently on Linux and MacOS (with the same source code environment). This makes me believe it's a coding error for sure.
It took me quite a while to track down because my initial attempt at a simplified version didn't fail at all. However I have a stripped down CMake file which shows the error on both Linux and MacOS.
Here's a repro case:
$ mkdir test && cd test
$ cat > CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(Test C)
add_library(foo OBJECT foo.c)
add_library(bar STATIC bar.c)
add_executable(exe exe.c)
target_link_libraries(exe PRIVATE foo)
$ touch foo.c bar.c
$ echo 'int main() { return 0; }' > exe.c
$ mkdir ../obj && cd ../obj
$ rm -rf * && cmake ../test && make
...
-- Build files have been written to: /home/pds/src/cmake/obj
Scanning dependencies of target foo
[ 20%] Building C object CMakeFiles/foo.dir/foo.c.o
[ 20%] Built target foo
Scanning dependencies of target exe
[ 40%] Building C object CMakeFiles/exe.dir/exe.c.o
[ 60%] Linking C executable exe
[ 60%] Built target exe
Scanning dependencies of target bar
[ 80%] Building C object CMakeFiles/bar.dir/bar.c.o
[100%] Linking C static library libbar.a
[100%] Built target bar
Works great without unity, but if I enable unity:
$ rm -rf * && cmake -DCMAKE_UNITY_BUILD=ON ../test && make
...
-- Build files have been written to: /home/pds/src/cmake/obj
Scanning dependencies of target foo
[ 20%] Building C object CMakeFiles/foo.dir/Unity/unity_0.c.o
[ 20%] Built target foo
Scanning dependencies of target exe
[ 40%] Building C object CMakeFiles/exe.dir/Unity/unity_0.c.o
make[2]: *** No rule to make target 'CMakeFiles/foo.dir/foo.c.o', needed by 'exe'. Stop.
make[1]: *** [CMakeFiles/Makefile2:80: CMakeFiles/exe.dir/all] Error 2
make: *** [Makefile:84: all] Error 2
The problem is that although a unity file is created for the object library, the link line and dependency for the exe
target is the .o
file (foo.c.o
) not the unity file.
Here's the very strange thing: if I remove bar
, the STATIC library, the problem goes away even though I don't actually use bar
at all in exe
!
I've seen this happen also if the main target including the OBJECT library is itself a STATIC library, rather than an executable, but I can't figure out how to reproduce that in a small test case.