From b4412afd5303aa6aa389b66ccea4bef2eabf0aca Mon Sep 17 00:00:00 2001 From: hangedman Date: Thu, 23 Nov 2023 22:47:58 +0900 Subject: [PATCH] Introduce CI workflow (#69) * Commit jmagick_build.yml, GitHub Action workflow. Remove Travis setting file. configure.ac cosmetic changes * Use AC_SYS_LARGEFILE instead of own checks * Use AS_HELP_STRING, to arrange help string indent docker improve * Use docker image `dpokidov/imagemagick` to build ImageMagick misc * Add .gitignore * Use cache on GitHub Action * Add os and jdk matrix * Fix for autotools doc style --- .github/workflows/jmagick_build.yml | 46 +++ .gitignore | 7 + .travis.yml | 4 - Changelog.txt | 6 + Dockerfile | 20 +- Make.def.in | 7 +- Make.rules | 7 - Makefile => Makefile.am | 20 +- configure.ac | 175 +++++---- install-sh | 562 +++++++++++++++++----------- 10 files changed, 527 insertions(+), 327 deletions(-) create mode 100644 .github/workflows/jmagick_build.yml delete mode 100644 .travis.yml rename Makefile => Makefile.am (73%) diff --git a/.github/workflows/jmagick_build.yml b/.github/workflows/jmagick_build.yml new file mode 100644 index 0000000..2a1415f --- /dev/null +++ b/.github/workflows/jmagick_build.yml @@ -0,0 +1,46 @@ +name: jmagick Makefile CI (multiple jdk versions) + +on: + push: + pull_request: + branches: [ "master" ] + +jobs: + build: + runs-on: ubuntu-latest # jammy + + name: ${{ matrix.jdk }} on ${{ matrix.os }} + strategy: + fail-fast: true + matrix: + jdk: ['8', '11'] + os: ['ubuntu', 'bullseye'] + exclude: + - jdk: '8' + os: 'bullseye' + + container: + image: dpokidov/imagemagick:7.1.1-10-${{ matrix.os }} + options: --user root + + steps: + - uses: actions/checkout@v3 + + - name: Package update + run: apt-get update -y && apt-get install -y sudo curl wget apt-utils + + - name: Install build tools + run: apt-get install -y autoconf automake libtool build-essential pkg-config openjdk-${{ matrix.jdk }}-jdk + + - name: Prepare autotools + run: | + touch NEWS AUTHORS ChangeLog + autoreconf --force --install + automake --add-missing + + - name: Configure + run: | + ./configure --with-java-home=/usr/lib/jvm/java-${{ matrix.jdk }}-openjdk-amd64 + + - name: Make + run: make diff --git a/.gitignore b/.gitignore index 0fe88f7..63a7051 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,13 @@ obj /config.log /config.status /configure +/configure~ /ltmain.sh /config.guess /config.sub +/missing +/Makefile +/Makefile.in +/compile + +.idea/ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 55a5981..0000000 --- a/.travis.yml +++ /dev/null @@ -1,4 +0,0 @@ -language: c -script: - - jdk_switcher use openjdk7 - diff --git a/Changelog.txt b/Changelog.txt index 07928ca..c91d43d 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -37,6 +37,12 @@ IM Before version 6.2.9 does not support the DivideCompositeOp CompositeOperator ========== Changelog =========== +2023-11-23 + * Added CI workflow support, configure.ac improved, see https://github.com/techblue/jmagick/commits/master for recent changes + +2023-06-09 + * Added build support for Java 11, 17 + 2014-08-02 Christian Ferbar * Add Kerning, InterwordSpacing, InterlineSpacing, getTypeMetrics, FormatMagickCaption diff --git a/Dockerfile b/Dockerfile index 876114e..1de8ff0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,14 +1,16 @@ -FROM ubuntu:14.04 +FROM dpokidov/imagemagick:7.1.1-10-ubuntu -RUN apt-get update -RUN apt-get install -y openjdk-7-jdk libmagickcore-dev libmagickwand-dev make +RUN apt-get update -y +RUN apt-get install -y autoconf automake libtool build-essential pkg-config openjdk-11-jdk -ADD docker/build.sh / -RUN chmod +x /build.sh -WORKDIR /src -VOLUME /src -VOLUME /build -CMD /build.sh +COPY . . +RUN touch NEWS AUTHORS ChangeLog +RUN autoreconf --force --install +RUN automake --add-missing +RUN ./configure --with-java-home=/usr/lib/jvm/java-11-openjdk-amd64 +RUN make +# override "dpokidov/imagemagick" default entrypoint +ENTRYPOINT [""] diff --git a/Make.def.in b/Make.def.in index a9d1538..24d7697 100644 --- a/Make.def.in +++ b/Make.def.in @@ -2,8 +2,6 @@ # Some macro definitions. # -OS = @OS@ - # Versions MAJOR = @VER_MAJOR@ MINOR = @VER_MINOR@ @@ -71,5 +69,8 @@ MAGICK_LIB_PATH = @MAGICK_LIB_PATH@ # Java include directories JAVA_INCLUDES = @JAVA_INCLUDES@ -#Shared library extension +# Shared library extension SHARED_LIB_EXT = @SHARED_LIB_EXT@ + +# osx or not +DARWIN = @DARWIN@ \ No newline at end of file diff --git a/Make.rules b/Make.rules index 1e60b92..6dcb22a 100644 --- a/Make.rules +++ b/Make.rules @@ -1,17 +1,10 @@ # Copyright (C) 1999 Eric Yeo. All rights reserved. -CYGPATH := $(shell command -v cygpath 2> /dev/null) - # Fix obscure libtool issue ifdef CYGPATH export echo=echo endif -ifeq ($(strip $(OS)),Darwin) -DARWIN = true -endif - - # This is the main Java sources. ifndef JAVA_SRC_DIR JAVA_SRC_DIR = $(PROJ_BASE_DIR)src diff --git a/Makefile b/Makefile.am similarity index 73% rename from Makefile rename to Makefile.am index d49abd5..12cab07 100644 --- a/Makefile +++ b/Makefile.am @@ -11,19 +11,17 @@ MAKE_PATH = . include $(MAKE_PATH)/Make.def -CYGPATH := $(shell command -v cygpath 2> /dev/null) - DIRS = src -ifdef CYGPATH -JAR_FILE = "$(shell cygpath -C UTF8 -w "$(LIB_DIR)/jmagick-$(MAJOR).$(MINOR).$(MICRO).jar")" -CLEAN_LIST = $(LIB_DIR)/jmagick-$(MAJOR).$(MINOR).$(MICRO).jar -JAVADOC_DEST = "$(shell cygpath -C UTF8 -s -w "$(DEST)$(JAVADOC_DIR)")" -JAVADOC_SRC = "$(shell cygpath -C UTF8 -s -w "$(JAVA_SRC_DIR)")" +if USE_CYGPATH + JAR_FILE = "$(shell cygpath -C UTF8 -w "$(LIB_DIR)/jmagick-$(MAJOR).$(MINOR).$(MICRO).jar")" + CLEAN_LIST = $(LIB_DIR)/jmagick-$(MAJOR).$(MINOR).$(MICRO).jar + JAVADOC_DEST = "$(shell cygpath -C UTF8 -s -w "$(DEST)$(JAVADOC_DIR)")" + JAVADOC_SRC = "$(shell cygpath -C UTF8 -s -w "$(JAVA_SRC_DIR)")" else -JAR_FILE = $(LIB_DIR)/jmagick-$(MAJOR).$(MINOR).$(MICRO).jar -CLEAN_LIST = $(JAR_FILE) -JAVADOC_DEST = $(DEST)$(JAVADOC_DIR) -JAVADOC_SRC = $(JAVA_SRC_DIR) + JAR_FILE = $(LIB_DIR)/jmagick-$(MAJOR).$(MINOR).$(MICRO).jar + CLEAN_LIST = $(JAR_FILE) + JAVADOC_DEST = $(DEST)$(JAVADOC_DIR) + JAVADOC_SRC = $(JAVA_SRC_DIR) endif all: dir default-target diff --git a/configure.ac b/configure.ac index eef09a3..8d2c635 100644 --- a/configure.ac +++ b/configure.ac @@ -1,36 +1,32 @@ dnl Copyright (C) 1999-2005 Eric Yeo. All rights reserved. dnl This is the autoconf input file for Java Magick. +AC_PREREQ(2.6.1) -AC_INIT(src/magick/MagickImage.java) -AC_CANONICAL_SYSTEM - -dnl Get the OS name - -if test -x "/bin/uname" ; then - UNAME=/bin/uname -elif test -x "/usr/bin/uname" ; then - UNAME=/usr/bin/uname -elif test -x "/usr/local/bin/uname" ; then - UNAME=/usr/local/bin/uname -else - echo configure: cannot find uname - exit 1 -fi +dnl The version number must change with every release +AC_INIT([jmagick], [7.0.4]) +AC_CANONICAL_BUILD +AC_CANONICAL_HOST +AC_CANONICAL_TARGET + +AM_INIT_AUTOMAKE([-Wno-portability]) +VER_MAJOR=$(echo "$PACKAGE_VERSION" | cut -d . -f 1) +VER_MINOR=$(echo "$PACKAGE_VERSION" | cut -d . -f 2) +VER_MICRO=$(echo "$PACKAGE_VERSION" | cut -d . -f 3) +VER_JMSUB="0" + +AC_SUBST(VER_MAJOR, ${VER_MAJOR}) +AC_SUBST(VER_MINOR, ${VER_MINOR}) +AC_SUBST(VER_MICRO, ${VER_MICRO}) +AC_SUBST(VER_JMSUB, ${VER_JMSUB}) LIB=lib if test -x "/usr/lib64" ; then LIB=lib64 fi -OS=`$UNAME -s` - -dnl The version number must change with every release -VER_MAJOR=7 -VER_MINOR=0 -VER_MICRO=4 -VER_JMSUB=0 - SHARED_LIB_EXT=.so +DARWIN=false +AM_CONDITIONAL(USE_CYGPATH, false) dnl Need the -G flag on Solaris when creating shared libraries. case "$target" in @@ -44,20 +40,25 @@ dnl Make sure we use -dynamiclib parameter for OS X Leopard *darwin9.*|*darwin10.*) SHARED_LDFLAGS="-dynamiclib" SHARED_LIB_EXT=.jnilib + DARWIN=true ;; *darwin1.[0-2]) + DARWIN=true ;; *darwin*) LIBTOOL_LINK_FLAG='-module' + DARWIN=true ;; *-*-cygwin|*-*-mingw32) SHARED_LDFLAGS="-shared" SHARED_LIB_EXT=.dll JFLAGS="-Xlint:deprecation -Xlint:unchecked" + AM_CONDITIONAL(USE_CYGPATH, true) JAVA_HOME=$(cygpath -C UTF8 "$(cygpath -C UTF8 -d "${JAVA_HOME}")") MAGICK_HOME=$(cygpath -C UTF-8 "$(cygpath -C UTF-8 -d "$(dirname "$(which convert)")")") ;; esac +AC_SUBST(DARWIN) dnl By default, we look at /usr/local. Need to explicitly do this because dnl some compilers don't. @@ -87,28 +88,7 @@ AC_PROG_INSTALL dnl Check for large file support. This test was taken from ImageMagick. dnl If this step is removed, there will be a mismatch of structures in dnl the ImageMagick headers. -AC_PATH_PROG(GETCONF, getconf, not_found) -if (test $GETCONF != not_found); then - AC_MSG_CHECKING(whether large file support needs explicit enabling) - result='no' - NEW_CFLAGS=`$GETCONF LFS_CFLAGS 2> /dev/null` - if (test -n "$NEW_CFLAGS"); then - CFLAGS="$CFLAGS $NEW_CFLAGS" - result='yes' - fi - NEW_LDFLAGS=`$GETCONF LFS_LDFLAGS 2> /dev/null` - if (test -n "$NEW_LDFLAGS"); then - LDFLAGS="$LDFLAGS $NEW_LDFLAGS" - result='yes' - fi - NEW_LIBS=`$GETCONF LFS_LIBS 2> /dev/null` - if (test -n "$NEW_LIBS"); then - LIBS="$LIBS $NEW_LIBS" - result='yes' - fi - AC_MSG_RESULT($result) -fi - +AC_SYS_LARGEFILE dnl Determine the X11 install paths. We don't really need this dnl if we are using shared libraries. @@ -132,10 +112,15 @@ esac AC_SUBST(CLASSSEP) dnl Determine if we have a decent Java distribution -AC_ARG_WITH(java-home, --with-java-home Java installation path, - JAVA_HOME=${withval}) -AC_ARG_WITH(java-includes, --with-java-includes Java includes path, - JAVA_INCLUDE_PATH="${withval}") +AC_ARG_WITH([java-home], + AS_HELP_STRING([--with-java-home=PATH], + [Java installation path]), + [JAVA_HOME="${withval}"]) +AC_ARG_WITH([java-includes], + AS_HELP_STRING([--with-java-includes=PATH], + [Java includes path]), + [JAVA_INCLUDE_PATH="${withval}"]) + if test -n "${JAVA_INCLUDE_PATH}" -a -d "${JAVA_INCLUDE_PATH}" ; then dnl Java include path supplied JAVA_INCLUDES=-I${JAVA_INCLUDE_PATH} @@ -176,8 +161,11 @@ else fi dnl Determine if there is a shared library extension supplied -AC_ARG_WITH(shared_lib_ext, --with-shared-lib-ext Shared library file extension, - SHARED_LIB_EXT=${withval}, SHARED_LIB_EXT=${SHARED_LIB_EXT}) +AC_ARG_WITH([shared_lib_ext], + AS_HELP_STRING([--with-shared-lib-ext], + [Shared library file extension]), + [SHARED_LIB_EXT="${withval}"], + [SHARED_LIB_EXT="${SHARED_LIB_EXT}"]) dnl Determine if jni.h is available OLD_CPPFLAGS=${CPPFLAGS} @@ -199,9 +187,12 @@ fi AC_SUBST(JAVA) dnl Determine if we prefer to use Jikes. -AC_ARG_WITH(jikes, --with-jikes use the IBM Jikes compiler, - PREFER_JIKES=yes, - PREFER_JIKES=no) +AC_ARG_WITH([jikes], + AS_HELP_STRING([--with-jikes], + [use the IBM Jikes compiler]), + [PREFER_JIKES="yes"], + [PREFER_JIKES="no"]) + if test ${PREFER_JIKES} = yes; then dnl Determine if Jikes is available. AC_PATH_PROG(JIKES, jikes, not_found) @@ -264,18 +255,25 @@ export PATH dnl Check if javadoc destination specified JAVADOC_DIR='${prefix}/share/doc/jmagick' -AC_ARG_WITH(javadoc-dir, --with-javadoc-dir=path where Javadoc is generated, - JAVADOC_DIR=${withval}) +AC_ARG_WITH([javadoc-dir], + AS_HELP_STRING([--with-javadoc-dir=PATH], + [where Javadoc is generated]), + [JAVADOC_DIR="${withval}"], + [JAVADOC_DIR="${withval}"]) AC_SUBST(JAVADOC_DIR) dnl Do you print extra diagnostic? -AC_ARG_ENABLE(diagnostic, - --enable-diagnostic enable C diagnostic output (default off), - C_DEBUG=-DDIAGNOSTIC,C_DEBUG=) +AC_ARG_ENABLE([diagnostic], + AS_HELP_STRING([--enable-diagnostic], + [enable C diagnostic output (default off)]), + [C_DEBUG=-DDIAGNOSTIC], + [C_DEBUG=]) AC_SUBST(C_DEBUG) -AC_ARG_WITH(magick-version, --with-magick-version=ImageMagick version, - MAGICK_VERSION=${withval}) +AC_ARG_WITH([magick-version], + AS_HELP_STRING([--with-magick-version=VERSION], + [ImageMagick version]), + [MAGICK_VERSION="${withval}"]) if (test -n "$MAGICK_VERSION"); then VER_MAJOR=$(echo "$MAGICK_VERSION" | cut -d . -f 1) VER_MINOR=$(echo "$MAGICK_VERSION" | cut -d . -f 2) @@ -283,8 +281,11 @@ if (test -n "$MAGICK_VERSION"); then fi dnl Check if ImageMagick home specified -AC_ARG_WITH(magick-home, --with-magick-home=path home directory of ImageMagick, - MAGICK_HOME=${withval}) +AC_ARG_WITH([magick-home], + AS_HELP_STRING([--with-magick-home=PATH], + [home directory of ImageMagick]), + [MAGICK_HOME="${withval}"]) + for MPATH in ${MAGICK_HOME} /usr /usr/local /usr/local/ImageMagick /usr/local/ImageMagick-${VER_MAJOR}.${VER_MINOR}.${VER_MICRO} ; do # Location before IM 6.3.8.something if test -f "${MPATH}/include/magick/api.h" ; then @@ -377,11 +378,22 @@ dnl Check if MagickWand-conf exists OLDPATH=${PATH} # MagickWand-config isn't installed in /usr/bin in Ubuntu 16.04+ due # to changes in libmagickcore-dev package. -PATH=${MAGICK_REALHOME}/bin:/usr/${LIB}/${build_os}/ImageMagick-${VER_MAJOR}.${VER_MINOR}.${VER_MICRO}-Q64HDRI/bin:/usr/${LIB}/${build_os}/ImageMagick-${VER_MAJOR}.${VER_MINOR}.${VER_MICRO}-Q64/bin:/usr/${LIB}/${build_os}/ImageMagick-${VER_MAJOR}.${VER_MINOR}.${VER_MICRO}-Q32HDRI/bin:/usr/${LIB}/${build_os}/ImageMagick-${VER_MAJOR}.${VER_MINOR}.${VER_MICRO}-Q32/bin:/usr/${LIB}/${build_os}/ImageMagick-${VER_MAJOR}.${VER_MINOR}.${VER_MICRO}-Q16HDRI/bin:/usr/${LIB}/${build_os}/ImageMagick-${VER_MAJOR}.${VER_MINOR}.${VER_MICRO}-Q16/bin:/usr/${LIB}/${build_os}/ImageMagick-${VER_MAJOR}.${VER_MINOR}.${VER_MICRO}-Q8HDRI/bin:/usr/${LIB}/${build_os}/ImageMagick-${VER_MAJOR}.${VER_MINOR}.${VER_MICRO}-Q8/bin:/usr/${LIB}/${build_os}/ImageMagick-${VER_MAJOR}.${VER_MINOR}.${VER_MICRO}/bin:${PATH} -export PATH -AC_PATH_PROG(MAGICKCONF, MagickWand-config, not_found) -PATH=${OLDPATH} -export PATH +AC_ARG_WITH([magickwand-config], + AS_HELP_STRING([--with-magickwand-config=PATH], + [path to magickwand-config tool]), + [magickwand_config="$withval"], + [magickwand_config=""]) + +if test -n "$magickwand_config"; then + MAGICKCONF="$magickwand_config" +else + PATH=${MAGICK_REALHOME}/bin:/usr/${LIB}/${build_os}/ImageMagick-${VER_MAJOR}.${VER_MINOR}.${VER_MICRO}-Q64HDRI/bin:/usr/${LIB}/${build_os}/ImageMagick-${VER_MAJOR}.${VER_MINOR}.${VER_MICRO}-Q64/bin:/usr/${LIB}/${build_os}/ImageMagick-${VER_MAJOR}.${VER_MINOR}.${VER_MICRO}-Q32HDRI/bin:/usr/${LIB}/${build_os}/ImageMagick-${VER_MAJOR}.${VER_MINOR}.${VER_MICRO}-Q32/bin:/usr/${LIB}/${build_os}/ImageMagick-${VER_MAJOR}.${VER_MINOR}.${VER_MICRO}-Q16HDRI/bin:/usr/${LIB}/${build_os}/ImageMagick-${VER_MAJOR}.${VER_MINOR}.${VER_MICRO}-Q16/bin:/usr/${LIB}/${build_os}/ImageMagick-${VER_MAJOR}.${VER_MINOR}.${VER_MICRO}-Q8HDRI/bin:/usr/${LIB}/${build_os}/ImageMagick-${VER_MAJOR}.${VER_MINOR}.${VER_MICRO}-Q8/bin:/usr/${LIB}/${build_os}/ImageMagick-${VER_MAJOR}.${VER_MINOR}.${VER_MICRO}/bin:${PATH} + export PATH + AC_PATH_PROG(MAGICKCONF, MagickWand-config, not_found) + PATH=${OLDPATH} + export PATH +fi + dnl Added $MAGICK_LIB_PATH and $MAGICK_INCLUDES here because of dnl a possible bug in Magick-conf for ImageMagick 5.4.6 if (test $MAGICKCONF != not_found); then @@ -395,15 +407,18 @@ if (test $MAGICKCONF != not_found); then fi dnl Check if ImageMagick library path specified -AC_ARG_WITH(magick-lib-dir, - --with-magick-lib-dir=path library path of ImageMagick, - MAGICK_LIB_PATH=${withval} - MAGICK_LIBS=-L${withval}) +AC_ARG_WITH([magick-lib-dir], + AS_HELP_STRING([--with-magick-lib-dir=PATH], + [library path of ImageMagick]), + [MAGICK_LIB_PATH="${withval}"], + [MAGICK_LIBS="-L${withval}"]) dnl Check if ImageMagick include path specified -AC_ARG_WITH(magick-inc-dir, - --with-magick-inc-dir=path include path of ImageMagick, - MAGICK_INCLUDES=-I${withval}) +AC_ARG_WITH([magick-inc-dir], + AS_HELP_STRING([--with-magick-inc-dir=PATH], + [path include path of ImageMagick]), + [MAGICK_INCLUDES="-I${withval}"]) + if ( test -f "${MAGICK_INCLUDE_PATH}/magick/api.h" ) ; then MAGICK_INCLUDES=-I${MAGICK_INCLUDE_PATH} MAGICK_VERSION=6 @@ -460,7 +475,7 @@ LDFLAGS=${OLD_LDFLAGS} dnl Configure libtool AC_DISABLE_STATIC -AC_PROG_LIBTOOL +LT_INIT AC_SUBST(JAVA_INCLUDES) AC_SUBST(X11_LIBS) @@ -474,11 +489,7 @@ AC_SUBST(JFLAGS) AC_SUBST(LIBS) AC_SUBST(SHARED_LDFLAGS) AC_SUBST(LIBTOOL_LINK_FLAG) -AC_SUBST(VER_MAJOR) -AC_SUBST(VER_MINOR) -AC_SUBST(VER_MICRO) -AC_SUBST(VER_JMSUB) AC_SUBST(SHARED_LIB_EXT) -AC_SUBST(OS) -AC_OUTPUT([Make.def]) +AC_CONFIG_FILES([Makefile Make.def]) +AC_OUTPUT diff --git a/install-sh b/install-sh index 0ae12c0..ec298b5 100755 --- a/install-sh +++ b/install-sh @@ -1,7 +1,7 @@ #!/bin/sh # install - install a program, script, or datafile -scriptversion=2005-11-07.23 +scriptversion=2020-11-14.01; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the @@ -35,56 +35,62 @@ scriptversion=2005-11-07.23 # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent -# `make' implicit rules from creating a file called install from it +# 'make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written -# from scratch. It can only install one file at a time, a restriction -# shared with many OS's install programs. +# from scratch. -# set DOITPROG to echo to test this script +tab=' ' +nl=' +' +IFS=" $tab$nl" -# Don't use :- since 4.3BSD and earlier shells don't like it. -doit="${DOITPROG-}" +# Set DOITPROG to "echo" to test this script. -# put in absolute paths if you don't have them in your path; or use env. vars. +doit=${DOITPROG-} +doit_exec=${doit:-exec} -mvprog="${MVPROG-mv}" -cpprog="${CPPROG-cp}" -chmodprog="${CHMODPROG-chmod}" -chownprog="${CHOWNPROG-chown}" -chgrpprog="${CHGRPPROG-chgrp}" -stripprog="${STRIPPROG-strip}" -rmprog="${RMPROG-rm}" -mkdirprog="${MKDIRPROG-mkdir}" +# Put in absolute file names if you don't have them in your path; +# or use environment vars. -posix_glob= -posix_mkdir= +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} -# Symbolic mode for testing mkdir with directories. -# It is the same as 755, but also tests that "u+" works. -test_mode=u=rwx,g=rx,o=rx,u+wx +posix_mkdir= # Desired mode of installed file. mode=0755 -# Desired mode of newly created intermediate directories. -# It is empty if not known yet. -intermediate_mode= +# Create dirs (including intermediate dirs) using mode 755. +# This is like GNU 'install' as of coreutils 8.32 (2020). +mkdir_umask=22 +backupsuffix= +chgrpcmd= chmodcmd=$chmodprog chowncmd= -chgrpcmd= -stripcmd= +mvcmd=$mvprog rmcmd="$rmprog -f" -mvcmd="$mvprog" +stripcmd= + src= dst= dir_arg= -dstarg= -no_target_directory= +dst_arg= + +copy_on_change=false +is_target_a_directory=possibly -usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... @@ -94,97 +100,174 @@ In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --c (ignored) --d create directories instead of installing files. --g GROUP $chgrpprog installed files to GROUP. --m MODE $chmodprog installed files to MODE. --o USER $chownprog installed files to USER. --s $stripprog installed files. --t DIRECTORY install into DIRECTORY. --T report an error if DSTFILE is a directory. ---help display this help and exit. ---version display version info and exit. + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -p pass -p to $cpprog. + -s $stripprog installed files. + -S SUFFIX attempt to back up existing files, with suffix SUFFIX. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. Environment variables override the default commands: - CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG + +By default, rm is invoked with -f; when overridden with RMPROG, +it's up to you to specify -f if you want it. + +If -S is not specified, no backups are attempted. + +Email bug reports to bug-automake@gnu.org. +Automake home page: https://www.gnu.org/software/automake/ " -while test -n "$1"; do +while test $# -ne 0; do case $1 in - -c) shift - continue;; + -c) ;; + + -C) copy_on_change=true;; - -d) dir_arg=true - shift - continue;; + -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" - shift - shift - continue;; + shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 - shift - shift - continue;; + case $mode in + *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; -o) chowncmd="$chownprog $2" - shift - shift - continue;; + shift;; - -s) stripcmd=$stripprog - shift - continue;; + -p) cpprog="$cpprog -p";; - -t) dstarg=$2 - shift - shift - continue;; + -s) stripcmd=$stripprog;; - -T) no_target_directory=true - shift - continue;; + -S) backupsuffix="$2" + shift;; + + -t) + is_target_a_directory=always + dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) is_target_a_directory=never;; --version) echo "$0 $scriptversion"; exit $?;; - *) # When -d is used, all remaining arguments are directories to create. - # When -t is used, the destination is already specified. - test -n "$dir_arg$dstarg" && break - # Otherwise, the last argument is the destination. Remove it from $@. - for arg - do - if test -n "$dstarg"; then - # $@ is not empty: it contains at least $arg. - set fnord "$@" "$dstarg" - shift # fnord - fi - shift # arg - dstarg=$arg - done - break;; + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; esac + shift done -if test -z "$1"; then +# We allow the use of options -d and -T together, by making -d +# take the precedence; this is for compatibility with GNU install. + +if test -n "$dir_arg"; then + if test -n "$dst_arg"; then + echo "$0: target directory not allowed when installing a directory." >&2 + exit 1 + fi +fi + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi - # It's OK to call `install-sh -d' without argument. + # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi -test -n "$dir_arg" || trap '(exit $?); exit' 1 2 13 15 +if test -z "$dir_arg"; then + if test $# -gt 1 || test "$is_target_a_directory" = always; then + if test ! -d "$dst_arg"; then + echo "$0: $dst_arg: Is not a directory." >&2 + exit 1 + fi + fi +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi for src do - # Protect names starting with `-'. + # Protect names problematic for 'test' and other utilities. case $src in - -*) src=./$src ;; + -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then @@ -192,6 +275,10 @@ do dstdir=$dst test -d "$dstdir" dstdir_status=$? + # Don't chown directories that already exist. + if test $dstdir_status = 0; then + chowncmd="" + fi else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command @@ -202,131 +289,155 @@ do exit 1 fi - if test -z "$dstarg"; then + if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi + dst=$dst_arg - dst=$dstarg - # Protect names starting with `-'. - case $dst in - -*) dst=./$dst ;; - esac - - # If destination is a directory, append the input filename; won't work - # if double slashes aren't ignored. + # If destination is a directory, append the input filename. if test -d "$dst"; then - if test -n "$no_target_directory"; then - echo "$0: $dstarg: Is a directory" >&2 - exit 1 + if test "$is_target_a_directory" = never; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 fi dstdir=$dst - dst=$dstdir/`basename "$src"` + dstbase=`basename "$src"` + case $dst in + */) dst=$dst$dstbase;; + *) dst=$dst/$dstbase;; + esac dstdir_status=0 else - # Prefer dirname, but fall back on a substitute if dirname fails. - dstdir=` - (dirname "$dst") 2>/dev/null || - expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$dst" : 'X\(//\)[^/]' \| \ - X"$dst" : 'X\(//\)$' \| \ - X"$dst" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || - echo X"$dst" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q' - ` - + dstdir=`dirname "$dst"` test -d "$dstdir" dstdir_status=$? fi fi + case $dstdir in + */) dstdirslash=$dstdir;; + *) dstdirslash=$dstdir/;; + esac + obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') - posix_mkdir=false - if $mkdirprog -m $test_mode -p -- / >/dev/null 2>&1; then - posix_mkdir=true + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + # The $RANDOM variable is not portable (e.g., dash). Use it + # here however when possible just to lower collision chance. + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + + trap ' + ret=$? + rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null + exit $ret + ' 0 + + # Because "mkdir -p" follows existing symlinks and we likely work + # directly in world-writeable /tmp, make sure that the '$tmpdir' + # directory is successfully created first before we actually test + # 'mkdir -p'. + if (umask $mkdir_umask && + $mkdirprog $mkdir_mode "$tmpdir" && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + test_tmpdir="$tmpdir/a" + ls_ld_tmpdir=`ls -ld "$test_tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. - rmdir ./-m "$test_mode" ./-p ./-- 2>/dev/null - fi ;; + rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null + fi + trap '' 0;; esac if - $posix_mkdir && { - - # With -d, create the new directory with the user-specified mode. - # Otherwise, create it using the same intermediate mode that - # mkdir -p would use when creating intermediate directories. - # POSIX says that this mode is "$(umask -S),u+wx", so use that - # if umask -S works. - - if test -n "$dir_arg"; then - mkdir_mode=$mode - else - case $intermediate_mode in - '') - if umask_S=`(umask -S) 2>/dev/null`; then - intermediate_mode=$umask_S,u+wx - else - intermediate_mode=$test_mode - fi ;; - esac - mkdir_mode=$intermediate_mode - fi - - $mkdirprog -m "$mkdir_mode" -p -- "$dstdir" - } + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) then : else - # mkdir does not conform to POSIX, or it failed possibly due to - # a race condition. Create the directory the slow way, step by - # step, checking for races as we go. + # mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. case $dstdir in - /*) pathcomp=/ ;; - -*) pathcomp=./ ;; - *) pathcomp= ;; - esac - - case $posix_glob in - '') - if (set -f) 2>/dev/null; then - posix_glob=true - else - posix_glob=false - fi ;; + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; esac oIFS=$IFS IFS=/ - $posix_glob && set -f + set -f set fnord $dstdir shift - $posix_glob && set +f + set +f IFS=$oIFS + prefixes= + for d do - test "x$d" = x && continue - - pathcomp=$pathcomp$d - if test ! -d "$pathcomp"; then - $mkdirprog "$pathcomp" - # Don't fail if two instances are running concurrently. - test -d "$pathcomp" || exit 1 - fi - pathcomp=$pathcomp/ + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ done - obsolete_mkdir_used=true + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi fi fi @@ -334,18 +445,29 @@ do { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || - test -z "$chmodcmd" || $doit $chmodcmd "$mode" "$dst"; } || exit 1 + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. - dsttmp=$dstdir/_inst.$$_ - rmtmp=$dstdir/_rm.$$_ + dsttmp=${dstdirslash}_inst.$$_ + rmtmp=${dstdirslash}_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. - $doit $cpprog "$src" "$dsttmp" && + (umask $cp_umask && + { test -z "$stripcmd" || { + # Create $dsttmp read-write so that cp doesn't create it read-only, + # which would cause strip to fail. + if test -z "$doit"; then + : >"$dsttmp" # No need to fork-exec 'touch'. + else + $doit touch "$dsttmp" + fi + } + } && + $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # @@ -353,49 +475,67 @@ do # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # - { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ - && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ - && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ - && { test -z "$chmodcmd" || $doit $chmodcmd "$mode" "$dsttmp"; } && - - # Now rename the file to the real destination. - { $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null \ - || { - # The rename failed, perhaps because mv can't rename something else - # to itself, or perhaps because mv is so ancient that it does not - # support -f. - - # Now remove or move aside any old file at destination location. - # We try this two ways since rm can't unlink itself on some - # systems and the destination file might be busy for other - # reasons. In this case, the final cleanup might fail but the new - # file should still install successfully. - { - if test -f "$dst"; then - $doit $rmcmd -f "$dst" 2>/dev/null \ - || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null \ - && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }; }\ - || { - echo "$0: cannot unlink or rename $dst" >&2 - (exit 1); exit 1 - } - else - : - fi - } && + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + set +f && + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # If $backupsuffix is set, and the file being installed + # already exists, attempt a backup. Don't worry if it fails, + # e.g., if mv doesn't support -f. + if test -n "$backupsuffix" && test -f "$dst"; then + $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null + fi - # Now rename the file to the real destination. - $doit $mvcmd "$dsttmp" "$dst" - } - } || exit 1 + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 trap '' 0 fi done # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-end: "$" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" # End: