summaryrefslogtreecommitdiffstats
path: root/compilerplugins/Makefile-clang.mk
diff options
context:
space:
mode:
Diffstat (limited to 'compilerplugins/Makefile-clang.mk')
-rw-r--r--compilerplugins/Makefile-clang.mk365
1 files changed, 365 insertions, 0 deletions
diff --git a/compilerplugins/Makefile-clang.mk b/compilerplugins/Makefile-clang.mk
new file mode 100644
index 0000000000..16a75e44b4
--- /dev/null
+++ b/compilerplugins/Makefile-clang.mk
@@ -0,0 +1,365 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+# Make sure variables in this Makefile do not conflict with other variables (e.g. from gbuild).
+
+# Set to 1 if you need to debug the plugin).
+CLANGDEBUG=
+
+# Compile flags, you may occasionally want to override these:
+ifeq ($(OS),WNT)
+# See LLVM's cmake/modules/AddLLVM.cmake and LLVM build's
+# tools/llvm-config/BuildVariables.inc:
+# * Ignore "warning C4141: 'inline': used more than once" as emitted upon
+# "LLVM_ATTRIBUTE_ALWAYS_INLINE inline" in various LLVM include files.
+# * Ignore "warning C4577: 'noexcept' used with no exception handling mode
+# specified; termination on exception is not guaranteed. Specify /EHsc".
+CLANGCXXFLAGS=/nologo /D_HAS_EXCEPTIONS=0 /wd4141 /wd4577 /EHs-c- /GR-
+ifeq ($(CLANGDEBUG),)
+CLANGCXXFLAGS+=/O2 /Oi
+else
+CLANGCXXFLAGS+=/DEBUG /Od
+endif
+else # WNT
+CLANGCXXFLAGS=-Wall -Wextra -Wundef -fvisibility-inlines-hidden
+ifeq ($(CLANGDEBUG),)
+CLANGCXXFLAGS+=-O2
+else
+CLANGCXXFLAGS+=-g -O0 -UNDEBUG
+endif
+endif
+
+# Whether to make plugins use one shared ASTRecursiveVisitor (plugins run faster).
+# By default enabled, disable if you work on an affected plugin (re-generating takes time).
+LO_CLANG_SHARED_PLUGINS=1
+#TODO: Windows doesn't use LO_CLANG_SHARED_PLUGINS for now, see corresponding TODO comment in
+# configure.ac:
+ifeq ($(OS),WNT)
+LO_CLANG_SHARED_PLUGINS=
+endif
+
+# Whether to use precompiled headers for the sources. This is actually controlled
+# by gb_ENABLE_PCH like everywhere else, but unsetting this disables PCH.
+LO_CLANG_USE_PCH=1
+
+# The uninteresting rest.
+
+include $(SRCDIR)/solenv/gbuild/gbuild.mk
+include $(SRCDIR)/solenv/gbuild/Output.mk
+
+CLANG_COMMA :=,
+
+ifeq ($(OS),WNT)
+CLANG_DL_EXT = .dll
+CLANG_EXE_EXT = .exe
+else
+CLANG_DL_EXT = .so
+CLANG_EXE_EXT =
+endif
+
+# Clang headers require these.
+CLANGDEFS:=$(COMPILER_PLUGINS_CXXFLAGS)
+# All include locations needed (using -isystem silences various warnings when
+# including those files):
+ifneq ($(OS),WNT)
+CLANGDEFS:=$(filter-out -isystem/usr/include,$(foreach opt,$(CLANGDEFS),$(patsubst -I%,-isystem%,$(opt))))
+endif
+
+# Clang/LLVM libraries are intentionally not linked in, they are usually built as static libraries, which means the resulting
+# plugin would be big (even though the clang binary already includes it all) and it'd be necessary to explicitly specify
+# also all the dependency libraries.
+
+CLANGINDIR=$(SRCDIR)/compilerplugins/clang
+# Cannot use $(WORKDIR), the plugin should survive even 'make clean', otherwise the rebuilt
+# plugin will cause cache misses with ccache.
+CLANGOUTDIR=$(BUILDDIR)/compilerplugins/clang
+CLANGOBJDIR=$(CLANGOUTDIR)/obj
+
+ifdef LO_CLANG_SHARED_PLUGINS
+CLANGCXXFLAGS+=-DLO_CLANG_SHARED_PLUGINS
+endif
+
+ifneq ($(CLANGDEBUG),)
+ifeq ($(HAVE_GCC_SPLIT_DWARF),TRUE)
+CLANGCXXFLAGS+=-gsplit-dwarf
+endif
+endif
+
+QUIET=$(if $(verbose),,@)
+
+ifneq ($(ENABLE_WERROR),)
+ifeq ($(OS),WNT)
+CLANGWERROR :=
+#TODO: /WX
+else
+CLANGWERROR := -Werror
+# When COMPILER_PLUGINS_CXXFLAGS (obtained via `llvm-config --cxxflags`) contains options like
+# -Wno-maybe-uninitialized that are targeting GCC (when LLVM was actually built with GCC), and
+# COMPILER_PLUGINS_CXX (defaulting to CXX) denotes a Clang that does not understand those options,
+# it fails with -Werror,-Wunknown-warning-option, so we need -Wno-unknown-warning-option (but which
+# GCC does not understand) at least with -Werror:
+ifeq ($(COMPILER_PLUGINS_COM_IS_CLANG),TRUE)
+CLANGWERROR += -Wno-unknown-warning-option
+endif
+endif
+endif
+
+ifneq ($(LO_CLANG_USE_PCH),)
+# Reset and enable only if actually supported and enabled.
+LO_CLANG_USE_PCH=
+ifneq ($(gb_ENABLE_PCH),)
+ifneq ($(OS),WNT)
+# Currently only Clang PCH is supported (which should usually be the case, as Clang is usually self-built).
+ifneq ($(findstring clang,$(COMPILER_PLUGINS_CXX)),)
+LO_CLANG_USE_PCH=1
+LO_CLANG_PCH_FLAGS:=-Xclang -fno-pch-timestamp
+endif
+endif
+endif
+endif
+
+
+compilerplugins: compilerplugins-build
+
+ifdef LO_CLANG_SHARED_PLUGINS
+# The shared source, intentionally put first in the list because it takes the longest to build.
+CLANGSRCOUTDIR=$(CLANGOUTDIR)/sharedvisitor/sharedvisitor.cxx
+CLANGSRC+=$(CLANGSRCOUTDIR)
+endif
+# The list of source files, generated automatically (all files in clang/, but not subdirs).
+CLANGSRCINDIR=$(sort $(foreach src,$(wildcard $(CLANGINDIR)/*.cxx), $(notdir $(src))))
+CLANGSRC+=$(CLANGSRCINDIR)
+
+# Remember the sources and if they have changed, force plugin relinking.
+CLANGSRCCHANGED= \
+ $(shell mkdir -p $(CLANGOUTDIR) ; \
+ echo $(CLANGSRC) | sort > $(CLANGOUTDIR)/sources-new.txt; \
+ if diff $(CLANGOUTDIR)/sources.txt $(CLANGOUTDIR)/sources-new.txt >/dev/null 2>/dev/null; then \
+ echo 0; \
+ else \
+ mv $(CLANGOUTDIR)/sources-new.txt $(CLANGOUTDIR)/sources.txt; \
+ echo 1; \
+ fi; \
+ )
+ifeq ($(CLANGSRCCHANGED),1)
+.PHONY: CLANGFORCE
+CLANGFORCE:
+$(CLANGOUTDIR)/plugin$(CLANG_DL_EXT): CLANGFORCE
+endif
+# Make the .so also explicitly depend on the sources list, to force update in case CLANGSRCCHANGED was e.g. during 'make clean'.
+$(CLANGOUTDIR)/plugin$(CLANG_DL_EXT): $(CLANGOUTDIR)/sources.txt
+$(CLANGOUTDIR)/sources.txt:
+ touch $@
+
+compilerplugins-build: $(CLANGOUTDIR) $(CLANGOBJDIR) $(CLANGOUTDIR)/plugin$(CLANG_DL_EXT)
+
+compilerplugins-clean:
+ rm -rf \
+ $(CLANGOBJDIR) \
+ $(CLANGOUTDIR)/clang-timestamp \
+ $(CLANGOUTDIR)/plugin$(CLANG_DL_EXT) \
+ $(CLANGOUTDIR)/clang.pch{,.d} \
+ $(CLANGOUTDIR)/sharedvisitor/*.plugininfo \
+ $(CLANGOUTDIR)/sharedvisitor/clang.pch{,.d} \
+ $(CLANGOUTDIR)/sharedvisitor/sharedvisitor.{cxx,d,o} \
+ $(CLANGOUTDIR)/sharedvisitor/{analyzer,generator}{$(CLANG_EXE_EXT),.d,.o} \
+ $(CLANGOUTDIR)/sources-new.txt \
+ $(CLANGOUTDIR)/sources-shared-new.txt \
+ $(CLANGOUTDIR)/sources-shared.txt \
+ $(CLANGOUTDIR)/sources.txt
+
+$(CLANGOUTDIR):
+ mkdir -p $(CLANGOUTDIR)
+
+$(CLANGOBJDIR):
+ mkdir -p $(CLANGOBJDIR)
+
+CLANGOBJS=
+
+ifeq ($(OS),WNT)
+
+# clangbuildsrc cxxfile objfile dfile
+define clangbuildsrc
+$(2): $(1) $(SRCDIR)/compilerplugins/Makefile-clang.mk $(CLANGOUTDIR)/clang-timestamp
+ $$(call gb_Output_announce,$(subst $(SRCDIR)/,,$(subst $(BUILDDIR)/,,$(1))),$(true),CXX,3)
+ $(QUIET)$(COMPILER_PLUGINS_CXX) $(CLANGDEFS) $(CLANGCXXFLAGS) $(CLANGWERROR) \
+ $(CLANGINCLUDES) /I$(BUILDDIR)/config_host /I$(CLANGINDIR) $(1) /MD \
+ /c /Fo: $(2)
+
+-include $(3) #TODO
+
+$(CLANGOUTDIR)/plugin$(CLANG_DL_EXT): $(2)
+$(CLANGOUTDIR)/plugin$(CLANG_DL_EXT): CLANGOBJS += $(2)
+endef
+
+else
+
+# clangbuildsrc cxxfile ofile dfile
+define clangbuildsrc
+$(2): $(1) $(SRCDIR)/compilerplugins/Makefile-clang.mk $(CLANGOUTDIR)/clang-timestamp \
+ $(if $(LO_CLANG_USE_PCH),$(CLANGOUTDIR)/clang.pch)
+ $$(call gb_Output_announce,$(subst $(SRCDIR)/,,$(subst $(BUILDDIR)/,,$(1))),$(true),CXX,3)
+ $(QUIET)$(COMPILER_PLUGINS_CXX) $(CLANGDEFS) $(CLANGCXXFLAGS) $(CLANGWERROR) \
+ $(CLANGINCLUDES) -I$(BUILDDIR)/config_host -I$(CLANGINDIR) $(1) \
+ $(if $(LO_CLANG_USE_PCH),-include-pch $(CLANGOUTDIR)/clang.pch -DPCH_LEVEL=$(gb_ENABLE_PCH)) \
+ -fPIC -c -o $(2) -MMD -MT $(2) -MP -MF $(3)
+
+-include $(3)
+
+$(CLANGOUTDIR)/plugin$(CLANG_DL_EXT): $(2)
+$(CLANGOUTDIR)/plugin$(CLANG_DL_EXT): CLANGOBJS += $(2)
+endef
+
+endif
+
+$(foreach src, $(CLANGSRCOUTDIR), $(eval $(call clangbuildsrc,$(src),$(src:.cxx=.o),$(src:.cxx=.d))))
+$(foreach src, $(CLANGSRCINDIR), $(eval $(call clangbuildsrc,$(CLANGINDIR)/$(src),$(CLANGOBJDIR)/$(src:.cxx=.o),$(CLANGOBJDIR)/$(src:.cxx=.d))))
+
+$(CLANGOUTDIR)/plugin$(CLANG_DL_EXT): $(CLANGOBJS)
+ $(call gb_Output_announce,$(subst $(BUILDDIR)/,,$@),$(true),LNK,4)
+ifeq ($(OS),WNT)
+ $(QUIET)$(COMPILER_PLUGINS_CXX) /LD $(CLANGOBJS) /Fe: $@ $(CLANGLIBDIR)/clang.lib \
+ mincore.lib version.lib /link $(COMPILER_PLUGINS_CXX_LINKFLAGS)
+else
+ $(QUIET)$(COMPILER_PLUGINS_CXX) -shared $(CLANGOBJS) -o $@ \
+ $(if $(filter MACOSX,$(OS)),-Wl$(CLANG_COMMA)-flat_namespace \
+ -Wl$(CLANG_COMMA)-undefined -Wl$(CLANG_COMMA)suppress)
+endif
+
+# Clang most probably doesn't maintain binary compatibility, so rebuild when clang changes
+# (either the binary can change if it's a local build, or config_clang.h will change if configure detects
+# a new version of a newly installed system clang).
+$(CLANGOUTDIR)/clang-timestamp: $(CLANGDIR)/bin/clang$(CLANG_EXE_EXT) $(BUILDDIR)/config_host/config_clang.h
+ $(QUIET)touch $@
+
+
+ifdef LO_CLANG_SHARED_PLUGINS
+SHARED_SOURCES := $(sort $(shell grep -l "LO_CLANG_SHARED_PLUGINS" $(CLANGINDIR)/*.cxx))
+SHARED_SOURCE_INFOS := $(foreach source,$(SHARED_SOURCES),$(patsubst $(CLANGINDIR)/%.cxx,$(CLANGOUTDIR)/sharedvisitor/%.plugininfo,$(source)))
+
+$(CLANGOUTDIR)/sharedvisitor/%.plugininfo: $(CLANGINDIR)/%.cxx \
+ $(CLANGOUTDIR)/sharedvisitor/analyzer$(CLANG_EXE_EXT) \
+ $(CLANGOUTDIR)/sharedvisitor/clang.pch
+ $(call gb_Output_announce,$(subst $(BUILDDIR)/,,$@),$(true),GEN,1)
+ $(QUIET)$(ICECREAM_RUN) $(CLANGOUTDIR)/sharedvisitor/analyzer$(CLANG_EXE_EXT) \
+ $(COMPILER_PLUGINS_TOOLING_ARGS:%=-arg=%) $< > $@
+
+$(CLANGOUTDIR)/sharedvisitor/sharedvisitor.cxx: $(SHARED_SOURCE_INFOS) $(CLANGOUTDIR)/sharedvisitor/generator$(CLANG_EXE_EXT)
+ $(call gb_Output_announce,$(subst $(BUILDDIR)/,,$@),$(true),GEN,1)
+ $(QUIET)$(ICECREAM_RUN) $(CLANGOUTDIR)/sharedvisitor/generator$(CLANG_EXE_EXT) \
+ $(SHARED_SOURCE_INFOS) > $@
+
+# Flags used internally in analyzer.
+# Older versions of Clang have a problem to find their own internal headers, so add it.
+# Also filter out the c++ library, it's not necessary to be specific about it in this case
+# and it can also cause trouble with finding the proper headers.
+CLANGTOOLDEFS = $(filter-out -stdlib=%,$(CLANGDEFS) -I$(CLANGSYSINCLUDE))
+CLANGTOOLDEFS += -w
+ifneq ($(filter MACOSX,$(OS)),)
+CLANGTOOLLIBS += -Wl,-rpath,$(CLANGLIBDIR)
+else ifneq ($(filter-out WNT,$(OS)),)
+ifneq ($(CLANGDIR),/usr)
+# Help the generator find Clang shared libs, if Clang is built so and installed in a non-standard prefix.
+CLANGTOOLLIBS += -Wl,--rpath,$(CLANGLIBDIR)
+endif
+endif
+
+$(CLANGOUTDIR)/sharedvisitor/analyzer$(CLANG_EXE_EXT): $(CLANGINDIR)/sharedvisitor/analyzer.cxx \
+ | $(CLANGOUTDIR)/sharedvisitor
+ $(call gb_Output_announce,$(subst $(BUILDDIR)/,,$@),$(true),GEN,1)
+ $(QUIET)$(COMPILER_PLUGINS_CXX) $(CLANGDEFS) $(CLANGCXXFLAGS) $(CLANGWERROR) $(CLANGINCLUDES) \
+ -I$(BUILDDIR)/config_host -DCLANGFLAGS='"$(CLANGTOOLDEFS)"' \
+ -DLO_CLANG_USE_ANALYZER_PCH=$(if $(COMPILER_PLUGINS_ANALYZER_PCH),1,0) \
+ -c $< -o $(CLANGOUTDIR)/sharedvisitor/analyzer.o -MMD -MT $@ -MP \
+ -MF $(CLANGOUTDIR)/sharedvisitor/analyzer.d
+ $(QUIET)$(COMPILER_PLUGINS_CXX) $(CLANGDEFS) $(CLANGCXXFLAGS) $(CLANGOUTDIR)/sharedvisitor/analyzer.o \
+ -o $@ $(CLANGTOOLLIBS)
+
+$(CLANGOUTDIR)/sharedvisitor/generator$(CLANG_EXE_EXT): $(CLANGINDIR)/sharedvisitor/generator.cxx \
+ | $(CLANGOUTDIR)/sharedvisitor
+ $(call gb_Output_announce,$(subst $(BUILDDIR)/,,$@),$(true),GEN,1)
+ $(QUIET)$(COMPILER_PLUGINS_CXX) $(CLANGDEFS) $(CLANGCXXFLAGS) $(CLANGWERROR) \
+ -c $< -o $(CLANGOUTDIR)/sharedvisitor/generator.o -MMD -MT $@ -MP \
+ -MF $(CLANGOUTDIR)/sharedvisitor/generator.d
+ $(QUIET)$(COMPILER_PLUGINS_CXX) $(CLANGDEFS) $(CLANGCXXFLAGS) $(CLANGOUTDIR)/sharedvisitor/generator.o \
+ -o $@
+
+$(CLANGOUTDIR)/sharedvisitor/analyzer$(CLANG_EXE_EXT): $(SRCDIR)/compilerplugins/Makefile-clang.mk $(CLANGOUTDIR)/clang-timestamp
+
+$(CLANGOUTDIR)/sharedvisitor/generator$(CLANG_EXE_EXT): $(SRCDIR)/compilerplugins/Makefile-clang.mk
+
+$(CLANGOUTDIR)/sharedvisitor:
+ mkdir -p $(CLANGOUTDIR)/sharedvisitor
+
+-include $(CLANGOUTDIR)/sharedvisitor/analyzer.d
+-include $(CLANGOUTDIR)/sharedvisitor/generator.d
+# TODO WNT version
+
+# Remember the sources that are shared and if they have changed, force sharedvisitor.cxx generating.
+# Duplicated from CLANGSRCCHANGED above.
+CLANGSRCSHAREDCHANGED= \
+ $(shell mkdir -p $(CLANGOUTDIR) ; \
+ echo $(SHARED_SOURCES) | sort > $(CLANGOUTDIR)/sources-shared-new.txt; \
+ if diff $(CLANGOUTDIR)/sources-shared.txt $(CLANGOUTDIR)/sources-shared-new.txt >/dev/null 2>/dev/null; then \
+ echo 0; \
+ else \
+ mv $(CLANGOUTDIR)/sources-shared-new.txt $(CLANGOUTDIR)/sources-shared.txt; \
+ echo 1; \
+ fi; \
+ )
+ifeq ($(CLANGSRCSHAREDCHANGED),1)
+.PHONY: CLANGFORCE
+CLANGFORCE:
+$(CLANGOUTDIR)/sharedvisitor/sharedvisitor.cxx: CLANGFORCE
+endif
+# Make sharedvisitor.cxx also explicitly depend on the sources list, to force update in case CLANGSRCSHAREDCHANGED was e.g. during 'make clean'.
+$(CLANGOUTDIR)/sharedvisitor/sharedvisitor.cxx: $(CLANGOUTDIR)/sources-shared.txt
+$(CLANGOUTDIR)/sources-shared.txt:
+ touch $@
+endif
+
+ifneq ($(LO_CLANG_USE_PCH),)
+# the PCH for plugin sources themselves
+
+ifeq ($(OS),WNT)
+# TODO
+else
+$(CLANGOUTDIR)/clang.pch: $(CLANGINDIR)/precompiled_clang.hxx \
+ $(SRCDIR)/compilerplugins/Makefile-clang.mk $(CLANGOUTDIR)/clang-timestamp
+ $(call gb_Output_announce,$(subst $(BUILDDIR)/,,$@),$(true),PCH,1)
+ $(QUIET)$(COMPILER_PLUGINS_CXX) -x c++-header $(CLANGDEFS) $(CLANGCXXFLAGS) $(CLANGWERROR) \
+ $(CLANGINCLUDES) -I$(BUILDDIR)/config_host -I$(CLANGINDIR) -DPCH_LEVEL=$(gb_ENABLE_PCH) \
+ $(LO_CLANG_PCH_FLAGS) \
+ -fPIC -c $< -o $@ -MMD -MT $@ -MP -MF $(CLANGOUTDIR)/clang.pch.d
+endif
+-include $(CLANGOUTDIR)/clang.pch.d
+
+endif
+
+ifeq ($(COMPILER_PLUGINS_ANALYZER_PCH),TRUE)
+# the PCH for usage in sharedvisitor/analyzer
+
+# these are from the invocation in analyzer.cxx
+LO_CLANG_ANALYZER_PCH_CXXFLAGS := -I$(BUILDDIR)/config_host $(CLANGTOOLDEFS)
+
+$(CLANGOUTDIR)/sharedvisitor/clang.pch: $(CLANGINDIR)/sharedvisitor/precompiled_clang.hxx \
+ $(SRCDIR)/compilerplugins/Makefile-clang.mk $(CLANGOUTDIR)/clang-timestamp \
+ | $(CLANGOUTDIR)/sharedvisitor
+ $(call gb_Output_announce,$(subst $(BUILDDIR)/,,$@),$(true),PCH,1)
+ $(QUIET)$(CLANGDIR)/bin/clang -x c++-header $(LO_CLANG_ANALYZER_PCH_CXXFLAGS) \
+ $(LO_CLANG_PCH_FLAGS) $(COMPILER_PLUGINS_TOOLING_ARGS) -c $< -o $@ -MMD -MT $@ -MP \
+ -MF $(CLANGOUTDIR)/sharedvisitor/clang.pch.d
+
+-include $(CLANGOUTDIR)/sharedvisitor/clang.pch.d
+
+else
+$(CLANGOUTDIR)/sharedvisitor/clang.pch:
+ touch $@
+endif
+
+# vim: set noet sw=4 ts=4: