Configuration files and log files installation with automake - automake

Let's say I have a project like that:
(dev dir)
- README
- INSTALL
/ src
- blah.cpp
- blah.hpp
/ conf
- blah_one.xml
- blah_two.xml
I made out a configure.ac and Makefile.am to install binaries under (/usr/local)/bin . configure.ac is something like:
AC_INIT([blah], [0.1])
AC_PREREQ([2.67])
AM_INIT_AUTOMAKE([1.11])
AC_CONFIG_SRCDIR([src/blah.cpp])
AC_PROG_CXX
AC_LANG([C++])
AC_HEADER_STDC
AC_CONFIG_FILES([Makefile])
AC_CONFIG_FILES([src/Makefile])
AC_OUTPUT
... Makefile is something like
SUBDIRS = src
...and src/Makefile.am is something like
bin_PROGRAMS = blah
blah_SOURCES = blah.cpp blah.hpp
It all works, and "make install" correctly install the binary under (/usr/local)/bin.
Now:
I want extend these to make the command "make install" (after configure, build and whatsoever) to install configuration files blah_one.xml and blah_two.xml under /etc/blah, and to "prepare" a log directory under /var/log/blah/
What is the correct way to do it?

Well, I'd do this:
blahconfdir=$(sysconfdir)/blah
blahconf_DATA = blah_one.xml blah_two.xml
blahlogdir = $(localstatedir)/log/blah
then when you configure:
./configure --sysconfdir=/etc --localstatedir=/var
Without knowing details of your "prepare" step, it's hard to know what needs to happen, and how to get it to happen.

Related

Yocto Transaction Test, two recipes install the same file

I am adding a custom recipe to my image. It is bases on DBCPPP. This project is built using cmake. My issue only comes to light when I include a new layer meta-swupdate. It seems meta-swupdate alters the kernel in a way that conflicts with dbcppp. My full error is:
Error: Transaction test error:
file /usr/lib/libxml2.so.2.9.10 conflicts between attempted installs of dbcppp-1.0+gitr0+fa8ce17468-r0.cortexa7t2hf_neon and libxml2-2.9.10-r0.cortexa7t2hf_neon
To build and include dbcppp I added the recipe:
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
SRC_URI = "gitsm://github.com/xR3b0rn/dbcppp.git;protocol=https;branch=master"
PV = "1.0+gitr${SRCPV}"
SRCREV = "${AUTOREV}"
DEPENDS += " boost"
S = "${WORKDIR}/git"
inherit pkgconfig cmake
FILES_${PN} += "/usr/lib/xml2Conf.sh /usr/lib/lib*.so.*"
SOLIBS = ".so"
FILES_SOLIBSDEV = ""
INSANE_SKIP_${PN} += "dev-so"
I have read a few other questions and attempted two solutions by adding a do_install_append step.
Change folder permission level install -d 0755 ${D}/usr/lib
Remove the folder rm -rf ${D}/usr/lib
Neither solution worked. I need both libraries in my application and I unsure how to proceed.
Edit: After some further reading I found a suggestion to delete the tmp, cache, and sstate-chace folders. I did this but I receive the same error.
Edit: My local.conf has PACKAGE_CLASSES ?= 'package_rpm' defined. if I remove this I still get a do_rootfs error, but the error message is not helpful.
Edit: In my recipe for dbcppp I have attempted to remove the file in question. This gives me the same error. Makes no difference.
do_install_append() {
rm -rf /usr/lib/libxml2.so.2.9.10
}

How can I package a Qt program built with CMake on Windows?

