libtool-patches
[Top][All Lists]
Advanced

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

Re: [PATCH] [mingw] Add cross-compile support to cwrapper


From: Roumen Petrov
Subject: Re: [PATCH] [mingw] Add cross-compile support to cwrapper
Date: Mon, 19 May 2008 00:03:29 +0300
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.13) Gecko/20080329 SeaMonkey/1.1.9

Charles Wilson wrote:
Roumen Petrov wrote:
Charles Wilson wrote:
[mingw] Add cross-compile support to cwrapper

May be the patch can be more simple. In a previous post I confirm that for the wine emulator is enough items in path list, where every item is absolute path from build system, to be separated by DOS path-separator only.

Right, and thank you for that. What wasn't clear, however, was whether this automatic path translation was a peculiarity of your wine setup (e.g. "identity mounts" or something) or is a documented feature of wine.

Automatic path translation work for me. I may ask wine-developers to
confirm.


This is enough and at run-time wine(wineloader?) will translate internally from "build system absolute path" to the "path from emulated environment".

So it only works for absolute paths, but is applied to all environment variables (like PATH)?

winepath will convert relative paths, AFAICT, although it converts them to absolute first, and canonicalizes if you have permissions to chdir to the target:

No it work for relative paths too, but with limitation:
path can be relative to the executable location and current work
directory is equal to executable path it works.
I attach my test case (bootstrap.sh) executabel + two dependent shared
libraries from different directories.



The wine is setup with $WINEPREFIX/dosdevices/m: linked <MINGWCROSS>>
Note that <MINGWCROSS> is absolute path in build system.
Lets see output from the script:
========================================
<autotool build>
=== ./foo-t1.exe ===
in main()
in foo1(11)
in foo2(22)
in foo1(22)
(main) argv[0]      : ./foo-t1.exe
(main) program_name : foo-t1.exe
(find_executable)   : ./foo-t1.exe
(check_executable)  : M:\1\lt-HEAD-mingw-mlib-autotools\appl/./foo-t1.exe
(main) found exe (before symlink chase) at :
M:\1\lt-HEAD-mingw-mlib-autotools\appl/./foo-t1.exe
(main) found exe (after symlink chase) at :
M:\1\lt-HEAD-mingw-mlib-autotools\appl/./foo-t1.exe
(main) libtool target name: foo.exe
(lt_setenv) setting 'BIN_SH' to 'xpg4'
(lt_setenv) setting 'DUALCASE' to '1'
(lt_update_lib_path) modifying 'PATH' by prepending
'<MINGWCROSS>/1/lt-HEAD-mingw-mlib-autotools/lib2/.libs;<MINGWCROSS>/1/lt-HEAD-mingw-mlib-autotools/lib1/.libs;'
(lt_setenv) setting 'PATH' to
'<MINGWCROSS>/1/lt-HEAD-mingw-mlib-autotools/lib2/.libs;<MINGWCROSS>/1/lt-HEAD-mingw-mlib-autotools/lib1/.libs;c:\windows\system32;c:\windows;z:\opt\mingw\bin;z:\opt\mingw\gtk2\bin'
(lt_update_exe_path) modifying 'PATH' by prepending
';<MINGWCROSS>/1/lt-HEAD-mingw-mlib-autotools/lib2/.libs;<MINGWCROSS>/1/lt-HEAD-mingw-mlib-autotools/lib1/.libs;/tmp/test/pkg/lt-HEAD-mingw-mlib/lib;/tmp/test/pkg/lt-HEAD-mingw-mlib/bin;'
(lt_setenv) setting 'PATH' to
';<MINGWCROSS>/1/lt-HEAD-mingw-mlib-autotools/lib2/.libs;<MINGWCROSS>/1/lt-HEAD-mingw-mlib-autotools/lib1/.libs;/tmp/test/pkg/lt-HEAD-mingw-mlib/lib;/tmp/test/pkg/lt-HEAD-mingw-mlib/bin;<MINGWCROSS>/1/lt-HEAD-mingw-mlib-autotools/lib2/.libs;<MINGWCROSS>/1/lt-HEAD-mingw-mlib-autotools/lib1/.libs;c:\windows\system32;c:\windows;z:\opt\mingw\bin;z:\opt\mingw\gtk2\bin'
(main) lt_argv_zero : M:/1/lt-HEAD-mingw-mlib-autotools/appl/./.libs/foo.exe
(main) newargz[0]   :
M:/1/lt-HEAD-mingw-mlib-autotools/appl/./.libs/foo-t1.exe
DONE[t1]=126
=== ./foo-t2.exe ===
in main()
in foo1(11)
in foo2(22)
in foo1(22)
(main) argv[0]      : ./foo-t2.exe
(main) program_name : foo-t2.exe
(find_executable)   : ./foo-t2.exe
(check_executable)  : M:\1\lt-HEAD-mingw-mlib-autotools\appl/./foo-t2.exe
(main) found exe (before symlink chase) at :
M:\1\lt-HEAD-mingw-mlib-autotools\appl/./foo-t2.exe
(main) found exe (after symlink chase) at :
M:\1\lt-HEAD-mingw-mlib-autotools\appl/./foo-t2.exe
(main) libtool target name: foo.exe
(lt_setenv) setting 'BIN_SH' to 'xpg4'
(lt_setenv) setting 'DUALCASE' to '1'
(lt_update_lib_path) modifying 'PATH' by prepending
'<MINGWCROSS>/1/lt-HEAD-mingw-mlib-autotools/lib2/.libs;../lib1/.libs;'
(lt_setenv) setting 'PATH' to
'<MINGWCROSS>/1/lt-HEAD-mingw-mlib-autotools/lib2/.libs;../lib1/.libs;c:\windows\system32;c:\windows;z:\opt\mingw\bin;z:\opt\mingw\gtk2\bin'
(lt_update_exe_path) modifying 'PATH' by prepending
';<MINGWCROSS>/1/lt-HEAD-mingw-mlib-autotools/lib2/.libs;../lib1/.libs;/tmp/test/pkg/lt-HEAD-mingw-mlib/lib;/tmp/test/pkg/lt-HEAD-mingw-mlib/bin;'
(lt_setenv) setting 'PATH' to
';<MINGWCROSS>/1/lt-HEAD-mingw-mlib-autotools/lib2/.libs;../lib1/.libs;/tmp/test/pkg/lt-HEAD-mingw-mlib/lib;/tmp/test/pkg/lt-HEAD-mingw-mlib/bin;<MINGWCROSS>/1/lt-HEAD-mingw-mlib-autotools/lib2/.libs;../lib1/.libs;c:\windows\system32;c:\windows;z:\opt\mingw\bin;z:\opt\mingw\gtk2\bin'
(main) lt_argv_zero : M:/1/lt-HEAD-mingw-mlib-autotools/appl/./.libs/foo.exe
(main) newargz[0]   :
M:/1/lt-HEAD-mingw-mlib-autotools/appl/./.libs/foo-t2.exe
DONE[t2]=126
========================================

The libtool create C-wrapper with absolute paths.
- foo-t1.exe, where ':' is replaced with ';' : can be run from any location.
- foo-t1.exe, where path to one of libraries is relative. : work only if
is run for executable directory.

~ $ winepath -w ../<anonther user>
Z:\home\<my_user>\..\<another user>

~ $ winepath -w ../../mnt
Z:\mnt


The same is in run time.


Also the mapping can be changed after build of package (creation of cwrapper). So that translated paths (in cwrapper) may point to non existing more locations in emulated environment.

Well, this is also true of winepath:

$ winepath -w /tmp/nonexistent
Z:\tmp\nonexistent

