Makefile with sources in diferent folders

Hi guys!
I have a problem to create a makefile when using 2 types of sources.
Suppose we have sources at master_source folder:

  • 1.c
  • 2.c
    and also we have sources at platform_source folder:
  • 1.c

I really need to use platform_source folder because there is many of them (one folder with 1.c, 2.c, neither or both for each platform)

I need to copy master_source files to a diferent folder (say tmp) and there overwrite files with ones at platform_source folder.

So if i touch platform_source/1.c it shoul copy only this file to tmp folder. And if i touch master_src/1.c, it should copy master_src/1.c to tmp and after it copy platform_source/1.c to tmp (or not do anything, because our source depends mostly on platform_source folder)

If someone can help me to create such a makefile i would apreciate it.
Thanks!

It could be done, I suppose, but are you sure this is really the right approach? A customary arrangement would be to factor the platform-dependent stuff to individual #include files or directories, then at compilation time pass in a #define which selects which platform to build for. By and large, this sounds like a more maintainable and scalable approach than what you are proposing (and avoids this pesky issue of copying files and then being sure whatever is there is indeed the correct version).

"Classic" make is not very amenable to conditional dependencies; if GNU make syntax or some other extension is permissible, then it almost sounds doable, but still not necessarilly elegant and sustainable.

Whatever you come up with, I'd think you need to take into account idempotency and concurrency issues; what if a make is aborted, and the files are left lying there for the next make to pick up; or, what if two makes are started at roughly the same time?

Well, that what you propose is very nice, but i just give you an example, so you can understand that i have no other way.
I'm working in a company that makes games for cellphones, games have common java source files and specific for phone. So for example i have midlet.jpp at common source, and for phone Sony Ericsson k790 this source is working fine, but for Motorola Z6 it's not. So programmers here create midlet.jpp for Motorola Z6.
I'm sure that putting defines everywhere at code for all phones will be a mess, i have seen projects like this, and it is very difficult to read that kind of source.
And what's for concurrency issues, i really don't much care, because i will just compile project without starting two makes.
Thanks for your reply

I created a makefile that is not copying 2.c to tmp:

all: tmp/*.c

master_source/*.c:

platform_source/*.c:

tmp/*.c: master_source/*.c platform_source/*.c
      @cp $< tmp/

Note that if there exists platform_source/3.c it must be copied too, when modificated.

And forking a file every time you need to tweak it for another platform is not a mess? Brrr ....

Still, doesn't Java allow you to create an include path, so that when instructed to compile fnord.jpp, it would look first for motorola/fnord.jpp and then if it's not available, fall back to generic/fnord.jpp?

Make doesn't understand wildcards; again, if GNU make syntax is acceptable, then there is some hope, but still, I'm thinking that there are ways to work with the compiler which would obviate the need for copying stuff in the Makefile.

Its okay when we're talking about small program, but we're talking about lines and lines of code. If you would see something ugly as:

#ifdef MOTOROLA_Z6
// 3000 lines of code
#else
#ifdef SONYERICSSON_K790
//other 3000 lines of code
#else
//other 3000 lines of code
#endif
#endif

i'm sure you would understand this. It's better sometimes to "fork" a new file that use one file for 10-20 phones. But we are out of subject :). I just wanted to know if there is a way to copy only necessarily files using make.
I have GNU make, and it understand wildcards: but appearently when using rule:
tmp/.c: master_source/.c platform_source/*.c
it only looks for files with same name in both master_source and platform_source. Is there some way to workaround this feature?, so it can copy all needed files not only ones with same name.

I figured it out. The solution was to use timestamps. Here is the makefile:


MASTER_SRC_DIR         = master_src
MASTER_SRC_FILES       = $(wildcard $(MASTER_SRC_DIR)/*.c)
SPECIFIC_SRC_DIR       = platform_src
SPECIFIC_SRC_FILES     = $(wildcard $(SPECIFIC_SRC_DIR)/*.c)

SOURCE_DIR             = tmp
SOURCE_FILES           = $(subst $(MASTER_SRC_DIR),$(SOURCE_DIR),$(MASTER_SRC_FILES)) \
                         $(subst $(SPECIFIC_SRC_DIR),$(SOURCE_DIR),$(SPECIFIC_SRC_FILES))

TIMESTAMP_MASTER_SRC   = $(SOURCE_DIR)/MasterSrc.time
TIMESTAMP_PLATFORM_SRC = $(SOURCE_DIR)/PlatformSrc.time

all: $(SOURCE_FILES)

$(SOURCE_FILES): $(TIMESTAMP_MASTER_SRC) $(TIMESTAMP_PLATFORM_SRC)

$(TIMESTAMP_MASTER_SRC): $(MASTER_SRC_FILES)
	$(foreach FILE, $?, \
		if [ ! -e $(subst $(MASTER_SRC_DIR),$(SPECIFIC_SRC_DIR),$(FILE)) ] ; then cp $(FILE) $(SOURCE_DIR)/ ; \
		else cp $(subst $(MASTER_SRC_DIR),$(SPECIFIC_SRC_DIR),$(FILE)) $(SOURCE_DIR)/ ; fi ; \
	)
	echo Do not delete! >$(TIMESTAMP_MASTER_SRC)

$(TIMESTAMP_PLATFORM_SRC): $(SPECIFIC_SRC_FILES)
	$(foreach FILE, $?, cp $(FILE) $(SOURCE_DIR)/ ; )
	echo Do not delete! >$(TIMESTAMP_PLATFORM_SRC)


That's it. As era said it's pretty ugly, but it's working. Can close the thread now.

I would have thought something more or less along these lines:

tmp/%.c:
      cp $$(test -e platform_source/$*.c && echo platform_source || echo master_source)/$*.c $@

I'm still just struggling with the idea that it's probably better to tell the compiler to prefer files from platform_source over files from master_source and avoid this whole silly copying business (gripes over apparent negligence towards code modularity notwithstanding).

jeje, it's really better, but the company is working with batch files (Windows XP), and that's my idea to reduce compiling time. It would really take a long time to modify all source files along with creating Makefiles. For now I just will create makefile, repeating steps of batch files. Anyway thanks for replys. Good luck!