Android Tutorial Conditional Compilation & Build Configurations

B4A v3.80 adds support for conditional compilation.

From Wikipedia:
In computer programming, conditional compilation is compilation implementing methods which allow the compiler to produce differences in the executable produced controlled by parameters that are provided during compilation.

Conditional compilation allows you to exclude parts of the code based on the selected build configuration. You can use it to create several applications from the same project. For example you can create one application with ads and another application without ads.

Build Configurations

The build configurations dialog is available under Project -> Build Configurations (Ctrl + B).

SS-2014-05-08_09.58.38.png


This dialog allows you to edit or add new configurations and to choose the current active configuration.
A build configuration is made of a package name and a set of conditional symbols.
The package name replaces the previously global package field. This means that you can produce APKs with different package names from the same project. Note that multiple configurations can share the same package name.

The conditional symbols define the active compiler symbols. This allows you to exclude parts of the code based on the chosen build configuration.
You can set multiple symbols separated with commas.

There are several built-in symbols:
- B4A: B4A, DEBUG and RELEASE. Either DEBUG or RELEASE will be active based on the deployment mode.
- B4J: B4J, DEBUG, RELEASE, UI or NON_UI (based on the app type)
- B4i: B4I, DEBUG, RELEASE

Code Exclusion

With the conditional compilation feature you can exclude any code you like from the code editor, manifest editor and designer script (any text can be excluded, including complete subs and attributes).
Excluded code will not be parsed and will be effectively removed before it reaches the compiler.
Note that the manifest editor and designer script will not visualize the excluded code. However it still works properly.

The code exclusion syntax:

SS-2014-05-08_10.19.51.png


B4X:
#If [symbol]
...
#End If

Each build configuration holds a set of symbols. Multiple configurations can share all or some of the symbols. This makes it possible to include or exclude code in several different configurations.

Starting from B4A v5, B4J v3 and B4i v2 more complex expressions are supported.
For example:
B4X:
#If FULL and Not(WITH_ADS)
'Do something
#Else If WITH_ADS OR (TRIAL And IN_APP)
'...
#Else
'...
#End If
 
Last edited:

Computersmith64

Well-Known Member
Licensed User
Longtime User
Yeah probably, but no matter - I have figured it out.
 

Computersmith64

Well-Known Member
Licensed User
Longtime User
It's more of a workaround than a fix. I have 2 variables that I set & then use conditionally throughout the app to turn on/off various options:

