Bug 9340 - Debugable = true for release builds
Summary: Debugable = true for release builds
Alias: None
Product: Android
Classification: Xamarin
Component: General ()
Version: 4.4.x
Hardware: PC Mac OS
: High critical
Target Milestone: ---
Assignee: Jonathan Pryor
Depends on:
Reported: 2013-01-07 16:07 UTC by anthony taranto
Modified: 2014-07-30 10:52 UTC (History)
13 users (show)

Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description anthony taranto 2013-01-07 16:07:16 UTC
Packages built in Release mode will have Debugable set to true. This is a regression.
Comment 1 Stephen Shaw 2013-01-17 12:03:03 UTC
This is bad, so very bad ;)
Comment 2 Justin 2013-01-17 12:14:57 UTC
A couple failed workaround attempts:

1)Modifying the AssemblyInfo.cs file:

#if DEBUG 
[assembly: Application(Debuggable=true)]
[assembly: Application(Debuggable=false)] 

2)Setting the debuggable property to false in the manifest:

   android:debuggable="false" />
Comment 3 Jonathan Pryor 2013-01-17 12:16:50 UTC
Alas, that's not all of it.

If we take a Default project, build and Package as Release, and view obj\Release\android\AndroidManifest.xml, I see:

  <application android:name="mono.android.app.Application">

i.e. no android:debuggable attribute at all.

Note: building with:

    xbuild /t:SignAndroidPackage /p:Configuration=Release *.csproj

If I update the project to contain:

    [assembly:Application (Debuggable=false)]

Resulting AndroidManifest.xml contains:

>  <application android:debuggable="false" android:name="mono.android.app.Application">

which also makes sense.

If I further update the project to instead contain:

    #if DEBUG
    [assembly:Application (Debuggable=true)]
    [assembly:Application (Debuggable=false)]

AndroidManifest.xml is unchanged.

This is with Mono for Android on OSX.

So I'm stumped in getting a repro for the described behavior.
Comment 4 Jonathan Pryor 2013-01-17 12:18:46 UTC
If I use this:

    [assembly:Application (
    	#if DEBUG

Resulting AndroidManifest.xml is:

  <application android:name="mono.android.app.Application">
Comment 5 Jonathan Pryor 2013-01-17 12:20:46 UTC
Whether we explicitly set/create the //application/@android:debuggable attribute is dependent upon the $(DebugSymbols) MSBuild property.

For example, in my appcsproj:

>   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
>     <DebugSymbols>True</DebugSymbols>

QUESTION: Do you have <DebugSymbols>True</DebugSymbols> set in your Release group, e.g.:

>   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
>     <DebugSymbols>True</DebugSymbols>
Comment 6 Jonathan Pryor 2013-01-17 12:35:07 UTC
Truly bizarre offhand; if I try to deliberate break things as described in Comment #5:

>   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
>     <DebugSymbols>True</DebugSymbols>

It doesn't break:

  <application android:name="mono.android.app.Application">

However, if I specify DebugSymbols on the command line:

> xbuild /p:Configuration=Release /t:SignAndroidPackage *.csproj /v:diag /p:DebugSymbols=True

THEN it breaks:

>   <application android:name="mono.android.app.Application" android:debuggable="true">

So I think I have the right idea -- $(DebugSymbols) is being defined (somehow), which is causing //application/@android:debuggable to be generated -- but I don't know why it needs to be specified on the command line in this fashion. :-(
Comment 7 Jonathan Pryor 2013-01-17 12:38:32 UTC
> $ rm -Rf obj; xbuild /p:Configuration=Release /t:SignAndroidPackage *.csproj /v:diag /p:DebugSymbols=True > out.txt
> $ rm -Rf obj; xbuild /p:Configuration=Release /t:SignAndroidPackage *.csproj /v:diag /p:DebugSymbols=True > out-cl.txt
> $ diff -u out.txt out-cl.txt
> @@ -740,7 +747,7 @@
>                 Using task GenerateJavaStubs from Xamarin.Android.Tasks.GenerateJavaStubs, Novell.MonoDroid.Build.Tasks, Version=, Culture=neutral, PublicKeyToken=null
>                 GenerateJavaStubs Task
>                   ManifestTemplate: 
> -                 Debug: False
> +                 Debug: True


FYI, from Novell.MonoDroid.Common.targets:


I think I'll blame XBuild bug on this...so let's avoid that rabbit hole.

In any event, $(DebugSymbols) appears to be the culprit...
Comment 8 Jonathan Pryor 2013-01-17 14:12:01 UTC
So why is $(DebugSymbols) true?

Here's a way to set it to True within MonoDevelop:

1. Click Project > <ProjectName> Options
2. In the left-hand tree, click Build > Compiler
3. In the right-hand panel:
3.a: In the Configuration drop-down, select Release
3.b: Select the [X] Emit debugging information check box.

Save, and when I inspect the .csproj I see that the Release section has:

Comment 9 Luzanne 2013-01-22 09:16:46 UTC
Maybe it is something else. When I look into the MSBuild output and then at the ExtraArgs for aapt.exe, at the end of the line is a --debug-mode, which adds a debuggable=true to the manifest.

Task "Aapt"
  Aapt Task
    AndroidSdkDirectory: C:\Program Files (x86)\Android\android-sdk\
    AssetDirectory: obj\Release\assets\
    ManifestFile: obj\Release\android\AndroidManifest.xml
    ResourceDirectory: obj\Release\res\
    JavaDesignerOutputDirectory: C:\Users\User\AppData\Local\Temp\ewkcmhqv.1tc
    PackageName: nl.sumbeam.memorytest
  C:\Program Files (x86)\Android\android-sdk\platform-tools\aapt.exe package -f -m -M obj\Release\android\AndroidManifest.xml -J C:\Users\User\AppData\Local\Temp\ewkcmhqv.1tc --custom-package nl.user.memorytest -F obj\Release\android\bin\packaged_resources.bk -S obj\Release\res -I "C:\Program Files (x86)\Android\android-sdk\platforms\android-8\android.jar" --auto-add-overlay --debug-mode 
Done executing task "Aapt".

$(DebugSymbols) is not true in my case when i look at the output. It is also not defined in my csproj file under Release.
> Task "CopyResource" skipped, due to false condition; ('$(DebugSymbols)' == 'true') was evaluated as ('' == 'true').

This is on W7 64bit, MonoDroid 4.4.54, Visual Studio 2010

And the output for "GenerateJavaStubs":
Task "GenerateJavaStubs"
  GenerateJavaStubs Task
    ManifestTemplate: \\psf\home\documents\visual studio 2010\Projects\Sample\SampleProject\Properties\AndroidManifest.xml
    Debug: False
Done executing task "GenerateJavaStubs".
Comment 10 Jonathan Pryor 2013-01-23 14:56:04 UTC
@Luzanne: You're onto something. I hadn't noticed --debug-mode.

--debug-mode is _always_ added.

However, it doesn't always change AndroidManifest //application/@android:debuggable. It only sets //application/@android:debuggable IFF it isn't previously specified.

Aside: this is where `apktool` comes in handy, as it allows you to see the AndroidManifest.xml that results _after_ `aapt` executes, which MAY NOT be the same as e.g. obj\Debug\android\AnddroidManifest.xml.


For example, start with the default Application project. Build a Release .apk:

    xbuild /t:SignAndroidPackage /p:Configuration=Release *.csproj

obj\Release\android\AndroidManifest.xml DOES NOT contain //application/@android:debuggable. As per the Android documentation, the default value is false, so we're good, right?


    $ apktool d *-Signed.apk  t
    $ open t/AndroidManifest.xml

    <application android:name="mono.android.app.Application" android:debuggable="true">

Low and behold, _there_ is where we get //application/@android:debuggable="true"!

The Workarounds listed in Comment #2 work because `aapt --debug-mode` won't replace the @android:debuggable attribute, so adding this C# source code and rebuilding the .apk will result in AndroidManifest.xml containing android:debuggable="false":

    <application android:name="mono.android.app.Application" android:debuggable="false">
Comment 11 Luzanne 2013-01-23 15:16:56 UTC
Yep, you are right. Didn't notice that that works because he mentioned it as 'failed'. When I add that to my own manifest, build a release and check the apk with apktool, there is a debuggable="false" in the manifest. So that works. Yay!

I already made a batch file as workaround to decompile the apk, change the manifest, recompile the app, replace the new manifest in the original apk with the one from the new apk and resign/zipalign the original apk.

(All buildsteps in VS 2010)
Comment 12 Jonathan Pryor 2013-01-23 15:22:10 UTC
Commit monodroid/665898a2 removes the --debug-mode parameter from `aapt` invocation.
Comment 13 Jonathan Pryor 2013-01-23 16:03:19 UTC
Related: Commit monodroid/051cddf9 changes things so that if Properties\AndroidManifest.xml is present, we don't REPLACE the //application/@android:debuggable attribute when $(DebugSymbols) is True.

For example:

1. Create a default project.

2. Add Properties\AndroidManifest.xml (via Options...).

3. Edit Properties\AndroidManifest.xml so that the <application/> element has android:debuggable="false".

4. Build the .apk, and view e.g. obj\Debug\android\AndoidManifest.xml.

In Mono for Android <= 4.4, (4) will contain android:debuggable="true", despite the fact that we overrode that value in (3).

This will be fixed in 4.6 so that the developer-provided AndroidManifest.xml is respected.
Comment 14 Jonathan Pryor 2013-01-23 16:09:01 UTC
Outstanding issue (and this requires some thought/debate):

As per Comment #5 and Comment #8, the following scenario is possible:

1. Create default project.
2. Set Configuration to Release
3. Edit Project Options so that debug symbols are generated (Comment #8)
4. Build the .apk

The result? obj\Release\android\AndroidManifest.xml will contain android:debuggable="true". This seems wrong, as intuitively Release builds should not default to being debuggable, yet that's what we currently do.

Question: What should be done, and HOW should we do that, in a way which is documentable and itself intuitive/understandable.
Comment 15 Justin 2013-01-23 17:01:01 UTC
As an update to comment 2... The workarounds failed because we had the emit debug information checked in our release build.  That was an accident and as soon as we turned off that option the workarounds did indeed work.
Comment 16 Luzanne 2013-01-23 17:31:20 UTC
My thoughts:

In Debug build:
Default setting is debuggable="true".
When de developer overrides this setting in the custom Properties\AndroidManifest.xml by setting it to false, the app is not debuggable and the value should not be changed.

In Release build:
Default setting is debuggable="false".
When de developer overrides this setting in the custom Properties\AndroidManifest.xml by setting it to true or edit the settings that the debug symbols are added, the app is debuggable and the value should not be changed.

I think the custom AndroidManifest if presented must be the leading one when the android:debuggable is added to that file.

When that file is not presented or the debuggable is not added to the application node in that file, the default setting should be respected.

But what to do with the different options to edit the application node, for example from the assembly.cs or the application attribute?
Comment 17 Jonathan Pryor 2013-01-23 18:55:02 UTC
@Luzanne: Your thoughts regarding Debug and Release builds should be the case in 4.6, as per Comment #13.

> But what to do with the different options to edit the application node, for
> example from the assembly.cs or the application attribute?

How it _should_ be (because this is how we documented it) is that AndroidManifest.xml overrides source code which overrides default values:

    AndroidManifest.xml > C# source > defaults

This wasn't the case for the android:debuggable attribute until I fixed it as per Comment #13.
Comment 18 dean.ellis 2013-03-08 07:26:06 UTC
The $(DebugSymbols) in Visual Studio is controlled from
1) Open the Project Properties (Right Click on project click Properties)
2) Got to the Build Tab
3) Click the Advanced button near the bottom of the tab
4) Set the Debug Info to anything but None (valid values are None, PdbOnly and Full)

This will result in $(DebugSymbols) being set to true and the pdb and then the mdb files being generated and included in the apk (once I commit the fix for https://bugzilla.xamarin.com/show_bug.cgi?id=9433)

If we are including .mdb files in the release build because the developer set the Debug Info to full or pdbonly in their release configuration then I would expect the android:debuggable attribute to be set to true. I know its counter intuitive to debug release mode stuff, but I know guys who work this way.
Comment 19 Miguel de Icaza [MSFT] 2013-03-11 10:53:49 UTC
Xamarin Studio and MCS on Mono 2.10 do not support setting the PdbOnly option.

What we are going to do is:

(a) Add support to Xamarin Studio to set the value to PdbOnly which would enable symbols, but not set the Debuggable attribute to true behind your back (you can still override as discussed before).

(b) Delay the full fix for Mono 3.0-based systems, as those allow /debug:full and /debug:pdbonly

(c) We will roll this out for Visual Studio, as that one does not have the /debug:pdbonly limitation.
Comment 20 Mikayla Hutchinson [MSFT] 2013-03-12 21:50:38 UTC
PdbOnly support is in xbuild in Mono master.
Comment 21 Jonathan Pryor 2013-03-14 17:36:42 UTC
Comment #14 is fixed with monodroid/980303ec. This should appear in the 4.8 release.

With this fix, the AndroidManifest.xml /manifest/application/@android:debuggable attribute will be set and .mdb symbols will be packaged ONLY when:

1. $(DebugSymbols) is True
2. $(DebugType) is Full.

Consequently, if you do a build with "PdbOnly" symbols, the /manifest/application/@android:debuggable  attribute will _not_ be implicitly created, and (once Bug #9433 is fixed) .mdb files will NOT appear in the .apk.

If $(DebugType) is Full, then /manifest/application/@android:debuggable will be set to true (unless overridden via custom attributes, etc.) and .mdb files WILL be deployed (or _eventually_ will be deployed, with the fix of Bug #9433), EVEN ON Release BUILDS.

Rephrasing: Release builds w/ PdbOnly symbols: No debug symbols in .apk.
Release builds w/ Full symbols: Debug symbols included in .apk.
Comment 22 Mikayla Hutchinson [MSFT] 2013-03-16 13:22:51 UTC
Landed pdbonly support in XS master (bug 3478).
Comment 32 Jonathan Pryor 2014-04-25 13:32:33 UTC
@Allie: wrt Comment #23, I am unable to reproduce (or I don't understand the scenario).

If I add this to AssemblyInfo.cs:

[assembly: Application(Debuggable = true)]
[assembly: Application(Debuggable = false)]

Then build a Debug build (in which DEBUG is set), then the resulting .apk has //application/@android:debuggable="true", as expected, according to apktool.

If I build a Release build (in which DEBUG is not set), then the resulting .apk has //application/@android:debuggable="false", as expected, according to apktool.

I don't understand the comment about `#if RELEASE`.

Comment #29 through Comment #32 verified with Xamarin.Android 4.12.3.
Comment 34 Jonathan Pryor 2014-07-30 10:52:36 UTC
@Allie: You can't use `#if RELEASE`, by default, as RELEASE is _not_ a #defined symbol in Release builds. Debug builds get DEBUG (by default); Release builds get _nothing_ (by default). Consequently, given:

    #if RELEASE
    [assembly: Application(Debuggable = false)]
    [assembly: Application(Debuggable = true)]

Because RELEASE will _never_ be defined, even in Release builds, that means that `#if RELEASE` will always be false, meaning ALL builds will get [assembly:Application(Debuggable=true)], which is what the customer reported seeing.

If you want to use `#if RELEASE`, you must manually add RELEASE to the list of Define Symbols (e.g. Xamarin Studio Project Options > Build / Compiler > General Options > Define Symbols).

I would instead suggest NOT using RELEASE, and instead depend on DEBUG (which is present in the default template for Debug configuration builds).