1###############################################################################
2#
3# Makefile for libxlsxwriter library.
4#
5# Copyright 2014-2021, John McNamara, jmcnamara@cpan.org
6#
7
8# Keep the output quiet by default.
9Q=@
10ifdef V
11Q=
12endif
13
14DESTDIR ?=
15PREFIX  ?= /usr/local
16
17PYTEST ?= py.test
18PYTESTFILES ?= test
19
20VERSION   = $(shell sed -n -e 's/.*LXW_VERSION \"\(.*\)\"/\1/p'   include/xlsxwriter.h)
21
22.PHONY: docs tags examples third_party
23
24# Build libxlsxwriter.
25all : third_party
26	$(Q)$(MAKE) -C src
27
28# Build the third party libs.
29third_party :
30ifndef USE_SYSTEM_MINIZIP
31	$(Q)$(MAKE) -C third_party/minizip
32endif
33ifndef USE_STANDARD_TMPFILE
34	$(Q)$(MAKE) -C third_party/tmpfileplus
35endif
36ifndef USE_NO_MD5
37ifndef USE_OPENSSL_MD5
38	$(Q)$(MAKE) -C third_party/md5
39endif
40endif
41ifdef USE_DTOA_LIBRARY
42	$(Q)$(MAKE) -C third_party/dtoa
43endif
44
45# Build a macOS universal binary.
46universal_binary :
47	$(Q)$(MAKE) clean
48	$(Q)TARGET_ARCH="-target x86_64-apple-macos10.12" $(MAKE) all
49	$(Q)mv lib/libxlsxwriter.a     libxlsxwriter_x86_64.a
50	$(Q)mv lib/libxlsxwriter.dylib libxlsxwriter_x86_64.dylib
51
52	$(Q)$(MAKE) clean
53	$(Q)TARGET_ARCH="-target arm64-apple-macos11" $(MAKE) all
54	$(Q)mv lib/libxlsxwriter.a     lib/libxlsxwriter_arm64.a
55	$(Q)mv lib/libxlsxwriter.dylib lib/libxlsxwriter_arm64.dylib
56	$(Q)mv libxlsxwriter_x86_64.a libxlsxwriter_x86_64.dylib lib
57
58	$(Q)lipo -create -output lib/libxlsxwriter.a     lib/libxlsxwriter_x86_64.a     lib/libxlsxwriter_arm64.a
59	$(Q)lipo -create -output lib/libxlsxwriter.dylib lib/libxlsxwriter_x86_64.dylib lib/libxlsxwriter_arm64.dylib
60
61# Build the example programs.
62examples : all
63	$(Q)$(MAKE) -C examples
64
65# Clean src and test directories.
66clean :
67	$(Q)$(MAKE) clean -C src
68	$(Q)$(MAKE) clean -C test/unit
69	$(Q)$(MAKE) clean -C test/functional/src
70	$(Q)$(MAKE) clean -C test/cpp
71	$(Q)$(MAKE) clean -C examples
72	$(Q)rm -rf docs/html
73	$(Q)rm -rf test/functional/__pycache__
74	$(Q)rm -f  test/functional/*.pyc
75	$(Q)rm -f  lib/*
76	$(Q)$(MAKE) clean -C third_party/minizip
77	$(Q)$(MAKE) clean -C third_party/tmpfileplus
78	$(Q)$(MAKE) clean -C third_party/md5
79	$(Q)$(MAKE) clean -C third_party/dtoa
80
81# Clean src and lib dir only, as a precursor for static analysis.
82clean_src :
83	$(Q)$(MAKE) clean -C src
84	$(Q)rm -f  lib/*
85
86# Run the unit tests.
87test : all test_cpp test_unit test_functional
88
89# Test for C++ const correctness on APIs.
90test_const : all
91	$(Q)$(MAKE) clean -C test/functional/src
92	$(Q)! $(MAKE) -C test/functional/src CFLAGS=-Wwrite-strings 2>&1 | grep -A 1 "note:"
93
94
95# Run the functional tests.
96test_functional : all
97	$(Q)$(MAKE) -C test/functional/src
98	$(Q)$(PYTEST) test/functional -v -k $(PYTESTFILES)
99
100# Run all tests.
101test_unit : all
102	$(Q)$(MAKE) -C src test_lib
103	$(Q)$(MAKE) -C test/unit test
104
105# Test C++ compilation.
106test_cpp : all
107	$(Q)$(MAKE) -C test/cpp
108
109# Test Cmake. This test should really be done with Cmake in the cmake dir but
110# this is a workaround for now.
111test_cmake :
112ifneq ($(findstring m32,$(CFLAGS)),m32)
113	$(Q)$(MAKE) -C src clean
114	$(Q)cd cmake; cmake .. -DBUILD_TESTS=ON -DBUILD_EXAMPLES=ON; make clean; make; cp libxlsxwriter.a ../src/
115	$(Q)cmake/xlsxwriter_unit
116	$(Q)$(MAKE) -C test/functional/src
117	$(Q)$(PYTEST) test/functional -v -k $(PYTESTFILES)
118else
119	@echo "Skipping Cmake tests on 32 bit target."
120endif
121
122# Test the functional test exes with valgrind (in 64bit mode only).
123test_valgrind : all
124ifndef NO_VALGRIND
125	$(Q)$(MAKE) -C test/functional/src test_valgrind
126	$(Q)$(MAKE) -C examples test_valgrind
127endif
128
129# Minimal target for quick compile without creating the libs.
130test_compile :
131	$(Q)$(MAKE) -C src	test_compile
132
133# Indent the source files with the .indent.pro settings.
134indent:
135	$(Q)gindent src/*.c include/*.h include/xlsxwriter/*.h
136
137tags:
138	$(Q)rm -f TAGS
139	$(Q)etags src/*.c include/*.h include/xlsxwriter/*.h
140
141# Build the doxygen docs.
142doc: docs
143docs:
144	$(Q)$(MAKE) -C docs
145	@echo "Docs built."
146
147docs_doxygen_only:
148	$(Q)$(MAKE) -C docs docs_doxygen_only
149
150docs_external:
151	$(Q)make -C ../libxlsxwriter.github.io release
152
153# Simple install.
154install: all
155	$(Q)mkdir -p        $(DESTDIR)$(PREFIX)/include
156	$(Q)cp -R include/* $(DESTDIR)$(PREFIX)/include
157	$(Q)mkdir -p        $(DESTDIR)$(PREFIX)/lib
158	$(Q)cp -R lib/*     $(DESTDIR)$(PREFIX)/lib
159	$(Q)mkdir -p        $(DESTDIR)$(PREFIX)/lib/pkgconfig
160	$(Q)sed -e          's|@PREFIX@|$(PREFIX)|g'  -e 's|@VERSION@|$(VERSION)|g' dev/release/pkg-config.txt > $(DESTDIR)$(PREFIX)/lib/pkgconfig/xlsxwriter.pc
161
162# Simpler uninstall.
163uninstall:
164	$(Q)rm -rf $(DESTDIR)$(PREFIX)/include/xlsxwriter*
165	$(Q)rm     $(DESTDIR)$(PREFIX)/lib/libxlsxwriter.*
166	$(Q)rm     $(DESTDIR)$(PREFIX)/lib/pkgconfig/xlsxwriter.pc
167
168# Strip the lib files.
169strip:
170	$(Q)strip lib/*
171
172# Run a coverity static analysis.
173coverity: clean_src third_party
174	$(Q)rm -rf  cov-int
175	$(Q)rm -f libxlsxwriter-coverity.tgz
176	$(Q)../../cov-analysis-linux64-2019.03/bin/cov-build --dir cov-int make -C src libxlsxwriter.a
177	$(Q)tar -czf libxlsxwriter-coverity.tgz cov-int
178	$(Q)$(MAKE) -C src clean
179	$(Q)rm -f  lib/*
180
181# Run gcov coverage analysis.
182gcov: third_party
183	$(Q)$(MAKE) -C src clean
184	$(Q)$(MAKE) -C src                 GCOV="--coverage" OPT_LEVEL="-O0"
185	$(Q)$(MAKE) -C src test_lib        GCOV="--coverage"
186	$(Q)$(MAKE) -C test/unit test      GCOV="--coverage"
187	$(Q)$(MAKE) -C test/functional/src GCOV="--coverage"
188	$(Q)$(PYTEST) test/functional -v -k $(PYTESTFILES)
189	$(Q)mkdir -p build
190	$(Q)gcovr -r src --html-details -o build/libxlsxwriter_gcov.html
191	$(Q)gcovr -r . -f src --sonarqube build/coverage.xml
192
193# Run sonarcloud analysis.
194sonarcloud: gcov
195ifndef SONAR_TOKEN
196	@echo "Please define SONAR_TOKEN to run this analysis."
197	@exit 1
198endif
199	$(Q)$(MAKE) clean
200	$(Q)../sonar-scanner-4.6.1.2450-macosx/bin/build-wrapper-macosx-x86 --out-dir build make all
201	$(Q)../sonar-scanner-4.6.1.2450-macosx/bin/sonar-scanner \
202        -Dsonar.organization=jmcnamara-github \
203        -Dsonar.projectKey=jmcnamara_libxlsxwriter \
204        -Dsonar.projectName=libxlsxwriter \
205        -Dsonar.projectVersion=$(VERSION) \
206        -Dsonar.sources=src \
207        -Dsonar.sourceEncoding=UTF-8 \
208        -Dsonar.cfamily.build-wrapper-output=build \
209        -Dsonar.working.directory=build/scannerwork \
210        -Dsonar.host.url=https://sonarcloud.io \
211        -Dsonar.cfamily.threads=4 \
212        -Dsonar.coverageReportPaths=build/coverage.xml \
213        -Dsonar.cfamily.cache.enabled=false
214
215sonarcloud_no_gcov:
216ifndef SONAR_TOKEN
217	@echo "Please define SONAR_TOKEN to run this analysis."
218	@exit 1
219endif
220	$(Q)$(MAKE) clean
221	$(Q)../sonar-scanner-4.6.1.2450-macosx/bin/build-wrapper-macosx-x86 --out-dir build make all
222	$(Q)../sonar-scanner-4.6.1.2450-macosx/bin/sonar-scanner \
223        -Dsonar.organization=jmcnamara-github \
224        -Dsonar.projectKey=jmcnamara_libxlsxwriter \
225        -Dsonar.projectName=libxlsxwriter \
226        -Dsonar.projectVersion=$(VERSION) \
227        -Dsonar.sources=src \
228        -Dsonar.sourceEncoding=UTF-8 \
229        -Dsonar.cfamily.build-wrapper-output=build \
230        -Dsonar.working.directory=build/scannerwork \
231        -Dsonar.host.url=https://sonarcloud.io \
232        -Dsonar.cfamily.threads=4 \
233        -Dsonar.cfamily.cache.enabled=false
234
235
236# Run a scan-build static analysis.
237scan_build: clean_src third_party
238	$(Q)scan-build make -C src libxlsxwriter.a
239	$(Q)$(MAKE) -C src clean
240	$(Q)rm -f  lib/*
241
242spellcheck:
243	$(Q)for f in docs/src/*.dox;         do aspell --lang=en_US --check $$f; done
244	$(Q)for f in include/xlsxwriter/*.h; do aspell --lang=en_US --check $$f; done
245	$(Q)for f in src/*.c;                do aspell --lang=en_US --check $$f; done
246	$(Q)for f in examples/*.c;           do aspell --lang=en_US --check $$f; done
247	$(Q)aspell --lang=en_US --check Changes.txt
248	$(Q)aspell --lang=en_US --check Readme.md
249	$(Q)aspell --lang=en_US --check docs/src/examples.txt
250
251releasecheck:
252	$(Q)dev/release/release_check.sh
253
254release: releasecheck
255	@echo
256	@echo "Pushing to git main ..."
257	$(Q)git push origin main
258	$(Q)git push --tags
259
260	@echo
261	@echo "Pushing updated docs ..."
262	$(Q)make -C ../libxlsxwriter.github.io release
263
264	@echo
265	@echo "Pushing the cocoapod ..."
266	$(Q)pod trunk push libxlsxwriter.podspec --use-libraries
267
268	@echo
269	@echo "Finished. Opening files."
270	$(Q)open https://libxlsxwriter.github.io/changes.html
271	$(Q)open https://cocoadocs.org/docsets/libxlsxwriter
272	$(Q)open https://github.com/jmcnamara/libxlsxwriter
273	$(Q)open https://github.com/jmcnamara/libxlsxwriter/releases
274