#***************************************************************************************************
#                                             Makefile                                             *
#                                            ----------                                            *
# Description : Build system for the GNU SPICE GUI project C++ source files.                       *
# Started     : 2003-03-18                                                                         *
# Last update : 2018-11-04                                                                         *
# Copyright   : (C) 2003-2018 MSWaters                                                             *
#***************************************************************************************************

#***************************************************************************************************
#                                                                                                  *
#       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.                    *
#                                                                                                  *
#***************************************************************************************************

#***************************************************************************************************
# Any or all of the values in this section may be set below or on the command line when envoking
# make eg. :
#
#   make GSPICEUI_DEBUG=1 GSPICEUI_WXLIB=2.8 GSPICEUI_MSWIN=1
#
# Note : Values specified on the command line over-ride those specified below.
#***************************************************************************************************

# Create bin file containing debug information (ie. for gdb) and enable debug code
GSPICEUI_DEBUG = 0

# Specify the version of the wxWidgets library to compile against
GSPICEUI_WXLIB = 3.0

# Specify if the host operating system is MS Windows
GSPICEUI_MSWIN = 0

# Specify the install directory
DESTDIR = /usr/local/bin

# This is a temporary switch for implementing layout managers in the analysis panels. It's bad not
# using a layout manager but that's how it's done at present. I've invented the this pre-processor
# flag "LAYOUT_MNGR" to help transition to full use of layout managers. The idea is to switch
# between layout manager and hard coded layout. Ie. keep the hard coded layout code until I'm sure
# the new layout manager code works.
LAYOUT_MNGR = 1

#***************************************************************************************************
# Specify string values
#***************************************************************************************************

# Which compiler and linker (eg. g++ or clang++)
CXX = g++
LD  = g++
ifneq ($(GSPICEUI_MSWIN),0)
  LD += -static-libstdc++ -static-libgcc
  WINDRES = windres
endif

# Application name
PROG = gspiceui

# Indentify the wxWidgets configuration utility to use :
# (for GTK3 -> wx-config-gtk3 or for GTK2 -> wx-config)
#   wxgtk2      --> /usr/bin/wx-config       --> wxWidgets 3.0.4  built on GTK2 --> broken (relocation error)
#   wxgtk3      --> /usr/bin/wx-config-gtk3  --> wxWidgets 3.0.4  built on GTK3 --> broken (relocation error)
#   wxgtk2.8    --> /usr/bin/wx-config-2.8   --> wxWidgets 2.8.12 built on GTK2 --> works with warnings and only if debugging is switched on
#   Local build --> /usr/local/bin/wx-config --> wxWidgets 3.0.4  built on GTK2 --> works OK
ifeq ($(GSPICEUI_DEBUG),0)
  WXCFG  = /usr/bin/wx-config
else
  WXCFG  = /usr/local/bin/wx-config
endif
WXCFG += --unicode --version=$(GSPICEUI_WXLIB)
ifneq ($(GSPICEUI_MSWIN),0)
WXCFG += --static
endif

# Dependency file
DEPS = Makefile.deps

# Directories
# Long winded but unambiguous
#ROOT := $(shell cd .. ; pwd)
# Short form but possibly ambiguous
ROOT   = ..
SRCDIR = $(ROOT)/src
OBJDIR = obj
BINDIR = $(ROOT)/bin

# Compiler options :
#  -Wall         Enable all optional warnings desirable for normal code
#  -Wextra       Enable extra warning flags not enabled by "-Wall"
#  -pipe         Use pipes rather than temp. files for comms. between various stages of compilation
#  -O0           Reduce compilation time but don't break debugging (this is the default)
#  -O1           Optimize
#  -O2           Optimize even more
#  -O3           Optimize yet more
#  -Ofast        Optimize till it hurts : "-O3" + enable opts not valid for all standard-compliants
#  -Os           Optimize for size
#  -Og           Optimize debugging experience but don't break debugging
#  -std=[C++NO]  The C++ standard to use where C++NO is eg. c++98, c++03, c++11, c++14, c++17, etc.
ifeq ($(GSPICEUI_DEBUG),0)
  # Options for release (not using -Wall since it's GCC specific)
  CXXFLAGS := -O3 -std=c++11 -pipe $(shell $(WXCFG) --cxxflags)
else
  # Options for development
  CXXFLAGS := -g -Og -std=c++11 -Wall -Wextra -Wpedantic -pipe $(shell $(WXCFG) --cxxflags)
endif

# I like to compile using the option "-Wall". Tests that are not of interest or break wxWidgets are
# turned off below :
ifeq ($(GSPICEUI_DEBUG),1)
  # I'm not interested in the following warnings
  CXXFLAGS += -Wno-unused-parameter
  CXXFLAGS += -Wno-misleading-indentation
  # The following suppresses spurious warnings associated with wxWidgets generally
  CXXFLAGS += -Wno-cast-function-type
  # The following suppresses spurious warnings associated with wxWidgets v3.0.4
  ifeq ($(GSPICEUI_WXLIB),3.0)
    CXXFLAGS += -Wno-ignored-qualifiers
  endif
  # The following suppresses spurious warnings associated with wxWidgets v2.8.12
  ifeq ($(GSPICEUI_WXLIB),2.8)
    CXXFLAGS += -Wno-unused-local-typedefs
    CXXFLAGS += -Wno-ignored-qualifiers
  endif
endif

# To turn on the new layout manager code uncomment the following line :
ifneq ($(LAYOUT_MNGR),0)
  CXXFLAGS += -DLAYOUT_MNGR
endif

# Includes
INCLUDES = -I.

# Libraries
LIBS := $(shell $(WXCFG) --libs core,base,html)
# (The pkg-config stuff was requested by a user, somehow pangox was missing)
#ifeq ($(GSPICEUI_MSWIN),0)
#LIBS := $(shell $(WXCFG) --libs core,base,html) # $(shell pkg-config --libs-only-l pangox)
#else
#LIBS := $(shell $(WXCFG) --libs core,base,html) $(shell pkg-config --libs pangowin32)
#endif

# Source files
#HDRS := $(wildcard *.hpp) $(wildcard */*.hpp) $(wildcard */*/*.hpp)
SRCS := $(wildcard *.cpp) $(wildcard */*.cpp) $(wildcard */*/*.cpp)
ifneq ($(GSPICEUI_MSWIN),0)
  RSRC := $(wildcard *.rc)
endif

# Objects
OBJS := $(SRCS)
OBJS := $(filter-out test-apps/%.cpp, $(OBJS))
OBJS := $(notdir $(OBJS))
OBJS := $(patsubst %.cpp, obj/%.o, $(OBJS))
ifneq ($(GSPICEUI_MSWIN),0)
  OBJS := $(OBJS) $(patsubst %.rc, obj/%.o, $(RSRC))
endif

# Specify list of directories that `make' should search for prerequisite files
VPATH = $(BINDIR)

# Set search paths for the specific file types
vpath   %.cpp    base main netlist process utility test-apps             \
	               ngspice ngspice/commands ngspice/dialogs ngspice/panels \
	               gnucap  gnucap/commands  gnucap/dialogs  gnucap/panels
vpath   %.o      $(OBJDIR)
vpath   test_%   $(BINDIR)

#***************************************************************************************************
# Make these targets
#***************************************************************************************************

all : bnr_beg $(OBJS) $(PROG) bnr_end

bnr_beg :
	@echo -e "\n**************************** Build gSpiceUI binary ****************************\n"

bnr_end :
	@echo -e "\n*************************** Build process completed ***************************\n"

#***************************************************************************************************
# Rules to make targets
#***************************************************************************************************

# Compiler Rules :
#   $<  is the name of the first dependency
#   $@  is the file name of the target
#   -c  compile only, don't link, produces object file ie. <name>.o files
#   -o  place output file in $@

$(OBJDIR)/%.o : %.cpp
	$(CXX) -c $(CXXFLAGS) $(INCLUDES) $< -o $@
	@echo

# Linker Rules :
#   -pipe  use pipes rather temporary files for interprocess communications
#   -o     specify the output file name

$(BINDIR)/$(PROG) : $(OBJS)
	$(LD) -pipe -o $(BINDIR)/$(PROG) obj/*.o $(LIBS)
ifeq ($(ROOT)/GSpiceUI.app,$(wildcard $(ROOT)/GSpiceUI.app))
	cp $(BINDIR)/$(PROG) $(ROOT)/GSpiceUI.app/Contents/MacOS/gspiceui
endif

# Windows resource manipulation (windres is part of GNU Binary Utilities)

ifneq ($(GSPICEUI_MSWIN),0)
$(OBJDIR)/%.o : %.rc
	$(WINDRES) -i $< -o $@ $(INCLUDES) $(shell $(WXCFG) --cppflags)
endif

#***************************************************************************************************
# Include the dependencies file
#***************************************************************************************************

ifeq ($(DEPS),$(wildcard $(DEPS)))
  include $(DEPS)
endif

#***************************************************************************************************
# Create the dependencies file
#***************************************************************************************************

deps :
	@echo -e "\n***************************** Build dependencies ******************************\n"
	$(CXX) -MM -D wxCHECK_VERSION="" -I. $(SRCS) | \
	gawk 'BEGIN {} { printf "%s%s\n", (index($$0," ")!=1 ? "$(OBJDIR)/" : ""), $$0 }' > $(DEPS)
	@echo -e "\n**************************** Build deps completed *****************************\n"

#***************************************************************************************************
# Build the test utilities
#***************************************************************************************************

tests : test_Component test_NetList test_CnvtType test_CmdNgSpiceOPT test_CmdNgSpicePR           \
	      test_CmdNgSpiceDC test_CmdNgSpiceAC test_CmdNgSpiceTR test_CmdGnuCapOPT test_CmdGnuCapPR \
	      test_CmdGnuCapOP  test_CmdGnuCapDC  test_CmdGnuCapAC  test_CmdGnuCapTR  test_CmdGnuCapFO \
	      test_CmdGnuCapGEN test_StrUtils test_Config test_AppConfig test_AppPnlValue              \
	      test_AppPrcBase test_AppPrcGNetList

# Compiler options

test_% : CXXFLAGS  = -Wall -g -pipe $(shell $(WXCFG) --cxxflags)
ifeq ($(GSPICEUI_WXLIB),2.8)  # This suppresses spurious warnings from gcc with wxWidgets v2.8.12
  test_% : CXXFLAGS += -Wno-unused-local-typedefs
endif
test_% : CXXFLAGS += -D $(shell echo $@ | tr "[:lower:]" "[:upper:]")
# Libraries
test_% : LIBS = $(shell $(WXCFG) --libs core,base)

# Compiler Rules for test utilities :
#   $^  is the names of all the prerequisites
#   $@  is the file name of the target

test_% : %.cpp
	@echo
	$(CXX) $(CXXFLAGS) $(INCLUDES) $^ -o $(BINDIR)/$@ $(LIBS)
	@echo

test_StrUtils       : StrUtils.cpp Component.cpp CnvtType.cpp
test_CnvtType       : CnvtType.cpp
test_Config         : Config.cpp TypeDefs.cpp StrUtils.cpp Component.cpp CnvtType.cpp
test_Component      : Component.cpp CnvtType.cpp StrUtils.cpp
test_NetList        : NetList.cpp Component.cpp StrUtils.cpp TypeDefs.cpp CnvtType.cpp

test_CmdNgSpiceOPT  : CmdNgSpiceOPT.cpp CmdBase.cpp CnvtType.cpp
test_CmdNgSpiceDC   : CmdNgSpiceDC.cpp  CmdBase.cpp CnvtType.cpp
test_CmdNgSpiceAC   : CmdNgSpiceAC.cpp  CmdBase.cpp CnvtType.cpp
test_CmdNgSpiceTR   : CmdNgSpiceTR.cpp  CmdBase.cpp CnvtType.cpp
test_CmdNgSpicePR   : CmdNgSpicePR.cpp  CmdBase.cpp CnvtType.cpp TypeDefs.cpp StrUtils.cpp \
                      Component.cpp NetList.cpp

test_CmdGnuCapOPT   : CmdGnuCapOPT.cpp  CmdBase.cpp CnvtType.cpp
test_CmdGnuCapOP    : CmdGnuCapOP.cpp   CmdBase.cpp CnvtType.cpp
test_CmdGnuCapDC    : CmdGnuCapDC.cpp   CmdBase.cpp CnvtType.cpp
test_CmdGnuCapAC    : CmdGnuCapAC.cpp   CmdBase.cpp CnvtType.cpp
test_CmdGnuCapTR    : CmdGnuCapTR.cpp   CmdBase.cpp CnvtType.cpp
test_CmdGnuCapFO    : CmdGnuCapFO.cpp   CmdBase.cpp CnvtType.cpp
test_CmdGnuCapGEN   : CmdGnuCapGEN.cpp  CmdBase.cpp CnvtType.cpp
test_CmdGnuCapPR    : CmdGnuCapPR.cpp   CmdBase.cpp CnvtType.cpp TypeDefs.cpp StrUtils.cpp \
	                    Component.cpp NetList.cpp

test_AppConfig      : AppConfig.cpp Config.cpp TypeDefs.cpp StrUtils.cpp Component.cpp CnvtType.cpp
test_AppPnlValue    : AppPnlValue.cpp PnlValue.cpp UnitsBase.cpp ChoUnits.cpp LblUnits.cpp \
	                    PnlTxtSpn.cpp PnlLblTxt.cpp CnvtType.cpp
test_AppPrcBase     : AppPrcBase.cpp PrcBase.cpp TypeDefs.cpp TextCtrl.cpp StrUtils.cpp \
                      Component.cpp CnvtType.cpp
test_AppPrcGNetList : PrcGNetList.cpp PrcBase.cpp TypeDefs.cpp TextCtrl.cpp StrUtils.cpp \
                      Component.cpp CnvtType.cpp

#***************************************************************************************************
# Install the application
#***************************************************************************************************

install :
	mkdir -p $(DESTDIR)/bin
	cp ../bin/$(PROG) $(DESTDIR)/bin

#***************************************************************************************************
# Uninstall the application
#***************************************************************************************************

uninstall :
	rm -f $(DESTDIR)/bin/$(PROG)
#	rmdir --ignore-fail-on-non-empty $(DESTDIR)/bin

#***************************************************************************************************
# Check for bugs using cppcheck (a tool for static C/C++ code analysis)
#
# Note : 1. The check process can be confined to a specific sub-directory as in the following eg. :
#             cd <GSPICEUI>/src/base
#             make -f ../Makefile check
# Note : 2. Can also use valgrind as follows :
#             cd <GSPICEUI>/bin
#             valgrind --tool=memcheck ./gspiceui
# Note : 3. Could also try the clang static analyser.
#***************************************************************************************************

check :
	@echo -e "\n************************** Perform static bug check ***************************\n"
	@cppcheck --enable=all --suppress=unusedFunction --std=c++11 -I. .
	@echo -e "\n************************* Static bug check completed **************************\n"

#***************************************************************************************************
# Remove old versions of the main application binary and object files
#***************************************************************************************************

clean :
	rm -f $(BINDIR)/$(PROG) $(OBJDIR)/*.o

#***************************************************************************************************
# Remove old versions of test utility binaries
#***************************************************************************************************

cleantests :
	rm -f $(BINDIR)/test_*

#***************************************************************************************************
# Remove old versions of all application and test utility binaries and object files
#***************************************************************************************************

cleanall : clean cleantests

#***************************************************************************************************
# Display a help message
#***************************************************************************************************

help :
	@echo
	@echo -e "gSpiceUI source code build system. "
	@echo
	@echo -e "Available make targets :"
	@echo -e "  all        - Build the application binary (default)"
	@echo -e "  deps       - Create the dependencies file"
	@echo -e "  tests      - Build the all test utilities"
	@echo -e "  test_*     - Build a particular test utility"
	@echo -e "  install    - Install   the application binary"
	@echo -e "  uninstall  - Uninstall the application binary"
	@echo -e "  check      - Check for bugs using cppcheck"
	@echo -e "  clean      - Remove the application binary and object files"
	@echo -e "  cleantests - Remove the test utility binaries"
	@echo -e "  cleanall   - Remove the application and test utility binaries and object files"
	@echo -e "  help       - Display this message"
	@echo

#***************************************************************************************************
# Specify phony targets (ie. targets which are not files)
#***************************************************************************************************

.PHONY : bnr_beg bnr_end deps install uninstall check clean cleantests help

#***************************************************************************************************
