Bug 1290026 - Automatically set LIB from configure. r=chmanchester
☠☠ backed out by ca6285618c89 ☠ ☠
authorMike Hommey <mh+mozilla@glandium.org>
Wed, 27 Jul 2016 18:01:04 +0900
changeset 347427 90559af62774f42daa4aab8500c6bd6a8a39d3d2
parent 347426 a4a381f85dc805e4ef288ef1f747a05d19f48931
child 347428 2f171516dfc2c4dbfd8e3b11551aec4ef9d2ce0a
push id6389
push userraliiev@mozilla.com
push dateMon, 19 Sep 2016 13:38:22 +0000
treeherdermozilla-beta@01d67bfe6c81 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerschmanchester
bugs1290026
milestone50.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1290026 - Automatically set LIB from configure. r=chmanchester
build/moz.configure/windows.configure
config/config.mk
--- a/build/moz.configure/windows.configure
+++ b/build/moz.configure/windows.configure
@@ -45,41 +45,58 @@ def windows_sdk_dir(value, host):
 
     return tuple(x[1] for x in get_registry_values(
         r'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots'
         r'\KitsRoot*'))
 
 # The Windows SDK 8.1 and 10 have different layouts. The former has
 # $SDK/include/$subdir, while the latter has $SDK/include/$version/$subdir.
 # The vcvars* scripts don't actually care about the version, they just take
-# the last.
+# the last alphanumerically.
+# The $SDK/lib directories always have version subdirectories, but while the
+# versions match the one in $SDK/include for SDK 10, it's "winv6.3" for SDK
+# 8.1.
 @imports('os')
 @imports('re')
 @imports(_from='__builtin__', _import='sorted')
 @imports(_from='__builtin__', _import='WindowsError')
-def get_include_dir(sdk, subdir):
-    base = os.path.join(sdk, 'include')
-    try:
-        subdirs = [d for d in os.listdir(base)
-                   if os.path.isdir(os.path.join(base, d))]
-    except WindowsError:
-        subdirs = []
-    if not subdirs:
-        return None
-    if subdir in subdirs:
-        return os.path.join(base, subdir)
-    # At this point, either we have an incomplete or invalid SDK directory,
-    # or we exclusively have version numbers in subdirs.
-    versions = sorted((Version(d) for d in subdirs), reverse=True)
-    # Version('non-number').major is 0, so if the biggest version we have is
-    # 0, we have a problem.
-    if versions[0].major == 0:
-        return None
-    path = os.path.join(base, str(versions[0]), subdir)
-    return path if os.path.isdir(path) else None
+def get_sdk_dirs(sdk, subdir):
+    def get_dirs_containing(sdk, stem, subdir):
+        base = os.path.join(sdk, stem)
+        try:
+            subdirs = [d for d in os.listdir(base)
+                       if os.path.isdir(os.path.join(base, d))]
+        except WindowsError:
+            subdirs = []
+        if not subdirs:
+            return ()
+        if subdir in subdirs:
+            return (base,)
+        # At this point, either we have an incomplete or invalid SDK directory,
+        # or we exclusively have version numbers in subdirs.
+        return tuple(os.path.join(base, s) for s in subdirs
+                     if os.path.isdir(os.path.join(base, s, subdir)))
+
+    def categorize(dirs):
+        return {os.path.basename(d): d for d in dirs}
+
+    include_dirs = categorize(get_dirs_containing(sdk, 'include', subdir))
+    lib_dirs = categorize(get_dirs_containing(sdk, 'lib', subdir))
+
+    if 'include' in include_dirs:
+        include_dirs['winv6.3'] = include_dirs['include']
+        del include_dirs['include']
+
+    valid_versions = sorted(set(include_dirs) & set(lib_dirs), reverse=True)
+    if valid_versions:
+        return namespace(
+            path=sdk,
+            lib=lib_dirs[valid_versions[0]],
+            include=include_dirs[valid_versions[0]],
+        )
 
 
 @imports(_from='mozbuild.shellutil', _import='quote')
 def valid_windows_sdk_dir_result(value):
     if value:
         return '0x%04x in %s' % (value.version, quote(value.path))
 
 @depends_win(c_compiler, windows_sdk_dir, valid_windows_version,
@@ -88,61 +105,64 @@ def valid_windows_sdk_dir_result(value):
 @imports(_from='__builtin__', _import='sorted')
 @imports(_from='textwrap', _import='dedent')
 def valid_windows_sdk_dir(compiler, windows_sdk_dir, target_version,
                           windows_sdk_dir_env):
     if windows_sdk_dir_env:
         windows_sdk_dir_env = windows_sdk_dir_env[0]
     sdks = {}
     for d in windows_sdk_dir:
-        um_dir = get_include_dir(d, 'um')
-        shared_dir = get_include_dir(d, 'shared')
-        if um_dir and shared_dir:
+        sdk = get_sdk_dirs(d, 'um')
+        if sdk:
             check = dedent('''\
             #include <winsdkver.h>
             WINVER_MAXVER
             ''')
+            um_dir = os.path.join(sdk.include, 'um')
+            shared_dir = os.path.join(sdk.include, 'shared')
             result = try_preprocess(compiler.wrapper + [compiler.compiler] +
                                     compiler.flags +
                                     ['-I', um_dir, '-I', shared_dir], 'C',
                                     check)
             if result:
                 maxver = result.splitlines()[-1]
                 try:
                     maxver = int(maxver, 0)
                 except:
                     pass
                 else:
-                    sdks[d] = maxver
+                    sdks[d] = maxver, sdk
                     continue
         if d == windows_sdk_dir_env:
             raise FatalCheckError(
                 'Error while checking the version of the SDK in '
                 'WINDOWSSDKDIR (%s). Please verify it contains a valid and '
                 'complete SDK installation.' % windows_sdk_dir_env)
 
-    valid_sdks = sorted(sdks, key=lambda x: sdks[x], reverse=True)
+    valid_sdks = sorted(sdks, key=lambda x: sdks[x][0], reverse=True)
     if valid_sdks:
-        biggest_version = sdks[valid_sdks[0]]
+        biggest_version, sdk = sdks[valid_sdks[0]]
     if not valid_sdks or biggest_version < target_version:
         if windows_sdk_dir_env:
             raise FatalCheckError(
                 'You are targeting Windows version 0x%04x, but your SDK only '
                 'supports up to version 0x%04x. Install and use an updated SDK, '
                 'or target a lower version using --with-windows-version. '
                 'Alternatively, try running the Windows SDK Configuration Tool '
                 'and selecting a newer SDK. See '
                 'https://developer.mozilla.org/En/Windows_SDK_versions for '
                 'details on fixing this.' % (target_version, biggest_version))
 
         raise FatalCheckError(
             'Cannot find a Windows SDK for version >= 0x%04x.' % target_version)
 
     return namespace(
-        path=valid_sdks[0],
+        path=sdk.path,
+        include=sdk.include,
+        lib=sdk.lib,
         version=biggest_version,
     )
 
 
 add_old_configure_assignment(
     'WINDOWSSDKDIR',
     delayed_getattr(valid_windows_sdk_dir, 'path'))
 add_old_configure_assignment(
@@ -159,40 +179,44 @@ def valid_ucrt_sdk_dir_result(value):
 @depends_win(windows_sdk_dir, 'WINDOWSSDKDIR')
 @checking('for Universal CRT SDK', valid_ucrt_sdk_dir_result)
 @imports(_from='__builtin__', _import='sorted')
 def valid_ucrt_sdk_dir(windows_sdk_dir, windows_sdk_dir_env):
     if windows_sdk_dir_env:
         windows_sdk_dir_env = windows_sdk_dir_env[0]
     sdks = {}
     for d in windows_sdk_dir:
-        ucrt_dir = get_include_dir(d, 'ucrt')
-        if ucrt_dir:
-            version = os.path.basename(os.path.dirname(ucrt_dir))
+        sdk = get_sdk_dirs(d, 'ucrt')
+        if sdk:
+            version = os.path.basename(sdk.include)
             # We're supposed to always find a version in the directory, because
             # the 8.1 SDK, which doesn't have a version in the directory, doesn't
             # contain the Universal CRT SDK. When the main SDK is 8.1, there
             # is, however, supposed to be a reduced install of the SDK 10
             # with the UCRT.
             if version != 'include':
-                sdks[d] = Version(version)
+                sdks[d] = Version(version), sdk
                 continue
         if d == windows_sdk_dir_env:
             raise FatalCheckError(
                 'The SDK in WINDOWSSDKDIR (%s) does not contain the Universal '
                 'CRT.' % windows_sdk_dir_env)
 
-    valid_sdks = sorted(sdks, key=lambda x: sdks[x], reverse=True)
+    valid_sdks = sorted(sdks, key=lambda x: sdks[x][0], reverse=True)
     if not valid_sdks:
         raise FatalCheckError('Cannot find the Universal CRT SDK. '
                               'Please install it.')
 
+    version, sdk = sdks[valid_sdks[0]]
+
     return namespace(
-        path=valid_sdks[0],
-        version=sdks[valid_sdks[0]],
+        path=sdk.path,
+        include=sdk.include,
+        lib=sdk.lib,
+        version=version,
     )
 
 
 @depends_win(c_compiler)
 @imports('os')
 def vc_path(c_compiler):
     if c_compiler.type != 'msvc':
         return
@@ -226,43 +250,92 @@ def dia_sdk_dir(vc_path):
 def include_path(vc_path, windows_sdk_dir, ucrt_sdk_dir, dia_sdk_dir):
     if not vc_path:
         return
     atlmfc_dir = os.path.join(vc_path, 'atlmfc', 'include')
     if not os.path.isdir(atlmfc_dir):
         die('Cannot find the ATL/MFC headers in the Visual C++ directory (%s). '
             'Please install them.' % vc_path)
 
-    winrt_dir = get_include_dir(windows_sdk_dir.path, 'winrt')
+    winrt_dir = os.path.join(windows_sdk_dir.include, 'winrt')
     if not os.path.isdir(winrt_dir):
         die('Cannot find the WinRT headers in the Windows SDK directory (%s). '
             'Please install them.' % windows_sdk_dir.path)
 
     includes = []
     include_env = os.environ.get('INCLUDE')
     if include_env:
         includes.append(include_env)
     includes.extend((
         os.path.join(vc_path, 'include'),
         atlmfc_dir,
-        get_include_dir(windows_sdk_dir.path, 'shared'),
-        get_include_dir(windows_sdk_dir.path, 'um'),
+        os.path.join(windows_sdk_dir.include, 'shared'),
+        os.path.join(windows_sdk_dir.include, 'um'),
         winrt_dir,
-        get_include_dir(ucrt_sdk_dir.path, 'ucrt'),
+        os.path.join(ucrt_sdk_dir.include, 'ucrt'),
     ))
     if dia_sdk_dir:
         includes.append(os.path.join(dia_sdk_dir, 'include'))
     # Set in the environment for old-configure
     includes = os.pathsep.join(includes)
     os.environ['INCLUDE'] = includes
     return includes
 
 set_config('INCLUDE', include_path)
 
 
+@depends_win(target, vc_path, valid_windows_sdk_dir, valid_ucrt_sdk_dir, dia_sdk_dir)
+@imports('os')
+def lib_path(target, vc_path, windows_sdk_dir, ucrt_sdk_dir, dia_sdk_dir):
+    if not vc_path:
+        return
+    vc_target = {
+        'x86': '',
+        'x86_64': 'amd64',
+        'arm': 'arm',
+    }.get(target.cpu)
+    if vc_target is None:
+        return
+    # As vc_target can be '', and os.path.join will happily use the empty
+    # string, leading to a string ending with a backslash, that Make will
+    # interpret as a "string continues on next line" indicator, use variable
+    # args.
+    vc_target = (vc_target,) if vc_target else ()
+    sdk_target = {
+        'x86': 'x86',
+        'x86_64': 'x64',
+        'arm': 'arm',
+    }.get(target.cpu)
+
+    atlmfc_dir = os.path.join(vc_path, 'atlmfc', 'lib', *vc_target)
+    if not os.path.isdir(atlmfc_dir):
+        die('Cannot find the ATL/MFC libraries in the Visual C++ directory (%s). '
+            'Please install them.' % vc_path)
+
+
+    libs = []
+    lib_env = os.environ.get('LIB')
+    if lib_env:
+        libs.append(lib_env)
+    libs.extend((
+        os.path.join(vc_path, 'lib', *vc_target),
+        atlmfc_dir,
+        os.path.join(windows_sdk_dir.lib, 'um', sdk_target),
+        os.path.join(ucrt_sdk_dir.lib, 'ucrt', sdk_target),
+    ))
+    if dia_sdk_dir:
+        libs.append(os.path.join(dia_sdk_dir, 'lib', *vc_target))
+    # Set in the environment for old-configure
+    libs = os.pathsep.join(libs)
+    os.environ['LIB'] = libs
+    return libs
+
+set_config('LIB', lib_path)
+
+
 option(env='MT', nargs=1, help='Path to the Microsoft Manifest Tool')
 
 @depends_win(valid_windows_sdk_dir)
 @imports(_from='os', _import='environ')
 @imports('platform')
 def sdk_bin_path(valid_windows_sdk_dir):
     if not valid_windows_sdk_dir:
         return
--- a/config/config.mk
+++ b/config/config.mk
@@ -359,16 +359,22 @@ export MACOSX_DEPLOYMENT_TARGET
 endif # MACOSX_DEPLOYMENT_TARGET
 
 # Export to propagate to cl and submake for third-party code.
 # Eventually, we'll want to just use -I.
 ifdef INCLUDE
 export INCLUDE
 endif
 
+# Export to propagate to link.exe and submake for third-party code.
+# Eventually, we'll want to just use -LIBPATH.
+ifdef LIB
+export LIB
+endif
+
 ifdef MOZ_USING_CCACHE
 ifdef CLANG_CXX
 export CCACHE_CPP2=1
 endif
 endif
 
 # Set link flags according to whether we want a console.
 ifeq ($(OS_ARCH),WINNT)