#
# Copyright (C) 2012-2023 Intel Corporation.
# SPDX-License-Identifier: MIT
#

###### Common definitions ######

# In this section we place all the generic flags. Later sections provide
# additional flags depending on architecutre, compiler etc.

## General flags

# If we are testing Pin, add some internal checks. Don't do this by default
# since it may incur a performance penatly.
PIN_TESTFLAGS :=
ifeq ($(PIN_TESTING),1)
    PIN_TESTFLAGS += -slow_asserts
endif

#If running on Docker set TARGET_DOCKER
ifneq ($(wildcard /.dockerenv),)
    TARGET_DOCKER := 1
endif

#If running on LXC set TARGET_LXC
ifeq ($(shell which systemd-detect-virt 2>&1 >/dev/null ; echo $$?),0)
ifeq ($(shell systemd-detect-virt | grep lxc >/dev/null; echo $$?),0)
    TARGET_LXC := 1
endif
endif

# Flags to pass to "make" when invoking a .test recipe.
MAKE_TESTFLAGS :=

## Output control

# When cross compiling, the first flag in these variables should be -m32.
# So we wait until the end of the file to define them.
COMP_OBJ :=
COMP_EXE :=
LINK_EXE :=

## Special compilation/linkage directives

ifeq ($(TARGET_OS),mac)
    STATIC :=
else
    STATIC := -static
endif
NO_RANDOM :=
PIC := -fPIC
# There's no concept of compiling a file to be specifically PIE in windows.
NO_PIC := -fno-PIC -fno-pic
PIE := -pie
SSE2 := -msse2
AVX := -mavx
AVX2 := -mavx2
AVX512 := -mavx512f -mavx512pf -mavx512bw -mavx512vl
FP387 := -mfpmath=387 -mno-sse
ASMCPP := -x assembler-with-cpp
NO_STDLIBS := -nostartfiles -nodefaultlibs -nostdlib 
ifeq ($(TARGET_OS),mac)
  EXPORT_ALL := -Wl,-export_dynamic
  EXPORT := -Wl,-exported_symbol,$(GLOBALFUN_PREFIX)
else
  EXPORT_ALL := -Wl,--export-dynamic
  # The following is essentially a no-op for compatibility. It has no effect on the resulting linked file.
  EXPORT := -Wl,--trace-symbol=
endif

# Flags to suppress errors when the linker has trouble solving relocations but they are still valid.
SUPPRESS_RELOCS :=

## Include paths

# COMPONENT_INCLUDES will be defined later in the directory structure section.
# APP_INCLUDES and TOOL_INCLUDES are internal utilities for this file.
APP_INCLUDES :=
TOOL_INCLUDES :=

## Library paths

APP_LPATHS :=
TOOL_LPATHS :=
SATOOL_LPATHS :=
CXX_LPATHS :=

## Libraries to link

ifeq ($(TARGET_OS),mac)
    APP_LIBS := -lm
else
    APP_LIBS := -Wl,--as-needed -lm
endif
ifeq ($(ICC),1)
    LIBPIN_SUFFIX := -icc
else
    LIBPIN_SUFFIX :=
endif
DL_LIB :=
APP_DL_LIB :=
APP_LIB_ATOMIC := -latomic
APP_LIB_XED := -lxed
TOOL_LIBS := -lpin$(LIBPIN_SUFFIX) -lxed
SATOOL_LIBS := -lsapin$(LIBPIN_SUFFIX) -lxed
CXX_LIBS :=

BIONIC_ARCH := x86
ifneq ($(TARGET),ia32)
    BIONIC_ARCH := x86_64
endif

## Compiler flags

# Throughout this file, we only fill in the NOOPT versions of these variables.
# At the bottom of the file, the full versions are built from the NOOPT and
# the relevant optimization and debug flags (see below).
# e.g. APP_CXXFLAGS := $(APP_CXXFLAGS_NOOPT) $(APP_OPT_CXX) $(DBG_INFO_CXX)

# On Unix, ASM_FLAGS is identical to APP_CXXFLAGS, therefore it is built at
# the end of this file, same as APP_CXXFLAGS.

APP_CXXFLAGS_NOOPT :=
TOOL_CXXFLAGS_NOOPT := -Wall -Werror -Wno-unknown-pragmas -DPIN_CRT=1
DLL_CXXFLAGS :=
ENABLE_DEPRECATED := -DPIN_DEPRECATED_WARNINGS=0
CPP11FLAGS := -std=c++11
CPP11LIBS := -Wl,--no-as-needed -lpthread
RTM_FLAGS := -mrtm

## Linker flags

# Throughout this file, we only fill in the NOOPT versions of these variables.
# At the bottom of the file, the full versions are built from the NOOPT and
# the relevant optimization and debug flags (see below).
# e.g. TOOL_LDFLAGS := $(TOOL_LDFLAGS_NOOPT) $(TOOL_OPT_LD) $(DBG_INFO_LD)

APP_LDFLAGS_NOOPT :=
TOOL_LDFLAGS_NOOPT := -shared
SATOOL_LDFLAGS_NOOPT :=
DLL_LDFLAGS := -shared

# Flags to link an executable file from a single assembly file with main() function as entry point.
APP_LDFLAGS_LINK_ASM :=

###### Debugging and optimizations ######

## Utility variables "internal" to this file

# The following variables depend on the user-defined DEBUG variable.
# If DEBUG=1 was specified, no optimizations will be applied and debug
# information will be generated. Otherwise, full optimization will be
# performed and debug information will not be generated.

# On Unix platforms we don't apply any link-time optimizations. The
# variables are defined here for readability.

# On Unix platforms the debug info flags for the compiler and linker
# are the same, we support two different variables for compatibility
# with Windows. This will incur two instances of the "-g" flag when
# compiling most applications with debug information. It's ugly but
# it doesn't do any harm.

ifeq ($(DEBUG),1)
    APP_OPT_CXX := -O0
    APP_OPT_LD :=
    TOOL_OPT_CXX := -O0
    TOOL_OPT_LD :=
    DBG_INFO_CXX := -g
    DBG_INFO_LD := -g
else
    APP_OPT_CXX := -O3
    APP_OPT_LD :=
    TOOL_OPT_CXX := -O3 -fomit-frame-pointer -fno-strict-aliasing
    TOOL_OPT_LD :=
    DBG_INFO_CXX :=
    DBG_INFO_LD :=
endif

## Debugging flags to be used in any makefile.rules file

# The following variables do not depend on the user-defined DEBUG
# variable. When they are used, debug information will always be
# generated.

DBG_INFO_CXX_ALWAYS := -g
DBG_INFO_LD_ALWAYS := -g

###### Additional flags depending on the compiler ######

# These variables are used to determine if the target system has a compiler or not. Some systems, do
# not have a native compiler and we don't want annoying error messages about 'missing cc' etc.
# This check needs to run on the target machine (which may be a remote machine), so we can't use the
# wildcard function, we must use the shell.
CCPATH ?= $(shell which $(CC) 2> /dev/null)
CXXPATH ?= $(shell which $(CXX) 2> /dev/null)
APP_CCPATH ?= $(shell which $(APP_CC) 2> /dev/null)
APP_CXXPATH ?= $(shell which $(APP_CXX) 2> /dev/null)
export CCPATH
export CXXPATH
export APP_CCPATH
export APP_CXXPATH

# This allows us to acquire information about the compiler
ifneq ($(CCPATH),)
    HELPOUT := $(shell $(CC) -v --help 2>&1)
endif

# GLIBC version 2.4 implements the function __stack_chk_fail used by new GCC
# versions when stack-protector is on. Therefore, disable this option (if supported)
ifneq ($(findstring stack-protector,$(HELPOUT)),)
    TOOL_CXXFLAGS_NOOPT += -fno-stack-protector
endif

ifneq ($(findstring -fexceptions,$(HELPOUT))$(findstring -f[no-]exceptions,$(HELPOUT)),)
    TOOL_CXXFLAGS_NOOPT += -fno-exceptions
endif

ifneq ($(findstring -funwind-tables,$(HELPOUT)),)
    TOOL_CXXFLAGS_NOOPT += -funwind-tables
endif

ifneq ($(findstring clang LLVM compiler,$(HELPOUT)),)
    TOOL_CXXFLAGS_NOOPT += -funwind-tables
endif

ifneq ($(findstring -fasynchronous-unwind-tables,$(HELPOUT)),)
    TOOL_CXXFLAGS_NOOPT += -fasynchronous-unwind-tables
endif

ifneq ($(findstring -fno-rtti,$(HELPOUT))$(findstring -frtti,$(HELPOUT)),)
    TOOL_CXXFLAGS_NOOPT += -fno-rtti
endif

ifneq ($(findstring clang LLVM compiler,$(HELPOUT)),)
    TOOL_CXXFLAGS_NOOPT += -Wtypedef-redefinition
endif

# Pin-probe runtime doesn't support the new GNU_HASH style
# First check if the linker used to build the tools support the flag --hash-style.
# In this case set the hash-style to be the old (SYSV) style
ifneq ($(findstring --hash-style,$(HELPOUT)),)
    TOOL_LDFLAGS_NOOPT += -Wl,--hash-style=sysv
    SATOOL_LDFLAGS_NOOPT += -Wl,--hash-style=sysv
endif

