CMAKE + Visual Studio: /MT vs /MD builds

3,607 views
Skip to first unread message

Greg Ercolano

unread,
Dec 12, 2017, 8:36:41 PM12/12/17
to fltkg...@googlegroups.com
For what it's worth, anyone using fltk 1.4.x + CMAKE + Visual Studio
might want to do what I needed to do: change the default /MD build flag
to use /MT instead.

My FLTK applications build with the /MT flag, but the default cmake
creates IDE projects that by default build FLTK with /MD, the discrepancy
causing not-so-helpful errors at link time, the likes of which being:

MSVCRT.lib(MSVCR90.dll) : error LNK2005: _malloc already defined in LIBCMT.lib(bla.obj)
MSVCRT.lib(MSVCR90.dll) : error LNK2005: _fwrite already defined in LIBCMT.lib(bla.obj)
MSVCRT.lib(MSVCR90.dll) : error LNK2005: _getenv already defined in LIBCMT.lib(bla.obj)
[..ad nauseum..]

To solve this, I grepped around for the /MD flag, and found them in the
default CMakeCache.txt file that cmake created.

I found I could redefine the variables (named things like CMAKE_*_FLAGS_RELEASE)
via the cmake command line:

cmake -G "Visual Studio 7" \
-D CMAKE_BUILD_TYPE=Release \
-D CMAKE_CXX_FLAGS_RELEASE="/MT /O2 /Ob2 /D NDEBUG" \
-D CMAKE_C_FLAGS_RELEASE="/MT /O2 /Ob2 /D NDEBUG" ..

..which created an fltk project with the /MT flag that then Visual Studio
would build correctly for my apps.

This made it easier to have a script rebuild FLTK for my application setup.

The above settings worked for Visual Studio 7.. I imagine similar techniques
can be used for the newer Visual Studio compilers.

I'm not sure if there's an easier way to control this flag, as there's
quite a few other flags, and there's several variable names for other
build targets, e.g. debug builds (which were not my concern in this case).

Anyway, hope that helps someone..

Albrecht Schlosser

unread,
Dec 13, 2017, 8:26:05 AM12/13/17
to fltkg...@googlegroups.com
On 13.12.2017 02:36 Greg Ercolano wrote:
> For what it's worth, anyone using fltk 1.4.x + CMAKE + Visual Studio
> might want to do what I needed to do: change the default /MD build flag
> to use /MT instead.
>
> My FLTK applications build with the /MT flag, but the default cmake
> creates IDE projects that by default build FLTK with /MD, the discrepancy
> causing not-so-helpful errors at link time, the likes of which being:
>
> MSVCRT.lib(MSVCR90.dll) : error LNK2005: _malloc already defined in LIBCMT.lib(bla.obj)
> MSVCRT.lib(MSVCR90.dll) : error LNK2005: _fwrite already defined in LIBCMT.lib(bla.obj)
> MSVCRT.lib(MSVCR90.dll) : error LNK2005: _getenv already defined in LIBCMT.lib(bla.obj)
> [..ad nauseum..]
>
> To solve this, I grepped around for the /MD flag, and found them in the
> default CMakeCache.txt file that cmake created.
>
> I found I could redefine the variables (named things like CMAKE_*_FLAGS_RELEASE)
> via the cmake command line:
>
> cmake -G "Visual Studio 7" \
> -D CMAKE_BUILD_TYPE=Release \
> -D CMAKE_CXX_FLAGS_RELEASE="/MT /O2 /Ob2 /D NDEBUG" \
> -D CMAKE_C_FLAGS_RELEASE="/MT /O2 /Ob2 /D NDEBUG" ..
>
> ..which created an fltk project with the /MT flag that then Visual Studio
> would build correctly for my apps.
>
> This made it easier to have a script rebuild FLTK for my application setup.
>
> The above settings worked for Visual Studio 7.. I imagine similar techniques
> can be used for the newer Visual Studio compilers.

Thanks for finding this as a *workaround*. However this can't be
recommended as a way to do it since you'd have to know all the other
compiler flags generated by CMake.

> I'm not sure if there's an easier way to control this flag, as there's
> quite a few other flags, and there's several variable names for other
> build targets, e.g. debug builds (which were not my concern in this case).

This flag should be controlled by CMake with a user option so nobody
needs to know the (other) compiler and linker flags. Unfortunately there
doesn't seem to be a simple way to change this flag with CMake, as a
quick web search showed. Anyway, I'm sure we can do it.

I'm not a Visual Studio expert, but AFAICT this option controls which
runtime library should be used, and, beyond that, if it is linked
statically or dynamically. This, i.e. runtime library selection and
linkage, is not a Windows/Visual Studio specific but a more general
issue. So I suggest to add a CMake option:

OPTION_RUNTIME_STATIC:BOOL "Use static runtime"

or something like that. This would change the /MD or /MDd Visual Studio
compiler and linker options to /MT or /MTd, respectively.

It would also add "-static-libgcc -static-libstdc++" to the MinGW linker
options for GNU compilers and likely clang as well.

I believe the same options are suitable for Linux as well, although
maybe not that important.

I have no idea if there are similar issues on macOS. Input would be
appreciated.

FYI: I found these two very informative stackoverflow questions (among
others):

<https://stackoverflow.com/questions/10113017/setting-the-msvc-runtime-in-cmake>

<https://stackoverflow.com/questions/14172856/cmake-compile-with-mt-instead-of-md>

Although this is strictly not on topic in fltk.general I'd appreciate
comments and suggestions from as many users as possible: about the best
naming and usage of option syntax for different OS's or build platforms.

Greg, would you please file an STR including the keyword "CMake" in its
title so we don't forget to implement it? I'll take the STR and try to
implement it as soon as it is clear how to proceed.

PS: Issues that may be interesting to discuss: I'm aware that the
semantics of such an option on different platforms may be slightly
different, but I'd prefer a common option (name) for all platforms
rather than multiple build-type specific options (and names). I can also
imagine that one may want this option be TRUE on one platform (for
instance on Windows with MinGW and/or Visual Studio) but FALSE on Linux
or macOS but this can be handled easily in the user's script that sets
the option differently on different platforms.

Greg Ercolano

unread,
Dec 13, 2017, 2:01:14 PM12/13/17
to fltkg...@googlegroups.com
On 12/13/17 05:25, Albrecht Schlosser wrote:
> Thanks for finding this as a *workaround*.

Agreed ;)

> However this can't be recommended as a way to do it since you'd
> have to know all the other compiler flags generated by CMake.

Yeah, it's a pain, which is why I mentioned the technique
so that it can be repeated. (e.g. grep the CMakeCache.txt
for /MD, and then replicate all the settings shown, changing
just the /MD -> /MT)

>> I'm not sure if there's an easier way to control this flag, as there's
>> quite a few other flags, and there's several variable names for other
>> build targets, e.g. debug builds (which were not my concern in this case).
>
> This flag should be controlled by CMake with a user option so nobody
> needs to know the (other) compiler and linker flags. Unfortunately there
> doesn't seem to be a simple way to change this flag with CMake, as a
> quick web search showed. Anyway, I'm sure we can do it.

Right; each compiler is different about how to handle static
vs dynamic references to the C library.

> I'm not a Visual Studio expert, but AFAICT this option controls which
> runtime library should be used, and, beyond that, if it is linked
> statically or dynamically.

Yep, pretty much.

Basically the linker gets confused if FLTK wants to access
C library functions dynamically, while the app it's linked with
wants static access. The linker then barfs about the multiple
references.

> OPTION_RUNTIME_STATIC:BOOL "Use static runtime"

Sure -- so this new option could perhaps show up in cmake's
help somehow? (e.g. similar to "configure --help" showing all
of FLTK's configure flag extensions)

> or something like that. This would change the /MD or /MDd Visual Studio
> compiler and linker options to /MT or /MTd, respectively.

Right.

And I think cmake /already/ has a way to control DEBUG vs RELEASE
builds, another common option, via the CMAKE_BUILD_TYPE macro, e.g.

cmake -D CMAKE_BUILD_TYPE=Debug

> It would also add "-static-libgcc -static-libstdc++" to the MinGW linker
> options for GNU compilers and likely clang as well.


> I believe the same options are suitable for Linux as well, although
> maybe not that important.

Yes.. there's I think a -static flag, or something like that.
Been a while since I looked. Thought it was a linker option though.

> I have no idea if there are similar issues on macOS. Input would be
> appreciated.

Yes, not sure myself.

A long time ago I figured out what my commercial app needed
to work effectively on customer's variety of machines, and just
stuck with that.

> Although this is strictly not on topic in fltk.general I'd appreciate
> comments and suggestions from as many users as possible: about the best
> naming and usage of option syntax for different OS's or build platforms.

I don't care what it is myself, as long as it's documented
so I can find it when I need it ;)

