Flex conditional compilation of MXML? - apache-flex

In Flex it is now possible to use the -define compiler option to do all sorts of cool stuff.
In my program, I am using the option such that some of my code is excluded by blocks like this:
CONFIG::FACEBOOK{
//Some code
}
And this is working well.
How do I get a similar behaviour with MXML?
I want to do the same thing, but omitting/including MXML tags in this way, not blocks of AS code.

My solution is to add some tags that could help to comment out unnecessary blocks of mxml code in certain build.
For example I want to add different buttons in Android and iOS builds:
<!-- iOS --><!--
<s:Button id="backBtn"
icon="{SHOW_LIST}"
click="navigator.popView()"/>
--><!-- /iOS -->
<!--Android-->
<s:Button id="exitBtn"
label="Exit"
click="NativeApplication.nativeApplication.exit()"/>
<!--/Android-->
Now run simple batch script which will comment out all Android specific code in the source for iOS build
PrepareForIos.cmd
#echo off
"C:\Program Files (x86)\bin\fart.exe" -r -w -- H:\Flash\MyProject\src\* "<!--Android-->" "<!-- Android --><!--"
"C:\Program Files (x86)\bin\fart.exe" -r -w -- H:\Flash\MyProject\src\* "<!--/Android-->" "--><!-- /Android -->"
"C:\Program Files (x86)\bin\fart.exe" -r -w -- H:\Flash\MyProject\src\* "<!-- iOS --><!--" "<!--iOS-->"
"C:\Program Files (x86)\bin\fart.exe" -r -w -- H:\Flash\MyProject\src\* "--><!-- /iOS -->" "<!--/iOS-->"
pause
FART is a command-line tool for finding and replacing strings
Now our code looks like this and is ready to be built for iOS:
<!--iOS-->
<s:Button id="backBtn"
icon="{SHOW_LIST}"
click="navigator.popView()"/>
<!--/iOS-->
<!-- Android --><!--
<s:Button id="exitBtn"
label="Exit"
click="NativeApplication.nativeApplication.exit()"/>
--><!-- /Android -->
Inverse operation batch:
PrepareForAndroid.cmd
#echo off
"C:\Program Files (x86)\bin\fart.exe" -r -w -- H:\Flash\MyProject\src\* "<!--Android-->" "<!-- Android --><!--"
"C:\Program Files (x86)\bin\fart.exe" -r -w -- H:\Flash\MyProject\src\* "<!--/Android-->" "--><!-- /Android -->"
"C:\Program Files (x86)\bin\fart.exe" -r -w -- H:\Flash\MyProject\src\* "<!-- iOS --><!--" "<!--iOS-->"
"C:\Program Files (x86)\bin\fart.exe" -r -w -- H:\Flash\MyProject\src\* "--><!-- /iOS -->" "<!--/iOS-->"
pause

A trick I use is to create a static class that holds constants for the different builds:
package
{
public class MyAppConstants
{
CONFIG::Debug
public static const DEBUG:Boolean = true;
CONFIG::Release
public static const DEBUG:Boolean = false;
}
}
And then I use these constants in my MXML:
<namespace:component visible="{MyAppConstants.DEBUG}" includeInLayout="{MyAppConstants.DEBUG}"/>
This will make sure the component is not added to the display list and thusly not measured either. If you would only use the visible attribute the dimensions of the component are still taken into account and will therefore leave "empty" spaces.

Edited response, based on this comment:
Sorry for being slow to get back to this thread. My intention was to have some interface elements (Buttons, and the like) which were omitted in some builds and included in others. My current workaround is to simply set the visible property of the component to the compiler defined boolean constant - it's crude, but it works. Any thoughts on a better way? – Chris Kitching Sep 20 at 14:40
I think you might be able to use the deferred initialisation behaviour of flex to control which components are created and added to your parent component - it might be a little against the idea of MXML, but I think it's possible.
Here is a bit of background on manually initialising deferred components (for spark and mx components):
http://help.adobe.com/en_US/flex/using/WS2db454920e96a9e51e63e3d11c0bf69084-7aee.html
Flex 3
If you're using Flex 3 then you can override the createComponentsFromDescriptors() method and access the childDescriptors property to control exactly which child MXML components will be created.
The Creating deferred components article shows how you can get information about an MXML component from the descriptor. You could use this behaviour to determine which components should or shouldn't be instantiated for the current build.
Class reference for UIComponentDescriptor:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/core/UIComponentDescriptor.html
Flex 4
In Flex 4 it's a little less clear - all MXML components will be created from their descriptors (there isn't a childDescriptors property, just the mxmlContentFactory instance which will create all of the children).
Two options for controlling the display of MXML components might be:
Override the createDeferredContent() method and initialise the child components with the mxmlContentFactor but remove elements from the returned array before setting the mxmlContent property (which adds them to the display list).
Implement a template component that defines exactly what type of components are allowed as children, and only initialising the appropriate children for your current build type.
Here is an example of creating a template component in this way: Using IDeferredInstance in a template component.
Hopefully that gives you something to think about, and hopefully it's not too complicated :)
Original answer:
The short answer is that you can't use conditional compilation for MXML tags.
All MXML tags will be compiled into the component.
What are your goals in wanting to use conditional MXML?
Are you trying to include/exclude classes based on the compiler properties but still keep the short-hand MXML declarations? i.e. not have to define everything in actionscript.
With a bit more info we might be able to work through to an acceptable alternative :)

Related

How to discover default target in make?

I've seen the question "How does “make” app know default target to build if no target is specified?", which explains that the default target is the first target that doesn't being with a '.'.
How do I get make to tell me what that target is?
Context: I've got a recursive make system, with a variety of included makefiles. If I add a new target to my top level Makefile (or to my common include), that becomes the default target. I want to add .DEFAULT_GOAL: original-default-target, but I don't know what original-default-target is.
Running make -d results in a lot of debug output. If you search this for the first occurrence of 'Updating goal targets', and look at the next target mentioned, this appears to be the default target.
For example:
$ make -d | grep -A2 -m1 'goal targets'
Updating goal targets....
Considering target file 'all'.
File 'all' does not exist.
This implies that, for this Makefile at least, the current default target is all. This can then be enforced by adding .DEFAULT_GOAL: all to the top-level Makefile.

spring boot/spring web app embedded version number

What are the strategies to embed a unique version number in a Spring application?
I've got an app using Spring Boot and Spring Web.
Its matured enough that I want to version it and see it displayed on screen at run time.
I believe what you are looking for is generating this version number during build time (Usually by build tools like Ant, Maven or Gradle) as part of their build task chain.
I believe a quite common approach is to either put the version number into the Manifest.mf of the produced JAR and then read it, or create a file that is part of the produced JAR that can be read by your application.
Another solution would be just using Spring Boot's banner customization options described here: http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-spring-application.html#boot-features-banner
However, this will only allow you to change spring-boot banner.
I also believe that Spring Boot exposes product version that is set in Manifest.MF of your application. To achieve this you will need to make sure Implementation-Version attribute of the manifest is set.
Custom solution for access anywhere in the code
Lets assume you would like to have a version.properties file in your src/main/resources that contains your version information. It will contain placeholders instead of actual values so that these placeholders can be expanded during build time.
version=${prodVersion}
build=${prodBuild}
timestamp=${buildTimestamp}
Now that you have a file like this you need to fill it with actual data. I use Gradle so there I would make sure that processResources task which is automatically running for builds is expanding resources. Something like this should do the trick in the build.gradle file for Git-based code:
import org.codehaus.groovy.runtime.*
import org.eclipse.jgit.api.*
def getGitBranchCommit() {
try {
def git = Git.open(project.file(project.getRootProject().getProjectDir()));
def repo = git.getRepository();
def id = repo.resolve(repo.getFullBranch());
return id.abbreviate(7).name()
} catch (IOException ex) {
return "UNKNOWN"
}
}
processResources {
filesMatching("**/version.properties") {
expand (
"prodVersion": version,
"prodBuild": getGitBranchCommit(),
"buildTimestamp": DateGroovyMethods.format(new Date(), 'yyyy-MM-dd HH:mm')
)
}
}
processResources.outputs.upToDateWhen{ false }
In the code about the following is happening:
We defined a function that can take a build number out of the VCS
(in this case Git). The commit hash is limited to 7 characters.
We configure the processResources task to process
version.properties file and fill it with our variables.
prodVersion is taken from Gradle project version. It's usually set
as version in gradle.properties file (part of the general build
setup).
As a last step we ensure that it's always updated (Gradle
has some mechanics to detect if files ened to be processed
Considering you are on SVN, you will need to have a getSvnBranchCommit() method instead. You could for instance use SVNKit or similar for this.
The last thing that is missing now is reading of the file for use in your application.
This could be achieved by simply reading a classpath resource and parsing it into java.util.Properties. You could take it one step further and for instance create accessor methods specifically for each field, e.g getVersion(), getBuild(), etc.
Hope this helps a bit (even though may not be 100% applicable straight off)
Maven can be used to track the version number, e.g.:
<!-- pom.xml -->
<version>2.0.3</version>
Spring Boot can refer to the version, and expose it via REST using Actuator:
# application.properties
endpoints.info.enabled=true
info.app.version=#project.version#
Then use Ajax to render the version in the browser, for example using Polymer iron-ajax:
<!-- about-page.html -->
<iron-ajax auto url="/info" last-response="{{info}}"></iron-ajax>
Application version is: [[info.app.version]]
This will then show in the browser as:
Application version is: 2.0.3
I'm sure you've probably figured something out since this is an older question, but here's what I just did and it looks good. (Getting it into the banner requires you to duplicate a lot).
I'd recommend switching to git (it's a great SVN client too), and then using this in your build.gradle:
// https://github.com/n0mer/gradle-git-properties
plugins {
id "com.gorylenko.gradle-git-properties" version "1.4.17"
}
// http://docs.spring.io/spring-boot/docs/current/reference/html/deployment-install.html
springBoot {
buildInfo() // create META-INF/build-info.properties
}
bootRun.dependsOn = [assemble]
And this in your SpringBoot application:
#Resource
GitProperties props;
#Resource
BuildProperties props2;
Or this way to expose those properties into the standard spring environment:
#SpringBootApplication
#PropertySources({
#PropertySource("classpath:git.properties"),
#PropertySource("classpath:META-INF/build-info.properties")
})
public class MySpringBootApplication {
and then referencing the individual properties as needed.
#Value("${git.branch}")
String gitBranch;
#Value("${build.time}")
String buildTime;

How to deploy a Ruby class in a Java web project

I am trying to create an hybrid between a JRuby and a Java application, so that it may be possible to migrate single components at a time. What I am trying to do right now is really simple, here is the Ruby class:
require 'java'
java_package 'eu.netprophecy.test'
class RubyViewModel
java_signature 'String getGreeting()'
def getGreeting
puts "Hello, ZK, from Ruby!"
end
end
I want to be able to use this View Model from a ZK project:
<?page title="Hello, Ruby!" contentType="text/html;charset=UTF-8"?>
<zk>
<window title="Hello Ruby!!" border="normal" width="200px" apply="org.zkoss.bind.BindComposer"
viewModel="#id('vm') #init('eu.netprophecy.test.RubyViewModel')">
<label value="#load(vm.greeting)"/>
</window>
</zk>
I tried creating a jar with marbler, but it places the .class file with the java bytecode in a directory with the project name in front, messing with the expected package structure (in this case I get EJB/eu/netprophecy/test/RubyViewModel, which means I am unable to use the generated Java class in the Java code).
Does anyone know if this is at all possible, if there are better ways to do it,, or if I have to create manually the jar?
you need to generate a java class from your ruby class which is perfectly possible (even without pre-compilation) with become_java!, just make sure the ruby script gets executed before the view is rendered (or compiled I'm not sure what you're using).
class RubyViewModel
java_signature 'String getGreeting()'
def getGreeting
puts "Hello, ZK, from Ruby!"
end
end
require 'jruby/core_ext'
RubyViewModel.become_java! # returns a java.lang.Class
you might check the method is there (the java way) using :
RubyViewModel.java_class.getDeclaredMethods.map { |method| method.to_s }

How can I programmatically add build files to Xcode4?

I've been trying to figure out how to programmatically add files to an Xcode4 project and it seemed like AppleScript would be the way to go, however I'm running into "missing value" errors.
Here's the code I've got:
tell application "Xcode"
set theProject to first project
set theTarget to first target of theProject
set theBuildPhase to compile sources phase of theTarget
tell first group of theProject
set theFileRef to make new file reference with properties {full path:"/Users/jeff/Projects/XcodeTest/XcodeTest/MyViewController.h", name:"MyViewController.h", path:"XcodeTest/MyViewController.h", path type:group relative}
add theFileRef to theProject
end tell
--tell theBuildPhase to make new build file with properties {build phase:theBuildPhase, name:"MyViewController.h", file reference:theFileRef, target:theTarget, project:theProject}
end tell
I've tried the commented-out line instead of the add-command as well, but that doesn't work either (I get "missing value").
The 'add' error is:
error "Xcode got an error: file reference id \"251AD3431432472E006E300F\" of Xcode 3 group id \"251AD32C14324645006E300F\" of project \"XcodeTest\" of workspace document \"XcodeTest.xcodeproj/project.xcworkspace\" doesn’t understand the add message." number -1708 from file reference id "251AD3431432472E006E300F" of Xcode 3 group id "251AD32C14324645006E300F" of project "XcodeTest" of workspace document "XcodeTest.xcodeproj/project.xcworkspace"
The "make new reference" does add the file to the list of files in Xcode, but I also need it to be added to the project target so that I can add actions and outlets to the file from Xcode w/o having to first check the checkbox to add it to the "target membership".
I ended up sending this question to the devs on the xcode developer list and the response I got was effectively "you can't".
This appears to be completely broken in Xcode4, but I've seen a project that does it. I think what they are doing is parsing and modifying the "project.pbxproj" file directly. (this file is hidden inside the xcodeproj bundle)
The file is a GUID soup, but once you look at it for a while it seems possible to safely modify it, especially if you are only adding stuff.
Edit:
Found this stackoverflow answer that might help.
Tutorial or Guide for Scripting XCode Build Phases
There is a poorly documented user defined build setting that can be added. Files can be both excluded and included from compilation
Go to your target's Build Settings > Tap the + button > Add User-Defined Setting
The key is either INCLUDED_SOURCE_FILE_NAMES or EXCLUDED_SOURCE_FILE_NAMES
The value is a space separated list of file paths
See reference:
http://lists.apple.com/archives/xcode-users/2009/Jun/msg00153.html

"Link" against a SWC in Flex

I'm trying to do a very simple app in Flash/Flex, that loads an image embedded in the swf itself and then shows it. The thing is I'm trying to do it using the command line only (mxmlc and compc) and without using #Embed, and failing miserably.
I have a very simple Main.as :
package
{
import flash.display.*;
import flash.utils.*;
public class Main extends Sprite
{
public function Main () : void
{
var pDef:Class = getDefinitionByName("icon_big.png") as Class;
var _image:BitmapData = new pDef(0, 0);
var pSprite:Sprite = new Sprite();
pSprite.graphics.beginBitmapFill(_image);
pSprite.graphics.drawRect(0, 0, _image.width, _image.height);
pSprite.graphics.endFill();
addChild(pSprite);
}
}
}
This works fine if I add icon_big.png to the Library using the Flash IDE, but I can't figure out how to do it from the command line.
I'm using compc to put the png inside a swc :
compc --include-file icon_big.png icon_big.png -output assets.swc
This generates a 17 kb assets.swf, slightly bigger than icon_big.png. Then I try to compile and link Main.as :
mxmlc -include-libraries+=assets.swc Main.as
This produces a 944 byte Main.swf, which clearly doesn't include the asset, and fails at runtime.
According to the mxmlc docs I found, -include-libraries should link with every class, including the ones not directly referenced by code (as is the case here, since I'm getting the class from code), and it unsurprisingly fails at runtime.
Note that this same code (or, more precisely, quite equivalent code) works when used within a Flash project - I'm not looking to fix the code, but how to do in the command line whatever Flash does internally.
I feel I'm just "not getting" something... any clues?
I recommend you to download the swftools from swftools.org. Once you have them, run:
swfdump -D assets.swf
Take a look in particular at the output which relates to SWF tag with value 76 (0x4C), called SYMBOLCLASS.
Here is an example of an exported class, named IntegerMemberBySlot:
[04c] 24 SYMBOLCLASS
exports 0001 as "IntegerMemberBySlot"
What symbols are you exporting from your assets.swf?
Have you tried adding the path of the assets to your source path parameter when compiling with mxmlc?
-source-path ./PATH/TO/ASSET
I think you need to embed the PNGs in a class, then compile that class into a SWC. I don't think you can put the PNGs directly into a SWC like you are trying to, but I could be wrong.
I had a similar situation (large project, resource swc with graphic assets), and no matter what I tried, I could't get Flex to include assets and classes not directly referenced from the project (I wanted to include different skins, and then instantiate the proper one at runtime, depending on the configuration).
Finally, I found a workaround by instead of static swc liking, switching over to runtime shared libraries (RSLs). Basically, flex unbundles the swc, and loads and links the included swf in runtime, before running the application itself. All of the classes and assets in the swf are loaded this way. May not be exactly what you're after, but it works for me.

Resources