xref: /core/compilerplugins/Makefile-clang.mk (revision db123aba)
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