Difference between PRIVATE and PUBLIC with target_link_libraries

classic Classic list List threaded Threaded
18 messages Options
Reply | Threaded
Open this post in threaded view
|

Difference between PRIVATE and PUBLIC with target_link_libraries

Patrick Boettcher
Hi list,

What is the differences between PRIVATE and PUBLIC when used with
target_link_libraries?

I read the help and understood that it works like in C++: PRIVATE will
make everything which was PUBLIC before also PRIVATE if inherited
privately.

An example:

  add_library(lib1 INTERFACE)
  target_include_directories(lib1 INTERFACE /tmp)

  add_library(lib2 src2.c)
  target_include_directories(lib2 PUBLIC /bin)
  target_link_libraries(lib2 PRIVATE lib1) # PRIVATE here

  add_library(lib3 src3.c)
  target_include_directories(lib3 PUBLIC /bin)
  target_link_libraries(lib3 PUBLIC lib1) # PUBLIC here
 
  add_executable(exe1 exe.c)
  target_link_libraries(exe1 lib2)

  add_executable(exe2 exe.c)
  target_link_libraries(exe2 lib3)


When building exe2 both include-dirs (from lib1 and lib3) are present:

  [..] -I/bin -I/tmp  [..]

as they are for exe1 - however I would have expected to not see /tmp
because lib3 and lib1 are linked privately.

Where is my mistake?

Thanks,
--
Patrick.

--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Difference between PRIVATE and PUBLIC with target_link_libraries

Attila Krasznahorkay
Hi Patrick,

I *think* that these public/private rules behave a bit differently for static libraries than they do for shared ones.

But I have to admit, that based on this code I also would've guessed that -I/tmp would not show up in the build of exe1...

I did manage to use public and private dependencies as expected in my own configurations, so I'm not exactly sure what's going wrong in your case. Which version of CMake did you use for the test?

Cheers,
              Attila

> On 10 May 2016, at 07:59, Patrick Boettcher <[hidden email]> wrote:
>
> Hi list,
>
> What is the differences between PRIVATE and PUBLIC when used with
> target_link_libraries?
>
> I read the help and understood that it works like in C++: PRIVATE will
> make everything which was PUBLIC before also PRIVATE if inherited
> privately.
>
> An example:
>
>  add_library(lib1 INTERFACE)
>  target_include_directories(lib1 INTERFACE /tmp)
>
>  add_library(lib2 src2.c)
>  target_include_directories(lib2 PUBLIC /bin)
>  target_link_libraries(lib2 PRIVATE lib1) # PRIVATE here
>
>  add_library(lib3 src3.c)
>  target_include_directories(lib3 PUBLIC /bin)
>  target_link_libraries(lib3 PUBLIC lib1) # PUBLIC here
>
>  add_executable(exe1 exe.c)
>  target_link_libraries(exe1 lib2)
>
>  add_executable(exe2 exe.c)
>  target_link_libraries(exe2 lib3)
>
>
> When building exe2 both include-dirs (from lib1 and lib3) are present:
>
>  [..] -I/bin -I/tmp  [..]
>
> as they are for exe1 - however I would have expected to not see /tmp
> because lib3 and lib1 are linked privately.
>
> Where is my mistake?
>
> Thanks,
> --
> Patrick.
>
> --
>
> Powered by www.kitware.com
>
> Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ
>
> Kitware offers various services to support the CMake community. For more information on each offering, please visit:
>
> CMake Support: http://cmake.org/cmake/help/support.html
> CMake Consulting: http://cmake.org/cmake/help/consulting.html
> CMake Training Courses: http://cmake.org/cmake/help/training.html
>
> Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html
>
> Follow this link to subscribe/unsubscribe:
> http://public.kitware.com/mailman/listinfo/cmake

--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Difference between PRIVATE and PUBLIC with target_link_libraries

Patrick Boettcher
On Tue, 10 May 2016 11:39:49 +0200
Attila Krasznahorkay <[hidden email]> wrote:

