#32426: angelscript: sometimes rebuilds in destroot phase, causing wrong library install_name -------------------------------------+-------------------------------------- Reporter: ryandesign@… | Owner: rudloff@… Type: defect | Status: new Priority: Normal | Milestone: Component: ports | Version: 2.0.3 Keywords: | Port: angelscript -------------------------------------+-------------------------------------- Comment(by ryandesign@…): The makefile defines a variable `TARG` representing all the targets that will be built and installed (i.e. the three libraries): {{{ TARG = $(LIBDIR)/$(LIB) $(LIBDIR)/$(DEVLIB) $(LIBDIR)/$(BUNDLE) }}} The `all` and `install` rules depend on this variable, and thus on all three libraries: {{{ all: $(TARG) ... install: $(TARG) }}} There are also two rules to create directories: the object directory (where objects get built before they're packed into a library) and the library directory (where the libraries go after they're built): {{{ $(OBJDIR): mkdir $(OBJDIR) $(LIBDIR): mkdir $(LIBDIR) }}} There are also variables `OBJ` and `BOBJ` containing the lists of objects needed for the libraries, not relevant to the problem. The three libraries are defined as depending on the creation of the directories, and on their list of objects, as follows: {{{ $(LIBDIR)/$(LIB): $(OBJDIR) $(LIBDIR) $(OBJ) ... $(LIBDIR)/$(DEVLIB): $(OBJDIR) $(LIBDIR) $(OBJ) ... $(LIBDIR)/$(BUNDLE): $(OBJDIR) $(LIBDIR) $(BOBJ) ... }}} The problem comes about because of the way `make` works, and the way directories work. The way `make` works is that for each rule, it determines whether the file (or directory) that the rule is for exists. If not, it deals with the dependencies, and then makes the rule. If the file the rule is for does exist, it looks at the timestamps of that file, and of the dependencies' files, and of the makefile; if the makefile or the dependencies are newer, then the rule is remade. The way directories work is that if you add or remove a file in the directory, the directory's modification time is updated. The error is always reproducible in a serial build (unless you have a computer that's 10-20 times faster than mine). The sequence of events is as follows: * T1 * MacPorts runs `make all`, which depends on `TARG`, which expands to the three libraries. * T2 * The dependencies of the first library are evaluated. Neither the object directory nor the library directory exist, so those rules are run, thus creating those directories. Their modification time is T2. * T3 * The first object is built, in the object directory. The act of creating the object file in the object directory causes the object directory's modification time to be updated to T3. * ... similarly for the other object files. This takes a couple dozen seconds on my system. As each object is built, the object directory's modification time advances. * T4 * The first library is built. This takes some seconds. It gets put into the library directory. This causes the library directory's modification time to be updated and is now T4. * T5 * The dependencies of the second library are evaluated. The directories already exist; no action necessary. The objects are the same as the first library's so they're already built too. * T6 * The second library is built. This takes some seconds. It gets put into the library directory, thus updating the library directory's modification time to T6. * ... similarly with the third library * T7 * MacPorts runs `make install`, which depends on `TARG`, which expands to the three libraries. * T8 * The first library exists; its modification time is T4. The dependencies of the first library are evaluated. The object directory exists and its modification time is somewhere between T3 and T4 which is older than the library so we move on. The library directory exists, but its modification time is T6. This is newer than the library's T4 modification time, so `make` rebuilds the first library, and there we have the problem. The reason the problem is intermittent is that MacPorts runs a parallel build by default -- and not a serial build -- provided you have enough memory and processor cores. On my system, the libraries were either finishing up their simultaneous builds at the same exact second (in which case the destroot would happen normally), or a second apart (thus triggering the rebuild in the destroot phase, and, in my case, an error message from [wiki:UsingTheRightCompiler#testing]). -- Ticket URL: <https://trac.macports.org/ticket/32426#comment:1> MacPorts <http://www.macports.org/> Ports system for Mac OS