Skip to content
This repository
Browse code

Merge pull request #65 from matthewrmshin/fcm-make-class-prop

fcm make: *.prop declaration enhancements
  • Loading branch information...
commit 843ae972f7cb2b0bab9377b5ecd95e78b24ffd68 2 parents beb1e4b + 6143f2f
Ben Fitzpatrick benfitzpatrick authored
28 doc/user_guide/annex_cfg.html
@@ -463,18 +463,22 @@ <h2 id="make">FCM Make Configuration</h2>
463 463 <li>Unless stated otherwise, declarations are inherited.</li>
464 464
465 465 <li>The default values of the property settings of each step class (e.g.
466   - <code>build.prop{fc}</code>) can be modified in a site/user FCM make
467   - configuration file:
  466 + <code>build.prop{fc}</code>) can be modified in:
468 467
469 468 <ol>
470   - <li><samp>$FCM/etc/fcm/make.cfg</samp> where <var>$FCM/bin/</var> is
471   - the where <code>fcm</code> is invoked.</li>
  469 + <li>The site configuration file <samp>$FCM/etc/fcm/make.cfg</samp>
  470 + where <var>$FCM/bin/</var> is the where <code>fcm</code> is
  471 + invoked.</li>
472 472
473   - <li><samp>$HOME/.metomi/fcm/make.cfg</samp>.</li>
  473 + <li>The user configuration file
  474 + <samp>$HOME/.metomi/fcm/make.cfg</samp>.</li>
  475 +
  476 + <li><samp>*.prop{class,*}</samp> declarations in the FCM make
  477 + configuration file of the current session.</li>
474 478 </ol>
475 479
476   - <p>The syntax in a site/user FCM make configuration file is identical to
477   - a normal FCM make configuration file except that:</p>
  480 + <p>The syntax is identical to a normal FCM make configuration file
  481 + declaration except that:</p>
478 482
479 483 <ul>
480 484 <li>Only <samp>*.prop{*}</samp> declarations are accepted.</li>
@@ -896,10 +900,11 @@ <h3 id="make.build">FCM Make Configuration: Build</h3>
896 900 <p><dfn>modifier</dfn>: The name of one (or more) property. See
897 901 below.</p>
898 902
899   - <p><dfn>namespace</dfn>: Optional. A list of space-delimited namespaces
900   - to which this setting applies. If not specified, the setting applies to
901   - the global/root namespace. N.B. Not all build properties accept a
902   - namespace. See below for detail.</p>
  903 + <p><dfn>namespace</dfn>: Optional. A list of space-delimited namespaces to
  904 + which this setting applies. The namespace can be target names, if
  905 + applicable, or the hierarchical namespaces of source files. If not
  906 + specified, the setting applies to the global/root namespace. N.B. Not all
  907 + build properties accept a namespace. See below for detail.</p>
903 908
904 909 <p><dfn>value</dfn>: The value of the property.</p>
905 910
@@ -911,6 +916,7 @@ <h3 id="make.build">FCM Make Configuration: Build</h3>
911 916 build.prop{fc.flags}[egg ham bacon] = -C -W
912 917 build.prop{fc.flag-define} = -D%s
913 918 build.prop{cc.defs,fc.defs}[gen] = LOWERCASE UNDERSCORE
  919 +build.prop{fc.libs}[myprog.exe] = netcdf grib
914 920 </pre>
915 921 </dd>
916 922 </dl>
16 doc/user_guide/make.html
@@ -1551,6 +1551,22 @@ <h3 id="build.target-source">Build Targets from Source Files</h3>
1551 1551 the temporary archive.</dd>
1552 1552 </dl>
1553 1553
  1554 + <h3 id="build.target-prop">Build Targets and Properties</h3>
  1555 +
  1556 + <p>If you need to specify a property a specific target, you can either use
  1557 + their source file namespace or the target key. E.g. If the
  1558 + <samp>sausage.o</samp> taregt is generated from the source file in the
  1559 + <samp>src/food/sausage.f90</samp> namespace, you can specify its Fortran
  1560 + compiler flags <code><a href=
  1561 + "annex_cfg.html#make.build.prop.fc.flags">build.prop{fc.flags}</a></code> by
  1562 + doing either:</p>
  1563 +
  1564 + <pre>
  1565 +build.prop{fc.flags}[sausage.o] = -O4
  1566 +# would be the same as:
  1567 +build.prop{fc.flags}[src/food/sausage.f90] = -O4
  1568 +</pre>
  1569 +
