CMake ExternalProject_Add creates unpackaged files

Hello everyone,
I’m trying to ship a Qt plugin privately (so in /usr/share/harbour-sailfin, to comply with harbour rules) with my application, which is located in another git repository. Since I’m building with CMake, the logical thing to do for me was to use ExternalProject_Add. See the snippet attached below

set(DEPLOY_ROOT /home/deploy/installroot/)
ExternalProject_Add(BlurhashQt
    # PREFIX ${CMAKE_CURRENT_BINARY_DIR}/lib/blurhash-qt
    GIT_REPOSITORY https://github.com/HenkKalkwater/BlurhashQt.git
    GIT_TAG 6a0d05919a798eedeacdbc30507470b774b90f8d

    CMAKE_ARGS -DBUILD_SHARED_LIBS:BOOL=ON -DENABLE_EXPORT=OFF -DCMAKE_INSTALL_LIBDIR=${DEPLOY_ROOT}usr/share/harbour-sailfin/plugins)

The repository contains a CMake project as well, so CMake will naturally try to build it in the standard CMake way, by invoking another instance of CMake on that project. Yet this will try to install the project to “/usr/local” in the build engine, which doesn’t work of course. So to “help” CMake in building to the correct location, I thought I’ll give it a hint by passing the CMake argument -DCMAKE_INSTALL_LIBDIR=${DEPLOY_ROOT}usr/share/harbour-sailfin/plugins, where DEPLOYROOT is /home/deploy/installroot/. CMake will now happily install the project in the given location and they lived happily ever after.

But, they don’t, since the validator comes in and tells

Checking for unpackaged file(s): /usr/lib/rpm/check-files /home/deploy/installroot
error: Installed (but unpackaged) file(s) found:
   /home/deploy/installroot/usr/share/harbour-sailfin/plugins/libblurhash-qt.so

My Spectacle file in the build directory contains

Files:
  - '%{_bindir}'
  - '%{_datadir}/%{name}'
  - '%{_datadir}/applications/%{name}.desktop'
  - '%{_datadir}/icons/hicolor/*/apps/%{name}.png'

so it should be matched by the %{_datadir}/%{name}, right? It does work for the other library I build within my project itself with CMake. Well, when I enter the build engine and execute ls /home/deploy/installroot/usr/share/harbour-sailfin/plugins' it complains about the directory not being found, while /installroot/usr/share/harbour-sailfin/libdoes containlibjellyfin-qt.so`, as expected.

Full build log can be found here, due to post length limitations
Full source code of the project, as of writing, can be found here

Is there something wrong with my approach? Is it the cross compiler doing weird things? Can it be fixed?

I don’t want to copy the source of the blurhash-qt into my project, since I’m intending to reuse it some other projects of mine as well and it could potentionally be usefull to others as well (if the library would work properly :stuck_out_tongue: ).

Side note
The lines containing

+ CXXFLAGS='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -Wformat -Wformat-security -fmessage-length=0 -march=armv7-a -mfloat-abi=hard -mfpu=neon -mthumb -Wno-psabi'
+ export CXXFLAGS

very likely explain the issue which I’d encountered earlier, when the same project I was working on still was using QMake:

In your build log I found this line:

-- Installing: /home/deploy/installroot/home/deploy/installroot/usr/share/harbour-sailfin/plugins/libblurhash-qt.so

Notice how the /home/deploy/installroot part is there twice?

Maybe you should try removing the ${DEPLOY_ROOT} part from CMAKE_INSTALL_LIBDIR.

If I do that, so like this:

ExternalProject_Add(BlurhashQt
    # PREFIX ${CMAKE_CURRENT_BINARY_DIR}/lib/blurhash-qt
    GIT_REPOSITORY https://github.com/HenkKalkwater/BlurhashQt.git
    GIT_TAG 6a0d05919a798eedeacdbc30507470b774b90f8d

    CMAKE_ARGS -DBUILD_SHARED_LIBS:BOOL=ON -DENABLE_EXPORT=OFF -DCMAKE_INSTALL_LIBDIR=/usr/share/harbour-sailfin/plugins)

I’ll get eventually the error

[100%] Built target blurhash-qt
make[4]: Leaving directory '/home/chris/Programmeren/Sailfish/harbour-sailfin/build-armv7hl/sailfish/BlurhashQt-prefix/src/BlurhashQt-build'
Install the project...
-- Install configuration: ""
CMake Error at cmake_install.cmake:55 (file):
  file cannot create directory: /usr/share/harbour-sailfin/plugins.  Maybe
  need administrative privileges.


make[3]: *** [Makefile:118: install] Error 1
make[3]: Leaving directory '/home/chris/Programmeren/Sailfish/harbour-sailfin/build-armv7hl/sailfish/BlurhashQt-prefix/src/BlurhashQt-build'
make[2]: *** [sailfish/CMakeFiles/BlurhashQt.dir/build.make:77: sailfish/BlurhashQt-prefix/src/BlurhashQt-stamp/BlurhashQt-install] Error 2
make[2]: Leaving directory '/home/chris/Programmeren/Sailfish/harbour-sailfin/build-armv7hl'
make[1]: *** [CMakeFiles/Makefile2:218: sailfish/CMakeFiles/BlurhashQt.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....

And by setting the LIBDIR to share/harbour-sailfin/plugins, I’ll get roughly the same error, but for the path /usr/local/share/harbour-sailfin/plugins. Without it, it gets installed into /usr/local/lib/libblurhash-qt.so, which also fails.

The CMakeLists.txt of the blurhash-qt seems pretty standard to me:

cmake_minimum_required(VERSION 3.11)
project(blurhash-qt VERSION 1.0.0)

find_package(Qt5 COMPONENTS Core Qml Quick REQUIRED)
set(CMAKE_AUTOMOC ON)
include(GNUInstallDirs)

set(blurhash-qt_SOURCES
	blurhash_plugin.cpp
	blurhash.cpp)

set(qblurhash-qt_HEADERS
	blurhash_plugin.h
	blurhash.h)

option(ENABLE_EXPORT "Enable exporting of targets" ON)

add_library(blurhash-qt ${qt-blurhash_SOURCES})
target_link_libraries(blurhash-qt PRIVATE Qt5::Core Qt5::Qml Qt5::Quick)

install(TARGETS blurhash-qt EXPORT "BlurhashQt" 
	ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
	LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})

add_custom_command(
    TARGET blurhash-qt
    POST_BUILD
    COMMAND
        ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_LIST_DIR}/qmldir $<TARGET_FILE_DIR:blurhash-qt>/qmldir
)

if(${ENABLE_EXPORT})
	install(EXPORT "BlurhashQt" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
endif()

Ok, let’s try another approach:
Add this line in your .spec, after %make_install:

mv /home/deploy/installroot/home/deploy/installroot/usr/share/harbour-sailfin/plugins /home/deploy/installroot/usr/share/harbour-sailfin/plugins

Of course it would be better to get the file installed in the correct place in the first place. This is just a workaround…

Ugly workaround, but it works.

I think I also found the problem: ExternalProject_Add runs “make install” on the subproject being added during both the build phase and install phase of the project. During the build phase (make), it gets installed to /home/deploy/installroot/usr/share/harbour-sailfin/plugins, then the script seems to remove the entire /home/deploy/installroot directory when finally make install gets executed and the subproject gets installed to /home/deploy/installroot/home/deploy/installroot/usr/share/harbour-sailfin/plugins.

After some browsing on the internet, I’ve seen some CMakeFiles which first install the subproject with ExternalProject_Add to ${PROJECT_BINARY_DIR} during the build phase and use ExternalProject_Add_Step to copy the binary files to the correct location during the install phase. I think this way should be the cleaner way to go, but nevertheless, thanks a lot for your help! If it weren’t for you, I probably wouldn’t have found out!