Der Crosscompiler

Aus MySlug
Wechseln zu: Navigation, Suche

Um Programme außerhalb der NSLU2 für Unslung zu kompilieren muss eine Compilerumgebung auf einem Linux System aufgesetzt werden. Wer hierzu keine native Installation anlegen möchte, oder dies getrennt von einem bereits installierten Linux erledigen will, für dem empfiehlt es sich eine virtuelle Maschine anzulegen. Als kostenloses Programm empfehle ich VirtualBox, das man auch ohne Weiteres auf einem Windows XP oder Vista installieren und damit ein Linux in Betrieb nehmen kann.

Ich habe in meinen Beispiel ein Debian Linux (4.0r3 Etch) auf einer virtuellen Maschine installiert, damit ich diese sowohl unter Windows als auch unter Linux starten kann. Aber wie schon gesagt, zwingend notwendig ist die virtuelle Maschine nicht, sondern man kann dies auch auf ein nativ installiertes Linux durchführen.

Folgende Pakete müssen unter Linux installiert werden:

passende linux-headers
build-essential
subversion
bison
flex

Die Header hängen von der jeweiligen Distribution und dem installierten Kernel ab. Welchen Kernel Ihr installiert habt könnt Ihr mittels dem Konsolenbefehl

uname -a

in Erfahrung bringen. Unter Debian installiert Ihr dann die Headers wie folgt:

apt-get install linux-headers-2.VERSIONSNUMMER

Danach installiert Ihr die restlich benötigten Pakete mittels

apt-get install build-essential subversion bison flex

Die Crosscompiler-Umgebung installiert Ihr über einen SVN Checkout. Gebt dazu an der Konsole folgenden Befehl ein:

svn co https://svn.nslu2-linux.org/svnroot/optware/trunk optware

Das legt Euch ein neues Unterverzeichnis namens optware an. Als nächstes müssen wir die Compilerumgebung einrichten. Wechselt dazu in das Optwareverzeichnis:

cd optware

Danach folgender Befehl:

make nslu2-target

Jetzt wechselt ein Verzeichnis weiter:

cd nslu2

Dann noch ein

make directories ipkg-utils

Bevor nun letztendlich ein Programm kompilierbar wird müssen noch einige Copilertools nachgezogen werden. Hierzu stoßen wir einfach einen Kompile eines kleinen Tools an, dessen Makefile bereits mitgeliefert wurde. Stellt sicher, dass Ihr eine offene Internetverbindung habt. Gebt dann aus dem aktuellen /optware/nslu2/ Verzeichnis folgenden Befehl ein:

make htop

Das kann dann durchaus eine Ecke dauern. Der Compile sollte fehlerfrei durchlaufen. Bricht dieser mit einer Error Meldung ab, dann fehlt in der Regel noch ein Installationspaket Eures Debian Systemes. In der Regel gibt die Fehlermeldung darüber Aufschluss, welches Paket noch zu installieren ist. Allerdings sollte dies in der Basisversion durchlaufen.

Die Scripte um ein Paket zu installieren liegen im Unterverzeichnis /make. Vom Prinzip her ist in diesem Makefile der komplette Uübersetzungsvorgang hinterlegt. Hier werden ersteinmal die allgemeinen Daten des Maintainers hinterlegt. Dann muss genau festgelegt werden, von woher die Quelldateien des Programmes geladen werden sollen. Das Makefile zieht sich die Quellen aus dem Netz, hinterlegt diese in einem Buildverzeichnis und lässt dann den Compiler darüber laufen. Der Vorgang wird mit einem

make makefile

gestartet. Wenn der Buildvorgang durch ist wird dann das ipk Paket gebaut, das man dann auf die Slug kopieren und installieren kann:

make makefile-ipk

Das fertige Paket liegt dann unter /optware/nslu2/builds.
Wenn Ihr also ein neues Programm kompilieren wollt schaut Euch ein einfaches Makefile aus dem Make-Vereichnis an, gleicht es an das neue Programm entsprechend an und speichert es als neues Makefile mit dem Namen des Programmes ab ( programmname.mk ).

Ein Makefile, das ich für den Compile für den curl-ssl geschrieben habe sieht wie folgt aus (bitte NICHT als Vorlage verwenden, da die Formatiereung hier teilweise Zeilen umbricht!!!!):

###########################################################
#
# curl-ssl
#
###########################################################

# You must replace "curl-ssl" and "CURL-SSL" with the lower case name and
# upper case name of your new package.  Some places below will say
# "Do not change this" - that does not include this global change,
# which must always be done to ensure we have unique names.

