How should config packages handle components?

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

How should config packages handle components?

Robert Dailey-2
First of all, I want to apologize for including the developer list.
Maybe I'm not being patient enough, but it seems like every post I've
made on the normal users list doesn't get any attention.

Secondly, the cmake-packages portion of the cmake documentation
doesn't go into a ton of detail about components, but it does give an
example towards the bottom of how you export targets for components.
This leads to my questions:

When defining the target exports via install(TARGET foo EXPORT
foo-export), is it recommended for all components to collectively
export as 1 target.cmake script? Or is it better to have 1
target.cmake script per component? If we use Boost as an example, the
latter would mean having:

boost-config.cmake
boost-target-filesystem.cmake
boost-target-thread.cmake
...etc...

This means that boost-config.cmake would "include()" only the relevant
target cmake scripts based on the provided COMPONENTS list, I assume?

Which is the better approach here and why?

One problem I thought of with the former (one big target.cmake with
all import targets in there) is that if you only ask for a subset of
components in find_package(), you will still get all of them since all
imports are defined in a single file. Does this go against any design
principles? Assuming this really happens, are there any negative side
effects?
--

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: [cmake-developers] How should config packages handle components?

Alex Turbov
Hi Robert,


On Fri, Sep 1, 2017 at 9:21 PM, Robert Dailey <[hidden email]> wrote:

One problem I thought of with the former (one big target.cmake with
all import targets in there) is that if you only ask for a subset of
components in find_package(), you will still get all of them since all
imports are defined in a single file.

In my project I have a bunch of components and do one exported target per component
exactly by the mentioned reason -- user didn't ask for others...
 
Does this go against any design
principles?

As far as I know, there are no clear design principles :) (yet, at least nowadays) -- at least doing
a lot of CMake projects since 2009, I've never seen an explicit list of them %)
IMHO, there is a lack of "official guildelines" (or it is really hard to search for 'em)

Assuming this really happens, are there any negative side
effects?

I could see the impact on build time only in this case... and for me the most obvious is increasing
time to process the lists (which is for some reasons really slow on Windows, at least in our
build farm which uses vargant and VirtualBox images)
(but I don't have any particular numbers, cuz never implemented the first approach)
 



--

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-developers


--

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: [cmake-developers] How should config packages handle components?

Robert Dailey-2
On Fri, Sep 1, 2017 at 1:40 PM, Alex Turbov <[hidden email]> wrote:

> Hi Robert,
>
>
> On Fri, Sep 1, 2017 at 9:21 PM, Robert Dailey <[hidden email]>
> wrote:
>>
>>
>> One problem I thought of with the former (one big target.cmake with
>> all import targets in there) is that if you only ask for a subset of
>> components in find_package(), you will still get all of them since all
>> imports are defined in a single file.
>
>
> In my project I have a bunch of components and do one exported target per
> component
> exactly by the mentioned reason -- user didn't ask for others...
>
>>
>> Does this go against any design
>> principles?
>
>
> As far as I know, there are no clear design principles :) (yet, at least
> nowadays) -- at least doing
> a lot of CMake projects since 2009, I've never seen an explicit list of them
> %)
> IMHO, there is a lack of "official guildelines" (or it is really hard to
> search for 'em)
>
>> Assuming this really happens, are there any negative side
>> effects?
>
>
> I could see the impact on build time only in this case... and for me the
> most obvious is increasing
> time to process the lists (which is for some reasons really slow on Windows,
> at least in our
> build farm which uses vargant and VirtualBox images)
> (but I don't have any particular numbers, cuz never implemented the first
> approach)

Thanks for the quick response. The "official guidelines" or "package
standard" is really exactly what we need I think. What worries me the
most is that it seems like this is deep knowledge that is stuck in the
brains of folks like Brad King and David Cole. I think somehow getting
a knowledge dump from them into a documentation page would be a
valuable task. I think for something as complex and variable as
packages in CMake (install process in general) deserves some
standardization, because we need the ability to distinguish between
practices that we should follow for legacy (backward compatibility)
reasons, non-cmake project reasons, and fully "modern" cmake packages.
--

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: [cmake-developers] How should config packages handle components?

Alex Turbov
I've started to use CMake a quite long time ago, and do not search for "standards" or "guidelines" anymore %)
But I could mention some chapters in the official documentation (in the "Reference Manuals" section) which are really full of "secret knowledge", but the problem is that they are too complicated for newcomers %) but personally I read them many many times before and each time found smth "new" to me :)

I would say that after a couple of years I started to feel comfortable w/ CMake -- when I've used almost all offered features in a different set of platform and generators.

On Fri, Sep 1, 2017 at 9:49 PM, Robert Dailey <[hidden email]> wrote:
On Fri, Sep 1, 2017 at 1:40 PM, Alex Turbov <[hidden email]> wrote:
> Hi Robert,
>
>
> On Fri, Sep 1, 2017 at 9:21 PM, Robert Dailey <[hidden email]>
> wrote:
>>
>>
>> One problem I thought of with the former (one big target.cmake with
>> all import targets in there) is that if you only ask for a subset of
>> components in find_package(), you will still get all of them since all
>> imports are defined in a single file.
>
>
> In my project I have a bunch of components and do one exported target per
> component
> exactly by the mentioned reason -- user didn't ask for others...
>
>>
>> Does this go against any design
>> principles?
>
>
> As far as I know, there are no clear design principles :) (yet, at least
> nowadays) -- at least doing
> a lot of CMake projects since 2009, I've never seen an explicit list of them
> %)
> IMHO, there is a lack of "official guildelines" (or it is really hard to
> search for 'em)
>
>> Assuming this really happens, are there any negative side
>> effects?
>
>
> I could see the impact on build time only in this case... and for me the
> most obvious is increasing
> time to process the lists (which is for some reasons really slow on Windows,
> at least in our
> build farm which uses vargant and VirtualBox images)
> (but I don't have any particular numbers, cuz never implemented the first
> approach)

Thanks for the quick response. The "official guidelines" or "package
standard" is really exactly what we need I think. What worries me the
most is that it seems like this is deep knowledge that is stuck in the
brains of folks like Brad King and David Cole. I think somehow getting
a knowledge dump from them into a documentation page would be a
valuable task. I think for something as complex and variable as
packages in CMake (install process in general) deserves some
standardization, because we need the ability to distinguish between
practices that we should follow for legacy (backward compatibility)
reasons, non-cmake project reasons, and fully "modern" cmake packages.


--

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: [cmake-developers] How should config packages handle components?

Florent Castelli
In reply to this post by Alex Turbov
On 01/09/2017 20:40, Alex Turbov wrote:
Hi Robert,


On Fri, Sep 1, 2017 at 9:21 PM, Robert Dailey <[hidden email]> wrote:

One problem I thought of with the former (one big target.cmake with
all import targets in there) is that if you only ask for a subset of
components in find_package(), you will still get all of them since all
imports are defined in a single file.

In my project I have a bunch of components and do one exported target per component
exactly by the mentioned reason -- user didn't ask for others...
 
Does this go against any design
principles?

As far as I know, there are no clear design principles :) (yet, at least nowadays) -- at least doing
a lot of CMake projects since 2009, I've never seen an explicit list of them %)
IMHO, there is a lack of "official guildelines" (or it is really hard to search for 'em)

Assuming this really happens, are there any negative side
effects?

I could see the impact on build time only in this case... and for me the most obvious is increasing
time to process the lists (which is for some reasons really slow on Windows, at least in our
build farm which uses vargant and VirtualBox images)
(but I don't have any particular numbers, cuz never implemented the first approach)

Well, there's no impact on build time. The module will provide IMPORTED targets, if they are not used,
they won't be used in the solution / Makefile. And I don't think CMake has any significant bottleneck
on having just a few more IMPORTED targets around from a find_package() module.

Components might be important for an old "FindFoo.cmake" module where you don't want to find
a lot more libraries in your path, not so much for a "FooConfig.cmake" which is a "dumb" file that
just defines a lot of targets and their properties.

/Florent

--

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: How should config packages handle components?

Robert Dailey-2
In reply to this post by Robert Dailey-2
In the case where I'm exporting 1 target.cmake script per component
for a single package, could someone provide an example on how to
manage dependencies? There are 2 types of dependencies:

1. Dependencies on external packages
2. Cross-dependencies within the same package (i.e. on other
components in the same package)

The cmake-packages doc kind of goes over #1, but #2 doesn't seem to
have examples.

On Fri, Sep 1, 2017 at 1:21 PM, Robert Dailey <[hidden email]> wrote:

> First of all, I want to apologize for including the developer list.
> Maybe I'm not being patient enough, but it seems like every post I've
> made on the normal users list doesn't get any attention.
>
> Secondly, the cmake-packages portion of the cmake documentation
> doesn't go into a ton of detail about components, but it does give an
> example towards the bottom of how you export targets for components.
> This leads to my questions:
>
> When defining the target exports via install(TARGET foo EXPORT
> foo-export), is it recommended for all components to collectively
> export as 1 target.cmake script? Or is it better to have 1
> target.cmake script per component? If we use Boost as an example, the
> latter would mean having:
>
> boost-config.cmake
> boost-target-filesystem.cmake
> boost-target-thread.cmake
> ...etc...
>
> This means that boost-config.cmake would "include()" only the relevant
> target cmake scripts based on the provided COMPONENTS list, I assume?
>
> Which is the better approach here and why?
>
> One problem I thought of with the former (one big target.cmake with
> all import targets in there) is that if you only ask for a subset of
> components in find_package(), you will still get all of them since all
> imports are defined in a single file. Does this go against any design
> principles? Assuming this really happens, are there any negative side
> effects?
--

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
|

How should config packages handle components?

Alan W. Irwin
On 2017-09-05 14:33-0500 Robert Dailey wrote:

> In the case where I'm exporting 1 target.cmake script per component
> for a single package, could someone provide an example on how to
> manage dependencies? There are 2 types of dependencies:
>
> 1. Dependencies on external packages
> 2. Cross-dependencies within the same package (i.e. on other
> components in the same package)
>
> The cmake-packages doc kind of goes over #1, but #2 doesn't seem to
> have examples.

Hi Robert:

This is an interesting topic to me because I am not at all satisfied
with the way that PLplot currently exports its components (which have
both kinds of the above dependencies).  I implemented those exports a
decade ago so the result is far from best practices.  Therefore, I am
glad you have brought up this topic, and I am looking forward to
seeing how your questions are finally answered.

To make it easier to get those final answers on best export practices,
I suggest you implement the simplest possible example with say two
components that have the two kinds of dependencies above. Then follow
up by asking the experts here to comment on the best export practices
for that simple example with the goal that once your simple example
has been modified to use best export practices that it should be
published in the CMake Wiki.  Such an example would be a big help to
me and I presume others as well who want to modernize the exports
from their project or who are designing a build system from scratch
for a project with multiple components that are exported.

By the way, I think cross-posting is a bad idea since it means those
subscribed to both lists always get annoying duplicate posts. So I
have thought about which list should be used for this topic, and my
conclusion is it belongs on the CMake list for now since it is about
how to use CMake rather than about some suggested CMake implementation
change.  But it can always be moved later to the CMake developer list
in the unlikely event that some CMake implementation change is
required to allow build-system designers to follow best export
practices.

Alan
__________________________
Alan W. Irwin

Astronomical research affiliation with Department of Physics and Astronomy,
University of Victoria (astrowww.phys.uvic.ca).

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.sf.net); 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:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: [cmake-developers] How should config packages handle components?

Alex Turbov
In reply to this post by Robert Dailey-2
In my projects I always, have external dependencies with finder module providing exported (imported in my project) targets, so my targets (one per file) always have a list of `Vendor::target`. Some of them are mine (i.e. your type 2 -- built by the same project).

I wrote a helper module and a function to write an additional `blah-blah-target-depedencies.cmake`. And this is a little bit subtle thing...
Normally, generated `blah-blah-target.cmake` (where the `blah-blah-target` is the export name used in call to `install(EXPORT)`) to load all installed configurations do the following:

  file(GLOB CONFIG_FILES "${_DIR}/blah-blah-target-*.cmake")


so my additional file would be loaded "automatically" :)

My helper function accepts a target name as the only parameter. First of all, it collects all dependencies of the given target and classifies them as internal (same project) and external. It prepares some variables and finally, render a `blah-blah-target-dependencies.cmake` which is a result of the combination of 3 templates:
0) a base, header+footer and conditionally "include" the next two
1) import internal dependencies
2) import external dependencies

Note templates have random string in final names, so being running (loading) by the same script (`blah-blah-config.cmake`) won't interfere...

As for "prepared variables" there are the following:
* "internal dependencies" is just a list of target names... having a name is enough to form a `blah-blah-target.cmake` name to be `include()`d, cuz we really know where this file is installed
* for external dependencies the most important a list of packages, assuming that the initial external (imported) target had the form of `Vendor::target`, and `Vendor` in fact is a package name suitable as the first argument to `find_package()`.
* other variables related to external targets have a variadic part based on upcased name of the vendor. Example:

    set(_blah_blah_PACKAGES ACE;Boost)
    set(_blah_blah_ACE_VENDOR ACE)
    set(_blah_blah_ACE_COMPONENTS ace;ssl)
    set(_blah_blah_ACE_VERSION 5.7.5)
    set(_blah_blah_BOOST_VENDOR Boost)
    set(_blah_blah_BOOST_COMPONENTS chrono;filesystem;program_options;thread)
    set(_blah_blah_BOOST_VERSION 1.65.0)

