Files
proxmark3/client/Makefile
T
MsprgandClaude Fable 5 d852118de5 client: build the tab completion vocabulary at runtime from the command tree
Tab completion used a generated table (pm3line_vocabulary.h, refreshed by
hand via `make commands`) that drifted from the real command tables: new
commands were missing (e.g. `hw bwm*`), removed ones lingered, and the
"offline" flag depended on the platform of whoever regenerated it
(IfPm5() returns true offline on PM5 builds).

Build the vocabulary at startup instead:

- cmdparser: add walkCommandsRecursive(), a tree walk using a fourth
  internal sentinel (XX_internal_command_walk_XX) next to the dump ones.
  It hands each leaf to a visitor as its command_t chain (ancestors +
  leaf). A dispatch counter detects entries shown like a category but
  with their own parser (reveng) and reports them as leaves.
- pm3line_vocabulary: dynamic vocabulary holding the IsAvailable()
  predicates of every command and its ancestor categories, so completion
  applies exactly the rule CmdsHelp() uses, live, for both offline and
  connected devices. Script entries ("script run <relpath>") come from
  the same directories `script list` scans, sorted, including
  subdirectories with the path `script run` needs.
- pm3line: readline and linenoise completers consume the live vocabulary.
  The walk runs with output disabled so category handlers stay silent.
- Drop pm3_help2list.py and the header regeneration from `make commands`.

Behaviour change: entries whose category is hidden by `help` (e.g. `mem`,
`usart` offline) are no longer offered, matching `help`; when connected,
commands the device does not support are no longer offered either.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-28 14:29:04 +02:00

1228 lines
35 KiB
Makefile

