Index: /CMT/HEAD/ChangeLog
===================================================================
--- /CMT/HEAD/ChangeLog	(revision 428)
+++ /CMT/HEAD/ChangeLog	(revision 429)
@@ -1,2 +1,14 @@
+2007-11-22    <rybkin@lal.in2p3.fr> 335
+
+	* source/cmt_generators.h: idem
+	* source/cmt_generators.cxx: idem
+	* source/cmt_lock.cxx: idem
+	* mgr/fragments/constituent_lock: idem
+	* mgr/fragments/nmake/constituent_lock: idem
+	* mgr/requirements: Implement a locking mechanism to allow simultaneous/parallel
+	builds for multiple binary tags. Used suggestions from Pere, Stefan, and Andrea
+	* mgr/lockfile.bat: Basic semaphore-file creator for Windows
+	* mgr/lockfile.sh: Basic semaphore-file creator for Unix
+	
 2007-10-31    <rybkin@lal.in2p3.fr> 334
 
Index: /CMT/HEAD/mgr/fragments/constituent_lock
===================================================================
--- /CMT/HEAD/mgr/fragments/constituent_lock	(revision 429)
+++ /CMT/HEAD/mgr/fragments/constituent_lock	(revision 429)
@@ -0,0 +1,87 @@
+#-- start of constituent_lock ------
+
+cmt_${CONSTITUENT}_${HASTARGETTAG} = 1
+
+#--------------------------------------------------------
+
+ifdef cmt_${CONSTITUENT}_has_target_tag
+
+ifdef READONLY
+cmt_local_tagfile_${CONSTITUENT} = /tmp/CMT_$(${PACKAGE}_tag)_${CONSTITUENT}.make$(cmt_lock_pid)
+cmt_final_setup_${CONSTITUENT} = /tmp/CMT_${PACKAGE}_${CONSTITUENT}setup.make
+cmt_local_${CONSTITUENT}_makefile = /tmp/CMT_${CONSTITUENT}$(cmt_lock_pid).make
+else
+cmt_local_tagfile_${CONSTITUENT} = $(${PACKAGE}_tag)_${CONSTITUENT}.make
+cmt_final_setup_${CONSTITUENT} = $(bin)${PACKAGE}_${CONSTITUENT}setup.make
+cmt_local_${CONSTITUENT}_makefile = $(bin)${CONSTITUENT}.make
+endif
+
+${CONSTITUENT}_extratags = -tag_add=target_${CONSTITUENT}
+
+$(cmt_local_tagfile_${CONSTITUENT}) : $(cmt_lock_setup)
+	@/bin/echo "------> (constituents.make) Rebuilding setup.make $(cmt_local_tagfile_${CONSTITUENT})"
+	@if test -f $(cmt_local_tagfile_${CONSTITUENT}); then /bin/rm -f $(cmt_local_tagfile_${CONSTITUENT}); fi ; \
+	  $(cmtexe) -quiet -tag=$(tags) $(${CONSTITUENT}_extratags) build tag_makefile >>$(cmt_local_tagfile_${CONSTITUENT}); \
+	  if test -f $(cmt_final_setup_${CONSTITUENT}); then /bin/rm -f $(cmt_final_setup_${CONSTITUENT}); fi; \
+	  $(cmtexe) -quiet -tag=$(tags) $(${CONSTITUENT}_extratags) show setup >>$(cmt_final_setup_${CONSTITUENT})
+	@/bin/echo setup.make ok
+
+else
+
+ifdef READONLY
+cmt_local_tagfile_${CONSTITUENT} = /tmp/CMT_$(${PACKAGE}_tag).make$(cmt_lock_pid)
+cmt_final_setup_${CONSTITUENT} = /tmp/CMT_${PACKAGE}setup.make
+cmt_local_${CONSTITUENT}_makefile = /tmp/CMT_${CONSTITUENT}$(cmt_lock_pid).make
+else
+cmt_local_tagfile_${CONSTITUENT} = $(${PACKAGE}_tag).make
+cmt_final_setup_${CONSTITUENT} = $(bin)${PACKAGE}setup.make
+cmt_local_${CONSTITUENT}_makefile = $(bin)${CONSTITUENT}.make
+endif
+
+endif
+
+$(cmt_local_${CONSTITUENT}_makefile) :: $(${CONSTITUENT}_dependencies) $(cmt_local_tagfile_${CONSTITUENT}) build_library_links dirs
+	@echo "------> (constituents.make) Building ${CONSTITUENT}.make"; \
+	  $(cmtexe) -quiet -tag=$(tags) $(${CONSTITUENT}_extratags) build constituent_makefile -out=$(cmt_local_${CONSTITUENT}_makefile) ${CONSTITUENT}
+
+${CONSTITUENT} :: $(${CONSTITUENT}_dependencies) $(cmt_local_${CONSTITUENT}_makefile)
+	@echo "------> (constituents.make) Creating ${CONSTITUENT}${lock_suffix}"
+	@${lock_command} ${CONSTITUENT}${lock_suffix}
+	@echo "------> (constituents.make) Starting ${CONSTITUENT}"
+	@$(MAKE) -f $(cmt_local_${CONSTITUENT}_makefile) $(MAKEFLAGS) cmt_lock_pid=$${cmt_lock_pid} ${CONSTITUENT}; \
+	status=$$?; ${unlock_command} ${CONSTITUENT}${lock_suffix}; exit $${status}
+	@echo "------> (constituents.make) ${CONSTITUENT} done"
+
+clean :: ${CONSTITUENT}clean
+
+${CONSTITUENT}clean :: $(${CONSTITUENT}clean_dependencies) ##$(cmt_local_${CONSTITUENT}_makefile)
+	@-if test -f $(cmt_local_${CONSTITUENT}_makefile); then \
+	  echo "------> (constituents.make) Starting ${CONSTITUENT}clean"; \
+	  $(MAKE) -f $(cmt_local_${CONSTITUENT}_makefile) $(MAKEFLAGS) cmt_lock_pid=$${cmt_lock_pid} ${CONSTITUENT}clean; \
+	fi
+
+##	  /bin/rm -f $(cmt_local_${CONSTITUENT}_makefile) $(bin)${CONSTITUENT}_dependencies.make
+
+install :: ${CONSTITUENT}install
+
+${CONSTITUENT}install :: $(${CONSTITUENT}_dependencies) $(cmt_local_${CONSTITUENT}_makefile)
+	@echo "------> (constituents.make) Starting install ${CONSTITUENT}"
+	@-$(MAKE) -f $(cmt_local_${CONSTITUENT}_makefile) $(MAKEFLAGS) cmt_lock_pid=$${cmt_lock_pid} install
+	@echo "------> (constituents.make) install ${CONSTITUENT} done"
+
+uninstall :: ${CONSTITUENT}uninstall
+
+${CONSTITUENT}uninstall :: $(cmt_local_${CONSTITUENT}_makefile)
+	@echo "------> (constituents.make) Starting uninstall ${CONSTITUENT}"
+	@-$(MAKE) -f $(cmt_local_${CONSTITUENT}_makefile) $(MAKEFLAGS) cmt_lock_pid=$${cmt_lock_pid} uninstall
+	@echo "------> (constituents.make) uninstall ${CONSTITUENT} done"
+
+ifndef PEDANTIC
+.DEFAULT::
+	@echo "------> (constituents.make) Starting $@ ${CONSTITUENT}"
+	@echo Using default action for $@
+	@echo "------> (constituents.make) $@ ${CONSTITUENT} done"
+endif
+
+
+#-- end of constituent_lock ------
Index: /CMT/HEAD/mgr/fragments/nmake/constituent_lock
===================================================================
--- /CMT/HEAD/mgr/fragments/nmake/constituent_lock	(revision 429)
+++ /CMT/HEAD/mgr/fragments/nmake/constituent_lock	(revision 429)
@@ -0,0 +1,78 @@
+#-- start of constituent_lock ------
+
+cmt_${CONSTITUENT}_${HASTARGETTAG} = 1
+
+#--------------------------------------------------------
+
+!if defined (cmt_${CONSTITUENT}_has_target_tag)
+
+cmt_local_tagfile_${CONSTITUENT} = $(${PACKAGE}_tag)_${CONSTITUENT}.nmake
+cmt_final_setup_${CONSTITUENT} = $(bin)${PACKAGE}_${CONSTITUENT}_setup.nmake
+cmt_local_${CONSTITUENT}_makefile = $(bin)${CONSTITUENT}.nmake
+
+${CONSTITUENT}_extratags = -tag_add=target_${CONSTITUENT}
+
+!if [if not exist $(bin) mkdir $(bin)] == 0
+!endif
+
+!if [cmt -quiet -tag=$(tags) $(${CONSTITUENT}_extratags) build tag_makefile >$(cmt_local_tagfile_${CONSTITUENT})] == 0
+!endif
+
+!if [$(cmtexe) -quiet -tag=$(tags) $(${CONSTITUENT}_extratags) show setup >$(cmt_final_setup_${CONSTITUENT})] == 0
+!endif
+
+!else
+
+cmt_local_tagfile_${CONSTITUENT} = $(${PACKAGE}_tag).nmake
+cmt_final_setup_${CONSTITUENT} = $(bin)${PACKAGE}_setup.nmake
+cmt_local_${CONSTITUENT}_makefile = $(bin)${CONSTITUENT}.nmake
+
+!endif
+
+$(cmt_local_${CONSTITUENT}_makefile) :: $(${CONSTITUENT}_dependencies) $(cmt_local_tagfile_${CONSTITUENT}) dirs
+	@echo (constituents.nmake) Building ${CONSTITUENT}.nmake
+	@set include=$(include)
+	@set lib=$(lib)
+	@$(cmtexe) -quiet -tag=$(tags) $(${CONSTITUENT}_extratags) build -nmake constituent_makefile ${CONSTITUENT}
+	@move ${CONSTITUENT}.nmake $(bin)
+	@echo (constituents.nmake) ${CONSTITUENT}.nmake done
+
+${CONSTITUENT} :: $(${CONSTITUENT}_dependencies) $(cmt_local_${CONSTITUENT}_makefile)
+	@echo "------> (constituents.make) Creating ${CONSTITUENT}$(lock_suffix)"
+	@$(lock_command) ${CONSTITUENT}$(lock_suffix)
+	@echo (constituents.nmake) Starting ${CONSTITUENT}
+	@set include=$(include)
+	@set lib=$(lib)
+	@$(MAKE) /nologo /f $(cmt_local_${CONSTITUENT}_makefile) $(MAKEFLAGS) build_strategy=keep_makefiles ${CONSTITUENT} tag=$(tag) \
+	|| ($(unlock_command) ${CONSTITUENT}$(lock_suffix) & exit 1)
+	@$(unlock_command) ${CONSTITUENT}$(lock_suffix)
+	@echo (constituents.nmake) ${CONSTITUENT} done
+
+clean :: ${CONSTITUENT}clean
+
+${CONSTITUENT}clean :: $(${CONSTITUENT}clean_dependencies) ##$(cmt_local_${CONSTITUENT}_makefile)
+	@echo (constituents.nmake) Starting ${CONSTITUENT}clean
+	@set include=$(include)
+	@set lib=$(lib)
+	@-if exist $(cmt_local_${CONSTITUENT}_makefile) $(MAKE) /nologo /f $(cmt_local_${CONSTITUENT}_makefile) $(MAKEFLAGS) build_strategy=keep_makefiles ${CONSTITUENT}clean tag=$(tag)
+	@echo (constituents.nmake) ${CONSTITUENT}clean done
+
+install :: ${CONSTITUENT}install
+
+${CONSTITUENT}install :: $(${CONSTITUENT}_dependencies) $(cmt_local_${CONSTITUENT}_makefile)
+	@echo (constituents.nmake) Starting install ${CONSTITUENT}
+	@set include=$(include)
+	@set lib=$(lib)
+	@-$(MAKE) /nologo /f $(cmt_local_${CONSTITUENT}_makefile) $(MAKEFLAGS) build_strategy=keep_makefiles install tag=$(tag)
+	@echo (constituents.nmake) install ${CONSTITUENT} done
+
+uninstall :: ${CONSTITUENT}uninstall
+
+${CONSTITUENT}uninstall :: $(cmt_local_${CONSTITUENT}_makefile)
+	@echo (constituents.nmake) Starting uninstall ${CONSTITUENT}"
+	@set include=$(include)
+	@set lib=$(lib)
+	@-$(MAKE) /nologo /f $(cmt_local_${CONSTITUENT}_makefile) $(MAKEFLAGS) build_strategy=keep_makefiles uninstall tag=$(tag)
+	@echo (constituents.nmake) uninstall ${CONSTITUENT} done
+
+#-- end of constituent_lock ------
Index: /CMT/HEAD/mgr/lockfile.bat
===================================================================
--- /CMT/HEAD/mgr/lockfile.bat	(revision 429)
+++ /CMT/HEAD/mgr/lockfile.bat	(revision 429)
@@ -0,0 +1,16 @@
+@echo off
+
+if not "%1"=="" (
+  set /A secs=8+1
+:lock
+  mkdir %1 2>nul
+  if errorlevel 1 (
+    ping -n %secs% localhost >nul
+    goto lock
+  )
+)
+
+if "%1"=="" (
+  echo Usage: lockfile file
+)
+
Index: /CMT/HEAD/mgr/lockfile.sh
===================================================================
--- /CMT/HEAD/mgr/lockfile.sh	(revision 429)
+++ /CMT/HEAD/mgr/lockfile.sh	(revision 429)
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+# lockfile.sh: Basic semaphore-file creator for Unix
+# Use it if the lockfile utility from http://www.procmail.org/
+# is not installed
+
+if [ "$1" != "" ]; then
+    secs=8
+    until mkdir $1 2>/dev/null; do
+	sleep $secs
+    done
+else
+    echo Usage: lockfile file
+fi
Index: /CMT/HEAD/mgr/requirements
===================================================================
--- /CMT/HEAD/mgr/requirements	(revision 428)
+++ /CMT/HEAD/mgr/requirements	(revision 429)
@@ -445,9 +445,15 @@
 macro library_suffix ""
 
-macro lock_command "chmod -R a-w ../*" \   
-      VisualC      "attrib /S /D +R ..\*"
-
-macro unlock_command "chmod -R g+w ../*" \   
-      VisualC      "attrib /S /D -R ..\*"
+macro lock_command "" \
+      Linux        "lockfile " \
+      Darwin       "lockfile " \
+      VisualC      "%CMTROOT%\mgr\lockfile.bat "
+
+macro unlock_command "rm -rf " \   
+      VisualC        "rmdir "
+
+macro lock_name "cmt"
+macro lock_suffix ".lock"
+macro lock_file "${lock_name}${lock_suffix}"
 
 macro preprocessor_command "" \
@@ -554,4 +560,5 @@
 make_fragment group
 make_fragment constituent
+make_fragment constituent_lock
 make_fragment constituents_trailer
 
Index: /CMT/HEAD/source/cmt_generators.cxx
===================================================================
--- /CMT/HEAD/source/cmt_generators.cxx	(revision 428)
+++ /CMT/HEAD/source/cmt_generators.cxx	(revision 429)
@@ -2404,4 +2404,5 @@
   group_fragment.set ("group");
   constituent_fragment.set ("constituent");
+  constituent_lock_fragment.set ("constituent_lock");
   check_application_header_fragment.set ("check_application_header");
 }
@@ -2414,4 +2415,5 @@
   group_fragment.reset ();
   constituent_fragment.reset ();
+  constituent_lock_fragment.reset ();
   check_application_header_fragment.reset ();
 }
@@ -2452,5 +2454,5 @@
 
   cmt_string save_file_name = file_name;
-  save_file_name += "sav";
+  save_file_name += "cmtsave";
 
   if (CmtSystem::test_file (file_name))
@@ -2487,4 +2489,22 @@
         }
       
+      bool lock = false;
+      Symbol* lock_command_macro = Symbol::find ("lock_command");
+      if (lock_command_macro != 0)
+	{
+	  cmt_string lock_command = lock_command_macro->resolve_macro_value ();
+	  if (lock_command != "")
+	    {
+	      Symbol* unlock_command_macro = Symbol::find ("unlock_command");
+	      if (unlock_command_macro != 0)
+		{
+		  cmt_string unlock_command = unlock_command_macro->resolve_macro_value ();
+		  if (unlock_command != "")
+		    {
+		      lock = true;
+		    }
+		}
+	    }
+	}
       for (number = 0; number < constituents.size (); number++)
         {
@@ -2505,10 +2525,24 @@
 	    }
 
-          constituent_fragment.copy (m_output_file, constituent.variables, 5, 
-				     &m_PACKAGE,
-				     &m_CONSTITUENT, 
-                                     &m_CONSTITUENTSUFFIX,
-                                     &m_LINE,
-				     &m_HASTARGETTAG);
+	  if (constituent.type == Document && lock == true)
+	    {
+	      constituent_lock_fragment.copy (m_output_file, constituent.variables,
+					      5,
+					      &m_PACKAGE,
+					      &m_CONSTITUENT, 
+					      &m_CONSTITUENTSUFFIX,
+					      &m_LINE,
+					      &m_HASTARGETTAG);
+	    }
+	  else
+	    {
+	      constituent_fragment.copy (m_output_file, constituent.variables,
+					 5,
+					 &m_PACKAGE,
+					 &m_CONSTITUENT, 
+					 &m_CONSTITUENTSUFFIX,
+					 &m_LINE,
+					 &m_HASTARGETTAG);
+	    }
 
           if (constituent.need_check)
Index: /CMT/HEAD/source/cmt_generators.h
===================================================================
--- /CMT/HEAD/source/cmt_generators.h	(revision 428)
+++ /CMT/HEAD/source/cmt_generators.h	(revision 429)
@@ -208,4 +208,5 @@
   FragmentHandle group_fragment;
   FragmentHandle constituent_fragment;
+  FragmentHandle constituent_lock_fragment;
   FragmentHandle check_application_header_fragment;
 };
Index: /CMT/HEAD/source/cmt_lock.cxx
===================================================================
--- /CMT/HEAD/source/cmt_lock.cxx	(revision 428)
+++ /CMT/HEAD/source/cmt_lock.cxx	(revision 429)
@@ -14,24 +14,38 @@
 CmtLock::status CmtLock::lock ()
 {
-  status s = check ();
+//   status s = check ();
 
-  switch (s)
+//   switch (s)
+//     {
+//     case locked_by_user:
+//       cerr << "Package already locked by you" << endl;
+//       return (s);
+//     case locked_by_another_user:
+//       CmtError::set (CmtError::cannot_lock, "lock> Package already locked by another user");
+//       return (s);
+//     case not_locked:
+//       break;
+//     }
+
+//   cmt_string text = "locked by ";
+//   text += CmtSystem::user ();
+//   text += " date ";
+//   text += CmtSystem::now ();
+
+//   if (!text.write ("lock.cmt"))
+//     {
+//       CmtError::set (CmtError::cannot_write_lock, "lock>");
+//       return (still_unlocked);
+//     }
+
+//  cmt_string command = lock_command->build_macro_value ();
+
+  cmt_string lock_command;
+  Symbol* lock_command_macro = Symbol::find ("lock_command");
+  if (lock_command_macro != 0)
     {
-    case locked_by_user:
-      cerr << "Package already locked by you" << endl;
-      return (s);
-    case locked_by_another_user:
-      CmtError::set (CmtError::cannot_lock, "lock> Package already locked by another user");
-      return (s);
-    case not_locked:
-      break;
+      lock_command = lock_command_macro->resolve_macro_value ();
     }
-
-  cmt_string text = "locked by ";
-  text += CmtSystem::user ();
-  text += " date ";
-  text += CmtSystem::now ();
-
-  if (!text.write ("lock.cmt"))
+  if (lock_command == "")
     {
       CmtError::set (CmtError::cannot_write_lock, "lock>");
@@ -39,17 +53,22 @@
     }
 
-  Symbol* lock_command = Symbol::find ("lock_command");
-  if (lock_command != 0)
+  cmt_string lock_file;
+  Symbol* lock_file_macro = Symbol::find ("lock_file");
+  if (lock_file_macro != 0)
     {
-      cmt_string command = lock_command->build_macro_value ();
+      lock_file = lock_file_macro->resolve_macro_value ();
+    }
+  if (lock_file == "")
+    {
+      CmtError::set (CmtError::cannot_write_lock, "lock>");
+      return (still_unlocked);
+    }
 
-      if (command != "")
-	{
-	  if (CmtSystem::execute (command) != 0)
-	    {
-	      CmtError::set (CmtError::cannot_run_lock_command, "lock>");
-	      return (still_unlocked);
-	    }
-	}
+  cmt_string command = lock_command + " " + lock_file;
+
+  if (CmtSystem::execute (command) != 0)
+    {
+      CmtError::set (CmtError::cannot_run_lock_command, "lock>");
+      return (still_unlocked);
     }
 
@@ -72,26 +91,58 @@
       return (s);
     case not_locked:
-      cerr << "The package was not locked" << endl;
+      cerr << "Package not locked" << endl;
       return (s);
     }
 
-  Symbol* unlock_command = Symbol::find ("unlock_command");
-  if (unlock_command != 0)
+//   Symbol* unlock_command = Symbol::find ("unlock_command");
+//   if (unlock_command != 0)
+//     {
+//       cmt_string command = unlock_command->build_macro_value ();
+
+//       if (command != "")
+// 	{
+// 	  if (CmtSystem::execute (command) != 0)
+// 	    {
+// 	      CmtError::set (CmtError::cannot_run_unlock_command, "unlock>");
+// 	      return (still_locked);
+// 	    }
+// 	}
+//     }
+
+//   if (!CmtSystem::remove_file ("lock.cmt"))
+//     {
+//       CmtError::set (CmtError::cannot_remove_lock, "unlock>");
+//       return (still_locked);
+//     }
+
+  cmt_string unlock_command;
+  Symbol* unlock_command_macro = Symbol::find ("unlock_command");
+  if (unlock_command_macro != 0)
     {
-      cmt_string command = unlock_command->build_macro_value ();
-
-      if (command != "")
-	{
-	  if (CmtSystem::execute (command) != 0)
-	    {
-	      CmtError::set (CmtError::cannot_run_unlock_command, "unlock>");
-	      return (still_locked);
-	    }
-	}
+      unlock_command = unlock_command_macro->resolve_macro_value ();
+    }
+  if (unlock_command == "")
+    {
+      CmtError::set (CmtError::cannot_remove_lock, "unlock>");
+      return (still_locked);
     }
 
-  if (!CmtSystem::remove_file ("lock.cmt"))
+  cmt_string lock_file;
+  Symbol* lock_file_macro = Symbol::find ("lock_file");
+  if (lock_file_macro != 0)
+    {
+      lock_file = lock_file_macro->resolve_macro_value ();
+    }
+  if (lock_file == "")
     {
       CmtError::set (CmtError::cannot_remove_lock, "unlock>");
+      return (still_locked);
+    }
+
+  cmt_string command = unlock_command + " " + lock_file;
+
+  if (CmtSystem::execute (command) != 0)
+    {
+      CmtError::set (CmtError::cannot_run_unlock_command, "unlock>");
       return (still_locked);
     }
@@ -105,24 +156,35 @@
 CmtLock::status CmtLock::check ()
 {
-  cmt_string me = CmtSystem::user ();
-  cmt_string text;
+//   cmt_string me = CmtSystem::user ();
+//   cmt_string text;
 
-  if (text.read ("lock.cmt"))
+//   if (text.read ("lock.cmt"))
+//     {
+//       CmtSystem::cmt_string_vector words;
+
+//       CmtSystem::split (text, " ", words);
+
+//       if (words.size () >= 3)
+// 	{
+// 	  if (words[2] == me)
+// 	    {
+// 	      return (locked_by_user);
+// 	    }
+// 	  else
+// 	    {
+// 	      return (locked_by_another_user);
+// 	    }
+// 	}
+//     }
+  cmt_string lock_file;
+  Symbol* lock_file_macro = Symbol::find ("lock_file");
+  if (lock_file_macro != 0)
     {
-      CmtSystem::cmt_string_vector words;
+      lock_file = lock_file_macro->resolve_macro_value ();
+    }
 
-      CmtSystem::split (text, " ", words);
-
-      if (words.size () >= 3)
-	{
-	  if (words[2] == me)
-	    {
-	      return (locked_by_user);
-	    }
-	  else
-	    {
-	      return (locked_by_another_user);
-	    }
-	}
+  if (CmtSystem::test_file (lock_file) || CmtSystem::test_directory (lock_file))
+    {
+      return (locked_by_user);
     }
 	
