# Licensed under the Apache License, Version 2.0 (the "License"); you may not # use this file except in compliance with the License. You may obtain a copy of # the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations under # the License. # *************************************************** # WARNING! If you edit this file, also edit Makefile! # *************************************************** include version.mk SHELL=cmd.exe REBAR?=$(CURDIR)\bin\rebar.cmd PYTHON=python.exe ERLFMT?=$(CURDIR)\bin\erlfmt.cmd MAKE=make -f Makefile.win # REBAR?=$(shell where rebar.cmd) # Handle the following scenarios: # 1. When building from a tarball, use version.mk. # 2. When building from a clean release tag (#.#.#), use that tag. # 3. When building from a clean RC tag (#.#.#-RC#), use JUST the version # number inside the tarball, but use the full name for the name of the # tarball itself. # 4. When not on a clean tag, use version.mk + git sha + dirty status. COUCHDB_GIT_SHA=$(git_sha) IN_RELEASE = $(shell if not exist .git echo true) ifeq ($(IN_RELEASE), true) # 1. Building from tarball, use version.mk. COUCHDB_VERSION = $(vsn_major).$(vsn_minor).$(vsn_patch) else # Gather some additional information. # We do it this way so we don't bake shell-isms into Makefile # to make it easier to port to Windows. I know, I know. -jst # IN_RC contains the -RCx suffix in the name if present IN_RC = $(shell git describe --tags --always --first-parent \ | grep -Eo -- '-RC[0-9]+' 2>nul) # ON_TAG matches *ONLY* if we are on a release or RC tag ON_TAG = $(shell git describe --tags --always --first-parent \ | grep -Eo -- '^[0-9]+\.[0-9]\.[0-9]+(-RC[0-9]+)?$$' 2>nul) # REL_TAG contains the #.#.# from git describe, which might be used REL_TAG = $(shell git describe --tags --always --first-parent \ | grep -Eo -- '^[0-9]+\.[0-9]\.[0-9]+' 2>nul) # DIRTY identifies if we're not on a commit DIRTY = $(shell git describe --dirty | grep -Eo -- '-dirty' 2>nul) # COUCHDB_GIT_SHA is our current git hash. COUCHDB_GIT_SHA=$(shell git rev-parse --short=7 --verify HEAD) ifeq ($(ON_TAG),) # 4. Not on a tag. COUCHDB_VERSION_SUFFIX = $(COUCHDB_GIT_SHA)$(DIRTY) COUCHDB_VERSION = $(vsn_major).$(vsn_minor).$(vsn_patch)-$(COUCHDB_VERSION_SUFFIX) else # 2 and 3. On a tag. COUCHDB_VERSION = $(REL_TAG)$(DIRTY) endif endif # needed to do text substitutions comma:= , empty:= space:= $(empty) $(empty) DESTDIR= # Rebar options apps= skip_deps=folsom,meck,mochiweb,triq,proper,snappy,bcrypt,hyper,ibrowse,local suites= tests= # no sed on Windows (per default), but powershell COMPILE_OPTS=$(shell powershell -command "('apps=${apps} ') -replace '[a-z_]+= ', ' '") EUNIT_OPTS=$(shell powershell -command "('skip_deps=${skip_deps} suites=${suites} tests=${tests} ') -replace '[a-z]+= ', ' '") DIALYZE_OPTS=$(shell powershell -command "('apps=${apps} skip_deps=${skip_deps} ') -replace '[a-z]+= ', ' '") EXUNIT_OPTS=$(subst $(comma),$(space),$(tests)) TEST_OPTS=-c startup_jitter=0 -c default_security=admin_local ################################################################################ # Main commands ################################################################################ .PHONY: all # target: all - Build everything all: couch fauxton docs .PHONY: help # target: help - Print this help help: @powershell -Command 'Select-String Makefile.win -Pattern "^# target: (?.*) - (?.*)" | ForEach-Object { ("{0,-22} - {1}" -f $$_.Matches[0].Groups["name"], $$_.Matches[0].Groups["description"]) } | Sort' ################################################################################ # Building ################################################################################ .PHONY: couch # target: couch - Build CouchDB core, use ERL_COMPILER_OPTIONS to provide custom compiler's options couch: config.erl @set COUCHDB_VERSION=$(COUCHDB_VERSION) && set COUCHDB_GIT_SHA=$(COUCHDB_GIT_SHA) && $(REBAR) compile $(COMPILE_OPTS) @copy src\couch\priv\couchjs.exe bin .PHONY: docs # target: docs - Build documentation ifeq ($(IN_RELEASE), true) docs: share\docs\html else docs: src\docs\build endif .PHONY: fauxton # target: fauxton - Build Fauxton web UI fauxton: share\www ################################################################################ # Testing ################################################################################ .PHONY: check # target: check - Test everything check: all @$(MAKE) eunit @$(MAKE) mango-test @$(MAKE) elixir-suite ifdef apps subdirs = $(apps) else subdirs=$(shell dir /b src) endif .PHONY: eunit # target: eunit - Run EUnit tests, use EUNIT_OPTS to provide custom options eunit: export BUILDDIR = $(shell echo %cd%) eunit: export ERL_AFLAGS = -config $(shell echo "%cd%")/rel/files/eunit.config eunit: export COUCHDB_QUERY_SERVER_JAVASCRIPT = $(shell echo %cd%)/bin/couchjs $(shell echo %cd%)/share/server/main.js eunit: export COUCHDB_TEST_ADMIN_PARTY_OVERRIDE=1 eunit: couch @set COUCHDB_VERSION=$(COUCHDB_VERSION) && set COUCHDB_GIT_SHA=$(COUCHDB_GIT_SHA) && $(REBAR) setup_eunit 2> nul @cmd /c "FOR %d IN ($(subdirs)) DO set COUCHDB_VERSION=$(COUCHDB_VERSION) & set COUCHDB_GIT_SHA=$(COUCHDB_GIT_SHA) & $(REBAR) -r eunit $(EUNIT_OPTS) apps=%d || exit /b 1" .PHONY: exunit # target: exunit - Run ExUnit tests, use EXUNIT_OPTS to provide custom options exunit: export BUILDDIR = $(shell echo %cd%) exunit: export MIX_ENV=test exunit: export ERL_LIBS = $(shell echo %cd%)/src exunit: export ERL_AFLAGS = -config $(shell echo "%cd%")/rel/files/eunit.config exunit: export COUCHDB_QUERY_SERVER_JAVASCRIPT = $(shell echo %cd%)/bin/couchjs $(shell echo %cd%)/share/server/main.js exunit: couch elixir-init setup-eunit elixir-check-formatted elixir-credo @mix test --cover --trace $(EXUNIT_OPTS) setup-eunit: export BUILDDIR = $(shell echo %cd%) setup-eunit: export ERL_AFLAGS = -config $(shell echo "%cd%")/rel/files/eunit.config setup-eunit: @$(REBAR) setup_eunit 2> nul just-eunit: export BUILDDIR = $(shell echo %cd%) just-eunit: export ERL_AFLAGS = -config $(shell echo "%cd%")/rel/files/eunit.config just-eunit: @$(REBAR) -r eunit $(EUNIT_OPTS) # target: erlfmt-check - Check Erlang source code formatting erlfmt-check: export ERLFMT_PATH = $(ERLFMT) erlfmt-check: @$(PYTHON) dev\format_check.py # target: erlfmt-format - Apply Erlang source code format standards automatically erlfmt-format: export ERLFMT_PATH = $(ERLFMT) erlfmt-format: @$(PYTHON) dev\format_all.py .venv/bin/black: @$(PYTHON) -m venv .venv @.venv\Scripts\pip3.exe install black==23.3.0 || copy /b .venv\Scripts\black.exe +,, # target: python-black - Check Python code formatting (requires Python >= 3.6) python-black: .venv/bin/black @$(PYTHON) -c "import sys; exit(1 if sys.version_info < (3,6) else 0)" || \ echo 'Python formatter not supported on Python < 3.6; check results on a newer platform' @$(PYTHON) -c "import sys; exit(1 if sys.version_info >= (3,6) else 0)" || \ .venv\Scripts\black.exe --check \ --exclude="build/|buck-out/|dist/|_build/|\.git/|\.hg/|\.mypy_cache/|\.nox/|\.tox/|\.venv/|src/erlfmt|src/rebar/pr2relnotes.py|src/fauxton" \ build-aux dev\run dev\format_*.py src\mango\test src\docs\src\conf.py src\docs\ext . # target: python-black-update - Apply Python source code format standards automatically (requires Python >= 3.6) python-black-update: .venv/bin/black @$(PYTHON) -c "import sys; exit(1 if sys.version_info < (3,6) else 0)" || \ echo 'Python formatter not supported on Python < 3.6; check results on a newer platform' @$(PYTHON) -c "import sys; exit(1 if sys.version_info >= (3,6) else 0)" || \ .venv\Scripts\black.exe \ --exclude="build/|buck-out/|dist/|_build/|\.git/|\.hg/|\.mypy_cache/|\.nox/|\.tox/|\.venv/|src/erlfmt|src/rebar/pr2relnotes.py|src/fauxton" \ build-aux dev\run dev\format_*.py src\mango\test src\docs\src\conf.py src\docs\ext . .PHONY: elixir elixir: export MIX_ENV=integration elixir: export COUCHDB_TEST_ADMIN_PARTY_OVERRIDE=1 elixir: elixir-init elixir-check-formatted elixir-credo devclean @dev\run $(TEST_OPTS) -a adm:pass -n 1 --enable-erlang-views \ --locald-config test/elixir/test/config/test-config.ini \ --no-eval 'mix test --trace --exclude without_quorum_test --exclude with_quorum_test $(EXUNIT_OPTS)' .PHONY: elixir-init elixir-init: MIX_ENV=test elixir-init: config.erl @mix local.rebar --force && mix local.hex --force && mix deps.get .PHONY: elixir-cluster-without-quorum elixir-cluster-without-quorum: export MIX_ENV=integration elixir-cluster-without-quorum: elixir-init elixir-check-formatted elixir-credo devclean @dev\run -n 3 -q -a adm:pass \ --degrade-cluster 2 \ --no-eval 'mix test --trace --only without_quorum_test $(EXUNIT_OPTS)' .PHONY: elixir-cluster-with-quorum elixir-cluster-with-quorum: export MIX_ENV=integration elixir-cluster-with-quorum: elixir-init elixir-check-formatted elixir-credo devclean @dev\run -n 3 -q -a adm:pass \ --degrade-cluster 1 \ --no-eval 'mix test --trace --only with_quorum_test $(EXUNIT_OPTS)' .PHONY: elixir-suite # target: elixir-suite - Run Elixir-based integration tests elixir-suite: export MIX_ENV=integration elixir-suite: export COUCHDB_TEST_ADMIN_PARTY_OVERRIDE=1 elixir-suite: elixir-init devclean @dev\run -n 1 -q -a adm:pass \ --enable-erlang-views \ --no-join \ --locald-config test/elixir/test/config/test-config.ini \ --erlang-config rel/files/eunit.config \ --no-eval 'mix test --trace --include test\elixir\test\config\suite.elixir --exclude test\elixir\test\config\skip.elixir' .PHONY: elixir-search # target: elixir-search - Run search tests, requires a running Clouseau instance elixir-search: export MIX_ENV=integration elixir-search: elixir-init devclean @dev\run -n 1 -q -a adm:pass \ --locald-config test/config/test-config.ini \ --no-eval 'mix test --trace --include test/elixir/test/config/search.elixir' .PHONY: elixir-source-checks # target: elixir-source-checks - Check source code formatting of Elixir test files elixir-source-checks: export MIX_ENV=integration elixir-source-checks: elixir-init @mix format --check-formatted @mix credo .PHONY: build-report # target: build-report - Generate a build report build-report: @$(PYTHON) build-aux/show-test-results.py --suites=10 --tests=10 > test-results.log .PHONY: check-qs # target: check-qs - Run query server tests (ruby and rspec required!) check-qs: @QS_LANG=js rspec test\view_server\query_server_spec.rb .PHONY: list-eunit-apps # target: list-eunit-apps - List EUnit target apps list-eunit-apps: @powershell -Command 'Get-ChildItem -Path src -Recurse -Filter "*_tests?.erl" | Resolve-Path -Relative | ForEach-Object { $$_.Split("\") | Select -Skip 2 -First 1 } | Sort -Unique' .PHONY: list-eunit-suites # target: list-eunit-suites - List EUnit target test suites list-eunit-suites: @powershell -Command 'Get-ChildItem -Path src -Recurse -Filter "*_tests?.erl" | ForEach-Object { "{0}" -f $$_.BaseName } | Sort' .PHONY: mango-test # target: mango-test - Run Mango tests mango-test: export COUCHDB_TEST_ADMIN_PARTY_OVERRIDE=1 mango-test: devclean all @cd src\mango && \ python.exe -m venv .venv && \ .venv\Scripts\pip.exe install -r requirements.txt @cd src\mango && \ ..\..\dev\run $(TEST_OPTS) \ -n 1 \ --admin=adm:pass \ "env COUCH_USER=adm COUCH_PASS=pass .venv\Scripts\nose2 $(MANGO_TEST_OPTS)" ################################################################################ # Developing ################################################################################ .PHONY: build-plt # target: build-plt - Build project-specific PLT build-plt: @$(REBAR) -r build-plt $(DIALYZE_OPTS) .PHONY: check-plt # target: check-plt - Check the PLT for consistency and rebuild it if it is not up-to-date check-plt: @$(REBAR) -r check-plt $(DIALYZE_OPTS) .PHONY: dialyze # target: dialyze - Analyze the code for discrepancies dialyze: .rebar @$(REBAR) -r dialyze $(DIALYZE_OPTS) .PHONY: find_bugs # target: find_bugs - Find unused exports etc find_bugs: @$(REBAR) --keep-going --recursive xref $(DIALYZE_OPTS) .PHONY: introspect # target: introspect - Check for commits difference between rebar.config and repository introspect: @$(REBAR) -r update-deps @escript build-aux\introspect ################################################################################ # Distributing ################################################################################ .PHONY: dist # target: dist - Make release tarball dist: all derived @.\build-aux\couchdb-build-release.sh $(COUCHDB_VERSION) @copy -r share\www apache-couchdb-$(COUCHDB_VERSION)\share @mkdir apache-couchdb-$(COUCHDB_VERSION)\share\docs\html @copy -r src\docs\build\html apache-couchdb-$(COUCHDB_VERSION)\share\docs @mkdir apache-couchdb-$(COUCHDB_VERSION)\share\docs\man @copy src\docs\build\man\apachecouchdb.1 apache-couchdb-$(COUCHDB_VERSION)\share\docs\man @tar czf apache-couchdb-$(COUCHDB_VERSION).tar.gz apache-couchdb-$(COUCHDB_VERSION) @echo 'Done: apache-couchdb-$(COUCHDB_VERSION).tar.gz' .PHONY: release # target: release - Create an Erlang release including CouchDB! -include install.mk release: all @echo 'Installing CouchDB into rel\couchdb\ ...' -@rmdir /s/q rel\couchdb @$(REBAR) generate @copy src\couch\priv\couchjs.exe rel\couchdb\bin ifeq ($(with_fauxton), 1) -@mkdir rel\couchdb\share -@xcopy share\www rel\couchdb\share\www /E/I endif ifeq ($(with_docs), 1) -@mkdir rel\couchdb\share\www\docs -@mkdir rel\couchdb\share\docs ifeq ($(IN_RELEASE), true) @xcopy share\docs\html rel\couchdb\share\www\docs /E /I @copy share\docs\man\apachecouchdb.1 rel\couchdb\share\docs\couchdb.1 else @xcopy src\docs\build\html rel\couchdb\share\www\docs /E /I @copy src\docs\build\man\apachecouchdb.1 rel\couchdb\share\docs\couchdb.1 endif endif @echo ... done @echo . @echo You can now copy the rel\couchdb directory anywhere on your system. @echo Start CouchDB with .\bin\couchdb.cmd from within that directory. @echo . .PHONY: install # target: install - Install CouchDB :) install: release @echo . @echo Notice: There is no 'make install' command for CouchDB 2.x+. @echo . @echo To install CouchDB into your system, copy the rel\couchdb @echo to your desired installation location. For example: @echo xcopy /E rel\couchdb C:\CouchDB\ @echo . ################################################################################ # Cleaning ################################################################################ .PHONY: clean # target: clean - Remove build artifacts clean: @$(REBAR) -r clean -@rmdir /s/q .rebar -@del /f/q bin\couchjs.exe -@rmdir /s/q src\*\ebin -@rmdir /s/q src\*\.rebar -@del /f/q/s src\*.dll -@del /f/q src\couch\priv\*.exe -@del /f/q share\server\main.js share\server\main-ast-bypass.js share\server\main-coffee.js -@rmdir /s/q tmp -@rmdir /s/q dev\data -@rmdir /s/q dev\lib -@rmdir /s/q dev\logs -@rmdir /s/q src\mango\.venv -@del /f/q src\couch\priv\couch_js\config.h -@del /f/q dev\boot_node.beam dev\pbkdf2.pyc log\crash.log .PHONY: distclean # target: distclean - Remove build and release artifacts distclean: clean -@del install.mk -@del config.erl -@del rel\couchdb.config ifneq ($(IN_RELEASE), true) # when we are in a release, don’t delete the # copied sources, generated docs, or fauxton -@rmdir /s/q rel\couchdb -@rmdir /s/q share\www -@rmdir /s/q src\docs endif .PHONY: devclean # target: devclean - Remove dev cluster artifacts devclean: -@rmdir /s/q dev\lib\node1\data -@rmdir /s/q dev\lib\node2\data -@rmdir /s/q dev\lib\node3\data -@rmdir /s/q dev\lib\node1\etc -@rmdir /s/q dev\lib\node2\etc -@rmdir /s/q dev\lib\node3\etc ################################################################################ # Misc ################################################################################ .rebar: build-plt config.erl: @echo Apache CouchDB has not been configured. @echo Try "powershell -ExecutionPolicy Bypass .\configure.ps1 -?" for help. @echo You probably want "powershell -ExecutionPolicy Bypass .\configure.ps1". @echo. @false src\docs\build: @echo 'Building docs...' ifeq ($(with_docs), 1) @cd src\docs && make.bat html && make.bat man endif share\www: ifeq ($(with_fauxton), 1) @echo 'Building Fauxton' @cd src\fauxton && npm install && .\node_modules\.bin\grunt couchdb endif derived: @echo "COUCHDB_GIT_SHA: $(COUCHDB_GIT_SHA)" @echo "COUCHDB_VERSION: $(COUCHDB_VERSION)" @echo "COUCHDB_VERSION_SUFFIX: $(COUCHDB_VERSION_SUFFIX)" @echo "DIRTY: $(DIRTY)" @echo "IN_RC: $(IN_RC)" @echo "IN_RELEASE: $(IN_RELEASE)" @echo "ON_TAG: $(ON_TAG)" @echo "REL_TAG: $(REL_TAG)" @echo "SUB_VSN: $(SUB_VSN)"