#
# CURL-SSL_VERSION, CURL-SSL_SITE and CURL-SSL_SOURCE define
# the upstream location of the source code for the package.
# CURL-SSL_DIR is the directory which is created when the source
# archive is unpacked.
# CURL-SSL_UNZIP is the command used to unzip the source.
# It is usually "zcat" (for .gz) or "bzcat" (for .bz2)
#
# You should change all these variables to suit your package.
# Please make sure that you add a description, and that you
# list all your packages' dependencies, seperated by commas.
# 
# If you list yourself as MAINTAINER, please give a valid email
# address, and indicate your irc nick if it cannot be easily deduced
# from your name or email address.  If you leave MAINTAINER set to
# "NSLU2 Linux" other developers will feel free to edit.
#
CURL-SSL_SITE=http://dev.myslug.de/curl
CURL-SSL_VERSION=7.17.1
CURL-SSL_SOURCE=curl-ssl-$(CURL-SSL_VERSION).tar.gz
CURL-SSL_DIR=curl-ssl-$(CURL-SSL_VERSION)
CURL-SSL_UNZIP=zcat
CURL-SSL_MAINTAINER=NSLU2 Version myslug.de
CURL-SSL_DESCRIPTION=Download Manager
CURL-SSL_SECTION=net
CURL-SSL_PRIORITY=optional
CURL-SSL_DEPENDS=openssl
CURL-SSL_SUGGESTS=
CURL-SSL_CONFLICTS=

#
# CURL-SSL_IPK_VERSION should be incremented when the ipk changes.
#
CURL-SSL_IPK_VERSION=1

#
# CURL-SSL_CONFFILES should be a list of user-editable files
# CURL-SSL_CONFFILES=/opt/etc/curl-ssl.conf /opt/etc/init.d/SXXcurl-ssl

#
# CURL-SSL_PATCHES should list any patches, in the the order in
# which they should be applied to the source code.
#
# CURL-SSL_PATCHES=$(CURL-SSL_SOURCE_DIR)/configure.patch

#
# If the compilation of the package requires additional
# compilation or linking flags, then list them here.
#
CURL-SSL_CPPFLAGS=
CURL-SSL_LDFLAGS=

#
# CURL-SSL_BUILD_DIR is the directory in which the build is done.
# CURL-SSL_SOURCE_DIR is the directory which holds all the
# patches and ipkg control files.
# CURL-SSL_IPK_DIR is the directory in which the ipk is built.
# CURL-SSL_IPK is the name of the resulting ipk files.
#
# You should not change any of these variables.
#
CURL-SSL_BUILD_DIR=$(BUILD_DIR)/curl-ssl
CURL-SSL_SOURCE_DIR=$(SOURCE_DIR)/curl-ssl
CURL-SSL_IPK_DIR=$(BUILD_DIR)/curl-ssl-$(CURL-SSL_VERSION)-ipk
CURL-SSL_IPK=$(BUILD_DIR)/curl-ssl_$(CURL-SSL_VERSION)-$(CURL-SSL_IPK_VERSION)_$(TARGET_ARCH).ipk

.PHONY: curl-ssl-source curl-ssl-unpack curl-ssl curl-ssl-stage curl-ssl-ipk curl-ssl-clean curl-ssl-dirclean curl-ssl-check

#
# This is the dependency on the source code.  If the source is missing,
# then it will be fetched from the site using wget.
#
$(DL_DIR)/$(CURL-SSL_SOURCE):
	$(WGET) -P $(DL_DIR) $(CURL-SSL_SITE)/$(CURL-SSL_SOURCE) || \
	$(WGET) -P $(DL_DIR) $(SOURCES_NLO_SITE)/$(CURL-SSL_SOURCE)

#
# The source code depends on it existing within the download directory.
# This target will be called by the top level Makefile to download the
# source code's archive (.tar.gz, .bz2, etc.)
#
curl-ssl-source: $(DL_DIR)/$(CURL-SSL_SOURCE) $(CURL-SSL_PATCHES)

#
# This target unpacks the source code in the build directory.
# If the source archive is not .tar.gz or .tar.bz2, then you will need
# to change the commands here.  Patches to the source code are also
# applied in this target as required.
#
# This target also configures the build within the build directory.
# Flags such as LDFLAGS and CPPFLAGS should be passed into configure
# and NOT $(MAKE) below.  Passing it to configure causes configure to
# correctly BUILD the Makefile with the right paths, where passing it
# to Make causes it to override the default search paths of the compiler.
#
# If the compilation of the package requires other packages to be staged
# first, then do that first (e.g. "$(MAKE) <bar>-stage <baz>-stage").
#
# If the package uses  GNU libtool, you should invoke $(PATCH_LIBTOOL) as
# shown below to make various patches to it.
#
$(CURL-SSL_BUILD_DIR)/.configured: $(DL_DIR)/$(CURL-SSL_SOURCE) $(CURL-SSL_PATCHES) make/curl-ssl.mk
#	$(MAKE) <bar>-stage <baz>-stage
	rm -rf $(BUILD_DIR)/$(CURL-SSL_DIR) $(CURL-SSL_BUILD_DIR)
	$(CURL-SSL_UNZIP) $(DL_DIR)/$(CURL-SSL_SOURCE) | tar -C $(BUILD_DIR) -xvf -
	if test -n "$(CURL-SSL_PATCHES)" ; \
		then cat $(CURL-SSL_PATCHES) | \
		patch -d $(BUILD_DIR)/$(CURL-SSL_DIR) -p0 ; \
	fi
	if test "$(BUILD_DIR)/$(CURL-SSL_DIR)" != "$(CURL-SSL_BUILD_DIR)" ; \
		then mv $(BUILD_DIR)/$(CURL-SSL_DIR) $(CURL-SSL_BUILD_DIR) ; \
	fi
	(cd $(CURL-SSL_BUILD_DIR); \
		$(TARGET_CONFIGURE_OPTS) \
		CPPFLAGS="$(STAGING_CPPFLAGS) $(CURL-SSL_CPPFLAGS)" \
		LDFLAGS="$(STAGING_LDFLAGS) $(CURL-SSL_LDFLAGS)" \
		./configure \
		--build=$(GNU_HOST_NAME) \
		--host=$(GNU_TARGET_NAME) \
		--target=$(GNU_TARGET_NAME) \
		--prefix=/opt \
		--disable-nls \
		--disable-static \
		--with-ssl=/opt/bin/openssl \
	)
	$(PATCH_LIBTOOL) $(CURL-SSL_BUILD_DIR)/libtool
	touch $@

curl-ssl-unpack: $(CURL-SSL_BUILD_DIR)/.configured

#
# This builds the actual binary.
#
$(CURL-SSL_BUILD_DIR)/.built: $(CURL-SSL_BUILD_DIR)/.configured
	rm -f $@
	$(MAKE) -C $(CURL-SSL_BUILD_DIR)
	touch $@

#
# This is the build convenience target.
#
curl-ssl: $(CURL-SSL_BUILD_DIR)/.built

#
# If you are building a library, then you need to stage it too.
#
$(CURL-SSL_BUILD_DIR)/.staged: $(CURL-SSL_BUILD_DIR)/.built
	rm -f $@
	$(MAKE) -C $(CURL-SSL_BUILD_DIR) DESTDIR=$(STAGING_DIR) install
	touch $@

curl-ssl-stage: $(CURL-SSL_BUILD_DIR)/.staged

#
# This rule creates a control file for ipkg.  It is no longer
# necessary to create a seperate control file under sources/curl-ssl
#
$(CURL-SSL_IPK_DIR)/CONTROL/control:
	@install -d $(@D)
	@rm -f $@
	@echo "Package: curl-ssl" >>$@
	@echo "Architecture: $(TARGET_ARCH)" >>$@
	@echo "Priority: $(CURL-SSL_PRIORITY)" >>$@
	@echo "Section: $(CURL-SSL_SECTION)" >>$@
	@echo "Version: $(CURL-SSL_VERSION)-$(CURL-SSL_IPK_VERSION)" >>$@
	@echo "Maintainer: $(CURL-SSL_MAINTAINER)" >>$@
	@echo "Source: $(CURL-SSL_SITE)/$(CURL-SSL_SOURCE)" >>$@
	@echo "Description: $(CURL-SSL_DESCRIPTION)" >>$@
	@echo "Depends: $(CURL-SSL_DEPENDS)" >>$@
	@echo "Suggests: $(CURL-SSL_SUGGESTS)" >>$@
	@echo "Conflicts: $(CURL-SSL_CONFLICTS)" >>$@

#
# This builds the IPK file.
#
# Binaries should be installed into $(CURL-SSL_IPK_DIR)/opt/sbin or $(CURL-SSL_IPK_DIR)/opt/bin
# (use the location in a well-known Linux distro as a guide for choosing sbin or bin).
# Libraries and include files should be installed into $(CURL-SSL_IPK_DIR)/opt/{lib,include}
# Configuration files should be installed in $(CURL-SSL_IPK_DIR)/opt/etc/curl-ssl/...
# Documentation files should be installed in $(CURL-SSL_IPK_DIR)/opt/doc/curl-ssl/...
# Daemon startup scripts should be installed in $(CURL-SSL_IPK_DIR)/opt/etc/init.d/S??curl-ssl
#
# You may need to patch your application to make it use these locations.
#
$(CURL-SSL_IPK): $(CURL-SSL_BUILD_DIR)/.built
	rm -rf $(CURL-SSL_IPK_DIR) $(BUILD_DIR)/curl-ssl_*_$(TARGET_ARCH).ipk
	$(MAKE) -C $(CURL-SSL_BUILD_DIR) DESTDIR=$(CURL-SSL_IPK_DIR) install-strip
	install -d $(CURL-SSL_IPK_DIR)/opt/etc/
