Advice on how to remove duplicated code for object and interface library setup

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

Advice on how to remove duplicated code for object and interface library setup

Stephen McDowell
I am trying to obey modern CMake target-based practices, with a twist that everything is available as an OBJECT library if desired.  I have this working and can explain why if desired, but I feel it is extraneous for this question.  What I create:

- mylib <- the main library
    - mylib_obj <- contains all of the actual objects for the library (OBJECT library)
    - mylib_interface <- linked with mylib

So it looks like this:

    add_library(mylib_obj OBJECT "")
    add_library(mylib_interface INTERFACE)

Based on various options / settings, target_sources(mylib_obj) will be set and all of the various compiler operations etc.  At the end, I have

    # MYLIB_LIBRARY_TYPE is either SHARED or STATIC
    add_library(mylib ${MYLIB_LIBRARY_TYPE} $<TARGET_OBJECTS:mylib_obj>)
    target_link_libraries(mylib mylib_interface)

This works nicely, but internally I have to do the same operations for both mylib_obj and mylib_interface.

    target_include_directories(mylib_obj PUBLIC ${SomeLib_INCLUDE_DIRS})
    target_include_directories(mylib_interface INTERFACE ${SomeLib_INCLUDE_DIRS})
    target_link_libraries(mylib_interface INTERFACE ${SomeLib_LIBRARIES})

Without mylib_interface, I cannot include the future linking information as well as include / compiler directive information will not be propagated with target_link_libraries(something mylib).  But mylib_obj also needs include information, etc.  But I can’t do

    target_link_libraries(mylib_obj mylib_interface)

because mylib_obj is an object library.

Is there a way to avoid having to set the same thing for both mylib_obj and mylib_interface given the requirement that mylib_obj is intended to house all of the actual objects?

Thank you for any guidance, I’m sorry if this question doesn’t make much sense.  I’m trying to unlearn all of my outdated self-taught CMake!

-Stephen


--

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: Advice on how to remove duplicated code for object and interface library setup

Deniz Bahadir-2
Am 16.03.2018 um 03:17 schrieb Stephen McDowell:

> I am trying to obey modern CMake target-based practices, with a twist
> that everything is available as an OBJECT library if desired.  I have
> this working and can explain why if desired, but I feel it is extraneous
> for this question.  What I create:
>
> - mylib <- the main library
>      - mylib_obj <- contains all of the actual objects for the library
> (OBJECT library)
>      - mylib_interface <- linked with mylib
>
> So it looks like this:
>
>      add_library(*mylib_obj OBJECT* "")
> **add_library(*mylib_interface INTERFACE*)
>
> Based on various options / settings, *target_sources(mylib_obj)* will be
> set and all of the various compiler operations etc.  At the end, I have
>
>      # MYLIB_LIBRARY_TYPE is either SHARED or STATIC
>      add_library(*mylib* ${MYLIB_LIBRARY_TYPE}
> *$<TARGET_OBJECTS:mylib_obj>*)
>      target_link_libraries(*mylib mylib_interface*)
>
> This works nicely, but internally I have to do the same operations for
> both *mylib_obj* and *mylib_interface*.
>
>      target_include_directories(*mylib_obj PUBLIC* ${SomeLib_INCLUDE_DIRS})
>      target_include_directories(*mylib_interface INTERFACE*
> ${SomeLib_INCLUDE_DIRS})
>      target_link_libraries(*mylib_interface INTERFACE* ${SomeLib_LIBRARIES})
> *
> *
> Without *mylib_interface*, I cannot include the future linking
> information as well as include / compiler directive information will not
> be propagated with *target_link_libraries(something mylib)*.  But
> *mylib_obj* also needs include information, etc. *But* I can’t do
>
>      target_link_libraries(*mylib_obj mylib_interface*)
> *
> *
> because *mylib_obj* is an object library.

Best idea is to use the latest development-version of CMake from master
branch (which will become CMake 3.12). That one supports linking of
object-libraries natively like other targets, too. (See:
https://gitlab.kitware.com/cmake/cmake/merge_requests/1524)

>
> Is there a way to avoid having to set the same thing for both
> *mylib_obj* and *mylib_interface* given the requirement that
> *mylib_obj* is intended to house all of the actual objects?
>
> Thank you for any guidance, I’m sorry if this question doesn’t make much
> sense.  I’m trying to unlearn all of my outdated self-taught CMake!
>
> -Stephen
>

Hope that helps,
Deniz
--

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: Advice on how to remove duplicated code for object and interface library setup

Stephen McDowell
Hi Deniz,

Thanks for the response!  I tested it out and it seems to work exactly as you describe :)

I don’t want to depend on an un-released version of CMake though.  The original desire is because I kept making mistakes / adding definitions for one and not the other (code duplication at its finest…).

I discovered that I can populate one, e.g. only modify mylib_obj and then later grab these properties to add to the interface:

    get_target_property(MYLIB_OBJ_INTERFACE_COMPILE_DEFINITIONS mylib_obj INTERFACE_COMPILE_DEFINITIONS)

and also the same for INTERFACE_COMPILE_OPTIONS etc. (Note: for anybody reading this, understand that INTERFACE_COMPILE_DEFINITIONS is desired here, COMPILE_DEFINITIONS includes private items which I do not want in this case).

Is getting the properties and then later setting them a reasonable solution here, or is this a bad idea?

-Stephen


--

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