# -*- Makefile -*-

# Copyright 2008, 2009, QNX Software Systems Ltd. All Rights Reserved
#  
# This source code has been published by QNX Software Systems Ltd. (QSSL).
# However, any use, reproduction, modification, distribution or transfer of
# this software, or any software which includes or is based upon any of this
# code, is only permitted under the terms of the QNX Realtime Plaform End User
# License Agreement (see licensing.qnx.com for details) or as otherwise
# expressly authorized by a written license agreement from QSSL. For more
# information, please email licensing@qnx.com.

#
# @@@ TODO: documentation
# @@@ TODO: header checking
#

# Flexelint lint object modules (lobs) to be created (i.e. files to be linted)
#

LOBS += $(filter-out $(EXCLUDE_LOBS),$(addsuffix .lob,$(filter-out $(basename $(notdir $(filter %.s %.S,$(SRCS) $(LATE_SRCS)))),$(basename $(OBJS)))))
LOBS += $(EXTRA_LOBS)

# Flexelint command lines for C and C++ respectively
#

FLINT_c_lob = $(FLINTDEP) $(FLINT_HOST) $(FLINTFLAGS) $(FLINTBASE.c) -u -oo=$*.lob $(FLINTCONFIG.c) $(FLINTENV) $<
FLINT_cc_lob = $(FLINTDEP) $(FLINT_HOST) $(FLINTFLAGS) $(FLINTBASE.cc) -u -oo=$*.lob $(FLINTCONFIG.cc) $(FLINTENV) $<

# Flexelint XML command lines for C and C++ respectively
#

FLINT_c_xml = $(FLINTXML) $(FLINT_HOST) $(FLINTFLAGS) -os=$*.lob.xml $(FLINTBASE.c) -u -oo=$*.lob $(FLINTCONFIG.c) qnx-env-xml.lnt $<
FLINT_cc_xml = $(FLINTXML) $(FLINT_HOST) $(FLINTFLAGS) -os=$*.lob.xml $(FLINTBASE.cc) -u -oo=$*.lob $(FLINTCONFIG.cc) qnx-env-xml.lnt $<

# Flexelint preprocessor output command lines for C and C++ respectively
#

FLINT_c_li = $(FLINT_HOST) -p -os=$@ $(FLINTPPFLAGS) $(FLINTBASE.li) $<
FLINT_cc_lii = $(FLINT_HOST) -p -os=$@ $(FLINTPPFLAGS) $(FLINTBASE.lii) $<

# Flexelint executable
#

FLINT_HOST ?= $(QNX_HOST)/usr/bin/flint

# Flexelint non-preprocessor flags
#

FLINTFLAGS ?= $(DEFFLINTFLAGS)
DEFFLINTFLAGS += -vdfi
DEFFLINTFLAGS += +ffn
DEFFLINTFLAGS += $(EXTRA_FLINTFLAGS)

# Flexelint preprocessor flags
#

FLINTPPFLAGS ?= $(DEFFLINTPPFLAGS)
DEFFLINTPPFLAGS += -v1d
DEFFLINTPPFLAGS += +ffn
DEFFLINTPPFLAGS += $(EXTRA_FLINTPPFLAGS)

# Flexelint basic and toolchain config (per target)
#

FLINTBASE.c ?= $(DEFFLINTBASE.c)
DEFFLINTBASE.c += -i$(MKFILES_ROOT)
DEFFLINTBASE.c += qnx-base-lob.lnt
DEFFLINTBASE.c += qnx-base.lnt
DEFFLINTBASE.c += $*.co.lnt
DEFFLINTBASE.c += $(FLINTBASE_c$(select_compiler))
DEFFLINTBASE.c += qnx-co.lnt
DEFFLINTBASE.c += $(EXTRA_FLINTBASE)

FLINTBASE.cc ?= $(DEFFLINTBASE.cc)
DEFFLINTBASE.cc += -i$(MKFILES_ROOT)
DEFFLINTBASE.cc += qnx-base-lob.lnt
DEFFLINTBASE.cc += qnx-base.lnt
DEFFLINTBASE.cc += $*.co.lnt
DEFFLINTBASE.cc += $(FLINTBASE_cxx$(select_compiler))
DEFFLINTBASE.cc += qnx-co.lnt
DEFFLINTBASE.cc += $(EXTRA_FLINTBASE)

