Skip to content

Instantly share code, notes, and snippets.

@gvanem
Last active October 19, 2018 21:42
Show Gist options
  • Select an option

  • Save gvanem/46a43de4f6d2376260c27430dbb003f1 to your computer and use it in GitHub Desktop.

Select an option

Save gvanem/46a43de4f6d2376260c27430dbb003f1 to your computer and use it in GitHub Desktop.
GNU Makefiles for Qwt - A plotting library for Qt5
#
# GNU Makefiles for Qwt (MSVC + clang-cl).
#
# Project page: https://sourceforge.net/projects/qwt/
# Repository: svn://svn.code.sf.net/p/qwt/code/trunk/qwt
#
DATE := $(shell date +%d-%B-%Y)
#
# The full name of the makefile that includes this '$(THIS_FILE)'.
#
THIS_FILE = $(firstword $(MAKEFILE_LIST))
#
# Support 64-bit targets some day?
#
CXX_BITS = 32
#
# Where should these come from?
#
VER_MAJOR = 6
VER_MINOR = 1
VER_MICRO = 0
#
# Choose your weapons:
# You better do a 'make -f Makefile.Windows clean' after changing *any* of these.
#
# Options for compiler + linker:
#
USE_CRT_DEBUG ?= 0
USE_CLANG_CL ?= 0
USE_CLANG_FORMATER ?= 1
USE_GUI_FLAGS ?= 1
USE_QWT_DLL ?= 1
USE_MP_COMPILE ?= 1
MAKE_DOCS ?= 1
#
# The 'all' target is below.
#
default: all
#
# What we will build:
#
TARGETS = bin/Qwt$(D).dll \
lib/Qwt$(D).lib \
lib/Qwt$(D)_static.lib \
bin/QwtMathML$(D).dll \
lib/QwtMathML$(D).lib \
lib/QwtMathML$(D)_static.lib
TARGETS += bin/qwt_designer_plugin$(D).dll \
lib/qwt_designer_plugin$(D).lib
#
# Programs from 'playground/*/*.cpp':
#
TARGETS += $(addprefix bin/, \
curvetracker.exe \
graphicscale.exe \
plotmatrix.exe \
rescaler.exe \
scaleengine.exe \
shapes.exe \
svgmap.exe \
symbols.exe \
timescale.exe \
vectorfield.exe)
#
# Programs from 'examples/*/*.cpp':
#
TARGETS += $(addprefix bin/, \
animation.exe \
barchart.exe \
bode.exe \
controls.exe \
cpuplot.exe \
curvdemo1.exe \
dials.exe \
distrowatch.exe \
friedberg.exe \
itemeditor.exe \
legends.exe \
oscilloscope.exe \
radio.exe \
rasterview.exe \
realtime.exe \
refreshtest.exe \
scatterplot.exe \
simpleplot.exe \
sinusplot.exe \
spectrogram.exe \
splineeditor.exe \
stockchart.exe \
sysinfo.exe \
tvplot.exe)
#
# This program needs 'lib/QwtMathML$(D).lib' or 'lib/QwtMathML$(D)_static.lib'.
# See below.
#
TARGETS += bin/mmlbrowser.exe
#
# All library objects + moc_*.cpp files are produces under this directory.
#
OBJ_DIR = objects
#
# It is assumed that Qt5 headers, libraries and DLLs are setup in
# %INCLUDE%, %LIB% and %PATH% respectively.
#
# The 'QT_ROOT' is the base directory of where Qt5 is installed.
# It's value should match the output of 'qmake.exe -query':
# ...
# QT_INSTALL_PREFIX:f:/Qt/59/5.9.1/msvc2015
#
QT_ROOT ?= $(realpath $(QTDIR))
#
# The following codes used in macro 'colour_msg' assumes you have
# MSys/Cygwin's echo with colour support.
#
BRIGHT_RED = \e[1;31m
BRIGHT_GREEN = \e[1;32m
BRIGHT_YELLOW = \e[1;33m
colour_msg = @echo -e "$(1)\e[0m"
define WARNING
$(1)
$(1) DO NOT EDIT! This file was automatically generated
$(1) from $(realpath $(THIS_FILE)) at $(DATE).
$(1) Edit that file instead.
$(1)
endef
define Generating
$(call colour_msg,$(BRIGHT_GREEN)Generating $(strip $(1)))
$(file > $(1),$(call WARNING, $(2)))
endef
#
# 'CFLAGS' and 'LDFLAGS' common for both 'cl' and 'clang-cl'.
#
CFLAGS = -nologo -Zi -Zo -Ot -EHsc -GF -GS -GR
LDFLAGS = -nologo -debug -incremental:no -map -verbose
#
# Include the generated 'moc_*.cpp' files in the respective .cpp-file.
#
CFLAGS += -DQWT_MOC_INCLUDE=1
#
# We want SVG too
#
CFLAGS += -DQT_SVG_LIB
ifeq ($(USE_CRT_DEBUG),1)
D = d
CFLAGS += -FIcrtdbg.h -D_CRT_MAP_ALLOC
CXX_TYPE = debug
else
D =
CXX_TYPE = release
endif
CFLAGS += -MD$(D) -I./$(OBJ_DIR) -I./textengines/mathml
#
# Only when fully debugged
#
# CFLAGS += -DQT_NO_DEBUG \
# -DQT_NO_DEBUG_OUTPUT \
# -DNDEBUG
#
# Compile using 'clang-cl'?
#
ifeq ($(USE_CLANG_CL),1)
CXX_NAME = clang-cl
CXX = clang-cl
CFLAGS += -W4 -ferror-limit=3
#
# No point. -MP is not faster with clang-cl.
#
USE_MP_COMPILE = 0
export CL=
else
CXX_NAME = MSVC
CXX = cl
CFLAGS += -W4 -wd4127 -wd4456 -wd4701 -guard:cf
#
# 'cl' fails on several application files when '-DQWT_DLL' is defined.
#
USE_QWT_DLL = 0
endif
#
# Which Qwt libraries to use for all programs?
#
ifeq ($(USE_QWT_DLL),1)
programs_LIB = lib/Qwt$(D).lib \
lib/QwtMathML$(D).lib # Needed in bin/mmlbrowser.exe only
else
programs_LIB = lib/Qwt$(D)_static.lib \
lib/QwtMathML$(D)_static.lib # Needed in bin/mmlbrowser.exe only
endif
#
# Use an explicit path to the Qt5 libraries to avoid any erreonous
# 'LIB' or 'LibraryPath' settings to trick us.
#
# This list is too long for most targets. But the linker will ignore
# the ones not needed.
#
QT_LIBS = $(addprefix $(QT_ROOT)/lib/, \
Qt5Core$(D).lib \
Qt5Gui$(D).lib \
Qt5Widgets$(D).lib \
Qt5Svg$(D).lib \
Qt5OpenGL$(D).lib \
Qt5Xml$(D).lib \
Qt5PrintSupport$(D).lib) \
Qt5Designer$(D).lib
#
# We should never need this library.
#
LDFLAGS += -nodefaultlib:oldnames.lib
ifeq ($(USE_GUI_FLAGS),1)
LDFLAGS += -subsystem:windows
programs_LIB += $(QT_ROOT)/lib/qtmain$(D).lib
else
LDFLAGS += -subsystem:console
endif
#
# The Qt include directories we commonly need:
#
CFLAGS += -I$(QT_ROOT)/include \
-I$(QT_ROOT)/include/QtCore \
-I$(QT_ROOT)/include/QtWidgets \
-I$(QT_ROOT)/include/QtNetwork \
-I$(QT_ROOT)/include/QtMultimedia \
-I$(QT_ROOT)/include/QtOpenGL \
-I$(QT_ROOT)/include/QtSvg \
-I$(QT_ROOT)/include/QtPrintSupport \
-I$(QT_ROOT)/include/QtConcurrent \
-I$(QT_ROOT)/include/QtXml \
-I$(QT_ROOT)/include/QtDesigner \
-DQT_SHARED
QT_MOC = $(QT_ROOT)/bin/moc.exe
QT_RCC = $(QT_ROOT)/bin/rcc.exe
#
# Only used in the C++ preprocess rule below.
#
PYTHON ?= python
#
# Create these directories under '.':
#
GEN_DIRS = objects objects/dynamic objects/static bin lib
#
# These are *always* needed in every 'Makefile.Windows' file.
#
GENERATED = $(CXX).args moc.args
MOC_HEADERS = $(addprefix src/, \
qwt_abstract_legend.h \
qwt_abstract_scale.h \
qwt_abstract_slider.h \
qwt_analog_clock.h \
qwt_compass.h \
qwt_counter.h \
qwt_dial.h \
qwt_dyngrid_layout.h \
qwt_knob.h \
qwt_legend.h \
qwt_legend_label.h \
qwt_magnifier.h \
qwt_panner.h \
qwt_picker.h \
qwt_plot.h \
qwt_plot_canvas.h \
qwt_plot_glcanvas.h \
qwt_plot_magnifier.h \
qwt_plot_opengl_canvas.h \
qwt_plot_panner.h \
qwt_plot_picker.h \
qwt_plot_renderer.h \
qwt_plot_rescaler.h \
qwt_plot_zoomer.h \
qwt_sampling_thread.h \
qwt_scale_widget.h \
qwt_slider.h \
qwt_text_label.h \
qwt_thermo.h \
qwt_wheel.h)
#
# These '$(OBJ_DIR)/moc_*.cpp' must be created before we can compile any 'src/*.cpp' files.
#
QWT_MOC_CPP = $(addprefix $(OBJ_DIR)/moc_, \
$(sort $(notdir $(MOC_HEADERS:.h=.cpp))))
GENERATED += $(QWT_MOC_CPP)
#
# Sources for Qwt$(D).dll
#
QWT_SRC = $(addprefix src/, \
qwt_abstract_legend.cpp \
qwt_abstract_scale.cpp \
qwt_abstract_scale_draw.cpp \
qwt_abstract_slider.cpp \
qwt_analog_clock.cpp \
qwt_arrow_button.cpp \
qwt_bezier.cpp \
qwt_clipper.cpp \
qwt_color_map.cpp \
qwt_column_symbol.cpp \
qwt_compass.cpp \
qwt_compass_rose.cpp \
qwt_counter.cpp \
qwt_curve_fitter.cpp \
qwt_date.cpp \
qwt_date_scale_draw.cpp \
qwt_date_scale_engine.cpp \
qwt_dial.cpp \
qwt_dial_needle.cpp \
qwt_dyngrid_layout.cpp \
qwt_event_pattern.cpp \
qwt_graphic.cpp \
qwt_interval.cpp \
qwt_interval_symbol.cpp \
qwt_knob.cpp \
qwt_legend.cpp \
qwt_legend_data.cpp \
qwt_legend_label.cpp \
qwt_magnifier.cpp \
qwt_math.cpp \
qwt_matrix_raster_data.cpp \
qwt_null_paintdevice.cpp \
qwt_painter.cpp \
qwt_painter_command.cpp \
qwt_panner.cpp \
qwt_picker.cpp \
qwt_picker_machine.cpp \
qwt_pixel_matrix.cpp \
qwt_plot.cpp \
qwt_plot_abstract_barchart.cpp \
qwt_plot_abstract_canvas.cpp \
qwt_plot_axis.cpp \
qwt_plot_barchart.cpp \
qwt_plot_canvas.cpp \
qwt_plot_curve.cpp \
qwt_plot_dict.cpp \
qwt_plot_directpainter.cpp \
qwt_plot_glcanvas.cpp \
qwt_plot_grid.cpp \
qwt_plot_histogram.cpp \
qwt_plot_intervalcurve.cpp \
qwt_plot_item.cpp \
qwt_plot_layout.cpp \
qwt_plot_legenditem.cpp \
qwt_plot_magnifier.cpp \
qwt_plot_marker.cpp \
qwt_plot_multi_barchart.cpp \
qwt_plot_opengl_canvas.cpp \
qwt_plot_panner.cpp \
qwt_plot_picker.cpp \
qwt_plot_rasteritem.cpp \
qwt_plot_renderer.cpp \
qwt_plot_rescaler.cpp \
qwt_plot_scaleitem.cpp \
qwt_plot_seriesitem.cpp \
qwt_plot_shapeitem.cpp \
qwt_plot_spectrocurve.cpp \
qwt_plot_spectrogram.cpp \
qwt_plot_svgitem.cpp \
qwt_plot_textlabel.cpp \
qwt_plot_tradingcurve.cpp \
qwt_plot_vectorfield.cpp \
qwt_plot_xml.cpp \
qwt_plot_zoneitem.cpp \
qwt_plot_zoomer.cpp \
qwt_point_3d.cpp \
qwt_point_data.cpp \
qwt_point_mapper.cpp \
qwt_point_polar.cpp \
qwt_raster_data.cpp \
qwt_round_scale_draw.cpp \
qwt_sampling_thread.cpp \
qwt_scale_div.cpp \
qwt_scale_draw.cpp \
qwt_scale_engine.cpp \
qwt_scale_map.cpp \
qwt_scale_widget.cpp \
qwt_series_data.cpp \
qwt_slider.cpp \
qwt_spline.cpp \
qwt_spline_basis.cpp \
qwt_spline_cubic.cpp \
qwt_spline_curve_fitter.cpp \
qwt_spline_local.cpp \
qwt_spline_parametrization.cpp \
qwt_spline_pleasing.cpp \
qwt_symbol.cpp \
qwt_system_clock.cpp \
qwt_text.cpp \
qwt_text_engine.cpp \
qwt_text_label.cpp \
qwt_thermo.cpp \
qwt_transform.cpp \
qwt_weeding_curve_fitter.cpp \
qwt_wheel.cpp \
qwt_widget_overlay.cpp)
# QWT_SRC += $(QWT_MOC_CPP)
#
# Sources for QwtMathML$(D).dll:
#
QWT_MATHML_SRC = $(addprefix textengines/mathml/, \
qwt_mathml_text_engine.cpp \
qwt_mml_document.cpp \
qwt_mml_entity_table.cpp)
#
# Sources for bin/qwt_designer_plugin$(D).dll:
#
QWT_DESIGNER_SRC = $(addprefix designer/, \
qwt_designer_plotdialog.cpp \
qwt_designer_plugin.cpp \
moc_qwt_designer_plotdialog.cpp \
moc_qwt_designer_plugin.cpp \
qrc_qwt_designer_plugin.cpp)
QWT_STATIC_OBJ = $(addprefix $(OBJ_DIR)/static/, $(notdir $(QWT_SRC:.cpp=.obj)))
QWT_DYNAMIC_OBJ = $(addprefix $(OBJ_DIR)/dynamic/, $(notdir $(QWT_SRC:.cpp=.obj)))
QWT_MATHML_DYNAMIC_OBJ = $(addprefix $(OBJ_DIR)/dynamic/, $(notdir $(QWT_MATHML_SRC:.cpp=.obj)))
QWT_MATHML_STATIC_OBJ = $(addprefix $(OBJ_DIR)/dynamic/, $(notdir $(QWT_MATHML_SRC:.cpp=.obj)))
QWT_DESIGNER_OBJ = $(addprefix $(OBJ_DIR)/dynamic/, $(notdir $(QWT_DESIGNER_SRC:.cpp=.obj)))
all: $(GEN_DIRS) $(GENERATED) $(TARGETS) docs_$(MAKE_DOCS)
############### Rules for building Qwt libraries ##########################################
lib/Qwt$(D).lib: bin/Qwt$(D).dll
lib/QwtMathML$(D).lib: bin/QwtMathML$(D).dll
lib/qwt_designer_plugin$(D).lib: bin/qwt_designer_plugin$(D).dll
bin/Qwt$(D).dll: $(QWT_DYNAMIC_OBJ) $(OBJ_DIR)/Qwt.res
$(call link_DLL, $@, lib/Qwt$(D).lib, $^ $(QT_LIBS) $(QT_LIBS))
bin/QwtMathML$(D).dll: $(QWT_MATHML_DYNAMIC_OBJ) $(OBJ_DIR)/QwtMathML.res lib/Qwt$(D).lib
$(call link_DLL, $@, lib/QwtMathML$(D).lib, $^ $(QT_LIBS))
bin/qwt_designer_plugin$(D).dll: $(QWT_DESIGNER_OBJ) $(OBJ_DIR)/qwt_designer_plugin.res lib/Qwt$(D).lib
$(call link_DLL, $@, lib/qwt_designer_plugin$(D).lib, $^ $(QT_LIBS))
lib/Qwt$(D)_static.lib: $(QWT_STATIC_OBJ)
$(call create_lib, $@, $^)
lib/QwtMathML$(D)_static.lib: $(QWT_MATHML_STATIC_OBJ)
$(call create_lib, $@, $^)
designer/qrc_qwt_designer_plugin.cpp: designer/qwt_designer_plugin.qrc
$(call create_RCC, $@, $<)
$(OBJ_DIR)/Qwt.rc: $(THIS_FILE)
$(call Generating, $@, //)
$(file >> $@, #define RC_DESCRIPTION "Qwt Plot library")
$(file >> $@, #define RC_BASENAME "Qwt.dll")
$(file >> $@, $(QWT_RC_COMMON))
$(OBJ_DIR)/QwtMathML.rc: $(THIS_FILE)
$(call Generating, $@, //)
$(file >> $@, #define RC_DESCRIPTION "Qwt Math Markup Language library??")
$(file >> $@, #define RC_BASENAME "QwtMathML.dll")
$(file >> $@, $(QWT_RC_COMMON))
$(OBJ_DIR)/qwt_designer_plugin.rc: $(THIS_FILE)
$(call Generating, $@, //)
$(file >> $@, #define RC_DESCRIPTION "Qwt designer plugin")
$(file >> $@, #define RC_BASENAME "qwt_designer_plugin.dll")
$(file >> $@, $(QWT_RC_COMMON))
$(CXX).args: $(THIS_FILE)
$(call colour_msg,$(BRIGHT_YELLOW)All CFLAGS are in $@)
$(call create_rsp_file, $@, $(CFLAGS))
moc.args: $(THIS_FILE)
$(call colour_msg,$(BRIGHT_YELLOW)All moc flags are in $@)
$(call create_rsp_file, $@, $(filter -D% -I%, $(CFLAGS)) -DQ_OS_WIN --compiler-flavor=msvc)
#
# All $(QWT_SRC) files must be compiled twice :-(
# Could a generated .def-file be used instead?
#
ifeq ($(USE_MP_COMPILE),1)
#
# With MSVC's 'cl' it is a LOT faster to simply compile all $(QWT_SRC) files in one go.
# Even if that could compile too many already up-to-date .obj-files.
#
$(QWT_DYNAMIC_OBJ): $(QWT_SRC)
$(call CPP_compile, $(OBJ_DIR)/dynamic\\, -MP -DQWT_DLL -DQWT_MAKEDLL $^)
$(QWT_STATIC_OBJ): $(QWT_SRC)
$(call CPP_compile, $(OBJ_DIR)/static\\, -MP $^)
else
$(OBJ_DIR)/dynamic/%.obj: src/%.cpp | $(CXX).args
$(call CPP_compile, $@, -DQWT_DLL -DQWT_MAKEDLL $<)
$(OBJ_DIR)/static/%.obj: src/%.cpp | $(CXX).args
$(call CPP_compile, $@, $<)
endif
$(OBJ_DIR)/dynamic/%.obj: textengines/mathml/%.cpp | $(CXX).args
$(call CPP_compile, $@, -DQWT_DLL -DQWT_MAKEDLL $<)
$(OBJ_DIR)/static/%.obj: textengines/mathml/%.cpp | $(CXX).args
$(call CPP_compile, $@, $<)
#
# The '-DQT_PLUGIN' CFLAGS seems to be unneeded.
# The 'qwt_designer_plugin.dll' will export these symbols anyhow:
# qt_plugin_instance
# qt_plugin_query_metadata
#
$(OBJ_DIR)/dynamic/%.obj: designer/%.cpp | $(CXX).args
$(call CPP_compile, $@, -DQWT_DLL -DQT_PLUGIN $<)
$(OBJ_DIR)/moc_%.cpp: src/%.h | moc.args
$(call create_MOC, $@, $<)
############### Rules for building Qwt examples programs #############################
animation_OBJ = examples/animation/main.obj \
examples/animation/plot.obj
barchart_OBJ = examples/barchart/barchart.obj \
examples/barchart/main.obj \
examples/barchart/moc_barchart.obj
bode_OBJ = examples/bode/plot.obj \
examples/bode/main.obj \
examples/bode/mainwindow.obj \
examples/bode/moc_mainwindow.obj \
examples/bode/moc_plot.obj
controls_OBJ = $(addprefix examples/controls/, \
sliderbox.obj \
slidertab.obj \
wheelbox.obj \
wheeltab.obj \
knobbox.obj \
knobtab.obj \
dialbox.obj \
dialtab.obj \
main.obj \
moc_dialbox.obj \
moc_knobbox.obj \
moc_sliderbox.obj \
moc_wheelbox.obj)
cpuplot_OBJ = $(addprefix examples/cpuplot/, \
cpuplot.obj \
cpustat.obj \
cpupiemarker.obj \
moc_cpuplot.obj)
curvdemo1_OBJ = examples/curvdemo1/curvdemo1.obj
dials_OBJ = $(addprefix examples/dials/, \
attitude_indicator.obj \
speedo_meter.obj \
cockpit_grid.obj \
compass_grid.obj \
dials.obj \
moc_attitude_indicator.obj \
moc_cockpit_grid.obj)
distrowatch_OBJ = $(addprefix examples/distrowatch/, \
barchart.obj \
main.obj \
moc_barchart.obj)
friedberg_OBJ = $(addprefix examples/friedberg/, \
friedberg2007.obj \
plot.obj \
main.obj \
moc_plot.obj)
itemeditor_OBJ = $(addprefix examples/itemeditor/, \
editor.obj \
shapefactory.obj \
plot.obj \
main.obj \
moc_editor.obj \
moc_plot.obj)
legends_OBJ = $(addprefix examples/legends/, \
mainwindow.obj \
panel.obj \
plot.obj \
main.obj \
moc_mainwindow.obj \
moc_panel.obj \
moc_plot.obj)
mmlbrowser_OBJ = $(addprefix examples/mmlbrowser/, \
formulaview.obj \
treeview.obj \
mainwindow.obj \
main.obj \
moc_formulaview.obj \
moc_mainwindow.obj \
moc_treeview.obj)
oscilloscope_OBJ = $(addprefix examples/oscilloscope/, \
signaldata.obj \
plot.obj \
knob.obj \
wheelbox.obj \
samplingthread.obj \
curvedata.obj \
mainwindow.obj \
main.obj \
moc_knob.obj \
moc_mainwindow.obj \
moc_plot.obj \
moc_samplingthread.obj \
moc_wheelbox.obj)
radio_OBJ = $(addprefix examples/radio/, \
mainwindow.obj \
ampfrm.obj \
tunerfrm.obj \
radio.obj \
moc_ampfrm.obj \
moc_tunerfrm.obj)
rasterview_OBJ = $(addprefix examples/rasterview/, \
main.obj \
plot.obj \
moc_plot.obj)
realtime_OBJ = $(addprefix examples/realtime/, \
incrementalplot.obj \
main.obj \
mainwindow.obj \
randomplot.obj \
scrollbar.obj \
scrollzoomer.obj \
moc_incrementalplot.obj \
moc_mainwindow.obj \
moc_randomplot.obj \
moc_scrollbar.obj \
moc_scrollzoomer.obj)
refreshtest_OBJ = $(addprefix examples/refreshtest/, \
circularbuffer.obj \
panel.obj \
plot.obj \
mainwindow.obj \
main.obj \
moc_mainwindow.obj \
moc_panel.obj \
moc_plot.obj)
scatterplot_OBJ = $(addprefix examples/scatterplot/, \
plot.obj \
mainwindow.obj \
main.obj \
moc_mainwindow.obj \
moc_plot.obj)
simpleplot_OBJ = examples/simpleplot/simpleplot.obj
sinusplot_OBJ = examples/sinusplot/sinusplot.obj
spectrogram_OBJ = $(addprefix examples/spectrogram/, \
plot.obj \
main.obj \
moc_plot.obj)
splineeditor_OBJ = $(addprefix examples/splineeditor/, \
canvaspicker.obj \
plot.obj \
main.obj \
scalepicker.obj \
moc_canvaspicker.obj \
moc_plot.obj \
moc_scalepicker.obj)
stockchart_OBJ = $(addprefix examples/stockchart/, \
griditem.obj \
legend.obj \
main.obj \
plot.obj \
quotefactory.obj \
moc_legend.obj \
moc_plot.obj)
sysinfo_OBJ = examples/sysinfo/sysinfo.obj
tvplot_OBJ = $(addprefix examples/tvplot/, \
main.obj \
tvplot.obj \
moc_tvplot.obj)
programs_OBJ = $(animation_OBJ) \
$(barchart_OBJ) \
$(bode_OBJ) \
$(controls_OBJ) \
$(cpuplot_OBJ) \
$(curvdemo1_OBJ) \
$(dials_OBJ) \
$(distrowatch_OBJ) \
$(friedberg_OBJ) \
$(itemeditor_OBJ) \
$(legends_OBJ) \
$(mmlbrowser_OBJ) \
$(oscilloscope_OBJ) \
$(radio_OBJ) \
$(rasterview_OBJ) \
$(realtime_OBJ) \
$(refreshtest_OBJ) \
$(scatterplot_OBJ) \
$(simpleplot_OBJ) \
$(sinusplot_OBJ) \
$(spectrogram_OBJ) \
$(splineeditor_OBJ) \
$(stockchart_OBJ) \
$(sysinfo_OBJ) \
$(tvplot_OBJ)
############### Rules for building Qwt playground programs ##########################
curvetracker_OBJ = $(addprefix playground/curvetracker/, \
curvetracker.obj \
main.obj \
plot.obj \
moc_plot.obj)
graphicscale_OBJ = $(addprefix playground/graphicscale/, \
canvas.obj \
mainwindow.obj \
main.obj \
moc_mainwindow.obj)
plotmatrix_OBJ = $(addprefix playground/plotmatrix/, \
main.obj \
plotmatrix.obj \
moc_plotmatrix.obj)
rescaler_OBJ = $(addprefix playground/rescaler/, \
main.obj \
mainwindow.obj \
plot.obj \
moc_mainwindow.obj \
moc_plot.obj)
scaleengine_OBJ = $(addprefix playground/scaleengine/, \
transformplot.obj \
moc_transformplot.obj \
plot.obj \
moc_plot.obj \
mainwindow.obj \
moc_mainwindow.obj \
scaleengine.obj)
svgmap_OBJ = $(addprefix playground/svgmap/, \
main.obj \
plot.obj \
moc_plot.obj)
timescale_OBJ = $(addprefix playground/timescale/, \
main.obj \
mainwindow.obj \
moc_mainwindow.obj \
panel.obj \
moc_panel.obj \
plot.obj \
moc_plot.obj)
shapes_OBJ = playground/shapes/shapes.obj
symbols_OBJ = playground/symbols/symbols.obj
vectorfield_OBJ = playground/vectorfield/main.obj
programs_OBJ += $(curvetracker_OBJ) \
$(graphicscale_OBJ) \
$(plotmatrix_OBJ) \
$(rescaler_OBJ) \
$(scaleengine_OBJ) \
$(shapes_OBJ) \
$(svgmap_OBJ) \
$(symbols_OBJ) \
$(timescale_OBJ) \
$(vectorfield_OBJ)
.SECONDARY: $(programs_OBJ)
ifeq ($(USE_QWT_DLL),1)
%.obj: %.cpp | $(CXX).args
$(call CPP_compile, $@, -DQWT_DLL $<)
else
%.obj: %.cpp | $(CXX).args
$(call CPP_compile, $@, $<)
endif
moc_%.cpp: %.h
$(call create_MOC, $@, $<)
############### Rules for creating Doxygen documentation ################################
docs_0:
$(call colour_msg,Doxygen generation needs a $(BRIGHT_GREEN)MAKE_DOCS=1)
#
# Doxygen seems unwilling to run 'hhc' itself. Do it manually.
#
docs_1: run_doxygen run_hhc run_pdflatex
run_doxygen: doc/Doxyfile2
cd doc; doxygen Doxyfile2 > Doxygen.log
run_hhc:
cd doc/html ; hhc index.hhp
mv -f doc/qwt.chm .
run_pdflatex:
pdflatex -quiet -include-directory=doc/latex \input refman.tex
makeindex refman.idx
pdflatex -quiet -include-directory=doc/latex \input refman.tex
mv -f refman.pdf qwt.pdf
#
# We want LaTeX and Compressed HTML generated. So create another Doxyfile2.
# The 'hhc' (Microsoft HTML Help Compiler) cannot cope with '/' slashes in 'CHM_FILE'!?
# Besides a '\' is a sed and Make ESCape char. Hence must be given 4 times!
#
CHM_FILE := $(subst /,\\\\,$(dir $(realpath $(THIS_FILE)))doc/qwt.chm)
DOXY_REPLACE = -e 's@GENERATE_LATEX[ ]*=.*@GENERATE_LATEX=YES@' \
-e 's@GENERATE_HTMLHELP[ ]*=.*@GENERATE_HTMLHELP=YES@' \
-e 's@CHM_FILE[ ]*=.*@CHM_FILE=$(CHM_FILE)@'
doc/Doxyfile2: doc/Doxyfile $(THIS_FILE)
$(call Generating, $@, #)
sed $(DOXY_REPLACE) < $< >> $@
############### Other general rules #####################################################
bin/mmlbrowser.exe: $(mmlbrowser_OBJ) $(programs_LIB)
$(call link_EXE, $@, $^ $(QT_LIBS) shell32.lib)
#
# '.SECONDEXPANSION' is a cool GNU-make feature to make more compact pattern rules.
# The below will create a series of rules.
# E.g:
# bin/animation.exe: $(animation_OBJ) $(programs_LIB)
# $(call link_EXE, $@, $^ $(QT_LIBS) shell32.lib)
#
# Ref:
# https://www.gnu.org/software/make/manual/make.html#Secondary-Expansion
#
.SECONDEXPANSION:
bin/%.exe: $$($$*_OBJ) $(programs_LIB)
$(call link_EXE, $@, $^ $(QT_LIBS) shell32.lib)
#
# Currently only bin/Qwt.dll uses a .res-file. But this rule could be
# used for other PE-files.
#
$(OBJ_DIR)/%.res: $(OBJ_DIR)/%.rc
$(call make_res, $@, $<)
#
# C++ preprosessing rules:
# Using e.g. 'make -f Makefile.Windows qwt_plot.i' uses this rule for $(QWT_SRC):
#
%.i: src/%.cpp FORCE $(GENERATED) cpp_filter.py
$(call CPP_preprocess, $@, $< -DQWT_DLL -DQWT_MAKEDLL, $(CPP_FORMATER))
#
# But for other .cpp-files you'll need to say e.g.:
# make -f Makefile.Windows examples/dials/dials.i
#
# which uses this rule:
#
%.i: %.cpp FORCE $(GENERATED) cpp_filter.py
$(call CPP_preprocess, $@, $<, $(CPP_FORMATER))
FORCE:
#
# The 'examples/*/moc_*.cpp' and 'playground/*/moc_*.cpp' files are already
# deleted by make since those are treated as 'SECONDARY' targets.
# But $(programs_OBJ) are not since they are marked as '.SECONDARY'.
#
clean:
- rm -f $(GENERATED) $(OBJ_DIR)/*.{obj,cpp,rc,res} $(OBJ_DIR)/static/*.obj $(OBJ_DIR)/dynamic/*.obj \
$(programs_OBJ) vc1*.pdb cpp_filter.py cl.args clang-cl.args link.tmp link.args .depend.Windows \
designer/qrc_qwt_designer_plugin.cpp
- rmdir $(OBJ_DIR)/static $(OBJ_DIR)/dynamic $(OBJ_DIR)
realclean vclean: clean clean_docs_$(MAKE_DOCS)
- rm -f $(TARGETS) \
$(sort $(TARGETS:.exe=.map) $(TARGETS:.dll=.map) \
$(TARGETS:.exe=.pdb) $(TARGETS:.dll=.pdb))
- rmdir bin lib
clean_docs_0:
clean_docs_1:
- rm -f refman.* qwt.chm qwt.pdf doc/Doxygen.log doc/Doxyfile2
- rm -fR doc/html/* doc/latex/*
- rmdir doc/html doc/latex
$(GEN_DIRS):
- mkdir --parents $@
#
# Macro to create an EXE from objects.
# Syntax: $(call link_EXE, ...):
# arg1, $(1): The .exe file.
# arg2, $(2): The .obj file(s), extra args and libs.
#
define link_EXE
$(call colour_msg,$(BRIGHT_GREEN)Linking $(strip $(1)))
$(call create_rsp_file, link.args, $(2))
link $(LDFLAGS) -out:$(strip $(1)) @link.args > link.tmp
@cat link.tmp >> $(1:.exe=.map)
@rm -f link.tmp $(1:.exe=.exp) $(1:.exe=.lib)
$(call colour_msg,Welcome to $(BRIGHT_GREEN)$(strip $(1))!)
@echo
endef
#
# Macro to create a DLL + import-lib from objects.
# Syntax: $(call link_DLL, ...):
# arg1, $(1): The .dll file.
# arg2, $(2): The import-lib.
# arg3, $(3): The .obj file(s), extra args and libs.
#
define link_DLL
$(call colour_msg,$(BRIGHT_GREEN)Linking $(strip $(1)))
$(call create_rsp_file, link.args, $(3))
link $(LDFLAGS) -dll -out:$(strip $(1)) -implib:$(strip $(2)) @link.args > link.tmp
@cat link.tmp >> $(1:.dll=.map)
@rm -f $(2:.lib=.exp) link.tmp
$(call colour_msg,Welcome to $(BRIGHT_GREEN)$(strip $(1))!)
@echo
endef
define CPP_compile
$(CXX) -c @$(CXX).args -Fo$(strip $(1)) $(2)
endef
#
# Macro to create a static .lib:
# arg1: $(1): the .lib file.
# arg2: $(2): the .obj files to put in it.
#
define create_lib
$(call colour_msg,Creating $(BRIGHT_GREEN)$(strip $(1)))
lib -nologo -out:$(strip $(1)) $(2)
@echo
endef
#
# Macro to compile a .rc file:
# arg1: $(1): the .res file.
# arg2: $(2): the .rc to compile.
#
define make_res
rc -nologo -D_MSC_VER -fo $(1) $(2)
@echo
endef
#
# Run Qt's moc (Meta Object Compiler) to produce a 'moc_*.cpp' file
# from any "Mocable" .h-file (a file with a 'Q_OBJECT' line).
#
define create_MOC
$(call colour_msg,Generating $(BRIGHT_GREEN)$(strip $(1))\e[0m\
from $(BRIGHT_YELLOW)$(strip $(2)))
$(QT_MOC) @moc.args -o $(1) $(2)
@echo
endef
#
# Run Qt's resource-compiler on a .qrc-file and generate a .cpp file.
#
define create_RCC
$(call colour_msg,Generating $(BRIGHT_GREEN)$(strip $(1))\e[0m\
from $(BRIGHT_YELLOW)$(strip $(2)))
$(QT_RCC) --output $(1) $(2)
@echo
endef
ifeq ($(USE_CLANG_FORMATER),1)
C_FORMATER = | clang-format -style=Mozilla -assume-filename=c
CPP_FORMATER = | clang-format -style=Mozilla -assume-filename=cpp
endif
define CPP_preprocess
@echo "The result of preprocessing $(word 1, $(2)) with these CFLAGS:" > $(1)
cat $(CXX).args >> $(1)
@echo "-------------------------------- " >> $(1)
$(CXX) -E @$(CXX).args $(2) | $(PYTHON) cpp_filter.py $(3) >> $(1)
endef
define create_rsp_file
$(file > $(1))
$(foreach f, $(2), $(file >> $(1),$(strip $(f))) )
endef
define CPP_FILTER_PY
import sys, os
try:
import ntpath
except ImportError as e:
print ("Failed to import ntpath: %s" % e)
sys.exit(1)
def _win32_abspath (path):
path = ntpath.abspath (path)
return path.replace ('\\', '/')
def skip_cwd (s1, s2):
''' Skip the leading part that is in common with s1 and s2
'''
i = 0
while i < len(s1) and s1[i] == s2[i]:
i += 1
return s2[i:]
cwd = _win32_abspath (os.getcwd()) + '/'
last_line = '??'
last_fname = '??'
empty_lines = 0
while True:
line = sys.stdin.readline()
if not line:
break
if line.startswith('\n') or line.startswith('\r'):
empty_lines += 1
continue
if line.lstrip().startswith("#line"):
line = line.replace ("\\\\", "/")
fname = None
quote = line.find ('\"')
if line.startswith ("#line ") and quote > 0:
fname = _win32_abspath (line[quote:])
last_fname = fname
if line.strip() != '' and last_line != '':
if fname is None or fname != last_fname:
print (line, end="")
if line.strip() == '}' or line.strip() == '};': # Print a newline after a functions or structs
print ("")
last_line = line
if empty_lines > 0:
sys.stderr.write ("Removed %d empty lines." % empty_lines)
endef
cpp_filter.py: $(THIS_FILE)
@echo 'Generating $@...'
$(file > $@,#!/usr/bin/env python)
$(file >> $@,#)
$(file >> $@,# DO NOT EDIT! This file was generated automatically)
$(file >> $@,# from $(realpath $<). Edit that file instead.)
$(file >> $@,#)
$(file >> $@,from __future__ import print_function)
$(file >> $@,if 1:)
$(file >> $@,$(CPP_FILTER_PY))
#
# Stuff common to all .rc-files.
#
# They all have the same version since it's rather hard to parse that
# information out of a *.pri / *.pri file. If that is even defined.
#
define QWT_RC_COMMON
#include <winver.h>
#define RC_VERSION $(VER_MAJOR),$(VER_MINOR),$(VER_MICRO),0
#define RC_VER_STRING "$(VER_MAJOR).$(VER_MINOR).$(VER_MICRO)"
#ifndef RC_BASENAME
#error "Add a 'RC_BASENAME' before including me."
#endif
#ifndef RC_DESCRIPTION
#error "Add a 'RC_DESCRIPTION' before including me."
#endif
VS_VERSION_INFO VERSIONINFO
FILEVERSION RC_VERSION
PRODUCTVERSION RC_VERSION
FILEFLAGSMASK 0x3fL
FILEOS VOS__WINDOWS32
FILESUBTYPE 0
FILEFLAGS 0
#ifdef RC_FILETYPE
FILETYPE RC_FILETYPE /* Could be set to 'VFT_APP'; i.e. an .exe-file */
#else
FILETYPE VFT_DLL /* Otherwise assume 'VFT_DLL' */
#endif
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Qwt - Qt Widgets for Technical Applications; http://qwt.sourceforge.net/"
VALUE "FileDescription", RC_DESCRIPTION
VALUE "ProductName", RC_DESCRIPTION
VALUE "FileVersion", RC_VER_STRING " ($(CXX_NAME), $(CXX_BITS)-bit $(CXX_TYPE))"
VALUE "ProductVersion", RC_VER_STRING " ($(CXX_NAME), $(CXX_BITS)-bit $(CXX_TYPE))"
VALUE "InternalName", RC_BASENAME
VALUE "OriginalFilename", RC_BASENAME
VALUE "LegalCopyright", "The MIT License (MIT)"
VALUE "PrivateBuild", "The private build of <gvanem@yahoo.no>."
VALUE "Comments", "Built on $(DATE)"
VALUE "LegalTrademarks", ""
VALUE "SpecialBuild", ""
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
endef
DEP_REPLACE = sed -e 's|\(.*\)\.o: |\n$$(OBJ_DIR)\/\1.obj: |' \
-e 's|$(QT_ROOT)|$$(QT_ROOT)|g'
DEP_CFLAGS = -MM -std=c++11 $(filter -I% -D%, $(CFLAGS))
depend: $(OBJ_DIR) $(GENERATED)
$(call Generating, .depend.Windows, #)
g++ $(DEP_CFLAGS) $(QWT_SRC) | $(DEP_REPLACE) >> .depend.Windows
-include .depend.Windows
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment