1# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*-
2#
3# This file is part of the LibreOffice project.
4#
5# This Source Code Form is subject to the terms of the Mozilla Public
6# License, v. 2.0. If a copy of the MPL was not distributed with this
7# file, You can obtain one at http://mozilla.org/MPL/2.0/.
8#
9
10$(eval $(call gb_ExternalProject_ExternalProject,python3))
11
12$(eval $(call gb_ExternalProject_use_externals,python3,\
13	expat \
14	$(if $(filter WNT LINUX,$(OS)),libffi) \
15	openssl \
16	zlib \
17))
18
19$(eval $(call gb_ExternalProject_register_targets,python3,\
20	build \
21	$(if $(filter MACOSX,$(OS)),\
22		fixscripts \
23		fixinstallnames \
24		executables \
25		removeunnecessarystuff \
26	) \
27))
28
29ifeq ($(OS),WNT)
30
31# TODO: using Debug configuration and related mangling of pyconfig.h
32
33# at least for MSVC 2008 it is necessary to clear MAKEFLAGS because
34# nmake is invoked
35$(call gb_ExternalProject_get_state_target,python3,build) :
36	$(call gb_Trace_StartRange,python3,EXTERNAL)
37	$(call gb_ExternalProject_run,build,\
38		MAKEFLAGS= MSBuild.exe pcbuild.sln /t:Build $(gb_MSBUILD_CONFIG_AND_PLATFORM) \
39			/p:opensslIncludeDir=$(call gb_UnpackedTarball_get_dir,openssl)/include \
40			/p:opensslOutDir=$(call gb_UnpackedTarball_get_dir,openssl) \
41			/p:zlibDir=$(call gb_UnpackedTarball_get_dir,zlib) \
42			/p:libffiOutDir=$(call gb_UnpackedTarball_get_dir,libffi)/$(HOST_PLATFORM)/.libs \
43			/p:libffiIncludeDir=$(call gb_UnpackedTarball_get_dir,libffi)/$(HOST_PLATFORM)/include \
44			/maxcpucount \
45			$(if $(filter 160,$(VCVER)),/p:PlatformToolset=v142 /p:VisualStudioVersion=16.0 /ToolsVersion:Current) \
46			$(if $(filter 10,$(WINDOWS_SDK_VERSION)),/p:WindowsTargetPlatformVersion=$(UCRTVERSION)) \
47	,PCBuild)
48	$(call gb_Trace_EndRange,python3,EXTERNAL)
49
50else
51
52# --with-system-expat: this should find the one in the workdir (or system)
53
54# OPENSSL_INCLUDES OPENSSL_LDFLAGS OPENSSL_LIBS cannot be set via commandline!
55# use --with-openssl instead, which requires include/ and lib/ subdirs.
56
57# libffi is not all that stable, with 3 different SONAMEs currently, so we
58# have to bundle it; --without-system-ffi does not work any more on Linux.
59# Unfortuantely (as of 3.7) pkg-config is used to locate libffi so we do some
60# hacks to find the libffi.pc in workdir by overriding PKG_CONFIG_LIBDIR.
61# Also, pkg-config is only used to find the headers, the libdir needs to be
62# passed extra.
63
64# create a symlink "LO_lib" because the .so are in a directory with platform
65# specific name like build/lib.linux-x86_64-3.3
66
67python3_cflags = $(ZLIB_CFLAGS)
68ifneq (,$(ENABLE_VALGRIND))
69    python3_cflags += $(VALGRIND_CFLAGS)
70endif
71
72# This happens to override the -O3 in the default OPT set in
73# workdir/UnpackedTarball/python3/configure.ac while keeping the other content of that OPT intact:
74ifeq ($(ENABLE_OPTIMIZED),)
75python3_cflags += $(gb_COMPILERNOOPTFLAGS)
76endif
77
78$(call gb_ExternalProject_get_state_target,python3,build) :
79	$(call gb_Trace_StartRange,python3,EXTERNAL)
80	$(call gb_ExternalProject_run,build,\
81		$(if $(filter MACOSX,$(OS)), \
82			$(if $(filter 10.8 10.9 10.10 10.11,$(MACOSX_DEPLOYMENT_TARGET)), \
83				ac_cv_func_getentropy=no \
84				ac_cv_func_clock_gettime=no \
85			) \
86		) \
87		$(gb_RUN_CONFIGURE) ./configure \
88		$(if $(CROSS_COMPILING),--build=$(BUILD_PLATFORM) --host=$(HOST_PLATFORM)) \
89		$(if $(ENABLE_VALGRIND),--with-valgrind) \
90		$(if $(ENABLE_DBGUTIL),--with-pydebug) \
91		--prefix=/python-inst \
92		--with-system-expat \
93		$(if $(filter AIX,$(OS)), \
94			--disable-ipv6 --with-threads OPT="-g0 -fwrapv -O3 -Wall") \
95		$(if $(filter MACOSX,$(OS)), \
96			$(if $(filter INTEL,$(CPUNAME)),--enable-universalsdk=$(MACOSX_SDK_PATH) \
97                                --with-universal-archs=intel \
98            ) \
99			--enable-framework=/@__________________________________________________OOO --with-framework-name=LibreOfficePython, \
100			--enable-shared \
101			$(if $(filter 1090 101000 101100 101200,$(MAC_OS_X_VERSION_MIN_REQUIRED)),ac_cv_func_utimensat=no) \
102		) \
103		$(if $(ENABLE_OPENSSL),$(if $(SYSTEM_OPENSSL),,\
104			--with-openssl=$(call gb_UnpackedTarball_get_dir,openssl) \
105		) ) \
106		$(if $(filter LINUX,$(OS)), \
107			PKG_CONFIG_LIBDIR="$(call gb_UnpackedTarball_get_dir,libffi)/$(HOST_PLATFORM)$${PKG_CONFIG_LIBDIR:+:$$PKG_CONFIG_LIBDIR}" \
108		) \
109		CC="$(strip $(CC) \
110			$(if $(SYSTEM_EXPAT),,-I$(call gb_UnpackedTarball_get_dir,expat)/lib) \
111			$(if $(SYSBASE), -I$(SYSBASE)/usr/include) \
112			)" \
113		$(if $(python3_cflags),CFLAGS='$(python3_cflags)') \
114		$(if $(filter -fsanitize=%,$(CC)),LINKCC="$(CXX) -pthread") \
115		LDFLAGS="$(strip $(LDFLAGS) \
116			$(if $(filter LINUX,$(OS)),-L$(call gb_UnpackedTarball_get_dir,libffi)/$(HOST_PLATFORM)/.libs) \
117			$(if $(SYSTEM_EXPAT),,-L$(gb_StaticLibrary_WORKDIR)) \
118			$(if $(SYSTEM_ZLIB),,-L$(gb_StaticLibrary_WORKDIR)) \
119			$(if $(SYSBASE), -L$(SYSBASE)/usr/lib) \
120			$(gb_LTOFLAGS) \
121			)" \
122		&& MAKEFLAGS= $(MAKE) \
123			$(if $(filter MACOSX,$(OS)),DESTDIR=$(EXTERNAL_WORKDIR)/python-inst install) \
124			$(if $(SYSTEM_ZLIB),,ZLIB_INCDIR=$(WORKDIR)/UnpackedTarball/zlib) \
125		&& ln -s build/lib.* LO_lib \
126	)
127	$(call gb_Trace_EndRange,python3,EXTERNAL)
128
129endif
130
131# If you want to run Python's own unit tests, add this to the chain of commands above:
132#		&& MAKEFLAGS= $(MAKE) \
133#			$(if $(filter MACOSX,$(OS)),DESTDIR=$(EXTERNAL_WORKDIR)/python-inst) \
134#			$(if $(SYSTEM_ZLIB),,ZLIB_INCDIR=$(WORKDIR)/UnpackedTarball/zlib) \
135#			test \
136
137ifeq ($(OS),MACOSX)
138
139python3_fw_prefix=$(call gb_UnpackedTarball_get_dir,python3)/python-inst/@__________________________________________________OOO/LibreOfficePython.framework
140
141# rule to allow relocating the whole framework, removing reference to buildinstallation directory
142# also scripts are not allowed to be signed as executables (with extended attributes), but need to
143# be treated as data/put into Resources folder, see also
144# https://developer.apple.com/library/archive/technotes/tn2206/_index.html
145$(call gb_ExternalProject_get_state_target,python3,fixscripts) : $(call gb_ExternalProject_get_state_target,python3,build)
146	$(call gb_Output_announce,python3 - remove reference to installroot from scripts,build,CUS,5)
147	$(COMMAND_ECHO)cd $(python3_fw_prefix)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/bin/ && \
148	for file in \
149		2to3-$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR) \
150		easy_install-$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR) \
151		idle$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR) \
152		pip$(PYTHON_VERSION_MAJOR) \
153		pip$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR) \
154		pydoc$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR) \
155		python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)-config \
156	; do { rm "$$file" && $(gb_AWK) '\
157		BEGIN {print "#!/bin/bash\n\
158origpath=$$(pwd)\n\
159bindir=$$(cd $$(dirname \"$$0\") ; pwd)\n\
160cd \"$$origpath\"\n\
161\"$$bindir/../Resources/Python.app/Contents/MacOS/LibreOfficePython\" - $$@ <<EOF"} \
162		FNR==1{next} \
163		      {print} \
164		END   {print "EOF"}' > "../Resources/$$file" ; } < "$$file" && \
165	chmod +x "../Resources/$$file" && ln -s "../Resources/$$file" ; done
166	touch $@
167
168$(call gb_ExternalProject_get_state_target,python3,fixinstallnames) : $(call gb_ExternalProject_get_state_target,python3,build) \
169        | $(call gb_ExternalProject_get_state_target,python3,removeunnecessarystuff)
170	$(INSTALL_NAME_TOOL) -change \
171		$(python3_fw_prefix)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/LibreOfficePython \
172		@executable_path/../../../../LibreOfficePython \
173		$(python3_fw_prefix)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/Resources/Python.app/Contents/MacOS/LibreOfficePython
174	for file in $(shell $(FIND) $(python3_fw_prefix)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib/python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib-dynload -name "*.so") ; do \
175	$(INSTALL_NAME_TOOL) -change \
176		$(python3_fw_prefix)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/LibreOfficePython \
177		@loader_path/../../../LibreOfficePython $$file ; done
178	touch $@
179
180$(call gb_ExternalProject_get_state_target,python3,executables) : $(call gb_ExternalProject_get_state_target,python3,build)
181	cd $(python3_fw_prefix)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/bin ; \
182	$(INSTALL_NAME_TOOL) -change \
183		$(python3_fw_prefix)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/LibreOfficePython \
184		@executable_path/../LibreOfficePython python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)
185	touch $@
186
187# Remove modules (both Python and binary bits) of questionable usefulness that we don't ship on
188# other platforms either. See the "packages not shipped" comment in ExternalPackage_python3.mk.
189
190$(call gb_ExternalProject_get_state_target,python3,removeunnecessarystuff) : $(call gb_ExternalProject_get_state_target,python3,build)
191	$(call gb_Output_announce,python3 - remove the stuff we don't need to ship,build,CUS,5)
192	rm -r $(python3_fw_prefix)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib/python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/dbm
193	rm -r $(python3_fw_prefix)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib/python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/sqlite3
194	rm -r $(python3_fw_prefix)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib/python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/curses
195	rm -r $(python3_fw_prefix)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib/python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/idlelib
196	rm -r $(python3_fw_prefix)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib/python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/tkinter
197	rm -r $(python3_fw_prefix)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib/python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/turtledemo
198	rm -r $(python3_fw_prefix)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib/python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/test
199	rm -r $(python3_fw_prefix)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib/python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/venv
200	# Then the binary libraries
201	rm $(python3_fw_prefix)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib/python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib-dynload/_dbm.cpython-$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)*.so
202	rm $(python3_fw_prefix)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib/python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib-dynload/_sqlite3.cpython-$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)*.so
203	rm $(python3_fw_prefix)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib/python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib-dynload/_curses.cpython-$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)*.so
204	rm $(python3_fw_prefix)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib/python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib-dynload/_curses_panel.cpython-$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)*.so
205	rm $(python3_fw_prefix)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib/python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib-dynload/_test*.cpython-$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)*.so
206	touch $@
207
208endif
209
210# vim: set noet sw=4 ts=4:
211