Observations/Patch Concerning --prefix Permission Requirements

craig@jcb-sc.com craig@jcb-sc.com
Sat Feb 20 07:20:00 GMT 1999


I propose the following patch to clean up some permissions issues
"across the wall" between the user doing the build and the user
doing the install.  After the ChangeLog entries, a long explanation
follows, then the patch itself.

As explained below, I won't commit this for a day or two, to give
people time to let me know if there are problems or concerns with
the proposed changes.


gcc/ChangeLog:

	* Makefile.in (all.internal, all.cross): Depend on `doc'
	target, to ensure docs get made before installation.

gcc/ch/ChangeLog:

	* Make-lang.in (CHILL.info): Depend on intermediate ch/chill.info
	target instead of the chill.texi file.
	(ch/chill.info): New target, depends on the chill.texi source file.
	Its command writes ch/chill.info instead of chill.info.
	(CHILL.install-info): Install from ch/chill.info instead of
	chill.info.
	If any ch/chill.info* files exist, delete *all* chill.info* files
	in $infodir first, not just the ones corresponding to the
	files to be installed (just in case the docs get smaller).

gcc/cp/ChangeLog:

	* Make-lang.in (cplib2.ready): Don't consider updating
	cplib2 stuff if the current directory isn't writable, as
	it won't work (such as during a `make install').

gcc/f/ChangeLog:

	* Make-lang.in (f77.install-common, f77.install-info,
	f77.install-man, f77.uninstall): Use `$(prefix)/lang-f77'
	instead of `lang-f77' for flag file, to be sure of a
	writable directory, and remove the flag file after each
	operation to keep things clean.


I've experimented with the current requirements of the typical,
rather simple `make bootstrap' and `make install' steps by doing
the following:

  -  Trying a build as user `craig' on my system, with the --prefix
     directory set to `/home3/giarc/gnubin', a nonexistent directory.

     At first, `/home3/giarc' existed but with `rwx------'
     permissions, so user `craig' couldn't even read it.  But
     this yielded permission-denied errors during his build, so
     user `giarc' changed the permissions of her home directory so
     user `craig' could see that the --prefix directory did not exist.
     This point is expanded upon further, below.

  -  Trying an install as user `giarc' from with the build directory
     of user `craig'.  `craig' gives `giarc' no write access anywhere
     in his directory tree (checked before and after the build completed).

     This tests whether installation works without write access to either
     the source and build directories.  I found a number of problems,
     and believe I've fixed them all, but I've tested only
     `make bootstrap' (though my fixes should work fine for `make').


