Forcing compiler flags on deps

50 views
Skip to first unread message

Raghu Krishnamurthy

unread,
Feb 22, 2021, 7:13:54 PM2/22/21
to gn-dev
Hello experts,

I'm working on a GN project(https://git.trustedfirmware.org/hafnium/hafnium.git/), mostly a C project,  and i'm trying to find out how i can do the following. I've tried using gn help and looking through the gn referece docs but could not really find the answer.

I have target, that is a template, that eventually compiles into an executable. The target has the 'deps' field which contain only source_set's containing C files. Each source_set has its own public_config that includes extra defines and flags as required by the source set. What i want to be able to do is to use the same source_sets and create two different target executables, that only differ in a few flags. For example, i want target1 to have -DFOO and target2 to not have -DFOO. If i add a config at the target level, it only applies while linking but not to all the source_set's that the target depends on, ie. all the C files in both target1 and target2 dont compile with -DFOO. I have an example with comments:

config("myconfig_a") {
  defines = ["DEFINESFOR_A"]
}

config("myconfig_b") {
  defines = ["DEFINESFOR_B"]
}

config("myconfig_target1") {
  defines = ["FOO"]
}

source_set("src_a") {
  public_configs = [":myconfig_a"]
  sources = ["a.c"]
}

source_set("src_b") {
  public_configs = [":myconfig_a"]
  sources = ["a.c"]
}

template("my_target") {
  executables(target_name) {
   forward_variables_from(invoker,  [cflags, cflags_c, defines,public_configs, sources])
  }
}

my_target("target1") {
 public_configs = [":myconfig_target1"]
# I want c files in src_a and src_b to also include myconfig_target1 defines
# THIS DOES NOT WORK AS I WANT IT TO
 deps= [
    ":src_a",
    ":src_b"
  ]
}

my_target("target2") {
# I want c files in src_a and src_b to NOT include myconfig_target1 defines
 # THIS WORKS AS EXPECTED
 deps= [
    ":src_a",
    ":src_b"
  ]
}

Thanks
Raghu

Brett Wilson

unread,
Feb 22, 2021, 7:20:53 PM2/22/21
to Raghu Krishnamurthy, gn-dev
The public configs thing applies only to the targets that depend on you.

A target can never modify its dependencies. Otherwise, that creates a situation where that other target has an ambiguous definition based on who is depending on it. In addition to forcing a target to have multiple definitions, this would also create unsolvable build graphs if the same target is referred as a dependency through multiple paths, each with their own flags.

Brett

raghu....@gmail.com

unread,
Feb 22, 2021, 7:50:42 PM2/22/21
to Brett Wilson, gn-dev

Thanks Brett. Understood. In that case what is the GN way to solve the situation below? How are debug vs production builds typically created for example on a given target? How can I build the same source set with different flags?

Do I just create different source sets for the two targets with different configs?

Brett Wilson

unread,
Feb 22, 2021, 7:57:36 PM2/22/21
to Raghu Krishnamurthy, gn-dev
Most commonly debug and release would be different builds. The developer would then configure their build with the build args. So your BUILDCONFIG.gn would do something like

  declare_args() {
    is_debug = true  # Default to debug build.
  }

And then in your compiler setup code for your build you have something like:

  if (is_debug) {
   cflags = [ ... ]
  } else {
   cflags = [ ... ]
  }

Then the developer would use "gn args" to set or clear the is_debug clag according to what they want. I maintain and out/debug and out/release directory for most of my projects.

If you really need to do this in the same build, you can use toolchains to define a separate debug and release toolchain that both get compiled. But this is more complicated and normally less developer-friendly.

Brett

raghu....@gmail.com

unread,
Feb 22, 2021, 9:09:59 PM2/22/21
to Brett Wilson, gn-dev

Thanks Brett. I think that answers my question.

Reply all
Reply to author
Forward
0 new messages