From e310677df7b3ce6506b35044abafcb507caa7e07 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Mon, 10 Mar 2014 17:44:25 +0100 Subject: Verify runtime_dependencies when running 'otp_build patch_app' --- Makefile.in | 8 +- erts/Makefile.in | 5 + erts/doc/src/erlang.xml | 4 +- erts/etc/win32/nsis/erlang.nsi | 1 - erts/etc/win32/nsis/erlang20.nsi | 1 - lib/kernel/doc/src/app.xml | 21 +- make/otp_released_app.mk | 43 ++++ make/otp_subdir.mk | 9 + make/verify_runtime_dependencies | 313 ++++++++++++++++++++++++++ otp_build | 74 +++--- otp_versions.table | 0 system/doc/installation_guide/otp_version.xml | 96 -------- system/doc/installation_guide/part.xml | 1 - system/doc/installation_guide/xmlfiles.mk | 1 - system/doc/system_principles/part.xml | 1 + system/doc/system_principles/versions.xml | 267 ++++++++++++++++++++++ system/doc/system_principles/xmlfiles.mk | 3 +- 17 files changed, 706 insertions(+), 142 deletions(-) create mode 100644 make/otp_released_app.mk create mode 100755 make/verify_runtime_dependencies create mode 100644 otp_versions.table delete mode 100644 system/doc/installation_guide/otp_version.xml create mode 100644 system/doc/system_principles/versions.xml diff --git a/Makefile.in b/Makefile.in index bfaf749465..c667eb5f79 100644 --- a/Makefile.in +++ b/Makefile.in @@ -397,9 +397,9 @@ endif ERL_TOP=$(ERL_TOP) PATH=$(INST_PATH_PREFIX)"$${PATH}" \ $(MAKE) BUILD_ALL=1 TESTROOT="$(RELEASE_ROOT)" release ifeq ($(RELEASE_ROOT),) - $(INSTALL_DATA) "$(ERL_TOP)/OTP_VERSION" "$(OTP_DEFAULT_RELEASE_PATH)" + $(INSTALL_DATA) "$(ERL_TOP)/OTP_VERSION" "$(OTP_DEFAULT_RELEASE_PATH)/releases/@OTP_REL@" else - $(INSTALL_DATA) "$(ERL_TOP)/OTP_VERSION" "$(RELEASE_ROOT)" + $(INSTALL_DATA) "$(ERL_TOP)/OTP_VERSION" "$(RELEASE_ROOT)/releases/@OTP_REL@" endif # --------------------------------------------------------------- @@ -1038,9 +1038,9 @@ install.Install: install.otp_version: ifeq ($(ERLANG_LIBDIR),) - $(INSTALL_DATA) "$(ERL_TOP)/OTP_VERSION" "$(OTP_DEFAULT_RELEASE_PATH)" + $(INSTALL_DATA) "$(ERL_TOP)/OTP_VERSION" "$(OTP_DEFAULT_RELEASE_PATH)/releases/@OTP_REL@" else - $(INSTALL_DATA) "$(ERL_TOP)/OTP_VERSION" "$(ERLANG_LIBDIR)" + $(INSTALL_DATA) "$(ERL_TOP)/OTP_VERSION" "$(ERLANG_LIBDIR)/releases/@OTP_REL@" endif # diff --git a/erts/Makefile.in b/erts/Makefile.in index e3db37d3fd..47298cccba 100644 --- a/erts/Makefile.in +++ b/erts/Makefile.in @@ -48,6 +48,7 @@ debug opt clean: ( cd $$d && $(MAKE) $@ FLAVOR=$(FLAVOR) ) || exit $$? ; \ fi ; \ done + (cd preloaded/src && $(MAKE) ../ebin/erts.app) # ---------------------------------------------------------------------- # These are "convenience targets", provided as shortcuts for developers @@ -135,6 +136,10 @@ release: ( cd $$d && $(MAKE) $@ ) || exit $$? ; \ fi ; \ done + ( $(MAKE) -f "$(ERL_TOP)/make/otp_released_app.mk" \ + APP_PWD="$(ERL_TOP)/erts" APP_VSN=VSN APP=erts \ + TESTROOT="$(TESTROOT)" update) \ + || exit $$? .PHONY: release_docs release_docs: diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index aeded7c719..b06d5aeb12 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -6121,8 +6121,8 @@ ok erlang:system_info() argument giving the exact OTP version. This since the exact OTP version in the general case is hard to determine. For more information see - the - documentation of the OTP version in the installation + the + documentation of versions in the system principles guide.

port_parallelism diff --git a/erts/etc/win32/nsis/erlang.nsi b/erts/etc/win32/nsis/erlang.nsi index 162e634148..f4fd2b4cdb 100644 --- a/erts/etc/win32/nsis/erlang.nsi +++ b/erts/etc/win32/nsis/erlang.nsi @@ -93,7 +93,6 @@ SectionIn 1 RO skip_silent_mode: SetOutPath "$INSTDIR" - File "${TESTROOT}\OTP_VERSION" File "${TESTROOT}\Install.ini" File "${TESTROOT}\Install.exe" File /r "${TESTROOT}\releases" diff --git a/erts/etc/win32/nsis/erlang20.nsi b/erts/etc/win32/nsis/erlang20.nsi index 3ee33e8121..3333c4a9aa 100644 --- a/erts/etc/win32/nsis/erlang20.nsi +++ b/erts/etc/win32/nsis/erlang20.nsi @@ -144,7 +144,6 @@ Section "Development" SecErlangDev SectionIn 1 RO SetOutPath "$INSTDIR" - File "${TESTROOT}\OTP_VERSION" File "${TESTROOT}\Install.ini" File "${TESTROOT}\Install.exe" SetOutPath "$INSTDIR\releases" diff --git a/lib/kernel/doc/src/app.xml b/lib/kernel/doc/src/app.xml index 8f968cc988..b24a2bd7bd 100644 --- a/lib/kernel/doc/src/app.xml +++ b/lib/kernel/doc/src/app.xml @@ -90,6 +90,8 @@ RTDeps [ApplicationVersion] [] description, vsn, modules, registered and applications. The other keys are ignored by systools.

+

The RTDeps type was introduced in OTP 17.0 and + might be subject to changes during the OTP 17 release.

description @@ -188,10 +190,10 @@ RTDeps [ApplicationVersion] [] start phases must be a subset of the set of phases defined for the primary application. Refer to OTP Design Principles for more information.

- runtime_dependencies - A list of application versions that the application + runtime_dependencies +

A list of application versions that the application depends on. An example of such an application version is - "kernel-3.0". Application versions specified as runtime + "kernel-3.0". Application versions specified as runtime dependencies are minimum requirements. That is, a larger application version than the one specified in the dependency satisfies the requirement. For information on @@ -202,7 +204,18 @@ RTDeps [ApplicationVersion] [] specifies a source code version. An additional indirect requirement is that installed binary application of the specified version has been built so that it is - compatible with the rest of the system. + compatible with the rest of the system.

+

Some dependencies might only be required in specific runtime + scenarios. In the case such optional dependencies exist, these are + specified and documented in the corresponding "App" documentation + of the specific application.

+

The runtime_dependencies key was introduced in + OTP 17.0. The type of its value might be subject to changes during + the OTP 17 release.

+

All runtime dependencies specified in OTP applications + during the OTP 17 release might not be completely correct. This + is actively worked on. Declared runtime dependencies in OTP + applications are expected to be correct in OTP 18.

diff --git a/make/otp_released_app.mk b/make/otp_released_app.mk new file mode 100644 index 0000000000..fb5205ab23 --- /dev/null +++ b/make/otp_released_app.mk @@ -0,0 +1,43 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2014. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% + +include $(ERL_TOP)/make/target.mk +include $(ERL_TOP)/make/$(TARGET)/otp.mk +include $(APP_PWD)/vsn.mk +include $(ERL_TOP)/make/otp_default_release_path.mk + +RELEASED_APP_VSN=$(APP)-$($(APP_VSN)) +ifeq ($(TESTROOT),) +REL_DIR=$(OTP_DEFAULT_RELEASE_PATH)/releases/$(SYSTEM_VSN) +else +REL_DIR=$(TESTROOT)/releases/$(SYSTEM_VSN) +endif +INST_APP_VSNS=$(REL_DIR)/installed_application_versions + +.PHONY: update + +update: + test -d "$(REL_DIR)" || mkdir -p "$(REL_DIR)" ; \ + if test ! -f "$(INST_APP_VSNS)" ; then \ + echo "$(RELEASED_APP_VSN)" > "$(INST_APP_VSNS)" || exit 1; \ + else \ + if test x = x`grep $(RELEASED_APP_VSN) "$(INST_APP_VSNS)"` ; then \ + echo $(RELEASED_APP_VSN) >> "$(INST_APP_VSNS)" || exit 1; \ + fi ; \ + fi + diff --git a/make/otp_subdir.mk b/make/otp_subdir.mk index f31ab05c87..e6a75cce17 100644 --- a/make/otp_subdir.mk +++ b/make/otp_subdir.mk @@ -44,5 +44,14 @@ opt debug release docs release_docs tests release_tests clean depend valgrind st fi ; \ done ; \ if test -f vsn.mk; then \ + if test release = $@ && test ! -f SKIP; then \ + app=`basename $$app_pwd` ; \ + app_vsn=`echo $$app | sed "y|abcdefghijklmnopqrstuvwxyz|ABCDEFGHIJKLMNOPQRSTUVWXYZ|"` ; \ + app_vsn=$${app_vsn}_VSN ; \ + ( $(MAKE) -f "$(ERL_TOP)/make/otp_released_app.mk" \ + APP_PWD="$$app_pwd" APP_VSN=$$app_vsn APP=$$app \ + TESTROOT="$(TESTROOT)" update) \ + || exit $$? ; \ + fi ; \ echo "=== Leaving application" `basename $$app_pwd` ; \ fi diff --git a/make/verify_runtime_dependencies b/make/verify_runtime_dependencies new file mode 100755 index 0000000000..b8eea06b6e --- /dev/null +++ b/make/verify_runtime_dependencies @@ -0,0 +1,313 @@ +#!/usr/bin/env escript +%% -*- erlang -*- + +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2014. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%%------------------------------------------------------------------- +%%% @author Rickard Green +%%% @copyright (C) 2014, Rickard Green +%%% @doc +%%% Verify runtime dependencies when patching OTP applications. +%%% @end +%%% Created : 4 Mar 2014 by Rickard Green +%%%------------------------------------------------------------------- + +-mode(compile). + +-export([main/1]). + +main(Args) -> + {Force, Release, SourceDir, TargetDir, AppList} = parse_args(Args, + false, + [], + [], + [], + []), + SourceAppInfo = read_source_app_info(AppList, SourceDir), + AppVsnsTab0 = current_target_app_vsns(TargetDir, Release), + AppVsnsTab1 = add_source_app_vsns(SourceAppInfo, AppVsnsTab0), + case verify_runtime_deps(SourceAppInfo, AppVsnsTab1, true) of + true -> + ok; + false -> + case Force of + true -> + warn("Your OTP development system was updated with " + "unfulfilled runtime dependencies. The system " + "may not be working as expected.", []); + false -> + err("Unfulfilled runtime dependencies. " + "See warnings above.~n", []) + end + end, + halt(0). + +parse_args(["-force" | Args], _, Release, SourceDir, TargetDir, Apps) -> + parse_args(Args, true, Release, SourceDir, TargetDir, Apps); +parse_args(["-release", Release | Args], Force, _, SourceDir, TargetDir, Apps) -> + parse_args(Args, Force, Release, SourceDir, TargetDir, Apps); +parse_args(["-source", SourceDir | Args], Force, Release, _, TargetDir, Apps) -> + parse_args(Args, Force, Release, SourceDir, TargetDir, Apps); +parse_args(["-target", TargetDir | Args], Force, Release, SourceDir, _, Apps) -> + parse_args(Args, Force, Release, SourceDir, TargetDir, Apps); +parse_args([App | Args], Force, Release, SourceDir, TargetDir, OldApps) -> + parse_args(Args, Force, Release, SourceDir, TargetDir, [App | OldApps]); +parse_args([], _, [], _, _, _) -> + err("Missing release~n", []); +parse_args([], _, _, [], _, _) -> + err("Missing source directory~n", []); +parse_args([], _, _, _, [], _) -> + err("Missing target directory~n", []); +parse_args([], _, _, _, _, []) -> + err("Missing applications~n"); +parse_args([], Force, Release, SourceDir, TargetDir, Apps) -> + {Force, Release, SourceDir, TargetDir, Apps}. + + +%warn(Format) -> +% warn(Format, []). + +warn(Format, Args) -> + io:format(standard_error, "WARNING: " ++ Format, Args). + +err(Format) -> + err(Format, []). + +err(Format, Args) -> + io:format(standard_error, "ERROR: " ++ Format, Args), + halt(1). + +read_file(FileName) -> + case file:read_file(FileName) of + {ok, Content} -> + binary_to_list(Content); + {error, Error} -> + err("Failed to read ~s: ~p~n", [FileName, Error]) + end. + +consult_file(FileName) -> + case file:consult(FileName) of + {ok, Terms} -> + Terms; + {error, Error} -> + err("Failed to consult ~s: ~p~n", [FileName, Error]) + end. + +current_target_app_vsns(TargetDir, Release) -> + IAV = read_file(filename:join([TargetDir, "releases", Release, + "installed_application_versions"])), + DirList = string:tokens(IAV, "\n\r\t "), + LibDir = filename:join(TargetDir, "lib"), + make_app_vsns_tab(DirList, LibDir, gb_trees:empty()). + +make_app_vsns_tab([], _LibDir, GBT) -> + GBT; +make_app_vsns_tab([AppVer | AppVsns], LibDir, GBT0) -> + GBT1 = try + case file:read_file_info(filename:join(LibDir, AppVer)) of + {ok, _FInfo} -> + [App, Vsn] = string:tokens(AppVer, "-"), + add_app_vsn(App, Vsn, GBT0); + _ -> + GBT0 + end + catch + _:_ -> + warn("Unexpected directory: ~p~n", + [filename:join(LibDir, AppVer)]), + GBT0 + end, + make_app_vsns_tab(AppVsns, LibDir, GBT1). + +add_app_vsn(App, VsnList, GBT) when is_atom(App) -> + Vsn = parse_vsn(VsnList), + case gb_trees:lookup(App, GBT) of + none -> + gb_trees:insert(App, [Vsn], GBT); + {value, Vsns} -> + gb_trees:update(App, [Vsn | Vsns], GBT) + end; +add_app_vsn(AppStr, VsnList, GBT) -> + add_app_vsn(list_to_atom(AppStr), VsnList, GBT). + +add_source_app_vsns([], AppVsnsTab) -> + AppVsnsTab; +add_source_app_vsns([{App, Vsn, _IReqs} | AI], AppVsnsTab) -> + add_source_app_vsns(AI, add_app_vsn(App, Vsn, AppVsnsTab)). + +read_source_app_info([], _SourceDir) -> + []; +read_source_app_info([App | Apps], SourceDir) -> + AppFile = case App of + "erts" -> + filename:join([SourceDir, "erts", "preloaded", "ebin", + "erts.app"]); + _ -> + filename:join([SourceDir, "lib", App, "ebin", + App ++ ".app"]) + end, + AppAtom = list_to_atom(App), + case consult_file(AppFile) of + [{application, AppAtom, InfoList}] -> + Vsn = case lists:keyfind(vsn, 1, InfoList) of + {vsn, V} -> + V; + _ -> + err("Missing vsn in ~p~n", AppFile) + end, + AI = case lists:keyfind(runtime_dependencies, 1, InfoList) of + {runtime_dependencies, IReqs} -> + case parse_inst_reqs(IReqs) of + error -> + err("Failed to parse runtime_dependencies in ~p~n", + [AppFile]); + ParsedIReqs -> + {AppAtom, Vsn, ParsedIReqs} + end; + _ -> + {AppAtom, Vsn, []} + end, + [AI | read_source_app_info(Apps, SourceDir)]; + _ -> + err("Failed to parse ~p~n", [AppFile]) + end. + +parse_vsn(VsnStr) -> + list_to_tuple(lists:map(fun (IL) -> + list_to_integer(IL) + end, string:tokens(VsnStr, "."))). + +parse_inst_reqs(InstReqs) -> + try + parse_inst_reqs_aux(InstReqs) + catch + _ : _ -> + error + end. + +parse_inst_reqs_aux([]) -> + []; +parse_inst_reqs_aux([IR | IRs]) -> + [App, VsnStr] = string:tokens(IR, "-"), + [{list_to_atom(App), parse_vsn(VsnStr)} | parse_inst_reqs_aux(IRs)]. + +make_app_vsn_str({App, VsnTup}) -> + make_app_vsn_str(tuple_to_list(VsnTup), [atom_to_list(App), $-]). + +make_app_vsn_str([I], Acc) -> + lists:flatten([Acc, integer_to_list(I)]); +make_app_vsn_str([I | Is], Acc) -> + make_app_vsn_str(Is, [Acc, integer_to_list(I), $.]). + +missing_min_req(App, AppVsn, IReq) -> + warn("Unfulfilled runtime dependency for application ~p-~s: ~s~n", + [App, AppVsn, make_app_vsn_str(IReq)]). + +verify_runtime_deps([], _AppVsnsTab, Res) -> + Res; +verify_runtime_deps([{App, Vsn, IReqs} | SAIs], AppVsnsTab, Res0) -> + Res = lists:foldl( + fun ({IRApp, IRMinVsn} = InstReq, AccRes) -> + case gb_trees:lookup(IRApp, AppVsnsTab) of + none -> + missing_min_req(App, Vsn, InstReq), + false; + {value, AppVsns} -> + try + lists:foreach( + fun (AppVsn) -> + case meets_min_req(AppVsn, IRMinVsn) of + true -> + throw(true); + false -> + false + end + end, + AppVsns), + missing_min_req(App, Vsn, InstReq), + false + catch + throw : true -> + AccRes + end + end + end, + Res0, + IReqs), + verify_runtime_deps(SAIs, AppVsnsTab, Res). + +meets_min_req(Vsn, Vsn) -> + true; +meets_min_req({X}, VsnReq) -> + meets_min_req({X, 0, 0}, VsnReq); +meets_min_req({X, Y}, VsnReq) -> + meets_min_req({X, Y, 0}, VsnReq); +meets_min_req(Vsn, {X}) -> + meets_min_req(Vsn, {X, 0, 0}); +meets_min_req(Vsn, {X, Y}) -> + meets_min_req(Vsn, {X, Y, 0}); +meets_min_req({X, _Y, _Z}, {XReq, _YReq, _ZReq}) when X > XReq -> + true; +meets_min_req({X, Y, _Z}, {X, YReq, _ZReq}) when Y > YReq -> + true; +meets_min_req({X, Y, Z}, {X, Y, ZReq}) when Z > ZReq -> + true; +meets_min_req({_X, _Y, _Z}, {_XReq, _YReq, _ZReq}) -> + false; +meets_min_req(Vsn, VsnReq) -> + gp_meets_min_req(mk_gp_vsn_list(Vsn), mk_gp_vsn_list(VsnReq)). + +gp_meets_min_req([X, Y, Z | _Vs], [X, Y, Z]) -> + true; +gp_meets_min_req([X, Y, Z | _Vs], [XReq, YReq, ZReq]) -> + meets_min_req({X, Y, Z}, {XReq, YReq, ZReq}); +gp_meets_min_req([X, Y, Z | Vs], [X, Y, Z | VReqs]) -> + gp_meets_min_req_tail(Vs, VReqs); +gp_meets_min_req(_Vsn, _VReq) -> + %% Versions on different version branches, i.e., the minimum + %% required functionality is not included in Vsn. + false. + +gp_meets_min_req_tail([V | Vs], [V | VReqs]) -> + gp_meets_min_req_tail(Vs, VReqs); +gp_meets_min_req_tail([], []) -> + true; +gp_meets_min_req_tail([_V | _Vs], []) -> + true; +gp_meets_min_req_tail([V | _Vs], [VReq]) when V > VReq -> + true; +gp_meets_min_req_tail(_Vs, _VReqs) -> + %% Versions on different version branches, i.e., the minimum + %% required functionality is not included in Vsn. + false. + +mk_gp_vsn_list(Vsn) -> + [X, Y, Z | Tail] = tuple_to_list(Vsn), + [X, Y, Z | remove_trailing_zeroes(Tail)]. + +remove_trailing_zeroes([]) -> + []; +remove_trailing_zeroes([0 | Vs]) -> + case remove_trailing_zeroes(Vs) of + [] -> []; + NewVs -> [0 | NewVs] + end; +remove_trailing_zeroes([V | Vs]) -> + [V | remove_trailing_zeroes(Vs)]. diff --git a/otp_build b/otp_build index 6e016c88d2..b629bf54d4 100755 --- a/otp_build +++ b/otp_build @@ -52,7 +52,7 @@ usage () echo " release [-a] - creates full release to " echo " smp [-a] - build an Erlang system, smp flavor only" echo " tests - Build testsuites to " - echo " patch_app ... - build given apps to " + echo " patch_app [-f] ... - build given apps to " echo " If core apps are patched, new start scripts will be created" echo " and 'Install' must be run again." echo "" @@ -1209,25 +1209,37 @@ do_patch_app () if [ X`$MAKE is_cross_configured` = Xyes ]; then TARGET=`$MAKE target_configured` fi + if [ "x$1" = "x-f" ]; then + force="-force" + shift + else + force= + fi target_dir=$1 - if [ ! -d $target_dir/releases/$otp_major_vsn ]; then + if [ ! -d "$target_dir/releases/$otp_major_vsn" ]; then echo "No OTP $otp_major_vsn installation in $target_dir" 1>&2 exit 1 fi shift - otp_version=`cat "$target_dir/OTP_VERSION"` || { echo "Not able to read $target_dir/OTP_VERSION" 1>&2; exit 1; } - { echo "$otp_version" | sed "s|^\([^\*]*\)\**|\1\*\*|g" > $target_dir/OTP_VERSION; } 2>/dev/null || { echo "Not able to update $target_dir/OTP_VERSION" 1>&2; exit 1; } + otp_version=`cat "$target_dir/releases/$otp_major_vsn/OTP_VERSION"` || { echo "Not able to read $target_dir/releases/$otp_major_vsn/OTP_VERSION" 1>&2; exit 1; } + { echo "$otp_version" | sed "s|^\([^\*]*\)\**|\1\*\*|g" > "$target_dir/releases/$otp_major_vsn/OTP_VERSION"; } 2>/dev/null || { echo "Not able to update $target_dir/OTP_VERSION" 1>&2; exit 1; } + + PATH="$ERL_TOP/bootstrap/bin:$PATH" $ERL_TOP/make/verify_runtime_dependencies -release "$otp_major_vsn" -source "$ERL_TOP" -target "$target_dir" $force "$@" + + if [ $? -ne 0 ]; then + exit $? + fi # Build all applications to target for app in "$@"; do if [ "$app" = "erts" ] && [ -d $ERL_TOP/$app ]; then (cd $ERL_TOP/$app && $MAKE MAKE="$MAKE" TARGET=$TARGET \ - TESTROOT=$target_dir release) || exit 1 + TESTROOT="$target_dir" release) || exit 1 elif [ "$app" != "erts" ] && [ -d $ERL_TOP/lib/$app ]; then (cd $ERL_TOP/lib/$app && $MAKE MAKE="$MAKE" TARGET=$TARGET \ - TESTROOT=$target_dir release) || exit 1 + TESTROOT="$target_dir" release) || exit 1 else echo "Invalid application $app" 1>&2 exit 1 @@ -1254,19 +1266,19 @@ do_patch_app () # and find the old versions for those not included if [ "X$update_rel" != "X" ]; then if [ "X$erts_vsn" = "X" ]; then - erts_vsns=`ls -d $target_dir/erts-* | sed "s|$target_dir/erts-\([0-9\.].*\)|\1|g"` + erts_vsns=`ls -d "$target_dir"/erts-* | sed "s|$target_dir/erts-\([0-9\.].*\)|\1|g"` erts_vsn=`echo "$erts_vsns" | sort -t '.' -g | tail -n 1` fi if [ "X$kernel_vsn" = "X" ]; then - kernel_vsns=`ls -d $target_dir/lib/kernel-* | sed "s|$target_dir/lib/kernel-\([0-9\.].*\)|\1|g"` + kernel_vsns=`ls -d "$target_dir"/lib/kernel-* | sed "s|$target_dir/lib/kernel-\([0-9\.].*\)|\1|g"` kernel_vsn=`echo "$kernel_vsns" | sort -t '.' -g | tail -n 1` fi if [ "X$stdlib_vsn" = "X" ]; then - stdlib_vsns=`ls -d $target_dir/lib/stdlib-* | sed "s|$target_dir/lib/stdlib-\([0-9\.].*\)|\1|g"` + stdlib_vsns=`ls -d "$target_dir"/lib/stdlib-* | sed "s|$target_dir/lib/stdlib-\([0-9\.].*\)|\1|g"` stdlib_vsn=`echo "$stdlib_vsns" | sort -t '.' -g | tail -n 1` fi if [ "X$sasl_vsn" = "X" ]; then - sasl_vsns=`ls -d $target_dir/lib/sasl-* | sed "s|$target_dir/lib/sasl-\([0-9\.].*\)|\1|g"` + sasl_vsns=`ls -d "$target_dir"/lib/sasl-* | sed "s|$target_dir/lib/sasl-\([0-9\.].*\)|\1|g"` sasl_vsn=`echo "$sasl_vsns" | sort -t '.' -g | tail -n 1` fi @@ -1274,42 +1286,42 @@ do_patch_app () start_clean="{release, {\"OTP APN 181 01\",\"$otp_major_vsn\"}, {erts, \"$erts_vsn\"},\n [{kernel,\"$kernel_vsn\"},\n {stdlib,\"$stdlib_vsn\"}]}.\n" start_sasl="{release, {\"OTP APN 181 01\",\"$otp_major_vsn\"}, {erts, \"$erts_vsn\"},\n [{kernel,\"$kernel_vsn\"},\n {stdlib,\"$stdlib_vsn\"},\n {sasl,\"$sasl_vsn\"}]}.\n" - tmp_dir=$target_dir/tmp; - if [ ! -d $tmp_dir ]; then - mkdir $tmp_dir + tmp_dir="$target_dir/tmp"; + if [ ! -d "$tmp_dir" ]; then + mkdir "$tmp_dir" fi - echo $start_sasl > $tmp_dir/start_sasl.rel - echo $start_clean > $tmp_dir/start_clean.rel - echo $start_clean > $tmp_dir/no_dot_erlang.rel + echo "$start_sasl" > "$tmp_dir/start_sasl.rel" + echo "$start_clean" > "$tmp_dir/start_clean.rel" + echo "$start_clean" > "$tmp_dir/no_dot_erlang.rel" - erlc=$ERL_TOP/bootstrap/bin/erlc - if [ ! -x $erlc ]; then + erlc="$ERL_TOP/bootstrap/bin/erlc" + if [ ! -x "$erlc" ]; then echo "erlc not found, can not create .script and .boot files" 1>&2 exit 1 fi - $erlc -I$target_dir/lib/*/ebin -o$tmp_dir $tmp_dir/start_sasl.rel || exit 1 - $erlc -I$target_dir/lib/*/ebin -o$tmp_dir +no_warn_sasl $tmp_dir/start_clean.rel || exit 1 - $erlc -I$target_dir/lib/*/ebin -o$tmp_dir +no_warn_sasl +no_dot_erlang $tmp_dir/no_dot_erlang.rel || exit 1 + $erlc -I"$target_dir"/lib/*/ebin -o$tmp_dir $tmp_dir/start_sasl.rel || exit 1 + $erlc -I"$target_dir"/lib/*/ebin -o$tmp_dir +no_warn_sasl $tmp_dir/start_clean.rel || exit 1 + $erlc -I"$target_dir"/lib/*/ebin -o$tmp_dir +no_warn_sasl +no_dot_erlang $tmp_dir/no_dot_erlang.rel || exit 1 # Generate RELEASES file - erl=$ERL_TOP/bootstrap/bin/erl - if [ ! -x $erl ]; then + erl="$ERL_TOP/bootstrap/bin/erl" + if [ ! -x "$erl" ]; then echo "erl not found, can not create RELEASES file" 1>&2 exit 1 fi - $erl -noinput +B -eval "release_handler:create_RELEASES(\"%ERL_ROOT%\", \"$tmp_dir\", \"$tmp_dir/start_sasl.rel\", []), halt()" || exit 1 + "$erl" -noinput +B -eval "release_handler:create_RELEASES(\"%ERL_ROOT%\", \"$tmp_dir\", \"$tmp_dir/start_sasl.rel\", []), halt()" || exit 1 # If all good so far, move generated files into target area - mv $tmp_dir/RELEASES $target_dir/releases/RELEASES.src - mv $tmp_dir/* $target_dir/releases/$otp_major_vsn - rmdir $tmp_dir + mv "$tmp_dir/RELEASES" "$target_dir/releases/RELEASES.src" + mv "$tmp_dir"/* "$target_dir/releases/$otp_major_vsn" + rmdir "$tmp_dir" # Remove old start scripts (forces a new run of Install) - rm -f $target_dir/releases/RELEASES - rm -f $target_dir/bin/*.script - rm -f $target_dir/bin/*.boot - rm -f $target_dir/bin/erl + rm -f "$target_dir"/releases/RELEASES + rm -f "$target_dir"/bin/*.script + rm -f "$target_dir"/bin/*.boot + rm -f "$target_dir"/bin/erl fi } diff --git a/otp_versions.table b/otp_versions.table new file mode 100644 index 0000000000..e69de29bb2 diff --git a/system/doc/installation_guide/otp_version.xml b/system/doc/installation_guide/otp_version.xml deleted file mode 100644 index 0ce5144160..0000000000 --- a/system/doc/installation_guide/otp_version.xml +++ /dev/null @@ -1,96 +0,0 @@ - - - - -
- - 2014 - Ericsson AB. All Rights Reserved. - - - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. - - - - OTP version - - - - - - 2014-02-19 - - otp_version.xml -
-