#-----------------------------------------------------------------------------
# Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# See LICENSE.txt for the text of the license.
#-----------------------------------------------------------------------------
ifeq ($(PLTNAME),)
PLATFORM_FILE ?= ../Makefile.platform
-include $(PLATFORM_FILE)
-include ../.Makefile.options.cache
# Default platform if no platform specified
PLATFORM?=PM3RDV4
ifneq ($(PLATFORM), $(CACHED_PLATFORM))
$(error platform definitions have been changed, please "make clean" at the root of the project)
endif
endif
include ../Makefile.defs
ifeq ($(PLATFORM),PM3ICOPYX)
INCLUDES += -DICOPYX
endif
ifeq ($(PLATFORM),PM5)
INCLUDES += -DDEFAULT_PM5
endif
INSTALLBIN = proxmark3
INSTALLSHARE = cmdscripts lualibs luascripts pyscripts resources dictionaries
VPATH = ../common src
vpath %.dic dictionaries
OBJDIR = obj
ifeq ($(USE_BREW),1)
INCLUDES += -I$(BREW_PREFIX)/include
LDLIBS += -L$(BREW_PREFIX)/lib
PKG_CONFIG_ENV := PKG_CONFIG_PATH=$(BREW_PREFIX)/lib/pkgconfig:$(BREW_PREFIX)/opt/qt@5/lib/pkgconfig:$(BREW_PREFIX)/opt/qt@5/lib/pkgconfig
endif
ifeq ($(USE_MACPORTS),1)
INCLUDES += -I$(MACPORTS_PREFIX)/include
LDLIBS += -L$(MACPORTS_PREFIX)/lib
PKG_CONFIG_ENV := PKG_CONFIG_PATH=$(MACPORTS_PREFIX)/lib/pkgconfig
endif
PM3INCLUDES =
###################
# local libraries #
###################
## Amiibo
AMIIBOLIBPATH = ./deps/amiitool
AMIIBOLIBINC = -I$(AMIIBOLIBPATH)
AMIIBOLIB = $(AMIIBOLIBPATH)/libamiibo.a
AMIIBOLIBLD =
## Cliparser / Argtable3
CLIPARSERLIBPATH = ./deps/cliparser
CLIPARSERLIBINC = -I$(CLIPARSERLIBPATH)
CLIPARSERLIB = $(CLIPARSERLIBPATH)/libcliparser.a
CLIPARSERLIBLD =
## Hardnested
HARDNESTEDLIBPATH = ./deps/hardnested
HARDNESTEDLIBINC = -I$(HARDNESTEDLIBPATH)
HARDNESTEDLIB = $(HARDNESTEDLIBPATH)/libhardnested.a
HARDNESTEDLIBLD =
## ID48
## must be manually kept in sync with updates to deps/id48/CMakeLists.txt
ID48LIBPATH = ./deps/id48/src
ID48LIBINC = -I$(ID48LIBPATH)/../public
ID48LIB = $(ID48LIBPATH)/libid48.a
ID48LIBLD =
## Jansson
JANSSONLIBPATH = ./deps/jansson
JANSSONLIBINC = -I$(JANSSONLIBPATH)
JANSSONLIB = $(JANSSONLIBPATH)/libjansson.a
JANSSONLIBLD =
## Linenoise
# Can be used if Readline is unavailable or explicitely disabled
# Requires to be unpacked, see deps/get_linenoise.sh
LINENOISELIBPATH = ./deps/linenoise
LINENOISELIBINC = -I$(LINENOISELIBPATH)
LINENOISELIB = $(LINENOISELIBPATH)/liblinenoise.a
LINENOISELIBLD =
## Lua
LUALIBPATH = ./deps/liblua
LUALIBINC = -I$(LUALIBPATH)
LUALIB = $(LUALIBPATH)/liblua.a
LUALIBLD =
LUAPLATFORM = generic
ifdef IS_MINGW
LUAPLATFORM = mingw
else
ifdef IS_DARWIN
LUAPLATFORM = macosx
else
LUALIBLD += -ldl
LUAPLATFORM = linux
endif
endif
## Winsock2
ifdef IS_MINGW
LDLIBS += -lws2_32
endif
## Reveng
REVENGLIBPATH = ./deps/reveng
REVENGLIBINC = -I$(REVENGLIBPATH)
REVENGLIB = $(REVENGLIBPATH)/libreveng.a
REVENGLIBLD =
## OpenJPEG (JPEG2000 decoding for the picture viewer)
OPENJPEGLIBPATH = ./deps/openjpeg
OPENJPEGLIBINC = -I$(OPENJPEGLIBPATH)
OPENJPEGLIB = $(OPENJPEGLIBPATH)/openjpeg.a
OPENJPEGLIBLD =
## Tinycbor
TINYCBORLIBPATH = ./deps/tinycbor
TINYCBORLIBINC = -I$(TINYCBORLIBPATH)
TINYCBORLIB = $(TINYCBORLIBPATH)/tinycbor.a
TINYCBORLIBLD =
## Whereami
WHEREAMILIBPATH = ./deps/whereami
WHEREAMILIBINC = -I$(WHEREAMILIBPATH)
WHEREAMILIB = $(WHEREAMILIBPATH)/libwhereami.a
WHEREAMILIBLD =
## MQTT
MQTTLIBPATH = ./deps/mqtt
MQTTLIBINC = -I$(MQTTLIBPATH)
MQTTLIB = $(MQTTLIBPATH)/mqtt.a
MQTTLIBLD =
## VEC
VECLIBPATH = ./deps/vec
VECLIBINC = -I$(VECLIBPATH)
##########################
# common local libraries #
##########################
## mbed TLS
MBEDTLSLIBPATH = ../common/mbedtls
MBEDTLSLIBINC = -I$(MBEDTLSLIBPATH)
MBEDTLSLIB = $(OBJDIR)/libmbedtls.a
MBEDTLSLIBCLIENTRELPATH = ../../client
########################################################
# optional system libraries to replace local libraries #
########################################################
## Amiibo
# not distributed as system library
STATICLIBS += $(AMIIBOLIB)
LDLIBS += $(AMIIBOLIBLD)
PM3INCLUDES += $(AMIIBOLIBINC)
## Cliparser / Argtable3
# not distributed as system library
STATICLIBS += $(CLIPARSERLIB)
LDLIBS += $(CLIPARSERLIBLD)
PM3INCLUDES += $(CLIPARSERLIBINC)
## Hardnested
# not distributed as system library
STATICLIBS += $(HARDNESTEDLIB)
LDLIBS +=$(HARDNESTEDLIBLD)
PM3INCLUDES += $(HARDNESTEDLIBINC)
## ID48
# not distributed as system library
STATICLIBS += $(ID48LIB)
LDLIBS += $(ID48LIBLD)
PM3INCLUDES += $(ID48LIBINC)
## Linenoise
# wait to see if Readline is available
## Lua
ifneq ($(SKIPLUASYSTEM),1)
ifdef MACPORTS_PREFIX
LUAINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags lua-5.4 2>/dev/null)
LUALDLIBS = $(shell $(PKG_CONFIG_ENV) pkg-config --libs lua-5.4 2>/dev/null)
else
LUAINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags lua5.4 2>/dev/null)
LUALDLIBS = $(shell $(PKG_CONFIG_ENV) pkg-config --libs lua5.4 2>/dev/null)
endif
ifneq ($(LUALDLIBS),)
LUALIB =
LUALIBLD = $(LUALDLIBS)
LUALIBINC = $(LUAINCLUDES)
LUA_FOUND = 1
endif
endif
STATICLIBS += $(LUALIB)
LDLIBS += $(LUALIBLD)
PM3INCLUDES += $(LUALIBINC)
## Jansson
# Jansson section needs to be after Lua to avoid interferences on macOS if a locally incompatible Lua was available, see PR 1155
ifneq ($(SKIPJANSSONSYSTEM),1)
JANSSONINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags jansson 2>/dev/null)
JANSSONLDLIBS = $(shell $(PKG_CONFIG_ENV) pkg-config --libs jansson 2>/dev/null)
ifneq ($(JANSSONLDLIBS),)
JANSSONLIB =
JANSSONLIBLD = $(JANSSONLDLIBS)
JANSSONLIBINC = $(JANSSONINCLUDES)
JANSSON_FOUND = 1
endif
endif
STATICLIBS += $(JANSSONLIB)
LDLIBS += $(JANSSONLIBLD)
PM3INCLUDES += $(JANSSONLIBINC)
## mbed TLS
# system library cannot be used because it is compiled by default without CMAC support
STATICLIBS += $(MBEDTLSLIB)
LDLIBS += $(MBEDTLSLIBLD)
PM3INCLUDES += $(MBEDTLSLIBINC)
## Reveng
# not distributed as system library
STATICLIBS += $(REVENGLIB)
LDLIBS += $(REVENGLIBLD)
PM3INCLUDES += $(REVENGLIBINC)
## OpenJPEG
# vendored, Qt has no JPEG2000 image handler.
# Only linked in when the Qt GUI is built, see the "gui" section below
PM3INCLUDES += $(OPENJPEGLIBINC)
## Tinycbor
# not distributed as system library
STATICLIBS += $(TINYCBORLIB)
LDLIBS += $(TINYCBORLIBLD)
PM3INCLUDES += $(TINYCBORLIBINC)
## Whereami
ifneq ($(SKIPWHEREAMISYSTEM),1)
ifneq (,$(wildcard /usr/include/whereami.h))
WHEREAMILIB =
WHEREAMILIBLD = -lwhereami
WHEREAMILIBINC =
WHEREAMI_FOUND = 1
endif
endif
STATICLIBS += $(WHEREAMILIB)
LDLIBS += $(WHEREAMILIBLD)
PM3INCLUDES += $(WHEREAMILIBINC)
## MQTT
# not distributed as system library
STATICLIBS += $(MQTTLIB)
LDLIBS += $(MQTTLIBLD)
PM3INCLUDES += $(MQTTLIBINC)
## VEC
# not distributed as system library
PM3INCLUDES += $(VECLIBINC)
####################
# system libraries #
####################
## Atomic
# RPi Zero gcc requires -latomic
# but MacOSX /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld
# doesn't recognize option --as-needed
ifndef IS_DARWIN
LDLIBS += -Wl,--as-needed -latomic -Wl,--no-as-needed
endif
## BZIP2
LDLIBS += -lbz2
## LZ4
LDLIBS += -llz4
## ZLIB
ZLIBINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags zlib 2>/dev/null)
ZLIBLDLIBS = $(shell $(PKG_CONFIG_ENV) pkg-config --libs zlib 2>/dev/null)
ifneq ($(ZLIBLDLIBS),)
LDLIBS += $(ZLIBLDLIBS)
PM3INCLUDES += $(ZLIBINCLUDES)
ZLIB_FOUND = 1
endif
## Bluez (optional)
ifneq ($(SKIPBT),1)
BTINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags bluez 2>/dev/null)
BTLDLIBS = $(shell $(PKG_CONFIG_ENV) pkg-config --libs bluez 2>/dev/null)
ifneq ($(BTLDLIBS),)
BTLIBLD = $(BTLDLIBS)
BTLIBINC = $(BTINCLUDES)
BT_FOUND = 1
endif
endif
LDLIBS += $(BTLIBLD)
PM3INCLUDES += $(BTLIBINC)
## Math
LDLIBS += -lm
## Pthread
# Some have no pthread, e.g. termux
ifneq ($(SKIPPTHREAD),1)
LDLIBS += -lpthread
endif
## Python3 (optional)
ifneq ($(SKIPPYTHON),1)
# since python3.8, applications willing to embed python must use -embed:
PYTHONINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags $(PYTHON3_PKGCONFIG)-embed 2>/dev/null)
PYTHONLDLIBS = $(shell $(PKG_CONFIG_ENV) pkg-config --libs $(PYTHON3_PKGCONFIG)-embed 2>/dev/null)
ifneq ($(PYTHONLDLIBS),)
PYTHONLIBLD = $(PYTHONLDLIBS)
PYTHONLIBINC = $(subst -I,-isystem ,$(PYTHONINCLUDES))
PYTHON_FOUND = 1
else
PYTHONINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags $(PYTHON3_PKGCONFIG) 2>/dev/null)
PYTHONLDLIBS = $(shell $(PKG_CONFIG_ENV) pkg-config --libs $(PYTHON3_PKGCONFIG) 2>/dev/null)
ifneq ($(PYTHONLDLIBS),)
PYTHONLIBLD = $(PYTHONLDLIBS)
PYTHONLIBINC = $(subst -I,-isystem ,$(PYTHONINCLUDES))
PYTHON_FOUND = 1
endif
endif
endif
LDLIBS += $(PYTHONLIBLD)
PM3INCLUDES += $(PYTHONLIBINC)
## QT6 (or QT5 fallback) (optional)
ifneq ($(SKIPQT),1)
ifneq ($(SKIPQT6),1)
# Check for correctly configured Qt6
QTINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags Qt6Core Qt6Widgets Qt6Gui 2>/dev/null)
QTLDLIBS = $(shell $(PKG_CONFIG_ENV) pkg-config --libs Qt6Core Qt6Widgets Qt6Gui 2>/dev/null)
MOC = $(shell $(PKG_CONFIG_ENV) pkg-config --variable=libexecdir Qt6Core 2>/dev/null)/moc
UIC = $(shell $(PKG_CONFIG_ENV) pkg-config --variable=libexecdir Qt6Core 2>/dev/null)/uic
QMAKE = $(shell $(PKG_CONFIG_ENV) pkg-config --variable=bindir Qt6Core 2>/dev/null)/qmake
ifeq ($(QTINCLUDES),)
# pkg-config not available for Qt6.2.4 (e.g. Ubuntu 22.04), fall back to qmake6
QMAKE6 := $(shell command -v qmake6 2>/dev/null)
ifneq ($(QMAKE6),)
QT6_INCDIR := $(shell $(QMAKE6) -query QT_INSTALL_HEADERS 2>/dev/null)
ifneq ($(QT6_INCDIR),)
QTINCLUDES := -I$(QT6_INCDIR) -I$(QT6_INCDIR)/QtCore -I$(QT6_INCDIR)/QtWidgets -I$(QT6_INCDIR)/QtGui
endif
QT6_LIBDIR := $(shell $(QMAKE6) -query QT_INSTALL_LIBS 2>/dev/null)
ifneq ($(QT6_LIBDIR),)
QTLDLIBS := -L$(QT6_LIBDIR) -lQt6Core -lQt6Widgets -lQt6Gui
endif
QT6_LIBEXECDIR := $(shell $(QMAKE6) -query QT_INSTALL_LIBEXECS 2>/dev/null)
ifneq ($(QT6_LIBEXECDIR),)
MOC := $(QT6_LIBEXECDIR)/moc
UIC := $(QT6_LIBEXECDIR)/uic
endif
QT6_BINDIR := $(shell $(QMAKE6) -query QT_INSTALL_BINS 2>/dev/null)
ifneq ($(QT6_BINDIR),)
QMAKE := $(QMAKE6)
endif
endif
endif
ifneq ($(QTLDLIBS),)
QT6_FOUND = 1
endif
endif
ifneq ($(QT6_FOUND),1)
# if Qt6 not found check for correctly configured Qt5
QTINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags Qt5Core Qt5Widgets 2>/dev/null)
QTLDLIBS = $(shell $(PKG_CONFIG_ENV) pkg-config --libs Qt5Core Qt5Widgets 2>/dev/null)
MOC = $(shell $(PKG_CONFIG_ENV) pkg-config --variable=host_bins Qt5Core 2>/dev/null)/moc
UIC = $(shell $(PKG_CONFIG_ENV) pkg-config --variable=host_bins Qt5Core 2>/dev/null)/uic
QMAKE = $(shell $(PKG_CONFIG_ENV) pkg-config --variable=host_bins Qt5Core 2>/dev/null)/qmake
endif
ifeq ($(QTLDLIBS),)
# if both pkg-config commands failed, search in common places
# TODO: to be checked on OSX...
ifneq ($(QTDIR),)
ifneq ($(SKIPQT6),1)
ifneq ($(wildcard $(QTDIR)/lib/libQt6Core),)
# QT6
QTINCLUDES = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui -I$(QTDIR)/include/QtWidgets
QTLDLIBS = -L$(QTDIR)/lib -lQt6Core -lQt6Gui -lQt6Widgets
QT6_FOUND = 1
endif
endif
ifneq ($(QT6_FOUND),1)
# QT5
QTINCLUDES = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui -I$(QTDIR)/include/QtWidgets
QTLDLIBS = -L$(QTDIR)/lib -lQt5Core -lQt5Gui -lQt5Widgets
endif
MOC = $(QTDIR)/bin/moc
UIC = $(QTDIR)/bin/uic
QMAKE = $(QTDIR)/bin/qmake
endif
endif
ifneq ($(QTLDLIBS),)
QT_FOUND = 1
endif
endif
LDLIBS += $(QTLDLIBS)
# Treat Qt headers as system headers, to avoid a bug with Qt 6.6.3
QTINCLUDES_FIX = $(patsubst -I%,-isystem %,$(QTINCLUDES))
CXXINCLUDES += $(QTINCLUDES_FIX)
## GD (optional)
ifneq ($(SKIPGD),1)
GDINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags gdlib 2>/dev/null)
GDLDLIBS = $(shell $(PKG_CONFIG_ENV) pkg-config --libs gdlib 2>/dev/null)
ifneq ($(GDLDLIBS),)
LDLIBS += $(GDLDLIBS)
PM3INCLUDES += $(GDINCLUDES)
GD_FOUND = 1
endif
endif
## Readline
ifneq ($(SKIPREADLINE),1)
ifeq ($(USE_BREW),1)
LDLIBS += -L$(BREW_PREFIX)/opt/readline/lib
PM3INCLUDES += -I$(BREW_PREFIX)/opt/readline/include
endif
ifeq ($(USE_MACPORTS),1)
PM3INCLUDES += -I$(MACPORTS_PREFIX)/include/readline
endif
LDLIBS += -lreadline
READLINE_FOUND = 1
else
## Linenoise
ifneq ($(SKIPLINENOISE),1)
ifneq (,$(wildcard $(LINENOISELIBPATH)))
STATICLIBS += $(LINENOISELIB)
LDLIBS += $(LINENOISELIBLD)
PM3INCLUDES += $(LINENOISELIBINC)
LINENOISE_LOCAL_FOUND = 1
endif
endif
endif
########
# SWIG #
########
ifneq ("$(wildcard src/pm3_luawrap.c)","")
SWIG_LUA_FOUND = 1
endif
ifeq ($(PYTHON_FOUND),1)
ifneq ("$(wildcard src/pm3_pywrap.c)","")
SWIG_PYTHON_FOUND = 1
endif
endif
#######################################################################################################
# clang doesn't like this params
#MYCFLAGS += --param max-completely-peeled-insns=1000 --param max-completely-peel-times=10000
MYCFLAGS += -O3
CFLAGS ?= $(DEFCFLAGS)
CFLAGS += $(MYDEFS) $(MYCFLAGS) $(MYINCLUDES)
# We cannot just use CFLAGS+=... because it has impact on sub-makes if CFLAGS is defined in env:
PM3CFLAGS = $(CFLAGS)
PM3CFLAGS += -I./src -I./include -I../include -I../common -I../common_fpga $(PM3INCLUDES) $(INCLUDES)
# WIP Testing
#PM3CFLAGS += -std=c11 -pedantic
PREFIX ?= /usr/local
ifdef IS_MINGW
# Mingw uses by default Microsoft printf, we want the GNU printf (e.g. for %z)
# and setting _ISOC99_SOURCE sets internally __USE_MINGW_ANSI_STDIO=1
# FTR __USE_MINGW_ANSI_STDIO seems deprecated in Mingw32
# but not Mingw64 https://fr.osdn.net/projects/mingw/lists/archive/users/2019-January/000199.html
PM3CFLAGS += -D_ISOC99_SOURCE
PM3CFLAGS += -mno-ms-bitfields -fexec-charset=cp850
endif
ifeq ($(READLINE_FOUND),1)
PM3CFLAGS += -DHAVE_READLINE
endif
ifeq ($(LINENOISE_LOCAL_FOUND),1)
PM3CFLAGS += -DHAVE_LINENOISE
endif
ifeq ($(BT_FOUND),1)
PM3CFLAGS += -DHAVE_BLUEZ
endif
ifeq ($(PYTHON_FOUND),1)
PM3CFLAGS += -DHAVE_PYTHON
endif
ifeq ($(GD_FOUND),1)
PM3CFLAGS += -DHAVE_GD
endif
ifeq ($(ZLIB_FOUND),1)
PM3CFLAGS += -DHAVE_ZLIB
endif
ifeq ($(SWIG_LUA_FOUND),1)
PM3CFLAGS += -DHAVE_LUA_SWIG
endif
ifeq ($(SWIG_PYTHON_FOUND),1)
PM3CFLAGS += -DHAVE_PYTHON_SWIG
endif
PM3CFLAGS += -DHAVE_SNPRINTF
CXXFLAGS ?= $(DEFCXXFLAGS)
CXXFLAGS += $(MYDEFS) $(MYCXXFLAGS) $(MYINCLUDES)
PM3CXXFLAGS = $(CXXFLAGS)
PM3CXXFLAGS += -I../include -I./include
ifeq ($(QT_FOUND),1)
PM3CFLAGS += -DHAVE_GUI
PM3CXXFLAGS += -DQT_NO_DEBUG
ifeq ($(QT6_FOUND),1)
# Qt6 is claiming for a C++17 compiler
PM3CXXFLAGS += -std=c++17
else
# On OSX Qt6 is claiming for a C++11 compiler (gnu++14 works too, but if nothing it fails)
PM3CXXFLAGS += -std=c++11
endif
endif
PM3CXXFLAGS += -DHAVE_SNPRINTF
LDFLAGS ?= $(DEFLDFLAGS)
LDFLAGS += $(MYLDFLAGS)
PM3LDFLAGS = $(LDFLAGS)
ifdef IS_IOS
PM3LDFLAGS += -framework Foundation -framework UIKit
endif
ifdef IS_MACOS
# M* macOS devices return arm
PM3LDFLAGS += -framework Foundation -framework AppKit
endif
###################
# printing status #
###################
$(info ===================================================================)
$(info Version info: $(shell ../tools/mkversion.sh --short 2>/dev/null))
$(info Client platform: $(platform))
ifeq ($(SKIPQT),1)
$(info GUI support: skipped)
else
ifeq ($(QT_FOUND),1)
ifeq ($(QT6_FOUND),1)
$(info GUI support: QT6 found, enabled ($(shell QT_SELECT=6 $(QMAKE) -v 2>/dev/null|grep -o 'Qt version.*')))
else
ifeq ($(FORCEQT6),1)
$(error FORCEQT6 not satisfied, aborting)
endif
$(info GUI support: QT5 found, enabled ($(shell QT_SELECT=5 $(QMAKE) -v 2>/dev/null|grep -o 'Qt version.*')))
endif
else
$(info GUI support: QT not found, disabled)
ifeq ($(FORCEQT),1)
$(error FORCEQT not satisfied, aborting)
endif
endif
endif
ifeq ($(SKIPBT),1)
$(info native BT support: skipped)
else
ifeq ($(BT_FOUND),1)
$(info native BT support: Bluez found, enabled)
else
$(info native BT support: Bluez not found, disabled)
ifeq ($(FORCEBT),1)
$(error FORCEBT not satisfied, aborting)
endif
endif
endif
ifeq ($(SKIPJANSSONSYSTEM),1)
$(info Jansson library: local library forced)
else ifeq ($(JANSSON_FOUND),1)
$(info Jansson library: system library found)
else
$(info Jansson library: system library not found, using local library)
ifeq ($(FORCEJANSSONSYSTEM),1)
$(error FORCEJANSSONSYSTEM not satisfied, aborting)
endif
endif
ifeq ($(SKIPLUASYSTEM),1)
$(info Lua library: local library forced)
else
ifeq ($(LUA_FOUND),1)
$(info Lua library: system library found)
else
$(info Lua library: system library not found, using local library)
ifeq ($(FORCELUASYSTEM),1)
$(error FORCELUASYSTEM not satisfied, aborting)
endif
endif
endif
ifeq ($(SKIPPYTHON),1)
$(info Python3 library: skipped)
else
ifeq ($(PYTHON_FOUND),1)
$(info Python3 library: Python3 v$(shell $(PKG_CONFIG_ENV) pkg-config --modversion $(PYTHON3_PKGCONFIG)) found, enabled)
else
$(info Python3 library: Python3 not found, disabled)
ifeq ($(FORCEPYTHON),1)
$(error FORCEPYTHON not satisfied, aborting)
endif
endif
endif
ifeq ($(SKIPGD),1)
$(info GD library: skipped)
else
ifeq ($(GD_FOUND),1)
$(info GD library: GD v$(shell $(PKG_CONFIG_ENV) pkg-config --modversion gdlib) found, enabled)
else
$(info GD library: GD not found, disabled)
ifeq ($(FORCEGD),1)
$(error FORCEGD not satisfied, aborting)
endif
endif
endif
ifeq ($(SKIPZLIB),1)
$(info Zlib library: skipped)
else
ifeq ($(ZLIB_FOUND),1)
$(info Zlib library: system library found, enabled)
else
$(info Zlib library: not found, disabled)
ifeq ($(FORCEZLIB),1)
$(error FORCEZLIB not satisfied, aborting)
endif
endif
endif
ifeq ($(SKIPREADLINE),1)
$(info Readline library: skipped)
else
ifeq ($(READLINE_FOUND),1)
$(info Readline library: enabled)
else
$(info Readline library: Readline not found, disabled)
ifeq ($(FORCEREADLINE),1)
$(error FORCEREADLINE not satisfied, aborting)
endif
endif
endif
ifneq ($(READLINE_FOUND),1)
ifeq ($(SKIPLINENOISE),1)
$(info Linenoise library: skipped)
else
ifeq ($(LINENOISE_LOCAL_FOUND),1)
$(info Linenoise library: enabled)
else
$(info Linenoise library: Linenoise not found, disabled)
ifeq ($(FORCELINENOISE),1)
$(error FORCELINENOISE not satisfied, aborting)
endif
endif
endif
endif
ifeq ($(SKIPWHEREAMISYSTEM),1)
$(info Whereami library: local library forced)
else
ifeq ($(WHEREAMI_FOUND),1)
$(info Whereami library: system library found)
else
$(info Whereami library: system library not found, using local library)
ifeq ($(FORCEWHEREAMISYSTEM),1)
$(error FORCEWHEREAMISYSTEM not satisfied, aborting)
endif
endif
endif
ifeq ($(SWIG_LUA_FOUND),1)
$(info Lua SWIG: wrapper found)
endif
ifeq ($(SWIG_PYTHON_FOUND),1)
$(info Python SWIG: wrapper found)
endif
$(info compiler version: $(shell $(CC) --version|head -n 1))
$(info ===================================================================)
################
# dependencies #
################
# Flags to generate temporary dependency files
DEPFLAGS = -MT $@ -MMD -MP -MF $(OBJDIR)/$*.Td
# make temporary to final dependency files after successful compilation
POSTCOMPILE = $(MV) -f $(OBJDIR)/$*.Td $(OBJDIR)/$*.d && $(TOUCH) $@
################
# enumerations #
################
SRCS = mifare/aiddesfire.c \
aidsearch.c \
atrs.c \
cmdanalyse.c \
cmdcrc.c \
cmddata.c \
cmdflashmem.c \
cmdflashmemspiffs.c \
cmdhf.c \
cmdhf14a.c \
pla.c \
cmdhf14b.c \
cmdhf15.c \
cmdhfaliro.c \
cmdhfcalypso.c \
cmdhfcryptorf.c \
cmdhfepa.c \
cmdhfemrtd.c \
cmdhffelica.c \
cmdhffido.c \
cmdhffmcos.c \
cmdhffudan.c \
cmdhfgallagher.c \
cmdhfgst.c \
cmdhfksx6924.c \
cmdhfcipurse.c \
cmdhfsecc.c \
cmdhficlass.c \
cmdhfict.c \
cmdhflegic.c \
cmdhfjooki.c \
cmdhflist.c \
cmdhflto.c \
cmdhfmf.c \
cmdhfmfdes.c \
cmdhfmfhard.c \
cmdhfmfp.c \
cmdhfmfsen.c \
cmdhfmfu.c \
cmdhfntag424.c \
cmdhfsaflok.c \
cmdhfseos.c \
cmdhfst.c \
cmdhfst25ta.c \
cmdhftesla.c \
cmdhfthinfilm.c \
cmdhftopaz.c \
cmdhftexkom.c \
cmdhfvas.c \
cmdhfxerox.c \
cmdhw.c \
cmdfpga.c \
cmdlf.c \
cmdlfawid.c \
cmdlfcotag.c \
cmdlfdestron.c \
cmdlfem.c \
cmdlfem410x.c \
cmdlfem4x05.c \
cmdlfem4x50.c \
cmdlfem4x70.c \
cmdlffdxb.c \
cmdlfguard.c \
cmdlfgallagher.c \
cmdlfhid.c \
cmdlfhitag.c \
cmdlfhitaghts.c \
cmdlfhitagu.c \
cmdlfidteck.c \
cmdlfindala.c \
cmdlfio.c \
cmdlfjablotron.c \
cmdlfkeri.c \
cmdlfmotorola.c \
cmdlfnedap.c \
cmdlfnexwatch.c \
cmdlfnoralsy.c \
cmdlfpac.c \
cmdlfparadox.c \
cmdlfpcf7931.c \
cmdlfpresco.c \
cmdlfpyramid.c \
cmdlfsecurakey.c \
cmdlft55xx.c \
cmdlfti.c \
cmdlftrovan.c \
cmdlfviking.c \
cmdlfvisa2000.c \
cmdlfzx8211.c \
cmdmad.c \
cmdmain.c \
cmdmqtt.c \
cmdnfc.c \
cmdparser.c \
cmdpiv.c \
cmdscript.c \
cmdsmartcard.c \
cmdtrace.c \
cmdusart.c \
cmdwiegand.c \
comms.c \
crypto/asn1dump.c \
crypto/asn1utils.c\
crypto/duoxcrypto.c\
crypto/libpcrypto.c\
crypto/originality.c\
emv/cmdemv.c \
emv/crypto.c\
emv/crypto_polarssl.c\
emv/dol.c \
emv/emv_pk.c\
emv/emv_pki.c\
emv/emv_pki_priv.c\
emv/emv_roca.c \
emv/emv_tags.c \
emv/emvcore.c \
emv/emvjson.c\
emv/tlv.c \
emv/test/crypto_test.c\
emv/test/cryptotest.c\
emv/test/cda_test.c\
emv/test/dda_test.c\
emv/test/sda_test.c\
fido/additional_ca.c \
fido/cose.c \
fido/cbortools.c \
fido/fidocore.c \
ksx6924/ksx6924core.c \
cipurse/cipursecore.c \
cipurse/cipursecrypto.c \
cipurse/cipursetest.c \
emrtd/emrtd_pace.c \
emrtd/emrtd_pacetest.c \
fileutils.c \
flash.c \
frame_progress.c \
generator.c \
graph.c \
hidsio.c \
jansson_path.c \
jsonutils.c \
iso4217.c \
iso7816/apduinfo.c \
iso7816/iso7816core.c \
loclass/cipher.c \
loclass/cipher_bs.c \
loclass/cipher_bs_avx2.c \
loclass/cipher_bs_avx512.c \
loclass/cipher_bs_dispatch.c \
loclass/cipher_bs_neon.c \
loclass/cipherutils.c \
loclass/elite_crack.c \
loclass/ikeys.c \
lua_bitlib.c \
mifare/lrpcrypto.c \
mifare/desfirecrypto.c \
mifare/desfirecore.c \
mifare/desfiresecurechan.c \
mifare/desfiretest.c \
mifare/gallaghercore.c \
mifare/gallaghertest.c \
mifare/mad.c \
mifare/mad_test.c \
mifare/mfkey.c \
mifare/mifare4.c \
mifare/mifaredefault.c \
mifare/mifarehost.c \
mifare/prime.c \
mifare/gen4.c \
nfc/ndef.c \
parsers/parsehrt.c \
parsers/hrtparser/hrtparser.c \
pm3.c \
pm3_binlib.c \
pm3_bitlib.c \
pm3_dsp.c \
pm3_fit.c \
preferences.c \
pm3line.c \
pm3line_vocabulary.c \
proxmark3.c \
scandir.c \
relay/relay_posix.c \
relay/relay_win32.c \
uart/ringbuffer.c \
uart/uart_common.c \
uart/uart_posix.c \
uart/ble_posix.c \
uart/uart_win32.c \
scripting.c \
ui.c \
util.c \
qrcode/qrcode.c \
version_pm3.c \
wiegand_formats.c \
wiegand_formatutils.c
# common
SRCS += bucketsort.c \
bruteforce.c \
cardhelper.c \
crapto1/crapto1.c \
crapto1/crypto1.c \
crc.c \
crc16.c \
crc32.c \
crc64.c \
commonutil.c \
hitag2/hitag2_crypto.c \
iso15693tools.c \
legic_prng.c \
lfdemod.c \
util_posix.c
ifeq ($(GD_FOUND),1)
# electronic shelf labels
SRCS += imgutils.c \
cmdhfwaveshare.c
endif
# swig
SWIGSRCS =
ifeq ($(SWIG_LUA_FOUND),1)
SWIGSRCS += pm3_luawrap.c
endif
ifeq ($(SWIG_PYTHON_FOUND),1)
SWIGSRCS += pm3_pywrap.c
endif
# gui
ifeq ($(QT_FOUND),1)
CXXSRCS = proxgui.cpp proxguiqt.cpp proxguiqt.moc.cpp
# Qt has no JPEG2000 image handler, so we decode EF_DG2 & friends ourselves
SRCS += imgjp2.c
# openjpeg.a is a static lib, avoid __declspec(dllimport) on its Windows API decls
PM3CFLAGS += -DOPJ_STATIC
STATICLIBS += $(OPENJPEGLIB)
LDLIBS += $(OPENJPEGLIBLD)
else
CXXSRCS = guidummy.cpp
endif
# OS X & iOS
ifdef IS_DARWIN
OBJCSRCS = util_darwin.m
endif
OBJS = $(SRCS:%.c=$(OBJDIR)/%.o)
OBJS += $(SWIGSRCS:%.c=$(OBJDIR)/%.o)
OBJS += $(CXXSRCS:%.cpp=$(OBJDIR)/%.o)
OBJS += $(OBJCSRCS:%.m=$(OBJDIR)/%.o)
BINS = proxmark3
CLEAN = $(BINS) src/version_pm3.c src/*.moc.cpp src/ui/ui_overlays.h src/ui/ui_image.h lualibs/pm3_cmd.lua lualibs/mfc_default_keys.lua
# transition: cleaning also old path stuff
CLEAN += flasher *.moc.cpp ui/ui_overlays.h ui/ui_image.h
###########
# targets #
###########
# need to assign dependancies to build these first...
all: $(BINS)
all-static: LDLIBS:=-static $(LDLIBS)
all-static: $(BINS)
proxmark3: $(OBJS) $(STATICLIBS) lualibs/pm3_cmd.lua lualibs/mfc_default_keys.lua
$(info [=] CXX $@)
# $(Q)$(CXX) $(PM3LDFLAGS) $(OBJS) $(STATICLIBS) $(LDLIBS) -o $@
$(Q)$(CXX) $(PM3CFLAGS) $(PM3LDFLAGS) $(OBJS) $(STATICLIBS) $(LDLIBS) -o $@
src/proxgui.cpp: src/ui/ui_overlays.h src/ui/ui_image.h
src/proxguiqt.cpp: src/proxguiqt.h
src/proxguiqt.moc.cpp: src/proxguiqt.h
$(info [-] MOC $@)
$(Q)$(MOC) -o$@ $^
src/proxguiqt.h: src/ui/ui_overlays.h src/ui/ui_image.h
src/ui/ui_overlays.h: src/ui/overlays.ui
$(info [-] UIC $@)
$(Q)$(UIC) $^ > $@
# fix the header generated by some Qt6 versions (seen on 6.4.2 & 6.6.3)
ifdef IS_DARWIN
$(Q)sed -E -i '' 's/&QLabel::setNum);/qOverload<int>(\&QLabel::setNum));/g' $@
else
$(Q)sed -i 's/&QLabel::setNum);/qOverload<int>(\&QLabel::setNum));/g' $@
endif
src/ui/ui_image.h: src/ui/image.ui
$(info [-] UIC $@)
$(Q)$(UIC) $^ > $@
lualibs/pm3_cmd.lua: ../include/pm3_cmd.h
$(info [=] GEN $@)
$(Q)awk -f pm3_cmd_h2lua.awk $^ > $@
lualibs/mfc_default_keys.lua : mfc_default_keys.dic
$(info [=] GEN $@)
$(Q)awk -f default_keys_dic2lua.awk $^ > $@
clean:
$(Q)$(RM) $(CLEAN)
$(Q)$(RMDIR) $(OBJDIR)
$(Q)$(MAKE) --no-print-directory -C $(AMIIBOLIBPATH) clean
$(Q)$(MAKE) --no-print-directory -C $(CLIPARSERLIBPATH) clean
$(Q)$(MAKE) --no-print-directory -C $(HARDNESTEDLIBPATH) clean
$(Q)$(MAKE) --no-print-directory -C $(ID48LIBPATH) clean
$(Q)$(MAKE) --no-print-directory -C $(JANSSONLIBPATH) clean
ifeq ($(LINENOISE_LOCAL_FOUND), 1)
$(Q)$(MAKE) --no-print-directory -C $(LINENOISELIBPATH) clean
endif
$(Q)$(MAKE) --no-print-directory -C $(LUALIBPATH) clean
$(Q)$(MAKE) --no-print-directory -C $(REVENGLIBPATH) clean
$(Q)$(MAKE) --no-print-directory -C $(OPENJPEGLIBPATH) clean
$(Q)$(MAKE) --no-print-directory -C $(TINYCBORLIBPATH) clean
$(Q)$(MAKE) --no-print-directory -C $(WHEREAMILIBPATH) clean
$(Q)$(MAKE) --no-print-directory -C $(MQTTLIBPATH) clean
@# Just in case someone compiled within these dirs:
$(Q)$(MAKE) --no-print-directory -C $(MBEDTLSLIBPATH) clean
install: all
$(info [@] Installing client to $(DESTDIR)$(PREFIX)...)
ifneq (,$(INSTALLBIN))
$(Q)$(INSTALLSUDO) $(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLBINRELPATH)
$(Q)$(INSTALLSUDO) $(CP) $(INSTALLBIN) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLBINRELPATH)
endif
ifneq (,$(INSTALLSHARE))
$(Q)$(INSTALLSUDO) $(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)
# hack ahead: inject installation path into pm3_resources.py
ifdef IS_DARWIN
$(Q)sed -E -i '' 's|^TOOLS_PATH \?= \?None|TOOLS_PATH="$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)"|' pyscripts/pm3_resources.py
$(Q)sed -E -i '' 's|^DICTS_PATH \?= \?None|DICTS_PATH="$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)/dictionaries"|' pyscripts/pm3_resources.py
$(Q)$(INSTALLSUDO) $(CP) $(INSTALLSHARE) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)
$(Q)sed -E -i '' 's|^TOOLS_PATH \?=.*|TOOLS_PATH = None|' pyscripts/pm3_resources.py
$(Q)sed -E -i '' 's|^DICTS_PATH \?=.*|DICTS_PATH = None|' pyscripts/pm3_resources.py
else
$(Q)sed -i 's|^TOOLS_PATH \?= \?None|TOOLS_PATH="$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)"|' pyscripts/pm3_resources.py
$(Q)sed -i 's|^DICTS_PATH \?= \?None|DICTS_PATH="$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)/dictionaries"|' pyscripts/pm3_resources.py
$(Q)$(INSTALLSUDO) $(CP) $(INSTALLSHARE) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)
$(Q)sed -i 's|^TOOLS_PATH \?=.*|TOOLS_PATH = None|' pyscripts/pm3_resources.py
$(Q)sed -i 's|^DICTS_PATH \?=.*|DICTS_PATH = None|' pyscripts/pm3_resources.py
endif
endif
@true
uninstall:
$(info [@] Uninstalling client from $(DESTDIR)$(PREFIX)...)
ifneq (,$(INSTALLBIN))
$(Q)$(INSTALLSUDO) $(RM) $(foreach tool,$(INSTALLBIN),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLBINRELPATH)$(PATHSEP)$(notdir $(tool)))
endif
ifneq (,$(INSTALLSHARE))
$(Q)$(INSTALLSUDO) $(RMDIR) $(foreach tool,$(INSTALLSHARE),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)$(PATHSEP)$(notdir $(tool)))
endif
@true
tarbin: $(BINS)
$(info [=] TAR ../proxmark3-$(platform)-bin.tar)
$(Q)$(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(BINS:%=client/%) $(WINBINS:%=client/%)
###########################
# local libraries targets #
###########################
$(AMIIBOLIB): .FORCE
$(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C $(AMIIBOLIBPATH) all
$(CLIPARSERLIB): .FORCE
$(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C $(CLIPARSERLIBPATH) all
$(HARDNESTEDLIB): .FORCE
$(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C $(HARDNESTEDLIBPATH) all
$(ID48LIB): .FORCE
$(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C $(ID48LIBPATH) all
$(JANSSONLIB): .FORCE
ifneq ($(JANSSON_FOUND),1)
$(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C $(JANSSONLIBPATH) all
endif
$(LINENOISELIB): .FORCE
ifeq ($(LINENOISE_LOCAL_FOUND), 1)
$(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C $(LINENOISELIBPATH) all
endif
$(LUALIB): .FORCE
ifneq ($(LUA_FOUND),1)
$(info [*] MAKE $@ for $(LUAPLATFORM))
$(Q)$(MAKE) --no-print-directory -C $(LUALIBPATH) $(LUAPLATFORM)
endif
$(MBEDTLSLIB): .FORCE
$(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C $(MBEDTLSLIBPATH) OBJDIR=$(MBEDTLSLIBCLIENTRELPATH)/$(OBJDIR)/mbedtls BINDIR=$(MBEDTLSLIBCLIENTRELPATH)/$(OBJDIR) all
$(REVENGLIB): .FORCE
$(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C $(REVENGLIBPATH) all
$(OPENJPEGLIB): .FORCE
$(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C $(OPENJPEGLIBPATH) all
$(TINYCBORLIB): .FORCE
$(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C $(TINYCBORLIBPATH) all
$(WHEREAMILIB): .FORCE
ifneq ($(WHEREAMI_FOUND),1)
$(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C $(WHEREAMILIBPATH) all
endif
$(MQTTLIB): .FORCE
$(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C $(MQTTLIBPATH) all
########
# SWIG #
########
src/pm3_luawrap.c: pm3.i
$(info [=] GEN $@)
$(Q)$(SWIG) -lua -o $@ $<
src/pm3_pywrap.c: pm3.i
$(info [=] GEN $@)
$(Q)$(SWIG) -python -o $@ $<
########
# misc #
########
.PHONY: all clean install uninstall tarbin .FORCE
# version_pm3.c should be checked on every compilation
src/version_pm3.c: default_version_pm3.c .FORCE
$(info [=] CHECK $@)
$(Q)$(SH) ../tools/mkversion.sh $@ || $(CP) $< $@
# easy printing of MAKE VARIABLES
print-%: ; @echo $* = $($*)
# SWIG files emit a number of warnings, we've to ignore them
%wrap.o: %wrap.c
$(OBJDIR)/%wrap.o : %wrap.c $(OBJDIR)/%.d
$(info [-] CC $<)
$(Q)$(MKDIR) $(dir $@)
$(Q)$(CC) $(DEPFLAGS) $(PM3CFLAGS) -Wno-missing-prototypes -Wno-missing-declarations -Wno-missing-field-initializers -c -o $@ $<
$(Q)$(POSTCOMPILE)
%.o: %.c
$(OBJDIR)/%.o : %.c $(OBJDIR)/%.d
$(info [-] CC $<)
$(Q)$(MKDIR) $(dir $@)
$(Q)$(CC) $(DEPFLAGS) $(PM3CFLAGS) -c -o $@ $<
$(Q)$(POSTCOMPILE)
%.o: %.cpp
$(OBJDIR)/%.o : %.cpp $(OBJDIR)/%.d
$(info [-] CXX $<)
$(Q)$(MKDIR) $(dir $@)
$(Q)$(CXX) $(DEPFLAGS) $(PM3CXXFLAGS) $(CXXINCLUDES) -c -o $@ $<
$(Q)$(POSTCOMPILE)
%.o: %.m
$(OBJDIR)/%.o : %.m $(OBJDIR)/%.d
$(info [-] CC $<)
$(Q)$(MKDIR) $(dir $@)
$(Q)$(CC) $(DEPFLAGS) $(PM3CFLAGS) -c -o $@ $<
$(Q)$(POSTCOMPILE)
DEPENDENCY_FILES = $(patsubst %.c, $(OBJDIR)/%.d, $(SRCS)) \
$(patsubst %wrap.c, $(OBJDIR)/%.d, $(SWIGSRCS)) \
$(patsubst %.cpp, $(OBJDIR)/%.d, $(CXXSRCS)) \
$(patsubst %.m, $(OBJDIR)/%.d, $(OBJCSRCS))
$(DEPENDENCY_FILES): ;
.PRECIOUS: $(DEPENDENCY_FILES)
-include $(DEPENDENCY_FILES)