Portable makefiles 3 #634
Workflow file for this run
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 }} |