I'm writing a cross-platform program which I'd like to package on Windows. I got it to run by putting three DLLs (Qt5Core, Qt5Widgets, Qt5Gui) in the build directory, then made a tarball and gave it to someone else with a Windows box, but it would not run on his Windows box. I searched for a way to get whatever else it needed and found Nathan Osman's post about windeployqt, so I copied windeployqt.cmake to the cmake/Modules directory, but couldn't figure out how to use it. Is there a way to use CPack to make a package (even if it's just a tarball) that has everything needed to run the program on a Windows box that doesn't have the compiler or Qt installed?
Here's the CMakeLists.txt file with some (hopefully irrelevant) stuff removed:
project(perfecttin)
cmake_minimum_required(VERSION 3.8.0)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_CXX_STANDARD 17) # appeared in CMake 3.8
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS ON)
set(SHARE_DIR ${CMAKE_INSTALL_PREFIX}/share/perfecttin)
add_definitions(-DBOOST_ALL_NO_LIB)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
set(Boost_USE_STATIC_LIBS ON)
else ()
set(Boost_USE_STATIC_LIBS OFF)
endif ()
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
find_package(LibPLYXX)
find_package(Qt5 COMPONENTS Core Widgets Gui LinguistTools REQUIRED)
find_package(Boost COMPONENTS program_options)
find_package(Threads)
qt5_add_resources(lib_resources perfecttin.qrc)
qt5_add_translation(qm_files perfecttin_en.ts perfecttin_es.ts)
# To update translations, run "lupdate *.cpp -ts *.ts" in the source directory.
add_executable(perfecttin-gui adjelev.cpp angle.cpp binio.cpp
<snip lots of source files>
unitbutton.cpp ${lib_resources} ${qm_files})
target_link_libraries(perfecttin-gui ${CMAKE_THREAD_LIBS_INIT} Qt5::Widgets Qt5::Core)
target_link_libraries(fuzzptin ${CMAKE_THREAD_LIBS_INIT})
target_compile_definitions(fuzzptin PUBLIC _USE_MATH_DEFINES)
target_compile_definitions(perfecttin-gui PUBLIC _USE_MATH_DEFINES)
set_target_properties(perfecttin-gui PROPERTIES WIN32_EXECUTABLE TRUE)
install(TARGETS perfecttin-gui DESTINATION bin)
install(FILES ${qm_files} DESTINATION share/perfecttin)
include_directories(${PROJECT_BINARY_DIR})
configure_file (config.h.in config.h)
set(CPACK_PACKAGE_VERSION_MAJOR ${PERFECTTIN_MAJOR_VERSION})
set(CPACK_PACKAGE_VERSION_MINOR ${PERFECTTIN_MINOR_VERSION})
set(CPACK_PACKAGE_VERSION_PATCH ${PERFECTTIN_PATCH_VERSION})
set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/COPYING)
set(CPACK_SOURCE_IGNORE_FILES /\\\\.git;.*~)
include(CPack)
include(CTest)
If you already have in your ${CMAKE_SOURCE_DIR}/cmake/Modules/ directory the file Windeployqt.cmake, you may use it like this:
install(TARGETS perfecttin-gui
DESTINATION "${INSTALL_BIN_PATH}"
)
if(WIN32)
include(Windeployqt)
windeployqt(nitroshare-cli ${INSTALL_BIN_PATH})
endif()
Here is the full example.
I did borrow a lot from this answer, however it was missing the necessary environmental setup which leads to Warning: Cannot find GCC installation directory. g++.exe must be in the path..
Qt has the following documentation on using windeployqt.exe
The tool can be found in QTDIR/bin/windeployqt. It needs to be run within the build environment in order to function correctly.
When using Qt Installer, the script QTDIR/bin/qtenv2.bat should be used to set it up.
Basically you need to run windeployqt.exe as a custom command within the correct environment.
# Retrieve the absolute path to qmake and then use that path to find
# the windeployqt executable
get_target_property(QMAKE_EXE Qt6::qmake IMPORTED_LOCATION)
get_filename_component(QT_BIN_DIR"${QMAKE_EXE }" DIRECTORY)
find_program(WINDEPLOYQT_ENV_SETUP qtenv2.bat HINTS "${QT_BIN_DIR}")
find_program(WINDEPLOYQT_EXECUTABLE windeployqt HINTS "${QT_BIN_DIR}")
# Run windeployqt immediately after build
add_custom_command(TARGET perfecttin-gui
POST_BUILD
COMMAND "${WINDEPLOYQT_ENV_SETUP}" && "${WINDEPLOYQT_EXECUTABLE}" \"$<TARGET_FILE:perfectin-gui>\"
)
"Since version 6.3, Qt offers a way to define additional deployment steps that are executed on installation."
- https://www.qt.io/blog/cmake-deployment-api
Among other things there is now a *deploy utility script generator already included.
install(TARGETS perfecttin-gui DESTINATION bin)
qt_generate_deploy_app_script(
TARGET perfecttin-gui
FILENAME_VARIABLE deploy_script
NO_UNSUPPORTED_PLATFORM_ERROR
)
install(SCRIPT ${deploy_script})
Documentation is at: generate-deploy-app-script
According to the docs so far this doesn't work on Linux
For some more options (and apparently Linux support?) one could use the function which the above convenience version actually invokes: qt-deploy-runtime-dependencies
For example qt_generate_deploy_app_script() puts the Qt plugins outside of the destination 'bin' directory, each in their own folder, which I don't like (I want them all under 'bin'). So I had to use the full version (this is all basically from the Qt docs linked above):
set(MY_APP perfecttin-gui)
if(APPLE)
set(executable_path "$<TARGET_FILE_NAME:${MY_APP}>.app")
else()
set(executable_path "\${QT_DEPLOY_BIN_DIR}/$<TARGET_FILE_NAME:${MY_APP}>")
endif()
set(deploy_script "${CMAKE_CURRENT_BINARY_DIR}/deploy_${MY_APP}.cmake")
file(GENERATE OUTPUT ${deploy_script} CONTENT "
include(\"${QT_DEPLOY_SUPPORT}\")
qt_deploy_runtime_dependencies(
EXECUTABLE \"${executable_path}\"
PLUGINS_DIR bin
)"
)
install(TARGETS ${MY_APP} DESTINATION bin)
install(SCRIPT ${deploy_script})
See https://www.qt.io/blog/cmake-deployment-api for more details about deployment in general
ADDED:
Found the source for qt_deploy_runtime_dependencies().
Looks like the next version adds a NO_TRANSLATIONS option, but it's not in my 6.4.1.
But I did find a hack to pass additional options to the deploy tool...
If you search that code for __qt_deploy_tool_extra_options you'll see the warning about how it may go away. But as a workaround...
My file(GENERATE OUTPUT) now looks like this (likely needs adjusting per platform):
file(GENERATE OUTPUT ${deploy_script} CONTENT "
include(\"${QT_DEPLOY_SUPPORT}\")
set(__qt_deploy_tool_extra_options --no-compiler-runtime --no-translations)
qt_deploy_runtime_dependencies(
EXECUTABLE \"${executable_path}\"
PLUGINS_DIR bin
# NO_TRANSLATIONS
)
")
Also the qt_generate_deploy_app_script() source if anyone is interested.

Automake/Autoconf scripts custom directory

My project's root folder is PROJECT, and there is only one script in PROJECT/scripts/abc.sh, which I want to install it into the directory /usr/share/xxx/abc.sh.
Because it is not install into /usr/bin/abc.sh, so bin_SCRIPTS = abc.sh is incorrect.
Could you please tell me how to write the Makefile.am?
You'll need to define the install directory:
xxxdir = $(datarootdir)/xxx
xxx_SCRIPTS = scripts/abc.sh
More typically as something like:
pkgdata_SCRIPTS = scripts/abc.sh
where automake has already setup pkgdatadir.

libtool: what is the path to my module?

I am creating a module from an autotools+libtool project:
The Makefile.am looks as follows
#the module:
lib_LTLIBRARIES = mmmm.la
mmmm_la_SOURCES = mmmm.c
mmmm_la_LDFLAGS = $(AM_LDFLAGS) -module -shared
Now, I want to write a C test for my module. The test should start loading the shared object mmmm.xx (where .xx is .so or .la)
What path should I give to dlopen() or lt_dlopen() in my C test?: The relative location of my module (compared to the test program) is different depending on whether I do make check, an out of tree make check, or a make installcheck...
I tried with lt_dlopen() hoping that the -dlopen option passed on the test Makefile.am would help autotools to locate the lib when lt_dlopen() is called, but it does not seem to help: lt_dlopen() can open the .la file, indeed, but one still have to tell where that file is located (possibly ommiting the .libs directory)
My test makefile looks like this when testing with the ltdl lib:
#the module test (tests are also installed, hence the "test" prefix)
test_PROGRAMS = tttt
tttt_SOURCES = tttt.c
tttt_LDADD = "-dlopen" mmmm.la
tttt_DEPENDENCIES = mmmm.la
Any good hint?
One way you can deal with that is to set up the LD_LIBRARY_PATH env variable to where your library will be installed.
However, since you need it for the tests I will say export a variable from the configure.ac to the config.h. Thus, any file including the config.h would have a #define your_variable which can be used to set up the path for dlopen.

Packaging a library with Autotools

I'm starting out with Autotools, and I'm trying to package a library (a generic stack implementation for learning purposes) along with some usage examples.
The library source lives in src and the example in examples.
I have the following Makefile.am:
lib_LTLIBRARIES = libstack.la
libstack_la_SOURCES = src/stack.c
check_PROGRAMS = example/stack
example_stack_SOURCES = example/stack.c
example_stack_LDADD = libstack.la
As long as my understanding goes, I need to specify a header for libstack.la, and include that from my example, but I get the following error when running autoreconf after adding libstack_la_HEADERS = src/stack.h to Makefile.am:
$ autoreconf -iv
... (omiting irrelevant parts)
Makefile.am:3: error: 'libstack_la_HEADERS' is used but 'libstack_ladir' is undefined
autoreconf: automake failed with exit status: 1
I couldn't find any information related to the dir prefix.
What am I missing here?
To handle header of library you should write something like this:
libstackincludedir = $(includedir)/my_mega_stack
libstackinclude_HEADERS = stack.h

Resources