Boost logo

Boost-Commit :

From: jurko.gospodnetic_at_[hidden]
Date: 2008-05-05 11:52:57


Author: jurko
Date: 2008-05-05 11:52:56 EDT (Mon, 05 May 2008)
New Revision: 45144
URL: http://svn.boost.org/trac/boost/changeset/45144

Log:
  Fixed a bug causing Boost Jam not to handle target file names specified as both short and long file names correctly. Bug fixed by making bindtarget() function map names to TARGETs by using their long file names.

  When scanning directories and creating a list of all their content (filent.c) it would identify all the located files and folders using their long file names. On the other hand, referencing a target using its short file name inside a Jam script caused Boost Jam to reference those files twice using two separate TARGET structures - one identified using the file's short name and one using the file's long name.

  One bad example was the MkDir which would always attempt to create a folder identified by its short name even if that folder already existed (due to the NOUPDATE rule getting applied on the incorrect TARGET).

  The change does not affect targets whose names do not represent existing file names.

  Also, it seems to me that the short_path_to_long_path() call in file_dirscan() in the filent.c module should most likely be moved to file_info() in the filesys.c module. This would make mapping file names to file_info_t & TARGET structures consistent. However, I have not done this in this patch just to make the patch as minimal as possible.

  Prepared tests have been do nothing on non Windows platforms.

Added:
   trunk/tools/build/v2/test/file_name_handling.py (contents, props changed)
Text files modified:
   trunk/tools/build/v2/test/test_all.py | 1 +
   trunk/tools/jam/src/rules.c | 3 +++
   2 files changed, 4 insertions(+), 0 deletions(-)

Added: trunk/tools/build/v2/test/file_name_handling.py
==============================================================================
--- (empty file)
+++ trunk/tools/build/v2/test/file_name_handling.py 2008-05-05 11:52:56 EDT (Mon, 05 May 2008)
@@ -0,0 +1,256 @@
+#!/usr/bin/python
+
+# Copyright 2008 Jurko Gospodnetic
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Tests Boost Jam & Boost Build's source & target file name handling. Originally
+# added as a regression test for a bug causing versions included in the Boost
+# library 1.35 release (and earlier) not handling Windows short file names
+# correctly. Also tests handling target file names containing spaces.
+
+# Implementation notes:
+#
+# We expect Boost Jam to automatically update the 'all' target when no target
+# has been explicitly specified on the command line.
+#
+# Windows short & long file names can not be matched until the file in
+# question actually exists so we need to create the file before running Boost
+# Jam.
+#
+# Currently Windows short file names are hardcoded but in case this proves
+# insufficient we should use the GetShortPathName() Windows API to get the
+# correct short file for a given long file name.
+# (30.04.2008.) (Jurko)
+
+import BoostBuild
+import os
+import time
+
+
+################################################################################
+#
+# prepare_file()
+# --------------
+#
+#
+################################################################################
+
+def prepare_file(tester, target_name, age_in_seconds = 0):
+ """Prepares a new file with the given name, optionally setting its last
+ access and modification timestamps to the given number of seconds in the
+ history.
+ """
+ tester.write( target_name, "Original file content." )
+ if ( ( not age_in_seconds is None ) and ( age_in_seconds != 0 ) ):
+ t = time.time() - age_in_seconds
+ os.utime( tester.native_file_name( target_name ), ( t, t ) )
+
+
+################################################################################
+#
+# test_simple_file_names()
+# ------------------------
+#
+################################################################################
+
+def test_simple_file_names():
+ """Runs simple file name handling that is not expected to fail anywhere. Not
+ really needed for regular testing but the test is really fast and its
+ content may be used for comparing to other more complex test functions in
+ this module which test the same system but with some potentially more
+ problematic file names.
+ """
+ t = BoostBuild.Tester(pass_toolset=0)
+
+ prepare_file(t, "source.txt" )
+ prepare_file(t, "target.txt" , 120)
+ prepare_file(t, "target_noupdate.txt", 240)
+
+ t.write("testScript.jam", """
+actions create-file
+{
+ echo Modified file content ($(1:E="")).> "$(1:E="")"
+}
+
+DEPENDS all : standaloneTarget.txt ;
+create-file standaloneTarget.txt : all ;
+
+DEPENDS all : target.txt ;
+DEPENDS target.txt : source.txt ;
+create-file target.txt ;
+
+NOUPDATE target_noupdate.txt ;
+DEPENDS all : target_noupdate.txt ;
+DEPENDS target_noupdate.txt : source.txt ;
+create-file target_noupdate.txt ;
+
+create-file shouldNotBeCreated1 ;
+create-file shouldNotBeCreated2 ;
+create-file shouldNotBeCreated3 ;
+""")
+
+ t.run_build_system("-ftestScript.jam")
+ t.expect_addition("standaloneTarget.txt")
+ t.expect_modification("target.txt")
+ t.expect_nothing_more()
+
+ t.cleanup()
+
+
+################################################################################
+#
+# test_short_file_name_with_action()
+# ----------------------------------
+#
+################################################################################
+
+def test_short_file_name_with_action():
+ """Tests how Boost Jam handles the case when a Windows short file name is
+ passed to a Boost Jam action.
+ """
+ if ( not BoostBuild.windows ):
+ return
+
+ t = BoostBuild.Tester(pass_toolset=0)
+
+ long_file_name1 = "1__target that should be rebuilt.txt"
+ long_file_name2 = "2__target that should be rebuilt.txt"
+ short_file_name2 = "2__tar~1.txt"
+
+ prepare_file(t, long_file_name1)
+ prepare_file(t, long_file_name2)
+
+ t.write("testScript.jam", """
+actions create-file
+{
+ echo Modified file content ($(1:E="")).> "$(1:E="")"
+}
+
+ALWAYS "%(long_file_name1)s" ;
+DEPENDS all : "%(long_file_name1)s" ;
+create-file "%(long_file_name1)s" ;
+
+ALWAYS "%(long_file_name2)s" ;
+DEPENDS all : "%(long_file_name2)s" ;
+create-file "%(short_file_name2)s" ;
+""" % {'long_file_name1': long_file_name1,
+ 'long_file_name2' : long_file_name2,
+ 'short_file_name2' : short_file_name2})
+
+ t.run_build_system("-ftestScript.jam")
+ t.expect_modification(long_file_name1)
+ t.expect_modification(long_file_name2)
+ t.expect_nothing_more()
+
+ t.cleanup()
+
+
+################################################################################
+#
+# test_short_file_name_with_ALWAYS()
+# ----------------------------------
+#
+################################################################################
+
+def test_short_file_name_with_ALWAYS():
+ """Tests how Boost Jam handles the case when a Windows short file name is
+ passed to the builtin ALWAYS rule.
+ """
+ if ( not BoostBuild.windows ):
+ return
+
+ t = BoostBuild.Tester(pass_toolset=0)
+
+ long_file_name1 = "1__target that should be rebuilt.txt"
+ long_file_name2 = "2__target that should be rebuilt.txt"
+ short_file_name2 = "2__tar~1.txt"
+
+ prepare_file(t, long_file_name1)
+ prepare_file(t, long_file_name2)
+
+ t.write("testScript.jam", """
+actions create-file
+{
+ echo Modified file content ($(1:E="")).> "$(1:E="")"
+}
+
+ALWAYS "%(long_file_name1)s" ;
+DEPENDS all : "%(long_file_name1)s" ;
+create-file "%(long_file_name1)s" ;
+
+ALWAYS "%(short_file_name2)s" ;
+DEPENDS all : "%(long_file_name2)s" ;
+create-file "%(long_file_name2)s" ;
+""" % {'long_file_name1': long_file_name1,
+ 'long_file_name2' : long_file_name2,
+ 'short_file_name2' : short_file_name2})
+
+ t.run_build_system("-ftestScript.jam")
+ t.expect_modification(long_file_name1)
+ t.expect_modification(long_file_name2)
+ t.expect_nothing_more()
+
+ t.cleanup()
+
+
+################################################################################
+#
+# test_short_file_name_with_NOUPDATE()
+# ------------------------------------
+#
+################################################################################
+
+def test_short_file_name_with_NOUPDATE():
+ """Tests how Boost Jam handles the case when a Windows short file name is
+ passed to the builtin NOUPDATE rule.
+ """
+ if ( not BoostBuild.windows ):
+ return
+
+ t = BoostBuild.Tester(pass_toolset=0)
+
+ long_file_name1 = "1__target that should be rebuilt.txt"
+ long_file_name2 = "2__target that should not be rebuilt.txt"
+ short_file_name2 = "2__tar~1.txt"
+
+ prepare_file(t, "source.txt" )
+ prepare_file(t, long_file_name1, 120)
+ prepare_file(t, long_file_name2, 120)
+
+ t.write("testScript.jam", """
+actions create-file
+{
+ echo Modified file content ($(1:E="")).> "$(1:E="")"
+}
+
+DEPENDS all : "%(long_file_name1)s" ;
+DEPENDS "%(long_file_name1)s" : source.txt ;
+create-file "%(long_file_name1)s" ;
+
+NOUPDATE "%(short_file_name2)s" ;
+DEPENDS all : "%(long_file_name2)s" ;
+DEPENDS "%(long_file_name2)s" : source.txt ;
+create-file "%(long_file_name2)s" ;
+""" % {'long_file_name1': long_file_name1,
+ 'long_file_name2' : long_file_name2,
+ 'short_file_name2' : short_file_name2})
+
+ t.run_build_system("-ftestScript.jam")
+ t.expect_modification(long_file_name1)
+ t.expect_nothing_more()
+
+ t.cleanup()
+
+
+################################################################################
+#
+# main()
+# ------
+#
+################################################################################
+
+test_simple_file_names()
+test_short_file_name_with_action()
+test_short_file_name_with_ALWAYS()
+test_short_file_name_with_NOUPDATE()

Modified: trunk/tools/build/v2/test/test_all.py
==============================================================================
--- trunk/tools/build/v2/test/test_all.py (original)
+++ trunk/tools/build/v2/test/test_all.py 2008-05-05 11:52:56 EDT (Mon, 05 May 2008)
@@ -167,6 +167,7 @@
           "example_make",
           "remove_requirement",
           "free_features_request",
+ "file_name_handling",
           "sort_rule"
           ]
 

Modified: trunk/tools/jam/src/rules.c
==============================================================================
--- trunk/tools/jam/src/rules.c (original)
+++ trunk/tools/jam/src/rules.c 2008-05-05 11:52:56 EDT (Mon, 05 May 2008)
@@ -137,6 +137,9 @@
             targethash = hashinit( sizeof( TARGET ), "targets" );
 
     /* Perforce added const everywhere. No time to merge that change. */
+#ifdef NT
+ targetname = short_path_to_long_path( (char*)targetname );
+#endif
         t->name = (char*)targetname;
 
         if( hashenter( targethash, (HASHDATA **)&t ) )


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk