You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

478 lines
15 KiB

  1. NULL =
  2. ACLOCAL_AMFLAGS = -I m4
  3. if ENABLE_SERVER
  4. IPASERVER_SUBDIRS = ipaserver
  5. SERVER_SUBDIRS = daemons init install
  6. endif
  7. if WITH_IPATESTS
  8. IPATESTS_SUBDIRS = ipatests
  9. endif
  10. IPACLIENT_SUBDIRS = ipaclient ipalib ipaplatform ipapython
  11. PYTHON_SUBDIRS = $(IPACLIENT_SUBDIRS) $(IPATESTS_SUBDIRS) $(IPASERVER_SUBDIRS)
  12. PYTHON_SCRIPT_SUBDIRS = \
  13. $(top_builddir) \
  14. $(top_builddir)/client \
  15. $(top_builddir)/daemons/dnssec \
  16. $(top_builddir)/install/certmonger \
  17. $(top_builddir)/install/oddjob \
  18. $(top_builddir)/install/restart_scripts \
  19. $(top_builddir)/install/tools \
  20. $(NULL)
  21. AZURE_PYTHON_SCRIPT_SUBDIR = $(top_builddir)/ipatests/azure
  22. IPA_PLACEHOLDERS = freeipa ipa ipaserver ipatests
  23. SUBDIRS = \
  24. asn1 \
  25. util \
  26. client \
  27. contrib \
  28. po \
  29. pypi \
  30. selinux \
  31. $(PYTHON_SUBDIRS) \
  32. $(SERVER_SUBDIRS) \
  33. $(NULL)
  34. GENERATED_PYTHON_FILES = \
  35. $(top_builddir)/ipaplatform/override.py \
  36. $(top_builddir)/ipapython/version.py \
  37. $(top_builddir)/makeaci \
  38. $(top_builddir)/makeapi \
  39. $(NULL)
  40. MOSTLYCLEANFILES = ipasetup.pyc ipasetup.pyo \
  41. pylint_plugins.pyc pylint_plugins.pyo
  42. # user-facing scripts
  43. nodist_bin_SCRIPTS = ipa
  44. # files required for build but not installed
  45. nodist_noinst_SCRIPTS = \
  46. makeapi \
  47. makeaci \
  48. $(NULL)
  49. dist_noinst_SCRIPTS = \
  50. make-doc \
  51. make-test \
  52. pylint_plugins.py \
  53. $(NULL)
  54. # templates
  55. dist_noinst_DATA = \
  56. ipa.in \
  57. makeaci.in \
  58. makeapi.in \
  59. $(NULL)
  60. ipasetup.py: ipasetup.py.in $(CONFIG_STATUS)
  61. $(AM_V_GEN)sed \
  62. -e 's|@VERSION[@]|$(VERSION)|g' \
  63. $< > $@
  64. .wheelconstraints: .wheelconstraints.in $(CONFIG_STATUS)
  65. $(AM_V_GEN)sed \
  66. -e 's|@VERSION[@]|$(VERSION)|g' \
  67. $< > $@
  68. EXTRA_DIST = .mailmap \
  69. ACI.txt \
  70. API.txt \
  71. BUILD.txt \
  72. config.rpath \
  73. README.md \
  74. Contributors.txt \
  75. COPYING.openssl \
  76. contrib \
  77. doc \
  78. freeipa.spec.in \
  79. ipasetup.py.in \
  80. pylintrc \
  81. .wheelconstraints.in
  82. clean-local:
  83. rm -rf "$(RPMBUILD)"
  84. rm -rf "$(top_builddir)/dist"
  85. rm -rf "$(top_builddir)/.tox"
  86. rm -rf "$(top_srcdir)/__pycache__"
  87. rm -f "$(top_builddir)"/$(PACKAGE)-*.tar.gz
  88. rm -rf "$(top_srcdir)/cov-int"
  89. rm -f "$(top_srcdir)/freeipa.tgz"
  90. # convenience targets for RPM build
  91. .PHONY: rpmroot rpmdistdir version-update _dist-version-bakein _rpms-prep \
  92. rpms _rpms-body srpms _srpms-body
  93. RPMBUILD ?= $(abs_builddir)/rpmbuild
  94. TARBALL = $(PACKAGE)-$(VERSION).tar.gz
  95. freeipa.spec: freeipa.spec.in $(top_builddir)/$(CONFIG_STATUS)
  96. $(AM_V_GEN)sed \
  97. -e 's|@VERSION[@]|$(VERSION)|g' \
  98. -e 's|@VENDOR_SUFFIX[@]|$(VENDOR_SUFFIX)|g' \
  99. $< > $@
  100. rpmroot:
  101. mkdir -p $(RPMBUILD)/BUILD
  102. mkdir -p $(RPMBUILD)/RPMS
  103. mkdir -p $(RPMBUILD)/SOURCES
  104. mkdir -p $(RPMBUILD)/SPECS
  105. mkdir -p $(RPMBUILD)/SRPMS
  106. rpmdistdir:
  107. mkdir -p $(top_builddir)/dist/rpms
  108. mkdir -p $(top_builddir)/dist/srpms
  109. # force IPA version re-generation (useful for build from Git)
  110. version-update:
  111. touch $(srcdir)/VERSION.m4
  112. # convert Git snapshot version to static value usable from inside of tarball
  113. _dist-version-bakein:
  114. if !IS_GIT_SNAPSHOT
  115. @echo "version-bakein target requires IPA_VERSION_IS_GIT_SNAPSHOT=yes"
  116. exit 1
  117. endif !IS_GIT_SNAPSHOT
  118. chmod u+w $(top_distdir)/VERSION.m4
  119. $(SED) -e 's/^define(IPA_VERSION_IS_GIT_SNAPSHOT,.*)/define(IPA_VERSION_IS_GIT_SNAPSHOT, no)/' -i $(top_distdir)/VERSION.m4
  120. $(SED) -e 's/^define(IPA_VERSION_PRE_RELEASE,\(.*\))/define(IPA_VERSION_PRE_RELEASE,\1.$(GIT_VERSION))/' -i $(top_distdir)/VERSION.m4
  121. cd $(top_distdir) && autoconf # re-generate configure from VERSION.m4
  122. if IS_GIT_SNAPSHOT
  123. VERSION_UPDATE_TARGET = version-update
  124. VERSION_BAKEIN_TARGET = _dist-version-bakein
  125. endif IS_GIT_SNAPSHOT
  126. # HACK to support IPA_VERSION_IS_GIT_SNAPSHOT:
  127. # touch VERSION.m4 will reexecute configure and change $(VERSION) used by dist
  128. # but it will not change $(VERSION) in already running target rpms.
  129. # We need to record new $(TARBALL) value used by dist for furher use
  130. # in rpms target.
  131. dist-hook: $(VERSION_BAKEIN_TARGET)
  132. echo "$(TARBALL)" > $(top_builddir)/.tarball_name
  133. echo "$(VERSION)" > $(top_builddir)/.version
  134. _rpms-prep: dist-gzip rpmroot rpmdistdir freeipa.spec
  135. cp $(top_builddir)/$$(cat $(top_builddir)/.tarball_name) $(RPMBUILD)/SOURCES/
  136. rm -f $(top_builddir)/.tarball_name
  137. rpms: $(VERSION_UPDATE_TARGET)
  138. $(MAKE) _rpms-body
  139. _rpms-body: _rpms-prep
  140. rpmbuild --define "_topdir $(RPMBUILD)" -ba $(top_builddir)/$(PACKAGE).spec $(RPMBUILD_OPTS)
  141. cp $(RPMBUILD)/RPMS/*/*$$(cat $(top_builddir)/.version)*.rpm $(top_builddir)/dist/rpms/
  142. cp $(RPMBUILD)/SRPMS/*$$(cat $(top_builddir)/.version)*.src.rpm $(top_builddir)/dist/srpms/
  143. rm -f rm -f $(top_builddir)/.version
  144. srpms: $(VERSION_UPDATE_TARGET)
  145. $(MAKE) _srpms-body
  146. _srpms-body: _rpms-prep
  147. rpmbuild --define "_topdir $(RPMBUILD)" -bs $(top_builddir)/$(PACKAGE).spec $(RPMBUILD_OPTS)
  148. cp $(RPMBUILD)/SRPMS/*$$(cat $(top_builddir)/.version)*.src.rpm $(top_builddir)/dist/srpms/
  149. rm -f rm -f $(top_builddir)/.version
  150. .PHONY: lite-server
  151. lite-server: $(GENERATED_PYTHON_FILES)
  152. +$(MAKE) -C $(top_builddir)/install/ui
  153. PYTHONPATH=$(top_srcdir) $(PYTHON) -bb \
  154. contrib/lite-server.py $(LITESERVER_ARGS)
  155. .PHONY: lint
  156. if WITH_POLINT
  157. POLINT_TARGET = polint
  158. endif WITH_POLINT
  159. if WITH_PYLINT
  160. PYLINT_TARGET = pylint
  161. endif WITH_PYLINT
  162. if WITH_JSLINT
  163. JSLINT_TARGET = jslint
  164. endif WITH_JSLINT
  165. lint: acilint apilint $(POLINT_TARGET) $(PYLINT_TARGET) $(JSLINT_TARGET) rpmlint yamllint
  166. .PHONY: devcheck
  167. devcheck: all
  168. if ! WITH_POLINT
  169. @echo "ERROR: polint not available"; exit 1
  170. endif
  171. if ! WITH_PYLINT
  172. @echo "ERROR: pylint not available"; exit 1
  173. endif
  174. if ! WITH_JSLINT
  175. @echo "ERROR: jslint not available"; exit 1
  176. endif
  177. @ # just tests, aci, api and pylint on Python 3
  178. PYTHONPATH=$(abspath $(top_srcdir)) $(PYTHON) ipatests/ipa-run-tests \
  179. --ipaclient-unittests
  180. $(MAKE) $(AM_MAKEFLAGS) acilint apilint polint pylint jslint rpmlint yamllint check
  181. @echo "All tests passed."
  182. .PHONY: fastcheck fasttest fastlint
  183. fastcheck:
  184. @$(MAKE) -j1 $(AM_MAKEFLAGS) fastlint rpmlint yamllint fasttest apilint acilint
  185. fasttest: $(GENERATED_PYTHON_FILES) ipasetup.py
  186. @ # --ignore doubles speed of total test run compared to pytest.skip()
  187. @ # on module.
  188. PATH=$(abspath ipatests):$$PATH PYTHONPATH=$(abspath $(top_srcdir)) \
  189. $(PYTHON) ipatests/ipa-run-tests \
  190. --skip-ipaapi \
  191. --ignore $(abspath $(top_srcdir))/ipatests/test_integration \
  192. --ignore $(abspath $(top_srcdir))/ipatests/test_xmlrpc
  193. fastlint: $(GENERATED_PYTHON_FILES) ipasetup.py
  194. if ! WITH_PYLINT
  195. @echo "ERROR: pylint not available"; exit 1
  196. endif
  197. @echo "Fast linting with $(PYTHON) from branch '$(GIT_BRANCH)'"
  198. @MERGEBASE=$$(git merge-base --fork-point $(GIT_BRANCH)); \
  199. PYFILES=$$(git diff --name-only --diff-filter=d $${MERGEBASE} \
  200. | grep -E '\.py$$' ); \
  201. INFILES=$$(git diff --name-only --diff-filter=d $${MERGEBASE} \
  202. | grep -E '\.in$$' \
  203. | xargs -n1 file 2>/dev/null | grep Python \
  204. | cut -d':' -f1; ); \
  205. if [ -n "$${PYFILES}" ] && [ -n "$${INFILES}" ]; then \
  206. FILES="$$( printf $${PYFILES}\\n$${INFILES} )" ; \
  207. elif [ -n "$${PYFILES}" ]; then \
  208. FILES="$${PYFILES}" ; \
  209. else \
  210. FILES="$${INFILES}" ; \
  211. fi ; \
  212. if [ -n "$${FILES}" ]; then \
  213. echo -e "Fast linting files:\n$${FILES}\n"; \
  214. echo "pycodestyle"; \
  215. echo "-----------"; \
  216. git diff -U0 $${MERGEBASE} | \
  217. $(PYTHON) -m pycodestyle --diff || exit $$?; \
  218. echo -e "\npylint"; \
  219. echo "------"; \
  220. PYTHONPATH=$(abspath $(top_srcdir)) $(PYTHON) -m pylint \
  221. --rcfile=$(top_srcdir)/pylintrc \
  222. --load-plugins pylint_plugins \
  223. $${FILES} || exit $$?; \
  224. else \
  225. echo "No modified Python files found"; \
  226. fi
  227. .PHONY: $(top_builddir)/ipaplatform/override.py
  228. $(top_builddir)/ipaplatform/override.py:
  229. (cd $(top_builddir)/ipaplatform && make override.py)
  230. .PHONY: $(top_builddir)/ipapython/version.py
  231. $(top_builddir)/ipapython/version.py:
  232. (cd $(top_builddir)/ipapython && make version.py)
  233. .PHONY: acilint
  234. acilint: $(GENERATED_PYTHON_FILES)
  235. cd $(srcdir); $(PYTHON) ./makeaci --validate
  236. .PHONY: apilint
  237. apilint: $(GENERATED_PYTHON_FILES)
  238. cd $(srcdir); $(PYTHON) ./makeapi --validate
  239. .PHONY: polint
  240. polint:
  241. $(MAKE) -C $(srcdir)/po PYTHON=$(PYTHON) \
  242. validate-src-strings validate-po test-gettext
  243. .PHONY: rpmlint
  244. rpmlint: freeipa.spec
  245. rpmlint ./$<
  246. # Try to load yml/yaml files via safe_load, which recognizes only standard
  247. # YAML tags and cannot construct an arbitrary Python object.
  248. # There are Jinja yaml templates, which differ from reqular ones. These
  249. # files should be placed on skip list (YAML_TEMPLATE_FILES), otherwise
  250. # safe_load fails.
  251. .PHONY: yamllint
  252. yamllint:
  253. YAML_TEMPLATE_FILES="\
  254. $(top_srcdir)/ipatests/azure/templates/ipa-test-config-template.yaml \
  255. "; \
  256. echo "jinja template files:"; \
  257. for YAML in $${YAML_TEMPLATE_FILES}; do \
  258. echo $${YAML}; \
  259. $(PYTHON) -c "import yaml; f = open('$${YAML}'); yaml.safe_load(f); f.close()" >/dev/null 2>&1 \
  260. && { echo Unexpected PASS of parsing yaml: $${YAML}. This file is a regular yaml.; exit 1; }; \
  261. done; \
  262. YAML_FILES=`find $(top_srcdir) \
  263. \( -name '*.yaml' -o \
  264. -name '*.yml' \) \
  265. $$(printf '! -path %s ' $${YAML_TEMPLATE_FILES})`; \
  266. echo -e "\nlint yaml files"; \
  267. echo "-----------"; \
  268. for YAML in $${YAML_FILES}; do \
  269. echo $${YAML}; \
  270. $(PYTHON) -c "import yaml; f = open('$${YAML}'); yaml.safe_load(f); f.close()" || { echo Your YAML file: $${YAML} has a wrong syntax or this is a Jinja template. In the latter clause, consider to add your YAML file to the YAML_TEMPLATE_FILES list in Makefile.am.; exit 1; } \
  271. done; \
  272. echo "-----------"
  273. # Run pylint for all python files. Finds all python files/packages, skips
  274. # folders rpmbuild, freeipa-* and dist. Skip (match, but don't print) .*,
  275. # *.in, *~. Finally print all python files, including scripts that do not
  276. # have python extension.
  277. .PHONY: pylint
  278. if WITH_PYLINT
  279. pylint: $(GENERATED_PYTHON_FILES) ipasetup.py python_scripts
  280. FILES=`find $(top_srcdir) \
  281. -type d -exec test -e '{}/__init__.py' \; -print -prune -o \
  282. -path './rpmbuild' -prune -o \
  283. -path './freeipa-*' -prune -o \
  284. -path './dist' -prune -o \
  285. -path './pypi' -prune -o \
  286. -path './.tox' -prune -o \
  287. -name '.*' -o \
  288. -name '*.in' -o \
  289. -name '*~' -o \
  290. -name '*.py' -print -o \
  291. -type f -exec grep -qsm1 '^#!.*\bpython' '{}' \; -print`; \
  292. FILES=`echo -e "$${FILES}\n$(AZURE_PYTHON_SCRIPT_SUBDIR)"`; \
  293. echo -e "Pylint on $(PYTHON) is running over files:\n$${FILES}\nPlease wait ...\n"; \
  294. PYTHONPATH=$(top_srcdir) $(PYTHON) -m pylint \
  295. --rcfile=$(top_srcdir)/pylintrc \
  296. --load-plugins pylint_plugins \
  297. $${FILES}
  298. endif # WITH_PYLINT
  299. .PHONY: jslint jslint-ui jslint-ui-test jslint-html \
  300. $(top_builddir)/install/ui/src/libs/loader.js
  301. if WITH_JSLINT
  302. jslint: jslint-ui jslint-ui-test jslint-html
  303. $(top_builddir)/install/ui/src/libs/loader.js:
  304. (cd $(top_builddir)/install/ui/src/libs && make loader.js)
  305. # create temporary symlinks to allow jslint to find libs/loader.js
  306. jslint-ui: $(top_builddir)/install/ui/src/libs/loader.js
  307. cd $(top_srcdir)/install/ui; \
  308. jsl -nologo -nosummary -nofilelisting -conf jsl.conf;
  309. jslint-ui-test:
  310. cd $(top_srcdir)/install/ui/test; \
  311. jsl -nologo -nosummary -nofilelisting -conf jsl.conf
  312. jslint-html:
  313. cd $(top_srcdir)/install/html; \
  314. jsl -nologo -nosummary -nofilelisting -conf jsl.conf
  315. endif # WITH_JSLINT
  316. .PHONY: bdist_wheel wheel_bundle wheel_placeholder pypi_packages
  317. WHEELDISTDIR = $(top_builddir)/dist/wheels
  318. WHEELPYPIDIR = $(top_builddir)/dist/pypi
  319. WHEELBUNDLEDIR = $(top_builddir)/dist/bundle
  320. @MK_IFEQ@ ($(IPA_SERVER_WHEELS),1)
  321. IPA_WHEEL_PACKAGES @MK_ASSIGN@ $(IPACLIENT_SUBDIRS) ipaplatform ipaserver
  322. IPA_OMIT_INSTALL @MK_ASSIGN@ 0
  323. @MK_ELSE@
  324. IPA_WHEEL_PACKAGES @MK_ASSIGN@ $(IPACLIENT_SUBDIRS)
  325. IPA_OMIT_INSTALL @MK_ASSIGN@ 1
  326. @MK_ENDIF@
  327. # additional wheels for bundle, e.g. IPA_EXTRA_WHEELS="ipatests[webui] pylint"
  328. IPA_EXTRA_WHEELS=
  329. $(WHEELDISTDIR):
  330. mkdir -p $(WHEELDISTDIR)
  331. $(WHEELBUNDLEDIR):
  332. mkdir -p $(WHEELBUNDLEDIR)
  333. $(WHEELPYPIDIR):
  334. mkdir -p $(WHEELPYPIDIR)
  335. bdist_wheel: $(WHEELDISTDIR)
  336. rm -f $(foreach item,$(IPA_WHEEL_PACKAGES) ipatests,$(WHEELDISTDIR)/$(item)-*.whl)
  337. export IPA_OMIT_INSTALL=$(IPA_OMIT_INSTALL); \
  338. for dir in $(IPA_WHEEL_PACKAGES) ipatests; do \
  339. $(MAKE) $(AM_MAKEFLAGS) -C $${dir} $@ || exit 1; \
  340. done
  341. wheel_bundle: $(WHEELBUNDLEDIR) bdist_wheel .wheelconstraints
  342. rm -f $(foreach item,$(IPA_WHEEL_PACKAGES) ipatests,$(WHEELBUNDLEDIR)/$(item)-*.whl)
  343. @# dbus-python sometimes fails when MAKEFLAGS is set to -j2 or higher
  344. MAKEFLAGS= $(PYTHON) -m pip wheel \
  345. --disable-pip-version-check \
  346. --constraint .wheelconstraints \
  347. --find-links $(WHEELDISTDIR) \
  348. --find-links $(WHEELBUNDLEDIR) \
  349. --wheel-dir $(WHEELBUNDLEDIR) \
  350. $(IPA_EXTRA_WHEELS) $(IPA_WHEEL_PACKAGES)
  351. pypi_packages: $(WHEELPYPIDIR) .wheelconstraints
  352. rm -f $(WHEELPYPIDIR)/*
  353. for dir in $(IPACLIENT_SUBDIRS); do \
  354. $(MAKE) $(AM_MAKEFLAGS) \
  355. IPA_OMIT_INSTALL=1 WHEELDISTDIR="$(abspath $(WHEELPYPIDIR))" \
  356. -C $${dir} bdist_wheel || exit 1; \
  357. done
  358. for dir in $(IPA_PLACEHOLDERS); do \
  359. $(MAKE) $(AM_MAKEFLAGS) \
  360. IPA_OMIT_INSTALL=1 WHEELDISTDIR="$(abspath $(WHEELPYPIDIR))" \
  361. -C $(top_srcdir)/pypi/$${dir} bdist_wheel || exit 1; \
  362. done
  363. @echo -e "\n\nTo upload packages to PyPI, run:\n"
  364. @echo -e " twine upload $(WHEELPYPIDIR)/*-$(VERSION)-py2.py3-none-any.whl\n"
  365. .PHONY: python_install
  366. python_install:
  367. for dir in $(PYTHON_SUBDIRS); do \
  368. $(MAKE) $(AM_MAKEFLAGS) -C $${dir} install || exit 1; \
  369. done
  370. .PHONY: python_scripts
  371. python_scripts:
  372. for dir in $(PYTHON_SCRIPT_SUBDIRS); do \
  373. $(MAKE) $(AM_MAKEFLAGS) -C $${dir} python_scripts_sub || exit 1; \
  374. done
  375. .PHONY:
  376. strip-po:
  377. $(MAKE) -C po strip-po
  378. .PHONY: cov-scan
  379. cov-scan:
  380. $(MAKE) clean
  381. @# analyse C code with workaround for missing _Float types
  382. @# https://stackoverflow.com/questions/50434236/coverity-scan-fails-to-build-stdlib-h-with-gnu-source-defined
  383. cov-build --dir cov-int $(MAKE) all \
  384. CFLAGS="-D_Float32=float -D_Float32x=double -D_Float64=double -D_Float64x='long double' -D_Float128='long double'"
  385. @# remove build directories and analyse Python
  386. rm -rf ipa*/build
  387. cov-build --dir cov-int --no-command \
  388. $(foreach d,$(PYTHON_SUBDIRS),--fs-capture-search $(d))
  389. @# analyze JS files
  390. cov-build --dir cov-int --no-command --fs-capture-search install/ui
  391. @# compress and upload
  392. tar czvf freeipa.tgz cov-int
  393. if [ -n "$${COVERITY_SCAN_TOKEN}" ]; then \
  394. curl --progress-bar --output /dev/null \
  395. --form token=$${COVERITY_SCAN_TOKEN} \
  396. --form email=scan@mg.freeipa.org \
  397. --form file=@freeipa.tgz \
  398. --form version="$(VERSION)" \
  399. --form description="FreeIPA" \
  400. "https://scan.coverity.com/builds?project=freeipa%2Ffreeipa"; \
  401. fi
  402. PYTHON_SHEBANG = \
  403. ipa \
  404. makeaci \
  405. makeapi \
  406. $(NULL)
  407. CLEANFILES = $(PYTHON_SHEBANG)
  408. include $(top_srcdir)/Makefile.pythonscripts.am