It's not sufficient to have the absolute path to the compiler, linker, etc. on Windows, as those tools rely on .dlls being in the PATH. We also need to support both x86 and x64 compilers within the same build (to support msvs_target_platform hackery). Different architectures require a di
(
toplevel_build_dir, generator_flags, system_includes, open_out
)
| 1158 | |
| 1159 | |
| 1160 | def GenerateEnvironmentFiles( |
| 1161 | toplevel_build_dir, generator_flags, system_includes, open_out |
| 1162 | ): |
| 1163 | """It's not sufficient to have the absolute path to the compiler, linker, |
| 1164 | etc. on Windows, as those tools rely on .dlls being in the PATH. We also |
| 1165 | need to support both x86 and x64 compilers within the same build (to support |
| 1166 | msvs_target_platform hackery). Different architectures require a different |
| 1167 | compiler binary, and different supporting environment variables (INCLUDE, |
| 1168 | LIB, LIBPATH). So, we extract the environment here, wrap all invocations |
| 1169 | of compiler tools (cl, link, lib, rc, midl, etc.) via win_tool.py which |
| 1170 | sets up the environment, and then we do not prefix the compiler with |
| 1171 | an absolute path, instead preferring something like "cl.exe" in the rule |
| 1172 | which will then run whichever the environment setup has put in the path. |
| 1173 | When the following procedure to generate environment files does not |
| 1174 | meet your requirement (e.g. for custom toolchains), you can pass |
| 1175 | "-G ninja_use_custom_environment_files" to the gyp to suppress file |
| 1176 | generation and use custom environment files prepared by yourself.""" |
| 1177 | archs = ("x86", "x64", "arm64") |
| 1178 | if generator_flags.get("ninja_use_custom_environment_files", 0): |
| 1179 | cl_paths = {} |
| 1180 | for arch in archs: |
| 1181 | cl_paths[arch] = "cl.exe" |
| 1182 | return cl_paths |
| 1183 | vs = GetVSVersion(generator_flags) |
| 1184 | cl_paths = {} |
| 1185 | for arch in archs: |
| 1186 | # Extract environment variables for subprocesses. |
| 1187 | args = vs.SetupScript(arch) |
| 1188 | args.extend(("&&", "set")) |
| 1189 | popen = subprocess.Popen( |
| 1190 | args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT |
| 1191 | ) |
| 1192 | variables = popen.communicate()[0].decode("utf-8") |
| 1193 | if popen.returncode != 0: |
| 1194 | raise Exception('"%s" failed with error %d' % (args, popen.returncode)) |
| 1195 | env = _ExtractImportantEnvironment(variables) |
| 1196 | |
| 1197 | # Inject system includes from gyp files into INCLUDE. |
| 1198 | if system_includes: |
| 1199 | system_includes = system_includes | OrderedSet( |
| 1200 | env.get("INCLUDE", "").split(";") |
| 1201 | ) |
| 1202 | env["INCLUDE"] = ";".join(system_includes) |
| 1203 | |
| 1204 | env_block = _FormatAsEnvironmentBlock(env) |
| 1205 | f = open_out(os.path.join(toplevel_build_dir, "environment." + arch), "w") |
| 1206 | f.write(env_block) |
| 1207 | f.close() |
| 1208 | |
| 1209 | # Find cl.exe location for this architecture. |
| 1210 | args = vs.SetupScript(arch) |
| 1211 | args.extend( |
| 1212 | ("&&", "for", "%i", "in", "(cl.exe)", "do", "@echo", "LOC:%~$PATH:i") |
| 1213 | ) |
| 1214 | popen = subprocess.Popen(args, shell=True, stdout=subprocess.PIPE) |
| 1215 | output = popen.communicate()[0].decode("utf-8") |
| 1216 | cl_paths[arch] = _ExtractCLPath(output) |
| 1217 | return cl_paths |
nothing calls this directly
no test coverage detected