mirror of
https://github.com/moses-smt/mosesdecoder.git
synced 2024-12-26 05:14:36 +03:00
f4c6aee6ce
Rationale: some systems are missing static glibc but have static boost. This will detect and link against static Boost on those systems.
348 lines
12 KiB
Plaintext
348 lines
12 KiB
Plaintext
import modules ;
|
|
import option ;
|
|
import os ;
|
|
import path ;
|
|
import project ;
|
|
import build-system ;
|
|
import version ;
|
|
|
|
#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) ] ] ;
|
|
}
|
|
|
|
rule shell_or_fail ( cmd ) {
|
|
local ret = [ SHELL $(cmd) : exit-status ] ;
|
|
if $(ret[2]) != 0 {
|
|
exit $(cmd) failed : 1 ;
|
|
}
|
|
}
|
|
|
|
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 * : main ? ) {
|
|
flags = $(cxxflags) $(ldflags) $(flags) ;
|
|
if ! $(main) {
|
|
main = "int main() {}" ;
|
|
}
|
|
local cmd = "bash -c \"g++ "$(flags:J=" ")" -x c++ - <<<'$(main)' -o $(TOP)/dummy >/dev/null 2>/dev/null && rm $(TOP)/dummy 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)" ] ;
|
|
}
|
|
|
|
requirements = ;
|
|
|
|
FORCE-STATIC = [ option.get "static" : : "yes" ] ;
|
|
if $(FORCE-STATIC) {
|
|
requirements += <link>static <runtime-link>static ;
|
|
}
|
|
|
|
rule test_library ( name ) {
|
|
if $(FORCE-STATIC) {
|
|
return [ test_flags "-Wl,-Bstatic -l$(name) -Wl,-Bdynamic" ] ;
|
|
} else {
|
|
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) ;
|
|
}
|
|
|
|
shared-command-line = ;
|
|
local argv = [ modules.peek : ARGV ] ;
|
|
while $(argv) {
|
|
if $(argv[1]) = "link=shared" {
|
|
shared-command-line = <link>shared ;
|
|
}
|
|
argv = $(argv[2-]) ;
|
|
}
|
|
|
|
#Determine if a library can be compiled statically.
|
|
rule auto-shared ( name : additional * ) {
|
|
additional ?= "" ;
|
|
if $(shared-command-line) = "<link>shared" {
|
|
return "<link>shared" ;
|
|
} else {
|
|
if [ test_flags $(additional)" -Wl,-Bstatic -l"$(name)" -Wl,-Bdynamic" ] {
|
|
return ;
|
|
} else {
|
|
if $(FORCE-STATIC) {
|
|
echo "Could not statically link against lib $(name). Your build will probably fail." ;
|
|
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 ;
|
|
requirements += $(boost-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 ;
|
|
requirements += $(boost-include) ;
|
|
} else {
|
|
L-boost-search = "" ;
|
|
boost-search = ;
|
|
I-boost-include = "" ;
|
|
boost-include = ;
|
|
}
|
|
}
|
|
|
|
#Convenience rule for boost libraries. Defines library boost_$(name).
|
|
rule boost-lib ( name macro : deps * ) {
|
|
flags = $(L-boost-search)" -lboost_"$(name)"$(boost-lib-version)" ;
|
|
local main ;
|
|
if $(name) = "unit_test_framework" {
|
|
main = "BOOST_AUTO_TEST_CASE(foo) {}" ;
|
|
flags += " -DBOOST_TEST_MODULE=CompileTest $(I-boost-include) -include boost/test/unit_test.hpp" ;
|
|
}
|
|
if $(boost-auto-shared) = "<link>shared" {
|
|
flags += " -DBOOST_$(macro)" ;
|
|
} else {
|
|
flags = " -Wl,-Bstatic $(flags) -Wl,-Bdynamic " ;
|
|
}
|
|
if [ test_flags $(flags) : $(main) ] {
|
|
lib inner_boost_$(name) : : <threading>single $(boost-search) <name>boost_$(name)$(boost-lib-version) : <link>static : <library>$(deps) ;
|
|
lib inner_boost_$(name) : : <threading>multi $(boost-search) <name>boost_$(name)$(boost-lib-version) : <link>static : <library>$(deps) ;
|
|
} else {
|
|
lib inner_boost_$(name) : : $(boost-search) <name>boost_$(name)$(boost-lib-version) : : <library>$(deps) ;
|
|
}
|
|
|
|
if $(boost-auto-shared) = "<link>shared" {
|
|
alias boost_$(name) : inner_boost_$(name) : <link>shared ;
|
|
requirements += <define>BOOST_$(macro) ;
|
|
} else {
|
|
alias boost_$(name) : inner_boost_$(name) : <link>static ;
|
|
}
|
|
}
|
|
|
|
#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_'\"" ;
|
|
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 ;
|
|
}
|
|
constant 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 ;
|
|
}
|
|
# If matching version tags exist, use them.
|
|
boost-lib-version = [ MATCH "#define BOOST_LIB_VERSION \"([^\"]*)\"" : $(boost-shell[1]) ] ;
|
|
if [ test_flags $(L-boost-search)" -lboost_program_options-"$(boost-lib-version) ] {
|
|
boost-lib-version = "-"$(boost-lib-version) ;
|
|
} else {
|
|
boost-lib-version = "" ;
|
|
}
|
|
|
|
#Are we linking static binaries against shared boost?
|
|
boost-auto-shared = [ auto-shared "boost_program_options"$(boost-lib-version) : $(L-boost-search) ] ;
|
|
|
|
#See tools/build/v2/contrib/boost.jam in a boost distribution for a table of macros to define.
|
|
boost-lib system SYSTEM_DYN_LINK ;
|
|
boost-lib thread THREAD_DYN_DLL : boost_system ;
|
|
boost-lib program_options PROGRAM_OPTIONS_DYN_LINK ;
|
|
boost-lib unit_test_framework TEST_DYN_LINK ;
|
|
boost-lib iostreams IOSTREAMS_DYN_LINK ;
|
|
boost-lib filesystem FILE_SYSTEM_DYN_LINK ;
|
|
# if $(BOOST-VERSION) >= 104800 {
|
|
# boost-lib chrono CHRONO_DYN_LINK ;
|
|
# boost-lib timer TIMER_DYN_LINK : boost_chrono ;
|
|
# }
|
|
}
|
|
|
|
#Link normally to a library, but sometimes static isn't installed so fall back to dynamic.
|
|
rule external-lib ( name : search-path * : deps * ) {
|
|
lib $(name) : : [ auto-shared $(name) : "-L"$(search-path) ] <search>$(search-path) <use>$(deps) ;
|
|
}
|
|
|
|
#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 for Linux is buggy.
|
|
requirements += <cxxflags>$(cxxflags) <cflags>$(cflags) <linkflags>$(ldflags) <os>LINUX,<toolset>clang:<link>shared ;
|
|
|
|
if ! [ option.get "without-libsegfault" : : "yes" ] && ! $(FORCE-STATIC) {
|
|
#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 : "" ;
|
|
}
|
|
|
|
local prefix = [ option.get "prefix" ] ;
|
|
if $(prefix) {
|
|
prefix = [ path.root $(prefix) [ path.pwd ] ] ;
|
|
prefix = $(prefix)$(GITTAG) ;
|
|
} else {
|
|
prefix = $(TOP)$(GITTAG) ;
|
|
}
|
|
|
|
path-constant PREFIX : $(prefix) ;
|
|
|
|
path-constant BINDIR : [ option.get "bindir" : $(PREFIX)/bin ] ;
|
|
path-constant 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 local p in $(projects) {
|
|
build-project $(p) ;
|
|
}
|
|
}
|
|
|
|
#Only one post build hook is allowed. Allow multiple.
|
|
post-hooks = ;
|
|
rule post-build ( ok ? ) {
|
|
for local r in $(post-hooks) {
|
|
$(r) $(ok) ;
|
|
}
|
|
}
|
|
IMPORT $(__name__) : post-build : : $(__name__).post-build ;
|
|
build-system.set-post-build-hook $(__name__).post-build ;
|
|
rule add-post-hook ( names * ) {
|
|
post-hooks += $(names) ;
|
|
}
|
|
|
|
rule failure-message ( ok ? ) {
|
|
if $(ok) != "ok" {
|
|
local args = [ modules.peek : ARGV ] ;
|
|
local args = $(args:J=" ") ;
|
|
if --debug-configuration in [ modules.peek : ARGV ] {
|
|
echo "The build failed with command line: " ;
|
|
echo " $(args)" ;
|
|
echo "If you need support, attach the full output to your e-mail." ;
|
|
} else {
|
|
echo "The build failed. If you need support, run:" ;
|
|
echo " $(args) --debug-configuration -d2 |gzip >build.log.gz" ;
|
|
echo "then attach build.log.gz to your e-mail." ;
|
|
echo "You MUST do 3 things before sending to the mailing list:" ;
|
|
echo " 1. Subscribe to the mailing list at http://mailman.mit.edu/mailman/listinfo/moses-support" ;
|
|
echo " 2. Attach build.log.gz to your e-mail" ;
|
|
echo " 3. Say what is the EXACT command you executed when you got the error" ;
|
|
}
|
|
echo "ERROR" ;
|
|
} else {
|
|
echo "SUCCESS" ;
|
|
}
|
|
}
|
|
add-post-hook failure-message ;
|
|
|
|
import feature : feature ;
|
|
feature options-to-write : : free ;
|
|
import toolset : flags ;
|
|
flags write-options OPTIONS-TO-WRITE <options-to-write> ;
|
|
actions write-options {
|
|
echo "$(OPTIONS-TO-WRITE)" > $(<) ;
|
|
}
|
|
|
|
#Compare contents of file with current. If they're different, write to the
|
|
#file. This file can then be used with <dependency>$(file) to force
|
|
#recompilation.
|
|
rule update-if-changed ( file current ) {
|
|
if ( ! [ path.exists $(file) ] ) || ( [ _shell "cat $(file)" ] != $(current) ) {
|
|
make $(file) : : $(__name__).write-options : <options-to-write>$(current) ;
|
|
always $(file) ;
|
|
}
|
|
}
|
|
|
|
if [ option.get "sanity-test" : : "yes" ] {
|
|
local current_version = [ modules.peek : JAM_VERSION ] ;
|
|
if ( $(current_version[0]) < 2000 && [ version.check-jam-version 3 1 16 ] ) || [ version.check-jam-version 2011 0 0 ] {
|
|
EXIT "Sane" : 0 ;
|
|
} else {
|
|
EXIT "Bad" : 1 ;
|
|
}
|
|
}
|
|
|
|
#Hack to act like alias in the sense that no lib is built, but only build cpp files once.
|
|
import type ;
|
|
rule fakelib ( name : deps * : requirements * : default-build * : usage-requirements * ) {
|
|
local c-files = ;
|
|
local real-deps = ;
|
|
for local c in $(deps) {
|
|
if [ type.type $(c) ] = CPP {
|
|
c-files += $(c) ;
|
|
} else {
|
|
real-deps += $(c) ;
|
|
}
|
|
}
|
|
for local c in $(c-files) {
|
|
obj $(c:B).o : $(c) $(real-deps) : $(requirements) : $(default-build) : $(usage_requirements) ;
|
|
}
|
|
alias $(name) : $(c-files:B).o $(real-deps) : $(requirements) : $(default-build) : $(usage-requirements) ;
|
|
}
|
|
|
|
use-project /top : . ;
|