#-----------------------------------------------------------------------------
# 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.
#-----------------------------------------------------------------------------
ifneq ($(V),1)
  Q?=@
endif
# To see full command lines, use make V=1

# been here
DEFSBEENHERE = true

# USER not defined on some platforms like Archlinux
USER ?= $(shell id -u -n)

CP = cp -a
GZIP = gzip
MKDIR = mkdir -p
RM = rm -f
RMDIR = rm -rf
# rmdir only if dir is empty, tolerate failure
RMDIR_SOFT = -rmdir
MV = mv
TOUCH = touch
FALSE = false
TAR = tar
TARFLAGS ?= -v --ignore-failed-read -r
TARFLAGS += -C .. -f
CROSS  ?= arm-none-eabi-
CC = gcc
CXX = g++
LD = g++
SH = sh
BASH = bash
PERL = perl
SWIG = swig
CC_VERSION = $(shell $(CC) -dumpversion 2>/dev/null|sed 's/\..*//')
CC_VERSION := $(or $(strip $(CC_VERSION)),0)

PATHSEP=/
PREFIX ?=              /usr/local
UDEV_PREFIX ?=         /etc/udev/rules.d
INSTALLBINRELPATH ?=   bin
INSTALLSHARERELPATH ?= share/proxmark3
INSTALLFWRELPATH ?=    share/proxmark3/firmware
INSTALLTOOLSRELPATH ?= share/proxmark3/tools
INSTALLDOCSRELPATH ?=  share/doc/proxmark3

platform = $(shell uname)
DETECTED_OS=$(platform)

ifeq ($(shell $(CC) -v 2>&1 | grep -c "clang version"), 1)
  DETECTED_COMPILER = clang
else
  DETECTED_COMPILER = gcc
endif

ifeq ($(platform),Darwin)
  USE_BREW ?= 1
  USE_MACPORTS ?= 0
  AR= /usr/bin/ar rcs
  RANLIB= /usr/bin/ranlib
else
  AR= ar rcs
  RANLIB= ranlib
endif

ifeq ($(USE_BREW),1)
  BREW_PREFIX = $(shell brew --prefix 2>/dev/null)
  ifeq ($(strip $(BREW_PREFIX)),)
    USE_BREW = 0
  endif
endif

ifeq ($(USE_MACPORTS),1)
  MACPORTS_PREFIX ?= /opt/local
endif

ifeq ($(DEBUG),1)
  DEFCXXFLAGS = -g -O0 -pipe
  DEFCFLAGS = -g -O0 -fstrict-aliasing -pipe
  DEFLDFLAGS =
else
  DEFCXXFLAGS = -Wall -Werror -O3 -pipe
  DEFCFLAGS = -Wall -Werror -O3 -fstrict-aliasing -pipe
  DEFLDFLAGS =
endif

ifeq ($(DEBUG_ARM),1)
  APP_CFLAGS += -g
  SKIP_COMPRESSION=1
endif
# Next ones are activated only if SANITIZE=1
ifeq ($(SANITIZE),1)
  DEFCFLAGS += -g -fsanitize=address -fno-omit-frame-pointer
  DEFCXXFLAGS += -g -fsanitize=address -fno-omit-frame-pointer
  DEFLDFLAGS += -g -fsanitize=address
endif
# Some more warnings we want as errors:
DEFCFLAGS += -Wbad-function-cast -Wredundant-decls -Wmissing-prototypes -Wchar-subscripts -Wshadow -Wundef -Wwrite-strings -Wunused -Wuninitialized -Wpointer-arith -Winline -Wformat -Wformat-security -Winit-self -Wmissing-include-dirs -Wnested-externs -Wmissing-declarations -Wempty-body -Wignored-qualifiers -Wmissing-field-initializers -Wtype-limits -Wold-style-definition
# Some more warnings we need first to eliminate, so temporarely tolerated:
DEFCFLAGS += -Wcast-align -Wno-error=cast-align
DEFCFLAGS += -Wswitch-enum -Wno-error=switch-enum
# GCC 10 has issues with false positives on stringop-overflow, let's disable them for now (cf https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92955, https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94335)
# beware these flags didn't exist for GCC < 7
ifeq ($(shell expr $(CC_VERSION) \>= 10), 1)
  ifneq ($(DETECTED_COMPILER), clang)
    DEFCFLAGS += -Wno-stringop-overflow -Wno-error=stringop-overflow
  endif
endif
ifeq ($(platform),Darwin)
  # their readline has strict-prototype issues
  DEFCFLAGS += -Wno-strict-prototypes
  # some warnings about braced initializers on structs we want to ignore
  DEFCFLAGS += -Wno-missing-braces
else
  DEFCFLAGS += -Wstrict-prototypes
endif

# Next ones are activated only if GCCEXTRA=1 or CLANGEXTRA=1
EXTRACFLAGS =
EXTRACFLAGS += -Wunused-parameter -Wno-error=unused-parameter
EXTRACFLAGS += -Wsign-compare -Wno-error=sign-compare
EXTRACFLAGS += -Wconversion -Wno-error=conversion -Wno-error=sign-conversion -Wno-error=float-conversion

# unknown to clang or old gcc:
# First we activate Wextra then we explicitly list those we know about
# Those without -Wno-error are supposed to be completely solved
GCCEXTRACFLAGS = -Wextra
GCCEXTRACFLAGS += -Wclobbered -Wno-error=clobbered
GCCEXTRACFLAGS += -Wcast-function-type
GCCEXTRACFLAGS += -Wimplicit-fallthrough=3 -Wno-error=implicit-fallthrough
GCCEXTRACFLAGS += -Wmissing-parameter-type
GCCEXTRACFLAGS += -Wold-style-declaration -Wno-error=old-style-declaration
GCCEXTRACFLAGS += -Woverride-init
GCCEXTRACFLAGS += -Wshift-negative-value
GCCEXTRACFLAGS += -Wunused-but-set-parameter -Wno-error=unused-but-set-parameter
ifeq ($(GCCEXTRA),1)
  DEFCFLAGS += $(GCCEXTRACFLAGS) $(EXTRACFLAGS)
endif
# unknown to gcc or old clang:
# First we activate Wextra then we explicitly list those we know about
# Those without -Wno-error are supposed to be completely solved
CLANGEXTRACFLAGS = -Wextra
CLANGEXTRACFLAGS += -Wtautological-type-limit-compare
CLANGEXTRACFLAGS += -Wnull-pointer-arithmetic
CLANGEXTRACFLAGS += -Woverride-init
CLANGEXTRACFLAGS += -Wshift-negative-value
CLANGEXTRACFLAGS += -Wimplicit-fallthrough
ifeq ($(CLANGEXTRA),1)
  DEFCFLAGS += $(CLANGEXTRACFLAGS) $(EXTRACFLAGS)
endif
ifeq ($(CLANGEVERYTHING),1)
  DEFCFLAGS += -Weverything -Wno-error
endif
ifeq ($(NOERROR),1)
  DEFCFLAGS += -Wno-error
endif