Generic Makefile/Project

I've been working on a development environment architecture. I am targeting a posix-style environment, but want it to work on Windows as well. I am having troubles with part of my makefile which builds all dependencies.

On linux I'm using g++ and make, on Windows I am targeting MinGW and make. I'm not against using Cmake or Qmake, but I haven't found a good resource which describes what I'm doing. They are all either way too basic, or way too specific. Any advice you could give would be great.

My repository structure looks like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
File structure
  bin        - Output directory for resulting app and test-app
  build      - Directory containing build and packing files (makefiles, CMakelists.txt, etc)
  dat/<proj> - Runtime data needed by the project, may also contain runtime data needed by dependants
  dat/<dep>  - Each dep also has a dedicated folder here.
  dbin       - Output directory for resulting app built in debug mode (-g)
  doc/src    - Contains doc/src for a doxy file, and doc/bin for generated documentation
  etc/<proj> - Configuration data (may be over-riden by dependenants)
  etc/<dep>  - Each dep also has a dedicated folder here.
  ext/<dep>  - Contains svn:externals for dependencies
               <proj> will build these, and install here before building itself.  
               Each <dep> is garunteed to also have this file structure.
  inc/<proj> - Contains include files from dependencies, and public include files from this project.
  inc/<dep>  - Each <dep> has it's include files available here.
  int/       - Contains garbage intermediate files
  lib        - Contains static libraries (may be the primary output of this project depending on type)
  src        - Contains all source files and headers,  may include subdirs.
  test       - Contains sources needed to build the test-app.
  var        - Contains log files.  Used during runtime only.  Not needed in repo 


Pseudocode for my makefile looks like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
Config
  <proj> = ProjectName
  <rootdir> = ..
  <dependencies> = dep1 dep2 dep3
  <Config> = Release|Debug
  <Template> = app|so|lib
Build Dependencies
  for each <dep> in <dependencies>
    if (<rootdir>/ext/<dep> exists)                   # Search for deps in ext/
      <depdir> = <rootdir>/ext/<dep>
      make -C <depdir>/build
    else if (<rootdir>/../<dep> exists)               # Maybe we are already a
      <depdir> = <rootdir>/../<dep>                   #  dep, check if our deps 
    else                                              #  are siblings
      throw error:  "Dependency not found"
    endif
    cp <depdir>/bin/*        <rootdir>/bin/           # Only for app dep
    cp <depdir>/lib/*.a      <rootdir>/lib/           # Only for static dep
    cp <depdir>/lib/*.so     <rootdir>/lib/           # Only for dynamic dep
    cp <depdir>/inc/<dep>/*  <rootdir>/inc/<dep>/    
    cp <depdir>/dat/<dep>/*  <rootdir>/dat/<dep>/
    cp <depdir>/etc/<dep>/*  <rootdir>/etc/<dep>/ -n
  endfor
Build my stuff
  Build my binaries
    compile ../src/*.cpp + subdirs to ../int/*.o
    link ../int/*.o ../lib/*.a and ../lib/*.so into */int/<proj>.a
    if <template>=so
      compile ../src/LibInterface.cpp and link ./lib/<proj>.a into ../lib/lib<proj>.so 
    else if <template>=app
      compile ./lib/<proj.a> into ../bin/<proj>
  Copy my public API
    cp ../src/*.h  ../inc/<proj> (probably want to define a subset)
  Build test
    compile ../test/*.cpp and link ../lib/<proj>.a into ../bin/<proj>-test
  Build documentation
	( cat <rootdir>/doc/src/doxy ; echo "OUTPUT_DIRECTORY=<rootdir>/doc/bin" ) | doxygen - */


I've got most sections working except for the "Build Dependencies" section because I can't figure out how to do the text-replacement in make for a procedure like this.

Would appreciate some help with how to template that!
Last edited on
I'm starting to think that the giant "cp" block could be handled inside of the dependencies makefile. In addition, the if/elseif/else section could be omitted, with the consequence of building super-generic libraries over and over and over for each dependency. It'd be an optimization I could figure out later.

Then it would look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Config
  <proj> = ProjectName
  <rootdir> = ..
  <dependencies> = dep1 dep2 dep3
  <Template> = app|so|lib
Build Dependencies
  for each <dep> in <dependencies>
    make -C <rootdir>/ext/<dep>
  endfor
Build my stuff
  Build my binaries
    compile ../src/*.cpp + subdirs to ../int/*.o
    link ../int/*.o ../lib/*.a and ../lib/*.so into */int/<proj>.a
    if <template>=so
      compile ../src/LibInterface.cpp and link ./lib/<proj>.a into ../lib/lib<proj>.so 
    else if <template>=app
      compile ./lib/<proj.a> into ../bin/<proj>
  Copy my public API
    cp ../src/*.h  ../inc/<proj> (probably want to define a subset)
  Build test
    compile ../test/*.cpp and link ../lib/<proj>.a into ../bin/<proj>-test
  Build documentation
	( cat <rootdir>/doc/src/doxy ; echo "OUTPUT_DIRECTORY=<rootdir>/doc/bin" ) | doxygen - */
  Install
    cp <rootdir>/bin/*        <installdir>/bin/           # Only for app dep
    cp <rootdir>/lib/*.a      <installdir>/lib/           # Only for static dep
    cp <rootdir>/lib/*.so     <installdir>/lib/           # Only for dynamic dep
    cp <rootdir>/inc/<dep>/*  <installdir>/inc/<dep>/    
    cp <rootdir>/dat/<dep>/*  <installdir>/dat/<dep>/
    cp <rootdir>/etc/<dep>/*  <installdir>/etc/<dep>/ -n */


That means the problem I need to solve is how to do this in make:
1
2
for each <dep> in <dependencies>
  make -C <rootdir>/ext/<dep>
Solved it:
1
2
3
4
DEPENDENCIES = dep1 dep2 dep3

$(DEPENDENCIES) : 
  $(MAKE) -C $(ROOTDIR)/ext/$@
Remember to declare DEPENDENCIES as phony or it won't work properly.
Topic archived. No new replies allowed.