How do I determine the current building platform when building a multi-targeting csproj using msbuild? - xamarin

I have a cross-platform shared class library project in my solution. In the other projects (such as xamarin.android, xamarin.ios, uwp, etc.), I add reference to the shared project.
Now when I run build on a platform specific project, the shared project will build for all platform but not only the platform which I am building.
I was wondering if there is any variable I can use for determine the current building platform to avoid a complete build for the shared platfom?
Like:
<TargetFrameworks Condition=" '$(<THE_WONDERFUL_PLATFORM_VARIABLE>)' == 'android' ">MonoAndroidxx</TargetFrameworks>
<TargetFrameworks Condition=" '$(<THE_WONDERFUL_PLATFORM_VARIABLE>)' == 'ios' ">Xamarin.iOSxx</TargetFrameworks>
<TargetFrameworks Condition=" '$(<THE_WONDERFUL_PLATFORM_VARIABLE>)' == 'uwp' ">uapxx.x.xxxx</TargetFrameworks>
Edit:
My project structure is:
My expected:
Actual:

Related

Azue Devops multitarget build order

I have complex Xamarin solution with android, ios and nestandard core project (defined via Microsoft.NET.Sdk) and few other csprojs with some logic (some are defined via Microsoft.NET.Sdk as netstandard2.0. others defined via MSBuild.Sdk.Extras for multitargeting the netstandard2.0, xamarin.ios10, monoandroid10.0 and have some platform specific code)
Local build on my macos with latest libraries is ok (both netcore 3 and 5, latest xamarin. tried on Rider and VS for mac).
ADO build succeed on windows-2019 agent using msbuild (just regular CI with codechecks etc)
ADO build on macos-10.15 agent (different jobs for ios and android packaging, using XamarinIos/XamarinAndroid tasks) fails with kind of strange behaviour:
i see a lot of namespace errors in droid/ios projects for platform-specific libraries from my solution.
i've made some investigations and found out that msbuild runs platform specific builds of csprojs first, copies the outputs, then runs the netstandard build for the same csprojs and replace files in output with netstandard versions. which, obviously, didn't have any line of platform specific code.
so, the question is wtf? how am i suppose to fix this?
what i tried:
replace Xamarin tasks with msbuild calls
change Xamarin SDK version to 16_12_3 and 16_12_0 (current is 16_12_2)
change .net version to 5 (current is 3.1.x) both ways - via global.json and installing v5 using the UseDotNet#2 task
core project was converted to multitarget
remove everything from sln and add every project from the scratch
also i thought that msbuild, maybe, trying to make a nupkg from my libraries so i tried this in build props:
<PropertyGroup>
<IsPackable>false</IsPackable>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
</PropertyGroup>
also i have this
<PropertyGroup Label="Multiplatform" Condition=" '$(TargetsToBuild)' != 'All' ">
<TargetFrameworks Condition=" '$(TargetsToBuild)' == 'Android' ">monoandroid10.0</TargetFrameworks>
<TargetFrameworks Condition=" '$(TargetsToBuild)' == 'iOS' ">xamarin.ios10</TargetFrameworks>
</PropertyGroup>
and multitarget projects has this
<PropertyGroup Label="Multiplatform">
<TargetFrameworks>netstandard2.0;xamarin.ios10;monoandroid10.0</TargetFrameworks>
</PropertyGroup>
of course i've tried to remove the tags above and build without them. no luck :(
So the answer is:
you should add csproj references to other projects in right order :/ order is matters for msbild

How to build a Xamarin.Android project without managed executables?

I'm tinkering with Xamarin.Forms on Visual Studio Community for Mac version 7.3.2
What I'm trying to accomplish is to convert all managed code to native executables using these options in MyApp.Droid.csproj:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<EmbedAssembliesIntoApk>false</EmbedAssembliesIntoApk>
<AotAssemblies>true</AotAssemblies>
<EnableLLVM>true</EnableLLVM>
</PropertyGroup>
EmbedAssembliesIntoApk does embed the assemblies into the apk so I've set it to false, because those are precisely what I want to get rid of.
I've also set AotAssemblies and EnableLLVM to true so the managed code is AOT compiled and converted to native code.
Those options build a signed apk with the lib/ folder containing the files below and no assemblies folder, which is what I want.
lib/
armeabi-v7a/
libgdbserver.so
libmono-profiler-log.so
libmonodroid.so
libmonosgen-2.0.so
The problem is that if I clear the application data on the device and try to run the app again it won't start giving me some error saying 'no assemblies found' or 'conflicts between different versions of the same assembly'
Is it possible to build and ship a Xamarin.Forms application for Android without any managed assemblies, but only native executables?
Update:
I tried Xamarin Studio and it adds the option BundleAssemblies, so the project setting are as follows but Xamarin fails build the target:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AndroidManagedSymbols>true</AndroidManagedSymbols>
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
<AndroidLinkMode>Full</AndroidLinkMode>
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
<AotAssemblies>true</AotAssemblies>
<EnableLLVM>true</EnableLLVM>
<BundleAssemblies>true</BundleAssemblies>
</PropertyGroup>
With those option on Visual Studio I get this executables:
lib/
armeabi-v7a/
libmonodroid_bundle_app.so
libmonodroid.so
libmonosgen-2.0.so
plus a bunch of files something.dll.so

