Bug 1045783 - Move OS_LIBS from a passthrough to a more fully supported variable. r=gps
authorMike Hommey <mh+mozilla@glandium.org>
Wed, 06 Aug 2014 07:25:05 +0900
changeset 219695 95cd38a0e6a54b3fc4e0a5969228e84300893fa9
parent 219694 ab8a104509b487d30915d6a207e19c60b4dd59a3
child 219696 98614c9969ce8ba59350f978514f60706e18e03b
push id3979
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 16:35:44 +0000
treeherdermozilla-beta@30f2cc610691 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgps
bugs1045783
milestone34.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 1045783 - Move OS_LIBS from a passthrough to a more fully supported variable. r=gps
build/docs/defining-binaries.rst
ipc/chromium/chromium-config.mozbuild
python/mozbuild/mozbuild/backend/recursivemake.py
python/mozbuild/mozbuild/frontend/data.py
python/mozbuild/mozbuild/frontend/emitter.py
python/mozbuild/mozbuild/frontend/sandbox_symbols.py
python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build
python/mozbuild/mozbuild/test/backend/test_recursivemake.py
python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build
python/mozbuild/mozbuild/test/frontend/test_emitter.py
--- a/build/docs/defining-binaries.rst
+++ b/build/docs/defining-binaries.rst
@@ -153,16 +153,43 @@ The corresponding ``SOURCES`` must match
        'FirstProgram.cpp',
        'SecondProgram.c',
    ]
 
 Similar to ``SIMPLE_PROGRAMS``, is ``CPP_UNIT_TESTS``, which defines, with the
 same rules, C++ unit tests programs.
 
 
+Linking with system libraries
+=============================
+
+Programs and libraries usually need to link with system libraries, such as a
+widget toolkit, etc. Those required dependencies can be given with the
+``OS_LIBS`` variable.
+
+   OS_LIBS += [
+       'foo',
+       'bar',
+   ]
+
+This expands to ``foo.lib bar.lib`` when building with MSVC, and
+``-lfoo -lbar`` otherwise.
+
+For convenience with ``pkg-config``, ``OS_LIBS`` can also take linker flags
+such as ``-L/some/path`` and ``-llib``, such that it is possible to directly
+assign ``LIBS`` variables from ``CONFIG``, such as:
+
+   OS_LIBS += CONFIG['MOZ_PANGO_LIBS']
+
+(assuming ``CONFIG['MOZ_PANGO_LIBS']`` is a list, not a string)
+
+Like ``USE_LIBS``, this variable applies to static and shared libraries, as
+well as programs.
+
+
 Building both static and shared libraries
 =========================================
 
 When both types of libraries are required, one needs to set both
 ``FORCE_SHARED_LIB`` and ``FORCE_STATIC_LIB`` boolean variables.
 
    FORCE_SHARED_LIB = True
    FORCE_STATIC_LIB = True
--- a/ipc/chromium/chromium-config.mozbuild
+++ b/ipc/chromium/chromium-config.mozbuild
@@ -9,17 +9,21 @@ LOCAL_INCLUDES += [
     '/ipc/glue',
 ]
 
 GENERATED_INCLUDES += [
     '/ipc/ipdl/_ipdlheaders',
 ]
 
 if CONFIG['OS_ARCH'] == 'WINNT':
-    OS_LIBS += [ '$(call EXPAND_LIBNAME,psapi shell32 dbghelp)' ]
+    OS_LIBS += [
+        'psapi',
+        'shell32',
+        'dbghelp',
+    ]
 
     DEFINES.update({
         'UNICODE': True,
         '_UNICODE': True,
         'NOMINMAX': True,
         '_CRT_RAND_S': True,
         'CERT_CHAIN_PARA_HAS_EXTRA_FIELDS': True,
         '_SECURE_ATL': True,
--- a/python/mozbuild/mozbuild/backend/recursivemake.py
+++ b/python/mozbuild/mozbuild/backend/recursivemake.py
@@ -1191,23 +1191,25 @@ class RecursiveMakeBackend(CommonBackend
     def _process_host_library(self, libdef, backend_file):
         backend_file.write('HOST_LIBRARY_NAME = %s\n' % libdef.basename)
 
     def _build_target_for_obj(self, obj):
         return '%s/%s' % (mozpath.relpath(obj.objdir,
             self.environment.topobjdir), obj.KIND)
 
     def _process_linked_libraries(self, obj, backend_file):
-        def recursive_get_shared_libs(lib):
+        def write_shared_and_system_libs(lib):
             for l in lib.linked_libraries:
                 if isinstance(l, StaticLibrary):
-                    for q in recursive_get_shared_libs(l):
-                        yield q
+                    write_shared_and_system_libs(l)
                 else:
-                    yield l
+                    backend_file.write_once('SHARED_LIBS += %s/%s\n'
+                        % (pretty_relpath(l), l.import_name))
+            for l in lib.linked_system_libs:
+                backend_file.write_once('OS_LIBS += %s\n' % l)
 
         def pretty_relpath(lib):
             return '$(DEPTH)/%s' % mozpath.relpath(lib.objdir, topobjdir)
 
         topobjdir = mozpath.normsep(obj.topobjdir)
         # This will create the node even if there aren't any linked libraries.
         build_target = self._build_target_for_obj(obj)
         self._compile_graph[build_target]
@@ -1233,39 +1235,41 @@ class RecursiveMakeBackend(CommonBackend
             self._compile_graph[build_target].add(
                 self._build_target_for_obj(lib))
             relpath = pretty_relpath(lib)
             if isinstance(obj, Library):
                 if isinstance(lib, StaticLibrary):
                     backend_file.write_once('STATIC_LIBS += %s/%s\n'
                                         % (relpath, lib.import_name))
                     if isinstance(obj, SharedLibrary):
-                        for l in recursive_get_shared_libs(lib):
-                            backend_file.write_once('SHARED_LIBS += %s/%s\n'
-                                        % (pretty_relpath(l), l.import_name))
+                        write_shared_and_system_libs(lib)
                 elif isinstance(obj, SharedLibrary):
                     assert lib.variant != lib.COMPONENT
                     backend_file.write_once('SHARED_LIBS += %s/%s\n'
                                         % (relpath, lib.import_name))
             elif isinstance(obj, (Program, SimpleProgram)):
                 if isinstance(lib, StaticLibrary):
                     backend_file.write_once('STATIC_LIBS += %s/%s\n'
                                         % (relpath, lib.import_name))
-                    for l in recursive_get_shared_libs(lib):
-                        backend_file.write_once('SHARED_LIBS += %s/%s\n'
-                                        % (pretty_relpath(l), l.import_name))
+                    write_shared_and_system_libs(lib)
                 else:
                     assert lib.variant != lib.COMPONENT
                     backend_file.write_once('SHARED_LIBS += %s/%s\n'
                                         % (relpath, lib.import_name))
             elif isinstance(obj, (HostLibrary, HostProgram, HostSimpleProgram)):
                 assert isinstance(lib, HostLibrary)
                 backend_file.write_once('HOST_LIBS += %s/%s\n'
                                    % (relpath, lib.import_name))
 
+        for lib in obj.linked_system_libs:
+            if obj.KIND == 'target':
+                backend_file.write_once('OS_LIBS += %s\n' % lib)
+            else:
+                backend_file.write_once('HOST_EXTRA_LIBS += %s\n' % lib)
+
     def _write_manifests(self, dest, manifests):
         man_dir = mozpath.join(self.environment.topobjdir, '_build_manifests',
             dest)
 
         # We have a purger for the manifests themselves to ensure legacy
         # manifests are deleted.
         purger = FilePurger()
 
--- a/python/mozbuild/mozbuild/frontend/data.py
+++ b/python/mozbuild/mozbuild/frontend/data.py
@@ -323,32 +323,50 @@ class ExampleWebIDLInterface(SandboxDeri
 
 
 class LinkageWrongKindError(Exception):
     """Error thrown when trying to link objects of the wrong kind"""
 
 
 class Linkable(SandboxDerived):
     """Generic sandbox container object for programs and libraries"""
-    __slots__ = ('linked_libraries')
+    __slots__ = (
+        'linked_libraries',
+        'linked_system_libs',
+    )
 
     def __init__(self, sandbox):
         SandboxDerived.__init__(self, sandbox)
         self.linked_libraries = []
+        self.linked_system_libs = []
 
     def link_library(self, obj):
         assert isinstance(obj, BaseLibrary)
         if isinstance(obj, SharedLibrary) and obj.variant == obj.COMPONENT:
             raise LinkageWrongKindError(
                 'Linkable.link_library() does not take components.')
         if obj.KIND != self.KIND:
             raise LinkageWrongKindError('%s != %s' % (obj.KIND, self.KIND))
         self.linked_libraries.append(obj)
         obj.refs.append(self)
 
+    def link_system_library(self, lib):
+        # The '$' check is here as a special temporary rule, allowing the
+        # inherited use of make variables, most notably in TK_LIBS.
+        if not lib.startswith('$') and not lib.startswith('-'):
+            if self.config.substs.get('GNU_CC'):
+                lib = '-l%s' % lib
+            else:
+                lib = '%s%s%s' % (
+                    self.config.import_prefix,
+                    lib,
+                    self.config.import_suffix,
+                )
+        self.linked_system_libs.append(lib)
+
 
 class BaseProgram(Linkable):
     """Sandbox container object for programs, which is a unicode string.
 
     This class handles automatically appending a binary suffix to the program
     name.
     If the suffix is not defined, the program name is unchanged.
     Otherwise, if the program name ends with the given suffix, it is unchanged
--- a/python/mozbuild/mozbuild/frontend/emitter.py
+++ b/python/mozbuild/mozbuild/frontend/emitter.py
@@ -309,16 +309,20 @@ class TreeMetadataEmitter(LoggingMixin):
                     name, candidates[0].relobjdir, candidates[0].relobjdir),
                     sandbox)
 
             elif isinstance(obj, StaticLibrary) and isinstance(candidates[0],
                     SharedLibrary):
                 self._static_linking_shared.add(obj)
             obj.link_library(candidates[0])
 
+        # Link system libraries from OS_LIBS/HOST_OS_LIBS.
+        for lib in sandbox.get(variable.replace('USE', 'OS'), []):
+            obj.link_system_library(lib)
+
     def emit_from_sandbox(self, sandbox):
         """Convert a MozbuildSandbox to tree metadata objects.
 
         This is a generator of mozbuild.frontend.data.SandboxDerived instances.
         """
         # We always emit a directory traversal descriptor. This is needed by
         # the recursive make backend.
         for o in self._emit_directory_traversal_from_sandbox(sandbox): yield o
@@ -376,17 +380,16 @@ class TreeMetadataEmitter(LoggingMixin):
             'EXTRA_PP_COMPONENTS',
             'FAIL_ON_WARNINGS',
             'FILES_PER_UNIFIED_FILE',
             'USE_STATIC_LIBS',
             'GENERATED_FILES',
             'IS_GYP_DIR',
             'MSVC_ENABLE_PGO',
             'NO_DIST_INSTALL',
-            'OS_LIBS',
             'PYTHON_UNIT_TESTS',
             'RCFILE',
             'RESFILE',
             'RCINCLUDE',
             'DEFFILE',
             'WIN32_EXE_LDFLAGS',
             'LD_VERSION_SCRIPT',
         ]
--- a/python/mozbuild/mozbuild/frontend/sandbox_symbols.py
+++ b/python/mozbuild/mozbuild/frontend/sandbox_symbols.py
@@ -327,16 +327,20 @@ VARIABLES = {
     'USE_LIBS': (StrictOrderingOnAppendList, list,
         """List of libraries to link to programs and libraries.
         """, None),
 
     'HOST_USE_LIBS': (StrictOrderingOnAppendList, list,
         """List of libraries to link to host programs and libraries.
         """, None),
 
+    'HOST_OS_LIBS': (List, list,
+        """List of system libraries for host programs and libraries.
+        """, None),
+
     'LOCAL_INCLUDES': (StrictOrderingOnAppendList, list,
         """Additional directories to be searched for include files by the compiler.
         """, None),
 
     'MSVC_ENABLE_PGO': (bool, bool,
         """Whether profile-guided optimization is enabled for MSVC in this directory.
         """, None),
 
--- a/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build
+++ b/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build
@@ -5,18 +5,16 @@
 SOURCES += ['bar.s', 'foo.asm']
 
 EXTRA_COMPONENTS = ['bar.js', 'foo.js']
 EXTRA_PP_COMPONENTS = ['bar.pp.js', 'foo.pp.js']
 
 HOST_SOURCES += ['bar.cpp', 'foo.cpp']
 HOST_SOURCES += ['bar.c', 'foo.c']
 
-OS_LIBS = ['foo.so', '-l123', 'bar.a']
-
 SOURCES += ['bar.c', 'foo.c']
 
 SOURCES += ['bar.mm', 'foo.mm']
 
 SOURCES += ['baz.S', 'foo.S']
 
 FAIL_ON_WARNINGS = True
 MSVC_ENABLE_PGO = True
--- a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
+++ b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
@@ -285,21 +285,16 @@ class TestRecursiveMakeBackend(BackendTe
             ],
             'HOST_CSRCS': [
                 'HOST_CSRCS += bar.c',
                 'HOST_CSRCS += foo.c',
             ],
             'MSVC_ENABLE_PGO': [
                 'MSVC_ENABLE_PGO := 1',
             ],
-            'OS_LIBS': [
-                'OS_LIBS += foo.so',
-                'OS_LIBS += -l123',
-                'OS_LIBS += bar.a',
-            ],
             'SSRCS': [
                 'SSRCS += baz.S',
                 'SSRCS += foo.S',
             ],
             'VISIBILITY_FLAGS': [
                 'VISIBILITY_FLAGS :=',
             ],
             'DELAYLOAD_LDFLAGS': [
--- a/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build
+++ b/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build
@@ -5,18 +5,16 @@
 SOURCES += ['fans.asm', 'tans.s']
 
 EXTRA_COMPONENTS=['fans.js', 'tans.js']
 EXTRA_PP_COMPONENTS=['fans.pp.js', 'tans.pp.js']
 
 HOST_SOURCES += ['fans.cpp', 'tans.cpp']
 HOST_SOURCES += ['fans.c', 'tans.c']
 
-OS_LIBS += ['foo.so', '-l123', 'aaa.a']
-
 SOURCES += ['fans.c', 'tans.c']
 
 SOURCES += ['fans.mm', 'tans.mm']
 
 SOURCES += ['bans.S', 'fans.S']
 
 FAIL_ON_WARNINGS = True
 MSVC_ENABLE_PGO = True
--- a/python/mozbuild/mozbuild/test/frontend/test_emitter.py
+++ b/python/mozbuild/mozbuild/test/frontend/test_emitter.py
@@ -154,17 +154,16 @@ class TestEmitterBasic(unittest.TestCase
             DISABLE_STL_WRAPPING=True,
             EXTRA_COMPONENTS=['fans.js', 'tans.js'],
             EXTRA_PP_COMPONENTS=['fans.pp.js', 'tans.pp.js'],
             FAIL_ON_WARNINGS=True,
             HOST_CPPSRCS=['fans.cpp', 'tans.cpp'],
             HOST_CSRCS=['fans.c', 'tans.c'],
             MSVC_ENABLE_PGO=True,
             NO_DIST_INSTALL=True,
-            OS_LIBS=['foo.so', '-l123', 'aaa.a'],
             SSRCS=['bans.S', 'fans.S'],
             VISIBILITY_FLAGS='',
             DELAYLOAD_LDFLAGS=['-DELAYLOAD:foo.dll', '-DELAYLOAD:bar.dll'],
             USE_DELAYIMP=True,
             RCFILE='foo.rc',
             RESFILE='bar.res',
             RCINCLUDE='bar.rc',
             DEFFILE='baz.def',