CMake cross compilation fails during linking stage on host (target is Raspberry Pi) - c

My source tree is
cpp
├── bin
├── CMakeLists.txt
├── src
├── headers
├── Makefile
├── TestConfig.h
├── TestConfig.h.in
├── README.txt
├── third_party
├── x_build
└── xtoolchain.cmake
I am using crosstool-ng.
Edit: Additional info (that may help others): I used reference of http://xecdesign.com/qemu-emulating-raspberry-pi-the-easy-way/ to boot RPI via QEMU (important resizing the img file to 8GB).
qemu-img resize 2014-01-07-wheezy-raspbian.img +6G
sudo fdisk /dev/mmcblk0
- use "parted" or 'd' options to delete the 2nd partition and then recreate it but with a larger size. (don't worry, the data will remain). 1st partition is vfat.
- reboot to activate the partition changes.
- use "sudo resize2fs /dev/mmclk0p2" (or /dev/sda2 if symlink set in udev rules) to enlarge the root file system.
- use e2fsck -f /dev/mmcblk0p2 to perform a file system check.
Installed all lib<package>-dev and other libraries using apt-get. Then shutdown the QEMU
mkdir -p /tmp/rasp
sudo mount /home/test/raspberrypi/2014-01-07-wheezy-raspbian.img /tmp/rasp/ -o offset=$((122880*512))
cd $HOME/raspberrypi
sudo cp -ar /tmp/rasp ./rootfs
sudo chown -R $USER:$USER rootfs/home/pi
cd $HOME/raspberrypi/rootfs
# also small hack around: error "Never use <bits/predefs.h> directly; include <stdc-predef.h> instead."
sudo cp /home/test/raspberrypi/rootfs/usr/include/features.h /home/test/raspberrypi/rootfs/usr/include/features.h-
sudo cp /home/test/local/x-tools/arm-unknown-linux-gnueabi/arm-unknown-linux-gnueabi/sysroot/usr/include/features.h /home/test/raspberrypi/rootfs/usr/include
sudo umount /tmp/rasp
I have also set up the target file system /home/test/raspberrypi/rootfs (This contains all the libraries necessary for cross compilation already installed)
The xtoolchain.cmake looks as follows
# ========================= CROSS COMPILATION INITIALIZATION BEGIN =======================
# this one is important
SET(CMAKE_SYSTEM_NAME Linux)
#this one not so much
SET(CMAKE_SYSTEM_VERSION 1)
# specify the cross compiler
SET(CMAKE_C_COMPILER
$ENV{HOME}/local/x-tools/arm-unknown-linux-gnueabi/bin/arm-unknown-linux-gnueabi-gcc)
SET(CMAKE_CXX_COMPILER
$ENV{HOME}/local/x-tools/arm-unknown-linux-gnueabi/bin/arm-unknown-linux-gnueabi-g++)
# where is the target environment
#SET(CMAKE_FIND_ROOT_PATH
#/home/test/local/x-tools/arm-unknown-linux-gnueabi /home/test/raspberrypi/rootfs)
SET(CMAKE_FIND_ROOT_PATH $ENV{HOME}/raspberrypi/rootfs)
# search for programs in the build host directories
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# for libraries and headers in the target directories
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
#include_directories ("/home/test/local/raspidev/include")
# ========================= CROSS COMPILATION INITIALIZATION END =========================
The CMakeLists.txt (This is in addition to CMakeLists.txt in the parent directory as you can see from the file structure) portion inside the src directory looks like
cmake_minimum_required(VERSION 2.8)
...
...
...
#Change 1 to 0 to disable logging
add_definitions(-DENABLE_LOG=1)
set(CMAKE_PREFIX_PATH $ENV{HOME}/raspberrypi/rootfs/)
set(CMAKE_LIBRARY_PATH $ENV{HOME}/raspberrypi/rootfs/lib:$ENV{HOME}/raspberrypi/rootfs/usr/lib:$ENV{HOME}/raspberrypi/rootfs/usr/local/lib)
set(CMAKE_MODULE_PATH $ENV{HOME}/raspberrypi/rootfs/usr/share/cmake-2.8/Modules)
#rdynamic is for stack unwinding on crash
set(CMAKE_CXX_FLAGS "-W -O3 -g -Wall -std=c++0x -rdynamic -D_AIBTRACE ${CMAKE_CXX_FLAGS}")
set_target_properties(${TARGET} PROPERTIES COMPILE_FLAGS ${CMAKE_CXX_FLAGS})
include_directories ("${PROJECT_SOURCE_DIR}/headers")
#add_subdirectory (headers)
...
...
...
# ======================== SQLITE3 =================================
pkg_check_modules(SQLITE3 REQUIRED sqlite3)
include_directories(${SQLITE3_INCLUDE_DIRS})
...
... (...And other libraries)
I do an out of source build inside the x_build directory. as follows
cmake -DCMAKE_TOOLCHAIN_FILE=/home/test/xcompile/cpp/xtoolchain.cmake ../
Strangely, it seems to be linking against the host libraries as opposed to the target libraries. make VERBOSE=1 shows this
It throws linker error for all the libraries (These libraries are definitely present on the target system rootfs)
/home/test/local/x-tools/arm-unknown-linux-gnueabi/lib/gcc/arm-unknown-linux-gnueabi/4.7.3/../../../../arm-unknown-linux-gnueabi/bin/ld: cannot find -lgmodule-2.0
/home/test/local/x-tools/arm-unknown-linux-gnueabi/lib/gcc/arm-unknown-linux-gnueabi/4.7.3/../../../../arm-unknown-linux-gnueabi/bin/ld: cannot find -lgthread-2.0
/home/test/local/x-tools/arm-unknown-linux-gnueabi/lib/gcc/arm-unknown-linux-gnueabi/4.7.3/../../../../arm-unknown-linux-gnueabi/bin/ld: cannot find -lxml2
/home/test/local/x-tools/arm-unknown-linux-gnueabi/lib/gcc/arm-unknown-linux-gnueabi/4.7.3/../../../../arm-unknown-linux-gnueabi/bin/ld: cannot find -lglib-2.0
/home/test/local/x-tools/arm-unknown-linux-gnueabi/lib/gcc/arm-unknown-linux-gnueabi/4.7.3/../../../../arm-unknown-linux-gnueabi/bin/ld: cannot find -lsqlite3
/home/test/local/x-tools/arm-unknown-linux-gnueabi/lib/gcc/arm-unknown-linux-gnueabi/4.7.3/../../../../arm-unknown-linux-gnueabi/bin/ld: cannot find -ldbus-1
collect2: error: ld returned 1 exit status
I am a bit lost.
Edit:
As requested here are few more things from CMakeLists.txt
set (SOURCES
file1.cc
file2.cc
main.cc
)
# Similarly, why not concise files grouping that will be reused ;)?
set (COMMONS_LIBS
${OpenCV_LIBS}
pthread
${GLIBMM_LIBRARIES}
${GTKMM_LIBRARIES}
#${GSTMM_LIBRARIES}
${GSTREAMER_LIBRARIES}
${SQLITE3_LIBRARIES}
#${DBUS_GLIB_LIBRARY}
${DBUS_LIBRARIES}
${DBUS_GLIB_LIBRARIES}
${OPENSSL_LIBRARIES}
)
add_executable (
${EXE_DAEMON}
${SOURCES}
)
target_link_libraries(
${EXE_DAEMON}
$COMMONS_LIBS}
)
install (TARGETS
${EXE_DAEMON}
DESTINATION bin)