sRelease (which is either "(Free)" or "(Paid)"
sDist (which is either "" or "Amazon"

My original plan was to replace every If statement in my app that uses one or both of these variables with an #If (FREE, PAID or AMAZON), but instead I just set the variables using #If:

B4X:
#If FREE
    Dim sRelease As String = "(Free)"
    Dim sDist As String = ""
#End If
#If PAID
    Dim sRelease As String = "(Paid)"
    Dim sDist As String = ""
#End If
#If AMAZON
    Dim sRelease As String = "(Free)"
    Dim sDist As String = "Amazon"
#End If

I also do the same with the version number & name (because they are different between the paid & free versions), which means that I still have 2 that are the same:

B4X:
#If FREE
    #ApplicationLabel: Yahtzee! (Free)
    #VersionCode: 119
    #VersionName: 11.9
#End If
#If AMAZON
    #ApplicationLabel: Yahtzee! (Free)
    #VersionCode: 119
    #VersionName: 11.9
#End If
#If PAID
    #ApplicationLabel: Yahtzee! (Paid)
    #VersionCode: 89
    #VersionName: 8.9
#End If

So it's a little inefficient, but it saves me from manually having to change these every time I release all three versions, so I can live with it...

-Colin.
 

Computersmith64

Well-Known Member
Licensed User
Longtime User
You can add a symbol named FreeOrAmazon to FREE and AMAZON configurations. This will allow you to write:
B4X:
#If FreeOrAmazon
...
#End If

Thanks Erel.
 
D

Deleted member 103

Guest
It would be nice if you could select the configuration so.
B4A-3.80.JPG


And it would also be nice if that were possible.
B4X:
  #If lite
    #ApplicationLabel: B4A-Lite
    #ApplicationIcon: LoadBitmap(File.DirAssets,"lite.png")
  #end if

  #If Pro
    #ApplicationLabel: B4A-Pro
    #ApplicationIcon: LoadBitmap(File.DirAssets,"pro.png")
  #end if
 
Last edited by a moderator:

Knoppi

Active Member
Licensed User
Longtime User
Is conditional compilation planed for b4j too?
 

canalrun

Well-Known Member
Licensed User
Longtime User
Thanks.
Conditional Compilation is a great addition.
Implementing via Build Configurations seems like a very good solution.

I tested the beta quickly. It seems that the output from each build configuration ends up in the Objects directory. Compiling under a different configuration will overwrite the output from a previous configuration. Am I correct?

It would seem to be very handy to have the output from the Default configuration go directly into the Objects directory as it does now, but if a different configuration is selected have it go into a subdirectory of the Objects directory. For example the output of the Default configuration would go into the Objects directory, but if the New_1 configuration is selected, compilation output would go to the Objects/New_1 directory.

Imagine the following scenario. You release an APK, compile several different configurations. Then 6 months later your customer comes back and says "My APK is corrupt". You go back and see that the configuration of the customers APK has been overwritten, but also that the source code has been changed. You now have to reverse the changes and hope that an equivalent APK can be generated. Of course it's better to back things up, but different output directories would be another level of security.

What do others think? Would this change affect too many other things? Am I incorrect in the way it operates?

Thanks,
Barry.

Added later…

Something I just thought of, but didn't test.

Is it possible to select one of several icons to be used as the icon for the build configuration. Is this already in there?
 
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
Is conditional compilation planed for b4j too?
Yes.

Is it possible to select one of several icons to be used as the icon for the build configuration. Is this already in there?
It is possible with the help of a custom build action. I will later write a small tutorial that shows how to switch files based on the build configuration.
 

bluedude

Well-Known Member
Licensed User
Longtime User
I think this is great but i'm struggling with the right approach. Say I want three versions which enable/disable stuff in the manifest:

1 A full version with support for custom URI, NFC and barcode reader
2 A version with just barcode support
3 A version with just NFC support

I'm wondering how that works? Can I combine #if FULL OR WITHNFC or do I need to have another approach?

Normally I would say #IF NFC add NFC manifest stuff.

Also not sure about the option to be able to add more symbols to a configuration? How to use that? How do I avoid over complicated conditional compilation?
 

bluedude

Well-Known Member
Licensed User
Longtime User
My "head" tells me logical wise I would do:

FULL
NONFC
NOBARCODE

But if I check for NONFC that would not work because I would actually not want to add anything to the manifest then. However with #IF NONFC that is impossible.
 

DonManfred

Expert
Licensed User
Longtime User
B4X:
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Public logError = 0
    Public logWarning = 1
    Public logNotice = 2
    Public logDebug = 3   
End Sub
Sub MyLog(LogType As Int, text As String)
    Select LogType
    Case 0
        LogColor("  Error: "&text,Colors.Red)
    Case 1
        LogColor("Warning: "&text,Colors.ARGB(255,255,140,0))
    Case 2
        LogColor(" Notice: "&text,Colors.Blue)
    Case 3
        LogColor("  Debug: "&text,Colors.ARGB(255,139,0,0))
    End Select   
End Sub
Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'If FirstTime Then
        'Activity.LoadLayout("main")
    'End If
    #If nfc
        MyLog(logNotice,"NFC enabled")
    #End If
    #If barcode
        MyLog(logNotice,"BARCODE enabled")
    #End If
    #If uri
        MyLog(logNotice,"URI enabled")
    #End If
end sub

snap0058.png


snap0059.png

snap0060.png


That´s the log from a compiling with Buildconfiguration set to Full

snap0061.png
 
Top