> Hi Patrick,
>
> I *think* that these public/private rules behave a bit differently
> for static libraries than they do for shared ones.
>
> But I have to admit, that based on this code I also would've guessed
> that -I/tmp would not show up in the build of exe1...
>
> I did manage to use public and private dependencies as expected in my
> own configurations, so I'm not exactly sure what's going wrong in
> your case. Which version of CMake did you use for the test?

I'm using cmake 3.5.0.

Thank you for your feedback - I'll try to use shared-libraries, to see
whether it changes something or not

regards,
--
Patrick.
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Difference between PRIVATE and PUBLIC with target_link_libraries

Iosif Neitzke
>> I *think* that these public/private rules behave a bit differently
>> for static libraries than they do for shared ones.

They do.  Assuming main calls a() and b() defined in A_lib and B_lib
respectively, for:
add_library(A_lib STATIC a.c)
add_library(B_lib STATIC b.c)
target_link_libraries(A_lib PRIVATE B_lib)
add_executable(main main.c)
target_link_libraries(main A_lib)

The PRIVATE in "target_link_libraries(A_lib PRIVATE B_lib)" is
useless.  It is the same as writing "target_link_libraries(A_lib
PUBLIC B_lib)", only more confusing to the reader. Static libraries
always link to their dependencies publically.

https://cmake.org/cmake/help/v3.5/command/target_link_libraries.html#libraries-for-a-target-and-or-its-dependents

However, if you change A_lib to be a shared library with
"add_library(A_lib SHARED a.c)" and left the rest of the code the
same, you would now get link errors for main not able to find b(),
because A_lib now does not pass on its dependency on B, it hides it
from main.   Change the last line to "target_link_libraries(main A_lib
B_lib)" and main builds again.
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Difference between PRIVATE and PUBLIC with target_link_libraries

