Ninja needs a special build var to set the current working directory, like builddir #431

rgeary1 opened this Issue Sep 26, 2012 · 2 comments

1 participant


I think ninja should have a feature to change the current working directory in the file, in the same way I can set the builddir variable to specify the .ninja_log folder. Here's why :

I'm writing a ninja file generator for Premake. Ideally, ninja files should use relative paths not absolute paths, otherwise trivial file system changes will break ninja & require the .ninja files to be regenerated. But if you build a file with an input path like "src/file.cpp", it generates a .o.d file containing "src/file.h". If you have another file in a subdirectory that attempts to build the same file with a relative path "../src/file.cpp", it will error as it expects "../src/file.h" in the .o.d file.

I create different files in subfolders as this allows me to change the default build targets depending on the directory the user invoked ninja from. These small files subninja in to a master file. The files set a buildvar "root" to the relative path from the current directory to the directory, then files reference all files as $root/blah

I really don't want to use -C, as this means I will have to ask Premake users to wrap ninja in a script before they invoke ninja.

Instead, I propose the "currentdirectory" special variable, which would be equivalent to -C command line option. I can set this instead of my build var "root".


Patch below. Creates a special var called "workingdir" :

From 42a8c7e0d7e9a266c3caab1e7255a5878e4365d1 Mon Sep 17 00:00:00 2001
From: Richard Geary <>
Date: Thu, 27 Sep 2012 06:21:35 -0400
Subject: [PATCH] Add workingdir special build variable to set the current working directory in the file

Change-Id: I4f270f6363b540a33b7899f26b4db14bac9a4b2d
 src/ |   19 +++++++++++++++++++
 1 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/src/ b/src/
index 8ee38cf..598de07 100644
--- a/src/
+++ b/src/
@@ -608,12 +608,28 @@ bool DebugEnable(const string& name, Globals* globals) {

+bool SetWorkingDirFromLog(Globals* globals) {
+  const string working_dir =
+      globals->state->bindings_.LookupVariable("workingdir");
+  if (!working_dir.empty()) {
+    if (chdir(working_dir.c_str()) < 0) {
+      Fatal("chdir to '%s' - %s", working_dir.c_str(), strerror(errno));
+    }
+    return true;
+  }
+  return false;
 bool OpenLog(BuildLog* build_log, Globals* globals,
              DiskInterface* disk_interface) {
   const string build_dir =
   const char* kLogPath = ".ninja_log";
   string log_path = kLogPath;
+  SetWorkingDirFromLog(globals);
   if (!build_dir.empty()) {
     log_path = build_dir + "/" + kLogPath;
     if (!disk_interface->MakeDirs(log_path) && errno != EEXIST) {
@@ -842,7 +858,10 @@ reload:

   if (tool && tool->when == Tool::RUN_AFTER_LOAD)
+  {
+    SetWorkingDirFromLog(&globals);
     return tool->func(&globals, argc, argv);
+  }

   BuildLog build_log;
   if (!OpenLog(&build_log, &globals, &disk_interface))

See #456

@rgeary1 rgeary1 closed this Nov 9, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment