views:

70

answers:

3

However it happens only on Windows 7. On Windows XP once it built and intact, no more builds. I narrowed down the issue to one prerequisite - $(jar_target_dir).

Here is part of the code

# The location where the JAR file will be created.
jar_target_dir := $(build_dir)/chrome

# The main chrome JAR file.
chrome_jar_file := $(jar_target_dir)/$(extension_name).jar

# The root of the JAR sources.
jar_source_root := chrome

# The sources for the JAR file.
jar_sources := bla #... some files, doesn't matter

jar_sources_no_dir := $(subst $(jar_source_root)/,,$(jar_sources))

$(chrome_jar_file): $(jar_sources) $(jar_target_dir)
    @echo "Creating chrome JAR file."
    @cd $(jar_source_root); $(ZIP) ../$(chrome_jar_file) $(jar_sources_no_dir)
    @echo "Creating chrome JAR file. Done!"

$(jar_target_dir): $(build_dir)
    echo "Creating jar target dir..."
    if [ ! -x $(jar_target_dir) ]; \
  then \
    mkdir $(jar_target_dir); \
  fi

$(build_dir):
    @if [ ! -x $(build_dir) ]; \
  then \
    mkdir $(build_dir); \
  fi

so if I just remove $(jar_target_dir) from $(chrome_jar_file) rule, it works fine.

UPD:

Here is the basic debug output from make on Windows 7

Reading makefiles...
Updating goal targets....
 File `all' does not exist.
     Prerequisite `../bin/build/chrome' is newer than
             target `../bin/build/chrome/alt.jar'.
    Must remake target `../bin/build/chrome/alt.jar'.
Creating chrome JAR file.
updating: content/about.js (deflated 66%)
updating: content/sprintf.js (deflated 52%)
...

and stats

$ stat ../bin/build/chrome/alt.jar ../bin/build/chrome
  File: `../bin/build/chrome/alt.jar'
  Size: 29220           Blocks: 32         IO Block: 65536  regular file
Device: 22c6affh/36465407d      Inode: 59672695062724268  Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/    acid)   Gid: (  513/    None)
Access: 2010-05-05 13:03:01.066457300 +0900
Modify: 2010-05-05 13:03:01.088960100 +0900
Change: 2010-05-05 13:03:01.091460400 +0900
  File: `../bin/build/chrome'
  Size: 0               Blocks: 0          IO Block: 65536  directory
Device: 22c6affh/36465407d      Inode: 3940649674014457  Links: 1
Access: (0755/drwxr-xr-x)  Uid: ( 1000/    acid)   Gid: (  513/    None)
Access: 2010-05-05 13:03:01.090960400 +0900
Modify: 2010-05-05 13:03:01.090960400 +0900
Change: 2010-05-05 13:03:01.090960400 +0900

as you can see chrome dir is really newer than alt.jar

SOL: Like Eric mentioned, it was bad idea to have directory prerequisite and make production file inside of it. Each time the mtime is updated hence 'need to rebuild'. This part is clear. However, for some cases the timestamps of directory and file created inside are always equal. That's confusing...

A: 

Your rule for creating $(jar_target_dir) looks suspicious. It creates the directory if it does not have the executable bit, which does not seem correct. My guess is that you want to do something like

$(jar_target_dir): $(build_dir)
        echo "Creating jar target dir..."
        [ -e $(jar_target_dir) ] || mkdir $(jar_target_dir)
JesperE
@JesperE: it didn't help, sorry...
Michael
A: 

I don't have Windows 7 to play with (hah!), but it looks as if when you modify a file, the OS then marks the directory it's in as being modified.

So you have to rethink the $(chrome_jar_file) rule. I suggest:

$(chrome_jar_file): $(jar_sources)
    @if [ ! -x $(build_dir) ]; then mkdir $(build_dir); fi
    @if [ ! -x $(jar_target_dir) ]; then mkdir $(jar_target_dir); fi
    ...
Beta
+1  A: 

Whenever you add or remove files in a directory, the modification time of the directory changes. For this reason, it's tricky to use directories as a prerequisite in a Makefile, particularly if the directory is intended to contain files created during the build.

If you are using GNU make 3.80 or 3.81, you can declare the directory dependency as an order-only prerequisite:

$(chrome_jar_file): $(jar_sources) | $(jar_target_dir)

Note the pipe character (or vertical bar) preceding $(jar_target_dir). This tells GNU make that the dependency is satisfied so long as the directory exists, regardless of the modification time of the prerequisite.

If you're not using GNU make, this issue is typically addressed with use of a "dummy" file in the directory. This file is created at the same time as the directory, and then your other targets depend on the dummy file instead of the directory itself. The advantage here of course is that the dummy file's modification time doesn't change when other files are added to the directory. Here's what this would look like:

$(chrome_jar_file): $(jar_sources) $(jar_target_dir)/dummy

$(jar_target_dir)/dummy:
        echo "Creating jar target dir..."
        mkdir -p $(jar_target_dir)
        touch $(jar_target_dir)/dummy
Eric Melski
@Eric Melski: You are right!
Michael