diff --git a/.vscode/launch.json b/.vscode/launch.json index 777abde3cf6..8917bb93a8a 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -44,6 +44,12 @@ "port": 10000, "preLaunchTask": "run-sample-under-dotnet", }, + { + "name": "Attach to Process", + "type": "coreclr", + "request": "attach", + "processId": "${input:processid}" + } ], "inputs": [ { @@ -52,6 +58,12 @@ "default": "Debug", "description": "The Build Configuration", "options": [ "Debug", "Release"] - } + }, + { + "id": "processid", + "type": "promptString", + "default": "0", + "description": "Enter dotnet build process id reported when setting the env var MSBUILDDEBUGONSTART=2", + }, ] } diff --git a/.vscode/tasks.json b/.vscode/tasks.json index e79dfcacc8d..4b652be3076 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -127,8 +127,8 @@ "label": "build-sample-under-dotnet", "type": "shell", "windows": { "command": "dotnet-local.cmd build ${input:project} -p:Configuration=${input:configuration} -t:${input:target} -bl:${input:target}.binlog", }, - "linux": { "command": "./dotnet-local.sh build ${input:project} -p:Configuration=${input:configuration} -t:${input:target} -bl:${input:target}.binlog",}, - "osx": { "command": "./dotnet-local.sh build ${input:project} -p:Configuration=${input:configuration} -t:${input:target} -bl:${input:target}.binlog",}, + "linux": { "command": "${input:debugbuildtasks} ./dotnet-local.sh build ${input:project} -p:Configuration=${input:configuration} -t:${input:target} -bl:${input:target}.binlog",}, + "osx": { "command": "${input:debugbuildtasks} ./dotnet-local.sh build ${input:project} -p:Configuration=${input:configuration} -t:${input:target} -bl:${input:target}.binlog",}, "group": { "kind": "build", "isDefault": true @@ -141,8 +141,8 @@ "label": "run-sample-under-dotnet", "type": "shell", "windows": { "command": "dotnet-local.cmd build ${input:project} \"-t:Run\" --no-restore -p:TargetFramework=${input:targetframework} -p:Configuration=${input:configuration} -p:AndroidAttachDebugger=${input:attach} -bl:run.binlog", }, - "linux": { "command": "./dotnet-local.sh build ${input:project} \"-t:Run\" --no-restore -p:TargetFramework=${input:targetframework} -p:Configuration=${input:configuration} -p:AndroidAttachDebugger=${input:attach} -bl:run.binlog",}, - "osx": { "command": "./dotnet-local.sh build ${input:project} \"-t:Run\" --no-restore -p:TargetFramework=${input:targetframework} -p:Configuration=${input:configuration} -p:AndroidAttachDebugger=${input:attach} -bl:run.binlog",}, + "linux": { "command": "${input:debugbuildtasks} ./dotnet-local.sh build ${input:project} \"-t:Run\" --no-restore -p:TargetFramework=${input:targetframework} -p:Configuration=${input:configuration} -p:AndroidAttachDebugger=${input:attach} -bl:run.binlog",}, + "osx": { "command": "${input:debugbuildtasks} ./dotnet-local.sh build ${input:project} \"-t:Run\" --no-restore -p:TargetFramework=${input:targetframework} -p:Configuration=${input:configuration} -p:AndroidAttachDebugger=${input:attach} -bl:run.binlog",}, "group": { "kind": "build", "isDefault": true @@ -220,5 +220,15 @@ "Everything", ] }, + { + "id": "debugbuildtasks", + "type": "pickString", + "default": "", + "description": "Debug Build Tasks?", + "options": [ + "", + "MSBUILDDEBUGONSTART=2" + ] + }, ] } \ No newline at end of file diff --git a/Documentation/guides/MSBuildBestPractices.md b/Documentation/guides/MSBuildBestPractices.md index bca45d30b5e..69c1b49d057 100644 --- a/Documentation/guides/MSBuildBestPractices.md +++ b/Documentation/guides/MSBuildBestPractices.md @@ -5,6 +5,74 @@ This guide is a work-in-progress, but really has two main goals: - What are good MSBuild practice in relation to what we already have going on in Xamarin.Android MSBuild targets? +## Debugging MSBuild Tasks + +One thing that is very useful is the ability to debug your Tasks while +they are being run on a build process. This is possible thanks to the +`MSBUILDDEBUGONSTART` environment variable. When set to `2` this will +force MSBuild to wait for a debugger connection before continuing. +You will see the following prompt. + +```dotnetcli +Waiting for debugger to attach (dotnet PID 13001). Press enter to continue... +``` + +You can then use VS or VSCode to attach to this process and debug you tasks. + +In the case of .NET Android we need to do a couple of thing first though. Firstly +we need to disable the use of `ILRepacker` on the `Xamarin.Android.Build.Tasks` +assembly. This is because `ILRepacker` does NOT handle debug symbols very well. +Assemblies it generates seem to be JIT optimized so the debugger will not load +the symbols. A new MSBuild property has been introduced to disable this feature +while debugging. `_ILRepackEnabled` can be set as an environment variable which +MSBuild will pickup. You will also need to build the `Debug` Configuration. + +```dotnetcli +export CONFIGURATION=Debug +make prepare && _ILRepackEnabled=false make jenkins +``` + +This will disable the `ILRepacker` for the build. + +You can then start your test app with the `dotnet-local` script (so it uses your build) + +### [MacOS](#tab/macos) + +```dotnetcli +MSBUILDDEBUGONSTART=2 ~//dotnet-local.sh build -m:1 +``` + +### [Linux](#tab/linux) + +```dotnetcli +MSBUILDDEBUGONSTART=2 ~//dotnet-local.sh build -m:1 +``` + +### [Windows](#tab/windows) + +```dotnetcli +set MSBUILDDEBUGONSTART=2 +~//dotnet-local.cmd build -m:1 +``` + +--- + +Note: the `-m:1` is important as it restricts MSBuild to 1 node. + +Once MSBuild starts it will print the following + +```dotnetcli +Waiting for debugger to attach (dotnet PID xxxx). Press enter to continue... +``` + +You need to copy the PID value so we can use this in the IDE. For Visual Studio you can use the `Attach to Process` menu option, while you have the Xamarin.Android.sln solution open. For VSCode open the workspace then use the `Attach to Process` Run and Debug option. You will be prompted for the PID and it will then connect. + +Once connected go back to your command prompt and press ENTER so that the MSBuild process can continue. + +You will be able to set breakpoints in Tasks (but not Targets) and step through code from this point on. + +If you want to test in-tree using the same the `build-sample-under-dotnet` command will ask you if you want to debug MSBuild tasks and fill in the `MSBUILDDEBUGONSTART` for you. The PID text will appear in the `Terminal` window in VSCode. In addition the `run-sample-under-dotnet` command will ask the same. + ## Naming MSBuild targets, properties, and item groups are prefixed with an diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targets index 081fbb15896..91a88bedf80 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targets @@ -28,6 +28,7 @@ <_MultiDexAarInAndroidSdk>extras\android\m2repository\com\android\support\multidex\1.0.1\multidex-1.0.1.aar <_SupportLicense Condition="Exists('$(_AndroidSdkLocation)\extras\android\m2repository\NOTICE.txt')">$(_AndroidSdkLocation)\extras\android\m2repository\NOTICE.txt <_SupportLicense Condition="Exists('$(_AndroidSdkLocation)\extras\android\m2repository\m2repository\NOTICE.txt')">$(_AndroidSdkLocation)\extras\android\m2repository\m2repository\NOTICE.txt + <_ILRepackEnabled Condition=" '$(_ILRepackEnabled)' == '' ">true