| # -*- Makefile -*- |
| # |
| # $Id$ |
| # |
| # 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: |