[gtk-doc/win-no-msys: 19/21] scangobj: Support Visual Studio compilers




commit 639690e5e393577807f1dd7813278cfecfe7a8b5
Author: Chun-wei Fan <fanchunwei src gnome org>
Date:   Wed Apr 15 12:03:53 2020 +0800

    scangobj: Support Visual Studio compilers
    
    We make use of distutils to check what type the default compiler is, and we pass in CC=cl
    if we detected Visual Studio to be the default compiler and CC is not set otherwise.  We
    also set LD=link when we are using Visual Studio and when LD is not set.
    
    Also set the compiler and linker flags appropriately when we are using Visual Studio when
    running gtkdoc-scangobj.
    
    Make sure we use forward slahes when retrieving the base_filename in scangobj.py so that
    when we build the scanner program the program does not get confused on the paths of the
    various files that is built using base_filename.

 gtkdoc-scangobj.in | 11 +++++--
 gtkdoc/scangobj.py | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 98 insertions(+), 9 deletions(-)
---
diff --git a/gtkdoc-scangobj.in b/gtkdoc-scangobj.in
index 7660c70b..27de6664 100755
--- a/gtkdoc-scangobj.in
+++ b/gtkdoc-scangobj.in
@@ -32,6 +32,7 @@ except ModuleNotFoundError:
 from gtkdoc import common, config, scangobj
 
 if __name__ == '__main__':
+    is_msvc = scangobj.check_is_msvc()
     parser = argparse.ArgumentParser(
         description='gtkdoc-rebase version %s - introspect g-objects' % config.version)
     parser.add_argument('--version', action='version', version=config.version)
@@ -66,9 +67,15 @@ if __name__ == '__main__':
         options.ldflags = ' '.join(options.ldflags)
 
     if not options.cc:
-        options.cc = os.environ.get('CC', 'gcc')
+        if is_msvc:
+            options.cc = os.environ.get('CC', 'cl')
+        else:
+            options.cc = os.environ.get('CC', 'gcc')
     if not options.ld:
-        options.ld = os.environ.get('LD', options.cc)
+        if is_msvc:
+            options.ld = os.environ.get('LD', 'link')
+        else:
+            options.ld = os.environ.get('LD', options.cc)
     if not options.cflags:
         options.cflags = os.environ.get('CFLAGS', '')
     if not options.ldflags:
diff --git a/gtkdoc/scangobj.py b/gtkdoc/scangobj.py
index 7434ec14..40e36e6c 100644
--- a/gtkdoc/scangobj.py
+++ b/gtkdoc/scangobj.py
@@ -25,12 +25,18 @@ compiling and running a small C program. CFLAGS and LDFLAGS must be set
 appropriately before running this script.
 """
 
+import distutils
 import logging
 import os
 import string
 import subprocess
 import shlex
 
+from distutils import ccompiler
+from distutils.cygwinccompiler import Mingw32CCompiler
+from distutils.msvccompiler import MSVCCompiler
+from distutils.sysconfig import customize_compiler
+
 from . import common, config
 
 
@@ -1212,7 +1218,7 @@ def run(options):
     c_file = options.module + '-scan.c'
     output = open(c_file, 'w', encoding='utf-8')
 
-    base_filename = os.path.join(options.output_dir, options.module)
+    base_filename = os.path.join(options.output_dir, options.module).replace('\\', '/')
     old_signals_filename = base_filename + '.signals'
     new_signals_filename = base_filename + '.signals.new'
     old_hierarchy_filename = base_filename + '.hierarchy'
@@ -1288,30 +1294,68 @@ def run(options):
     if 'libtool' in options.cc:
         o_file = options.module + '-scan.lo'
     else:
-        o_file = options.module + '-scan.o'
+        obj_ext = '.o'
+        if options.cc == 'cl':
+            obj_ext = '.obj'
+        o_file = options.module + '-scan' + obj_ext
 
     x_file = options.module + '-scan' + config.exeext
 
     logging.debug('Intermediate scanner files: %s, %s, %s', c_file, o_file, x_file)
 
+    # For Visual Studio, the intermediate compiled object files have the extension '.obj'
+    # and we ought to use '-Fo$(o_file)' instead of '-o $(o_file)', since although -o is
+    # supported on Visual Studio but is considered deprecated usage
+    compile_outfile_flag = ['-o', o_file]
+    if options.cc == 'cl':
+        compile_outfile_flag = ['-Fo' + o_file]
+
     res = execute_command(options, 'Compiling',
                           shlex.split(options.cc) + shlex.split(options.cflags) +
-                          ["-c", "-o", o_file, c_file])
+                          ["-c"] + compile_outfile_flag + [c_file])
     if res:
         return res
 
+    ldflags = shlex.split(options.ldflags)
+
+    # Make the GCC-style linker flags into what Visual Studio understands,
+    # (akin to what pkg-config --msvc-syntax does).  For '-Wl,rpath,', we
+    # prepend these items in order to %PATH%; for '-l' we drop the '-l' flag
+    # and append that argument with '.lib'; for '-L' we replace '-L' with '/libpath:'
+    if options.cc == 'cl':
+        path_index = 0
+        path_env = os.environ['PATH'].split(os.pathsep)
+        for idx,flag in enumerate(ldflags):
+            if flag.startswith('-L'):
+                ldflags[idx] = '/libpath:' + flag[2:]
+            elif flag.startswith('-l'):
+                ldflags[idx] = flag[2:] + '.lib'
+            elif flag.startswith('-Wl,-rpath,'):
+                path_env.insert(path_index, flag[11:].replace('/', '\\'))
+                path_index += 1
+
+        os.environ['PATH'] = os.pathsep.join(path_env)
+        o_flag = ['-out:' + x_file]
+    else:
+        o_flag = ['-o', x_file]
+
     res = execute_command(options, 'Linking',
                           shlex.split(options.ld) + [o_file] +
-                          shlex.split(options.ldflags) + ['-o', x_file])
+                          ldflags + o_flag)
     if res:
         return res
 
     run_env = os.environ.copy()
     run_env['LC_MESSAGES'] = 'C'
     run_env.pop('LC_ALL', None)
-    res = execute_command(options, 'Running',
-                          shlex.split(options.run) + ['./' + x_file],
-                          env=run_env)
+    if options.cc == 'cl':
+        res = execute_command(options, 'Running',
+                              shlex.split(options.run) + [x_file],
+                              env=run_env)
+    else:
+        res = execute_command(options, 'Running',
+                              shlex.split(options.run) + ['./' + x_file],
+                              env=run_env)
     if res:
         return res
 
@@ -1335,3 +1379,41 @@ def run(options):
     common.UpdateFileIfChanged(old_args_filename, new_args_filename, False)
 
     return 0
+
+# Used by gtkdoc-scangobj
+def check_is_msvc():
+    compiler = None
+    is_msvc = False
+    if os.name == 'nt':
+        # The compiler used here on Windows may well not be
+        # the same compiler that was used to build Python,
+        # as the official Python binaries are built with
+        # Visual Studio
+        compiler_name = os.environ.get('CC')
+        if compiler_name is None:
+            if os.environ.get('MSYSTEM') == 'MINGW32' or os.environ.get('MSYSTEM') == 'MINGW64':
+                compiler_name = 'mingw32'
+            else:
+                compiler_name = distutils.ccompiler.get_default_compiler()
+
+        if compiler_name != 'msvc' and \
+           compiler_name != 'mingw32' and \
+           compiler_name != 'clang' and \
+           compiler_name != 'clang-cl':
+            raise SystemExit('Specified Compiler \'%s\' is unsupported.' % compiler_name)
+    else:
+        # XXX: Is it common practice to use a non-Unix compiler
+        #      class instance on non-Windows on platforms g-i supports?
+        compiler_name = distutils.ccompiler.get_default_compiler()
+
+    # Now, create the distutils ccompiler instance based on the info we have.
+    if compiler_name == 'msvc':
+        # For MSVC, we need to create a instance of a subclass of distutil's
+        # MSVC9Compiler class, as it does not provide a preprocess()
+        # implementation
+        compiler = distutils.msvccompiler.MSVCCompiler()
+    else:
+        compiler = distutils.ccompiler.new_compiler(compiler=compiler_name)
+        customize_compiler(compiler)
+
+    return isinstance(compiler, distutils.msvccompiler.MSVCCompiler)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]