Now about generated `*-config.cmake`. As one may guess it handle targets to import as `COMPONENTS` of `find_package()`, where every component is an exported target name. So this module just `include()` it and check if target appeared:

    # Find components if requested
    set(blah_FOUND_COMPONENTS)
    foreach(_module ${blah_FIND_COMPONENTS})
        # TODO Avoid more than once find? (But be aware that is not a trivial `if` and skip %-)
        # TODO Make sure component is supported (exists)
        include(
            "${CMAKE_CURRENT_LIST_DIR}/blah-${_module}-targets.cmake"
            OPTIONAL
            RESULT_VARIABLE blah_${_module}_FOUND
        )

        if(blah_${_module}_FOUND AND TARGET Blah::${_module})
            list(APPEND blah_FOUND_COMPONENTS ${_module})

            # Add some interface properties to all found components
            string(TOUPPER "${_module}" _module_id)
            string(MAKE_C_IDENTIFIER "${_module_id}" _module_id)
            set_target_properties(
                Blah::${_module}
                PROPERTIES
                    # Set compatible version usage requirement
                    INTERFACE_BLAH_VERSION_MAJOR "${BLAH_VERSION_MAJOR}"
                    # What package to find
                    INTERFACE_BLAH_${_module_id}_PACKAGE_NAME "blah"
                )
            set_property(
                TARGET Blah::${_module}
                APPEND PROPERTY
                    COMPATIBLE_INTERFACE_STRING BLAH_VERSION_MAJOR
                )
            unset(_module_id)

        else()
            set(blah_${_module}_FOUND NOTFOUND)

            if (blah_FIND_REQUIRED_${_module})
                list(APPEND blah_NOT_FOUND_REQUIRED_COMPONENTS ${_module})
            else()
                list(APPEND blah_NOT_FOUND_COMPONENTS ${_module})
            endif()

        endif()
    endforeach()
    unset(_module)

When all components checked call the final package found/not-found checker:

    check_required_components(blah)

Yes, this particular implementation have obvious limitations to be named "universal and generic", but it works few years for me w/o problems... (however, I do some improvements from time to time %) It do not handle "plain old library names"... and as I said, all my external packages provide imported targets, where the Vendor name is the package name in fact... so I don't care (while having no reason to improve it for this case... maybe later %).

I'll attach my module (stripping not related and vendor specific parts) for further inspiration... Feel free to ask for details (or more code, if attached doesn't work... probably I miss some functions (from other parts of my framework)).

Have fun! :)


On Tue, Sep 5, 2017 at 10:33 PM, Robert Dailey <[hidden email]> wrote:
In the case where I'm exporting 1 target.cmake script per component
for a single package, could someone provide an example on how to
manage dependencies? There are 2 types of dependencies:

1. Dependencies on external packages
2. Cross-dependencies within the same package (i.e. on other
components in the same package)

The cmake-packages doc kind of goes over #1, but #2 doesn't seem to
have examples.

On Fri, Sep 1, 2017 at 1:21 PM, Robert Dailey <[hidden email]> wrote:
> First of all, I want to apologize for including the developer list.
> Maybe I'm not being patient enough, but it seems like every post I've
> made on the normal users list doesn't get any attention.
>
> Secondly, the cmake-packages portion of the cmake documentation
> doesn't go into a ton of detail about components, but it does give an
> example towards the bottom of how you export targets for components.
> This leads to my questions:
>
> When defining the target exports via install(TARGET foo EXPORT
> foo-export), is it recommended for all components to collectively
> export as 1 target.cmake script? Or is it better to have 1
> target.cmake script per component? If we use Boost as an example, the
> latter would mean having:
>
> boost-config.cmake
> boost-target-filesystem.cmake
> boost-target-thread.cmake
> ...etc...
>
> This means that boost-config.cmake would "include()" only the relevant
> target cmake scripts based on the provided COMPONENTS list, I assume?
>
> Which is the better approach here and why?
>
> One problem I thought of with the former (one big target.cmake with
> all import targets in there) is that if you only ask for a subset of
> components in find_package(), you will still get all of them since all
> imports are defined in a single file. Does this go against any design
> principles? Assuming this really happens, are there any negative side
> effects?
--

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-developers


--

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

cmake-export-dependencies.tar.bz2 (6K) Download Attachment