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
Question: How to instruct cmake to generate a static library? #175
Comments
@degski at the moment the build system hard codes the generation of a shared library. Would you like me to add an option for a static library build? |
Yes, please. Like I said, all goes well, except it's not what I would like to have. Just to be clear, that also implies static run-time linking (/MT, /MTd). |
Is the compilation with |
No, not that I'm aware of, it's just /MT for Release and /MTd for Debug. There is one thing, that is possibly something you did not consider. The There is one other point, though, that is the debug-info [where maybe I'm awkward]. The std way of doing things is to add the /Zi flag, while what I usually do is give the /Z7 flag. The result is the same, except with /Zi you get the famous .pdb file, with Z7, that's included (wrapped up) in the library, i.e. you end up with one file (including debug-info). The /Z7 flag is considered 'old fashioned' (and for decennia about the be removed), beats me why. |
Ok, thanks for the info! Do you happen to know if I can set these flags via some CMake mechanism? Or perhaps CMake already does the "right" thing when I tell it to build a static vs dynamic library, and release vs debug? I'd much rather set this sort of thing via, e.g., a target property rather than mucking around with the CXXFLAGS. |
Yeah, probably. I know not much about CMake. You could have a look at https://github.com/SFML/SFML/blob/master/CMakeLists.txt . Like I said, they deal with this using basically 1 flag, one macro. The CMake file is rather big, but it's mostly because SFML has masses of dependencies, I guess the static/dynamic bit is rather small. |
I could not find where |
https://github.com/bluescarni/mppp/blob/master/include/mp%2B%2B/detail/visibility.hpp Speaking of it, are these attributes still necessary when building a static library? As a first try, I'll just add an option to build a static library and observe what kind of flags CMake sets in the CI runs on appveyor. Crossing fingers, that might be good enough. Thanks for all the info! |
@degski sorry just saw your edit above about |
Ok so it looks like I could just add another definition to |
Yes. |
I have some initial code up here: https://github.com/bluescarni/mppp/compare/pr/static_lib Works locally on my linux installation, I'll check tonight what it does on the appveyor CI. |
I just compiled it with MSVC 2019 successfully, All tests ran in Release and Debug (for some tests considerably slower) |
I've tried the SFML has this code snippet to achieve the MD -> MT:
|
@degski it is not clear to me what the relation is between building a static version of the library and linking to the static runtime. Does one imply the other or are they independent? Is it allowed, e.g., to build a static library and link it to the dynamic runtime? |
Ok so I dug a bit and found this: https://gitlab.kitware.com/cmake/cmake/issues/19108 That is, the latest CMake git head exposes a target property for selecting the MSVC runtime to build against. So clearly this is the way to go for the future, but we still need a working solution for older CMake versions. This CMake FAQ entry discusses the topic a bit: So I'd be inclined to implement the "Dynamic Replace" solution, even with its shortcomings. |
To be clear, this means adding another CMake option |
No not really, but you cannot mix them [if you link in more than 1 lib], and in general it is considered good practice to link to the static crt when compiling static libs. Like f.e.
Yeah, I guess it's not perfect, but it works for SFML.
Additionally, I would name the macro |
If there is no specific reason for mixing static library with dynamic runtime (or vice versa), I'd rather go with the best practice and leave a single option ( Would that work for you? |
It has to include
You would do that to work around a problem. Like f.e. Intel Threading Building Blocks cannot [due to shared state issues in the lib] be compiled statically, so to work around this PS: I updated the other post. |
Sure sure, I was writing too fast :)
Just to make sure I understood, |
Yes, that one would be a build macro. |
Hello Francesco, |
Thanks a lot for the explanation! It sure does sound like an intricate system. Do you also agree that it's generally a sensible thing to do to link to the static runtime when building a static library? |
@degski how is it looking now? I took the chance to make some changes to the build system when using clang-cl, it would be good if you could confirm everything is working properly. |
I know you didn't ask me the question, but I'll add to what I already said [just to repeat that, yes, you can do both]. The way it's done is not very relevant, it's just /MT vs /MD. The effects are different though. Windows depends on CRT's. And every major update of VSXXXX and/or Windows OS comes with a new(er) additional run-time. This is distinctly different from Linux, which just gets a new kernel, the distribution maintainer re-compiles everything with that new kernel and the distro's package manager installs the lot, all dependencies that have changed due to a new kernel. On Windows that implies that if you distribute software, which is dynamically linked to the crt of the developer machine, now is directly dependent on having that particular crt installed on the target [the user] machine, side-by-side with various other crt's [this is called I re-submit that
I'm gonna have a look at that now and report back. |
I have successfully built and linked PS: Previously I have been using So, I have been looking for another solution, and I found one [it involves static linking :-)]. I have built a working statically linked version of gmp-6.2.1 with mingwx64/gcc-8.3.0, using msys2. It's as simple as:
and thereafter [with vc/link and clang-cl/lld] link to libgcc.a, libgmp.a. Because these are static c-libs, this linking works. Dynamic linking would not work (at least not so easily). There are some additional little issues, I have solved as well. Maybe you or I should put this somewhere on github? |
I've now also checked the |
@degski Thanks for checking! I am ok with doing what vcpkg does for the MSVC runtime, so, if the current solution is ok for you, I am ok with merging the PR. Regarding the MPIR/GMP discussion, in the past I have also been building GMP on windows with MinGW/MSYS and it always worked fine (as long as static linking was being used, as you point out). MinGW is great, but it has a critical issue for my use cases which is a bug in the implementation of I never understood the point of MPIR as a GMP fork. I understand the need of working around GMP's developers indifference/hostility to MSVC, but IMO a thin extra layer in the build system would have been enough (which, as I understand, is what Brian Gladman was/is doing). There was no need for a full fledged fork, and I never used MPIR myself. My only interaction with MPIR so far has been ensuring that mp++ works fine in conjunction with it. |
I'm ok with it.
Yeah, that's how it started, then other hobbyists got on board and basically took over the project. Thinking that you can do better than GMP seems rather stupid IMO, why even try?
I don't know exactly what you are referring to [as you are calling it a bug] but there is this repo, which adds almost all the missing bits at least. I just add an include line [to the files supplied by that repo] to the end of the relevant std-headers and this has worked for me so far. |
I don't know, who does what etc, but the distro I linked to is pretty solid, it's also multilib (and has ada, obj-c and fortran as well, the latter handy for OpenBlas), i.e. it builds both 32- and 64-bit apps. The latest build, with gcc-8.3.0 is pretty recent [like weeks old], who knows. These are the build specs:
|
Referring to these: https://sourceforge.net/p/mingw-w64/bugs/445/ You can find other reports if you search for them, which, I believe, are various manifestations of the same underlying problem (i.e., that the destructor of Note that this is an issue mostly with C++ classes which do non-trivial operations during destruction. If you limit yourself to C-like data types, you should be fine because there's really no destructor being called. |
Thanks for the pointer! I was using the mingw-builds builds, https://mingw-w64.org/doku.php/download/mingw-builds which, last time I checked, were stuck to an older version of GCC (8.1 I believe). I'll give a try to the builds you are using. |
There are definitely some issues related to |
@degski want to open a new report about the issues you encountered? |
Yes I will, but first have to be able to at least reproduce it on my end, for the moment I'm not sure what I'm looking at. I might revert back to Brian's setup, or try to mix Brian's |
Addressed in #176, will close this report for the time being. |
Yes, the changes are good. Re. TLS, there's a new ticket: https://sourceforge.net/p/mingw-w64/bugs/799/ |
How to instruct cmake to generate a static library. Do I need to define any MACRO.
I'm using VC17 + clang-cl-9. The generation goes fine, I just want/need a static library.
Thanks in advance.
The text was updated successfully, but these errors were encountered: