1 /** 2 * Run the C preprocessor on a C source file. 3 * 4 * Specification: C11 5 * 6 * Copyright: Copyright (C) 2022-2023 by The D Language Foundation, All Rights Reserved 7 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) 8 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 9 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/cpreprocess.d, _cpreprocess.d) 10 * Documentation: https://dlang.org/phobos/dmd_cpreprocess.html 11 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/cpreprocess.d 12 */ 13 14 module dmd.cpreprocess; 15 16 import core.stdc.stdio; 17 import core.stdc.stdlib; 18 import core.stdc.string; 19 20 import dmd.astenums; 21 import dmd.errors; 22 import dmd.globals; 23 import dmd.link; 24 import dmd.location; 25 import dmd.target; 26 import dmd.vsoptions; 27 28 import dmd.common.outbuffer; 29 30 import dmd.root.array; 31 import dmd.root.filename; 32 import dmd.root.rmem; 33 import dmd.root.rootobject; 34 import dmd.root.string; 35 36 // Use default for other versions 37 version (Posix) version = runPreprocessor; 38 version (Windows) version = runPreprocessor; 39 40 41 /*************************************** 42 * Preprocess C file. 43 * Params: 44 * csrcfile = C file to be preprocessed, with .c or .h extension 45 * loc = The source location where preprocess is requested from 46 * ifile = set to true if an output file was written 47 * defines = buffer to append any `#define` and `#undef` lines encountered to 48 * Result: 49 * filename of output 50 */ 51 extern (C++) 52 FileName preprocess(FileName csrcfile, ref const Loc loc, out bool ifile, OutBuffer* defines) 53 { 54 /* Look for "importc.h" by searching along import path. 55 * It should be in the same place as "object.d" 56 */ 57 const(char)* importc_h; 58 59 foreach (entry; (global.path ? (*global.path)[] : null)) 60 { 61 auto f = FileName.combine(entry, "importc.h"); 62 if (FileName.exists(f) == 1) 63 { 64 importc_h = f; 65 break; 66 } 67 FileName.free(f); 68 } 69 70 if (importc_h) 71 { 72 if (global.params.verbose) 73 message("include %s", importc_h); 74 } 75 else 76 { 77 error(loc, "cannot find \"importc.h\" along import path"); 78 fatal(); 79 } 80 81 //printf("preprocess %s\n", csrcfile.toChars()); 82 version (runPreprocessor) 83 { 84 /* 85 To get sppn.exe: http://ftp.digitalmars.com/sppn.zip 86 To get the dmc C headers, dmc will need to be installed: 87 http://ftp.digitalmars.com/Digital_Mars_C++/Patch/dm857c.zip 88 */ 89 const name = FileName.name(csrcfile.toString()); 90 const ext = FileName.ext(name); 91 assert(ext); 92 const ifilename = FileName.addExt(name[0 .. name.length - (ext.length + 1)], i_ext); 93 const command = global.params.cpp ? toDString(global.params.cpp) : cppCommand(); 94 auto status = runPreprocessor(command, csrcfile.toString(), importc_h, global.params.cppswitches, ifilename, defines); 95 if (status) 96 { 97 error(loc, "C preprocess command %.*s failed for file %s, exit status %d\n", 98 cast(int)command.length, command.ptr, csrcfile.toChars(), status); 99 fatal(); 100 } 101 //printf("C preprocess succeeded %s\n", ifilename.ptr); 102 ifile = true; 103 return FileName(ifilename); 104 } 105 else 106 return csrcfile; // no-op 107 } 108 109 private const(char)[] cppCommand() 110 { 111 if (auto p = getenv("CPPCMD")) 112 return toDString(p); 113 114 version (Windows) 115 { 116 if (target.objectFormat() == Target.ObjectFormat.coff) 117 { 118 VSOptions vsopt; 119 vsopt.initialize(); 120 auto path = vsopt.compilerPath(target.is64bit); 121 return toDString(path); 122 } 123 if (target.objectFormat() == Target.ObjectFormat.omf) 124 { 125 return "sppn.exe"; 126 } 127 // Perhaps we are cross-compiling. 128 return "cpp"; 129 } 130 else version (OpenBSD) 131 { 132 // On OpenBSD, we need to use the actual binary /usr/libexec/cpp 133 // rather than the shell script wrapper /usr/bin/cpp ... 134 // Turns out the shell script doesn't really understand -o 135 return "/usr/libexec/cpp"; 136 } 137 else version (OSX) 138 { 139 return "clang"; 140 } 141 else 142 { 143 return "cpp"; 144 } 145 }