I added the following to CMakeLists.txt and then few more changes below and got it working!
include($ENV{HOME}/raspberrypi/rootfs/usr/share/cmake-2.8/Modules/FindPkgConfig.cmake)
set(CMAKE_PREFIX_PATH $ENV{HOME}/raspberrypi/rootfs/)
set(SYSROOT $ENV{HOME}/raspberrypi/rootfs/)
set (PKG_CONFIG_SYSROOT_DIR ${SYSROOT})
set(PKG_CONFIG_PATH ${SYSROOT}/usr/lib/pkgconfig:${SYSROOT}/usr/local/lib/pkgconfig:${SYSROOT}/usr/lib/arm-linux-gnueabihf/pkgconfig:${SYSROOT}/usr/share/pkgconfig)
#Change 1 to 0 to disable logging
add_definitions(-DENABLE_LOG=1)
find_program(PKG_CONFIG_EXECUTABLE NAMES pkg-config PATHS /usr/bin DOC "pkg-config executable" NO_CMAKE_FIND_ROOT_PATH)
set (CMAKE_CXX_FLAGS "-W -O3 -g -Wall -std=c++0x -rdynamic -D_TRACE ${CMAKE_CXX_FLAGS}" CACHE STRING "" FORCE)
#rdynamic is for stack unwinding on crash
set(CMAKE_PREFIX_PATH $ENV{HOME}/raspberrypi/rootfs/)
set(CMAKE_LIBRARY_PATH $ENV{HOME}/raspberrypi/rootfs/lib:$ENV{HOME}/raspberrypi/rootfs/usr/lib:$ENV{HOME}/raspberrypi/rootfs/usr/local/lib)
set(CMAKE_MODULE_PATH $ENV{HOME}/raspberrypi/rootfs/usr/share/cmake-2.8/Modules)
include_directories(SYSTEM
$ENV{HOME}/raspberrypi/rootfs/usr/include/arm-linux-gnueabihf
$ENV{HOME}/raspberrypi/rootfs/usr/include
$ENV{HOME}/raspberrypi/rootfs/usr/local/include
)
add_definitions(
-march=armv6zk
-mfpu=vfp
-mfloat-abi=hard
)
link_directories(
$ENV{HOME}/raspberrypi/rootfs/lib/arm-linux-gnueabihf
$ENV{HOME}/raspberrypi/rootfs/lib
$ENV{HOME}/raspberrypi/rootfs/usr/lib/arm-linux-gnueabihf
$ENV{HOME}/raspberrypi/rootfs/usr/lib
$ENV{HOME}/raspberrypi/rootfs/usr/local/lib
)
set_target_properties(${TARGET} PROPERTIES COMPILE_FLAGS ${CMAKE_CXX_FLAGS})
Then did the following
sudo vim /home/test/raspberrypi/rootfs/usr/lib/arm-linux-gnueabihf/libpthread.so
edited
OUTPUT_FORMAT(elf32-littlearm)
GROUP ( /lib/arm-linux-gnueabihf/libpthread.so.0 /usr/lib/arm-linux-gnueabihf/libpthread_nonshared.a )
to
OUTPUT_FORMAT(elf32-littlearm)
GROUP ( libpthread.so.0 libpthread_nonshared.a )
similarly,
sudo vim /home/test/raspberrypi/rootfs/usr/lib/arm-linux-gnueabihf/libc.so
edited
OUTPUT_FORMAT(elf32-littlearm)
GROUP ( /lib/arm-linux-gnueabihf/libc.so.6 /usr/lib/arm-linux-gnueabihf/libc_nonshared.a AS_NEEDED ( /lib/arm-linux-gnueabihf/ld-linux-armhf.so.3 ) )
to
OUTPUT_FORMAT(elf32-littlearm)
GROUP ( libc.so.6 libc_nonshared.a AS_NEEDED ( ld-linux-armhf.so.3 ) )
Lastly, I added the -lpcre library to my COMMON_LIBS
Compile was successful. I then booted the raspberrypi via QEMU and used scp scp daemon pi#<ip address>:~ to transfer the resulting binary to PI emulator and ran it. Tadaa!!! it works fine!

Related

How to link to FreeGlut instead of Glut on macOS using cmake and find_package?

I have the latest version of macOS Big Sur, running intel based cpu, clang12, cmake 3.19 and brew. I have installed freeglut via brew.
However whenever I called find_package(GLUT) it always finds my system GLUT (/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk/System/Library/Frameworks/GLUT.framework) over the FreeGLUT brew has installed. I have tried changing the find_package to FreeGlut with no success.
I am sure its something really simple I am missing but not knowing a lot about the macOS linking process, this has me rather confused.
Here is my cmake command line being used...
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/bin/clang -DCMAKE_CXX_COMPILER=/usr/bin/clang++ -G Ninja
Here is my cmake file.
# Set cmake minimum version.
cmake_minimum_required(VERSION 3.15)
# Set the project details.
set(PROJECT_NAME Project)
project(${PROJECT_NAME} LANGUAGES C)
# Treat warnings as errors.
option(WarningsAsErrors "WarningsAsErrors" OFF)
# If enabled, the post build symlink will copy instead.
option(CopyResources "CopyResources" OFF)
option(GenerateDoxygen "GenerateDoxygen" OFF)
# Disable in-source builds.
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
set(CMAKE_DISABLE_SOURCE_CHANGES ON)
# Set build type to debug by default.
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug)
endif()
# Add Linux flag.
if(UNIX AND NOT APPLE)
set(LINUX TRUE)
endif()
# Define the executable.
add_executable(${PROJECT_NAME})
set_property(TARGET ${PROJECT_NAME} PROPERTY C_STANDARD 11)
# Find dependencies.
# find_package(OpenGL REQUIRED COMPONENTS OpenGL)
find_package(OpenGL REQUIRED)
find_package(GLUT REQUIRED)
# Build 3rd Party Libraries
add_subdirectory(lib)
# Define source files.
add_subdirectory(src)
if (MSVC)
string(REGEX REPLACE "/W[0-4]" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
endif()
# Treat warnings as errors if enabled.
if (WarningsAsErrors)
target_compile_options(${PROJECT_NAME} PRIVATE
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:GNU>>:-Werror>
$<$<CXX_COMPILER_ID:MSVC>:/WX>
)
endif(WarningsAsErrors)
# Set compile flags.
target_compile_options(${PROJECT_NAME} PRIVATE
# Clang
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>:
-Weverything -fcolor-diagnostics
# Disable specific warnings.
-Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-padded
-Wno-deprecated-declarations -Wno-exit-time-destructors
-Wno-switch-enum -Wno-weak-vtables -Wno-global-constructors>
# GCC
$<$<CXX_COMPILER_ID:GNU>:-Wall -Wextra -Wpedantic -fdiagnostics-color=always>
# Visual Studio
$<$<CXX_COMPILER_ID:MSVC>:/W4>
# Enable the clang sanitizer.
$<$<AND:$<CONFIG:Debug>,$<CXX_COMPILER_ID:Clang>,$<PLATFORM_ID:${SANITIZER_OS}>>:${SANITIZER_FLAGS}>
)
# Link against the clang sanitizer.
target_link_options(${PROJECT_NAME} PRIVATE
$<$<AND:$<CONFIG:Debug>,$<CXX_COMPILER_ID:Clang>,$<PLATFORM_ID:${SANITIZER_OS}>>:${SANITIZER_FLAGS}>
)
if (LINUX)
target_link_libraries(${PROJECT_NAME} PRIVATE -lm)
endif()
# Include and link against dependencies.
target_link_libraries(${PROJECT_NAME} PRIVATE OpenGL::GL OpenGL::GLU GLUT::GLUT stb OpenAL SndFile::sndfile BigBalls::Physics lua ${CMAKE_DL_LIBS})
if (GenerateDoxygen)
find_package(Doxygen)
if (DOXYGEN_FOUND)
set(DOXYGEN_IN ${CMAKE_SOURCE_DIR}/.doxyconf)
configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} #ONLY)
add_custom_target(doc ALL
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_IN}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Generating API documentation with Doxygen"
VERBATIM)
endif (DOXYGEN_FOUND)
endif (GenerateDoxygen)
# Symlink or copy the resources to the binary location.
if (NOT DisablePostBuild)
if (NOT CopyResources)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E create_symlink
${CMAKE_SOURCE_DIR}/res $<TARGET_FILE_DIR:${PROJECT_NAME}>/res)
else()
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_SOURCE_DIR}/res $<TARGET_FILE_DIR:${PROJECT_NAME}>/res)
endif()
endif()
So FindGLUT is a builtin module
ref: https://cmake.org/cmake/help/latest/module/FindGLUT.html
looking at the source code:
see https://github.com/Kitware/CMake/blob/master/Modules/FindGLUT.cmake
so it seems to use find_path()
find_path(GLUT_INCLUDE_DIR glut.h ${OPENGL_LIBRARY_DIR})
You can try to set GLUT_ROOT or OPENGL_LIBRARY_DIR as default path to help CMake to find the correct one...
ref https://cmake.org/cmake/help/latest/command/find_path.html

Linking external headers file in ROS package

