From 62948308b6b9080d928281c9720b9f95e403a1af Mon Sep 17 00:00:00 2001 From: Alex Lin Date: Wed, 13 Mar 2019 16:17:08 -0500 Subject: [PATCH 1/7] Adding back a lost capability, but better this time. The user can now specify a python module name where the class and functions will be visible in python. With care the user can mimic the C++ namespaces their models reside in, but it isn't perfect nor automatic. It's still pretty neat. --- libexec/trick/make_makefile_swig | 80 +++++++++++++++++-- libexec/trick/pm/html.pm | 2 +- .../RUN_test/unit_test.py | 41 ++++++++++ test/SIM_python_namespace/S_define | 26 ++++++ test/SIM_python_namespace/S_overrides.mk | 4 + test/SIM_python_namespace/models/BarFood.hh | 33 ++++++++ test/SIM_python_namespace/models/FooFood.hh | 33 ++++++++ .../models/FooInnerFood.hh | 31 +++++++ test/makefile | 1 + 9 files changed, 242 insertions(+), 9 deletions(-) create mode 100644 test/SIM_python_namespace/RUN_test/unit_test.py create mode 100644 test/SIM_python_namespace/S_define create mode 100644 test/SIM_python_namespace/S_overrides.mk create mode 100644 test/SIM_python_namespace/models/BarFood.hh create mode 100644 test/SIM_python_namespace/models/FooFood.hh create mode 100644 test/SIM_python_namespace/models/FooInnerFood.hh diff --git a/libexec/trick/make_makefile_swig b/libexec/trick/make_makefile_swig index 364d9d40..a11b13b0 100755 --- a/libexec/trick/make_makefile_swig +++ b/libexec/trick/make_makefile_swig @@ -19,6 +19,9 @@ my @files_to_process ; my @ext_lib_files ; my %md5s ; my $verbose_build = exists($ENV{'TRICK_VERBOSE_BUILD'}) ; +my %trick_headers ; +my %python_modules ; +my %python_module_dirs ; sub get_paths { my @paths = split /:/ , $ENV{$_[0]} ; @@ -140,9 +143,21 @@ sub write_makefile_swig_deps() { close DEPENDENCIES_FILE ; } +sub get_trick_headers() { + foreach my $f ( @files_to_process, @ext_lib_files) { + my %trick_header = extract_trick_header( $f, do { local( @ARGV, $/ ) = $f ; <> }, 0, 0 ) ; + if ( exists $trick_header{python_module} ) { + $trick_headers{$f}{python_module} = $trick_header{python_module}; + ($trick_headers{$f}{python_module_dir} = $trick_header{python_module}) =~ s/\./\//g; + $python_modules{$trick_headers{$f}{python_module}} = 1; + $python_module_dirs{$trick_headers{$f}{python_module_dir}} = 1; + } + $trick_headers{$f}{swig} = $trick_header{swig} if ( exists $trick_header{swig} ); + } +} + sub has_swig_no($) { - my %trick_header = extract_trick_header( $_[0], do { local( @ARGV, $/ ) = $_[0] ; <> }, 0, 0 ) ; - my $result = $trick_header{swig} =~ /^NO$/i ; + my $result = $trick_headers{$_[0]}{swig} =~ /^NO$/i ; print "SWIG Skip SWIG: (NO): $_[0]\n" if $verbose_build and $result ; return $result ; } @@ -204,10 +219,25 @@ all: \$(TRICK_FIXED_PYTHON) SWIG_I =" ; foreach my $file ( @files_to_process ) { - (my $swig_file = $file) =~ s/\.[^.]*$/_py.i/ ; - print MAKEFILE " \\\n build$swig_file" ; - $swig_file =~ s/i$/o/ ; - print PY_LINK_LIST "build$swig_file\n" ; + if ( !exists $trick_headers{$file}{python_module_dir} ) { + (my $swig_file = $file) =~ s/\.[^.]*$/_py.i/ ; + print MAKEFILE " \\\n build$swig_file" ; + $swig_file =~ s/i$/o/ ; + print PY_LINK_LIST "build$swig_file\n" ; + } + } + + print MAKEFILE " + +SWIG_I_CUSTOM_OUTDIR =" ; + + foreach my $file ( @files_to_process ) { + if ( exists $trick_headers{$file}{python_module_dir} ) { + (my $swig_file = $file) =~ s/\.[^.]*$/_py.i/ ; + print MAKEFILE " \\\n build$swig_file" ; + $swig_file =~ s/i$/o/ ; + print PY_LINK_LIST "build$swig_file\n" ; + } } print MAKEFILE " @@ -234,9 +264,24 @@ SWIG_SRC = \$(subst .i,.cpp,\$(SWIG_I)) $swig_src_dir/top.cpp \t\@echo \$(SWIG) \$(TRICK_INCLUDE) \$(TRICK_DEFINES) \$(TRICK_VERSIONS) \$(TRICK_SWIG_FLAGS) -c++ -python -includeall -ignoremissing -w201,303,325,362,389,401,451 -outdir trick -o \$@ \$< >> \$(MAKE_OUT) \t\$(ECHO_CMD)\$(SWIG) \$(TRICK_INCLUDE) \$(TRICK_DEFINES) \$(TRICK_VERSIONS) \$(TRICK_SWIG_FLAGS) -c++ -python -includeall -ignoremissing -w201,303,325,362,389,401,451 -outdir trick -o \$@ \$< 2>&1 | \$(TEE) -a \$(MAKE_OUT) ; exit \$\${PIPESTATUS[0]} +SWIG_SRC_CUSTOM_OUTDIR = \$(subst .i,.cpp,\$(SWIG_I_CUSTOM_OUTDIR))\n" ; + + foreach my $file ( @files_to_process ) { + if ( exists $trick_headers{$file}{python_module_dir} ) { + (my $swig_file = $file) =~ s/\.[^.]*$/_py.i/ ; + (my $cpp_file = $file) =~ s/\.[^.]*$/_py.cpp/ ; + print MAKEFILE " +build$cpp_file : build$swig_file | trick/$trick_headers{$file}{python_module_dir} +\t\$(PRINT_SWIG) +\t\@echo \$(SWIG) \$(TRICK_INCLUDE) \$(TRICK_DEFINES) \$(TRICK_VERSIONS) \$(TRICK_SWIG_FLAGS) -c++ -python -includeall -ignoremissing -w201,303,325,362,389,401,451 -outdir trick/$trick_headers{$file}{python_module_dir} -o \$@ \$< >> \$(MAKE_OUT) +\t\$(ECHO_CMD)\$(SWIG) \$(TRICK_INCLUDE) \$(TRICK_DEFINES) \$(TRICK_VERSIONS) \$(TRICK_SWIG_FLAGS) -c++ -python -includeall -ignoremissing -w201,303,325,362,389,401,451 -outdir trick/$trick_headers{$file}{python_module_dir} -o \$@ \$< 2>&1 | \$(TEE) -a \$(MAKE_OUT) ; exit \$\${PIPESTATUS[0]}\n"; + } + } + + print MAKEFILE " # SWIG_OBJECTS ================================================================= -SWIG_OBJECTS = \$(subst .cpp,.o,\$(SWIG_SRC)) $swig_src_dir/init_swig_modules.o +SWIG_OBJECTS = \$(subst .cpp,.o,\$(SWIG_SRC)) \$(subst .cpp,.o,\$(SWIG_SRC_CUSTOM_OUTDIR)) $swig_src_dir/init_swig_modules.o \$(SWIG_OBJECTS): %.o: %.cpp \t\$(PRINT_COMPILE_SWIG) @@ -323,6 +368,9 @@ LINK_LISTS += \$(LD_FILELIST)build/py_link_list print INITFILE "import sys\n" ; print INITFILE "import os\n" ; print INITFILE "sys.path.append(os.getcwd() + \"/trick\")\n" ; + foreach my $dir ( keys %python_module_dirs ) { + print INITFILE "sys.path.append(os.getcwd() + \"/trick/$dir\")\n" ; + } print INITFILE "\n" ; print INITFILE "import _sim_services\n" ; @@ -335,12 +383,16 @@ LINK_LISTS += \$(LD_FILELIST)build/py_link_list foreach $f ( @files_to_process, @ext_lib_files ) { print INITFILE "# $f\n" ; - print INITFILE "import _m$md5s{$f}\n" ; print INITFILE "from m$md5s{$f} import *\n" ; print INITFILE "combine_cvars(all_cvars, cvar)\n" ; print INITFILE "cvar = None\n\n" ; } + foreach my $mod ( keys %python_modules ) { + print INITFILE "import trick.$mod\n" ; + } + + print INITFILE "\n" ; print INITFILE "# S_source.hh\n" ; print INITFILE "import _m${s_source_md5}\n" ; print INITFILE "from m${s_source_md5} import *\n\n" ; @@ -357,6 +409,17 @@ LINK_LISTS += \$(LD_FILELIST)build/py_link_list print INITFILE "cvar = all_cvars\n\n" ; close INITFILE ; + foreach my $dir ( keys %python_module_dirs ) { + system("mkdir -p trick/$dir"); + open MODULE_INITFILE, ">trick/$dir/__init__.py"; + foreach my $file ( @files_to_process ) { + if ( exists $trick_headers{$file}{python_module_dir} and $trick_headers{$file}{python_module_dir} eq $dir ) { + print MODULE_INITFILE "from m$md5s{$file} import *\n" ; + } + } + close MODULE_INITFILE; + } + return ; } @@ -366,6 +429,7 @@ LINK_LISTS += \$(LD_FILELIST)build/py_link_list read_files_to_process() ; write_makefile_swig_deps() ; +get_trick_headers() ; # Remove SWIG: (NO) files, but not before they're written to the dependency file. # If SWIG: (NO) is removed, Makefile_swig needs to be regenerated. purge_swig_no_files() ; diff --git a/libexec/trick/pm/html.pm b/libexec/trick/pm/html.pm index b4e5f326..86dac2b1 100644 --- a/libexec/trick/pm/html.pm +++ b/libexec/trick/pm/html.pm @@ -31,7 +31,7 @@ sub extract_trick_header($$$$) { $header{icg_ignore} = $2 if $trick_header =~ /ICG[ _]IGNORE[ _]TYPE(S)?:[^(]*(.*?)\)([A-Z _\t\n\r]+:|[ \t\n\r]*$)/si ; $header{swig} = $1 if $trick_header =~ /SWIG:[^(]*\((.*?)\)([A-Z _\t\n\r]+:|[ \t\n\r]*$)/si ; $header{default_data} = $1 if $trick_header =~ /DEFAULT[ _]DATA:[^(]*(.*?)\)([A-Z _\t\n\r]+:|[ \t\n\r]*$)/si ; - $header{python_module} = $1 if $trick_header =~ /PYTHON[ _]MODULE:[^(]*(.*?)\)([A-Z _\t\n\r]+:|[ \t\n\r]*$)/si ; + $header{python_module} = $1 if $trick_header =~ /PYTHON[ _]MODULE:[^(]*\((.*?)\)([A-Z _\t\n\r]+:|[ \t\n\r]*$)/si ; $header{programmers} = $1 if $trick_header =~ /PROGRAMMERS:[^(]*(.*?)\)([A-Z _\t\n\r]+:|[ \t\n\r]*$)/si ; $header{language} = $1 if $trick_header =~ /LANGUAGE:[^(]*(.*?)\)([A-Z _\t\n\r]+:|[ \t\n\r]*$)/si ; diff --git a/test/SIM_python_namespace/RUN_test/unit_test.py b/test/SIM_python_namespace/RUN_test/unit_test.py new file mode 100644 index 00000000..55ddb85b --- /dev/null +++ b/test/SIM_python_namespace/RUN_test/unit_test.py @@ -0,0 +1,41 @@ + +from trick.unit_test import * + +def main(): + trick.stop(1.0) + trick_utest.unit_tests.enable() + trick_utest.unit_tests.set_file_name( os.getenv("TRICK_HOME") + "/trick_test/SIM_python_namespace.xml" ) + trick_utest.unit_tests.set_test_name( "PythonNamespace" ) + test_suite = "python_namespace" + + # normal class methods from S_define + ball.foo_food.print_me() + ball.foo_inner_food.print_me() + ball.bar_food.print_me() + print + + # new class from Foo.Food + food = trick.Foo.Food() + food.print_me() + TRICK_EXPECT_EQ( food.fast , 0, test_suite , "first level python namespace" ) + food.fast = trick.Foo.Burger + TRICK_EXPECT_EQ( food.fast , 2, test_suite , "first level python namespace" ) + + # new class from Foo.Food.Inner + foodinner = trick.Foo.Inner.Food() + foodinner.print_me() + TRICK_EXPECT_EQ( foodinner.fast , 1, test_suite , "second level python namespace" ) + foodinner.fast = trick.Foo.Inner.Burger + TRICK_EXPECT_EQ( foodinner.fast , 0, test_suite , "second level python namespace" ) + + # new class from Foo.Food.Inner + bar = trick.Bar.Food() + bar.print_me() + TRICK_EXPECT_EQ( bar.fast , 2, test_suite , "another first level python namespace" ) + bar.fast = trick.Bar.Burger + TRICK_EXPECT_EQ( bar.fast , 1, test_suite , "another first level python namespace" ) + +if __name__ == "__main__": + main() + + diff --git a/test/SIM_python_namespace/S_define b/test/SIM_python_namespace/S_define new file mode 100644 index 00000000..cceef8c7 --- /dev/null +++ b/test/SIM_python_namespace/S_define @@ -0,0 +1,26 @@ +/************************TRICK HEADER************************* +PURPOSE: + (blah blah blah) +*************************************************************/ + +#include "sim_objects/default_trick_sys.sm" + +##include "FooFood.hh" +##include "FooInnerFood.hh" +##include "BarFood.hh" + +class SimObj : public Trick::SimObject { + + public: + Foo::Food foo_food ; + Foo::Inner::Food foo_inner_food ; + Bar::Food bar_food ; + + /** Constructor to add the jobs */ + SimObj() { + } +} ; + +// Instantiations +SimObj ball ; + diff --git a/test/SIM_python_namespace/S_overrides.mk b/test/SIM_python_namespace/S_overrides.mk new file mode 100644 index 00000000..27536a3b --- /dev/null +++ b/test/SIM_python_namespace/S_overrides.mk @@ -0,0 +1,4 @@ + +TRICK_CFLAGS += -I./models +TRICK_CXXFLAGS += -I./models + diff --git a/test/SIM_python_namespace/models/BarFood.hh b/test/SIM_python_namespace/models/BarFood.hh new file mode 100644 index 00000000..9947d31d --- /dev/null +++ b/test/SIM_python_namespace/models/BarFood.hh @@ -0,0 +1,33 @@ +/** +@file + +@verbatim +PURPOSE: (Namespace Test) +PYTHON_MODULE: (Bar) +@endverbatim +*******************************************************************************/ + +#ifndef BARFOOD_HH +#define BARFOOD_HH + +#include + +namespace Bar { + +enum Fast { + Pizza, + Burger, + Taco +}; + +class Food { + public: + Food() : fast(Taco) {} + void print_me() { std::cout << "Bar::Food::print_me!" << std::endl; } + Fast fast; +}; + +} + +#endif /* _BALL_HH_ */ + diff --git a/test/SIM_python_namespace/models/FooFood.hh b/test/SIM_python_namespace/models/FooFood.hh new file mode 100644 index 00000000..2502848a --- /dev/null +++ b/test/SIM_python_namespace/models/FooFood.hh @@ -0,0 +1,33 @@ +/** +@file + +@verbatim +PURPOSE: (Namespace Test) +PYTHON_MODULE: (Foo) +@endverbatim +*******************************************************************************/ + +#ifndef FOOFOOD_HH +#define FOOFOOD_HH + +#include + +namespace Foo { + +enum Fast { + Taco, + Pizza, + Burger +}; + +class Food { + public: + Food() : fast(Taco) {} + void print_me() { std::cout << "Foo::Food::print_me!" << std::endl; } + Fast fast; +}; + +} + +#endif /* _BALL_HH_ */ + diff --git a/test/SIM_python_namespace/models/FooInnerFood.hh b/test/SIM_python_namespace/models/FooInnerFood.hh new file mode 100644 index 00000000..1e0b1b02 --- /dev/null +++ b/test/SIM_python_namespace/models/FooInnerFood.hh @@ -0,0 +1,31 @@ +/** +@file + +@verbatim +PURPOSE: (Namespace Test) +PYTHON_MODULE: (Foo.Inner) +@endverbatim +*******************************************************************************/ + +#ifndef FOOINNERFOOD_HH +#define FOOINNERFOOD_HH + +namespace Foo { + namespace Inner { + enum Fast { + Burger, + Taco, + Pizza + }; + + class Food { + public: + Food() : fast(Taco) {} + void print_me() { std::cout << "Foo::Inner::Food::print_me!" << std::endl; } + Fast fast; + }; + } +} + +#endif /* _BALL_HH_ */ + diff --git a/test/makefile b/test/makefile index 13326e08..c110a529 100644 --- a/test/makefile +++ b/test/makefile @@ -5,6 +5,7 @@ export TRICK_HOST_CPU := $(shell $(TRICK_HOME)/bin/trick-gte TRICK_HOST_CPU) COMPILE_DIRS = \ SIM_demo_sdefine \ SIM_events \ + SIM_python_namespace \ SIM_rti \ SIM_stls \ SIM_test_dp \ From 41f151f2ee8535a8291b183ac281e8d24542ff34 Mon Sep 17 00:00:00 2001 From: Alex Lin Date: Thu, 14 Mar 2019 09:33:50 -0500 Subject: [PATCH 2/7] Adding doxygen style python module desgnation. Adding another file to example that shows 2 files in same namespace. --- libexec/trick/pm/html.pm | 3 ++ .../RUN_test/unit_test.py | 8 +++++ test/SIM_python_namespace/S_define | 2 ++ .../models/FooYummyFood.hh | 33 +++++++++++++++++++ 4 files changed, 46 insertions(+) create mode 100644 test/SIM_python_namespace/models/FooYummyFood.hh diff --git a/libexec/trick/pm/html.pm b/libexec/trick/pm/html.pm index 86dac2b1..a6da5c62 100644 --- a/libexec/trick/pm/html.pm +++ b/libexec/trick/pm/html.pm @@ -55,6 +55,9 @@ sub extract_trick_header($$$$) { # save doxygen style trick_lib_dependency fields in field = liblist. $header{liblist} = [@lib_list] ; } + if ( $contents =~ /(?:@|\\)python_module\s*{\s*(.*?)\s*}/) { + $header{python_module} = $1; + } $header{language} = "CPP" if ( $header{language} =~ /c[p\+]+/i ) ; diff --git a/test/SIM_python_namespace/RUN_test/unit_test.py b/test/SIM_python_namespace/RUN_test/unit_test.py index 55ddb85b..b50e2da3 100644 --- a/test/SIM_python_namespace/RUN_test/unit_test.py +++ b/test/SIM_python_namespace/RUN_test/unit_test.py @@ -12,6 +12,7 @@ def main(): ball.foo_food.print_me() ball.foo_inner_food.print_me() ball.bar_food.print_me() + ball.foo_yummyfood.print_me() print # new class from Foo.Food @@ -35,6 +36,13 @@ def main(): bar.fast = trick.Bar.Burger TRICK_EXPECT_EQ( bar.fast , 1, test_suite , "another first level python namespace" ) + # new class from Foo.Food.Inner + yummy = trick.Foo.YummyFood() + yummy.print_me() + TRICK_EXPECT_EQ( yummy.yummy , 1, test_suite , "additional file in same namespace" ) + yummy.yummy = trick.Foo.Doughnuts + TRICK_EXPECT_EQ( yummy.yummy , 2, test_suite , "additional file in same namespace" ) + if __name__ == "__main__": main() diff --git a/test/SIM_python_namespace/S_define b/test/SIM_python_namespace/S_define index cceef8c7..ff42c34c 100644 --- a/test/SIM_python_namespace/S_define +++ b/test/SIM_python_namespace/S_define @@ -8,6 +8,7 @@ PURPOSE: ##include "FooFood.hh" ##include "FooInnerFood.hh" ##include "BarFood.hh" +##include "FooYummyFood.hh" class SimObj : public Trick::SimObject { @@ -15,6 +16,7 @@ class SimObj : public Trick::SimObject { Foo::Food foo_food ; Foo::Inner::Food foo_inner_food ; Bar::Food bar_food ; + Foo::YummyFood foo_yummyfood ; /** Constructor to add the jobs */ SimObj() { diff --git a/test/SIM_python_namespace/models/FooYummyFood.hh b/test/SIM_python_namespace/models/FooYummyFood.hh new file mode 100644 index 00000000..8959b969 --- /dev/null +++ b/test/SIM_python_namespace/models/FooYummyFood.hh @@ -0,0 +1,33 @@ +/** +@file + +@verbatim +PURPOSE: (Namespace Test) +PYTHON_MODULE: (Foo) +@endverbatim +*******************************************************************************/ + +#ifndef FOOYUMMYFOOD_HH +#define FOOYUMMYFOOD_HH + +#include + +namespace Foo { + +enum Yummy { + Butter, + Bacon, + Doughnuts +}; + +class YummyFood { + public: + YummyFood() : yummy(Bacon) {} + void print_me() { std::cout << "Foo::YummyFood::print_me!" << std::endl; } + Yummy yummy; +}; + +} + +#endif /* _BALL_HH_ */ + From 787f2c7dc21d85e7df4b49d0553446ab4fc73934 Mon Sep 17 00:00:00 2001 From: Jose Perez Date: Wed, 20 Mar 2019 15:32:11 -0500 Subject: [PATCH 3/7] Support Shared and Static library. Optionally package trickified generated code and source code in to one library. --- share/trick/makefiles/trickify.mk | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/share/trick/makefiles/trickify.mk b/share/trick/makefiles/trickify.mk index 9fd586f9..1678d6b2 100644 --- a/share/trick/makefiles/trickify.mk +++ b/share/trick/makefiles/trickify.mk @@ -92,6 +92,15 @@ TRICK_CXXFLAGS += $(TRICKIFY_CXX_FLAGS) # Ensure we can process all headers TRICK_EXT_LIB_DIRS := +# Trick library build type, defaulted to PLO +# PLO - Partially-linked object library +# STATIC - Static library +# SHARED - Dynamic shared library +TRICK_LIB_BUILD_TYPE ?= PLO + +# Add project source objects to trickified library. +SRC_OBJS ?= + # When given a library, the linker will only link in objects that are known to # be needed at link time. However, Trick uses dlsym to dynamically load the # objects we'll be creating here. It cannot be known which objects will be @@ -106,9 +115,15 @@ TRICK_EXT_LIB_DIRS := # change infrequently. Moreover, the methods for force-linking a library differ # between Linux and Mac, so obviating the need for it simplifies a Trickified # project's user-facing makefile. -$(TRICKIFY_OBJECT_NAME): $(SWIG_OBJECTS) $(IO_OBJECTS) | $(dir $(TRICKIFY_OBJECT_NAME)) +$(TRICKIFY_OBJECT_NAME): $(SWIG_OBJECTS) $(IO_OBJECTS) $(SRC_OBJS) | $(dir $(TRICKIFY_OBJECT_NAME)) $(info $(call COLOR,Linking) $@) +ifeq ($(TRICK_LIB_BUILD_TYPE),PLO) @ld -r -o $@ $^ +else ifeq ($(TRICK_LIB_BUILD_TYPE),SHARED) + @c++ -shared -o $@ $^ 2> $@.log +else ifeq ($(TRICK_LIB_BUILD_TYPE),STATIC) + @ar rcs $@ $^ 2> $@.log +endif $(dir $(TRICKIFY_OBJECT_NAME)) $(TRICKIFY_PYTHON_DIR) build: @mkdir -p $@ From 4146834f103b2c9c40839d80d6c36a5057f19ecb Mon Sep 17 00:00:00 2001 From: Derek Bankieris Date: Mon, 25 Mar 2019 08:12:20 -0500 Subject: [PATCH 4/7] Support static/dynamic libraries in Trickification Update documentation Change TRICK_LIB_BUILD_TYPE to TRICKIFY_BUILD_TYPE Remove support for linking in arbitrary objects Conform logging to existing pattern --- share/trick/makefiles/trickify.mk | 88 ++++++++++++++++--------------- 1 file changed, 46 insertions(+), 42 deletions(-) diff --git a/share/trick/makefiles/trickify.mk b/share/trick/makefiles/trickify.mk index 1678d6b2..35092672 100644 --- a/share/trick/makefiles/trickify.mk +++ b/share/trick/makefiles/trickify.mk @@ -1,6 +1,6 @@ -# This file can be used to create an object file containing the io_* and py_* -# code that Trick would normally generate during the simulation build process. -# Sims can then link against this object file, reducing compilation time. +# This file can be used to create an object file or library containing the io_* +# and py_* code that Trick would normally generate during the simulation build +# process. Sims can then link against that, reducing compilation time. # # To use it, create a directory that includes a file named S_source.hh that # includes all header files for which you want io_* and py_* code generated. @@ -25,9 +25,26 @@ # paths to the header files included by your S_source.hh. For instance: # -I$(HOME)/myproject/foo/include -I$(HOME)/myproject/bar/include # +# TRICKIFY_BUILD_TYPE (optional) +# Valid options are: +# 1. STATIC (.a) +# Create a static library. This will require the use of --whole-archive (on +# Linux) or -all_load/-force_load (on Mac) when linking the sim executeable. +# Trick uses dlsym to dynamically load symbols at run time, but the linker, +# by default, will not include symbols from static libraries that are not +# known to be needed at compile time. +# 2. SHARED (.so) +# Create a shared object (dynamically linked library). This may require the +# use of -rpath to ensure the linker can find the shared object at runtime +# unless you explicitly link against it (as opposed to using -L and -l) +# during compilation. +# 3. PLO (.o) [default] +# Create a partially-linked object. No special linker options are required. +# # TRICKIFY_OBJECT_NAME (optional) -# The name of the generated object file. The default value is trickified.o. -# You should choose something more meaningful, like trickified_myproject.o. +# The name of the generated object file or library. The default value is +# trickified.o. You should choose something more meaningful, especially if +# you're using another build type. # # TRICKIFY_PTYON_DIR (optional) # The directory into which generated Python modules are placed. The default @@ -74,9 +91,11 @@ ifndef TRICKIFY_CXX_FLAGS $(error TRICKIFY_CXX_FLAGS must be set) endif +TRICKIFY_BUILD_TYPE ?= PLO TRICKIFY_OBJECT_NAME ?= trickified.o TRICKIFY_PYTHON_DIR ?= python TRICK_HOME := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))/../../..) +MAKE_OUT ?= build/MAKE_out ifneq ($(wildcard build),) SWIG_OBJECTS := $(shell cat build/S_library_swig) @@ -92,37 +111,17 @@ TRICK_CXXFLAGS += $(TRICKIFY_CXX_FLAGS) # Ensure we can process all headers TRICK_EXT_LIB_DIRS := -# Trick library build type, defaulted to PLO -# PLO - Partially-linked object library -# STATIC - Static library -# SHARED - Dynamic shared library -TRICK_LIB_BUILD_TYPE ?= PLO - -# Add project source objects to trickified library. -SRC_OBJS ?= - -# When given a library, the linker will only link in objects that are known to -# be needed at link time. However, Trick uses dlsym to dynamically load the -# objects we'll be creating here. It cannot be known which objects will be -# needed at link time, so the sim has to link them all. In that case, we might -# as well create an object (which will be fully linked in by the sim) instead -# of a library (which would require the use of the -whole-archive option). -# -# One disadvantage of this approach is that we have to link all of the objects -# in this rule no matter how many have changed, whereas ar would allow us to -# replace only the changed objects. However, Trickified projects are -# necessarily used as third-party libraries, and so would be expected to -# change infrequently. Moreover, the methods for force-linking a library differ -# between Linux and Mac, so obviating the need for it simplifies a Trickified -# project's user-facing makefile. -$(TRICKIFY_OBJECT_NAME): $(SWIG_OBJECTS) $(IO_OBJECTS) $(SRC_OBJS) | $(dir $(TRICKIFY_OBJECT_NAME)) +$(TRICKIFY_OBJECT_NAME): $(SWIG_OBJECTS) $(IO_OBJECTS) | $(dir $(TRICKIFY_OBJECT_NAME)) $(info $(call COLOR,Linking) $@) -ifeq ($(TRICK_LIB_BUILD_TYPE),PLO) - @ld -r -o $@ $^ -else ifeq ($(TRICK_LIB_BUILD_TYPE),SHARED) - @c++ -shared -o $@ $^ 2> $@.log -else ifeq ($(TRICK_LIB_BUILD_TYPE),STATIC) - @ar rcs $@ $^ 2> $@.log +ifeq ($(TRICKIFY_BUILD_TYPE),PLO) + @echo ld -r -o $@ $^ >> $(MAKE_OUT) + $(ECHO_CMD)ld -r -o $@ $^ 2>&1 | $(TEE) -a $(MAKE_OUT); exit $${PIPESTATUS[0]} +else ifeq ($(TRICKIFY_BUILD_TYPE),SHARED) + @echo c++ -shared -o $@ $^ >> $(MAKE_OUT) + $(ECHO_CMD)c++ -shared -o $@ $^ 2>&1 | $(TEE) -a $(MAKE_OUT); exit $${PIPESTATUS[0]} +else ifeq ($(TRICKIFY_BUILD_TYPE),STATIC) + @echo ar rcs $@ $^ >> $(MAKE_OUT) + $(ECHO_CMD)ar rcs $@ $^ 2>&1 | $(TEE) -a $(MAKE_OUT); exit $${PIPESTATUS[0]} endif $(dir $(TRICKIFY_OBJECT_NAME)) $(TRICKIFY_PYTHON_DIR) build: @@ -130,7 +129,8 @@ $(dir $(TRICKIFY_OBJECT_NAME)) $(TRICKIFY_PYTHON_DIR) build: $(IO_OBJECTS): %.o: %.cpp $(info $(call COLOR,Compiling) $<) - @$(TRICK_CPPC) $(TRICK_CXXFLAGS) $(TRICK_SYSTEM_CXXFLAGS) -std=c++11 -Wno-invalid-offsetof -MMD -MP -c -o $@ $< + @echo $(TRICK_CPPC) $(TRICK_CXXFLAGS) $(TRICK_SYSTEM_CXXFLAGS) -std=c++11 -Wno-invalid-offsetof -MMD -MP -c -o $@ $< >> $(MAKE_OUT) + $(ECHO_CMD)$(TRICK_CPPC) $(TRICK_CXXFLAGS) $(TRICK_SYSTEM_CXXFLAGS) -std=c++11 -Wno-invalid-offsetof -MMD -MP -c -o $@ $< 2>&1 | $(TEE) -a $(MAKE_OUT) ; exit $${PIPESTATUS[0]} $(IO_OBJECTS:.o=.d): %.d: ; @@ -138,16 +138,19 @@ $(IO_OBJECTS:.o=.d): %.d: ; $(SWIG_OBJECTS): %.o: %.cpp $(info $(call COLOR,Compiling) $<) - @$(TRICK_CPPC) $(TRICK_CXXFLAGS) $(TRICK_SYSTEM_CXXFLAGS) $(PYTHON_INCLUDES) -Wno-unused-parameter -Wno-shadow -c -o $@ $< + @echo $(TRICK_CPPC) $(TRICK_CXXFLAGS) $(TRICK_SYSTEM_CXXFLAGS) $(PYTHON_INCLUDES) -Wno-unused-parameter -Wno-shadow -c -o $@ $< >> $(MAKE_OUT) + $(ECHO_CMD)$(TRICK_CPPC) $(TRICK_CXXFLAGS) $(TRICK_SYSTEM_CXXFLAGS) $(PYTHON_INCLUDES) -Wno-unused-parameter -Wno-shadow -c -o $@ $< 2>&1 | $(TEE) -a $(MAKE_OUT) ; exit $${PIPESTATUS[0]} $(SWIG_OBJECTS:.o=.cpp): %.cpp: %.i | $(TRICKIFY_PYTHON_DIR) $(SWIG_OBJECTS:.o=.i) $(info $(call COLOR,SWIGing) $<) - @$(SWIG) $(TRICK_INCLUDE) $(TRICK_DEFINES) $(TRICK_VERSIONS) $(TRICK_SWIG_FLAGS) -c++ -python -includeall -ignoremissing -w201,303,325,362,389,401,451 -outdir $(TRICKIFY_PYTHON_DIR) -o $@ $< + @echo $(SWIG) $(TRICK_INCLUDE) $(TRICK_DEFINES) $(TRICK_VERSIONS) $(TRICK_SWIG_FLAGS) -c++ -python -includeall -ignoremissing -w201,303,325,362,389,401,451 -outdir $(TRICKIFY_PYTHON_DIR) -o $@ $< >> $(MAKE_OUT) + $(ECHO_CMD)$(SWIG) $(TRICK_INCLUDE) $(TRICK_DEFINES) $(TRICK_VERSIONS) $(TRICK_SWIG_FLAGS) -c++ -python -includeall -ignoremissing -w201,303,325,362,389,401,451 -outdir $(TRICKIFY_PYTHON_DIR) -o $@ $< 2>&1 | $(TEE) -a $(MAKE_OUT) ; exit $${PIPESTATUS[0]} define create_convert_swig_rule build/%_py.i: /%.$1 $$(info $$(call COLOR,Converting) $$<) - ${TRICK_HOME}/$(LIBEXEC)/trick/convert_swig ${TRICK_CONVERT_SWIG_FLAGS} $$< + @echo ${TRICK_HOME}/$(LIBEXEC)/trick/convert_swig ${TRICK_CONVERT_SWIG_FLAGS} $$< >> $(MAKE_OUT) + $(ECHO_CMD)${TRICK_HOME}/$(LIBEXEC)/trick/convert_swig ${TRICK_CONVERT_SWIG_FLAGS} $$< 2>&1 | $(TEE) -a $(MAKE_OUT) ; exit $$${PIPESTATUS[0]} endef EXTENSIONS := H h hh hxx h++ hpp @@ -185,8 +188,9 @@ $(foreach EXTENSION,$(EXTENSIONS),$(eval $(call create_convert_swig_rule,$(EXTEN # http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/ build/S_source.d: | $(dir $@) - @$(TRICK_HOME)/bin/trick-ICG $(TRICK_CXXFLAGS) $(TRICK_SYSTEM_CXXFLAGS) $(TRICK_ICGFLAGS) S_source.hh - @$(TRICK_HOME)/$(LIBEXEC)/trick/make_makefile_swig - @$(TRICK_CC) -MM -MP -MT $@ -MF $@ $(TRICKIFY_CXX_FLAGS) S_source.hh + $(ECHO_CMD)$(TRICK_HOME)/bin/trick-ICG $(TRICK_CXXFLAGS) $(TRICK_SYSTEM_CXXFLAGS) $(TRICK_ICGFLAGS) S_source.hh + $(ECHO_CMD)$(TRICK_HOME)/$(LIBEXEC)/trick/make_makefile_swig 2>&1 | $(TEE) -a $(MAKE_OUT) ; exit $${PIPESTATUS[0]} + @echo $(TRICK_CC) -MM -MP -MT $@ -MF $@ $(TRICKIFY_CXX_FLAGS) S_source.hh >> $(MAKE_OUT) + $(ECHO_CMD) $(TRICK_CC) -MM -MP -MT $@ -MF $@ $(TRICKIFY_CXX_FLAGS) S_source.hh 2>&1 | $(TEE) -a $(MAKE_OUT) ; exit $${PIPESTATUS[0]} -include build/S_source.d From 951bee52c014980fa20dd60646c442cc79afd10e Mon Sep 17 00:00:00 2001 From: Derek Bankieris Date: Mon, 25 Mar 2019 11:33:50 -0500 Subject: [PATCH 5/7] Use existing variables for LD and c++ This is why we have code reviews! --- share/trick/makefiles/trickify.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/share/trick/makefiles/trickify.mk b/share/trick/makefiles/trickify.mk index 35092672..46579f55 100644 --- a/share/trick/makefiles/trickify.mk +++ b/share/trick/makefiles/trickify.mk @@ -114,10 +114,10 @@ TRICK_EXT_LIB_DIRS := $(TRICKIFY_OBJECT_NAME): $(SWIG_OBJECTS) $(IO_OBJECTS) | $(dir $(TRICKIFY_OBJECT_NAME)) $(info $(call COLOR,Linking) $@) ifeq ($(TRICKIFY_BUILD_TYPE),PLO) - @echo ld -r -o $@ $^ >> $(MAKE_OUT) + @echo $(LD) $(LD_PARTIAL) -o $@ $^ >> $(MAKE_OUT) $(ECHO_CMD)ld -r -o $@ $^ 2>&1 | $(TEE) -a $(MAKE_OUT); exit $${PIPESTATUS[0]} else ifeq ($(TRICKIFY_BUILD_TYPE),SHARED) - @echo c++ -shared -o $@ $^ >> $(MAKE_OUT) + @echo $(TRICK_CPPC) -shared -o $@ $^ >> $(MAKE_OUT) $(ECHO_CMD)c++ -shared -o $@ $^ 2>&1 | $(TEE) -a $(MAKE_OUT); exit $${PIPESTATUS[0]} else ifeq ($(TRICKIFY_BUILD_TYPE),STATIC) @echo ar rcs $@ $^ >> $(MAKE_OUT) From e52449309c2dfdfe249e219405cfffbd94641b92 Mon Sep 17 00:00:00 2001 From: Aaron Brogley Date: Tue, 26 Mar 2019 16:52:27 -0500 Subject: [PATCH 6/7] Create the shortcut trick.mc_add_variable. This is shorter than the existing trick_mc.mc.add_variable and is accessible through the trick namespace with 'import trick'. --- share/trick/swig/shortcuts.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/share/trick/swig/shortcuts.py b/share/trick/swig/shortcuts.py index 5d8debfc..863325ba 100644 --- a/share/trick/swig/shortcuts.py +++ b/share/trick/swig/shortcuts.py @@ -18,6 +18,10 @@ if hasattr(top.cvar, 'trick_sys'): # from monte carlo mc_add_range = top.cvar.trick_sys.sched.add_range +# from Monte Carlo +if hasattr(top.cvar, 'trick_mc'): + mc_add_variable = top.cvar.trick_mc.mc.add_variable + # from the memory manager wrapper if hasattr(top.cvar, 'trick_mm'): read_checkpoint_from_string = top.cvar.trick_mm.mm.read_checkpoint_from_string From b29a117902359fc362379973d794a818c59804c1 Mon Sep 17 00:00:00 2001 From: Alex Lin Date: Tue, 26 Mar 2019 17:03:11 -0500 Subject: [PATCH 7/7] ICG does not compile with LLVM 8.0 #747 getLocEnd got changed to getEndLoc. Made a LLVM version based macro to handle both. --- trick_source/codegen/Interface_Code_Gen/BraceMacro.hh | 6 ++++++ .../codegen/Interface_Code_Gen/TranslationUnitVisitor.cpp | 8 ++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/trick_source/codegen/Interface_Code_Gen/BraceMacro.hh b/trick_source/codegen/Interface_Code_Gen/BraceMacro.hh index c533151a..b0c4b1e3 100644 --- a/trick_source/codegen/Interface_Code_Gen/BraceMacro.hh +++ b/trick_source/codegen/Interface_Code_Gen/BraceMacro.hh @@ -7,4 +7,10 @@ #define RBRACELOC getRBraceLoc #endif +#if (LIBCLANG_MAJOR >=8) +#define GETLOCEND getEndLoc +#else +#define GETLOCEND getLocEnd +#endif + #endif diff --git a/trick_source/codegen/Interface_Code_Gen/TranslationUnitVisitor.cpp b/trick_source/codegen/Interface_Code_Gen/TranslationUnitVisitor.cpp index f815301d..788bf6d0 100644 --- a/trick_source/codegen/Interface_Code_Gen/TranslationUnitVisitor.cpp +++ b/trick_source/codegen/Interface_Code_Gen/TranslationUnitVisitor.cpp @@ -68,7 +68,7 @@ bool TranslationUnitVisitor::TraverseDecl(clang::Decl *d) { typedef struct Astruct {} Bstruct ; */ std::set< std::string >::iterator it ; - std::string file_name = getFileName(ci , d->getLocEnd(), hsd) ; + std::string file_name = getFileName(ci , d->GETLOCEND(), hsd) ; std::string source_type = cvis.get_class_data()->getName() ; it = fwd_declared_classes[file_name].find(source_type) ; if ( it != fwd_declared_classes[file_name].end() ) { @@ -79,7 +79,7 @@ bool TranslationUnitVisitor::TraverseDecl(clang::Decl *d) { } else { // These are forward declarations. Insert this into the set of fwd declares keyed by the current file. if ( ! crd->getNameAsString().empty() ) { - fwd_declared_classes[getFileName(ci , d->getLocEnd(), hsd)].insert(crd->getNameAsString()) ; + fwd_declared_classes[getFileName(ci , d->GETLOCEND(), hsd)].insert(crd->getNameAsString()) ; } } } @@ -116,14 +116,14 @@ bool TranslationUnitVisitor::TraverseDecl(clang::Decl *d) { case clang::Decl::Typedef : { clang::TypedefDecl * td = static_cast(d) ; if ( isInUserCode(ci, td->getSourceRange().getBegin(), hsd) ) { - TypedefVisitor tv(ci , cs, hsd, pa, fwd_declared_classes[getFileName(ci , d->getLocEnd(), hsd)]) ; + TypedefVisitor tv(ci , cs, hsd, pa, fwd_declared_classes[getFileName(ci , d->GETLOCEND(), hsd)]) ; tv.TraverseDecl(d) ; } } break ; case clang::Decl::Var : { if ( isInUserCode(ci, d->getSourceRange().getBegin(), hsd) ) { - VariableVisitor tv(ci , cs, hsd, pa, fwd_declared_classes[getFileName(ci , d->getLocEnd(), hsd)]) ; + VariableVisitor tv(ci , cs, hsd, pa, fwd_declared_classes[getFileName(ci , d->GETLOCEND(), hsd)]) ; tv.TraverseDecl(d) ; } }