Installing only one target (and its dependencies) out of a complex project with cmake (open to better solutions)

元气小坏坏 提交于 2019-11-28 21:39:00

What works:

  • Remove dependency of "install" target to "all" target (once, in the main CMakeLists.txt):

    set(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY true)

  • Set to OPTIONAL installation of all targets you do not want to always build:

    install(TARGETS <<targetname>> DESTINATION . OPTIONAL)

  • Build the targets you want to install

    ninja -j7 <<list of targets>>, or more generally:

    <<your builder>> <<your options>> <<list of targets>>

    This will build all the targets listed and their dependencies

  • Call the installer ninja install. This will install all the libraries you have built, those you mentioned explicitly and those to which they depended. This solves the problem of installing a specific target together with its dependencies!

  • To concatenate the commands, both on Unix and Windows you can use

    ninja -j7 <<list of targets>> && ninja install

  • Note that, at least for ninja, you cannot simply prepend "install" to the list of targets, as the target "install" does not depend anymore on any target and ninja in parallelizing the job will run install while you are still building your targets. A replacement to the old ninja -j7 install is

    ninja -j7 && ninja install.

    The target "all" is still available (and it is still the default target).

  • If you need to create a list of targets you want to build together, you can define a custom target:

    add_custom_target(<<collective target name>> DEPENDS <<list of targets>>)

    This will not be included in the target all. Adding also a COMMAND would also allow to create an install target for as many as target as we want, for example ninja -j7 install_D, but I think now we are beyond the scope of this question.

Further considerations:

  • (Note, July 2018: This might be outdated) If you use RUNTIME DESTINATION, LIBRARY DESTINATION etc., most likely because of a CMake bug the OPTIONAL keyword should be put exactly in the position indicated below:

    install(TARGETS <<targetname>> OPTIONAL RUNTIME DESTINATION <<some dir>> LIBRARY DESTINATION <<some (other) dir>>)

    This contradicts what written in the documentation, and I will proceed to report it as a bug to the CMake developers.

  • Using EXCLUDE_FROM_ALL in combination with INSTALL + OPTIONAL is a bad idea

    Installing a target with EXCLUDE_FROM_ALL set to true has undefined behavior.

    (and cmake tries to warn you when it parses the code)

If you have used add_subdirectory to add your sub-projects to your CMakeLists.txt you will see, that in your build-directory you have subdirectories for all your subprojects.

If you only want to install the targets from D just do:

cd build-dir/D
make install

this will only install the D-targets.

Of course you have to have built your project before in build-dir. I'm using it is this way using gnu-make. I don't know if it works with Ninja.

As I answered here, recent versions of Ninja provide the option to build only targets in a subdirectory.

The same feature holds for installs. So if your target D from your question were in a subdirectory D you can run this command:

ninja D/install

Find more info at the CMake documentation to the Ninja Generator here.

As mentioned by unapiedra the ninja build file generated by cmake includes rules for building/testing/installing/packaging what's inside a particular directory.

This is fine but you cannot do:

ninja <targetName>/install

You can only do

ninja path/where/targetName/is/install

If you don't know where the targetName is you may use:

ninja -t query <targetName>

to see outputs.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!