ifeq ($(ICC),1)
    # ICC requires some system utilites, this directs it to the right ones.
    # Also, override CXXPATH with the full path to g++. This is correct because the CXXPATH variable
    # is used to determine whether or not to use Pin's cpp libraries (e.g. libstdc++) which depend
    # on the g++ version, not the icpc version.
    ifeq ($(GCCVER),)
        ICC_CXXFLAGS := -gcc-name=/usr/bin/gcc -gxx-name=/usr/bin/g++
        ICC_LDFLAGS := -Qlocation,ld,/usr/bin -gcc-name=/usr/bin/gcc -gxx-name=/usr/bin/g++
        CXXPATH := /usr/bin/g++
    else
	    ICC_CXXFLAGS := -gcc-name=/usr/intel/pkgs/gcc/$(GCCVER)/bin/gcc -gxx-name=/usr/intel/pkgs/gcc/$(GCCVER)/bin/g++
	    ICC_LDFLAGS := -Wl,-rpath=/usr/intel/pkgs/gcc/$(GCCVER)/lib \
	                   -Qlocation,gld,/usr/intel/pkgs/gcc/$(GCCVER)/bin
        CXXPATH := /usr/intel/pkgs/gcc/$(GCCVER)/bin/g++
    endif

    # Enable ICC optimizations
    # ICC splits the called function into 2 different funcs - the actual func that using nonconventional
    # calling standard (args passed in regs), and a func which handle standard calling convention (pass
    # args to regs). Pin is trying to change the last func. To avoid this we disable inter-procedural
    # optimizations. Maybe in ICC 12 we could use -opt-args-in-reg=none
    APP_CXXFLAGS_NOOPT += -inline-level=1 -no-ip $(ICC_CXXFLAGS)
    TOOL_CXXFLAGS_NOOPT += -inline-level=1 -no-ip $(ICC_CXXFLAGS) -fno-builtin
   
    # Add ICC link flags to all linkage flags
    APP_LDFLAGS_NOOPT += $(ICC_LDFLAGS)
    TOOL_LDFLAGS_NOOPT += $(ICC_LDFLAGS)
    APP_LDFLAGS_LINK_ASM += $(ICC_LDFLAGS)

    # Disable warnings
    TOOL_CXXFLAGS_NOOPT += -wd1418 -wd1419 -wd981 -wd383 -wd869 -wd593 -wd266 -wd279 -wd444 -wd168 -wd810 -wd810 \
                           -wd181 -wd1195 -wd168 -wd193 -wd584

    ifeq ($(CCOV),1)
        # code coverage is on
        ifeq ($(findstring "cc/10.",$(ICCDIR)),)
            # icc version >= 11 
            TOOL_LDFLAGS_NOOPT += -prof-gen=srcpos
        else
            # icc version 10
            TOOL_LDFLAGS_NOOPT += -prof-genx
        endif
        ifneq ($(CCOVDIR),)
            TOOL_LDFLAGS_NOOPT += -prof-dir $(CCOVDIR)
        endif
    endif
    CRT_INC_DIR := -I
    
    # Setup runtime environment.
    # ICC requires to have its libraries in LD_LIBRARY_PATH.
    # ICC_LIB_DIR_64 and ICC_LIB_DIR_32 are environment variables set by the validation script.
    ifeq ($(TARGET_OS),linux)
        ifeq ($(TARGET),ia32)
            export LD_LIBRARY_PATH=$$LD_LIBRARY_PATH:$(ICC_LIB_DIR_32)
        else
            export LD_LIBRARY_PATH=$$LD_LIBRARY_PATH:$(ICC_LIB_DIR_64)
        endif
    endif
    
else
    CRT_INC_DIR := -isystem
endif

###### Additional flags depending on directory structure ######