FLINTBASE.li ?= $(DEFFLINTBASE.li)
DEFFLINTBASE.li += -i$(MKFILES_ROOT)
DEFFLINTBASE.li += qnx-base-pp.lnt
DEFFLINTBASE.li += qnx-base.lnt
DEFFLINTBASE.li += $*.co.lnt
DEFFLINTBASE.li += $(FLINTBASE_c$(select_compiler))
DEFFLINTBASE.li += qnx-co.lnt
DEFFLINTBASE.li += $(EXTRA_FLINTBASE)

FLINTBASE.lii ?= $(DEFFLINTBASE.lii)
DEFFLINTBASE.lii += -i$(MKFILES_ROOT)
DEFFLINTBASE.lii += qnx-base-pp.lnt
DEFFLINTBASE.lii += qnx-base.lnt
DEFFLINTBASE.lii += $*.co.lnt
DEFFLINTBASE.lii += $(FLINTBASE_cxx$(select_compiler))
DEFFLINTBASE.lii += qnx-co.lnt
DEFFLINTBASE.lii += $(EXTRA_FLINTBASE)

FLINTBASE_c_nto_any_gcc_qcc += qnx-co-gcc-c.lnt
FLINTBASE_cxx_nto_any_gcc_qcc += qnx-co-gcc-cxx.lnt

FLINTBASE_c_nto_arm_gcc_qcc += $(FLINTBASE_c_nto_any_gcc_qcc)
FLINTBASE_cxx_nto_arm_gcc_qcc += $(FLINTBASE_cxx_nto_any_gcc_qcc)

FLINTBASE_c_nto_mips_gcc_qcc += $(FLINTBASE_c_nto_any_gcc_qcc)
FLINTBASE_cxx_nto_mips_gcc_qcc += $(FLINTBASE_cxx_nto_any_gcc_qcc)

FLINTBASE_c_nto_ppc_gcc_qcc += $(FLINTBASE_c_nto_any_gcc_qcc)
FLINTBASE_cxx_nto_ppc_gcc_qcc += $(FLINTBASE_cxx_nto_any_gcc_qcc)

FLINTBASE_c_nto_sh_gcc_qcc += $(FLINTBASE_c_nto_any_gcc_qcc)
FLINTBASE_cxx_nto_sh_gcc_qcc += $(FLINTBASE_cxx_nto_any_gcc_qcc)

FLINTBASE_c_nto_x86_gcc_qcc += $(FLINTBASE_c_nto_any_gcc_qcc)
FLINTBASE_cxx_nto_x86_gcc_qcc += $(FLINTBASE_cxx_nto_any_gcc_qcc)

# Flexelint detailed config (per target)
#

FLINTCONFIG.c ?= $(DEFFLINTCONFIG.c)
DEFFLINTCONFIG.c += $(FLINTCONFIG)
DEFFLINTCONFIG.c += $(EXTRA_FLINTCONFIG)

FLINTCONFIG.cc ?= $(DEFFLINTCONFIG.cc)
DEFFLINTCONFIG.cc += $(FLINTCONFIG)
DEFFLINTCONFIG.cc += $(EXTRA_FLINTCONFIG)

FLINTCONFIG ?= $(DEFFLINTCONFIG)
DEFFLINTCONFIG += qnx-std.lnt
DEFFLINTCONFIG += $(FLINTCONFIG_$(FLINTPOLICY))
DEFFLINTCONFIG += $(wildcard $(PROJECT_ROOT)/project.lnt)
DEFFLINTCONFIG += $(wildcard $(PROJECT_ROOT)/project-$(FLINTPOLICY).lnt)
DEFFLINTCONFIG += $(FLINTCONFIG_$(basename $@))
DEFFLINTCONFIG += $(FLINTCONFIG_$(basename $@)_$(CPU))

FLINTPOLICY ?= default

FLINTCONFIG_default += qnx-policy-default.lnt

FLINTCONFIG_basic += $(FLINTCONFIG_coreos)

FLINTCONFIG_coreos += qnx-policy-coreos.lnt

FLINTCONFIG_WO790585 += qnx-policy-WO790585.lnt

FLINTCONFIG_SIL3 += qnx-policy-SIL3.lnt

# Flexelint display environment (i.e. output configuration)
#

FLINTENV ?= qnx-env-term.lnt

# Flexelint dependency generator command line
#

FLINTDEP = source="$<" object="$@" $(FLINTDEP_HOST)

