1# 2# This file is part of the LibreOffice project. 3# 4# This Source Code Form is subject to the terms of the Mozilla Public 5# License, v. 2.0. If a copy of the MPL was not distributed with this 6# file, You can obtain one at http://mozilla.org/MPL/2.0/. 7# 8 9# Make sure variables in this Makefile do not conflict with other variables (e.g. from gbuild). 10 11# Set to 1 if you need to debug the plugin). 12CLANGDEBUG= 13 14# Compile flags, you may occasionally want to override these: 15ifeq ($(OS),WNT) 16# See LLVM's cmake/modules/AddLLVM.cmake and LLVM build's 17# tools/llvm-config/BuildVariables.inc: 18# * Ignore "warning C4141: 'inline': used more than once" as emitted upon 19# "LLVM_ATTRIBUTE_ALWAYS_INLINE inline" in various LLVM include files. 20# * Ignore "warning C4577: 'noexcept' used with no exception handling mode 21# specified; termination on exception is not guaranteed. Specify /EHsc". 22CLANGCXXFLAGS=/nologo /D_HAS_EXCEPTIONS=0 /wd4141 /wd4577 /EHs-c- /GR- 23ifeq ($(CLANGDEBUG),) 24CLANGCXXFLAGS+=/O2 /Oi 25else 26CLANGCXXFLAGS+=/DEBUG 27endif 28else # WNT 29CLANGCXXFLAGS=-Wall -Wextra -Wundef 30ifeq ($(CLANGDEBUG),) 31CLANGCXXFLAGS+=-O2 32else 33CLANGCXXFLAGS+=-g 34endif 35endif 36 37# Whether to make plugins use one shared ASTRecursiveVisitor (plugins run faster). 38# By default enabled, disable if you work on an affected plugin (re-generating takes time). 39LO_CLANG_SHARED_PLUGINS=1 40#TODO: 41ifeq ($(OS),WNT) 42LO_CLANG_SHARED_PLUGINS= 43endif 44 45# Whether to use precompiled headers for the analyzer too. Does not apply to compiling sources. 46LO_CLANG_USE_ANALYZER_PCH=1 47 48# The uninteresting rest. 49 50include $(SRCDIR)/solenv/gbuild/gbuild.mk 51include $(SRCDIR)/solenv/gbuild/Output.mk 52 53CLANG_COMMA :=, 54 55ifeq ($(OS),WNT) 56CLANG_DL_EXT = .dll 57CLANG_EXE_EXT = .exe 58else 59CLANG_DL_EXT = .so 60CLANG_EXE_EXT = 61endif 62 63# Clang headers require these. 64CLANGDEFS=-D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS 65ifneq ($(OS),WNT) 66CLANGDEFS += -fno-rtti 67endif 68# All include locations needed (using -isystem silences various warnings when 69# including those files): 70ifeq ($(OS),WNT) 71CLANGINCLUDES=-I$(CLANGDIR)/include 72else 73CLANGINCLUDES=$(if $(filter /usr,$(CLANGDIR)),,-isystem $(CLANGDIR)/include) 74endif 75 76LLVMCONFIG=$(CLANGDIR)/bin/llvm-config 77 78# Clang/LLVM libraries are intentionally not linked in, they are usually built as static libraries, which means the resulting 79# plugin would be big (even though the clang binary already includes it all) and it'd be necessary to explicitly specify 80# also all the dependency libraries. 81 82CLANGINDIR=$(SRCDIR)/compilerplugins/clang 83# Cannot use $(WORKDIR), the plugin should survive even 'make clean', otherwise the rebuilt 84# plugin will cause cache misses with ccache. 85CLANGOUTDIR=$(BUILDDIR)/compilerplugins/clang 86CLANGOBJDIR=$(CLANGOUTDIR)/obj 87 88ifdef LO_CLANG_SHARED_PLUGINS 89CLANGCXXFLAGS+=-DLO_CLANG_SHARED_PLUGINS 90endif 91 92ifneq ($(CLANGDEBUG),) 93ifeq ($(HAVE_GCC_SPLIT_DWARF),TRUE) 94CLANGCXXFLAGS+=-gsplit-dwarf 95endif 96endif 97 98QUIET=$(if $(verbose),,@) 99 100ifneq ($(ENABLE_WERROR),) 101ifeq ($(OS),WNT) 102CLANGWERROR := 103#TODO: /WX 104else 105CLANGWERROR := -Werror 106endif 107endif 108 109compilerplugins: compilerplugins-build 110 111ifdef LO_CLANG_SHARED_PLUGINS 112# The shared source, intentionally put first in the list because it takes the longest to build. 113CLANGSRCOUTDIR=$(CLANGOUTDIR)/sharedvisitor/sharedvisitor.cxx 114CLANGSRC+=$(CLANGSRCOUTDIR) 115endif 116# The list of source files, generated automatically (all files in clang/, but not subdirs). 117CLANGSRCINDIR=$(foreach src,$(wildcard $(CLANGINDIR)/*.cxx), $(notdir $(src))) 118CLANGSRC+=$(CLANGSRCINDIR) 119 120# Remember the sources and if they have changed, force plugin relinking. 121CLANGSRCCHANGED= \ 122 $(shell mkdir -p $(CLANGOUTDIR) ; \ 123 echo $(CLANGSRC) | sort > $(CLANGOUTDIR)/sources-new.txt; \ 124 if diff $(CLANGOUTDIR)/sources.txt $(CLANGOUTDIR)/sources-new.txt >/dev/null 2>/dev/null; then \ 125 echo 0; \ 126 else \ 127 mv $(CLANGOUTDIR)/sources-new.txt $(CLANGOUTDIR)/sources.txt; \ 128 echo 1; \ 129 fi; \ 130 ) 131ifeq ($(CLANGSRCCHANGED),1) 132.PHONY: CLANGFORCE 133CLANGFORCE: 134$(CLANGOUTDIR)/plugin$(CLANG_DL_EXT): CLANGFORCE 135endif 136# Make the .so also explicitly depend on the sources list, to force update in case CLANGSRCCHANGED was e.g. during 'make clean'. 137$(CLANGOUTDIR)/plugin$(CLANG_DL_EXT): $(CLANGOUTDIR)/sources.txt 138$(CLANGOUTDIR)/sources.txt: 139 touch $@ 140 141compilerplugins-build: $(CLANGOUTDIR) $(CLANGOBJDIR) $(CLANGOUTDIR)/plugin$(CLANG_DL_EXT) 142 143compilerplugins-clean: 144 rm -rf \ 145 $(CLANGOBJDIR) \ 146 $(CLANGOUTDIR)/clang-timestamp \ 147 $(CLANGOUTDIR)/plugin$(CLANG_DL_EXT) \ 148 $(CLANGOUTDIR)/sharedvisitor/*.plugininfo \ 149 $(CLANGOUTDIR)/sharedvisitor/clang.pch \ 150 $(CLANGOUTDIR)/sharedvisitor/sharedvisitor.{cxx,d,o} \ 151 $(CLANGOUTDIR)/sharedvisitor/{analyzer,generator}{$(CLANG_EXE_EXT),.d,.o} \ 152 $(CLANGOUTDIR)/sources-new.txt \ 153 $(CLANGOUTDIR)/sources.txt 154 155$(CLANGOUTDIR): 156 mkdir -p $(CLANGOUTDIR) 157 158$(CLANGOBJDIR): 159 mkdir -p $(CLANGOBJDIR) 160 161CLANGOBJS= 162 163ifeq ($(OS),WNT) 164 165# clangbuildsrc cxxfile objfile dfile 166define clangbuildsrc 167$(2): $(1) $(SRCDIR)/compilerplugins/Makefile-clang.mk $(CLANGOUTDIR)/clang-timestamp 168 $$(call gb_Output_announce,$(subst $(SRCDIR)/,,$(subst $(BUILDDIR)/,,$(1))),$(true),CXX,3) 169 $(QUIET)$(COMPILER_PLUGINS_CXX) $(CLANGCXXFLAGS) $(CLANGWERROR) $(CLANGDEFS) \ 170 $(CLANGINCLUDES) /I$(BUILDDIR)/config_host /I$(CLANGINDIR) $(1) /MD \ 171 /c /Fo: $(2) 172 173-include $(3) #TODO 174 175$(CLANGOUTDIR)/plugin$(CLANG_DL_EXT): $(2) 176$(CLANGOUTDIR)/plugin$(CLANG_DL_EXT): CLANGOBJS += $(2) 177endef 178 179else 180 181# clangbuildsrc cxxfile ofile dfile 182define clangbuildsrc 183$(2): $(1) $(SRCDIR)/compilerplugins/Makefile-clang.mk $(CLANGOUTDIR)/clang-timestamp 184 $$(call gb_Output_announce,$(subst $(SRCDIR)/,,$(subst $(BUILDDIR)/,,$(1))),$(true),CXX,3) 185 $(QUIET)$(COMPILER_PLUGINS_CXX) $(CLANGCXXFLAGS) $(CLANGWERROR) $(CLANGDEFS) \ 186 $(CLANGINCLUDES) -I$(BUILDDIR)/config_host -I$(CLANGINDIR) $(1) \ 187 -fPIC -c -o $(2) -MMD -MT $(2) -MP -MF $(3) 188 189-include $(3) 190 191$(CLANGOUTDIR)/plugin$(CLANG_DL_EXT): $(2) 192$(CLANGOUTDIR)/plugin$(CLANG_DL_EXT): CLANGOBJS += $(2) 193endef 194 195endif 196 197$(foreach src, $(CLANGSRCOUTDIR), $(eval $(call clangbuildsrc,$(src),$(src:.cxx=.o),$(src:.cxx=.d)))) 198$(foreach src, $(CLANGSRCINDIR), $(eval $(call clangbuildsrc,$(CLANGINDIR)/$(src),$(CLANGOBJDIR)/$(src:.cxx=.o),$(CLANGOBJDIR)/$(src:.cxx=.d)))) 199 200$(CLANGOUTDIR)/plugin$(CLANG_DL_EXT): $(CLANGOBJS) 201 $(call gb_Output_announce,$(subst $(BUILDDIR)/,,$@),$(true),LNK,4) 202ifeq ($(OS),WNT) 203 $(QUIET)$(COMPILER_PLUGINS_CXX) /LD $(CLANGOBJS) /Fe: $@ $(CLANGLIBDIR)/clang.lib \ 204 mincore.lib version.lib /link $(COMPILER_PLUGINS_CXX_LINKFLAGS) 205else 206 $(QUIET)$(COMPILER_PLUGINS_CXX) -shared $(CLANGOBJS) -o $@ \ 207 $(if $(filter MACOSX,$(OS)),-Wl$(CLANG_COMMA)-flat_namespace \ 208 -Wl$(CLANG_COMMA)-undefined -Wl$(CLANG_COMMA)suppress) 209endif 210 211# Clang most probably doesn't maintain binary compatibility, so rebuild when clang changes 212# (either the binary can change if it's a local build, or config_clang.h will change if configure detects 213# a new version of a newly installed system clang). 214$(CLANGOUTDIR)/clang-timestamp: $(CLANGDIR)/bin/clang$(CLANG_EXE_EXT) $(BUILDDIR)/config_host/config_clang.h 215 $(QUIET)touch $@ 216 217 218ifdef LO_CLANG_SHARED_PLUGINS 219SHARED_SOURCES := $(shell grep -l "LO_CLANG_SHARED_PLUGINS" $(CLANGINDIR)/*.cxx) 220SHARED_SOURCE_INFOS := $(foreach source,$(SHARED_SOURCES),$(patsubst $(CLANGINDIR)/%.cxx,$(CLANGOUTDIR)/sharedvisitor/%.plugininfo,$(source))) 221 222$(CLANGOUTDIR)/sharedvisitor/%.plugininfo: $(CLANGINDIR)/%.cxx \ 223 $(CLANGOUTDIR)/sharedvisitor/analyzer$(CLANG_EXE_EXT) \ 224 $(CLANGOUTDIR)/sharedvisitor/clang.pch 225 $(call gb_Output_announce,$(subst $(BUILDDIR)/,,$@),$(true),GEN,1) 226 $(QUIET)$(ICECREAM_RUN) $(CLANGOUTDIR)/sharedvisitor/analyzer$(CLANG_EXE_EXT) \ 227 $(COMPILER_PLUGINS_TOOLING_ARGS:%=-arg=%) $< > $@ 228 229$(CLANGOUTDIR)/sharedvisitor/sharedvisitor.cxx: $(SHARED_SOURCE_INFOS) $(CLANGOUTDIR)/sharedvisitor/generator$(CLANG_EXE_EXT) 230 $(call gb_Output_announce,$(subst $(BUILDDIR)/,,$@),$(true),GEN,1) 231 $(QUIET)$(ICECREAM_RUN) $(CLANGOUTDIR)/sharedvisitor/generator$(CLANG_EXE_EXT) \ 232 $(SHARED_SOURCE_INFOS) > $@ 233 234CLANGTOOLLIBS = -lclangTooling -lclangDriver -lclangFrontend -lclangParse -lclangSema -lclangEdit -lclangAnalysis \ 235 -lclangAST -lclangLex -lclangSerialization -lclangBasic $(shell $(LLVMCONFIG) --ldflags --libs --system-libs) 236# Path to the clang system headers (no idea if there's a better way to get it). 237CLANGTOOLDEFS = -DCLANGSYSINCLUDE=$(shell $(LLVMCONFIG) --libdir)/clang/$(shell $(LLVMCONFIG) --version | sed 's/svn//')/include 238# -std=c++11 is in line with the default value for COMPILER_PLUGINS_CXX in configure.ac: 239CLANGSTDOPTION := $(or $(filter -std=%,$(COMPILER_PLUGINS_CXX)),-std=c++11) 240CLANGTOOLDEFS += -DSTDOPTION=\"$(CLANGSTDOPTION)\" 241ifneq ($(filter-out MACOSX WNT,$(OS)),) 242ifneq ($(CLANGDIR),/usr) 243# Help the generator find Clang shared libs, if Clang is built so and installed in a non-standard prefix. 244CLANGTOOLLIBS += -Wl,--rpath,$(shell $(LLVMCONFIG) --libdir) 245endif 246endif 247 248$(CLANGOUTDIR)/sharedvisitor/analyzer$(CLANG_EXE_EXT): $(CLANGINDIR)/sharedvisitor/analyzer.cxx \ 249 | $(CLANGOUTDIR)/sharedvisitor 250 $(call gb_Output_announce,$(subst $(BUILDDIR)/,,$@),$(true),GEN,1) 251 $(QUIET)$(COMPILER_PLUGINS_CXX) $(CLANGCXXFLAGS) $(CLANGWERROR) $(CLANGDEFS) $(CLANGTOOLDEFS) $(CLANGINCLUDES) \ 252 -DCLANGDIR=$(CLANGDIR) -I$(BUILDDIR)/config_host \ 253 -DLO_CLANG_USE_ANALYZER_PCH=$(LO_CLANG_USE_ANALYZER_PCH) \ 254 -c $< -o $(CLANGOUTDIR)/sharedvisitor/analyzer.o -MMD -MT $@ -MP \ 255 -MF $(CLANGOUTDIR)/sharedvisitor/analyzer.d 256 $(QUIET)$(COMPILER_PLUGINS_CXX) $(CLANGCXXFLAGS) $(CLANGOUTDIR)/sharedvisitor/analyzer.o \ 257 -o $@ $(CLANGTOOLLIBS) 258 259$(CLANGOUTDIR)/sharedvisitor/generator$(CLANG_EXE_EXT): $(CLANGINDIR)/sharedvisitor/generator.cxx \ 260 | $(CLANGOUTDIR)/sharedvisitor 261 $(call gb_Output_announce,$(subst $(BUILDDIR)/,,$@),$(true),GEN,1) 262 $(QUIET)$(COMPILER_PLUGINS_CXX) $(CLANGCXXFLAGS) $(CLANGWERROR) \ 263 -c $< -o $(CLANGOUTDIR)/sharedvisitor/generator.o -MMD -MT $@ -MP \ 264 -MF $(CLANGOUTDIR)/sharedvisitor/generator.d 265 $(QUIET)$(COMPILER_PLUGINS_CXX) $(CLANGCXXFLAGS) $(CLANGOUTDIR)/sharedvisitor/generator.o \ 266 -o $@ 267 268$(CLANGOUTDIR)/sharedvisitor/analyzer$(CLANG_EXE_EXT): $(SRCDIR)/compilerplugins/Makefile-clang.mk $(CLANGOUTDIR)/clang-timestamp 269 270$(CLANGOUTDIR)/sharedvisitor/generator$(CLANG_EXE_EXT): $(SRCDIR)/compilerplugins/Makefile-clang.mk 271 272$(CLANGOUTDIR)/sharedvisitor: 273 mkdir -p $(CLANGOUTDIR)/sharedvisitor 274 275-include $(CLANGOUTDIR)/sharedvisitor/analyzer.d 276-include $(CLANGOUTDIR)/sharedvisitor/generator.d 277# TODO WNT version 278 279# Remember the sources that are shared and if they have changed, force sharedvisitor.cxx generating. 280# Duplicated from CLANGSRCCHANGED above. 281CLANGSRCSHAREDCHANGED= \ 282 $(shell mkdir -p $(CLANGOUTDIR) ; \ 283 echo $(SHARED_SOURCES) | sort > $(CLANGOUTDIR)/sources-shared-new.txt; \ 284 if diff $(CLANGOUTDIR)/sources-shared.txt $(CLANGOUTDIR)/sources-shared-new.txt >/dev/null 2>/dev/null; then \ 285 echo 0; \ 286 else \ 287 mv $(CLANGOUTDIR)/sources-shared-new.txt $(CLANGOUTDIR)/sources-shared.txt; \ 288 echo 1; \ 289 fi; \ 290 ) 291ifeq ($(CLANGSRCSHAREDCHANGED),1) 292.PHONY: CLANGFORCE 293CLANGFORCE: 294$(CLANGOUTDIR)/sharedvisitor/sharedvisitor.cxx: CLANGFORCE 295endif 296# Make sharedvisitor.cxx also explicitly depend on the sources list, to force update in case CLANGSRCSHAREDCHANGED was e.g. during 'make clean'. 297$(CLANGOUTDIR)/sharedvisitor/sharedvisitor.cxx: $(CLANGOUTDIR)/sources-shared.txt 298$(CLANGOUTDIR)/sources-shared.txt: 299 touch $@ 300endif 301 302ifdef LO_CLANG_USE_ANALYZER_PCH 303 304# these are from the invocation in analyzer.cxx 305LO_CLANG_ANALYZER_PCH_CXXFLAGS := -I$(BUILDDIR)/config_host -I$(CLANGDIR)/include $(CLANGTOOLDEFS) $(CLANGSTDOPTION) \ 306 -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS 307 308$(CLANGOUTDIR)/sharedvisitor/clang.pch: $(CLANGINDIR)/sharedvisitor/precompiled_clang.hxx \ 309 $(CLANGOUTDIR)/clang-timestamp \ 310 | $(CLANGOUTDIR)/sharedvisitor 311 $(call gb_Output_announce,$(subst $(BUILDDIR)/,,$@),$(true),PCH,1) 312 $(QUIET)$(CLANGDIR)/bin/clang -x c++-header $(LO_CLANG_ANALYZER_PCH_CXXFLAGS) \ 313 $(COMPILER_PLUGINS_TOOLING_ARGS) $< -o $@ 314else 315$(CLANGOUTDIR)/sharedvisitor/clang.pch: 316 touch $@ 317endif 318 319# vim: set noet sw=4 ts=4: 320
