Hi,

I have two proposals for fixing issues with CMake generating suitable
command lines for static linking on Cray supercomputers when using Intel as
the base compiler. I hope I'm posting to the right list for discussion.
Happy to switch to cmake-developers or Mantis. :-)

Summary: The default Linux-Intel.cmake platform file adds -rdynamic to the
command line for compiling the test for whether the toolchain works, which
can fail if the toolchain isn't set up to deal with that

Background: Cray provides a wrapper compiler that handles things like MPI
and CUDA, and that wrapper compiler can be configured to use the Gnu, Intel
or Cray compilers as their base. The wrapper can also be configured to
require the use of static linking. This requirement can be side-stepped
with "export XTPE_LINK_TYPE=dynamic", but this doesn't mean that a suitable
library exists.

Symptoms:

On Archer (Cray XC30 in Edinburgh) with CMake 2.8.12 (or pre-3.1 CMake git
master) I get:

debug trycompile on
-- The C compiler identification is Intel 14.0.0.20140805
-- The CXX compiler identification is Intel 14.0.0.20140805
-- Check for working C compiler: /opt/cray/craype/2.2.0/bin/cc
-- Check for working C compiler: /opt/cray/craype/2.2.0/bin/cc -- broken
CMake Error at
/home2/y07/y07/cmake/2.8.12-i386/share/cmake-2.8/Modules/CMakeTestCCompiler.cmake:61
(message):
  The C compiler "/opt/cray/craype/2.2.0/bin/cc" is not able to compile a
  simple test program.

...

  /opt/cray/craype/2.2.0/bin/cc
  CMakeFiles/cmTryCompileExec3645868218.dir/testCCompiler.c.o -o
  cmTryCompileExec3645868218 -rdynamic

  ld: dynamic STT_GNU_IFUNC symbol `strcmp' with pointer equality in
  `/usr/lib64/gcc/x86_64-suse-linux/4.3/../../../../lib64/libc.a(strcmp.o)'
  can not be used when making an executable; recompile with -fPIE and relink
  with -pie

There may be a fair point here that the Cray and Intel machinery should not
be combining to pick up stuff from /usr/lib64/gcc, but I don't see a libc
in the Intel compiler installation, so maybe that is a feature after all.
Using Gnu as the base compiler also generates the -rdynamic, but it copes
with it.

The issue for CMake is the existence of -rdynamic on the command line, when
testing for basic functionality in a toolchain intended for static linking.
The -rdynamic is a feature (see http://www.cmake.org/Bug/view.php?id=9985),
set in the platform file, that supports some minor functionality, and when
it is a problem, it can mostly be worked around by users by

SET(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "")

However, fixing the above problem only works if such set() commands are
present in the platform file. Unfortunately, that's where the settings they
are working around are made...

Solutions could be:

1) We could introduce a specific platform files for
Linux-Intel-Cray-${lang}-static (in CMake or in an end-user application),
just to make sure -rdynamic isn't set by default. This permits the test for
compiler functionality to pass, and as a side effect, avoids users of the
platform file needing to set this in their CMakery.

2) The attached patch (based on CMake git master) allows CMake to recognize
a situation when there's no linking going on, and to avoid adding linking
flags. However, it is general to all platforms and calls to generate
linking command lines. I don't know whether this is a good idea, because it
could affect other platforms that depend on such behaviour for linking
system libraries, etc. How good is the CMake CI setup? :-) If so, maybe
some kind of policy setting might be needed.

Are there other options, or issues I haven't considered?

Regards,

Mark
From 8ded90a797a2f1ea45cfc02bbb106b3c0128c730 Mon Sep 17 00:00:00 2001
From: Mark Abraham <mark.j.abra...@gmail.com>
Date: Tue, 18 Nov 2014 13:36:58 +0000
Subject: [PATCH] Stop compiler tests appending unnecessary linking flags

The old CMake code appended flags for handling linking, which tend to
default to "-rdynamic" on Linux. These get appended even when nothing
is being (explicitly) linked. This can be problem for the tests CMake
runs for whether the compiler is functional. Those tests do not link
anything explicitly, but if the compilation toolchain cannot handle
the default linking style, then the test can fail because the useless
linking flags are present.

This is actually a problem when using Intel as the base compiler on
Cray supercomputers (e.g. XC30 and XC40), when the Cray wrapper
compiler is configured to require static linking. Then, the linker
might find shared system libraries, but not be able to actually link.
Using Gnu as the base compiler does not have this problem, but I am
not sure why.

Part of the problem is that Modules/Platform/Linux-Intel.cmake sets
CMAKE_SHARED_LIBRARY_LINK_*_FLAGS to "-rdynamic" by default, and
cmLocalGenerator::OutputLinkLibraries is hard-coded to use those. The
workaround of clearing those variables (see
http://www.cmake.org/Bug/view.php?id=9985) is only effective for these
tests when a custom platform file is used.

The need for a custom platform file is avoided if OutputLinkLibraries
doesn't add linking flags when there's no libraries to link. This
patch implements that feature.
---
 Source/cmLocalGenerator.cxx | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 3fb1e1e..eaef20e 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1883,8 +1883,10 @@ void cmLocalGenerator::OutputLinkLibraries(std::string& linkLibraries,
     }
   cmComputeLinkInformation& cli = *pcli;
 
-  // Collect library linking flags command line options.
-  std::string linkLibs;
+  // Collect command-line flags needed for linking libraries
+  std::string linkFlags;
+  // Collect the command-line contents needed for linking
+  std::string linkCommandLine;
 
   std::string linkLanguage = cli.GetLinkLanguage();
 
@@ -1899,8 +1901,8 @@ void cmLocalGenerator::OutputLinkLibraries(std::string& linkLibraries,
   linkFlagsVar += "_FLAGS";
   if( tgt.GetType() == cmTarget::EXECUTABLE )
     {
-    linkLibs = this->Makefile->GetSafeDefinition(linkFlagsVar);
-    linkLibs += " ";
+    linkFlags = this->Makefile->GetSafeDefinition(linkFlagsVar);
+    linkFlags += " ";
     }
 
   // Append the framework search path flags.
@@ -1946,17 +1948,20 @@ void cmLocalGenerator::OutputLinkLibraries(std::string& linkLibraries,
       }
     if(li->IsPath)
       {
-      linkLibs += this->ConvertToLinkReference(li->Value, shellFormat);
+      linkCommandLine += this->ConvertToLinkReference(li->Value, shellFormat);
       }
     else
       {
-      linkLibs += li->Value;
+      linkCommandLine += li->Value;
       }
-    linkLibs += " ";
+    linkCommandLine += " ";
     }
 
   // Write the library flags to the build rule.
-  fout << linkLibs;
+  if (0 < linkCommandLine.size())
+    {
+    fout << linkFlags << " " << linkCommandLine;
+    }
 
   // Get the RPATH entries.
   std::vector<std::string> runtimeDirs;
-- 
1.8.5.2

-- 

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: 
http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more 
information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at 
http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake

Reply via email to