How to change compiler switches?

Apologies if this is answered somewhere, I searched for a while and couldn't find it.

The Arduino IDE seems to set various compiler switches, amongst them:

-Os -w -fno-exceptions -ffunction-sections -fdata-sections

I have a couple of concerns about this. For one thing I usually use -Wall to get maximum warnings. Also I note that the -Os switch causes this behaviour apparently:

When optimizing with -Os ... any function up to 30 "estimated insns" in size will be considered for inlining.

A little while back I tried to reduce code size by moving duplicated instructions to a function, however the code size did not change. Possibly the compiler chose to inline the function for me, thus defeating my well-meaning attempts. This is of some concern where we are trying to fit the maximum code in a small amount of memory. (Right now I can't reproduce it unfortunately).

My question is two-fold:

  • Can the compiler switches be changed by altering some configuration file or entry somewhere?

  • Failing that, if I wanted to compile "manually" is there a recommended way of doing it? I can see from the verbose output that the normal behaviour compiles lots of library files (and your own sketch of course), turns them into xxx.a files, and then links the whole lot together at the end.

You cannot change the compiler flags without re-compiling the source.

The flags are set in app/src/processing/app/debug/Compiler.java:

    List baseCommandLinker = new ArrayList(Arrays.asList(new String[] {
      avrBasePath + "avr-gcc",
      "-Os",
      "-Wl,--gc-sections"+optRelax,
      "-mmcu=" + boardPreferences.get("build.mcu"),
      "-o",
      buildPath + File.separator + primaryClassName + ".elf"
    }));

The only other alternative is to compile outside of the IDE. There are various makefiles around to do the job if you want to have a go.

Here’s a patch so you can set options in the preferences file. It also removes the -w switch, because that can’t be overridden (even with -Wall, to the best of my knowledge). It’s from the Aprli 24, 2012 commit (64f8f0aa62cb2248aa4086f4de0c5cecb4ca5fed). You make options in the preferences file with build.[verbose.]{s,c,cpp}flags and each switch is space-separated.

diff --git a/app/src/processing/app/debug/Compiler.java b/app/src/processing/app/debug/Compiler.java
index 2995366..0b71c4d 100644
--- a/app/src/processing/app/debug/Compiler.java
+++ b/app/src/processing/app/debug/Compiler.java
@@ -536,6 +536,18 @@ public class Compiler implements MessageConsumer {
       "-DARDUINO=" + Base.REVISION,
     }));
 
+    String flags = Preferences.get("build.sflags");
+    if (Preferences.getBoolean("build.verbose" )) {
+        String verboseflags = Preferences.get("build.verbose.sflags");
+        if (verboseflags != null) flags += " " + verboseflags;
+    }
+    if (flags != null) {
+        String[] splitflags = flags.split(" +"); // Split with 1 or more spaces
+        for (String flag : splitflags) {
+            baseCommandCompiler.add(flag);   
+        }
+    }
+
     for (int i = 0; i < includePaths.size(); i++) {
       baseCommandCompiler.add("-I" + (String) includePaths.get(i));
     }
@@ -555,7 +567,7 @@ public class Compiler implements MessageConsumer {
       "-c", // compile, don't link
       "-g", // include debugging info (so errors include line numbers)
       "-Os", // optimize for size
-      Preferences.getBoolean("build.verbose") ? "-Wall" : "-w", // show warnings if verbose
+      //Preferences.getBoolean("build.verbose") ? "-Wall" : "-w", // show warnings if verbose
       "-ffunction-sections", // place each function in its own section
       "-fdata-sections",
       "-mmcu=" + boardPreferences.get("build.mcu"),
@@ -563,6 +575,18 @@ public class Compiler implements MessageConsumer {
       "-MMD", // output dependancy info
       "-DARDUINO=" + Base.REVISION,
     }));
+
+    String flags = Preferences.get("build.cflags");
+    if (Preferences.getBoolean("build.verbose" )) {
+        String verboseflags = Preferences.get("build.verbose.sflags");
+        if (verboseflags != null) flags += " " + verboseflags;
+    }
+    if (flags != null) {
+        String[] splitflags = flags.split(" +"); // Split with 1 or more spaces
+        for (String flag : splitflags) {
+            baseCommandCompiler.add(flag);   
+        }
+    }
 		
     for (int i = 0; i < includePaths.size(); i++) {
       baseCommandCompiler.add("-I" + (String) includePaths.get(i));
@@ -585,7 +609,7 @@ public class Compiler implements MessageConsumer {
       "-c", // compile, don't link
       "-g", // include debugging info (so errors include line numbers)
       "-Os", // optimize for size
-      Preferences.getBoolean("build.verbose") ? "-Wall" : "-w", // show warnings if verbose
+      //Preferences.getBoolean("build.verbose") ? "-Wall" : "-w", // show warnings if verbose
       "-fno-exceptions",
       "-ffunction-sections", // place each function in its own section
       "-fdata-sections",
@@ -595,6 +619,18 @@ public class Compiler implements MessageConsumer {
       "-DARDUINO=" + Base.REVISION,
     }));
 
+    String flags = Preferences.get("build.cppflags");
+    if (Preferences.getBoolean("build.verbose" )) {
+        String verboseflags = Preferences.get("build.verbose.sflags");
+        if (verboseflags != null) flags += " " + verboseflags;
+    }
+    if (flags != null) {
+        String[] splitflags = flags.split(" +"); // Split with 1 or more spaces
+        for (String flag : splitflags) {
+            baseCommandCompilerCPP.add(flag);   
+        }
+    }
+
     for (int i = 0; i < includePaths.size(); i++) {
       baseCommandCompilerCPP.add("-I" + (String) includePaths.get(i));
     }

(Please excuse any mistakes; I’ve never done a patch before)

ultimately you could write a wrapper (e.g. in C#) that intercepts the avrgcc call and replaces the params with those of your choice....

Or switch to using mpide instead that allows you to set compiler and linker options on a per board basis. Although if you are using 1.0 capabilities this isn't an option as mpide isn't using the 1.0 core files yet.