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
Related
I'm such a beginner on OpenWrt and Makefiles, trying to demonstrate "Helloworld" example of creating a package but at the package feed update step, from command ./scripts/feeds update mypackages I get this error
Updating feed 'mypackages' from '/home/onur/Desktop/OpenWRT/openwrt/mypackages' ...
Create index file './feeds/mypackages.index'
/home/onur/Desktop/OpenWRT/openwrt/feeds/mypackages.tmp/info/.files-packageinfo.mk:1: *** target pattern contains no '%'. Stop.
I have src-link mypackages /home/onur/Desktop/OpenWRT/openwrt/mypackages in my feeds.conf, "helloworld" C program compiled on /openwrt/helloworld directory and below is my Makefile:
include $(TOPDIR)/rules.mk
# Name, version and release number
# The name and version of your package are used to define the variable to point to the build directory of your package: $(PKG_BUILD_DIR)
PKG_NAME:=helloworld
PKG_VERSION:=1.0
PKG_RELEASE:=1
# Source settings (i.e. where to find the source codes)
# This is a custom variable, used below
SOURCE_DIR:=/home/onur/Desktop/OpenWRT/openwrt/helloworld
include $(INCLUDE_DIR)/package.mk
# Package definition; instructs on how and where our package will appear in the overall configuration menu ('make menuconfig')
define Package/helloworld
SECTION:=examples
CATEGORY:=Examples
TITLE:=Hello, World!
endef
# Package description; a more verbose description on what our package does
define Package/helloworld/description
A simple "Hello, world!" -application.
endef
# Package preparation instructions; create the build directory and copy the source code.
# The last command is necessary to ensure our preparation instructions remain compatible with the patching system.
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
cp $(SOURCE_DIR)/* $(PKG_BUILD_DIR)
$(Build/Patch)
endef
# Package build instructions; invoke the target-specific compiler to first compile the source file, and then to link the file into the final executable
define Build/Compile
$(MAKE) -C $(PKG_BUILD_DIR) \
CXX="$(TARGET_CROSS)g++"
endef
# Package install instructions; create a directory inside the package to hold our executable, and then copy the executable we built previously into the folder
define Package/helloworld/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/helloworld $(1)/usr/bin
endef
# This command is always the last, it uses the definitions and variables we give above in order to get the job done
$(eval $(call BuildPackage,helloworld))
I know I may have mistake on cross-compile part but I don't think that's the issue that I'm having right now.
When I try to make this Makefile, I get that error.
Makefile:13: /package.mk: No such file or directory
make: *** No rule to make target '/package.mk'. Stop.
I can't find any problem like this anywhere. Why it can't even find "package.mk" file.
My directory structure is like, Top directory is Desktop/OpenWrt/openwrt and this Makefile is in Desktop/OpenWrt/openwrt/mypackage folder. I'm on Ubuntu 20.04
I found solution to my question on OpenWrt Forum. Here is the link of thread
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
I am trying to cross-compile a project for embedded ARM Cortex builds, but I am unable to get the linker working. I want to use armlink, but no files are passed to armlink and hence no .elf file is produced.
My CMakeLists.txt is pretty simple and given below. The failure is shown after that which shows that armlink was invoked by the makefile without any arguments.
Any pointers will help - I searched and read many posts, but they all seem to have more involved requirements.
cmake_minimum_required(VERSION 2.8)
project(test_arm)
enable_language(C ASM)
# Cross-compilation for ARM
SET(CMAKE_C_COMPILER armcc)
SET(CMAKE_LINKER armlink)
SET(CMAKE_C_LINK_EXECUTABLE armlink)
SET(CMAKE_C_FLAGS "--cpu=Cortex-M3")
SET(LINK_FLAGS "--map --ro-base=0x0 --rw-base=0x0008000 --first='boot.o(RESET)' --datacompressor=off")
SET(CMAKE_EXE_LINKER_FLAGS "--map --ro-base=0x0 --rw-base=0x0008000 --first='boot.o(RESET)' --datacompressor=off")
include_directories(../include)
add_executable(blinky blinky.c)
set_target_properties(blinky PROPERTIES LINKER_LANGUAGE C)
The failure is as follows, but I guess it would be obvious to someone given that I have some stupid issue in my CMakeLists:
$ make VERBOSE=1
[100%] Building C object CMakeFiles/blinky.dir/blinky.c.o
/usr/bin/cmake -E cmake_link_script CMakeFiles/blinky.dir/link.txt --verbose=1
armlink
Linking C executable blinky
Product: DS-5 Professional 5.21.0 [5210017]
Component: ARM Compiler 5.05 update 1 (build 106)
Tool: armlink [4d0efa]
For support see http://www.arm.com/support/
Software supplied by: ARM Limited
Usage: armlink option-list input-file-list
where
....
I was expecting the CMake generated Makefile to invoke armlink with something like:
armlink --map --ro-base=0x0 --rw-base=0x0008000 \
--first='boot.o(RESET)' --datacompressor=off \
CMakeFiles/blinky.dir/blinky.c.o -o blinky.elf
Starting with CMake v3.5 you don't need a toolchain anymore for Keil ARM C/C++ compilation tools:
Support was added for the ARM Compiler (arm.com) with compiler id ARMCC.
Just set your C/CXX compiler variables accordingly
cmake -DCMAKE_C_COMPILER:PATH="C:\Program Files (x86)\DS-5\bin\armcc.exe"
-DCMAKE_CXX_COMPILER:PATH="C:\Program Files (x86)\DS-5\bin\armcc.exe"
...
References
ARMCC toolchain support
Add support for the ARM Compiler (arm.com)
CMake Error at CMakeLists.txt:30 (project): No CMAKE_C_COMPILER could be found
From my experience, you cannot set CMAKE_EXE_LINKER_FLAGS in a CMakeLists.txt file. It has to be passed via a CMAKE_TOOLCHAIN_FILE when CMake is invoked the very first time in a build directory.
I don't find any documentation regarding this problem, but there is the cross-compilation with CMake page which you should use it if you do cross-compilation.
For a start, just put your set-calls in a toolchain file and run
cmake -DCMAKE_TOOLCHAIN_FILE=<yourfile.toolchain>
in a clean build directory.
A toolchain file may be a good idea. Here is what I've came up the last time I tried CMake 2.8.10 with the DS-5 toolchain (it could still be optimized, but it should give you a starting point):
INCLUDE(CMakeForceCompiler)
# This one is important
SET(CMAKE_SYSTEM_NAME Generic)
SET(CMAKE_SYSTEM_PROCESSOR arm)
# Specify the cross compiler
SET(CMAKE_C_COMPILER "C:/Program Files (x86)/DS-5/bin/armcc.exe")
SET(CMAKE_CXX_COMPILER "C:/Program Files (x86)/DS-5/bin/armcc.exe")
SET(CMAKE_AR "C:/Program Files (x86)/DS-5/bin/armar.exe" CACHE FILEPATH "Archiver")
#CMAKE_FORCE_C_COMPILER("C:/Program Files (x86)/DS-5/sw/gcc/bin/arm-linux-gnueabihf-gcc.exe" GNU)
#CMAKE_FORCE_CXX_COMPILER("C:/Program Files (x86)/DS-5/sw/gcc/bin/arm-linux-gnueabihf-g++.exe" GNU)
UNSET(CMAKE_C_FLAGS CACHE)
SET(CMAKE_C_FLAGS "--cpu=Cortex-A9 --thumb -Ospace" CACHE STRING "" FORCE)
UNSET(CMAKE_CXX_FLAGS CACHE)
SET(CMAKE_CXX_FLAGS ${CMAKE_C_FLAGS} CACHE STRING "" FORCE)
UNSET(CMAKE_EXE_LINKER_FLAGS CACHE)
SET(CMAKE_EXE_LINKER_FLAGS "" CACHE STRING "" FORCE)
UNSET(CMAKE_AR_FLAGS CACHE)
SET(CMAKE_AR_FLAGS "-p -armcc,-Ospace" CACHE STRING "" FORCE)
# set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> cr <TARGET> <LINK_FLAGS> <OBJECTS>")
SET(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> ${CMAKE_AR_FLAGS} -o <TARGET> <OBJECTS>" CACHE STRING "C Archive Create")
# set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> cr <TARGET> <LINK_FLAGS> <OBJECTS>")
SET(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> ${CMAKE_AR_FLAGS} -o <TARGET> <OBJECTS>" CACHE STRING "CXX Archive Create")
include_directories("C:/Program Files (x86)/DS-5/include")
#include_directories("C:/Program Files (x86)/DS-5/sw/gcc/arm-linux-gnueabihf/libc/usr/include/arm-linux-gnueabi")
# Where is the target environment
SET(CMAKE_FIND_ROOT_PATH "C:/Program Files (x86)/DS-5")
# 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)
Regarding your question
Some failure analysis
What you have tried should work (see also e.g. How do I add a linker or compile flag in a CMake file?). But it seems something goes wrong during the configuration step.
I don't know your command line call for CMake's configuration/generation steps, so some general tips to find the root cause:
You could try calling
cmake.exe --trace ...
to see what went wrong with your CMAKE_EXE_LINKER_FLAGS variable. This will generate a lot of output, so here are some basics on what CMake does:
The project() command will trigger the compiler evaluation
This will write CMAKE_EXE_LINKER_FLAGS into your CMakeCache.txt
You are overwriting it with a local variable (see variable scope docu here)
If you look into share\cmake-2.8\Modules\CMakeCommonLanguageInclude.cmake:
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS_INIT} $ENV{LDFLAGS}"
CACHE STRING "Flags used by the linker.")
You could use CMAKE_EXE_LINKER_FLAGS_INIT, but you have to set it before the project() command or in the toolchain file.
Because you set the link language to C take a look into share\cmake-2.8\Modules\CMakeCInformation.cmake:
if(NOT CMAKE_C_LINK_EXECUTABLE)
set(CMAKE_C_LINK_EXECUTABLE
"<CMAKE_C_COMPILER> <FLAGS> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
endif()
So you can use CMAKE_C_LINK_EXECUTABLE to overwrite the complete linker call or you could use CMAKE_C_LINK_FLAGS to set additional flags.
The "official" way
The official way to set the target's linker and compiler flags would be (before CMake 2.8.12):
set_property(TARGET blinky APPEND_STRING PROPERTY COMPILE_FLAGS "--cpu=Cortex-M3")
set_property(TARGET blinky APPEND_STRING PROPERTIES LINK_FLAGS "--map --ro-base=0x0 --rw-base=0x0008000 --first='boot.o(RESET)' --datacompressor=off")
Starting with CMake 2.8.12 it would be something like:
add_compile_options("--cpu=Cortex-M3")
I am new in NDK and I am following this guide to build OpenSSL for Android, I am using Windows 7 and Cygwin for this.
I'm having errors when trying to build the OpenSSL library.
# From the 'root' directory
$ . ./setenv-android.sh
$ cd openssl-1.0.1g/
$ perl -pi -e 's/install: all install_docs install_sw/install: install_docs install_sw/g' Makefile.org
$ ./config shared no-ssl2 no-ssl3 no-comp no-hw no-engine --openssldir=/usr/local/ssl/$ANDROID_API
$ make depend
$ make all
When I try the make depend command I have 2 errors:
cryptlib.c:171:3: error: #error "Inconsistency between crypto.h and cryptlib.c"
# error "Inconsistency between crypto.h and cryptlib.c"
the cryplib.c line 171 says:
#if CRYPTO_NUM_LOCKS != 41
# error "Inconsistency between crypto.h and cryptlib.c"
#endif
I don't know how to fix that error.
the other one is uid.c:77:10: error: #include expects "FILENAME" or <FILENAME>
#include OPENSSL_UNISTD
if I change the line 77 in uid.c to #include <unistd.h> I get an error in the Makefile, so I don't know if it's the way to fix it, the error was in depend Makefile.
depend:
#[ -z "$(THIS)" -o -f buildinf.h ] || touch buildinf.h # fake buildinf.h if it does not exist
#[ -z "$(THIS)" ] || $(MAKEDEPEND) -- $(CFLAG) $(INCLUDE) $(DEPFLAG) -- $(PROGS) $(LIBSRC)
#[ -z "$(THIS)" -o -s buildinf.h ] || rm buildinf.h
#[ -z "$(THIS)" ] || (set -e; target=depend; $(RECURSIVE_MAKE) )
#if [ -z "$(THIS)" ]; then $(MAKE) -f $(TOP)/Makefile reflect THIS=$#; fi
Another question is if I can use this guide to build the OpenSSL library to the 64bit arch. (x86_64, arm64 and mips64) I haven't found information about OpenSSL for Android in those architectures, all post about it are old and those arch didn't exist for Android
EDIT
I found a way to solve partially my problem (not the best one but it works), the problem was due some errors in some paths, because I was trying to use Cywin on Windows and some files(I don't which ones) were trying to reach some paths that doesn't exist because I was on Windows and not in Linux, so I just install Ubuntu on a virtual machine and try this guide again, and I could compile libraries and I have libcrypto.a libcrypto.so libssl.a libssl.so for Android ARM, x86, mips, ARM64 and x86_64 Architectures.
But the libraries doesn't work for x86_64 and ARM64, when I try to compile a .c using the android.mk for x86_64 or arm64 eabi it doesn't compile due some compatibility errors, but if a try to compile de same .c file withe the "x86_64" or "arm-64" for a x86 or arm eabi it does compile, so they are still a 32bit libraries, this is not the answer because I need the libraries for all the architecture (at least for armv5, armv7, armv8-64, x86, x86_64), this is just a small step.
I will be updating to help someone with the same problem and if someone want to help me.
When I try the make depend command I have 2 errors:
cryptlib.c:171:3: error: #error "Inconsistency between crypto.h and cryptlib.c"
# error "Inconsistency between crypto.h and cryptlib.c"
There's a problem with the symlinks. Unpack the tarball again with tar zxvf. Then, verify the header files are not 0 length.
Also see Inconsistency between crypto.h and cryptlib.c on the OpenSSL mailing list. And How to copy symbolic link file from Linux to Windows and then back to Linux but still keeping it as a symbolic link on Stack Overflow.
Using this guide and modifying the file setenv-android.sh you can easy compile openssl for arm, x86 and mips.
You just have to modify _ANDROID_NDK _ANDROID_ARCH _ANDROID_EABI _ANDROID_API parameters
note: for mips you'll have to add some lines in the file around
around line 120:
arch-mips)
ANDROID_TOOLS="mipsel-linux-android-gcc mipsel-linux-android-ranlib mipsel-linux-android-ld"
;;
around line 200:
if [ "$_ANDROID_ARCH" == "arch-mips" ]; then
export MACHINE=mipsel
export RELEASE=2.6.37
export SYSTEM=android
export ARCH=mips
export CROSS_COMPILE="mipsel-linux-android-"
fi
if you follow the guide you'll have libcrypto.a, libssl.a, libcrypto.so and libssl.so.
if you want the libraries for 64 bits architecture you can do a pull from a device using adb, all android device have libcrypto.so and libssl.so in /system/lib64 for 64bits version (only in a 64bits device), and /system/lib the 32bits version, you can use an emulator for that, if you can want the 64bits version of the static libraries (libcrypto.a and libssl.a) in this link you can find the way to do it.
I am trying to build a arm toolchain from scratch.
I am referring to this site.
http://www.nixit.co.uk/cortex-m3-mac-1
Followed all the instructions carefully. Everything went well till newlib compilation. I am getting strange error.
/bin/bash: arm-none-eabi-cc: command not found
So I checked the Makefile
there is a line in makefile. There is a directive related to arm-none-eabi-cc
# -----------------------------------------------
# Programs producing files for the TARGET machine
# -----------------------------------------------
AR_FOR_TARGET=arm-none-eabi-ar
AS_FOR_TARGET=arm-none-eabi-as
CC_FOR_TARGET=$(STAGE_CC_WRAPPER) arm-none-eabi-cc
# If GCC_FOR_TARGET is not overriden on the command line, then this
# variable is passed down to the gcc Makefile, where it is used to
# build libgcc2.a. We define it here so that it can itself be
# overridden on the command line.
GCC_FOR_TARGET=$(STAGE_CC_WRAPPER) arm-none-eabi-gcc
I checked the /usr/arm/bin directory. So i do find arm-none-eabi tools, but not arm-none-eabi-cc
arm-none-eabi-ld arm-none-eabi-readelf
arm-none-eabi-ar arm-none-eabi-gcc-4.4.3 arm-none-eabi-nm arm-none-eabi-size
arm-none-eabi-as **arm-none-eabi-gcc**
Please help
Try replacing arm-none-eabi-cc in the Makefile with arm-none-eabi-gcc, or symlinking arm-none-eabi-cc to arm-none-eabi-gcc.