MantisBT - CMake
View Issue Details
0014444CMake(No Category)public2013-09-26 18:142016-06-10 14:31
Blaise Gassend 
Kitware Robot 
normalfeaturehave not tried
closedmoved 
 
 
0014444: Allow installing targets from multiple directories in one command
If you try to INSTALL TARGET a target that was defined in a different directory, CMake fails with an error.

This is behaviour is really annoying. We are trying to install only libraries that get used by executables that need to be installed. However, if the library and executable are defined in different directories, this bug prevents you from INSTALLing the library at the place where you know you need to install it. Using INSTALL FILES partially works, but causes stripping and rpath changing to break, as CMake no longer recognizes the library as a library.

If this behaviour is a feature, it would be really nice to have documentation of why it is a feature. (I can't seem to be able to define targets with the same name in different directories, so why on earth would INSTALL TARGETS be the only command that only considers
I'll attach a tarball for a directory that reproduces this. To reproduce:

cd cmake_deb_test
mkdir build
cd build
cmake ..

[ret=2] blaise@bnl: /st/stor1/blaise/work/cmake_deb_test/build $ cmake ..
-- The C compiler identification is GNU
-- The CXX compiler identification is GNU
-- Check for working C compiler: /usr/lib/ccache/gcc
-- Check for working C compiler: /usr/lib/ccache/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
m-- Check for working CXX compiler: /usr/lib/ccache/c++
ak-- Check for working CXX compiler: /usr/lib/ccache/c++ -- works
-- Detecting CXX compiler ABI info
e -- Detecting CXX compiler ABI info - done
CMake Error at CMakeLists.txt:10 (install):
  install TARGETS given target "mylib2" which does not exist in this
  directory.


-- Configuring incomplete, errors occurred!
The following patch fixes the problem. I don't understand the cmake philosophy enough to know if it hopelessly breaks something else though.


Description: INSTALL TARGETS will find non-local targets
 .
 cmake (2.8.7-0ubuntu5) precise-proposed; urgency=low
 .
   * Fix corrupted tarballs when using DEB generator in CPack.
     (LP: #972419)
Author: David Dunsmore <david.dunsmore@sbl-dd-laptop1.seebyte.com>
Bug-Ubuntu: https://bugs.launchpad.net/bugs/972419 [^]
 
---
The information above should follow the Patch Tagging Guidelines, please
checkout http://dep.debian.net/deps/dep3/ [^] to learn about the format. Here
are templates for supplementary fields that you might want to add:

Origin: <vendor|upstream|other>, <url of original patch>
Bug: <url in upstream bugtracker>
Bug-Debian: http://bugs.debian.org/<bugnumber> [^]
Bug-Ubuntu: https://launchpad.net/bugs/<bugnumber> [^]
Forwarded: <no|not-needed|url proving that it has been forwarded>
Reviewed-By: <name and email of someone who approved the patch>
Last-Update: <YYYY-MM-DD>

--- cmake-2.8.7.orig/Source/cmInstallCommand.cxx
+++ cmake-2.8.7/Source/cmInstallCommand.cxx
@@ -350,8 +350,8 @@ bool cmInstallCommand::HandleTargetsMode
       targetIt!=targetList.GetVector().end();
       ++targetIt)
     {
- // Lookup this target in the current directory.
- if(cmTarget* target=this->Makefile->FindTarget(targetIt->c_str()))
+ // Lookup this target
+ if(cmTarget* target=this->Makefile->FindTargetToUse(targetIt->c_str()))
         {
         // Found the target. Check its type.
         if(target->GetType() != cmTarget::EXECUTABLE &&
@@ -373,7 +373,7 @@ bool cmInstallCommand::HandleTargetsMode
         // Did not find the target.
         cmOStringStream e;
         e << "TARGETS given target \"" << (*targetIt)
- << "\" which does not exist in this directory.";
+ << "\" which does not exist.";
         this->SetError(e.str().c_str());
         return false;
         }
No tags attached.
tgz cmake_deb_test.tgz (594) 2013-09-26 18:14
https://public.kitware.com/Bug/file/4889/cmake_deb_test.tgz
Issue History
2013-09-26 18:14Blaise GassendNew Issue
2013-09-26 18:14Blaise GassendFile Added: cmake_deb_test.tgz
2013-09-27 08:17Brad KingNote Added: 0033904
2013-09-27 08:24Brad KingNote Added: 0033905
2013-09-27 08:34Brad KingNote Added: 0033906
2013-09-27 08:34Brad KingSeverityminor => feature
2013-09-27 08:34Brad KingStatusnew => backlog
2013-09-27 08:34Brad KingSummaryINSTALL TARGET command does not work with targets outside the current directory => Allow installing targets from multiple directories in one command
2013-09-27 17:24Blaise GassendNote Added: 0033920
2013-09-30 08:23Brad KingNote Added: 0033930
2016-06-10 14:29Kitware RobotNote Added: 0042378
2016-06-10 14:29Kitware RobotStatusbacklog => resolved
2016-06-10 14:29Kitware RobotResolutionopen => moved
2016-06-10 14:29Kitware RobotAssigned To => Kitware Robot
2016-06-10 14:31Kitware RobotStatusresolved => closed

Notes
(0033904)
Brad King   
2013-09-27 08:17   
The described behavior is as intended. The install(TARGETS) command can only work for targets in the current directory. Perhaps this could be changed with debate on the developers' list, but it is not a bug.

In the linked Ubuntu issue the reporter claims that upstream CMake works and Ubuntu-packaged CMake fails. Why is the solution then another Ubuntu patch that changes the behavior of CMake instead of fixing the reason Ubuntu's packaging broke it in the first place?
(0033905)
Brad King   
2013-09-27 08:24   
Re 0014444:0033904: Okay, Ubuntu issue 972419 has nothing to do with this issue, and the proposed patch has no Ubuntu issue linked in it, so that answers my question.

Still, the behavior is currently as intended.
(0033906)
Brad King   
2013-09-27 08:34   
The reasons for the restriction:

1. Historical. In older implementations the patch would not have been so simple.

2. Makefile hierarchy. Running "make install" in a subdirectory of the project first builds the subdirectory-specific "all" target and then runs the install rules for the current directory and below. If those install rules could reach out to other directories this use case would break. Then we would have to make install(TARGETS) influence what is part of the "all" target, which is very confusing.

We frequently encapsulate install rules inside various conditions in order to achieve behavior like that requested.
(0033920)
Blaise Gassend   
2013-09-27 17:24   
Hi Brad,

Thanks for the insightful explanation of the technical rationale for this limitation. It sounds like one sensible option would be to allow a target to be "imported" into the current subdirectory. That would add the target to the subdirectory's all target, and allow it to be used in install(TARGETS). Unfortunately, this kind of changes requires more understanding of the CMake codebase than I'm likely to have time to pick up.

As you suggested, install rules inside conditions is what we have resorted to, but it isn't a very satisfactory approach to us. It means that if subdirectory B depends on subdirectory A, you have to have a flow like this:

1. set up variables that will be used in the condition around the install
2. process subdirectory A
3. process subdirectory B

That means that the dependency of B on A needs to be captured in at least two places. In step 1, and in step 3. With these two places being in different files. (I'm assuming that A isn't a subdirectory of B, as there are plenty of dependency graphs on which this would not be an option.)

So I still think having some way of doing cross-directory install(TARGETS) would be a powerful addition to cmake. I'll let you decide an appropriate fate for this ticket, and suggest where further discussion should be had.

Regards,
Blaise
(0033930)
Brad King   
2013-09-30 08:23   
Re 0014444:0033920: IIUC your use case is to install an executable target plus all its shared library dependencies whether they are in the same directory or not. Is that correct?

If so, then another approach could be to have an option to install(TARGETS) to enable automatic inclusion of a target's (runtime) dependencies in the installation. Such dependencies would already be build-time dependencies even across directories so the targets should exist by the time the installation occurs.

Of course this could get tricky if multiple targets have the same dependency and are installed in this way, or if one of the dependencies also has its own install rule. I'm not sure how to define behavior for that.
(0042378)
Kitware Robot   
2016-06-10 14:29   
Resolving issue as `moved`.

This issue tracker is no longer used. Further discussion of this issue may take place in the current CMake Issues page linked in the banner at the top of this page.