I suspect that the manual is actually saying what I'm doing wrong, but I can't really see a solution; the problem occurs when the .c file and the .o file to be build are not in the same directory, and the .c file has an automatic dependency on a .h file which has to be generated on the fly. The problem can be probably be solved by manually setting dependencies between the .c and .h file, but I would like to avoid that.
I have the following directory structure:
weird/
Jamfile
b.c
src/
a.c
c.c
The src/a.c file is like this:
#include "src/a.h"
int main(int argc, char *argv[])
{
return 0;
}
The b.c file is like this:
#include "src/b.h"
int main(int argc, char *argv[])
{
return 0;
}
The src/c.c file is like this:
#include "c.h"
int main(int argc, char *argv[])
{
return 0;
}
The Jamfile is:
rule CreateHeader
{
Clean clean : $(1) ;
}
actions CreateHeader
{
echo "int x = 10;" > $(1)
}
Object a.o : src/a.c ;
Object b.o : b.c ;
Object c.o : src/c.c ;
CreateHeader src/a.h ;
CreateHeader src/b.h ;
CreateHeader src/c.h ;
The following command correctly creates b.o and src/b.h:
jam b.o
The following command creates src/a.h, but then GCC fails to create a.o; the reason is quite obviously that the #include in a.c mentions src/a.h while in fact should simply refer to a.h:
jam a.o
The following command fails completely, and does not even create c.h; the reason is probably that when Jam analyzes c.c it generates a dependency on c.h instead of src/c.h, and in the Jamfile there are no rules for generating c.h:
jam c.o
This command compiles properly if I explicitly ask to generate src/c.h before asking for c.o:
jam src/c.h
jam c.o
In my opinion the jam src/c.h should not be necessary. What's wrong here? Check the Jam manual for more information, particularly under the section Header File Scanning.
Added after I accepted the answer
I kept experimenting a little bit with the constructs suggested by the author of the accepted answer, and I'll post here the results. In this setting you can type:
jam app
And the application will be linked under bin/app. Unfortunately I had to use a UNIX path when setting LOCATE_TARGET, and my understanding is that this is not exactly a good practice.
Directory Structure:
project/
Jamfile
src/
main.c
gen/
bin/
obj/
File Jamfile:
SubDir TOP ;
rule CreateHeader
{
MakeLocate $(1) : $(LOCATE_SOURCE) ;
Clean clean : $(1) ;
}
actions CreateHeader
{
BUILD_DATE=`date`
echo "char build_date[] = \"$BUILD_DATE\";" > $(1)
}
SEARCH_SOURCE = src ;
LOCATE_TARGET = bin/obj ;
SubDirHdrs gen ;
Object main.o : main.c ;
LOCATE_TARGET = bin ;
MainFromObjects app : main.o ;
LOCATE_SOURCE = gen ;
CreateHeader info.h ;
File src/main.c
src/main.c
#include <stdio.h>
#include "info.h"
int main(int argc, char *argv[])
{
printf("Program built with Jam on %s.\n", build_date);
return 0;
}