cc-rs icon indicating copy to clipboard operation
cc-rs copied to clipboard

Rebuild after modifying environment variables that the C compiler reads

Open madsmtm opened this issue 2 years ago • 3 comments

Cargo has the ability to specify that a build script depends on specific environment variables using cargo:rerun-if-env-changed=NAME, but no such mechanism exist for C compilers (that I know of).

This means that when you update an environment variable that your C compiler reads, you have to run cargo clean before the change takes effect. It would be nice if cc could prevent this by outputting a list of known variables that the C compiler it is about to invoke may read.

A list of the major ones I've found so far in Clang/LLVM (see also their limited docs about it):

  • SDKROOT on Apple targets
  • VCINSTALLDIR / VCToolsInstallDir on Windows
  • INCLUDE / CPATH / C_INCLUDE_PATH / C_PLUS_INCLUDE_PATH / OBJC_INCLUDE_PATH / OBJCPLUS_INCLUDE_PATH
  • MACOSX_DEPLOYMENT_TARGET / IPHONEOS_DEPLOYMENT_TARGET / TVOS_DEPLOYMENT_TARGET / WATCHOS_DEPLOYMENT_TARGET / XROS_DEPLOYMENT_TARGET on Apple targets

Note that some of these may need to be handled by rustc/cargo itself.

Clang/LLVM read a bunch more, but they're mostly for debugging, or for stuff like setting up the terminal width, so I don't think those are applicable.

Additionally, C compilers usually rely on a few fundamental ones like PATH, PWD and PATHEXT on Windows that I would honestly expect cargo to handle, though I get why it may be difficult to do right.

madsmtm avatar Nov 23 '23 10:11 madsmtm

MACOSX_DEPLOYMENT_TARGET / IPHONEOS_DEPLOYMENT_TARGET / TVOS_DEPLOYMENT_TARGET / WATCHOS_DEPLOYMENT_TARGET

Also XROS_DEPLOYMENT_TARGET (visionOS).

briansmith avatar Jun 21 '24 03:06 briansmith

cc @madsmtm can we close this now #1103 is merged?

NobodyXu avatar Jun 25 '24 22:06 NobodyXu

Hmm, while #1103 does improve this situation, it does not really address the underlying issue of the C compiler itself using these variables.

What I mean is that it only works because we're reading e.g. SDKROOT in cc right now, but if that was to change, this would break again.

What I really want is something like:

let _ = self.getenv("SDKROOT");
let _ = self.getenv("INCLUDE");
let _ = self.getenv("CPATH");
let _ = self.getenv("MACOSX_DEPLOYMENT_TARGET");
let _ = self.getenv("IPHONEOS_DEPLOYMENT_TARGET");
let _ = self.getenv("TVOS_DEPLOYMENT_TARGET");
// ...

To run sometime before we invoke the compiler (I guess it could perhaps be slightly more granular than this, if we knew that the compiler doesn't read some of these on certain targets / with certain build flags, but you get the idea).

madsmtm avatar Jun 25 '24 23:06 madsmtm