How to build x86 and ARM in a single apk under Xamarin?

In my setup, I have a simple Xamarin app MyApp under Visual Studio 2015. The wizard automatically generates various sub-projects such as MyApp.Droid, MyApp.iOS, etc. I also have a C++ Android Shared Dynamic Library project MyShared in the solution and MyApp.Droid has a reference to MySharedproject. Here is the relevant information from MyApp.Droid.csproj file:
<ItemGroup>
<ProjectReference Include="..\..\MyShared\MyShared.vcxproj">
<Project>{4301be08-ecf3-4c36-a487-473858bc5506}</Project>
<Name>MyShared</Name>
<TargetPlatformIdentifier>Android</TargetPlatformIdentifier>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="..\MyApp\MyApp.csproj">
<Project>{321FA0D9-3F50-4AC3-8F86-4E97DCA3FA86}</Project>
<Name>MyApp</Name>
</ProjectReference>
</ItemGroup>
Project MyApp.Droid also has armeabi-v7a and x86 platforms selected under Properties-->Android Options-->Advanced settings.
When I build the solution and export the apk file, here is what I see under lib/ directory:
lib/x86/libMyShared.so
lib/x86/libmonodroid.so
lib/x86/libmonosgen-2.0.so
lib/armeabi-v7a/libmonodroid.so
lib/armeabi-v7a/libmonosgen-2.0.so
As you can see, libMyShared.so is missing for armeabi-v7a architecture.
How do I configure the project such that libMyShared.so is built and pulled in for both the architectures? Regards.

Using MSBUILD when specified configuration is not provided

I have a solution with multiple projects. I am trying to use MSBUILD to automate the deployment. I have following configuration values for building
1. Debug
2. Release
3. Dev
For Some projects, I am using Release mode for DEV configuration. But while using DEV as configuration in MSBUILD command, it is throwing exception saying DEV configuration was not found.
Is there any way we can tell MSBUILD to use Release mode if DEV is not available for a project when DEV is used as configuration in MSBUILD?
Thanks
Ashwani
In your (presumably C#) project file, there is typically a line that looks like this:
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
For the projects that don't have a "Dev" configuration, you can get the behavior you want by adding another line, right before that one...
<Configuration Condition=" '$(Configuration)' == 'Dev' ">Release</Configuration>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
This way, when you build with "Dev" specified, these projects will build their Release configuration instead, which mimics the behavior of the solution's configuration manager (which I tend to think of as an abomination of a feature) directly in the project file itself, which is the right place to do it.
Another approach is to use the AdditionalProperties metadata on the item array you would be passing to the MSBuild task to get your projects built. You can specify--for the projects of interest--the following...
<SolutionItem Include="./PathTo/SomeProject.csproj">
<AdditionalProperties Condition="'$(Configuration)' == 'Dev'"
>Configuration=Release</AdditionalProperties>
</SolutionItem>
(Excerpted from the book "MSBuild Trickery" trick #80)
I don't think it can be done with a command argument to MSBuild.
What you could do is use the Configuration Manager for Visual Studio and for the solution configuration 'Dev' point the projects which don't have the 'Dev' configuration to Release.
Then you do a solution build for Dev configuration and some projects will build in release.

How to target both Win32 and x64 platforms with ONLY one set of solution/project files?

I'm trying to migrate a multiple-project from VC++2005 to VC++2010, and I also need to port this application from Win32 to x64 platform.
I know that a project file could contain settings for both platforms, but it requires that I have to manully change the platfrom setting for each project say if I want to build for x64.
What I want to do is to have ONLY one set of solution/project files that could target both of these platforms, and with some kind of simple switch I can choose what platform I am building now.
Is there such a way? Or do I have to maintain two sets of solution/projects files, one for each platform, so that if I want to build for x64, I can only open the solution file for x64, and if I want to build for Win32, I have to open the solution file for Win32?
You can use the "Configuration Manager" in Visual Studio 2010 to make multiple configurations for your solution and project files.
In the menu bar of VS 2010, go to "Build" --> "Configuration Manager..."
Let's say you've the platform property which duplicates in each project file:
<Platform>x86</Platform>
You can extract this property from ALL project file in a single CommonProperties.properties file:
<?xml version="1.0" encoding="utf-8" ?>
<Project
ToolsVersion="4.0"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
DefaultTargets="Default">
<PropertyGroup>
<Platform>x86</Platform>
</PropertyGroup>
</Project>
And then just import it in ALL project files:
<Import Project="CommonProperties.properties" />
EDIT: Multiple platform support
<Platform Condition="'$(Platform)' == 'Win32'">x86</Platform>
<Platform Condition="'$(Platform)' == 'x64'">x64</Platform>
Useful links:
Property Element
MSBuild Conditional Constructs

Resources