#	install -m 644 $(CURL-SSL_SOURCE_DIR)/curl-ssl.conf $(CURL-SSL_IPK_DIR)/opt/etc/curl-ssl.conf
	install -d $(CURL-SSL_IPK_DIR)/opt/etc/init.d
#	install -m 755 $(CURL-SSL_SOURCE_DIR)/rc.curl-ssl $(CURL-SSL_IPK_DIR)/opt/etc/init.d/SXXcurl-ssl
#	sed -i -e '/^#!/aOPTWARE_TARGET=${OPTWARE_TARGET}' $(CURL-SSL_IPK_DIR)/opt/etc/init.d/SXXcurl-ssl
	$(MAKE) $(CURL-SSL_IPK_DIR)/CONTROL/control
#	install -m 755 $(CURL-SSL_SOURCE_DIR)/postinst $(CURL-SSL_IPK_DIR)/CONTROL/postinst
#	sed -i -e '/^#!/aOPTWARE_TARGET=${OPTWARE_TARGET}' $(CURL-SSL_IPK_DIR)/CONTROL/postinst
#	install -m 755 $(CURL-SSL_SOURCE_DIR)/prerm $(CURL-SSL_IPK_DIR)/CONTROL/prerm
#	sed -i -e '/^#!/aOPTWARE_TARGET=${OPTWARE_TARGET}' $(CURL-SSL_IPK_DIR)/CONTROL/prerm
	if test -n "$(UPD-ALT_PREFIX)"; then \
		sed -i -e '/^[ 	]*update-alternatives /s|update-alternatives|$(UPD-ALT_PREFIX)/bin/&|' \
			$(CURL-SSL_IPK_DIR)/CONTROL/postinst $(CURL-SSL_IPK_DIR)/CONTROL/prerm; \
	fi
	echo $(CURL-SSL_CONFFILES) | sed -e 's/ /\n/g' > $(CURL-SSL_IPK_DIR)/CONTROL/conffiles
	cd $(BUILD_DIR); $(IPKG_BUILD) $(CURL-SSL_IPK_DIR)

#
# This is called from the top level makefile to create the IPK file.
#
curl-ssl-ipk: $(CURL-SSL_IPK)

#
# This is called from the top level makefile to clean all of the built files.
#
curl-ssl-clean:
	rm -f $(CURL-SSL_BUILD_DIR)/.built
	-$(MAKE) -C $(CURL-SSL_BUILD_DIR) clean

#
# This is called from the top level makefile to clean all dynamically created
# directories.
#
curl-ssl-dirclean:
	rm -rf $(BUILD_DIR)/$(CURL-SSL_DIR) $(CURL-SSL_BUILD_DIR) $(CURL-SSL_IPK_DIR) $(CURL-SSL_IPK)
#
#
# Some sanity check for the package.
#
curl-ssl-check: $(CURL-SSL_IPK)
	perl scripts/optware-check-package.pl --target=$(OPTWARE_TARGET) $(CURL-SSL_IPK)

Da hier erstmal wenn Ihr das Programm neu erzeugt im Scriptfile alle CURL-SSL und curl-ssl Strings auf Euer neues Programm umgeschrieben werden muss bietet es sich an, dies über einen sed Befehl unter Linux zu erledigen. Sonst besteht die Gefahr, dass Ihr irgendwo vergesst, den Namen zu ändern und damit das Script nicht funktioniert. Wir nehmen einmal an, dass das Script curl-ssl.mk in das Programm testi.mk umgebaut werden muss. D.h. folgende Strings können wir automatisiert abändern:

curl-ssl --> testi
CURL-SSL --> TESTI

Der Befehl lautet hierzu (curl-ssl.mk liegt bereits im /make-Verzeichnis und Ihr befindet Euch nach wie vor unter /optware/nslu2). Zuerst kopieren wir curl.ssl.mk als neue Datei testi.mk:

cp make/curl-ssl.mk make/testi.mk

Dann genau aufpassen beim Eintippen:

sed -i 's/CURL-SSL/TESTI/g' make/testi.mk
sed -i 's/curl-ssl/testi/g' make/testi.mk

Jetzt müsst Ihr nur noch den Rest des Files angleichen. Es wird nicht ausbleiben, dass Ihr den einen oder anderen Fehler zuerst bekommen werdet. Hier müsst Ihr viel probieren, bis Ihr durch das Prinzip des Makefiles steigt. Aber wer halbwegs Erfahrung damit hat, wird letztendlich schnell damit zurecht kommen.

Crosskompiler auf Debian Etch in einer VirtualBox auf Windows Vista 64bit Ultimate:
Crosscompile.jpg