-
Notifications
You must be signed in to change notification settings - Fork 564
[build-tools] Update library outputs to not include <abi> suffix #47
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
Conversation
5025acd to
917211d
Compare
| <ConfigureFlags>--host=armv5-linux-androideabi $(_TargetConfigureFlags)</ConfigureFlags> | ||
| <OutputRuntime>libmonosgen-2.0.so</OutputRuntime> | ||
| <OutputRuntime>libmonosgen-2.0</OutputRuntime> | ||
| <OutputRuntimeExtension>so</OutputRuntimeExtension> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we're going to split out the extension like this, we should alter %(OutputProfiler) and %(OutputMonoPosixHelper) to follow suit.
I'd also be inclined to change the naming convention, but I'm not aware of a short name for "name without extension", and %(OutputRuntimeWithoutExtension) looks ugly. %(OutputRuntimeBasename) also doesn't quite fit the bill, as normally "basename" includes the file extension.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looking at the well known msbuild properties [1]
%(Filename) = Filename without the extension
%(Extension) = extension :)
so following that
%(OutputRuntimeFilename)
%(OutputRuntimeExtension)
seems to be reasonable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, I like that. However, we don't need %(OutputRuntimeExtension); the extension will be the same for all those %(Output*) properties. Thus, %(OutputRuntimeFilename) and %(NativeLibraryExtension)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup already on it :)
917211d to
5c8217f
Compare
|
@jonpryor this has been updated as per our discussion |
| /> | ||
| </Target> | ||
| <ItemGroup> | ||
| <_InstallRuntimesInputs Include="@(_MonoRuntime->'$(IntermediateOutputPath)\%(Identity)\mono\mini\.libs\%(OutputRuntimeFilename).%(NativeLibraryExtension)')" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't @(_InstallRuntimeInputs) be identical to @(_BuildRuntimeOutputs)? Meaning you could just use @(_BuildRuntimeOutputs)?
5c8217f to
8fe53f6
Compare
| SourceFiles="@(_MonoRuntime->'$(IntermediateOutputPath)\%(Identity)\support\.libs\%(OutputMonoPosixHelper)')" | ||
| DestinationFiles="@(_MonoRuntime->'$(OutputPath)\lib\xbuild\Xamarin\Android\lib\%(Identity)\%(OutputMonoPosixHelper)')" | ||
| Conditional=" '$(Configuration)' != 'Debug' " | ||
| Command="%(_MonoRuntime.Strip) "$(OutputPath)\lib\xbuild\Xamarin\Android\lib\%(Identity)\%(OutputRuntimeFilename).%(NativeLibraryExtension)"" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
%(_MonoRuntime.Strip) should be quoted, in case the path contains spaces:
""%(_MonoRuntime.Strip)" ..."
c20043d to
abf645b
Compare
The native libraries are output into an <abi> specific folder in lib/xbuild/Xamarin/Android/libs As a result we really do not need to have an <abi> suffix as part of the native library name. In additon the libmonosgen library was having -unstripped appended to the end of the library so it was libmonosgen-2.0.so-unstripped this looks a bit weird since it replaces the normal .so extension. This has been removed.
Commit b6431ac broke the build of `src/java-interop`: Using task Exec from Microsoft.Build.Tasks.Exec, Microsoft.Build.Tasks.v4.0, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a Executing: gcc -g -shared -std=c99 -o "obj/libjava-interop-m32.dylib" -m32 -DDEBUG -DJI_DLL_EXPORT -DMONODEVELOP -DMONO_DLL_EXPORT -fvisibility=hidden -Wl,-undefined -Wl,suppress -Wl,-flat_namespace -L /Library/Frameworks/Mono.framework/Libraries -lmonosgen-2.0 jni.c java-interop.c java-interop-mono.c java-interop-gc-bridge-mono.c Environment variables being passed to the tool: jni.c:7:10: fatal error: 'jni.h' file not found #include <jni.h> ^ 1 error generated. In file included from java-interop-mono.c:1: ./java-interop-mono.h:30:11: fatal error: 'mono/metadata/assembly.h' file not found #include <mono/metadata/assembly.h> ^ 1 error generated. The problem? There's no `gcc -Ipath` option, so the compiler doesn't know where to find `<jni.h>` or `<mono/metadata/assembly.h>`. The `-I` values are derived from the `@(JdkIncludePath) and `@(MonoIncludePath)` MSBuild item groups: <!-- via bin/BuildDebug/JdkInfo.props --> <PropertyGroup> <JdkJvmPath Condition=" '$(JdkJvmPath)' == '' ">/Library/Java/JavaVirtualMachines/jdk1.8.0_77.jdk/Contents/Home/jre/lib/server/libjvm.dylib</JdkJvmPath> </PropertyGroup> <ItemGroup> <JdkIncludePath Condition=" '$(JdkJvmPath)' == '' " Include="/Library/Java/JavaVirtualMachines/jdk1.8.0_77.jdk/Contents/Home/include" /> <JdkIncludePath Condition=" '$(JdkJvmPath)' == '' " Include="/Library/Java/JavaVirtualMachines/jdk1.8.0_77.jdk/Contents/Home/include/darwin" /> </ItemGroup> <!-- via bin/BuildDebug/MonoInfo.props --> <PropertyGroup> <MonoFrameworkPath Condition=" '$(MonoFrameworkPath)' == '' ">/Library/Frameworks/Mono.framework/Libraries/libmonosgen-2.0.1.dylib</MonoFrameworkPath> </PropertyGroup> <ItemGroup> <MonoIncludePath Condition=" '$(MonoFrameworkPath)' == '' " Include="/Library/Frameworks/Mono.framework/Headers/mono-2.0" /> </ItemGroup> The *intent* to commit b6431ac is that if e.g. `$(JdkJvmPath)` is overridden, then we shouldn't automatically generate the `@(JdkIncludePath)` items, because they'll be for the "wrong" JDK. If `$(JdkJvmPath)` is overridden, then `@(JdkIncludePath)` should be as well. (Ditto `$(MonoFrameworkPath)` and `@(MonoIncludePath)`.) The problem is [evaluation time][0]: > During the evaluation phase of a build, imported files are > incorporated into the build in the order in which they appear. > Properties and items are defined in three passes in the following > order: > > * Properties are defined and modified in the order in which they appear. > * Item definitions are defined and modified in the order in which they appear. > * Items are defined and modified in the order in which they appear. Properties are *always* evaluated before items, meaning when it came time to evaluate `//JdkIncludePath/@Condition`, `$(JdkJvmPath)` was *always* defined, and thus `@(JdkIncludePath)` was *always* empty. Which is why there are no instances of `gcc -I` in the `gcc` compile line, and why those headers can't be found. The fix is to instead use the `<Choose/>` element to ensure that the default items are specified when the "controlling" property isn't overridden: <!-- via bin/BuildDebug/JdkInfo.props --> <Choose> <When Condition=" '$(JdkJvmPath)' == '' "> <PropertyGroup> <JdkJvmPath>/Library/Java/JavaVirtualMachines/jdk1.8.0_77.jdk/Contents/Home/jre/lib/server/libjvm.dylib</JdkJvmPath> </PropertyGroup> <ItemGroup> <JdkIncludePath Include="/Library/Java/JavaVirtualMachines/jdk1.8.0_77.jdk/Contents/Home/include" /> <JdkIncludePath Include="/Library/Java/JavaVirtualMachines/jdk1.8.0_77.jdk/Contents/Home/include/darwin" /> </ItemGroup> </When> </Choose> <!-- via bin/BuildDebug/MonoInfo.props --> <Choose> <When Condition=" '$(MonoFrameworkPath)' == '' "> <PropertyGroup> <MonoFrameworkPath>/Library/Frameworks/Mono.framework/Libraries/libmonosgen-2.0.1.dylib</MonoFrameworkPath> <MonoLibs >-L /Library/Frameworks/Mono.framework/Libraries -lmonosgen-2.0</MonoLibs> </PropertyGroup> <ItemGroup> <MonoIncludePath Include="/Library/Frameworks/Mono.framework/Headers/mono-2.0" /> </ItemGroup> </When> </Choose> This allows `@(JdkIncludePath)` and `@(MonoIncludePath)` to have values when `$(JdkJvmPath)` and `$(MonoFrameworkPath)` aren't overridden, which in turn allows `gcc -I` to be used, and allows `src/java-interop` to build. [0]: https://msdn.microsoft.com/en-us/library/dd997067.aspx#Anchor_2
In commit 75023bd we noticed an issue the value of `MonoPackageManager_Resouces.ApiPackageName` was `""` even after it was replaced at built time with a new `.class` file which contained an actual value. The fix in that PR was to make the temp file in java-runtime have a value of `null` rather than `""`. This made thing work but we didn't know WHY. After some more investigation it turns out that the value was being inlined by the java compiler. public static java.lang.String getApiPackageName(); descriptor: ()Ljava/lang/String; Code: 0: ldc #48 // String 2: areturn The code above is pointing to a string in the Constants table. What we were expecting was that the statick method would be called in the file generated by the build system. Making the temp file have a `null` rather than `""` resulted in the following code public static java.lang.String getApiPackageName(); descriptor: ()Ljava/lang/String; Code: 0: getstatic #47 // Field mono/MonoPackageManager_Resources.ApiPackageName:Ljava/lang/String; 3: areturn This is why changing to `null` worked. It prevented the compiler from inlining the value. This commit removes the `final` keyword from the `MonoPackageManager_Resources` class fields to make sure that they never get inlined.
In commit 75023bd we noticed that the value of `MonoPackageManager_Resouces.ApiPackageName` was `""` even after it was replaced at build time with a new `.class` file which contained an actual value: > We don't yet fully understand this failure scenario, but setting > `ApiPackageName` to null allows things to work. The fix in 75023bd was to make the default value within `MonoPackageManager_Resources.java` have a value of `null` rather than `""`. This allowed things to work but we didn't know WHY. After some more investigation it turns out that when `MonoPackageManager_Resouces.ApiPackageName` was `""`, the empty string value was being *inlined* by `javac` when generating `MonoPackageManager.getApiPackageName()`: public static java.lang.String getApiPackageName(); descriptor: ()Ljava/lang/String; Code: 0: ldc #48 // String 2: areturn `ldc` loads a constant from the Constants table, in this case `""`. When `null` was used, `javac` instead emitted a field access: public static java.lang.String getApiPackageName(); descriptor: ()Ljava/lang/String; Code: 0: getstatic #47 // Field mono/MonoPackageManager_Resources.ApiPackageName:Ljava/lang/String; 3: areturn (Why `javac` didn't inline `null` is beyond @jonpryor.) This is why changing to `null` worked: it prevented the compiler from inlining the value. However, while that "worked," it is not at all obvious, and short of reading the Java Language Spec to determine if `null` is even a value which *can* be inlined, the current approach of using a `final` value seems potentially *dangerous*, as behavior may be subject to the compiler used and subject to change. To fix this, remove the `final` keyword from the `MonoPackageManager_Resources` fields prevent inlining.
The native libraries are output into an specific folder in
As a result we really do not need to have an suffix as part
of the native library name. In additon the libmonosgen library was
having -unstripped appended to the end of the library so it was
this looks a bit weird since it replaces the normal .so extension.
This has been removed.