`action` demo

46 views
Skip to first unread message

Zhanbang He

unread,
Apr 8, 2023, 11:20:05 PM4/8/23
to gn-dev
hi all, Could anyone give me a simple demo for `action` as below ?

Dependencies: target A(do some gcc-compiled) depends on Action B.

Dirk Pranke

unread,
Apr 10, 2023, 7:05:23 PM4/10/23
to Zhanbang He, gn-dev
Hi,

You can see a very small demo GN project at https://https://github.com/dpranke/minimal_gn .

If you substitute `hello` for A, `world` for B and `clang-compiled` for gcc-compiled, it'll show you
what you want.

But, copy-pasting that here so that you don't actually need to go look at the project:

action("world") {
  gen_dir = "./gen"

  script = "generate_world.py"
  args = [
    gen_dir,
    "world.cc",
    "world.h",
  ]
  outputs = [
    "$root_build_dir/$gen_dir/world.cc",
    "$root_build_dir/$gen_dir/world.h",
  ]
}

executable("hello") {
  sources = [ "hello.cc" ] + get_target_outputs(":world")
  include_dirs = [ "$root_build_dir/gen" ]
  libs = [ "c++" ]
  deps = [ ":world" ]
}


On Sat, Apr 8, 2023 at 8:20 PM Zhanbang He <hezha...@gmail.com> wrote:
hi all, Could anyone give me a simple demo for `action` as below ?

Dependencies: target A(do some gcc-compiled) depends on Action B.

--
To unsubscribe from this group and stop receiving emails from it, send an email to gn-dev+un...@chromium.org.
Message has been deleted
Message has been deleted

Zhanbang He

unread,
Apr 11, 2023, 11:14:58 AM4/11/23
to gn-dev, dpr...@google.com, gn-dev, Zhanbang He
hi @dpr, I make a demo https://github.com/liyoubdu/minimal_gn.git based on that you gave me https://github.com/dpranke/minimal_gn  .

here is my step:
1.change content in file `flag.txt`.
2.run `ninja -C out -j 1 -v`
3.run `out/hello`.
4.repeat steps 1 through 3

something wrong:
string value from `world()` in `out/hello` is different from out/gen/world.h.

my commands below:
 echo =============================1 && \
 echo $(( $RANDOM % 5000 + 1 )) > flag.txt && \
 echo =============================2 && \
 ninja -C out -j 1 -v && \
 echo =============================3 && \
 cat out/gen/world.h && \
 echo =============================4 && \
 out/hello

Charles Nicholson

unread,
Apr 11, 2023, 11:33:42 AM4/11/23
to Zhanbang He, gn-dev, dpr...@google.com
This one is tricky and I've bumped into it once or twice.

From the manual:
 For binary targets (source sets, executables, and libraries), the known file
  types will be compiled with the associated tools. Unknown file types and
  headers will be skipped. However, you should still list all C/C+ header files
  so GN knows about the existence of those files for the purposes of include
  checking.

GN simply ignores header files that are added to sources when determining dependencies, I guess because it assumes ninja's deps system will handle it correctly. If you add the ":world" target outputs as _inputs_ intead of _sources_, GN gets it right:

executable("hello") {
  sources = [ "hello.cc" ]
  inputs = get_target_outputs(":world")

  include_dirs = [ "$root_build_dir/gen" ]
  libs = [ "c++" ]
  deps = [ ":world" ]
}

Charles Nicholson

unread,
Apr 11, 2023, 3:30:24 PM4/11/23
to Zhanbang He, gn-dev, dpr...@google.com
Re-reading this, it does feel like a bug to me, or at least a user-hostile experience. It makes sense that GN doesn't try to compile a .h file, but at the same time, the GN user explicitly added a file to the "sources" section of a target, and GN silently dropped an explicit file dependency on the floor.

It's definitely surprising behavior, even if it is documented. Additionally, the documentation isn't particularly clear on what "skipped" means; it's very easy to read it as "won't be compiled" and not "will be fully ignored for both build and dependency purposes".

Charles

Brett Wilson

unread,
Apr 11, 2023, 3:38:05 PM4/11/23
to Charles Nicholson, Zhanbang He, gn-dev, dpr...@google.com
On Tue, Apr 11, 2023 at 12:30 PM Charles Nicholson <charles....@gmail.com> wrote:
Re-reading this, it does feel like a bug to me, or at least a user-hostile experience. It makes sense that GN doesn't try to compile a .h file, but at the same time, the GN user explicitly added a file to the "sources" section of a target, and GN silently dropped an explicit file dependency on the floor.

It's definitely surprising behavior, even if it is documented. Additionally, the documentation isn't particularly clear on what "skipped" means; it's very easy to read it as "won't be compiled" and not "will be fully ignored for both build and dependency purposes".

GN is expecting you to hook up your compiler's dependency tracking for files included by your source files to the Ninja build. This will automatically discover the transitive set of include files and will cause rebuilds as necessary.

This behavior is critical to build performance. As an example, changing any file in Chrome's base target (depended on by almost everything) would rebuild the entire build graph rather than just the files that need rebuilding.

Brett

Dirk Pranke

unread,
Apr 11, 2023, 3:38:28 PM4/11/23
to Charles Nicholson, Zhanbang He, gn-dev
1) get_target_outputs only works for targets within the same BUILD.gn file. If you want to move the ':world' target to a different file, you'll need to add a source_set()  target in the same file as the world target, and have the source_set argument call get_target_outputs(). Then make :hello depend on the source_set.

2) If I understand correctly, you're wondering why if you touch flag.txt, world.h is regenerated but hello.o isn't being recompiled? If so, that would be a bad bug in (one or both of) GN and Ninja if the rules were written correctly. Fortunately, it turns out that my sample project had a bug and the rules weren't being written correctly. I missed the `depfile` variable declaration on the cxx tool, and so we weren't telling Ninja to look in obj/hello.o.d, even though it was being compiled correctly.


On Tue, Apr 11, 2023 at 12:30 PM Charles Nicholson <charles....@gmail.com> wrote:

Dirk Pranke

unread,
Apr 11, 2023, 3:43:55 PM4/11/23
to Brett Wilson, Charles Nicholson, Zhanbang He, gn-dev
On Tue, Apr 11, 2023 at 12:38 PM Brett Wilson <bre...@chromium.org> wrote:
On Tue, Apr 11, 2023 at 12:30 PM Charles Nicholson <charles....@gmail.com> wrote:
Re-reading this, it does feel like a bug to me, or at least a user-hostile experience. It makes sense that GN doesn't try to compile a .h file, but at the same time, the GN user explicitly added a file to the "sources" section of a target, and GN silently dropped an explicit file dependency on the floor.

It's definitely surprising behavior, even if it is documented. Additionally, the documentation isn't particularly clear on what "skipped" means; it's very easy to read it as "won't be compiled" and not "will be fully ignored for both build and dependency purposes".

GN is expecting you to hook up your compiler's dependency tracking for files included by your source files to the Ninja build. This will automatically discover the transitive set of include files and will cause rebuilds as necessary.

Yup. Our replies crossed in the ether, but my sample project had a bug :). See this change for the fix.

Sorry for the confusion. There may be other situations where Charles' workaround is necessary, but I don't think this is one of them. It should not be necessary and you don't need to declare inputs to anything other than the action() target.

-- Dirk

Charles Nicholson

unread,
Apr 11, 2023, 4:05:40 PM4/11/23
to Dirk Pranke, Brett Wilson, Zhanbang He, gn-dev
Ah, thanks for the corrections. Are there legitimate cases where you don't want "deps" in a c/c++ compile tool? Could GN warn there?
Reply all
Reply to author
Forward
0 new messages