# Flexelint dependency generator executable
#

FLINTDEP_HOST ?= $(PYTHON_HOST) $(MKFILES_ROOT)/flintdep

# Flexelint XML and dependency generator command line
#

FLINTXML = source="$<" object="$@" prefixes="$(INSTALL_ROOT_$(OS))" $(FLINTXML_HOST)

# Flexelint XML and dependency generator executable
#

FLINTXML_HOST ?= $(PYTHON_HOST) $(MKFILES_ROOT)/flintxml

# Lint delta calculation command line
#

FLINTDELTA = prefixes="$(INSTALL_ROOT_$(OS))" $(FLINTDELTA_HOST)

# Lint delta calculation executable
#

FLINTDELTA_HOST ?= $(PYTHON_HOST) $(MKFILES_ROOT)/flintdelta

# Lint delta directory
#

FLINTDELTADIR ?= $(PRODUCT_ROOT)/lint/$(FLINTPOLICY)/delta/$(patsubst $(PRODUCT_ROOT)/%,%,$(CURDIR))

# Lint storage directory
#

FLINTSTOREDIR ?= $(PRODUCT_ROOT)/lint/$(FLINTPOLICY)/store/$(patsubst $(PRODUCT_ROOT)/%,%,$(CURDIR))

# Lint summary command line
#

FLINTSUMMARY = prefixes="$(INSTALL_ROOT_$(OS))" $(FLINTSUMMARY_HOST)

# Lint summary executable
#

FLINTSUMMARY_HOST ?= $(PYTHON_HOST) $(MKFILES_ROOT)/flintsummary

# Lint summary flags
#

FLINTSUMMARYFLAGS ?= $(DEFFLINTSUMMARYFLAGS)
DEFFLINTSUMMARYFLAGS += -v
DEFFLINTSUMMARYFLAGS += $(EXTRA_FLINTSUMMARYFLAGS)

# cpp2lnt command for C and C++ respectively (generates include search paths and initial defines)
#

CPP2LNT_c_lnt = $(CPP2LNT.c) $(CCPREF) -E $(CCFLAGS) $(FLAGS) $(CCVFLAGS) $(CCOPTS) $(CPP2LNTFLAGS.c)
CPP2LNT_cc_lnt = $(CPP2LNT.cc) $(CCPREF) -E $(CCFLAGS) $(FLAGS) $(CCVFLAGS) $(CCOPTS) $(CPP2LNTFLAGS.cc)

# cpp2lnt executables for C and C++ respectively
#

CPP2LNT.c = $(CPP2LNT_c$(select_compiler))
CPP2LNT.cc = $(CPP2LNT_cxx$(select_compiler))

CPP2LNT_c_any_any_gcc_any = $(GCC2LNT_HOST)
CPP2LNT_cxx_any_any_gcc_any = $(GCC2LNT_HOST)

CPP2LNT_c_nto_arm_gcc_qcc = $(CPP2LNT_c_any_any_gcc_any)
CPP2LNT_cxx_nto_arm_gcc_qcc = $(CPP2LNT_cxx_any_any_gcc_any)

CPP2LNT_c_nto_mips_gcc_qcc = $(CPP2LNT_c_any_any_gcc_any)
CPP2LNT_cxx_nto_mips_gcc_qcc = $(CPP2LNT_cxx_any_any_gcc_any)

CPP2LNT_c_nto_ppc_gcc_qcc = $(CPP2LNT_c_any_any_gcc_any)
CPP2LNT_cxx_nto_ppc_gcc_qcc = $(CPP2LNT_cxx_any_any_gcc_any)

CPP2LNT_c_nto_sh_gcc_qcc = $(CPP2LNT_c_any_any_gcc_any)
CPP2LNT_cxx_nto_sh_gcc_qcc = $(CPP2LNT_cxx_any_any_gcc_any)

CPP2LNT_c_nto_x86_gcc_qcc = $(CPP2LNT_c_any_any_gcc_any)
CPP2LNT_cxx_nto_x86_gcc_qcc = $(CPP2LNT_cxx_any_any_gcc_any)

# cpp2lnt flags to force preprocessor to generate include search path and initial defines
#

CPP2LNTFLAGS.c = $(CPP2LNTFLAGS_c$(select_compiler))

