coin-or-tools / BuildTools

Macros and patches for GNU autotools
https://coin-or-tools.github.io/BuildTools/
Other
3 stars 7 forks source link

How to have different flags for compiling and linking #137

Closed tkralphs closed 4 years ago

tkralphs commented 4 years ago

Be default, it seems that CFLAGS are added to the link line by autotools. In the SYMPHONY Makefile produced by the autotools, we have:

LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
    $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
    $(AM_LDFLAGS) $(LDFLAGS) -o $@

The problem is that with cl, there is a flag -TP that needs to used when compiling source files, but not when linking (this flag tells cl to treat files with extension .c as C++ source files). It seems what we did before was actually over-write the link command manually, i.e., we had this in our Makefile.am and then susbtituted a different set of flags (without the -TP).

SYMLINK += cp -f main.$(OBJEXT) symphony-main.$(OBJEXT); $(LIBTOOL) \
    --tag=CXX --mode=link $(CCLD) $(AM_CFLAGS) $(CCLCFLAGS) \
    $(AM_LDFLAGS) $(LDFLAGS) -o $@

It would be nice to avoid this and there must be a more elegant way. I can actually think of lots of ways of doing this, but there must be one that is the "right" way. @svigerske do you know the "right" way to do this?

svigerske commented 4 years ago

Rename your .c files is the first and best thing that comes into my mind. Good opportunity now. :)

Alternatively, you might want to think about it the other way around. How to get -TP only into the flags that are used while compiling. In Clp's Makefile, I see

CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
    $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)

(I guess it's the same on Symphony.) So AM_CPPFLAGS and DEFS would be good candidates to add -TP to.

But you may still need a LINK command that calls the C++ compiler, at least on systems where that has a different name. Maybe adding one dummy .cpp file will do?

tkralphs commented 4 years ago

Yeah, I could rename the files, but it bugs me, since they are (mostly) pure C. It's only Windows with cl that's an issue. It's actually easier when the C++ compiler has a different name, since I can then just set the name of the C compiler to be the C++ compiler. The fact that it calls the C compiler to link doesn't seem to be an issue, since it has the same name. I was able to link SYMPHONY with --tag=CC --mode=link, as long as there is no -TP flag.

I did think about trying to add -TP rather than subtracting it. It doesn't make sense to me that AM_CPPFLAGS is used for compiling and not linking, although they both use the C compiler and not the C++ compiler, but I guess I could use that. DEFS would be OK, although that is obviously not its purpose.

OK, thanks, looks like it will be a hack one way or the other. Why isn't there an obvious easy way to do this?

svigerske commented 4 years ago

There is no "mostly C". If it's C, then use a C compiler. If it's C++, then you want a C++ compiler. Naming the file appropriately helps. You shouldn't mix two languages in one file.

With cl, you have the same compiler for C and C++, with gcc/g++ you wouldn't, so you should make sure that linking will happen with g++ (CXX).

AM_CPPFLAGS is for the C/C++ preprocessor. (AM_CXXFLAGS is for the C++ compiler.)

tkralphs commented 4 years ago

A few small C++ things snuck in over time (variables not declared at the top of blocks, etc.), which I could eliminate if there was a reason, but it is mainly that we are using Osi, etc. internally. I guess you cannot compile C code that call into C++ code with a C compiler. Yeah, I could probably create a C interface for Osi and use that, but what's the point? I could drop back to the C interfaces of individual solvers, but again, what's the point? I think it would be confusing to call this C++ code, when it clearly does not use even the most basic C++ idioms, especially for memory management. Compiling it as C++ is just a hack to save writing and maintaining some C interfaces for no reason.

Anyway, everything is already working fine already with gcc/g++. I didn't realize the distinction between AM_CPPFLAGS and AM_CXXFLAGS. That is pretty arcane, but good to know.