Petalinux Recipe-app for mixed C and C++ application - c++

I have a rather large C program that I have already written. I'm now being asked to utilize a C++ class that a co-worker has written. I'm use to working with python, so writing my application in C and now being asked to work with C++ is causing some migraines. So ignoring my main application I decided to do some research and came across a youtube video that shows me how to do a very simple C program that calls a C++ class.
In order to compile the C program and allow it to call a C++ file, I needed to do two things, 1) use the C++ compiler (g++) and make sure to surround my c++ functions with < extern "C">. By doing this I was able to compile and run the application with no issues.
Here are the files that I'm currently using.
cppObject.cpp
cppObject.h
cppFunctions.cpp
cppFunctions.h
test.c
"test.c" is where the main method is, which calls the cppFunctions class, which then references functions within cppObject.cpp. Now I don't think I need to go into each of these functions as I can compile this with no issues, using.
g++ cppObject.cpp cppFunctions.cpp test.c -o test_exc
This generates an executable which runs with no issues.
Now because this is being built with Petalinux, Petalinux generates a recipe-app that includes a bitbake file and a makefile. Which both need to be modified in some way to accomplish my goal.
I'll be using this test case to reference for my main application.
As my C application has mainly been written, compiles, and runs with no issues. I decided to model the makefile and bitbake files after them.
APP = APP_name
# Add any other object files to this list below
APP_OBJS = file1.o \
file2.o \
file3.o \
file4.o \
file5.o \
# ...
all: build
build: $(APP)
LDLIBS += -lm
LDFLAGS += -lpthread
$(APP): $(APP_OBJS)
$(CC) -o $# $(APP_OBJS) $(LDFLAGS) $(LDLIBS)
clean:
rm -f $(APP) *.o
So based on the above makefile I attempted the same thing, using the test applications file names, and g++ instead of gcc
APP = test
# Add any other object files to this list below
APP_OBJS = cppObject.o cppFunctions.o test.o
all: build
build: $(APP)
$(APP): $(APP_OBJS)
$(CXX) -o $# $(APP_OBJS) $(LDFLAGS) $(LDLIBS)
clean:
rm -f $(APP) *.o
Now the bitbake file which matches my original application looks like this.
#
# This file is the **** recipe.
#
SUMMARY = "Simple **** application"
SECTION = "PETALINUX/apps"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
SRC_URI = "file://file1.c \
file://file2.c \
file://file3.c \
file://file4.c \
file://file5.c \
file://file2.h \
file://file3.h \
...
"
S = "${WORKDIR}"
do_compile() {
oe_runmake
}
do_install() {
install -d ${D}${bindir}
install -m 0755 **** ${D}${bindir}
}
I ended up making this one for the test application
#
# This file is the test recipe.
#
SUMMARY = "Simple test application"
SECTION = "PETALINUX/apps"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
SRC_URI = "file://cppObject.cpp \
file://cppFunctions.cpp \
file://cppObject.h \
file://cppFunctions.cpp \
file://test.c \
file://Makefile \
"
S = "${WORKDIR}"
do_compile() {
oe_runmake
}
do_install() {
install -d ${D}${bindir}
install -m 0755 test ${D}${bindir}
}
The petalinux-build -c for the application fails to build and the main error "test.c:2:10: fatal error: cppFunctions.h No such file or directory"
If I setup the makefile on its own and run make, it will build just fine, if I replace the objectfiles with the C/C++ files instead.
I'm assuming what is happening is Petalinux uses the bitbake file to generate the object files. Which then the Makefile uses to build the actual application.
Any insight that would allow me to use petalinux to build the application.
So caught a error in the .bb file, #vermaete also pointed it out. I left off the cppFunctions.h file. I ended up adding it to the .bb file and rebuilt the recipe. Unfortunately, I'm still getting a build error. However, its different, in that its having issues with an undefined reference.
undefined reference to 'printObjValue'
Which is a function call.

Related

Use SDK (libraries, header files, etc) during creating a C++ ROS package