Craig Scott-3
Hopefully the explanation that follows helps clarify what PRIVATE, PUBLIC and INTERFACE mean and do. From my understanding of things, I think there may have been some subtle inaccuracies in some of the discussions so far, so hopefully the following is helpful and if I've got something wrong, then by all means please point out the inaccuracies.

  • When A links in B as PRIVATE, it is saying that A uses B in its implementation, but B is not used in any part of A's public API. Any code that makes calls into A would not need to refer directly to anything from B. An example of this could be a networking library A which can be built to use one of a number of different SSL libraries internally (which B represents). A presents a unified interface for client code which does not reference any of the internal SSL data structures or functions. Client code would have no idea what SSL implementation (B) is being used by A, nor does that client code need to care.
  • When A links in B as INTERFACE, it is saying that A does not use B in its implementation, but B is used in A's public API. Code that calls into A may need to refer to things from B in order to make such calls. One example of this is an interface library which simply forwards calls along to another library but doesn't actually reference the objects on the way through other than by a pointer or reference. Another example is where A is defined in CMake as an interface library, meaning it has no actual implementation itself, it is effectively just a collection of other libraries (I'm probably over-simplifying here, but you get the picture).
  • When A links in B as PUBLIC, it is essentially a combination of PRIVATE and INTERFACE. It says that A uses B in its implementation and B is also used in A's public API.

Consider first what this means for include search paths. If something links against A, it will also need any include search paths from B if B is in A's public API. Thus, if A links in B either as PUBLIC or INTERFACE, then any header search paths defined for target B will also apply to anything that links to A. Any PRIVATE header search path for B will NOT be carried through to anything that links only to A. The target_include_directories() command handles this. The situation with compile flags is analogously handled with target_compile_definitions() and target_compile_options().

Now consider the situation for the actual libraries involved. If A is a shared library, then A will have encoded into it a dependency on B. This information can be inspected with tools like ldd on Linux, otool on Mac and something like Dependency Walker (a.k.a. depends.exe) on Windows. If other code links directly to A, then it also will have encoded into it a dependency on A. It will not, however, have a dependency on B unless A links in B as PUBLIC or INTERFACE. So far, so good. If, however, A is a static library, the situation changes. Static libraries do not carry information about other libraries they depend on. For this reason, when A links in B as PRIVATE and another target C links in A, CMake will still add B to the list of libraries to be linked for C because parts of B are needed by A, but A itself doesn't have that dependency encoded into it. So even though B is an internal implementation detail of A, C still needs B added to the linker command, which CMake conveniently handles for you.

If you were paying careful attention, you would have noticed that when A links in B as PRIVATE, the include directories of B never propagate to something linking to A, but if A is a static library, then the linking of B behaves as though the relationship was PUBLIC. This PRIVATE-becomes-PUBLIC behaviour for static libraries only applies to the linking, not to the other dependencies (compiler options/flags and include search paths). The upshot of all this is that if you select PRIVATE, PUBLIC or INTERFACE based on the explanations in the dot points above, then CMake will ensure dependencies propagate through to where they are required, regardless of whether libraries are static or shared. This does, of course, rely on you the developer not missing any dependencies or specifying the wrong PRIVATE/PUBLIC/INTERFACE relationship.

As a final note, if you call target_link_libraries() and do not specify any of PRIVATE, PUBLIC or INTERFACE, you may be tempted to believe that it will be treated as PUBLIC. The situation is actually more complicated than that though. It may be treated as PUBLIC or PRIVATE, depending on what other target_link_library() calls and/or target property manipulations have been performed. The documentation for target_link_libraries() talks a bit about this, but you have to go digging into the documentation for the target properties it mentions to get an understanding of what circumstances lead to PRIVATE or PUBLIC behaviour.

Hope that helps clarify some things. Sorry if this has gone off on a tangent from the original enquiry, I'm coming in late to this thread.


On Wed, May 11, 2016 at 8:33 PM, iosif neitzke <[hidden email]> wrote:
>> I *think* that these public/private rules behave a bit differently
>> for static libraries than they do for shared ones.

They do.  Assuming main calls a() and b() defined in A_lib and B_lib
respectively, for:
add_library(A_lib STATIC a.c)
add_library(B_lib STATIC b.c)
target_link_libraries(A_lib PRIVATE B_lib)
add_executable(main main.c)
target_link_libraries(main A_lib)

The PRIVATE in "target_link_libraries(A_lib PRIVATE B_lib)" is
useless.  It is the same as writing "target_link_libraries(A_lib
PUBLIC B_lib)", only more confusing to the reader. Static libraries
always link to their dependencies publically.

https://cmake.org/cmake/help/v3.5/command/target_link_libraries.html#libraries-for-a-target-and-or-its-dependents

However, if you change A_lib to be a shared library with
"add_library(A_lib SHARED a.c)" and left the rest of the code the
same, you would now get link errors for main not able to find b(),
because A_lib now does not pass on its dependency on B, it hides it
from main.   Change the last line to "target_link_libraries(main A_lib
B_lib)" and main builds again.
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake



--
Craig Scott
Melbourne, Australia

--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Difference between PRIVATE and PUBLIC with target_link_libraries

Iosif Neitzke
> When A links in B as PRIVATE, it is saying that A uses B in its
> implementation, but B is not used in any part of A's public API.

> When A links in B as INTERFACE, it is saying that A does not use B in its
> implementation, but B is used in A's public API.

> When A links in B as PUBLIC, it is essentially a combination of PRIVATE and
> INTERFACE. It says that A uses B in its implementation and B is also used in
> A's public API.

All totally correct, and that is how visibility for target_link and
target_include commands idiomatically should be used, but I don't
believe anything in CMake ensures the code architecture adheres to
this scheme.
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Difference between PRIVATE and PUBLIC with target_link_libraries

Patrick Boettcher
In reply to this post by Craig Scott-3
On Wed, 11 May 2016 21:58:34 +1000
Craig Scott <[hidden email]> wrote:

[..]

