[sldev] strange behaviour of cmake on Windows

Alissa Sabre alissa_sabre at yahoo.co.jp
Sat Oct 25 20:42:42 PDT 2008


This is a summary and follow up to a thread I began.

> I'm having a build problem on Windows.
> 
> I'm working on 1.21.6 using Visual C++ Express 2005 on Windows XP.

> CMake Error at CMakeLists.txt:34 (add_subdirectory):
>   add_subdirectory not given a binary directory but the given source
>   directory "C:/alissa/dev/1.21.6/linden/indra/llcharacter" is not a
>   subdirectory of "c:/alissa/Dev/1.21.6/linden/indra".  When specifying an
>   out-of-tree source a binary directory must be explicitly specified.

> the first directory
> is surely a subdirectory
+ (of the second, although they are partly in different cases.)

Several comments received on this list in mind, I examined CMake
source, develop.py, and related python files.  I'm still puzzled and
not sure what exactly is occuring, but I found a stable workaround.

- Never use upper case letters in the full path name to the SL
  development directory.

- Patch develop.py so that it receives the drive letter from getcwd()
  in upper case.  (The patch is attached for your reference.)

The detailed story follows:

The most strange thing is that this behaviour is unstable, i.e., it is
sometimes hard to reproduce.  I kept receiving the above message for
about a week, but when I tried the same thing on a different Windows
PC, the issue disappeared.  I believe I did the same thing; even the
full path name to the development directory was same.  (It contained
/Dev/ with capital D.)  But develop.py worked fine on the machine.  I
first thought it was a version issue of some development tool, then.
However, I was still wrong because the next day, on that second
machine, I received the above message when I worked on another copy of
SL source...  When I received the error, the full path didn't contain
any capital letter.  (The case difference cmake complained was in the
drive letter.)  That means, even with the same version of development
tools, the above _difference_ may or may not detected by CMake.  Even
on the same hard drive, the drive letter may or may not recognized as
in the same case.

I have no idea why.

We can change directory name to lowercase, but we can't change the
case of drive letter.  So, workaround to rename the direcotry doesn't
apply to the drive letter.

I examined sources.  I found the followings:

- The first full path name is found by CMake by calling getcwd() C
  library function.

- The second full path name is found by develop.py by calling python
  os.getcwd() method and passed to CMake as a command line argument.

- For whatever reason, CMake tests the case of the drive letter got
  from getcwd() and makes it upper case if it is in lower case.  There
  is a comment saying "make sure the drive letter is capital".

So, I assumed that python os.getcwd() sometimes returns DOS drive
letter in upper case and sometimes in lower case.

How should we fix it?

Well, I believe it is a fundamental bug of CMake that CMake always
compares DOS path names in a case sensitive way (and probably
Macintosh path names, too.)  If my assumption that python returns
drive letter in a random case is correct, I believe it is a bug of
python, too.  A bug should be fixed at a location where the bug is in,
IMHO.  However, I considered fixing develop.py as a workaround is
easier.

Hence, I produced the attached patch.  It works fine for me.

   Alissa Sabre

-------------- next part --------------
Index: linden/indra/develop.py
===================================================================
--- linden/indra/develop.py	(revision 715)
+++ linden/indra/develop.py	(working copy)
@@ -53,6 +53,16 @@
         if err.errno != errno.EEXIST or not os.path.isdir(path):
             raise
 
+def getcwd():
+    cwd = os.getcwd()
+    if 'a' <= cwd[0] <= 'z' and cwd[1] == ':':
+        # CMake wants DOS drive letters to be in uppercase.  The above
+        # condition never asserts on platforms whose full path names
+        # always begin with a slash, so we don't need to test whether
+        # we are running on Windows.
+        cwd = cwd[0].upper() + cwd[1:]
+    return cwd
+
 def quote(opts):
     return '"' + '" "'.join([ opt.replace('"', '') for opt in opts ]) + '"'
 
@@ -141,7 +151,7 @@
         # do a sanity check to make sure we have a generator
         if not hasattr(self, 'generator'):
             raise "No generator available for '%s'" % (self.__name__,)
-        cwd = os.getcwd()
+        cwd = getcwd()
         created = []
         try:
             for d in self.build_dirs():
@@ -396,7 +406,7 @@
                 '%(opts)s %(dir)r' % args)
 
     def run_build(self, opts, targets):
-        cwd = os.getcwd()
+        cwd = getcwd()
         if targets:
             targets = ' '.join(['-target ' + repr(t) for t in targets])
         else:
@@ -530,11 +540,11 @@
                              + os.path.join(build_dir,'SecondLife.sln') \
                              + ' --config RelWithDebInfo' \
                              + ' --startup secondlife-bin'
-                print 'Running %r in %r' % (vstool_cmd, os.getcwd())
+                print 'Running %r in %r' % (vstool_cmd, getcwd())
                 self.run(vstool_cmd)        
         
     def run_build(self, opts, targets):
-        cwd = os.getcwd()
+        cwd = getcwd()
         build_cmd = self.get_build_cmd()
 
         for d in self.build_dirs():


More information about the SLDev mailing list