# This file is part of the Astrometry.net suite.
# Licensed under a 3-clause BSD style license - see LICENSE

INCLUDE_BASE_DIR := $(BASEDIR)/include
INCLUDE_DIR := $(INCLUDE_BASE_DIR)/astrometry

PYTHON ?= python
INSTALL_DIR ?= /usr/local/astrometry
# Put INSTALL_DIR in the environment of commands run by Make.
export INSTALL_DIR

# don't change this one -- it must match what is in the bin/* scripts.
PYTHON_SCRIPT_DEFAULT := /usr/bin/env python

# change this if you want to set exactly which python program gets run to
# execute the python scripts in bin/ (image2pnm and friends).
# Note that this must be a full path (this is a bash requirement).
PYTHON_SCRIPT ?= $(PYTHON_SCRIPT_DEFAULT)
# eg,
#PYTHON_SCRIPT ?= /usr/bin/python3.5

# Installation subdirs

PY_BASE_INSTALL_DIR ?= $(INSTALL_DIR)/lib/python/astrometry
INCLUDE_INSTALL_DIR := $(INSTALL_DIR)/include/astrometry
LIB_INSTALL_DIR := $(INSTALL_DIR)/lib
BIN_INSTALL_DIR := $(INSTALL_DIR)/bin
DATA_INSTALL_DIR := $(INSTALL_DIR)/data
PY_BASE_LINK_DIR := ../lib/python/astrometry
ETC_INSTALL_DIR ?= $(INSTALL_DIR)/etc
MAN1_INSTALL_DIR ?= $(INSTALL_DIR)/share/man/man1
DOC_INSTALL_DIR ?= $(INSTALL_DIR)/doc
EXAMPLE_INSTALL_DIR ?= $(INSTALL_DIR)/examples

# If your build system stages an install in one place (say, a temp
# dir) and then copies everything to the final install place, (eg,
# debian), set *_INSTALL_DIR to the staging place and *_FINAL_DIR to
# the final destination directory.

# This should rarely be used, since hardly anything should care that
# it's going to be moved after being staged.
# (ie, the only place it's used at the moment is in blind/Makefile when
#  putting the final data directory in the config file etc/astrometry.cfg)

FINAL_DIR ?= $(INSTALL_DIR)
DATA_FINAL_DIR ?= $(FINAL_DIR)/data


# only set CC if it hasn't already been set
# (this allows the user to override it)
## can't use "CC ?= gcc" because CC gets a default value
ifeq ($(origin CC), default)
  CC := gcc
endif

# no default rules
.SUFFIXES :=

# These are files
%.py: ;
%.i: ;
%.c: ;
%.h: ;
%.awk: ;
%.inc: ;
%.ph: ;
makefile.%: ;
Makefile: ;

# Cancel stupid implicit rules.
%: %,v
%: RCS/%,v
%: RCS/%
%: s.%
%: SCCS/s.%

# sh shell
AN_SHELL ?= /bin/sh

RANLIB ?= ranlib

AWK ?= LC_ALL=C LC_NUMERIC=EN_US awk

SED ?= sed

MV ?= mv

CP ?= cp

CHMOD_EXECUTABLE ?= chmod 755

MKDIR ?= mkdir -p

FLAGS_DEF := -g -Wall

TMPFILE := cc-out.tmp

# Test whether $(CC) accepts a particular argument; set ARG before running.

#CCTEST = $(CC) -x c -c -o $(TMPFILE) $(ARG) - < /dev/null > /dev/null 2> /dev/null && echo $(ARG)

# On MacOS, unrecognized gcc args don't cause it to return 1... look for error messages on stderr.
# Intel icc/13 says: icc: command line warning #10006: ignoring unknown option '-fno-signaling-nans'
CCTEST = $(CC) -x c -c -o $(TMPFILE) $(ARG) - 2>&1 > /dev/null < /dev/null | grep "unrecognized\|invalid\|error:\|warning" > /dev/null || echo $(ARG)

LINKTEST = $(CC) -x c -o $(TMPFILE) $(ARG) - 2>&1 > /dev/null < /dev/null | grep "unrecognized\|invalid\|error:\|warning:" > /dev/null || echo $(ARG)

#PROGLINKTEST = echo "int main() { return 0; }" | $(CC) -x c -o $(TMPFILE).o - && $(CC) -o $(TMPFILE) $(TMPFILE).o $(ARG) 2>&1 > /dev/null | grep "unrecognized\|invalid\|error:\|warning:" > /dev/null || echo $(ARG)

