Fixed on GIT ANDROID_MANIFEST Config += operator not working


Active member
3rd Party Module Dev
3rd Party Tool Dev
Mar 5, 2018
I have a problem with AndroidManifest.xml and several other file like build.gradle and so on. The problem is like this...
When I have a line code using this [ += ]:

When compile the output file become like this, which produce error

| <bla>/> | <bla>
       | <bla>
| <bla>

There are symbol " | " appear making error in the output. compile release fail
Last edited:
Without knowing which version of Cerberus you are using. It would be just guess work.
There was a similar issue that was highlighted as a bug, that was fixed with this commit as far as I know.
Last edited:
I think he uses an older version. but I can confirm this with the latest version and adding to this, the changes to API33 included braking changes to the manifest itself which now don't take in stuff that is set from a module. Moving this into bugs.
Should be simple to fix by updating the android builder to include .Replace( "|", " " ) where required.
To maintain some backwards compatibility. I would replace
        SetConfigVar "ANDROID_LIBRARY_REFERENCE_1",GetConfigVar( "ANDROID_LIBRARY_REFERENCE_1" ).Replace( ";","~n" )+"~n"
        SetConfigVar "ANDROID_LIBRARY_REFERENCE_2",GetConfigVar( "ANDROID_LIBRARY_REFERENCE_2" ).Replace( ";","~n" )+"~n"
        SetConfigVar "ANDROID_MANIFEST_MAIN",GetConfigVar( "ANDROID_MANIFEST_MAIN" ).Replace( ";","~n" )+"~n"
        Local manifest:String = GetConfigVar( "ANDROID_MANIFEST_APPLICATION" ).Replace( ";","~n" )+"~n"
with something this to /transcc/builders/android.cxs like:
        Local ref1=GetConfigVar( "ANDROID_LIBRARY_REFERENCE_1" )
        Local ref2=GetConfigVar( "ANDROID_LIBRARY_REFERENCE_2" )
        Local manifest:String = GetConfigVar( "ANDROID_MANIFEST_APPLICATION" )
        If ref1.Contains( ";" ) then ref1=ref1.Replace( ";","~n" )+"~n" Else ref1=ref1.Replace( "|","~n" )+"~n"
        If ref2.Contains( ";" ) then ref2=ref2.Replace( ";","~n" )+"~n" Else ref2=ref2.Replace( "|","~n" )+"~n"
        If manifest.Contains( ";" ) then manifest=manifest.Replace( ";","~n" )+"~n" Else manifest=manifest.Replace( "|","~n" )+"~n"
        SetConfigVar "ANDROID_LIBRARY_REFERENCE_1",ref1
        SetConfigVar "ANDROID_LIBRARY_REFERENCE_2",ref2
        SetConfigVar "ANDROID_MANIFEST_MAIN",manifest
NOTE: I've not tested this.
Last edited:
I will look into this tomorrow. I did the last changes on the Android target and hope I didn't break functionality with the manifest placeholders there.
At first glance I would rather think it's an old bug with config separators that already caused some headache, once with resource file types, then with compiler options and seemingly now with "" blank separators. ... I can be totally wrong though :cool:

Edit: After a quick look at my changes for API 33 I am sure that I broke it accidentally. I was sure I kept all the placeholders but obviously this was not in the commit. Will fix it tomorrow.
Last edited:
Its a latest version. (cerberus-v2023-05-26)

