help-make
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

make features request


From: Maxim Yegorushkin
Subject: make features request
Date: Sat, 27 Mar 2010 12:13:56 +0000
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.8) Gecko/20100301 Fedora/3.0.3-1.fc12 Thunderbird/3.0.3

Currently, pattern rules allow only for one % character. This works well when the target file name is a simple transformation of its dependency, like:

  %.o : %.cc

There are times though, when more advanced filename transformation is required. For example, in Qt world they generate ui .h files from corresponding .ui files using the following naming conventions (don't ask me why):

  ui_%.h : %.ui

This works for makefile systems which require target files to be generated in the same source folder (relative filename method), like recursive make.

For non-recursive makefile systems which always use a complete dependency tree using explicit path method, when targets and dependencies are in different folders, something like the following is required:

  ${gen_src_dir}/%/ui_%.h : ${src_dir}/%/%.ui

An expansion, for example:


/home/max/works/builds/Linux-x86_64-64.g++-release/gen_src/gui/monitor/ui_monitor.h : /home/max/works/src/gui/monitor/monitor.ui

What would solve this issue nicely is regex pattern rules, something like the following:

  .REGEX-RULES-BEGIN
  ${gen_src_dir}/(.+)/ui_(\w+).h : ${src_dir}/\1/\2.ui
  .REGEX-RULES-END

***

Anther issue with building into a separate build directory is that target directories need to be created on demand. This leads to having to manually establish directory dependencies:

  ${obj_dir}/project/main.o : ${src_dir}/project/main.cc
  ${obj_dir}/project/main.o : | ${obj_dir}/project
  ${obj_dir}/project : mkdir -p $@

There are two issues with these rules.

First, is that for every object file has to have an order-only dependency on its directory, so that make creates the directory before any targets are put there.

Second, is that `mkdir -p` does not work for parallel builds. This occurs when make tries to invoke, for example, `mkdir -p /a/b` and `mkdir -p /a/c` in parallel, with directory /a being non-existent. What `mkdir -p` does is that first it stats /a directory and if it does not exist it tries to create that. There is a race condition between stat'ing the directory and creating it, during which another parallel invocation of mkdir creates this same directory, which causes creating /a directory in the former mkdir to return EEXIST and fail. It must be mkdir bug (both gnu and Solaris), but I not sure if it can be fixed in mkdir, since if creating a directory returns EEXIST, that directory needs to be stat'ed again, to make sure it is a directory and not a file, leading to a race condition again. (no POSIX interface to create a directory and if that name already exists in the filesystem return its type).

So, it would be very useful if make could create directories for targets on demand. Something like the following:

  .CREATE-TARGET-DIRECTORIES-BEGIN
  ${obj_dir}/project/main.o : ${src_dir}/project/main.cc
  .CREATE-TARGET-DIRECTORIES-END

Or, along with the first feature request:

  .REGEX-RULES-BEGIN
  .CREATE-TARGET-DIRECTORIES-BEGIN
  ${obj_dir}/(.+)/(\w+).o : ${src_dir}/\1/\2.cc
  .CREATE-TARGET-DIRECTORIES-END
  .REGEX-RULES-END

To work around these two issues I currently have to do macro expansion in make:

  $(eval $(call O_TARGET,project,main.o other.o))

Which expands to something like that:

  ${obj_dir}/project/main.o : ${src_dir}/project/main.cc
  ${obj_dir}/project/other.o : ${src_dir}/project/other.cc
${obj_dir}/project/main.o ${obj_dir}/project/other.o : | ${obj_dir}/project
  ${obj_dir}/project : | ${obj_dir}
  ${obj_dir} ${obj_dir}/project : mkdir $@

With the features I mentioned above I would not need make macro expansion at all.

Any thoughts?

Max





reply via email to

[Prev in Thread] Current Thread [Next in Thread]