MakeMake: Generate make files from C source code
github.com
github.com
E.g.:
force-update-deps::
rm .deps
.deps:
gcc -MM *.c > $@
include .deps CFLAGS += -MD
-include $(wildcard *.d)
I personally like to also pass `-MP` to add phony targets so removing a header doesn't complain about headers which are intentionally removed.You can pass `-MMD` instead of `-MD` to avoid having system includes in the generated depfiles just like the example you wrote does.
I also personally prefer to be explicit and avoid wildcards in makefiles wherever possible so I would do something like this:
CFLAGS += -MD -MP
objs := foo.o bar.o ... baz.o
deps = $(objs:.o=.d)
...
-include $(deps)
That being said, this doesn't solve the "everything should depend on the Makefile" problem as well as the "what if I generate a generate source code" problem or finally "what if I have to compile C to generate C to compile my program" problem.As such, I have personally switched to redo.
In particular, you probably want to use `-include` instead of `include`, to continue even a given .dep file doesn't exist (as on the first run).
The GNU Make maintainer wrote in-depth about ways to do it here: https://make.mad-scientist.net/papers/advanced-auto-dependen...
default: all
Common.mk:
$(error Not configured)
include Common.mk
gives a nicer error message if you 'make' having not './configure'dI've mostly used CMake for my build systems over the past ~20 years.
But recently I got into CUDA programming, and I was put off by the large amount of opaque magic provided by CMake's built-in CUDA support.
It made it somewhat harder to have clarity about the variety of CUDA build commands, which kinds of file each could ingest and produce, and which options they accepted.
As someone new to the entire CUDA toolchain, that magic was more of an impediment than an help.
So for starters I'm just writing a Bash script for building my code. But the next step for automation will be a hand-written Makefile, not a CMakeLists.txt file.
CMake is just a little too high level for my taste. Like I don't really understand how its figuring stuff out under the hood. Now that is of course because I haven't bothered studying up on it, but the point is you don't really have to with Make since the basic concept is dead simple.
Did you have an interest in makemake before? This github repo looks brand new.
https://www.csh.rit.edu/~tommut/tech/makemake.html
I seem to recall there being a similarly named program in the late 80's, early 90's, but it could just be a script some colleague wrote ..
But there has been a C makemake version in 1996, I have used that IIRC.
I don't want to sound too negative, but what does this version do that all the other existing 13843215 versions don't?
> In July 2008, in accordance with IAU rules for classical Kuiper belt objects, 2005 FY9 was given the name of a creator deity. The name of Makemake, the creator of humanity and god of fertility in the myths of the Rapa Nui, the native people of Easter Island, was chosen in part to preserve the object's connection with Easter.
Id say the main use case is to move dependencies from a project file to the actiual C files that have the dependencies, This way if the dependencies change all projects that use the file have their build process automaticaly updated. It also removes the need to list the files included in a project since this is information that already exists in the .c files.
Any time you have to define the same thing in two places, you have the risk of them not beeing in sync. This way there is only one canoical ground truth. Source and build process can never be out of sync.
I'll try another one: does it correctly set preprocessor directives before parsing the includes? E.g. does it correctly parse stuff like
#ifdef FOO
#include <bar>
#else
#include <baz>
#endifThis means that all source code files has to be compilable on all platforms, and thats good practice anyways, so thats not a problem for me.
The makemake pragma lets you define platform specific build options.
And then it hits the real world and you need to switch to a tool that handles it.
I just don't understand why you wouldn't use CMake for this? Especially since VS has built-in CMake support.
* Before CMake 3.20, released in 2021, CMake tracked dependencies at configuration time. As a result, any time you add/remove a header file, you need to re-run CMake in order to have correct builds. CMake 3.20 finally delegated this out to the underlying compiler.
* The Makefile produced by CMake does not have a target for the object file. Even though it prints out the path `CMakeFiles/cmake_target.dir/src/my_file.cc.o`, and generates that file, you cannot run `make CMakeFiles/cmake_target.dir/src/my_file.cc.o` from inside the build directory. Instead, you need to run `make src/my_file.cc.o`, a PHONY target which actually builds the object file.
* Wildcard rules in CMake are expanded to static rules in Make, rather than wildcard rules. As a result, any time you add/remove a file, such as when checking out a new branch, you need to re-run CMake in order to have a correct build.
* Until recently, the makefiles produced by CMake did give useful information with `make --dry-run`. Instead of printing the command required to compile a file, it instead printed an internal delegation back to cmake.
* Non-transferable build. The `CMakeCache.txt` stores a record of what options have been enabled/disabled, but also has local file information. As a result, the contents of `CMakeCache.txt` are essential to know what I actually built, but I cannot send it to somebody else as a way to reproduce my build. Makefiles generally avoid this by having explicit include files, which then can be transferred.
So, in order to have correct and reproducible builds, I need to re-run CMake every time I'm building a project, the usual tools for debugging a build error are broken, and including my build environment in a bug report is useless for reproduction. I can see why somebody would want to avoid it.
FD: CMake developer
So… when did CMake start its “modern” phase? Does my experience resonate with yours at all?
CMake release notes pretty consistently have at least one thing that makes me go "how is that a thing that just got implemented now and not 20 years ago?" That's not exactly a positive, but there are a very large number of things where 15 years ago you'd be shocked and frustrated to discover that there's no good way to do it, while today there's an obvious and simple way.
Do you mind pointing me to that issue? Off-HN is fine too (same GitHub handles here; grab an email address from commit metadata).
Also note that while Windows might have POSIX APIs, sometimes the semantics are just not quite right. File permissions is one such place where things "exist" but act like they're in an alternate dimension (e.g., what would `umask` do on Windows?).
You are shooting your future self in the foot by going out of your way to use a handbuilt new framework.
It can still be valuable as a learning project.
More complicated project? Might shoot out to 2 pages. It'll still work in 20 years time too, the tools won't change under you (I'm looking at you, pretty much all other build systems)
while true; do make -q || make; sleep 0.5; done
I'd much rather install entr if it's available and do something like
`ls ** | entr -c make`
watch : while true; do \ clear; $(MAKE) -j all tests; \ inotifywait -qre close_write src tests; \ done
https://latedev.wordpress.com/2014/11/08/generic-makefiles-w...
is a blog article i wrote a long time back abouut how to automate makefiles. there is a lot wrong with it, but some of the concepts might be useful for people trying to do better.
edit: in the blog i said "indirection" when i meant "redirection". doh.
In C, "extern" is normally implicit for functions. Does your tool require them to be explicitly marked?
function makemake() {
>makefile echo '
.RECIPEPREFIX = >
ASAN = -fsanitize=address
CFLAGS += -Wall -Wextra -g3
CFLAGS += $(ASAN)
LDFLAGS += $(ASAN) -Wall -Wextra -g3
SRCS = $(wildcard .c)
OBJS = $(patsubst .c, .o, $(SRCS))
#CC = clang
# main function must be in the $NAME.c file
'"NAME=${1:-main}" '
all: $(NAME)
$(NAME): $(OBJS)
print_name: > @echo $(NAME)
clean: > rm -rf .o
fclean: clean > rm -rf ${NAME}
re: fclean all
.PHONY: print_name clean fclean re
' }
Ofc, what's really needed is a tool to make the MakeMakeMake script. Struggling for a name though ...
Basically it is a build system that uses C as a DSL. And no dependency tracking I think?
This is in the site guidelines: https://news.ycombinator.com/newsguidelines.html.
(Edit: I see downthread that you mentioned it wasn't your intention.)
make make does this by looking for any function declaration using extern,
Taking that at face value (I'd not inspected the code in detail), then it would miss functions with implicit externs, no? My apologies if you found my posting offensive, that was not my intention.The issue is phrasing a statement as a question like you did is passive aggressive, and unconstructive.