# file : bootstrap.gmake -*- Makefile -*- # copyright : Copyright (c) 2014-2019 Code Synthesis Ltd # license : MIT; see accompanying LICENSE file # This makefile requires GNU make 3.81 or later and can be used to bootstrap # the build system similar to the bootstrap.sh script. Its main advantages over # the script are support for parallel compilation and an out of tree build. # # Similar to the script, the makefile expects to find the libbutl/ or # libbutl-*/ directory either in the current directory (build2 root) or one # level up. Both in-tree and out-of-tree builds as well as the 'clean' target # are supported. The result is saved as build2/b-boot. # # Typical in-tree build: # # cd build2-X.Y.Z # make -f bootstrap.gmake -j 8 CXX=g++-7 # # Typical out-of-tree build: # # mkdir build2-boot # cd build2-boot # make -f ../build2-X.Y.Z/bootstrap.gmake -j 8 CXX=g++-7 # # If used on Windows, then this makefile assumes you are building in the # MinGW environment and sets things up similar to bootstrap-mingw.bat. # # The following standard make variables can be used to customize the build: # # CXX # CPPFLAGS # CXXFLAGS # LDFLAGS # LIBS exe := host := chost := ifeq ($(OS),Windows_NT) exe := .exe host := i686-w64-mingw32 chost := i686-w64-mingw32 override LIBS += -limagehlp else override LIBS += -lpthread endif # Remove all the built-in rules, enable second expansion, etc. # .SUFFIXES: ifeq ($(filter -r,$(MAKEFLAGS)),) MAKEFLAGS += -r endif .DELETE_ON_ERROR: .SECONDEXPANSION: # We build in CWD and figure out the source directory based on the makefile # path. # out_root := . src_root := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST)))) ifeq ($(realpath $(out_root)),$(realpath $(src_root))) in_tree := true else in_tree := false endif # See if there is libbutl or libbutl-* in src_root or one directory up. # libbutl := ifeq ($(libbutl),) libbutl := $(filter %/,$(wildcard $(src_root)/libbutl/)) ifeq ($(libbutl),) libbutl := $(filter %/,$(wildcard $(src_root)/libbutl-*/)) endif endif ifeq ($(libbutl),) libbutl := $(filter %/,$(wildcard $(src_root)/../libbutl/)) ifeq ($(libbutl),) libbutl := $(filter %/,$(wildcard $(src_root)/../libbutl-*/)) endif endif ifeq ($(libbutl),) $(error unable to find libbutl, use libbutl=<dir> to specify its location) endif ifneq ($(words $(libbutl)),1) $(error found multiple libbutl, use libbutl=<dir> to specify its location) endif libbutl := $(patsubst %/,%,$(libbutl)) # Figure out libbutl output directory. If we are building in-tree, then build # libbutl in-tree as well, whether inside or level up. Otherwise -- in the # libbutl subdirectory. # ifeq ($(in_tree),true) libbutl_out := $(libbutl)/libbutl else libbutl_out := $(out_root)/libbutl endif # Obtain the host triplet. # ifeq ($(host),) host := $(shell $(src_root)/config.guess) ifeq ($(host),) $(error unable to guess host triplet, use host=<triplet> to specify) endif chost := $(host) else ifeq ($(chost),) chost := $(shell $(src_root)/config.sub $(host)) ifeq ($(chost),) $(error unable to canonicalize host triplet, use chost=<triplet> to specify) endif endif endif # Figure out the list of source/object files. # # Note: list nested subdirectories first (used in clean). # sub_dirs := \ config \ dist \ bin \ c \ cc \ cxx \ test/script \ test \ version \ install \ in build2_src := $(wildcard $(src_root)/build2/*.cxx) build2_src += $(foreach d,$(sub_dirs),$(wildcard $(src_root)/build2/$d/*.cxx)) libbutl_src := $(wildcard $(libbutl)/libbutl/*.cxx) # Filter out *.test.cxx sources. # build2_src := $(filter-out %.test.cxx,$(build2_src)) libbutl_src := $(filter-out %.test.cxx,$(libbutl_src)) # Note that we use the .b.o object file extension to avoid clashing with the # build2 builds. # build2_obj := $(patsubst $(src_root)/%.cxx,$(out_root)/%.b.o,$(build2_src)) libbutl_obj := $(patsubst $(libbutl)/libbutl/%.cxx,$(libbutl_out)/%.b.o,$(libbutl_src)) # Build. # $(out_root)/build2/b-boot$(exe): $(build2_obj) $(libbutl_obj) $(CXX) -std=c++1y $(CXXFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) $(out_root)/build2/%.b.o: $(src_root)/build2/%.cxx | $$(dir $$@). $(CXX) -I$(libbutl) -I$(src_root) -DBUILD2_BOOTSTRAP -DBUILD2_HOST_TRIPLET=\"$(chost)\" $(CPPFLAGS) -std=c++1y $(CXXFLAGS) -o $@ -c $< $(libbutl_out)/%.b.o: $(libbutl)/libbutl/%.cxx | $$(dir $$@). $(CXX) -I$(libbutl) -DBUILD2_BOOTSTRAP $(CPPFLAGS) -std=c++1y $(CXXFLAGS) -o $@ -c $< .PRECIOUS: %/. %/. : mkdir -p $* .PHONY: all all: $(out_root)/build2/b-boot$(exe) # Clean. # .PHONY: clean cleano cleano: rm -f $(build2_obj) rm -f $(libbutl_obj) clean: cleano rm -f $(out_root)/build2/b-boot$(exe) ifeq ($(in_tree),false) rm -fd $(foreach d,$(sub_dirs),$(out_root)/build2/$d) $(out_root)/build2 $(libbutl_out) endif