I wonder, If I added some other reference like ANDROID_LIBRARY_REFERENCE_3 into my custom templete for example, do this need manualy changes to CX source code like android builder or something (sorry I'm not sure how the CX source work) for it to be able to work like other original one... like ANDROID_LIBRARY_REFERENCE_1
Last edited:
I wonder, If I added some other reference like ANDROID_LIBRARY_REFERENCE_3 into my custom templete for example, do this need manualy changes to CX source code like android builder or something
AFAIK You should be able to add your own configs if they are merely replacing strings. @dawlane's code kind of undoes the concatenation of trans that is done with a default separator.
But honestly we should think of other ways to deal with it if you need changes like adding config vars. I am not a big fan of custom versions for target files.
code kind of undoes the concatenation of trans that is done with a default separator.
You could always try the double replace.
SetConfigVar "ANDROID_LIBRARY_REFERENCE_1",GetConfigVar( "ANDROID_LIBRARY_REFERENCE_1" ).Replace( ";","~n" )+"~n".Replace( "|","~n" )+"~n"
Last edited:
I fixed my mistake of removing the placeholders and it seems to work on my MacBook just by doing that. Will check on Windows - that's what you, @magic, are using, right?
@MikeHart @dawlane I have the same issue on Windows with the latest version. And it is that old bug with the trans preprocessor using a default separator I was referring to before.
We changed the default separator from ";" to "|" but it seems we missed some places. While thinking about what is the best internal default separator I think both variants are not perfect. ";" is sometimes used in normal text like comments and "|" is uses as an operator in build.gradle for example.
What about using something exotic like ASCII 30 "RecordSeparator"? We could make it a Constant and make sure it is never visible outside of TransCC.
Is it easy to input in code?
@MikeHart ,@Phil7
Things to take into consideration with selecting a separation delimiter.
  1. It needs to be easily accessed on all keyboard types. I vaguely remember someone posting, or submitting a pull request to use the pipe("|") because the semicolon(";") was problematic on non English keyboards to easily type. The resource separator is one of those that would come under the problematic category on any keyboard.
  2. It cannot use any key combination that would trigger an operating system accelerator short cut. The Option key on Apple, and Alt tend to be used for this, with or without the other modifier keys.
  3. It cannot be used if it can be used as part of a valid file path.
  4. It cannot be used if the back end tool chain uses it as part of a parameter. MSBuild uses the semicolon as a short hand for passing parameters for multiple properties.
So far the pipe character is the best when it comes to dealing with passing configuration variables.
In the end; most issues should be handled when writing the transcc sources for the targets builder. Where it should correctly format build files or parameters for the back end tool chain.

We could make it a Constant and make sure it is never visible outside of TransCC.
The pipe character is hard coded in the predecessor, so already is a constant. And then not everyone is going to want to type every time:

Some would just want to do the one liner. Which is what the above does internally in the pre processor.

The first bit of code wouldn't have worked, as I forgot that it would still have the same issue if the delimiters were mixed.
Last edited:
Is it easy to input in code?
Not as a keyboard character.
On Linux I have to hold down Ctrl+Shift+U, and then type the code as unicode point in hex to get a resource separator. Plus it's a non printable, so you would see what would look like a corrupt character. And that keyboard combination wouldn't work in TED.
Last edited:
So then it should something similar to ~n ~q etc. Or?
My idea was not so much about which separator to choose but to make a clear distinction between an internal separator handled by transcc and the user facing separator that can still be varying depending on the use case of the variable.
The reason for my exotic character proposal was just that it needs to be very unlikely that a config value entered by a user accidentally contains that character.
Adding another character into the mix would add additional overhead and complexity. As then you would have three characters to replace or split to maintain some backwards compatibly. Issues have already been shown with just changing it from a semicolon to a pipe as the default.

I think it would be better just to use the pipe as the default delimiter for configuration variables and go through all the modules, builders and project templates to replace any semicolons within configuration variables, unless they form part of a parameter list as in item 4 in post 14.

As shown in post 9. The simplest way to avoid all that would be just to do a double replace when it comes to getting the configuration variables. Any more than two double replaces would add more overhead, especially as it will not be know how large the concatenated string will be.
I think I understand your solutions and concerns. I appreciate that a lot! In my head my solution just looks fine and the fact that we are tinkering with issues like this for quite some time let's me assume that there is either some existing complexity not dealt with in code or the current code structure is suboptimal in terms of readability.
I guess the only way for me to find out is to implement my idea and get my head shattered at the truth of real code to then eventually admit that your solution is the way to go to begin with. 😅
Good luck Phil and thanks for your time.
Top Bottom