Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix external_project failing due to the drive letter in the path on Windows #13916

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion data/test.schema.json
Original file line number Diff line number Diff line change
@@ -43,7 +43,9 @@
"msvc",
"gcc",
"cygwin",
"!cygwin"
"!cygwin",
"windows",
"!windows"
]
},
"version": {
2 changes: 2 additions & 0 deletions docs/markdown/Contributing.md
Original file line number Diff line number Diff line change
@@ -320,6 +320,8 @@ considered if the platform matches. The following values for
| `gcc` | Not `msvc` |
| `cygwin` | Matches when the platform is cygwin |
| `!cygwin` | Not `cygwin` |
| `windows` | Matches when the platform is windows or cygwin |
| `!windows` | Not `windows` |

#### matrix

27 changes: 20 additions & 7 deletions mesonbuild/modules/external_project.py
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@
from pathlib import Path
import os
import shlex
import shutil
import subprocess
import typing as T

@@ -19,7 +20,7 @@
from ..interpreter.type_checking import ENV_KW, DEPENDS_KW
from ..interpreterbase.decorators import ContainerTypeInfo, KwargInfo, typed_kwargs, typed_pos_args
from ..mesonlib import (EnvironmentException, MesonException, Popen_safe, MachineChoice,
get_variable_regex, do_replacement, join_args, relpath)
get_variable_regex, do_replacement, join_args)
from ..options import OptionKey

if T.TYPE_CHECKING:
@@ -89,19 +90,29 @@ def __init__(self,
self.includedir = Path(_i)
self.name = self.src_dir.name

# On Windows if the prefix is "c:/foo" and DESTDIR is "c:/bar", `make`
# will install files into "c:/bar/c:/foo" which is an invalid path.
# Work around that issue by removing the drive from prefix.
if self.prefix.drive:
self.prefix = Path(relpath(self.prefix, self.prefix.drive))
self.prefix = self._cygpath_convert(self.prefix)

# self.prefix is an absolute path, so we cannot append it to another path.
self.rel_prefix = Path(relpath(self.prefix, self.prefix.root))
# On Windows (where cygpath is not applied),
# if the prefix is "c:/foo" and DESTDIR is "c:/bar",
# `make` will install files into "c:/bar/c:/foo" which is an invalid path.
# This also removes the drive letter from the prefix to workaround the issue.
self.rel_prefix = self.prefix.relative_to(self.prefix.anchor)

self._configure(state)

self.targets = self._create_targets(extra_depends)

def _cygpath_convert(self, winpath: Path) -> Path:
# On Cygwin, MSYS2 and GitBash, the configure command and the prefix
# should be converted to unix style path like "/c/foo" by cygpath command,
# because the colon in the drive letter breaks many configure scripts.
# Do nothing on other environment where cygpath is not available.
if winpath.drive and shutil.which('cygpath'):
_p, o, _e = Popen_safe(['cygpath', '-u', winpath.as_posix()])
return Path(o.strip('\n'))
return winpath

def _configure(self, state: 'ModuleState') -> None:
if self.configure_command == 'waf':
FeatureNew('Waf external project', '0.60.0').use(self.subproject, state.current_node)
@@ -116,6 +127,8 @@ def _configure(self, state: 'ModuleState') -> None:
configure_path = Path(self.src_dir, self.configure_command)
configure_prog = state.find_program(configure_path.as_posix())
configure_cmd = configure_prog.get_command()
if len(configure_cmd) >= 2 and configure_cmd[-1] == configure_path.as_posix():
configure_cmd = configure_cmd[:-1] + [self._cygpath_convert(configure_path).as_posix()]
workdir = self.build_dir
self.make = state.find_program('make').get_command()

2 changes: 2 additions & 0 deletions run_project_tests.py
Original file line number Diff line number Diff line change
@@ -158,6 +158,8 @@ def get_path(self, compiler: str, env: environment.Environment) -> T.Optional[Pa
'gcc': canonical_compiler != 'msvc',
'cygwin': env.machines.host.is_cygwin(),
'!cygwin': not env.machines.host.is_cygwin(),
'windows': env.machines.host.is_windows() or env.machines.host.is_cygwin(),
'!windows': not (env.machines.host.is_windows() or env.machines.host.is_cygwin()),
}.get(self.platform or '', True)
if not matches:
return None
17 changes: 17 additions & 0 deletions test cases/common/230 external project/libfoo/configure
Original file line number Diff line number Diff line change
@@ -2,6 +2,23 @@

srcdir=$(dirname "$0")

# some configure scripts seem to iterate over srcdir and other paths
# with for-loop using path_separator (most cases colon.)
PATH_SEPARATOR=:
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
PATH_SEPARATOR=';'
}
IFS=$PATH_SEPARATOR
for i in $srcdir
do
if [ "$i" != "$srcdir" ]
then
echo "failed to extract $srcdir using path separator $PATH_SEPARATOR"
exit 1
fi
done

for i in "$@"
do
case $i in
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@ p = mod.add_project('configure',
'--libext=' + libext,
],
depends: somelib,
verbose: true,
)

libfoo_dep = declare_dependency(link_with : somelib,
4 changes: 0 additions & 4 deletions test cases/common/230 external project/meson.build
Original file line number Diff line number Diff line change
@@ -8,10 +8,6 @@ if not find_program('make', required : false).found()
error('MESON_SKIP_TEST: make not found')
endif

if host_machine.system() == 'windows'
error('MESON_SKIP_TEST: The fake configure script is too dumb to work on Windows')
endif

if meson.is_cross_build()
# CI uses PKG_CONFIG_SYSROOT_DIR which breaks -uninstalled.pc usage.
error('MESON_SKIP_TEST: Cross build support is too limited for this test')
4 changes: 2 additions & 2 deletions test cases/common/230 external project/test.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"installed": [
{ "type": "shared_lib", "file": "usr/lib/foo", "platform": "!cygwin" },
{ "type": "file", "file": "usr/lib/libfoo.dll", "platform": "cygwin" },
{ "type": "shared_lib", "file": "usr/lib/foo", "platform": "!windows" },
{ "type": "file", "file": "usr/lib/libfoo.dll", "platform": "windows" },
{ "type": "file", "file": "usr/include/libfoo.h" },
{ "type": "file", "file": "usr/lib/pkgconfig/somelib.pc" }
]