But I'm not sure that supporting "changing the mapping after building the wrapper" is something we should support (e.g. deliberately code the wrapper to allow it, and then have to answer questions about why it does or does not work in some user's wacky wine setup, down the road.) Is there a realistic use case where this facility is important, that couldn't be solved by "okay, then rm -f wrapper.exe, make wrapper"

So if the wine developers confirm that run-time translation in not
"side-effect" we may skip winepath and the problem will disappear
and will not depend of $WINEPREFIX/dosdevice links.
In well setup environment z in link to the root of the filesystems on
build. In my test-environment m: is an additional link (to
<MINGWCROSS>) and z: is removed intentionally before tests.


Also, it's a bit odd to convert the $target_exe path (the argument of _spawnv) to $host format, but set PATH using $build format path components. Or does wine's emulation of _spawnv ALSO do automatic path translation, and we could -- if we choose -- leave ALL paths in $build format with the exception of s|/|\\|g and s|:|;|g?

I still think we don't want to do /that/ -- see caveats, below.
>
Please, let me know if you need more info (strace output, dos device mapping, etc). The test case that I use was posted to the list. In brief:
- library foo1 in ./lib1
- library libfoo2 in ./lib2
- executable foo.exe in ./appl that call functions from foo1 and foo2 libraries.

Well, you didn't actually say whether the existing patch works or not -- just that you think it could be simplified. <g>

Does the current patch work?

Not yet tested, but looks good.


The problem I have with "echo $val | sed -e 's|:|;|g'" is what if, somehow, a dos-style path is in $val?

C:\bob -> C;\bob

May we left "the build path cannot contain ':'" as limitation of libtool in case of cross-compilation environment ?


