From 8770043db5cb4720e1d7b254df0f9632ed11196d Mon Sep 17 00:00:00 2001 From: Jose Quijada Date: Wed, 10 Jul 2019 07:47:22 -0400 Subject: [PATCH] fix: address issues encountered while building on Windows+Cygwin environments Addresses #1782 --- gyp/gyp_main.py | 32 ++++++++++++++++++++++++++++++-- gyp/pylib/gyp/common.py | 20 +++++++++++++++++++- gyp/pylib/gyp/generator/msvs.py | 12 +++++++++++- lib/configure.js | 7 +++++++ 4 files changed, 67 insertions(+), 4 deletions(-) diff --git a/gyp/gyp_main.py b/gyp/gyp_main.py index 25a6eba94a..4e6c3a4366 100755 --- a/gyp/gyp_main.py +++ b/gyp/gyp_main.py @@ -6,10 +6,38 @@ import os import sys +import subprocess + +# Below IsCygwin() function copied from pylib/gyp/common.py +def IsCygwin(): + try: + out = subprocess.Popen("uname", + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + stdout,stderr = out.communicate() + return "CYGWIN" in str(stdout) + except Exception: + return False + + +def UnixifyPath(path): + try: + if not IsCygwin(): + return path + out = subprocess.Popen(["cygpath", "-u", path], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + stdout,stderr = out.communicate() + return str(stdout) + except Exception: + return path + # Make sure we're using the version of pylib in this repo, not one installed -# elsewhere on the system. -sys.path.insert(0, os.path.join(os.path.dirname(sys.argv[0]), 'pylib')) +# elsewhere on the system. Also convert to Unix style path on Cygwin systems, +# else the 'gyp' library will not be found +path = UnixifyPath(sys.argv[0]) +sys.path.insert(0, os.path.join(os.path.dirname(path), 'pylib')) import gyp if __name__ == '__main__': diff --git a/gyp/pylib/gyp/common.py b/gyp/pylib/gyp/common.py index 657134a78f..35c83ea4ae 100644 --- a/gyp/pylib/gyp/common.py +++ b/gyp/pylib/gyp/common.py @@ -9,6 +9,7 @@ import re import tempfile import sys +import subprocess # A minimal memoizing decorator. It'll blow up if the args aren't immutable, @@ -337,11 +338,16 @@ def WriteOnDiff(filename): class Writer(object): """Wrapper around file which only covers the target if it differs.""" def __init__(self): + # On Cygwin remove the "dir" argument because `C:` prefixed paths are treated as relative, + # consequently ending up with current dir "/cygdrive/c/..." being prefixed to those, which was + # obviously a non-existent path, for example: "/cygdrive/c//C:\". + # See https://docs.python.org/2/library/tempfile.html#tempfile.mkstemp for more details + base_temp_dir = "" if IsCygwin() else os.path.dirname(filename) # Pick temporary file. tmp_fd, self.tmp_path = tempfile.mkstemp( suffix='.tmp', prefix=os.path.split(filename)[1] + '.gyp.', - dir=os.path.split(filename)[0]) + dir=base_temp_dir) try: self.tmp_file = os.fdopen(tmp_fd, 'wb') except Exception: @@ -611,3 +617,15 @@ def CrossCompileRequested(): os.environ.get('AR_target') or os.environ.get('CC_target') or os.environ.get('CXX_target')) + +def IsCygwin(): + try: + out = subprocess.Popen("uname", + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + stdout,stderr = out.communicate() + return "CYGWIN" in str(stdout) + except Exception: + return False + + diff --git a/gyp/pylib/gyp/generator/msvs.py b/gyp/pylib/gyp/generator/msvs.py index 5e5b2ee52a..2028b9eacb 100644 --- a/gyp/pylib/gyp/generator/msvs.py +++ b/gyp/pylib/gyp/generator/msvs.py @@ -165,7 +165,7 @@ def _FixPath(path): Returns: The path with all slashes made into backslashes. """ - if fixpath_prefix and path and not os.path.isabs(path) and not path[0] == '$': + if fixpath_prefix and path and not os.path.isabs(path) and not path[0] == '$' and not _IsWindowsAbsPath(path): path = os.path.join(fixpath_prefix, path) path = path.replace('/', '\\') path = _NormalizedSource(path) @@ -174,6 +174,16 @@ def _FixPath(path): return path +def _IsWindowsAbsPath(path): + """ + On Cygwin systems Python needs a little help determining if a path is an absolute Windows path or not, so that + it does not treat those as relative, which results in bad paths like: + + '..\C:\\some_source_code_file.cc' + """ + return path.startswith('c:') or path.startswith('C:') + + def _FixPaths(paths): """Fix each of the paths of the list.""" return [_FixPath(i) for i in paths] diff --git a/lib/configure.js b/lib/configure.js index 267e7587f5..20b955cabc 100644 --- a/lib/configure.js +++ b/lib/configure.js @@ -295,6 +295,7 @@ function configure (gyp, argv, callback) { outputDir = buildDir } var nodeGypDir = path.resolve(__dirname, '..') + var nodeLibFile = path.join(nodeDir, !gyp.opts.nodedir ? '<(target_arch)' : '$(Configuration)', release.name + '.lib') @@ -308,6 +309,12 @@ function configure (gyp, argv, callback) { argv.push('-Dnode_exp_file=' + nodeExpFile) } argv.push('-Dnode_gyp_dir=' + nodeGypDir) + + // Do this to keep Cygwin environments happy, else the unescaped '\' gets eaten up, + // resulting in bad paths, Ex c:parentFolderfolderanotherFolder instead of c:\parentFolder\folder\anotherFolder + if (win) { + nodeLibFile = nodeLibFile.replace(/\\/g, '\\\\') + } argv.push('-Dnode_lib_file=' + nodeLibFile) argv.push('-Dmodule_root_dir=' + process.cwd()) argv.push('-Dnode_engine=' +