conditional compilation

444 views
Skip to first unread message

Doug Snyder

unread,
Mar 7, 2013, 6:30:38 PM3/7/13
to mi...@dartlang.org
is there a way to do conditional compilation in dart?

i wasn't able to find anything online

thanks,
doug

Seth Ladd

unread,
Mar 7, 2013, 7:07:02 PM3/7/13
to General Dart Discussion
Hi Doug,

Thanks for reaching out! We've been working on a deferred library loading solution. Can you tell us more about what you're trying to do?

Thanks!
Seth



--
Consider asking HOWTO questions at Stack Overflow: http://stackoverflow.com/tags/dart
 
 

Doug Snyder

unread,
Mar 8, 2013, 12:58:43 AM3/8/13
to mi...@dartlang.org
i was looking to do similar to what can be done in C

for example:

class A
{
#if OPTION_X
    int i;
#elif OPTION_Y
    double d;
#endif

  A()
  {
#if OPTION_X
    i = 5;
#elif OPTION_Y
    d = 17.5;
#endif
  }

  void Update()
  {
#if OPTION_X
    i += 2;
#elif OPTION_Y
    d += 1.75;
#endif
  }

}


if OPTION_X is defined, only the variables/code associated with OPTION_X are generated/compiled

this capability can be used to target different browsers, generate different build versions and enable/disable debug code

doug

Lasse R.H. Nielsen

unread,
Mar 8, 2013, 3:49:39 AM3/8/13
to mi...@dartlang.org
Since Dart is distributed as source code, not compiled code, there really isn't a "compilation" step in the traditional sense. I think it would be better to have a preprocessing step that removed all the unnecessary code. It's better than sending extra code to a browser and having it ignored there.

Ofcourse that requires the tests to be statically determinable. If the tests require data that can only be detected at runtime, they really become normal conditionals, not optional "compilation". 

/L


--
Consider asking HOWTO questions at Stack Overflow: http://stackoverflow.com/tags/dart
 
 



--
Lasse R.H. Nielsen - l...@google.com  
'Faith without judgement merely degrades the spirit divine'
Google Denmark ApS - Frederiksborggade 20B, 1 sal - 1360 København K - Denmark - CVR nr. 28 86 69 84

Seth Ladd

unread,
Mar 8, 2013, 12:40:41 PM3/8/13
to General Dart Discussion, Justin Fagnani
Agreed, I think with annotations like @devonly we might be able to remove some of the code from the compiled output?

It sounds like there are two goals here:

1) omit dev-time only code from the shipped product
2) generated different versions of the app, based on experiments or other

We've heard #2 before. Conditionally loading libraries might help here. Not sure how others are thinking of attacking this problem. @Justin?

For #1, the example here might be "remove all logging statements". Do we need something more than annotations here?

@Doug, where do these items fall on your list of priorities?

Kevin Moore

unread,
Mar 8, 2013, 12:44:12 PM3/8/13
to mi...@dartlang.org, Justin Fagnani
https://code.google.com/p/dart/issues/detail?id=7238

This issue may be too broad. It basically asks for something, with references to Closure Compiler and .NET features.

Doug Snyder

unread,
Mar 8, 2013, 1:00:58 PM3/8/13
to mi...@dartlang.org
this is not a high priority request.  it would make some things easier, though.


Justin Fagnani

unread,
Mar 8, 2013, 1:40:37 PM3/8/13
to Seth Ladd, General Dart Discussion
On Fri, Mar 8, 2013 at 9:40 AM, Seth Ladd <seth...@google.com> wrote:
Agreed, I think with annotations like @devonly we might be able to remove some of the code from the compiled output?

It sounds like there are two goals here:

1) omit dev-time only code from the shipped product
2) generated different versions of the app, based on experiments or other

We've heard #2 before. Conditionally loading libraries might help here. Not sure how others are thinking of attacking this problem. @Justin?

re #2: I think conditional loading is a good way to approach this, but for large apps with experiments systems, it will probably be important to structure the app in fine-grained and encapsulated enough libraries to be able to swap them out with out wanting conditional compilation within the library. Hopefully many experiments will be possible without even conditional libraries. Minification/obfuscation might be enough to allow experiments based on flags.
 
For #1, the example here might be "remove all logging statements". Do we need something more than annotations here?

Annotations currently aren't allowed in all the places needed for this. I don't think they're allowed on statements, for example, which would be required for annotated blocks like:

@devonly {
  onlyInDev();
}

However we have built experimental systems that allow transformations based on function calls like:

devonly(() {
  onlyInDev();
});

The nice thing about this is that without the compilation step you can still control whether the code is executed. devonly() would implemented like this:

bool dev = true;
void devonly(f) {
  if (dev) f();
}

And removing the call is an optional optimization. This is an important property I'd like to see maintained with any compilation step, that the compilation is optional and the program still runs correctly without it. It may require a non-production environment, like Dartium, but it'll still run in development without forcing a compiler run, preserving the fast edit-refresh cycle.

Another nice thing about annotations or function based transformation is that we can do it in a way that guarantees there are no syntax errors after processing. I'd personally hate to see an extra-linguistic pre-processor system in Dart.

-Justin

Seth Ladd

unread,
Mar 8, 2013, 1:58:24 PM3/8/13
to Justin Fagnani, General Dart Discussion
See inline below...


On Fri, Mar 8, 2013 at 10:40 AM, Justin Fagnani <justin...@google.com> wrote:



On Fri, Mar 8, 2013 at 9:40 AM, Seth Ladd <seth...@google.com> wrote:
Agreed, I think with annotations like @devonly we might be able to remove some of the code from the compiled output?

It sounds like there are two goals here:

1) omit dev-time only code from the shipped product
2) generated different versions of the app, based on experiments or other

We've heard #2 before. Conditionally loading libraries might help here. Not sure how others are thinking of attacking this problem. @Justin?

re #2: I think conditional loading is a good way to approach this, but for large apps with experiments systems, it will probably be important to structure the app in fine-grained and encapsulated enough libraries to be able to swap them out with out wanting conditional compilation within the library. Hopefully many experiments will be possible without even conditional libraries. Minification/obfuscation might be enough to allow experiments based on flags.
 
For #1, the example here might be "remove all logging statements". Do we need something more than annotations here?

Annotations currently aren't allowed in all the places needed for this. I don't think they're allowed on statements, for example, which would be required for annotated blocks like:

@devonly {
  onlyInDev();
}

However we have built experimental systems that allow transformations based on function calls like:

devonly(() {
  onlyInDev();
});

The nice thing about this is that without the compilation step you can still control whether the code is executed. devonly() would implemented like this:

bool dev = true;
void devonly(f) {
  if (dev) f();
}

And removing the call is an optional optimization. This is an important property I'd like to see maintained with any compilation step, that the compilation is optional and the program still runs correctly without it. It may require a non-production environment, like Dartium, but it'll still run in development without forcing a compiler run, preserving the fast edit-refresh cycle.

Does dart2js (which also powered dart2dart) have the extensibility to let me, the end user, add a plugin and give guidance to remove devonly() from the production output? Asked another way, how far are we from this type of solution?

@Doug, would wrapping sections of code in a function work for you?

Peter Ahé

unread,
Mar 8, 2013, 2:32:29 PM3/8/13
to mi...@dartlang.org, Justin Fagnani


On Friday, March 8, 2013, Seth Ladd wrote:
See inline below...


On Fri, Mar 8, 2013 at 10:40 AM, Justin Fagnani <justin...@google.com> wrote:



On Fri, Mar 8, 2013 at 9:40 AM, Seth Ladd <seth...@google.com> wrote:
Agreed, I think with annotations like @devonly we might be able to remove some of the code from the compiled output?

It sounds like there are two goals here:

1) omit dev-time only code from the shipped product
2) generated different versions of the app, based on experiments or other

We've heard #2 before. Conditionally loading libraries might help here. Not sure how others are thinking of attacking this problem. @Justin?

re #2: I think conditional loading is a good way to approach this, but for large apps with experiments systems, it will probably be important to structure the app in fine-grained and encapsulated enough libraries to be able to swap them out with out wanting conditional compilation within the library. Hopefully many experiments will be possible without even conditional libraries. Minification/obfuscation might be enough to allow experiments based on flags.
 
For #1, the example here might be "remove all logging statements". Do we need something more than annotations here?

Annotations currently aren't allowed in all the places needed for this. I don't think they're allowed on statements, for example, which would be required for annotated blocks like:

@devonly {
  onlyInDev();
}

However we have built experimental systems that allow transformations based on function calls like:

devonly(() {
  onlyInDev();
});

The nice thing about this is that without the compilation step you can still control whether the code is executed. devonly() would implemented like this:

bool dev = true;
void devonly(f) {
  if (dev) f();
}

And removing the call is an optional optimization. This is an important property I'd like to see maintained with any compilation step, that the compilation is optional and the program still runs correctly without it. It may require a non-production environment, like Dartium, but it'll still run in development without forcing a compiler run, preserving the fast edit-refresh cycle.

