[Cmake-commits] CMake branch, next, updated. v3.6.0-rc2-372-g8a827d1

Brad King brad.king at kitware.com
Fri Jun 17 10:58:38 EDT 2016


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".

The branch, next has been updated
       via  8a827d1b19a8f88238eac6077ad6d5aee4ef03f0 (commit)
       via  96242f8022fa4bc718ef36cda43f5dfe6236c066 (commit)
      from  541633c9ddc26fc44454b3b7eea74ec19115b81b (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8a827d1b19a8f88238eac6077ad6d5aee4ef03f0
commit 8a827d1b19a8f88238eac6077ad6d5aee4ef03f0
Merge: 541633c 96242f8
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Fri Jun 17 10:58:37 2016 -0400
Commit:     CMake Topic Stage <kwrobot at kitware.com>
CommitDate: Fri Jun 17 10:58:37 2016 -0400

    Merge topic 'link_what_you_use' into next
    
    96242f80 Add options to run `ldd -u -r` as a "link-what-you-use" tool


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=96242f8022fa4bc718ef36cda43f5dfe6236c066
commit 96242f8022fa4bc718ef36cda43f5dfe6236c066
Author:     Bill Hoffman <bill.hoffman at kitware.com>
AuthorDate: Thu Jun 2 18:08:30 2016 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Fri Jun 17 10:56:40 2016 -0400

    Add options to run `ldd -u -r` as a "link-what-you-use" tool
    
    Create a LINK_WHAT_YOU_USE target property and corresponding
    CMAKE_LINK_WHAT_YOU_USE variable to enable this behavior.
    Extend link commands by running `ldd -u -r` to detect shared
    libraries that are linked but not needed.

diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst
index 3403dcd..6a7560a 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -217,6 +217,7 @@ Properties on Targets
    /prop_tgt/LINK_LIBRARIES
    /prop_tgt/LINK_SEARCH_END_STATIC
    /prop_tgt/LINK_SEARCH_START_STATIC
+   /prop_tgt/LINK_WHAT_YOU_USE
    /prop_tgt/LOCATION_CONFIG
    /prop_tgt/LOCATION
    /prop_tgt/MACOSX_BUNDLE_INFO_PLIST
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index 85b8eae..36d00dc 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -275,6 +275,7 @@ Variables that Control the Build
    /variable/CMAKE_LINK_INTERFACE_LIBRARIES
    /variable/CMAKE_LINK_LIBRARY_FILE_FLAG
    /variable/CMAKE_LINK_LIBRARY_FLAG
+   /variable/CMAKE_LINK_WHAT_YOU_USE
    /variable/CMAKE_MACOSX_BUNDLE
    /variable/CMAKE_MACOSX_RPATH
    /variable/CMAKE_MAP_IMPORTED_CONFIG_CONFIG
diff --git a/Help/prop_tgt/LINK_WHAT_YOU_USE.rst b/Help/prop_tgt/LINK_WHAT_YOU_USE.rst
new file mode 100644
index 0000000..32d6edb
--- /dev/null
+++ b/Help/prop_tgt/LINK_WHAT_YOU_USE.rst
@@ -0,0 +1,15 @@
+LINK_WHAT_YOU_USE
+---------------------------
+
+This is a boolean option that when set to ``TRUE`` will automatically run
+``ldd -r -u`` on the target after it is linked. In addition, the linker flag
+``-Wl,--no-as-needed`` will be passed to the target with the link command so
+that all libraries specified on the command line will be linked into the
+target. This will result in the link producing a list of libraries that
+provide no symbols used by this target but are being linked to it.
+This is only applicable to executable and shared library targets and
+will only work when ld and ldd accept the flags used.
+
+This property is initialized by the value of
+the :variable:`CMAKE_LINK_WHAT_YOU_USE` variable if it is set
+when a target is created.
diff --git a/Help/variable/CMAKE_LINK_WHAT_YOU_USE.rst b/Help/variable/CMAKE_LINK_WHAT_YOU_USE.rst
new file mode 100644
index 0000000..90c4d3f
--- /dev/null
+++ b/Help/variable/CMAKE_LINK_WHAT_YOU_USE.rst
@@ -0,0 +1,6 @@
+CMAKE_LINK_WHAT_YOU_USE
+---------------------------------
+
+Default value for :prop_tgt:`LINK_WHAT_YOU_USE` target property.
+This variable is used to initialize the property on each target as it is
+created.
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index 9d42257..ba4c6e6 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -187,6 +187,9 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
     this->LocalGenerator->AppendFlags(
       linkFlags, this->Makefile->GetDefinition(export_flag_var));
   }
+  if (this->GeneratorTarget->GetProperty("LINK_WHAT_YOU_USE")) {
+    this->LocalGenerator->AppendFlags(linkFlags, " -Wl,--no-as-needed");
+  }
 
   // Add language feature flags.
   this->AddFeatureFlags(flags, linkLanguage);
@@ -356,6 +359,15 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
     vars.LinkFlags = linkFlags.c_str();
     vars.Manifests = manifests.c_str();
 
+    if (this->GeneratorTarget->GetProperty("LINK_WHAT_YOU_USE")) {
+      std::string cmakeCommand =
+        this->Convert(cmSystemTools::GetCMakeCommand(), cmLocalGenerator::NONE,
+                      cmLocalGenerator::SHELL);
+      cmakeCommand += " -E __run_iwyu --lwyu=";
+      cmakeCommand += targetOutPathReal;
+      real_link_commands.push_back(cmakeCommand);
+    }
+
     // Expand placeholders in the commands.
     this->LocalGenerator->TargetImplib = targetOutPathImport;
     for (std::vector<std::string>::iterator i = real_link_commands.begin();
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index 128291d..6666c36 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -163,6 +163,9 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink)
     extraFlags, "CMAKE_SHARED_LINKER_FLAGS", this->ConfigName);
   this->AddModuleDefinitionFlag(extraFlags);
 
+  if (this->GeneratorTarget->GetProperty("LINK_WHAT_YOU_USE")) {
+    this->LocalGenerator->AppendFlags(extraFlags, " -Wl,--no-as-needed");
+  }
   this->WriteLibraryRules(linkRuleVar, extraFlags, relink);
 }
 
@@ -682,6 +685,15 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
       // Get the set of commands.
       std::string linkRule = this->GetLinkRule(linkRuleVar);
       cmSystemTools::ExpandListArgument(linkRule, real_link_commands);
+      if (this->GeneratorTarget->GetProperty("LINK_WHAT_YOU_USE") &&
+          (this->GeneratorTarget->GetType() == cmState::SHARED_LIBRARY)) {
+        std::string cmakeCommand =
+          this->Convert(cmSystemTools::GetCMakeCommand(),
+                        cmLocalGenerator::NONE, cmLocalGenerator::SHELL);
+        cmakeCommand += " -E __run_iwyu --lwyu=";
+        cmakeCommand += targetOutPathReal;
+        real_link_commands.push_back(cmakeCommand);
+      }
 
       // Expand placeholders.
       for (std::vector<std::string>::iterator i = real_link_commands.begin();
@@ -728,6 +740,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
     commands.insert(commands.end(), commands1.begin(), commands1.end());
     commands1.clear();
   }
+
   // Add the post-build rules when building but not when relinking.
   if (!relink) {
     this->LocalGenerator->AppendCustomCommands(
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 3e91545..7c18414 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -295,6 +295,22 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd()
     const char* linkCmd = mf->GetDefinition(linkCmdVar);
     if (linkCmd) {
       cmSystemTools::ExpandListArgument(linkCmd, linkCmds);
+      if (this->GetGeneratorTarget()->GetProperty("LINK_WHAT_YOU_USE")) {
+        std::string cmakeCommand =
+          this->GetLocalGenerator()->ConvertToOutputFormat(
+            cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL);
+        cmakeCommand += " -E __run_iwyu --lwyu=";
+        cmGeneratorTarget& gt = *this->GetGeneratorTarget();
+        const std::string cfgName = this->GetConfigName();
+        std::string targetOutput = ConvertToNinjaPath(gt.GetFullPath(cfgName));
+        std::string targetOutputReal =
+          this->ConvertToNinjaPath(gt.GetFullPath(cfgName,
+                                                  /*implib=*/false,
+                                                  /*realpath=*/true));
+        cmakeCommand += targetOutputReal;
+        cmakeCommand += " || true";
+        linkCmds.push_back(cmakeCommand);
+      }
       return linkCmds;
     }
   }
@@ -467,6 +483,10 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
   vars["MANIFESTS"] = this->GetManifests();
 
   vars["LINK_PATH"] = frameworkPath + linkPath;
+  std::string lwyuFlags;
+  if (genTarget.GetProperty("LINK_WHAT_YOU_USE")) {
+    lwyuFlags = " -Wl,--no-as-needed";
+  }
 
   // Compute architecture specific link flags.  Yes, these go into a different
   // variable for executables, probably due to a mistake made when duplicating
@@ -474,16 +494,17 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
   if (targetType == cmState::EXECUTABLE) {
     std::string t = vars["FLAGS"];
     localGen.AddArchitectureFlags(t, &genTarget, TargetLinkLanguage, cfgName);
+    t += lwyuFlags;
     vars["FLAGS"] = t;
   } else {
     std::string t = vars["ARCH_FLAGS"];
     localGen.AddArchitectureFlags(t, &genTarget, TargetLinkLanguage, cfgName);
     vars["ARCH_FLAGS"] = t;
     t = "";
+    t += lwyuFlags;
     localGen.AddLanguageFlags(t, TargetLinkLanguage, cfgName);
     vars["LANGUAGE_COMPILE_FLAGS"] = t;
   }
-
   if (this->GetGeneratorTarget()->HasSOName(cfgName)) {
     vars["SONAME_FLAG"] = mf->GetSONameFlag(this->TargetLinkLanguage);
     vars["SONAME"] = this->TargetNameSO;
@@ -607,7 +628,6 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
     vars["POST_BUILD"] = ":";
     symlinkVars["POST_BUILD"] = postBuildCmdLine;
   }
-
   cmGlobalNinjaGenerator& globalGen = *this->GetGlobalGenerator();
 
   int commandLineLengthLimit = -1;
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index f435a1d..8327af2 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -139,6 +139,7 @@ void cmTarget::SetMakefile(cmMakefile* mf)
     this->SetPropertyDefault("C_CLANG_TIDY", 0);
     this->SetPropertyDefault("C_COMPILER_LAUNCHER", 0);
     this->SetPropertyDefault("C_INCLUDE_WHAT_YOU_USE", 0);
+    this->SetPropertyDefault("LINK_WHAT_YOU_USE", 0);
     this->SetPropertyDefault("C_STANDARD", 0);
     this->SetPropertyDefault("C_STANDARD_REQUIRED", 0);
     this->SetPropertyDefault("C_EXTENSIONS", 0);
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 535dead..161256e 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -271,6 +271,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
       std::string iwyu;
       std::string tidy;
       std::string sourceFile;
+      std::string lwyu;
       for (std::string::size_type cc = 2; cc < args.size(); cc++) {
         std::string const& arg = args[cc];
         if (arg == "--") {
@@ -281,6 +282,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
           tidy = arg.substr(7);
         } else if (doing_options && cmHasLiteralPrefix(arg, "--source=")) {
           sourceFile = arg.substr(9);
+        } else if (doing_options && cmHasLiteralPrefix(arg, "--lwyu=")) {
+          lwyu = arg.substr(7);
         } else if (doing_options) {
           std::cerr << "__run_iwyu given unknown argument: " << arg << "\n";
           return 1;
@@ -288,7 +291,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
           orig_cmd.push_back(arg);
         }
       }
-      if (tidy.empty() && iwyu.empty()) {
+      if (tidy.empty() && iwyu.empty() && lwyu.empty()) {
         std::cerr << "__run_iwyu missing --tidy= or --iwyu=\n";
         return 1;
       }
@@ -296,7 +299,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
         std::cerr << "__run_iwyu --tidy= requires --source=\n";
         return 1;
       }
-      if (orig_cmd.empty()) {
+      if (orig_cmd.empty() && lwyu.empty()) {
         std::cerr << "__run_iwyu missing compile command after --\n";
         return 1;
       }
@@ -345,13 +348,37 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
           std::cerr << "Error running '" << tidy_cmd[0] << "'\n";
           return 1;
         }
-
         // Output the stdout from clang-tidy to stderr
         std::cerr << stdOut;
       }
