Struggling with ImportC
So I added a .c file to my project
#pragma attribute(push, nothrow, nogc)
#if defined(_WIN32)
# include "pcap.h"
#endif
By default, Visual Studio treats it as a C/C++ file and hands it to cl.exe for compiling.
So, I change the file's Item Type to "D Compile", which matches all the D source files:
That kinda seemed to have some effect, now when I build, the file is included in the DMD command line:
1>Compiling appliance.d [...] variant.d zip.d os.c # <-- NOTE THE os.c FILE HERE
1>COMPILED : error : C preprocess command C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.39.33519\bin\HostX64\x64\cl.exe failed for file third_party\urt\src\urt\internal\os.c, exit status 2
1>
1>third_party\urt\src\urt\internal\os.c(12): fatal error C1083: Cannot open include file: 'pcap.h': No such file or directory
But you can see from that build output, it invokes DMD (apparently correctly), and then it seems to try and build it with cl.exe as well??
Or, is that output coming from pipelink.exe (or whatever it's called) and it is delegating the .c file out to the C compiler before it reackes DMD?
Surprisingly, it complains because it can't find the include path, so it seems cl.exe is definitely invoked and trying to build the file; but the error is surprising, because the C/C++ compiler config actually DOES specify the correct include path. If I change that file back to "C/C++ compiler" and let the C compiler compile it, it does compile properly in that case.
So, I guess something is just askew when forcing a .c file to use the D Compiled item type...
I just tried something else; instead of including it in the build, I thought if I import the .c file into .d source, then DMD would do the business through it's normal import logic:
import urt.internal.os; // <- this is os.c
I exclude the .c file from the build in the project settings to try and make sure MSBuild ignores it:
Build:
1>Compiling appliance.d [...] variant.d zip.d # <-- NO .c files on passed to the compiler
1>src\router\iface\package.d(27): error : C preprocess command C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.39.33519\bin\HostX64\x64\cl.exe failed for file third_party/urt/src/urt\internal\os.c, exit status 2
1>
1>third_party/urt/src/urt\internal\os.c(12): fatal error C1083: Cannot open include file: 'pcap.h': No such file or directory
Still trying to invoke cl.exe... strange?
Has anyone ever tried to use importC with VisualD?
Also worth noting; when the .c file is set to D Compiler, making changes to the .c file does not seem to cause a project rebuild... it just thinks nothing changed :/
Still trying to invoke cl.exe... strange?
is it not using cl for preprocessing? Does it do the same if you run cl with whatever the equivalent of -E is (to get a .i file)?
Yes, dmd is invoking cl.exe to preprocess the C file, but the C/C++ options are not known to the D compiler, so you will have to add the necessary ones (defines and C only include paths) with -P.
I have only tried import C once (it failed too easily on system or SDK headers), but I would expect C files to best be compiled with msvc, and only import the C source or header files. dmd should handle this automatically (including the preprocessing), but might need additional include path options.
Also worth noting; when the .c file is set to
D Compiler, making changes to the .c file does not seem to cause a project rebuild... it just thinks nothing changed :/
It looks like the dependency tracker doesn't capture the activity of the cl.exe subprocess used for preprocessing. Not sure if it is easy to change that.
Edit: the tracker works and produces dmd-cl.read.tlog, but it isn't yet merged with the other dependencies.
Oh? I thought Walter put the preprocessor he wrote some years back in DMD... does that mean DMD for windows depends on MSVC? It doesn't seem right that DMD depends on the VS C compiler to preprocess .c files :/
IIRC Walter was worried about all the system specific extensions the compiler writers have added to the preprocessor and that are used in system headers.
Oh? I thought Walter put the preprocessor he wrote some years back in DMD
No.
does that mean DMD for windows depends on MSVC?
It's either that or Clang or GCC (via MinGW). The flag -cpp= controls this choice, as does the environment variable CPPCMD.
Is there anything VisualD can do to get the proper args through to the preprocessor?
Is there anything VisualD can do to get the proper args through to the preprocessor?
I guess we could grab the VC project settings and forward them to dmd. That doesn't work for settings on specific files, though, as it is unknown upfront which files will be imported.
I would expect the project settings applied to the current D compilation to cascade through to any imports... so I wouldn't grab it from the C++ settings, I'd probably grab the -I paths from the D settings?
I'd probably grab the -I paths from the D settings?
I was expecting dmd to already do that (it searches c/h files there itself), but in fact that is not the case. Adding an option for the C include path is probably the simplest and setting its default to %(ImportPaths) makes it inherit the D import paths.
That seems nice, I have argued on the forum that the C include paths should be separate to -I, but apparently Walter likes it the way it is. We'd be breaking from DMD's intent (although that seems fine 😉)
Do you reckon it's a bug in DMD that it's not already passing the -I paths through, or is there some intention there?
I have added an option to set the C include search path, but inheriting another setting turned out to be a nightmare wasting hours unsuccessfully trying to do a simple text replacement on a list in msbuild. So let's stick with dmds' behavior and not forward the import paths by default ;)
While testing I noticed that the semantic analysis also errors on C imports, that also needs to be adjusted.
BTW: It think Iain has also changed the search slightly for dmd 2.112 and it might also find .h files when importing.
Hmmm, yeah okay let's wait until the next DMD release to see where this stuff lands.
The added import C support can be found in https://github.com/dlang/visuald/releases/tag/v1.4.2-beta1.
The semantic engine now also runs the preprocessor, but an edited .c/.h file must be saved, though, as it is controlled by Visual C, not Visual D.
I used those new options, made propgress. I couldn't see anywhere to pass flags to the preprocessor though. I wanted to silence preprocessor warnings.
For some reason #pragma warning(disable:4005) in the code doesn't actually affect the preprocessor's behaviour as I'd expect :/
For some reason #pragma warning(disable:4005) in the code.
In importc.h or in your own files?
You can pass options to the preprocessor with -P as additional command line option, e.g. -P/wd4005
For some reason #pragma warning(disable:4005) in the code.
In
importc.hor in your own files?
At the top of the .c file that I'm compiling, before the #include that emits the warnings. I'll try the -P strategy Rainer suggested (thanks!).