I have a project with about 1000 sources files.
Make takes about 5 seconds to check whether the project is up to date.
Is there any solution to improve this check? (Is C-Make more suitable for this kind of project?)
CMake uses Make, so using CMake probably won't help.
One thing you can try is find out whether disk I/O is the bottleneck. That seems likely if rerunning your make command is a lot faster than the initial run. To be sure, put the files on a memory-mapped filesystem (on Linux, I use /dev/shm; on Windows, I use ImDisk).
You may also need to check whether your rules can be optimized. GNU Make doesn't have any profiling built in to help you with that.
There is a version of GNU make called remake that includes a profiler.
Related
I happen to think (but maybe is a myth) that Cmake is greater than Autotools about making easy supporting Microsoft.
At the same time, I'm kind of sure that Autotools is even more straightforward than Cmake when it comes to important UNIX derivatives such as macOS and most popular Linux distros.
What if I can't choose?
Can a project support both Autotools and Cmake at the same time?
Bonus for: can a project support both Autotools and Cmake and even simply bare Make at the same time?
By "at the same time" I mean that ideally one should not necessarily run a clean script when changing from trying one of the build systems to another. But I guess it would be a reasonable configuration, if necessary.
Finally, do you know an example project that uses both Autotools and Cmake? One that uses both Autotools, Cmake and simply bare Make?
Yes, you can very easily support both CMake and Autotools at the same time, since they don't overlap (that is, the files you use to create those environments are different, so you can have both types of files in your project at the same time). One example of this is the GNU uCommon C++ framework.
No, you can't (easily) support bare make and either of the above systems at the same time. Neither Autotools nor CMake are actually build tools themselves. They're "build tool generators". So you don't run autotools or cmake and the result is your built project: instead you run autotools or cmake and they generate control files for a build tool. Then you run the build tool and the result is your built project.
Autotools generates makefiles, and cmake generates many different types of control files, where makefiles are one of the most common.
So, you can't have your OWN makefile in your project, because they'll conflict with the makefile generated by autotools or cmake.
Of course, you can do things like put your own makefiles in a subdirectory then invoke make with an argument like make -f rawmake/makefile or something like that. But there's no convenient way to support them all.
Realistically, I would never choose to support more than one of the above options. You will spend a lot of time getting it right, and every time you need to change your build environment it's two or three times as much work. People will find issues with whichever one of them you tend to use less often. It's a huge hassle for not that much benefit.
Which you choose depends a lot on your project. If your project runs only (or almost exclusively) on POSIX-type systems, you want it to be maximally portable even to much older systems even though it uses a lot of special OS features, or you want its installation and build options to be extremely flexible (straightforward support for cross-compilation, etc.) then autotools is a good choice. If your project runs on lots of different OS types (Windows in particular) and you want people to be able to develop with their choice of IDE (Visual Studio, Xcode, etc.) easily, then cmake is a good choice.
If your program is straightforward to build and needs hardly any configuration or customization, or you are already familiar with makefiles and don't feel like learning a whole new language just for builds, then raw makefiles may be a good choice.
How can I ensure that object files compiled for one hardware target will not be used for a different hardware target that needs to be compiled differently?
I am using the GNU ARM Embedded Toolchain while I am learning about embedded development. I already have a couple of development boards (with STM32F0 and STM32F4 processors), and plan to make my own boards in the future. I want to have several iterations of hardware using a common software repository.
Obviously I will have multiple targets in my Makefile, invoking the appropriate defines and compiler flags for each platform, and perhaps a make all to build for all platforms at once. As I understand it, make is an incremental build system that only re-compiles object code (*.o) files if the source file has been changed, it won't recompile if I have use different defines and options, and the wrong object code will be passed to the linker.
It seems that I could diligently make clean when switching between different targets, but that would rely on the human action and could produce bad builds if I forgot, and could not be used for a make all that produces multiple binaries for their respective hardware.
Edit Notes: Per feedback comments, I have shorted and rearranged to make the question more clear and objective. I'm not asking generically how to use Make, but rather how to prevent, say mylib.o being compiled for an STM32F0 and then later being re-used in a build for an STM32F4.
I am curious about alternative tools, and welcome discussion in the comments, but this question is specific to GNU Make.
To avoid the need for a clean build between targets, it is necessary for each target to have separate build directories in order that the target dependencies are independent and specifically generated using the appropriate tool chain and build switches etc.
I am learning compilers and want to make changes of my own to GCC parser and lexer. Is there any testing tool or some another way available which let me change gcc code and test it accordingly.
I tried changing the lexical analysis file but now I am stuck because I don't know how to compile these files. I tried the compilation using other GCC compiler but show errors. I even tried configure and make but doing this with every change does not seems efficient.
The purpose of these changes is just learning and I have to consider GCC only as this is the only compiler my instructor allowed.
I even tried configure and make but doing that wit every change is not at all efficient.
That is exactly what you should be doing. (Well, you don't need to re-configure after every change, just run make again.) However, by default GCC configures itself in bootstrap mode, which means not only does your host compiler compile GCC, that compiled GCC then compiles GCC again (and again). That is overkill for your purposes, and you can prevent that from happening by adding --disable-bootstrap to the configuration options.
Another option that can help significantly reduce build times is enabling only the languages you're interested in. Since you're experimenting, you'll likely be very happy if you create something that works for C or for C++, even if for some obscure reason Java happens to break. Testing other languages becomes relevant when you make your changes available for a larger audience, but that isn't the case just yet. The configuration option that covers this is --enable-languages=c,c++.
Most of the configuration options are documented on the Installing GCC: Configuration page. Throroughly testing your changes is documented on the Contributing to GCC page, but that's likely something for later: you should know how to make your own simpler tests pass, by simply trying code that makes use of your new feature.
You make changes (which are made "permanent" by saving the files you modify), compile the code, and run the test suite.
You typically write additional tests or remove those that are invalidated by your changes and that's it.
If your changes don't contribute anything "positive" to the compiler upstream will probably never accept them, and the only "permanence" you can get is the modifications in your local copy.
There is a bug in RHEL5's gcc-4.3.2 with which we are stuck. As a work-around we have extracted the missing object and put it in an object file. Adding this object file to every link makes the problem go away.
While adding it directly to LDFLAGS seems like a good solution, this doesn't work since e.g. libtool cannot cope with non-la files in there.
A slightly more portable solution seems to be to directly patch the gcc spec to add this to every link. I came up with
*startfile:
+ %{shared-libgcc:%{O*:%{!O0:/PATH/TO/ostream-inst.o}}}
where ostream-inst.o is added to the list of startfiles used in the link when compiling a shared library with optimizations.
Trying to compile boost with this spec gives some errors though since its build directly sets some objects with ld's --startgroup/--endgroup.
How should I update that spec to cover that case as well, or even better, all cases?
Go through this URL Specifying subprocesses and the switches to pass to them and GCC Command Options
If this help you, thats great.
I know this is not the answer you want to hear (since you specified otherwise in your question), but you are running into trouble here and are likely to run into more since your compiler is buggy. You should find a way of replacing it, since you'll find yourself writing even more work-around code the next time some obscure build system comes along. There's not only bjam out there.
Sorry I can't help you more. You might try simply writing a .lo file by hand (it's a two-liner, after all) and insert it into your LDFLAGS.
If it is a bug of GCC 4.3, did you try to build (by compiling from sources) and use a newer GCC. GCC 4.6.2 is coming right now. Did you consider using it?
When compiling from source, I never know which configure flags to use to optimize the compilation for my environment. Assume the following hardware/OS:
Single Core, 2 GHz Intel
512MB Ram
Debian 4
I usually just go with
./configure --prefix=/usr/local
Should I be doing anything else?
I always use Debian packages. Compiling from sources can break your development environment during libraries conflicts and such problems are hard to detect.
You might want to check those few options out, which may be required by a Ruby On Rails environment, in which case they should be compiled. Just make sure the directory corresponds to your current settings.
--with-openssl-dir=/usr --with-readline-dir=/usr --with-zlib-dir=/usr
I recommend mixing in a few packages from Debian Unstable feeds. They tend to be pretty stable, despite the name. They're also very up to date.