ndsol / volcano

Get started with Vulkan. Keep it simple, short and sweet. See https://github.com/ndsol/VolcanoSamples
GNU General Public License v3.0
5 stars 1 forks source link

Skia BUILDCONFIG and GN cleanup #5

Closed volcanoauthors closed 7 years ago

volcanoauthors commented 7 years ago

There are several compromises made to apply skia's BUILD.gn and BUILDCONFIG.gn to the larger Volcano project.

  1. Symlinks. Skia's gn and third_party dirs and Volcano vendor dirs use symlinks due to a GN limitation.
  2. Skia does not have a supported way to build for Android on a Windows machine.
  3. Skia does not support cross-compiling well: the toolchain definitions in gn/BUILD.gn do not support building host tools while cross-compiling. Chromium does support this, so this is down to skia's BUILD.gn and toolchain setup being a little sparse.
volcanoauthors commented 7 years ago

@Qix- has surveyed the major build systems used for native development.

From https://github.com/facebook/buck/issues/939:
![Qix](https://avatars2.githubusercontent.com/u/885648?v=3&s=88) @Qix- commented on Oct 12, 2016
I know there was some [discussion a while back](https://github.com/facebook/buck/issues/130#issuecomment-45268067) about `.buckconfig` files being mandatory. This anti-nesting paradigm is ultimately the reason why I have personally strayed away from build systems like [Bazel](https://github.com/bazelbuild/bazel) and (now, potentially) Buck. Let's start with the needless empty `.buckconfig` file: I'm still getting the following ``` console $ buck --version buck version de38173cc0b9de07cb129298191280260a6c35e0 $ buck build //:foo This does not appear to be the root of a Buck project. Please 'cd' to the root of your project before running buck. If this really is the root of your project, run 'touch .buckconfig' and then re-run your buck command. ``` This whole concept of "project roots" throws a wrench into the whole [modularity thing](https://12factor.net/dependencies) (link is to factor 2). Why? Because you can't nest modules anymore. At least, not in any clear or direct way. **Projects/repositories will (should) never know if they're really the "project root".** --- Here's an example. Let's take [this sample repository](https://github.com/Qix-/nested-buck) that has a dependency within a dependency. At a glance, here is the directory structure for each dependency: ``` /BUCK /ext/names/BUCK /ext/names/ext/compiler/BUCK <------ downstream --------- -------- upstream ---------> ``` In the real world, each of the above would be a dependency of some sort, either via a submodule or some package manager. Each dependency is **completely unaware of their consumers (downstream dependents)** and merely expose a `'PUBLIC'`-ly visible member for the outer codebase (downstream dependent) to consume. Let's take a look at the compilation chain here, starting first with the inner-most dependency. All it does is export a single executable script using `genrule()` (since [`export_file()` doesn't support executables](https://github.com/facebook/buck/issues/938)). Compiling it by itself is, of course, just fine. ``` console $ cd ext/names/ext/compiler $ buck build //:compiler Using watchman. [-] PROCESSING BUCK FILES...FINISHED 0.0s [100%] 🐳 New buck daemon [-] DOWNLOADING... (0.00 B/S AVG, TOTAL: 0.00 B, 0 Artifacts) [-] BUILDING...FINISHED 0.6s [100%] (1/1 JOBS, 1 UPDATED, 1 [100.0%] CACHE MISS) ``` Now let's go up a directory and try the `names` project. This project will "build" the compiler if it isn't already built (copied), and will proceed to use it to compile all of the names into a single file. ``` console $ cd ext/names/ $ buck build //:all Using watchman. compiling 2 files [-] PROCESSING BUCK FILES...FINISHED 0.0s [100%] 🐳 New buck daemon [-] DOWNLOADING... (0.00 B/S AVG, TOTAL: 0.00 B, 0 Artifacts) [-] BUILDING...FINISHED 0.6s [100%] (2/2 JOBS, 2 UPDATED, 2 [100.0%] CACHE MISS) ``` Sweet, it appears to have found the compiler and has executed it (the output `compiling 2 files` resulting from our 'compiler' script). Let's go back up to the main repository and try to build it. It uses the names dependency to get a list of all names, and then reverses them. We're in the business of reversing things so this is _really_ our intended output. We don't care that it uses a compiler dependency (the product manager has approved, etc.) thus we're just after its main `all.names` file. ``` console $ buck build //:reversed Using watchman. [-] PROCESSING BUCK FILES...FINISHED 0.0s [100%] 🐳 New buck daemon [+] DOWNLOADING... (0.00 B/S, TOTAL: 0.00 B, 0 Artifacts) [+] BUILDING...0.3s BUILD FAILED: Couldn't get dependency '//ext/compiler:compiler' of target '//ext/names:all': No build file at ext/compiler/BUCK when resolving target //ext/compiler:compiler. ``` Wait a second! Buck is looking for the nested compiler dependency in `/ext`. That's not right! Maybe we need relative paths. Let's apply this diff: ``` diff diff --git a/ext/names/BUCK b/ext/names/BUCK index 6fc3742..e634800 100644 --- a/ext/names/BUCK +++ b/ext/names/BUCK @@ -5,5 +5,5 @@ genrule( name='all', srcs=['a.names', 'b.names'], out='all.names', - cmd='$(exe //ext/compiler:compiler) $SRCS > $OUT', + cmd='$(exe //./ext/compiler:compiler) $SRCS > $OUT', visibility=['PUBLIC']) ``` Cool, now we'll look for `//./ext/compiler:compiler` instead of the root `ext` folder. ``` console $ buck build //:reversed Using watchman. [-] PROCESSING BUCK FILES...FINISHED 0.0s [100%] 🐳 New buck daemon [+] DOWNLOADING... (0.00 B/S, TOTAL: 0.00 B, 0 Artifacts) [+] BUILDING...0.3s BUILD FAILED: Couldn't get dependency '//ext/names:all' of target '//:reversed': //ext/names:all: Build target path cannot be absolute or contain . or .. (found //./ext/compiler:compiler) ``` Alright, what if we drop the `//` altogether? Maybe that means 'relative': ``` diff diff --git a/ext/names/BUCK b/ext/names/BUCK index 6fc3742..34613fe 100644 --- a/ext/names/BUCK +++ b/ext/names/BUCK @@ -5,5 +5,5 @@ genrule( name='all', srcs=['a.names', 'b.names'], out='all.names', - cmd='$(exe //ext/compiler:compiler) $SRCS > $OUT', + cmd='$(exe ext/compiler:compiler) $SRCS > $OUT', visibility=['PUBLIC']) ``` Let's try that. ``` console $ buck build //:reversed [-] PROCESSING BUCK FILES...FINISHED 0.0s [100%] Environment variable changes: [PATH, MANPATH, NVM_PATH, NVM_BIN] [+] DOWNLOADING... (0.00 B/S, TOTAL: 0.00 B, 0 Artifacts) [+] BUILDING...0.2s BUILD FAILED: Couldn't get dependency '//ext/names:all' of target '//:reversed': //ext/names:all: Path in ext/compiler:compiler must start with // ``` Well, what do we do now? Do we really have to re-adjust all of those dependencies to use the root of _our_ repository? What if I (hypothetically) have the source code for [Awesomium](http://www.awesomium.com/) complete with a vendored `BUCK` file by their team, and it in turn has Chromium inside of it with a vendored `BUCK` file vendored by Google. If I build Awesomium by itself, great! It would work, assuming Google doesn't use any nested dependencies. But, when I include it in my own project and use Awesomium as a nested dependency, the whole thing will fail because it will look for Chromium relative to my "project root". --- And thus we have a completely unusable nested dependency system in Buck. CMake has a very similar problem, one which I [addressed](https://gitlab.kitware.com/cmake/cmake/issues/16255#note_156227) a while back, where `CMAKE_SOURCE_DIR` doesn't refer to the directory that houses `CMakeLists.txt` but instead the _some/dir_ when running `cmake some/dir`. The developers insisted all projects update their CMakeLists.txt to use `CMAKE_CURRENT_SOURCE_DIR` instead, which was pretty poorly documented (completely unocumented?) [until version 3.0.2](https://cmake.org/cmake/help/v3.0/variable/CMAKE_CURRENT_SOURCE_DIR.html). While that isn't a problem _now_, most CMakeLists.txt for projects [older than 2014](https://cmake.org/files/v3.0/) that haven't been updated in a while (there are a lot!) will fall fate to this flaw. This renders `add_subdirectory()` very, very spotty in terms of intended functionality. CMake isn't the only culprit. Several build systems fall short in this area, which is troubling since this directly hinders any usable package managers from spawning that can rely on a battle-tested build system instead of using their own and (ab)using strange tricks like symlinks or path variables to do what they do: - [Bazel](https://www.bazel.io/) only has [external](https://www.bazel.io/versions/master/docs/external.html) dependencies and suffers from a very similar limitation to Buck. - [Ninja](https://ninja-build.org/) gets close but [also falls short](https://github.com/ninja-build/ninja/issues/977) with their ambiguous `subninja` function. - [Tup](http://gittup.org/tup/manual.html) also gets close, but places [too many restrictions](http://stackoverflow.com/questions/14301543/why-does-tup-need-one-tupfile-per-directory) on visibility of the files underneath a directory with a `Tupfile`. - GNU Make only has [the `-C` option](https://www.gnu.org/software/make/manual/html_node/Options-Summary.html), which is fine I suppose but you lose out on just about every directed graph benefit with an added cost of increased confusion of how dependencies interact. The whole concept of "project root" kind of sullies non-standard dependency management (e.g. not Java). Substitute the above submodule hierarchy with some package manager (e.g. `npm@2`, which we know is [still used a lot](https://semaphoreci.com/blog/2015/12/15/nodejs-version-usage-in-commercial-projects-2015-edition.html) since `npm@3` doesn't work with node 0.10 and [`nvm`](https://github.com/creationix/nvm) automatically configures `npm@2` all the way up through node 4.0.0!) and you'll run into these problems very quickly. --- There are two proposals here - one is arguably more "philosophically correct" but more-breaky, and the other doesn't get rid of that pesky empty `.buckconfig` file -- but won't break as much. **Proposal 1** I propose the requirement for an empty `.buckconfig` be dropped and instead count on the user running `buck` from within a (sub)directory of a `BUCK` file (i.e. traverse upward until Buck finds a `BUCK` file and run from there). Existing `.buckconfig` files are treated normally. This is pretty much [exactly how Git does it](https://github.com/facebook/buck/issues/130#issuecomment-45235719). Secondly, I propose `//`-prefixed paths refer to the `BUCK` file they are used in. How do I reference rules above the current `BUCK` file? Simple: you don't. This would _philosophically_ enforce that `BUCK` files are considered an upstream dependency and thus should never depend on a downstream dependency (parent directory, in this case) which would ultimately break the dependency chain. This results in one less messy empty dotfile and makes building up project dependencies _much_ cleaner and easier to maintain. **Proposal 2** I propose that `.buckconfig` actually marks a directory as a Buck project (officially). This means that all `//...` paths in all recursive `BUCK` files (that do not, in turn, have a `.buckconfig` sibling) refer to the next parent up directory with a `.buckconfig` file. This is almost identical to the current functionality, though any nested projects that also have a `.buckconfig` file will have their target paths resolve to those respective directories instead of the "project root". --- I understand either of these would introduce a breaking change, though without them, _it makes Buck very hard to adopt_ by ad-hoc languages or environments, especially in the world of native development. Please consider at least addressing this issue and discussing ways to handle such use cases. 💃
![Qix](https://avatars2.githubusercontent.com/u/885648?v=3&s=88) @Qix- commented on Oct 12, 2016
I can't even fix this using the workaround of re-creating the rules in the higher directories right now. ``` [+] PARSING BUCK FILES...0.2s BUILD FAILED: 'ext/arua-bootstrap-grammar/src/arua.leg' in '//:arua-leg' crosses a buck package boundary. This file is owned by 'ext/arua-bootstrap-grammar'. Find the owning rule that references 'ext/arua-bootstrap-grammar/src/arua.leg', and use a reference to that rule instead of referencing the desired file directly. ``` I'm going to have to use an `os.unlink()` call in the main `BUCK` file to remove the nested `BUCK` files in order to get passed the boundary and tell Git to ignore those submodules being dirty. :/ **EDIT:** the workaround: ``` python # XXX temporary - see facebook/buck#939 import os import os.path as path def punlink(*args, **kwargs): try: os.unlink(*args, **kwargs) except: pass punlink('ext/arua-bootstrap-grammar/BUCK') punlink('ext/arua-bootstrap-grammar/.buckconfig') punlink('ext/arua-bootstrap-grammar/ext/BUCK') # XXX end temporary ```
[evancox10](https://github.com/evancox10) commented on Oct 12, 2016
You've hit the nail on the head. I looked at using Buck or Bazel for managing HDL environments (Verilog, SystemVerilog, VHDL, etc.), but lack of support for nesting projects was a show stopper. In Verilog, the basic unit of "code" is actually called a module, so one would think it would be easy to adapt Buck to it. Not so! I'm unable to reuse a module from another Buck project if that modules also happened to reuse sub-modules Thanks for the write-up here.
[sdwilsh](https://github.com/sdwilsh) commented on Oct 13, 2016
I believe the undocumented Cells feature solves this problem. It's undocumented because it's still evolving as the team figures out edge cases that don't work well with it. I believe the Gerrit project uses these to manage some of their third-party dependencies (@davido has filed issues too that has led to improvements of the Cell UI). @mzlee and @philipjameson have also been playing with them and have been helping to improve the Cell UI.
![Qix](https://avatars2.githubusercontent.com/u/885648?v=3&s=88) @Qix- commented on Oct 13, 2016
@sdwilsh I'm not sure I'm following. What are cells? Where can I read about them?
[sdwilsh](https://github.com/sdwilsh) commented on Oct 13, 2016
The best there is right now is probably the integration tests for it (so documentation by example only): https://github.com/facebook/buck/tree/master/test/com/facebook/buck/crosscell/testdata
![Qix](https://avatars2.githubusercontent.com/u/885648?v=3&s=88) @Qix- commented on Oct 13, 2016
From what I can gather about cells, no, this is not what I'm addressing. From what I can tell (since there is no documentation) cells are just sibling directories with Buck projects inside that allow you to reference another sibling. This doesn't solve this problem.
![Coneko](https://avatars0.githubusercontent.com/u/1614903?v=3&s=88) [Coneko](https://github.com/Coneko) commented on Oct 13, 2016
Buck was initially developed for use in a monorepo, and is still pretty biased towards it. We currently use cross cell with a flat hierarchy of cells, so I'm not sure how well it works with nested cells, but at least in theory it should as long as each cell only refers to its child cells, and not other descendants or ancestors. In your example repo, I applied this patch: ``` diff --git a/.buckconfig b/.buckconfig index e69de29..612c65d 100644 --- a/.buckconfig +++ b/.buckconfig @@ -0,0 +1,2 @@ +[repositories] +names=ext/names diff --git a/BUCK b/BUCK index 9ebe9f4..c372eda 100644 --- a/BUCK +++ b/BUCK @@ -1,5 +1,5 @@ genrule( name='reversed', - srcs=['//ext/names:all'], + srcs=['names//:all'], out='reversed.names', cmd='cat $SRCS | rev > $OUT') diff --git a/ext/names/.buckconfig b/ext/names/.buckconfig index e69de29..205fa39 100644 --- a/ext/names/.buckconfig +++ b/ext/names/.buckconfig @@ -0,0 +1,2 @@ +[repositories] +compiler=ext/compiler diff --git a/ext/names/BUCK b/ext/names/BUCK index 6fc3742..068beaa 100644 --- a/ext/names/BUCK +++ b/ext/names/BUCK @@ -5,5 +5,5 @@ genrule( name='all', srcs=['a.names', 'b.names'], out='all.names', - cmd='$(exe //ext/compiler:compiler) $SRCS > $OUT', + cmd='$(exe compiler//:compiler) $SRCS > $OUT', visibility=['PUBLIC']) ``` Now you can build it: ``` log-mbp:nested-buck coneko$ NO_BUCKD=1 buck build //:reversed --show-output Not using buckd because NO_BUCKD is set. [-] PROCESSING BUCK FILES...FINISHED 0.7s [100%] 🐳 New buck daemon [+] DOWNLOADING... (0.00 B/S, TOTAL: 0.00 B, 0 Artifacts) [+] BUILDING...0.4s [0%] (0/1 JOBS, 0 UPDATED, 0 [0.0%] CACHE MISS) |=> //:reversed... 0.0s (checking local cache) |=> IDLE |=> IDLE |=> IDLE The outputs are: //:reversed buck-out/gen/reversed/reversed.names log-mbp:nested-buck coneko$ cat buck-out/gen/reversed/reversed.names xelA nitsuA nairdA lA kcuB ylliB boB pmurB ecniboB ``` Does this feature fit your needs?
![Qix](https://avatars2.githubusercontent.com/u/885648?v=3&s=88) @Qix- commented on Oct 13, 2016
If Buck is to remain a monorepo-biased build system then yes, that does work. Thank you for the followup @coneko :)
--- From https://gitlab.kitware.com/cmake/cmake/issues/15555
### Closed Issue [#15555](https://gitlab.kitware.com/cmake/cmake/issues/15555) opened 2015.05.04 ago by Kitware Robot ## Ninja: Object file compilation unconditionally depends on artifacts of dependencies This issue was created automatically from an original [Mantis Issue](https://cmake.org/Bug/view.php?id=15555). Further discussion may take place here. --- When the Ninja generator generates targets for .cc files, it adds dependencies on any libraries that their target depend on. This means that in a parallel build, ninja won't start building any .cc files from one library until all depended-upon libraries have been built -- an unnecessary restriction. The only requirement should be that a target cannot be linked until its required libraries are built. This severely limits build parallelism in large projects. I manually post-processed a build.ninja file from a medium-size C++ project to remove these dependencies, and a parallel build using icecc on a small cluster was reduced from 1m30s to 1m0s. Looking at a Gantt chart of the build, I could see that all of the cluster cores were kept occupied much better after the fix, especially at the start of the build. *Edited 2017.04.26 ago* ### 1 Related Merge Request [!430](https://gitlab.kitware.com/cmake/cmake/merge_requests/430) ninja: break unnecessary target dependencies
[Brad King](https://gitlab.kitware.com/brad.king) @brad.king commented 2016.07.28
I changed the title back to be Ninja-specific because this problem is really only solvable with the Ninja generator. I couldn't find this issue when looking for it as a result of having no mention of Ninja.
[Mitchell Blank](https://gitlab.kitware.com/mitchblank) @mitchblank commented 2017.01.04
I also tripped over this problem years ago. For what it's worth, my minimal repro at the time was to use this CMakeLists.txt ``` PROJECT(libDependencyTest C) ADD_LIBRARY ( a STATIC a.c ) ADD_LIBRARY ( b STATIC b.c ) TARGET_LINK_LIBRARIES ( b a ) ADD_EXECUTABLE ( e e.c ) TARGET_LINK_LIBRARIES ( e b ) ``` and then do: ```console $ touch a.c b.c $ echo 'int main(){return 0;}' > e.c $ cmake -G Ninja . ``` ...and then look at the dependencies in build.ninja. On cmake 2.8.12.1 these looked like: ```console $ grep C_COMPILER build.ninja build CMakeFiles/a.dir/a.o: C_COMPILER a.c build CMakeFiles/b.dir/b.o: C_COMPILER b.c || liba.a build CMakeFiles/e.dir/e.o: C_COMPILER e.c || liba.a libb.a ``` On cmake 3.7.1 the ninja generator emits the dependencies differently, but the dependencies on the .a's are still there: ``` build cmake_order_depends_target_e: phony || liba.a libb.a build CMakeFiles/e.dir/e.c.o: C_COMPILER__e e.c || cmake_order_depends_target_e build cmake_order_depends_target_b: phony || liba.a build CMakeFiles/b.dir/b.c.o: C_COMPILER__b b.c || cmake_order_depends_target_b build CMakeFiles/a.dir/a.c.o: C_COMPILER__a a.c ``` I patched our local copy of cmake (first 2.8.x, later 3.0.x) to just force it to drop a bunch of dependencies. In `cmNinjaTargetGenerator::WriteObjectBuildStatement()` I just did: ```C++ std::string rule = this->LanguageCompilerRule(language); // [...] if (rule != "C_COMPILER" && rule != "CXX_COMPILER") // <----- added this line this->GetLocalGenerator()->AppendTargetDepends(this->Target, orderOnlyDeps); ``` basically I hardwired .o files to only depend on my C/C++ source files and nothing else. It's obviously an unsafe and incomplete hack around the problem. I'm looking at finally updating our local version of cmake and was researching if something like that will still be needed... I guess it will be, although the names of the rules have changed in the newer cmakes, so I'll have to adjust my logic a bit. Anyway, hopefully there will be an official fix for this some day so I can run a stock cmake binary again.
[Ben Boeckel](https://gitlab.kitware.com/benboeckel) @benboeckel commented 2017.01.04
Yeah, that's the symptoms. For clarity, this is done because it is what the Makefiles do. If you'd like to work on the proper fix, you can drop the dependency from B's objects on dependent library A if A's custom command dependencies are a subset of B's custom command dependencies (i.e., any headers/sources/etc. A needs generated are also already dependencies of B itself).
#### [!430](https://gitlab.kitware.com/cmake/cmake/merge_requests/430) merged 2017.04.19
*(following comments elided)*
--- From https://github.com/ninja-build/ninja/issues/977
I would attempt a PR for this, but I'm not entirely sure this is a bug or if it's intended. When including a subninja, I get > ninja: error: 'mod.c', needed by 'mod.o', missing and no known rule to make it although running ninja directly in that directory works just fine. Under the suspicion that relative paths may be to blame, I copied the project structure to a new directory, prepended each input/output with the absolute path, and ran ninja from the parent directory (containing the `build.ninja` that `subninja`'d the module). It built just fine. Is this suggesting we should be generating our ninja configurations with absolute paths? This has a lot of problems, along with the fact not every generator I've seen does this. Further, the documentation doesn't make a distinction, and Ninja runs just fine otherwise. I want to err on the side of _it's a bug_, but I feel like a PR that does runtime path canonicalization might introduce a performance hit (though I'm waving my hands here without any benchmarks to back up that suspicion).
[nico](https://github.com/nico) commented on Jun 20, 2015
All paths are relative to the build directory, not to the file containing the subninja line.
![Qix](https://avatars2.githubusercontent.com/u/885648?v=3&s=88) @Qix- commented on Jun 21, 2015
That makes no sense, though. That means generators are going to have to _all_ implement some way to prepend a prefix to the files, which means changing the working directory commands run in (which may change the original intent of the build configuration depending on how the generator/commands run). What, then, are contrasting use cases for `subninja` vs `include`? A subninja with paths relative to the build file would be useful in that depdencies that are configured to run within their own directory can do so without having to modify their paths, but can still contribute to the dependency graph of the parent ninja configuration. `include` functionality would be unmodified, and would act exactly how subninjas act other than the fact rule names would now be in a combined namespace (as per #921). Currently, `subninja` and `include` achieve essentially the same thing other than scoping variables and rule names...
[nico](https://github.com/nico) commented on Jun 21, 2015
The idea is that the generator generates all .ninja files, so they can write paths relative to the build directory. It's an interesting idea to combine ninja files generated by different generators (it sounds like that's what you want to do?), but that's not something that's supported at the moment. Correct, the difference between `subninja` and `include` is that the former adds a scope and the latter doesn't. The use case for this is that the toplevel ninja can define common build rules such as cc that reference variables such as `cflags`, and each subninja can set `cflags` to what's appropriate for that target, and there can be one-off actions in there. To see an example, you can run python misc/write_fake_manifests.py /tmp/foo` to write a bunch of .ninja files to /tmp/foo that use this pattern.
![Qix](https://avatars2.githubusercontent.com/u/885648?v=3&s=88) @Qix- commented on Jun 21, 2015
That makes sense, though I still don't see much of a benefit (other than scope). > It's an interesting idea to combine ninja files generated by different generators (it sounds like that's what you want to do?) Exactly. Being able to include Ninja itself as a submodule for my generator, and then another CMake project (which is configured to output Ninja build files), and then generating the Ninja config files for both and including them as `subninja`s in _my_ project's `build.ninja` file in order to be able to build them as if they were on their own, but still allow my project to use their outputs (and thus their dependency graphs) in order to build the whole project at once. If that makes sense. Immediate use-case that I see with my generator in particular is that it's borrowing a few concepts from Tup (which IIRC influenced some design decisions within Ninja itself) in that I can include N subprojects, all with their own `build.ninja` files, and then tap into their graphs to allow me to automatically construct a much larger dependency graph. I personally think that'd make `subninja` a whole lot more useful, though I could see it being a potentially breaking change. However, I don't see a way around this unless 1) I modify the dependencies' `build.ninja` files with a patch or 2) sacrifice the ability to harness the dependencies' dependency graphs. Thoughts?
![Qix](https://avatars2.githubusercontent.com/u/885648?v=3&s=88) @Qix- commented on Jun 21, 2015
How about: ``` ninja subninja path/to/build.ninja relative path/to ``` and an absent `relative` defaults to `./`. That would make it non-breaking but still give the functionality if a generator so desires. Or, following in the steps of other Ninja constructs, maybe ``` ninja subninja path/to/build.ninja relative = path/to ```
[evmar](https://github.com/evmar) commented on Jun 21, 2015
Suppose you have a project at .../foo and it has a subdirectory bar, and that Ninja had the relative-path logic you suggest. If your build system wants to write all build outputs to /foo/obj, a subninja in /foo/bar that used directory-relative paths would need to know to write its output into ../obj/bar, as that's the path to the file from that subdirectory. So whatever is generating your build.ninja files must already be aware of the global path hierarchy, in which case making all paths relative is effectively the same problem as prepending a bar/ to the paths in the bar/ directory. Maybe there are enough people who write build output in their source directories that the above doesn't matter, though. I mostly hear from people who want even stronger separation -- like the people who sent patches to Ninja to make it so they can build Ninja with the build output in a totally unrelated directory.
![Qix](https://avatars2.githubusercontent.com/u/885648?v=3&s=88) @Qix- commented on Jun 21, 2015
I'm not sure I understand. Subninjas, in the use-case I've described in particular, don't normally know about the parent ninja's structure (at least, don't need to know). I'm sure someone out there could find a case where they do, though. The problem I'm facing right now is dependencies (third party libraries, etc.) that don't use my generator (which is 100% of them) currently need to be built using a bootstrapper, and have to be bootstrapped every time they're updated or changed, etc. Most generators I work with have the options to output to a ninja configuration, but they're all configured for that directory alone (i.e. relative to that directory). Being able to perform selective rebuilds using their configurations and graphs would be huge. Currently, I cannot do this due to the fact `subninja` assumes paths relative to the build directory.
[nico](https://github.com/nico) commented on Jul 5, 2015
Evan: The way I understood this is that you'd create a tree like this: ``` builddir subbuild1 subbuild2 ``` and since generators usually support putting the build dir in arbitrary places, building project 1 in subbuild1 and project 2 in subbuild 2 should work. Then there's a toplevel ninja file in builddir that Qix- wants to drive building the subprojects. Unrelated: this `relative` feature also has to change the cwd to its argument if any rules depend on the current directory being equal to their build dir (say, if a rule strips built artifacts or something).
Qix- commented 7 years ago

Quickly chiming in - there are still no good build systems out there IMO ;) If you find one, let me know.

volcanoauthors commented 7 years ago

My preference is, first, to fix ninja, by fork if necessary. That "fixes" any generator that targets ninja. I've got til Tuesday to make a plan. I'll send you a slack invite, in case you have time.

Coneko commented 7 years ago

From the Buck side of things I'll confirm hierarchically nested projects are still not supported very well, only a flat nesting structure works.

@njlr and @nikhedonia might be interested in this as authors of https://github.com/LoopPerfect/buckaroo .

njlr commented 7 years ago

Can confirm that we are using Buck with nested projects for Buckaroo. Our dependency resolver flattens the graph so I can't comment on how well Buck handles multiply nested projects.

I wrote a quick example of how Buck can be used with submodules, which you might find helpful.

Looking at Volcano, I think your use-case would work OK. The larger piece of work will be either porting or wrapping the build system of each of your dependencies. Happy to help if you get stuck here - we've ported lots of projects now, including some pretty big ones like LLVM!

volcanoauthors commented 7 years ago

subninja now supports chdir. I should be pushing the rest of the BUILDCONFIG cleanup soon.