1554 1570 <h3 id="build.target-source-fortran">Build Targets from Source Files: Fortran
1555 1571 Specifics</h3>
1556 1572
4 lib/FCM/System/Make.pm
@@ -106,7 +106,7 @@ sub _init {
106 106 my ($id, $label) = split(qr{\.}msx, $entry->get_label(), 2);
107 107 if (exists($attrib_ref->{subsystem_of}{$id})) {
108 108 my $subsystem = $attrib_ref->{subsystem_of}{$id};
109   - if (!$subsystem->init_config_parse_prop($entry, $label)) {
  109 + if (!$subsystem->config_parse_class_prop($entry, $label)) {
110 110 push(@unknown_entries, $entry);
111 111 }
112 112 }
@@ -421,7 +421,7 @@ represent the settings of the $ctx.
421 421 Returns a new context for the subsystem. The $id_of_class is the ID of the
422 422 subsystem class. The $id is the step ID of the context.
423 423
424   -=item $subsystem->init_config_parse_prop($entry,$label)
  424 +=item $subsystem->config_parse_class_prop($entry,$label)
425 425
426 426 Reads a configuration $entry into the subsystem default property. The $label is
427 427 the label of the $entry, but with the prefix (the subsystem ID plus a dot)
24 lib/FCM/System/Make/Build.pm
@@ -92,10 +92,11 @@ __PACKAGE__->class(
92 92 { init => \&_init,
93 93 action_of => {
94 94 config_parse => \&_config_parse,
  95 + config_parse_class_prop => \&_config_parse_class_prop,
95 96 config_parse_inherit_hook => \&_config_parse_inherit_hook,
96 97 config_unparse => \&_config_unparse,
  98 + config_unparse_class_prop => \&_config_unparse_class_prop,
97 99 ctx => \&_ctx,
98   - init_config_parse_prop => \&_init_config_parse_prop,
99 100 main => \&_main,
100 101 },
101 102 },
@@ -912,20 +913,30 @@ sub _targets_props_assign {
912 913 = _prev_hash_item_getter($m_ctx, $ctx, sub {$_[0]->get_target_of()});
913 914 my %NO_INHERIT_CATEGORY_IN
914 915 = map {$_ => 1} _props($attrib_ref, 'no-inherit-target-category', $ctx);
  916 + my %CTX_PROP_OF = %{$ctx->get_prop_of()};
915 917 for my $target (@{$targets_ref}) {
916 918 # Properties
917 919 my $FILE_TYPE_UTIL
918 920 = $attrib_ref->{file_type_util_of}->{$target->get_type()};
919 921 my $task = $FILE_TYPE_UTIL->task_of()->{$target->get_task()};
  922 + my $key = $target->get_key();
920 923 if ($task->can('prop_of')) {
921 924 my %prop_of = %{$task->prop_of($target)};
922 925 while (my $name = each(%prop_of)) {
923   - $target->get_prop_of()->{$name}
924   - = _prop($attrib_ref, $name, $ctx, $target->get_ns());
  926 + if ( exists($CTX_PROP_OF{$name})
  927 + && exists($CTX_PROP_OF{$name}->get_ctx_of()->{$key})
  928 + ) {
  929 + $target->get_prop_of()->{$name}
  930 + = $CTX_PROP_OF{$name}->get_ctx_of()->{$key}->get_value();
  931 + }
  932 + else {
  933 + $target->get_prop_of()->{$name}
  934 + = _prop($attrib_ref, $name, $ctx, $target->get_ns());
  935 + }
925 936 }
926 937 }
927 938 # Path, checksum and previous properties
928   - my $p_target = $P_TARGET_GETTER->($target->get_key());
  939 + my $p_target = $P_TARGET_GETTER->($key);
929 940 if (defined($p_target)) {
930 941 $target->set_checksum($p_target->get_checksum());
931 942 if ($p_target->is_ok()) {
@@ -1193,7 +1204,10 @@ sub _targets_select {
1193 1204 my @invalid_prop_ns_list;
1194 1205 while (my ($name, $prop) = each(%{$ctx->get_prop_of()})) {
1195 1206 while (my ($ns, $prop_ctx) = each(%{$prop->get_ctx_of()})) {
1196   - if (!$prop_ctx->get_inherited() && !exists($has_ns_in{$ns})) {
  1207 + if ( !$prop_ctx->get_inherited()
  1208 + && !exists($target_of{$ns})
  1209 + && !exists($has_ns_in{$ns})
  1210 + ) {
1197 1211 push(
1198 1212 @invalid_prop_ns_list,
1199 1213 [$ctx->get_id(), $name, $ns, $prop_ctx->get_value()],
3  lib/FCM/System/Make/Extract.pm
@@ -71,10 +71,11 @@ __PACKAGE__->class(
71 71 { init => \&_init,
72 72 action_of => {
73 73 config_parse => \&_config_parse,
  74 + config_parse_class_prop => \&_config_parse_class_prop,
74 75 config_parse_inherit_hook => \&_config_parse_inherit_hook,
75 76 config_unparse => \&_config_unparse,
  77 + config_unparse_class_prop => \&_config_unparse_class_prop,
76 78 ctx => \&_ctx,
77   - init_config_parse_prop => \&_init_config_parse_prop,
78 79 main => \&_main,
79 80 },
80 81 },
3  lib/FCM/System/Make/Mirror.pm
@@ -64,10 +64,11 @@ __PACKAGE__->class(
64 64 { init => \&_init,
65 65 action_of => {
66 66 config_parse => \&_config_parse,
  67 + config_parse_class_prop => \&_config_parse_class_prop,
67 68 config_parse_inherit_hook => \&_config_parse_inherit_hook,
68 69 config_unparse => \&_config_unparse,
  70 + config_unparse_class_prop => \&_config_unparse_class_prop,
69 71 ctx => \&_ctx,
70   - init_config_parse_prop => \&_init_config_parse_prop,
71 72 main => \&_main,
72 73 },
73 74 },
52 lib/FCM/System/Make/Share/Config.pm
@@ -57,19 +57,32 @@ sub _parse {
57 57 }
58 58 else {
59 59 my ($id, $label) = split(qr{\.}msx, $entry->get_label(), 2);
60   - my $ctx = $m_ctx->get_ctx_of($id);
61   - if (!defined($ctx) && exists($attrib_ref->{subsystem_of}{$id})) {
62   - $ctx = $attrib_ref->{subsystem_of}{$id}->ctx($id, $id);
63   - $m_ctx->get_ctx_of()->{$id} = $ctx;
64   - }
65   - my $rc;
66   - if (defined($ctx)) {
67   - my $id_of_class = $ctx->get_id_of_class();
68   - my $subsystem = $attrib_ref->{subsystem_of}{$id_of_class};
69   - $rc = $subsystem->config_parse($ctx, $entry, $label);
  60 + if ( $label eq 'prop'
  61 + && exists($entry->get_modifier_of()->{'class'})
  62 + && exists($attrib_ref->{subsystem_of}{$id})
  63 + ) {
  64 + my $subsystem = $attrib_ref->{subsystem_of}{$id};
  65 + if (!$subsystem->config_parse_class_prop($entry, $label)) {
  66 + push(@unknown_entries, $entry);
  67 + }
70 68 }
71   - if (!$rc) {
72   - push(@unknown_entries, $entry);
  69 + else {
  70 + my $ctx = $m_ctx->get_ctx_of($id);
  71 + if ( !defined($ctx)
  72 + && exists($attrib_ref->{subsystem_of}{$id})
  73 + ) {
  74 + $ctx = $attrib_ref->{subsystem_of}{$id}->ctx($id, $id);
  75 + $m_ctx->get_ctx_of()->{$id} = $ctx;
  76 + }
  77 + my $rc;
  78 + if (defined($ctx)) {
  79 + my $id_of_class = $ctx->get_id_of_class();
  80 + my $subsystem = $attrib_ref->{subsystem_of}{$id_of_class};
  81 + $rc = $subsystem->config_parse($ctx, $entry, $label);
  82 + }
  83 + if (!$rc) {
  84 + push(@unknown_entries, $entry);
  85 + }
73 86 }
74 87 }
75 88 }
@@ -160,6 +173,10 @@ sub _parse_use {
160 173 # Turns the context back into a config.
161 174 sub _unparse {
162 175 my ($attrib_ref, $m_ctx) = @_;
  176 + my %subsystem_of = map {
  177 + my $id = $m_ctx->get_ctx_of()->{$_}->get_id_of_class();
  178 + ($id, $attrib_ref->{subsystem_of}->{$id});
  179 + } @{$m_ctx->get_steps()};
163 180 map {$_->as_string()} (
164 181 ( map { FCM::Context::ConfigEntry->new({
165 182 label => 'step.class',
@@ -184,12 +201,15 @@ sub _unparse {
184 201 [sub {$m_ctx->get_dest()}, 'dest' ],
185 202 ),
186 203 ),
187   - ( map { my $ctx = $_;
  204 + ( map { my $id = $_;
  205 + $subsystem_of{$id}->config_unparse_class_prop($id);
  206 + }
  207 + sort keys(%subsystem_of)
  208 + ),
  209 + ( map { my $ctx = $m_ctx->get_ctx_of()->{$_};
188 210 my $id_of_class = $ctx->get_id_of_class();
189   - my $subsystem = $attrib_ref->{subsystem_of}{$id_of_class};
190   - $subsystem ? $subsystem->config_unparse($ctx) : ();
  211 + $subsystem_of{$id_of_class}->config_unparse($ctx);
191 212 }
192   - map {$m_ctx->get_ctx_of()->{$_}}
193 213 @{$m_ctx->get_steps()}
194 214 ),
195 215 );
76 lib/FCM/System/Make/Share/Subsystem.pm
@@ -25,11 +25,12 @@ use base qw{Exporter};
25 25
26 26 our @EXPORT = qw{
27 27 _config_parse
  28 + _config_parse_class_prop
28 29 _config_parse_prop
29 30 _config_parse_inherit_hook_prop
  31 + _config_unparse_class_prop
30 32 _config_unparse_join
31 33 _config_unparse_prop
32   - _init_config_parse_prop
33 34 _prop
34 35 _prop0
35 36 _props
@@ -45,13 +46,12 @@ use constant {PROP_DEFAULT => 0, PROP_NS_OK => 1};
45 46
46 47 # Aliases
47 48 my $E = 'FCM::System::Exception';
48   -my %L = ('prop' => 'prop');
49 49
50 50 # Parses a configuration entry into the context.
51 51 sub _config_parse {
52 52 my ($attrib_ref, $ctx, $entry, $label) = @_;
53 53 my %config_parser_of = (
54   - $L{'prop'} => \&_config_parse_prop,
  54 + 'prop' => \&_config_parse_prop,
55 55 %{$attrib_ref->{config_parser_of}},
56 56 );
57 57 if (!$label || !exists($config_parser_of{$label})) {
@@ -61,6 +61,25 @@ sub _config_parse {
61 61 1;
62 62 }
63 63
  64 +# Parses a configuration entry into the subsystem property.
  65 +sub _config_parse_class_prop {
  66 + my ($attrib_ref, $entry, $label) = @_;
  67 + if ($label ne 'prop') {
  68 + return;
  69 + }
  70 + if (@{$entry->get_ns_list()}) {
  71 + return $E->throw($E->CONFIG_NS, $entry);
  72 + }
  73 + my @keys = grep {$_ ne 'class'} keys(%{$entry->get_modifier_of()});
  74 + if (grep {!exists($attrib_ref->{prop_of}{$_})} @keys) {
  75 + return $E->throw($E->CONFIG_MODIFIER, $entry);
  76 + }
  77 + for my $key (@keys) {
  78 + $attrib_ref->{prop_of}{$key}[PROP_DEFAULT] = $entry->get_value();
  79 + }
  80 + 1;
  81 +}
  82 +
64 83 # Reads the ?.prop declaration from a config entry.
65 84 sub _config_parse_prop {
66 85 my ($attrib_ref, $ctx, $entry) = @_;
@@ -117,10 +136,23 @@ sub _config_unparse_join {
117 136 );
118 137 }
119 138
  139 +# Entries of the class prop settings.
  140 +sub _config_unparse_class_prop {
  141 + my ($attrib_ref, $id) = @_;
  142 + map {
  143 + my $key = $_;
  144 + FCM::Context::ConfigEntry->new({
  145 + label => join(q{.}, $id, 'prop'),
  146 + modifier_of => {'class' => 1, $key => 1},
  147 + value => $attrib_ref->{prop_of}{$key}[PROP_DEFAULT],
  148 + });
  149 + } sort keys(%{$attrib_ref->{prop_of}});
  150 +}
  151 +
120 152 # Entries of the prop settings.
121 153 sub _config_unparse_prop {
122 154 my ($attrib_ref, $ctx) = @_;
123   - my $label = join(q{.}, $ctx->get_id(), $L{'prop'});
  155 + my $label = join(q{.}, $ctx->get_id(), 'prop');
124 156 my %prop_of = %{$ctx->get_prop_of()};
125 157 map {
126 158 my $key = $_;
@@ -140,25 +172,6 @@ sub _config_unparse_prop {
140 172 } sort(keys(%prop_of));
141 173 }
142 174
143   -# Parses a configuration entry into the subsystem property.
144   -sub _init_config_parse_prop {
145   - my ($attrib_ref, $entry, $label) = @_;
146   - if ($label ne $L{'prop'}) {
147   - return;
148   - }
149   - if (@{$entry->get_ns_list()}) {
150   - return $E->throw($E->CONFIG_NS, $entry);
151   - }
152   - my @keys = keys(%{$entry->get_modifier_of()});
153   - if (grep {!exists($attrib_ref->{prop_of}{$_})} @keys) {
154   - return $E->throw($E->CONFIG_MODIFIER, $entry);
155   - }
156   - for my $key (@keys) {
157   - $attrib_ref->{prop_of}{$key}[PROP_DEFAULT] = $entry->get_value();
158   - }
159   - 1;
160   -}
161   -
162 175 # Returns the value of a named property (for a given $ns).
163 176 sub _prop {
164 177 my ($attrib_ref, $id, $ctx, $ns) = @_;
@@ -241,6 +254,12 @@ Reads a configuration $entry into the $ctx context. The $label is the label of
241 254 the $entry, but with the prefix (which should be the same as $ctx->get_id() plus
242 255 a dot) removed.
243 256
  257 +=item _config_parse_class_prop(\%attrib,$entry,$label)
  258 +
  259 +Reads a configuration $entry into the subsystem default property
  260 +$attrib{prop_of}. The $label is the label of the $entry, but with the prefix
  261 +(the subsystem ID plus a dot) removed.
  262 +
244 263 =item _config_parse_prop(\%attrib,$ctx,$entry)
245 264
246 265 Reads a property configuration $entry into the $ctx context. This method may
@@ -259,15 +278,14 @@ inherited subsystem context. Inherits property settings from $i_ctx into $ctx.
259 278
260 279 Joins the @list into a string that can be parsed again by shellwords.
261 280
262   -=item _config_unparse_prop(\%attrib,$ctx)
  281 +=item _config_unparse_class_prop(\%attrib,$id)
263 282
264   -Turns the properties in $ctx into a list configuration entries.
  283 +Turns the default properties in the current subsystem into a list of
  284 +configuration entries. $id is the ID of the current subsystem.
265 285
266   -=item _init_config_parse_prop(\%attrib,$entry,$label)
  286 +=item _config_unparse_prop(\%attrib,$ctx)
267 287
268   -Reads a configuration $entry into the subsystem default property
269   -$attrib{prop_of}. The $label is the label of the $entry, but with the prefix
270   -(the subsystem ID plus a dot) removed.
  288 +Turns the properties in $ctx into a list of configuration entries.
271 289
272 290 =item _prop(\%attrib,$id,$ctx,$ns)
273 291
1  t/fcm-make/06-extract-ssh.t 100644 → 100755
@@ -25,6 +25,7 @@ N_TESTS=6
25 25 tests $N_TESTS
26 26 #-------------------------------------------------------------------------------
27 27 # Get a remote host for testing
  28 +T_HOST=
28 29 for FILE in $HOME/.metomi/fcm/t.cfg $FCM_HOME/etc/fcm/t.cfg; do
29 30 if [[ ! -f $FILE || ! -r $FILE ]]; then
30 31 continue
72 t/fcm-make/12-build-class-prop.t
... ... @@ -0,0 +1,72 @@
  1 +#!/bin/bash
  2 +#-------------------------------------------------------------------------------
  3 +# (C) British Crown Copyright 2006-2013 Met Office.
  4 +#
  5 +# This file is part of FCM, tools for managing and building source code.
  6 +#
  7 +# FCM is free software: you can redistribute it and/or modify
  8 +# it under the terms of the GNU General Public License as published by
  9 +# the Free Software Foundation, either version 3 of the License, or
  10 +# (at your option) any later version.
  11 +#
  12 +# FCM is distributed in the hope that it will be useful,
  13 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 +# GNU General Public License for more details.
  16 +#
  17 +# You should have received a copy of the GNU General Public License
  18 +# along with FCM. If not, see <http://www.gnu.org/licenses/>.
  19 +#-------------------------------------------------------------------------------
  20 +# Tests for "fcm make", *.prop{class,*}.
  21 +#-------------------------------------------------------------------------------
  22 +. $(dirname $0)/test_header
  23 +#-------------------------------------------------------------------------------
  24 +tests 6
  25 +cp -r $TEST_SOURCE_DIR/$TEST_KEY_BASE/* .
  26 +PATH=$PWD/bin:$PATH
  27 +#-------------------------------------------------------------------------------
  28 +TEST_KEY="$TEST_KEY_BASE"
  29 +run_pass "$TEST_KEY" fcm make
  30 +find .fcm-make build* -type f | sort >"$TEST_KEY.find"
  31 +file_cmp "$TEST_KEY.find" "$TEST_KEY.find" <<'__FIND__'
  32 +.fcm-make/config-as-parsed.cfg
  33 +.fcm-make/config-on-success.cfg
  34 +.fcm-make/ctx.gz
  35 +.fcm-make/log
  36 +build/bin/hello.bin
  37 +build/o/hello.o
  38 +build_house/bin/hello_house
  39 +build_house/o/hello_house.o
  40 +build_office/bin/hello_office
  41 +build_office/o/hello_office.o
  42 +build_road/bin/hello_road
  43 +build_road/o/hello_road.o
  44 +__FIND__
  45 +sed '/^\[info\] shell(0.*)/!d; s/^\[info\] shell(0.*) //' .fcm-make/log \
  46 + >"$TEST_KEY.log"
  47 +file_cmp "$TEST_KEY.log" "$TEST_KEY.log" <<__LOG__
  48 +my-fc -oo/hello.o -c -I./include $PWD/src/hello.f90
  49 +my-fc -obin/hello.bin o/hello.o
  50 +my-fc -oo/hello_house.o -c -I./include $PWD/src/hello_house.f90
  51 +my-fc -obin/hello_house o/hello_house.o
  52 +my-fc -oo/hello_office.o -c -I./include $PWD/src/hello_office.f90
  53 +my-fc -obin/hello_office o/hello_office.o
  54 +gfortran -oo/hello_road.o -c -I./include $PWD/src/hello_road.f90
  55 +gfortran -obin/hello_road o/hello_road.o
  56 +__LOG__
  57 +#-------------------------------------------------------------------------------
  58 +TEST_KEY="$TEST_KEY_BASE-incr"
  59 +find build* -type f -exec stat -c'%Y %n' {} \; | sort >"$TEST_KEY.mtime.old"
  60 +run_pass "$TEST_KEY" fcm make
  61 +find build* -type f -exec stat -c'%Y %n' {} \; | sort >"$TEST_KEY.mtime"
  62 +file_cmp "$TEST_KEY.mtime" "$TEST_KEY.mtime.old" "$TEST_KEY.mtime"
  63 +sed '/^\[info\] \(compile\|link\) targets:/!d; s/total-time=.*$//' \
  64 + .fcm-make/log >"$TEST_KEY.log"
  65 +file_cmp "$TEST_KEY.log" "$TEST_KEY.log" <<'__LOG__'
  66 +[info] compile targets: modified=0, unchanged=1,
  67 +[info] compile targets: modified=0, unchanged=1,
  68 +[info] compile targets: modified=0, unchanged=1,
  69 +[info] compile targets: modified=0, unchanged=1,
  70 +__LOG__
  71 +#-------------------------------------------------------------------------------
  72 +exit 0
2  t/fcm-make/12-build-class-prop/bin/my-fc
... ... @@ -0,0 +1,2 @@
  1 +#!/bin/bash
  2 +exec gfortran "$@"
14 t/fcm-make/12-build-class-prop/fcm-make.cfg
... ... @@ -0,0 +1,14 @@
  1 +step.class[build_house build_office build_road]=build
  2 +steps=build build_house build_office build_road
  3 +build.prop{class,fc}=my-fc
  4 +build.prop{class,file-ext.bin}=
  5 +build.source=$HERE/src
  6 +build.target=hello.bin
  7 +build.prop{file-ext.bin}=.bin
  8 +build_house.source=$HERE/src
  9 +build_house.target=hello_house
  10 +build_office.source=$HERE/src
  11 +build_office.target=hello_office
  12 +build_road.source=$HERE/src
  13 +build_road.target=hello_road
  14 +build_road.prop{fc}=gfortran
3  t/fcm-make/12-build-class-prop/src/hello.f90
... ... @@ -0,0 +1,3 @@
  1 +program hello
  2 +WRITE(*, '(A,1X,A)') 'Hello', 'World'
  3 +end program hello
3  t/fcm-make/12-build-class-prop/src/hello_house.f90
... ... @@ -0,0 +1,3 @@
  1 +program hello_house
  2 +WRITE(*, '(A,1X,A)') 'Hello', 'House'
  3 +end program hello_house
3  t/fcm-make/12-build-class-prop/src/hello_office.f90
... ... @@ -0,0 +1,3 @@
  1 +program hello_office
  2 +WRITE(*, '(A,1X,A)') 'Hello', 'Office'
  3 +end program hello_office
3  t/fcm-make/12-build-class-prop/src/hello_road.f90
... ... @@ -0,0 +1,3 @@
  1 +program hello_road
  2 +WRITE(*, '(A,1X,A)') 'Hello', 'Road'
  3 +end program hello_road
57 t/fcm-make/13-build-target-prop.t
... ... @@ -0,0 +1,57 @@
  1 +#!/bin/bash
  2 +#-------------------------------------------------------------------------------
  3 +# (C) British Crown Copyright 2006-2013 Met Office.
  4 +#
  5 +# This file is part of FCM, tools for managing and building source code.
  6 +#
  7 +# FCM is free software: you can redistribute it and/or modify
  8 +# it under the terms of the GNU General Public License as published by
  9 +# the Free Software Foundation, either version 3 of the License, or
  10 +# (at your option) any later version.
  11 +#
  12 +# FCM is distributed in the hope that it will be useful,
  13 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 +# GNU General Public License for more details.
  16 +#
  17 +# You should have received a copy of the GNU General Public License
  18 +# along with FCM. If not, see <http://www.gnu.org/licenses/>.
  19 +#-------------------------------------------------------------------------------
  20 +# Test "fcm make", build.prop{*}[target].
  21 +#-------------------------------------------------------------------------------
  22 +. $(dirname $0)/test_header
  23 +#-------------------------------------------------------------------------------
  24 +tests 5
  25 +cp -r $TEST_SOURCE_DIR/$TEST_KEY_BASE/* .
  26 +PATH=$PWD/bin:$PATH
  27 +#-------------------------------------------------------------------------------
  28 +TEST_KEY="$TEST_KEY_BASE"
  29 +run_pass "$TEST_KEY" fcm make
  30 +find .fcm-make build -type f | sort >"$TEST_KEY.find"
  31 +file_cmp "$TEST_KEY.find" "$TEST_KEY.find" <<'__OUT__'
  32 +.fcm-make/config-as-parsed.cfg
  33 +.fcm-make/config-on-success.cfg
  34 +.fcm-make/ctx.gz
  35 +.fcm-make/log
  36 +build/bin/hello.exe
  37 +build/include/world.mod
  38 +build/o/hello.o
  39 +build/o/world.o
  40 +__OUT__
  41 +sed '
  42 + /\[info\] shell(0.*) \(gfortran\|my-fc\)/!d;
  43 + /hello\.exe/d;
  44 + s/^\[info\] shell(0.*) //
  45 +' .fcm-make/log >"$TEST_KEY.log"
  46 +file_cmp "$TEST_KEY.log" "$TEST_KEY.log" <<__LOG__
  47 +my-fc -oo/world.o -c -I./include $PWD/src/world.f90
  48 +gfortran -oo/hello.o -c -I./include $PWD/src/hello.f90
  49 +__LOG__
  50 +#-------------------------------------------------------------------------------
  51 +TEST_KEY="$TEST_KEY_BASE-incr"
  52 +find build -type f -exec stat -c'%Y %n' {} \; | sort >"$TEST_KEY.mtime.old"
  53 +run_pass "$TEST_KEY" fcm make
  54 +find build -type f -exec stat -c'%Y %n' {} \; | sort >"$TEST_KEY.mtime"
  55 +file_cmp "$TEST_KEY.mtime" "$TEST_KEY.mtime.old" "$TEST_KEY.mtime"
  56 +#-------------------------------------------------------------------------------
  57 +exit 0
20 t/fcm-make/13-build-target-prop/bin/my-fc
... ... @@ -0,0 +1,20 @@
  1 +#!/usr/bin/env bash
  2 +#-------------------------------------------------------------------------------
  3 +# (C) British Crown Copyright 2006-2013 Met Office.
  4 +#
  5 +# This file is part of FCM, tools for managing and building source code.
  6 +#
  7 +# FCM is free software: you can redistribute it and/or modify
  8 +# it under the terms of the GNU General Public License as published by
  9 +# the Free Software Foundation, either version 3 of the License, or
  10 +# (at your option) any later version.
  11 +#
  12 +# FCM is distributed in the hope that it will be useful,
  13 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 +# GNU General Public License for more details.
  16 +#
  17 +# You should have received a copy of the GNU General Public License
  18 +# along with FCM. If not, see <http://www.gnu.org/licenses/>.
  19 +#-------------------------------------------------------------------------------
  20 +exec gfortran "$@"
4 t/fcm-make/13-build-target-prop/fcm-make.cfg
... ... @@ -0,0 +1,4 @@
  1 +steps = build
  2 +build.source = $HERE/src
  3 +build.target{task} = link
  4 +build.prop{fc}[world.o] = my-fc
4 t/fcm-make/13-build-target-prop/src/hello.f90
... ... @@ -0,0 +1,4 @@
  1 +program hello
  2 +use world, only: get_world
  3 +WRITE(*, '(A,A)') 'Hello ', trim(get_world())
  4 +end program hello
8 t/fcm-make/13-build-target-prop/src/world.f90
... ... @@ -0,0 +1,8 @@
  1 +module world
  2 +character(*), parameter :: world1 = 'Earth'
  3 +contains
  4 +elemental function get_world() result(w)
  5 +character(len=len(world1)) :: w
  6 +w = world1
  7 +end function get_world
  8 +end module world

0 comments on commit 843ae97

Please sign in to comment.
Something went wrong with that request. Please try again.