blob: 2a413440133bfe9722f71240bc6ed4c8bd6f204e [file] [log] [blame]
# GRPC global makefile
# This currently builds C and C++ code.
<%!
from copy import deepcopy
import re
proto_re = re.compile('(.*)\.proto')
def excluded(filename, exclude_res):
for r in exclude_res:
if r.match(filename):
return True
return False
def proto_to_cc(filename):
m = proto_re.match(filename)
if not m:
return filename
return 'gens/' + m.group(1) + '.pb.cc'
%>
<%
altlibs = []
for lib in libs:
for alt in lib.get('alternates', []):
new = deepcopy(lib)
new.name = alt.name
new.alternates = []
exclude_res = [re.compile(str) for str in alt.get('exclude_res', [])]
src = [file for file in new.get('src', []) if not excluded(file, exclude_res)]
src.extend(alt.get('include_src', []))
new.src = src
headers = [file for file in new.get('headers', []) if not excluded(file, exclude_res)]
headers.extend(alt.get('include_headers', []))
new.headers = headers
public_headers = [file for file in new.get('public_headers', []) if not excluded(file, exclude_res)]
public_headers.extend(alt.get('include_public_headers', []))
new.public_headers = public_headers
for prop in alt.properties:
new[prop.name] = prop.value
altlibs.append(new)
libs.extend(altlibs)
protos = set()
for lib in libs:
for src in lib.src:
m = proto_re.match(src)
if m:
protos.add(m.group(1))
for tgt in targets:
for src in tgt.src:
m = proto_re.match(src)
if m:
protos.add(m.group(1))
protos = sorted(protos)
%>
# General settings.
# You may want to change these depending on your system.
prefix ?= /usr/local
PROTOC = protoc
CC = gcc
CXX = g++
LD = gcc
LDXX = g++
AR = ar
STRIP = strip --strip-unneeded
INSTALL = install -D
RM = rm -f
HOST_CC = $(CC)
HOST_CXX = $(CXX)
HOST_LD = $(LD)
HOST_LDXX = $(LDXX)
ifeq ($(DEBUG),)
CPPFLAGS += -O2
DEFINES += NDEBUG
else
CPPFLAGS += -O0
DEFINES += _DEBUG DEBUG
endif
CFLAGS += -std=c89 -pedantic
CXXFLAGS += -std=c++11
CPPFLAGS += -g -fPIC -Wall -Werror -Wno-long-long
LDFLAGS += -g -pthread -fPIC
INCLUDES = . include gens
LIBS = rt m z event event_pthreads pthread
LIBSXX = protobuf
LIBS_SECURE = ssl crypto dl
LIBS_PROTOC = protoc protobuf
ifneq ($(wildcard /usr/src/gtest/src/gtest-all.cc),)
GTEST_LIB = /usr/src/gtest/src/gtest-all.cc -I/usr/src/gtest
else
GTEST_LIB = -lgtest
endif
GTEST_LIB += -lgflags
ifeq ($(V),1)
E = @:
Q =
else
E = @echo
Q = @
endif
VERSION = ${settings.version.major}.${settings.version.minor}.${settings.version.micro}.${settings.version.build}
CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES))
CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS)
LDFLAGS += $(ARCH_FLAGS)
LDLIBS += $(addprefix -l, $(LIBS))
LDLIBSXX += $(addprefix -l, $(LIBSXX))
LDLIBS_SECURE += $(addprefix -l, $(LIBS_SECURE))
HOST_LDLIBS_PROTOC += $(addprefix -l, $(LIBS_PROTOC))
HOST_CPPFLAGS = $(CPPFLAGS)
HOST_CFLAGS = $(CFLAGS)
HOST_CXXFLAGS = $(CXXFLAGS)
HOST_LDFLAGS = $(LDFLAGS)
HOST_LDLIBS = $(LDLIBS)
# These are automatically computed variables.
# There shouldn't be any need to change anything from now on.
HOST_SYSTEM = $(shell uname | cut -f 1 -d_)
ifeq ($(SYSTEM),)
SYSTEM = $(HOST_SYSTEM)
endif
ifeq ($(wildcard .git),)
IS_GIT_FOLDER = false
else
IS_GIT_FOLDER = true
endif
EVENT2_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/event2.c -levent $(LDFLAGS)
OPENSSL_ALPN_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/openssl-alpn.c -levent $(LDFLAGS) $(LDLIBS_SECURE)
ZLIB_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/event2.c -levent $(LDFLAGS)
HAS_SYSTEM_EVENT2 = $(shell $(EVENT2_CHECK_CMD) 2> /dev/null && echo true || echo false)
HAS_SYSTEM_OPENSSL_ALPN = $(shell $(OPENSSL_ALPN_CHECK_CMD) 2> /dev/null && echo true || echo false)
HAS_SYSTEM_ZLIB = $(shell $(ZLIB_CHECK_CMD) 2> /dev/null && echo true || echo false)
ifeq ($(wildcard third_party/libevent/include/event2/event.h),)
HAS_EMBEDDED_EVENT2 = false
else
HAS_EMBEDDED_EVENT2 = true
endif
ifeq ($(wildcard third_party/openssl/ssl/ssl.h),)
HAS_EMBEDDED_OPENSSL_ALPN = false
else
HAS_EMBEDDED_OPENSSL_ALPN = true
endif
ifeq ($(wildcard third_party/zlib/zlib.h),)
HAS_EMBEDDED_ZLIB = false
else
HAS_EMBEDDED_ZLIB = true
endif
ifneq ($(SYSTEM),MINGW32)
ifeq ($(HAS_SYSTEM_EVENT2),false)
DEP_MISSING += libevent
endif
endif
ifeq ($(HAS_SYSTEM_ZLIB),false)
ifeq ($(HAS_EMBEDDED_ZLIB),true)
ZLIB_DEP = third_party/zlib/libz.a
CPPFLAGS += -Ithird_party/zlib
LDFLAGS += -Lthird_party/zlib
else
DEP_MISSING += zlib
endif
endif
ifeq ($(HAS_SYSTEM_OPENSSL_ALPN),false)
ifeq ($(HAS_EMBEDDED_OPENSSL_ALPN),true)
OPENSSL_DEP = third_party/openssl/libssl.a
CPPFLAGS += -Ithird_party/openssl/include
LDFLAGS += -Lthird_party/openssl
else
NO_SECURE = true
endif
endif
ifneq ($(DEP_MISSING),)
NO_DEPS = true
endif
ifneq ($(MAKECMDGOALS),clean)
NO_DEPS = true
endif
.SECONDARY = %.pb.h %.pb.cc
ifeq ($(DEP_MISSING),)
all: static shared\
% for tgt in targets:
% if tgt.build == 'all':
bins/${tgt.name}\
% endif
% endfor
dep_error:
@echo "You shouldn't see this message - all of your dependencies are correct."
else
all: dep_error git_update stop
dep_error:
@echo
@echo "DEPENDENCY ERROR"
@echo
@echo "You are missing system dependencies that are essential to build grpc,"
@echo "and the third_party directory doesn't have them:"
@echo
@echo " $(DEP_MISSING)"
@echo
@echo "Installing the development packages for your system will solve"
@echo "this issue. Please consult INSTALL to get more information."
@echo
@echo "If you need information about why these tests failed, run:"
@echo
@echo " make run_dep_checks"
@echo
endif
git_update:
ifeq ($(IS_GIT_FOLDER),true)
@echo "Additionally, since you are in a git clone, you can download the"
@echo "missing dependencies in third_party by running the following command:"
@echo
@echo " git submodule update --init"
@echo
endif
openssl_dep_error: openssl_dep_message git_update stop
openssl_dep_message:
@echo
@echo "DEPENDENCY ERROR"
@echo
@echo "The target you are trying to run requires OpenSSL with ALPN support."
@echo "Your system doesn't have it, and neither does the third_party directory."
@echo
@echo "Please consult INSTALL to get more information."
@echo
@echo "If you need information about why these tests failed, run:"
@echo
@echo " make run_dep_checks"
@echo
stop:
@false
run_dep_checks:
$(EVENT2_CHECK_CMD) || true
$(OPENSSL_ALPN_CHECK_CMD) || true
$(ZLIB_CHECK_CMD) || true
third_party/zlib/libz.a:
(cd third_party/zlib ; CFLAGS="-fPIC -fvisibility=hidden" ./configure --static)
$(MAKE) -C third_party/zlib
third_party/openssl/libssl.a:
(cd third_party/openssl ; CC="$(CC) -fPIC -fvisibility=hidden" ./config)
$(MAKE) -C third_party/openssl build_crypto build_ssl
static: static_c static_cxx
static_c: dep_c\
% for lib in libs:
% if lib.build == 'all' and not lib.get('c++', False):
libs/lib${lib.name}.a\
% endif
% endfor
static_cxx: dep_cxx\
% for lib in libs:
% if lib.build == 'all' and lib.get('c++', False):
libs/lib${lib.name}.a\
% endif
% endfor
shared: shared_c shared_cxx
shared_c: dep_c\
% for lib in libs:
% if lib.build == 'all' and not lib.get('c++', False):
libs/lib${lib.name}.so.$(VERSION)\
% endif
% endfor
shared_cxx: dep_cxx\
% for lib in libs:
% if lib.build == 'all' and lib.get('c++', False):
libs/lib${lib.name}.so.$(VERSION)\
% endif
% endfor
privatelibs: privatelibs_c privatelibs_cxx
privatelibs_c: dep_c\
% for lib in libs:
% if lib.build == 'private':
libs/lib${lib.name}.a\
% endif
% endfor
privatelibs_cxx: dep_cxx\
% for lib in libs:
% if lib.build == 'private':
libs/lib${lib.name}.a\
% endif
% endfor
buildtests: buildtests_c buildtests_cxx
buildtests_c: bins_dep_c privatelibs_c\
% for tgt in targets:
% if tgt.build == 'test' and not tgt.get('c++', False):
bins/${tgt.name}\
% endif
% endfor
buildtests_cxx: bins_dep_cxx privatelibs_cxx\
% for tgt in targets:
% if tgt.build == 'test' and tgt.get('c++', False):
bins/${tgt.name}\
% endif
% endfor
test: test_c test_cxx
test_c: buildtests_c
% for tgt in targets:
% if tgt.build == 'test' and tgt.get('run', True) and not tgt.get('c++', False):
$(E) "[RUN] Testing ${tgt.name}"
$(Q) ./bins/${tgt.name} || ( echo test ${tgt.name} failed ; exit 1 )
% endif
% endfor
test_cxx: buildtests_cxx
% for tgt in targets:
% if tgt.build == 'test' and tgt.get('run', True) and tgt.get('c++', False):
$(E) "[RUN] Testing ${tgt.name}"
$(Q) ./bins/${tgt.name} || ( echo test ${tgt.name} failed ; exit 1 )
% endif
% endfor
tools: privatelibs\
% for tgt in targets:
% if tgt.build == 'tool':
bins/${tgt.name}\
% endif
% endfor
protoc_plugins:\
% for tgt in targets:
% if tgt.build == 'protoc':
bins/${tgt.name}\
% endif
% endfor
buildbenchmarks: privatelibs\
% for tgt in targets:
% if tgt.build == 'benchmark':
bins/${tgt.name}\
% endif
% endfor
benchmarks: buildbenchmarks
strip: strip-static strip-shared
strip-static_c: static_c
% for lib in libs:
% if not lib.get("c++", False):
% if lib.build == "all":
$(E) "[STRIP] Stripping lib${lib.name}.a"
$(Q) $(STRIP) libs/lib${lib.name}.a
% endif
% endif
% endfor
strip-static_cxx: static_cxx
% for lib in libs:
% if lib.get("c++", False):
% if lib.build == "all":
$(E) "[STRIP] Stripping lib${lib.name}.a"
$(Q) $(STRIP) libs/lib${lib.name}.a
% endif
% endif
% endfor
strip-shared_c: shared_c
% for lib in libs:
% if not lib.get("c++", False):
% if lib.build == "all":
$(E) "[STRIP] Stripping lib${lib.name}.so"
$(Q) $(STRIP) libs/lib${lib.name}.so.$(VERSION)
% endif
% endif
% endfor
strip-shared_cxx: shared_cxx
% for lib in libs:
% if lib.get("c++", False):
% if lib.build == "all":
$(E) "[STRIP] Stripping lib${lib.name}.so"
$(Q) $(STRIP) libs/lib${lib.name}.so.$(VERSION)
% endif
% endif
% endfor
% for p in protos:
deps/gens/${p}.pb.dep:
$(Q) mkdir -p `dirname $@`
$(Q) touch $@
gens/${p}.pb.cc: ${p}.proto protoc_plugins
$(E) "[PROTOC] Generating protobuf CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --cpp_out=gens --grpc_out=gens --plugin=protoc-gen-grpc=bins/cpp_plugin $<
% endfor
deps/%.dep : %.c
$(E) "[DEP] Generating dependencies for $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(CC) $(CFLAGS) $(CPPFLAGS_NO_ARCH) -MG -M $< > $@
deps/%.dep : %.cc
$(E) "[DEP] Generating dependencies for $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(CXX) $(CXXFLAGS) $(CPPFLAGS_NO_ARCH) -MG -M $< > $@
objs/%.o : %.c
$(E) "[C] Compiling $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
objs/%.o : gens/%.pb.cc
$(E) "[CXX] Compiling $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
objs/src/compiler/%.o : src/compiler/%.cc
$(E) "[HOSTCXX] Compiling $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(HOST_CXX) $(HOST_CXXFLAGS) $(HOST_CPPFLAGS) -c -o $@ $<
objs/%.o : %.cc
$(E) "[CXX] Compiling $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
dep: dep_c dep_cxx
dep_c:\
% for lib in libs:
% if not lib.get('c++', False):
deps_lib${lib.name}\
% endif
% endfor
bins_dep_c:\
% for tgt in targets:
% if not tgt.get('c++', False):
deps_${tgt.name}\
% endif
% endfor
dep_cxx:\
% for lib in libs:
% if lib.get('c++', False):
deps_lib${lib.name}\
% endif
% endfor
bins_dep_cxx:\
% for tgt in targets:
% if tgt.get('c++', False):
deps_${tgt.name}\
% endif
% endfor
install: install_c install_cxx
install_c: install-headers_c install-static_c install-shared_c
install_cxx: install-headers_cxx install-static_cxx install-shared_cxx
install-headers: install-headers_c install-headers_cxx
install-headers_c:
$(E) "[INSTALL] Installing public C headers"
$(Q) $(foreach h, $(PUBLIC_HEADERS_C), $(INSTALL) $(h) $(prefix)/$(h) && ) exit 0 || exit 1
install-headers_cxx:
$(E) "[INSTALL] Installing public C++ headers"
$(Q) $(foreach h, $(PUBLIC_HEADERS_CXX), $(INSTALL) $(h) $(prefix)/$(h) && ) exit 0 || exit 1
install-static: install-static_c install-static_cxx
install-static_c: static_c strip-static_c
% for lib in libs:
% if not lib.get("c++", False):
% if lib.build == "all":
$(E) "[INSTALL] Installing lib${lib.name}.a"
$(Q) $(INSTALL) libs/lib${lib.name}.a $(prefix)/lib/lib${lib.name}.a
% endif
% endif
% endfor
install-static_cxx: static_cxx strip-static_cxx
% for lib in libs:
% if lib.get("c++", False):
% if lib.build == "all":
$(E) "[INSTALL] Installing lib${lib.name}.a"
$(Q) $(INSTALL) libs/lib${lib.name}.a $(prefix)/lib/lib${lib.name}.a
% endif
% endif
% endfor
install-shared_c: shared_c strip-shared_c
% for lib in libs:
% if not lib.get("c++", False):
% if lib.build == "all":
$(E) "[INSTALL] Installing lib${lib.name}.so"
$(Q) $(INSTALL) libs/lib${lib.name}.so.$(VERSION) $(prefix)/lib/lib${lib.name}.so.$(VERSION)
% endif
% endif
% endfor
install-shared_cxx: shared_cxx strip-shared_cxx
% for lib in libs:
% if lib.get("c++", False):
% if lib.build == "all":
$(E) "[INSTALL] Installing lib${lib.name}.so"
$(Q) $(INSTALL) libs/lib${lib.name}.so.$(VERSION) $(prefix)/lib/lib${lib.name}.so.$(VERSION)
% endif
% endif
% endfor
clean:\
% for lib in libs:
clean_lib${lib.name}\
% endfor
% for tgt in targets:
clean_${tgt.name}\
% endfor
$(Q) $(RM) -r deps objs libs bins gens
# The various libraries
% for lib in libs:
${makelib(lib)}
% endfor
# All of the test targets, and protoc plugins
% for tgt in targets:
${maketarget(tgt)}
% endfor
<%def name="makelib(lib)">
LIB${lib.name.upper()}_SRC = \\
% for src in lib.src:
${proto_to_cc(src)} \\
% endfor
% if "public_headers" in lib:
% if lib.get("c++", False):
PUBLIC_HEADERS_CXX += \\
% else:
PUBLIC_HEADERS_C += \\
% endif
% for hdr in lib.public_headers:
${hdr} \\
% endfor
% endif
LIB${lib.name.upper()}_OBJS = $(addprefix objs/, $(addsuffix .o, $(basename $(LIB${lib.name.upper()}_SRC))))
LIB${lib.name.upper()}_DEPS = $(addprefix deps/, $(addsuffix .dep, $(basename $(LIB${lib.name.upper()}_SRC))))
% if lib.get('secure', True):
LIB${lib.name.upper()}_OBJS += $(OPENSSL_DEP)
ifeq ($(NO_SECURE),true)
libs/lib${lib.name}.a: openssl_dep_error
else
% endif
libs/lib${lib.name}.a: $(LIB${lib.name.upper()}_OBJS)
$(E) "[AR] Creating $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(AR) rcs libs/lib${lib.name}.a $(LIB${lib.name.upper()}_OBJS)
% if lib.build == "all":
libs/lib${lib.name}.so.$(VERSION): $(LIB${lib.name.upper()}_OBJS)
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
% if lib.get('c++', False):
$(Q) $(LDXX) $(LDFLAGS) -shared -Wl,-soname,lib${lib.name}.so.${settings.version.major} \
% else:
$(Q) $(LD) $(LDFLAGS) -shared -Wl,-soname,lib${lib.name}.so.${settings.version.major} \
% endif
-o libs/lib${lib.name}.so.$(VERSION) $(LIB${lib.name.upper()}_OBJS) $(LDLIBS)\
% if lib.get('secure', True):
$(LDLIBS_SECURE)\
% endif
% endif
% if lib.get('secure', True):
endif
% endif
deps_lib${lib.name}: $(LIB${lib.name.upper()}_DEPS)
% if lib.get('secure', True):
ifneq ($(NO_SECURE),true)
% endif
ifneq ($(NO_DEPS),true)
-include $(LIB${lib.name.upper()}_DEPS)
endif
% if lib.get('secure', True):
endif
% endif
clean_lib${lib.name}:
$(E) "[CLEAN] Cleaning lib${lib.name} files"
$(Q) $(RM) $(LIB${lib.name.upper()}_OBJS)
$(Q) $(RM) $(LIB${lib.name.upper()}_DEPS)
$(Q) $(RM) libs/lib${lib.name}.a
$(Q) $(RM) libs/lib${lib.name}.so.$(VERSION)
</%def>
<%def name="maketarget(tgt)">
${tgt.name.upper()}_SRC = \\
% for src in tgt.src:
${proto_to_cc(src)} \\
% endfor
${tgt.name.upper()}_OBJS = $(addprefix objs/, $(addsuffix .o, $(basename $(${tgt.name.upper()}_SRC))))
${tgt.name.upper()}_DEPS = $(addprefix deps/, $(addsuffix .dep, $(basename $(${tgt.name.upper()}_SRC))))
% if tgt.get('secure', True):
ifeq ($(NO_SECURE),true)
bins/${tgt.name}: openssl_dep_error
else
% endif
bins/${tgt.name}: $(${tgt.name.upper()}_OBJS)\
% for dep in tgt.deps:
libs/lib${dep}.a\
% endfor
% if tgt.get("c++", False):
% if tgt.build == 'protoc':
$(E) "[HOSTLD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(HOST_LDXX) $(HOST_LDFLAGS) $(${tgt.name.upper()}_OBJS)\
% else:
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(${tgt.name.upper()}_OBJS)\
% endif
% if tgt.build == 'test':
$(GTEST_LIB)\
% endif
-Llibs\
% else:
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(${tgt.name.upper()}_OBJS) -Llibs\
% endif
% for dep in tgt.deps:
-l${dep}\
% endfor
% if tgt.get("c++", False):
% if tgt.build == 'protoc':
$(HOST_LDLIBSXX)\
% else:
$(LDLIBSXX)\
% endif
% endif
% if tgt.build == 'protoc':
$(HOST_LDLIBS)\
% else:
$(LDLIBS)\
% endif
% if tgt.build == 'protoc':
$(HOST_LDLIBS_PROTOC)\
% elif tgt.get('secure', True):
$(LDLIBS_SECURE)\
% endif
-o bins/${tgt.name}
% if tgt.get('secure', True):
endif
% endif
deps_${tgt.name}: $(${tgt.name.upper()}_DEPS)
% if tgt.get('secure', True):
ifneq ($(NO_SECURE),true)
% endif
ifneq ($(NO_DEPS),true)
-include $(${tgt.name.upper()}_DEPS)
endif
% if tgt.get('secure', True):
endif
% endif
clean_${tgt.name}:
$(E) "[CLEAN] Cleaning ${tgt.name} files"
$(Q) $(RM) $(${tgt.name.upper()}_OBJS)
$(Q) $(RM) $(${tgt.name.upper()}_DEPS)
$(Q) $(RM) bins/${tgt.name}
</%def>
.PHONY: all strip tools \
dep_error openssl_dep_error openssl_dep_message git_update stop \
buildtests buildtests_c buildtests_cxx \
test test_c test_cxx \
install install_c install_cxx \
install-headers install-headers_c install-headers_cxx \
install-shared install-shared_c install-shared_cxx \
install-static install-static_c install-static_cxx \
strip strip-shared strip-static \
strip_c strip-shared_c strip-static_c \
strip_cxx strip-shared_cxx strip-static_cxx \
clean \
dep_c dep_cxx bins_dep_c bins_dep_cxx\
% for lib in libs:
deps_lib${lib.name} clean_lib${lib.name}\
% endfor
% for tgt in targets:
deps_${tgt.name} clean_${tgt.name}\
% endfor