Skip to content

Commit

Permalink
Makefile: Move conditionals into separate script
Browse files Browse the repository at this point in the history
There is no portable syntax for conditionals and other more complex
constructs, including shell scripts. This patch moves non-portable
conditionals and other such parts into a separate script written in
OCaml. The script itself is fully portable, it does not require GNU
tools or even a POSIX shell.

With this patch the main makefile becomes fully portable and currently
works with GNU Make, BSD make, Solaris make and NMAKE.
  • Loading branch information
tleedjarv committed Dec 17, 2024
1 parent 035b8f3 commit af361f8
Show file tree
Hide file tree
Showing 7 changed files with 745 additions and 385 deletions.
103 changes: 38 additions & 65 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
# Unison file synchronizer: Makefile
# See LICENSE for terms.

# IMPORTANT!
#
# This file is portable and compatible with GNU Make, BSD make, Solaris
# (d)make and NMAKE. Do not make any changes in this file unless you are
# certain that the changes do not break this portability.

default: all
.PHONY: default

# Sub-makefiles are perfectly fine for parallel builds.
# This makefile is not, due to recursive invocations of make.
.NOTPARALLEL:
Expand All @@ -9,85 +18,49 @@
all: src manpage

.PHONY: src
src:
$(MAKE) -C src
src: FRC
cd src && $(MAKE)
FRC: ;
# Not all make seem to work without FRC, even with .PHONY

.PHONY: tui gui macui fsmonitor depend
tui gui macui fsmonitor depend:
cd src && $(MAKE) $@

# It's a wart that docs need "unison" built (vs some docs utility).
.PHONY: docs
docs: src manpage
$(MAKE) -C doc
cd doc && $(MAKE)

# "src" is a prerequisite to prevent parallel build errors.
# manpage builds currently require a pre-built "unison" binary.
.PHONY: manpage
manpage: src
$(MAKE) -C man
cd man && $(MAKE)

.PHONY: test
test: ./src/unison
./src/unison -ui text -selftest

.PHONY: depend
depend:
$(MAKE) -C src depend
test:
ocaml src/make_tools.ml run ./src/unison -ui text -selftest
# Note: unison binary is not built automatically for the test target,
# so as to avoid building it with unwanted configuration.

# This construct is here to remain compatible with make implementations
# that do not have the -C option, work with different (also non-POSIX)
# shells, and not rely on single shell per line execution.
.PHONY: clean
clean:
$(MAKE) -C doc clean
$(MAKE) -C man clean
$(MAKE) -C src clean

INSTALL ?= install
INSTALL_PROGRAM ?= $(INSTALL)
INSTALL_DATA ?= $(INSTALL) -m 644
clean: clean_doc clean_man clean_src
.PHONY: clean_doc
clean_doc:
cd doc && $(MAKE) clean
.PHONY: clean_man
clean_man:
cd man && $(MAKE) clean
.PHONY: clean_src
clean_src:
cd src && $(MAKE) clean

prefix = /usr/local
PREFIX ?= $(prefix)
exec_prefix = $(PREFIX)
EXEC_PREFIX ?= $(exec_prefix)
bindir = $(EXEC_PREFIX)/bin
BINDIR ?= $(bindir)
datarootdir = $(PREFIX)/share
DATAROOTDIR ?= $(datarootdir)
mandir = $(DATAROOTDIR)/man
MANDIR ?= $(mandir)
man1dir = $(MANDIR)/man1
MAN1DIR ?= $(man1dir)
manext = .1
MANEXT ?= $(manext)

.PHONY: install
install: all
$(INSTALL) -d "$(DESTDIR)$(BINDIR)"
ifneq ($(wildcard src/unison),)
$(INSTALL_PROGRAM) src/unison "$(DESTDIR)$(BINDIR)/unison"
endif
ifneq ($(wildcard src/unison-gui),)
$(INSTALL_PROGRAM) src/unison-gui "$(DESTDIR)$(BINDIR)/unison-gui"
endif
ifneq ($(wildcard src/unison-fsmonitor),)
$(INSTALL_PROGRAM) src/unison-fsmonitor "$(DESTDIR)$(BINDIR)/unison-fsmonitor"
else
ifneq ($(wildcard src/fsmonitor.py),)
$(INSTALL_PROGRAM) src/fsmonitor.py "$(DESTDIR)$(BINDIR)/fsmonitor.py"
endif
endif
ifneq ($(wildcard man/unison.1),)
$(INSTALL) -d "$(DESTDIR)$(MAN1DIR)"
$(INSTALL_DATA) man/unison.1 "$(DESTDIR)$(MAN1DIR)/unison$(MANEXT)"
endif
ifneq ($(wildcard src/uimac/build/Default/Unison.app),)
$(info !!! The GUI for macOS has been built but will NOT be installed automatically. \
You can find the built GUI package at $(abspath src/uimac/build/Default/Unison.app))
endif

# Delegate other targets to the sub-makefile
.PHONY: Makefile

./src/%:
$(MAKE) -C src $*

%: FORCE
$(MAKE) -C src $@
.PHONY: FORCE
FORCE: ;
install:
ocaml src/make_tools.ml install
2 changes: 2 additions & 0 deletions src/.depend
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,8 @@ main.cmx : \
remote.cmx \
ubase/prefs.cmx \
os.cmx
make_tools.cmo :
make_tools.cmx :
name.cmo : \
ubase/util.cmi \
ubase/umarshal.cmi \
Expand Down
86 changes: 43 additions & 43 deletions src/Makefile
Original file line number Diff line number Diff line change
@@ -1,39 +1,55 @@
# Unison file synchronizer: src/Makefile
# Copyright 1999-2023 (see ../LICENSE for terms).
# Copyright 1999-2024 (see ../LICENSE for terms).

## User Settings

# Set NATIVE=false if you are not using the native code compiler (ocamlopt)
# This is not advised, though: Unison runs much slower when byte-compiled.
# Set NATIVE=true to force a native build, should auto-detection fail.
NATIVE=auto
# IMPORTANT!
#
# This file is portable and compatible with GNU Make, BSD make, Solaris
# (d)make and NMAKE. Do not make any changes in this file unless you are
# certain that the changes do not break this portability.

########################################################################
########################################################################
# (There should be no need to change anything from here on) ##
########################################################################

######################################################################
# Building installation instructions

.PHONY: all
all: tui guimaybe macuimaybe fsmonitor

########################################################################
## Miscellaneous developer-only switches
# [2023-05] This check is here only temporarily for a smooth transition
ifeq ($(STATIC), true)
$(error Variable STATIC is no longer in use. Please set appropriate LDFLAGS,\
like -static, instead)
endif

# NAME, VERSION, and MAJORVERSION, automatically generated
-include Makefile.ProjectInfo

########################################################################
### Compilation rules
default: all
.PHONY: default

# Executed only by BSD make
.BEGIN:
@touch _mk.cfg
@ocaml make_tools.ml conf > Makefile.cfg
@ocaml make_tools.ml conf2 > Makefile2.cfg

# Executed only by Solaris dmake
.INIT:
@touch _mk.cfg
@ocaml make_tools.ml conf ASSUME_DMAKE=true > Makefile.cfg
@ocaml make_tools.ml conf2 ASSUME_DMAKE=true > Makefile2.cfg

# Executed only by GNU Make and NMAKE
Makefile.cfg: _mk.cfg
@ocaml make_tools.ml conf > Makefile.cfg
@ocaml make_tools.ml conf2 MAKE="$(MAKE)" > Makefile2.cfg
_mk.cfg: ;

TARGETS = all tui gui macui fsmonitor clean depend dependgraph paths
FILES = unison unison.exe

.NOTPARALLEL:
.PHONY: $(TARGETS)
$(TARGETS) $(FILES): Makefile.cfg
$(MAKE) -f Makefile.OCaml $@

# Though not ideal, recursive make is needed here, in the name of portability.
#
# Directly including the freshly-generated Makefile.cfg could work with GNU
# Make (when the target filename in the rule is guarded by $(MAKE_RESTARTS)
# to prevent gmake from going into infinite loop), but fails with all other
# make implementations. Solaris make, BSD make and NMAKE all read Makefile.cfg
# before generating it (failing when *.cfg does not exist, reading stale
# contents otherwise). "-include" instead of "include" is not portable.

include Makefile.OCaml

######################################################################
# For developers
Expand All @@ -55,19 +71,3 @@ tags:
; fi

TAGS: tags

######################################################################
# Misc

.PHONY: clean

####################################################################
# Documentation strings

# Cons up a fake strings.ml if necessary (the real one is generated when
# we build the documentation, but we need to be able to compile the
# executable here to do that!)
strings.ml:
echo "(* Dummy strings.ml *)" > strings.ml
echo "let docs = []" >> strings.ml

Loading

0 comments on commit af361f8

Please sign in to comment.