I am trying to use the Kilobot simulator Kilombo with a ROS package. I am installing Kilombo as normal and then trying to include the Kilombo header file inside the ROS package. The CMakeLists.txt of Kilombo looks like this
add_library(sim display.c skilobot.c kbapi.c params.c stateio.c runsim.c neighbors.c distribution.c gfx/SDL_framerate.c gfx/SDL_gfxPrimitives.c gfx/SDL_gfxBlitFunc.c gfx/SDL_rotozoom.c)
add_library(headless skilobot.c kbapi.c params.c stateio.c runsim.c neighbors.c distribution.c)
set_target_properties(headless PROPERTIES COMPILE_DEFINITIONS "SKILO_HEADLESS")
if(CMAKE_COMPILER_IS_GNUCXX)
add_definitions(-std=c99)
add_definitions("-Wall -O2 -g")
# add_definitions("-Wall -O3 -march=native -g")
endif()
INSTALL(TARGETS sim headless
ARCHIVE DESTINATION lib
)
INSTALL(FILES kilombo.h DESTINATION include)
INSTALL(FILES kilolib.h message.h message_crc.h params.h skilobot.h
DESTINATION include/kilombo)
add_subdirectory(tests)
The CMakeLists.txt of the ROS package I am creating looks like this:
cmake_minimum_required(VERSION 2.8.3)
project(Kilombo_test)
find_package(catkin REQUIRED roscpp std_msgs)
if(CMAKE_COMPILER_IS_GNUCXX)
add_definitions(-std=c99)
add_definitions("-Wall -O2 -g")
endif()
include_directories(/usr/local/include /usr/local/lib)
link_directories(/usr/local/include)
add_executable(generated_test orbit.c)
target_link_libraries(generated_test ${catkin_LIBRARIES})
I include the Kilombo header files just as normal: "#include <kilombo.h>"
However, when I run catkin_make, I get many "undefined reference" errors. Some of those messages are:
orbit.c:53 undefined reference to 'kilo_turn_left'
orbit.c:53 undefined reference to 'set_motors'
These messages are shown after the commands:
####
#### Running command: "make -j2 -l2" in "/home/viki/catkin_ws/build"
####
Linking C executable generated_test
Both, kilo_turn_left and the function set_motors is defined in "kilolib.h" which itself is included in "kilombo.h".
Everything works fine if try running the simulation normally and not as a ROS package. The Makefile when I try to run it normally looks like the following. I have removed the parts which compiled for the real bot and not for the simulation.
SOURCES=orbit.c
EXECUTABLE=orbit
# path of kilombo.h distributed with the simulator but also needed
# when compiling the user program for the real kilobot (avr-gcc has different default paths)
SIMHEADERS=/usr/local/include
#path to kilolib.a in the official kilolib, needed for real bots only
KILOLIB =$(KILOHEADERS)/build/kilolib.a
SIM_CFLAGS = -c -g -O2 -Wall -std=c99
SIM_LFLAGS = -lsim -lSDL -lm -ljansson
sim: $(EXECUTABLE)
hex: $(EXECUTABLE).hex
all: sim hex
clean :
rm *.o $(EXECUTABLE) *.elf *.hex
However, when running a simulation as a ROS package, we need to define a CMakeLists.txt which is what I am having trouble with. What exactly am I doing wrong?
The problem was that I wasn't linking to the correct libraries in the CMakeLists.txt of the simulation. Changing the line target_link_libraries(generated_test ${catkin_LIBRARIES}) to target_link_libraries(generated_test ${catkin_LIBRARIES} sim headless SDL m Jansson) fixed it.

Error while executing cross-compiled program for openwrt

I'm trying to export a software to openwrt and i'm able to generate the ipk but the compiled file always gives me this error
-ash: scanReportProbe: not found
I've tried everything but i'm not able to make it work.
To be complete this is what i have done to prepare the environment:
git clone git://github.com/openwrt/openwrt.git
cd openwrt
./scripts/feeds update -a
./scripts/feeds install -a
make defconfig
make prereq
make menuconfig
[here i selected the package with the M and saved the configuration]
make tools/install
make toolchain/install
make package/scanReport_probe/compile
I have no idea of to fix this error so i need some hint of solution.
I don't think that the error is in the code but in casse is needed this is my program:
file structure
scanReport_probe
├── LICENSE
├── Makefile
├── README.md
└── src
├── data
│ └── THIS IS FOR DATA FILES.txt
├── runScript
│ └── scanReportProbe
├── scanReport_probe
│ ├── a.c
│ └── makefile
└── scanReport_probe.conf
makefile for openwrt
include $(TOPDIR)/rules.mk
# name of package
# version number of the sources you're using
# how many times you've released a package based on the above version number
PKG_NAME:=scanReport_probe
PKG_VERSION:=1.0
PKG_RELEASE:=1
PKG_LICENSE:=MIT
# sources will be unpacked into this directory (you shouldn't need to change this)
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
#needed
include $(INCLUDE_DIR)/package.mk
# Metadata; information about what the package is for the ipkg listings
# to keep things simple, a number of fields have been left at their defaults
# and are not shown here.
define Package/scanReport_probe
SECTION:=utils
CATEGORY:=Utilities
TITLE:=scanReport_probe
URL:=https://github.com/luigiDB/scan-report_probe
TITLE:=Scan in monitor mode probe over wifi channel with periodic report to a server through http post.
MAINTAINER:=Please refer to github repository page
endef
define Package/scanReport_probe/description
This is the best tool ever.
Scan probe over wifi and at regualar interval send results via http post.
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
CONFIGURE_VARS+= \
CC="$(TOOLCHAIN_DIR)/bin/$(TARGET_CC)"
define Build/Compile
$(MAKE) -C $(PKG_BUILD_DIR)/scanReport_probe $(TARGET_CONFIGURE_OPTS)
endef
# We'll use the OpenWrt defaults to configure and compile the package. Otherwise we'd need to define
# Build/Configure - commands to invoke a configure (or similar) script
# Build/Compile - commands used to run make or otherwise build the source
define Package/scanReport_probe/install
# Now that we have the source compiled (magic huh?) we need to copy files out of the source
# directory and into our ipkg file. These are shell commands, so make sure you start the lines
# with a TAB. $(1) here represents the root filesystem on the router.
# INSTALL_DIR, INSTALL_BIN, INSTALL_DATA are used for creating a directory, copying an executable,
# or a data file. +x is set on the target file for INSTALL_BIN, independent of it's mode on the host.
# make a directory for the config
$(INSTALL_DIR) $(1)/etc/scanReport_probe/
# copy the config
$(INSTALL_CONF) $(PKG_BUILD_DIR)/scanReport_probe.conf $(1)/etc/scanReport_probe
# make a directory for some random data files required by scanReport_probe
$(INSTALL_DIR) $(1)/usr/share/scanReport_probe
# copy the data files
$(INSTALL_DATA) $(PKG_BUILD_DIR)/data/* $(1)/usr/share/scanReport_probe
#make directory bin
$(INSTALL_DIR) $(1)/bin
# copy the binary
$(INSTALL_BIN) $(PKG_BUILD_DIR)/scanReport_probe/scanReportProbe $(1)/bin
#make the directory init.d in case isn't present
$(INSTALL_DIR) $(1)/etc/init.d
#copy script to init.d
$(INSTALL_BIN) $(PKG_BUILD_DIR)/runScript/scanReportProbe $(1)/etc/init.d
endef
#runned post installation call the enable on the service
define Package/scanReport_probe/postinst
#!/bin/sh
# check if we are on real system
if [ -z "$${IPKG_INSTROOT}" ]; then
echo "Enabling rc.d symlink for scanReportProbe"
/etc/init.d/scanReportProbe enable
fi
exit 0
endef
#runned pre uninstallation call the disable on the service
define Package/scanReport_probe/prerm
#!/bin/sh
# check if we are on real system
if [ -z "$${IPKG_INSTROOT}" ]; then
echo "Removing rc.d symlink for scanReportProbe"
/etc/init.d/scanReportProbe disable
fi
exit 0
endef
$(eval $(call BuildPackage,scanReport_probe))
a.c
#include <stdio.h>
int main(void)
{
printf("Hello World\n");
return 0;
}
makefile for c program
PROFILE = -O2 -s
CFLAGS = $(PROFILE)
LDFLAGS =
all: main
# build it
main: a.o
$(CC) $(LDFLAGS) a.o -o scanReportProbe
a.o: a.c
$(CC) $(CFLAGS) -c a.c
# clean it
clean:
rm *.o a
For -ash, IIRC, ash is a [boot] shell. It is saying that it can't find a particular command.
So, it may be one of:
(1) In your rc script section, you're doing /etc/init.d/scanReportProbe enable but the package you're building uses scanReport_probe. So, you may need to add or remove an _ here or there and/or some other renames so things match up.
(2) If the file structure you gave is the final one, I'm not sure the script is in the right directory.
(3) Are the permissions for the script correct (i.e. has execute)?

subdir-objects option for automake doesn't work

After reading the autotools mythbuster, I have tried to write a little example of the non recursive makefile with the use of subdir-objects in order to have my binary in the directory of my source files.
Here is the the organization of my little test:
/
autogen.sh
configure.ac
Makefile.am
src/
main.c
The autogen.sh :
#!/bin/sh
echo "Running aclocal..." ; aclocal $ACLOCAL_FLAGS || exit 1
echo "Running autoheader..." ; autoheader || exit 1
echo "Running autoconf..." ; autoconf || exit 1
echo "Running automake..." ; automake --add-missing --copy --gnu || exit 1
./configure "$#"
The configure.ac :
AC_PREREQ([2.69])
AC_INIT([test], [0.0.1], [devel#hell.org])
AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_HEADERS([config.h])
# Checks for programs.
AC_PROG_CC
AM_INIT_AUTOMAKE([1.14 foreign subdir-objects])
AM_MAINTAINER_MODE([enable])
AC_OUTPUT(Makefile)
The Makefile.am :
MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.h.in configure depcomp install-sh missing compile
bin_PROGRAMS=toto
toto_SOURCES=src/main.c
I compile everything with :
./autogen.sh
make
I thought that the binary toto would have been created in the src directory with the option subdir-objects but it seems that this option have no effect and the toto binary is always generated in the root directory.
I have also tried to pass this option in the Makefile.am with AUTOMAKE_OPTIONS = subdir-objects but wihtout success.
That's not what the subdir-objects option does. It puts intermediate build results, especially *.o object files, in the same directory as the sources from which they are built. In particular, you should find main.o there instead of in the top directory.
The final build result, on the other hand, must be what and where you specify in your Automake file. If you want toto to go in the src/ directory too, then use this Makefile.am:
MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.h.in configure depcomp install-sh missing compile
bin_PROGRAMS=src/toto
src_toto_SOURCES=src/main.c

binutils for compiling/cross compiling gcc for sony reader prs900

I have a rooted Sony reader PRS900, running an OEM linux kernel 2.6.23, and I can run arbitrary bash/sh scripts from the SD memory card drive on it.
I want to compile and execute C programs ... but am having dynamic linker problems.
I first tried loading gcc for arm (slackware 14's) on the SD card, but even when using LD_LIBRARY_PATH, the sony will fail to "find" most newer elf .so libraries, although newer programs which use old libraries do in fact run properly. ( I can run slackware-14's "readelf" just fine. but not ar, or gcc...) If I try to upgrade /lib/ld-linux.so.3, I get a "kernel too old" error message.
I then tried an old slackware 10 version of gcc, and although that solves the elf library "finding" problem -- I then get an "illegal instruction" error when running programs.
So -- I need to make a gcc cross compiler on my x86 for the proper ARM processor and then use it to recompile gcc for the sony.
But I don't know what legacy version of binutils I must use since it assembles and links to ELF format that either works or breaks on the sony.
The Sony is running an arm6 compatible MX31 EBX5016 processor.
and some relevant OEM file names on the sony are:
/lib/ld-2.5.so
/lib/ld-linux.so.3 -> ld-2.5.s
/lib/libc-2.5.so
/lib/libgcc_s.so.1
I know, from the kernel, that gcc-4.2.0 was used.
I would prefer to use the newest version of gcc which will work with whatever legacy binutils package I need to install.
How do I figure out which version of binutils that I need, and what options I have for gcc?
Thanks!
You can find the toolchain Sony used over at their Source Code Distribution Service site:
http://www.sony.net/Products/Linux/Audio/PRS-900.html
It seems sourceryg++-4.2-28armeabi.src.rpm is the compiler.
I would not recommend running the compiler on the device itself; it will be very slow.
Regarding the "Illegal instruction" issue, it's possible that your compiler is generating too new instructions, and passing -march=armv6 might just solve it.
Sony is using a kernel put out by motavista linux; According to montavista, the compiler for that kernel was made with binutils 2.17. I wasn't able to find any way to figure out which binutils originally developed with which version of GCC from the gnu project itself. Even the repository upload dates vary inconsistently... but I did find which binutils montavista was developed with.
The minimum version of a working cross compiler from stock GCC source code that I was able to make, came from gcc-4.2.0 with binutils 2.19.1 and glibc-2.5 using glibc-ports-2.5 for the arm processor/linux extensions.
The rest of this answer details building that cross compiler from scratch, as a reference for other people wanting to build a linux cross compiler for arm with the gnu c library included; eg: gcc with eabi and glibc for linux: arm-linux-gnueabi- tool.
It's a totally non-trivial problem, and I hope my notes are useful to others.
The sony reader PRS900 uses an EABI compiler to make the kernel, and it is also configured as little endian.
Binutils was switching from arm eabi-V4 to eabi-V5 at the time, and Sony's PRS-900 /lib/ld-* appears to expect the eabi-5 flag to be set or else it gets confused. when linking with binutils, people can accidentally mix eabi 4 and 5 object files which causes most of the problems, because it will default back to eabi-version 4 for the link: so, the way to make sure that eabi 4 is never produced accidentally, is to edit the default header files for the gas (Gnu ASsmebler) so it always defaults to eabi-5 even when building the cross compiler libraries unless explicitly told to do otherwise.
eg: these two files in binutil:
gas/config/te-armeabi.h <--change EABI_VER4 to --> #define EABI_DEFAULT EF_ARM_EABI_VER5
gas/config/te-armlinuxeabi.h <--do same--> #define EABI_DEFAULT EF_ARM_EABI_VER5
It would in fact be easier to use the code-sourcery tools than to build a gcc toolchain,
from scratch (I'm going to test them to see if they work on kernel modules, too) -- but as I intend to upgrade to newer tools -- I needed to know how to do this from scratch.
Below: I've included a script which is more important for the notes it contains than for it's usability; eg: It is NOT intended to be run and is not automatic -- but rather, it's to be cut and pasted into a shell and used as a cheat sheet outlining the flags which work and the files which must be manipulated to circumvent bugs. It has comments which are meant to be read, and although imperfect -- a human reading error messages should be able to figure out the rest from the shell's error messages.
I could not get libmudflap, libgomp, or libssp to work in gcc -- no matter how I tried, so they are disabled in the GCC build because all three cause insoluble compiling problems; but other than that, this script shows what is needed to build a "C" cross compiler arm-linux-gnueabi- toolchain which will compile and link Sony PRS-900 binary executables that run without segfaults, or errors.
One note:
It does NOT build kernel modules with the correct CRC codes, and it seems that the kernel that sony releases on their website (see previous post) is slightly different than the one on my sony; although the dates are identical and I used the /proc/config.gz from my actual sony. I intend to open a separate thread to solve that problem... but at least one can build user space executables with this cross compiler with no problems.
#!/bin/false
# Do not run this script directly, until you have read and edited source
# files appropriately. It's not automated. vim is a text editor...
# This script creates a toolchain in a local directory (not root).
# I made it to build a gcc toolchain on a USB memory stick,
# mounted under /media/memory1 on slackware14.
#
# Needed source files:
#
# binutils-2.19.1.tar.bz2
# gcc-core-4.2.0.tar.bz2
# linux-2.6.23_091126.tgz
# glibc-2.5.tar.bz2
# glibc-ports-2.5.tar.bz2
#
# and from the sony PRS-900, itself, you need file: /proc/config.gz
# To guarantee the kernel is compiled the same.
# First make a local script to set paths for the toolchain once it it built
# --------------
echo -e "\
#!--/bin/bash-- # but must run as . setArmEnvironment.rc \n\
# There are two kinds of binaries for cross compilation, the tool binaries\n\
# and libraries, and the target headers, libraries, etc.\n\
export CROSSROOT="\$PWD/.local"\n\
export TARGETROOT="\$PWD/.target"\n\
export PATH="\$PATH:\$CROSSROOT/bin"\n\
export LD_CONFIG_PATH="\$CROSSROOT/lib:\$LD_CONFIG_PATH"\n\
" > setArmEnvironment.rc
# ----------
# Next:
# Create the local binary and header directories for the cross compiler toolchain
# .local is the buld machines' local tools for arm development
# This is for the binaries for the machine doing the cross compiling.
mkdir .local
cd .local
ln -s . usr
ln -s . local
mkdir include
mkdir lib
mkdir bin
ln -s include sys-linux
cd ..
# Target is for the host tools, headers, etc. it is a pure ARM directory.
# Everthing here is potentially installable on the sony itself.
# And is what would appear on the SONY PRS-900 if it had a toolchain.
mkdir .target
cd .target
ln -s . usr
ln -s . local
mkdir include
mkdir lib
mkdir bin
ln -s include sys-linux
cd ..
# Now, we need to set the paths so that as we make build tools, we can
# use them from the shell we are in.
. setArmEnvironment.rc
# FIRST! ----------------------------------------------------------------------
# Problem: GCC supposedly needs some g-libc header files for proper target code
# generation...
# but they don't really exist until compiled -- so chicken-egg-rooster prob !
# Which to make first...
#
# Solve it by installing headers from uncompiled packages, using a broken gcc/binutils
# then, re-build and re-install proper header files -- re-build proper gcc... etc.
# build a broken binutils package.
tar -xf /tmp/binutils-2.19.1.tar.bz2
mkdir build.binutils.eabi
cd build.binutils.eabi
../binutils-2.19.1/configure --target=arm-eabi --prefix=$CROSSROOT
# Make with flags to prevent warning creep on newer GCC's compiling older code.
make CFLAGS="-Os -w"
make install
cd ..
# build a broken gcc core.
tar -xf /tmp/gcc-core-4.2.0.tar.bz2
mkdir build.gcc.eabi
cd build.gcc.eabi
../gcc-4.2.0/configure --target=arm-eabi --prefix=$CROSSROOT --enable-multilib --disable-libssp
make CFLAGS="-Os -w"
make install
cd ..
# Install kernel headers using first pass (broken) cross-compiler -------------
tar -xf /tmp/linux-2.6.23_091126.tgz
gzip -d config.gz
cp config linux-2.6.23_091126/.config
cd linux-2.6.23_091126
# The makefile is a little broken for use on slackware 14...
# edit so that:
# CROSS_COMPILE ?= arm-eabi-
# and make the two implicit rules explicit:
# eg: lines 425 and 1476 contain rules that need to be broken into two rules each:
# Here's a patch file to do it automatically -- paste as one quoted unit to shell:
# ******************** START ECHO DIFF COPY/PASTE
echo '192c192
< CROSS_COMPILE ?= /opt/timesys/toolchains/armv6j-linux/bin/armv6j-linux-
---
> CROSS_COMPILE ?= arm-eabi-
422c422
< config %config: scripts_basic outputmakefile FORCE
---
> %config: scripts_basic outputmakefile FORCE
424a425,428
> config: scripts_basic outputmakefile FORCE
> $(Q)mkdir -p include/linux include/config
> $(Q)$(MAKE) $(build)=scripts/kconfig $#
>
1472c1476,1479
< / %/: prepare scripts FORCE
---
> %/: prepare scripts FORCE
> $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
> $(build)=$(build-dir)
> /: prepare scripts FORCE
1475c1482
< %.ko: prepare scripts FORCE
---
> %%.ko: prepare scripts FORCE' > Makefile.diff
# ******************** END ECHO DIFF COPY/PASTE
# now apply the patch to the Makefile
patch Makefile Makefile.diff
# You might also need to edit
# vim linux scripts/unidef.c and search all instances of getline, replacing it with _getline to avoid stdio.h overloading conflict.
# This is not always necessary... but if you have the problem... that's the solution.
make ARCH=arm INSTALL_HDR_PATH=$TARGETROOT headers_install
cd ..
# DONE installing kernel header files somewhat sanitized...
------------------------ GLibc, headers install
## Create aliases for binutils so I don't need to fight with glibc...
cd .local/bin
for i in `ls arm-eabi-*`; do ln -s $i arm-linux${i##arm-eabi} ; done
cd ../..
# Now we need to build glibc-2.5 with the arm port (glibc-ports-2.5.tar.gz)
tar -xzf glibc-2.5.tar.gz
cd glibc-2.5
tar -xzf ../glibc-ports-2.5.tar.gz
mv glibc-ports-2.5 ports
# Steal configuration for arm from other processors... probably not needed.
cp sysdeps/wordsize-32/bits/wordsize.h bits # 32bits
cp sysdeps/i386/bits/endian.h bits # little endian
cd ..
# For the first pass, just make enough of libc to install the header files.
mkdir build.glibc.eabi
#bash # Enter a new shell, because path needs to be forced.
# CAUTION: You must not do this as superuser, or with write priveleges to
# the system directores, as there are bugs in the GLIBC install that
# will try to put them there even though they don't belong there in a cross
# compiler..!
(
cd build.glibc.eabi
export LD_LIBRARY_PATH=""
export PATH=$CROSSROOT/bin:$PATH
echo "libc_cv_forced_unwind=yes" > config.cache
echo "libc_cv_c_cleanup=yes" >> config.cache
echo "libc_cv_arm_tls=yes" >> config.cache # For posix threads, but maybe not.
../glibc-2.5/configure --with-binutils=$CROSSROOT/arm-eabi/bin --build=i686-linux --host=arm-linux --prefix=/usr --enable-kernel=2.6.23 --with-headers=$TARGETROOT/include --enable-add-ons --disable-profile --config-cache --disable-sanity-checks --with-tls --with-__thread
# Caution, this install will attempt to install to both --prefix=/usr AND install_root.
# Because any directories where actual compilation is unfinished will
# not make install_root= correctly, but default back to prefix.
# Therefore,
# Do not allow writes to local system directories, by not installing as root!
# ... AND ...
# You must run make install_headers twice so everything does end up in $TARGETROOT
make -k install-headers install_root=$TARGETROOT
make -k install-headers install_root=$TARGETROOT
# Manually install two files, ... or GCC won't build. Three if you want it all.
# Glibc has a *REAAAALY* crappy installer script ...
cp bits/stdio_lim.h $TARGETROOT/include/bits
touch $TARGETROOT/include/gnu/stubs.h
cp nptl/sysdeps/pthread/pthread.h $TARGETROOT/include
# Long-double is messed up ... I ran into this. :)
( cd $TARGETROOT/include/bits
sed '/ifndef.*NO_LONG_DOUBLE/,/#endif/d' < mathdef.h > mathdef.h.new
mv mathdef.h.new mathdef.h
)
# LIB-C woes.
# We don't have the core files made yet, but generally, linking for arm needs:
# ... elf-init.o crt1.o crti.o crtbegin.o [-L] [user.o's] [gcc lb] [C lb] crtend.o crtn.o
# Unfortunately, GCC uses these during configuration tests and to make libgcc.o
# so we need them NOW, even if they are a little wrong, to make gcc.
# What they are:
# crt1.o -- from glibc's Start.S --calls libc's __libc_csu_init, __libc_csu_fini
# crti.o -- gcc's default version is no good; but libc's is. defines prolog _init
# crtn.o -- ... ; defines function epilog _fini
# crtbegin.o and crtend.o are supplied by gcc, for constructors/destructors.
# elf-init.o -- I don't remember what it is, but it has fn's that gcc needs.
#
# so, we need to build the crt files -- and only them... as the rest can't be
# done yet. So we 'make' the crt's subdirectory.
make CFLAGS="-Os -w" ARCH=arm cross-compiling=yes csub/subdir_lib
# Manually install them in a place where the linker will find them...
cp csu/crt*.o $TARGETROOT/lib
# elf-init.o is only needed during the build of GCC. It should be removed
# after the new gcc is made, or if it causes errors when gcc is made for
# redundant symbols.
cp csu/elf-init.o $TARGETROOT/lib
) # finished with bash subtask. restore environment to normal.
# The .local tools we built previously are now basically useless
# I'll just move them, although you might want to remove them...
mv .local .local.eabi
# ****************************************************************************
# ----------------------------------------------------------------------------
# Build actual tools
# We must build gcc.linux.gnueabi in order for glibc programs to compile right...
# ----------------------------------------------------------------------------
# Create a clean .local directory
mkdir .local
cd .local
ln -s . usr
ln -s . local
mkdir include
mkdir lib
mkdir bin
ln -s include sys-linux
cd ..
# Rebuild the toolchain with the basic headers we just installed.
# First do bintools
# Be sure to Change the DEFAULT_EABI to version 5 before compiling gas.
mkdir build.binutils2.19.1.linux.gnueabi
cd build.binutils2.19.1.linux.gnueabi
../binutils-2.19.1/configure --target=arm-linux-gnueabi --prefix=$CROSSROOT --with-sysroot=$TARGETROOT
# Make with flags to prevent warning creep on newer GCC's compiling older code.
make CFLAGS="-O2 -w"
make install
cd ..
# !!!! Now for GCC.
mkdir build.gcc.linux.gnueabi
cd build.gcc.linux.gnueabi
../gcc-4.2.0/configure --target=arm-linux-gnueabi --prefix=$CROSSROOT --enable-multilib --disable-libssp --enable-shared --disable-libgomp --disable-werror --disable-libmudflap --with-sysroot=$TARGETROOT
make -j2
make install
cd ..
# Create the specs file for editing GCC's configuration if we want to...
arm-linux-gnueabi-gcc -dumpspecs > .local/arm-linux-gnueabi/lib/specs
# Edit the specs file, and make *startfile command read:
#
# %{!shared: %{pg|p|profile:gcrt1.o%s;pie:Scrt1.o%s;:crt1.o%s}} elf-init.o%s crti.o%s %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s}
vim .local/arm-linux-gnueabi/lib/specs
# This edit will cause GCC to link the elf-init.o crti.o crt1.o crtn.o files (happily) from $TARGETROOT/lib where a user can easily install them.
# There are a few abused/problem header files... so fix them!
vim glibc-2.5/posix/regex_internal.h # line 393, changed static int to
#static reg_errcode_t build_wcs_upper_buffer (re_string_t *pstr) internal_function;
vim .target/include/asm/unistd.h # find line 410, comment it out...
# And do a softlink to fake out an abused header...
ln -s hwcap.h .target/include/asm/procinfo.h
# Now we can finally build a true libc...
mkdir build.glibc.gnueabi
( # Enter a new shell, because path needs to be forced.
rm -rf build.glibc.gnueabi/*
cd build.glibc.gnueabi
# GLibc errors out if it thinks LD_LIBRARY_PATH is set wrong, even if it's not.
# So disable it temporarily.
export LD_LIBRARY_PATH=""
echo "libc_cv_forced_unwind=yes" > config.cache # No crt1.o exists, yet...force
echo "libc_cv_ctors_header=yes" >> config.cache # constructor headers, yes?
echo "libc_cv_c_cleanup=yes" >> config.cache
echo "cross_compiling=yes" >> config.cache
echo "install_root=$TARGETROOT" > configparms # Where to really install target
export CFLAGS="-fgnu89-inline -D__OPTIMIZE__ -O2 "
../glibc-2.5/configure --build=i686 --host=arm-linux-gnueabi --prefix=/ --enable-kernel=2.6.23 --with-headers=$TARGETROOT/include --enable-add-ons --disable-profile --with-tls --with-__thread --cache-file=config.cache
make
make install-headers install_root=$TARGETROOT
make localedata/install-locales install_root=$TARGETROOT
) # End of subshell

Resources