forked from idapython/src
-
Notifications
You must be signed in to change notification settings - Fork 0
/
makefile
551 lines (470 loc) · 19.7 KB
/
makefile
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
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
#
# WARNING: Many rules in this file use pattern matching, where 'make'
# first considers rules as simple strings, not paths. Consequently,
# it is necessary that we don't end up with 'some_dir//some_file'.
# Thus, we have to settle for a makefile-wide policy of either:
# - terminating dir paths with '/', in which case we have to write:
# $(SOMEDIR)somefile, or
# - not terminating dir paths with '/', in which case it becomes:
# $(SOMEDIR)/somefile
# In other makefiles sitting in IDA's source tree, we use the first approach,
# but this one demands the second: not only is this more natural for
# non-hexrays people looking at the file, it also allows us to work in
# a more natural manner with other tools (such as the build.py wrapper, that
# uses os.path.join())
#
ifdef __X64__
ifdef __LINUX__
LINUX64=1
endif
endif
ifdef LINUX64
all:
@echo "Not building Python for Linux x64"
else
PROC=python
API_CONTENTS=api_contents.txt
PYDOC_INJECTIONS=pydoc_injections.txt
IDA_INCLUDE=../../include
DIST=$(F)dist
ifdef __NT__
SYSNAME=win
MSRUNTIME=/MD
else
endif
ifdef __LINUX__
SYSNAME=linux
DEFS=-D__LINUX__
PYTHON32_LIBRARY_PATH?=/usr/lib
PYTHON32_LIBRARY_INCLUDE=-L$(PYTHON32_LIBRARY_PATH)
endif
ifdef __BSD__
SYSNAME=bsd
DEFS=-D__BSD__
endif
ifdef __MAC__
SYSNAME=mac
DEFS=-D__MAC__
endif
# O1=idaapi
# __USE_RTTI__=1
DONT_ERASE_LIB=1
include ../plugin.mak
PLUGIN_SCRIPT=
ifdef __LINUX__
OUTDLLOPTS=-Wl,-soname,$(notdir $(BINARY))
else
ifdef __MAC__
OUTDLLOPTS=-Wl,-install_name,@executable_path/plugins/$(notdir $(BINARY))
endif
endif
ST_SWIG=$(F)swig
ifeq ($(OUT_OF_TREE_BUILD),)
ST_SDK=$(F)idasdk
else
ST_SDK=$(IDA_INCLUDE)
endif
ST_PYW=$(F)pywraps
ST_WRAP=$(F)wrappers
ST_PARSED_HEADERS_NOXML=$(F)parsed_notifications
ST_PARSED_HEADERS=$(ST_PARSED_HEADERS_NOXML)/xml
ST_API_CONTENTS=$(F)api_contents.txt.new
ST_PYDOC_INJECTIONS=$(F)pydoc_injections.txt
# output directory for python scripts
DEPLOY_PYDIR=$(R)python
DEPLOY_INIT_PY=$(DEPLOY_PYDIR)/init.py
DEPLOY_IDC_PY=$(DEPLOY_PYDIR)/idc.py
DEPLOY_IDAUTILS_PY=$(DEPLOY_PYDIR)/idautils.py
ifeq ($(OUT_OF_TREE_BUILD),)
TEST_IDC=test_idc
DBLZIP_SCRIPT:=$(abspath ../../ida/build/dblzip.py)
PKGBIN_SCRIPT:=$(abspath ../../ida/build/pkgbin.py)
endif
#
SDK_SOURCES=$(wildcard $(IDA_INCLUDE)/*.h) $(wildcard $(IDA_INCLUDE)/*.hpp)
ifeq ($(OUT_OF_TREE_BUILD),)
ST_SDK_TARGETS=$(SDK_SOURCES:$(IDA_INCLUDE)/%=$(ST_SDK)/%)
else
ST_SDK_TARGETS=$(SDK_SOURCES)
endif
PYTHON_DYNLOAD=$(BIN_PATH)../python/lib/python2.7/lib-dynload
DEPLOY_LIBDIR=$(PYTHON_DYNLOAD)/ida_$(ADRSIZE)
$(DEPLOY_LIBDIR):
-@if [ ! -d "$(DEPLOY_LIBDIR)" ] ; then mkdir -p 2>/dev/null $(DEPLOY_LIBDIR) ; fi
$(DEPLOY_PYDIR):
-@if [ ! -d "$(DEPLOY_PYDIR)" ] ; then mkdir -p 2>/dev/null $(DEPLOY_PYDIR) ; fi
ifdef __NT__
MODULE_SFX=.pyd
else
MODULE_SFX=.so
endif
# We are building 'MODULES_NAMES' from subvars because it appears some versions
# of make do not deal too well with '\'s, and introduce spaces, which later is
# problematic when substituting ' ' for ',' & passing modules list to scripts
MNAMES_0=allins area auto bytes dbg diskio entry enum expr fixup
MNAMES_1=fpro frame funcs gdl graph hexrays ida idaapi idd idp ints
MNAMES_2=kernwin lines loader moves nalt name netnode offset pro queue
MNAMES_3=registry search segment srarea strlist struct typeinf ua xref
MODULES_NAMES=$(MNAMES_0) $(MNAMES_1) $(MNAMES_2) $(MNAMES_3)
MODULES=$(MODULES_NAMES:%=$(F)_ida_%$(MODULE_SFX))
DEPLOYED_MODULES=$(MODULES_NAMES:%=$(DEPLOY_LIBDIR)/_ida_%$(MODULE_SFX))
MODULES_OBJECTS=$(MODULES_NAMES:%=$(F)%$(O))
ALL_ST_SWIG=$(foreach mod,$(MODULES_NAMES),$(ST_SWIG)/$(mod).i)
ALL_ST_WRAP_CPP=$(foreach mod,$(MODULES_NAMES),$(ST_WRAP)/$(mod).cpp)
ALL_ST_WRAP_PY=$(foreach mod,$(MODULES_NAMES),$(ST_WRAP)/ida_$(mod).py)
PYTHON_MODULES=$(MODULES_NAMES:%=$(DEPLOY_PYDIR)/ida_%.py)
ifdef __NT__
MODULE_LINKIDA=
CREATE_IMPLIB=$(RS)lib32.bat
IDAPYTHON_IMPLIB_DEF=$(F)idapython_implib.def
IDAPYTHON_IMPLIB_DEF_IN=tools/idapython_implib.def.in
IDAPYTHON_IMPLIB_PATH=$(F)python.lib
BINARY_LINKOPTS=/def:$(IDAPYTHON_IMPLIB_DEF) /IMPLIB:$(IDAPYTHON_IMPLIB_PATH)
RESFILES=$(IDAPYTHON_IMPLIB_DEF)
else
MODULE_LINKIDA=-L$(R) $(LINKIDA) $(BINARY)
endif
all: objdir pyfiles config $(DEPLOYED_MODULES) $(PYTHON_MODULES) $(ST_API_CONTENTS) $(IDAPYTHON_IMPLIB) $(ST_PYDOC_INJECTIONS) #$(TEST_IDC)
# used python version
PYTHON_VERSION_MAJOR?=2
PYTHON_VERSION_MINOR?=7
# IDAPython version
IDAPYTHON_VERSION_MAJOR=6
IDAPYTHON_VERSION_MINOR=9
IDAPYTHON_VERSION_PATCH=5
PACKAGE_NAME=idapython-$(IDAPYTHON_VERSION_MAJOR).$(IDAPYTHON_VERSION_MINOR).$(IDAPYTHON_VERSION_PATCH)-python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)-$(SYSNAME)
# HIJACK the $(I) variable to point to our staging SDK
I=$(ST_SDK)/
ifdef __CODE_CHECKER__
ADDITIONAL_GOALS:=$(filter-out pyfiles config $(TEST_IDC),$(ADDITIONAL_GOALS))
OBJS:=$(filter-out $(OBJ1),$(OBJS))
endif
ifdef __NT__ # os and compiler specific flags
ifneq ($(UCRT_INCLUDE),)
I_UCRT_INCLUDE=/I$(UCRT_INCLUDE)
endif
PYTHON_ROOT?=c:
PYTHON_DIR=$(PYTHON_ROOT)/python$(PYTHON_VERSION_MAJOR)$(PYTHON_VERSION_MINOR)
IDAPYTHON_CFLAGS=-w -Z7 /EHsc /bigobj /I$(MSVCDIR)Include $(I_UCRT_INCLUDE)
ifdef __X64__
PYTHONLIB=vcx64_python$(PYTHON_VERSION_MAJOR)$(PYTHON_VERSION_MINOR).lib -nodefaultlib:python$(PYTHON_VERSION_MAJOR)$(PYTHON_VERSION_MINOR).lib
else
PYTHONLIB=$(PYTHON_DIR)/libs/python$(PYTHON_VERSION_MAJOR)$(PYTHON_VERSION_MINOR).lib
endif
_SWIGFLAGS=-D__NT__ -DWIN32 -D_USRDLL -I$(PYTHON_DIR)/include
SWIGINCLUDES?= # nothing
# FIXME: Cannot enable the .cfg file ATM, because there's just too many errors if I do.
PLATFORM_CFLAGS=$(_SWIGFLAGS) -UNO_OBSOLETE_FUNCS
else # unix/mac
ifdef __LINUX__
# use the precompiled 2.7
ifeq ($(OUT_OF_TREE_BUILD),)
# assign right away, so it won't be eval'd 10301829 times
PYDIR:=$(shell pwd)/precompiled
PYLIBDIR=$(PYDIR)
# copy these files to IDA's directory
PYLIBFILES:=$(shell find precompiled/lib -type f)
PRECOMPILED_COPY=$(R)$(PYTHONLIBNAME) $(patsubst precompiled/%,$(DEPLOY_PYDIR)/%,$(PYLIBFILES))
else
PYDIR=$(IDAPYTHON_PYTHONHOME)
PYLIBDIR=$(PYDIR)/lib
endif
PYTHON32_INCLUDE:=-I$(PYDIR)/include/python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)
PYTHONLIBNAME=libpython$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR).so.1.0
PYTHONLIB=$(PYLIBDIR)/$(PYTHONLIBNAME) -ldl
else
PYVER=$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)
PYTHON32_INCLUDE:=$(shell python$(PYVER)-config --includes)
PYTHONLIB:=$(shell python$(PYVER)-config --ldflags)
MACDEFINES=-DMACSDKVER=$(MACSDKVER)
endif
IDAPYTHON_CFLAGS=-w -g
PLATFORM_CFLAGS=$(SYS) -g $(PYTHON32_INCLUDE) $(ARCH_CFLAGS) $(PIC) -UNO_OBSOLETE_FUNCS # gcc flags
_SWIGFLAGS=$(DEFS)
SWIGINCLUDES?=-I$(SWIGDIR)share/swig/$(SWIG_VERSION)/python -I$(SWIGDIR)share/swig/$(SWIG_VERSION)
endif
# Apparently that's not needed, but I don't understand why ATM, since doc says:
# ...Then, only modules compiled with SWIG_TYPE_TABLE set to myprojectname
# will share type information. So if your project has three modules, all three
# should be compiled with -DSWIG_TYPE_TABLE=myprojectname, and then these
# three modules will share type information. But any other project's
# types will not interfere or clash with the types in your module.
DEF_TYPE_TABLE=-DSWIG_TYPE_TABLE=idaapi
SWIGFLAGS=$(_SWIGFLAGS) $(SWIGINCLUDES) $(DEF_TYPE_TABLE)
ADDITIONAL_LIBS=$(PYTHONLIB)
PUBTREE_DIR=$(F)/public_tree
.PHONY: pyfiles docs $(TEST_IDC) staging_dirs clean check_python package public_tree
config: $(C)python.cfg
clean:
rm -rf obj/
pyfiles: $(DEPLOY_PYDIR)/idautils.py \
$(DEPLOY_PYDIR)/idc.py \
$(DEPLOY_PYDIR)/init.py \
$(DEPLOY_PYDIR)/idaapi.py
GENHOOKS=tools/genhooks/
_SPACE := $(null) #
_COMMA := ,
$(DEPLOY_INIT_PY): python/init.py | $(DEPLOY_PYDIR)
$(CP) $? $@
$(DEPLOY_IDC_PY): python/idc.py | $(DEPLOY_PYDIR)
$(CP) $? $@
$(DEPLOY_IDAUTILS_PY): python/idautils.py | $(DEPLOY_PYDIR)
$(CP) $? $@
$(DEPLOY_PYDIR)/idaapi.py: python/idaapi.py tools/genidaapi.py | $(DEPLOY_PYDIR)
$(PYTHON) tools/genidaapi.py -i $< -o $@ -m $(subst $(_SPACE),$(_COMMA),$(MODULES_NAMES))
$(DEPLOY_PYDIR)/lib/%: precompiled/lib/%
mkdir -p $(@D)
cp $< $@
@chmod +w $@
$(C)python.cfg: python.cfg
$(CP) $? $@
$(R)$(PYTHONLIBNAME): $(PYDIR)/$(PYTHONLIBNAME)
$(CP) $? $@
# -------------------------------------------------------------------------
# Hooks generation
# http://stackoverflow.com/questions/11032280/specify-doxygen-parameters-through-command-line
GENERATED_HEADERS=$(ST_PARSED_HEADERS)/headers_generated.marker
$(GENERATED_HEADERS): $(I)idp.hpp $(I)dbg.hpp $(I)kernwin.hpp $(GENHOOKS)doxy_gen_notifs.cfg $(ST_SDK_TARGETS)
ifeq ($(OUT_OF_TREE_BUILD),)
@( cat $(GENHOOKS)doxy_gen_notifs.cfg; echo "OUTPUT_DIRECTORY=$(ST_PARSED_HEADERS_NOXML)" ) | $(DOXYGEN_BIN) -
else
(cd $(F) && unzip ../../out_of_tree/parsed_notifications.zip)
endif
@touch $@
#
staging_dirs:
-@if [ ! -d "$(ST_SDK)" ] ; then mkdir -p 2>/dev/null $(ST_SDK) ; fi
-@if [ ! -d "$(ST_SWIG)" ] ; then mkdir -p 2>/dev/null $(ST_SWIG) ; fi
-@if [ ! -d "$(ST_PYW)" ] ; then mkdir -p 2>/dev/null $(ST_PYW) ; fi
-@if [ ! -d "$(ST_WRAP)" ] ; then mkdir -p 2>/dev/null $(ST_WRAP) ; fi
-@if [ ! -d "$(ST_PARSED_HEADERS)" ] ; then mkdir -p 2>/dev/null $(ST_PARSED_HEADERS) ; fi
# -------------------------------------------------------------------------
# obj/.../idasdk/*.h[pp]
#
ifeq ($(OUT_OF_TREE_BUILD),)
$(ST_SDK)/%.h: $(IDA_INCLUDE)/%.h | staging_dirs $(PRECOMPILED_COPY)
$(PYTHON) ../../bin/update_sdk.py -filter-file -input $^ -output $@
$(ST_SDK)/%.hpp: $(IDA_INCLUDE)/%.hpp | staging_dirs $(PRECOMPILED_COPY)
$(PYTHON) ../../bin/update_sdk.py -filter-file -input $^ -output $@
endif
# -------------------------------------------------------------------------
# obj/.../pywraps/*
#
$(ST_PYW)/%.hpp: pywraps/%.hpp | staging_dirs
@$(CP) $^ $@ && chmod +rw $@
$(ST_PYW)/%.py: pywraps/%.py | staging_dirs
@$(CP) $^ $@ && chmod +rw $@
ifneq ($(OUT_OF_TREE_BUILD),)
# envvar HAS_HEXRAYS must have been set by build.py if needed
else
HAS_HEXRAYS=1 # force hexrays bindings
endif
# These require special care, as they will have to be injected w/ hooks -- this
# only happens if we are sitting in the hexrays source tree; when published to
# the outside world, the pywraps must already contain the injected code.
$(ST_PYW)/py_idp.hpp: pywraps/py_idp.hpp \
$(I)idp.hpp \
$(GENHOOKS)genhooks.py \
$(GENHOOKS)recipe_idphooks.py \
$(GENERATED_HEADERS) | staging_dirs $(SDK_SOURCES)
@$(PYTHON) $(GENHOOKS)genhooks.py -i $< -o $@ \
-x $(ST_PARSED_HEADERS)/structprocessor__t.xml -e idp_notify \
-r int -n 0 -m hookgenIDP -q "processor_t::" \
-R $(GENHOOKS)recipe_idphooks.py
$(ST_PYW)/py_idp_idbhooks.hpp: pywraps/py_idp_idbhooks.hpp \
$(I)idp.hpp \
$(GENHOOKS)genhooks.py \
$(GENHOOKS)recipe_idbhooks.py \
$(GENERATED_HEADERS) | staging_dirs $(SDK_SOURCES)
@$(PYTHON) $(GENHOOKS)genhooks.py -i $< -o $@ \
-x $(ST_PARSED_HEADERS)/namespaceidb__event.xml -e event_code_t \
-r int -n 0 -m hookgenIDB -q "idb_event::" \
-R $(GENHOOKS)recipe_idbhooks.py
$(ST_PYW)/py_dbg.hpp: pywraps/py_dbg.hpp \
$(I)dbg.hpp \
$(GENHOOKS)genhooks.py \
$(GENHOOKS)recipe_dbghooks.py \
$(GENERATED_HEADERS) | staging_dirs $(SDK_SOURCES)
@$(PYTHON) $(GENHOOKS)genhooks.py -i $< -o $@ \
-x $(ST_PARSED_HEADERS)/dbg_8hpp.xml -e dbg_notification_t \
-r void -n 0 -m hookgenDBG \
-R $(GENHOOKS)recipe_dbghooks.py
$(ST_PYW)/py_kernwin.hpp: pywraps/py_kernwin.hpp \
$(I)kernwin.hpp \
$(GENHOOKS)genhooks.py \
$(GENHOOKS)recipe_uihooks.py \
$(GENERATED_HEADERS) | staging_dirs $(SDK_SOURCES)
@$(PYTHON) $(GENHOOKS)genhooks.py -i $< -o $@ \
-x $(ST_PARSED_HEADERS)/kernwin_8hpp.xml -e ui_notification_t \
-r void -n 0 -m hookgenUI \
-R $(GENHOOKS)recipe_uihooks.py \
-d "ui_dbg_,ui_obsolete" -D "ui:" -s "ui_"
ifneq ($(HAS_HEXRAYS),)
WITH_HEXRAYS=-DWITH_HEXRAYS
WITH_HEXRAYS_CHKAPI=--with-hexrays
endif
CFLAGS= $(CCOPT) $(PLATFORM_CFLAGS) $(MSRUNTIME) -D__EXPR_SRC -I. -I$(ST_SWIG) -I$(ST_SDK) -I$(F) \
-DVER_MAJOR="1" -DVER_MINOR="7" -DVER_PATCH="0" -D__IDP__ \
-DUSE_STANDARD_FILE_FUNCTIONS $(IDAPYTHON_CFLAGS) \
$(SWITCH64) $(ARCH_CFLAGS) $(WITH_HEXRAYS) $(DEF_TYPE_TABLE)
ST_SWIG_HEADER=$(ST_SWIG)/header.i
$(ST_SWIG)/header.i: tools/deploy/header.i.in tools/genswigheader.py $(ST_SDK_TARGETS) | staging_dirs
$(PYTHON) tools/genswigheader.py -i $< -o $@ -m $(subst $(_SPACE),$(_COMMA),$(MODULES_NAMES)) -s $(ST_SDK)
ifdef __NT__
$(IDAPYTHON_IMPLIB_DEF): $(IDAPYTHON_IMPLIB_DEF_IN)
sed s/%LIBNAME%/$(notdir $(BINARY))/ < $? > $@
endif
find-pywraps-deps = $(wildcard pywraps/py_$(subst .i,,$(notdir $1))*.*)
# Some .i files depend on some other .i files in order to be parseable by SWiG
# (e.g., srarea.i imports area.i). Declare the list of such dependencies here
# so they will be picked by the auto-generated rules.
SWIG_IFACE_bytes=area
SWIG_IFACE_dbg=idd
SWIG_IFACE_frame=area
SWIG_IFACE_funcs=area
SWIG_IFACE_gdl=area
SWIG_IFACE_hexrays=typeinf
SWIG_IFACE_segment=area
SWIG_IFACE_srarea=area
SWIG_IFACE_typeinf=idp
define make-module-rules
# Note: apparently make cannot work well when a given recipe generates multiple files
# http://stackoverflow.com/questions/19822435/multiple-targets-from-one-recipe-and-parallel-execution
# Consequently, rules such as this:
#
# $(ST_WRAP)/ida_$1.py: $(ST_WRAP)/$1.cpp
#
# i.e., that do nothing but rely on the generation of another file,
# will not work in // execution. Thus, we will rely exclusively on
# the presence of the generated .cpp file, and not other generated
# files.
# ../../bin/x86_linux_gcc/python/ida_$1.py (note: dep. on .cpp. See note above.)
$(DEPLOY_PYDIR)/ida_$1.py: $(ST_WRAP)/$1.cpp | $(DEPLOY_PYDIR) tools/inject_pydoc.py
$(PYTHON) tools/inject_pydoc.py \
-i $(ST_WRAP)/ida_$1.py \
-w $(ST_SWIG)/$1.i \
-o $$@ \
-v > $(ST_WRAP)/ida_$1.pydoc_injection 2>&1
# obj/x86_linux_gcc/swig/X.i
$(ST_SWIG)/$1.i: $(addprefix $(F),$(call find-pywraps-deps,$1)) swig/$1.i $(ST_SWIG_HEADER) $(SWIG_IFACE_$1:%=$(ST_SWIG)/%.i) $(ST_SWIG_HEADER) tools/deploy.py
$(PYTHON) tools/deploy.py --pywraps $(ST_PYW) --template $$(subst $(F),,$$@) --output $$@ --module $$(subst .i,,$$(notdir $$@)) --interface-dependencies=$(subst $(_SPACE),$(_COMMA),$(SWIG_IFACE_$1))
# obj/x86_linux_gcc/wrappers/X.cpp
$(ST_WRAP)/$1.cpp: $(ST_SWIG)/$1.i
$(SWIG) -modern $(WITH_HEXRAYS) -python -threads -c++ -shadow \
$(MACDEFINES) -D__GNUC__ $(SWIGFLAGS) $(SWITCH64) -I$(ST_SWIG) \
-outdir $(ST_WRAP) -o $$@ -I$(ST_SDK) $$<
@$(PYTHON) tools/patch_constants.py --file $(ST_WRAP)/$1.cpp
ifdef __NT__
@$(PYTHON) tools/patch_directors_cc.py --file $(ST_WRAP)/$1.h
endif
# The copying of the .py will preserve attributes (including timestamps).
# And, since we have patched $1.cpp, it'll be more recent than ida_$1.py,
# and make would keep copying the .py file at each invocation.
# To prevent that, let's make the source .py file more recent than .cpp.
@touch $(ST_WRAP)/ida_$1.py
# obj/x86_linux_gcc/X.o32
$(F)$1$(O): $(ST_WRAP)/$1.cpp
ifdef __CODE_CHECKER__
touch $$@
else
$(CXX) $(CFLAGS) $(MSRUNTIME) $(NORTTI) -DPLUGIN_SUBMODULE -DSWIG_DIRECTOR_NORTTI -c $(OBJSW)$$@ $(ST_WRAP)/$1.cpp
ifndef __NT__
ifeq ($(OUT_OF_TREE_BUILD),)
@$(STRIPSYM_TOOL) $$@ $(STRIPSYMS) > /dev/null || ($(RM) $$@; false)
endif
endif
endif
# obj/x86_linux_gcc/_ida_X.so
$(F)_ida_$1$(MODULE_SFX): $(F)$1$(O) $(BINARY) $(IDAPYTHON_IMPLIB_DEF)
ifdef __NT__
$(LINKER) $(LINKOPTS) /OPT:ICF /OPT:REF /INCREMENTAL:NO /STUB:../../plugins/stub /OUT:$$@ $$< $(IDALIB) user32.lib $(ADDITIONAL_LIBS) $(IDAPYTHON_IMPLIB_PATH)
else
$(CCL) $(OUTDLL) $(OUTSW)$$@ $$< $(MODULE_LINKIDA) $(PLUGIN_SCRIPT) $(ADDITIONAL_LIBS) $(STDLIBS)
endif
# ../../bin/x86_linux_gcc/python/lib/lib-dynload/ida_32/_ida_X.so
$(DEPLOY_LIBDIR)/_ida_$1$(MODULE_SFX): $(F)_ida_$1$(MODULE_SFX) | $(DEPLOY_LIBDIR)
@$(CP) $$< $$@
endef
$(foreach mod,$(MODULES_NAMES),$(eval $(call make-module-rules,$(mod))))
$(ST_API_CONTENTS): $(ALL_ST_WRAP_CPP)
$(PYTHON) tools/chkapi.py $(WITH_HEXRAYS_CHKAPI) -i $(subst $(_SPACE),$(_COMMA),$(ALL_ST_WRAP_CPP)) -p $(subst $(_SPACE),$(_COMMA),$(ALL_ST_WRAP_PY)) -r $(ST_API_CONTENTS)
@(diff -w $(API_CONTENTS) $(ST_API_CONTENTS)) > /dev/null || \
(echo "API CONTENTS CHANGED! update api_contents.txt or fix the API" && \
echo "(New API: $(ST_API_CONTENTS)) ***" && \
(diff -U 1 -w $(API_CONTENTS) $(ST_API_CONTENTS) && false))
# Check that doc injection is stable
PYDOC_INJECTIONS_RESULTS=$(MODULES_NAMES:%=$(ST_WRAP)/ida_%.pydoc_injection)
$(ST_PYDOC_INJECTIONS): $(PYTHON_MODULES)
cat $(PYDOC_INJECTIONS_RESULTS) > $@
@(diff -w $(PYDOC_INJECTIONS) $(ST_PYDOC_INJECTIONS)) > /dev/null || \
(echo "PYDOC INJECTION CHANGED! update $(PYDOC_INJECTIONS) or fix .. what needs fixing" && \
echo "(New API: $(ST_PYDOC_INJECTIONS)) ***" && \
(diff -U 1 -w $(PYDOC_INJECTIONS) $(ST_PYDOC_INJECTIONS) && false))
# Require a strict SWiG version (other versions might generate different code.)
SWIG_VERSION_ACTUAL=$(shell $(SWIG) -version | awk "/SWIG Version [0-9.]+/ { if (match(\$$0, /([0-9.]+)/)) { print substr(\$$0, RSTART, RLENGTH); } }")
# ST_WRAP_FILES=$(MODULES_NAMES:%=$(ST_WRAP)/%.cpp) $(MODULES_NAMES:%=$(ST_WRAP)/%.h) $(MODULES_NAMES:%=$(ST_WRAP)/ida_%.py)
# .PRECIOUS: $(ST_WRAP_FILES) $(MODULES_OBJECTS)
.PRECIOUS: $(ST_API_CONTENTS) $(ST_PYDOC_INJECTIONS)
DOCS_MODULES=$(MODULES_NAMES:%=ida_%)
tools/docs/hrdoc.cfg: tools/docs/hrdoc.cfg.in
sed s/%IDA_MODULES%/"$(DOCS_MODULES)"/ < $? > $@
# the html files are produced in docs\hr-html directory
docs: tools/docs/hrdoc.py tools/docs/hrdoc.cfg tools/docs/hrdoc.css
ifndef __NT__
TVHEADLESS=1 $(R)idal -Stools/docs/hrdoc.py -t > /dev/null
else
$(R)idaq -Stools/docs/hrdoc.py -t
endif
# Test that all functions that are present in ftable.cpp
# are present in idc.py (and therefore made available by
# the idapython).
ifdef __NT__
IDA_CMD=TVHEADLESS=1 $(R)idaw$(X64SUFF)$(SUFF64)
else
IDA_CMD=TVHEADLESS=1 $(R)idal$(X64SUFF)$(SUFF64)
endif
# the demo version of ida does not have the -B command line option
ifeq ($(OUT_OF_TREE_BUILD),)
ISDEMO=$(shell grep "define DEMO$$" $(IDA_INCLUDE)/commerc.hpp)
ifeq ($(ISDEMO),)
BATCH_SWITCH=-B
endif
endif
$(TEST_IDC): $(F)idctest.log
$(F)idctest.log: $(RS)idc/idc.idc | $(BINARY) pyfiles $(PRECOMPILED_COPY)
ifneq ($(wildcard ../../tests),)
@$(RM) $(F)idctest.log
@$(IDA_CMD) $(BATCH_SWITCH) -S"test_idc.py $^" -t -L$(F)idctest.log> /dev/null || \
(echo "ERROR: The IDAPython IDC interface is incomplete. IDA log:" && cat $(F)idctest.log && false)
endif
package:
ifeq ($(OUT_OF_TREE_BUILD),)
-@if [ ! -d "$(DIST)" ] ; then mkdir -p 2>/dev/null $(DIST) ; fi
$(PYTHON) $(PKGBIN_SCRIPT) \
--input-binary-tree $(R) \
--output-dir $(DIST) \
--confirmed \
--component plugins/idapython
(cd $(DIST) && $(PYTHON) $(DBLZIP_SCRIPT) --once --output ../../../obj/$(PACKAGE_NAME))
endif
public_tree: all
ifeq ($(OUT_OF_TREE_BUILD),)
-@if [ ! -d "$(PUBTREE_DIR)/out_of_tree" ] ; then mkdir -p 2>/dev/null $(PUBTREE_DIR)/out_of_tree ; fi
rsync -a --exclude=obj/ \
--exclude=precompiled/ \
--exclude=repl.py \
--exclude=test_idc.py \
--exclude=RELEASE.md \
. $(PUBTREE_DIR)
(cd $(F) && zip -r ../../$(PUBTREE_DIR)/out_of_tree/parsed_notifications.zip parsed_notifications)
endif
echo_modules:
@echo $(MODULES_NAMES)
# MAKEDEP dependency list ------------------
$(F)python$(O) : $(I)area.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)diskio.hpp $(I)expr.hpp $(I)fpro.h $(I)funcs.hpp \
$(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \
$(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \
$(I)netnode.hpp $(I)pro.h $(I)segment.hpp $(I)ua.hpp \
$(I)xref.hpp python.cpp pywraps.hpp pywraps.cpp | $(ST_SDK_TARGETS)
endif