ifeq ($(KIT),1)
    # In the kit tree, the default Pin root is the kit root.
    # However, don't overwrite a user-defined PIN_ROOT definition (if it exists)
    PIN_ROOT ?= ../../..
    PIN_ROOT_ABS := $(shell cd $(PIN_ROOT) && pwd -P)
    XED_ROOT := $(PIN_ROOT)/extras/xed-$(TARGET)
    TOOLS_ROOT := $(PIN_ROOT)/source/tools
    
    COMPONENT_INCLUDES := -I$(PIN_ROOT)/extras/components/include
    TOOL_INCLUDES += -I$(PIN_ROOT)/source/include/pin \
                     -I$(PIN_ROOT)/source/include/pin/gen
    ifeq ($(NEWCPP),1)
            TOOL_INCLUDES += $(CRT_INC_DIR) $(PIN_ROOT_ABS)/extras/cxx/include
    else
            TOOL_INCLUDES += $(CRT_INC_DIR) $(PIN_ROOT_ABS)/extras/stlport/include \
                             $(CRT_INC_DIR) $(PIN_ROOT_ABS)/extras/libstdc++/include
    endif
    TOOL_INCLUDES += $(CRT_INC_DIR) $(PIN_ROOT_ABS)/extras/crt/include \
                     $(CRT_INC_DIR) $(PIN_ROOT_ABS)/extras/crt/include/arch-$(BIONIC_ARCH) \
                     $(CRT_INC_DIR) $(PIN_ROOT_ABS)/extras/crt/include/kernel/uapi \
                     $(CRT_INC_DIR) $(PIN_ROOT_ABS)/extras/crt/include/kernel/uapi/asm-x86
    
    APP_LPATHS += -L$(PIN_ROOT)/extras/components/lib/$(TARGET)
    TOOL_LPATHS += -L$(PIN_ROOT)/$(TARGET)/runtime/pincrt \
                   -L$(PIN_ROOT)/$(TARGET)/lib \
                   -L$(PIN_ROOT)/$(TARGET)/lib-ext
    SATOOL_LPATHS += -L$(PIN_ROOT)/$(TARGET)/runtime/pincrt \
                     -L$(PIN_ROOT)/$(TARGET)/lib \
                     -L$(PIN_ROOT)/$(TARGET)/lib-ext
    TOOL_LDFLAGS_NOOPT += $(PIN_ROOT)/$(TARGET)/runtime/pincrt/crtbeginS.o
    SATOOL_LDFLAGS_NOOPT += $(PIN_ROOT)/$(TARGET)/runtime/pincrt/crtbegin.o
    ifneq ($(filter linux,$(TARGET_OS)),)
        TOOL_LIBS += $(PIN_ROOT)/$(TARGET)/runtime/pincrt/crtendS.o
        SATOOL_LIBS += $(PIN_ROOT)/$(TARGET)/runtime/pincrt/crtend.o
        SATOOL_LDFLAGS_NOOPT += -Wl,-pie
    else
        ifeq ($(TARGET_OS),mac)
            SATOOL_LDFLAGS_NOOPT += -Wl,-no_new_main
        endif
    endif
    
    # If Pin was compiled with icc, tools need to be linked with the libraries below.
    ifeq ($(COMPILER),icc)
        TOOL_LIBS += -limf -lintlc -lirng -lsvml
        SATOOL_LIBS += -limf -lintlc -lirng -lsvml
    endif

    PIN := $(PIN_ROOT)/pin
    PINBIN := $(PIN_ROOT)/$(TARGET)/bin/pinbin
    PIN32 := $(PIN_ROOT)/ia32/bin/pinbin
    PIN64 := $(PIN_ROOT)/intel64/bin/pinbin
    
    VSCRIPT_DIR := $(PIN_ROOT)/source/include/pin
    
    
    ADDITIONAL_CRT_DLL_PATH := $(PIN_ROOT)/$(TARGET)/runtime/pincrt
    ifeq ($(TARGET_OS),mac)
        # macOS* has a different variable for notifying the loader where to look for libraries
        LOADER_LIBRARY_PATH := DYLD_LIBRARY_PATH
        SET_DLL_PATH := export $(LOADER_LIBRARY_PATH)=$(OBJDIR):$(PIN_ROOT)/$(TARGET)/lib-ext:$(PIN_ROOT)/extras/xed-$(TARGET)/lib:$(ADDITIONAL_CRT_DLL_PATH):.:$$$(LOADER_LIBRARY_PATH);
        CLANG_VER_GE_13_0 := $(shell $(TOOLS_ROOT)/Utils/testToolVersion $(CXXPATH) ge 13.0)
        ifeq ($(CLANG_VER_GE_13_0),1)
            TOOL_CXXFLAGS_NOOPT += -Wno-non-c-typedef-for-linkage
        endif
    else
        # Command to set the search path for libraries required by a stand-alone tool.
        # Note that some OSs don't look for SOs in the current directory automatically so we need to add "."
        # to the search path.
        LOADER_LIBRARY_PATH := LD_LIBRARY_PATH
        SET_DLL_PATH := export $(LOADER_LIBRARY_PATH)=$(OBJDIR):$(PIN_ROOT)/$(TARGET)/lib:$(PIN_ROOT)/extras/xed-$(TARGET)/lib:$(ADDITIONAL_CRT_DLL_PATH):.:$$$(LOADER_LIBRARY_PATH);
    endif

