MantisBT - CMake
View Issue Details
0010569CMakeCMakepublic2010-04-16 13:382010-06-14 17:16
Daniel Richard G. 
Brad King 
normalminoralways
closedfixed 
CMake-2-8 
 
0010569: "Unix Makefiles" generator fails to account for Tru64 make(1) quirk
Building 2.8.1 on Tru64 with a prebuilt CMake and the native make(1) program:

[...]
-- Java version .. configured successfully!
-- Could NOT find Java (missing: Java_JAR_EXECUTABLE _java_version_acceptable)
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/cmake-build
user@host:/tmp/cmake-build> make
Make: Cannot open Source/kwsys/CMakeFiles/cmsys.dir/Source/kwsys/CMakeFiles/cmsys.dir/depend.make. Stop.
*** Exit 1
Stop.
*** Exit 1
Stop.
user@host:/tmp/cmake-build> bash
bash-3.1$ find . -name \*.make | while read f; do perl -pi -e 's!^include !include \$(CMAKE_BINARY_DIR)/!' $f; done
bash-3.1$ exit
user@host:/tmp/cmake-build> make
Scanning dependencies of target cmsys
[ 0%] Building C object Source/kwsys/CMakeFiles/cmsys.dir/ProcessUNIX.o
[ 0%] Building C object Source/kwsys/CMakeFiles/cmsys.dir/Base64.o

What's going on here is the odd way Tru64's make(1) resolves relative paths in "include" directives. Let me assemble a toy example:

$ mkdir -p foo/bar/baz
$ cat >foo/bar/baz/Makefile
include foo/bar/baz/inc.make
test:
        echo Hello $(NAME)
^D
$ cat >foo/bar/baz/inc.make
NAME = Bob
^D
$ make -f foo/bar/baz/Makefile
Make: Cannot open foo/bar/baz/foo/bar/baz/inc.make. Stop.

Relative paths are interpreted as relative to the file doing the include. Which can be handily addressed by qualifying the paths with $(CMAKE_BINARY_DIR).
No tags attached.
patch cmake-10569-fix.patch (1,553) 2010-04-22 14:00
https://public.kitware.com/Bug/file/3055/cmake-10569-fix.patch
Issue History
2010-04-16 13:38Daniel Richard G.New Issue
2010-04-16 15:37Bill HoffmanNote Added: 0020227
2010-04-16 15:37Bill HoffmanStatusnew => assigned
2010-04-16 15:37Bill HoffmanAssigned To => Brad King
2010-04-16 15:37Bill HoffmanNote Added: 0020228
2010-04-16 15:42Brad KingNote Added: 0020231
2010-04-16 15:59Daniel Richard G.Note Added: 0020233
2010-04-16 16:19Brad KingNote Added: 0020235
2010-04-17 20:51Daniel Richard G.Note Added: 0020243
2010-04-22 14:00Daniel Richard G.File Added: cmake-10569-fix.patch
2010-04-22 14:00Daniel Richard G.Note Added: 0020357
2010-04-22 14:30Brad KingNote Added: 0020360
2010-04-22 16:04Daniel Richard G.Note Added: 0020363
2010-04-22 16:21Brad KingAssigned ToBrad King => Bill Hoffman
2010-06-10 11:56Brad KingAssigned ToBill Hoffman => Brad King
2010-06-10 11:57Brad KingNote Added: 0020968
2010-06-10 15:04Daniel Richard G.Note Added: 0020979
2010-06-12 19:23Daniel Richard G.Note Added: 0020998
2010-06-14 08:24Brad KingNote Added: 0020999
2010-06-14 12:58Daniel Richard G.Note Added: 0021001
2010-06-14 13:08Brad KingNote Added: 0021002
2010-06-14 17:13Daniel Richard G.Note Added: 0021007
2010-06-14 17:16Brad KingNote Added: 0021008
2010-06-14 17:16Brad KingStatusassigned => closed
2010-06-14 17:16Brad KingResolutionopen => fixed

Notes
(0020227)
Bill Hoffman   
2010-04-16 15:37   
Can we just use gmake on this platform?
(0020228)
Bill Hoffman   
2010-04-16 15:37   
I suppose we could use full path include...
(0020231)
Brad King   
2010-04-16 15:42   
Does that make tool deal with spaces in the path? What happens if you do

include $(CMAKE_BINARY_DIR)/foo/bar/baz/inc.make

when the variable replacement has a space?
(0020233)
Daniel Richard G.   
2010-04-16 15:59   
I tested that, Brad, and surprisingly, make(1) handles the space in the variable expansion perfectly.

What's more, putting single-quotes, double-quotes, or backslashes into the mix breaks things. If the expansion starts with a quote and not a slash, make(1) interprets that as a relative path. Even if you only quote the path components with spaces, make(1) uses the expansion as a literal filename (e.g. if it sees /tmp/"foo bar"/baz, it tries to open "/tmp/\"foo bar\"/baz").
(0020235)
Brad King   
2010-04-16 16:19   
In Source/cmMakefileTargetGenerator.cxx find the method cmMakefileTargetGenerator::WriteCommonCodeRules. Look for lines that use this->IncludeDirective and add "$(CMAKE_BINARY_DIR)/" to the string literal that currently just has a space.
(0020243)
Daniel Richard G.   
2010-04-17 20:51   
Yep! That does the trick. With those edits, CMake's generated Unix makefiles are compatible with Tru64's /usr/ccs/bin/make program. (I also tried /usr/opt/ultrix/usr/bin/make and /usr/bin/posix/make, and those work as well.)

--- cmake-2.8.1/Source/cmMakefileTargetGenerator.cxx 2010-04-06 10:45:35.000000000 -0400
+++ cmake-2.8.1-tru64/Source/cmMakefileTargetGenerator.cxx 2010-04-16 16:41:12.000000000 -0400
@@ -194,7 +194,7 @@
   dependFileNameFull += "/depend.make";
   *this->BuildFileStream
     << "# Include any dependencies generated for this target.\n"
- << this->LocalGenerator->IncludeDirective << " "
+ << this->LocalGenerator->IncludeDirective << " $(CMAKE_BINARY_DIR)/"
     << this->Convert(dependFileNameFull.c_str(),
                      cmLocalGenerator::HOME_OUTPUT,
                      cmLocalGenerator::MAKEFILE)
@@ -205,7 +205,7 @@
     // Include the progress variables for the target.
     *this->BuildFileStream
       << "# Include the progress variables for this target.\n"
- << this->LocalGenerator->IncludeDirective << " "
+ << this->LocalGenerator->IncludeDirective << " $(CMAKE_BINARY_DIR)/"
       << this->Convert(this->ProgressFileNameFull.c_str(),
                        cmLocalGenerator::HOME_OUTPUT,
                        cmLocalGenerator::MAKEFILE)
@@ -238,7 +238,7 @@
   // Include the flags for the target.
   *this->BuildFileStream
     << "# Include the compile flags for this target's objects.\n"
- << this->LocalGenerator->IncludeDirective << " "
+ << this->LocalGenerator->IncludeDirective << " $(CMAKE_BINARY_DIR)/"
     << this->Convert(this->FlagFileNameFull.c_str(),
                                      cmLocalGenerator::HOME_OUTPUT,
                                      cmLocalGenerator::MAKEFILE)
(0020357)
Daniel Richard G.   
2010-04-22 14:00   
The attached patch, against 2.8.1, fixes this bug.
(0020360)
Brad King   
2010-04-22 14:30   
I'm not confident that the patch will work on all platforms, plus the status quo has been working everywhere else for 10 years. Instead we could do

  if(this->Makefile->IsOn("CMAKE_MAKEFILE_INCLUDE_FULLPATH")) {...}

to add the $(CMAKE_BINARY_DIR). Then the Modules/Platform/Tru64.cmake file can set this variable to activate it. We can trust that it works for all Make tools that come on that OS.
(0020363)
Daniel Richard G.   
2010-04-22 16:04   
What's the concern? Are you worried about spaces in $(CMAKE_BINARY_DIR) ?

