-
Notifications
You must be signed in to change notification settings - Fork 65
/
CMThirdpartyLibrary.class.st
327 lines (248 loc) · 7.93 KB
/
CMThirdpartyLibrary.class.st
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
"
My subclasses describing a configuration/settings necessary to build some third-party library used by VM
or by one of it's plugins.
We cannot use cmake configuration for those libraries, since most of them having own
configuration/make scripts which build that library.
I serve as a convenience layer for building those libraries and connecting them with cmake configuration,
as well as provide necessary information, what output file(s) should be bundled with virtual machine.
"
Class {
#name : #CMThirdpartyLibrary,
#superclass : #Object,
#instVars : [
'gen',
'vmGen',
'configurationFlags'
],
#category : #'CMakeVMMaker-Libs'
}
{ #category : #accessing }
CMThirdpartyLibrary class >> canonicalName [
"answer the library canonical name, like
'freetype2'
or 'cairo'
etc.
Note , this method is used to find the corresponding library
from all subclasses of CMThirdpartyLibrary
"
^ self subclassResponsibility
]
{ #category : #'instance creation' }
CMThirdpartyLibrary class >> named: aName config: aCPlatformConfig [
^ (self allSubclasses detect: [:cls |
cls canonicalName = aName and: [ cls supports: aCPlatformConfig ] ])
new
]
{ #category : #accessing }
CMThirdpartyLibrary class >> platformName [
^nil
]
{ #category : #testing }
CMThirdpartyLibrary class >> supports: aConfig [
"default implementation"
^ self platformName = aConfig platformName
]
{ #category : #accessing }
CMThirdpartyLibrary >> archiveFileName [
^ self downloadURL asUrl fileName
]
{ #category : #'package properties' }
CMThirdpartyLibrary >> archiveMD5Sum [
"answer the MD5 checksum (in string) for downloaded library archive
(to check that downloaded file is not corrupt).
You can take this sum by issuing:
md5 filename
from command line
"
^ self subclassResponsibility
]
{ #category : #'generating actions' }
CMThirdpartyLibrary >> build [
self subclassResponsibility
]
{ #category : #'package properties' }
CMThirdpartyLibrary >> buildTarget [
^ self canonicalName
]
{ #category : #'package properties' }
CMThirdpartyLibrary >> canonicalName [
"answer the library canonical name, like
'freetype2'
or 'cairo'
etc"
^ self class canonicalName
]
{ #category : #settings }
CMThirdpartyLibrary >> configurationFlags [
^(configurationFlags
ifNil: [ self defaultConfigurationFlags ])
reduce: [ :a :b | a, ' ', b]
]
{ #category : #settings }
CMThirdpartyLibrary >> configurationFlags: aCollection [
configurationFlags := aCollection
]
{ #category : #'generating actions' }
CMThirdpartyLibrary >> copy: src to: dest [
| str |
str := 'add_custom_command( OUTPUT "{2}"
COMMAND cp "{1}" "{2}"
DEPENDS "{1}"
)' format: {src. dest }.
gen puts: str
]
{ #category : #'generating actions' }
CMThirdpartyLibrary >> copyArtefacts [
self subclassResponsibility
]
{ #category : #settings }
CMThirdpartyLibrary >> defaultConfigurationFlags [
^#(
'CFLAGS=''-arch i386'''
'LDFLAGS=''-arch i386''')
]
{ #category : #'generating actions' }
CMThirdpartyLibrary >> defineAsTarget [
self subclassResponsibility
]
{ #category : #'generating actions' }
CMThirdpartyLibrary >> defineGlobalTargets [
self subclassResponsibility
]
{ #category : #'package properties' }
CMThirdpartyLibrary >> dependencies [
^ #()
]
{ #category : #'generating actions' }
CMThirdpartyLibrary >> download [
"Produce output to download library archive.
By default, we use .tgz extension.. since it is most often used by OSS.
Note, that we check if file is already present, to not download it every time
we build"
gen puts:
'if (NOT EXISTS "${workDir}/${archiveFileName}")
Message("Downloading ',self fileServerURL,'${archiveFileName}")
FILE(DOWNLOAD
', self fileServerURL , self archiveFileName ,'
"${workDir}/${archiveFileName}"
STATUS downloadStatus
SHOW_PROGRESS
)
LIST(GET downloadStatus 0 downloadError)
if (NOT downloadError EQUAL 0)
Message("File is missing on file server (', self fileServerURL,'), downloading from official repository...")
FILE(DOWNLOAD
${url}
"${workDir}/${archiveFileName}"
STATUS downloadStatus
SHOW_PROGRESS
EXPECTED_MD5 ${md5sum}
)
LIST(GET downloadStatus 0 downloadError)
endif ()
if (NOT downloadError EQUAL 0)
message(FATAL_ERROR "Cannot find/download the source file from:" ${url})
endif ()
endif ()
'
]
{ #category : #'package properties' }
CMThirdpartyLibrary >> downloadURL [
"answer the url where given library can be downloaded from"
^ self subclassResponsibility
]
{ #category : #settings }
CMThirdpartyLibrary >> fileServerURL [
"Base url to file server where all external libs sources stored"
^'http://files.pharo.org/vm/src/lib/'
]
{ #category : #'generating cmake file' }
CMThirdpartyLibrary >> generate [
gen message: 'Configuring thirdparty package: ', self canonicalName.
self
setVariables;
download;
unpack;
build;
copyArtefacts;
defineAsTarget.
]
{ #category : #'generating cmake file' }
CMThirdpartyLibrary >> generateFor: aVMGenerator [
| libDir stream contents |
vmGen := aVMGenerator.
gen := CMakeGenerator new
output: (String new writeStream).
libDir := (aVMGenerator thirdpartyDir / self canonicalName) ensureDirectory.
stream := String new writeStream.
self generate.
stream nextPutAll: (vmGen config fixLineEndsOf: gen output contents).
contents := stream contents.
(self isFile: (libDir asFileReference / gen outputFileName) fullName hasContents: contents) ifFalse: [
"contents changed, update the file. Because fucking cmake will force rebuild everything if we change its modification date
without changing its contents"
(FileStream forceNewFileNamed: (libDir asFileReference / gen outputFileName)) nextPutAll: contents; close.
].
vmGen addSubdirectory: vmGen thirdpartyDirName , '/' , self canonicalName.
self defineGlobalTargets.
]
{ #category : #'generating cmake file' }
CMThirdpartyLibrary >> isFile: aFileName hasContents: aString [
| newContents old |
newContents := false.
old := FileStream oldFileOrNoneNamed: aFileName.
old ifNil: [ ^ false ].
^ [ old contents = aString ] ensure: [ old close ]
]
{ #category : #'package properties' }
CMThirdpartyLibrary >> libraryFileName [
"answer the built library file name"
self subclassResponsibility
]
{ #category : #'generating actions' }
CMThirdpartyLibrary >> setVariables [
gen
set: #libName toString: self canonicalName;
set: #workDir toString: '${thirdpartyDir}/${libName}';
set: #unpackedDirName toString: self unpackedDirName;
set: #libSourcesDir toString: '${workDir}/${unpackedDirName}';
set: #url toString: self downloadURL;
set: #md5sum toString: self archiveMD5Sum;
set: #archiveFileName toString: self archiveFileName;
set: #installPrefix toString: '${thirdpartyDir}/out'.
]
{ #category : #exports }
CMThirdpartyLibrary >> targetForLinking [
"Answer a target or path to library to link with, which can be used by
external plugins or VM module"
^ '${externalModulesDir}/', self libraryFileName
]
{ #category : #'generating actions' }
CMThirdpartyLibrary >> unpack [
"produce commands for unpacking the library archive.
the output of this command should use a directory
${workDir}/${libName}
where the unpacked library sources will be located.
see #setVariables method for understanding what variables used here
"
gen set: #unpackTarget toString: '${libSourcesDir}/touch.cmake'.
gen puts:
'add_custom_command(OUTPUT "${unpackTarget}"
COMMAND tar -xzf "${archiveFileName}"
COMMAND touch "${unpackTarget}"
COMMENT "Unpacking ${libName} ... "
)
'.
]
{ #category : #'package properties' }
CMThirdpartyLibrary >> unpackedDirName [
"answer the directory name, which is created after unpacking
downloaded archive i.e.
the archive downloaded from
http://ftp.igh.cnrs.fr/pub/nongnu/freetype/freetype-2.4.9.tar.gz
if untarred, will create
freetype-2.4.9
subdirectory. But since there is no conventions, it could be anything,
so we should specify it here, so build system will know where to look for unpacked files"
^ self subclassResponsibility
]