As of OTP release 17, the OTP release number corresponds to - the major part of the OTP version. The OTP version as a concept was - introduced in OTP 17. In the normal case, the OTP version will be - constructed as - <Major>.<Minor>.<Patch> where <Major> - is the most significant part. However, more dot separated parts than - this may exist. The dot separated parts consists of integers. If all - parts less significant than <Minor> equals 0, they - are omitted. The three normal parts - <Major>.<Minor>.<Patch> will be changed as - follows:

- - <Major>Increased when major changes, - including incompatibilities, have been made. - <Minor>Increased when new functionality - has been added. - <Patch>Increased when pure bug fixes - have been made. - -

When a part in the version number is increased, all less significant - parts are set to 0. Release candidates have an -rc<N> - suffix. The suffix -rc0 will be used during development up to - the first release candidate.

- -

OTP of a specific version is a set of applications of - specific versions. The application versions identified by - an OTP version corresponds to application versions that - have been tested together by the Erlang/OTP team at Ericsson AB. - An OTP system can however be put together with applications from - different OTP versions. Such a combination of application versions - has not been tested by the Erlang/OTP team. It is therefore - always preferred to use OTP applications from one single OTP - version.

- -

Application versions will be managed the same way as the OTP version. - Application versions part of a release candidate will however not have an - -rc<N> suffix as the OTP version. Also note that a major - increment in an application version does not necessarily imply a major - increment of the OTP version. This depends on whether the - major change in the application is considered as a major change for - OTP as a whole or not.

