# Is target specific stuff transitive to dependencies?

**URL:** https://discourse.cmake.org/t/is-target-specific-stuff-transitive-to-dependencies/336
**Category:** Usage
**Created:** [December 9, 2019, 2:08am UTC](https://discourse.cmake.org/t/is-target-specific-stuff-transitive-to-dependencies/336 "2019-12-09T02:08:06Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![oscarh](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/o/aca169/32.png) [@oscarh](https://discourse.cmake.org/u/oscarh)
#### Post date: [December 9, 2019, 2:08am UTC](https://discourse.cmake.org/t/is-target-specific-stuff-transitive-to-dependencies/336/1 "2019-12-09T02:08:06Z")

</div>

We have some libraries that are to be consumed by multiple applications, but with different compile definitions or flags. For example, when compiled with app-A, we need -DappA. When compiled with app-B, we need -DappB. In tranditional Makefile, we do it with target specific variables:

> app-A: CFAGS+=-DappA  
> app-A: commonLib
> 
> app-B: CFLAGS+=-DappB  
> app-B: commonLib

With CMake, I expected target specific commands like target\_compile\_definitions to be transitive to dependencies, so I did this:

> add\_subdirectory(commonLib) #where there is add\_library(commonLib …)  
> add\_executable(app-A …)  
> target\_compile\_definitions(app-A PRIVATE appA)  
> target\_link\_libraries(app-A commonLib)

But I didn’t see -DappA was used when compiling the commonLib. Did I do anything wrong? Or it is not transitive to dependencies at all? I have quite a few “common” libraries, and quite a few apps, so it’ll be nice if it is transitive.

---

<div class="post-metadata">

### Author: ![erk](https://discourse.cmake.org/user_avatar/discourse.cmake.org/erk/32/114_2.png) [@erk](https://discourse.cmake.org/u/erk)
#### Post date: [December 9, 2019, 5:05am UTC](https://discourse.cmake.org/t/is-target-specific-stuff-transitive-to-dependencies/336/2 "2019-12-09T05:05:33Z")

</div>

Unless I missed something transitivity goes the other way around, if A depends on B then public INTERFACE on **B** will propagate to A.

In your description `app-A` depends on `commonLib` and `target_compile_definitions(app-A PRIVATE appA)`  
applies to target `app-A` so source any file in `app-A` will be compiled with `-DappA`.

But why/how would this propagate to the `commonLib` compilation?  
If this was propagated this way and `commonLib` was used by **both** `app-A` **and** `app-B` you’ll get both `-DappA` and `-DappB` ?

From my point of view there is 2 options:

- either commonLib is a header only lib and the current scheme should work because `-DappA` will be defined when compiling `app-A`
- or `commonLib` needs to be compiled twice, once for `appA` and once for `appB`.

---

<div class="post-metadata">

### Author: ![oscarh](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/o/aca169/32.png) [@oscarh](https://discourse.cmake.org/u/oscarh)
#### Post date: [December 9, 2019, 6:44am UTC](https://discourse.cmake.org/t/is-target-specific-stuff-transitive-to-dependencies/336/3 "2019-12-09T06:44:59Z")

</div>

> But why/how would this propagate to the `commonLib` compilation?

It’s because there is some conditional code in commonLib like:

> #ifdef appA  
> …  
> #endif  
> #ifdef appB  
> …  
> #endif

I know this is ugly. It could be organized better, but it is a project with long history, I cannot avoid it for now.

So CMake does not have a feature similar to GNU make’s target-specific variables: [GNU make](https://www.gnu.org/software/make/manual/make.html#Target_002dspecific)?

---

<div class="post-metadata">

### Author: ![erk](https://discourse.cmake.org/user_avatar/discourse.cmake.org/erk/32/114_2.png) [@erk](https://discourse.cmake.org/u/erk)
#### Post date: [December 9, 2019, 7:03am UTC](https://discourse.cmake.org/t/is-target-specific-stuff-transitive-to-dependencies/336/4 "2019-12-09T07:03:34Z")

</div>

> So CMake does not have a feature similar to GNU make’s target-specific variables

Yes CMake does just as make. The doc make says:

This feature allows you to define different values for the same variable, based on _the target that make is currently building_.

`target_compile_definitions(app-A PRIVATE appA)`

does that as well.

> It’s because there is some conditional code in commonLib like

Like I said this will work when app-A source file in #including part of commonLib.

The following example works for me:  
[target\_specific\_define.zip](https://discourse.cmake.org/uploads/short-url/ujFhaGtXytN5Y8OL3wb8rcBYgpJ.zip) (1.5 KB)

may be you can provide us with an example of your that does not work as expected?

---

<div class="post-metadata">

### Author: ![oscarh](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/o/aca169/32.png) [@oscarh](https://discourse.cmake.org/u/oscarh)
#### Post date: [December 9, 2019, 8:21am UTC](https://discourse.cmake.org/t/is-target-specific-stuff-transitive-to-dependencies/336/5 "2019-12-09T08:21:36Z")

</div>

Hi, @erk, I understand it works if commonLib is a header only lib. Unfortunately, it is not my case. my commonLib has \*.c files, in which there is:

> #ifdef appA  
> …  
> #endif  
> #ifdef appB  
> …  
> #endif

Thanks  
-Oscar

---

<div class="post-metadata">

### Author: ![erk](https://discourse.cmake.org/user_avatar/discourse.cmake.org/erk/32/114_2.png) [@erk](https://discourse.cmake.org/u/erk)
#### Post date: [December 9, 2019, 8:35am UTC](https://discourse.cmake.org/t/is-target-specific-stuff-transitive-to-dependencies/336/6 "2019-12-09T08:35:05Z")

</div>

Then commonLib shall be compiled twice, once for AppA and once for AppB.  
Did you mean that `make` is doing that _automagically_ ?

Do you have a complete example (using make) that does that?

---

<div class="post-metadata">

### Author: ![oscarh](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/o/aca169/32.png) [@oscarh](https://discourse.cmake.org/u/oscarh)
#### Post date: [December 9, 2019, 8:41am UTC](https://discourse.cmake.org/t/is-target-specific-stuff-transitive-to-dependencies/336/7 "2019-12-09T08:41:56Z")

</div>

I’ll compose an example tomorrow.  
What make can do is to pass -DappA down to commonLib. For example:

app-A: CFLAGS+=-DappA

app-A: commonLib

In your commonLib’s makefile:

commonLib: x.c y.c  
CC …

You’ll see, when x.c is compiled, -DappA is in the compiling command line. Thus, I can choose different feature to compile from the top app’s makefile.

Not sure if this makes sense to you. I’ll get you an example tomorrow.

---

<div class="post-metadata">

### Author: ![erk](https://discourse.cmake.org/user_avatar/discourse.cmake.org/erk/32/114_2.png) [@erk](https://discourse.cmake.org/u/erk)
#### Post date: [December 9, 2019, 9:03am UTC](https://discourse.cmake.org/t/is-target-specific-stuff-transitive-to-dependencies/336/8 "2019-12-09T09:03:57Z")

</div>

It makes perfectly sense (I did use makefile a lot some time ago), but I bet that in that case commonLib is not really a “library” since it shall be _recompiled_ for different app. What you describe is a way to bring in a new commonLib-A into A by specifying a set of source file that need to be recompiled for A.

So you need to create your interface library, with appropriate associated source files in it:

```cmake
add_library(common INTERFACE)
target_include_directories(common INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
target_sources(common INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/common.cpp)

```

then:

```cmake
add_executable(A-app a.cpp)
target_link_libraries(A-app common)
target_compile_definitions(A-app PRIVATE withA)

add_executable(B-app b.cpp)
target_link_libraries(B-app common)
target_compile_definitions(B-app PRIVATE withB)

```

and you’ll get what you want (I guess).  
see:

```auto
$ ninja -v 
[1/6 (4) - 0.155] /usr/bin/c++ -DwithB -I../ -MD -MT CMakeFiles/B-app.dir/common.cpp.o -MF CMakeFiles/B-app.dir/common.cpp.o.d -o CMakeFiles/B-app.dir/common.cpp.o -c ../common.cpp
[2/6 (3) - 0.220] /usr/bin/c++ -DwithA -I../ -MD -MT CMakeFiles/A-app.dir/common.cpp.o -MF CMakeFiles/A-app.dir/common.cpp.o.d -o CMakeFiles/A-app.dir/common.cpp.o -c ../common.cpp
[3/6 (2) - 0.240] /usr/bin/c++ -DwithB -I../ -MD -MT CMakeFiles/B-app.dir/b.cpp.o -MF CMakeFiles/B-app.dir/b.cpp.o.d -o CMakeFiles/B-app.dir/b.cpp.o -c ../b.cpp
[4/6 (2) - 0.285] /usr/bin/c++ -DwithA -I../ -MD -MT CMakeFiles/A-app.dir/a.cpp.o -MF CMakeFiles/A-app.dir/a.cpp.o.d -o CMakeFiles/A-app.dir/a.cpp.o -c ../a.cpp
[5/6 (2) - 0.309] : && /usr/bin/c++ CMakeFiles/B-app.dir/b.cpp.o CMakeFiles/B-app.dir/common.cpp.o -o B-app && :
[6/6 (1) - 0.357] : && /usr/bin/c++ CMakeFiles/A-app.dir/a.cpp.o CMakeFiles/A-app.dir/common.cpp.o -o A-app && :

```

Here comes the archive of this:  
[target\_specific\_define.zip](https://discourse.cmake.org/uploads/short-url/kw1QGxb21IEV3R7561ENw0Ii7DT.zip) (1.7 KB)

---

<div class="post-metadata">

### Author: ![marc.chevrier](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/m/ecb155/32.png) [@marc.chevrier](https://discourse.cmake.org/u/marc.chevrier)
#### Post date: [December 9, 2019, 10:25am UTC](https://discourse.cmake.org/t/is-target-specific-stuff-transitive-to-dependencies/336/9 "2019-12-09T10:25:50Z")

</div>

Even with `GNU Make`, I don’t understand how you get the expected behavior. The `GNU Make` documentation specifies, for target specific variables values:

```auto
Be aware that a given prerequisite will only be built once per invocation of make, at most. If the same file is a prerequisite of multiple targets, and each of those targets has a different value for the same target-specific variable, then the first target to be built will cause that prerequisite to be built and the prerequisite will inherit the target-specific value from the first target. It will ignore the target-specific values from any other targets. 

```

So `CommonLib` will not be compiled twice!

---

<div class="post-metadata">

### Author: ![oscarh](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/o/aca169/32.png) [@oscarh](https://discourse.cmake.org/u/oscarh)
#### Post date: [December 10, 2019, 12:25am UTC](https://discourse.cmake.org/t/is-target-specific-stuff-transitive-to-dependencies/336/10 "2019-12-10T00:25:15Z")

</div>

Hi, @erk  
Your example demonstrated exactly what I want. Thank yo so much.

---

<div class="post-metadata">

### Author: ![oscarh](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/o/aca169/32.png) [@oscarh](https://discourse.cmake.org/u/oscarh)
#### Post date: [December 10, 2019, 12:30am UTC](https://discourse.cmake.org/t/is-target-specific-stuff-transitive-to-dependencies/336/11 "2019-12-10T00:30:33Z")

</div>

@marc.chevrier, let me ellaborate a little bit more. We do compile twice. We have separate makefiles for appA and appB, which include commonLib’s makefile “commonLib.mk”. With GNU make’s target-specific variable feature, the CFLAGS used to compile commonLib can be tuned by its dependant (appA or appB here)