CPP2LNTFLAGS_c_any_any_gcc_qcc += -D_lint
CPP2LNTFLAGS_c_any_any_gcc_qcc += -Wp,-v
CPP2LNTFLAGS_c_any_any_gcc_qcc += -Wp,-dM
CPP2LNTFLAGS_c_any_any_gcc_qcc += -xc /dev/null

CPP2LNTFLAGS_c_nto_arm_gcc_qcc += $(CPP2LNTFLAGS_c_any_any_gcc_qcc)

CPP2LNTFLAGS_c_nto_mips_gcc_qcc += $(CPP2LNTFLAGS_c_any_any_gcc_qcc)

CPP2LNTFLAGS_c_nto_ppc_gcc_qcc += $(CPP2LNTFLAGS_c_any_any_gcc_qcc)

CPP2LNTFLAGS_c_nto_sh_gcc_qcc += $(CPP2LNTFLAGS_c_any_any_gcc_qcc)

CPP2LNTFLAGS_c_nto_x86_gcc_qcc += $(CPP2LNTFLAGS_c_any_any_gcc_qcc)

CPP2LNTFLAGS.cc = $(CPP2LNTFLAGS_cxx$(select_compiler))

CPP2LNTFLAGS_cxx_any_any_gcc_qcc += -D_lint
CPP2LNTFLAGS_cxx_any_any_gcc_qcc += -Wp,-v
CPP2LNTFLAGS_cxx_any_any_gcc_qcc += -Wp,-dM
CPP2LNTFLAGS_cxx_any_any_gcc_qcc += -xc++ /dev/null

CPP2LNTFLAGS_cxx_nto_arm_gcc_qcc += $(CPP2LNTFLAGS_cxx_any_any_gcc_qcc)

CPP2LNTFLAGS_cxx_nto_mips_gcc_qcc += $(CPP2LNTFLAGS_cxx_any_any_gcc_qcc)

CPP2LNTFLAGS_cxx_nto_ppc_gcc_qcc += $(CPP2LNTFLAGS_cxx_any_any_gcc_qcc)

CPP2LNTFLAGS_cxx_nto_sh_gcc_qcc += $(CPP2LNTFLAGS_cxx_any_any_gcc_qcc)

CPP2LNTFLAGS_cxx_nto_x86_gcc_qcc += $(CPP2LNTFLAGS_cxx_any_any_gcc_qcc)

# gcc2lnt executable (handles both gcc and g++ output, independent of driver)
#

GCC2LNT_HOST ?= $(POSIXSHELL_HOST) $(MKFILES_ROOT)/gcc2lnt

# move-if-change executable (mv $1 to $2 iff $1 newer; otherwise rm $1)
#

MOVE-IF-CHANGE ?= >/dev/null $(POSIXSHELL_HOST) $(MKFILES_ROOT)/move-if-change

# mkinstalldirs executable (recursively create all named directories)
#

MKDIR_HOST ?= $(POSIXSHELL_HOST) $(MKFILES_ROOT)/mkinstalldirs

# POSIX shell executable
#

POSIXSHELL_HOST ?= ${QNX_HOST}/usr/bin/ksh

# Python executable
#

PYTHON_HOST ?= python

# Extra clean items
#

lint-clean += *.flintdelta.xml
lint-clean += *.lob *.lob.xml
lint-clean += *.lob.Po *.lob.xml.Po
lint-clean += *.co.lnt *.co.lnt.h
lint-clean += *.Tpo *.Tln *.Tlh
lint-clean += *.li *.lii *.plint

EXTRA_CLEAN += $(lint-clean)

# Lists of base XML, delta XML, and storage locations.
#

lint-xml += $(addsuffix .xml,$(LOBS))

lint-delta += $(addsuffix .flintdelta.xml,$(basename $(LOBS)))

lint-store += $(addprefix $(FLINTSTOREDIR)/,$(lint-xml))
lint-store += $(addprefix $(FLINTDELTADIR)/,$(lint-delta))

# Top level rules
#

.PHONY: lint
lint:: lint-delta

.PHONY: lint-text
lint-text:: lint-lob

.PHONY: lint-ide
lint-ide:: lint-lob

.PHONY: lint-summary
lint-summary:: lint-summary-delta

.PHONY: lint-lob
lint-lob:: $(LOBS)

.PHONY: lint-xml
lint-xml:: $(lint-xml)

.PHONY: lint-delta
lint-delta:: $(lint-delta)

.PHONY: lint-store
lint-store:: $(lint-store)

.PHONY: lint-clean
lint-clean::
	-$(RM_HOST) $(lint-clean)

# Conventional force rebuild target
#

.PHONY: FORCE
FORCE:

# Summary generation rules
#

.PHONY: lint-summary-full
lint-summary-full: $(lint-xml)
	$(FLINTSUMMARY) $(FLINTSUMMARYFLAGS) --all $^

.PHONY: lint-summary-delta
lint-summary-delta: $(lint-delta)
	$(FLINTSUMMARY) $(FLINTSUMMARYFLAGS) $^

# Pattern rules for %.lob generation (i.e. lint checking)
#

.SECONDARY: %.lob

%.lob: %.c %.co.lnt %.co.lnt.h
	$(FLINT_c_lob)

%.lob: %.cc %.co.lnt %.co.lnt.h
	$(FLINT_cc_lob)

%.lob: %.cxx %.co.lnt %.co.lnt.h
	$(FLINT_cc_lob)

%.lob: %.cpp %.co.lnt %.co.lnt.h
	$(FLINT_cc_lob)

%.lob: %.C %.co.lnt %.co.lnt.h
	$(FLINT_cc_lob)

# Pattern rules for %.lob.xml generation (i.e. lint XML generation)
#

.SECONDARY: %.lob.xml

%.lob.xml: %.c %.co.lnt %.co.lnt.h
	$(FLINT_c_xml)

%.lob.xml: %.cc %.co.lnt %.co.lnt.h
	$(FLINT_cc_xml)

%.lob.xml: %.cxx %.co.lnt %.co.lnt.h
	$(FLINT_cc_xml)

%.lob.xml: %.cpp %.co.lnt %.co.lnt.h
	$(FLINT_cc_xml)

%.lob.xml: %.C %.co.lnt %.co.lnt.h
	$(FLINT_cc_xml)

# Pattern rules for %.li and %.lii generation (i.e. lint preprocessor output)
#

# N.B. Flexelint 8.00x does not output -vi in -p mode making proper
# dependency generation impossible, hence FORCE.

.SECONDARY: %.li %.lii

%.li: %.c %.co.lnt %.co.lnt.h FORCE
	$(FLINT_c_li)

%.plint: %.c %.co.lnt %.co.lnt.h FORCE
	$(FLINT_c_li)

%.lii: %.cc %.co.lnt %.co.lnt.h FORCE
	$(FLINT_cc_lii)

%.lii: %.cxx %.co.lnt %.co.lnt.h FORCE
	$(FLINT_cc_lii)

%.lii: %.cpp %.co.lnt %.co.lnt.h FORCE
	$(FLINT_cc_lii)

%.lii: %.C %.co.lnt %.co.lnt.h FORCE
	$(FLINT_cc_lii)

# Pattern rules for %.flintdelta.xml generation (i.e. lint delta output)
#

.SECONDARY: %.flintdelta.xml

%.flintdelta.xml: %.lob.xml
	old="$(FLINTSTOREDIR)/$<"; [ -e $${old} ] || unset old; $(FLINTDELTA) -o $@ $${old:+"--old=$${old}"} --new=$<

# Pattern rules for lint-store pseudo-target
#

$(FLINTSTOREDIR)/%.lob.xml: %.lob.xml
	@[ -d $(@D) ] || $(MKDIR_HOST) $(@D)
	$(CP_HOST) $< $@

$(FLINTDELTADIR)/%.flintdelta.xml: %.flintdelta.xml
	@[ -d $(@D) ] || $(MKDIR_HOST) $(@D)
	$(CP_HOST) $< $@

# Pattern rules for compiler options files
#