else
    PIN_ROOT := ../..
    PIN_ROOT_ABS := $(shell cd $(PIN_ROOT) && pwd -P)
    XED_ROOT := $(PIN_ROOT)/build/Source/xed/xed-$(COMPILER)-pin-$(TARGET_OS)-$(TARGET)/xed-kit
    TOOLS_ROOT := $(PIN_ROOT)/PinTools

	COMPONENT_INCLUDES := -I$(PIN_ROOT)/Source/atomic/00-export-include \
                          -I$(PIN_ROOT)/Source/barecrt/00-export-include \
                          -I$(PIN_ROOT)/Source/sync/00-export-include \
                          -I$(PIN_ROOT)/Source/util/00-export-include
    TOOL_INCLUDES += -I$(TOOLS_ROOT)/Include \
                     -I$(PIN_ROOT)/build/Source/pin/internal-include-$(TARGET_OS)-$(TARGET)
    TOOL_LDFLAGS_NOOPT += $(PIN_ROOT)/build/Source/bionic/libc/export-$(TARGET_OS)-$(HOST_ARCH)-$(TARGET_OS)-$(TARGET)/$(TARGET)/crtbeginS.o
    SATOOL_LDFLAGS_NOOPT += $(PIN_ROOT)/build/Source/bionic/libc/export-$(TARGET_OS)-$(HOST_ARCH)-$(TARGET_OS)-$(TARGET)/$(TARGET)/crtbegin.o
    ifneq ($(filter linux,$(TARGET_OS)),)
        TOOL_LIBS += $(PIN_ROOT)/build/Source/bionic/libc/export-$(TARGET_OS)-$(HOST_ARCH)-$(TARGET_OS)-$(TARGET)/$(TARGET)/crtendS.o
        SATOOL_LIBS += $(PIN_ROOT)/build/Source/bionic/libc/export-$(TARGET_OS)-$(HOST_ARCH)-$(TARGET_OS)-$(TARGET)/$(TARGET)/crtend.o
    else
        ifeq ($(TARGET_OS),mac)
            SATOOL_LDFLAGS_NOOPT += -Wl,-no_new_main
        endif
    endif

    ifeq ($(NEWCPP),1)
        TOOL_INCLUDES += $(CRT_INC_DIR) $(PIN_ROOT_ABS)/Source/bionic/c++/llvm/libcxx/v1
    else
        TOOL_INCLUDES += $(CRT_INC_DIR) $(PIN_ROOT_ABS)/Source/bionic/stlport/stlport
    endif

    TOOL_INCLUDES += $(CRT_INC_DIR) $(PIN_ROOT_ABS)/Source/bionic

    ifneq ($(NEWCPP),1)
        TOOL_INCLUDES += $(CRT_INC_DIR) $(PIN_ROOT_ABS)/Source/bionic/libstdc++/include
    endif

    TOOL_INCLUDES += $(CRT_INC_DIR) $(PIN_ROOT_ABS)/Source/bionic/libc/additional/include \
                     $(CRT_INC_DIR) $(PIN_ROOT_ABS)/Source/bionic/libc/include \
                     $(CRT_INC_DIR) $(PIN_ROOT_ABS)/Source/bionic/libm/include \
                     $(CRT_INC_DIR) $(PIN_ROOT_ABS)/Source/bionic/libc/arch-$(BIONIC_ARCH)/include \
                     $(CRT_INC_DIR) $(PIN_ROOT_ABS)/Source/bionic/libc/kernel/uapi \
                     $(CRT_INC_DIR) $(PIN_ROOT_ABS)/Source/bionic/libc/kernel/uapi/asm-x86 \
                     $(CRT_INC_DIR) $(PIN_ROOT_ABS)/Source/os-apis/00-export-include \
                     $(CRT_INC_DIR) $(PIN_ROOT_ABS)/Source/asm/00-export-include

    ifeq ($(TARGET_OS),mac)
        # extracting the clang version command breakdown:
        # 1. we need only the first line since it contains the version number
        # 2. using sed groups we capture the version in a group "\([0-9].[0-9]\)" and
        #    replace the entire line with the captured group "\1"
        CLANG_VERSION := $(shell $(CXX) --version | head -n 1 | sed 's/Apple LLVM version \([0-9].[0-9]\).*/\1/')
        export CLANG_VERSION
    endif
	
# TBD - this one does not exist anymore - is it relevant?
    APP_LPATHS += -L$(PIN_ROOT)/build/Source/pin/internal-include-$(TARGET_OS)-$(TARGET)/lib
    TOOL_LPATHS += -L$(PIN_ROOT)/build/Source/pin/pin-$(TARGET_OS)-$(TARGET) \
                   -L$(PIN_ROOT)/External/pindwarf/$(TARGET_OS)/$(TARGET)
    SATOOL_LPATHS += -L$(PIN_ROOT)/build/Source/pin/pin-$(TARGET_OS)-$(TARGET) \
                     -L$(PIN_ROOT)/External/pindwarf/$(TARGET_OS)/$(TARGET)
    
# TBD - this one does not exist anymore - is it relevant?
    PINCRT_LIBPATH := $(PIN_ROOT)/build/Source/bionic/stlport/export-$(TARGET_OS)-$(HOST_ARCH)-$(TARGET_OS)-$(TARGET)/$(TARGET) \
                      $(PIN_ROOT)/build/Source/bionic/libm/export-$(TARGET_OS)-$(HOST_ARCH)-$(TARGET_OS)-$(TARGET)/$(TARGET) \
                      $(PIN_ROOT)/build/Source/bionic/libc/export-$(TARGET_OS)-$(HOST_ARCH)-$(TARGET_OS)-$(TARGET)/$(TARGET) \
                      $(PIN_ROOT)/build/Source/bionic/libunwind/export-$(TARGET_OS)-$(HOST_ARCH)-$(TARGET_OS)-$(TARGET)/$(TARGET)
    TOOL_LPATHS += $(foreach dir,$(PINCRT_LIBPATH),-L$(dir))
    SATOOL_LPATHS += $(foreach dir,$(PINCRT_LIBPATH),-L$(dir))
    ifeq ($(TARGET_OS),linux)
        PINCRT_DLPATH := $(PIN_ROOT)/build/Source/bionic/libdl/export-linux-$(HOST_ARCH)-linux-$(TARGET)/$(TARGET)
        TOOL_LPATHS += -L$(PINCRT_DLPATH)
        SATOOL_LPATHS += -L$(PINCRT_DLPATH)
    endif
    PIN := $(PIN_ROOT)/Source/pin/pin-runner-$(TARGET_OS)-$(TARGET).sh
	
    PINBIN := $(PIN_ROOT)/build/Source/pin/pin-$(TARGET_OS)-$(TARGET)/pin
    PIN32 := $(PIN_ROOT)/build/Source/pin/pin-$(TARGET_OS)-ia32/pin
    PIN64 := $(PIN_ROOT)/build/Source/pin/pin-$(TARGET_OS)-intel64/pin
	
    VSCRIPT_DIR := $(TOOLS_ROOT)/Include
endif

TOOL_INCLUDES += $(COMPONENT_INCLUDES) \
                 -I$(XED_ROOT)/include/xed \
                 -I$(TOOLS_ROOT)/Utils \
                 -I$(TOOLS_ROOT)/InstLib
APP_INCLUDES += -I$(TOOLS_ROOT)/Utils

APP_LPATHS += -L$(XED_ROOT)/lib
TOOL_LPATHS += -L$(XED_ROOT)/lib
SATOOL_LPATHS += -L$(XED_ROOT)/lib

ifeq ($(TARGET_OS),linux)
    DWARF_LIBS := -lpindwarf -ldwarf
else
    DWARF_LIBS := -lpin3dwarf
endif

###### Additional flags depending on architecture ######

ifeq ($(TARGET),ia32)
    APP_CXXFLAGS_NOOPT += -DTARGET_IA32 -DHOST_IA32 -DFUND_TC_TARGETCPU=FUND_CPU_IA32 -DFUND_TC_HOSTCPU=FUND_CPU_IA32
    TOOL_CXXFLAGS_NOOPT += -DTARGET_IA32 -DHOST_IA32
    
    # cross compilation
    ifeq ($(HOST_ARCH),intel64)
        COMP_OBJ += -m32
        COMP_EXE += -m32
        LINK_EXE += -m32
    endif
endif

ifeq ($(TARGET),intel64)
    APP_CXXFLAGS_NOOPT += -DTARGET_IA32E -DHOST_IA32E -DFUND_TC_TARGETCPU=FUND_CPU_INTEL64 -DFUND_TC_HOSTCPU=FUND_CPU_INTEL64
    TOOL_CXXFLAGS_NOOPT += -DTARGET_IA32E -DHOST_IA32E -fPIC
    DLL_CXXFLAGS += -fPIC
endif

###### Additional flags depending on OS ######