#CCTEST = $(CC) -x c -c -o $(TMPFILE) $(ARG) - 2>&1 < /dev/null | tee "CCTEST-$(ARG)" | grep "unrecognized\|invalid\|error:" > /dev/null || echo $(ARG)
# Test whether a particular string appears in the compiler's default environment;
# set STR before running.
DEFTEST = $(CC) -dM -E - < /dev/null 2> /dev/null | grep "$(STR)" > /dev/null

ARG := -shared
SHAREDLIBFLAGS_DEF := $(shell $(LINKTEST))
SHAREDLIB_SUFFIX = so

# Cygwin peculiarities:
# --.dll filename suffix for shared libraries (created by python distutils)
# -- -fPIC produces warnings

UNAME = $(shell uname -s)
ifneq (CYGWIN,$(findstring CYGWIN,$(UNAME)))
  SHAREDLIBFLAGS_DEF += -fPIC
endif 

# Get the library suffix used by python distutils (.dll on cygwin, .so elsewhere for py2; .PLATFORM.so for py3)
PYTHON_SO_EXT ?= $(shell $(PYTHON) -c "from distutils import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX') or sysconfig.get_config_var('SO'))")

# Set a default, otherwise terrible things happen:
#   in util/Makefile : clean: rm -f *$(PYTHON_SO_EXT)
ifeq ($(PYTHON_SO_EXT)x,x)
  PYTHON_SO_EXT := .so
endif

# gcc 5.1 changes inline semantics
#ARG := -std=gnu89
#FLAGS_DEF += $(shell $(CCTEST))
# Handled in keywords.h instead

#ARG := -Wno-error=unused-command-line-argument-hard-error-in-future
#FLAGS_DEF += $(shell $(CCTEST))

ARG := -ffinite-math-only
FLAGS_DEF += $(shell $(CCTEST))

# clang: warning: argument unused during compilation: '-fno-signaling-nans'
ARG := -fno-signaling-nans
FLAGS_DEF += $(shell $(CCTEST))

# gcc non-IEEE faster math
#ARG := -ffast-math
#FLAGS_DEF += $(shell $(CCTEST))

# gcc 3.3 on Mac doesn't support -pthread
# clang 4.1: warns about including -pthread
ARG := -pthread
FLAGS_DEF += $(shell $(CCTEST))

# Avoid "undefined reference to `isfinite'" on gcc 4.7.0 (carver)
#ARG := -std=c99
#FLAGS_DEF += $(shell $(CCTEST))

## Below, we try to guess good compiler flags for this CPU / architecture.
## If we make an incorrect choice -- ie, the code fails in some way on the
## machine on which it was compiled, please let us know by posting at
##    astrometry.net/group
## If you want to override this setting, you can set the
##      ARCH_FLAGS
## environment variable in your shell.
## With gcc 4.2 and later, gcc should be able to make the optimal choice on its own.
## See the README section "I wanna go fast!" for more details.
ifneq ($(origin ARCH_FLAGS),undefined)
  FLAGS_DEF += $(ARCH_FLAGS)
else
  # Try to guess some good compiler flags for this CPU.

  # Use -march=native if it's available (gcc 4.2 and above)
  ARG := -march=native
  X := $(shell $(CCTEST))
  ifneq ($(X),)
    FLAGS_DEF += $(X)
  else
    # Try to guess -march
    MACHINE:=$(shell uname -m)
    ifeq ($(MACHINE), i686)
      # gcc before version 3.1 doesn't support "pentium4"; use "i686" instead.

      ARG := -march=pentium4
      X := $(shell $(CCTEST))
      ifneq ($(X),)
        STR := \#define __tune_pentium4__ 1
        FLAGS_DEF += $(shell $(DEFTEST) && echo "-march=pentium4" \
                                        || echo "-march=i686")
      else
        ARG := -march=i686
        FLAGS_DEF += $(shell $(CCTEST))
      endif

    else
      # make 3.79 doesn't allow multiple "else" statements, so nest 'em.
      ifeq ($(MACHINE), x86_64)
        STR := \#define __tune_k8__ 1
        FLAGS_DEF += $(shell $(DEFTEST) && echo "-march=k8")
          FLAGS_DEF += -m64
      else # ppc, ...
        FLAGS_DEF += -DNOT_686

      endif

    endif
  endif

endif

STR := __APPLE__
X := $(shell $(DEFTEST) && echo "-DNOBOOL")