# N.B.  This is somewhat subtle.  The ultimate goal is for a higher
# level target (e.g. a %.lob or %.li) to be able to pick up the
# correct compiler options which would be used when actually compiling
# the source (the include search paths in %.co.lnt; and the initial
# defines in %.co.lnt.h).  This is harder to accomplish than it might
# at first appear.
#
# The flags which would be passed to the actual compilation depend not
# only on the myriad makefile fragments which make up the build
# system, but also on the user's command line, and even on the
# environment variables inherited from the parent process.  Because of
# this, the recomputation of the compiler options files is forced to
# occur on each run.  This is accomplished via the phony FORCE target.
# However, this unconditional rebuild of the compiler options files
# should not - in and of itself - force an unnecessary rebuild of the
# higher target: a rebuild should only be forced from this level if
# the command line has actually changed.
#
# In order to accomplish this, the fact that the "make" dependency
# graph traversal algorithm updates its nodes with the timestamp of
# the target files as they exist at the time the rules have finished
# executing (and not the time at which the rules were executed) can be
# exploited.  The compiler options files are unconditionally generated
# using temporary (but well known) file names and a "real" version is
# only replaced with a new version if the new version is different.
# The dependency graph node then gets updated either with the
# timestamp of the new file (if there was a change) or of the original
# old file (if not).  In the former case a rebuild is triggered; in
# the latter case a rebuild will not be triggered - at least not by
# these targets.
#
# The real difficulty arises when trying to compute the flags which
# would be used by the actual compilation.  (In fact, in the most
# general case it is probably impossible - or, at very least,
# extremely difficult - to accomplish from within "make" itself, even
# using tricks like secondary "make" invocations and/or the "-n"
# flag.) A solution which appears to be sufficient for the time being
# is to assume that all the targets would be compiled using
# $(COMPILE_c_o) and to extract the necessary flags from there,
# ideally by running the preprocessor itself.  That is the task of
# $(CPP2LNT_c_lnt) (and, without loss of generality, $(CPP2LNT_cc_lnt)
# etc.).  This leads to the most difficult of the mechanical problems:
# some of the makevars which comprise $(COMPILE_c_o) have names which
# are computed from $< and, even worse, $@.
#
# In the case of $@, there is no general solution.  Fortunately it
# happens that currently $@ is only ever used in the expression
# $(basename $@).  As a result, as long as the basenames of the lint
# files being processed by CPP2LNT are the same as the basename of the
# object file, the expansion of the basename expression will be
# identical, by definition.  A necessary consequence of this is that
# both of the temporary compiler option files must have only one level
# of file extension (i.e. %.Tln, with one, is fine; but %.co.lnt.tmp,
# with three, is not).  Likewise both temporary files must have the
# same basename since the dependency graph traversal may arrive at the
# CPP2LNT node via either prerequisite (and therefore have a different
# $@ depending on which of the two is the actual effective target at
# build time - this matters because some defines have a value which is
# computed from $(basename $@), e.g. _BASE_FILE_).
#
# For $< the situation is somewhat simpler: it only needs to be
# arranged that the first prerequisite is the same as it would be for
# actual compilation (i.e. %.c, %.cc, etc.)  Note that this
# prerequisite is not "real": the compiler options files do not depend
# in any way on the content of the source file itself.  However, the
# only consequence of this "fake" prerequisite would be rebuilding the
# compiler options files whenever the source code changes; since these
# files always rebuild every time anyway, no extra work is actually
# done.
#
# Exposing the generation of the temporary files as implicit targets,
# although theoretically unnecessary, does make debugging somewhat
# simpler.  Declaring the compiler option files .PRECIOUS is
# necessary to prevent "make" from automatically removing them at the
# end of each run (which would somewhat defeat the purpose of this
# whole exercise :-)

.PRECIOUS: %.co.lnt %.co.lnt.h

%.co.lnt %.co.lnt.h: %.Tln %.Tlh
	$(MOVE-IF-CHANGE) $*.Tln $*.co.lnt
	$(MOVE-IF-CHANGE) $*.Tlh $*.co.lnt.h

%.Tln %.Tlh: %.c FORCE
	includes="$*.Tln" defines="$*.Tlh" header="$*.co.lnt.h" $(CPP2LNT_c_lnt)

%.Tln %.Tlh: %.cc FORCE
	includes="$*.Tln" defines="$*.Tlh" header="$*.co.lnt.h" $(CPP2LNT_cc_lnt)

%.Tln %.Tlh: %.cxx FORCE
	includes="$*.Tln" defines="$*.Tlh" header="$*.co.lnt.h" $(CPP2LNT_cc_lnt)

%.Tln %.Tlh: %.cpp FORCE
	includes="$*.Tln" defines="$*.Tlh" header="$*.co.lnt.h" $(CPP2LNT_cc_lnt)

%.Tln %.Tlh: %.C FORCE
	includes="$*.Tln" defines="$*.Tlh" header="$*.co.lnt.h" $(CPP2LNT_cc_lnt)

# Automatic dependency handling
#

-include $(addsuffix .Po, $(LOBS)) /dev/null
