# 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 := x86_64-w64-mingw32
chost := x86_64-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=
to specify its location)
endif
ifneq ($(words $(libbutl)),1)
$(error found multiple libbutl, use libbutl= 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= 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= to specify)
endif
endif
endif
# Figure out the list of source/object files.
#
# Note: list nested subdirectories first (used in clean).
#
build2_sub := \
c \
cc \
cxx
libbuild2_sub := \
config \
dist \
test/script \
test \
install \
bin \
version \
in
build2_src := $(wildcard $(src_root)/build2/*.cxx)
build2_src += $(foreach d,$(build2_sub),$(wildcard $(src_root)/build2/$d/*.cxx))
libbuild2_src := $(wildcard $(src_root)/libbuild2/*.cxx)
libbuild2_src += $(foreach d,$(libbuild2_sub),$(wildcard $(src_root)/libbuild2/$d/*.cxx))
libbutl_src := $(wildcard $(libbutl)/libbutl/*.cxx)
# Filter out *.test.cxx sources.
#
build2_src := $(filter-out %.test.cxx,$(build2_src))
libbuild2_src := $(filter-out %.test.cxx,$(libbuild2_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))
libbuild2_obj := $(patsubst $(src_root)/%.cxx,$(out_root)/%.b.o,$(libbuild2_src))
libbutl_obj := $(patsubst $(libbutl)/libbutl/%.cxx,$(libbutl_out)/%.b.o,$(libbutl_src))
# Build.
#
$(out_root)/build2/b-boot$(exe): $(build2_obj) $(libbuild2_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 $<
$(out_root)/libbuild2/%.b.o: $(src_root)/libbuild2/%.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 $(libbuild2_obj)
rm -f $(libbutl_obj)
clean: cleano
rm -f $(out_root)/build2/b-boot$(exe)
ifeq ($(in_tree),false)
rm -fd $(foreach d,$(build2_sub),$(out_root)/build2/$d) $(out_root)/build2 $(foreach d,$(libbuild2_sub),$(out_root)/libbuild2/$d) $(out_root)/libbuild2 $(libbutl_out)
endif