From fd8ae3d34c444cef04c77a38b55e0baee94f6753 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 2 Nov 2004 08:32:03 -0500 Subject: [PATCH] BUG: Fixed subdirectory implementation for Borland Make. --- Source/cmLocalUnixMakefileGenerator2.cxx | 143 ++++++++++++++++------- Source/cmLocalUnixMakefileGenerator2.h | 12 +- 2 files changed, 111 insertions(+), 44 deletions(-) diff --git a/Source/cmLocalUnixMakefileGenerator2.cxx b/Source/cmLocalUnixMakefileGenerator2.cxx index de8ae34b4..ac73b966f 100644 --- a/Source/cmLocalUnixMakefileGenerator2.cxx +++ b/Source/cmLocalUnixMakefileGenerator2.cxx @@ -33,11 +33,23 @@ cmLocalUnixMakefileGenerator2::~cmLocalUnixMakefileGenerator2() { } +//---------------------------------------------------------------------------- +void cmLocalUnixMakefileGenerator2::SetEmptyCommand(const char* cmd) +{ + m_EmptyCommands.clear(); + if(cmd) + { + m_EmptyCommands.push_back(cmd); + } +} + //---------------------------------------------------------------------------- void cmLocalUnixMakefileGenerator2::Generate(bool fromTheTop) { // TODO: Account for control-c during Makefile generation. + // TODO: Think about unifying generation of "@" for silent commands. + // Generate old style for now. this->cmLocalUnixMakefileGenerator::Generate(fromTheTop); @@ -376,7 +388,7 @@ cmLocalUnixMakefileGenerator2 cmOStringStream depCmd; // TODO: Account for source file properties and directory-level // definitions when scanning for dependencies. - depCmd << "$(CMAKE_COMMAND) -E cmake_depends " << lang << " " + depCmd << "@$(CMAKE_COMMAND) -E cmake_depends " << lang << " " << this->ConvertToRelativeOutputPath(obj.c_str()) << " " << this->ConvertToRelativeOutputPath(source.GetFullPath().c_str()); std::vector includeDirs; @@ -710,16 +722,16 @@ cmLocalUnixMakefileGenerator2 depends.push_back("cmake_check_build_system"); // Recursively build pre-order directories. - commands.push_back(this->GetRecursiveMakeCall("all.subdirs.pre")); + commands.push_back(this->GetRecursiveMakeCall("all.subdirs.pre", true)); // Recursively build dependencies. - commands.push_back(this->GetRecursiveMakeCall("all.depends")); + commands.push_back(this->GetRecursiveMakeCall("all.depends", true)); // Recursively build targets. - commands.push_back(this->GetRecursiveMakeCall("all.build")); + commands.push_back(this->GetRecursiveMakeCall("all.build", true)); // Recursively build post-order directories. - commands.push_back(this->GetRecursiveMakeCall("all.subdirs.post")); + commands.push_back(this->GetRecursiveMakeCall("all.subdirs.post", true)); // Write the rule. std::string preEcho = "Entering directory "; @@ -762,7 +774,7 @@ cmLocalUnixMakefileGenerator2 std::vector no_depends; std::vector commands; commands.push_back( - "$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)"); + "@$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)"); this->WriteMakeRule(makefileStream, "Special rule to re-run CMake using make.", "Running CMake to regenerate build system...", @@ -791,7 +803,7 @@ cmLocalUnixMakefileGenerator2 std::vector no_depends; std::vector commands; commands.push_back( - "$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) -i"); + "@$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) -i"); this->WriteMakeRule(makefileStream, "Special rule to re-run CMake cache editor using make.", "Running interactive CMake command-line interface...", @@ -872,6 +884,14 @@ cmLocalUnixMakefileGenerator2 } } } + + // If there are no dependencies, use empty commands. + if(depends.empty()) + { + commands = m_EmptyCommands; + } + + // Write the rule. this->WriteMakeRule(makefileStream, "Main dependencies target for this directory.", 0, @@ -898,6 +918,14 @@ cmLocalUnixMakefileGenerator2 } } } + + // If there are no dependencies, use empty commands. + if(depends.empty()) + { + commands = m_EmptyCommands; + } + + // Write the rule. this->WriteMakeRule(makefileStream, "Main build target for this directory.", 0, @@ -945,29 +973,8 @@ cmLocalUnixMakefileGenerator2 // Write the subdir driver rules. Hook them to the last // subdirectory of their corresponding order. - std::vector pre_depends; - std::vector post_depends; - std::vector no_commands; - if(lastPre.size()) - { - pre_depends.push_back(lastPre); - } - if(lastPost.size()) - { - post_depends.push_back(lastPost); - } - std::string preComment = "Pre-order subdirectory driver target for "; - preComment += pass; - std::string postComment = "Post-order subdirectory driver target for "; - postComment += pass; - std::string preTarget = pass; - preTarget += ".subdirs.pre"; - std::string postTarget = pass; - postTarget += ".subdirs.post"; - this->WriteMakeRule(makefileStream, preComment.c_str(), 0, - preTarget.c_str(), pre_depends, no_commands); - this->WriteMakeRule(makefileStream, postComment.c_str(), 0, - postTarget.c_str(), post_depends, no_commands); + this->WriteSubdirDriverRule(makefileStream, pass, "pre", lastPre); + this->WriteSubdirDriverRule(makefileStream, pass, "post", lastPost); } //---------------------------------------------------------------------------- @@ -992,15 +999,20 @@ cmLocalUnixMakefileGenerator2 commands.push_back(cmd); // Build the target for this pass. - commands.push_back(this->GetRecursiveMakeCall(pass)); + commands.push_back(this->GetRecursiveMakeCall(pass, true)); - // Change back to the starting directory. + // Change back to the starting directory. Any trailing slash must + // be removed to avoid problems with Borland Make. std::string destFull = m_Makefile->GetStartOutputDirectory(); destFull += "/"; destFull += subdir; std::string back = cmSystemTools::RelativePath(destFull.c_str(), m_Makefile->GetStartOutputDirectory()); + if(back.size() && back[back.size()-1] == '/') + { + back = back.substr(0, back.size()-1); + } cmd = "@cd "; cmd += this->ConvertToOutputForExisting(back.c_str()); commands.push_back(cmd); @@ -1015,7 +1027,7 @@ cmLocalUnixMakefileGenerator2 // Build the target for this pass. cmd += " && "; - cmd += this->GetRecursiveMakeCall(pass); + cmd += this->GetRecursiveMakeCall(pass, false); // Add the command as a single line. commands.push_back(cmd); @@ -1034,6 +1046,45 @@ cmLocalUnixMakefileGenerator2 last = tgt; } +//---------------------------------------------------------------------------- +void +cmLocalUnixMakefileGenerator2 +::WriteSubdirDriverRule(std::ostream& makefileStream, const char* pass, + const char* order, const std::string& last) +{ + // This rule corresponds to a particular pass (all, clean, etc). It + // dispatches the build into subdirectories in pre- or post-order. + std::vector depends; + std::vector commands; + if(last.size()) + { + // Use the dependency to drive subdirectory processing. + depends.push_back(last); + } + else + { + // There are no subdirectories. Use the empty commands to avoid + // make errors on some platforms. + commands = m_EmptyCommands; + } + + // Build comment to describe purpose. + std::string comment = "Driver target for "; + comment += order; + comment += "-order subdirectories during "; + comment += pass; + comment += "."; + + // Build the make target name. + std::string tgt = pass; + tgt += ".subdirs."; + tgt += order; + + // Write the rule. + this->WriteMakeRule(makefileStream, comment.c_str(), 0, + tgt.c_str(), depends, commands); +} + //---------------------------------------------------------------------------- void cmLocalUnixMakefileGenerator2 @@ -1397,7 +1448,7 @@ cmLocalUnixMakefileGenerator2 } // Add a command to remove any existing files for this library. - std::string remove = "$(CMAKE_COMMAND) -E remove -f "; + std::string remove = "@$(CMAKE_COMMAND) -E remove -f "; remove += targetFullPathReal; if(targetFullPathSO != targetFullPathReal) { @@ -1421,7 +1472,7 @@ cmLocalUnixMakefileGenerator2 // Add a rule to create necessary symlinks for the library. if(targetFullPath != targetFullPathReal) { - std::string symlink = "$(CMAKE_COMMAND) -E cmake_symlink_library "; + std::string symlink = "@$(CMAKE_COMMAND) -E cmake_symlink_library "; symlink += targetFullPathReal; symlink += " "; symlink += targetFullPathSO; @@ -1756,10 +1807,15 @@ cmLocalUnixMakefileGenerator2 //---------------------------------------------------------------------------- std::string cmLocalUnixMakefileGenerator2 -::GetRecursiveMakeCall(const char* tgt) +::GetRecursiveMakeCall(const char* tgt, bool silent) { // Call make on the given file. - std::string cmd = "$(MAKE) -f Makefile2 "; + std::string cmd; + if(silent) + { + cmd += "@"; + } + cmd += "$(MAKE) -f Makefile2 "; // Pass down verbosity level. if(m_MakeSilentFlag.size()) @@ -1828,13 +1884,14 @@ cmLocalUnixMakefileGenerator2 commands.push_back(cmd); // Check the build system in destination directory. - commands.push_back(this->GetRecursiveMakeCall("cmake_check_build_system")); + commands.push_back(this->GetRecursiveMakeCall("cmake_check_build_system", + true)); // Build the targets's dependencies. - commands.push_back(this->GetRecursiveMakeCall(dep.c_str())); + commands.push_back(this->GetRecursiveMakeCall(dep.c_str(), true)); // Build the target. - commands.push_back(this->GetRecursiveMakeCall(tgt.c_str())); + commands.push_back(this->GetRecursiveMakeCall(tgt.c_str(), true)); // Jump back to the starting directory. cmd = "@cd "; @@ -1850,15 +1907,15 @@ cmLocalUnixMakefileGenerator2 // Check the build system in destination directory. cmd += " && "; - cmd += this->GetRecursiveMakeCall("cmake_check_build_system"); + cmd += this->GetRecursiveMakeCall("cmake_check_build_system", false); // Build the targets's dependencies. cmd += " && "; - cmd += this->GetRecursiveMakeCall(dep.c_str()); + cmd += this->GetRecursiveMakeCall(dep.c_str(), false); // Build the target. cmd += " && "; - cmd += this->GetRecursiveMakeCall(tgt.c_str()); + cmd += this->GetRecursiveMakeCall(tgt.c_str(), false); // Add the command as a single line. commands.push_back(cmd); diff --git a/Source/cmLocalUnixMakefileGenerator2.h b/Source/cmLocalUnixMakefileGenerator2.h index 712d6ea07..ae0c1561a 100644 --- a/Source/cmLocalUnixMakefileGenerator2.h +++ b/Source/cmLocalUnixMakefileGenerator2.h @@ -38,6 +38,11 @@ public: virtual ~cmLocalUnixMakefileGenerator2(); + /** Set the command used when there are no dependencies or rules for + a target. This is used to avoid errors on some make + implementations. */ + void SetEmptyCommand(const char* cmd); + /** * Generate the makefile for this directory. fromTheTop indicates if this * is being invoked as part of a global Generate or specific to this @@ -78,6 +83,8 @@ protected: void WriteSubdirRules(std::ostream& makefileStream, const char* pass); void WriteSubdirRule(std::ostream& makefileStream, const char* pass, const char* subdir, std::string& last); + void WriteSubdirDriverRule(std::ostream& makefileStream, const char* pass, + const char* order, const std::string& last); void WriteRequiresRule(std::ostream& ruleFileStream, const cmTarget& target, const char* targetFullPath); void WriteExecutableRule(std::ostream& ruleFileStream, @@ -115,7 +122,7 @@ protected: void AddConfigVariableFlags(std::string& flags, const char* var); void AppendFlags(std::string& flags, const char* newFlags); void AppendLibDepend(std::vector& depends, const char* name); - std::string GetRecursiveMakeCall(const char* tgt); + std::string GetRecursiveMakeCall(const char* tgt, bool silent); void WriteJumpAndBuildRules(std::ostream& makefileStream); static bool ScanDependenciesC(const char* objFile, const char* srcFile, @@ -136,6 +143,9 @@ private: // List the files for which to check dependency integrity. std::set m_CheckDependFiles; + + // Command used when a rule has no dependencies or commands. + std::vector m_EmptyCommands; }; #endif