How to build debian package with CPack to execute setup.py?
Question: Until now, my project had only **.cpp** files that were compiled into
different binaries and I managed to configure **CPack** to build a proper
**debian package** without any problems.

Recently I wrote a couple of python applications and added them to the
project, as well as some custom modules that I would also like to incorporate
to the package.

After writing a `setup.py` script, I'm wondering how to add these files to the
**CPack** configuration in a way that `setup.py` get's executed automatically
when the user installs the package on the system with `dpkg -i package.deb`.

I'm struggling to find relevant information on how to configure CPack to
install custom python applications/modules. Has anyone tried this?


Answer: I figured out a way to do it but it's not very simple. I'll do my best to
explain the procedure so please be patient.

## The idea of this approach is to use _postinst_ and _prerm_ to install and
remove the python application from the system.

In the **CMakeLists.txt** that defines the project, you need to state that
**CPACK** is going to be used to generate a **.deb package**. There's some
variables that need to be filled with info related to the package itself, but
one named `CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA` is very important because it's
used to specify the location of **postinst** and **prerm** , which are
standard scripts of the _debian packaging system_ that are automatically
executed by **dpkg** when the package is installed/removed.

At some point of your **main** `CMakeLists.txt` you should have something like
this:

    
    
    add_subdirectory(name_of_python_app)
    
    set(CPACK_COMPONENTS_ALL_IN_ONE_PACKAGE 1)
    
    set(CPACK_PACKAGE_NAME "fake-package")
    set(CPACK_PACKAGE_VENDOR "ACME")
    set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "fake-package - brought to you by ACME")
    set(CPACK_PACKAGE_VERSION "1.0.2")
    set(CPACK_PACKAGE_VERSION_MAJOR "1")
    set(CPACK_PACKAGE_VERSION_MINOR "0")
    set(CPACK_PACKAGE_VERSION_PATCH "2")
    SET(CPACK_SYSTEM_NAME "i386")
    
    set(CPACK_GENERATOR "DEB")
    set(CPACK_DEBIAN_PACKAGE_MAINTAINER "ACME Technology")
    set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.3.1-6), libgcc1 (>= 1:3.4.2-12), python2.6, libboost-program-options1.40.0 (>= 1.40.0)")
    set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_SOURCE_DIR}/name_of_python_app/postinst;${CMAKE_SOURCE_DIR}/name_of_python_app/prerm;")
    set(CPACK_SET_DESTDIR "ON")
    
    include(CPack)
    

Some of these variables are **optional** , but I'm filling them with info for
educational purposes.

Now, let's take a look at the scripts:

**postinst** :

    
    
    #!/bin/sh
    # postinst script for fake_python_app
    
    set -e
    
    cd /usr/share/pyshared/fake_package
    sudo python setup.py install
    

**prerm** :

    
    
    #!/bin/sh
    # prerm script
    #
    # Removes all files installed by: ./setup.py install
    sudo rm -rf /usr/share/pyshared/fake_package
    sudo rm /usr/local/bin/fake_python_app
    

If you noticed, script **postinst** enters at
`/usr/share/pyshared/fake_package` and executes the **setup.py** that is
laying there to install the app on the system. Where does this file come from
and how it ends up there? This file is created by you and will be copied to
that location when your package is installed on the system. This action is
configured in `name_of_python_app/CMakeLists.txt`:

    
    
    install(FILES setup.py
            DESTINATION "/usr/share/pyshared/fake_package"
    )
    
    install(FILES __init__.py
            DESTINATION "/usr/share/pyshared/fake_package/fake_package"
    )
    
    install(FILES fake_python_app
            DESTINATION "/usr/share/pyshared/fake_package/fake_package"
    )
    
    install(FILES fake_module_1.py
            DESTINATION "/usr/share/pyshared/fake_package/fake_package"
    )
    
    install(FILES fake_module_2.py
            DESTINATION "/usr/share/pyshared/fake_package/fake_package"
    )
    

As you can probably tell, besides the python application I want to install
there's also 2 custom python modules that I wrote that also need to be
installed. Below I describe the contents of the most important files:

**setup.py** :

    
    
    #!/usr/bin/env python
    from distutils.core import setup
    
    setup(name='fake_package',
          version='1.0.5',
          description='Python modules used by fake-package',
          py_modules=['fake_package.fake_module_1', 'fake_package.fake_module_2'],
          scripts=['fake_package/fake_python_app']
         )
    

**__init_ _.py**: is an empty file.

**fake_python_app** : your python application that will be installed in
/usr/local/bin

And that's pretty much it!

