Build settings
Since Uno generates projects in different formats depending on the build target it is sometimes necessary to be able to control various aspects of the generated project, for instance to include headers and link libraries. This is especially true when interoperating with native libraries. This document is a reference of the available settings.
For an example of how some of these settings can be used together with foreign code, see the Facebook login tutorial. Another document that may come in handy is the UXL handbook, which outlines features that often necessitate changing some build setting.
Two ways to change a setting
The settings in this document can either be set as an attribute attached to an Uno class or method. The benefit of doing these as attributes is that they then only take effect when that class is used (since Uno strips out unused code), which is usually what you want.
To use a setting on an Uno class, add
using Uno.Compiler.ExportTargetInterop;
to the top of the file and use e.g. the following code:
[Require("LinkDirectory", "my/path")]
public class MyClass
{
...
}
When the settings become numerous or require long strings, it can be convenient
to do it in a separate file. We use .uxl
files with unoproj
filetype
Extensions
to do this.
An example of uxl
file that adds to the Xcode plist
file is the following:
<Extensions Backend="CPlusPlus" Condition="iOS">
<Require Xcode.Plist.Element>
<![CDATA[
<key>NSLocationUsageDescription</key>
<string></string>
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>
<key>NSLocationAlwaysUsageDescription</key>
<string></string>
]]>
</Require>
</Extensions>
Here we see we first specify the backend (usually CPlusPlus
), and
(optionally) a target Condition
, meaning that the code is only used on iOS
in this case. We then Require
an Xcode.Plist.Element
and use XML character
data (CDATA
) to avoid having to escape the XML that we want inserted in the
Plist
file.
C++ target settings
Most of our build settings apply only to our C++ targets. These include iOS
and Android
as well as the native
desktop targets, while apps built for
desktop preview use the CIL target.
Including a static library
The following is an example of how a typical library might be included in the project when targeting iOS. See below for a reference for the settings that we use.
[extern(iOS) Require("LinkDirectory", "@('typicalLibrary/lib':Path)")]
[extern(iOS) Require("IncludeDirectory", "@('typicalLibrary/include':Path)")]
[extern(iOS) Require("LinkLibrary", "typicalLibrary")]
[extern(iOS) Require("Source.Include", "typicalLibrary.h")]
class AClassThatNeedsTypicalLibrary { }
Here we're assuming that typicalLibrary
has a header called
typicalLibrary.h
under typicalLibrary/include
(in the directory of our
unoproj
) and that there is a libtypicalLibrary.a
file under
typicalLibrary/lib
.
We use extern(iOS)
on the attributes to only link the library when targeting
iOS.
We also add the library's files to our unoproj
:
{
...
"Includes": [
...
"typicalLibrary/include/typicalLibrary.h:File",
"typicalLibrary/lib/libtypicalLibrary.a:File",
]
}
Here we use the File
filetype, which indicates that Uno shouldn't do anything
special with the files. We do this since we're including the files manually by
using attributes.
Build flags
[Require("LinkDirectory", "my/path")]
Adds my/path
to the library search path. This is equivalent to passing
-Lmy/path
to the C++ compiler. Using "@('my/relative/path':Path)"
as the
path means that it's relative.
[Require("LinkLibrary", "mylibrary")]
Link the application with mylibrary
. This is equivalent to passing
-lmylibrary
to the C++ compiler.
Note: For linking libraries on Android, use the JNI.*
settings below.
[Require("IncludeDirectory", "my/path")]
Adds my/path
to the include search path. This is equivalent to passing
-Imy/path
to the C++ compiler. Using "@('my/relative/path':Path)"
as the
path means that it's relative.
Including foreign source files
We add Objective-C, Java, and C source files to Uno projects as follows:
{
...
"Includes": [
"*",
"Example.hh:ObjCHeader:iOS",
"Example.mm:ObjCSource:iOS",
"Example.java:Java:Android"
"Example.h:CHeader",
"Example.c:CSource",
]
}
For more information, see the foreign code documentation.
Android-specific settings
JNI
Since we treat shared and static native libraries differently on Android we do
not use LinkLibrary
for both, but instead use the following two elements:
[Require("JNI.SharedLibrary", "mylib.so")]
Loads mylib.so
using System.loadLibrary
when the application starts, and
includes mylib.so
in the app.
[Require("JNI.SystemLibrary", "systemlib")]
Loads systemlib
using System.loadLibrary
when the application starts
(without including it in the app, assuming it's a system library like log
).
[Require("JNI.StaticLibrary", "mylib.a")]
Statically links the application with mylib.a
.
Resources
[Require("Android.ResStrings.Declaration", "<string name=\"hello\">Hello!</string>")]
Adds <string name="hello">Hello!</string>
to the string resource file:
res/values/strings.xml
.
Manifest
[Require("AndroidManifest.ActivityElement", "<an-activity-element />")]
Adds <an-activity-element />
to the application's activity
section in the
AndroidManifest.xml
file.
[Require("AndroidManifest.ApplicationElement", "<an-application-element />")]
Adds <an-application-element />
to the application
section in the
AndroidManifest.xml
file.
[Require("AndroidManifest.Permission", "android.permission.A_PERMISSION")]
Adds <uses-permission android:name="android.permission.A_PERMISSION" />
to
the AndroidManifest.xml
file.
[Require("AndroidManifest.RootElement", "<a-root-element />")]
Adds <a-root-element />
at the root level below the manifest
tag in the
AndroidManifest.xml
file.
[Require("AndroidManifest.Activity.ViewIntentFilter",
"android:host=\"sites.google.com\" android:pathPrefix=\"/site/appindexingex/home/main\" android:scheme=\"https\"")]
Adds the specified string to the application view's intent-filter.
Gradle
These settings apply when building for Android using our preliminary Gradle
experimental support which is enabled when building with the -DGRADLE
Uno flag.
See
this
for more information about dependency management using Gradle.
[Require("Gradle.Dependency", "compile('myDependency') { transitive = true }")]
Adds compile('myDependency') { transitive = true }
to dependencies
in the
app's generated build.gradle
file.
[Require("Gradle.Dependency.ClassPath", "myDependency")]
Adds classpath 'myDependency'
to dependencies
in the top-level generated build.gradle
file.
[Require("Gradle.Dependency.Compile", "myDependency")]
Adds compile 'myDependency'
to dependencies
in the app's generated build.gradle
file.
[Require("Gradle.BuildFile.End", "stuff")]
Adds stuff
to the very end of the app's generated build.gradle
file.
[Require("Gradle.Repository", "mavenCentral()")]
Adds mavenCentral()
to repositories
in the app's generated build.gradle
file.
iOS-specific settings
Xcode settings
[Require("Xcode.EmbeddedFramework", "my.framework")]
Adds my.framework
as an embedded framework to the generated Xcode project.
Using "@('my/relative.framework':Path)"
as the path means that it's relative.
[Require("Xcode.Framework", "a.framework")]
Adds a.framework
as a framework to the generated Xcode project. If the path
to the framework is not absolute, it is assumed to be relative to
SDKROOT/System/Library/Frameworks
and can therefore be used for frameworks
from the iPhone SDK.
Using "@('my/relative.framework':Path)"
as the path means that it's relative.
[Require("Xcode.FrameworkDirectory", "@('my/relative/framework/path':Path")]
Adds my/relative/framework/path
to the framework search path. This is
equivalent to passing -Fmy/relative/framework/path
to the C++ compiler.
Note: When including frameworks using Xcode.Framework
or
Xcode.EmbeddedFramework
this flag is automatically set, so it need not be set
in that case.
[Require("Xcode.Plist.Element", "<plist-element />")]
Adds <plist-element />
to the application's plist
file.
[Require("Xcode.ShellScript", "someScript")]
Adds someScript
in a PBXProjShellScriptBuildPhase
in the generated
Xcode project's .pbxproj
file.
CocoaPods
These settings apply when building for iOS using our preliminary CocoaPods
support which is enabled when building with the -DCOCOAPODS
Uno flag.
[Require("Cocoapods.Platform.Name", "platformName")]
Adds
platform :platformName, ''
to the generated Podfile
.
[Require("Cocoapods.Platform.Version", "platformVersion")]
If Cocoapods.Platform.Name
is set to platformName
, adds
platform :platformName, 'platformVersion'
to the generated Podfile
.
[Require("Cocoapods.Podfile.Target", "pod 'Firebase'")]
Adds pod 'Firebase'
to the application's target
configuration in the
generated Podfile
.
[Require("Cocoapods.Podfile.Pre", "myPreStatement")]
Adds myPreStatement
to the beginning of the generated Podfile
.
[Require("Cocoapods.Podfile.Post", "myPostStatement")]
Adds myPostStatement
to the end of the generated Podfile
.