| # |
| # 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: |