> If you were paying careful attention, you would have noticed that
> when A links in B as PRIVATE, the include directories of B never
> propagate to something linking to A, but if A is a static library,
> then the *linking* of B behaves as though the relationship was
> PUBLIC. This PRIVATE-becomes-PUBLIC behaviour for static libraries
> only applies to the *linking*, not to the other dependencies
> (compiler options/flags and include search paths). The upshot of all
> this is that if you select PRIVATE, PUBLIC or INTERFACE based on the
> explanations in the dot points above, then CMake will ensure
> dependencies propagate through to where they are required, regardless
> of whether libraries are static or shared. This does, of course, rely
> on you the developer not missing any dependencies or specifying the
> wrong PRIVATE/PUBLIC/INTERFACE relationship.

Thank you for you long explanation. It was exactly my understanding.

So cmake 3.5.0 has a bug then because I don't see the behavior you
describe. Have you seen my example I sent in my first mail?

http://public.kitware.com/pipermail/cmake/2016-May/063382.html

Include-dirs from B are propagated to C which links to A which itself
linked privately to B.

Should I file a bug?

regards,
--
Patrick.





 


--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Difference between PRIVATE and PUBLIC with target_link_libraries

Iosif Neitzke
My reading of your examples:

exe1 gets linked to lib2, and lib2/bin is included.  exe1 probably
won't link ultimately because lib2 may need symbols from lib1.
Depends on the structure of the C code between lib2 and lib1.   See
John Lakos for further information on that.

exe2 gets linked to lib3, and gets lib3/bin included because lib3 has
PUBLIC in its own target_include_directories command.  Because exe2
gets lib3, it also gets lib1 and lib1/tmp.

On Thu, May 12, 2016 at 8:19 AM, Patrick Boettcher
<[hidden email]> wrote:

> On Wed, 11 May 2016 21:58:34 +1000
> Craig Scott <[hidden email]> wrote:
>
> [..]
>> If you were paying careful attention, you would have noticed that
>> when A links in B as PRIVATE, the include directories of B never
>> propagate to something linking to A, but if A is a static library,
>> then the *linking* of B behaves as though the relationship was
>> PUBLIC. This PRIVATE-becomes-PUBLIC behaviour for static libraries
>> only applies to the *linking*, not to the other dependencies
>> (compiler options/flags and include search paths). The upshot of all
>> this is that if you select PRIVATE, PUBLIC or INTERFACE based on the
>> explanations in the dot points above, then CMake will ensure
>> dependencies propagate through to where they are required, regardless
>> of whether libraries are static or shared. This does, of course, rely
>> on you the developer not missing any dependencies or specifying the
>> wrong PRIVATE/PUBLIC/INTERFACE relationship.
>
> Thank you for you long explanation. It was exactly my understanding.
>
> So cmake 3.5.0 has a bug then because I don't see the behavior you
> describe. Have you seen my example I sent in my first mail?
>
> http://public.kitware.com/pipermail/cmake/2016-May/063382.html
>
> Include-dirs from B are propagated to C which links to A which itself
> linked privately to B.
>
> Should I file a bug?
>
> regards,
> --
> Patrick.
>
>
>
>
>
>
>
>
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Difference between PRIVATE and PUBLIC with target_link_libraries

Patrick Boettcher
On Thu, 12 May 2016 08:47:33 -0500
iosif neitzke <[hidden email]> wrote:

> My reading of your examples:
>
> exe1 gets linked to lib2, and lib2/bin is included.  exe1 probably
> won't link ultimately because lib2 may need symbols from lib1.
> Depends on the structure of the C code between lib2 and lib1.   See
> John Lakos for further information on that.

It links - because it is a STATIC library - so propagated even though
it's PRIVATE.

My problem is just the include-dir of lib1 (/tmp) which should _not_ be
propagated to exe1, but it is propagated.

regards,
--
Patrick.
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Difference between PRIVATE and PUBLIC with target_link_libraries

Iosif Neitzke
target_include_directories(lib1 INTERFACE /tmp) means /tmp is
propagated with lib1, but not used to build lib1.

"The INTERFACE, PUBLIC and PRIVATE keywords are required to specify
the scope of the following arguments. PRIVATE and PUBLIC items will
populate the INCLUDE_DIRECTORIES property of <target>. PUBLIC and
INTERFACE items will populate the INTERFACE_INCLUDE_DIRECTORIES
property of <target>."

https://cmake.org/cmake/help/v3.5/command/target_include_directories.html

On Thu, May 12, 2016 at 8:59 AM, Patrick Boettcher
<[hidden email]> wrote:

> On Thu, 12 May 2016 08:47:33 -0500
> iosif neitzke <[hidden email]> wrote:
>
>> My reading of your examples:
>>
>> exe1 gets linked to lib2, and lib2/bin is included.  exe1 probably
>> won't link ultimately because lib2 may need symbols from lib1.
>> Depends on the structure of the C code between lib2 and lib1.   See
>> John Lakos for further information on that.
>
> It links - because it is a STATIC library - so propagated even though
> it's PRIVATE.
>
> My problem is just the include-dir of lib1 (/tmp) which should _not_ be
> propagated to exe1, but it is propagated.
>
> regards,
> --
> Patrick.
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Difference between PRIVATE and PUBLIC with target_link_libraries

Patrick Boettcher
On Thu, 12 May 2016 09:04:10 -0500
iosif neitzke <[hidden email]> wrote:

> target_include_directories(lib1 INTERFACE /tmp) means /tmp is
> propagated with lib1, but not used to build lib1.

I know. Could you elaborate how this is related with lib3 PRIVATEly linking to
lib1?

regards,
--
Patrick.
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Difference between PRIVATE and PUBLIC with target_link_libraries

Iosif Neitzke
I'm sorry, I'm not sure I understand.  In your example, there is
target_link_libraries(lib3 PUBLIC lib1).  It looks like lib2 has
target_link_libraries(lib2 PRIVATE lib1).

http://public.kitware.com/pipermail/cmake/2016-May/063382.html

On Thu, May 12, 2016 at 9:10 AM, Patrick Boettcher
<[hidden email]> wrote:

> On Thu, 12 May 2016 09:04:10 -0500
> iosif neitzke <[hidden email]> wrote:
>
>> target_include_directories(lib1 INTERFACE /tmp) means /tmp is
>> propagated with lib1, but not used to build lib1.
>
> I know. Could you elaborate how this is related with lib3 PRIVATEly linking to
> lib1?
>
> regards,
> --
> Patrick.
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Difference between PRIVATE and PUBLIC with target_link_libraries

Patrick Boettcher
On Thu, 12 May 2016 09:20:10 -0500
iosif neitzke <[hidden email]> wrote:

> I'm sorry, I'm not sure I understand.  In your example, there is
> target_link_libraries(lib3 PUBLIC lib1).  It looks like lib2 has
> target_link_libraries(lib2 PRIVATE lib1).

Yes. That is correct.

When building the code for lib2 and lib3 the include-path of lib1 is
provided (as expected).

Then when building exe1 (links to lib2) and exe2 (links to lib3) the
lib1's include-path is present in both cases.

Whereas it should not be present with exe1, at least that is my
understanding.

--
Patrick.
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Difference between PRIVATE and PUBLIC with target_link_libraries

Iosif Neitzke
I guess the key is static libraries don't exactly adhere to the rules
of PUBLIC or PRIVATE, so you end up with a library that CMake passes
along with a populated INTERFACE_INCLUDE_DIRECTORIES, and so exe1 uses
it because it is there?  Not sure how it is supposed to work at this point.

On Thu, May 12, 2016 at 9:26 AM, Patrick Boettcher
<[hidden email]> wrote:

> On Thu, 12 May 2016 09:20:10 -0500
> iosif neitzke <[hidden email]> wrote:
>
>> I'm sorry, I'm not sure I understand.  In your example, there is
>> target_link_libraries(lib3 PUBLIC lib1).  It looks like lib2 has
>> target_link_libraries(lib2 PRIVATE lib1).
>
> Yes. That is correct.
>
> When building the code for lib2 and lib3 the include-path of lib1 is
> provided (as expected).
>
> Then when building exe1 (links to lib2) and exe2 (links to lib3) the
> lib1's include-path is present in both cases.
>
> Whereas it should not be present with exe1, at least that is my
> understanding.
>
> --
> Patrick.
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Difference between PRIVATE and PUBLIC with target_link_libraries

