412 lines
21 KiB
Makefile
412 lines
21 KiB
Makefile
# -*- Makefile -*-
|
|
#
|
|
# $Id: GNUmakefile.cfg 629815 2008-02-21 14:54:57Z faridz $
|
|
#
|
|
# makefile to configure the C++ Standard library
|
|
#
|
|
########################################################################
|
|
#
|
|
# Licensed to the Apache Software Foundation (ASF) under one or more
|
|
# contributor license agreements. See the NOTICE file distributed
|
|
# with this work for additional information regarding copyright
|
|
# ownership. The ASF licenses this file to you under the Apache
|
|
# License, Version 2.0 (the "License"); you may not use this file
|
|
# except in compliance with the License. You may obtain a copy of
|
|
# the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
# implied. See the License for the specific language governing
|
|
# permissions and limitations under the License.
|
|
#
|
|
# Copyright 1999-2007 Rogue Wave Software, Inc.
|
|
#
|
|
########################################################################
|
|
#
|
|
# Creates a C++ header file, config.h, containing a list of (possibly
|
|
# commented out) preprocessor #defines in the form _RWSTD_NO_XXX,
|
|
# where the XXX is the file name part (w/o the extension) of XXX.cpp
|
|
# (some C or C++ program)
|
|
#
|
|
# Files named NO_XXX.cpp are assumed to be negative tests, which are
|
|
# considered successful unless they exit with zero status, in which
|
|
# case they are considered failed and the corresponding macro,
|
|
# _RWSTD_NO_XXX, is #defined.
|
|
#
|
|
# Each test named XXX.lib.cpp is translated into a static or dynamic
|
|
# library (depending on the presence of shared in BUILDMODE variable),
|
|
# and may be linked into other executables. To link a library into an
|
|
# executable the name of the library must be mentioned in LDOPTS
|
|
# somewhere in the executable's source.
|
|
#
|
|
# XXX.cpp can but doesn't need to contain main(). If it doesn't, the
|
|
# macro _RWSTD_NO_XXX will be commented out in config.h iff XXX.cpp
|
|
# successfully compiles.
|
|
#
|
|
# If XXX.cpp contains main(), _RWSTD_NO_XXX will be commented out iff
|
|
# XXX.cpp not only successfully compiles, but also links and runs.
|
|
#
|
|
# Any output produced by the executable XXX obtained by compiling and
|
|
# linking XXX.cpp is appended to the end of config.h.
|
|
#
|
|
########################################################################
|
|
|
|
include ../makefile.in
|
|
|
|
SRCDIR = $(TOPDIR)/etc/config/src
|
|
VPATH = $(SRCDIR)
|
|
|
|
CPPFLAGS += -I.
|
|
CPPFLAGS := $(filter-out -I$(TOPDIR)/include/ansi,$(CPPFLAGS))
|
|
|
|
CXXFLAGS += $(WARNFLAGS)
|
|
|
|
# get a sorted list of config tests, starting with any shell scripts
|
|
# with the .sh suffix, followed by C++ (.cpp) programs
|
|
SRCS := $(sort $(notdir $(wildcard $(SRCDIR)/*.sh)))
|
|
SRCS += $(sort $(notdir $(wildcard $(SRCDIR)/*.cpp)))
|
|
OBJS := $(SRCS:.cpp=.o)
|
|
TARGET := $(SRCS:.cpp=)
|
|
PWD := $(shell pwd)
|
|
DASH_H = -H
|
|
|
|
CCNAME = $(CXX)-$(CCVER)
|
|
LOGFILE = config.log
|
|
|
|
# can't use LDOPTS when working with HP aCC, it's used by the linker
|
|
ifneq ($(CXX),aCC)
|
|
LOPT = LDOPTS
|
|
LDFLAGS += $(LDOPTS)
|
|
else
|
|
LOPT = _LDOPTS
|
|
LDFLAGS += $(_LDOPTS)
|
|
endif
|
|
|
|
# append $(LDLIBS) last, after $(LDOPTS), since the latter may depend
|
|
# on the former being after it on the link line
|
|
LDFLAGS += -lm $(LDLIBS)
|
|
|
|
# CXXPRELINK - command for compilers that use template
|
|
# instantiation models that require a prelink stage
|
|
ifneq ($(PRELINKFLAGS),)
|
|
CXXPRELINK = $(CXX) $(CPPFLAGS) $(LDFLAGS) $(PRELINKFLAGS)
|
|
endif # ($(PRELINKFLAGS),)
|
|
|
|
|
|
# helper function to compile a file and log results
|
|
# arguments:
|
|
# $(1): source file name
|
|
# $(2): object file name
|
|
# $(3): additional compiler flags (optional)
|
|
define compile
|
|
command="$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(3) -c $(1) -o $(2)"; \
|
|
echo "$$command" >>$(LOGFILE); \
|
|
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(3) -c $(1) -o $(2) >>$(LOGFILE) 2>&1
|
|
endef
|
|
|
|
# helper function to link a file and log results
|
|
# arguments:
|
|
# $(1): object file name
|
|
# $(2): executable file name
|
|
# $(3): additional linker flags (optional)
|
|
define link
|
|
command="$(LD) $(1) $(LDFLAGS) $(3) -o $(2)"; \
|
|
echo "$$command" >>$(LOGFILE); \
|
|
$(LD) $(1) $(LDFLAGS) $(3) -o $(2) >>$(LOGFILE) 2>&1
|
|
endef
|
|
|
|
# helper function to compile and link a file and log results
|
|
# arguments:
|
|
# $(1): source file name
|
|
# $(2): object file name
|
|
# $(3): executable file name
|
|
# $(4): additional compiler flags (optional)
|
|
# $(5): additional linker flags (optional)
|
|
define compile_then_link
|
|
command="$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(4) -c $(1) -o $(2)" \
|
|
"&& $(LD) $(2) $(LDFLAGS) $(5) -o $(3)"; \
|
|
echo "$$command" >>$(LOGFILE); \
|
|
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(4) -c $(1) -o $(2) >>$(LOGFILE) 2>&1 \
|
|
&& $(LD) $(2) $(LDFLAGS) $(5) -o $(3) >>$(LOGFILE) 2>&1
|
|
endef
|
|
|
|
# helper function to prelink a file and log results
|
|
# arguments:
|
|
# $(1): source file name
|
|
# $(2): object file name
|
|
define prelink
|
|
command="$(CXXPRELINK) $(1) -o $(2)"; \
|
|
echo "$$command" >>$(LOGFILE); \
|
|
$(CXXPRELINK) $(1) -o $(2) >>$(LOGFILE)
|
|
endef
|
|
|
|
# helper function to create an archive out of an object file
|
|
define archive
|
|
command="$(AR) $(ARFLAGS) $(1) $(2)"; \
|
|
echo "$$command" >>$(LOGFILE); \
|
|
$(AR) $(ARFLAGS) $(1) $(2) >>$(LOGFILE)
|
|
endef
|
|
|
|
########################################################################
|
|
# TARGETS
|
|
########################################################################
|
|
|
|
all: config.h
|
|
|
|
|
|
# recreate config.h and update its timestamp
|
|
config.h: $(SRCS)
|
|
$(MAKE) config
|
|
touch config.h
|
|
|
|
# (re)create config.h; do not change timestamp if the new file is the same
|
|
# make .o first to make sure the %.o: %.cpp rule gets invoked (make bug?)
|
|
# run a configure script as the last step (e.g., to remove unwanted files)
|
|
|
|
# creates a file named vars.sh, containing shell assignments corresponding
|
|
# to makefile variables defined in $(BUILDDIR)/makefile.in (variables with
|
|
# invalid names (those containing periods) are commented out); vars.sh is
|
|
# used in libc_decl.sh to invoke the compiler and linker
|
|
config: clean sane
|
|
@([ -f config.h ] && mv config.h config.h.~ ; \
|
|
echo "// configured for $(CCNAME) on `uname -sr`" >config.h ; \
|
|
for file in $(TARGET) ; do \
|
|
src=$(SRCDIR)/$$file.cpp; \
|
|
desc=`head -n 1 2>/dev/null $$src | sed "s:// *::"`; \
|
|
[ "$$desc" != "" ] && printf "%-50.50s " "$$desc"; \
|
|
grep "[^a-zA-Z0-9_]*main *(" $$src >/dev/null 2>&1 ; \
|
|
if [ $$? -eq 0 ] ; then \
|
|
opts=`sed -n "s/^[^A-Z_a-z0-9]*LDOPTS *= *\(.*\)/\1/p" \
|
|
$$src`; \
|
|
targets="$$file.o $$file run RUN=$$file $(LOPT)=$$opts"; \
|
|
elif [ `echo $$file | grep "\.lib"` ] ; then \
|
|
targets="$$file$(LIBSUFFIX)" ; \
|
|
elif [ `echo $$file | grep "\.sh"` ] ; then \
|
|
if [ ! -f vars.sh ] ; then \
|
|
cat ../makefile.in \
|
|
| sed -e "s/= *\([^ ][^ ]* .*\)/=\"\1\"/" \
|
|
-e "s/^\( *[^=]*\.[^=]*=.*\)/# \1/" \
|
|
-e "s/^\([^ ]*\) *= *\(.*\)/\1=\2 ; export \1/" \
|
|
-e 's/$$(\([^)]*\))/${\1}/g' >vars.sh ; \
|
|
fi ; \
|
|
$(SRCDIR)/$$file config.h $(LOGFILE) ; \
|
|
echo ; \
|
|
continue ; \
|
|
else \
|
|
targets="$$file.o run RUN=$$file.o" ; \
|
|
fi; \
|
|
$(MAKE) $$targets OUTPUT=config.h -k >/dev/null 2>&1 ; \
|
|
if [ "$$desc" != "" ] ; then \
|
|
sym="_RWSTD_" ; \
|
|
echo $$file | grep "^NO_" >/dev/null ; \
|
|
[ $$? -ne 0 ] && sym="$${sym}NO_" ; \
|
|
str=`sed -n "s/\(.*\)\(#\)define $$sym$$file$$/\1\2/p" \
|
|
config.h`; \
|
|
if [ "$$str" = "// #" ] ; then \
|
|
echo "ok"; \
|
|
elif [ "$$str" = "#" ] ; then \
|
|
echo "no ($$sym$$file)"; \
|
|
else \
|
|
echo "--" ; \
|
|
fi; \
|
|
fi; \
|
|
done; \
|
|
diff config.h config.h.~ >/dev/null 2>&1 ; \
|
|
if [ $$? -eq 0 ] ; then \
|
|
mv config.h.~ config.h ; \
|
|
echo "config.h unchanged"; \
|
|
elif [ -f config.h~ ] ; then \
|
|
echo "previous config.h saved in config.h~"; \
|
|
fi; \
|
|
[ -x ./configure ] && ./configure -f ./config.h -d $(TOPDIR) ; \
|
|
exit 0)
|
|
|
|
# run one or more (perhaps all) executables in $(RUN) or $(TARGET) if
|
|
# the former is not defined; if an executable doesn't exist and the .o
|
|
# doesn't contain main it is still considered success (this is needed
|
|
# when the run target is invoked from within the %.o: %.cpp pattern rule
|
|
# .o's are not run (obviously) and are just assumed to be the result of
|
|
# a successful compilation
|
|
run:
|
|
@(output=$(OUTPUT) ; \
|
|
[ "$$output" = "" ] && output=/dev/tty ; \
|
|
target=$(RUN) ; \
|
|
[ "$$target" = "" ] && target=$(TARGET) ; \
|
|
for file in $$target ; do \
|
|
symbol="#define _RWSTD_" ; \
|
|
basename $$file | grep "^NO_" >/dev/null 2>&1 ; \
|
|
neg=$$? ; \
|
|
[ $$neg -ne 0 ] && symbol="$${symbol}NO_" ; \
|
|
symbol="$${symbol}`echo $$file \
|
|
| sed -e 's:.*/::' -e 's/\.o//'`"; \
|
|
if [ `echo $$file | grep "\.o"` ] ; then \
|
|
test -r $$file ; \
|
|
elif [ ! -x $$file ] ; then \
|
|
nm -gp $$file.o 2>&1 | grep "T *main *$$" >/dev/null ; \
|
|
test -f $$file.o -a ! $$? -eq 0 ; \
|
|
else \
|
|
echo "./$$file" >>$(LOGFILE) ; \
|
|
LD_LIBRARY_PATH=$$LD_LIBRARY_PATH:. ; \
|
|
LIBPATH=$$LIBPATH:. ; \
|
|
export LIBPATH LD_LIBRARY_PATH ; \
|
|
text=`./$$file` ; \
|
|
fi; \
|
|
res=$$? ; \
|
|
[ $$res -eq 0 -a $$neg -ne 0 ] \
|
|
|| [ $$res -ne 0 -a $$neg -eq 0 ] && symbol="// $$symbol" ;\
|
|
grep "$$symbol$$" config.h ; \
|
|
if [ $$? -ne 0 ] ; then \
|
|
echo "$$symbol" >>$$output; \
|
|
if [ "$$text" != "" ]; then \
|
|
printf "%s\n" "$$text" >>$$output; \
|
|
fi; \
|
|
fi; \
|
|
done; \
|
|
exit 0)
|
|
|
|
# determine the type of architecture (LP32, ILP32, ILP64, LLP64, or LP64)
|
|
arch:
|
|
@(output=$(OUTPUT); \
|
|
[ "$$output" = "" ] && output=/dev/tty ; \
|
|
for type in int long "long long" "void*" ; do \
|
|
echo "int main () { return sizeof ($$type); }" \
|
|
| tee a.cpp >>$(LOGFILE) ; \
|
|
$(call compile_then_link,a.cpp,a.o,a.out); \
|
|
if [ $$? -eq 0 ] ; then \
|
|
size="$$size`./a.out ; echo $$?`" ; \
|
|
else \
|
|
size="$${size}-"; \
|
|
fi; \
|
|
done; \
|
|
case "$$size" in \
|
|
24?4 ) arch="LP32" ;; 44?4 ) arch="ILP32" ;; \
|
|
88?8 ) arch="ILP64" ;; 4488 ) arch="LLP64" ;; \
|
|
48?8 ) arch="LP64" ;; * ) arch="$$size" ;; \
|
|
esac ; \
|
|
echo "int main () { int i = 1; return *(char*)&i; }" \
|
|
| tee a.cpp >>$(LOGFILE) ; \
|
|
$(call compile_then_link,a.cpp,a.o,a.out); \
|
|
if [ $$? -eq 0 ] ; then \
|
|
endian=" little endian" ; \
|
|
./a.out ; \
|
|
[ $$? -eq 0 ] && endian=" big endian" ; \
|
|
else \
|
|
echo "error"; \
|
|
cat $(LOGFILE); \
|
|
exit 1; \
|
|
fi; \
|
|
echo "$$arch$$endian" >$$output ; \
|
|
)
|
|
|
|
# check compiler, linker, and run environment's sanity, determine
|
|
# system (or compiler) architecture (word size, address size, etc.)
|
|
sane:
|
|
@(echo; \
|
|
echo "configuring stdcxx $(LIBVER) for $(CCNAME) on $(PLATFORM)"; \
|
|
echo; \
|
|
rm -f a.out ; \
|
|
echo "int main () { return 0; }" | tee a.cpp >>$(LOGFILE) ; \
|
|
printf "%-50.50s " "checking if the compiler is sane"; \
|
|
$(call compile,a.cpp,a.o); \
|
|
if [ $$? -eq 0 ] ; then \
|
|
echo "ok (invoked with $(CXX))"; \
|
|
else \
|
|
echo "no"; echo; \
|
|
cat $(LOGFILE) ; \
|
|
exit 1; \
|
|
fi; \
|
|
printf "%-50.50s " "checking if the linker is sane"; \
|
|
$(call link,a.o,a.out); \
|
|
if [ $$? -eq 0 ] ; then \
|
|
echo "ok (invoked with $(LD))"; \
|
|
else \
|
|
echo "no"; echo; \
|
|
cat $(LOGFILE) ; \
|
|
exit 1; \
|
|
fi; \
|
|
printf "%-50.50s " "checking system architecture"; \
|
|
`$(MAKE) arch OUTPUT=a.cpp>/dev/null 2>&1` ; \
|
|
cat a.cpp ; \
|
|
rm a.cpp )
|
|
|
|
clean:
|
|
@rm -f a.out core *.o *.i *.ii *.ti vars.sh \
|
|
*$(LIBSUFFIX) $(TARGET)
|
|
|
|
realclean: clean
|
|
rm -f *.d *.o *.a *.so a.cpp
|
|
|
|
listtarget:
|
|
@echo $(TARGET)
|
|
|
|
|
|
.PHONY: all clean config configure c_headers listtarget realclean run
|
|
|
|
|
|
########################################################################
|
|
# COMMON RULES
|
|
########################################################################
|
|
|
|
#empty rule for .cc files so they won't be separately compiled
|
|
%: %.cc ;
|
|
|
|
# compile .cpp so that any macros used by the translation unit are configured
|
|
# checks config.h to make sure macro isn't yet defined before going recursive
|
|
# *.lib.cpp files a compiled (and linked) into libraries (shared or static)
|
|
# with LDOPTS reset to the empty string
|
|
%.o: %.cpp
|
|
@(dep=`egrep "^ *# *if[n]*def *_RWSTD_" $< \
|
|
| sed -e "s/.*# *if[n]*def *\([^ ]*\) */\1/g" \
|
|
-e "s/_RWSTD_NO_//g" -e "s/_RWSTD_//g"` ; \
|
|
for sym in $$dep ; do \
|
|
fname=$$sym ; \
|
|
src=$(SRCDIR)/$$fname.cpp; \
|
|
[ ! -r $$src ] && fname="NO_$$fname" ; \
|
|
grep "_RWSTD_NO_$$sym$$" config.h >/dev/null ; \
|
|
if [ $$? -ne 0 ] ; then \
|
|
grep "[^a-zA-Z0-9_]*main *(" $$src >/dev/null 2>&1 ; \
|
|
if [ $$? -eq 0 ] ; then \
|
|
opts=`sed -n \
|
|
"s/^[^A-Z_a-z0-9]*LDOPTS *= *\(.*\)/\1/p" \
|
|
$$src`; \
|
|
targets="$$fname.o $$fname run RUN=$$fname \
|
|
$(LOPT)=$$opts" ; \
|
|
elif [ `echo $$fname | grep "\.lib"` ] ; then \
|
|
targets="$$fname$(LIBSUFFIX) $(LOPT)=" ; \
|
|
else \
|
|
targets="$$fname.o run RUN=$$fname.o" ; \
|
|
fi; \
|
|
$(MAKE) $$targets OUTPUT=config.h -k ; \
|
|
fi; \
|
|
done; \
|
|
true)
|
|
$(call compile,$<,$@)
|
|
|
|
# remove .o to prevent the run target from getting confused
|
|
%: %.o
|
|
$(call link,$^,$@); rm $<
|
|
|
|
# build a library from any source file named *.lib.cpp
|
|
%.lib$(LIBSUFFIX): %.lib.cpp
|
|
ifeq ($(findstring shared,$(BUILDMODE)),shared)
|
|
$(call compile,$<,$@.o,$(PICFLAGS))
|
|
ifeq ($(findstring xlC,$(CXX)),xlC)
|
|
# IBM xlC first "preprocesses" .o's with -qmkshrobj
|
|
# and then uses `ar' to create a shared library...
|
|
$(call prelink,$@.o,@.lib.o)
|
|
$(call archive,$@,$@.lib.o)
|
|
else
|
|
$(call link,$@.o,$@,$(LDSOFLAGS))
|
|
endif
|
|
else
|
|
$(call compile,$<,$@.o)
|
|
$(call archive,$@,$@.o)
|
|
endif
|
|
|
|
|
|
# parallelization of the configuration infrastructure not supported
|
|
.NOTPARALLEL:
|