From 5724a738b6b5c375e17cc3311a7028d391bb642c Mon Sep 17 00:00:00 2001 From: Robert Izzard <r.izzard@surrey.ac.uk> Date: Mon, 18 Nov 2019 17:02:47 +0800 Subject: [PATCH] clean up meson build: now builds a static library which can be then be used to build the executable and shared library. This reduces the dependency list and speeds up builds because we no longer have to build the object files twice (or worse!). added a meson/pgo.sh script to do profile-guided optimization automatically --- doc/binary_c2.lyx | 331 ++++++++++++++--- meson.build | 675 ++++++++++++++++++++-------------- meson/c_main_sourcefiles.sh | 4 + meson/check_binary_grid2.sh | 15 + meson/list_shared_symbols.sh | 13 + meson/pgo.sh | 114 ++++++ src/perl/scripts2/template.pl | 8 +- src/setup/version.c | 1 - tbse | 15 +- 9 files changed, 837 insertions(+), 339 deletions(-) create mode 100755 meson/c_main_sourcefiles.sh create mode 100755 meson/check_binary_grid2.sh create mode 100755 meson/list_shared_symbols.sh create mode 100755 meson/pgo.sh diff --git a/doc/binary_c2.lyx b/doc/binary_c2.lyx index 126e83e3a..ebf54e588 100644 --- a/doc/binary_c2.lyx +++ b/doc/binary_c2.lyx @@ -3919,6 +3919,91 @@ pip3 install meson \end_inset which should get you the latest version. +\begin_inset Newline newline +\end_inset + + +\begin_inset Newline newline +\end_inset + +Note: +\begin_inset Flex Software +status open + +\begin_layout Plain Layout +emacs +\end_layout + +\end_inset + + users should install the meson-mode. + Go to +\begin_inset CommandInset href +LatexCommand href +target "https://github.com/wentasah/meson-mode" +literal "false" + +\end_inset + + and download +\begin_inset Flex File +status open + +\begin_layout Plain Layout +meson-mode.el +\end_layout + +\end_inset + + to your +\begin_inset Flex File +status open + +\begin_layout Plain Layout +~/.emacs-el +\end_layout + +\end_inset + + directory. + In your +\begin_inset Flex File +status open + +\begin_layout Plain Layout +~/.emacs +\end_layout + +\end_inset + + file add the following. +\begin_inset listings +inline false +status open + +\begin_layout Plain Layout + +; meson support +\end_layout + +\begin_layout Plain Layout + +(load "~/.emacs-el/meson-mode.el") +\end_layout + +\end_inset + +You can edit the +\begin_inset Flex File +status open + +\begin_layout Plain Layout +meson-mode.el +\end_layout + +\end_inset + + to suit your needs: I changed the indentation from 2 to 4, for example. \end_layout \begin_layout Itemize @@ -4092,6 +4177,32 @@ gdb . \end_layout +\begin_layout Itemize +I highly recommend the use of +\begin_inset Flex Software +status open + +\begin_layout Plain Layout + +\emph off +ccache +\end_layout + +\end_inset + + to speed up builds. + You can usually install this as a system package, or see +\begin_inset CommandInset href +LatexCommand href +name "the ccache homepage" +target "https://ccache.dev/" +literal "false" + +\end_inset + +. +\end_layout + \begin_layout Standard By using \emph on @@ -4381,6 +4492,135 @@ unzip the files in the appropriate places. \end_layout +\begin_layout Subsubsection +Set up ccache (optional) +\end_layout + +\begin_layout Standard +If you have +\begin_inset Flex Software +status open + +\begin_layout Plain Layout +ccache +\end_layout + +\end_inset + + installed, you will need to set it up so that it works with precompiled + headers. + To do this, run the following command. +\begin_inset listings +lstparams "language=bash" +inline false +status open + +\begin_layout Plain Layout + +ccache --set-config=sloppiness=pch_defines,time_macros +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +Alternatively, if you are using +\begin_inset Flex Software +status open + +\begin_layout Plain Layout +bash +\end_layout + +\end_inset + + as your shell and +\begin_inset Flex Software +status open + +\begin_layout Plain Layout +ccache +\end_layout + +\end_inset + + is installed in +\begin_inset Flex File +status open + +\begin_layout Plain Layout +binary_c +\end_layout + +\end_inset + + (the standard location in +\begin_inset Flex OS +status open + +\begin_layout Plain Layout +Ubuntu Linux +\end_layout + +\end_inset + +, put the following in your +\begin_inset Flex File +status open + +\begin_layout Plain Layout +.bashrc +\end_layout + +\end_inset + + to have +\begin_inset Flex Software +status open + +\begin_layout Plain Layout +ccache +\end_layout + +\end_inset + + always behave as you wish. +\begin_inset listings +inline false +status open + +\begin_layout Plain Layout + +# use ccache if available +\end_layout + +\begin_layout Plain Layout + +if [[ -d /usr/lib/ccache ]]; then +\end_layout + +\begin_layout Plain Layout + + export PATH=/usr/lib/ccache/:$PATH +\end_layout + +\begin_layout Plain Layout + + export CCACHE_SLOPPINESS=pch_defines,time_macros +\end_layout + +\begin_layout Plain Layout + +fi +\end_layout + +\end_inset + + +\end_layout + \begin_layout Subsubsection Building with Meson \begin_inset CommandInset label @@ -6000,24 +6240,21 @@ tbse \end_inset pgo Profile guided optimization. - This builds -\emph on + This option is deprecated. + Please use the +\begin_inset Flex File +status open + +\begin_layout Plain Layout +meson/pgo.sh +\end_layout -\begin_inset Formula $\binaryc$ \end_inset + script instead (see +\begin_inset space ~ +\end_inset -\emph default - once, runs a number of systems, then rebuilds with extra optimization based - on the profile generated by the runs. - This works for -\emph on -GCC -\emph default - and probably also -\emph on -clang -\emph default . \end_layout @@ -19081,70 +19318,64 @@ tbse <filename> \end_layout \begin_layout Subsection -How to use profile guided optimization (PGO) +How to use profile-guided optimization (PGO) \end_layout \begin_layout Standard -When compiling with -\begin_inset Flex Software -status open - -\begin_layout Plain Layout -gcc -\end_layout - -\end_inset +\begin_inset CommandInset label +LatexCommand label +name "subsec:How-to-use-PGO" -, just run -\begin_inset Newline newline \end_inset -\family typewriter -\series bold - -\begin_inset listings -lstparams "language=bash" -inline false +\begin_inset Flex Software status open \begin_layout Plain Layout - -tbse pgo +Meson \end_layout \end_inset - -\end_layout - -\begin_layout Standard -You may want to change the -\begin_inset Flex Args + supports profile-guided optimization (PGO), and this has been written into + the +\begin_inset Flex File status open \begin_layout Plain Layout -REPEAT +meson/pgo.sh \end_layout \end_inset - variable as defined in -\begin_inset Flex bashscript + script which you can use to test it. + You should just run this, with an optional argument that is the number + of test systems (this defaults to 1000), e.g. +\begin_inset space ~ +\end_inset + +from the +\begin_inset Formula $\binaryc$ +\end_inset + + root directory: +\begin_inset listings +inline false status open \begin_layout Plain Layout -tbse + +./meson/pgo.sh 1000 \end_layout \end_inset -. - It is set to 10000, but if your code is running too slowly, set it to less. + \end_layout \begin_layout Standard -For details see +For details about profile-guided optimization, please see \begin_inset Flex URL status open @@ -19155,11 +19386,7 @@ https://en.wikipedia.org/wiki/Profile-guided_optimization \end_inset - -\end_layout - -\begin_layout Standard -Generally, I find a 5-10% speedup from PGO. + or your compiler's documentation. \end_layout \begin_layout Subsection diff --git a/meson.build b/meson.build index 240f6edc4..acb9198ee 100644 --- a/meson.build +++ b/meson.build @@ -10,7 +10,6 @@ ############################################################ # TODO: # -# automate symlink of libbinary_c.so? # 'gprof'/'gcov' builds # profile-guided optimization # build data_objects in builddir, not in source tree @@ -19,6 +18,12 @@ # ############################################################ # +# See also +# https://github.com/mesonbuild/meson/blob/master/docs/markdown/howtox.md +# as a useful cookbook. +# +############################################################ +# # A typical clean build with gcc and "time make" gives # 95.23user 21.08system 0:34.64elapsed 335%CPU (0avgtext+0avgdata 425420maxresident)k # @@ -28,12 +33,13 @@ ############################################################ # define the binary_c project project( - 'binary_c','c', - version : run_command('sh','-c','meson/binary_c_version.sh').stdout().strip(), - default_options : [ - 'c_std=gnu99', - ] - ) + 'binary_c','c', + version : run_command('sh','-c','meson/binary_c_version.sh').stdout().strip(), + default_options : [ + 'c_std=gnu99', + ] +) +binary_c_version = run_command('sh','-c','meson/binary_c_version.sh').stdout().strip() compiler = meson.get_compiler('c') ############################################################ @@ -58,34 +64,27 @@ git_url = run_command('sh','-c','meson/git_url.sh').stdout().strip() svn_url = run_command('sh','-c','meson/svn_url.sh').stdout().strip() ############################################################ -# default include directories +# default include and library search directories incdirs = [ '.', './src' ] libdirs = [ './src' ] absolute_incdirs = [ binary_c, binary_c_src ] absolute_libdirs = [ ] -############################################################ -# list of libraries with which we should link: libs come -# first and are appended to, postlibs come last. -libs = ['-lc','-lm'] -postlibs = ['-lc','-lm','-ldl'] - ############################################################ # determine whether we're a debug or generic build have_gnu99 = compiler.has_argument('-std=gnu99') have_avx = compiler.has_argument('-mavx') ############################################################ -# default C flags (compiler options) - -# TODO: do not omit frame pointer if profile guided -cflags = ['-fPIC','-DALIGNSIZE=16'] +# default C flags +# +cflags = ['-DALIGNSIZE=16'] if have_gnu99 - cflags += [ '-std=gnu99' ] + cflags += [ '-std=gnu99' ] endif if have_avx and get_option('generic') == false - cflags += [ '-mavx' ] + cflags += [ '-mavx' ] endif ############################################################ @@ -95,45 +94,48 @@ optional_flags = [ ] # generic build if get_option('generic') == true - optional_flags += [ - '-mtune=generic', - ] + optional_flags += [ + '-mtune=generic', + ] else - optional_flags += [ - '-march=native', - '-mtune=native', - ] + optional_flags += [ + '-march=native', + '-mtune=native', + ] endif # accurate mathematical options if get_option('accurate') == true - optional_flags += [ - '-frounding-math', - '-fno-stack-protector', - '-ffloat-store', - '-fno-fast-math' - ] + optional_flags += [ + '-frounding-math', + '-fno-stack-protector', + '-ffloat-store', + '-fno-fast-math' + ] else - optional_flags += [ - '-ffast-math', - '-fno-associative-math', - ] + optional_flags += [ + '-ffast-math', + '-fno-associative-math', + ] endif optional_flags += [ - '-fno-finite-math-only', - '-fsignaling-nans', - '-fomit-frame-pointer', - '-fvisibility=hidden', - ] - + '-fno-finite-math-only', + '-fsignaling-nans', + '-fomit-frame-pointer', + '-fvisibility=hidden', +] + ############################################################ # debug C flags if get_option('buildtype').startswith('debug') - optional_flags += [ '-rdynamic', '-O0' ] + optional_flags += [ '-rdynamic', '-O0' ] endif -# flags that are not strictly required, but that help a lot +############################################################ +# Now go through the optional_flags, and use those that +# are supported by the compiler. +# foreach _flag : optional_flags if compiler.has_argument(_flag) cflags += _flag @@ -145,195 +147,221 @@ endforeach # per-compiler options if compiler.get_id() == 'clang' - # clang flags - cflags += [ '-fbracket-depth=512' ] + # clang flags + cflags += [ '-fbracket-depth=512' ] else - # default to gcc flags - cflags += [] + # default to gcc flags + cflags += [] endif -libs += [] - ############################################################ # system options cflags += '-DCPUFREQ=' + cpufreq if host_machine.system() == 'linux' - # Linux system - cflags += ['-DLINUX', '-DLARGEFILE_SOURCE'] - - # check for perf_event_paranoid - _perf_event = run_command('cat','/proc/sys/kernel/perf_event_paranoid').stdout().strip() - if _perf_event == '1' or _perf_event == '2' - cflags += '-D__HAVE_PERF_EVENTS__' - endif + # Linux system + cflags += ['-DLINUX', '-DLARGEFILE_SOURCE'] endif if compiler.compiles('int main(int argc,char **argv){return 0;}', args : '-m64', name : '64-bit check') - # 64-bit system - cflags += '-D_FILE_OFFSET_BITS=64' + # 64-bit system + cflags += '-D_FILE_OFFSET_BITS=64' else - # assume 32-bit system + # assume 32-bit system endif ############################################################ # version control options if git_revision != '' - _flag = '-DGIT_REVISION="' + git_revision + '"' - cflags += _flag + _flag = '-DGIT_REVISION="' + git_revision + '"' + cflags += _flag endif if svn_revision != '' - _flag = '-DSVN_REVISION="' + svn_revision + '"' - cflags += _flag + _flag = '-DSVN_REVISION="' + svn_revision + '"' + cflags += _flag endif if git_url != '' - _flag = '-DGIT_URL="' + git_url + '"' - cflags += _flag + _flag = '-DGIT_URL="' + git_url + '"' + cflags += _flag endif if svn_url != '' - _flag = '-DSVN_URL="' + svn_url + '"' - cflags += _flag + _flag = '-DSVN_URL="' + svn_url + '"' + cflags += _flag endif ############################################################ -# dependencies that have pkg-config -libgsl_dep = compiler.find_library('gsl',required: true) - +# dependencies are put in the list called dependencies +# +dependencies = [ ] ############################################################ # dependencies that usually have no pkg-config # THESE NEED TO BE SET IN $LIBRARY_PATH (or $LIBPATH on Windoze) # -# required system libraries -libc_dep = compiler.find_library('c', required: true) -libm_dep = compiler.find_library('m', required: true) - -############################################################ -# dependencies -# - -####### -# GSL # -# -# todo : https://mesonbuild.com/Reference-tables.html see "Dependency lookup methods" -if libgsl_dep.found() - cflags += run_command('sh','-c','gsl-config --cflags').stdout().strip().split(' ') - cflags += '-DUSE_GSL' - libs += run_command('sh','-c','gsl-config --libs').stdout().strip().split(' ') - gsl_libdirs = run_command('sh','-c','gsl-config --libs | tr " " "\n"|grep ^-L | tr "\n" " "').stdout().strip().split(' ') - libdirs += gsl_libdirs - incdirs += run_command('sh','-c','gsl-config --prefix').stdout().strip()+'/include' -endif - - -############################# -# required libraries # -# libgsl etc. # -# -foreach libname : ['gsl'] - _dep = compiler.find_library(libname,required:false) +# system libraries : note that libm may not be required +# on some systems (GSL may also specify) +dependencies += [ + compiler.find_library('c', required: true), + compiler.find_library('m', required: false), +] + + +############################################################ +# libraries : required and optional +# +_required_libraries = [ + 'c', + 'gsl', + 'gslcblas', +] +_optional_libraries = [ + 'backtrace', + 'bfd', + 'bsd', + 'iberty', + 'm', # optional on some platforms (gsl probably required is) + 'memoize', + 'rinterpolate', +] +libs = [] # list sent to the compiler +foreach libname : _required_libraries + _dep = compiler.find_library(libname, + required:true) if _dep.found() - cflags += '-D__HAVE_LIB' + libname.to_upper() +'__' - libs += '-l' + libname + cflags += '-D__HAVE_LIB' + libname.to_upper() +'__' + libs += '-l' + libname + + # extras + if libname == 'gsl' + # use gsl-config to find cflags, libraries, etc. + message('Adding GSL-specific flags from gsl-config') + cflags += run_command('sh','-c','gsl-config --cflags').stdout().strip().split(' ') + cflags += '-DUSE_GSL' + libs += run_command('sh','-c','gsl-config --libs').stdout().strip().split(' ') + gsl_libdirs = run_command('sh','-c','gsl-config --libs | tr " " "\n"|grep ^-L | tr "\n" " "').stdout().strip().split(' ') + libdirs += gsl_libdirs + incdirs += run_command('sh','-c','gsl-config --prefix').stdout().strip()+'/include' + endif endif + dependencies += _dep endforeach +# Note : this should work, but does not :( +# +#gsl_dep = dependency( +# 'gsl', +# required : true, +# version : '>=2.4', +# method : 'config-tool', +# ) + ############################# -# optional libraries # -# libbacktrace, libbfd etc. # +# optional libraries +# libbacktrace, libbfd etc. +# (generic builds should not use these) # if get_option('generic') == false - foreach libname : ['bfd','backtrace','bsd','iberty','memoize','rinterpolate'] - _dep = compiler.find_library(libname,required:false) - if _dep.found() - cflags += '-D__HAVE_LIB' + libname.to_upper() +'__' - libs += '-l' + libname - endif - endforeach + foreach libname : _optional_libraries + _dep = compiler.find_library(libname,required:false) + if _dep.found() + cflags += '-D__HAVE_LIB' + libname.to_upper() +'__' + libs += '-l' + libname + endif + endforeach endif + +############################################################ +# features which are converted into preprocessor flags (-D) +# + ########### # drand48 # # if compiler.sizeof('drand48_r', prefix : '#include <stdlib.h>') > 0 - cflags += '-D__HAVE_DRAND48__' + cflags += '-D__HAVE_DRAND48__' endif - + ############ # malloc.h # # if compiler.has_header('malloc.h') - cflags += '-D__HAVE_MALLOC_H__' + cflags += '-D__HAVE_MALLOC_H__' endif ################################# # pkg-config (external command) # # if run_command('pkg-config','--version').returncode() == 0 - cflags += '-D__HAVE_PKG_CONFIG__' + cflags += '-D__HAVE_PKG_CONFIG__' endif ########################### # valgrind (header files) # # if compiler.has_header('valgrind/valgrind.h') - cflags += '-D__HAVE_VALGRIND__' + cflags += '-D__HAVE_VALGRIND__' endif ################### # show_starstruct # # if run_command('sh','-c','meson/make_starstruct.sh').returncode() == 0 - cflags += '-D__SHOW_STARDATA__' + cflags += '-D__SHOW_STARDATA__' endif ################### # diff_starstruct # # if run_command('sh','-c','meson/diff_starstruct.sh').returncode() == 0 - cflags += '-D__DIFF_STARDATA__' + cflags += '-D__DIFF_STARDATA__' endif ######################## # Unsupported features # # if compiler.get_id() != 'gcc' and compiler.get_id() != 'clang' - cflags += '-UBACKTRACE' + cflags += '-UBACKTRACE' endif ############################################################ # make a list of include directories +# We do this so that $HOME/include is searched (e.g. for +# libgsl) +# my_incdirs = [] found = false -foreach idir : [ - homedir + '/include', - '/usr/include', - '/usr/local/include', - ] - inc_arg = idir - _Inc_arg = '-I' + idir - if not found and compiler.has_header('gsl/gsl_blas.h', - args: _Inc_arg) - my_incdirs += [inc_arg] - found = true - endif +_include_search_paths = [ + homedir + '/include', + '/usr/include', + '/usr/local/include', +] +foreach idir : _include_search_paths + inc_arg = idir + _Inc_arg = '-I' + idir + if not found and compiler.has_header('gsl/gsl_blas.h', + args: _Inc_arg) + my_incdirs += [inc_arg] + found = true + endif endforeach -incdirs += [my_incdirs] +incdirs += [ my_incdirs ] ############################################################ # data objects # # list and build them +message('Checking and building data objects') data_objects = run_command('meson/data_object_list_and_build.sh').stdout().strip().split(' ') if get_option('clean_data_objects') == true - run_command('meson/clean_data_objects.sh') + run_command('meson/clean_data_objects.sh') endif ############################################################ @@ -345,17 +373,12 @@ run_command('meson/make_version_macros.pl') # source files # c_sourcefiles = run_command('meson/c_sourcefiles.sh').stdout().strip().split('\n') +c_main_sourcefiles = run_command('meson/c_main_sourcefiles.sh').stdout().strip().split('\n') h_sourcefiles = run_command('meson/h_sourcefiles.sh').stdout().strip().split('\n') -############################################################ -# full list of libraries with which we wish to link -# -libs = libs + postlibs - ############################################################ # extra quoted flags to pass into binary_c # - cflags_with_O = cflags + [ '-O' + get_option('optimization') ] # cflags with -O<n> cflags_quoted = ' '.join(cflags_with_O) # turn to string cflags_quoted = ''.join(cflags_quoted.split('"')) # remove " @@ -370,19 +393,25 @@ libs_quoted = '-DLIBS=' + ''.join(['"', ' '.join(libs),'"']) libs_quoted = '_slash_'.join(libs_quoted.split('/')) # hence a quoted version of the cflags -quoted_cflags_list = [ cflags_quoted, - cc_quoted, - incdirs_quoted, - ld_quoted, - libdirs_quoted, - libs_quoted, - ] +quoted_cflags_list = [ + cflags_quoted, + cc_quoted, + incdirs_quoted, + ld_quoted, + libdirs_quoted, + libs_quoted, +] ############################################################ # compiler warning flags ############################################################ warn_flags = [] -foreach _arg : ['all','format','strict-prototypes','format-signedness'] +foreach _arg : [ + 'all', + 'format', + 'strict-prototypes', + 'format-signedness' +] _warn_arg = '-W' + _arg if compiler.has_argument(_warn_arg) warn_flags += _warn_arg @@ -401,90 +430,137 @@ cflags += warn_flags # its dependencies in a pch.d/gch.d file. This is a bit # complicated, as you will see below. # - -if get_option('usepch') == true - - _opt = '-O' + get_option('optimization') # required for __OPTIMIZE__ - - # normal dep file - _depfile_path = binary_c_src + '/binary_c.h.gch.d' - - # make a list of incdirs each prefixed by -I - _incdirs = [] - foreach _i : absolute_incdirs - _I = '-I' + _i - _incdirs += _I - endforeach - _incdirs += [ '-I.' ] - - # choose your compiler... - if compiler.get_id() == 'clang' - # clang PCH - - _pch = 'binary_c.h.pch' - use_pch_cflags = [ '-include-pch', _pch ] - pch_cflags = [ - _opt, - _incdirs, - ] - pch_sourcefiles = [ _pch ] - pch_post = [ '-o', _pch ] - pch_depfile = '' - - else - # GCC PCH - - _gch = 'binary_c.h.gch' - _gchd = '../src/' + _gch + '.d' - use_pch_cflags = [ ] # -include is not required - pch_cflags = [ _opt, - _incdirs, - '-MT', 'binary_c.h.gch', - '-MMD', - '-MP', - '-MF', _depfile_path, - '-x', 'c-header' - ] - pch_sourcefiles = [ _gch ] - cflags += [ '-fpch-deps', '-fpch-preprocess' ] - pch_post = [ ] - pch_depfile = _gch + '.d' - endif - - - # make cflags for pch build - pch_cflags_array = cflags + pch_cflags - - # append usage flags - cflags += use_pch_cflags - - pch_compiler = compiler.cmd_array() + pch_cflags_array - - precompiled_headers = custom_target( - 'binary_c.h.pch', - build_by_default : true, - input : ['src/binary_c.h'], - output : pch_sourcefiles, - command : [ pch_compiler, '-gdwarf-2', '@INPUT@', pch_post ], - depend_files : [h_sourcefiles], - ) +if get_option('usepch') == true + # get optimization level, required for __OPTIMIZE__ + _opt = '-O' + get_option('optimization') + + # make sure we precompile with fPIC and symbols + _pic = ['-g','-fPIC'] + + # normal dep file + _depfile_path = binary_c_src + '/binary_c.h.gch.d' + + # make a list of incdirs each prefixed by -I + _incdirs = [] + foreach _i : absolute_incdirs + _I = '-I' + _i + _incdirs += _I + endforeach + _incdirs += [ '-I.' ] + + # choose your compiler... + if compiler.get_id() == 'clang' + # clang PCH + + _pch = 'binary_c.h.pch' + use_pch_cflags = [ + '-include-pch', + _pch ] + pch_cflags = [ + _opt, + _pic, + _incdirs, + ] + pch_sourcefiles = [ _pch ] + pch_post = [ '-o', _pch ] + pch_depfile = '' + + else + # GCC PCH + + _gch = 'binary_c.h.gch' + _gchd = '../src/' + _gch + '.d' + use_pch_cflags = [ ] # -include is not required + pch_cflags = [ + _opt, + _pic, + _incdirs, + '-MT', 'binary_c.h.gch', + '-MMD', + '-MP', + '-MF', _depfile_path, + '-x', 'c-header' + ] + pch_sourcefiles = [ _gch ] + cflags += [ + '-fpch-deps', + '-fpch-preprocess' + ] + pch_post = [ ] + pch_depfile = _gch + '.d' + endif + + # make cflags for pch build + pch_cflags_array = cflags + pch_cflags + + # append usage flags + cflags += use_pch_cflags + + # make PCH compiler: this is just the normal compiler with PCH flags + pch_compiler = compiler.cmd_array() + pch_cflags_array + + message('building precompiled headers') + precompiled_headers = custom_target( + 'binary_c.h.pch', + build_by_default : true, + input : ['src/binary_c.h'], + output : pch_sourcefiles, + command : [ + pch_compiler, + '-gdwarf-2', + '@INPUT@', + pch_post + ], + depend_files : [ h_sourcefiles ], + ) else - # disable PCH by removing the files it would have generated - - all_pch_sourcefiles = [ 'binary_c.h.gch', 'binary_c.h.pch' ] - precompiled_headers = custom_target( - 'binary_c.h.pch', - build_by_default : true, - input : ['src/binary_c.h'], - output : all_pch_sourcefiles, - command : [ 'rm', '-f', all_pch_sourcefiles ], - depend_files : [h_sourcefiles], - ) + # disable PCH by removing the files it would have generated + + all_pch_sourcefiles = [ 'binary_c.h.gch', 'binary_c.h.pch' ] + precompiled_headers = custom_target( + 'binary_c.h.pch', + build_by_default : true, + input : [ 'src/binary_c.h' ], + output : all_pch_sourcefiles, + command : [ 'rm', '-f', all_pch_sourcefiles ], + depend_files : [h_sourcefiles], + ) endif +############################################################ +# command to install binary_c in its 'legacy' locations +# (required for binary_grid2) +binary_c_legacy_install_cmd = [ + 'cp','--remove-destination','binary_c','../', + '&&', + 'cp','--remove-destination','libbinary_c.so','../src/', + '&&', + 'echo','libbinary_c.so built with symbols:', + '&&', + '../meson/list_shared_symbols.sh','libbinary_c.so' +] + +############################################################ +# +# Convenience for Rob: try to locate binary_grid2.pm and +# hence touch (and rebuild) it when the shared library is +# rebuild +# +if run_command('sh','-c','meson/check_binary_grid2.sh').returncode() == 0 + binary_grid2_file = run_command( + 'sh', + '-c', + 'meson/check_binary_grid2.sh' + ).stdout().strip() + binary_c_legacy_install_cmd += [ + '&&', + 'touch', + binary_grid2_file + ] +endif ############################################################ # @@ -492,30 +568,72 @@ endif # run: ninja libbinary_c_symlink # libbinary_c_symlink = custom_target( - 'libbinary_c_symlink', - build_by_default: false, - output: [ 'libbinary_c_symlink' ], - command: [ 'sh', '-c', '../meson/symlink_libbinary_c.sh' ], - ) - + 'libbinary_c_symlink', + build_by_default: false, + output: [ 'libbinary_c_symlink' ], + command: [ + 'sh', + '-c', + '../meson/symlink_libbinary_c.sh' + ], +) + + +############################################################ +# +# make binary_c objects +# +# We put the objects in here so they can be shared by +# the executable and library builds. We're not really +# interested in the static library, but we have to call +# this build something. +# +binary_c_objects = build_target( + 'binary_c_objects', + build_by_default: true, + pic: true, + target_type : 'static_library', # pretend we're a static library! + sources : [ + c_sourcefiles, + h_sourcefiles, + precompiled_headers + ], + include_directories: include_directories(incdirs), + dependencies : dependencies, + c_args : [ + cflags, + quoted_cflags_list, + ], + objects : data_objects, + link_args : [ + libs, + ], + ) + ############################################################ # # make shared library # run: ninja libbinary_c.so # binary_c_shared_library = shared_library( - get_option('libname'), - build_by_default : false, - install: true, - sources : [c_sourcefiles, h_sourcefiles, precompiled_headers ], - include_directories: include_directories(incdirs), - dependencies : [ libgsl_dep ], - c_args : [ cflags, quoted_cflags_list, '-fvisibility=hidden' ], - link_args : libs, - objects : data_objects, - ) - - + get_option('libname'), + build_by_default : false, + install: true, + include_directories: include_directories(incdirs), + dependencies : [ dependencies ], + c_args : [ + cflags, + quoted_cflags_list, + '--whole-archive', + ], + link_whole: [ + binary_c_objects, + ], + link_args : [ + libs, + '-fvisibility=hidden', + ], +) ############################################################ # @@ -523,48 +641,37 @@ binary_c_shared_library = shared_library( # run: ninja binary_c # binary_c_executable = executable( - 'binary_c', - install: true, - sources : [ - c_sourcefiles, - h_sourcefiles, - precompiled_headers - ], - include_directories: include_directories(incdirs), - dependencies : [ libgsl_dep ], - c_args : [ - cflags, - quoted_cflags_list - ], - link_args : libs, - objects : data_objects, - ) - - -############################################################ -# -# symlink executable to binary_c directory -# run : ninja binary_c_symlink -# -binary_c_symlink = custom_target('symlink_binary_c', - build_by_default: true, - output: ['binary_c_symlink'], - command: [ 'sh', '-c', '../meson/symlink_binary_c.sh' ], - depends : [ binary_c_executable ], - ) - + 'binary_c', + build_by_default : true, + install: true, + sources : [ + c_main_sourcefiles, + ], + include_directories: include_directories(incdirs), + dependencies : [ dependencies ], + c_args : [ + cflags, + quoted_cflags_list, + ], + objects : data_objects, + link_args : [ + libs, + ], + link_with: [ binary_c_objects ], +) ############################################################ # install both binary_c and libbinary_c.so in their legacy # locations -binary_c_install_legacy = custom_target('binary_c_install_legacy', - build_by_default: false, - output: ['binary_c_install_legacy'], - command: [ - 'cp','--remove-destination','binary_c','../', - '&&', - 'cp','--remove-destination','libbinary_c.so','../src/' - ], - depends : [ binary_c_executable, binary_c_shared_library ], - ) +# +binary_c_install_legacy = custom_target( + 'binary_c_install_legacy', + build_by_default: false, + output: [ 'binary_c_install_legacy' ], + command: binary_c_legacy_install_cmd, + depends : [ + binary_c_executable, + binary_c_shared_library, + ], +) diff --git a/meson/c_main_sourcefiles.sh b/meson/c_main_sourcefiles.sh new file mode 100755 index 000000000..395085b70 --- /dev/null +++ b/meson/c_main_sourcefiles.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +# list binary_c C source files for meson +ls -1 src/*.c src/*/*.c |grep main.c diff --git a/meson/check_binary_grid2.sh b/meson/check_binary_grid2.sh new file mode 100755 index 000000000..fb0c695f2 --- /dev/null +++ b/meson/check_binary_grid2.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +# test if Rob's binary_grid2.pm exists +# +# if so, echo its path and return 0 +# +# otherwise, return 1 +FILE="$HOME/progs/perl/modules/astro/binary_grid/lib/binary_grid2.pm" +if [ -f $FILE ]; then + echo $FILE + exit 0 +else + exit 1 +fi + diff --git a/meson/list_shared_symbols.sh b/meson/list_shared_symbols.sh new file mode 100755 index 000000000..b9c524948 --- /dev/null +++ b/meson/list_shared_symbols.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# list shared symbols in the library (file name passed in) +SOFILE=$1 + +# red +echo -e "\e[31m" + +nm -CD -f p $SOFILE | awk '{if ($2 == "T"){print $1}}' | grep -v _fini|grep -v _init | tr "\n" " " + +#reset +echo -e "\e[0m" + diff --git a/meson/pgo.sh b/meson/pgo.sh new file mode 100755 index 000000000..50b9960d4 --- /dev/null +++ b/meson/pgo.sh @@ -0,0 +1,114 @@ +#!/bin/bash + +# script to do PGO with Meson + + +# set defaults +BUILDDIR="builddir" +N=$1 +: ${N:="1000"} +NCORES=`cat /proc/cpuinfo |grep -i Processor | wc -l` +: ${NCORES:="1"} +TMP="/tmp/" +NCORES1=$((NCORES - 1)) +REPEAT_PER_CORE=$(($N/$NCORES)) +SLEEP=0 +MESON=meson +NINJA=ninja + +# where to redirect stderr, stdout on meson and ninja calls +MESON_STDERR=/dev/stderr +MESON_STDOUT=/dev/null +NINJA_STDERR=/dev/stderr +NINJA_STDOUT=/dev/null + +# tbse command +TBSE="./tbse" +WARMUP_SECS=0 +COMMAND1="random_systems 1 repeat $REPEAT_PER_CORE warmup_cpu $WARMUP_SECS" + +# status message +echo "Using Meson to build binary_c with Profile Guided Optimization (PGO) on $N systems across $NCORES cores" + +# function to kill child processes +KillChildren() { + local pid="${1}" + local self="${2:-false}" + if children="$(pgrep -P "$pid")"; then + for child in $children; do + KillChildren "$child" true + done + fi + + if [ "$self" == true ]; then + #kill -s SIGTERM "$pid" || (sleep 10 && kill -9 "$pid" &) + kill -9 "$pid" + fi +} + +# kill children on exit +trap '[ -n "$(jobs -pr)" ] && KillChildren $$' INT QUIT TERM EXIT + +############################################################ +# first build: use builddir if already avaialble +echo "Configure meson for PGO build 1" +if [ -d $BUILDDIR ] ; then + meson configure $BUILDDIR -Db_pgo=generate > $MESON_STDOUT 2> $MESON_STDERR +else + meson $BUILDDIR -Db_pgo=generate > $MESON_STDOUT 2> $MESON_STDERR +fi +echo "Build (1) with ninja" +#ninja -C $BUILDDIR > $NINJA_STDOUT 2> $NINJA_STDERR + + + +############################################################ +# run and filter to files +START=`date +%s%N` +echo "Running binary_c" +for i in `seq 0 $NCORES1`; do + echo "Launch tbse on core $i" + taskset -c $i $TBSE $COMMAND1 | grep At | awk '{print substr($0, index($0,$5))}' > /tmp/binary_c_pgo.$i & + sleep $SLEEP +done +wait +END=`date +%s%N` +PGO1_DURATION=$(echo "(0.000000001*($END - $START))"|bc) + +############################################################ +# rebuild +echo "Configure meson for PGO build 2" +meson configure $BUILDDIR -Db_pgo=use > $MESON_STDOUT 2> $MESON_STDERR +echo "Build (2) with ninja" +ninja -C $BUILDDIR > $NINJA_STDOUT 2> $NINJA_STDERR + +# remove trap +trap - INT QUIT TERM EXIT + +############################################################ +# rerun + +# kill children on exit +trap '[ -n "$(jobs -pr)" ] && KillChildren $$' INT QUIT TERM EXIT + +START=`date +%s%N` +echo "Running binary_c" +for i in `seq 0 $NCORES1`; do + env FIRST_TBSE="warmup_cpu $WARMUP_SECS" taskset -c $i $TBSE /tmp/binary_c_pgo.$i 2>&1 >/dev/null & + sleep $SLEEP +done +wait +END=`date +%s%N` +PGO2_DURATION=$(echo "(0.000000001*($END - $START))"|bc) + +# remove trap +trap - INT QUIT TERM EXIT + +echo "Run 1 (without PGO) took : $PGO1_DURATION s" +echo "Run 2 ( with PGO) took : $PGO2_DURATION s" + +# final speedup % +echo -n "Profile guided optimization speedup is " +echo -n $(echo "(100.0*($PGO1_DURATION-$PGO2_DURATION)/$PGO1_DURATION)"|bc) +echo "%" +exit diff --git a/src/perl/scripts2/template.pl b/src/perl/scripts2/template.pl index 5a24038f5..e457dc4df 100755 --- a/src/perl/scripts2/template.pl +++ b/src/perl/scripts2/template.pl @@ -102,7 +102,12 @@ $population->set( # stardata->star[0].mass, # stardata->model.probability, # stardata->model.dt); -# ' + # ' + + + flexigrid => { + 'grid type' => 'monte carlo' + } ); ############################################################ @@ -135,6 +140,7 @@ if($duplicity == 0) 'precode' =>'$m1=exp($lnm1);', 'probdist' =>'Kroupa2001($m1)*$m1', 'dphasevol' =>'$dlnm1', + 'gridtype' =>'monte carlo', ); } elsif($duplicity == 1) diff --git a/src/setup/version.c b/src/setup/version.c index 6d2195f03..e28a53fb9 100644 --- a/src/setup/version.c +++ b/src/setup/version.c @@ -760,7 +760,6 @@ void version(struct stardata_t * RESTRICT const stardata) Macrotest(__APPLE__); Macrotest(__arm__); Macrotest(__i386__); - Macrotest(__HAVE_PERF_EVENTS__); #ifdef ALIGNSIZE Printf("Memory is aligned to %d bytes (set in ALIGNSIZE)\n",ALIGNSIZE); #else diff --git a/tbse b/tbse index f1ec1c107..8866bff0f 100755 --- a/tbse +++ b/tbse @@ -2366,7 +2366,7 @@ then ARGS=$(echo $ARGS | sed -e s/At\ 20[0-9][0-9]-[0-9][0-9]-[0-9][0-9]\ [0-9][0-9]\:[0-9][0-9]\:[0-9][0-9]\ \:\ //) # run binary_c - $ARGS_PREFIX $DEFAULT_ARGS $ARGS $ARGS_POSTFIX $@ + $ARGS_PREFIX $DEFAULT_ARGS $ARGS $ARGS_POSTFIX $@ $FIRST_TBSE ERROR=$? # save return code and exit if non-zero if (($ERROR != 0)); then @@ -2376,6 +2376,10 @@ then echo exit $ERROR fi + + if [[ ! -z $FIRST_TBSE ]]; then + FIRST_TBSE="" + fi fi done < <(grep -v \# $argfile ) done @@ -2409,6 +2413,15 @@ fi if [ "$RUNMODE" == "pgo" ]; then + echo "Profile-guided optimization (PGO) through tbse has been deprecated : please use Meson to do pgo. A bash script to do this (meson/pgo.sh), run with as + +./meson/pgo.sh <N> + +where N is the number of systems to run, per CPU core, in a timing test. + +" + exit + # profile-guided optimisation build: this option # configures, builds, runs, rebuilds and reruns bonnfires # so that it uses profile-guided optimisation, i.e. -- GitLab