[CMake] ExternalProject, target_link_libraries(), and Multi-configuration Builds.

michael lowell roberts zoarre at gmail.com
Sun Oct 9 19:24:45 EDT 2011


On Sun, Oct 9, 2011 at 7:49 AM, Michael Hertling <mhertling at online.de>wrote:

> On 10/09/2011 02:09 AM, michael lowell roberts wrote:
> > On Sat, Oct 8, 2011 at 6:40 AM, Michael Hertling <mhertling at online.de
> >wrote:
> >
> >> On 10/08/2011 05:33 AM, michael lowell roberts wrote:
> >>> Hi all,
> >>>
> >>> I'm attempting to use the ExternalProject module to compile and link
> >> against
> >>> a library and I've run into a problem that I'm not certain how to
> >> address.
> >>> I'm using CMake 2.8.6 and Visual Studio 10 Express.
> >>>
> >>> The external project, in my case, is a CMake-compiled project and CMake
> >>> predictably builds a matching configuration in the external project.
> >>>
> >>> The target_link_libraries() command, however, only allows for two
> >>> configurations, at most, mapped to labels "debug" and "optimized."
> >>>
> >>> This allows for only two of the four default build configurations to
> >>> complete successfully.
> >>>
> >>> For example, in my build scripts, I have told target_link_libraries()
> to
> >> map
> >>> "debug" configurations to the Debug version of library and optimized
> >>> configurations map to the "RelWithDebInfo" build of the library.
> >> Therefore,
> >>> if I build the "Release" configuration, I get linker errors because the
> >>> external project was also built with the "Release" configuration but I
> >> need
> >>> to link against "RelWithDebInfo."
> >>>
> >>> It seems to be that no matter how the target_link_library() mappings
> are
> >> set
> >>> up, only half of the default configurations will build properly because
> >> of
> >>> the dualism that target_link_libraries() uses.
> >>>
> >>> How do I get all four default build configurations working?
> >>>
> >>> Regards,
> >>> Mike
> >>
> >> Could you boil down this issue to a minimal but self-contained
> >> exemplary project and post it here for further investigation?
> >>
> >
> > Certainly.
> >
> > I've attached a sample project that downloads and compiles the trio
> library,
> > which can be found at the following site:
> >
> > http://daniel.haxx.se/projects/trio/
> >
> > It then attempts to link the library into a trivial executable that
> simply
> > prints a message to the screen.
> >
> > The build exhibits the problem I mentioned. Debug builds complete
> > successfully. Release builds do not.
>
> Okay, I was able to reproduce the issue. In fact, it is caused by your
> manual mapping of configurations between your project and the external
> project via TARGET_LINK_LIBRARIES()' debug/optimized keywords. However,
> that's inappropriate anyways; you should use an imported library along
> with its IMPORTED_LOCATION_<CONFIG> target properties instead. Look at
> the attached trio.cmake file or the related diff, respectively. With
> the new trio.cmake, I was able to build all configurations of the
> exemplary project flawlessly, but please consider this just as a
> hotfix, not a rock-solid solution.
>

That makes sense; thanks.


>
> > Additionally, the IDE appears incapable of determining when the build is
> > up-to-date. Try to debug the executable to reproduce this problem. I'm
> > inclined to believe that this is due to something I've done wrong and any
> > help with this problem would also be appreciated.
>
> I can't confirm this. When the test.c file ist touched, Visual Studio
> recompiles it and relinkes the final executable as it should, and if
> nothing has changed, nothing does happen. Could you provide further
> information when the IDE does not behave as expected?
>

I'm still experiencing this problem. When I start the debugger, Visual
Studio presents me with a dialog asking if I want to rebuild trio and
ZERO_CHECK.

I'm not sure it matters anymore, however, in light of the remainder of what
you've said.


> > Lastly, I'm certain that there are other problems I have not identified
> yet.
> > If you could point out anything else that is obviously problematic, I
> would
> > be grateful. Perhaps I am over-complicating the code, for example.
>
> Hhm, yes, this might be the case... ;) Besides, there was a minor flaw
> with include_directories(), see the diff, and constructions like
>
> get_filename_component(TRIO_PREFIX "${TRIO_LIBRARY}" PATH)
>
> doesn't seem to work well if TRIO_LIBRARY is something like
>
> debug;.../lib/Debug/trio.lib;optimized;.../lib/RelWithDebInfo/trio.lib
>

I'm having one of those "I wonder why it worked at all?" moments. :)


> AFAICS, the basic problem is that you need the trio library already
> installed when your actual project is configured, and this can't be
> done by a simple external project because the latter is completely
> processed at build time, i.e. when your project's configuration is
> already finished. For that reason, you need lines like
>
> if(WIN32)
>        set(TRIO_LIBRARY_NAME trio.lib)
> else()
>        set(TRIO_LIBRARY_NAME libtrio.a)
> endif()
>
> which is usually performed by CMake's FIND_LIBRARY() automatically.
>

OIC. I appreciate you reminding me of this. It makes a lot of things
clearer.


>
> IMO, possible solutions are:
>
> - Integrate the external project's code base in your project's one,
>  set it up appropriately and process it with an ADD_SUBDIRECTORY().
>  However, in this way, you'll miss the external project's upstream.
> - Apply the so-called super-build approach, i.e. provide a top-level
>  CMakeLists.txt that pulls in the foreign project *and* your actual
>  project as external projects with your project being the last one.
>  In this manner, the foreign project is already build and possibly
>  installed when your project is configured, so you can use CMake's
>  FIND_*() commands to locate the foreign project's files. However,
>  you must explicitly forward each variable that should be used in
>  your project from the top-level CMakeLists.txt to your project's
>  ExternalProject_Add() invocation, and there might also be issues
>  w.r.t. the projects' common installation, see [1].
>
> 'hope that helps.
>

It does. I'm going to elect for the add_subdirectory() approach.

The super-build option doesn't seem especially useful for a project that I'm
using to actively develop source code. The IDE only shows custom build rules
for an external project, not the source files I would want convenient access
to. It seems that the super-build option is more appropriate for collecting
related projects into something like an automated build process.

Thanks again for your help and wisdom.

Regards,
Mike
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.cmake.org/pipermail/cmake/attachments/20111009/2cd772ab/attachment-0001.htm>


More information about the CMake mailing list