+      if (!lwyu.empty()) {
+        // Construct the ldd -r -u (link what you use lwyu) command line
+        // ldd -u -r lwuy target
+        std::vector<std::string> lwyu_cmd;
+        lwyu_cmd.push_back("ldd");
+        lwyu_cmd.push_back("-u");
+        lwyu_cmd.push_back("-r");
+        lwyu_cmd.push_back(lwyu);
+
+        // Run the ldd -u -r command line.
+        // Capture its stdout and hide its stderr.
+        std::string stdOut;
+        if (!cmSystemTools::RunSingleCommand(lwyu_cmd, &stdOut, 0, &ret, 0,
+                                             cmSystemTools::OUTPUT_NONE)) {
+          std::cerr << "Error running '" << lwyu_cmd[0] << "'\n";
+          return 1;
+        }
 
+        // Output the stdout from ldd -r -u to stderr
+        // Warn if lwyu reported anything.
+        if (stdOut.find("Unused direct dependencies:") != stdOut.npos) {
+          std::cerr << "Warning: " << stdOut;
+        }
+      }
+      ret = 0;
       // Now run the real compiler command and return its result value.
-      if (!cmSystemTools::RunSingleCommand(
+      if (lwyu.empty() &&
+          !cmSystemTools::RunSingleCommand(
             orig_cmd, 0, 0, &ret, 0, cmSystemTools::OUTPUT_PASSTHROUGH)) {
         std::cerr << "Error running '" << orig_cmd[0] << "'\n";
         return 1;
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index d16e5e7..b6d1c38 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -307,6 +307,14 @@ if(CMAKE_OSX_ARCHITECTURES AND XCODE AND NOT "${XCODE_VERSION}" MATCHES "^[^12]"
 endif()
 
 if("${CMAKE_GENERATOR}" MATCHES "Make|Ninja")
+  if(UNIX AND NOT CYGWIN)
+    execute_process(COMMAND ldd --help
+      OUTPUT_VARIABLE LDD_HELP)
+    if("${LDD_HELP}" MATCHES
+        "(-r, --function-relocs.*process data and function relocations.*-u, --unused.*print unused direct dependencies)")
+      add_RunCMake_test(LinkWhatYouUse)
+    endif()
+  endif()
   add_executable(pseudo_tidy pseudo_tidy.c)
   add_executable(pseudo_iwyu pseudo_iwyu.c)
   add_RunCMake_test(ClangTidy -DPSEUDO_TIDY=$<TARGET_FILE:pseudo_tidy>)
diff --git a/Tests/RunCMake/LinkWhatYouUse/C-Build-stdout.txt b/Tests/RunCMake/LinkWhatYouUse/C-Build-stdout.txt
new file mode 100644
index 0000000..95eafad
--- /dev/null
+++ b/Tests/RunCMake/LinkWhatYouUse/C-Build-stdout.txt
@@ -0,0 +1,2 @@
+.*Warning: Unused direct dependencies.*
+.*libm.*
diff --git a/Tests/RunCMake/LinkWhatYouUse/C-launch-Build-stdout.txt b/Tests/RunCMake/LinkWhatYouUse/C-launch-Build-stdout.txt
new file mode 100644
index 0000000..95eafad
--- /dev/null
+++ b/Tests/RunCMake/LinkWhatYouUse/C-launch-Build-stdout.txt
@@ -0,0 +1,2 @@
+.*Warning: Unused direct dependencies.*
+.*libm.*
diff --git a/Tests/RunCMake/LinkWhatYouUse/C-launch.cmake b/Tests/RunCMake/LinkWhatYouUse/C-launch.cmake
new file mode 100644
index 0000000..e66ca20
--- /dev/null
+++ b/Tests/RunCMake/LinkWhatYouUse/C-launch.cmake
@@ -0,0 +1,3 @@
+set(CTEST_USE_LAUNCHERS 1)
+include(CTestUseLaunchers)
+include(C.cmake)
diff --git a/Tests/RunCMake/LinkWhatYouUse/C.cmake b/Tests/RunCMake/LinkWhatYouUse/C.cmake
new file mode 100644
index 0000000..4c3f428
--- /dev/null
+++ b/Tests/RunCMake/LinkWhatYouUse/C.cmake
@@ -0,0 +1,4 @@
+enable_language(C)
+set(CMAKE_LINK_WHAT_YOU_USE TRUE)
+add_executable(main main.c)
+target_link_libraries(main m)
diff --git a/Tests/RunCMake/LinkWhatYouUse/CMakeLists.txt b/Tests/RunCMake/LinkWhatYouUse/CMakeLists.txt
new file mode 100644
index 0000000..18dfd26
--- /dev/null
+++ b/Tests/RunCMake/LinkWhatYouUse/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.2)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/LinkWhatYouUse/CXX-Build-stdout.txt b/Tests/RunCMake/LinkWhatYouUse/CXX-Build-stdout.txt
new file mode 100644
index 0000000..95eafad
--- /dev/null
+++ b/Tests/RunCMake/LinkWhatYouUse/CXX-Build-stdout.txt
@@ -0,0 +1,2 @@
+.*Warning: Unused direct dependencies.*
+.*libm.*
diff --git a/Tests/RunCMake/LinkWhatYouUse/CXX-launch-Build-stdout.txt b/Tests/RunCMake/LinkWhatYouUse/CXX-launch-Build-stdout.txt
new file mode 100644
index 0000000..95eafad
--- /dev/null
+++ b/Tests/RunCMake/LinkWhatYouUse/CXX-launch-Build-stdout.txt
@@ -0,0 +1,2 @@
+.*Warning: Unused direct dependencies.*
+.*libm.*
diff --git a/Tests/RunCMake/LinkWhatYouUse/CXX-launch.cmake b/Tests/RunCMake/LinkWhatYouUse/CXX-launch.cmake
new file mode 100644
index 0000000..3002c9d
--- /dev/null
+++ b/Tests/RunCMake/LinkWhatYouUse/CXX-launch.cmake
@@ -0,0 +1,3 @@
+set(CTEST_USE_LAUNCHERS 1)
+include(CTestUseLaunchers)
+include(CXX.cmake)
diff --git a/Tests/RunCMake/LinkWhatYouUse/CXX.cmake b/Tests/RunCMake/LinkWhatYouUse/CXX.cmake
new file mode 100644
index 0000000..9555832
--- /dev/null
+++ b/Tests/RunCMake/LinkWhatYouUse/CXX.cmake
@@ -0,0 +1,4 @@
+enable_language(CXX)
+set(CMAKE_LINK_WHAT_YOU_USE TRUE)
+add_executable(main main.cxx)
+target_link_libraries(main m)
diff --git a/Tests/RunCMake/LinkWhatYouUse/RunCMakeTest.cmake b/Tests/RunCMake/LinkWhatYouUse/RunCMakeTest.cmake
new file mode 100644
index 0000000..897f568
--- /dev/null
+++ b/Tests/RunCMake/LinkWhatYouUse/RunCMakeTest.cmake
@@ -0,0 +1,21 @@
+include(RunCMake)
+
+
+function(run_lwyu lang)
+  # Use a single build tree for tests without cleaning.
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${lang}-build)
+  set(RunCMake_TEST_NO_CLEAN 1)
+  file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+  file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+  run_cmake(${lang})
+
+  set(RunCMake_TEST_OUTPUT_MERGE 1)
+  run_cmake_command(${lang}-Build ${CMAKE_COMMAND} --build .)
+endfunction()
+
+run_lwyu(CXX)
+run_lwyu(C)
+if (NOT RunCMake_GENERATOR STREQUAL "Watcom WMake")
+  run_lwyu(C-launch)
+  run_lwyu(CXX-launch)
+endif()
diff --git a/Tests/RunCMake/LinkWhatYouUse/main.c b/Tests/RunCMake/LinkWhatYouUse/main.c
new file mode 100644
index 0000000..8488f4e
--- /dev/null
+++ b/Tests/RunCMake/LinkWhatYouUse/main.c
@@ -0,0 +1,4 @@
+int main(void)
+{
+  return 0;
+}
diff --git a/Tests/RunCMake/LinkWhatYouUse/main.cxx b/Tests/RunCMake/LinkWhatYouUse/main.cxx
new file mode 100644
index 0000000..f8b643a
--- /dev/null
+++ b/Tests/RunCMake/LinkWhatYouUse/main.cxx
@@ -0,0 +1,4 @@
+int main()
+{
+  return 0;
+}

-----------------------------------------------------------------------

Summary of changes:


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list