Skip to content

Portable makefiles 3 #634

Portable makefiles 3

Portable makefiles 3 #634

Workflow file for this run

name: CI
env:
PROJECT_NAME: unison
PROJECT_DESC: "`unison` file synchronizer"
PROJECT_EXES: "unison unison-fsmonitor"
on:
- pull_request
- push
jobs:
docs:
runs-on: ubuntu-20.04
steps:
- run: sudo apt-get update
- name: Checkout code
uses: actions/checkout@v4
- name: Use OCaml
uses: ocaml/setup-ocaml@v3
with:
ocaml-compiler: 4.14.x
- run: sudo apt-get install hevea lynx texlive-latex-base
- run: opam exec -- make docs
- name: Store user manual for the build jobs
uses: actions/upload-artifact@v4
with:
name: unison-docs
path: |
doc/unison-manual.txt
doc/unison-manual.html
doc/unison-manual.pdf
man/unison.1
build:
if: ${{ !cancelled() }} # Don't fail if 'docs' failed
needs: docs
strategy:
fail-fast: false
matrix:
job:
- { os: macos-14 , ocaml-version: 5.2.x }
- { os: macos-14 , ocaml-version: 4.14.x , publish: true , fnsuffix: -macos-arm64 }
- { os: macos-13 , ocaml-version: 4.14.x , publish: true , fnsuffix: -macos-x86_64 }
- { os: ubuntu-22.04 , ocaml-version: 5.2.x }
- { os: ubuntu-22.04 , ocaml-version: 4.14.x }
- { os: ubuntu-22.04 , ocaml-version: "ocaml-variants.4.14.2+options,ocaml-option-32bit", publish: true, fnsuffix: -ubuntu-i386 }
- { os: ubuntu-20.04 , ocaml-version: 4.14.x }
- { os: windows-2022 , ocaml-version: "ocaml.4.14.2,system-mingw" , publish: true , fnsuffix: -windows-x86_64 }
- { os: windows-2019 , ocaml-version: "ocaml.4.14.2,system-mingw,arch-x86_32" , publish: true , fnsuffix: -windows-i386 }
- { os: windows-2022 , ocaml-version: "ocaml.4.14.2,system-msvc" }
- { os: windows-2019 , ocaml-version: "ocaml.4.14.2,system-msvc,arch-x86_32" }
runs-on: ${{ matrix.job.os }}
steps:
- if: contains(matrix.job.os, 'ubuntu')
run: sudo apt-get update
- name: Checkout code
uses: actions/checkout@v4
- name: Initialize workflow variables
id: vars
shell: bash
run: |
outputs() { for var in "$@" ; do echo steps.vars.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT ; done; }
# architecture/platform vars
EXE_suffix='' ; case '${{ matrix.job.os }}' in windows-*) EXE_suffix=".exe" ;; esac
MinGW_ARCH='x86_64' ; case '${{ matrix.job.ocaml-version }}' in *x86_32*) MinGW_ARCH='i686' ;; *mingw*) MinGW_ARCH='x86_64' ;; esac
WINBUILD_ARCH='x64' ; case '${{ matrix.job.ocaml-version }}' in *x86_32*) WINBUILD_ARCH='x86' ;; *x86_64*) WINBUILD_ARCH='x64' ;; esac
outputs EXE_suffix MinGW_ARCH WINBUILD_ARCH
MACOSX_DEPLOYMENT_TARGET=10.13
case '${{ matrix.job.os }}' in
macos-*) echo "MACOSX_DEPLOYMENT_TARGET=${MACOSX_DEPLOYMENT_TARGET}" >> $GITHUB_ENV ;
echo "XCODEFLAGS=-arch $(uname -m) -mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET} MACOSX_DEPLOYMENT_TARGET=${MACOSX_DEPLOYMENT_TARGET}" >> $GITHUB_ENV ;
echo "CFLAGS=${CFLAGS} -mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET}" >> $GITHUB_ENV ;;
esac
# staging environment
STAGING_DIR='_staging'
outputs STAGING_DIR
# parse commit reference info
echo GITHUB_REF=${GITHUB_REF}
echo GITHUB_SHA=${GITHUB_SHA}
REF_NAME="${GITHUB_REF#refs/*/}"
unset REF_BRANCH ; case "${GITHUB_REF}" in refs/heads/*) REF_BRANCH="${GITHUB_REF#refs/heads/}" ;; esac;
unset REF_TAG ; case "${GITHUB_REF}" in refs/tags/*) REF_TAG="${GITHUB_REF#refs/tags/}" ;; esac;
REF_SHAS="${GITHUB_SHA:0:8}"
outputs REF_BRANCH REF_NAME REF_SHAS REF_TAG
# deployable tag? (ie, leading "vM" or "M"; M == version number)
unset DEPLOY ; if [[ $REF_TAG =~ ^[vV]?[0-9].* ]]; then DEPLOY='true' ; fi
outputs DEPLOY
# package name
PKG_suffix='.tar.gz' ; case '${{ matrix.job.os }}' in windows-*) PKG_suffix='.zip' ;; esac;
PKG_VER="${REF_TAG:-git_$REF_SHAS}"
PKG_VER="${PKG_VER#v}"
PKG_BASENAME="${PROJECT_NAME}-${PKG_VER}${{ matrix.job.fnsuffix }}"
PKG_NAME="${PKG_BASENAME}${PKG_suffix}"
PKG_DIR="${STAGING_DIR}/${PKG_BASENAME}"
outputs PKG_VER PKG_BASENAME PKG_DIR PKG_NAME PKG_suffix
COMPRESS_CMD='tar czf'; case '${{ matrix.job.os }}' in windows-*) COMPRESS_CMD='7z -y a' ;; esac;
outputs COMPRESS_CMD
- name: Create/configure any needed build/workspace
shell: bash
run: |
# create build/work space
mkdir -p '${{ steps.vars.outputs.STAGING_DIR }}'
mkdir -p '${{ steps.vars.outputs.PKG_DIR }}'
mkdir -p '${{ steps.vars.outputs.PKG_DIR }}'/bin
- name: Use OCaml ${{ matrix.job.ocaml-version }}
uses: ocaml/setup-ocaml@v3
with:
ocaml-compiler: "${{ matrix.job.ocaml-version }}"
opam-pin: false
# setup-ocaml can prepare the build environment from unison.opam
# We're not relying on that capability here, to make sure the builds
# also work without using unison.opam
## note: at this point, after OCaml installation, windows platforms will use Cygwin bash as the default
## ... Cygwin bash cannot handle shell scripts containing CRLF EOLs (which are what is generated by GHA on windows platforms)
## ... so, "igncr" must be added to SHELLOPTS
- name: Prepare Cygwin environment (Windows)
if: runner.os == 'Windows'
shell: cmd
run: |
echo SHELLOPTS=igncr>> %GITHUB_ENV%
- shell: bash
env:
LDFLAGS: ${{ matrix.job.static }}
run: |
opam exec -- make tui
opam exec -- make fsmonitor
# stage
# * notes: darwin/macos doesn't build `unison-fsmonitor`
for file in ${PROJECT_EXES} ; do
if [ -f "src/${file}${{ steps.vars.outputs.EXE_suffix }}" ]; then
cp "src/${file}${{ steps.vars.outputs.EXE_suffix }}" '${{ steps.vars.outputs.PKG_DIR }}/bin'
echo "'src/${file}${{ steps.vars.outputs.EXE_suffix }}' copied to '${{ steps.vars.outputs.PKG_DIR }}/bin'"
fi
done
- run: opam exec -- make test
## There is still code to run tests with old ocaml on Windows.
## That remains intentionally so that someone could turn it on if
## desired.
- name: Run self-tests over RPC
if: runner.os == 'Windows' && !contains(matrix.job.ocaml-version, '4.14') && !contains(matrix.job.ocaml-version, '5.')
shell: bash
run: |
# Separate backup dir must be set for server instance so that the central
# backup location of both instances doesn't overlap
UNISONBACKUPDIR=./src/testbak2 ./src/unison -socket 55443 &
sleep 1 # Wait for the server to be fully started
./src/unison -ui text -selftest testr1 socket://127.0.0.1:55443/testr2 -killserver
- name: Run self-tests over local socket
# Recent Windows versions do support Unix domain sockets
# but at least OCaml 4.14 is required to use that support
if: runner.os != 'Windows' || contains(matrix.job.ocaml-version, '4.14') || contains(matrix.job.ocaml-version, '5.')
shell: bash
run: |
mkdir localsocket
chmod 700 localsocket
# Separate backup dir must be set for server instance so that the central
# backup location of both instances doesn't overlap
UNISONBACKUPDIR=./src/testbak4 ./src/unison -socket ./localsocket/test.sock &
sleep 1 # Wait for the server to be fully started
${{ runner.os == 'Windows' }} || test -S ./localsocket/test.sock
./src/unison -ui text -selftest testr3 socket://{./localsocket/test.sock}/testr4 -killserver
- name: Prepare lablgtk install (Windows)
if: ${{ runner.os == 'Windows' && contains(matrix.job.ocaml-version, 'mingw') }}
shell: bash
run: |
setup-x86_64.exe --quiet-mode --root "${CYGWIN_ROOT}" --site http://cygwin.mirror.constant.com --symlink-type=sys --packages hicolor-icon-theme,adwaita-icon-theme
# [2022-11] This terrible (terrible) hack is here to forcibly skip
# building the fontconfig cache because it can take 30-45 minutes
# on GHA runners and is never needed anyway.
setup-x86_64.exe --quiet-mode --root "${CYGWIN_ROOT}" --site http://cygwin.mirror.constant.com --symlink-type=sys --local-package-dir D:/a --download --packages mingw64-${{ steps.vars.outputs.MinGW_ARCH }}-fontconfig
cd 'D:/a/https%3a%2f%2fcygwin.mirror.constant.com%2f/noarch/release/'mingw64-${{ steps.vars.outputs.MinGW_ARCH }}-fontconfig
CNAMEXZ=$(ls mingw64-${{ steps.vars.outputs.MinGW_ARCH }}-fontconfig*.tar.xz)
CNAME=${CNAMEXZ%.xz}
unxz ${CNAMEXZ}
tar --delete --file ${CNAME} etc/postinstall/zp_mingw64-${{ steps.vars.outputs.MinGW_ARCH }}-fontconfig_cache.sh
xz ${CNAME}
sha512sum > sha512.sum
CSZ=$(stat -c %s ${CNAMEXZ})
SHASUM=$(sha512sum ${CNAMEXZ})
cd 'D:/a/https%3a%2f%2fcygwin.mirror.constant.com%2f/x86_64'
mv setup.ini tsetup.ini
rm -f setup*
sed -E -e "\|install: noarch/release/mingw64-${{ steps.vars.outputs.MinGW_ARCH }}-fontconfig/${CNAMEXZ}|s/xz .+/xz ${CSZ} ${SHASUM%% *}/" tsetup.ini > setup.ini
rm tsetup.ini
sha512sum > sha512.sum
setup-x86_64.exe --quiet-mode --root "${CYGWIN_ROOT}" --symlink-type=sys --local-install --local-package-dir 'D:/a/https%3a%2f%2fcygwin.mirror.constant.com%2f' --mirror-mode --no-verify --packages mingw64-${{ steps.vars.outputs.MinGW_ARCH }}-fontconfig
# [2024-11] Not exactly sure what is happening here, but opam
# packages using pkg-config will fail in Windows without this.
# /usr/bin/pkg-config is a symlink to /usr/bin/pkgconf
# This does not work when opam packages try to execute pkg-config
# directly (that is, D:\cygwin\bin\pkg-config).
# It looks like this issue is being worked around package-by-package
# upstream, but the fix here is universal, so let's keep it for now.
cp /usr/bin/pkgconf /usr/bin/pkg-config.exe
# [2024-11] opam depext has been broken/disabled by migration to
# opam >= 2.2 which can support Windows natively. System dependencies
# in Windows must be installed manually (for now, at least).
setup-x86_64.exe --quiet-mode --root "${CYGWIN_ROOT}" --site http://cygwin.mirror.constant.com --symlink-type=sys --packages mingw64-${{ steps.vars.outputs.MinGW_ARCH }}-cairo,mingw64-${{ steps.vars.outputs.MinGW_ARCH }}-gtk3
# [2024-11] Setting PKG_CONFIG_LIBDIR like this is required with
# opam >= 2.2 which can support Windows natively. Not sure why,
# but it's likely due to pkg-conf being executed "outside" Cygwin
# environment.
echo PKG_CONFIG_LIBDIR=/usr/${{ steps.vars.outputs.MinGW_ARCH }}-w64-mingw32/sys-root/mingw/lib/pkgconfig >> "$GITHUB_ENV"
- name: "Windows: Cache GTK installation"
if: ${{ runner.os == 'Windows' && contains(matrix.job.ocaml-version, 'msvc') }}
id: win-gtk-cache
uses: actions/cache@v4
with:
key: wingtk-${{ matrix.job.os }}-${{ steps.vars.outputs.WINBUILD_ARCH }}
path: D:\gtk
- if: ${{ runner.os == 'Windows' && contains(matrix.job.ocaml-version, 'msvc') && !steps.win-gtk-cache.outputs.cache-hit }}
uses: actions/setup-python@v5
with:
python-version: 3.x
- name: "Windows: Install GTK"
# 32-bit GTK builds are not distributed; build locally
if: ${{ runner.os == 'Windows' && contains(matrix.job.ocaml-version, 'msvc') && !steps.win-gtk-cache.outputs.cache-hit }}
shell: pwsh
run: |
$env:PIPX_DEFAULT_PYTHON = (Get-Command -CommandType Application python -Syntax | Select-Object -First 1)
$env:PIPX_HOME = ".\pipx"
mkdir pipx
pipx install gvsbuild
gvsbuild build --platform ${{ steps.vars.outputs.WINBUILD_ARCH }} --configuration release --ninja-opts -j2 --vs-install-path $(Resolve-Path "C:\Program Files*\Microsoft Visual Studio\*\*\" | Select-Object -First 1) --build-dir D:\gtk-build gtk3
Move-Item "D:\gtk-build\gtk\*\release" D:\gtk
# Reset PKG_CONFIG_PATH, which would otherwise point to Python installation in GHA
"PKG_CONFIG_PATH=" >> "${env:GITHUB_ENV}"
# Disabled, but here for the record. 64-bit installation only
#- name: "Windows: Install GTK"
# if: ${{ false && runner.os == 'Windows' && contains(matrix.job.ocaml-version, 'msvc') && !contains(matrix.job.ocaml-version, 'x86_32') }}
# shell: pwsh
# run: |
# Invoke-WebRequest https://github.com/wingtk/gvsbuild/releases/download/2024.11.1/GTK3_Gvsbuild_2024.11.1_x64.zip -OutFile GTK3.zip
# Expand-Archive -Path GTK3.zip -DestinationPath D:\gtk
- name: "Windows: Prepare lablgtk install"
if: ${{ runner.os == 'Windows' && contains(matrix.job.ocaml-version, 'msvc') }}
shell: pwsh
run: |
# Prevent Cygwin env messing up the Windows build (opam will add Cygwin
# back to PATH, but still...)
# [2024-12] Somehow this was not required before a dune update that
# switched from using pkg-config to pkgconf, but doing this should not
# hurt in any case.
rm D:\cygwin\bin\pkgconf*
rm D:\cygwin\bin\pkg-config*
"PKG_CONFIG=D:\gtk\bin\pkgconf.exe" >> "${env:GITHUB_ENV}"
$env:Path = (${env:Path} -split ';' | Where-Object { $_ -Notlike "*cygwin*" }) -join ";"
##
"PATH=D:\gtk\bin;${env:Path}" >> "${env:GITHUB_ENV}"
"LIB=D:\gtk\lib;${env:LIB}" >> "${env:GITHUB_ENV}"
"INCLUDE=D:\gtk\include;D:\gtk\include\cairo;D:\gtk\include\glib-2.0;D:\gtk\include\gobject-introspection-1.0;D:\gtk\lib\glib-2.0\include;${env:INCLUDE}" >> "${env:GITHUB_ENV}"
"PKG_CONFIG_PATH=D:\gtk\lib\pkgconfig" >> "${env:GITHUB_ENV}"
# [2024-12] Patch opam packages for MSVC. Only needed for as long as
# upstream does not work with MSVC out of the box.
mkdir _opampkgs
cd _opampkgs
opam source cairo2
cd cairo2*
@'
--- a/config/discover.ml
+++ b/config/discover.ml
@@ -15,7 +15,7 @@ let default_cairo c =
libs = ["/LC:\\gtk\\lib"; "cairo.lib"] }
else { P.cflags = ["-I/usr/include/cairo"]; libs = ["-lcairo"] }
-let c_header_has_ft () =
+let c_header ~has_ft () =
let fh = open_in "cairo_ocaml.h.p" in
let buf = Buffer.create 4096 in
let b = Bytes.create 4096 in
@@ -25,8 +25,12 @@ let c_header_has_ft () =
done;
close_in fh;
let s = Buffer.contents buf in
- let re = Str.regexp "/\\* *#define *OCAML_CAIRO_HAS_FT .*\\*/" in
- let s = Str.global_replace re "#define OCAML_CAIRO_HAS_FT 1" s in
+ let s =
+ if has_ft then
+ let re = Str.regexp "/\\* *#define *OCAML_CAIRO_HAS_FT .*\\*/" in
+ Str.global_replace re "#define OCAML_CAIRO_HAS_FT 1" s
+ else s
+ in
let fh = open_out "cairo_ocaml.h" in
output_string fh s;
close_out fh
@@ -70,7 +74,8 @@ let discover_cairo c =
| C.C_define.Value.Switch b -> b
| _ -> false in
let cflags, libs =
- if has_ft_font && has_fc_font then (
+ c_header ~has_ft:has_ft_font ();
+ if has_ft_font || has_fc_font then (
match P.get c with
| Some p ->
(match P.query p ~package:"fontconfig freetype2" with
@@ -81,7 +86,6 @@ let discover_cairo c =
if String.length f > 2 && f.[0] = '-' && f.[1] = 'I' then
f :: (f ^ "/freetype") :: l
else f :: l in
- c_header_has_ft ();
(List.fold_left freetype [] f.cflags @ cflags,
f.libs @ libs)
| None -> cflags, libs)
--- a/src/cairo_stubs.c
+++ b/src/cairo_stubs.c
@@ -1082,7 +1082,7 @@ CAMLexport value caml_cairo_scaled_font_get_type(value vff)
/* Ft : TrueType fonts
***********************************************************************/
-#if CAIRO_HAS_FT_FONT && CAIRO_HAS_FC_FONT
+#if CAIRO_HAS_FT_FONT
#include <cairo-ft.h>
CAMLexport value caml_cairo_Ft_init_FreeType(value unit)
@@ -1132,6 +1132,8 @@ CAMLexport value caml_cairo_ft_create_for_ft_face(
CAMLreturn(vff);
}
+#if CAIRO_HAS_FC_FONT
+
CAMLexport value caml_cairo_ft_create_for_pattern(
value voptions, value vpattern)
{
@@ -1170,6 +1172,12 @@ CAMLexport value caml_cairo_ft_create_for_pattern(
CAMLreturn(vff);
}
+#else
+
+UNAVAILABLE2(cairo_ft_create_for_pattern)
+
+#endif
+
CAMLexport value caml_cairo_ft_scaled_font_lock_face(value vsf)
{
CAMLparam1(vsf);
@@ -1228,15 +1236,15 @@ CAMLexport value caml_cairo_ft_synthesize_unset(
#else
-UNAVAILABLE1(Ft_init_FreeType)
-UNAVAILABLE2(caml_Ft_new_face)
-UNAVAILABLE3(caml_cairo_ft_create_for_ft_face)
-UNAVAILABLE2(caml_cairo_ft_create_for_pattern)
-UNAVAILABLE1(caml_cairo_ft_scaled_font_lock_face)
-UNAVAILABLE1(caml_cairo_ft_scaled_font_unlock_face)
-UNAVAILABLE1(caml_cairo_ft_synthesize_get)
-UNAVAILABLE3(caml_cairo_ft_synthesize_set)
-UNAVAILABLE3(caml_cairo_ft_synthesize_unset)
+UNAVAILABLE1(cairo_Ft_init_FreeType)
+UNAVAILABLE2(cairo_Ft_new_face)
+UNAVAILABLE3(cairo_ft_create_for_ft_face)
+UNAVAILABLE2(cairo_ft_create_for_pattern)
+UNAVAILABLE1(cairo_ft_scaled_font_lock_face)
+UNAVAILABLE1(cairo_ft_scaled_font_unlock_face)
+UNAVAILABLE1(cairo_ft_synthesize_get)
+UNAVAILABLE3(cairo_ft_synthesize_set)
+UNAVAILABLE3(cairo_ft_synthesize_unset)
#endif
@@ -1613,13 +1621,13 @@ SURFACE_CREATE_DATA(data8)
SURFACE_CREATE_DATA(data32)
#undef b
-#define SURFACE_GET_DATA(type, num_dims, dims ...) \
+#define SURFACE_GET_DATA(type, num_dims, ...) \
CAMLexport value caml_cairo_image_surface_get_##type(value vsurf) \
{ \
CAMLparam1(vsurf); \
CAMLlocal1(vb); \
unsigned char* data = cairo_image_surface_get_data(SURFACE_VAL(vsurf)); \
- intnat dim[num_dims] = {dims}; \
+ intnat dim[num_dims] = {__VA_ARGS__}; \
struct caml_ba_proxy * proxy = (struct caml_ba_proxy *) \
cairo_surface_get_user_data(SURFACE_VAL(vsurf), &image_bigarray_key); \
\
'@ | patch -Nu -p 1
opam pin --no-action add cairo2 .
cd ..
opam source lablgtk3
cd lablgtk3*
@'
--- a/lablgtk3.opam
+++ b/lablgtk3.opam
@@ -22,8 +22,6 @@ depends: [
"dune" { >= "1.8.0" }
"cairo2" { >= "0.6" }
"conf-gtk3" { >= "18" }
- "ocamlfind" { dev }
- "camlp5" { dev }
]
build: [
--- a/src/dune
+++ b/src/dune
@@ -34,6 +34,6 @@
ml_gtkmenu ml_gtkfile ml_gtktree ml_gtkpack
ml_gtkstock ml_gtkrange ml_gtkassistant
)
- (c_flags (:include cflag-gtk+-3.0.sexp) (:include cflag-extraflags.sexp) -Wno-deprecated-declarations)
+ (c_flags (:include cflag-gtk+-3.0.sexp) (:include cflag-extraflags.sexp))
(c_library_flags (:include clink-gtk+-3.0.sexp))
(libraries threads cairo2))
'@ | patch -Nu -p 1
opam pin --no-action add lablgtk3 .
- name: "Ubuntu: Prepare lablgtk install (i386)"
if: ${{ contains(matrix.job.os, 'ubuntu') && contains(matrix.job.ocaml-version, '-32bit') }}
run: |
sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt-get install libgtk-3-dev:i386 libexpat1-dev:i386
echo PKG_CONFIG_LIBDIR=/usr/lib/i386-linux-gnu/pkgconfig:/usr/share/pkgconfig:"$PKG_CONF_LIBDIR" >> "$GITHUB_ENV"
# [2024-12] Recent dune release switched from using pkg-config to pkgconf.
# However, pkgconf is broken in many environments and this breaks building
# cairo2, a dependency for lablgtk3 (and likely would break lablgtk3, too,
# if building ever got to that point). ubuntu-20.04 is one such case
# (pkgconf segfaults). As a workaround, just uninstall pkgconf, which makes
# dune fall back to pkg-config.
- name: "Ubuntu 20.04: Prepare lablgtk install"
if: ${{ contains(matrix.job.os, 'ubuntu-20.04') }}
run: sudo apt-get remove pkgconf
- name: lablgtk install
## [2020-09] non-working/unavailable for musl OCaml variant
if: ${{ !contains(matrix.job.ocaml-version, '-musl') }}
run: opam install lablgtk3 ocamlfind
- if: ${{ !matrix.job.static }} ## unable to build static gtk/gui
shell: bash
run: |
opam exec -- make gui
# stage
# * copy only main/first project binary
project_exe_stem=${PROJECT_EXES%% *}
cp "src/${project_exe_stem}-gui${{ steps.vars.outputs.EXE_suffix }}" "${{ steps.vars.outputs.PKG_DIR }}/bin/"
- name: "Build WinOS text+gui hybrid"
if: ${{ runner.os == 'Windows' && !matrix.job.static && !contains(matrix.job.ocaml-version, 'msvc') }} ## WinOS, non-static (unable to build static gtk/gui)
shell: bash
run: |
# create and stage text+gui hybrid for Windows
# * copy only main/first project binary
project_exe_stem=${PROJECT_EXES%% *}
# * clean/remove build artifact(s)
rm "src/${project_exe_stem}-gui${{ steps.vars.outputs.EXE_suffix }}" ##.or.# opam exec -- make -C src clean #.or.# opam exec -- make clean
# * re-create (with hybrid text+gui UI)
opam exec -- make gui UI_WINOS=hybrid
cp "src/${project_exe_stem}-gui${{ steps.vars.outputs.EXE_suffix }}" "${{ steps.vars.outputs.PKG_DIR }}/bin/${project_exe_stem}-text+gui${{ steps.vars.outputs.EXE_suffix }}"
- uses: actions/upload-artifact@v4
if: false ## disable by default; only useful for debugging GHA
with:
name: unison-${{ steps.vars.outputs.REF_SHAS }}.ocaml-${{ matrix.job.ocaml-version }}.${{ matrix.job.os }}
path: ${{ steps.vars.outputs.PKG_DIR }}/bin/*
- name: Copy user manual
continue-on-error: ${{ !(steps.vars.outputs.DEPLOY && matrix.job.publish) }}
uses: actions/download-artifact@v4
with:
name: unison-docs
path: '${{ steps.vars.outputs.PKG_DIR }}'
- name: Prepare package
# if: steps.vars.outputs.DEPLOY
shell: bash
run: |
## package artifact(s)
PKG_DIR='${{ steps.vars.outputs.PKG_DIR }}'
# `strip` binaries
strip "${PKG_DIR}/bin"/*'${{ steps.vars.outputs.EXE_suffix }}'
# README and LICENSE
(shopt -s nullglob; for f in [R]'EADME'{,.*}; do cp $f "${PKG_DIR}"/ ; done)
(shopt -s nullglob; for f in [L]'ICENSE'{-*,}{,.*}; do cp $f "${PKG_DIR}"/ ; done)
cp INSTALL.md "${PKG_DIR}"/
cp CONTRIBUTING.md "${PKG_DIR}"/
cp NEWS.md "${PKG_DIR}"/
- if: ${{ runner.os == 'Windows' && contains(matrix.job.ocaml-version, 'mingw') }}
name: "Windows: Package gtk"
shell: bash
run: |
# [2023-03] Setting this PATH here (and it has to be right here) is
# a workaround for an unknown issue (most likely something with GHA)
# causing MinGW binutils not to be found (while other binutils
# pre-installed in the GHA images may be found instead), which in turn
# causes the DLL extracting functions to silently fail.
export PATH="/usr/${{ steps.vars.outputs.MinGW_ARCH }}-w64-mingw32/bin":"/usr/${{ steps.vars.outputs.MinGW_ARCH }}-w64-mingw32/sys-root/mingw/bin":${PATH}
## package artifact(s)
PKG_DIR='${{ steps.vars.outputs.PKG_DIR }}'
# collect any needed dlls/libraries
# dlls
dll_refs() { eval "$(opam env)" ; objdump -x "$@" | grep -Po "\S+[.]dll$" | xargs -I{} 2>/dev/null which "{}" | sort -u ; }
filtered_dll_refs() { list="$(dll_refs "$@" | grep -vF "$(cygpath ${WINDIR})" | perl -lape '$_ = qq/@{[sort @F]}/')" ; echo "$list" ; }
recursive_filtered_dll_refs() { list="$(filtered_dll_refs "$@")" ; n=0 ; while [ $n -lt $(echo "$list" | wc -l) ]; do n=$(echo "$list" | wc -l) ; list="$(filtered_dll_refs $list)" ; done ; echo "$list" ; }
IFS=$'\n' DLL_list=( "$(recursive_filtered_dll_refs "${PKG_DIR}"/bin/*)" )
for dll in ${DLL_list[@]} ; do cp "${dll}" "${PKG_DIR}"/bin ; done
# required gdk support files
mkdir "${PKG_DIR}"/lib
cp -r /usr/${{ steps.vars.outputs.MinGW_ARCH }}-w64-mingw32/sys-root/mingw/lib/gdk-pixbuf-2.0 "${PKG_DIR}"/lib/
# update loader.cache to point to local relative installation
mv "${PKG_DIR}"/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache "${PKG_DIR}"/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache.original
cat "${PKG_DIR}"/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache.original | sed -E 's#([^"]*)(lib/gdk-pixbuf-2.0/2.10.0/loaders/[^"]*[.]dll)#../\2#' > "${PKG_DIR}"/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache
rm "${PKG_DIR}"/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache.original
# required icons
mkdir "${PKG_DIR}"/share
cp -rL /usr/share/icons "${PKG_DIR}"/share
# compile glib settings schema
mkdir -p "${PKG_DIR}"/share/glib-2.0
cp -r /usr/${{ steps.vars.outputs.MinGW_ARCH }}-w64-mingw32/sys-root/mingw/share/glib-2.0/schemas "${PKG_DIR}"/share/glib-2.0
glib-compile-schemas "${PKG_DIR}"/share/glib-2.0/schemas
# add gtk configuration
mkdir -p "${PKG_DIR}"/etc/gtk-3.0
printf "[Settings]\ngtk-button-images=true\ngtk-font-name=Segoe UI 9\n" > "${PKG_DIR}"/etc/gtk-3.0/settings.ini
- if: ${{ runner.os == 'Windows' && contains(matrix.job.ocaml-version, 'msvc') }}
name: "Windows: Package gtk"
shell: pwsh
run: |
# Make sure MSVC is in the path (for dumpbin) and GTK is first in path
opam env | Invoke-Expression
$env:Path = "C:\gtk\bin;" + $env:Path
# collect any needed dlls/libraries
function recursive_deps { param ($prefix, $list, $filename) if ($list.Keys -contains $filename.ToLower()) { Write-Debug "$prefix NOT dumping $filename"; return }; Write-Debug "$prefix DUMPING $filename"; $files = (dumpbin /dependents $filename | ForEach-Object { $_.Trim() | Where-Object { $_ -Like "*.dll" } } | ForEach-Object { Get-Command -CommandType Application -Syntax -ErrorAction SilentlyContinue $_ | Select-Object -First 1 | Where-Object { $_ -notlike "$env:WINDIR*" -and $_ -notlike "*\api-ms-win-*" } }); $list[$filename.ToLower()] = $files; $files | ForEach-Object { recursive_deps " $prefix" $list $_ } }
function all_deps { param ($filename) $dep_list = @{}; recursive_deps "" $dep_list $filename; $dep_list.Values | ForEach-Object {$_} | Sort-Object -CaseSensitive | Get-Unique }
cd "${{ steps.vars.outputs.PKG_DIR }}\bin"
Get-ChildItem | ForEach-Object { all_deps $_.FullName | ForEach-Object { Write-Debug $_; Copy-Item $_ } }
cd ..
# glib settings schema
mkdir -p "share\glib-2.0\schemas"
Split-Path (Get-Command -Type Application glib-compile-schemas).Source | Join-Path -ChildPath "..\share\glib-2.0\schemas\gschemas.compiled" | Copy-Item -Destination "share\glib-2.0\schemas"
# add gtk configuration
mkdir -p "etc\gtk-3.0"
"[Settings]`ngtk-button-images=true`n" > "etc\gtk-3.0\settings.ini"
- name: Package
shell: bash
run: cd '${{ steps.vars.outputs.PKG_DIR }}/' && ${{ steps.vars.outputs.COMPRESS_CMD }} '../${{ steps.vars.outputs.PKG_NAME }}' *
- uses: actions/upload-artifact@v4
if: matrix.job.publish
with:
name: ${{ steps.vars.outputs.PKG_NAME }}___ocaml-${{ matrix.job.ocaml-version }}.${{ matrix.job.os }}-publish
path: ${{ steps.vars.outputs.STAGING_DIR }}/${{ steps.vars.outputs.PKG_NAME }}
- name: Publish
if: steps.vars.outputs.DEPLOY && matrix.job.publish
uses: softprops/action-gh-release@v1
with:
files: |
${{ steps.vars.outputs.STAGING_DIR }}/${{ steps.vars.outputs.PKG_NAME }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- if: runner.os == 'macOS'
name: "macOS: Build and package Unison.app"
id: macapp
run: |
opam exec -- make macui
# package
APP_NAME=Unison-${{ steps.vars.outputs.PKG_VER }}${{ matrix.job.fnsuffix }}.app.tar.gz
echo APP_NAME=${APP_NAME} >> $GITHUB_OUTPUT
tar czf ${APP_NAME} -C src/uimac/build/Default Unison.app
- if: runner.os == 'macOS' && matrix.job.publish
name: "macOS: Upload Unison.app artifact"
uses: actions/upload-artifact@v4
with:
name: ${{ steps.macapp.outputs.APP_NAME }}___ocaml-${{ matrix.job.ocaml-version }}.${{ matrix.job.os }}-publish
path: ${{ steps.macapp.outputs.APP_NAME }}
- if: runner.os == 'macOS' && steps.vars.outputs.DEPLOY && matrix.job.publish
name: "macOS: Publish Unison.app"
uses: softprops/action-gh-release@v1
with:
files: ${{ steps.macapp.outputs.APP_NAME }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
rpc_abicheck:
needs: build
strategy:
fail-fast: false
matrix:
# This list is intended to balance good enough coverage and
# limited resource usage.
job:
- { os: ubuntu-22.04 , ocaml-version: 5.2.x , ref: v2.53.7 }
- { os: ubuntu-22.04 , ocaml-version: 4.14.x , ref: v2.53.7 }
- { os: ubuntu-22.04 , ocaml-version: 4.14.x , ref: v2.52.1 , oldmake: true }
- { os: ubuntu-22.04 , ocaml-version: 4.14.x , ref: v2.51.5 , oldmake: true }
- { os: ubuntu-22.04 , ocaml-version: 4.08.x , ref: v2.51.5 , oldmake: true }
- { os: ubuntu-22.04 , ocaml-version: 4.08.x , ref: v2.51.2 , oldmake: true }
- { os: windows-2019 , ocaml-version: ocaml-variants.4.14.0+mingw64c , ref: v2.53.7 }
- { os: windows-2019 , ocaml-version: ocaml-variants.4.14.0+mingw64c , ref: v2.52.1 , oldmake: true }
- { os: windows-2019 , ocaml-version: ocaml-variants.4.08.1+mingw32c , ref: v2.51.5 , oldmake: true }
- { os: macos-13 , ocaml-version: 4.14.x , ref: v2.53.7 }
- { os: macos-13 , ocaml-version: 4.14.x , ref: v2.52.1 , oldmake: true }
- { os: macos-13 , ocaml-version: 4.08.x , ref: v2.51.2 , oldmake: true }
runs-on: ${{ matrix.job.os }}
steps:
- if: contains(matrix.job.os, 'ubuntu')
run: sudo apt-get update
- name: Use OCaml ${{ matrix.job.ocaml-version }}
uses: ocaml/setup-ocaml@v2
with:
ocaml-compiler: "${{ matrix.job.ocaml-version }}"
opam-pin: false
opam-depext: false
# setup-ocaml can prepare the build environment from unison.opam
# We're not relying on that capability here, to make sure the builds
# also work without using unison.opam
- name: Prepare Cygwin environment (Windows)
if: runner.os == 'Windows'
shell: cmd
run: |
echo %CYGWIN_ROOT_BIN%>> %GITHUB_PATH%
echo %CYGWIN_ROOT_WRAPPERBIN%>> %GITHUB_PATH%
echo SHELLOPTS=igncr>> %GITHUB_ENV%
- name: Checkout HEAD to _new
uses: actions/checkout@v4
with:
path: _new
- run: cd _new && opam exec -- make tui
shell: bash
- name: Checkout ${{ matrix.job.ref }} to _prev
uses: actions/checkout@v4
with:
ref: "${{ matrix.job.ref }}"
path: _prev
- name: "2.51.0: Patch connection header in _prev"
if: contains(matrix.job.ref, '2.51.0')
shell: bash
run: |
# Connection header string was broken in 2.51.0
cd _prev && git apply - <<"EOF"
diff --git a/src/remote.ml b/src/remote.ml
index ddca0d77..7f819eab 100644
--- a/src/remote.ml
+++ b/src/remote.ml
@@ -920,7 +920,7 @@ let connectionHeader =
Scanf.sscanf Sys.ocaml_version "%d.%d.%d" (fun x y z -> (x,y,z)) in
let compiler =
if major < 4
- || major = 4 && minor <= 2
+ || major = 4 && minor < 2
|| major = 4 && minor = 2 && patchlevel <= 1
then "<= 4.01.1"
else ">= 4.01.2"
EOF
- name: "2.51.{2,3}: Patch bugs in _prev"
if: contains(matrix.job.ref, '2.51.2') || contains(matrix.job.ref, '2.51.3')
shell: bash
run: |
cd _prev && git apply - <<"EOF"
diff --git a/src/bytearray_stubs.c b/src/bytearray_stubs.c
index 2b29421a..2850f2d8 100644
--- a/src/bytearray_stubs.c
+++ b/src/bytearray_stubs.c
@@ -10,7 +10,7 @@
CAMLprim value ml_marshal_to_bigarray(value v, value flags)
{
char *buf;
- long len;
+ intnat len;
output_value_to_malloc(v, flags, &buf, &len);
return alloc_bigarray(BIGARRAY_UINT8 | BIGARRAY_C_LAYOUT | BIGARRAY_MANAGED,
1, buf, &len);
diff --git a/src/uicommon.ml b/src/uicommon.ml
index 9fa94cf5..65fc37a5 100644
--- a/src/uicommon.ml
+++ b/src/uicommon.ml
@@ -494,10 +494,11 @@ let promptForRoots getFirstRoot getSecondRoot =
(* ---- *)
let makeTempDir pattern =
- let ic = Unix.open_process_in (Printf.sprintf "(mktemp --tmpdir -d %s.XXXXXX || mktemp -d -t %s) 2>/dev/null" pattern pattern) in
- let path = input_line ic in
- ignore (Unix.close_process_in ic);
- path
+ let path = Filename.temp_file pattern "" in
+ let fspath = System.fspathFromString path in
+ System.unlink fspath; (* Remove file created by [temp_file]... *)
+ System.mkdir fspath 0o755; (* ... and create a dir instead. *)
+ path ^ Filename.dir_sep
(* The first time we load preferences, we also read the command line
arguments; if we re-load prefs (because the user selected a new profile)
EOF
- name: "2.51.2: Patch _prev for mingw compilers"
if: contains(matrix.job.ref, '2.51.2')
shell: bash
run: |
cd _prev && git apply - <<"EOF"
diff --git a/src/Makefile.OCaml b/src/Makefile.OCaml
index 7cefa2ec..95b1bec4 100644
--- a/src/Makefile.OCaml
+++ b/src/Makefile.OCaml
@@ -107,8 +107,8 @@ CAMLFLAGS+=-I system/$(SYSTEM) -I lwt/$(SYSTEM)
ifeq ($(OSARCH),win32)
# Win32 system
EXEC_EXT=.exe
- OBJ_EXT=.obj
- OUTPUT_SEL=/Fo
+ OBJ_EXT=.o
+ OUTPUT_SEL=-o
CWD=.
# Fix suggested by Karl M, Jan 2009:
# "The new flexlink wrapper that OCaml 3.11 uses was gagging on the res
@@ -120,8 +120,6 @@ ifeq ($(OSARCH),win32)
COBJS+=system/system_win_stubs$(OBJ_EXT) lwt/lwt_unix_stubs$(OBJ_EXT)
WINOBJS=system/system_win.cmo
SYSTEM=win
- CLIBS+=-cclib "-link win32rc/unison.res" shell32.lib
- STATICLIBS+=-cclib "-link win32rc/unison.res" shell32.lib
buildexecutable::
@echo Building for Windows
else
EOF
- name: "2.51.2: Patch _prev for newer compilers/OS"
if: contains(matrix.job.ref, '2.51.2')
shell: bash
run: |
cd _prev && git apply - <<"EOF"
diff --git a/src/Makefile.OCaml b/src/Makefile.OCaml
index 7cefa2ec..ffc3ab9e 100644
--- a/src/Makefile.OCaml
+++ b/src/Makefile.OCaml
@@ -180,7 +180,7 @@ else
buildexecutable:: $(NAME)$(EXEC_EXT)
endif
-MINOSXVERSION=10.5
+MINOSXVERSION=10.7
# XCODEFLAGS=-sdk macosx$(MINOSXVERSION)
ifeq ($(OSARCH),osx)
CAMLFLAGS+=-ccopt -mmacosx-version-min=$(MINOSXVERSION)
diff --git a/src/files.ml b/src/files.ml
index 5ff18810..1d1fbcc6 100644
--- a/src/files.ml
+++ b/src/files.ml
@@ -734,7 +734,7 @@ let get_files_in_directory dir =
with End_of_file ->
dirh.System.closedir ()
end;
- Sort.list (<) !files
+ List.sort String.compare !files
let ls dir pattern =
Util.convertUnixErrorsToTransient
diff --git a/src/recon.ml b/src/recon.ml
index 2c619bb8..2412c18e 100644
--- a/src/recon.ml
+++ b/src/recon.ml
@@ -661,8 +661,8 @@ let rec reconcile
(* Sorts the paths so that they will be displayed in order *)
let sortPaths pathUpdatesList =
- Sort.list
- (fun (p1, _) (p2, _) -> Path.compare p1 p2 <= 0)
+ List.sort
+ Path.compare
pathUpdatesList
let rec enterPath p1 p2 t =
diff --git a/src/system/system_generic.ml b/src/system/system_generic.ml
index 453027d0..290851e1 100755
--- a/src/system/system_generic.ml
+++ b/src/system/system_generic.ml
@@ -47,7 +47,7 @@ let open_out_gen = open_out_gen
let chmod = Unix.chmod
let chown = Unix.chown
let utimes = Unix.utimes
-let link = Unix.link
+let link x y = Unix.link x y
let openfile = Unix.openfile
let opendir f =
let h = Unix.opendir f in
EOF
- name: "2.51.0 - 2.52.1: Patch tests in _prev"
if: contains(matrix.job.ref, '2.51') || matrix.job.ref == 'v2.52.0' || matrix.job.ref == 'v2.52.1'
shell: bash
run: |
cd _prev && git apply - <<"EOF"
diff --git a/src/test.ml b/src/test.ml
index 3d480409..60ed014d 100644
--- a/src/test.ml
+++ b/src/test.ml
@@ -542,6 +542,77 @@ let test() =
*)
end;
+ if not bothRootsLocal then
+ begin
+ let localR, remoteR, localRaw =
+ match r1 with
+ | Common.Local, _ -> R1, R2, r1
+ | _ -> R2, R1, r2
+ in
+
+ (* Test RPC function "fingerprintSubfile" *)
+ runtest "RPC: transfer append" [] (fun () ->
+ let prefixLen = 1024 * 1024 + 1 in
+ let len = prefixLen + 31 in
+ let contents = String.make len '.' in
+ let fileName = "bigfile" in
+ let prefixPath = Path.fromString fileName in
+ let (workingDir, _) = Fspath.findWorkingDir (snd localRaw) prefixPath in
+ let prefixName = Path.toString (Os.tempPath ~fresh:false workingDir prefixPath) in
+ put remoteR (Dir [(fileName, File contents)]);
+ put localR (Dir [(prefixName, File (String.sub contents 0 prefixLen))]);
+ sync ();
+ check "1" localR (Dir [(fileName, File contents)]);
+ );
+
+ (* Test RPC function "updateProps" *)
+ runtest "RPC: update props" ["times = true"] (fun () ->
+ let state = [("a", File "x")] in
+ put remoteR (Dir state);
+ put localR (Dir []);
+ sync ();
+ (* Having to sleep here is an unfortunate side-effect of the current
+ Windows limitations-inspired time comparison algorithm which is
+ designed to work on FAT filesystems (2-second granularity). *)
+ Unix.sleep 2;
+ put remoteR (Dir state);
+ sync ();
+ check "1" localR (Dir state);
+ );
+
+ (* Test RPC function "replaceArchive" *)
+ runtest "RPC: replaceArchive" [] (fun () ->
+ put localR (Dir [("n", File "to delete")]);
+ put remoteR (Dir []);
+ sync ();
+ put remoteR (Dir []);
+ sync ();
+ check "1" localR (Dir []);
+ );
+
+ (* Test RPC functions "mkdir" and "setDirProp" *)
+ runtest "RPC: mkdir, setDirProp" [] (fun () ->
+ let state = [("subd", Dir [])] in
+ put localR (Dir state);
+ put remoteR (Dir []);
+ sync ();
+ check "1" remoteR (Dir state);
+ );
+
+ (* Test RPC function "setupTargetPaths" *)
+ runtest "RPC: merge" ["merge = Name ma -> echo x> NEW"; "backupcurr = Name ma"] (fun () ->
+ let result = match Sys.os_type with
+ | "Win32" -> ("ma", File "x\r\n")
+ | _ -> ("ma", File "x\n")
+ in
+ put localR (Dir [("ma", File "a")]);
+ put remoteR (Dir [("ma", File "b")]);
+ sync ();
+ check "1" localR (Dir [result]);
+ check "2" remoteR (Dir [result]);
+ );
+ end;
+
if !failures = 0 then
Util.msg "Success :-)\n"
else
EOF
- name: "2.52.0: Patch _prev for newer compilers"
if: contains(matrix.job.ref, '2.52.0')
shell: bash
run: |
cd _prev && git apply - <<"EOF"
diff --git a/src/system/system_win_stubs.c b/src/system/system_win_stubs.c
index 50ea663f..57940d98 100644
--- a/src/system/system_win_stubs.c
+++ b/src/system/system_win_stubs.c
@@ -373,7 +373,7 @@ typedef enum _FILE_INFORMATION_CLASS {
#include <caml/version.h> /* Available since OCaml 4.02 */
#endif
-#if !defined(OCAML_VERSION) || OCAML_VERSION < 40300
+#if !defined(OCAML_VERSION) || OCAML_VERSION < 40300 || OCAML_VERSION >= 41400
typedef struct _REPARSE_DATA_BUFFER {
ULONG ReparseTag;
EOF
- name: "2.52 - 2.53.3: Patch _prev for newer compilers"
if: contains(matrix.job.ref, '2.52') || matrix.job.ref == 'v2.53.0' || matrix.job.ref == 'v2.53.1' || matrix.job.ref == 'v2.53.2' || matrix.job.ref == 'v2.53.3'
shell: bash
run: |
cd _prev && git apply - <<"EOF"
diff --git a/src/lwt/lwt_unix_stubs.c b/src/lwt/lwt_unix_stubs.c
index 37154710..51caabff 100644
--- a/src/lwt/lwt_unix_stubs.c
+++ b/src/lwt/lwt_unix_stubs.c
@@ -392,8 +392,8 @@ CAMLprim value win_check_connection (value socket, value kind, value h) {
static HANDLE dummyEvent;
-CAMLprim value init_lwt (value callback) {
- CAMLparam1 (callback);
+CAMLprim value init_lwt (value callb) {
+ CAMLparam1 (callb);
// GUID GuidConnectEx = WSAID_CONNECTEX;
// SOCKET s;
// DWORD l;
@@ -401,7 +401,7 @@ CAMLprim value init_lwt (value callback) {
D(printf("Init...\n"));
caml_register_global_root(&completionCallback);
- completionCallback = callback;
+ completionCallback = callb;
dummyEvent = CreateEvent(NULL, TRUE, FALSE, NULL); // Dummy event
EOF
- run: cd _prev && opam exec -- make src UISTYLE=text OSTYPE=$OSTYPE
shell: bash
if: matrix.job.oldmake
- run: cd _prev && opam exec -- make tui
shell: bash
if: ${{ !matrix.job.oldmake }}
# IMPORTANT! These tests do not exercise the entire RPC API. Yet, they
# should work fine as a smoke test.
- name: Run self-tests over RPC - new client to prev server
env:
UNISON: test1
shell: bash
run: |
# Separate backup dir must be set for server instance so that the central
# backup location of both instances doesn't overlap
UNISONBACKUPDIR=./_prev/src/testbak_s _prev/src/unison -socket 55443 &
sleep 1 # Wait for the server to be fully started
_new/src/unison -ui text -selftest testr_c socket://127.0.0.1:55443/testr_s -killserver
- name: Run self-tests over RPC - prev client to new server
env:
UNISON: test2
shell: bash
run: |
# Separate backup dir must be set for server instance so that the central
# backup location of both instances doesn't overlap
UNISONBACKUPDIR=./_new/src/testbak_s _new/src/unison -socket 55443 &
sleep 1 # Wait for the server to be fully started
_prev/src/unison -ui text -selftest testr_c socket://127.0.0.1:55443/testr_s -killserver
## We know the code is ok with various ocaml versions, so this is
## just checking the dune build process. Therefore build each OS
## family just once. Pick a different ocaml version because that's
## better coverage without adding a build.
opam_dune_build:
strategy:
fail-fast: false
matrix:
job:
- { os: ubuntu-22.04 , ocaml-compiler: 4.12.x }
- { os: macos-14 , ocaml-compiler: 4.14.x }
runs-on: ${{ matrix.job.os }}
steps:
- if: contains(matrix.job.os, 'ubuntu')
run: sudo apt-get update
- name: Checkout code
uses: actions/checkout@v4
- name: Use OCaml ${{ matrix.job.ocaml-compiler }}
uses: ocaml/setup-ocaml@v3
with:
ocaml-compiler: "${{ matrix.job.ocaml-compiler }}"
- run: opam install . --deps-only
- run: opam exec -- dune build && cp -L ./_build/install/default/bin/unison* ./src/
# - run: opam exec -- make test
bytecode_build:
strategy:
fail-fast: false
matrix:
job:
- { os: ubuntu-22.04 , ocaml-compiler: 4.14.x }
runs-on: ${{ matrix.job.os }}
steps:
- if: contains(matrix.job.os, 'ubuntu')
run: sudo apt-get update
- name: Checkout code
uses: actions/checkout@v4
- name: Use OCaml ${{ matrix.job.ocaml-compiler }}
uses: ocaml/setup-ocaml@v3
with:
ocaml-compiler: "${{ matrix.job.ocaml-compiler }}"
opam-pin: false
- run: opam exec -- make tui NATIVE=false
- run: opam exec -- make test
build_compat:
if: ${{ !cancelled() }} # Don't fail if 'docs' failed
needs: docs
strategy:
fail-fast: false
matrix:
job:
- { ocaml-version: 4.14.x, publish: true, fnsuffix: -ubuntu-x86_64 }
- { ocaml-version: "ocaml-variants.4.14.2+options,ocaml-option-musl,ocaml-option-static,ocaml-option-flambda", publish: true, fnsuffix: -ubuntu-x86_64-static, static: -static }
- { ocaml-version: 4.12.x }
- { ocaml-version: 4.08.x }
runs-on: ubuntu-20.04
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Use OCaml ${{ matrix.job.ocaml-version }}
uses: ocaml/setup-ocaml@v2
with:
ocaml-compiler: ${{ matrix.job.ocaml-version }}
opam-disable-sandboxing: true
opam-pin: false
opam-depext: false
- name: Build text UI
env:
LDFLAGS: ${{ matrix.job.static }}
run: |
opam exec -- make
mkdir -p pkg/bin
cp src/unison pkg/bin/
cp src/unison-fsmonitor pkg/bin/
- name: Run local tests
run: opam exec -- make test
- name: Run remote tests
run: |
mkdir localsocket
chmod 700 localsocket
# Separate backup dir must be set for server instance so that the central
# backup location of both instances doesn't overlap
UNISONBACKUPDIR=./src/testbak4 ./src/unison -socket ./localsocket/test.sock &
sleep 1 # Wait for the server to be fully started
test -S ./localsocket/test.sock
./src/unison -ui text -selftest testr3 socket://{./localsocket/test.sock}/testr4 -killserver
# [2024-12] Recent dune release switched from using pkg-config to pkgconf.
# However, pkgconf is broken in many environments and this breaks building
# cairo2, a dependency for lablgtk3 (and likely would break lablgtk3, too,
# if building ever got to that point). ubuntu-20.04 is one such case
# (pkgconf segfaults). As a workaround, just uninstall pkgconf, which makes
# dune fall back to pkg-config.
- name: Build GUI
if: ${{ !contains(matrix.job.ocaml-version, '-musl') }}
run: |
sudo apt-get remove pkgconf
opam depext --install --verbose --yes lablgtk3 && opam install ocamlfind
opam exec -- make gui
cp src/unison-gui pkg/bin/
- name: Initialize packaging variables
id: vars
run: |
REF_SHAS=$(echo '${{ github.sha }}' | awk '{ print substr($0, 1, 8) }')
unset REF_TAG ; case "${GITHUB_REF}" in refs/tags/*) REF_TAG="${GITHUB_REF#refs/tags/}" ;; esac;
PKG_VER="${REF_TAG:-git_$REF_SHAS}"
PKG_VER="${PKG_VER#v}"
echo PKG_NAME="${PROJECT_NAME}-${PKG_VER}${{ matrix.job.fnsuffix }}.tar.gz" >> $GITHUB_OUTPUT
echo REF_SHAS=${REF_SHAS} >> $GITHUB_OUTPUT
- uses: actions/upload-artifact@v4
if: false ## disable by default; only useful for debugging GHA
with:
name: unison-${{ steps.vars.outputs.REF_SHAS }}.ocaml-${{ matrix.job.ocaml-version }}.ubuntu.x86_64
path: pkg/bin/*
- name: Copy user manual
if: matrix.job.publish
continue-on-error: ${{ !(github.ref_type == 'tag' && startsWith(github.ref_name, 'v') && matrix.job.publish) }}
uses: actions/download-artifact@v4
with:
name: unison-docs
path: pkg
- name: Prepare package
if: matrix.job.publish
run: |
strip pkg/bin/*
cp README* pkg/
cp LICENSE* pkg/
cp INSTALL.md pkg/
cp CONTRIBUTING.md pkg/
cp NEWS.md pkg/
- name: Package
if: matrix.job.publish
run: cd pkg && tar czf '${{ steps.vars.outputs.PKG_NAME }}' *
- uses: actions/upload-artifact@v4
if: matrix.job.publish
with:
name: ${{ steps.vars.outputs.PKG_NAME }}___ocaml-${{ matrix.job.ocaml-version }}.ubuntu_compat-publish
path: pkg/${{ steps.vars.outputs.PKG_NAME }}
- name: Publish
if: github.ref_type == 'tag' && startsWith(github.ref_name, 'v') && matrix.job.publish
uses: softprops/action-gh-release@v1
with:
files: pkg/${{ steps.vars.outputs.PKG_NAME }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}