Craig Scott-3
Patrick,

I suggest if you can reduce your problem down to a small, reproducible example, then file a bug. I did a test just now with CMake 3.5.2 and everything behaved as expected, including the header search path propagation, so maybe there's something unusual in your project which a simple case doesn't capture. Perhaps also try different generator types in case that results in something different (unlikely, but since you see different behaviour to me, give it a go).


On Fri, May 13, 2016 at 12:30 AM, iosif neitzke <[hidden email]> wrote:
I guess the key is static libraries don't exactly adhere to the rules
of PUBLIC or PRIVATE, so you end up with a library that CMake passes
along with a populated INTERFACE_INCLUDE_DIRECTORIES, and so exe1 uses
it because it is there?  Not sure how it is supposed to work at this point.

On Thu, May 12, 2016 at 9:26 AM, Patrick Boettcher
<[hidden email]> wrote:
> On Thu, 12 May 2016 09:20:10 -0500
> iosif neitzke <[hidden email]> wrote:
>
>> I'm sorry, I'm not sure I understand.  In your example, there is
>> target_link_libraries(lib3 PUBLIC lib1).  It looks like lib2 has
>> target_link_libraries(lib2 PRIVATE lib1).
>
> Yes. That is correct.
>
> When building the code for lib2 and lib3 the include-path of lib1 is
> provided (as expected).
>
> Then when building exe1 (links to lib2) and exe2 (links to lib3) the
> lib1's include-path is present in both cases.
>
> Whereas it should not be present with exe1, at least that is my
> understanding.
>
> --
> Patrick.



--
Craig Scott
Melbourne, Australia

--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Difference between PRIVATE and PUBLIC with target_link_libraries

Patrick Boettcher
On Fri, 13 May 2016 07:06:32 +1000
Craig Scott <[hidden email]> wrote:

> Patrick,
>
> I suggest if you can reduce your problem down to a small, reproducible
> example, then file a bug. I did a test just now with CMake 3.5.2 and
> everything behaved as expected, including the header search path
> propagation, so maybe there's something unusual in your project which
> a simple case doesn't capture. Perhaps also try different generator
> types in case that results in something different (unlikely, but
> since you see different behaviour to me, give it a go).

I filed a bug with a test-case reduced to 7 lines of cmake. I
reproduced it with GNU Make and Ninja a generator.

https://cmake.org/Bug/view.php?id=16102

I'm also reading some cmake-code, but haven't yet found where includes
are inherited from linked targets. Currently looking at
cmGeneratorTarget::GetIncludeDirectories() ...

Thanks for your feedback.

best regards,
--
Patrick.
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Difference between PRIVATE and PUBLIC with target_link_libraries

Alan W. Irwin-2
In reply to this post by Craig Scott-3
Hi Craig:

It appears you pretty much made the definitive statement about
target_link_libraries (TLL) <INTERFACE|PUBLIC|PRIVATE> options at
<https://cmake.org/pipermail/cmake/2016-May/063400.html>.  However,
I have some further questions about this key section of your
statement:

"[...] when A links in B as PRIVATE, the include directories of B
never propagate to something linking to A, but if A is a static
library, then the *linking* of B behaves as though the relationship
was PUBLIC. This PRIVATE-becomes-PUBLIC behaviour for static libraries
only applies to the *linking*, not to the other dependencies (compiler
options/flags and include search paths). The upshot of all this is
that if you select PRIVATE, PUBLIC or INTERFACE based on the
explanations in the dot points above, then CMake will ensure
dependencies propagate through to where they are required, regardless
of whether libraries are static or shared. This does, of course, rely
on you the developer not missing any dependencies or specifying the
wrong PRIVATE/PUBLIC/INTERFACE relationship."

The issues I am concerned with are the following:

