commit f00d66f3ee7d7de45c3e6db8d1e3477734aeebcee84c5dbf50b502bb1064edc1 Author: Adrian Schröter Date: Thu Dec 21 13:27:00 2023 +0100 Sync from SUSE:ALP:Source:Standard:1.0 ocaml-rpm-macros revision ea8fc1b2a682e96b55d82beb371b96fb diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9b03811 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,23 @@ +## Default LFS +*.7z filter=lfs diff=lfs merge=lfs -text +*.bsp filter=lfs diff=lfs merge=lfs -text +*.bz2 filter=lfs diff=lfs merge=lfs -text +*.gem filter=lfs diff=lfs merge=lfs -text +*.gz filter=lfs diff=lfs merge=lfs -text +*.jar filter=lfs diff=lfs merge=lfs -text +*.lz filter=lfs diff=lfs merge=lfs -text +*.lzma filter=lfs diff=lfs merge=lfs -text +*.obscpio filter=lfs diff=lfs merge=lfs -text +*.oxt filter=lfs diff=lfs merge=lfs -text +*.pdf filter=lfs diff=lfs merge=lfs -text +*.png filter=lfs diff=lfs merge=lfs -text +*.rpm filter=lfs diff=lfs merge=lfs -text +*.tbz filter=lfs diff=lfs merge=lfs -text +*.tbz2 filter=lfs diff=lfs merge=lfs -text +*.tgz filter=lfs diff=lfs merge=lfs -text +*.ttf filter=lfs diff=lfs merge=lfs -text +*.txz filter=lfs diff=lfs merge=lfs -text +*.whl filter=lfs diff=lfs merge=lfs -text +*.xz filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text +*.zst filter=lfs diff=lfs merge=lfs -text diff --git a/ocaml-findlib.rpm.prov_req.attr.sh b/ocaml-findlib.rpm.prov_req.attr.sh new file mode 100644 index 0000000..b29f399 --- /dev/null +++ b/ocaml-findlib.rpm.prov_req.attr.sh @@ -0,0 +1,235 @@ +#!/bin/bash +set -e +prov_req_name="ocamlfind" +td=`mktemp --directory` + +test -n "${td}" +_x() { + rm -rf "${td}" +} +trap _x EXIT + +cmd= +test "$1" = "-prov" && cmd=prov +test "$1" = "-req" && cmd=req +do_work() { + local f=$1 + local pkg_name + local pkg_prov_req + local pkg_prov + local pkg_req + local elem req + pkg_name="${f##*/}" + if test "${pkg_name}" = "META" + then + pkg_name="${f%/*}" + pkg_name="${pkg_name##*/}" + else + pkg_name="${pkg_name#META.}" + fi + pkg_prov_req="` + env \ + pkg_name="${pkg_name}" \ + cmd="${cmd}" \ + awk ' + BEGIN { + dbg=0; + count=1; + depth=0; + pkg_name=ENVIRON["pkg_name"]; + cmd=ENVIRON["cmd"]; + + if(dbg) printf "bEGIN \\"%s\\" cmd: %s\n", pkg_name, cmd > "/dev/stderr" ; + requires[pkg_name]="" + ppx_runtime_deps[pkg_name]="" + pkg_names[depth]=pkg_name + } + + { + if(dbg) printf "line: %s\n", $0 > "/dev/stderr" + } + + /^[[:blank:]]*directory[[:blank:]]*=/ { + if(dbg) printf "GOT: %s\n", $0 > "/dev/stderr" ; + if (depth == 0) { + x = split($0, a, "\\""); + if ( a[2] ) { + candidate = a[2]; + if(dbg) printf "dir: %s %s\n", x, candidate > "/dev/stderr" ; + if (candidate == "^") { + next + } + if (candidate == "+") { + next + } + if (candidate ~ /^\^/) { + next + } + if (candidate ~ /^\+/) { + candidate = substr(candidate, 2); + } + if (candidate ~ /^\//) { + x = split(candidate, a, "/"); + if ( x ) + candidate = a[x]; + } + if (candidate ~ /^\.\.\//) { + x = split(candidate, a, "/"); + if ( x ) + candidate = a[x]; + } + if(dbg) printf "dir: %s %s\n", x, candidate > "/dev/stderr" ; + if (candidate != pkg_name) { + requires[candidate] = requires[pkg_name]; + delete requires[pkg_name]; + pkg_name = candidate; + if(dbg) printf "new pkg_name %s %s\n", x, pkg_name > "/dev/stderr" ; + pkg_names[depth]=pkg_name + } else { + if(dbg) printf "pkg_name remains %s\n", pkg_name > "/dev/stderr" ; + } + } + } + next + } + + /^[[:blank:]]*requires(|\([^-][^)]+\))[[:blank:]]*(+=|=)/ { + if(dbg) printf "GOT: %s\n", $0 > "/dev/stderr" ; + done=0 + requires_line = "" + do { + need_next_line = 1 + line = $0 + requires_line = sprintf("%s%s", requires_line, line) + l = length(requires_line) + qm = index(requires_line, "\\"") + if (l > qm) { + line = substr(requires_line, qm + 1) + qm = index(line, "\\"") + need_next_line = qm == 0 + } + + if (need_next_line) { + done = getline == 0 + } else { + done = 1 + } + } while (done == 0) + + x = split(requires_line, a, "\\""); + if ( a[2] ) { + if(dbg) printf "req2 %s %s\n", x, a[2] > "/dev/stderr" ; + x = gsub("[[:blank:]]+", ",", a[2]); + if(dbg) printf "req2 %s %s\n", x, a[2] > "/dev/stderr" ; + if (requires[pkg_name] == "") { + requires[pkg_name] = a[2] + } else { + requires[pkg_name] = sprintf("%s,%s", requires[pkg_name],a[2]) + } + } + next + } + + /^[[:blank:]]*ppx_runtime_deps[[:blank:]]*(+=|=)/ { + if(dbg) printf "GOT: %s\n", $0 > "/dev/stderr" ; + done=0 + ppx_runtime_deps_line = "" + do { + need_next_line = 1 + line = $0 + ppx_runtime_deps_line = sprintf("%s%s", ppx_runtime_deps_line, line) + l = length(ppx_runtime_deps_line) + qm = index(ppx_runtime_deps_line, "\\"") + if (l > qm) { + line = substr(ppx_runtime_deps_line, qm + 1) + qm = index(line, "\\"") + need_next_line = qm == 0 + } + + if (need_next_line) { + done = getline == 0 + } else { + done = 1 + } + } while (done == 0) + + x = split(ppx_runtime_deps_line, a, "\\""); + if ( a[2] ) { + if(dbg) printf "req2 %s %s\n", x, a[2] > "/dev/stderr" ; + x = gsub("[[:blank:]]+", ",", a[2]); + if(dbg) printf "req2 %s %s\n", x, a[2] > "/dev/stderr" ; + if (ppx_runtime_deps[pkg_name] == "") { + ppx_runtime_deps[pkg_name] = a[2] + } else { + requires[pkg_name] = sprintf("%s,%s", requires[pkg_name],a[2]) + } + } + next + } + + /^[[:blank:]]*package[[:blank:]]/ { + if(dbg) printf "GOT: %s\n", $0 > "/dev/stderr" ; + depth = depth + 1; + if(dbg) printf "depth %s\n", depth > "/dev/stderr" ; + x = split($0, a, "\\""); + if ( a[2] ) { + if(dbg) printf "req2 %s %s\n", x, a[2] > "/dev/stderr" ; + pkg_name = pkg_name"."a[2]; + requires[pkg_name]="" + pkg_names[depth]=pkg_name + if(dbg) printf "new pkg_name %s %s\n", x, pkg_name > "/dev/stderr" ; + } + next + } + + /^[[:blank:]]*)/ { + if(dbg) printf "GOT: %s\n", $0 > "/dev/stderr" ; + depth = depth -1; + if(dbg) printf "depth %s\n", depth > "/dev/stderr" ; + pkg_name=pkg_names[depth] + if(dbg) printf "old pkg_name %s %s\n", x, pkg_name > "/dev/stderr" ; + next + } + + END { + if(dbg) printf "eND \\"%s\\"\n", pkg_name > "/dev/stderr" ; + for (req in requires) { + if(dbg)printf "eNd \\"%s\\"\n", req > "/dev/stderr"; + # format: provides:requires + printf "%s:%s\n", req, requires[req]; + } + for (req in ppx_runtime_deps) { + if(dbg)printf "eNd \\"%s\\"\n", req > "/dev/stderr"; + # format: provides:requires + printf "%s:%s\n", req, ppx_runtime_deps[req]; + } + if(dbg) printf "ENd \\"%s\\"\n", pkg_name > "/dev/stderr" ; + } + ' \"${f}\" + `" + for elem in ${pkg_prov_req} + do + pkg_prov="${elem%%:*}" + pkg_req="${elem#*:}" + pkg_req="${pkg_req//,/ }" + if test -n "${pkg_prov}" && test "${cmd}" = "prov" + then + echo "${prov_req_name}($pkg_prov)" + fi + if test "${cmd}" = "req" + then + for i in ${pkg_req} + do + echo "${prov_req_name}(${i})" + done + fi + done +} +while read filename +do + case "${filename}" in + */META*) do_work "${filename}" ;; + *) ;; + esac +done +# vim: tw=666 ts=2 shiftwidth=2 et diff --git a/ocaml-ocaml.rpm.prov_req.attr.sh b/ocaml-ocaml.rpm.prov_req.attr.sh new file mode 100644 index 0000000..fb9d5de --- /dev/null +++ b/ocaml-ocaml.rpm.prov_req.attr.sh @@ -0,0 +1,247 @@ +#!/bin/bash +# This is a helper for rpm which collects 'Provides' and 'Requires' information from OCaml files. +# It reads a list of filenames from STDIN. +# It expects as argument either '--provides|-P' or '--requires|-R'. +# Additional optional arguments are: +# -f "ocamlobjinfo command" +# -c # ignored, recognized just for compat reasons +# -i NAME # omit the Requires/Provides for this bytecode unit name +# -x NAME # omit the Requires/Provides for this native unit name +# +# OCaml object files contain either bytecode or native code. +# Each bytecode variant provides a certain interface, which is represented by a hash. +# Each native variant provides a certain interface and a certain implementation, which are represented by hashes. +# Each variant may also require a certain interface and/or implementation provided by other files. +# The details for each file can be inspected with 'ocamlobjinfo'. +# +# Each file contains at least one module. +# Information about each module follows after a line starting with "Name:" or "Unit name:": +# +# cma/cmi/cmo (bytecode): +# Unit name: NAME +# Interfaces imported: +# HASH NAME +# HASH NAME_FROM_OTHER_MODULE +# +# cmx/cmxa/cmxs (native): +# Name: NAME +# CRC of implementation: HASH +# Interfaces imported: +# HASH NAME +# HASH NAME_FROM_OTHER_MODULE +# Implementations imported: +# HASH NAME_FROM_OTHER_MODULE +# +# cmxs files are recoqnized, but need to be ignored. +# They contain references of the interfaces and implementations +# compiled into them. +# +# The hash may contain just '-', in which case it is ignored. +# +# Output: +# ocaml(NAME) = HASH # for interfaces (bytecode and native) +# ocamlx(NAME) = HASH # for implementations (native) + +set -e +# +OCAMLOBJINFO=ocamlobjinfo +rpm_prefix_interface='ocaml' +rpm_prefix_implementation='ocamlx' +# +parse() { + local filename="$1" + + ${OCAMLOBJINFO} "${filename}" | awk ' + BEGIN { + debug=0 + mode=ENVIRON["mode"] + RPM_BUILD_ROOT=ENVIRON["RPM_BUILD_ROOT"] + rpm_prefix_interface=ENVIRON["rpm_prefix_interface"] + rpm_prefix_implementation=ENVIRON["rpm_prefix_implementation"] + state="find" + unit="" + + split(ENVIRON["ignore_implementation"], ignore_implementation_a) + for (i in ignore_implementation_a) { + val=ignore_implementation_a[i] + if (debug) + printf "INFO: ignore_implementation %s\n", val > "/dev/stderr" + ignore_implementation[val]=1 + } + split(ENVIRON["ignore_interface"], ignore_interface_a) + for (i in ignore_interface_a) { + val=ignore_interface_a[i] + if (debug) + printf "INFO: ignore_interface %s\n", val > "/dev/stderr" + ignore_interface[val]=1 + } + } + + /^File / { + if (RPM_BUILD_ROOT != "" ) { + file=substr($2,length(RPM_BUILD_ROOT)+1) + } else { + file=$2 + } + state="file" + next + } + /^Unit name:/ { + unit=$3 + state="cma" + next + } + /^Name:/ { + unit=$2 + state="cmx" + next + } + + /^CRC of implementation:/ { + if (state == "cmx") { + if (ignore_implementation[unit] != "") { + if (ignore_implementation[unit] != "seen") { + printf "INFO: ignoring Provides %s(%s)=%s from %s\n", rpm_prefix_implementation, unit, $4, file > "/dev/stderr" + ignore_implementation[unit]="seen" + } + } else { + implementation_provides[unit]=$4 + } + } else { + printf "WARN: state %s, expected cmx, got %s\n", state, $0 > "/dev/stderr" + } + state="crc" + next + } + + /^Interfaces imported:/ { + state="interface" + next + } + + /^Implementations imported:/ { + state="implementation" + next + } + + /^\t/ { + if (state == "interface" && NF > 1 && match($1, "^-") == 0) { + if (unit == $2) { + if (ignore_interface[unit] != "") { + if (ignore_interface[unit] != "seen") { + printf "INFO: ignoring Provides %s(%s)=%s from %s\n", rpm_prefix_interface, unit, $1, file > "/dev/stderr" + ignore_interface[unit]="seen" + } + } else { + interface_provides[unit]=$1 + } + } else { + if (ignore_interface[$2] != "") { + if (ignore_interface[$2] != "seen") { + printf "INFO: ignoring Requires %s(%s)=%s from %s\n", rpm_prefix_interface, $2, $1, file > "/dev/stderr" + ignore_interface[$2]="seen" + } + } else { + interface_requires[$2]=$1 + } + } + next + } else if (state == "implementation" && NF > 1 && match($1, "^-") == 0) { + if (unit == $2) { + if (ignore_implementation[unit] != "") { + if (ignore_implementation[unit] != "seen") { + printf "INFO: ignoring Provides %s(%s)=%s from %s\n", rpm_prefix_implementation, unit, $1, file > "/dev/stderr" + ignore_implementation[unit]="seen" + } + } else { + implementation_provides[unit]=$1 + } + } else { + if (ignore_implementation[$2] != "") { + if (ignore_implementation[$2] != "seen") { + printf "INFO: ignoring Requires %s(%s)=%s from %s\n", rpm_prefix_implementation, $2, $1, file > "/dev/stderr" + ignore_implementation[$2]="seen" + } + } else { + implementation_requires[$2]=$1 + } + } + next + } else { + next + } + } + /^.*/ { + state="find" + } + + END { + if (mode == "provides") { + for (i in interface_provides) { + printf "%s(%s) = %s\n", rpm_prefix_interface, i, interface_provides[i] + } + for (i in implementation_provides) { + printf "%s(%s) = %s\n", rpm_prefix_implementation, i, implementation_provides[i] + } + } + if (mode == "requires") { + for (i in interface_requires) { + printf "%s(%s) = %s\n", rpm_prefix_interface, i, interface_requires[i] + } + for (i in implementation_requires) { + printf "%s(%s) = %s\n", rpm_prefix_implementation, i, implementation_requires[i] + } + } + } + ' +} +# +# +usage() { + echo >&2 "Usage: ${0##*/} -provides|-requires [-f 'ocamlobjinfo cmd']" +} +# +mode= +ignore_implementation_a=() +ignore_interface_a=() +while test "$#" -gt 0 +do + : "${1}" "${2}" + case "${1}" in + -P|--provides) mode='provides' ;; + -R|--requires) mode='requires' ;; + -i) ignore_interface_a+=("$2") ; shift ;; + -x) ignore_implementation_a+=("$2") ; shift ;; + -f) OCAMLOBJINFO="$2"; shift ;; + -h|--help) usage ; exit 0 ;; + -c) ;; # ignored + --) break ;; + *) usage ; exit 1 ;; + esac + shift +done +if test -z "${mode}" +then + usage + exit 1 +fi +# +export rpm_prefix_interface +export rpm_prefix_implementation +export mode +export ignore_implementation="${ignore_implementation_a[@]}" +export ignore_interface="${ignore_interface_a[@]}" +# +while read filename +do + case "${filename}" in + *.cma) parse "${filename}" ;; + *.cmi) parse "${filename}" ;; + *.cmo) parse "${filename}" ;; + *.cmx) parse "${filename}" ;; + *.cmxa) parse "${filename}" ;; + *.cmxs) ;; + *) continue ;; + esac +done +# vim: tw=666 ts=2 shiftwidth=2 et diff --git a/ocaml-rpm-macros.changes b/ocaml-rpm-macros.changes new file mode 100644 index 0000000..ae28d1e --- /dev/null +++ b/ocaml-rpm-macros.changes @@ -0,0 +1,188 @@ +------------------------------------------------------------------- +Tue Oct 31 21:44:55 UTC 2023 - Aaron Puchert + +- Increase stack size limit for riscv64 like for ppc64(le). + +------------------------------------------------------------------- +Sun Jan 29 08:34:55 UTC 2023 - Bernhard Wiedemann + +- Allow variables in smp_mflags to be interpolated + for https://github.com/rpm-software-management/rpm/issues/2343 + +------------------------------------------------------------------- +Sun Jan 1 01:01:01 UTC 2023 - ohering@suse.de + +- Remove stale references to ocaml_make_testsuite + +------------------------------------------------------------------- +Thu Jul 7 07:07:07 UTC 2022 - ohering@suse.de + +- Handle plain ^ and + as values for directory= in findlib META files + They stand for the OCaml standard library directory. + +------------------------------------------------------------------- +Sat Apr 9 12:34:56 UTC 2022 - ohering@suse.de + +- remove unused ocaml_dune_bootstrap_directory +- move all invocations of dune from ocaml_dune_setup to ocaml_dune_build +- process content of ocaml_standard_library only if it exists in buildroot + +------------------------------------------------------------------- +Tue Feb 22 22:22:22 UTC 2022 - ohering@suse.de + +- remove usage of external-lib-deps for dune3 +- define ocaml_dune_bootstrap_directory for dune3 +- remove braces from rpm macros + +------------------------------------------------------------------- +Wed Oct 27 07:31:27 UTC 2021 - ohering@suse.de + +- Move cmxs files into the main package + Applications like Coq may load them at runtime. +- Ignore dependencies for cmxs files +- Restore dummy ocaml_native_compiler to allow quilt setup with + old packages + +------------------------------------------------------------------- +Sat Sep 11 12:34:56 UTC 2021 - ohering@suse.de + +- Rename a single opam file to $dune_release_pkgs.opam + +------------------------------------------------------------------- +Wed Apr 21 12:34:56 UTC 2021 - ohering@suse.de + +- Remove ocaml_native_compiler flag, assume native target + This flag puts too much burden on pkgs that use ocaml, but build + with their buildsystem instead of using dune + +------------------------------------------------------------------- +Fri Apr 9 09:09:09 UTC 2021 - ohering@suse.de + +- Use bcond suse_ocaml_use_rpm_license_macro for license in filelist +- Add suse prefix to ocaml_native_compiler to avoid conflict +- Create Provides/Requires only for rpm variants which understand fileattrs +- Fix syntax for chmod of .cmxs +- Add conditional to disable debug_package macro when building with broken rpm variants + +------------------------------------------------------------------- +Tue Feb 9 09:09:09 UTC 2021 - ohering@suse.de + +- Fix regex in file list generator to really match dot and extension + +------------------------------------------------------------------- +Thu Jan 21 21:21:21 UTC 2021 - ohering@suse.de + +- Adjust parser of ocamfind() requires + Take negative predicates in requires() into account, and ignore them. + This is supposed to avoid dependency cycles due to excessive + list of dependencies. + +------------------------------------------------------------------- +Thu Jan 14 14:14:14 UTC 2021 - ohering@suse.de + +- Adjust injection of version into findlib META files + A file VERSION is not handled anymore by dune since 1.11. + Remove version: from *.opam files, inject version into dune-project + +------------------------------------------------------------------- +Thu Aug 20 20:20:20 UTC 2020 - ohering@suse.de + +- Package also *.v, for Coq +- Package changelog files +- Enable native riscv64 + +------------------------------------------------------------------- +Thu May 14 14:14:14 UTC 2020 - ohering@suse.de + +- The filename for rpm *.attr files and the tag used within these + files must match. Otherwise rpm will not execute the helper scripts. + Use tag 'suseocaml', rename zocaml.attr to suseocaml.attr to + avoid filename conflicts with rpm-build.rpm (bsc#1154874) +- Rename also ocamlfind to suseocamlfind +- Escape plain % chars + +------------------------------------------------------------------- +Sun Apr 12 12:12:12 UTC 2020 - ohering@suse.de + +- run OCaml rpm dependency generator only if both path and magic matches (rpm#1173) + +------------------------------------------------------------------- +Sat Mar 21 12:34:56 UTC 2020 - ohering@suse.de + +- Disable parallel build for OCaml 4.08, 4.09 and 4.10 + to get reproducible cma archives (issue#9307) + +------------------------------------------------------------------- +Thu Feb 20 20:20:20 UTC 2020 - ohering@suse.de + +- Add ocaml-ocaml.rpm.prov_req.attr.sh + New script for rpm Provides/Requires, replacement for rpm + built-in ocaml(NAME)=hash, which covers bytecode and interfaces + Now it covers also native code via ocamlx(NAME)=HASH (bsc#1154874) +- Update the filelist generator + Use awk to match directories in ocamls built-in ld.conf + C stublibs in default locations do not need a ld.so.conf entry + Remaining ld.so.conf files for stublibs go to the devel package +- Disable debug in ocamlfind() Provides/Requires generator + Update META parser to handle multiline statements and ppx +- Provide a ocaml_standard_library macro +- Explicitly preserve debuginfo in .cmxs, already enforced by dune +- Install also COPYRIGHT.txt as license, needed for some JaneStreet pkgs + +------------------------------------------------------------------- +Mon Nov 25 12:34:56 UTC 2019 - ohering@suse.de + +- Install also LGPL as license, needed by ocaml-lablgtk2 + +------------------------------------------------------------------- +Fri Nov 1 12:34:56 UTC 2019 - ohering@suse.de + +- Moved ocaml-findlib.rpm.prov_req.attr.sh from ocaml to provide + ocamlfind() in ocaml itself +- Handle license separately because sed w truncates output +- Document individual file extensions +- Move cmxs and so files to devel packages because they are not + used at runtime. Also, cmxs dependencies in main pkg are + not covered by ocaml-find-requires.sh (bsc#1154874) +- Set VERSION unconditionally for each patch, sometimes dune picks it up +- Pass --for-release-of-packages to dune via dune_release_pkgs= +- Print potential BuildRequires during build +- Package sml for camlp5 +- SLE_12 has still no license macro, package as doc instead +- Use _smp_mflags instead of nproc for parallel build + +------------------------------------------------------------------- +Wed Oct 9 05:48:16 UTC 2019 - ohering@suse.de + +- Package also COPYRIGHT, for labltk +- Package also Copyright, for dose3 +- Package also *.cmo +- Package also *.so.owner +- Package also *.o +- Package also /etc/ld.so.conf.d +- Package also *.js + +------------------------------------------------------------------- +Fri Oct 4 07:56:44 UTC 2019 - ohering@suse.de + +- Use _rpmmacrodir +- Automatically package known license files in main pkg +- List unhandled files in ocaml_create_file_list macro +- Do not mark files as %config + +------------------------------------------------------------------- +Mon Sep 30 14:15:16 UTC 2019 - ohering@suse.de + +- Increase ulimit -s on ppc64 in dune macros + Required for at least ocaml-camomile +- Show external-lib-deps also for dune runtest +- Provide a ocaml_create_file_list macro +- Optional extra args for dune commands +- Pass --verbose to dune commands +- Move prefix/man to datadir/man to workaround bug in dune (#2670) + +------------------------------------------------------------------- +Mon Sep 30 12:34:56 UTC 2019 - ohering@suse.de + +- moved ocaml-rpm-macros from ocaml.spec to separate pkg + diff --git a/ocaml-rpm-macros.spec b/ocaml-rpm-macros.spec new file mode 100644 index 0000000..7a66452 --- /dev/null +++ b/ocaml-rpm-macros.spec @@ -0,0 +1,545 @@ +# +# spec file for package ocaml-rpm-macros +# +# Copyright (c) 2023 SUSE LLC +# +# All modifications and additions to the file contributed by third parties +# remain the property of their copyright owners, unless otherwise agreed +# upon. The license for this file, and modifications and additions to the +# file, is the same license as for the pristine package itself (unless the +# license for the pristine package is not an Open Source License, in which +# case the license is the MIT License). An "Open Source License" is a +# license that conforms to the Open Source Definition (Version 1.9) +# published by the Open Source Initiative. + +# Please submit bugfixes or comments via https://bugs.opensuse.org/ +# + + +Name: ocaml-rpm-macros +Version: 20231101 +Release: 0 +Summary: RPM macros for building OCaml source packages +License: GPL-2.0-only +Group: Development/Languages/OCaml +BuildRoot: %_tmppath/%name-%version-build +ExclusiveArch: %arm aarch64 %ix86 ppc ppc64 ppc64le riscv64 s390x x86_64 +URL: https://build.opensuse.org/project/show/devel:languages:ocaml +Source0: ocaml-ocaml.rpm.prov_req.attr.sh +Source1: ocaml-findlib.rpm.prov_req.attr.sh + +# Some rpm variants know about license, but can only use them in plain file context +%bcond_without suse_ocaml_use_rpm_license_macro +# Some rpm variants are unable to create proper debuginfo and/or debugsource packages +%bcond_without suse_ocaml_opt_debug_package +# Some rpm variants fail to build even this innocent package... +%define debug_package %nil + +%define ocaml_standard_library %_libdir/ocaml + +%description +OCaml is a high-level, strongly-typed, functional and object-oriented +programming language from the ML family of languages. + +This package contains a set of helper macros to unify common code used +in ocaml spec files. + +%prep + +%build + +%install +> files.fileattrs +if test -d '%_rpmconfigdir/fileattrs' +then + # Generating dependencies can currently only be done by rpm versions + # which support "fileattrs", because it is easy to add new hooks. + mkdir -vp %buildroot%_rpmconfigdir/fileattrs + + # Map ocamlobjinfo output to rpm Provides/Requires + # This tag name MUST match what ocaml.spec uses internally + tag="suseocaml" + file_attr="%_rpmconfigdir/fileattrs/${tag}.attr" + file_sh="%_rpmconfigdir/${tag}.sh" + attr_sh="%%_rpmconfigdir/${tag}.sh" + tee %buildroot${file_sh} < %{SOURCE0} + tee %buildroot${file_attr} <<_EOF_ +%%__${tag}_provides ${attr_sh} --provides +%%__${tag}_requires ${attr_sh} --requires +%%__${tag}_magic ^(Objective caml|OCaml) .*$ +%%__${tag}_path .(cma|cmi|cmo|cmx|cmxa)$ +%%__${tag}_flags magic_and_path +_EOF_ + echo "${file_attr}" >> files.fileattrs + echo "%%attr(755,root,root) ${file_sh}" >> files.fileattrs + + # Map findlib names to rpm Provides/Requires + tag="suseocamlfind" + file_attr="%_rpmconfigdir/fileattrs/${tag}.attr" + file_sh="%_rpmconfigdir/${tag}.sh" + attr_sh="%%_rpmconfigdir/${tag}.sh" + tee %buildroot${file_sh} < %{SOURCE1} + tee %buildroot${file_attr} <<_EOF_ +%%__${tag}_provides ${attr_sh} -prov +%%__${tag}_requires ${attr_sh} -req +%%__${tag}_path ^%ocaml_standard_library/.*/META$|^%ocaml_standard_library/META$ +_EOF_ + echo "${file_attr}" >> files.fileattrs + echo "%%attr(755,root,root) ${file_sh}" >> files.fileattrs +fi +# + +# install OCaml macros +mkdir -vp %buildroot%_rpmmacrodir +tee %buildroot%_rpmmacrodir/macros.%name <<'_EOF_' +# Guidelines: +# - Providing applications written in OCaml is the main goal of our packaging. +# - Applications written in OCaml are static binaries. +# - A concept of shared libraries does not exist, beside the Dynlink module +# - All binaries go into the main package, in case they are produced. +# - All modules go into the -devel subpackage +# - Helper applications below %ocaml_standard_library go into the -devel subpackage +# - License files go into the main package. +# - To aid debugging of cmxs files, their debuginfo is preserved by removing the executable bit. +# +# get rid of %_rpmconfigdir/find-debuginfo.sh +# strip kills the bytecode part of ELF binaries +# +# provide empty _find_debuginfo_dwz_opts +# the .dwz files contains identical contents, which leads to identical +# checksums, which leads to file conflicts due to identical symlinks +%%ocaml_standard_library %ocaml_standard_library +%if %{without suse_ocaml_opt_debug_package} +# Obviously, handling presence or absence of debug information works only when being built in a SUSE system. +%endif +%%ocaml_preserve_bytecode \ +%if %{without suse_ocaml_opt_debug_package} + %%define debug_package %%nil \ + %%define __debug_install_post %%nil \ +%endif + %%define _lto_cflags %%nil \ + %%nil +%%_find_debuginfo_dwz_opts %%nil + +# Compatibility for quilt setup and old packages +%%ocaml_native_compiler 1 +%%suse_ocaml_native_compiler 1 + +# Create file list for base pkg and base-devel pkg +# Files with known extensions or names are written to 'files' or 'files.devel' +# Other unknown files are shown on stdout +%%ocaml_create_file_list \ + > %%name.files ;\ + > %%name.files.changes ;\ + > %%name.files.devel ;\ + > %%name.files.ldsoconf ;\ + > %%name.files.license ;\ + > %%name.files.unhandled ;\ + for changes in \\\ + CHANGELOG.md \\\ + CHANGES \\\ + CHANGES.md \\\ + CHANGES.txt \\\ + ChangeLog \\\ + Changelog \\\ + ;\ + do\ + test -f "${changes}" && echo "%%%%doc ${changes}" >> '%%name.files.changes' ;\ + done ;\ + for license in \\\ + COPYING \\\ + COPYING.txt \\\ + COPYRIGHT \\\ + COPYRIGHT.txt \\\ + Copyright \\\ + LGPL \\\ + LICENCE \\\ + LICENSE \\\ + LICENSE.md \\\ + LICENSE.txt \\\ + ;\ + do\ +%if %{with suse_ocaml_use_rpm_license_macro} + license_macro='license' ;\ +%else + license_macro='doc' ;\ +%endif + test -f "${license}" && echo "%%%%${license_macro} ${license}" >> '%%name.files.license' ;\ + done ;\ + if test -d %%buildroot%%ocaml_standard_library ;\ + then\ + find %%buildroot%%ocaml_standard_library -name '*.cmxs' -exec chmod -v a-x '{}' + ;\ + find %%buildroot%%ocaml_standard_library ! -type d | awk\\\ + -v "buildroot=%%buildroot"\\\ + -v "ocaml_standard_library=%%ocaml_standard_library"\\\ + -v "out_files_main=%%name.files"\\\ + -v "out_files_devel=%%name.files.devel"\\\ + -v "out_files_ldconf=%%name.files.ldsoconf"\\\ + -v "out_files_unhandled=%%name.files.unhandled"\\\ + -v "ocaml_ldconf=$(ls -1d %%ocaml_standard_library/ld.conf || : ld.conf not found)"\\\ + '\ + BEGIN {\ + nr=0\ + if (ocaml_ldconf != "") {\ + do {\ + r = getline < ocaml_ldconf\ + if (r > 0) {\ + ldconf[nr++]=$0\ + }\ + } while (r > 0)\ + }\ + }\ + function _split (line) {\ + file_path=substr(line, length(buildroot) + 1)\ + m=match(file_path, "/[^/]+$")\ + dirname=substr(file_path, 0, m - 1)\ + basename=substr(file_path, m + 1)\ + if (dirname == ocaml_standard_library) {\ + # do not package above standard_library\ + parent_dir=""\ + } else {\ + m=match(dirname, "/[^/]+$")\ + parent_dir=substr(dirname, 0, m - 1)\ + }\ + }\ + function files_ldconf(line) {\ + _split(line)\ + print file_path >> out_files_devel\ + print "%%dir " dirname >> out_files_devel\ + for (ldconf_dir in ldconf) {\ + if (dirname == ldconf[ldconf_dir]) {\ + # done with this cycle, ocaml ld.conf covers it\ + next\ + }\ + }\ + print dirname >> out_files_ldconf\ + next\ + }\ + function files_devel(line) {\ + _split(line)\ + print file_path >> out_files_devel\ + print "%%dir " dirname >> out_files_devel\ + if (parent_dir != "") {\ + print "%%dir " parent_dir >> out_files_devel\ + }\ + next\ + }\ + function files_main(line) {\ + _split(line)\ + print file_path >> out_files_main\ + print "%%dir " dirname >> out_files_main\ + if (parent_dir != "") {\ + print "%%dir " parent_dir >> out_files_main\ + }\ + next\ + }\ + function files_unhandled(line) {\ + _split(line)\ + print file_path >> out_files_unhandled\ + next\ + }\ + # for findlib, describing a package\ + /\\/META$/{\ + files_devel($0)\ + }\ + # stub ELF library\ + /\\/[^/]+\\.so$/{\ + files_ldconf($0)\ + }\ + # stub ELF library\ + /\\/[^/]+\\.so.owner$/{\ + files_ldconf($0)\ + }\ + # ELF archive with object files\ + /\\/[^/]+\\.a$/{\ + files_devel($0)\ + }\ + # OCaml legacy source code annotations, produced via -annot\ + /\\/[^/]+\\.annot$/{\ + files_devel($0)\ + }\ + # OCaml library file with bytecode\ + /\\/[^/]+\\.cma$/{\ + files_devel($0)\ + }\ + # OCaml compiled header file\ + /\\/[^/]+\\.cmi$/{\ + files_devel($0)\ + }\ + # OCaml object file with bytecode\ + /\\/[^/]+\\.cmo$/{\ + files_devel($0)\ + }\ + # OCaml source code annotations, produced via -bin-annot from source files\ + /\\/[^/]+\\.cmt$/{\ + files_devel($0)\ + }\ + # OCaml source code annotations, produced via -bin-annot from header files\ + /\\/[^/]+\\.cmti$/{\ + files_devel($0)\ + }\ + # OCaml object file with native code\ + /\\/[^/]+\\.cmx$/{\ + files_devel($0)\ + }\ + # OCaml library file with native code\ + /\\/[^/]+\\.cmxa$/{\ + files_devel($0)\ + }\ + # ELF shared library with native code\ + /\\/[^/]+\\.cmxs$/{\ + files_main($0)\ + }\ + # Some helper binary\ + /\\/[^/]+\\.exe$/{\ + files_devel($0)\ + }\ + # C header\ + /\\/[^/]+\\.h$/{\ + files_devel($0)\ + }\ + #\ + /\\/[^/]+\\.js$/{\ + files_devel($0)\ + }\ + # OCaml source code, source file\ + /\\/[^/]+\\.ml$/{\ + files_devel($0)\ + }\ + # OCaml source code, header file\ + /\\/[^/]+\\.mli$/{\ + files_devel($0)\ + }\ + # ELF object file\ + /\\/[^/]+\\.o$/{\ + files_devel($0)\ + }\ + #\ + /\\/[^/]+\\.sml$/{\ + files_devel($0)\ + }\ + # generated by dune\ + /\\/dune-package$/{\ + files_devel($0)\ + }\ + # generated by dune\ + /\\/opam$/{\ + files_devel($0)\ + }\ + # Some Coq files\ + /\\/[^/]+\\.v$/{\ + files_devel($0)\ + }\ + #\ + # record unknown paths\ + files_unhandled($0)\ + END {\ + ;\ + }' ;\ + fi ;\ + cat '%%name.files.changes' >> '%%name.files' ;\ + cat '%%name.files.license' >> '%%name.files' ;\ + if test -s %%name.files.ldsoconf ;\ + then\ + ldsoconfd='/etc/ld.so.conf.d' ;\ + mkdir -vp "%%buildroot${ldsoconfd}" ;\ + tee "%%buildroot${ldsoconfd}/%%name.conf" < %%name.files.ldsoconf ;\ + echo "%config ${ldsoconfd}/%%name.conf" >> %%name.files.devel ;\ + fi ;\ + for i in \\\ + %%name.files \\\ + %%name.files.devel \\\ + %%name.files.ldsoconf \\\ + %%name.files.unhandled \\\ + ;\ + do\ + sort -u $i > $$ ;\ + mv $$ $i ;\ + done ;\ + %%nil + +# setup.ml comes from oasis, but this is here for libs oasis depends on +# +# html goes into a separate, browsable dir +# which is also safe regarding wiping due to %%doc macro usage +%%_oasis_docdir_base %%_datadir/doc/ocaml +%%_oasis_docdir_dvi %%_oasis_docdir_base/%%name +%%_oasis_docdir_html %%_oasis_docdir_base/%%name +%%_oasis_docdir_pdf %%_oasis_docdir_base/%%name +%%_oasis_docdir_ps %%_oasis_docdir_base/%%name +%%oasis_docdir %%_oasis_docdir_base/%%name +# +# For now provide a convinience macro which covers also the parent dir +%%oasis_docdir_dvi %%dir %%_oasis_docdir_base \ +%%_oasis_docdir_dvi +%%oasis_docdir_html %%dir %%_oasis_docdir_base \ +%%_oasis_docdir_html +%%oasis_docdir_pdf %%dir %%_oasis_docdir_base \ +%%_oasis_docdir_pdf +%%oasis_docdir_ps %%dir %%_oasis_docdir_base \ +%%_oasis_docdir_ps +# +# various macros to unify setup/build/install +%%oasis_setup \ + oasis setup +%%ocaml_oasis_configure \ +ocaml setup.ml -configure \\\ + --psdir %%_oasis_docdir_ps \\\ + --pdfdir %%_oasis_docdir_pdf \\\ + --dvidir %%_oasis_docdir_dvi \\\ + --htmldir %%_oasis_docdir_html \\\ + --docdir %%oasis_docdir \\\ + --localedir %%_datadir/locale \\\ + --datadir %%_datadir \\\ + \\\ + --bindir %%_bindir \\\ + --mandir %%_mandir \\\ + --destdir %%buildroot \\\ + --datarootdir %%_datadir \\\ + --infodir %%_infodir \\\ + --libdir %%_libdir \\\ + --libexecdir %%_libexecdir \\\ + --localstatedir %%_localstatedir \\\ + --sbindir %%_sbindir \\\ + --prefix %%_prefix \\\ + --sysconfdir %%_sysconfdir \\\ + --exec-prefix %%_prefix \\\ + --sharedstatedir %%_sharedstatedir +# +%%ocaml_oasis_build \ + ocaml setup.ml -build +%%ocaml_oasis_doc \ + ocaml setup.ml -doc +%%ocaml_oasis_install \ + ocaml setup.ml -install +%%ocaml_oasis_findlib_install \ + export OCAMLFIND_DESTDIR=%%buildroot%%ocaml_standard_library ; \ + export OCAMLFIND_LDCONF=/dev/null ; \ + mkdir -p $OCAMLFIND_DESTDIR ; \ + ocaml setup.ml -install +%%ocaml_oasis_test \ + ocaml setup.ml -test +# +%%ocaml_dune_setup \ +%ifarch ppc64 ppc64le riscv64 + ulimit -s $((1024 * 64)) ; \ +%endif +%if 0 + # obviously this works just with a single entry in dune_release_pkgs= +%endif + if test -n "${dune_release_pkgs}" ; \ + then \ + test -f 'opam' && mv -v 'opam' "${dune_release_pkgs}.opam" ; \ + fi ; \ + echo '%%version' | tee VERSION ; \ + for opam in *.opam \ + do\ + test -f "${opam}" || continue ; \ + sed -i~ '\ + /^version:/d\ + ' "${opam}" ; \ + diff -u "$_"~ "$_" || : got version ; \ + done ; \ + if test -f 'dune-project' ; \ + then \ + sed -i~ '\ + /^([[:blank:]]*version[[:blank:]]\\+/d\ + /^([[:blank:]]*lang[[:blank:]]\\+dune[[:blank:]]/a (version %%version)\ + ' 'dune-project'; \ + diff -u "$_"~ "$_" || : got version ; \ + fi ; \ + dune_for_release= ; \ + : dune_release_pkgs \ + if test -n "${dune_release_pkgs}" ; \ + then \ + echo "${dune_release_pkgs}" > dune_release_pkgs-%%name-%%version-%%release ; \ + dune_for_release="--for-release-of-packages=${dune_release_pkgs}" ; \ + fi ; \ + %%nil +%%ocaml_dune_build \ + dune --version ; \ + dune installed-libraries $OCAML_DUNE_INSTALLED_LIBRARIES_ARGS ; \ + if test -z "${_smp_mflags}" ;\ + then \ + _smp_mflags="%%{?_smp_mflags}" ;\ + case "$(ocamlc --version)" in \\\ + 4.08*) _smp_mflags='-j1' ;;\\\ + 4.09*) _smp_mflags='-j1' ;;\\\ + 4.10*) _smp_mflags='-j1' ;;\\\ + esac ;\ + fi ;\ + dune build \\\ + --verbose \\\ + ${dune_for_release} \\\ + ${_smp_mflags} \\\ + '@install' \\\ + $OCAML_DUNE_BUILD_INSTALL_ARGS +%%ocaml_dune_install \ +%ifarch ppc64 ppc64le riscv64 + ulimit -s $((1024 * 64)) ; \ +%endif + if test -z "${_smp_mflags}" ;\ + then \ + _smp_mflags="%%{?_smp_mflags}" ;\ + case "$(ocamlc --version)" in \\\ + 4.08*) _smp_mflags='-j1' ;;\\\ + 4.09*) _smp_mflags='-j1' ;;\\\ + 4.10*) _smp_mflags='-j1' ;;\\\ + esac ;\ + fi ;\ + dune_for_release= ;\ + if test -f dune_release_pkgs-%%name-%%version-%%release ; \ + then \ + read dune_release_pkgs < dune_release_pkgs-%%name-%%version-%%release ; \ + dune_for_release="--for-release-of-packages=${dune_release_pkgs}" ; \ + fi ;\ + dune install \\\ + --verbose \\\ + ${dune_for_release} \\\ + ${_smp_mflags} \\\ + --prefix=%%_prefix \\\ + --libdir=%%ocaml_standard_library \\\ + --destdir=%%buildroot \\\ + ${dune_release_pkgs//,/ } \\\ + $OCAML_DUNE_INSTALL_ARGS ;\ + rm -rfv %%buildroot%%_prefix/doc ;\ + if test -d %%buildroot%%_prefix/man ; then \ + mkdir -vp %%buildroot%%_datadir ; \ + mv -vt %%buildroot%%_datadir %%buildroot%%_prefix/man ; \ + fi ; +%%ocaml_dune_test \ +%ifarch ppc64 ppc64le + ulimit -s $((1024 * 64)) ; \ +%endif + dune_for_release= ; \ + if test -f dune_release_pkgs-%%name-%%version-%%release ; \ + then \ + read dune_release_pkgs < dune_release_pkgs-%%name-%%version-%%release ; \ + dune_for_release="--for-release-of-packages=${dune_release_pkgs}" ; \ + fi ; \ + if dune runtest \\\ + --verbose \\\ + ${dune_for_release} \\\ + $OCAML_DUNE_RUNTEST_ARGS ; \ + then \ + echo "dune runtest succeeded" ; \ + else \ + echo "dune runtest failed" ; \ + if test -n "${dune_test_tolerate_fail}" ; \ + then \ + echo "ignored" ; \ + else \ + echo "aborting" ; \ + exit 1 ; \ + fi ; \ + fi + +# +# +_EOF_ + +%files -f files.fileattrs +%defattr(-,root,root,-) +%_rpmmacrodir/* + +%changelog