Sign in Join
Wiki copytemporary

FPMake: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11**FPMake** is a build-system for Pascal code specifically. It can be compared with other build systems like Make, cons, scons, etc.
22
33With FPMake the code is split up into packages. A FPMake-package can contain units, binaries, examples and documentation. Each package can depend on other packages, in which case a package can use the units of it's dependences. FPMake uses two different locations to search for packages, a system-wide (global) and a local location. By default the global location points to the location of the fpc-installation, while the local location is user-specific.
44
55Some parts of fpc itself are compiled using FPMake. (The packages fastcgi and fcl-web in fpc 2.6 and all packages, utilities and the ide in fpc 2.7 and up)
66
77The packages-manager [[fppkg]] can be used to manage the FPMake packages and to install them from a remote repository.
88
99## How does it work
1010
1111FPMake works with Pascal-applications called fpmake, of which each can compile and install one or more FPMake-packages. All settings, location of the sources and instructions are defined inside the source of this fpmake-executable. This source-file is normally saved with the name fpmake.pp. The fpmake.pp is compiled into the fpmake-executable, and this executable can build and install the final packages.
1212
1313## Building FPMake packages
1414
1515The easiest is to use [[fppkg]] to build a FPMake package. But it can also be done manually. Locate the sources of the package you want to install and the fpmake.pp file. Now compile the fpmake.pp file:
1616
17-`fpc fpmake.pp`
17+```text
18+fpc fpmake.pp
19+```
1820
1921Typical output looks like:
2022
21-`Free Pascal Compiler version 2.7.1 [2014/11/26] for i386`\
22-`Copyright (c) 1993-2014 by Florian Klaempfl and others`\
23-`Target OS: Darwin for i386`\
24-`Compiling fpmake.pp`\
25-`Assembling (pipe) fpmake.s`\
26-`Linking fpmake`\
27-`203 lines compiled, 3.6 sec`
23+```text
24+Free Pascal Compiler version 2.7.1 [2014/11/26] for i386
25+Copyright (c) 1993-2014 by Florian Klaempfl and others
26+Target OS: Darwin for i386
27+Compiling fpmake.pp
28+Assembling (pipe) fpmake.s
29+Linking fpmake
30+203 lines compiled, 3.6 sec
31+```
2832
2933Now run the new fpmake(.exe)-executable to build the package(s). This example only contains one package.
3034
3135On unices or alike:
3236
33-`./fpmake build --globalunitdir=/usr/local/lib/fpc/2.7.1`
37+```text
38+./fpmake build --globalunitdir=/usr/local/lib/fpc/2.7.1
39+```
3440
3541On Windows or alike:
3642
37-`fpmake.exe build --globalunitdir=c:\pp`
43+```text
44+fpmake.exe build --globalunitdir=c:\pp
45+```
3846
3947Typical output looks like:
4048
41-`Start compiling package fcl-base for target i386-darwin.`\
42-`      Compiling src/ascii85.pp`\
43-`      Compiling src/avl_tree.pp`\
44-`      Compiling src/base64.pp`\
45-`      Compiling src/fpmimetypes.pp`\
46-`[100%] Compiled package fcl-base`
49+```text
50+Start compiling package fcl-base for target i386-darwin.
51+ Compiling src/ascii85.pp
52+ Compiling src/avl_tree.pp
53+ Compiling src/base64.pp
54+ Compiling src/fpmimetypes.pp
55+[100%] Compiled package fcl-base
56+```
4757
4858The --globalunitdir parameter gives the location of the already installed global packages. This way FPMake can find the packages that this package depends on. When there is a second location where packages are installed, in addition the --localunitdir parameter can be used.
4959
5060If you want to know which path you have to use for the --global(local)unitdir parameter, it's the directory which contains a directory called 'fpmkinst'.
5161
5262To remove all files generated during the build and to be able to do a 'clean' build, perform a clean.
5363
5464On unices or alike:
5565
56-`./fpmake clean`
66+```text
67+./fpmake clean
68+```
5769
5870On Windows or alike:
5971
60-`fpmake.exe clean`
72+```text
73+fpmake.exe clean
74+```
6175
6276Use the -h parameter to get an overview of all other available commands and options.
6377
6478## Installing FPMake packages
6579
6680Just like building packages, using [[fppkg]] to install FPMake packages is the easiest. But it canbe done manually. First compile the package and then call the fpmake executable to install the package.
6781
6882On unices or alike:
6983
70-`./fpmake install --globalunitdir=/usr/local/lib/fpc/2.7.1 --prefix=/usr/local --baseinstalldir=/usr/local/lib/fpc/2.7.1`
84+```text
85+./fpmake install --globalunitdir=/usr/local/lib/fpc/2.7.1 --prefix=/usr/local --baseinstalldir=/usr/local/lib/fpc/2.7.1
86+```
7187
7288On Windows or alike:
7389
74-`fpmake.exe install --globalunitdir=c:\pp --prefix=c:\pp --baseinstalldir=c:\pp`
90+```text
91+fpmake.exe install --globalunitdir=c:\pp --prefix=c:\pp --baseinstalldir=c:\pp
92+```
7593
7694Typical output looks like:
7795
78-`Installing package fcl-base`\
79-`Installation package fcl-base for target i386-darwin succeeded`
96+```text
97+Installing package fcl-base
98+Installation package fcl-base for target i386-darwin succeeded
99+```
80100
81101The globalunitdir contains the location where to look for packages that the FPMake package can depend on, just like when building the package. The baseinstalldir is the location where the package should be installed to. In general this is the same path as is used for the global- or local-unitdir. Some packages also installs files outside of the baseinstalldir. like configuration files. These packages most often also need a prefix, so providing one is advisable.
82102
83103## How to create FPMake-packages
84104
85105### Simple example fpmake.pp
86106
87107``` pascal
88108 program fpmake;
89109
90110 uses fpmkunit;
91111
92112 Var
93113 P: TPackage;
94114 T: TTarget;
95115
96116 begin
97117 With Installer do
98118 begin
99119 P := AddPackage('my-nice-program');
100120 P.OSes := [win32,openbsd,netbsd,freebsd,darwin,linux];
101121 T := P.Targets.AddUnit('myunit');
102122 T.ResourceStrings := True;
103123 T := P.Targets.AddUnit('myprogram');
104124 T.Dependencies.Add('myunit');
105125 Run;
106126 end;
107127 end.
108128```
109129
110130### More complex example fpmake.pp
111131
112132``` pascal
113133 program fpmake;
114134
115135 uses fpmkunit;
116136
117137 type TWidgetSet = (wsGDI, wsX, wsCarbon);
118138
119139 var WidgetSet : TWidgetSet;
120140 P : TPackage;
121141
122142 procedure DetermineWidgetSet;
123143 Var
124144 I : Integer;
125145 begin
126146 if Defaults.OS in AllWindowsOSes then
127147 WidgetSet := wsGDI else
128148 if Defaults.OS = MacOS then
129149 WidgetSet := wsCarbon else
130150 if Defaults.OS in AllUnixOSes then
131151 Widgetset := wsX;
132152
133153 // Check paramstr() to see if the widgetset was overriden on the commandline;
134154 For I := 1 to ParamCount do
135155 If ParamStr(i) = '--widgetset=X' then
136156 WidgetSet := wsX;
137157 end;
138158
139159 begin
140160 DetermineWidgetSet;
141161 With Installer do
142162 begin
143163 // ...
144164 Case WidgetSet of
145165 wsGDI : P.UnitPath.Add('corelib/gdi');
146166 wsX : P.UnitPath.Add('corelib/x11');
147167 // etc.
148168 end;
149169 // ...
150170 Run;
151171 end;
152172 end.
153173```
154174
155175### Changing Working Directory
156176
157177If working with units in a subfolder relative to ./fpmake, then "Directory" can be changed.
158178
159179``` pascal
160180 With Installer do
161181 begin
162182 ...
163183 Directory:='some/subdir';
164184 T:= Targets.AddUnit('unitinfolder');
165185 ...
166186 end;
167187```
168188
169189### Adding directories
170190
171191You can add directories with the unit path:
172192
173193``` pascal
174194 Case Defaults.OS of
175195 Win32, Win64:
176196 begin
177197 T.UnitPath.Add('corelib/gdi');
178198 T.Dependencies.Add('gfx_gdi');
179199 end;
180200 Linux:
181201 begin
182202 T.UnitPath.Add('corelib/x11');
183203 T.Dependencies.Add('gfx_x11');
184204 end;
185205 end;
186206```
187207
188208Often, it's more comfortable to use set constants like AllWindowsOSes, AllUnixOSes instead of specific OS names.
189209
190210### Appending Compiler Options
191211
192212Additional custom compiler options (i.e. compiler command line parameters) can be appended by using TTarget.Options, TPackage.Options, or Defaults.Options.
193213
194214``` pascal
195215 var T : TTarget;
196216 ...
197217 T.Options.Append('-dSOMEDEFINE');
198218 T.Options.Append('-xyzAnythingYouNeed');
199219```
200220
201221Or
202222
203223``` pascal
204224 var P : TPackage;
205225 ...
206226 P.Options.Append('-dSOMEDEFINE');
207227```
208228
209229Or
210230
211231``` pascal
212232 Defaults.Options.Append('-dSOMEDEFINE');
213233```
214234
215235**Note**: Before FPC 2.4.0, Options property was a simple string, and it seems it supported passing only one parameter to the compiler. Since FPC 2.4.0 (more precisely, since svn revision 13223) Options is a TStrings instance, so it's much more flexible. This also means that you should use \$ifdefs if you want to use Options and want your fpmake.pp be compatible with both FPC \< 2.4.0 and \>= 2.4.0.
216236
217237## Common error messages
218238
219239A few common error messages are explained here
220240
221241### Unknown target for unit "\[unitname\]" in dependencies for \[targetname\] in package \[packagename\]
222242
223243This indicates a problem in the fpmake.pp file. There is a dependency on a unit, added using Target.Dependencies.AddUnit('unitname'). But there is no corresponding target added to the package with the same unitname.
224244
225245In other words: for every dependency on a unit, there must be a corresponding target within the same package. When there is a dependency on a unit in another package, add a dependency on that package. A dependency on a single file within a different package will not work.
226246
227247Also note that the unit name has to be without the extension of the corresponding file. (Target.Dependencies.AddUnit('unitnams.pas') will not work, while Targets.Addunit requires the extension to be present)
228248
229249### Could not find unit directory for dependency package "rtl"
230250
231251In general the fpmake system scans the places typically used for fpc installations. In the case that fpmake doesn't find the FPC directory, you'll get the above mentioned error. In such case, set the FPCDIR environment variable to the base dir of the FPC installation, e.g.:
232252
233-` export FPCDIR=~/src/lib/fpc/2.6.4`
253+```text
254+ export FPCDIR=~/src/lib/fpc/2.6.4
255+```
234256
235257or
236258
237-` set FPCDIR=C:\lazarus\fpc\2.6.4\`
259+```text
260+ set FPCDIR=C:\lazarus\fpc\2.6.4\
261+```
238262
239263This can also be useful if you have to disambiguate over multiple FPC installations.
240264
241265---
242266*From the Free Pascal wiki, page "FPMake", as it stood on 2020-02-16 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history