mirror of
https://github.com/moses-smt/mosesdecoder.git
synced 2024-09-11 19:27:11 +03:00
349 lines
12 KiB
Plaintext
349 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 ;
|
|
}
|
|
}
|
|
|
|
rule shell_or_die ( cmd ) {
|
|
local ret = [ SHELL $(cmd) : exit-status ] ;
|
|
if $(ret[2]) != 0 {
|
|
exit $(cmd) failed : 1 ;
|
|
}
|
|
return [ trim-nl $(ret[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 * ) {
|
|
lib boost_$(name)_static : $(deps) : $(boost-search) <name>boost_$(name)$(boost-lib-version) <link>static ;
|
|
lib boost_$(name)_shared : $(deps) : $(boost-search) <name>boost_$(name)$(boost-lib-version) <link>shared : : <define>BOOST_$(macro) ;
|
|
|
|
alias boost_$(name)_default : $(deps) : <link>static:<source>boost_$(name)_static <link>shared:<source>boost_$(name)_shared ;
|
|
|
|
alias boost_$(name)_static_works : $(deps) : [ check-target-builds empty_test_shared "Shared Boost" : <source>boost_$(name)_default : <source>boost_$(name)_static ] ;
|
|
alias boost_$(name) : $(deps) : [ check-target-builds empty_test_static "Static Boost" : <source>boost_$(name)_static_works : <source>boost_$(name)_shared ] ;
|
|
}
|
|
|
|
#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 = "" ;
|
|
}
|
|
|
|
#Crazy amount of testing to make sure that BOOST_TEST_DYN_LINK is defined properly.
|
|
lib boost_unit_test_framework_static_test : : $(boost-search) <name>boost_unit_test_framework$(boost-lib-version) <link>static ;
|
|
obj empty_test_static.o : jam-files/empty_test_main.cc boost_unit_test_framework_static_test : $(boost-include) ;
|
|
exe empty_test_static : empty_test_static.o boost_unit_test_framework_static_test ;
|
|
|
|
lib boost_unit_test_framework_shared_test : : $(boost-search) <name>boost_unit_test_framework$(boost-lib-version) <link>shared : : <define>BOOST_TEST_DYN_LINK ;
|
|
obj empty_test_shared.o : jam-files/empty_test_main.cc boost_unit_test_framework_shared_test : $(boost-include) ;
|
|
exe empty_test_shared : empty_test_shared.o boost_unit_test_framework_shared_test ;
|
|
|
|
explicit empty_test_static.o empty_test_static empty_test_shared.o empty_test_shared ;
|
|
|
|
|
|
#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 iostreams IOSTREAMS_DYN_LINK ;
|
|
boost-lib filesystem FILE_SYSTEM_DYN_LINK ;
|
|
boost-lib unit_test_framework TEST_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 : . ;
|