Trouble building C library (with makefile) - c

I'm doing a project in which I need to connect to an AR.Drone 2.0. I have a functional GUI in Java, but to control the drone I have to use it's SDK which is a C library. I wrote the necessary functions to combine Java and C via JNI, but because of the modifications I did to an example delivered with the SDK, it doesn't build anymore. It is thought to be built with a makefile (which I also have tried changing without success) running the make command. The problem is I am very new to C and makefiles, and I have searched the web a lot but have not found any solution. So here's how the library looks like:
.: Folder root
|
+ src: Sources
|
+ ARDroneLib: The AR.Drone Library
| |
| + Soft: Containing the "interesting" part of the whole lib
| | |
| | + More subdirs... (Build: contains a makefile, Common: c and h files, Lib: stuff)
| |
| + Many other subdirectories (FFMPEG, ITTIAM, VLIB, VP_SDK)
|
+ DroneControl: My own code
|
+ Source:The source files
| |
| + Navdata: Code to retrieve the navigation data
| | |
| | + navdata.c
| | + navdata.h
| |
| + Video: Code to retrieve the drone's video stream
| | |
| | + video_stage.c
| | + video_stage.h
| |
| + ardrone_testing_tool.c: Main file, containing the main function, etc.
| + ardrone_testing_tool.h: Its header
| + dronecontrol_ARDrone: My own file, containing JNI methods (also has an init() function which calls main() in ardrone_testing_tool.c)
| + dronecontrol_ARDrone: Its header
| + vars.h: Some shared variables
|
+ Build:Contains the makefile
|
+ makefile: The makefile
Here's the makefile in ./src/DroneControl/Build/:
SDK_PATH:=$(shell pwd)/../../ARDroneLib
PC_TARGET=yes
USE_LINUX=yes
ifdef MYKONOS
include $(ARDRONE_CUSTOM_CONFIG)
include $(ARDRONE_BUILD_CONFIG)
else
include $(SDK_PATH)/Soft/Build/custom.makefile
include $(SDK_PATH)/Soft/Build/config.makefile
endif
ifeq "$(RELEASE_BUILD)" "yes"
ARDRONE_TARGET_DIR=$(shell pwd)/../../../
else
ARDRONE_TARGET_DIR=$(shell pwd)/../../../Debug
endif
TARGET=linux_sdk_demo
SRC_DIR:=$(shell pwd)/../Sources
# Define application source files
GENERIC_BINARIES_SOURCE_DIR:=$(SRC_DIR)
GENERIC_BINARIES_COMMON_SOURCE_FILES+= \
Navdata/navdata.c \
Video/video_stage.c
GENERIC_INCLUDES+= \
$(SRC_DIR) \
$(LIB_DIR) \
$(SDK_PATH)/Soft/Common \
$(SDK_PATH)/Soft/Lib
GENERIC_TARGET_BINARIES_PREFIX=
GENERIC_TARGET_BINARIES_DIR=$(ARDRONE_TARGET_DIR)
GENERIC_BINARIES_SOURCE_ENTRYPOINTS+= \
ardrone_testing_tool.c
GENERIC_INCLUDES:=$(addprefix -I,$(GENERIC_INCLUDES))
GENERIC_LIB_PATHS=-L$(GENERIC_TARGET_BINARIES_DIR)
GENERIC_LIBS=-lpc_ardrone -lgtk-x11-2.0 -lrt
SDK_FLAGS+="USE_APP=yes"
SDK_FLAGS+="APP_ID=linux_sdk_demo"
export GENERIC_CFLAGS
export GENERIC_LIBS
export GENERIC_LIB_PATHS
export GENERIC_INCLUDES
export GENERIC_BINARIES_SOURCE_DIR
export GENERIC_BINARIES_COMMON_SOURCE_FILES
export GENERIC_TARGET_BINARIES_PREFIX
export GENERIC_TARGET_BINARIES_DIR
export GENERIC_BINARIES_SOURCE_ENTRYPOINTS
export GENERIC_LIBRARY_SOURCE_DIR=$(GENERIC_BINARIES_SOURCE_DIR)
.PHONY: $(TARGET) build_libs
all: build_libs $(TARGET)
$(TARGET):
#$(MAKE) -C $(SDK_PATH)/VP_SDK/Build $(TMP_SDK_FLAGS) $(SDK_FLAGS) $(MAKECMDGOALS) USE_LINUX=yes
mv $(ARDRONE_TARGET_DIR)/ardrone_testing_tool $(TARGET)
mv $(TARGET) $(ARDRONE_TARGET_DIR)/
$(MAKECMDGOALS): build_libs
#$(MAKE) -C $(SDK_PATH)/VP_SDK/Build $(TMP_SDK_FLAGS) $(SDK_FLAGS) $(MAKECMDGOALS) USE_LINUX=yes
build_libs:
#$(MAKE) -C $(SDK_PATH)/Soft/Build $(TMP_SDK_FLAGS) $(SDK_FLAGS) $(MAKECMDGOALS) USE_LINUX=yes
But when I try to make this, the make command gives me following error:
Libs already extracted
Building target static
/bin/sh: 1: ./autoConf.bash: Permission denied
make[2]: *** [build] Error 126
Checking required Ubuntu packages ...
ok.
Building ARDroneTool/Lib
Building ARDroneTool/Lib
ld ardrone_testing_tool
/usr/bin/ld: cannot find -lswscale
/usr/bin/ld: cannot find -lavformat
/usr/bin/ld: cannot find -lavcodec
/usr/bin/ld: cannot find -lavutil
collect2: ld returned 1 exit status
make[3]: *** [/home/user/workspace/AutoFlight/lib/native/DroneControl/src/DroneControl/Build/../../..//ardrone_testing_tool] Error 1
make[2]: *** [all] Error 2
make[1]: *** [build_app] Error 2
make: *** [linux_sdk_demo] Error 2
I have not been able to figure out what -lwscale, -lavformat, etc. are. I have also tried the make command as su (mainly because that "Permission denied" error), and hope this is the right place to ask this.
So does anybody have suggestions on how to get this compiled into a dynamically linked library (.so file)? Any help would be highly appreciated!
UPDATE 1: The permission denied error is now solved (thanks #eyalm)
UPDATE 2: It works now. I've rewritten the makefile but I don't know what's different now that could affect ld's path.

autoConf.bash is probably not executable. Running with su will not help. try:
# chmod a+x autoConf.bash

> /usr/bin/ld: cannot find -lswscale
> /usr/bin/ld: cannot find -lavformat
> /usr/bin/ld: cannot find -lavcodec
> /usr/bin/ld: cannot find -lavutil
> collect2: ld returned 1 exit status
It could be that these dependencies (i.e., libswscale, libavformat, libavcodec,
and libavutil) are either not present on your system, or are present
in directories that are not part of ld's standard search path.
If the dependencies are absent, then you would need to install them. On Debian-derived systems you could use the apt-file command to find the package you would need to install. For example:
% apt-file -l find libswscale.a
libswscale-dev
% apt-file -l find libavutil.a
libavutil-dev
...etc...
If these libraries are already present on your system, but are in non-standard locations,
you could use ld's -L option to add the relevant directories to its search path. For example:
% ld ..other-options... -L SEARCHDIR1 -L SEARCHDIR2 ... -lswscale -lavutil ...etc...
Note that the -L SEARCHDIR options need to appear before the -l
LIB options.

Related

gcc/ld can't find ldpdk, even with -L and ldconfig for dpdk-burst-replay

I'm trying to make the project dpdk-burst-replay, but the make process failed with the following error:
gcc -g -O2 -W -Wall -DNDEBUG -O2 -I/usr/include/dpdk -march=native -I/usr/local/include -g -O2 -W -Wall -DNDEBUG -O2 -L/usr/local/lib -pthread -lnuma -lm -ldl -Wl,--whole-archive -Wl,--start-group -ldpdk -Wl,--end-group -Wl,--no-whole-archive -o dpdk-replay dpdk_replay-main.o dpdk_replay-cpus.o dpdk_replay-dpdk.o dpdk_replay-pcap.o dpdk_replay-utils.o
/opt/rh/devtoolset-8/root/usr/libexec/gcc/x86_64-redhat-linux/8/ld: cannot find -ldpdk
collect2: error: ld returned 1 exit status
make[2]: *** [dpdk-replay] Error 1
make[2]: Leaving directory `/home/user/dpdk-burst-replay/src'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/home/user/dpdk-burst-replay'
make: *** [all] Error 2
So the particular problem here is ld: cannot find -ldpdk, and you can see from the gcc statement that there is : two declarations for directories : -I/usr/include/dpdk and -L/usr/local/lib.
But I have the /usr/include/dpdk folder as a symbolic link as following:
[user#server ~]$ ls -l /usr/include/ | grep dpdk
lrwxrwxrwx. 1 root root 88 Jul 27 07:30 dpdk -> /home/user/project/_build/lib/src_ext/dpdk/src/dpdk/x86_64-native-linux-gcc/include/
And inside /usr/local/lib there is the archive (i.e. static library) : `libdpdk.a'
[user#server ~]$ ls -l /usr/local/lib | grep dpdk
lrwxrwxrwx. 1 root root 83 Jul 27 08:13 dpdk -> /home/user/project/_build/lib/src_ext/dpdk/src/dpdk/x86_64-native-linux-gcc/lib
[user#server ~]$ ls -l /usr/local/lib/dpdk/ | grep dpdk
-rw-rw-r--. 1 user user 2791 Jul 27 05:55 libdpdk.a
So, basically libdpdk.a exists in /usr/local/lib/dpdk/ (which is a symbolik link if that matters).
Also I have edited /etc/ld.so.conf to add those pathes as following:
[user#server ~]$ cat /etc/ld.so.conf
include ld.so.conf.d/*.conf
/home/user/project/_build/lib/src_ext/dpdk/src/dpdk/x86_64-native-linux-gcc/lib
/home/user/project/_build/lib/src_ext/dpdk/src/dpdk/x86_64-native-linux-gcc/include
Also I've checked the following:
[user#server ~]$ sudo ld -verbose -L/usr/lib/dpdk -ldpdk | grep dpdk.a
attempt to open /usr/lib/dpdk/libdpdk.a succeeded
opened script file /usr/lib/dpdk/libdpdk.a
opened script file /usr/lib/dpdk/libdpdk.a
ld: warning: cannot find entry symbol _start; not setting start address
But still cannot find -ldpdk
EDIT1: Important note: the makefile is autogenerated by some tools, and Iit is not recommended to modify it.
EDIT2: I have modified the gcc flag -L/usr/local/lib to be -L/usr/local/lib/dpdk and it worked!(Thanks to #secret squirrel for the idea of modifying the gcc command for test).
=> So basically, the problem is that -L/path/to/lib is not finding the dpdk library, maybe because it is a symbolic link?
By the way, I just tried both versions of gcc 4.8.5, and gcc 8.3.1.
I'm working on x86_64 machine, using Linux Centos7.
Thanks in advance

How to link files within other directories?

I have a project that is big enough to benefit from having its files classified by directory. I'm trying to build one kernel module out of all of them.
The documentation states the following:
--- 3.6 Descending down in directories
A Makefile is only responsible for building objects in its own
directory. Files in subdirectories should be taken care of by
Makefiles in these subdirs. The build system will automatically
invoke make recursively in subdirectories, provided you let it know of
them.
To do so, obj-y and obj-m are used.
ext2 lives in a separate directory, and the Makefile present in fs/
tells kbuild to descend down using the following assignment.
Example:
#fs/Makefile
obj-$(CONFIG_EXT2_FS) += ext2/
If CONFIG_EXT2_FS is set to either 'y' (built-in) or 'm' (modular)
the corresponding obj- variable will be set, and kbuild will descend
down in the ext2 directory.
However, this seems to be different from what I need. What comes out of this is two independent .ko files; one in each directory, each an amalgamation of the object files in its own directory.
This is my project (simplified):
root directory
|
+--- Makefile
|
+--- foo.c
|
+--- subdir
|
+--- Makefile
|
+--- bar.c
I would think that ending up with something like this would be reasonable:
root directory
|
+--- Makefile
|
+--- foo.c
|
+--- foo.o (containing foo.c's stuff)
|
+--- subdir
| |
| +--- Makefile
| |
| +--- bar.c
| |
| +--- bar.o (containing bar.c's stuff)
|
+--- kernel-module.ko (containing foo.o and subdir/bar.o)
What I really end up with is this:
root directory
|
+--- Makefile
|
+--- foo.c
|
+--- foo.o (containing foo.c's stuff)
|
+--- subdir
| |
| +--- Makefile
| |
| +--- bar.c
| |
| +--- bar.o (containing bar.c's stuff)
| |
| +--- bar.ko (containing bar.o)
|
+--- kernel-module.ko (containing only foo.o)
I'm hoping that building one module per directory is not a fundamental assumption of Kbuild's design. Shipping several modules sounds like a lot of mess for no gain.
This is my root Makefile:
KERNEL_DIR ?= /lib/modules/$(shell uname -r)/build
obj-m += kernel-module.o
obj-m += subdir/
kernel-module-objs += foo.o
all:
make -C ${KERNEL_DIR} M=$$PWD
modules:
make -C ${KERNEL_DIR} M=$$PWD $#
clean:
make -C ${KERNEL_DIR} M=$$PWD $#
This is subdir/Makefile:
obj-m += bar.o
This is foo.c:
int external_function(void);
int test(void)
{
return external_function();
}
And this is subdir/bar.c:
int external_function(void)
{
return 4;
}
make (in the root directory) spits the following warning:
WARNING: "external_function" [(...)/kernel-module.ko] undefined!
And my attempts to insert kernel-module.ko are refused:
$ sudo insmod kernel-module.ko
insmod: ERROR: could not insert module kernel-module.ko: Unknown symbol in module
$ dmesg | tail -1
[11688.540153] kernel_module: Unknown symbol external_function (err 0)
How do I tell Kbuild that subdir/bar.o is supposed to be part of kernel-module.ko and not its own module?
One solution is to append bar's object file to the kernel module's object listing. The problem with this code:
obj-m += kernel-module.o
obj-m += subdir/
kernel-module-objs += foo.o
Is that it's telling Kbuild to descend to subdir/, but it's not telling it to include the results of that in kernel-module.
This would fix that:
obj-m += kernel-module.o
obj-m += subdir/
kernel-module-objs += foo.o subdir/bar.o
However, I don't like this solution at all because it breaks the DRY principle: It means bar.o has to be named twice; one in /Makefile and the other one in /subdir/Makefile.
Also, this solution doesn't prevent Kbuild from creating the redundant subdir/bar.ko module.
Finally, certain documentation states that it is "NOT recommended practice" for some completely unstated reason.
So this solution is pretty bad. I don't think I will stick to it.
Another solution (which branches from the previous one) is to just delete subdir/Makefile and, within the root Makefile, instead of this:
obj-m += kernel-module.o
obj-m += subdir/
kernel-module-objs += foo.o
do this:
obj-m += kernel-module.o
kernel-module-objs += foo.o subdir/bar.o
This fixes the DRY issue and prevents subdir/bar.ko from being generated but still suffers from discouraged practice.
I will stick to this solution in the meantime, but since neither of them is ideal, I guess I'll leave the question open for a while.

compile a static kernel driver to module

I am compiling linux kernel version 3.17. by default a driver is statically compiled into the linux kernel and is probed at boot time. But I want this particular driver to be build as a module so I changed the CONFIG_driver from 'y' to 'm'. But after doing so the kernel outputs an undefined reference error and breaks the build.
following console log
| LD drivers/built-in.o
| LINK vmlinux
| LD vmlinux.o
| MODPOST vmlinux.o
| GEN .version
| CHK include/generated/compile.h
| UPD include/generated/compile.h
| CC init/version.o
| LD init/built-in.o
| drivers/built-in.o: In function `adv7511_irq_handler':
| /var/adnan/work/git/mel_repos/mel_cedar_2/build/build_zedboard-zynq7-mel/tmp/work-shared/zedboard-zynq7-mel/kernel-source/drivers/gpu/drm/i2c/adv7511_core.c:314: undefined reference to `drm_helper_hpd_irq_event'
| make: *** [vmlinux] Error 1
| ERROR: oe_runmake failed
where as the function drm_helper_hpd_irq_event is present in drm_probe_helper.c. and according to the makefile
obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
the module which I am building selects CONFIG_DRM_KMS_HELPER. In the .config this is directly proportional to my module when I build my module this also gets build in module and otherwise it build statically. But when it builds in module the file is not compiled.
Any Idea ? How can I force this into static build while doing my driver in module ?
As a workaround, you can replace
obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
by
obj-y += drm_kms_helper.o

Makefile: Manage multiple include path

I have a project with this kind of tree:
/arch/arm/include/
/include/
I want to include files from /arch/arm/include/ with #include <arch/header.h> and files from /include with #include <header.h>.
How to do this in a Makefile ?
Thanks
this can be solved by creating a symbolic link include/arch that points to arch/arm/include
ln -s arch/arm/include include/arch
then in the makefile:
CFLAGS += -I/include
Use -I< include directory > option.
ex:
$(CC) -o $(TGT) test.c -I/include
You can add this method in your makefile. Assuming your filesystem looks like this
--------------------------------
| | |
include arch src
| |
arm makefile
|
include
LIBS_INC = -I../include
LIBS_INC += -I../arch/arm/include

Unable to understand the errors given by running make

My directory structure is /home/akshayaj/Desktop/System Programs/dictionary/
Inside dictionary I have 3 files:
libdictionary.c (implements all the functions except main),
libentrypoint.c (contains main()),
libdictionary.h (contains declaration of all the functions)
Both C files include the header file
Now I wrote a make file for the above project. It goes like this:-
CFLAGS=-I /home/akshayaj/Desktop/System Programs/dictionary/
libdict: libentrypoint.o libdictionary.o
cc $(CFLAGS) -o libdict libentrypoint.o libdictionary.o
libentrypoint.o: libentrypoint.c libdictionary.h
cc $(CFLAGS) -c libentrypoint.c
libdictionary.o: libdictionary.c libdictionary.h
cc $(CFLAGS) -c libdictionary.c
Now when I ran it, I got these errors:-
cc -I /home/akshayaj/Desktop/System Programs/dictionary/ -c libentrypoint.c
cc: error: Programs/dictionary/: No such file or directory
make: *** [libentrypoint.o] Error 1
Where am I going wrong?
Note:- In CFLAGS I have given the whole path because I saw it in a similar question, but that didn't work. Here is the link to that question.
C Compile Error (No such file or directory, compilation terminated)
Try to use path /home/akshayaj/Desktop/System\ Programs/dictionary/, where \ handles the space.
Think about how that command line would be parsed...
cc -I /home/akshayaj/Desktop/System Programs/dictionary/ -c libentrypoint.c
^^ ^------------------------------^ ^------------------^ ^-----------------^
| | | |
Command -I arg BAD ARG -c arg
As you can see, the space between "System" and "Programs" is read as a separator between two command args.
Your options are either:
Change the path so that the space is removed (recommended). e.g. /home/akshayaj/Desktop/System-Programs/dictionary/.
Add a backslash before the space to escape it. e.g.:
/home/akshayaj/Desktop/System\ Programs/dictionary/
As a general rule, it's not wise to use paths with spaces in them when building stuff using make, or just building stuff in general. It makes ambiguities like this hard to solve.

Resources