ifeq ($(TARGET_OS),linux)
    NO_PIE := -no-pie
    APP_CXXFLAGS_NOOPT += -DTARGET_LINUX -DFUND_TC_TARGETOS=FUND_OS_LINUX -DFUND_TC_HOSTOS=FUND_OS_LINUX
    ifeq ($(shell $(CC) -v 2>&1 | $(QGREP) " --enable-default-pie " && echo default-pie),default-pie)
        LDFLAGS_DEFAULT_NO_PIE := $(NO_PIE)
    endif
    APP_LDFLAGS_NOOPT += $(LDFLAGS_DEFAULT_NO_PIE)
    TOOL_CXXFLAGS_NOOPT += -DTARGET_LINUX


    DL_LIB += -ldl-dynamic
    APP_DL_LIB += -ldl
    APP_LIBS += -ldl -lpthread
    TOOL_LIBS += $(DWARF_LIBS) $(DL_LIB)
    SATOOL_LIBS += $(DWARF_LIBS) $(DL_LIB)
    TOOL_LDFLAGS_NOOPT += -Wl,-Bsymbolic -Wl,--version-script=$(VSCRIPT_DIR)/pintool.ver

    SATOOL_LDFLAGS_NOOPT += -Wl,-Bsymbolic
    DWARF4 += -gdwarf-4

    ifeq ($(COMPILER),icx)
        TOOL_CXXFLAGS_NOOPT  += -DICX -D_LIBCPP_DISABLE_AVAILABILITY -fno-builtin-bcmp -Wno-non-c-typedef-for-linkage -fPIC
        TOOL_LDFLAGS_NOOPT   += -DICX -D_LIBCPP_DISABLE_AVAILABILITY -Wno-non-c-typedef-for-linkage -Wl,--hash-style=sysv
        SATOOL_LDFLAGS_NOOPT += -DICX -D_LIBCPP_DISABLE_AVAILABILITY -Wno-non-c-typedef-for-linkage
        APP_LDFLAGS_NOOPT += $(NO_PIE)
    else
        TOOL_CXXFLAGS_NOOPT  += -fabi-version=2
        TOOL_LDFLAGS_NOOPT   += -fabi-version=2
        SATOOL_LDFLAGS_NOOPT += -fabi-version=2
    endif

    # Add -faligned-new flag for gcc >= 7.0. This flag enables C++17 support for dynamic
    # allocation (using new operator) of an object that has alignment requirement that is
    # larger then the default for the system
    GCC_VER_LOWER_THAN_7 := $(shell $(TOOLS_ROOT)/Utils/testToolVersion $(CXXPATH) lt 7.0)
    ifeq ($(GCC_VER_LOWER_THAN_7),0)
        # GCC version >= 7.0
        TOOL_CXXFLAGS_NOOPT += -faligned-new
    endif

    DIST_NAME_FEDORA := $(shell $(TOOLS_ROOT)/Utils/testLinuxDistName eq fedora)
    DIST_NAME_RHEL = $(shell $(TOOLS_ROOT)/Utils/testLinuxDistName eq rhel)
    ifeq ($(DIST_NAME_RHEL),0)
        DIST_NAME_RHEL = $(shell $(TOOLS_ROOT)/Utils/testLinuxDistName has redhat)
    endif
    DIST_NAME_SUSE := $(shell $(TOOLS_ROOT)/Utils/testLinuxDistName has opensuse)
    DIST_NAME_SLES := $(shell $(TOOLS_ROOT)/Utils/testLinuxDistName has sles)
    DIST_NAME_UBUNTU := $(shell $(TOOLS_ROOT)/Utils/testLinuxDistName eq ubuntu)
    DIST_NAME_CENTOS := $(shell $(TOOLS_ROOT)/Utils/testLinuxDistName eq centos)
    DIST_NAME_OPENSUSE := $(shell $(TOOLS_ROOT)/Utils/testLinuxDistName eq opensuse-leap)

    CET_ENABLED := $(shell $(TOOLS_ROOT)/Utils/testLinuxIsCetEnabled)

    # On Fedora version 28 and up, on RedHat 8 and up,
    # on CentOS 8 and up and on Ubuntu 20.10 and up,
    # on SLES 15.3 and up and on OpenSUSE Leap 15.3 and up -
    # the RPC Interfaces have been removed from glibc.
    # An additional package is installed to provide the RPC interface.
    # The include path and library from the additional package are specified by the 
    # RPC_INCLUDES and RPC_LIBS variables
    RPC_INCLUDES :=
    RPC_LIBS := 
    ifeq ($(DIST_NAME_FEDORA),1)
        DIST_VER_GE_28 := $(shell $(TOOLS_ROOT)/Utils/testLinuxDistVersion ge 28)
        ifeq ($(DIST_VER_GE_28),1)
            RPC_INCLUDES += -I/usr/include/tirpc
            RPC_LIBS += -ltirpc
        endif
    endif
    ifeq ($(DIST_NAME_RHEL),1)
        DIST_VER_GE_8 := $(shell $(TOOLS_ROOT)/Utils/testLinuxDistVersion ge 8)
        ifeq ($(DIST_VER_GE_8),1)
            RPC_INCLUDES += -I/usr/include/tirpc
            RPC_LIBS += -ltirpc
        endif
    endif
    ifeq ($(DIST_NAME_CENTOS),1)
        DIST_VER_GE_8 := $(shell $(TOOLS_ROOT)/Utils/testLinuxDistVersion ge 8)
        ifeq ($(DIST_VER_GE_8),1)
            RPC_INCLUDES += -I/usr/include/tirpc
            RPC_LIBS += -ltirpc
        endif
    endif
    ifeq ($(DIST_NAME_UBUNTU),1)
        DIST_VER_GE_20_10 := $(shell $(TOOLS_ROOT)/Utils/testLinuxDistVersion ge 20.10)
        ifeq ($(DIST_VER_GE_20_10),1)
            RPC_INCLUDES += -I/usr/include/tirpc
            RPC_LIBS += -ltirpc
        endif
    endif
    ifeq ($(DIST_NAME_SLES),1)
        DIST_VER_GE_15_3 := $(shell $(TOOLS_ROOT)/Utils/testLinuxDistVersion ge 15.3)
        ifeq ($(DIST_VER_GE_15_3),1)
            RPC_INCLUDES += -I/usr/include/tirpc
            RPC_LIBS += -ltirpc
        endif
    endif
    ifeq ($(DIST_NAME_OPENSUSE),1)
        DIST_VER_GE_15_3 := $(shell $(TOOLS_ROOT)/Utils/testLinuxDistVersion ge 15.3)
        ifeq ($(DIST_VER_GE_15_3),1)
            RPC_INCLUDES += -I/usr/include/tirpc
            RPC_LIBS += -ltirpc
        endif
    endif
endif
ifeq ($(TARGET_OS),mac)
    NO_PIE := -Wl,-no_pie
    LDFLAGS_DEFAULT_NO_PIE := $(NO_PIE)
    APP_LDFLAGS_NOOPT += $(LDFLAGS_DEFAULT_NO_PIE)
    APP_CXXFLAGS_NOOPT += -DTARGET_MAC -DFUND_TC_TARGETOS=FUND_OS_MAC -DFUND_TC_HOSTOS=FUND_OS_MAC
    TOOL_CXXFLAGS_NOOPT += -DTARGET_MAC -D__DARWIN_ONLY_UNIX_CONFORMANCE=1 -D__DARWIN_UNIX03=0 $(MAC_CXXLIB)
    APP_LIBS += -lpthread
    TOOL_LIBS += $(DWARF_LIBS)
    SATOOL_LIBS += $(DWARF_LIBS)
    TOOL_LDFLAGS_NOOPT += -w -Wl,-exported_symbols_list,$(VSCRIPT_DIR)/pintool.exp $(MAC_CXXLIB)
    SATOOL_LDFLAGS_NOOPT += -w -Wl,-exported_symbols_list,$(VSCRIPT_DIR)/pintool.exp $(MAC_CXXLIB)
    # XED is built using libstdc++, if we want to link against it in Mavericks we must explicitly
    # require using libstdc++ instead of libc++ (introduced in 10.9).
    APP_LIB_XED += $(MAC_CXXLIB)
    # macOS* has a different compare program, so override CMP.
    # This is done here instead of unix.vars since it depends on TOOLS_ROOT which is defined in this file (above).
    CMP := cmp
	ifeq ($(TARGET),ia32)
		SUPPRESS_RELOCS := -Wl,-read_only_relocs,suppress
	endif 
	SIP_ENABLED = $(shell csrutil status | grep enabled >/dev/null && echo 1 || echo 0)
endif

ifeq ($(NEWCPP),1)
    TOOL_LIBS += -nostdlib -lc++ -lc++abi -lm-dynamic -lc-dynamic -lunwind-dynamic
    SATOOL_LIBS += -nostdlib -lc++ -lc++abi -lm-dynamic -lc-dynamic -lunwind-dynamic
else
    TOOL_LIBS += -nostdlib -lstlport-dynamic -lm-dynamic -lc-dynamic -lunwind-dynamic
    SATOOL_LIBS += -nostdlib -lstlport-dynamic -lm-dynamic -lc-dynamic -lunwind-dynamic
endif

###### Finalize flags ######

## Output control

COMP_OBJ += -c -o 
COMP_EXE += -o 
LINK_EXE += -o 

## Compiler and linker flags

# First define the assembler flags - they do not require any additional include paths.
ASM_FLAGS := $(APP_CXXFLAGS_NOOPT) $(ASMCPP) $(TOOL_INCLUDES)

# Now add the include paths to the compilation flags.
APP_CXXFLAGS_NOOPT += $(APP_INCLUDES)
TOOL_CXXFLAGS_NOOPT += $(TOOL_INCLUDES)

# Define the versions containing the full options
APP_CXXFLAGS := $(APP_CXXFLAGS_NOOPT) $(APP_OPT_CXX) $(DBG_INFO_CXX)
APP_LDFLAGS := $(APP_LDFLAGS_NOOPT) $(APP_OPT_LD) $(DBG_INFO_LD)
TOOL_CXXFLAGS := $(TOOL_CXXFLAGS_NOOPT) $(TOOL_OPT_CXX) $(DBG_INFO_CXX)
TOOL_CFLAGS := $(filter-out -fno-rtti -fno-exception -faligned-new,$(TOOL_CXXFLAGS))
TOOL_LDFLAGS := $(TOOL_LDFLAGS_NOOPT) $(TOOL_OPT_LD) $(DBG_INFO_LD)
SATOOL_LDFLAGS := $(SATOOL_LDFLAGS_NOOPT) $(TOOL_OPT_LD) $(DBG_INFO_LD)
ifeq ($(TARGET_OS),linux)
    ifneq ($(COMPILER),icx)
        TOOL_CXXFLAGS += -Wno-dangling-pointer
    endif
    VERSION_SCRIPT_PATTERN := -Wl,--version-script=%
    TOOL_LIBRARY_LDFLAGS_NOOPT := $(filter-out $(VERSION_SCRIPT_PATTERN),$(TOOL_LDFLAGS_NOOPT))
endif
ifeq ($(TARGET_OS),mac)
    TOOL_EXPORT_SYMBOLS_PATTERN := -w -Wl,-exported_symbols_list,$(VSCRIPT_DIR)/pintool.exp
    TOOL_LIBRARY_LDFLAGS_NOOPT := $(filter-out $(TOOL_EXPORT_SYMBOLS_PATTERN),$(TOOL_LDFLAGS_NOOPT))
    # This makes sure -no_new_main linker flag we add is respected and not ignored by the compiler (See mantis #4841)
    SATOOL_LDFLAGS += -mmacosx-version-min=10.7
endif

# Add debugging flags to the NOOPT versions and disable optimizations
APP_CXXFLAGS_NOOPT += -O0 $(DBG_INFO_CXX)
APP_LDFLAGS_NOOPT += $(DBG_INFO_LD)
TOOL_CXXFLAGS_NOOPT += -O0 $(DBG_INFO_CXX)
TOOL_LDFLAGS_NOOPT += $(DBG_INFO_LD)

# Tool's compiler options for static analysis tools
SATOOL_CXXFLAGS_NOOPT := $(TOOL_CXXFLAGS_NOOPT)
SATOOL_CXXFLAGS := $(TOOL_CXXFLAGS)

## Pin program finalization:

# Add any additional flags that the user specified to the Pin command line.
PIN += $(PIN_TESTFLAGS) $(PINFLAGS)
