1#########################################################################
2#
3# This is the master makefile.
4# Here we put all the top-level make targets, platform-independent
5# rules, etc. This is just a fancy wrapper around cmake, but for many
6# people, it's a lot simpler to just type "make" and have everything
7# happen automatically.
8#
9# Run 'make help' to list helpful targets.
10#
11# Copyright 2008-present Contributors to the OpenImageIO project.
12# SPDX-License-Identifier: BSD-3-Clause
13# https://github.com/OpenImageIO/oiio/blob/master/LICENSE.md
14#########################################################################
15
16
17.PHONY: all debug profile clean realclean nuke doxygen
18
19working_dir	:= ${shell pwd}
20
21# Figure out which architecture we're on
22include ${working_dir}/src/make/detectplatform.mk
23
24# Presence of make variables DEBUG and PROFILE cause us to make special
25# builds, which we put in their own areas.
26ifdef DEBUG
27    variant +=.debug
28endif
29ifdef PROFILE
30    variant +=.profile
31endif
32
33MY_MAKE_FLAGS ?=
34MY_NINJA_FLAGS ?=
35MY_CMAKE_FLAGS ?=
36BUILDSENTINEL ?= Makefile
37NINJA ?= ninja
38CMAKE ?= cmake
39CMAKE_BUILD_TYPE ?= Release
40
41# Site-specific build instructions
42OPENIMAGEIO_SITE ?= ${shell uname -n}
43ifneq (${shell echo ${OPENIMAGEIO_SITE} | grep imageworks.com},)
44include ${working_dir}/site/spi/Makefile-bits
45endif
46
47# Set up variables holding the names of platform-dependent directories --
48# set these after evaluating site-specific instructions
49top_build_dir ?= build
50build_dir     ?= ${top_build_dir}/${platform}${variant}
51top_dist_dir  ?= dist
52dist_dir      ?= ${top_dist_dir}/${platform}${variant}
53
54INSTALL_PREFIX ?= ${working_dir}/${dist_dir}
55
56VERBOSE ?= ${SHOWCOMMANDS}
57ifneq (${VERBOSE},)
58MY_MAKE_FLAGS += VERBOSE=${VERBOSE}
59MY_CMAKE_FLAGS += -DVERBOSE:BOOL=${VERBOSE}
60ifneq (${VERBOSE},0)
61	MY_NINJA_FLAGS += -v
62	TEST_FLAGS += -V
63endif
64$(info OPENIMAGEIO_SITE = ${OPENIMAGEIO_SITE})
65$(info dist_dir = ${dist_dir})
66$(info INSTALL_PREFIX = ${INSTALL_PREFIX})
67endif
68
69ifneq (${EMBEDPLUGINS},)
70MY_CMAKE_FLAGS += -DEMBEDPLUGINS:BOOL=${EMBEDPLUGINS}
71endif
72
73ifneq (${OIIO_THREAD_ALLOW_DCLP},)
74MY_CMAKE_FLAGS += -DOIIO_THREAD_ALLOW_DCLP:BOOL=${OIIO_THREAD_ALLOW_DCLP}
75endif
76
77ifneq (${NAMESPACE},)
78MY_CMAKE_FLAGS += -DOIIO_NAMESPACE:STRING=${NAMESPACE}
79endif
80
81ifneq (${USE_PYTHON},)
82MY_CMAKE_FLAGS += -DUSE_PYTHON:BOOL=${USE_PYTHON}
83endif
84
85ifneq (${PYTHON_VERSION},)
86MY_CMAKE_FLAGS += -DPYTHON_VERSION:STRING=${PYTHON_VERSION}
87endif
88
89ifneq (${PYLIB_LIB_PREFIX},)
90MY_CMAKE_FLAGS += -DPYLIB_LIB_PREFIX:BOOL=${PYLIB_LIB_PREFIX}
91endif
92
93ifneq (${PYLIB_INCLUDE_SONAME},)
94MY_CMAKE_FLAGS += -DPYLIB_INCLUDE_SONAME:BOOL=${PYLIB_INCLUDE_SONAME}
95endif
96
97ifneq (${USE_EXTERNAL_PUGIXML},)
98MY_CMAKE_FLAGS += -DUSE_EXTERNAL_PUGIXML:BOOL=${USE_EXTERNAL_PUGIXML}
99endif
100
101ifneq (${OPENEXR_ROOT},)
102MY_CMAKE_FLAGS += -DOPENEXR_ROOT:STRING=${OPENEXR_ROOT}
103endif
104
105ifneq (${ILMBASE_ROOT},)
106MY_CMAKE_FLAGS += -DILMBASE_ROOT:STRING=${ILMBASE_ROOT}
107endif
108
109ifneq (${NUKE_VERSION},)
110MY_CMAKE_FLAGS += -DNUKE_VERSION:STRING=${NUKE_VERSION}
111endif
112
113ifneq (${STOP_ON_WARNING},)
114MY_CMAKE_FLAGS += -DSTOP_ON_WARNING:BOOL=${STOP_ON_WARNING}
115endif
116
117ifneq (${BUILD_SHARED_LIBS},)
118MY_CMAKE_FLAGS += -DBUILD_SHARED_LIBS:BOOL=${BUILD_SHARED_LIBS}
119endif
120
121ifneq (${LINKSTATIC},)
122MY_CMAKE_FLAGS += -DLINKSTATIC:BOOL=${LINKSTATIC}
123endif
124
125ifneq (${OIIO_BUILD_TOOLS},)
126MY_CMAKE_FLAGS += -DOIIO_BUILD_TOOLS:BOOL=${OIIO_BUILD_TOOLS}
127endif
128
129ifneq (${OIIO_BUILD_TESTS},)
130MY_CMAKE_FLAGS += -DOIIO_BUILD_TESTS:BOOL=${OIIO_BUILD_TESTS}
131endif
132
133ifneq (${SOVERSION},)
134MY_CMAKE_FLAGS += -DSOVERSION:STRING=${SOVERSION}
135endif
136
137ifneq (${OIIO_LIBNAME_SUFFIX},)
138MY_CMAKE_FLAGS += -DOIIO_LIBNAME_SUFFIX:STRING=${OIIO_LIBNAME_SUFFIX}
139endif
140
141ifneq (${BUILD_OIIOUTIL_ONLY},)
142MY_CMAKE_FLAGS += -DBUILD_OIIOUTIL_ONLY:BOOL=${BUILD_OIIOUTIL_ONLY}
143endif
144
145ifdef DEBUG
146CMAKE_BUILD_TYPE=Debug
147endif
148
149ifdef PROFILE
150CMAKE_BUILD_TYPE=RelWithDebInfo
151endif
152
153ifneq (${MYCC},)
154MY_CMAKE_FLAGS += -DCMAKE_C_COMPILER:STRING="${MYCC}"
155endif
156ifneq (${MYCXX},)
157MY_CMAKE_FLAGS += -DCMAKE_CXX_COMPILER:STRING="${MYCXX}"
158endif
159
160ifneq (${USE_CPP},)
161MY_CMAKE_FLAGS += -DCMAKE_CXX_STANDARD=${USE_CPP}
162endif
163
164ifneq (${CMAKE_CXX_STANDARD},)
165MY_CMAKE_FLAGS += -DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}
166endif
167
168ifneq (${USE_LIBCPLUSPLUS},)
169MY_CMAKE_FLAGS += -DUSE_LIBCPLUSPLUS:BOOL=${USE_LIBCPLUSPLUS}
170endif
171
172ifneq (${GLIBCXX_USE_CXX11_ABI},)
173MY_CMAKE_FLAGS += -DGLIBCXX_USE_CXX11_ABI=${GLIBCXX_USE_CXX11_ABI}
174endif
175
176ifneq (${EXTRA_CPP_ARGS},)
177MY_CMAKE_FLAGS += -DEXTRA_CPP_ARGS:STRING="${EXTRA_CPP_ARGS}"
178endif
179
180ifneq (${USE_SIMD},)
181MY_CMAKE_FLAGS += -DUSE_SIMD:STRING="${USE_SIMD}"
182endif
183
184ifneq (${TEX_BATCH_SIZE},)
185MY_CMAKE_FLAGS += -DTEX_BATCH_SIZE:STRING="${TEX_BATCH_SIZE}"
186endif
187
188ifneq (${TEST},)
189TEST_FLAGS += -R ${TEST}
190endif
191
192ifneq (${USE_CCACHE},)
193MY_CMAKE_FLAGS += -DUSE_CCACHE:BOOL=${USE_CCACHE}
194endif
195
196ifeq (${USE_NINJA},1)
197MY_CMAKE_FLAGS += -G Ninja
198BUILDSENTINEL := build.ninja
199endif
200
201ifeq (${CODECOV},1)
202  CMAKE_BUILD_TYPE=Debug
203  MY_CMAKE_FLAGS += -DCODECOV:BOOL=${CODECOV}
204endif
205
206ifneq (${SANITIZE},)
207  MY_CMAKE_FLAGS += -DSANITIZE=${SANITIZE}
208endif
209
210ifneq (${CLANG_TIDY},)
211  MY_CMAKE_FLAGS += -DCLANG_TIDY:BOOL=1
212endif
213ifneq (${CLANG_TIDY_CHECKS},)
214  MY_CMAKE_FLAGS += -DCLANG_TIDY_CHECKS:STRING=${CLANG_TIDY_CHECKS}
215endif
216ifneq (${CLANG_TIDY_ARGS},)
217  MY_CMAKE_FLAGS += -DCLANG_TIDY_ARGS:STRING=${CLANG_TIDY_ARGS}
218endif
219ifneq (${CLANG_TIDY_FIX},)
220  MY_CMAKE_FLAGS += -DCLANG_TIDY_FIX:BOOL=${CLANG_TIDY_FIX}
221  MY_NINJA_FLAGS += -j 1
222  # N.B. when fixing, you don't want parallel jobs!
223endif
224
225ifneq (${CLANG_FORMAT_INCLUDES},)
226  MY_CMAKE_FLAGS += -DCLANG_FORMAT_INCLUDES:STRING=${CLANG_FORMAT_INCLUDES}
227endif
228ifneq (${CLANG_FORMAT_EXCLUDES},)
229  MY_CMAKE_FLAGS += -DCLANG_FORMAT_EXCLUDES:STRING=${CLANG_FORMAT_EXCLUDES}
230endif
231
232ifneq (${BUILD_MISSING_DEPS},)
233  MY_CMAKE_FLAGS += -DBUILD_MISSING_DEPS:BOOL=${BUILD_MISSING_DEPS}
234endif
235
236
237#$(info MY_CMAKE_FLAGS = ${MY_CMAKE_FLAGS})
238#$(info MY_MAKE_FLAGS = ${MY_MAKE_FLAGS})
239
240#########################################################################
241
242
243
244
245#########################################################################
246# Top-level documented targets
247
248all: dist
249
250# 'make debug' is implemented via recursive make setting DEBUG
251debug:
252	${MAKE} DEBUG=1 --no-print-directory
253
254# 'make profile' is implemented via recursive make setting PROFILE
255profile:
256	${MAKE} PROFILE=1 --no-print-directory
257
258# 'make config' constructs the build directory and runs 'cmake' there,
259# generating makefiles to build the project.  For speed, it only does this when
260# ${build_dir}/Makefile doesn't already exist, in which case we rely on the
261# cmake generated makefiles to regenerate themselves when necessary.
262config:
263	@ (if [ ! -e ${build_dir}/${BUILDSENTINEL} ] ; then \
264		${CMAKE} -E make_directory ${build_dir} ; \
265		cd ${build_dir} ; \
266		${CMAKE} -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} \
267			 -DCMAKE_INSTALL_PREFIX=${INSTALL_PREFIX} \
268			 ${MY_CMAKE_FLAGS} ../.. ; \
269	 fi)
270
271
272# 'make build' does a basic build (after first setting it up)
273build: config
274	@ ( cd ${build_dir} ; \
275	    ${CMAKE} --build . --config ${CMAKE_BUILD_TYPE} \
276	  )
277
278# 'make install' builds everthing and installs it in 'dist'.
279# Suppress pointless output from docs installation.
280install: build
281	@ ( cd ${build_dir} ; \
282	    ${CMAKE} --build . --target install --config ${CMAKE_BUILD_TYPE} | grep -v '^-- \(Installing\|Up-to-date\|Set runtime path\)' \
283	  )
284
285# 'make package' builds everything and then makes an installable package
286# (platform dependent -- may be .tar.gz, .sh, .dmg, .rpm, .deb. .exe)
287package: install
288	@ ( cd ${build_dir} ; \
289	    ${CMAKE} --build . --target package --config ${CMAKE_BUILD_TYPE} \
290	  )
291
292# 'make package_source' makes an installable source package
293# (platform dependent -- may be .tar.gz, .sh, .dmg, .rpm, .deb. .exe)
294package_source: install
295	@ ( cd ${build_dir} ; \
296	    ${CMAKE} --build . --target package_source --config ${CMAKE_BUILD_TYPE} \
297	  )
298
299# 'make clang-format' runs clang-format on all source files (if it's installed)
300clang-format: config
301	@ ( cd ${build_dir} ; \
302	    ${CMAKE} --build . --target clang-format --config ${CMAKE_BUILD_TYPE} \
303	  )
304
305
306# 'make dist' is just a synonym for 'make install'
307dist : install
308
309TEST_FLAGS += --force-new-ctest-process --output-on-failure
310
311# 'make test' does a full build and then runs all tests
312test: build
313	@ ${CMAKE} -E cmake_echo_color --switch=$(COLOR) --cyan "Running tests ${TEST_FLAGS}..."
314	@ ( cd ${build_dir} ; \
315	    PYTHONPATH=${PWD}/${build_dir}/lib/python/site-packages \
316	    ctest -E broken ${TEST_FLAGS} \
317	  )
318	@ ( if [[ "${CODECOV}" == "1" ]] ; then \
319	      cd ${build_dir} ; \
320	      lcov -b . -d . -c -o cov.info ; \
321	      lcov --remove cov.info "/usr*" -o cov.info ; \
322	      genhtml -o ./cov -t "Test coverage" --num-spaces 4 cov.info ; \
323	  fi )
324
325# 'make testall' does a full build and then runs all tests (even the ones
326# that are expected to fail on some platforms)
327testall: build
328	${CMAKE} -E cmake_echo_color --switch=$(COLOR) --cyan "Running all tests ${TEST_FLAGS}..."
329	( cd ${build_dir} ; PYTHONPATH=${PWD}/${build_dir}/lib/python/site-packages ctest ${TEST_FLAGS} )
330
331# 'make clean' clears out the build directory for this platform
332clean:
333	${CMAKE} -E remove_directory ${build_dir}
334
335# 'make realclean' clears out both build and dist directories for this platform
336realclean: clean
337	${CMAKE} -E remove_directory ${dist_dir}
338
339# 'make nuke' blows away the build and dist areas for all platforms
340nuke:
341	${CMAKE} -E remove_directory ${top_build_dir}
342	${CMAKE} -E remove_directory ${top_dist_dir}
343
344doxygen:
345	doxygen src/doc/Doxyfile
346
347#########################################################################
348
349
350
351# 'make help' prints important make targets
352help:
353	@echo "Targets:"
354	@echo "  make              Build and install optimized binaries and libraries"
355	@echo "  make install      Build and install optimized binaries and libraries"
356	@echo "  make build        Build only (no install) optimized binaries and libraries"
357	@echo "  make config       Just configure cmake, don't build"
358	@echo "  make debug        Build and install unoptimized with symbols"
359	@echo "  make profile      Build and install for profiling"
360	@echo "  make clean        Remove the temporary files in ${build_dir}"
361	@echo "  make realclean    Remove both ${build_dir} AND ${dist_dir}"
362	@echo "  make nuke         Remove ALL of build and dist (not just ${platform})"
363	@echo "  make test         Run tests"
364	@echo "  make testall      Run all tests, even broken ones"
365	@echo "  make clang-format Run clang-format on all the source files"
366	@echo ""
367	@echo "Helpful modifiers:"
368	@echo "  C++ compiler and build process:"
369	@echo "      VERBOSE=1                Show all compilation commands"
370	@echo "      STOP_ON_WARNING=0        Do not stop building if compiler warns"
371	@echo "      OPENIMAGEIO_SITE=xx      Use custom site build mods"
372	@echo "      MYCC=xx MYCXX=yy         Use custom compilers"
373	@echo "      CMAKE_CXX_STANDARD=14    Compile in C++14 mode (default is C++11)"
374	@echo "      USE_LIBCPLUSPLUS=1       For clang, use libc++"
375	@echo "      GLIBCXX_USE_CXX11_ABI=1  For gcc, use the new string ABI"
376	@echo "      EXTRA_CPP_ARGS=          Additional args to the C++ command"
377	@echo "      USE_NINJA=1              Set up Ninja build (instead of make)"
378	@echo "      USE_CCACHE=0             Disable ccache (even if available)"
379	@echo "      CODECOV=1                Enable code coverage tests"
380	@echo "      SANITIZE=name1,...       Enable sanitizers (address, leak, thread)"
381	@echo "      CLANG_TIDY=1             Run clang-tidy on all source (can be modified"
382	@echo "                                  by CLANG_TIDY_ARGS=... and CLANG_TIDY_FIX=1"
383	@echo "      CLANG_FORMAT_INCLUDES=... CLANG_FORMAT_EXCLUDES=..."
384	@echo "                               Customize files for 'make clang-format'"
385	@echo "  Linking and libraries:"
386	@echo "      SOVERSION=nn             Include the specifed major version number "
387	@echo "                                  in the shared object metadata"
388	@echo "      OIIO_LIBNAME_SUFFIX=name Optional name appended to library names"
389	@echo "      BUILD_SHARED_LIBS=0      Build static library instead of shared"
390	@echo "      LINKSTATIC=1             Link with static external libs when possible"
391	@echo "  Dependency hints:"
392	@echo "      For each dependeny Foo, defining ENABLE_Foo=0 disables it, even"
393	@echo "      if found. And you can hint where to find it with Foo_ROOT=path"
394	@echo "      Note that it is case sensitive! The list of package names is:"
395	@echo "          DCMTK  FFmpeg  Field3D  Freetype  GIF  JPEGTurbo"
396	@echo "          LibRaw  OpenColorIO  OpenCV  OpenGL  OpenJpeg  OpenVDB"
397	@echo "          PTex  R3DSDK  TBB  TIFF  Webp"
398	@echo "  Finding and Using Dependencies:"
399	@echo "      BOOST_ROOT=path          Custom Boost installation"
400	@echo "      OPENEXR_ROOT=path        Custom OpenEXR installation"
401	@echo "      ILMBASE_ROOT=path        Custom IlmBase installation"
402	@echo "      USE_EXTERNAL_PUGIXML=1   Use the system PugiXML, not the one in OIIO"
403	@echo "      USE_QT=0                 Skip anything that needs Qt"
404	@echo "      USE_PYTHON=0             Don't build the Python binding"
405	@echo "      PYTHON_VERSION=2.6       Specify the Python version"
406	@echo "      USE_NUKE=0               Don't build Nuke plugins"
407	@echo "      Nuke_ROOT=path           Custom Nuke installation"
408	@echo "      NUKE_VERSION=ver         Custom Nuke version"
409	@echo "  OIIO build-time options:"
410	@echo "      INSTALL_PREFIX=path      Set installation prefix (default: ./${INSTALL_PREFIX})"
411	@echo "      NAMESPACE=name           Override namespace base name (default: OpenImageIO)"
412	@echo "      EMBEDPLUGINS=0           Don't compile the plugins into libOpenImageIO"
413	@echo "      OIIO_THREAD_ALLOW_DCLP=0 Don't allow threads.h to use DCLP"
414	@echo "      OIIO_BUILD_TOOLS=0       Skip building the command-line tools"
415	@echo "      OIIO_BUILD_TESTS=0       Skip building the unit tests"
416	@echo "      BUILD_OIIOUTIL_ONLY=1    Build *only* libOpenImageIO_Util"
417	@echo "      USE_SIMD=arch            Build with SIMD support (comma-separated choices:"
418	@echo "                                  0, sse2, sse3, ssse3, sse4.1, sse4.2, f16c,"
419	@echo "                                  avx, avx2, avx512f)"
420	@echo "      TEX_BATCH_SIZE=16        Override TextureSystem SIMD batch size"
421	@echo "      BUILD_MISSING_DEPS=1     Try to download/build missing dependencies"
422	@echo "  make test, extra options:"
423	@echo "      TEST=regex               Run only tests matching the regex"
424	@echo ""
425
426