5 ms·
I don't like using tabs in Makefile syntax. Tabs are in many cases (especially on print) indistinguishable from spaces. Also, any "make" program for C should a
by codedokode 5y ago
I don't like using tabs in Makefile syntax. Tabs are in many cases (especially on print) indistinguishable from spaces.
Also, any "make" program for C should automatically detect dependencies between files because this information is present in the code and it doesn't make sense to duplicate it.
- fragmede 5y agoGNUMake allows for custom, non-tab leader characters. https://stackoverflow.com/questions/2131213/can-you-make-valid-makefiles-without-tab-characters/21920142#21920142 https://stackoverflow.com/questions/2131213/can-you-make-val...
- sigjuice 5y agomake doesn't really understand C or C dependencies, but the compilers usually do. Here is a minimal example that will take care of dependencies by passing -MD -MP to gcc or clang. The dependencies (*.d files) get generated as part of the normal gcc/clang invocations. There is no separate dependency generation step. $ cat Makefile CFLAGS := -MD -MP hello: hello.o x.o y.o -include *.d $ echo '#include "x.h"' > x.c $ echo '#include "y.h"' > y.c $ touch x.h y.h $ echo 'int main(void) {}' > hello.c $ make cc -MD -MP -c -o hello.o hello.c cc -MD -MP -c -o x.o x.c cc -MD -MP -c -o y.o y.c cc hello.o x.o y.o -o hello $ touch x.h $ make cc -MD -MP -c -o x.o x.c cc hello.o x.o y.o -o hello
- JdeBP 5y agoActually, the compilers do not and you are doing less than half of the job there. They don't emit information about the non-existent files that would change the build if they were to suddenly exist, such as an "x.h" in one of several standard search directories in that example. * http://jdebp.uk./FGA/introduction-to-redo.html#CompilerDeficiencies http://jdebp.uk./FGA/introduction-to-redo.html#CompilerDefic...
- glandium 5y agoAlso they don't add an empty rule for the source file (like they can do for headers), so if you rename from e.g. foo.c to foo.cpp, which still produces a foo.o, your incremental build fails because the dep file still has the dep on foo.c which doesn't exist anymore.
- brandmeyer 5y agoThe original sin here is generating the dependencies from the source files in the same step that was used to generate the object files. The only way to ensure that Make observes structural changes in the dependency DAG is if the graph is rebuilt.
- glandium 5y agoGood old "make depend". If only it didn't add a significant overhead...
- brandmeyer 5y agoYou can get make to only re-generate its rules incrementally based on what was changed. https://www.gnu.org/software/make/manual/html_node/Remaking-Makefiles.html#Remaking-Makefiles https://www.gnu.org/software/make/manual/html_node/Remaking-...
- sigjuice 5y agoLooks like gcc does not plan to do this https://gcc.gnu.org/bugzilla/show_bug.cgi?id=28810 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=28810
- sigjuice 5y agoIf a /usr/include/x.h were to appear, wouldn't that have lower priority than the x.h in the current directory and therefore not change the build?
- joshuamorton 5y ago> Also, any "make" program for C should automatically detect dependencies between files because this information is present in the code and it doesn't make sense to duplicate it. This requires that either you implement or shell out to a C/C++ parser as part of the dependency resolution step (which has to happen prior to the actual compilation). This will slow down your compilation a lot unless you're able to parse C/C++ as fast as your make/bazel/whatever language.
- JdeBP 5y agoThe idea behind redo, in contrast, is that "dependency resolution" is not a separate step. The dependencies can be generated at the same time as the compilation, by the compilation in a perfect world; through some post-processing in a less than perfect one. Unfortunately, current C and C++ compilers do not emit all of the information that they possess internally, only less than half of it (the positive information about files found, not the larger amount of negative information about non-existent files that were searched and would change the build if they were to exist). * http://jdebp.uk./FGA/introduction-to-redo.html http://jdebp.uk./FGA/introduction-to-redo.html
- joshuamorton 5y agoI guess my point is that in the case of some target a that depends on some target b existing (I'm not sure what the best example is here, I know that bazel takes advantage of this to parallelize compilation, but I'm not intimately familiar with c++ compilation internals, so it might be clearer with a generated file example). You have a.cc that depends on b.cc, but some tool generates b.cc, so it may not exist (but `b.do` does). If I invoke `a.do` to compile `a.cc`, and don't directly declare b.cc as a dependency in the .do file, the theoretical compiler will resolve that it depends on b.cc, and note that that doesn't exist, and then what? In the bazel world, since you define the dependency graph explicitly before invoking any compiler, you can't run into this issue, but in situations where you need to get dep info from the compiler...what happens with stuff like this?
- remram 5y agoWhy do you need to distinguish tabs from spaces?