Saturday, May 30, 2015

FPC and Lazarus development environment

Notes on how to set up a FreePascal/Lazarus development environment on a Linux system, with cross-compiling for OSX and Windows. Intended as a future reference for myself and anybody else who might find them useful.
I'm using Linux Mint 17.1 'Rebecca' MATE 64-bit.

Initial installation

Install fpc

~ $ sudo apt-get install fpc fp-utils

Check installed version

The current maintained version is 2.6.2:
~ $ which fpc
/usr/bin/fpc
~ $ fpc -?
Free Pascal Compiler version 2.6.2-8 [2014/01/22] for x86_64
Copyright (c) 1993-2012 by Florian Klaempfl and others
/usr/lib/fpc/2.6.2/ppcx64 [options] <inputfile> [options] 

Hello, world!

Write a simple program to show the compiler version:
~/Development/Hello $ nano hello.pas
{$MACRO ON}
program Hello;
begin
  Writeln('Hello, world from FPC ', FPC_FULLVERSION, '!');
end.
Compile and run it:
~/Development/Hello $ fpc hello.pas
Free Pascal Compiler version 2.6.2-8 [2014/01/2/2] for x86_64
Copyright (c) 1993-2012 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling hello.pas
Linking hello
/usr/bin/ld.bfd: warning: link.res contains output sections; did you forget -T?
5 lines compiled, 0.2 sec
~/Development/Hello $ ./hello
Hello, world from FPC 20602!

Latest (trunk) installation

Get latest fpc

~/Development $ svn checkout http://svn.freepascal.org/svn/fpc/trunk fpc

Build latest fpc (linux-x86_64)

Use fpc 2.6.2 to build the latest fpc:

~/Development/fpc $ make distclean
~/Development/fpc $ make all install FPC=/usr/bin/fpc OPT=-gl INSTALL_PREFIX=~

Configuration

The original installation creates a symlink in /etc/fpc.cfg pointing to /etc/alternatives/fpc.cfg which itself is a symlink pointing to /etc/fpc-2.6.2.cfg. In the code below, we copy the original config file to ~/Development and fix the symlink to point to it.
~/Development $ cp /etc/fpc.cfg ~/Development
~/Development $ sudo rm /etc/fpc.cfg
~/Development $ sudo ln -s ~/Development/fpc.cfg /etc/fpc.cfg
Modify the new configuration file:
@@ -124,6 +124,8 @@
 -Cppentiumm
 -Oppentiumm
 #endif
+  -gw
+  -XR/usr/lib/apple/SDKs/MacOSX10.6.sdk
 #endif
 
 # -----------------------
@@ -141,17 +143,17 @@
 #-Fr/usr/lib/fpc/$fpcversion/msg/errorr.msg
 
 # searchpath for units and other system dependent things
--Fu/usr/lib/fpc/$fpcversion/units/$fpctarget
--Fu/usr/lib/fpc/$fpcversion/units/$fpctarget/*
--Fu/usr/lib/fpc/$fpcversion/units/$fpctarget/rtl
+-Fu~/lib/fpc/$fpcversion/units/$fpctarget
+-Fu~/lib/fpc/$fpcversion/units/$fpctarget/*
+-Fu~/lib/fpc/$fpcversion/units/$fpctarget/rtl
 
 #IFDEF FPCAPACHE_1_3
--Fu/usr/lib/fpc/$fpcversion/units/$fpctarget/httpd13/
+-Fu~/lib/fpc/$fpcversion/units/$fpctarget/httpd13/
 #ELSE
 #IFDEF FPCAPACHE_2_0
--Fu/usr/lib/fpc/$fpcversion/units/$fpctarget/httpd20
+-Fu~/lib/fpc/$fpcversion/units/$fpctarget/httpd20
 #ELSE
--Fu/usr/lib/fpc/$fpcversion/units/$fpctarget/httpd22
+-Fu~/lib/fpc/$fpcversion/units/$fpctarget/httpd22
 #ENDIF
 #ENDIF
 
@@ -160,7 +162,7 @@
 
 # path to the gcclib
 #ifdef cpui386
--Fl/usr/lib/gcc/x86_64-linux-gnu/4.8
+-Fl/usr/lib/gcc/x86_64-linux-gnu/4.8/32
 #endif
 #ifdef cpux86_64
 -Fl/usr/lib/gcc/x86_64-linux-gnu/4.8
@@ -168,11 +170,16 @@
 
 # searchpath for libraries
 #-Fl/usr/lib/fpc/$fpcversion/lib
-#-Fl/lib;/usr/lib
--Fl/usr/lib/fpc/$fpcversion/lib/$FPCTARGET
+#ifdef cpui386
+-Fl/usr/lib/i386-linux-gnu;/lib32;/usr/lib32
+#endif
+#ifdef cpux86_64
+-Fl/lib;/usr/lib
+#endif
+-Fl~/lib/fpc/$fpcversion/lib/$fpctarget
 
 # searchpath for tools
--FD/usr/lib/fpc/$fpcversion/bin/$FPCTARGET
+-FD~/lib/fpc/$fpcversion/bin/$fpctarget
 
 #IFNDEF CPUI386
 #IFNDEF CPUAMD64
@@ -241,7 +248,7 @@
 # If you don't want so much verbosity use
 #-vw
 # multiarch library search path
--Fl/usr/lib/$fpctarget-*
+-Fl~/lib/$fpctarget-*
 # Third party units should be installe in a, multi-arch compatible location.
 # Units should be installed in /usr/lib/$fpctarget-gnu/fp-units-2.6.2/$pkg/.
 # Ech fp-units package should install a configuration file called $pkg.cfg in

Create a symlink for the new compiler:
~/Development/fpc $ ln -s ~/lib/fpc/3.1.1/ppcx64 ~/bin/ppcx64

Hello, world! (linux-x86_64)

~/Development/Hello $ fpc hello.pas
Free Pascal Compiler version 3.1.1 [2015/05/29] for x86_64
Copyright (c) 1993-2015 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling hello.pas
Linking hello
/usr/bin/ld: warning: link.res contains output sections; did you forget -T?
5 lines compiled, 0.3 sec
~/Development/Hello $ ./hello
Hello, world from FPC 30101!

Cross-compiling

See useful tips here.

Linux

Install prerequisites

For cross-compiling to 32-bit Linux, install gcc-multilib and create a few links.
~ $ sudo apt-get install gcc-multilib
~ $ sudo ln -s /usr/lib/i386-linux-gnu/libX11.so.6 /usr/lib/i386-linux-gnu/libX11.so
~ $ sudo ln -s /usr/lib/i386-linux-gnu/libgtk-x11-2.0.so.0 /usr/lib/i386-linux-gnu/libgtk-x11-2.0.so
~ $ sudo ln -s /usr/lib/i386-linux-gnu/libgdk_pixbuf-2.0.so.0 /usr/lib/i386-linux-gnu/libgdk_pixbuf-2.0.so
~ $ sudo ln -s /usr/lib/i386-linux-gnu/libgdk-x11-2.0.so.0 /usr/lib/i386-linux-gnu/libgdk-x11-2.0.so
~ $ sudo ln -s /usr/lib/i386-linux-gnu/libgobject-2.0.so.0 /usr/lib/i386-linux-gnu/libgobject-2.0.so
~ $ sudo ln -s /lib/i386-linux-gnu/libglib-2.0.so.0 /lib/i386-linux-gnu/libglib-2.0.so
~ $ sudo ln -s /usr/lib/i386-linux-gnu/libgthread-2.0.so.0 /usr/lib/i386-linux-gnu/libgthread-2.0.so
~ $ sudo ln -s /usr/lib/i386-linux-gnu/libgmodule-2.0.so.0 /usr/lib/i386-linux-gnu/libgmodule-2.0.so
~ $ sudo ln -s /usr/lib/i386-linux-gnu/libpango-1.0.so.0 /usr/lib/i386-linux-gnu/libpango-1.0.so
~ $ sudo ln -s /usr/lib/i386-linux-gnu/libcairo.so.2 /usr/lib/i386-linux-gnu/libcairo.so
~ $ sudo ln -s /usr/lib/i386-linux-gnu/libatk-1.0.so.0 /usr/lib/i386-linux-gnu/libatk-1.0.so

Cross-compiler for linux-i386

~ $ nano ~/bin/i386-linux-ld
#!/bin/bash
ld -A elf32-i386 $@
~ $ chmod +x ~/bin/i386-linux-ld
~ $ nano ~/bin/i386-linux-as
#!/bin/bash
as --32 $@
~ $ chmod +x ~/bin/i386-linux-as
~/Development/fpc $ make distclean OS_TARGET=linux CPU_TARGET=i386
~/Development/fpc $ make all crossinstall FPC=/usr/bin/fpc NOGDB=1 OS_TARGET=linux CPU_TARGET=i386 \
  INSTALL_PREFIX=~

Create a symlink for the new cross-compiler:
~ $ ln -s ~/lib/fpc/3.1.1/ppcross386 ~/bin/ppcross386

Hello, world! (linux-i386)

~/Development/Hello $ fpc -Pi386 hello.pas
Free Pascal Compiler version 3.1.1 [2015/05/29] for i386
Copyright (c) 1993-2015 by Florian Klaempfl and others
Target OS: Linux for i386
Compiling hello.pas
Linking hello
/usr/bin/ld: warning: link.res contains output sections; did you forget -T?
5 lines compiled, 0.2 sec
~/Development/Hello $ ./hello
Hello, world from FPC 30101!

Windows

Cross-compiler for win32-i386

~/Development/fpc $ make distclean OS_TARGET=win32 CPU_TARGET=i386
~/Development/fpc $ make all crossinstall FPC=/usr/bin/fpc NOGDB=1 OS_TARGET=win32 CPU_TARGET=i386 INSTALL_PREFIX=~

Hello, world! (win32-i386)

~/Development/Hello $ fpc -Twin32 -Pi386 hello.pas
Free Pascal Compiler version 3.1.1 [2015/05/29] for i386
Copyright (c) 1993-2015 by Florian Klaempfl and others
Target OS: Win32 for i386
Compiling hello.pas
Linking hello.exe
5 lines compiled, 0.0 sec, 26976 bytes code, 1284 bytes data

Cross-compiler for win64-x86_64

~/Development/fpc $ make distclean OS_TARGET=win64 CPU_TARGET=x86_64
~/Development/fpc $ make all crossinstall FPC=/usr/bin/fpc NOGDB=1 OS_TARGET=win64 CPU_TARGET=x86_64 \
  INSTALL_PREFIX=~

Hello, world! (win64-x86_64)

~/Development/Hello $ fpc -Twin64 -Px86_64 hello.pas
Free Pascal Compiler version 3.1.1 [2015/05/29] for x86_64
Copyright (c) 1993-2015 by Florian Klaempfl and others
Target OS: Win64 for x64
Compiling hello.pas
Linking hello.exe
5 lines compiled, 0.1 sec, 33504 bytes code, 1364 bytes data

OSX

Install odcctools and SDK

Install ppa:flosoft/cross-apple manually (to use maverick):
~ $ sudo nano /etc/apt/sources.list
deb http://ppa.launchpad.net/flosoft/cross-apple/ubuntu maverick main 
deb-src http://ppa.launchpad.net/flosoft/cross-apple/ubuntu maverick main
~ $ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys D0611AA0
~ $ sudo apt-get update
~ $ sudo apt-get install apple-x86-odcctools
~ $ sudo apt-get install apple-uni-sdk-10.6
~ $ ln -s /usr/bin/i686-apple-darwin10-ld ~/bin/x86_64-darwin-ld
~ $ ln -s /usr/bin/i686-apple-darwin10-ld ~/bin/i386-darwin-ld
~ $ ln -s /usr/bin/i686-apple-darwin10-as ~/bin/x86_64-darwin-as
~ $ ln -s /usr/bin/i686-apple-darwin10-as ~/bin/i386-darwin-as

Cross-compiler for darwin-i386

~/Development/fpc make distclean OS_TARGET=darwin CPU_TARGET=i386
~/Development/fpc $ make crossall crossinstall FPC=/usr/bin/fpc NOGDB=1 OS_TARGET=darwin CPU_TARGET=i386 \
  INSTALL_PREFIX=~ BINUTILSPREFIX=i686-apple-darwin10- \
  OPT="-gl -gw -godwarfsets -XX -CX -Xd -Fl/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib"

Hello, world! (darwin-i386)

~/Development/Hello $ fpc -Tdarwin -Pi386 hello.pas
Free Pascal Compiler version 3.1.1 [2015/05/29] for i386
Copyright (c) 1993-2015 by Florian Klaempfl and others
Target OS: Darwin for i386
Compiling hello.pas
Assembling (pipe) hello.s
Linking hello
5 lines compiled, 0.1 sec

Cross-compiler for darwin-x86_64

~/Development/fpc $ make distclean OS_TARGET=darwin CPU_TARGET=x86_64
~/Development/fpc $ make crossall crossinstall FPC=/usr/bin/fpc NOGDB=1 OS_TARGET=darwin CPU_TARGET=x86_64 \
  INSTALL_PREFIX=~ BINUTILSPREFIX=i686-apple-darwin10- \
  OPT="-gl -gw -godwarfsets -XX -CX -Xd -Fl/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib"

Hello, world! (darwin-x86_64)

~/Development/Hello $ fpc -Tdarwin -Px86_64 hello.pas
Free Pascal Compiler version 3.1.1 [2015/05/29] for x86_64
Copyright (c) 1993-2015 by Florian Klaempfl and others
Target OS: Darwin for x86_64
Compiling hello.pas
Assembling (pipe) hello.s
Linking hello
5 lines compiled, 0.1 sec

Lazarus

Get latest Lazarus

~/Development $ svn checkout http://svn.freepascal.org/svn/lazarus/trunk lazarus

Build LCL

Build LCL for Windows native and GTK2, OSX Carbon (32-bit), OSX Cocoa (64-bit), Linux GTK2:
~/Development/lazarus $ make distclean registration lazutils lcl OS_TARGET=win32 CPU_TARGET=i386 LCL_PLATFORM=win32
~/Development/lazarus $ make distclean registration lazutils lcl OS_TARGET=win32 CPU_TARGET=i386 LCL_PLATFORM=gtk2
~/Development/lazarus $ make distclean registration lazutils lcl OS_TARGET=win64 CPU_TARGET=x86_64 \
  LCL_PLATFORM=win32
~/Development/lazarus $ make distclean registration lazutils lcl OS_TARGET=win64 CPU_TARGET=x86_64 \
  LCL_PLATFORM=gtk2
~/Development/lazarus $ make distclean registration lazutils lcl OS_TARGET=darwin CPU_TARGET=i386 \
  LCL_PLATFORM=carbon
~/Development/lazarus $ make distclean registration lazutils lcl OS_TARGET=darwin CPU_TARGET=x86_64 \
  LCL_PLATFORM=cocoa
~/Development/lazarus $ make distclean registration lazutils lcl OS_TARGET=linux CPU_TARGET=i386 LCL_PLATFORM=gtk2
~/Development/lazarus $ make distclean all OS_TARGET=linux CPU_TARGET=x86_64 LCL_PLATFORM=gtk2
~/Development/lazarus $ ./lazbuild --build-ide=
The last two commands above will fully build LCL and the Lazarus IDE.

Updating

I'm using the following script to update both fpc and Lazarus to the latest trunk and rebuild everything:
#!/bin/bash

rm -rf ~/lib/fpc/3.1.1/~units
mv ~/lib/fpc/3.1.1/units ~/lib/fpc/3.1.1/~units
cd ~/Development/fpc
make distclean > /dev/null
cd ~/Development/lazarus
make distclean > /dev/null

cd ~/Development
svn info fpc
svn update fpc

svn info lazarus
svn update lazarus

cd ~/Development/fpc

echo "**** FreePascal Windows 32-bit begin ****"
make distclean OS_TARGET=win32 CPU_TARGET=i386 > /dev/null
make all crossinstall FPC=/usr/bin/fpc NOGDB=1 OS_TARGET=win32 CPU_TARGET=i386 INSTALL_PREFIX=~
echo "**** FreePascal Windows 32-bit end ****"
echo
echo "**** FreePascal Windows 64-bit begin ****"
make distclean OS_TARGET=win64 CPU_TARGET=x86_64 > /dev/null
make all crossinstall FPC=/usr/bin/fpc NOGDB=1 OS_TARGET=win64 CPU_TARGET=x86_64 INSTALL_PREFIX=~
echo "**** FreePascal Windows 64-bit end ****"
echo
echo "**** FreePascal MacOSX 32-bit begin ****"
make distclean OS_TARGET=darwin CPU_TARGET=i386 > /dev/null
make crossall crossinstall FPC=/usr/bin/fpc NOGDB=1 OS_TARGET=darwin CPU_TARGET=i386 INSTALL_PREFIX=~ \
  BINUTILSPREFIX=i686-apple-darwin10- \
  OPT="-gl -gw -godwarfsets -XX -CX -Xd -Fl/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib"
echo "**** FreePascal MacOSX 32-bit end ****"
echo
echo "**** FreePascal MacOSX 64-bit begin ****"
make distclean OS_TARGET=darwin CPU_TARGET=x86_64 > /dev/null
make crossall crossinstall FPC=/usr/bin/fpc NOGDB=1 OS_TARGET=darwin CPU_TARGET=x86_64 INSTALL_PREFIX=~ \
  BINUTILSPREFIX=i686-apple-darwin10- \
  OPT="-gl -gw -godwarfsets -XX -CX -Xd -Fl/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib"
echo "**** FreePascal MacOSX 64-bit end ****"
echo
echo "**** FreePascal Linux 32-bit begin ****"
make distclean OS_TARGET=linux CPU_TARGET=i386 > /dev/null
make all crossinstall FPC=/usr/bin/fpc NOGDB=1 OS_TARGET=linux CPU_TARGET=i386 INSTALL_PREFIX=~
echo "**** FreePascal Linux 32-bit end ****"
echo
echo "**** FreePascal Linux 64-bit begin ****"
make distclean OS_TARGET=linux CPU_TARGET=x86_64 > /dev/null
make all install FPC=/usr/bin/fpc OPT=-gl OS_TARGET=linux CPU_TARGET=x86_64 INSTALL_PREFIX=~
echo "**** FreePascal Linux 64-bit end ****"
echo
cd ~/Development/lazarus

echo "**** LCL Windows 32-bit native begin ****"
make distclean registration lazutils lcl OS_TARGET=win32 CPU_TARGET=i386 LCL_PLATFORM=win32
echo "**** LCL Windows 32-bit native end ****"
echo
echo "**** LCL Windows 32-bit GTK2 begin ****"
make distclean registration lazutils lcl OS_TARGET=win32 CPU_TARGET=i386 LCL_PLATFORM=gtk2
echo "**** LCL Windows 32-bit GTK2 end ****"
echo
echo "**** LCL Windows 64-bit native begin ****"
make distclean registration lazutils lcl OS_TARGET=win64 CPU_TARGET=x86_64 LCL_PLATFORM=win32
echo "**** LCL Windows 64-bit native end ****"
echo
echo "**** LCL Windows 64-bit GTK2 begin ****"
make distclean registration lazutils lcl OS_TARGET=win64 CPU_TARGET=x86_64 LCL_PLATFORM=gtk2
echo "**** LCL Windows 64-bit GTK2 end ****"
echo
echo "**** LCL MacOSX 32-bit Carbon begin ****"
make distclean registration lazutils lcl OS_TARGET=darwin CPU_TARGET=i386 LCL_PLATFORM=carbon
echo "**** LCL MacOSX 32-bit Carbon end ****"
echo
echo "**** LCL MacOSX 64-bit Cocoa begin ****"
make distclean registration lazutils lcl OS_TARGET=darwin CPU_TARGET=x86_64 LCL_PLATFORM=cocoa
echo "**** LCL MacOSX 64-bit Cocoa end ****"
echo
echo "**** LCL Linux 32-bit GTK2 begin ****"
make distclean registration lazutils lcl OS_TARGET=linux CPU_TARGET=i386 LCL_PLATFORM=gtk2
echo "**** LCL Linux 32-bit GTK2 end ****"
echo
echo "**** Lazarus Linux 64-bit GTK2 begin ****"
make distclean all OS_TARGET=linux CPU_TARGET=x86_64 LCL_PLATFORM=gtk2
./lazbuild --build-ide=
echo "**** Lazarus Linux 64-bit GTK2 end ****"
echo

cd ~/Development/fpc
USEZIP=0 USETAR=bz2 make zipsourceinstall
mv fpc.source.tar.bz2 ..
cd ~/
tar --create --bzip2 --recursion bin > ~/Development/bin.tar.bz2
tar --create --bzip2 --recursion lib > ~/Development/lib.tar.bz2
cd ~/Development/lazarus
tar --create --bzip2 --recursion lcl/units > ~/Development/lcl.tar.bz2
tar --create --bzip2 --recursion components/lazutils/lib > ~/Development/lazutils.tar.bz2
tar --create --bzip2 --recursion packager/units > ~/Development/packager.tar.bz2

cd ~/Development

Hello, world! (with UI)

Now you can use the Lazarus IDE to create and cross-compile your projects.

Project Options

Hello from Linux

Hello from Windows

Hello from OSX

About Lazarus

Tuesday, May 26, 2015

Delphi Code Monkey: 20 Years as a Delphi Developer

Delphi Code Monkey: 20 Years as a Delphi Developer

Warren Postma's TDUG talk on YouTube. Highly recommended, there's a lot of insight both looking back and forward.

I happen to have the same preference for past Delphi IDE versions: 7, 2007 and XE7.

It was nice to see some praise for Subversion integration (based on my delphisvn work).