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

[Xamarin.Android.Build.Tasks] Response file support for AOT #2062

Merged
merged 1 commit into from
Sep 4, 2019

Commits on Sep 4, 2019

  1. [Xamarin.Android.Build.Tasks] Response file support for AOT

    Our AOT system has issues when a user uses
    non ASCII characters and spaces on Windows.
    We use `GetShortPath` to get the old DOS
    8.3 short names of paths to get around
    paths having spaces and unicode characters.
    
    However on the latest versions of windows
    `GetShortPath` seems to be supported only
    on the main system drive (C:). Many of our
    developers and CI will be building on other
    drives. So we really need to support paths
    with spaces and unicode.
    
    This commit reworks the way we provide the
    `--aot` pargument to the cross compilers so
    that it actually works in those senarios.
    
    The first thing was how the arguments were
    parsed. `mono` uses the build in system
    command line parser `GetCommandLineW` to parse
    arguments. Given the following `--aot` argument
    
    	--aot=outfile="c:\Sandbox\repo\bin\BuildAotApplicationAndBundle AndÜmläüts_x86_True_True\obj\Release\libaot-Mono.Android.dll.so",asmwriter,mtriple=i686-linux-android,tool-prefix=C:\ProgramData\Microsoft\AndroidNDK\android-ndk-r13b\toolchains\x86-4.9\prebuilt\windows\bin\i686-linux-android-,ld-flags=C:\ProgramData\Microsoft\AndroidNDK\android-ndk-r13b\toolchains\x86-4.9\prebuilt\windows\lib\gcc\i686-linux-android\4.9.x\libgcc.a;C:\ProgramData\Microsoft\AndroidNDK\android-ndk-r13b\platforms\android-16\arch-x86\usr\lib\libc.so;C:\ProgramData\Microsoft\AndroidNDK\android-ndk-r13b\platforms\android-16\arch-x86\usr\lib\libm.so,temp-path="c:\Sandbox\repo\BuildAotApplicationAndBundle AndÜmläüts_x86_True_True\obj\Release\temp"
    
    This ends up as the following arguments
    
    	--aot=outfile="c:\Sandbox\repo\bin\BuildAotApplicationAndBundle
    	AndÜmläüts_x86_True_True\obj\Release\libaot-Mono.Android.dll.so"
    	,asmwriter,mtriple=i686-linux-android,tool-prefix=C:\ProgramData\Microsoft\AndroidNDK\android-ndk-r13b\toolchains\x86-4.9\prebuilt\windows\bin\i686-linux-android-,ld-flags=C:\ProgramData\Microsoft\AndroidNDK\android-ndk-r13b\toolchains\x86-4.9\prebuilt\windows\lib\gcc\i686-linux-android\4.9.x\libgcc.a;C:\ProgramData\Microsoft\AndroidNDK\android-ndk-r13b\platforms\android-16\arch-x86\usr\lib\libc.so;C:\ProgramData\Microsoft\AndroidNDK\android-ndk-r13b\platforms\android-16\arch-x86\usr\lib\libm.so,temp-path="c:\Sandbox\repo\BuildAotApplicationAndBundle
    	AndÜmläüts_x86_True_True\obj\Release\temp"
    
    As you can see the parameters have been split
    where there is a space. The solution to this is
    to double quote the ENTIRE argument and remove
    any quotes within the parameter list like so
    
    	"--aot=outfile=c:\Sandbox\repo\bin\BuildAotApplicationAndBundle AndÜmläüts_x86_True_True\obj\Release\libaot-Mono.Android.dll.so,asmwriter,mtriple=i686-linux-android,tool-prefix=C:\ProgramData\Microsoft\AndroidNDK\android-ndk-r13b\toolchains\x86-4.9\prebuilt\windows\bin\i686-linux-android-,ld-flags=C:\ProgramData\Microsoft\AndroidNDK\android-ndk-r13b\toolchains\x86-4.9\prebuilt\windows\lib\gcc\i686-linux-android\4.9.x\libgcc.a;C:\ProgramData\Microsoft\AndroidNDK\android-ndk-r13b\platforms\android-16\arch-x86\usr\lib\libc.so;C:\ProgramData\Microsoft\AndroidNDK\android-ndk-r13b\platforms\android-16\arch-x86\usr\lib\libm.so,temp-path=c:\Sandbox\repo\BuildAotApplicationAndBundle AndÜmläüts_x86_True_True\obj\Release\temp"
    
    This allows windows (and mac) to parse the paremters
    correctly as one block.
    
    There is another issue however. With the new argument
    line above if the `temp=` path has a space in it `mono`
    still has issues with that path. The good news is that we
    can use some domain knowledge to reduce not only the
    paths which need spaces but also the overall length of
    the argument.
    
    Because we know the cross compiler will be executed within
    `WorkingDirectory` we can shorten any path which is within
    that directory structure. `WorkingDirectory` is set to the
    directory of the projects csproj file. So the following
    
    	E:\Some Project\My Project\obj\Release\aot\System.dll\
    
    will become
    
    	obj\Release\aot\System.dll\
    
    This will fix the issue with the `temp=` argument. So we end up
    with something like this
    
    	"--aot=outfile=obj\Release\libaot-Mono.Android.dll.so,asmwriter,mtriple=i686-linux-android,tool-prefix=C:\ProgramData\Microsoft\AndroidNDK\android-ndk-r13b\toolchains\x86-4.9\prebuilt\windows\bin\i686-linux-android-,ld-flags=C:\ProgramData\Microsoft\AndroidNDK\android-ndk-r13b\toolchains\x86-4.9\prebuilt\windows\lib\gcc\i686-linux-android\4.9.x\libgcc.a;C:\ProgramData\Microsoft\AndroidNDK\android-ndk-r13b\platforms\android-16\arch-x86\usr\lib\libc.so;C:\ProgramData\Microsoft\AndroidNDK\android-ndk-r13b\platforms\android-16\arch-x86\usr\lib\libm.so,temp-path=obj\Release\temp"
    
    However we might still start hitting the command line length limit
    on windows. This is currently 246 characters. So depending on where
    a user creates the project we might end up with a long command line.
    
    To work around this issue we can make use of the new `--response=`
    argument in `mono`. Instead of passing all the arguments to the
    cross compiler we can instead write them to a file and pass the
    path to that file as the `--response=` argument. This will reduce
    our command line length to be within an acceptable range unless
    the user creates a project in a very very deep directory structure.
    So the final call will be something like
    
    	cross-arm --response="c:\Sandbox\repo\bin\BuildAotApplicationAndBundle AndÜmläüts_x86_True_True\obj\Release\Mono.Android.dll\response.txt"
    
    Which works perfectly.
    
    This commit also updates the `BuildAotApplication` and
    `BuildAotApplicationAndBundle` unit tests to use paths with
    both spaces and non-ascii characters to make sure we support
    both of those senarios.
    dellis1972 committed Sep 4, 2019
    Configuration menu
    Copy the full SHA
    ce5a293 View commit details
    Browse the repository at this point in the history