(I mean, really: s|:|;|g is bit naive. I was kinda hoping somebody would give me a better sed expression than the one I'm using in lt_sed_naive_backslashify...)

May be if ltmain.m4sh, during creation of dllsearchpath and some other variables, separate items by host system dir-separator the problem will be solved.


Anyway, to avoid C;\bob, I'd need a lot of special casing: if $val starts with a letter, followed by a ':', followed by an optional '/', then don't replace the ':', otherwise do. Also, if you see a rooted relative path (C:bar) which means 'get the drive-specific CWD for drive C:, and append \bar', then you should flag an error (because you don't know what the per-drive CWD is within the wine environment)? Or you should treat as if it is really 'C:\bar' instead, and insert the "missing" '\' (this is what cygpath does, BTW)?

libtool shouldn't need to worry about these details of one particular emulation environment. They (the wine people) gave us a path translator program, we should use it -- and let IT worry about those issues.

Sure, the existing code is a bit ugly, because of winepath's deficiency (it doesn't atomically convert pathLISTs), but I hope that eventually winepath WILL support that, and then our ugliness goes away...

P.S.:
Also winepath exit with zero(!?!?!?) even if path cannot be translated:
==============================
$ winepath -w `pwd`; echo $?
Warning: could not find DOS drive for current working directory '/...../lt-HEAD-mingw-mlib', starting in the Windows directory.

0

Well, that's just...evil. Is it possible that this is a bug in winepath that should be reported upstream? Surely exit-with-0-on-error is not the *design* behavior, is it?

I'm going to have to think hard about how to detect error status...there is a very ugly way to simultaneously redirect stdout to one var, and stderr to another, but that's just...wrong.

--
Chuck

Roumen
#! /bin/sh

#set -e
ARCH=i386
PKG=lt-HEAD-mingw-mlib

libtoolPREFIX=/usr/local/libtool/HEAD
automakePREFIX=/usr/local/automake/1.10.1
autoconfPREFIX=/usr/local/autoconf/2.61
aclocalVERSION=1.10


#===
PATH="$libtoolPREFIX/bin:$PATH"
PATH="$automakePREFIX/bin:$PATH"
PATH="$autoconfPREFIX/bin:$PATH"
. ../../mingw-env
export PATH

aclocal() {
"$automakePREFIX"/bin/aclocal \
  -I "$libtoolPREFIX"/share/aclocal \
  -I "$automakePREFIX"/share/aclocal-${aclocalVERSION} \
  -I "$mingwPREFIX"/share/aclocal \
  -I /usr/share/aclocal \
  ${1+"$@"}
}


#===
do_lib1() {
  test -d lib1 || mkdir lib1

  cat > lib1/foo.c <<EOF
#include <stdio.h>

extern void foo1(long n) {
  fprintf(stderr, "in foo1(%ld)\n", n);
}
EOF

  cat > lib1/Makefile.am <<EOF
lib_LTLIBRARIES = libfoo1.la
libfoo1_la_SOURCES = foo.c
EOF
}


do_lib2() {
  test -d lib2 || mkdir lib2

  cat > lib2/foo.c <<EOF
#include <stdio.h>
extern void foo1(long n);

extern void foo2(long n) {
  fprintf(stderr, "in foo2(%ld)\n", n);
  foo1(n);
}
EOF

  cat > lib2/Makefile.am <<EOF
lib_LTLIBRARIES = libfoo2.la
libfoo2_la_SOURCES = foo.c
libfoo2_la_LIBADD = ../lib1/libfoo1.la
EOF
}


do_appl() {
  test -d appl || mkdir appl

  cat > appl/foo.c <<EOF
#include <stdio.h>
extern void foo1(long n);
extern void foo2(long n);

int main() {
  fprintf(stderr, "in main()\n");
  foo1(11);
  foo2(22);
  return(126); /*to check exit code*/
}
EOF

  cat > appl/Makefile.am <<EOF
bin_PROGRAMS = foo
foo_SOURCES = foo.c
foo_LDADD = ../lib2/libfoo2.la
EOF
}


do_top() {
  test -d build-aux || mkdir build-aux

  cat > configure.ac <<EOF
AC_INIT([test], [0.0])
AC_PREREQ(2.60)
AC_CONFIG_AUX_DIR(build-aux)

AC_CANONICAL_HOST
AM_INIT_AUTOMAKE

AC_PROG_CC
LT_INIT([shared win32-dll])

AC_OUTPUT([
 lib1/Makefile
 lib2/Makefile
 appl/Makefile
 Makefile
])
EOF

  cat > Makefile.am <<EOF
SUBDIRS = lib1 lib2 appl
EOF
}


do_bootstrap() {
  do_lib1
  do_lib2
  do_appl
  do_top

  libtoolize --force --copy --automake
  aclocal
  automake --foreign --add-missing --copy
  autoconf
}


#===
do_bootstrap
./configure --prefix=/tmp/test/pkg/$PKG --build=${ARCH}-gnu-linux 
--host=${ARCH}-mingw32msvc
make LDFLAGS='-no-undefined -avoid-version'

(
cd appl
DEBUGWRAPPER="-DDEBUGWRAPPER"
CC=${ARCH}-mingw32msvc-gcc

awk '{ \
  if ( $0 ~ /PATH_VALUE.*=/ ) \
    gsub(":", ";"); \
  print $0; \
}' < .libs/lt-foo.c > .libs/lt-foo-t1.c

LIB1PWD=`cd ../lib1; pwd`
awk '{ \
  if ( $0 ~ /PATH_VALUE.*=/ ) \
    gsub("'$LIB1PWD'", "../lib1"); \
  print $0; \
}' < .libs/lt-foo-t1.c > .libs/lt-foo-t2.c

echo "=== ./foo-t1.exe ==="
$CC -g -O2 $DEBUGWRAPPER -o foo-t1.exe .libs/lt-foo-t1.c
wine ./foo-t1.exe
echo DONE[t1]=$?

echo "=== ./foo-t2.exe ==="
$CC -g -O2 $DEBUGWRAPPER -o foo-t2.exe .libs/lt-foo-t2.c
wine ./foo-t2.exe
echo DONE[t2]=$?
)


reply via email to

[Prev in Thread] Current Thread [Next in Thread]