Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ImportC: run cpp on Posix .c files #13955

Merged
merged 1 commit into from
May 2, 2022

Conversation

WalterBright
Copy link
Member

It's way past time for dmd to start running the C preprocessor. This kicks that baby bird out of the nest so it can learn to fly.

I like incrementalism, so this PR does as little as possible:

  1. it only works on .c files
  2. if you don't want to run the preprocessor on Posix, name the file with a .i extension
  3. it runs cpp on the default path
  4. no parameters can be passed to cpp
  5. doesn't automatically #include <importc.h>
  6. error messages are minimal
  7. most of the code is copypasta from runProgram() in link.d

Hence review should be easy.

Based on Max's prior work maxhaton@e132151 greatly simplified.

@WalterBright WalterBright added Review:Easy Review Feature:ImportC Pertaining to ImportC support labels Apr 6, 2022
@dlang-bot
Copy link
Contributor

Thanks for your pull request, @WalterBright!

Bugzilla references

Your PR doesn't reference any Bugzilla issue.

If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog.

Testing this PR locally

If you don't have a local development environment setup, you can use Digger to test this PR:

dub run digger -- build "master + dmd#13955"

@WalterBright WalterBright force-pushed the preprocess branch 2 times, most recently from ccdb18b to 06a362e Compare April 6, 2022 09:11
@WalterBright
Copy link
Member Author

Eh, looks like lexer.d is not liking the output of cpp. Will look at that tomorrow.

ibuclaw
ibuclaw previously requested changes Apr 6, 2022
src/dmd/dmodule.d Outdated Show resolved Hide resolved

import dmd.astenums;
import dmd.globals;
import dmd.link;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because, no dmd driver/backend code should be pulled into the front-end. (cc @kinke).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

offer a suggestion

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Compiler interface might be one place for it. That is at least one module that is not meant to be common amongst implementing compilers.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's already been replaced with a pointer.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's imported from dmd.link?

@WalterBright WalterBright force-pushed the preprocess branch 5 times, most recently from 8202e5c to 1c51280 Compare April 6, 2022 20:48
@WalterBright
Copy link
Member Author

@ibuclaw this fails on linux with:

... dshell/issue22816.d
==============================
Test 'dshell/issue22816.d' failed. The logged output:
[COMPILE_TEST] '/tmp/cirrus-ci-build/generated/linux/release/64/dmd' '-conf=' '-m64' '-fPIC' '-odtest_results/dshell/issue22816' '-oftest_results/dshell/issue22816/run' '-I=/tmp/cirrus-ci-build/test/dshell' '-I=test_results/dshell/issue22816' '-I=/tmp/cirrus-ci-build/test/tools/dshell_prebuilt' '-i' '-i=-dshell_prebuilt' 'test_results/dshell_prebuilt.o' '/tmp/cirrus-ci-build/test/dshell/issue22816.d'
[RUN_TEST] 'test_results/dshell/issue22816/run'
[RUN] '/tmp/cirrus-ci-build/generated/linux/release/64/dmd' '-m64' '-c' 'dshell/extra-files/issue22816.c'
core.exception.AssertError@/tmp/cirrus-ci-build/test/tools/dshell_prebuilt/dshell_prebuilt.d(287): Expected 'Error: cannot find input file'

The failing test case #13713 is written by you and I don't know what it is supposed to be doing. Please help.

@ibuclaw
Copy link
Member

ibuclaw commented Apr 6, 2022

@ibuclaw this fails on linux with:

... dshell/issue22816.d
==============================
Test 'dshell/issue22816.d' failed. The logged output:
[COMPILE_TEST] '/tmp/cirrus-ci-build/generated/linux/release/64/dmd' '-conf=' '-m64' '-fPIC' '-odtest_results/dshell/issue22816' '-oftest_results/dshell/issue22816/run' '-I=/tmp/cirrus-ci-build/test/dshell' '-I=test_results/dshell/issue22816' '-I=/tmp/cirrus-ci-build/test/tools/dshell_prebuilt' '-i' '-i=-dshell_prebuilt' 'test_results/dshell_prebuilt.o' '/tmp/cirrus-ci-build/test/dshell/issue22816.d'
[RUN_TEST] 'test_results/dshell/issue22816/run'
[RUN] '/tmp/cirrus-ci-build/generated/linux/release/64/dmd' '-m64' '-c' 'dshell/extra-files/issue22816.c'
core.exception.AssertError@/tmp/cirrus-ci-build/test/tools/dshell_prebuilt/dshell_prebuilt.d(287): Expected 'Error: cannot find input file'

The failing test case #13713 is written by you and I don't know what it is supposed to be doing. Please help.

See #13707 for the related bug fix.

It is expecting an error due to filemanager.lookup failing, but now you are calling preprocess and possibly getting another error (I hope not success).

To reproduce/get the new error message:

touch issue22816.d
dmd issue22816.c

Yes, those file extensions are correct.

@WalterBright
Copy link
Member Author

@ibuclaw thanks for the quick answer

@WalterBright WalterBright force-pushed the preprocess branch 2 times, most recently from a73e5ca to 59fd43a Compare April 6, 2022 23:24
src/dmd/README.md Outdated Show resolved Hide resolved
src/dmd/README.md Show resolved Hide resolved
src/dmd/globals.d Outdated Show resolved Hide resolved
if (FileName.equalsExt(srcfile.toString(), c_ext) &&
FileName.exists(srcfile.toString()))
{
filename = global.preprocess(srcfile); // run C preprocessor
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check for !is null.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It returns a struct, not a pointer.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I presume he means if (global.preprocess !is null) filename = global.preprocess(srcfile);?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer to ask @ibuclaw to explain, as I tire of guessing :-)

Yes, the function pointer might be null.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expect a "no-op preprocess" function would be provided that simply returned its argument. It's more attractive than adding the extra test.

Copy link
Member

@ljmf00 ljmf00 Apr 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expect a "no-op preprocess" function would be provided that simply returned its argument. It's more attractive than adding the extra test.

If you want that, global.preprocess should have a "contract" check for non-null function pointers. I agree with @ibuclaw anyway, because that way, there is a way to disable preprocess for those files. EDIT: I mean a "no-op" can do the job but it's counter-intuitive and a function call has higher latency for that purpose, instead of a simple test check.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't need a contract check for null pointers, as the hardware does that for you.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's counter-intuitive

It's a different style, called branchless programming. The nice thing about it is it removes clutter from the code.

and a function call has higher latency for that purpose, instead of a simple test check.

I'd agree if it was an inner loop, but it's once per file. Not significant.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initially this would be unimplemented in gdc and ldc though, resulting in a segfault. If this field was default initialized with a noop lambda then that'd be different.


import dmd.astenums;
import dmd.globals;
import dmd.link;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Compiler interface might be one place for it. That is at least one module that is not meant to be common amongst implementing compilers.

@WalterBright
Copy link
Member Author

WalterBright commented Apr 7, 2022

We've had ImportC without preprocessor support for 6 months or thereabouts. It desperately needs to support the preprocessor. This is just a first step. Please approve this so I can move forward to getting it completed and useful. We won't know what a better design would be without making more progress with this.

Nothing will move forward without this PR.

if (FileName.equalsExt(srcfile.toString(), c_ext) &&
FileName.exists(srcfile.toString()))
{
filename = global.preprocess(srcfile); // run C preprocessor
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I presume he means if (global.preprocess !is null) filename = global.preprocess(srcfile);?

src/dmd/root/env.d Outdated Show resolved Hide resolved
src/dmd/utils.d Outdated Show resolved Hide resolved
src/dmd/README.md Show resolved Hide resolved
@WalterBright
Copy link
Member Author

ping @ibuclaw

@RazvanN7
Copy link
Contributor

@WalterBright there is this comment from @ibuclaw that has not been addressed.

@RazvanN7
Copy link
Contributor

cc @maxhaton. What are your thoughts on this?

@WalterBright
Copy link
Member Author

@RazvanN7 it had already been addressed.

Copy link
Contributor

@thewilsonator thewilsonator left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it had already been addressed.

No it hasn't, dmd/cpreprocess.d still imports dmd/link.d

@WalterBright
Copy link
Member Author

No it hasn't, dmd/cpreprocess.d still imports dmd/link.d

Right. But cpreprocess.d is only called via a pointer. It does not need to be imported. It is only imported by mars.d, which is not used by gdc and ldc.

@WalterBright WalterBright dismissed thewilsonator’s stale review April 28, 2022 07:18

requirements are already met

@RazvanN7 RazvanN7 added the Merge:72h no objection -> merge The PR will be merged if there are no objections raised. label Apr 28, 2022
@RazvanN7
Copy link
Contributor

Added the "72h no objection -> merge" label.

@ljmf00
Copy link
Member

ljmf00 commented Apr 28, 2022

This should have a changelog entry.

@maxhaton
Copy link
Member

Added the "72h no objection -> merge" label.

The approach is fairly crude but I don't mind merging this for now, as I can still work on mine. This PR cannot last because it can't pick the right preprocessor, but it's good enough for the immediate future.

@ibuclaw
Copy link
Member

ibuclaw commented Apr 29, 2022

@kinke - any comments?

@kinke
Copy link
Contributor

kinke commented Apr 29, 2022

Somewhat off-topic, regarding hardcoded cpp for Posix targets - I assume there are according switches for gcc/clang too? LDC has a -gcc option to explicitly select the C[++] compiler for linking (other option: CC env var); it'd be nice to be able to reuse that for C preprocessing (especially for cross-compilation, where -gcc is often set to something like aarch64-linux-gnu-gcc).

@ibuclaw
Copy link
Member

ibuclaw commented Apr 29, 2022

Somewhat off-topic, regarding hardcoded cpp for Posix targets - I assume there are according switches for gcc/clang too? LDC has a -gcc option to explicitly select the C[++] compiler for linking (other option: CC env var); it'd be nice to be able to reuse that for C preprocessing (especially for cross-compilation, where -gcc is often set to something like aarch64-linux-gnu-gcc).

Agreed on the hard coding of cpp in this PR. For me it would pretty much mean that I can no longer run a part of the DMD testsuite locally anymore (I have a weird set-up with different sysroots for various sorts of compilers, however I'm usually running on the fringe anyway, so do regularly encounter periods when tests are broken for long stretches of time :-).

That the preprocessor handler is an extern(C++) callback though, that would mean you have the opportunity to implement it as you see fit.

I have reservations on this callback expecting a new file to be created though. I might chance it to instead do this all in memory without needing to fork().

@maxhaton
Copy link
Member

Somewhat off-topic, regarding hardcoded cpp for Posix targets - I assume there are according switches for gcc/clang too? LDC has a -gcc option to explicitly select the C[++] compiler for linking (other option: CC env var); it'd be nice to be able to reuse that for C preprocessing (especially for cross-compilation, where -gcc is often set to something like aarch64-linux-gnu-gcc).

Agreed on the hard coding of cpp in this PR. For me it would pretty much mean that I can no longer run a part of the DMD testsuite locally anymore (I have a weird set-up with different sysroots for various sorts of compilers, however I'm usually running on the fringe anyway, so do regularly encounter periods when tests are broken for long stretches of time :-).

That the preprocessor handler is an extern(C++) callback though, that would mean you have the opportunity to implement it as you see fit.

I have reservations on this callback expecting a new file to be created though. I might chance it to instead do this all in memory without needing to fork().

The design in my PR is intended at least somewhat to automate finding the right preprocessor, or make it illegal to use the wrong one. It's beerconf so why not discuss it there I think

@WalterBright
Copy link
Member Author

This PR is coming up on being a month old. I don't have any angst about replacing it with something better, but right now we don't have anything better. We need something that works, and this works.

@WalterBright
Copy link
Member Author

@ibuclaw what's holding this up?

@maxhaton
Copy link
Member

maxhaton commented May 1, 2022

@ibuclaw what's holding this up?

I can't see it so needs to implicitly ImportC.h for one otherwise it's useless in practice because no system headers will work.

@WalterBright
Copy link
Member Author

I'm planning on implicitly #include-ing importc.h after this one is merged.

@WalterBright
Copy link
Member Author

72 hours are up!

@WalterBright WalterBright merged commit 67c6479 into dlang:master May 2, 2022
@WalterBright WalterBright deleted the preprocess branch May 2, 2022 07:43
@kinke
Copy link
Contributor

kinke commented May 2, 2022

I assume there are according switches for gcc/clang too?

Answering myself: yes, both gcc and clang support -E for preprocessing only.

I'm planning on implicitly #include-ing importc.h after this one is merged.

For gcc and clang, -include importc.h does exactly that.

@WalterBright
Copy link
Member Author

@kinke yes. There's also a switch for both MSVC and DMC's preprocessors to do a -include.

WalterBright added a commit to WalterBright/dmd that referenced this pull request May 9, 2022
thewilsonator pushed a commit to thewilsonator/dmd that referenced this pull request May 26, 2022
thewilsonator pushed a commit to thewilsonator/dmd that referenced this pull request May 26, 2022
@ibuclaw
Copy link
Member

ibuclaw commented Nov 20, 2023

It looks like this PR introduced a CI regression.

https://issues.dlang.org/show_bug.cgi?id=24252

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature:ImportC Pertaining to ImportC support Merge:72h no objection -> merge The PR will be merged if there are no objections raised. Review:Easy Review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants