Build system: honour the CFLAGS and CPPFLAGS build variables#9824
Build system: honour the CFLAGS and CPPFLAGS build variables#9824dra27 merged 3 commits intoocaml:trunkfrom
Conversation
276f767 to
56c3214
Compare
|
Something in this is causing |
|
David Allsopp (2020/08/04 11:30 +0000):
Is this definitely what we want? It seems unquestionably correct that
the build of the system respects `CFLAGS` given at build time and
defaults to the `CFLAGS` at `configure` for building OCaml, but it
doesn’t seem like `ocamlc -c` should *have* to respect `CFLAGS`. If it
does, shouldn’t it be in the same way - i.e. shouldn’t `ocamlc -c`
always append the *current* value of `CFLAGS`, defaulting to the value
of `CFLAGS` when `config.mlp` was built if it’s not presently defined?
I am not sure I am following you, @dra27.
As far as I understand and could test, \utils/config.ml` will not
contain any reference to either CFLAGS or CPPFLAGS, so the values that
will be used by ocamlc and ocamlopt are thos that were passed to the
build system either at configure or at build time, the latter taking
precedence. Or am I misunderstanding your point here?
|
|
David Allsopp (2020/08/04 11:31 +0000):
Something in this is causing `-g` to be passed to msvc which is
displaying a warning and so causing several tests to fail. I’m happy
to look into this, @shindere?
Indeed, sorry about that.
I am able to reproduce the problem so I will work on it, thanks a lot
for having reported it, @dra27.
I will report back here as soon as I have a fix.
|
Well, I'm clearly not making my point properly! What I mean is that at
is better than permanently storing what |
56c3214 to
5cd670b
Compare
|
David Allsopp (2020/08/04 11:31 +0000):
Something in this is causing `-g` to be passed to msvc which is
displaying a warning and so causing several tests to fail. I’m happy
to look into this, @shindere?
IT's fixed. It was libtool (more precisely the LT_INIT macro) which
caused CFLAGS to be altered.
I didn't try to understand exactly why that happened. I just saved
CFLAGS before the call to LT_INIT and restored it right after the call.
This change has been squashed into the main commit.
|
|
David Allsopp (2020/08/04 06:13 -0700):
Well, I'm clearly not making my point properly! What I mean is that
at `configure`-time, we store the value of `CFLAGS` and `CPPFLAGS`
so that we can use them at build time if they're specified a second
time.
Well,; I'd have said if they are _not_ specified a second time. If they
are specified a second time, or if other values are given at build time,
then those will take precedence over the ones that have been stored at
configure time.
So at build time, you can override the values given at configure-time.
Yes, I agree with this.
I'm querying whether one of:
- `ocamlc -c foo.c` behaving the same way - if you specify `CFLAGS` (e.g. CFLAGS="-Wall -Werror" `ocamlc -c foo.c`) then you should get those `CFLAGS` and not the ones that `config.ml` was built with (i.e. in that example you'd get `$common_cflags $sharedlib_cflags -Wall -Werror`).
- ignoring `CFLAGS` and `CPPFLAGS` entirely in `OCAMLC_CFLAGS` and
- `OCAMLC_CPPFLAGS`. All of our C files are compiled directly by
- calling `$(CC)`, not by calling `ocamlc -c`, so the whole of _our_
- build system respects `CFLAGS` and `CPPFLAGS` - do we definitely
- need to preserve those flags so that they get used for `ocamlc -c`
- whose purpose is to invoke the C compiler to allow C stubs to be
- compiled correctly?
Yes, we do. It is something that had been discussed with the Bloomberg
team before I submitted the PR and they definitely need this feature. We
also discussed it with @xavierleroy and we really think it makes things
more coherent.
|
|
@dra27: While going through the It seems it was you who added that build. May I ask what you wanted to test there? Do you think there is a real need for this kind of build in addition to |
|
What about It means that the runtime itself is not linked with those set, neither is That's the only remaining question from me! |
5cd670b to
220aa34
Compare
|
David Allsopp (2020/08/04 14:17 +0000):
What about `MKEXE`? At the moment `MKEXE_BOOT` does include `CFLAGS`
and `CPPFLAGS` but `MKEXE` does not - I think it probably should?
Yes, you are absolutely right! Many thanks for your care in reviewing, I
apologies for having forgotten this variable.
I have rebased the branch on latest trunk, fixed `mkexe` in
`configure.ac` and also updated the Changes entry to credit you, @dra27.
|
|
check-typo is grumbling about whitespace at EOL in |
It was not used, except in lex/Makefile where this commit replaces its unique occurrence by its definition in the same file.
220aa34 to
8f0ed74
Compare
|
Many thanks again for your care, @dra27.
David Allsopp (2020/08/05 09:31 +0000):
check-typo is grumbling about whitespace at EOL in `configure.ac`.
Gasp, sorry. Fixed.
I have one remaining piece of nervousness about `MKEXE` - normally, it
calls a C compiler but for native Windows and shared-enabled Cygwin it
calls `flexlink`.
Well spotted, thanks!
I wonder if `CFLAGS` and `CPPFLAGS` should _not_ be
included if `mkexe` is changed to `flexlink`?
Yeah, you are right I think! I shall change the code to fix this, once
we are clear about what needs to be done. My concern here is that, sure
the flags should not be included if MKEXE boils down to calling
flexlink. But then, do we have a way to make sure that the flags would
ultimately be used? Shall they somehow be passed to flexlink so that it
can in turn pass them to the C compiler when it calls it, if it does so?
I'm musing if the error
was in fact that `MKEXE_BOOT` should not use `CFLAGS` or `CPPFLAGS`
(especially the latter, given that I don't think you can reliably use
`MKEXE` with `.c` files). Maybe MKEXE should only be respecting
`LDFLAGS` and never passing `CFLAGS` or `CPPFLAGS` because it should
never be compiling C sources?
I don't know. At the moment there is only one place where MKEXE compiles
a C source file, namely in the main Makefile where it compiles
checkstack.
|
|
This is really useful on the BSDs, where we often pass custom CFLAGS and CPPFLAGS as part of ports invocations! Just one suggestion: perhaps also pass LDFLAGS though to OC_LDFLAGS. It's fairly common practise to set both of these at the same time. For example, on OpenBSD, everything is installed in is often used to both find the include files and also let the linker find the shared libraries for a port. |
|
Reading for the nth time the GNU make documentation of
|
|
I agree with @avsm that |
|
I think the same consideration applies to |
|
Dear Anil,
Many thanks for your interest in this, it is warmly appreciated.
Yes, I fully agree with you that LDFLAGS should be honoured, too. Same
holds for LDLIBS actually, I think.
It was my initial intention to make all these variables work in this PR,
but then I renounced, because the PR seemed already big enough and is
useful in itself at least for your friends at Bloomberg and also because
I find the library-related variables in our build system a bit messy, so
it felt more convenient and swallowable to keep things separate. But I
definitely intent to work on the two other variables, too.
|
|
@Êra27 responding to your two last comments: I agree, as you cansee I
wrote the same.
But, is it okay to deal with LDFLAGS and LDLIBS in another PR?
|
|
I was wondering if you'd prefer to do that, yes, @shindere! In which case, to leave the tree in a good intermediate state prior to that PR, I think there are two things which should be done:
I think those changes are appropriate here for correct handling of |
|
Yes, @Êra27, that looks reasonable to me too and I will implement your
suggestions ASAP and come back to you.
Did you see my earlier question about the old-style build in
extra-checks?
Thanks!
|
Yes, I replied in #9824 (comment)! It was added in #8845 which includes the explanation - I think it should stay, because it tests that the build system doesn't mess up if the compiler is built in stages (in particular that you don't end up where the build system expects that |
|
OK thanks and sorry I missed this response, I don't know what I did.
Apologies.
|
|
Blame the heat! :) |
8f0ed74 to
7b8e489
Compare
|
David Allsopp (2020/08/05 06:28 -0700):
I think the same consideration applies to `LDLIBS`, although for our
purposes we can probably have `OC_LDFLAGS` as we do now including
`$(LDFLAGS) $(LDLIBS)`? (TL;DR from
https://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html is that `-L dir` goes in `LDFLAGS` and `-lfoo` goes in `LDLIBS`)
Ultimately, I'd like to have things very clean and very separate, so I
hope we will end up having the distinction between ld flags and ld
libraries in place both for the internal build system variables and for
the user variables we use.
|
|
David Allsopp (2020/08/05 06:25 -0700):
Reading for the nth time the GNU make documentation
It's funny, I, too, am constantly reading it again and again.
I can't think of any other documnetation I am reading that much, that
thoroughly and that repeatedly. I am unable to find any explanation to
that.
of `CFLAGS`, `CPPFLAGS` and `LDFLAGS`, `LDFLAGS` is definitely
flags intended for the _C compiler_ to pass on to the linker
(so `-L`, etc.). `flexlink` should accept anything you'd expect the
underlying compiler (either `cl` or `gcc`) to accept at this point
too, even though flexlink actually calls the linker directly
(we recently added `-Wl` support, for example, and `flexlink`
automatically makes `-lfoo` portable between cl and gcc).
Is that to say that the `-link` flags we add in front of each link flag
when passing them to flexlink has now become superfluous?
So I think we should:
- Ensure that `MKEXE` is only ever used as a linker - that means that whatever is called is expected to produce an executable file from .o or .obj files only.
- Only pass `$(OC_LDFLAGS)` and `$(LDFLAGS)` at this point
So that's done now, I think. In this PR, I mean.
|
There was a problem hiding this comment.
A suggestion only to use .INTERMEDIATE and not have to call rm by hand - it does have the added benefit that the files get cleaned up even if there's an error running them, which (I think) is nice.
The rule has a small change in semantics - in the past it silently skipped the check if the executable failed to build. That could be achieved with:
checkstack:
if $(MAKE) tools/checkstack$(EXE); then \
tools/checkstack$(EXE); \
rm -f tools/checkstack$(EXE); \
fialthough erasing tools/checkstack$(EXE) on error results in messy code. I wonder why @damiendoligez allowed the test to be skipped on a failed build originally?
Makefile
Outdated
| checkstack: tools/checkstack$(EXE) | ||
| $< | ||
| rm -f $< | ||
|
|
||
| tools/checkstack$(EXE): tools/checkstack.$(O) | ||
| $(MKEXE) $(OUTPUTEXE)$@ $< | ||
| rm $^ |
There was a problem hiding this comment.
| checkstack: tools/checkstack$(EXE) | |
| $< | |
| rm -f $< | |
| tools/checkstack$(EXE): tools/checkstack.$(O) | |
| $(MKEXE) $(OUTPUTEXE)$@ $< | |
| rm $^ | |
| checkstack: tools/checkstack$(EXE) | |
| $< | |
| .INTERMEDIATE: tools/checkstack$(EXE) tools/checkstacxk.$(O) | |
| tools/checkstack$(EXE): tools/checkstack.$(O) | |
| $(MKEXE) $(OUTPUTEXE)$@ $< |
This has the nice benefit that GNU make automatically removes the executable and object even if running the program fails.
No, for two reasons - the first is that I wouldn't be confident that |
7b8e489 to
f156a74
Compare
With this commit, it becomes possible to provide C compiler and preprocessor flags to use in addition to those defined by the build system. As required by the GNU coding standards, the flags can be provided either at configure or at make invocation. The provided CFLAGS and CPPFLAGS will also be taken into account when C code is compiled by ocamlc/ocamlopt. This commit removes the explicit reference to CFLAGS in the configuration for the xlc compiler, since it is not necessary any longer.
Use the ability to pass flags to the C compiler at configure time to simplify this CI script. Looking at the diff, it may seem that some flags like -fwrapv, -fno-strict-aliasing, -Wall and -Werror got lost by this commit. It is actually not the case. In its previous version, this script was overriding the flags as defined by the compiler's build system, so it had to provide a rather exhaustive list of flags. Now one only needs to add the flags specific to the build one wishes to do. The flags mentionned above* are provided by the compiler's build system so they do not need to be mentionned here any longer.
|
David Allsopp (2020/08/06 03:56 -0700):
@dra27 commented on this pull request.
A suggestion only to use `.INTERMEDIATE` and not have to call `rm` by hand - it does have the added benefit that the files get cleaned up even if there's an error running them, which (I think) is nice.
The rule has a small change in semantics - in the past it silently skipped the check if the executable failed to build. That could be achieved with:
```make
checkstack:
if $(MAKE) tools/checkstack$(EXE); then \
tools/checkstack$(EXE); \
rm -f tools/checkstack$(EXE)
fi
```
although erasing `tools/checkstack$(EXE)` on error results in messy code. I wonder why @damiendoligez allowed the test to be skipped on a failed build originally?
> +checkstack: tools/checkstack$(EXE)
+ $<
+ rm -f $<
+
+tools/checkstack$(EXE): tools/checkstack.$(O)
+ $(MKEXE) $(OUTPUTEXE)$@ $<
+ rm $^
```suggestion
checkstack: tools/checkstack$(EXE)
$<
.INTERMEDIATE: tools/checkstack$(EXE) tools/checkstacxk.$(O)
tools/checkstack$(EXE): tools/checkstack.$(O)
$(MKEXE) $(OUTPUTEXE)$@ $<
```
This has the nice benefit that GNU make automatically removes the
executable and object even if running the program fails.
Yeah that's a good idea! Thanks!
It makes the code a bit less weird.
It is sad I didn't think about htis in spite of these many readings of
make's doc.
But anyway, it has been implemented and I introduced a `checkstack`
variable to factorise the `tools/checkstack` bit.
@dra27 I don't know either why @damiendoligez did that trick to ignore
errors while compiling the program but it feels to me this should not be
so, at least as long as we don't know what the errors can be.
Also, @dra27, you didn't comment the `making checkstack a configure-time
check` bit. Is that to say you have no opinion on this?
|
f156a74 to
7c0623b
Compare
I get this feeling every time Xavier simplifies my code 😉
Oh no, that was an error - I don't have a strong opinion, because I don't fully understand the history of the script/program - it looks like the original intent was "if we can build this test, then rely on it" which sounds more like it should be in the build system. I think it's meant to stop you running a build with settings which are clearly likely to fail (and written at a time nearly 20 years ago where that might have wasted a lot of time). If it moves to |
|
Sure, precheck is a good idea. It's build #479.
And for the rest yes, let's leave this `checkstack` thing where it is at
the moment.
|
|
Sorry to bear bad news, but the "extra-checks" CI is broken. Hint: the |
|
Darn - can that be fixed by a partial revert of the deletions to extra-checks and use the set_key trick on OC_LDFLAGS? The hack can then be completely removed when |
|
Xavier Leroy (2020/08/06 08:02 -0700):
Sorry to bear bad news, but the "extra-checks" CI is broken.
Yep, I noticed, too.
Hint: the `-fsanitize=xxx` option is needed at link-time too, not just
at compile-time.
Thanks! It's weird, I was sure I did check that.
That confirms to me that extra-checks needs to be included in precheck.
|
|
I am pretty sure that CFLAGS must be passed to the C compiler even when linking. There's a number of options that are relevant for code generation and for linking as well, e.g. Quoting the scriptures (GNU make manual): "Extra flags to give to the C compiler" is not "extra flags to give to the C compiler unless it is supposed to invoke the linker". |
|
Xavier Leroy (2020/08/07 00:08 -0700):
I am pretty sure that CFLAGS must be passed to the C compiler even when linking. There's a number of options that are relevant for code generation and for linking as well, e.g. `-g` for debug builds.
Quoting the scriptures (GNU make manual):
```
'CFLAGS'
Extra flags to give to the C compiler.
'LDFLAGS'
Extra flags to give to compilers when they are supposed to invoke
the linker, 'ld', such as '-L'. Libraries ('-lfoo') should be
added to the 'LDLIBS' variable instead.
```
"Extra flags to give to the C compiler" is not "extra flags to give to
the C compiler unless it is supposed to invoke the linker".
Yeah that's my understanding, too. But htat means that we should have
left CFLAGS in the MKEXE and MKEXE_BOOT variables, right? And that the
most recent work on this PR (about checkstack) was perhaps a bit
counterproductive?
My suggestion would be that I create a new PR as a follow-up to this
one, where I add again the OC_CFLAGS and CFLAGS again to MKEXE and
MKEXE_BOOT but only when they call the C compiler, not when they call
flexlink.
What do you think @dra27 and @xavierleroy?
Shall I proceed that way?
… |
|
I think the checkstack part remains fine. I think your suggestion is the way to go for now, @shindere, so that everything gets back to working properly - then we can figure out whether to change that, or to change how flexlink is invoked, as the long-term fix to MKEXE |
|
Suggestion implemented in PR #9837, thanks.
|
|
David Allsopp (2020/08/05 08:46 -0700):
> Did you see my earlier question about the old-style build in
extra-checks?
Yes, I replied in
#9824 (comment)! It
was added in #8845 which includes the explanation - I think it should
stay, because it tests that the build system doesn't mess up if the
compiler is built in stages (in particular that you don't end up where
the build system expects that `.opt` tools should be available)
I started to split `extra-checks`in smaller bits by isolating
`check-typo`so that it runs as its own Jenkins job.
I'd like to do the same with that bit and am wondering what a good name
for that job would be? I'm thinking about `sequential-build. Can
somebody think about a name that conveys more meaning?
Then extra-checks would contain only calls to sanitizers, and we could
replace it with a more dedicated sanitizers job.
|
Sequential feels like it implies non-parallel. "Stepwise"? I referred to it as the "old school" build (idiomatically, it's very similar to old-fashioned, but with more respect and fondness). |
|
How about step-by-step-build ?
|
Sure! |
With this PR, it becomes possible to specify C preprocessor and
C compiler flags to be used in addition to those defined by the build
system when compiling OCaml.
These flags can be passed at both the
configureandmakestage.They are passed on also when ocamlc/ocamlopt invokes the C compiler to
compile a C source file.
This PR has 3 commits and is best reviewed commit by commit.
The first commit eliminates the unused
YACCFLAGSvariable.The second commit is the heart of the PR and implements what has been
described above.
The third and last commit takes advantage of what has been implemented
in the earlier one to slightly
simplify a continuous integration script.