There are three directory trees involved:

  -  The *source* directory, which contains the egcs/gcc sources.

     This directory should be usable in a read-only status, such as
     on a CD-ROM.  Therefore, distributions containing actual releases
     need to not only have all derived-but-distributed files (such
     as `gcc/c-parse.h' and `gcc/f/intdoc.texi') be up-to-date, but
     actually have timestamps that clearly indicate that they *are*
     up-to-date, vis-a-vis their respective sources.

     For distributions of snapshots, the source directory need not
     be usable as a read-only directory for the user doing the build
     (`craig' in the sample case).  The installer (`giarc') should be
     able to install, after the building user finishes the build,
     with read-only access to the source directory.

  -  The *build* directory contains the results of the build -- the
     directories, files, and programs to be installed.

     The user doing the build (`craig') requires normal write access
     to this directory.  The installer (`giarc') should be able to,
     after a successfully completed build, successfully install --
     despite having read-only access to the build directory.

  -  The *install* directory is where the built compiler is installed.

     Ideally, the user doing the build (`craig') should require no access
     whatsoever to this directory.  However, currently, sufficient access
     is required to allow determination that the directory and/or specific
     subdirectories and files do not exist -- "permission denied" errors
     occur, during the build, otherwise.

     The user doing the install (`giarc') requires normal write access
     to the install directory.

Specifics of what egcs currently does, and how my patch addresses
some deficiencies, follow.


*Permissions/Access Required By User Doing Build*

Starting with the bootstrap2 phase of the build, the compiler
invocation beginning "stage1/xgcc -Bstage1/" includes a -B specification
for the *install* directory.

This yields fatal errors if that directory cannot be read due to
"permission denied", for example.

This might indicate that --prefix identifies not just an *install*
directory, but also a directory in which to (potentially) find
files and programs supporting the build.  Does anyone know if that's
the case -- if there's a design requirement that one or more existing
files in the --prefix directory be used during the build process
in any configuration?

I don't have any patches to offer to "fix" this, at the moment.
It's not entirely clear to me this behavior is broken, but I
currently lean in that direction.

If the --prefix directory is reachable via `rx' permissions by the
building user, then things seem to work okay.


*Permissions/Access Required By User Doing Install*

The most annoying bug to date seems to be that the g77 documentation,
like gcc, cccp, and other Info files, does not get built until
`make install' is done, and, further, the g77 documentation is
built from a derived file that is shipped with the distribution and
is, in turn, built from other source files.  This file is named
`gcc/f/intdoc.texi'.

The effect of this is that, if `gcc/f/intdoc.texi' in the source
directory is not up-to-date (in terms of its timestamp vis-a-vis
its sources, if not in reality), it won't be rebuilt until
`make install' happens.  But the installing user won't necessarily
have write access to the *source* directory.

I believe my patch fixes that, by having the `all.internal' and
`all.cross' targets in `gcc/Makefile.in' also depend on the `doc'
target, which triggers the building of all of the Info documentation
in the tree.  (I haven't tested `all.cross', however.)

Further, the installing user (`giarc') currently is required to
have write access to the *build* directory, when there's no
conceptual need for that.

This is the result of a variety of things.  For one, g77's
installation procedure uses a "flag" file named `lang-f77' to
more reliably and efficiently (avoiding long command lines,
etc.) determine whether the Fortran language has been selected
and, therefore, whether to install g77 components.

For another, the Chill front-end's documentation targets weren't
quite kosher, causing an attempt to create the Info docs during
an installation, despite the `doc' target being on the list of
things to build.  To avoid problems with filesystems having
case-insensitive filenames, to bring Chill into line with other
front ends, and to bring it into line with its own
`CHILL.maintainer-clean' target, the `chill.info*' files need
to be built in, and installed from, the `gcc/ch/' directory, instead
of `gcc/'.

The trickiest problem is g++ wanting to write `gcc/cplib2.new',
compare it to `gcc/cplib2.txt' (which is okay, since that's
readable), and then touch `gcc/cplib2.ready', all each time a
build *or* install -- even after a successfully completed build --
is attempted.  This produces apparent fatal errors when the
`gcc/' directory cannot be written by the installing user (`giarc').
The fix that seems to me most obvious, and least likely to be wrong,
is that the test of whether to even try doing these writes should
be augmented to require write access to the current directory.

My patch fixes all of the above.

If anyone has any problems or questions regarding this patch, e.g. the
Chill and/or G++ components, please let me know!  Otherwise, within
a day or two, I'd like to commit it.

I think it's too much for egcs 1.1.2, though.  And, having now
done this work, I don't think HJ Lu's aftermarket patch causing
g77 docs to be built as part of the build process is all that bad,
but it, to, should probably not be put in egcs 1.1.2 (unless perhaps
it'd be the *only* aftermarket patch he'd need to provide).

        tq vm, (burley)


*** g77-e/gcc/Makefile.in.~1~	Fri Feb 19 18:05:05 1999
--- g77-e/gcc/Makefile.in	Sat Feb 20 06:13:13 1999
*************** config.status: configure version.c
*** 825,834 ****
  	fi
  
! all.internal: start.encap rest.encap
  # This is what to compile if making a cross-compiler.
  # Note that we can compile enquire using the cross-compiler just built,
  # although we can't run it on this machine.
  all.cross: native gcc-cross specs stmp-headers $(STMP_FIXPROTO) $(LIBGCC) \
! 	$(LIBGCC1_TEST) $(EXTRA_PARTS) lang.all.cross
  # This is what to compile if making gcc with a cross-compiler.
  all.build: native xgcc$(exeext) $(EXTRA_PARTS) lang.all.build
--- 825,834 ----
  	fi
  
! all.internal: start.encap rest.encap doc
  # This is what to compile if making a cross-compiler.
  # Note that we can compile enquire using the cross-compiler just built,
  # although we can't run it on this machine.
  all.cross: native gcc-cross specs stmp-headers $(STMP_FIXPROTO) $(LIBGCC) \
! 	$(LIBGCC1_TEST) $(EXTRA_PARTS) lang.all.cross doc
  # This is what to compile if making gcc with a cross-compiler.
  all.build: native xgcc$(exeext) $(EXTRA_PARTS) lang.all.build
*** g77-e/gcc/ch/Make-lang.in.~1~	Mon Jan 11 08:17:08 1999
--- g77-e/gcc/ch/Make-lang.in	Sat Feb 20 06:35:54 1999
*************** CHILL.start.encap: chill
*** 108,113 ****
  CHILL.rest.encap:
  
! CHILL.info: $(srcdir)/ch/chill.texi
! 	$(MAKEINFO) -I$(srcdir)/ch $(srcdir)/ch/chill.texi -o chill.info
  
  chill.dvi: $(srcdir)/ch/chill.texi $(srcdir)/extend.texi $(srcdir)/invoke.texi $(srcdir)/md.texi $(srcdir)/rtl.texi $(srcdir)/tm.texi
--- 108,115 ----
  CHILL.rest.encap:
  
! CHILL.info: ch/chill.info
! 
! ch/chill.info: $(srcdir)/ch/chill.texi
! 	$(MAKEINFO) -I$(srcdir)/ch $(srcdir)/ch/chill.texi -o ch/chill.info
  
  chill.dvi: $(srcdir)/ch/chill.texi $(srcdir)/extend.texi $(srcdir)/invoke.texi $(srcdir)/md.texi $(srcdir)/rtl.texi $(srcdir)/tm.texi
*************** CHILL.install-common:
*** 140,147 ****
  	fi
  
  CHILL.install-info:
! 	-for i in chill.info*; do \
! 	  rm -f $(infodir)/$$i; \
! 	  $(INSTALL_DATA) $$i $(infodir)/$$i; \
  	done
  
--- 142,152 ----
  	fi
  
+ # Don't delete $(infodir)/ch.info* unless there's actually new
+ # docs to install (in case LANGUAGES didn't contain chill earlier).
  CHILL.install-info:
! 	-for i in ch/chill.info*; do \
! 	  rm -f $(infodir)/chill.info*; \
! 	  realfile=`echo $$i | sed -e 's|.*/\([^/]*\)$$|\1|'`; \
! 	  $(INSTALL_DATA) $$i $(infodir)/$$realfile; \
  	done
  
*** g77-e/gcc/cp/Make-lang.in.~1~	Fri Feb  5 03:06:29 1999
--- g77-e/gcc/cp/Make-lang.in	Sat Feb 20 09:02:45 1999
*************** cplib2.txt: $(CXX_LIB2SRCS) $(CXX_EXTRA_
*** 190,195 ****
  
  # Or if it would be different.
  cplib2.ready: $(GCC_PASSES) $(LANGUAGES) $(LIBGCC2_DEPS) stmp-int-hdrs
! 	@if [ -r cplib2.txt ]; then \
  	  case " $(LANGUAGES) " in \
  	  *" "[cC]"++ "*) \
--- 190,198 ----
  
  # Or if it would be different.
+ # Don't try to do write if `.' is not writable;
+ # in that case, we're installing from someone else's directory.
+ # But go ahead and fail if that directory hasn't been properly built.
  cplib2.ready: $(GCC_PASSES) $(LANGUAGES) $(LIBGCC2_DEPS) stmp-int-hdrs
! 	@if [ -r cplib2.txt -a -w . ]; then \
  	  case " $(LANGUAGES) " in \
  	  *" "[cC]"++ "*) \
*** g77-e/gcc/f/Make-lang.in.~1~	Fri Feb  5 03:06:29 1999
--- g77-e/gcc/f/Make-lang.in	Sat Feb 20 06:09:32 1999
*************** f77.install-normal:
*** 332,339 ****
  f77.install-common:
  	case "$(LANGUAGES)" in \
! 	  *[fF]77*) touch lang-f77;; \
! 	  *) rm -f lang-f77;; \
  	esac
! 	-if [ -f lang-f77 -a -f f771$(exeext) ] ; then \
  	  if [ -f g77-cross$(exeext) ] ; then \
  	    rm -f $(bindir)/$(G77_CROSS_NAME)$(exeext); \
--- 332,339 ----
  f77.install-common:
  	case "$(LANGUAGES)" in \
! 	  *[fF]77*) touch $(prefix)/lang-f77;; \
! 	  *) rm -f $(prefix)/lang-f77;; \
  	esac
! 	-if [ -f $(prefix)/lang-f77 -a -f f771$(exeext) ] ; then \
  	  if [ -f g77-cross$(exeext) ] ; then \
  	    rm -f $(bindir)/$(G77_CROSS_NAME)$(exeext); \
*************** f77.install-common:
*** 355,358 ****
--- 355,359 ----
  	  echo ''; \
  	else true; fi
+ 	rm -f $(prefix)/lang-f77
  
  # $(INSTALL_DATA) might be a relative pathname, so we can't cd into srcdir
*************** f77.install-common:
*** 360,367 ****
  f77.install-info: f77.info
  	case "$(LANGUAGES)" in \
! 	  *[fF]77*) touch lang-f77;; \
! 	  *) rm -f lang-f77;; \
  	esac
! 	if [ -f lang-f77 -a -f f/g77.info ] ; then \
  	  rm -f $(infodir)/g77.info*; \
  	  for f in f/g77.info*; do \
--- 361,368 ----
  f77.install-info: f77.info
  	case "$(LANGUAGES)" in \
! 	  *[fF]77*) touch $(prefix)/lang-f77;; \
! 	  *) rm -f $(prefix)/lang-f77;; \
  	esac
! 	if [ -f $(prefix)/lang-f77 -a -f f/g77.info ] ; then \
  	  rm -f $(infodir)/g77.info*; \
  	  for f in f/g77.info*; do \
*************** f77.install-info: f77.info
*** 371,375 ****
  	  chmod a-x $(infodir)/g77.info*; \
  	else true; fi
! 	@if [ -f lang-f77 -a -f $(srcdir)/f/g77.info ] ; then \
  	  if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then \
  	    echo " install-info --info-dir=$(infodir) $(infodir)/g77.info"; \
--- 372,376 ----
  	  chmod a-x $(infodir)/g77.info*; \
  	else true; fi
! 	@if [ -f $(prefix)/lang-f77 -a -f $(srcdir)/f/g77.info ] ; then \
  	  if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then \
  	    echo " install-info --info-dir=$(infodir) $(infodir)/g77.info"; \
*************** f77.install-info: f77.info
*** 377,387 ****
  	  else : ; fi; \
  	else : ; fi
  
  f77.install-man: $(srcdir)/f/g77.1
  	case "$(LANGUAGES)" in \
! 	  *[fF]77*) touch lang-f77;; \
! 	  *) rm -f lang-f77;; \
  	esac
! 	-if [ -f lang-f77 -a -f f771$(exeext) ] ; then \
  	  if [ -f g77-cross$(exeext) ] ; then \
  	    rm -f $(man1dir)/$(G77_CROSS_NAME)$(manext); \
--- 378,389 ----
  	  else : ; fi; \
  	else : ; fi
+ 	rm -f $(prefix)/lang-f77
  
  f77.install-man: $(srcdir)/f/g77.1
  	case "$(LANGUAGES)" in \
! 	  *[fF]77*) touch $(prefix)/lang-f77;; \
! 	  *) rm -f $(prefix)/lang-f77;; \
  	esac
! 	-if [ -f $(prefix)/lang-f77 -a -f f771$(exeext) ] ; then \
  	  if [ -f g77-cross$(exeext) ] ; then \
  	    rm -f $(man1dir)/$(G77_CROSS_NAME)$(manext); \
*************** f77.install-man: $(srcdir)/f/g77.1
*** 394,404 ****
  	  fi; \
  	else true; fi
  
  f77.uninstall:
  	case "$(LANGUAGES)" in \
! 	  *[fF]77*) touch lang-f77;; \
! 	  *) rm -f lang-f77;; \
  	esac
! 	@if [ -f lang-f77 ] ; then \
  	  if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then \
  	    echo " install-info --delete --info-dir=$(infodir) $(infodir)/g77.info"; \
--- 396,407 ----
  	  fi; \
  	else true; fi
+ 	rm -f $(prefix)/lang-f77
  
  f77.uninstall:
  	case "$(LANGUAGES)" in \
! 	  *[fF]77*) touch $(prefix)/lang-f77;; \
! 	  *) rm -f $(prefix)/lang-f77;; \
  	esac
! 	@if [ -f $(prefix)/lang-f77 ] ; then \
  	  if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then \
  	    echo " install-info --delete --info-dir=$(infodir) $(infodir)/g77.info"; \
*************** f77.uninstall:
*** 406,410 ****
  	  else : ; fi; \
  	else : ; fi
! 	-if [ -f lang-f77 ]; then \
  	  rm -rf $(bindir)/$(G77_INSTALL_NAME)$(exeext); \
  	  rm -rf $(bindir)/$(G77_CROSS_NAME)$(exeext); \
--- 409,413 ----
  	  else : ; fi; \
  	else : ; fi
! 	-if [ -f $(prefix)/lang-f77 ]; then \
  	  rm -rf $(bindir)/$(G77_INSTALL_NAME)$(exeext); \
  	  rm -rf $(bindir)/$(G77_CROSS_NAME)$(exeext); \
*************** f77.uninstall:
*** 413,416 ****
--- 416,420 ----
  	  rm -rf $(infodir)/g77.info*; \
  	fi
+ 	rm -f $(prefix)/lang-f77
  #
  # Clean hooks:


More information about the Gcc-patches mailing list