-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathetoile.make
352 lines (307 loc) · 13.5 KB
/
etoile.make
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
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
#
# Etoile Makefile Extensions (dependency support, test support, etc.)
#
# NOTE: In this file, 'module' and 'project' words have exactly the same
# meaning.
# This variable can be used to check in a GNUmakefile whether a module is
# built as a part of Etoile or not.
export etoile = yes
### Linking Variables ###
# You can link all the core frameworks with the single flag ETOILE_CORE_LIBS and
# Smalltalk dependencies with SMALLTALK_LIBS. .
# Pass these flags to xxx_LIBRARIES_DEPEND_UPON for a framework/library, and to
# xxx_GUI_LIBS, xxx_TOOL_LIBS or xxx_BUNDLE_LIBS for other targets (applications,
# tools and bundles).
ETOILE_FOUNDATION_LIBS = -lEtoileFoundation -lEtoileThread -lEtoileXML
COREOBJECT_LIBS = -lCoreObject -lEtoileSerialize
ETOILE_UI_LIBS = -lEtoileUI
export ETOILE_CORE_LIBS = $(ETOILE_FOUNDATION_LIBS) $(COREOBJECT_LIBS) $(ETOILE_UI_LIBS)
export SMALLTALK_LIBS = -lEtoileFoundation -lLanguageKit -lSmalltalkSupport
### Installation Control ###
ifeq ($(ETOILE_CORE_MODULE), YES)
export GNUSTEP_INSTALLATION_DOMAIN = SYSTEM
endif
### Internal Dependency Handling ###
# CURDIR is the path where make is run, with gnustep-make the value changes in
# subdirectories since each 'submake' is a 'normal' make, sandboxed and not
# run recursively from the initial directory.
#
# PROJECT_DIR is the path where make is invoked, the first directory where
# make is run, this variable allows to keep a reference to the initial
# directory taking in account the previous comment about CURDIR.
#
# PROJECT_NAME is the name of the module to be built, by default the last path
# path component of PROJECT_DIR is used as name. It must match the module
# target variable like FRAMEWORK_NAME, APP_NAME etc. If you use a target name
# which is unrelated to the last path component of PROJECT_DIR, you must
# redefine this variable in your GNUmakefile.
#
# PRINT_PROJECT_NAME can be YES or NO. When the value is set to NO, make will
# ouput a new line but not 'Build Project: $(PROJECT_NAME)'. It is usually set
# to NO in any subproject that includes etoile.make.
#
# PWD or ./ is the path where the current makefile is located (for
# etoile.make, this is always Etoile/)
export PROJECT_DIR ?= $(CURDIR)
PROJECT_NAME ?= $(notdir $(PROJECT_DIR))
# We search etoile.make path in the repository... because Make doesn't provide
# any variables to obtain included makefile paths.
prefix = $(if $1,\
$(if $(wildcard $1/etoile.make),\
$(dir \
$(wildcard $1/etoile.make)),\
$(call prefix,\
$(patsubst %/$(notdir $1),%, $1))),\
$(warning No makefile etoile.make found in the repository tree.))
PREFIX = $(patsubst %/,%,$(call prefix,$(PROJECT_DIR)))
BUILD_DIR = $(PREFIX)/Build
# We create a temporary header directory to support #import <PROJECT_NAME/header.h>
# from within the library/framework project itself.
#
# If the project contains subprojects, the headers are all collected in the
# same directory in the main project.
#
# For embedded projects such as EtoileFoundation/EtoileXML, resetting
# PROJECT_DIR is enough to create a collected header directory just for the
# embedded project e.g. EtoileFoundation/EtoileXML/EtoileXML
export COLLECTED_HEADER_DIR = $(PROJECT_DIR)/$(PROJECT_NAME)
define create-local-header-dir
if [ ! -d $(COLLECTED_HEADER_DIR) ]; then \
if [ -n "$(LIBRARY_NAME)" -o -n "$(FRAMEWORK_NAME)" ]; then \
mkdir $(COLLECTED_HEADER_DIR); \
fi; \
fi;
endef
define collect-headers-in-subdirs
if [ -d $(COLLECTED_HEADER_DIR) ]; then \
for headerDir in "." "Headers" $(OTHER_HEADER_DIRS); do \
for header in `ls -1 $$headerDir/*.h 2> /dev/null`; do \
if [ ! -e $(COLLECTED_HEADER_DIR)/`basename $$header` ]; then \
ln -s $(CURDIR)/$$header $(COLLECTED_HEADER_DIR); \
fi; \
done; \
done; \
fi;
endef
before-all::
$(ECHO_NOTHING) \
echo ""; \
if [ "$(PRINT_PROJECT_NAME)" != "NO" ]; then \
echo "Build Project: $(PROJECT_NAME)"; \
echo ""; \
fi; \
$(create-local-header-dir) \
$(collect-headers-in-subdirs) \
if [ ! -d $(BUILD_DIR) ]; then \
mkdir $(BUILD_DIR); \
fi; \
$(END_ECHO)
define check-variables
if [ -z $(PROJECT_DIR) ]; then \
echo "Dependency export failed: PROJECT_DIR is not set"; \
echo ""; \
exit; \
fi; \
if [ -z $(PROJECT_NAME) ]; then \
echo "Dependency export failed: PROJECT_NAME is not set"; \
echo ""; \
exit; \
fi; \
if [ -z $(PREFIX) ]; then \
echo "Dependency export failed: PREFIX is not set"; \
echo ""; \
exit; \
fi;
endef
# For a framework target, we create a symbolic link inside Build for the
# framewrok itself inside but also a symbolic link libFrameworkName.so pointing on
# frameworkName.framework/Versions/Current/libFrameworkName.so
# TODO: Would be nice if gnustep-make could discover the library file by itself.
#
# NOTE: sh seems to have trouble to interpolate $() unlike ${} in the following case:
# for libfile in ${PROJECT_DIR}/${PROJECT_NAME}.framework/Versions/Current/lib${PROJECT_NAME}${SHARED_LIBEXT}*; do
# $(LN_S) -f $$libfile $(BUILD_DIR);
# done
define export-framework
if [ -d $(PROJECT_DIR)/$(PROJECT_NAME).framework ]; then \
exported="yes"; \
$(LN_S) -f $(PROJECT_DIR)/$(PROJECT_NAME).framework $(BUILD_DIR)/$(PROJECT_NAME).framework; \
$(LN_S) -f ${PROJECT_DIR}/${PROJECT_NAME}.framework/Versions/Current/${GNUSTEP_TARGET_LDIR}/lib${PROJECT_NAME}${SHARED_LIBEXT}* $(BUILD_DIR); \
fi;
endef
define export-library-files
if [ -f $(PROJECT_DIR)/obj/${GNUSTEP_TARGET_LDIR}/lib$(PROJECT_NAME)$(SHARED_LIBEXT) ]; then \
exported="yes"; \
$(LN_S) -f ${PROJECT_DIR}/obj/${GNUSTEP_TARGET_LDIR}/lib${PROJECT_NAME}${SHARED_LIBEXT}* $(BUILD_DIR); \
fi; \
\
if [ -f $(PROJECT_DIR)/Source/obj/${GNUSTEP_TARGET_LDIR}/lib$(PROJECT_NAME)$(SHARED_LIBEXT) ]; then \
exported="yes"; \
$(LN_S) -f ${PROJECT_DIR}/Source/obj/${GNUSTEP_TARGET_LDIR}/lib${PROJECT_NAME}${SHARED_LIBEXT}* $(BUILD_DIR); \
fi;
endef
# We use 'exported' variable in the after-all script to remember we detected a
# framework or a library in a module and we have to export the related headers.
define export-headers
if [ "$${exported}" = "yes" ]; then \
if [ -d $(COLLECTED_HEADER_DIR) -a ! -L $(BUILD_DIR)/$(PROJECT_NAME) ]; then \
$(LN_S) $(COLLECTED_HEADER_DIR) $(BUILD_DIR)/$(PROJECT_NAME); \
elif [ ! -L $(BUILD_DIR)/$(PROJECT_NAME) ]; then \
$(LN_S) $(PROJECT_DIR) $(BUILD_DIR)/$(PROJECT_NAME); \
fi; \
fi;
endef
# To debug, insert the next line close to the beginning of after-all.
#echo "etoile.make: PROJECT_DIR $(PROJECT_DIR) PROJECT_NAME $(PROJECT_NAME) BUILD_DIR $(BUILD_DIR)"; \
# For debug, insert the next line close to the end of after-all.
#echo "$(PROJECT_DIR) $(BUILD_DIR) $(PROJECT_NAME)"; \
#
# NOTE: Don't put these statements commented out directly in the code because
# it could make the build fails on some platforms as explained in bug report #8484
after-all::
$(ECHO_NOTHING) \
$(check-variables) \
$(export-framework) \
$(export-library-files) \
$(export-headers) \
$(END_ECHO)
define remove-local-header-dir
if [ -L $(COLLECTED_HEADER_DIR) ]; then \
rm -f $(COLLECTED_HEADER_DIR); \
elif [ -d $(COLLECTED_HEADER_DIR) ]; then \
rm -f $(COLLECTED_HEADER_DIR)/*.h; \
rmdir $(COLLECTED_HEADER_DIR); \
fi;
endef
define remove-exported-headers
if [ -L $(BUILD_DIR)/$(PROJECT_NAME) ]; then \
rm -f $(BUILD_DIR)/$(PROJECT_NAME); \
removed="yes"; \
fi;
endef
define remove-exported-library-files
if [ -L $(BUILD_DIR)/lib$(PROJECT_NAME)$(SHARED_LIBEXT) ]; then \
rm -f $(BUILD_DIR)/lib$(PROJECT_NAME)$(SHARED_LIBEXT)*; \
removed="yes"; \
fi;
endef
define remove-exported-framework
if [ -L $(BUILD_DIR)/$(PROJECT_NAME).framework ]; then \
rm -f $(BUILD_DIR)/$(PROJECT_NAME).framework; \
removed="yes"; \
fi;
endef
after-clean::
$(ECHO_NOTHING) \
echo ""; \
$(check-variables) \
$(remove-local-header-dir) \
$(remove-exported-headers) \
$(remove-exported-library-files) \
$(remove-exported-framework) \
if [ "$${removed}" = "yes" ]; then \
echo " Removed $(PROJECT_NAME) dependency export"; \
echo ""; \
fi; \
$(END_ECHO)
after-distclean:: after-clean
TEST_BUNDLE_NAME = $(PROJECT_NAME).bundle
check::
$(ECHO_NOTHING) \
if [ "$${compile}" != "no" ]; then \
${MAKE} test=yes; \
fi; \
if [ -d $(PROJECT_DIR)/$(TEST_BUNDLE_NAME) ]; then \
ukrun -q $(TEST_BUNDLE_NAME); \
if [ $$? -ne 0 ]; then \
echo "\n --- TESTING FAILED FOR $(PROJECT_NAME) --- \n"; \
fi; \
fi; \
$(END_ECHO)
### Default Variable Values For Conveniency ###
# You can overidde any variable values defined by below by resetting the value
# in the GNUmakefile.preamble of your module. For example:
# unexport ADDITIONAL_INCLUDE_DIRS =
# If you don't put 'unexport' in front of the variable name, the variable will
# be reset but still exported to submake instances (this is never the case with
# gnustep-make variables, that's why you should include a GNUmakefile.preamble
# in any subdirectories of your module usually).
# If we have dependency, once it's imported we need to include its headers
# located PROJECT_DIR/PROJECT_NAME. This means we have to look in
# PROJECT_DIR since we usually use include directive like
# #import <PROJECT_NAME/header.h>
#
# By default we also look for headers in PROJECT_DIR and PROJECT_DIR/Headers,
# this conveniency avoids to take care of such flags over and over.
export ADDITIONAL_INCLUDE_DIRS += -I$(BUILD_DIR) -I$(PROJECT_DIR) -I$(COLLECTED_HEADER_DIR) -I$(PROJECT_DIR)/Headers
# For Clang, see http://llvm.org/bugs/show_bug.cgi?id=7005
export ADDITIONAL_INCLUDE_DIRS += -I/usr/include/`${CC} -dumpmachine`/
# For libdispatch-objc2, see Dependencies/libdispatch-objc2/INSTALL
export ADDITIONAL_INCLUDE_DIRS += -I$(GNUSTEP_LOCAL_LIBRARIES)/Headers/dispatch
# If we have dependency, we need to link its resulting object file. Well, we
# have to look for a library or a framework most of time.
#
# NOTE: We cannot use $(GNUSTEP_SHARED_OBJ) instead of shared_obj because the
# former variable is relative to the project and could be modified by the
# developer. For example, it's commonly equals to ./shared_obj
export ADDITIONAL_LIB_DIRS += -L$(BUILD_DIR)
# To resolve library files that are linked by other library files, but whose
# symbols aren't referenced by the current project/target and hence not
# explicitly linked.
# For example, if you use EtoileFoundation that links to EtoileXML but you don't
# reference any EtoileXML symbols and doesn't link it. In this last case without
# a custom LD_LIBRARY_PATH or -rpath-link, a warning would be logged:
# /usr/bin/ld: warning: libEtoileXML.so.0, needed by /testEtoile/Build/libEtoileFoundation.so, not found (try using -rpath or -rpath-link)
# If -rpath-link is used, it overrides the search paths for shared libraries, so
# only installed static libraries are visible to the linker, but not the shared
# ones. That's why to allow the linking of shared libraries that are located
# outside of BUILD_DIR, '-rpath-link $(BUILD_DIR)' is not enough and
# LD_LIBRARY_PATH value has to be appended.
# Unlike shared libraries installed in standard locations such as /usr/lib,
# GNUstep libraries doesn't seem to be affected by -rpath-link, not sure why...
# Perhaps because gnustep-make is bypassing it for GNUstep install paths or core
# libraries in one way or another.
# We use LD_LIBRARY_PATH by default, since it is known to work well on various
# platforms.
#export ADDITIONAL_LDFLAGS += -Wl,-rpath-link $(BUILD_DIR):$(LD_LIBRARY_PATH)
export LD_LIBRARY_PATH := $(BUILD_DIR):$(LD_LIBRARY_PATH)
ifeq ($(CC), clang)
export LANG_FLAGS ?= -fobjc-nonfragile-abi -fblocks
endif
#export ERROR_FLAG ?= -Werror
# We pass -Wno-unused parameter for Clang which behaves as if -Wunused-parameter
# was present even when we pass -Wno-unused
export WARNING_FLAGS ?= -Wno-import -Wno-unused-parameter -Wno-unused -Wno-implicit
export ADDITIONAL_OBJCFLAGS += $(LANG_FLAGS) $(ERROR_FLAG) $(WARNING_FLAGS)
# Work around flags unsupported by Clang but still used by gnustep-make
ifeq ($(CC), clang)
# For -fexec-charset
export ADDITIONAL_OBJCFLAGS += -Qunused-arguments
# For -shared-libgcc
export ADDITIONAL_LDFLAGS += -Qunused-arguments
endif
# Ugly hack until gnustep-make is improved to export a variable that lets us know
# which libobjc version we compile against.
# If a libobjc.so.4 (v2) is installed in a path listed below, but you use another
# runtime you can force EtoileFoundation to use an older libobjc by exporting
# the used runtime version in your shell first. e.g.
# export GNU_RUNTIME_VERSION=1 && make clean && make
ifndef GNU_RUNTIME_VERSION
LIBOBJC = libobjc.so.4
GNU_RUNTIME_VERSION = 1
GNU_RUNTIME_VERSION := $(if $(wildcard $(GNUSTEP_SYSTEM_LIBRARIES)/$(GNUSTEP_TARGET_LDIR)/$(LIBOBJC)),2,$(GNU_RUNTIME_VERSION))
GNU_RUNTIME_VERSION := $(if $(wildcard $(GNUSTEP_LOCAL_LIBRARIES)/$(GNUSTEP_TARGET_LDIR)/$(LIBOBJC)),2,$(GNU_RUNTIME_VERSION))
GNU_RUNTIME_VERSION := $(if $(wildcard $(GNUSTEP_USER_LIBRARIES)/Library/Libraries/$(GNUSTEP_TARGET_LDIR)/$(LIBOBJC)),2,$(GNU_RUNTIME_VERSION))
GNU_RUNTIME_VERSION := $(if $(wildcard /usr/lib/$(LIBOBJC)),2,$(GNU_RUNTIME_VERSION))
GNU_RUNTIME_VERSION := $(if $(wildcard /usr/local/lib/$(LIBOBJC)),2,$(GNU_RUNTIME_VERSION))
endif
export GNU_RUNTIME_VERSION
export ADDITIONAL_CPPFLAGS += -DGNU_RUNTIME_VERSION=$(GNU_RUNTIME_VERSION)
# For test bundles, we must link UnitKit
ifeq ($(test), yes)
ifeq ($(FOUNDATION_LIB), apple)
export ADDITIONAL_OBJC_LIBS += -framework UnitKit
else
export ADDITIONAL_OBJC_LIBS += -lUnitKit
endif
endif