* The target_include_directories, target_compile_definitions, and
   target_compile_options (TID, TCD, and TCO) commands all have
   <INTERFACE|PUBLIC|PRIVATE> options.  I am pretty sure those options
   must take precedence over the TLL <INTERFACE|PUBLIC|PRIVATE> options,
   but can you confirm that?

* It appears to me that if a CMake-based build system is configured
   properly there is very little need for the PUBLIC option for TLL
   because PRIVATE works well for shared libraries and the
   PRIVATE-becomes-PUBLIC behaviour for static libraries you mentioned
   above.  Can you confirm this statement is generally true both for
   Unix and Windows?

I am concerned with the above issues because the PLplot build system
currently does the following:

* For shared libraries uses the PRIVATE TLL option for the Unix case
   and PUBLIC TLL option for the Windows case.

* For static libraries always uses the PUBLIC TLL option.

These decisions were based on my own understanding of transitive
linking needs for static Unix libraries and shared and static Windows
libraries many years ago, but now it appears that understanding is out
of date or else was wrong in the first place.

For example, in the static Linux case there is a nasty leakage of
compile and link flags between static libraries that I have just
tripped over when dealing with the D ldc2 compiler which cannot
understand those flags which are generated for the gcc compiler for a
C library which our D library depends on.  So to stop that leakage,
and in light of what you said three years ago, it appears to be a
no-brainer to use PRIVATE TLL for the PLplot static libraries at least
in the Unix case.  So assuming that for the PLplot build system I
follow up and prove that PRIVATE TLL works for both the shared and
static library cases on Unix, would you also recommend PLplot move to
PRIVATE TLL for both the shared and static library cases on Windows?

Thanks in advance for your further comments on these matters.

Alan
__________________________
Alan W. Irwin

Programming affiliations with the FreeEOS equation-of-state
implementation for stellar interiors (freeeos.sf.net); the Time
Ephemerides project (timeephem.sf.net); PLplot scientific plotting
software package (plplot.org); the libLASi project
(unifont.org/lasi); the Loads of Linux Links project (loll.sf.net);
and the Linux Brochure Project (lbproject.sf.net).
__________________________

Linux-powered Science
__________________________
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
https://cmake.org/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Difference between PRIVATE and PUBLIC with target_link_libraries

Simon Richter
Hi,

On Tue, Sep 17, 2019 at 04:21:36PM -0700, Alan W. Irwin wrote:

> * It appears to me that if a CMake-based build system is configured
>   properly there is very little need for the PUBLIC option for TLL
>   because PRIVATE works well for shared libraries and the
>   PRIVATE-becomes-PUBLIC behaviour for static libraries you mentioned
>   above.  Can you confirm this statement is generally true both for
>   Unix and Windows?

The PUBLIC option is required if your library has inline functions that
directly call a dependent library.

On Windows, "shared" linking uses import stubs. Symbols used by dependent
libs were resolved when the dependent lib was linked, so they are not
available anymore. On ELF systems, whether symbols from indirectly linked
libs are available is implementation dependent -- older versions of glibc's
ld.so built a global namespace, so it might appear to work there, but that
is not guaranteed.

My expectation is that PRIVATE should work in all cases as long as your use
of the dependent library is indeed private -- i.e. doesn't affect the
binary interface of your library. Ideally, your headers wouldn't include
their headers, but in reality requirements are a bit more relaxed, so you
are fine as long as you don't have inline functions in headers that call
into the private dependency, and any compiler flags that affect data layout
in any shared types are consistent (e.g. if you use GLM, then
the definition of GLM_FORCE_PURE must be PUBLIC, because that affects
struct alignment requirements).

A good way to test is to do a fully static build with a compiler that
supports link time optimization and provides diagnostics for mismatches.
For example, we know we have a bug in the way KiCad uses GLM, because we
get -Wlto warnings[1] about that.

   Simon

[1] https://jenkins.simonrichter.eu/job/linux-kicad-head-lto/24/gcc/
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
https://cmake.org/mailman/listinfo/cmake