r342499 - [Modules] Add platform and environment features to requires clause

Bruno Cardoso Lopes via cfe-commits cfe-commits at lists.llvm.org
Tue Sep 18 10:11:13 PDT 2018


Author: bruno
Date: Tue Sep 18 10:11:13 2018
New Revision: 342499

URL: http://llvm.org/viewvc/llvm-project?rev=342499&view=rev
Log:
[Modules] Add platform and environment features to requires clause

Allows module map writers to add build requirements based on
platform/os. This helps when target features and language dialects
aren't enough to conditionalize building a module, among other things,
it allow module maps for different platforms to live in the same file.

rdar://problem/43909745

Differential Revision: https://reviews.llvm.org/D51910

Added:
    cfe/trunk/test/Modules/target-platform-features.m
Modified:
    cfe/trunk/docs/Modules.rst
    cfe/trunk/lib/Basic/Module.cpp

Modified: cfe/trunk/docs/Modules.rst
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/Modules.rst?rev=342499&r1=342498&r2=342499&view=diff
==============================================================================
--- cfe/trunk/docs/Modules.rst (original)
+++ cfe/trunk/docs/Modules.rst Tue Sep 18 10:11:13 2018
@@ -411,7 +411,7 @@ A *requires-declaration* specifies the r
   *feature*:
     ``!``:sub:`opt` *identifier*
 
-The requirements clause allows specific modules or submodules to specify that they are only accessible with certain language dialects or on certain platforms. The feature list is a set of identifiers, defined below. If any of the features is not available in a given translation unit, that translation unit shall not import the module. When building a module for use by a compilation, submodules requiring unavailable features are ignored. The optional ``!`` indicates that a feature is incompatible with the module.
+The requirements clause allows specific modules or submodules to specify that they are only accessible with certain language dialects, platforms, environments and target specific features. The feature list is a set of identifiers, defined below. If any of the features is not available in a given translation unit, that translation unit shall not import the module. When building a module for use by a compilation, submodules requiring unavailable features are ignored. The optional ``!`` indicates that a feature is incompatible with the module.
 
 The following features are defined:
 
@@ -466,6 +466,11 @@ tls
 *target feature*
   A specific target feature (e.g., ``sse4``, ``avx``, ``neon``) is available.
 
+*platform/os*
+  A os/platform variant (e.g. ``freebsd``, ``win32``, ``windows``, ``linux``, ``ios``, ``macos``, ``iossimulator``) is available.
+
+*environment*
+  A environment variant (e.g. ``gnu``, ``gnueabi``, ``android``, ``msvc``) is available.
 
 **Example:** The ``std`` module can be extended to also include C++ and C++11 headers using a *requires-declaration*:
 

Modified: cfe/trunk/lib/Basic/Module.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Module.cpp?rev=342499&r1=342498&r2=342499&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Module.cpp (original)
+++ cfe/trunk/lib/Basic/Module.cpp Tue Sep 18 10:11:13 2018
@@ -71,6 +71,37 @@ Module::~Module() {
   }
 }
 
+static bool isPlatformEnvironment(const TargetInfo &Target, StringRef Feature) {
+  StringRef Platform = Target.getPlatformName();
+  StringRef Env = Target.getTriple().getEnvironmentName();
+
+  // Attempt to match platform and environment.
+  if (Platform == Feature || Target.getTriple().getOSName() == Feature ||
+      Env == Feature)
+    return true;
+
+  auto CmpPlatformEnv = [](StringRef LHS, StringRef RHS) {
+    auto Pos = LHS.find("-");
+    if (Pos == StringRef::npos)
+      return false;
+    SmallString<128> NewLHS = LHS.slice(0, Pos);
+    NewLHS += LHS.slice(Pos+1, LHS.size());
+    return NewLHS == RHS;
+  };
+
+  SmallString<128> PlatformEnv = Target.getTriple().getOSAndEnvironmentName();
+  // Darwin has different but equivalent variants for simulators, example:
+  //   1. x86_64-apple-ios-simulator
+  //   2. x86_64-apple-iossimulator
+  // where both are valid examples of the same platform+environment but in the
+  // variant (2) the simulator is hardcoded as part of the platform name. Both
+  // forms above should match for "iossimulator" requirement.
+  if (Target.getTriple().isOSDarwin() && PlatformEnv.endswith("simulator"))
+    return PlatformEnv == Feature || CmpPlatformEnv(PlatformEnv, Feature);
+
+  return PlatformEnv == Feature;
+}
+
 /// Determine whether a translation unit built using the current
 /// language options has the given feature.
 static bool hasFeature(StringRef Feature, const LangOptions &LangOpts,
@@ -93,7 +124,8 @@ static bool hasFeature(StringRef Feature
                         .Case("opencl", LangOpts.OpenCL)
                         .Case("tls", Target.isTLSSupported())
                         .Case("zvector", LangOpts.ZVector)
-                        .Default(Target.hasFeature(Feature));
+                        .Default(Target.hasFeature(Feature) ||
+                                 isPlatformEnvironment(Target, Feature));
   if (!HasFeature)
     HasFeature = std::find(LangOpts.ModuleFeatures.begin(),
                            LangOpts.ModuleFeatures.end(),

Added: cfe/trunk/test/Modules/target-platform-features.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/target-platform-features.m?rev=342499&view=auto
==============================================================================
--- cfe/trunk/test/Modules/target-platform-features.m (added)
+++ cfe/trunk/test/Modules/target-platform-features.m Tue Sep 18 10:11:13 2018
@@ -0,0 +1,79 @@
+// Clear and create directories
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: mkdir %t/cache
+// RUN: mkdir %t/InputsA
+
+// RUN: echo "module RequiresMacOS {"       >> %t/InputsA/module.map
+// RUN: echo "  requires macos"             >> %t/InputsA/module.map
+// RUN: echo "}"                            >> %t/InputsA/module.map
+// RUN: echo "module RequiresNotiOS {"      >> %t/InputsA/module.map
+// RUN: echo "  requires !ios"              >> %t/InputsA/module.map
+// RUN: echo "}"                            >> %t/InputsA/module.map
+// RUN: echo "module RequiresMain {"        >> %t/InputsA/module.map
+// RUN: echo "  module SubRequiresNotiOS {" >> %t/InputsA/module.map
+// RUN: echo "    requires !ios"            >> %t/InputsA/module.map
+// RUN: echo "  }"                          >> %t/InputsA/module.map
+// RUN: echo "}"                            >> %t/InputsA/module.map
+
+// RUN: %clang_cc1 -triple=x86_64-apple-macosx10.6 -DENABLE_DARWIN -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x objective-c -I%t/InputsA -verify %s 
+// expected-no-diagnostics
+
+// RUN: not %clang_cc1 -triple=arm64-apple-ios -DENABLE_DARWIN -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x objective-c -I%t/InputsA %s  2> %t/notios
+// RUN: FileCheck %s -check-prefix=CHECK-IOS < %t/notios
+#ifdef ENABLE_DARWIN
+// CHECK-IOS: module 'RequiresMacOS' requires feature 'macos'
+ at import RequiresMacOS;
+// CHECK-IOS: module 'RequiresNotiOS' is incompatible with feature 'ios'
+ at import RequiresNotiOS;
+// We should never get errors for submodules that don't match
+// CHECK-IOS-NOT: module 'RequiresMain'
+ at import RequiresMain;
+#endif
+
+// RUN: mkdir %t/InputsB
+// RUN: echo "module RequiresiOSSim {"     >> %t/InputsB/module.map
+// RUN: echo "  requires iossimulator"      >> %t/InputsB/module.map
+// RUN: echo "}"                            >> %t/InputsB/module.map
+// RUN: %clang_cc1 -triple=x86_64-apple-iossimulator -DENABLE_IOSSIM -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x objective-c -I%t/InputsB %s  -verify
+// RUN: %clang_cc1 -triple=x86_64-apple-ios-simulator -DENABLE_IOSSIM -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x objective-c -I%t/InputsB %s  -verify
+
+#ifdef ENABLE_IOSSIM
+ at import RequiresiOSSim;
+#endif
+
+// RUN: mkdir %t/InputsC
+// RUN: echo "module RequiresLinuxEABIA {"  >> %t/InputsC/module.map
+// RUN: echo "  requires linux, gnueabi"    >> %t/InputsC/module.map
+// RUN: echo "}"                            >> %t/InputsC/module.map
+// RUN: echo "module RequiresLinuxEABIB {"  >> %t/InputsC/module.map
+// RUN: echo "  requires gnueabi"           >> %t/InputsC/module.map
+// RUN: echo "}"                            >> %t/InputsC/module.map
+// RUN: echo "module RequiresLinuxEABIC {"  >> %t/InputsC/module.map
+// RUN: echo "  requires linux"             >> %t/InputsC/module.map
+// RUN: echo "}"                            >> %t/InputsC/module.map
+// RUN: %clang_cc1 -triple=armv8r-none-linux-gnueabi -DENABLE_LINUXEABI -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x objective-c -I%t/InputsC %s -verify
+
+#ifdef ENABLE_LINUXEABI
+ at import RequiresLinuxEABIA;
+ at import RequiresLinuxEABIB;
+ at import RequiresLinuxEABIC;
+#endif
+
+// RUN: mkdir %t/InputsD
+// RUN: echo "module RequiresWinMSVCA {"  >> %t/InputsD/module.map
+// RUN: echo "  requires windows"         >> %t/InputsD/module.map
+// RUN: echo "}"                          >> %t/InputsD/module.map
+// RUN: echo "module RequiresWinMSVCB {"  >> %t/InputsD/module.map
+// RUN: echo "  requires windows, msvc"   >> %t/InputsD/module.map
+// RUN: echo "}"                          >> %t/InputsD/module.map
+// RUN: echo "module RequiresWinMSVCC {"  >> %t/InputsD/module.map
+// RUN: echo "  requires msvc"            >> %t/InputsD/module.map
+// RUN: echo "}"                          >> %t/InputsD/module.map
+// RUN: %clang_cc1 -triple=thumbv7-unknown-windows-msvc -DENABLE_WINMSVC -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x objective-c -I%t/InputsD %s  -verify
+
+#ifdef ENABLE_WINMSVC
+ at import RequiresWinMSVCA;
+ at import RequiresWinMSVCB;
+ at import RequiresWinMSVCC;
+#endif




More information about the cfe-commits mailing list