ifneq ($(X),)
  # Darwin does dynamic libs differently
  ARG := -dynamic
  X := $(shell $(LINKTEST))
  SHAREDLIBFLAGS_DEF += $(X)

  # clang 3.1 wants...
  ARG := -dynamic -dynamiclib
  X :+ $(shell $(LINKTEST))
  SHAREDLIBFLAGS_DEF += $(X)

  # clang 4.1 doesn't support -dynamiclib
  ARG := -dynamiclib
  X := $(shell $(LINKTEST))
  SHAREDLIBFLAGS_DEF += $(X)

  # clang 4.1 seems to need this instead:
  ARG := -Wl,-dylib
  X := $(shell $(LINKTEST))
  SHAREDLIBFLAGS_DEF += $(X)

  ARG := -pthread
  X := $(shell $(LINKTEST))
  SHAREDLIBFLAGS_DEF += $(X)

endif

# delete temp files that may have been generated by the above tests.
X := $(shell rm -f $(TMPFILE))

# FLAGS_DEF are gcc flags that are shared between compiling and
# linking.  CFLAGS_DEF are compile flags, LDFLAGS_DEF are link flags.

# Turn optimization on by default; this statement only sets OPTIMIZE
# if it hasn't been set already (eg, in ../Makefile)
OPTIMIZE ?= yes
PROFILE ?= no
ASSERT ?= -DNDEBUG

ifeq ($(PROFILE),yes)
  FLAGS_DEF += -O2
  FLAGS_DEF += -pg -g
  FLAGS_DEF += $(ASSERT)
else

ifeq ($(OPTIMIZE),yes)
  # speedy!
  FLAGS_DEF += -O3
  FLAGS_DEF += -fomit-frame-pointer
  # turn off asserts:
  FLAGS_DEF += $(ASSERT)

else
  ifeq ($(OPTIMIZE),no)
    # debuggy!
    FLAGS_DEF += -O0
    FLAGS_DEF += -g
  endif

endif

endif

ifneq (CYGWIN,$(findstring CYGWIN,$(UNAME)))
FLAGS_DEF += -fpic
endif

# profily!
#FLAGS_DEF += -pg

## FIXME DEBUG
#FLAGS_DEF += -fstrict-aliasing -std=c99
#FLAGS_DEF += -Wstrict-aliasing
# More strict aliasing warnings; possible false positives.
#FLAGS_DEF += -Wstrict-aliasing=2

# Put inlined function definitions in .o files.
# FLAGS_DEF += -fkeep-inline-functions

FLAGS_DEF += -Winline


# If user set FLAGS, use those rather than FLAGS_DEF.
ifneq ($(origin FLAGS),undefined)
  FLAGS_DEF := $(FLAGS)
endif

# fold in the user's CFLAGS, if set...
CFLAGS_DEF := $(CFLAGS) $(FLAGS_DEF)
CFLAGS_DEF += -I$(INCLUDE_BASE_DIR)
CFLAGS_DEF += -I$(INCLUDE_DIR)
CFLAGS_DEF += -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
CFLAGS_DEF += -D_GNU_SOURCE

#ARG := -pthread
#CFLAGS_DEF += $(shell $(CCTEST))


#CFLAGS_DEF += -Wextra
#CFLAGS_DEF += -Wpointer-arith
#CFLAGS_DEF += -fmudflap
#LDFLAGS_DEF += -lmudflap

# What functions were and weren't inlined?
#CFLAGS_DEF += -Winline

# Print header files that are included
#CFLAGS_DEF += -H

# fold in the user's LDFLAGS, if set...
LDFLAGS_DEF := $(LDFLAGS) $(FLAGS_DEF)

#ARG := -pthread
#LDFLAGS_DEF += $(shell $(PROGLINKTEST))

LDLIBS_DEF := $(LDLIBS)

# Make's default link recipe is:
#    $(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)
# and some linkers demand that libraries appear *after* the object files,
# so if you want a lib always linked in, add it to LDLIBS.

# Provide for executable programs and FITS headers 
# GIT fields: revision, date and url via CFLAGS.
# These fields replace the deprecated SVN fields.
AN_GIT_REVISION := 0.73
AN_GIT_DATE := Thu_Nov_16_08:30:44_2017_-0500
AN_GIT_URL := https://github.com/dstndstn/astrometry.net

CFLAGS_DEF += -DAN_GIT_REVISION='"$(AN_GIT_REVISION)"'
CFLAGS_DEF += -DAN_GIT_DATE='"$(AN_GIT_DATE)"'
CFLAGS_DEF += -DAN_GIT_URL='"$(AN_GIT_URL)"'

