Cl.exe Output Directory

0 views
Skip to first unread message

Gerald Weiß

unread,
Aug 3, 2024, 6:04:09 PM8/3/24
to cerroseemitz

You can use the /Fo compiler option to set an output directory for all the object files generated by the CL compiler command. Or, you can use it to rename a single object file. Don't put a space between the /Fo option and the pathname argument.

To use the /Fo option to rename an object file, specify the output filename as the pathname argument. When you rename an object file, you can use any name and extension you want, but the recommended convention is to use an .obj extension. The compiler generates command line error D8036 if you specify a filename to /Fo when you've specified more than one source file to compile.

To use the /Fo option to set an output directory for all object files created by the CL command, specify the directory as the pathname argument. A directory is indicated by a trailing slash or backslash in the pathname argument. Use an escaped backslash (a double backslash), if you're using a quoted path. The directory path can be absolute, or relative to the source directory. The specified directory must exist, or the compiler reports error D8003. The directory isn't created automatically.

The following command line creates object files named sample1.obj and sample2.obj in an existing directory, D:\intermediate\. It uses escaped backslash characters as path segment separators in a quoted path:

The compiler (CL.EXE) can take multiple source files, but likes to generate all the OBJ files in the directory that it is invoked. I couldn't find the compiler flag to set an output directory but I did find one for an individual OBJ, but it can't take multiple sources.

as this would result in an escaped quote \" and would grab whatever else followed on the command line and put it into $(SOMEDIR). Took me a while to diagnose such a behavior, hope this would save time to someone else.

I think the part about not having the typical compiler installation path applies to your case. However, it is worth noting that we only fall back to deducing the "INCLUDE" env variable when it is not visible in the wrapped build (which should be the usual case). So I would start by understanding why the INCLUDE environment variable is missing in your build. Do you also use the -I CLI switch to provide the include directories to cl.exe?

You also mentioned that you tried setting the INCLUDE environment, but you are still getting the same message. Could you please share the exact sequence commands you used to set the environment variable, run the wrapped build, then the scanner (and their output)?

Environment:
We use Cygwin session for the Windows builds. As part of the build we have our batch script which would trigger the local builds. Regarding the usage of -I, I confirm we use /I to provide the include directories to cl.exe. Do you mean including -I could be the issue for INCLUDE environment variable missing in the build???

It seems to me that the INCLUDE env variable is indeed not intercepted by build-wrapper. Could you please double-check that the env variable is visible inside your Cygwin session (where you are running your wrapped build)? For example, by examining the output of any of the commands: set findstr INCLUDE or echo $INCLUDE?

Hi @vishal, I am afraid I need more details to understand your environment and track down the problem. I am trying to summarize below what I know about your situation, please correct me if I am off at any point:

build-wrapper should be able to capture all environment variables that are passed at the time cl.exe was invoked. You can check that yourself by examining the logs in the output directory from a command like this in your Cygwin session, you should be able to find your INCLUDE env var in the logs in the following simple case:

With that in mind, the only possible explanation I could think of is that you might have something in your build_ui.bat that manipulates the environment variables prior to invoking cl.exe. It would be nice if you could instrument your batch file, and inspect the output of set findstr INCLUDE throughout the execution of the script. Most importantly, at the point before cl.exe is invoked. Can you still see the expected value of your INCLUDE environment variable before cl.exe is invoked in your batch script?

The CUDA Toolkit targets a class of applications whose control part runs as a process on a general purpose computing device, and which use one or more NVIDIA GPUs as coprocessors for accelerating single program, multiple data (SPMD) parallel jobs. Such jobs are self-contained, in the sense that they can be executed and completed by a batch of GPU threads entirely without intervention by the host process, thereby gaining optimal benefit from the parallel graphics hardware.

The GPU code is implemented as a collection of functions in a language that is essentially C++, but with some annotations for distinguishing them from the host code, plus annotations for distinguishing different types of data memory that exists on the GPU. Such functions may have parameters, and they can be called using a syntax that is very similar to regular C function calling, but slightly extended for being able to specify the matrix of GPU threads that must execute the called function. During its life time, the host process may dispatch many parallel GPU tasks.

Source files for CUDA applications consist of a mixture of conventional C++ host code, plus GPU device functions. The CUDA compilation trajectory separates the device functions from the host code, compiles the device functions using the proprietary NVIDIA compilers and assembler, compiles the host code using a C++ host compiler that is available, and afterwards embeds the compiled GPU functions as fatbinary images in the host object file. In the linking stage, specific CUDA runtime libraries are added for supporting remote SPMD procedure calling and for providing explicit GPU manipulation such as allocation of GPU memory buffers and host-GPU data transfer.

The compilation trajectory involves several splitting, compilation, preprocessing, and merging steps for each CUDA source file. It is the purpose of nvcc, the CUDA compiler driver, to hide the intricate details of CUDA compilation from developers. It accepts a range of conventional compiler options, such as for defining macros and include/library paths, and for steering the compilation process. All non-CUDA compilation steps are forwarded to a C++ host compiler that is supported by nvcc, and nvcc translates its options to appropriate host compiler command line options.

nvcc assumes that the host compiler is installed with the standard method designed by the compiler provider. If the host compiler installation is non-standard, the user must make sure that the environment is set appropriately and use relevant nvcc compile options.

On all platforms, the default host compiler executable (gcc and g++ on Linux and cl.exe on Windows) found in the current execution search path will be used, unless specified otherwise with appropriate options (see File and Path Specifications).

Note, nvcc does not support the compilation of file paths that exceed the maximum path length limitations of the host system. To support the compilation of long file paths, please refer to the documentation for your system.

A compilation phase is a logical translation step that can be selected by command line options to nvcc. A single compilation phase can still be broken up by nvcc into smaller steps, but these smaller steps are just implementations of the phase: they depend on seemingly arbitrary capabilities of the internal tools that nvcc uses, and all of these internals may change with a new release of the CUDA Toolkit. Hence, only compilation phases are stable across releases, and although nvcc provides options to display the compilation steps that it executes, these are for debugging purposes only and must not be copied and used in build scripts.

nvcc phases are selected by a combination of command line options and input file name suffixes, and the execution of these phases may be modified by other command line options. In phase selection, the input file suffix defines the phase input, while the command line option defines the required output of the phase.

The following table specifies the supported compilation phases, plus the option to nvcc that enables the execution of each phase. It also lists the default name of the output file generated by each phase, which takes effect when no explicit output file name is specified using the option --output-file:

CUDA compilation works as follows: the input program is preprocessed for device compilation and is compiled to CUDA binary (cubin) and/or PTX intermediate code, which are placed in a fatbinary. The input program is preprocessed once again for host compilation and is synthesized to embed the fatbinary and transform CUDA specific C++ extensions into standard C++ constructs. Then the C++ host compiler compiles the synthesized host code with the embedded fatbinary into a host object. The exact steps that are followed to achieve this are displayed in Figure 1.

CUDA programs are compiled in the whole program compilation mode by default, i.e., the device code cannot reference an entity from a separate file. In the whole program compilation mode, device link steps have no effect. For more information on the separate compilation and the whole program compilation, see Using Separate Compilation in CUDA.

Each nvcc option has a long name and a short name, which are interchangeable with each other. These two variants are distinguished by the number of hyphens that must precede the option name: long names must be preceded by two hyphens, while short names must be preceded by a single hyphen. For example, -I is the short name of --include-path. Long options are intended for use in build scripts, where the size of the option is less important than the descriptive value. In contrast, short options are intended for interactive use.

c80f0f1006
Reply all
Reply to author
Forward
0 new messages