- -

In an OTP source code tree as well as in an installed OTP - development system, the OTP version can be read from the text - file OTP_VERSION in the OTP installation root directory - (code:root_dir()).

-

If the version read from the OTP_VERSION file in a - development system has a ** suffix, the system has been - patched using the $ERL_TOP/otp_build patch_app tool. In - this case, the system consists of application versions from - multiple OTP versions. The version preceding the ** - suffix corresponds to the OTP version of the base system that - has been patched. Note that if a development system is updated by - other means than $ERL_TOP/otp_build patch_app, the - OTP_VERSION file may identify wrong OTP version.

- -

On a target system (see the - system principles - documentation) no OTP_VERSION file will exist. This since - one easily can create a target system where it is hard to even - determine the base OTP version.

-
- diff --git a/system/doc/installation_guide/part.xml b/system/doc/installation_guide/part.xml index 150df39512..19808fd165 100644 --- a/system/doc/installation_guide/part.xml +++ b/system/doc/installation_guide/part.xml @@ -31,7 +31,6 @@

How to install Erlang/OTP on UNIX or Windows.

- diff --git a/system/doc/installation_guide/xmlfiles.mk b/system/doc/installation_guide/xmlfiles.mk index 245491ab94..3995c607af 100644 --- a/system/doc/installation_guide/xmlfiles.mk +++ b/system/doc/installation_guide/xmlfiles.mk @@ -17,7 +17,6 @@ # %CopyrightEnd% # INST_GUIDE_CHAPTER_FILES = \ - otp_version.xml \ install-binary.xml \ verification.xml \ INSTALL.xml \ diff --git a/system/doc/system_principles/part.xml b/system/doc/system_principles/part.xml index 915d5aca9b..811428baae 100644 --- a/system/doc/system_principles/part.xml +++ b/system/doc/system_principles/part.xml @@ -31,5 +31,6 @@ + diff --git a/system/doc/system_principles/versions.xml b/system/doc/system_principles/versions.xml new file mode 100644 index 0000000000..6bfa9d1eed --- /dev/null +++ b/system/doc/system_principles/versions.xml @@ -0,0 +1,267 @@ + + + + +
+ + 2014 + Ericsson AB. All Rights Reserved. + + + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + + + Versions + + + + + + 2014-02-19 + + versions.xml +
+
OTP Version +

As of OTP release 17, the OTP release number corresponds to + the major part of the OTP version. The OTP version as a concept was + introduced in OTP 17. The version + scheme used is described in more detail below.

+ +

OTP of a specific version is a set of applications of specific + versions. The application versions identified by an OTP version + corresponds to application versions that have been tested together + by the Erlang/OTP team at Ericsson AB. An OTP system can however be + put together with applications from different OTP versions. Such a + combination of application versions has not been tested by the + Erlang/OTP team. It is therefore always preferred to use OTP + applications from one single OTP version.

+ +

Release candidates have an -rc<N> + suffix. The suffix -rc0 will be used during development up to + the first release candidate.

+ +
Retrieving Current OTP Version +

In an OTP source code tree, the OTP version can be read from + the text file <OTP source root>/OTP_VERSION. The + absolute path to the file can be constructed by calling + filename:join([code:root_dir(), "OTP_VERSION"]).

+

In an installed OTP development system, the OTP version can be read + from the text file <OTP installation root>/releases/<OTP release number>/OTP_VERSION. + The absolute path to the file can by constructed by calling + filename:join([code:root_dir(), "releases", erlang:system_info(otp_release), "OTP_VERSION"]).

+

If the version read from the OTP_VERSION file in a + development system has a ** suffix, the system has been + patched using the + $ERL_TOP/otp_build patch_app + tool. In this case, the system consists of application versions from + multiple OTP versions. The version preceding the ** + suffix corresponds to the OTP version of the base system that + has been patched. Note that if a development system is updated by + other means than $ERL_TOP/otp_build patch_app, the + OTP_VERSION file may identify wrong OTP version.

+ +

No OTP_VERSION file will be placed in a + target system created + by OTP tools. This since one easily can create a target system + where it is hard to even determine the base OTP version. You may, + however, place such a file there yourself if you know the OTP + version.

+
+ +
OTP Versions Table +

The text file <OTP source root>/otp_versions.table + part of the source code contains information about all OTP versions + from OTP 17.0 up to current OTP version. Each line contains information + about application versions part of a specific OTP version, and is on + the format:

+
+<OtpVersion> : <ChangedAppVersions> # <UnchangedAppVersions>
+
+

<OtpVersion> is on the format OTP-<VSN>, i.e., + the same as the git tag used to identify the source. + <ChangedAppVersions> and <UnchangedAppVersions> + are white space separated lists of application versions on the + format <application>-<vsn>. + <ChangedAppVersions> corresponds to changed applications + with new version numbers in this OTP version, and + <UnchangedAppVersions> corresponds to unchanged application + versions in this OTP version. Both of them might be empty, although + not at the same time. If <ChangedAppVersions> is empty, no changes + has been made that change the build result of any application. This could + for example be a pure bug fix of the build system. The order of lines + is undefined.

+

Using ordinary UNIX tools like sed and grep one + can easily find answers to various questions like:

+ + Which OTP versions are kernel-3.0 part of? +

$ grep 'kernel-3\.0' otp_versions.table

+ In which OTP version was kernel-3.0 introduced? +

$ sed 's/#.*//;/kernel-3\.0/!d' otp_versions.table

+
+

The above commands give a bit more information than the exact answers, + but adequate information when manually searching for answers to these + questions.

+

The format of the otp_versions.table might be subject + to changes during the OTP 17 release.

+
+
+ +
Application Version +

As of OTP 17.0 application versions will use the same + version scheme as the + OTP version. Application versions part of a release candidate will + however not have an -rc<N> suffix as the OTP version. + Also note that a major increment in an application version does not + necessarily imply a major increment of the OTP version. This depends + on whether the major change in the application is considered as a + major change for OTP as a whole or not.

+
+ + +
Version Scheme + Note that the version scheme was changed as of OTP 17.0. This implies + that application versions used prior to OTP 17.0 do not adhere to this + version scheme. A list of + application versions used in OTP 17.0 can be found + at the end of this document. + +

In the normal case, a version will be constructed as + <Major>.<Minor>.<Patch> where <Major> + is the most significant part. However, more dot separated parts than + this may exist. The dot separated parts consists of non-negative integers. + If all parts less significant than <Minor> equals 0, + they are omitted. The three normal parts + <Major>.<Minor>.<Patch> will be changed as + follows:

+ + <Major>Increased when major changes, + including incompatibilities, have been made. + <Minor>Increased when new functionality + has been added. + <Patch>Increased when pure bug fixes + have been made. + +

When a part in the version number is increased, all less significant + parts are set to 0.

+ +

An application version or an OTP version identifies source code + versions. That is, it does not imply anything about how the application + or OTP has been built.

+ +
Order of Versions +

Version numbers in general are only partially ordered. However, + normal version numbers (with three parts) as of OTP 17.0 have a total + or linear order. This applies both to normal OTP versions and + normal application versions.

+ +

When comparing two version numbers that have an order, one + compare each part as ordinary integers from the most + significant part towards less significant parts. The order is + defined by the first parts of the same significance that + differ. An OTP version with a larger version include all + changes that that are part of a smaller OTP version. The same + goes for application versions.

+ +

In the general case, versions may have more than three parts. In + this case the versions are only partially ordered. Note that such + versions are only used in exceptional cases. When an extra + part (out of the normal three parts) is added to a version number, + a new branch of versions is made. The new branch has a linear + order against the base version. However, versions on different + branches have no order. Since they have no order, we + only know that they all include what is included in their + closest common ancestor. When branching multiple times from the + same base version, 0 parts are added between the base + version and the least significant 1 part until a unique + version is found. Versions that have an order can be compared + as described in the paragraph above.

+ +

An example of branched versions: The version 6.0.2.1 + is a branched version from the base version 6.0.2. + Versions on the form 6.0.2.<X> can be compared + with normal versions smaller than or equal to 6.0.2, + and other versions on the form 6.0.2.<X>. The + version 6.0.2.1 will include all changes in + 6.0.2. However, 6.0.3 will most likely + not include all changes in 6.0.2.1 (note that + these versions have no order). A second branched version from the base + version 6.0.2 will be version 6.0.2.0.1, and a + third branched version will be 6.0.2.0.0.1.

+
+
+ + +
OTP 17.0 Application Versions +

The following application versions were part of OTP 17.0. If + the normal part of an applications version number compares + as smaller than the corresponding application version in this list, + the version number does not adhere to the version scheme introduced + in OTP 17.0 and should be considered as not having an order against + versions used as of OTP 17.0.

+ + asn1-3.0 + common_test-1.8 + compiler-5.0 + cosEvent-2.1.15 + cosEventDomain-1.1.14 + cosFileTransfer-1.1.16 + cosNotification-1.1.21 + cosProperty-1.1.17 + cosTime-1.1.14 + cosTransactions-1.2.14 + crypto-3.3 + debugger-4.0 + dialyzer-2.7 + diameter-1.6 + edoc-0.7.13 + eldap-1.0.3 + erl_docgen-0.3.5 + erl_interface-3.7.16 + erts-6.0 + et-1.5 + eunit-2.2.7 + gs-1.5.16 + hipe-3.10.3 + ic-4.3.5 + inets-5.10 + jinterface-1.5.9 + kernel-3.0 + megaco-3.17.1 + mnesia-4.12 + observer-2.0 + odbc-2.10.20 + orber-3.6.27 + os_mon-2.2.15 + ose-1.0 + otp_mibs-1.0.9 + parsetools-2.0.11 + percept-0.8.9 + public_key-0.22 + reltool-0.6.5 + runtime_tools-1.8.14 + sasl-2.4 + snmp-4.25.1 + ssh-3.0.1 + ssl-5.3.4 + stdlib-2.0 + syntax_tools-1.6.14 + test_server-3.7 + tools-2.6.14 + typer-0.9.6 + webtool-0.8.10 + wx-1.2 + xmerl-1.3.7 + +
+
+ diff --git a/system/doc/system_principles/xmlfiles.mk b/system/doc/system_principles/xmlfiles.mk index 4cbc00ed52..9743949798 100644 --- a/system/doc/system_principles/xmlfiles.mk +++ b/system/doc/system_principles/xmlfiles.mk @@ -19,4 +19,5 @@ SYSTEM_PRINCIPLES_CHAPTER_FILES = \ system_principles.xml \ error_logging.xml \ - create_target.xml + create_target.xml \ + versions.xml -- cgit v1.2.3