3

For reasons that are not important here, I have a source code that I process automatically file-by-file and the processed source files are renamed in a systematic manner. For example, I start out with files called

fun1.c fun2.c

and end up with files

fun1_a.c fun2_a.c

I want the Makefile to be adapted automatically, too. A bare-bones version of the Makefile is

SRC=    fun1.c fun2.c

%.o: $.c
        $(CC) $(CFLAGS) -c $< -o $@

OBJ= $(SRC:.c=.o)

fun2.o: fun1.o

How can I best process the file so each entry in the definition of the source files and the dependencies is changed as needed, but the pattern rules are left untouched? In other words, what I need is:

SRC=    fun1_a.c fun2_a.c

%.o: $.c
        $(CC) $(CFLAGS) -c $< -o $@

OBJ= $(SRC:.c=.o)

fun2_a.o: fun1_a.o

I assume this is trivial, but my scripting abilities, especially in sed and perl are limited.

EDIT: Please note that in practice, not all the files will be called funx.c where x is an integer, so I'm looking for a solution that will work with any filename.

7
  • 1
    It would be possible to solve your problem entirely with make, is it a requirement to use tools such sed/perl/awk?
    – Kira
    Nov 17, 2015 at 15:38
  • Yes, I would prefer to have two separate copies of the Makefile. Nov 17, 2015 at 15:45
  • And isn't it relevant to better explain how your files are renamed? Otherwise something like sed 's/\(fun[0-9]\+\)/\1_a/' makefile would do the trick (I've not tested this, I'm trying to gather more information yet).
    – Kira
    Nov 17, 2015 at 15:47
  • Yes, you are right. I've edited my question accordingly. Nov 17, 2015 at 16:02
  • fun2.o: fun1.o ...this looks strange. I think that the rule .c --> .ois the default makefile rule. What is your makefile really doing?
    – JJoao
    Nov 18, 2015 at 0:01

2 Answers 2

1

i recommend to create a copy of the entire source tree then modify the files in the copy directory without renaming them. that way you don't need to modify the makefile. and as bonus you can have an overview of the changes just by comparing the directories.

instead of this

project
  fun1.c
  fun1_mod.c
  fun2.c
  fun2_mod.c
  Makefile
  Makefile_mod

you have this

project
  fun1.c
  fun2.c
  Makefile
project_mod
  fun1.c
  fun2.c
  Makefile

elaboration

if the makefile is super simple like in your example you might get away with using sed to modify the filenames in the makefile. but makefiles are arcane beasts. with a plethora of implicit rules and multiple levels of variable expansions.

mangling filenames is a common occurence even in simple makefiles. even your makefile has some filename mangling (OBJ= $(SRC:.c=.o)). this can get unexpected results if changing something using sed.

common wildcards like *.c can easily end up collecting more files than expected. and trying to write wildcards to exclude or include the suffix would be like herding cats.

if original and modified source files are in the same directory you can never be sure if not one of the originals was inadvertently compiled by the modified makefile or vice versa.

also, i forebode, you will not have just one modification. you will have many. so not just fun1_mod.c and fun2_mod.c but _mod1 _mod2 _mod3 _mod3butpartmod1 and so forth.

you will forever have headache figuring out what binary was compiled from which modset.

so create a copy of the entire source tree for each modification. modify the source in each directory. keep the filenames the same. keep the makefile the same.

that way you go in one directory and compile. go to other directory and compile. always the same makefile. and always know for sure which files will be compiled. (unless the makefile picks up source files from parent and sibling directories but that is not common practice and is frowned upon in the makefile community.)

bonus:

you can easily see what is different from one modset to another using a directory compare tool of your liking.

you can keep the modifications in source control like git. one branch for each mod. you can do changes in the main branch and propagate it to the other branches. you can cherry pick changes around. you can push and pull to colleagues.

0

Assuming that the original file names are static, and only the result of the rename operation is unpredictable. When you rename files, generate an additional file which would contain the mapping of the original file names to the new names, e.g.:

fun1.c=fun1_a.c
fun2.c=fun2_a.c

Assuming that this generated mapping file is called rename.mk, one can modify the Makefile in the following fashion:

include rename.mk
SRC=    $(fun1.c) $(fun2.c)

%.o: $.c
        $(CC) $(CFLAGS) -c $< -o $@

OBJ= $(SRC:.c=.o)

$(fun2.c:.c=.o): $(fun1.c:.c=.o)

The file names have become the variable names, and are used to access the new names via the mapping specified in the rename.mk.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.