The two cases I'd expect it to appear would be:

o In cmake's --help (or whatever the equivalent is to 'configure --help')
o In the README for building fltk, whatever that ends up being

I guess I'd also expect the current settings, whatever they are,
to appear in cmake's output when the IDE files are generated.

> Greg, would you please file an STR including the keyword "CMake" in its
> title so we don't forget to implement it? I'll take the STR and try to
> implement it as soon as it is clear how to proceed.

Sure; see STR #3443.

> PS: Issues that may be interesting to discuss: I'm aware that the
> semantics of such an option on different platforms may be slightly
> different, but I'd prefer a common option (name) for all platforms
> rather than multiple build-type specific options (and names).

Agreed; the easier it is to remember, the better.

FLTK_STATIC=true vs FLTK_DYNAMIC=true, or something like that.

IIRC, on Windows FLTK could build itself /twice/ within VS;
once for the dynamic build, and once for static build, such that
you'd end up with both .dll's and .lib versions of FLTK.
That might be another way to go, if possible? In that case
it might not even be an issue then.

Albrecht Schlosser

unread,
Dec 13, 2017, 6:06:15 PM12/13/17
to fltkg...@googlegroups.com
On 13.12.2017 20:01 Greg Ercolano wrote:
> On 12/13/17 05:25, Albrecht Schlosser wrote:
>
>> I'm not a Visual Studio expert, but AFAICT this option controls which
>> runtime library should be used, and, beyond that, if it is linked
>> statically or dynamically.
>
> Yep, pretty much.
>
> Basically the linker gets confused if FLTK wants to access
> C library functions dynamically, while the app it's linked with
> wants static access. The linker then barfs about the multiple
> references.
>
>> OPTION_RUNTIME_STATIC:BOOL "Use static runtime"
>
> Sure -- so this new option could perhaps show up in cmake's
> help somehow? (e.g. similar to "configure --help" showing all
> of FLTK's configure flag extensions)

I'm not aware of a "help" function in CMake to show user options like
these. CMake --help shows CMake commandline options only.

But there are of course CMake's GUI's: cmake-gui on all platforms and
ccmake likely only on Unix/Linux/macOS only (I'm not sure - it uses
ncurses, so it may be possible to build it elsewhere). You can run one
of these to view and change user options (i.e. CMake cache variables)
interactively.

Alternatively, as you found out, to view the values you can grep
CMakeCache.txt or use the commandline

$ cmake -L to show the "normal" CMake cache variables or
$ cmake -LA to show both the normal and the "advanced" variables.

>> or something like that. This would change the /MD or /MDd Visual Studio
>> compiler and linker options to /MT or /MTd, respectively.
>
> Right.
>
> And I think cmake /already/ has a way to control DEBUG vs RELEASE
> builds, another common option, via the CMAKE_BUILD_TYPE macro, e.g.
>
> cmake -D CMAKE_BUILD_TYPE=Debug

This is correct, it's a standard CMake variable, but it doesn't always
have exactly the same meaning.

In generators like "Unix Makefiles" or "Ninja" this defines the build
configuration to be used when configuring and generating the build
files. However, in "multiple configuration" generators like "Visual
Studio ..." I don't know what it means exactly. I assume it sets the
default build configuration (the IDE has more than one, and the user can
switch configurations within the IDE). Should be easy to check, but
needs some time. I guess since you're using a commandline build this is
what you're using to set the default and hence the actual build
configuration when you run 'nmake', right?

BTW: you may want to take a look at the 'cmake --build ...' docs. But
don't ask me, I'm not using this command. ;-)
https://cmake.org/cmake/help/v3.10/manual/cmake.1.html

But if I used it ;-) I'd see something like this:

$ cmake --build .
[1/1] Re-running CMake...
-- Configuring done
-- Generating done
-- Build files have been written to: /path/to/fltk-1.4/build/ninja
[122/122] Linking CXX executable bin/examples/pack
$ cmake --build .
ninja: no work to do.


>> It would also add "-static-libgcc -static-libstdc++" to the MinGW linker
>> options for GNU compilers and likely clang as well.
>
>> I believe the same options are suitable for Linux as well, although
>> maybe not that important.
>
> Yes.. there's I think a -static flag, or something like that.
> Been a while since I looked. Thought it was a linker option though.

Yes, contrary to the Visual Studio compiler (?) flags these are linker
flags under Unix/Linux/MinGW (GNU tools) and likely clang as well. With
configure/make you would add them to LDFLAGS.

But I didn't mean "-static" which controls static linking for the rest
of the commandline. I rather meant "-static-libgcc -static-libstdc++"
literally which is special for (what it says:) the runtime libs libgcc
and libstdc++.

These two switches are essential under MinGW to build redistributable
Windows binaries w/o MinGW dependencies. This is supported and legal
(compatible with the MinGW license) and should be supported by FLTK as
well with a simple option.

>> I have no idea if there are similar issues on macOS. Input would be
>> appreciated.
>
> Yes, not sure myself.
>
> A long time ago I figured out what my commercial app needed
> to work effectively on customer's variety of machines, and just
> stuck with that.
>
>> Although this is strictly not on topic in fltk.general I'd appreciate
>> comments and suggestions from as many users as possible: about the best
>> naming and usage of option syntax for different OS's or build platforms.
>
> I don't care what it is myself, as long as it's documented
> so I can find it when I need it ;)
>
> The two cases I'd expect it to appear would be:
>
> o In cmake's --help (or whatever the equivalent is to 'configure --help')

That would be cmake-gui or ccmake (see above)

> o In the README for building fltk, whatever that ends up being

Yep.

> I guess I'd also expect the current settings, whatever they are,
> to appear in cmake's output when the IDE files are generated.

That's simple.

>> Greg, would you please file an STR including the keyword "CMake" in its
>> title so we don't forget to implement it? I'll take the STR and try to
>> implement it as soon as it is clear how to proceed.
>
> Sure; see STR #3443.

Thanks.

>> PS: Issues that may be interesting to discuss: I'm aware that the
>> semantics of such an option on different platforms may be slightly
>> different, but I'd prefer a common option (name) for all platforms
>> rather than multiple build-type specific options (and names).
>
> Agreed; the easier it is to remember, the better.
>
> FLTK_STATIC=true vs FLTK_DYNAMIC=true, or something like that.

FLTK's CMake convention is to call such options "OPTION_SOMETHING". You
may check using "cmake -L | grep OPTION". My proposal was to use a
boolean option, that's why I wrote:

OPTION_RUNTIME_STATIC:BOOL

Could also be

OPTION_STATIC_RUNTIME:BOOL

or whatever.

BTW: Variables like "FLTK_something" are likely "exported" to be used in
user projects that use FLTK, so I would not use them here. Eventually we
could however export the resultant compiler flags "/MT" (among others)
to be used in projects using FLTK.

> IIRC, on Windows FLTK could build itself /twice/ within VS;
> once for the dynamic build, and once for static build, such that
> you'd end up with both .dll's and .lib versions of FLTK.
> That might be another way to go, if possible? In that case
> it might not even be an issue then.

This is a different thing. It controls whether FLTK itself is built as
multiple dll's additional to the static libs, and there is already an
option for it:

$ cmake -L | grep SHARED
...
OPTION_BUILD_SHARED_LIBS:BOOL=OFF

This is documented in README.CMake.txt. The default is OFF though, so if
you want your VS IDE to build FLTK with DLL's you may run CMake with

$ cmake -D "OPTION_BUILD_SHARED_LIBS[:BOOL]=ON" <more options> .

Note that ":BOOL" is optional, but I don't know if this is officially
optional or if it just works.
Reply all
Reply to author
Forward
0 new messages