I am working with Teledyne Lumenera USB Camera. I installed lucam-sdk_2.4.3.94 for Linux on my Ubuntu 18.04. It includes these files:
The api folder contains this files:
One of the folders is example which contains several examples for working with Teledyne Lumenera USB Camera. Each example in example folder, shows one of the aspects of the camera like setting focus, reading camera info, etc. Each example has a folder that contains some .cpp, .h and one make file.
I want to write a C++ ROS node that uses this SDK.
First, I create a ROS package in my catkin_ws/src then I copy one of the examples in SDK into the src package folder.
When I use catkin_make, it says that it does not recognize lucamapi.h, which is one of the header files in the SDK.
My question is two parts:
1- the code that I copied from example folders contains some .cpp and .h files. Also, that has a make file beside themselves. I do not know how to handle the make file. How can I put parameters of the following MakeFile into CMakeList.txt?
2- I do not know how to change CMakeList.txt in my ROS package in order to have access to SDK headers, lib, etc.
This is make file for one of of the examples in the SDK:
#
CC = g++
LD = $(CC)
ifndef ARCH
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/ -e s/x86_64/x86-64/)
endif
LU_LDFLAGS = -lm -lpthread -lstdc++
PROG = livePreview
VERSION = 0.1
INCLUDES = $(LUMENERA_SDK)/include
CFLAGS = -DVERSION=\"$(VERSION)\" -I$(INCLUDES) -g
CFLAGS += -DLUMENERA_LINUX_API
OBJS =
ALL_INCLUDES =
all lu: $(PROG)
clean:
rm -f $(PROG) *.o *.core core *.bak *~
livePreview: verify_environment livePreview.o Camera.o
$(LD) livePreview.o Camera.o `pkg-config --libs opencv` -llucamapi $(LU_LDFLAGS) -o $#
verify_environment:
#if test "$(LUMENERA_SDK)" = "" ; then \
echo "LUMENERA_SDK environment variable is not set!"; \
exit 1; \
fi
Camera.o: Camera.cpp $(INCLUDES)/lucamapi.h
$(CC) $(CFLAGS) -c Camera.cpp
livePreview.o: livePreview.cpp $(INCLUDES)/lucamapi.h
$(CC) $(CFLAGS) -c livePreview.cpp
I solved the problem. Working with CMakeList and ROS was confusing.
Go to this repository, and read instalation part, then look at CMakeList.txt:
https://github.com/farhad-dalirani/lumenera_camera_package

Yocto extensible SDK devtool getting error while deploying a plain makefile hello world project

I have created a custom yocto linux image for a raspberry pi and also an esdk.
I am trying to deploying a plain makefile helloworld project to a raspberry pi 3. I have tested the source code by building natively and running.
Then I set up a cross compiling environment and use devtool to add the source code. After that I try to build and deploy my recipe.
devtool build command is running succesfully without any error.
When i try devtool deploy-target ... I get the following error:
ERROR: No files to deploy - have you built the hello recipe? If so, the install step has not installed any files.
C++ source file (helloworld.cpp):
#include <stdio.h>
#include <stdlib.h>
#include <gnu/stubs.h>
int main(void) {
puts("Hello World!!!");
return EXIT_SUCCESS;
}
Makefile
PROJECT_NAME := XYZ
OUTPUT_DIR := build
CXXFLAGS = -O2 -g -Wall -fmessage-length=0
SRCS = helloworld.cpp
OBJS =$(SRCS:.cpp=.o)
LIBS =
TARGET = helloworld
PREFIX = /usr/bin
$(TARGET): $(OBJS)
$(CXX) $(CXXFLAGS) -o $(TARGET) $(OBJS) $(LIBS)
.cpp.o:
$(CXX) $(CXXFLAGS) -c $< -o $#
all: $(TARGET)
#echo Compiling project
clean:
rm -f $(OBJS) $(TARGET)
build_directory: $(OUT_DIR)
#echo Creating build directory
$(OUT_DIR):
mkdir -p $(OUTPUT_DIR)
install: $(TARGET)
install $(TARGET) $(PREFIX)
hello.bb recipe
# Recipe created by recipetool
# This is the basis of a recipe and may need further editing in order to be fully functional.
# (Feel free to remove these comments when editing.)
# Unable to find any files that looked like license statements. Check the accompanying
# documentation and source headers and set LICENSE and LIC_FILES_CHKSUM accordingly.
#
# NOTE: LICENSE is being set to "CLOSED" to allow you to at least start building - if
# this is not accurate with respect to the licensing of the software being built (it
# will not be in most cases) you must specify the correct value before using this
# recipe for anything other than initial testing/development!
LICENSE = "CLOSED"
LIC_FILES_CHKSUM = ""
# No information for SRC_URI yet (only an external source tree was specified)
SRC_URI = ""
# NOTE: this is a Makefile-only piece of software, so we cannot generate much of the
# recipe automatically - you will need to examine the Makefile yourself and ensure
# that the appropriate arguments are passed in.
do_configure () {
# Specify any needed configure commands here
:
}
do_compile () {
# You will almost certainly need to add additional arguments
oe_runmake
}
do_install () {
# This is a guess; additional arguments may be required
oe_runmake install
}
FILES_${PN} = "${bindir}/*"

Makefile target always up to date with code generation

I have a script which generates multiple C++ .h and .cpp files, based on a configuration file. This script also generates a file called 'Makefile.inc', and this file contains a variable with the required object filenames, for the generated .cpp files.
Example of a Makefile.inc file (all paths are absolute):
MESSAGE_OBJS = \
/scratch/openttd/software/AtLargePlatform/branches/lucas/libatlarge/atlarge/messages/error-message.o \
/scratch/openttd/software/AtLargePlatform/branches/lucas/libatlarge/atlarge/messages/challenge-request-message.o \
/scratch/openttd/software/AtLargePlatform/branches/lucas/libatlarge/atlarge/messages/challenge-response-message.o \
/scratch/openttd/software/AtLargePlatform/branches/lucas/libatlarge/atlarge/messages/login-message.o \
/scratch/openttd/software/AtLargePlatform/branches/lucas/libatlarge/atlarge/messages/get-game-list-message.o \
/scratch/openttd/software/AtLargePlatform/branches/lucas/libatlarge/atlarge/messages/game-list-response-message.o \
/scratch/openttd/software/AtLargePlatform/branches/lucas/libatlarge/atlarge/messages/join-game-message.o \
/scratch/openttd/software/AtLargePlatform/branches/lucas/libatlarge/atlarge/messages/connect-to-game-message.o \
/scratch/openttd/software/AtLargePlatform/branches/lucas/libatlarge/atlarge/messages/leave-game-message.o
Using the answer in this question as base, I created the following Makefile:
# Include the generated makefile for messages.
# This includes a variable with all message targets
include atlarge/messages/Makefile.inc
# Create a variable with all source targets
LIBOBJS = \
atlarge/exceptions.o \
atlarge/message-factory.o \
atlarge/envelope.o \
atlarge/client.o \
atlarge/user.o \
atlarge/atlarge-protocol.o \
atlarge/atlarge-gameserver.o \
$(MESSAGE_OBJS)
CXXFLAGS += -W -Wall -I. -g -O3 -MD \
`pkg-config jansson --cflags` \
`libgcrypt-config --cflags` \
`pkg-config glib-2.0 --cflags` \
-fPIC -DDEBUG -DENABLE_LOGGING
PREFIX = /usr/local
# TODO use pkg-config for jansson
LDLIBS += -lm -ljansson -latlarge-util `libgcrypt-config --libs` `pkg-config glib-2.0 --libs`
LDFLAGS += -shared -L/usr/local/lib
# Include automatically generated dependencies
-include $(LIBOBJS:.o=.d)
all: libatlarge.so
# If the message Makefile doesn't exist yet, generate it
atlarge/messages/Makefile.inc: atlarge/messages/messages.conf
python ../common/messagegen.py -o ./atlarge/messages/ atlarge/messages/messages.conf
libatlarge.so: $(LIBOBJS)
$(CXX) $(LDFLAGS) -o $# $^ $(LDLIBS)
clean:
#rm -f *.o
#rm -f atlarge/*.o
#rm -f atlarge/messages/*.o
#rm -f atlarge/messages/*.cpp
#rm -f atlarge/messages/*.h
#rm -f atlarge/messages/Makefile.inc
#rm -f atlarge/*.d
#rm -f atlarge/messages/*.d
#rm -f *.d
#rm -f ../common/*.d
#rm -f ../common/*.o
#rm -f *.a
#rm -f *.so
#rm -f tags
install: libatlarge.so
#install -m 0644 $^ $(PREFIX)/lib
#install -m 0755 -d $(PREFIX)/include/atlarge
#install -m 0755 -d $(PREFIX)/include/atlarge/messages
#install -m 0644 -D atlarge/*.h $(PREFIX)/include/atlarge
#install -m 0644 -D atlarge/messages/*.h $(PREFIX)/include/atlarge/messages
#ldconfig
#echo "Installed"
.PHONY: all clean install splint messages
As you can see, I first include the generated Makefile.inc. Then a variable with all library object files is defined, and this variable makes use of the variable declared in the generated Makefile.inc. After that some variables with compiler flags are declared.
To make use of Makefile remaking, I included a target rule for the generated Makefile.inc, so if the dependency of Makefile.inc (the configuration file) is newer than Makefile.inc, it gets regenerated, and Make will restart itself.
So this is the goal:
Check if Makefile.inc needs to be (re)generated.
Include it
Use the variable inside Makefile.inc in the $LIBOBJS variable in the main Makefile.
And this actually works. If I update the messages.conf file, Make detects that, and will run the python script. It will then restart itself, include the new Makefile.inc, and then proceed with compiling.
But here comes the part that doesn't work: if I don't update the messages.conf file, but only .h or .cpp files which are by default in the $LIBOBJS list, Make will not proceed to compile.
For example, if alter client.cpp and no other files, I get the following error:
make: `atlarge/exceptions.o' is up to date.
Well yeah, great you found out that exceptions.o is up to date, but I altered client.cpp, so why don't you start compiling that one? Why does make quit immediatly after seeing that the first target in LIBOBJS is up to date?
Who knows what's causing this, and what could be a solution? Is there maybe a better way to handle code generation with makefiles?
Thanks in advance.
NB: I also use dependency files generated by gcc, and that was working fine before I added the code generation, so I don't think that's a problem.
You need to move the all target to come BEFORE the include. Make always builds the first target it sees in the makefile unless you give a specific target on the command line. Since the include comes before any target, the first target defined in Makefile.inc will be the default target and when you run make that's the one that will be built. That's why it tries to build exceptions.o and then stops. If you run make all explicitly, it will work as you expect.
Where is the dependency for the object files on the source files
or the header files? There is an implicit rule which should
pick up the dependencies if the .cpp file is in the same
directory as the .o, but if they're not, you'll have to
provide your own, or use VPATH (see §4.5.1 in the manual). And
you also need to generate the dependencies for the includes, see
§4.1.4 in the manual.

How to merge two Makefiles (each builds scripts with certain environment variables set) into a single Makefile?

I have two different directories with two different C++ source codes each of them execute different program. Directories have their own Makefiles each of them builds scripts with certain environment variables set.
Now, I want to put both directories' contents into a single directory as I want to mix both C++ source codes in order to develop a new C++ source code that utilizes both programs capabilities.
So far, I placed all files in a single directory, and I can successfully build each of the original source codes when I place the corresponding Makefile. Now, I want to have a single Makefile that allows me to build each of the original source codes (without replacing the Makefile), and hopefully this would allow me to build the new mixed C++ source file...
I tried a trivial solution and I placed the contents of both Makefiles into a single Makefile and this didn't work ...
I think it is useful to post my two Makefiles
Here is the first one
# A simple $(MAKE)file to cause make to go look in the top directory. A simple
# convenience.
all: lib
$(MAKE) -C .. examples
lib:
$(MAKE) -C .. lib/libAria.so
%.so: ../lib/libAria.so %.cpp
$(MAKE) -C .. examples/$#
%: ../lib/libAria.so %.cpp
$(MAKE) -C .. examples/$#
%Static: ../lib/libAria.a %.cpp
$(MAKE) -C .. examples/$#
clean:
$(MAKE) -C .. cleanExamples
../lib/libAria.so: FORCE
$(MAKE) -C .. dirs lib/libAria.so
../lib/libAria.a: FORCE
$(MAKE) -C .. dirs lib/libAria.a
FORCE:
.PHONY: all FORCE clean lib
And the second Makefile is
LDLIBS = -lm
CXXFLAGS = -O3 -finline-functions -I. -I./qpoases/INCLUDE -I./qpoases/SRC
CFLAGS = -O3
CC = g++
OBJECTS = \
./qpoases/SRC/QProblemB.o \
./qpoases/SRC/Bounds.o \
./qpoases/SRC/Constraints.o \
./qpoases/SRC/SubjectTo.o \
./qpoases/SRC/Indexlist.o \
./qpoases/SRC/CyclingManager.o \
./qpoases/SRC/Utils.o \
./qpoases/SRC/MessageHandling.o \
./qpoases/solver.o \
integrator.o \
condensing.o \
gauss_newton_method.o
.PHONY: all
all: test libacado_exported_rti.a
test: ${OBJECTS} test.o
./qpoases/solver.o : ./qpoases/solver.hpp
integrator.o : acado.h
condensing.o : acado.h
gauss_newton_method.o : acado.h ./qpoases/solver.hpp
test.o : acado.h ./qpoases/solver.hpp
libacado_exported_rti.a: ${OBJECTS}
ar r $# $?
${OBJECTS} : ./qpoases/solver.hpp
.PHONY : clean
clean :
-rm -f *.o *.a ./qpoases/SRC/*.o ./qpoases/SRC/*.a test
I check all stackoverflow questions related to my question and the only closest situation to mine is a question titled (multiple makefiles in one directory);however, this is not exactly what I want to do...
Thanks a lot !
Why would you want to merge your source directories? I assume they are seperated for a reason. Instead, I'd leave them be and create a new make file in the directory above them that calls each of the sub makes files below it - either via includes or via shelling directly to each makefile. I would not mix the code just to make it "easier" to get inheritance or whatever working.
BTW, here's a link for you:Stack Overflow shows you how

Implicit Build Rules: GNU Make Multiple Makefiles Multiple Directories

I have the following directory structure:
.
..
./Graphic/
./Graphic/SymbolXLib
There are several other directories in this project but I won't list them for simplicities sake.I want a main makefile that drives the build of other Makefiles stored in their own directories. There are several project comming together, so I can't just move source around.
The main makefile is defined as:
[mehoggan#hogganz400 Core]$ cat ./Makefile
CORE_LIBS_DIR = libs
OBJS_DIR = obj/symb_obj
include ./Graphic/SymbolXLib/Makefile
The Graphic makefile is defined as:
#
# make BUILD_MODE={release|debug} OS_ARCH={32|64}
#
# default is 32-bit release build
#
BUILD_MODE = release
OS_ARCH = 64
OBJS_DIR = $(BUILD_MODE)$(OS_ARCH)
SRC = \
./Graphic/SymbolXLib/CartoCursor.cpp \
...
./Graphic/SymbolXLib/TextureConversion.cpp \
$(NULL)
CC = gcc -fPIC
OBJS = $(SRC:%.cpp=$(OBJS_DIR)/%.o)
COPTS = -m$(OS_ARCH) -O2
CDEFS = -DLINUXx86 \
-I../../../SharedArcGIS/Include/GraphicsPipeline/Display/SymbolX/SymbolXLib \
-I../../../SharedArcGIS/Include/System/Geometry/GeometryXLib \
-I../../../ArcSDE/pe/include \
-I../../../ArcSDE/shape/include
CFLAGS = $(COPTS) $(CDEFS) $(CINCS)
TARGET = libSymbolXLib.a
all : $(OBJS_DIR) $(OBJS_DIR)/$(TARGET)
$(OBJS_DIR) :
mkdir -p $(OBJS_DIR)
$(OBJS_DIR)/$(TARGET) : $(OBJS)
ar qc $# $^
$(OBJS_DIR)/%.o : %.cpp
$(CC) -c $(CFLAGS) -o $# $<
The response at the previous post (Previous Post) helped only if I moved alot of things around. I can't do this. So the question still remains, how do I get make to recognize the implicit build in a subdirectory from the main Makefile?
The error I am getting is
make: *** No rule to make target `release64/./Graphic/SymbolXLib/CartoCursor.o', needed by `release64/libSymbolXLib.a'. Stop.
I have to think you'd have far better success if you avoided include and instead use recursive make. In the top-level Makefile, something like:
graphic:
$(MAKE) -C Graphic
And the Makefile in Graphic/Makefile can have its sub-projects:
symbolxlib:
$(MAKE) -C SymbolXLib
and so on. You might need to add each of the targets to a default target or something similar to hang them all together on a single execution. You could give each of these targets an actual dependency (they should be .PHONY: if they don't have a dependency...) to rebuild them only when necessary or when commanded to by an upper-level target that touch(1)es "command files".
Alternatively, this paper recommends a different approach to avoid recursive make, but I've not yet read it -- and have found recursive make works well enough in projects I've been a part of that I don't mind recommending it.
Does this gnumake documentation help you?