Search code examples
cmakedebcpack

CMake install TARGETS given target which is not an executable, library, or module


I am trying to build a debian package that contains a single bash script. The script is generated by:

go.sh:

#!/bin/bash

cat >main <<EOF
#!/bin/bash
echo $@
EOF

chmod +x main

and my CMakeLists.txt:

cmake_minimum_required(VERSION 3.5)

add_custom_command(OUTPUT main ${CMAKE_CURRENT_SOURCE_DIR}/go.sh ${PROJECT_NAME})

add_custom_target(main ALL)

install(
    TARGETS main
    DESTINATION /usr/local/lib/
)

set(CPACK_GENERATOR "DEB")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Me")

include(CPack)

This just nets me a cryptic error message:

CMake Error at CMakeLists.txt:7 (install):
  install TARGETS given target "main" which is not an executable, library, or
  module.

Does anyone know what this error message means, and what I should do about it?

EDIT - I am so lost.

I've renamed the script that was generated by go.sh to program so that it doesn't conflict with the name of the target which is supposed to produce the file:

#!/bin/bash

MAIN=program

cat >$MAIN <<EOF
#!/bin/bash
echo $@
EOF

chmod 'x $MAIN

I've also changed my CMakeLists.txt file:

cmake_minimum_required(VERSION 3.5)

add_custom_target(
    main
    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/program
)

add_custom_command(
    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/program
    COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/go.sh ${PROJECT_NAME}
)

install(FILES ${CMAKE_CURRENT_BINARY_DIR}/program DESTINATION /usr/local/lib/)

set(CPACK_GENERATOR "DEB")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Me")

include(CPack)

However, my build still doesn't work. In this case, my main target doesn't get built. If I run:

rm -rf ./* && cmake .. && make package

I get an error about file INSTALL cannot find program

I think I am fundamentally misunderstanding the difference between a file and a target. I cannot imagine that, using cmake, one is expected to name every generated file and then give every generated file a distinct target name to sidestep naming conflicts. That just doesn't make any sense to me.


Solution

  • @tsyvarev's answer pointed you in the right direction and your edited question is almost correct. You left out the ALL option to add_custom_target(), which is why your main target didn't get built by default. Correcting your CMakeLists.txt file to account for this, the following should do what you want:

    cmake_minimum_required(VERSION 3.5)
    
    add_custom_target(
        main ALL
        DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/program
    )
    
    add_custom_command(
        OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/program
        COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/go.sh ${PROJECT_NAME}
    )
    
    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/program DESTINATION /usr/local/lib/)
    
    set(CPACK_GENERATOR "DEB")
    set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Me")
    
    include(CPack)
    

    This is a pretty standard pattern with CMake, having a custom command create a file and a custom target depend on it so that it can be triggered as needed.