Openwrt : How to add a specific library dependency in new package - makefile

I am trying to add a package for directfb tutorials. I followed the instructions in http://wiki.openwrt.org/doc/devel/packages.
Currently the package is downloaded successfully to the dl folder and even compiled in the build directory, but when I add the install section to the makefile I get dependency error:
Package directfb_tutorials is missing dependencies for the following libraries:
libdirect-1.4.so.0
libdirectfb-1.4.so.0
libfusion-1.4.so.0
libpthread.so.0
The package Makefile (I put it under package/utils/directfb_tutorials/):
include $(TOPDIR)/rules.mk
PKG_NAME:=DFBTutorials
PKG_VERSION:=0.5.0
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=http://www.directfb.org/downloads/Extras/
PKG_MD5SUM:=13e443a64bddd68835b574045d9025e9
PKG_LICENSE:=LGPLv2.1
PKG_LICENSE_FILES:=COPYING
PKG_FIXUP:=autoreconf
PKG_INSTALL:=1
include $(INCLUDE_DIR)/package.mk
define Package/directfb_tutorials
TITLE:=directfb_tutorials
SECTION:=utils
CATEGORY:=Utilities
URL:=http://directfb.org
DEPENDS:=+libdirectfb
endef
define Package/directfb_tutorials/description
DirectFB Tutorials
endef
define Build/Configure
$(call Build/Configure/Default,)
endef
define Package/directfb_tutorials/Build/Compile
$(MAKE) -C $(PKG_BUILD_DIR)
endef
define Package/directfb_tutorials/install
$(INSTALL_DIR) $(1)/bin/dfb_tutorials
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/image/image $(1)/bin/dfb_tutorials/
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/simple/simple $(1)/bin/dfb_tutorials/
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/keybuffer/keybuffer $(1)/bin/dfb_tutorials/
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/text/text $(1)/bin/dfb_tutorials/
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/sprite/sprite $(1)/bin/dfb_tutorials/
endef
$(eval $(call BuildPackage,directfb_tutorials))
When adding +libpthread to the DEPENDS section, libpthread.so.0 does not appear in the missing dependencies error message above:
Package directfb_tutorials is missing dependencies for the following libraries:
libdirect-1.4.so.0
libdirectfb-1.4.so.0
libfusion-1.4.so.0
is because I must have used DEPENDS in a wrong manner (DEPENDS= +libdirectfb). How can I tell the correct name of the library for the DEPENDS flag? Is the fact that the library is installed to /usr/lib instead of just /lib (like libpthread) makes a difference?
Thanks in advance,
Tomer

The message about missing libraries comes from check fired from include/package-ipkg.mk. It is the latest stage of package creation. This check is verifying all executable files have all needed libraries available in the system. To enforce that, system requires you to add some entries in "DEPENDS" section. But before - you need of course to know, which one(s) to add.
To find missing library provider, if the case is not obvious (usually it is just a library name), you may search in $STAGING_DIR/pkginfo folder. In my case it is staging_dir/target-mips_mips32_uClibc-0.9.33.2/pkginfo.
Just cd to that folder and run something like:
grep libdirect-1.4.so.0 "*.provides"
You should see one or more results. Use common sense to pick the best one, usually it is a package named similar to the library, but not always. This is a generic way, should be helpful in case you miss the package in DEPENDS and cannot easily guess the correct one(s).
My guess is, that you should modify DEPENDS in your Makefile to contain
this:
DEPENDS:=+libdirect +libdirectfb +libfusion +libpthread

Look at the iftop core package for a syntax example:
https://github.com/openwrt/openwrt/blob/master/package/network/utils/iftop/Makefile#L28
It is the perfect example. The right syntax should be:
DEPENDS:=+libdirectfb +libpthread

Related

Passing extra compilation flags to debug build in bitbake recipe

As Bitbake builds -dev and -debug for recipes is it possible for defining compilation definitions specific to debug build for a particular recipe. Lets say I have some source code under DEBUG_INFO for some recipe i.e.,
#ifdef DEBUG_INFO
........... do something
#endif /* DEBUG_INFO */
and uses cmake in bitbake environment.
I want this flag be enabled for the debug binaries generated in the .debug folder. Is this possible?
If I use EXTRA_OECMAKE = "-DDEBUG_INFO" it gets enabled to both dev and debug builds.
No, it is not possible. All packages of a recipe are built in one go, they're just the same files but split somehow.
The only difference is with "special flavors" of a recipe (native, nativesdk, target, multilib, toolchain-specific recipes, etc...), in that case, you can have different flags but still, all the packages resulting from the build of this "flavor" will be built with the same flag.
If you want to build another variant of a package where a certain CMake flag is set in the compilation, you can create a variant of the recipe. If the main recipe is named my-app_git.bb you can create another recipe file named my-app-tweak_git.bb and a common base, my-app.inc. In the bb files, include the inc file:
require my-app.inc
Move most of what's now in my-app_git.bb to my_app.inc, e.g. SRC_URI, but define different contents for EXTRA_OECMAKE in the .bb files.
Now you will have to decide which one of my-app and my-app-tweak goes into the image by specifying either my-app or my-app-tweak in an IMAGE_INSTALL definition.
This is not exactly what you asked for, but as has been stated by qschulz, you cannot change the contents of the -dev and -dbg sub-packages.
Also note that dbg and dev can be considered reserved words for variants of the package name, so if you want to use something other than tweak, as in my example, you cannot use any of them.

Why does cmake always use `-isystem` on imported interface target?

I'm trying to write a CMakeLists.txt to compile my Arduino-Projects to get to know cmake better.
I defined the Arduino-Core library as an imported interface and try to link my own target against it. The problem is, that, when calling make the avr-gcc is provided with the specified include-paths via -isystem instead of -I. This results in several errors.
CMakeLists.txt (minimal-version to reproduce the problem)
cmake_minimum_required(VERSION 3.1)
set(ARDUINO_DIR "/opt/arduino/arduino-1.8.13")
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_C_COMPILER ${ARDUINO_DIR}/hardware/tools/avr/bin/avr-gcc)
set(CMAKE_CXX_COMPILER ${ARDUINO_DIR}/hardware/tools/avr/bin/avr-g++)
set(CMAKE_SYSTEM_NAME NONE)
set(CMAKE_SYSTEM_PROCESSOR NONE)
add_library(Arduino::Core INTERFACE IMPORTED)
target_include_directories(Arduino::Core INTERFACE
"${ARDUINO_DIR}/hardware/arduino/avr/cores/arduino/"
"${ARDUINO_DIR}/hardware/arduino/avr/variants/eightanaloginputs/"
)
file(GLOB_RECURSE ARDUINO_CORE_SRC "${ARDUINO_DIR}/hardware/arduino/avr/cores/arduino/*.c[p]*")
file(GLOB_RECURSE ARDUINO_CORE_ASM "${ARDUINO_DIR}/hardware/arduino/avr/cores/arduino/*.S")
target_sources(Arduino::Core INTERFACE ${ARDUINO_CORE_SRC} ${ARDUINO_CORE_ASM})
project(Blinky)
set(${PROJECT_NAME}_SRC
src/Blink.cpp
)
add_executable(${PROJECT_NAME} ${${PROJECT_NAME}_SRC})
target_link_libraries(${PROJECT_NAME} Arduino::Core)
Here is my Blink.cpp:
#include <Arduino.h>
void setup()
{
pinMode(13,OUTPUT);
}
void loop()
{
digitalWrite(13,HIGH);
delay(1000);
digitalWrite(13,LOW);
delay(1000);
}
make --trace gives me the following output:
[ 5%] Building CXX object CMakeFiles/Blinky.dir/src/Blink.cpp.obj
/opt/arduino/arduino-1.8.13/hardware/tools/avr/bin/avr-g++ -isystem /opt/arduino/arduino-1.8.13/hardware/arduino/avr/cores/arduino -isystem /opt/arduino/arduino-1.8.13/hardware/arduino/avr/variants/eightanaloginputs -std=gnu++11 -o CMakeFiles/Blinky.dir/src/Blink.cpp.obj -c /tmp/so/src/Blink.cpp
As you can see, linking against the imported target includes the dependencies with -isystem even though I haven't declared SYSTEM anywhere? How can I prevent that?!
Is it, because it is an INTERFACE IMPORTED target?
I tried taget_include_directories(Arduino::Core PRIVATE ${my_include_dirs}) but obviously that is not allowed for INTERFACE-Targets.
Thanks in advance for every hint.
P.S. please note, that I'm aware, that this would not compile my arduino-code. This is just a mcve to show you my problem.
edit
I'm using Arduino-SDK 1.8.13 and cmake 3.18.2
It is because it is an imported target.
From the CMake docs on buildsystems at the section for "include directories and usage requirements" (one of the last paragraphs in the section):
When the INTERFACE_INCLUDE_DIRECTORIES of an imported target is consumed, the entries in the property are treated as SYSTEM include directories, as if they were listed in the INTERFACE_SYSTEM_INCLUDE_DIRECTORIES of the dependency. This can result in omission of compiler warnings for headers found in those directories. This behavior for Imported Targets may be controlled by setting the NO_SYSTEM_FROM_IMPORTED target property on the consumers of imported targets, or by setting the IMPORTED_NO_SYSTEM target property on the imported targets themselves.
See the docs for include_directories and target_include_directories for other documentation on SYSTEM.
As stated in the docs, you can solve this by modifying consumers of the imported target like set_target_property(${PROJECT_NAME} PROPERTIES NO_SYSTEM_FROM_IMPORTED TRUE) or set_property(TARGET ${PROJECT_NAME} PROPERTY NO_SYSTEM_FROM_IMPORTED TRUE).
But there's another option not mentioned in the docs I quoted that I think may be better: In the docs for NO_SYSTEM_FROM_IMPORTED, it says:
See the IMPORTED_NO_SYSTEM target property to set this behavior on the target providing the include directories rather than consuming them.
I think it's better because NO_SYSTEM_FROM_IMPORTED will change the "system-ness" of all imported targets that the consumer links to, which may not be desirable. Perhaps a similar argument could be made against IMPORTED_NO_SYSTEM, but I personally can't think of a good backing for such an argument at the moment.

GNU Make does not include all auto-generated includes before executing dependent rule

My makefile makes use of auto-generated dependencies. To do this, I have in my top-level makefile something similar to:
# Makefile
include target1.deps
include target2.deps
all: target2.deps
cat $^
target2.deps: target1.deps
target1.deps:
echo "target2.deps:" > $#
echo " touch target2.deps" >> $#
Initially, target1.deps and target2.deps do not exist. When make is first instantiated, it parses the entire Makefile and searches for a way to generate these include files. After building them, it reinvokes itself, causing the Makefile to be reparsed and the include files to be included this time. At least, that's my understanding.
The issue is that when I run the above Makefile, Make first builds target1.deps, then executes the body of the all rule, never having built or included target2.deps. This causes cat to error: cat: target2.deps: No such file or directory
This seems like a contradiction to me. I explicitly tell Make that all depends on target2.deps, but it attempts to execute the rule before satisfying its prerequisites!
The intended behavior is that target1.deps should be built and included, then target2.deps should be built and included using the rule contained within target1.deps, and then all should be run. How do I achieve this?
Context: Since this is weirdly abstract, here's my goal: I have a target index.html, which gets generated from a template index.html.in, but I don't know anything about its dependencies. I need to find out (a) which files I need to create before building index.html and (b) which files index.html will depend on at runtime.
For example index.html includes some inline css that's pulled out of global.css - I need to therefore build global.css before building index.html. On the other hand, index.html links to about.html, so after I build index.html I want to also build about.html. I call the former "build dependencies" and the latter "runtime dependencies". So my makefile looks something like this:
include index.html.build_deps
include index.html.runtime_deps
all: index.html $(runtime_deps_index.html)
%.build_deps: %.in
./extract_build_deps %< -o %#
%.runtime_deps: %
./extract_runtime_deps %< -o %#
%: %.in
./compile_template %< -o $#
What I want to happen is for Make to follow these steps:
Build index.html.build_deps
Include index.html.build_deps
Build global.css (now a known prerequisite of index.html)
Build index.html
Build index.html.runtime_deps
Include index.html.runtime_deps
Build about.html (contained inside $(runtime_deps_index.html) included from index.html.runtime_deps)
Target all is reached
What actually happens:
Make sees that index.html.build_deps can be directly build from index.html.in; does so.
Make sees that index.html.runtime_deps can be built from index.html, can be built from index.html.in.
Make builds index.html. It errors because global.css hasn't yet been built.
If Make had included index.html.build_deps after building that, then it would be aware of the global.css dependency. But because it tries to build all include files before expanding any of them, it's unaware of the dependency. I want to add a dependency "index.html.runtime_deps depends on index.html.build_deps having been included, but I'm not sure how to specify such a dependency.
#Dario is correct. To be a bit more specific, these are the steps make will follow here:
Read the makefile.
Try to build target1.deps.
Find a target target1.deps and execute the recipe.
The recipe succeeds, but make observes that the file target1.deps still does not exist, so make doesn't mark the target as updated.
Try to build target2.deps.
There's a target for it that depends on target1.deps, which make already built, but there's no recipe for it so make doesn't mark target2.deps as updated (since it was never updated, as far as make can tell--it didn't run any recipe to update it).
So, make decides none of the included makefiles were actually updated and it won't re-exec.
Then make wants to build all; it sees that all depends on target2.deps but make already considered that target and decided it didn't need to be rebuilt, so now make is done with all its work.
You can run make -d and follow along with the decisions make takes.

What is the exact role of the DEPENDS in Makefile?

Here is a sample of my Makefile.
define Package/luci-app-myapp
SECTION:=luci
CATEGORY:=LuCI
SUBMENU:=3. Applications
TITLE:=GUI for myapp package
PKGARCH:=all
DEPENDS:=+myapp
endef
What is the exact role of the DEPENDS in this Makefile?
And what elements can be the value of the DEPENDS?
DEPENDS is basically a variable. In openwrt this variable is used to define dependency between the packages.
Detailed use of this variable is documented in openwrt link

CMake Hierarchical Project Management Without Abusing Libraries

I have a project where there's only a handful of logical groupings for generating static libraries. However for convenience I want to have the library's source code to be managed with more granular folders.
Currently the only way I know to do this in CMake without having a library for each folder is to just list files as you would normally in with their relative paths:
add_library(SystemAbstraction STATIC "Some/Path/File.cpp")
However I can see this getting unwieldy as the project grows in size with all the different paths.
I tried to see if I could have a CMakeLists.txt in each folder and just use a variable in the base CMakeLists.txt when adding library dependencies. But it seems that add_subdirectory doesn't also import variables?
For expanding the scope of a variable inside a subdirectory, use the PARENT_SCOPE option of set. For example, you can test that if you have
# CMakeLists.txt
set(SRCS main.c)
add_subdirectory(foo)
message(${SRCS})
in the root directory and
# foo/CMakeLists.txt
set(SRCS ${SRCS} foo.c PARENT_SCOPE)
in a subdirectory then it will print main.c foo.c, i.e., the variable is correctly imported into the base CMakeLists.txt.
An option would be to use the object library feature of CMake. You still can but doesn't need to organise your CMake script into subdirectories:
add_library(lib1 OBJECT <srcs>)
add_library(lib2 OBJECT <srcs>)
...
add_library(mainlib $<TARGET_OBJECTS:lib1> $<TARGET_OBJECTS:lib2>)
You can set different compile flags for each object library:
target_include_directories(lib1 PRIVATE incl-dir-for-lib1)
target_compile_definitions(lib2 PRIVATE def-for-lib2)
You still need to set link libraries on your main library:
target_link_libraries(mainlib PRIVATE deps-of-lib1 deps-of-lib2)
Related documentation: Object Libraries

Resources