summaryrefslogtreecommitdiff
path: root/jam-files/sanity.jam
blob: 957f4f43cdcbd2930b41a7d5d9a554b6b037544b (plain)
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
import modules ;
import option ;
import os ;
import path ;
import project ;

#Shell with trailing line removed http://lists.boost.org/boost-build/2007/08/17051.php
rule trim-nl ( str extras * ) {
return [ MATCH "([^
]*)" : $(str) ] $(extras) ;
}
rule _shell ( cmd : extras * ) {
  return [ trim-nl [ SHELL $(cmd) : $(extras) ] ] ;
}

cxxflags = [ os.environ "CXXFLAGS" ] ;
cflags = [ os.environ "CFLAGS" ] ;
ldflags = [ os.environ "LDFLAGS" ] ;

#Run g++ with empty main and these arguments to see if it passes.  
rule test_flags ( flags * ) {
  local add = $(CXXFLAGS) $(LDFLAGS) ;
  add ?= "" ;
  local cmd = "bash -c \"g++ $(add) "$(flags:J=" ")" -x c++ - <<<'int main() {}' -o /dev/null >/dev/null 2>/dev/null\"" ;
  local ret = [ SHELL $(cmd) : exit-status ] ;
  if --debug-configuration in [ modules.peek : ARGV ] {
    echo $(cmd) ;
    echo $(ret) ;
  }
  if $(ret[2]) = 0 {
    return true ;
  } else {
    return ;
  }
}

rule test_header ( name ) {
  return [ test_flags "-include $(name)" ] ;
}

rule test_library ( name ) {
  return [ test_flags "-l$(name)" ] ;
}

{
  local cleaning = [ option.get "clean" : : yes ] ;
  cleaning ?= [ option.get "clean-all" : no : yes ] ;
  if "clean" in [ modules.peek : ARGV ] {
    cleaning = yes ;
  }
  constant CLEANING : $(cleaning) ;
}

#Determine if a library can be compiled statically.  
rule auto-shared ( name : additional * ) {
  additional ?= "" ;
  if [ test_flags $(additional)" -static -l"$(name) ] {
    return ;
  } else {
    return "<link>shared" ;
  }
}

# MacPorts' default location is /opt/local -- use this if no path is given.
with-macports = [ option.get "with-macports" : : "/opt/local" ] ;
if $(with-macports) {
  using darwin ;
  ECHO "Using --with-macports=$(with-macports), implying use of darwin GCC" ;

  L-boost-search = -L$(with-macports)/lib ;
  boost-search = <search>$(with-macports)/lib ;
  I-boost-include = -I$(with-macports)/include ;
  boost-include = <include>$(with-macports)/include ;
}
else {
  with-boost = [ option.get "with-boost" ] ;
  with-boost ?= [ os.environ "BOOST_ROOT" ] ;
  if $(with-boost) {
    L-boost-search = -L$(with-boost)/lib" "-L$(with-boost)/lib64 ;
    boost-search = <search>$(with-boost)/lib <search>$(with-boost)/lib64 ;
    I-boost-include = -I$(with-boost)/include ;
    boost-include = <include>$(with-boost)/include ;
  } else {
    L-boost-search = "" ;
    boost-search = ;
    I-boost-include = "" ;
    boost-include = ;
  }
}

requirements = ;
 
#Are we linking static binaries against shared boost?
boost-auto-shared = [ auto-shared "boost_program_options" : $(L-boost-search) ] ;
#Convenience rule for boost libraries.  Defines library boost_$(name).  
rule boost-lib ( name macro ) {
  #Link multi-threaded programs against the -mt version if available.  Old 
  #versions of boost do not have -mt tagged versions of all libraries.   Sadly,
  #boost.jam does not handle this correctly.  
  if [ test_flags $(L-boost-search)" -lboost_"$(name)"-mt" ] {
#    if [ test_flags $(L-boost-search)" -lboost_"$(name) ] {
#      lib inner_boost_$(name) : : <threading>single $(boost-search) <name>boost_$(name) ;
#      lib inner_boost_$(name) : : <threading>multi $(boost-search) <name>boost_$(name)-mt ;
#    } else {
      if ! <threading>multi in $(requirements) {
        requirements += <threading>multi ;
      }
      lib inner_boost_$(name) : : <threading>multi $(boost-search) <name>boost_$(name)-mt ;
#    }
  } else {
    lib inner_boost_$(name) : : $(boost-search) <name>boost_$(name) ;
  }

  alias boost_$(name) : inner_boost_$(name) : $(boost-auto-shared) : : <link>shared:<define>BOOST_$(macro) $(boost-include) ;
}

#Argument is e.g. 103600
rule boost ( min-version ) {
  local cmd = "bash -c \"g++ "$(I-boost-include)" -dM -x c++ -E /dev/null -include boost/version.hpp 2>/dev/null |grep '#define BOOST_VERSION '\"" ;
  local boost-shell = [ SHELL "$(cmd)" : exit-status ] ;
  if $(boost-shell[2]) != 0 && $(CLEANING) = no {
    echo Failed to run "$(cmd)" ;
    exit Boost does not seem to be installed or g++ is confused. : 1 ;
  }
  boost-version = [ MATCH "#define BOOST_VERSION ([0-9]*)" : $(boost-shell[1]) ] ;
  if $(boost-version) < $(min-version) && $(CLEANING) = no {
    exit You have Boost $(boost-version).  This package requires Boost at least $(min-version) (and preferably newer). : 1 ;
  }
  #See tools/build/v2/contrib/boost.jam in a boost distribution for a table of macros to define.   
  boost-lib thread THREAD_DYN_DLL ;
  boost-lib program_options PROGRAM_OPTIONS_DYN_LINK ;
  boost-lib unit_test_framework TEST_DYN_LINK ;
  boost-lib iostreams IOSTREAMS_DYN_LINK ;
  boost-lib serialization SERIALIZATION_DYN_LINK ;
  boost-lib mpi MPI_DYN_LINK ;
}
 
#Link normally to a library, but sometimes static isn't installed so fall back to dynamic.
rule external-lib ( name : search-path * ) {
  lib $(name) : : [ auto-shared $(name) : "-L"$(search-path) ] <search>$(search-path) ;
}

#Write the current command line to previous.sh.  This does not do shell escaping.  
{
  local build-log = $(TOP)/previous.sh ;
  if ! [ path.exists $(build-log) ] {
    SHELL "touch $(build-log) && chmod +x $(build-log)" ;
  }
  local script = [ modules.peek : ARGV ] ;
  if $(script[1]) = "./jam-files/bjam" {
    #The ./bjam shell script calls ./jam-files/bjam so that appears in argv but
    #we want ./bjam to appear so the environment variables are set correctly.  
    script = "./bjam "$(script[2-]:J=" ") ;
  } else {
    script = $(script:J=" ") ;
  }
  script = "#!/bin/sh\n$(script)\n" ;
  local ignored = @($(build-log):E=$(script)) ;
}

{
  #Boost jam's static clang is buggy.  
  requirements += <cxxflags>$(cxxflags) <cflags>$(cflags) <linkflags>$(ldflags) <toolset>clang:<link>shared ;

  #libSegFault prints a stack trace on segfault.  Link against it if available.  
  if [ test_flags "-lSegFault" ] {
    external-lib SegFault ;
    requirements += <library>SegFault ;
  }
}

if [ option.get "git" : : "yes" ] {
  local revision = [ _shell "git rev-parse --verify HEAD |head -c 7" ] ;
  constant GITTAG : "/"$(revision) ;
} else {
  constant GITTAG : "" ;
}

prefix = [ option.get "prefix" ] ;
if $(prefix) {
  prefix = [ path.root $(prefix) [ path.pwd ] ] ;
} else {
  prefix = $(TOP)/dist$(GITTAG) ;
}

bindir = [ option.get "bindir" : $(prefix)/bin ] ;
libdir = [ option.get "libdir" : $(prefix)/lib ] ;
rule install-bin-libs ( deps * ) {
  install prefix-bin : $(deps) : <location>$(bindir) <install-dependencies>on <install-type>EXE <link>shared:<dll-path>$(libdir) ;
  install prefix-lib : $(deps) : <location>$(libdir) <install-dependencies>on <install-type>LIB <link>shared:<dll-path>$(libdir) ;
}
rule install-headers ( name : list * : source-root ? ) {
  local includedir = [ option.get "includedir" : $(prefix)/include ] ;
  source-root ?= "." ;
  install $(name) : $(list) : <location>$(includedir) <install-source-root>$(source-root) ;
}

rule build-projects ( projects * ) {
  for p in $(projects) {
    build-project $(p) ;
  }
}