Does dart2js (which also powered dart2dart) have the extensibility to let me, the end user, add a plugin and give guidance to remove devonly() from the production output? Asked another way, how far are we from this type of solution?

I think dart2js will eventually support things like that, using the mirror API to reflect on source code instead of a live system. But it is not something we're actively pursuing at this time. Language feature completeness and performance is much more important right now.

However, you can really accomplish a lot with a const bool, subclassing, and factory methods. If dart2js sees code like this:

const DEBUG = false;

class ProductionBehavior {
  factory ProductionBehavior() {
    return DEBUG ? new DebugBehavior() : new ProductionBehavior.internal();
  }
  ProductionBehavior.internal();
  log(message) {}
}
class DebugBehavior extends ProductionBehavior {
  DebugBehavior() : super.internal();
  log(message) {
    doTheHarlemShake();
    print(message);
  }
}

main() {
  new ProductionBehavior().log('Embarrassing fact about my company');
}

You can rest assured that the code you send to your customers will not do the Harlem shake. In fact, DebugBehavior will not even be included in the generated JavaScript, and neither should the string 'Embarrassing fact about my company'.

Cheers,
Peter

Justin Fagnani

unread,
Mar 8, 2013, 4:55:47 PM3/8/13
to Peter Ahé, mi...@dartlang.org
This is now one of my favorite code examples in recent times :)

The tree-shaking will also work for functions, correct? How much of this would be included in the final output?

const DEV = false;

void devonly(f) {
  if (DEV) f();
}

devonly(() { print("shake"); });

And is the compiler smart enough inline the body of f() when DEV is true?

-Justin
Message has been deleted
Message has been deleted

Ladislav Thon

unread,
Mar 10, 2013, 7:47:50 AM3/10/13
to mi...@dartlang.org

Why this is not done in the traditional way?
With a traditional source code preprocessing.

You can run cpp (the C preprocessor) on any file, even a Dart source code. So you can do this
 
// Predefined macro
#if WEB_CLIENT
// Code for client side
#else
// Code for server side
#end

#if WEB_CLIENT
#error Illegal use of this library in the web client
#end

// Macro passed to cmd line args, e.g -dDEVELOPMENT
#if DEVELOPMENT
const String mode = 'DEVELOPMENT';
#else
const String mode = 'PRODUCTION';
#end

today, without any issues.

LT
Message has been deleted
Message has been deleted
Message has been deleted

Ladislav Thon

unread,
Mar 10, 2013, 10:25:54 AM3/10/13
to mi...@dartlang.org

@Ladislav Thon
>> You can run cpp (the C preprocessor) on any file, even a Dart source code. So you can do this
>> today, without any issues.

Again you're kidding?

You suggested source code preprocessing, I just mentioned that you can already do that. Anything beyond is out of my interest.

LT
Message has been deleted
Message has been deleted
Message has been deleted
Message has been deleted

Dirk Detering

unread,
Mar 10, 2013, 12:53:52 PM3/10/13
to mi...@dartlang.org

Andrew,

we all know what  pre-processing directives are and what they are used for. No need to quote full passages of encyclopedias at a large!

And I also think that Lasse has cleary described the differences between a language that is truely compiled at build time on

2.5 Pre-processing directives


Visual Studio .NET 2003

The pre-processing directives provide the ability to conditionally skip sections of source files, to report error and warning conditions, and to delineate distinct regions of source code. The term "pre-processing directives" is used only for consistency with the C and C++ programming languages. In C#, there is no separate pre-processing step; pre-processing directives are processed as part of the lexical analysis phase.

Message has been deleted

Alex Tatumizer

unread,
Mar 10, 2013, 1:59:19 PM3/10/13
to mi...@dartlang.org, mail...@googlemail.com
Mezoni, you have to be aware that the place you often cite as a source of good ideas has many angry and hungry lawyers, who are just waiting for the occasion to come after someone and make his life miserable.
Be very afraid !!!
LOL
  


Greg Lowe

unread,
Mar 10, 2013, 4:24:49 PM3/10/13
to mi...@dartlang.org
Just use the cpp command. I've used this with javascript before. It gets the job done, so that you can focus on more important things.

cpp [
-Dmacro[=defn]...] infile outfile


If you're stuck on windows, then you'll probably need to install cygwin, or gcc.

cpp -DWEB_CLIENT=1 code-with-directives.dart code-without.dart

#if WEB_CLIENT
// Code for client side
#else
// Code for server side
#end

When conditional compilation support lands in dart, then change your code to use that.
Reply all
Reply to author
Forward
Message has been deleted
0 new messages