# target\_link\_libraries, build order and build parallelism

**URL:** https://discourse.cmake.org/t/target-link-libraries-build-order-and-build-parallelism/313
**Category:** Code
**Created:** [December 3, 2019, 9:02am UTC](https://discourse.cmake.org/t/target-link-libraries-build-order-and-build-parallelism/313 "2019-12-03T09:02:59Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![rnyberg](https://discourse.cmake.org/user_avatar/discourse.cmake.org/rnyberg/32/210_2.png) [@rnyberg](https://discourse.cmake.org/u/rnyberg)
#### Post date: [December 3, 2019, 9:02am UTC](https://discourse.cmake.org/t/target-link-libraries-build-order-and-build-parallelism/313/1 "2019-12-03T09:02:59Z")

</div>

Hi CMake gurus!  
Given the example _CMakeLists.txt_ file below I have a few questions.

1. Why does building _libb_ first build _liba_? As I understand it _liba_ should just be propagated as a link time dependency to whatever actually links it in (_exec_), but I realize I’m missing something.
2. Also I have observed differences in build order between _ninja_, _make_ and _vs2019_. Is there an intended behavior in these cases or is it up to differences in the build systems or bugs?
  - When building _exec_ _ninja_ seems to be able to build _a.cpp_, _b.cpp_, and _c.cpp_ in parallel whereas _vs2019_ does _liba_, _libb_ and _exec_ in sequence.
  - When building _libf_, _ninja_ only compiles _f.cpp_, whereas _make_ and _vs2019_ first builds _libd_.

Do you have any suggestions to increase the parallelism of builds in general when using CMake?

> cmake\_minimum\_required( VERSION 3.16 )  
> project( Hmm LANGUAGES CXX )
> 
> add\_library( liba a.cpp )  
> add\_library( libb b.cpp )  
> target\_link\_libraries( libb PRIVATE liba )  
> add\_executable( exec c.cpp )  
> target\_link\_libraries( exec libb )
> 
> add\_library( libd d.cpp )  
> add\_library( libe INTERFACE )  
> target\_link\_libraries( libe INTERFACE libd )  
> add\_library( libf OBJECT f.cpp )  
> target\_link\_libraries( libf PRIVATE libe )  
> add\_executable( exeg g.cpp $\<TARGET\_OBJECTS:libf\> )  
> target\_link\_libraries( exeg PRIVATE libf )

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [December 3, 2019, 4:07pm UTC](https://discourse.cmake.org/t/target-link-libraries-build-order-and-build-parallelism/313/2 "2019-12-03T16:07:04Z")

</div>

> [@rnyberg](#):
>
> - Why does building _libb_ first build _liba_ ? As I understand it _liba_ should just be propagated as a link time dependency to whatever actually links it in ( _exec_ ), but I realize I’m missing something.
> - Also I have observed differences in build order between _ninja_ , _make_ and _vs2019_ . Is there an intended behavior in these cases or is it up to differences in the build systems or bugs?
> - When building _exec_ _ninja_ seems to be able to build _a.cpp_ , _b.cpp_ , and _c.cpp_ in parallel whereas _vs2019_ does _liba_ , _libb_ and _exec_ in sequence.
> - When building _libf_ , _ninja_ only compiles _f.cpp_ , whereas _make_ and _vs2019_ first builds _libd_ .

This is a guarantee that CMake provides as part of its model. If `liba` has any custom commands attached to it, `libb` can assume they exist because CMake does this. The Ninja generator has logic to relax this dependency if CMake can convince itself that the dependency is unnecessary.

---

<div class="post-metadata">

### Author: ![rnyberg](https://discourse.cmake.org/user_avatar/discourse.cmake.org/rnyberg/32/210_2.png) [@rnyberg](https://discourse.cmake.org/u/rnyberg)
#### Post date: [December 5, 2019, 10:22am UTC](https://discourse.cmake.org/t/target-link-libraries-build-order-and-build-parallelism/313/3 "2019-12-05T10:22:06Z")

</div>

> [@ben.boeckel](#):
>
> This is a guarantee that CMake provides as part of its model. If `liba` has any custom commands attached to it, `libb` can assume they exist because CMake does this. The Ninja generator has logic to relax this dependency if CMake can convince itself that the dependency is unnecessary.

That explains it, thanks! 🙂