I'd be hesitant to add yet another obscure CMake variable, to hedge against the risk of a change as straightforward as this. Even the brain-dead Tru64 make could handle spaces---and if someone does runs into trouble, you can tell them to use GNU Make while a more general fix is in the works. No worse than this bug.
(0020968)
Brad King   
2010-06-10 11:57   
Using $(CMAKE_BINARY_DIR) does not work with spaces in the path on any other make I tested. I've pushed an alternative fix to a topic branch here:

http://gitorious.org/~bradking/cmake/bradkings-cmake/commit/871923b7 [^]

This enables the change only on Tru64. Please try it and let me know.
(0020979)
Daniel Richard G.   
2010-06-10 15:04   
Brad, I can't build CMake master (plus your change) on Tru64 because of bug 10541 ("virtual thunk to cmOStringStream::~cmOStringStream(): multiply defined"). Could you commit the fix for that one? My tree is already hacked up with libarchive fixes, and this one isn't particularly trivial.
(0020998)
Daniel Richard G.   
2010-06-12 19:23   
Okay, I got the source tree set up correctly, and tried the fix. Two problems:

1. A newly-built CMake, with an up-to-date Modules/ directory tree, never gets around to reading Modules/Platform/Tru64.cmake on this system (according to --trace).

2. If I set -DCMAKE_MAKE_INCLUDE_FROM_ROOT=1 on the command line, broken makefiles are generated---there is no slash between "$(CMAKE_BINARY_DIR)" and the rest of the path.
(0020999)
Brad King   
2010-06-14 08:24   
I pushed an updated version of the patch to deal with problem (2):

http://www.gitorious.org/~bradking/cmake/bradkings-cmake/commit/febd6e5b [^]

For problem (1), does the trace output through Modules/CMakeSystemSpecificInformation.cmake indicate how CMAKE_SYSTEM_NAME and CMAKE_SYSTEM_INFO_FILE are set?
(0021001)
Daniel Richard G.   
2010-06-14 12:58   
I think I see what's going on:

/tmp/cmake-build/share/cmake-2.8/Modules/CMakeSystemSpecificInformation.cmake(34): SET(CMAKE_SYSTEM_INFO_FILE Platform/${CMAKE_SYSTEM_NAME} )
/tmp/cmake-build/share/cmake-2.8/Modules/CMakeSystemSpecificInformation.cmake(36): INCLUDE(${CMAKE_SYSTEM_INFO_FILE} OPTIONAL RESULT_VARIABLE _INCLUDED_SYSTEM_INFO_FILE )
/tmp/cmake-build/share/cmake-2.8/Modules/Platform/OSF1.cmake(1): SET(CMAKE_DL_LIBS )
/tmp/cmake-build/share/cmake-2.8/Modules/Platform/OSF1.cmake(3): IF(CMAKE_SYSTEM MATCHES OSF1-1.[012] )
/tmp/cmake-build/share/cmake-2.8/Modules/Platform/OSF1.cmake(5): IF(CMAKE_SYSTEM MATCHES OSF1-1.* )

It's OSF1.cmake that gets read, not Tru64.cmake ...
(0021002)
Brad King   
2010-06-14 13:08   
Okay, I'll just make the change to OSF1.cmake instead of Tru64.cmake:

  http://www.gitorious.org/cmake/bradkings-cmake/commit/c592df83 [^]

Do other platforms with different make tools also claim to be OSF1?
(0021007)
Daniel Richard G.   
2010-06-14 17:13   
From what I can tell (on Wikipedia), the only Unix that claims to be OSF/1 is Tru64. Other Unices have OSF elements (e.g. Motif), but only one has the whole kaboodle.

With that latest change, building with Tru64's native make(1) program is successful!
(0021008)
Brad King   
2010-06-14 17:16   
Great, thanks for testing it. I've pushed the commit to next:

  http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c592df83 [^]