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

Add necessary C++ flags for most common compilers #3802

Merged
merged 15 commits into from
Jan 13, 2021

Conversation

voodoos
Copy link
Collaborator

@voodoos voodoos commented Sep 18, 2020

This PR is an attempt to answer #3528.

It adds a new module with a small "database" of C++ flags that are necessary to the use of some of the most common C compiler to build C++ code.

Given the actual context and whether C or C++ code is being built, this module provide the set of necessary flags that should be added to the compiler command line : from the database mentioned above for C++ and from the config ocamlc_cflags and ocamlc_cppflags for C. For convenience it also add the FDO flags tot he list and also returns the output args that should be used for the specified compiler.

The main issue is that, because these C++ flags where not added by Dune before, users probably added them themselves and they will be duplicated in the command line. I am not sure whether this would break builds or not, but if it does we should consider enabling this change only for dune 2.8 or with a specific option in the dune-project file.

The added flags for C++ are the following:

Compiler C++ flags
gcc -x c++ -lstdc++ -shared-libgcc
clang -x c++
msvc /TP

@voodoos voodoos linked an issue Sep 18, 2020 that may be closed by this pull request
@voodoos voodoos changed the title Cxx flags db Add necessary C++ flags for most common compilers Sep 18, 2020
@voodoos voodoos requested a review from a user September 18, 2020 15:04
@voodoos
Copy link
Collaborator Author

voodoos commented Sep 18, 2020

Also, does someone has a good strategy in mind for testing these changes ?

@voodoos voodoos force-pushed the cxx-flags-db branch 2 times, most recently from e889855 to bd7f9f4 Compare September 28, 2020 14:33
Copy link
Member

@dra27 dra27 left a comment

Choose a reason for hiding this comment

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

Not a comprehensive review. This may well work now, but it does feel very brittle - there are Windows stories where the compiler may very well be callable, but this test would fail (and there are both clang and gcc on Windows, not that I actually used clang on Windows before).

The OCaml implementation of this is at https://github.com/ocaml/ocaml/blob/cb32b88aa1205339dc888a69a895e0de40b1bd3c/aclocal.m4#L38-L62 which works by invoking the C compiler.

Calling the C compiler every time might be a bit heavy (although ocamlc -config is acceptable, so maybe not?), but would it be possible to introduce a rule which is depended on by rules requiring the C++ compiler which effectively does this test once? Essentially, were I trying to detect this in dune files directly, I'd have something along the lines of:

(rule
  (with-stdout-to cxxflags.sexp (run configure.exe get-cxx-flags)))

(library
  ..
  (cflags (:include cxxflags.sexp)))

(cf.

src/ocaml-config/ocaml_config.ml Outdated Show resolved Hide resolved
@voodoos
Copy link
Collaborator Author

voodoos commented Oct 1, 2020

Not a comprehensive review. This may well work now, but it does feel very brittle - there are Windows stories where the compiler may very well be callable, but this test would fail (and there are both clang and gcc on Windows, not that I actually used clang on Windows before).

Thank you for your feedback !

We discussed this matter with @jeremiedimino and decided to keep the current strategy even if it is not complete.
We will make it an opt-in behaviour in the dune-project and ask early users to open an issue when the compiler detection fails to identify the compiler. This should help us identify the cases that need specific handling.

It also feels that this detection being done by OCaml, it could be easily reflected in the ocamlc_config ccomp_type field, shouldn't it ?

@rgrinberg
Copy link
Member

Also, does someone has a good strategy in mind for testing these changes ?
Consider using https://github.com/dune-universe/dune-universe

@voodoos
Copy link
Collaborator Author

voodoos commented Nov 4, 2020

After discussing the matter with @jeremiedimino, we decided to group both this PR and the one about C-flags under the same option to facilitate users ' conversion.

That led me to the quite ugly option name no_forced_c_flags_and_more_cxx_flags. If you have a better idea I am willing to change it.

This also means that both these PR should be merged in the same release (@rgrinberg).

@ghost
Copy link

ghost commented Nov 5, 2020

One idea would be to emphasis the fact that we want to make this the default in the future: future_c_and_cxx_flags_handling

@rgrinberg
Copy link
Member

One idea would be to emphasis the fact that we want to make this the default in the future: future_c_and_cxx_flags_handling

IMO, that's a bad name. It's going to be quite confusing when the future this option refers to will be the present. We should stick to names that reflect the behavior as best as possible.

@voodoos
Copy link
Collaborator Author

voodoos commented Nov 19, 2020

Compiler detection broke on MacOS Big Sur: cc is not a symlink to clang anymore but some sort of executable proxy.
Now I feel like we really need the detection to be more clever or too many users will receive the warning.

Our options are:

  1. Have the compiler add this to ocamlc -config
  2. Parse the --version output
  3. Test which preprocessor directives are defined (probably le best)

The difficulty is that we want to group this under the same option as Standard C flags but the timing may be bad for having everything on the same release. But if we decide the option not to be a boolean we could have:

(use_standard_c_and_cxx_flags none)
(use_standard_c_and_cxx_flags c_only)
(use_standard_c_and_cxx_flags both)

That way if this PR is not ready for Dune 2.8 we can just ship the first two options.

@jeremiedimino do you have an opinion on that ?

@ghost
Copy link

ghost commented Nov 25, 2020

The version without the argument seems simpler to me and one version is not a long time to wait. So I'd say we hold off releasing the first feature to user until the second one is ready.

AFAIU, the first feature is already in master. We don't need to revert it, instead we can "disconnect" the feature, i.e. disable the parsing of the option and let it always be disabled. And also disable the tests until 2.8 is released.

@voodoos voodoos added this to the 2.9 milestone Nov 25, 2020
@voodoos
Copy link
Collaborator Author

voodoos commented Dec 3, 2020

I reworked the detection of the compiler:

  • In the .dune folder a small C header file is written with preprocessor directives that check if some macros are define or not
  • When needed Dune will run the C compiler's preprocessor on this file and the output, the compiler type, will be written in a file in the .dune folder
  • This file is read when determining the content of the :standard flags that depend on the compiler type.

The current preprocessing file is the following:

#if defined ( __clang__ )
  #define CCOMP clang
#elif defined ( __MINGW32__ ) || defined ( __MINGW64__ )
  #define CCOMP mingw
#elif defined ( _MSC_VER )
  #define CCOMP msvc
#elif defined ( __GNUC__ )
  #define CCOMP gcc
#else
  #define CCOMP other
#endif

CCOMP

@jeremiedimino, @dra27 does that look more robust to you ?

@rgrinberg When do you plan to release dune 2.8 ? It would be great if we could squeeze this in because it blocks the C improvments PR (#3875) which is also ready. However no need to delay further the release, if necessary these will wait for 2.9.

@voodoos voodoos requested a review from dra27 December 3, 2020 17:17
src/dune_rules/cxx_rules.ml Outdated Show resolved Hide resolved
#if defined( __clang__ )
#define CCOMP clang
#elif defined( __MINGW32__) || defined( __MINGW64__ )
#define CCOMP mingw
Copy link
Member

Choose a reason for hiding this comment

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

This distinction isn't used anywhere (I think). Two options:

  • mingw-w64 defines __GNUC__, so this could be omitted
  • I haven't used/tested it, but it's possible (and done) to build mingw-w64 using clang - so if this distinction is to be kept, I think __MINGW32__ should be tested before __clang__ since otherwise __MINGW32__ trumps __GNUC__ but not __clang__

src/dune_rules/cxx_flags.ml Outdated Show resolved Hide resolved
Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

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

Looks good, except for the conditional generation of the rule in gen_rules.ml

src/dune_rules/gen_rules.ml Outdated Show resolved Hide resolved
Signed-off-by: Ulysse Gérard <thevoodoos@gmail.com>
Signed-off-by: Ulysse Gérard <thevoodoos@gmail.com>
Signed-off-by: Ulysse Gérard <thevoodoos@gmail.com>
Signed-off-by: Ulysse Gérard <thevoodoos@gmail.com>
Signed-off-by: Ulysse Gérard <thevoodoos@gmail.com>
Signed-off-by: Ulysse Gérard <thevoodoos@gmail.com>
Signed-off-by: Ulysse Gérard <thevoodoos@gmail.com>
Signed-off-by: Ulysse Gérard <thevoodoos@gmail.com>
Signed-off-by: Ulysse Gérard <thevoodoos@gmail.com>
Signed-off-by: Ulysse Gérard <thevoodoos@gmail.com>
Signed-off-by: Ulysse Gérard <thevoodoos@gmail.com>
Signed-off-by: Ulysse Gérard <thevoodoos@gmail.com>
Signed-off-by: Ulysse Gérard <thevoodoos@gmail.com>
Signed-off-by: Ulysse Gérard <thevoodoos@gmail.com>
Signed-off-by: Ulysse Gérard <thevoodoos@gmail.com>
Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

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

LGTM

@voodoos voodoos merged commit 1dd3d7c into ocaml:master Jan 13, 2021
rgrinberg added a commit to rgrinberg/opam-repository that referenced this pull request Jan 13, 2021
…ne-action-plugin, dune-private-libs and dune-glob (2.8.0)

CHANGES:

- `dune rules` accepts aliases and other non-path rules (ocaml/dune#4063, @mrmr1993)

- Action `(diff reference test_result)` now accept `reference` to be absent and
  in that case consider that the reference is empty. Then running `dune promote`
  will create the reference file. (ocaml/dune#3795, @bobot)

- Ignore special files (BLK, CHR, FIFO, SOCKET), (ocaml/dune#3570, fixes ocaml/dune#3124, ocaml/dune#3546,
  @ejgallego)

- Experimental: Simplify loading of additional files (data or code) at runtime
  in programs by introducing specific installation sites. In particular it allow
  to define plugins to be installed in these sites. (ocaml/dune#3104, ocaml/dune#3794, fixes ocaml/dune#1185,
  @bobot)

- Move all temporary files created by dune to run actions to a single directory
  and make sure that actions executed by dune also use this directory by setting
  `TMPDIR` (or `TEMP` on Windows). (ocaml/dune#3691, fixes ocaml/dune#3422, @rgrinberg)

- Fix bootstrap script with custom configuration. (ocaml/dune#3757, fixes ocaml/dune#3774, @marsam)

- Add the `executable` field to `inline_tests` to customize the compilation
  flags of the test runner executable (ocaml/dune#3747, fixes ocaml/dune#3679, @lubegasimon)

- Add `(enabled_if ...)` to `(copy_files ...)` (ocaml/dune#3756, @nojb)

- Make sure Dune cleans up the status line before exiting (ocaml/dune#3767,
  fixes ocaml/dune#3737, @alan-j-hu)

- Add `{gitlab,bitbucket}` as options for defining project sources with `source`
  stanza `(source (<host> user/repo))` in the `dune-project` file.  (ocaml/dune#3813,
  @rgrinberg)

- Fix generation of `META` and `dune-package` files when some targets (byte,
  native, dynlink) are disabled. Previously, dune would generate all archives
  for regardless of settings. (ocaml/dune#3829, ocaml/dune#4041, @rgrinberg)

- Do not run ocamldep to for single module executables & libraries. The
  dependency graph for such artifacts is trivial (ocaml/dune#3847, @rgrinberg)

- Fix cram tests inside vendored directories not being interpreted correctly.
  (ocaml/dune#3860, fixes ocaml/dune#3843, @rgrinberg)

- Add `package` field to private libraries. This allows such libraries to be
  installed and to be usable by other public libraries in the same project
  (ocaml/dune#3655, fixes ocaml/dune#1017, @rgrinberg)

- Fix the `%{make}` variable on Windows by only checking for a `gmake` binary
  on UNIX-like systems as a unrelated `gmake` binary might exist on Windows.
  (ocaml/dune#3853, @kit-ty-kate)

- Fix `$ dune install` modifying the build directory. This made the build
  directory unusable when `$ sudo dune install` modified permissions. (fix
  ocaml/dune#3857, @rgrinberg)

- Fix handling of aliases given on the command line (using the `@` and `@@`
  syntax) so as to correctly handle relative paths. (ocaml/dune#3874, fixes ocaml/dune#3850, @nojb)

- Allow link time code generation to be used in preprocessing executable. This
  makes it possible to use the build info module inside the preprocessor.
  (ocaml/dune#3848, fix ocaml/dune#3848, @rgrinberg)

- Correctly call `git ls-tree` so unicode files are not quoted, this fixes
  problems with `dune subst` in the presence of unicode files. Fixes ocaml/dune#3219
  (ocaml/dune#3879, @ejgallego)

- `dune subst` now accepts common command-line arguments such as
  `--debug-backtraces` (ocaml/dune#3878, @ejgallego)

- `dune describe` now also includes information about executables in addition to
  that of libraries. (ocaml/dune#3892, ocaml/dune#3895, @nojb)

- instrumentation backends can now receive arguments via `(instrumentation
  (backend <name> <args>))`. (ocaml/dune#3906, ocaml/dune#3932, @nojb)

- Tweak auto-formatting of `dune` files to improve readability. (ocaml/dune#3928, @nojb)

- Add a switch argument to opam when context is not default. (ocaml/dune#3951, @tmattio)

- Avoid pager when running `$ git diff` (ocaml/dune#3912, @AltGr)

- Add `(root_module ..)` field to libraries & executables. This makes it
  possible to use library dependencies shadowed by local modules (ocaml/dune#3825,
  @rgrinberg)

- Allow `(formatting ...)` field in `(env ...)` stanza to set per-directory
  formatting specification. (ocaml/dune#3942, @nojb)

- [coq] In `coq.theory`, `:standard` for the `flags` field now uses the
  flags set in `env` profile flags (ocaml/dune#3931 , @ejgallego @rgrinberg)

- [coq] Add `-q` flag to `:standard` `coqc` flags , fixes ocaml/dune#3924, (ocaml/dune#3931 , @ejgallego)

- Add support for Coq's native compute compilation mode (@ejgallego, ocaml/dune#3210)

- Add a `SUFFIX` directive in `.merlin` files for each dialect with no
  preprocessing, to let merlin know of additional file extensions (ocaml/dune#3977,
  @vouillon)

- Stop promoting `.merlin` files. Write per-stanza Merlin configurations in
  binary form. Add a new subcommand `dune ocaml-merlin` that Merlin can use to
  query the configuration files. The `allow_approximate_merlin` option is now
  useless and deprecated. Dune now conflicts with `merlin < 3.4.0` and
  `ocaml-lsp-server < 1.3.0` (ocaml/dune#3554, @voodoos)

- Configurator: fix a bug introduced in 2.6.0 where the configurator V1 API
  doesn't work at all when used outside of dune. (ocaml/dune#4046, @aalekseyev)

- Fix `libexec` and `libexec-private` variables. In cross-compilation settings,
  they now point to the file in the host context. (ocaml/dune#4058, fixes ocaml/dune#4057,
  @TheLortex)

- When running `$ dune subst`, use project metadata as a fallback when package
  metadata is missing. We also generate a warning when `(name ..)` is missing in
  `dune-project` files to avoid failures in production builds.

- Remove support for passing `-nodynlink` for executables. It was bypassed in
  most cases and not correct in other cases in particular on arm32.
  (ocaml/dune#4085, fixes ocaml/dune#4069, fixes ocaml/dune#2527, @emillon)

- Generate archive rules compatible with 4.12. Dune longer attempt to generate
  an archive file if it's unnecessary (ocaml/dune#3973, fixes ocaml/dune#3766, @rgrinberg)

- Fix generated Merlin configurations when multiple preprocessors are defined
  for different modules in the same folder. (ocaml/dune#4092, fixes ocaml/dune#2596, ocaml/dune#1212 and
  ocaml/dune#3409, @voodoos)

- Add the option `use_standard_c_and_cxx_flags` to `dune-project` that 1.
  disables the unconditional use of the `ocamlc_cflags` and `ocamlc_cppflags`
  from `ocamlc -config` in C compiler calls, these flags will be present in the
  `:standard` set instead; and 2. enables the detection of the C compiler family
  and populates the `:standard` set of flags with common default values when
  building CXX stubs. (ocaml/dune#3875, ocaml/dune#3802, fix ocaml/dune#3718 and ocaml/dune#3528, @voodoos)
@voodoos
Copy link
Collaborator Author

voodoos commented Apr 9, 2021

@ejgallego this has already been released in 2.8.0, but with an option in the dune-project to enable it.

I think we want to make that default for 3.0.0, i will change the Milestone accordingly.

@voodoos voodoos modified the milestones: 2.9, 3.0 Apr 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Better support for C++
3 participants