-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
CMake build system, attempt 2 #461
Conversation
@jirislaby @arrowd feel free to give this a try. |
Hmm doesn't build with CMake 2.8.12.2 on Ubuntu 14.04LTS, fixes will be coming soon. |
Okay build now works under under Ubuntu 14.04LTS with CMake 2.8.12.2 |
Okay hit a milestone :)
|
I guess these are beginner issues and not issues with the pull request
|
MSVC build now succeeds :) . The |
Yes there are two issues there.
It is important to understand that CMake is actually a "meta-build system" and not a build system itself. When you run the I'm going to try to write a guide on using the build system now. |
@NikolajBjorner @wintersteiger @nunoplopes I've tested the following configurations
There is documentation in the |
cool, bandwidth permitting... |
Looking like it's getting there, great! Is it a strict requirement that we have to have CMakeLists.txt file in every single directory? I'd rather see those go into a separate cmake-only directory or some such thing. |
@NikolajBjorner Okay. |
got it to build with yesterday's check-in using VS this time. VS uses threads. |
Technically it is not a strict requirement but practically it is. Re-implementing what I've done to keep the |
Great. You will want to use the latest version of this PR though because I didn't have the dll exports working properly yesterday so the |
Re nmake in parallel: in visual studio it's usually the compiler itself (cl) that parallelizes (with /MP), but we also have the --parallel flag on mk_make.py that tricks nmake into parallelism. |
Re new files everywhere: This is highly confusing for anybody who wants to debug a build issue, because it is not obvious to them that all those files flying about have nothing to do with what they are trying to achieve (e.g., default build via nmake). I would much rather have the python (or other) scripts that generate code moved into those directories (having everything in /scripts is actually quite painful) which can then be used by all build systems. Re moving files being painful: Sorry, but every other approach is also painful (except maybe for different persons). |
I'm afraid I really don't get your logic here. Having Also if there is an issue during configure CMake will tell in which file and at what line there is a problem in a Perhaps I'm not picturing exactly what you mean when you say |
I believe it is a matter of getting used to. |
Yes, I agree if there is only one build system and if everybody is familiar with it, but those assumption don't hold here. Whether this is "completely standard" in other projects is of no relevance, Z3 is "not standard" in many respects, and yes, we can try make it look "more standard", but that will be a major effort and until we decide to actually go for something like that, I'd rather not disrupt and confuse existing operations and users. So, if it's little bit more effort to make it self-contained and non-disruptive then I think we should go for that. |
Yes
Because the existing build system has this problem I decided that fixing it right now was orthogonal to implementing a CMake build system that largely duplicates the behaviour of the python build system. |
I don't think the idea of splitting your projects into components and having each component depend on each other is non-standard. But that is exactly how Z3 is organised and what the CMake build system I've created is designed around. As for a "little bit more effort".... it's not a little bit of effort. It would be a huge amount of effort with no real benefit. CMake is designed to be used in a particular way (the way I'm using it) and what you're suggesting is not a good fit for how CMake works. Also I am not willing to waste my time compromising the readability and maintainability of the CMake build system. I would much rather use my time doing something useful like teaching the CMake build system how to build and install Z3's language bindings which would bring the CMake build system to full feature parity with the Python build system. Also the Python and CMake build systems can co-exist fairly painlessly. If you're modifying source files you probably won't need to modify the CMake build system. You would only need to modify it if you're adding a new |
Before anybody wastes any more time on this, can we please do a rought cost/benefit calculation? I was under the impression that this contribution should be self-contained, non-disruptive, and basically @delcypher's pet project that will stay invisible to the end-user until they actively want to use it. It seems that the current strategy is to partially or completely replace the existing build system. And at the current time and state of affairs I'm strongly opposed to this, because it will most definitely be a huge load of time and effort for all of us, which nobody will get back in any kind of benefit. Here are some thoughts: If we wanted Makefiles in every directory, we would have done so a long time ago, and we would have made them nmake-compatible. In retrospect that may perhaps have been less effort overall, but at the current state I see no reason to change our mind, now that all the kinks have been worked out. Supporting and maintaining two independent builds systems is a truly terrible idea, for all people that are involved. I am open to discussion about replacing the existing system, but that will have to be much better organized and there will have to be a lot of discussion about what system we think is the best choice. I would much rather see that time and effort to go into refactoring of the existing system to make maintenace less painful, which, at the same time, would be much less disruptive for users as well. CMake is a great system if you need to build, test, and publish on multiple platforms. More than 99% of our users do not have that requirement. The number of people who do have this requirement is 2 (@NikolajBjorner and myself), and that set of people is perfectly happy with the current system. And further, they have about a 5-year investment of fixing build problems on exotic platforms in the current system. Much of this will have to be re-discovered and re-fixed. I can't speak for @NikolajBjorner, but personally I am not in any way keen on going down that route. Prospective future users could be found in the set of people that maintain our APIs (currently the same 2), because they have to make sure their APIs work on all platforms. But, at the same time this is also the most complicated part and so far has received no attention as far as I can tell. Adding yet another tool in the build chain is completely unnecessary complication for "newbie" users. Many of our users are not Comp Sci students and they do not run Ubuntu. If we have to ask them to compile the latest-bugfix version from the master branch, everything will have to go through without a hitch, because they won't have the knowledge or skills to fix any problems along the way. And yes, some of them will have trouble downloading CMake and installing it, and they will have no clue what's going on when they run the magic commands that we tell them to run. If we were to decide to replace the existing system, then CMake would not be my first choice of tool to use. (E.g., why don't they publish packages for BSDs? Current platforms on my todo list are Raspian, Solaris, OpenBSD. Will we have to give people a tutorial on how to compile CMake first?) Also, I would much rather just have Makefiles in every directory and ./configure scripts, and perhaps a static .vcxproj for Visual Studio. So, yes, I do appreciate @delcypher's enthusiams about this project, but at this point in time, from my point of view, it's just not cost-effective. This is OK if it stays invisible, but not otherwise. So at this point, I won't merge this PR, but I'm not the only one with write permissions, and if the others think there are benefits that I can't see, then I'm happy to be overruled. |
Building and install of python bindings is now implemented. This if off by default but can be enabled by setting the option I don't plan to implement support for any other bindings right now until this work is merged. |
Sure.
The CMake build system could replace the existing build system but that is not my decision to make. My goal has been to implement a CMake based build system that is readable and is as close to feature parity with the existing build system as possible that I and others can use.
The kinks haven't really all been worked out. Incremental builds are broken with the current build system. I wouldn't have even bothered to have implemented a new build system if the existing build system could do that.
It is only terrible if the maintenance cost is high. Right now I don't see this as being high at all. If you want zero additional overhead then you (and all other Z3 devs) don't even need to care about the build system and develop Z3 as your have been doing so far and I will send PRs when something breaks with CMake build. That way the CMake build system is not in your way all all. If you don't mind a little overhead then you can modify the CMake build system if you really feel like doing it but I'm happy to take on the work alone. You and I also clearly differ on our opinions on what is well organised. The project layout that CMake uses is very similar to every build system I have ever used (e.g. Automake, SCons, Manual makefiles and even Visual Studio solutions with multiple C# projects) except Z3's python build system. I am also having a really hard time understanding why you think a
It is not only great for that. It is also great if you want to integrate well with IDEs (like Xcode, Eclispe CDT and Visual Studio). It also very useful because it implements lots of things build systems need (e.g. setting SOVERSION, RPATH, ..etc) which is hard to get right and the Z3 team should not spend there time implementing in python. With CMake you get all this stuff for free.
I don't see this as a strong argument. The CMake build system is not intrusive and your users can continue to use the Python builds system without knowledge that it even exists. If they really want to use the CMake build system the documentation is there. Asking for a flawless compile from the Also your students "have no idea" what is going on when you tell them to run your python scripts to build Z3. Those scripts are incredibly complicated and convoluted. I learnt way more about them than I ever intended whilst trying to replicate it's functionality using CMake.
You are unlikely to need to tell people to compile CMake from source. It is very widely used project so it available for many platforms. CMake also knows about many more platforms and compilers that the existing build system so using CMake will make it easier to port to other platforms. For the BSDs, CMake is available from their package manager. Raspian is Debian (not a BSD) so CMake is also available from their package manager. Downloading the CMake binary from their website is something I'd ever do on Windows. Other platforms have package managers which make getting hold of CMake easy.
Right now this PR doesn't impact the existing build system in terms of functionality. In fact it improves it because I had to do some refactoring to use some of its functionality to generate some files needed for the build. Because the existing build system is not functionally effected and I've stated that if you don't need to care about the CMake build system if you don't want to I don't see this PR as invasive. Have you actually tried using the CMake build system I've implemented? It feels very much like you are criticising something you have not actually used. You only need to run a few commands to try it out. I'm more than happy to walk you through using it. @jirislaby @arrowd You have both expressed interest in the past in using CMake to build Z3. Do you have anything to add? |
Sorry, but this is not about whether it's nice and easy to use at all. Simply put, from my point of view, there is essentially zero benefit for zero people, i.e., not worth investing your time or our time on this. Worse, if it does interfere with the existing system (which it does, see changes to scripts/*.py), then we get negative benefit. But, as a I said, that's just my opinion. |
I tried the system yesterday, and it was easy enough to build without following instructions. From what I saw, the cmake system is perfectly reasonable with cross platform, incremental and other hooks that make good sense. I have yet to learn more about this environment. Maintainability and adaptability is my main question, but then cmake offers something the python scripts do not when it comes to various platforms. Although, the python scripts for compile-time generated code |
Hey all, I've been silently watching this fascinating discussion. Let me chime in. First, I want to cast a vote for cmake. A cmake-based build system for Z3 would make a huge difference for me. However, I understand the pitfalls of having multiple build systems, even when one is official and the other is just there. I want to suggest a constructive compromise:
This makes cmake invisible to users of the current build system at a slight increase in the cost of maintaining cmake build. This can be re-evaluated after some time, but is a way to move forward right now. |
What? You make an argument based on ease of use, I counter this and argue that it isn't difficult to use and then you tell me that ease of use doesn't matter.
That simply isn't true, do you speak for everyone? There are plenty of benefits to offering a CMake based build of Z3. Advantages of having a CMake build system for Z3 available:
Disadvantages of having a CMake build system for Z3 available (note I'm saying available, I'm not saying replacing the python build system).
There is a minor convenience due to the refactor but as I mention those parts of the Python build system hardly ever change. Also I have done you a favour with my changes to |
is applied to targets. The ``LINK_FLAGS`` property of a target is a string and not a list and so if ``Z3_DEPENDENT_EXTRA_CXX_LINK_FLAGS`` contained more than one flag the linker line would end up being ``-flag1;flag2;flag3;...`` which would not work. Now we use a new function ``z3_append_linker_flag_list_to_target()`` to iterate through the list and update the ``LINK_FLAGS`` property of the specified target correctly.
5538f71
to
a52d81e
Compare
Rebased and fixed merge conflict with cf5910e |
was already marked as executable but it wasn't possible to execute from a shell due to the missing shebang.
@wintersteiger Are there any additional changes you'd like me to make? I rebased recently to fix a merge conflict so the changes should still merge cleanly. |
Sorry, but it looks like you have completely taken apart mk_util.py and all API generation code. This will take a lot longer to review and test than I hoped it would. |
@wintersteiger Most of the changes made to |
This looks a lot better now, this is mergable. I still expect build and test failures in the next few builds, mainly due to the changes in the API generation code. See also notes below. Can you tell me what combinations of systems, APIs, and Python versions this has been tested already? Some notes:
|
Style note: we use 4 spaces for indentation, the new python parts use 2 spaces, please update your editor to use 4. |
Thanks for merging :)
The CMake build system was tested on
The python build system was tested on
Those extra scripts are necessary but that isn't obvious unless you look at how the CMake build system invokes them. The extra python scripts I've added are used as executable programs during the build (the CMake build system generates the files at build time, not configure time). To me this was the only sane way to generate the necessary files to build Z3 from CMake because the logic for generating those files is very complicated and reimplementing that logic in CMake seemed like a waste of time when instead I could refactor the existing python code so I could call it from a python script by passing the correct command line parameters. By code duplication I assume you mean the
Which part of the code are you talking about? Do you mean the I would say "unintuitive" here is very subjective. What I was trying to do here was have the ability to generate whatever API files I needed. The old code didn't really give you a choice, it always writes the The function could probably do with some comments though explaining this. Would you like me to add some? Aside: The reason that writing generated files into the source tree (rather than the build directory) is considered bad practice is because it potentially prevents having multiple build directories that all share the same source directory.
This is unfortunate but necessary. It couldn't make progress with
My intention is to add support for the other bindings at a later date when I (or someone else) has time to add support for them. I did the python bindings first because
|
Sorry about that. I'll try to fix that in the future. |
One other thought I had. The bits of the Python build system that the CMake build depends on is quite small and I think it might be a good idea separate those parts into their own file
How do you feel about this idea? If you're happy with it I can go ahead an implement it and create a PR. |
@delcypher: previous comment about adding comments: Always a good idea, I'd appreciate if you could add a couple sentences explaining the strategy. Hmm, mk_genfile_common.py sounds like a good idea to get rid of some of the code duplication, but what else would it improve? Are you proposing to remove mk_util.py but still keep the rest of the old build system alive somehow? What I would really is for someone to pick apart all the different APIs in update_api.py, which is a huge mess at the moment. Perhaps provide some common skeleton (like reading the annotations in Z3_api.h), but then have indenpendent code generation for each API, and in their own directories. |
based on discussion in Z3Prover#461.
Done in #490
No the idea isn't to remove any code duplication. Can we just clarify what code you think is duplicated here? As explained earlier by code duplication I'm assuming you mean the
scripts? These scripts just call into code inside So at least from my perspective I haven't added any unnecessary code duplication. Those scripts need to exist so CMake (and other clients) have a way of generating various files from the command line. What I'm proposing is to move the functions
and data structures they depend on into their own file and decouple them from using anything in The idea is to basically keep code that is used (directly and indirectly via the previously mentioned script) by both build systems separate from code that is only used by the Python build system. The advantage is that then developers know when they are touching code that effects both build system or code that just effects the python build system. This is quite minor so I don't particularly strongly about doing this but it was just an idea I had.
I agree this is a bit of a mess right now. Perhaps you should open an issue about this so we don't forget. Is there any reason you don't use SWIG to generate some of the boiler plate necessary for calling the C APIs from various languages? Either way if you create an issue you should probably mention if there are any reasons to not use it. |
No, I meant the command line args validation etc in the new .py files. Moving those functions into their own modules is probably a sensible thing to do, perhaps they could also move closer to the files they relate to (e.g., mem_init* gparams* into the dll folder, z3consts_py* into api/python, etc). SWIG never came up and there was never a need for it. The overall strategy has always been to use fewer tools than more, because of various cross-platform issues. Be warned though, if you dig into this pit, you may find yourself being the maintainer of some of those APIs. :-) |
@delcypher Could you make Z3_INSTALL_*_DIR options? FWIW, we need to install to lib64 on x86_64. |
@jirislaby It looks like CMake provides |
`contrib/cmake/bootstrap.py` script no longer needs to be executed. The previous location of the CMake files was a compromise proposed by @agurfinkel in Z3Prover#461. While this has served us well (allowing progress to me made) over time limitations of this approach have appeared. The main problem is that doing many git operations (e.g. pull, rebase) means the CMake files don't get updated unless the user remembers to run the script. This commit only does the file moving and necessary changes to `.gitignore`. Other changes will be done in subsequent commits.
`contrib/cmake/bootstrap.py` script no longer needs to be executed. The previous location of the CMake files was a compromise proposed by @agurfinkel in Z3Prover#461. While this has served us well (allowing progress to be made) over time limitations of this approach have appeared. The main problem is that doing many git operations (e.g. pull, rebase) means the CMake files don't get updated unless the user remembers to run the script. This can lead to broken and confusing build system behaviour. This commit only does the file moving and necessary changes to `.gitignore`. Other changes will be done in subsequent commits.
This is a rework of #459 that is no longer a "half-baked" (@nunoplopes) solution as it can now build the necessary generated files itself and so can function with needing to invoke from the Python build system first.
The last ( 98b61b8) commit lists some of the many advantages this build system has.
It will need some additional work to work under MSVC and to support building/installing/uninstalling the python, java, dotnet and ml language bindings but this can be done in the future.
To give this a try do
So far I've tested with make and ninja on Arch Linux with CMake 3.4.3. I will be testing more platforms shortly.