3 eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
4 & eval 'exec perl -S $0 $argv:q'
7 # configure script for OpenDDS
8 # Distributed under the OpenDDS License.
9 # See: http://www.opendds.org/license.html
23 use POSIX
qw(strftime);
28 use lib
"$FindBin::RealBin/tools/scripts/modules";
31 use ini qw
/read_ini_file/;
33 my $backup_timestamp = strftime
"%Y-%m-%d-%H-%M-%S", localtime time;
35 # save args before Getopt modifies them
38 my @default_configh = (
39 '#define ACE_DISABLE_MKTEMP',
40 '#define ACE_DISABLE_READDIR_R',
41 '#define ACE_DISABLE_TEMPNAM',
42 '#define TAO_HAS_UIOP 0',
46 return 'win32' if $^O
eq 'MSWin32';
47 return 'macos' if $^O
eq 'darwin';
51 sub perlOS_to_java_platform
{
52 return 'win32' if $^O
eq 'MSWin32';
56 my $targetUsageIndent = "\t\t";
60 'compilers' => ['cl'],
62 'cl_versions' => {13.1 => 'vc71', 14 => 'vc8', 15 => 'vc9',
63 16 => 'vc10', 17 => 'vc11', 18 => 'vc12',
64 19 => 'vc14', 19.1 => 'vs2017',
65 19.2 => 'vs2019', 19.3 => 'vs2022', 19.4 => 'vs2022'},
66 'cl_archs' => {'x64' => 1, 'Win32' => 1, 'ARM64' => 0, 'ARM' => 0}, # 1 if supported
69 'compilers' => ['clang++'],
70 'libpath' => 'DYLD_LIBRARY_PATH',
71 'aceconfig' => 'macosx',
72 'aceplatform' => 'macosx',
75 'compilers' => ['clang++'],
76 'libpath' => 'DYLD_LIBRARY_PATH',
77 'aceconfig' => 'macosx',
78 'aceplatform' => 'macosx',
80 'java_platform' => 'darwin',
81 'usage' => ['Use --target-arch or --target-compiler to ' .
82 'specify how the target', 'build should work'],
85 'compilers' => ['g++', 'clang++', 'clang'],
86 'libpath' => 'LD_LIBRARY_PATH',
87 'aceplatform' => 'linux_$NONSTDCOMP', # $NONSTDCOMP = clang
90 'libpath' => 'LD_LIBRARY_PATH',
91 'aceplatform' => 'linux',
92 'aceconfig' => 'linux',
94 'java_platform' => 'linux',
95 'usage' => ['Use --target-compiler to specify the ' .
96 'cross-compiler binary',
100 'compilers' => ['clang++'],
101 'libpath' => 'LD_LIBRARY_PATH',
104 'libpath' => 'LD_LIBRARY_PATH',
106 'aceplatform' => 'lynxos',
107 'compiler_root_env' => 'ENV_PREFIX',
108 'usage' => ['Set up the cross compile using '.
109 'the script from LynxOS',
113 'libpath' => 'LD_LIBRARY_PATH',
115 'usage' => ['Use the wrenv script before running configure',
116 'Specify the VSB with --macros=VSB_DIR=<dir>',
120 'libpath' => 'LD_LIBRARY_PATH',
121 'aceplatform' => 'android',
122 'aceconfig' => 'android',
125 "Use --macros=ANDROID_ABI=<ARCH> to specify the",
126 "target architecture.",
127 "Use --macros=android_sdk=<SDK_PATH> and",
128 "--macros=android_target_api=<API_NUMBER> to specify",
129 "where to find android.jar.",
131 'needs_i2jrt_corba' => 1,
132 'java_platform' => 'android',
135 'compilers' => ['clang++'],
136 'libpath' => 'DYLD_LIBRARY_PATH',
138 'aceconfig' => 'macosx-iOS',
139 'aceplatform' => 'macosx_iOS',
141 "Use --macros=IPHONE_TARGET=SIMULATOR or",
142 "--macros=IPHONE_TARGET=HARDWARE",
143 "to specify the target architecture."
150 print "Cross-compile targets: specify --target=TGT where TGT is one of:\n";
151 for my $k (sort keys %platforminfo) {
152 if ($platforminfo{$k}->{'no_host'}) {
154 if ($platforminfo{$k}->{'usage'}) {
155 for my $line (@
{$platforminfo{$k}->{'usage'}}) {
156 print "${targetUsageIndent}$line\n";
164 ## arg processing and usage
167 my $argIndent = "\n " . (' ' x
$argPadding);
169 # Array of array-refs, each inner array is an option group which
170 # has the format [Group Description, Opt1 Spec, Opt1 Description,
171 # Opt2 Spec, Opt2 Description, ...]
172 # <default>OPT is a custom token marking a string option that
173 # defaults to $opts{'OPT'} = '' and can be overridden by opts by passing
174 # --no-OPT or --OPT with a value.
175 # <hidden>OPT hides the option from --help
176 # <usage>OPT hides the option from GetOpt::Long
179 ['Options controlling the configure script:',
180 'help|h|?', 'Show this help and exit',
181 'target-help', 'Show details of cross-compile target configs',
182 'verbose|v', 'Trace script execution',
183 'dry-run|n', 'Don\'t do anything',
184 'backup!', 'Make backup of build configuration files (yes)',
185 '<hidden>force-clone-submodules', 'Get submodules as if this wasn\'t a git repo',
187 ['Build platform and compiler:',
188 'host=s', 'Host (auto detect: linux, win32, macosx)',
189 'compiler=s', 'Compiler (auto detect / guess by searching PATH)',
190 'std=s', 'C++ standard version (compiler default)',
191 'target=s', 'Cross-compile target (none): see --target-help',
192 'target-arch=s', 'Architecture for target (none): see --target-help',
193 'target-compiler=s', 'Compiler for target (if req\'d): see --target-help',
194 'host-tools=s', 'DDS_ROOT of host tools for cross compile (build)',
195 'host-ace=s', 'Define host ACE_ROOT (uses relative path from' .
196 $argIndent . 'target DDS_ROOT to target ACE_ROOT)',
197 'host-tools-only!', 'Just build the host tools (no)',
198 'prefix=s', 'Installation prefix (none)',
199 'install-origin-relative!', 'Install with RPATH relative to $ORIGIN (no)',
200 'workspace=s', 'Custom MPC workspace file to copy and use' .
201 $argIndent . '(Use a builtin one)',
204 'debug!', 'Debugging (yes)',
205 'optimize!', 'Optimization (no)',
206 'inline!', 'Inlining (yes)',
207 'static!', 'Static libraries (no)',
208 'ipv6!', 'IPv6 support (no)',
209 'sanitize=s@', 'Build with a sanitizer, can pass multiple times' .
210 $argIndent . 'or one list separated by commas, combining asan' .
211 $argIndent . "and tsan isn't recommended (no sanitizers)" .
212 $argIndent . ' asan: Address Sanitizer, gcc/clang only' .
213 $argIndent . ' tsan: Thread Sanitizer, gcc/clang only' .
214 $argIndent . ' ubsan: Undefined Behavior Sanitizer, clang only',
215 'compile-warnings=s', 'Enable additional compiler warnings' .
216 $argIndent . '(default compiler warnings)' .
217 $argIndent . ' WARNING: enable additional warnings' .
218 $argIndent . ' ERROR: enable additional warnings that are' .
219 $argIndent . ' treated as errors',
221 ['Required dependencies for OpenDDS:',
222 'ace=s', 'ACE (use ACE_ROOT, ACE_wrappers, or download)',
223 'tao=s', 'TAO (use TAO_ROOT, ACE_ROOT/TAO, or download)',
224 'mpc=s', 'MPC (use MPC_ROOT, ACE_ROOT/MPC, or download)',
225 'doc-group|doc_group!', 'Use the DOC Group release of TAO 2.5.x (yes)',
226 'doc-group3|doc_group3!', 'Use the DOC Group release of TAO 3.x (no)',
227 'ace-tao=s', 'Use the ACE/TAO version from acetao.ini',
228 'ace-github-latest!', 'Clone latest ACE/TAO/MPC from GitHub (no)',
229 'force-ace-tao', 'Force configuration of ACE/TAO (no)',
230 'no-disable-deprecated', 'Turn off disabling deprecated interfaces when' .
231 $argIndent . 'configuring ACE/TAO (no)',
233 ['Advanced configuration:',
234 'configh=s@', 'Extra text for config.h',
235 'macros=s@', 'Extra text for platform_macros.GNU',
236 'features=s@', 'Extra text for default.features',
237 'mpcopts=s@', 'Extra command-line options for MPC' .
238 $argIndent . 'This option can be given multiple times' .
239 $argIndent . 'For example:' .
240 $argIndent . ' --mpcopts=-value_template --mpcopts=build_flags+="-Wall -Werror"' .
241 $argIndent . 'turns into the following arguments for MPC:' .
242 $argIndent . ' -value_template build_flags+="-Wall -Werror"',
243 '<usage>mpc:OPT=VALUE', 'Extra command-line options for MPC' .
244 $argIndent . 'For example:' .
245 $argIndent . ' --mpc:value_template build_flags+="-Wall -Werror"' .
246 $argIndent . 'turns into the following arguments for MPC:' .
247 $argIndent . ' -value_template build_flags+="-Wall -Werror"' .
248 $argIndent . 'This option can be given multiple times',
249 'boottime!', 'Use CLOCK_BOOTTIME for timers (no)',
251 ['Optional dependencies for OpenDDS (disabled by default unless noted otherwise):',
252 'java:s', 'Java development kit (use JAVA_HOME)',
253 'jboss:s', 'JBoss application server (use JBOSS_HOME)',
254 'ant:s', 'Ant for JBoss (use ANT_HOME or system pkg)',
256 'Wireshark dev headers or source not built with' .
257 $argIndent . 'CMake (use WIRESHARK_SRC or system pkg)' .
258 $argIndent . 'Implies --glib',
259 'wireshark-cmake|wireshark_cmake:s',
260 'Wireshark source built with CMake, requires' .
261 $argIndent . '--wireshark-build. Requires --wireshark-lib if' .
262 $argIndent . 'guessing fails (use WIRESHARK_SRC)' .
263 $argIndent . 'Implies --glib',
264 'wireshark-build|wireshark_build=s', 'Wireshark CMake Build Location',
265 'wireshark-lib|wireshark_lib=s',
266 'Optional Wireshark CMake libraries location' .
267 $argIndent . 'relative to wireshark-build (guesses)',
268 'glib:s', 'GLib for Wireshark (use GLIB_ROOT or system pkg)',
269 '<default>rapidjson:s',
270 'RapidJSON for Wireshark dissector and JSON' .
271 $argIndent . 'Sample Serialization (Enabled by default,' .
272 $argIndent . 'use git submodule, RAPIDJSON_ROOT, or system pkg)',
273 'qt:s', 'Qt5 (use QTDIR or system pkg)',
274 'qt-include:s', 'Qt include dir (use QT5_INCDIR, QTDIR/include,' .
275 $argIndent . 'or system package)',
276 'xerces3:s', 'Xerces-C++ 3 for QoS XML handling, DDS Security',
277 'openssl:s', 'OpenSSL for DDS Security',
278 'cmake:s', 'Path to CMake for compiling GoogleTest' .
279 $argIndent . '(Check PATH and normal locations)',
280 'gtest:s', 'Path to GoogleTest, required for tests' .
281 $argIndent . '(uses GTEST_ROOT)' .
282 $argIndent . 'If not built, will try to build using CMake.',
284 ['Optional OpenDDS features:',
285 'built-in-topics!', 'Built-in Topics (yes)',
286 'content-subscription!', 'Content-Subscription Profile (yes)',
287 'content-filtered-topic!', 'ContentFilteredTopic (CS Profile) (yes)',
288 'multi-topic!', 'MultiTopic (CS Profile) (yes)',
289 'query-condition!', 'QueryCondition (CS Profile) (yes)',
290 'ownership-profile!', 'Ownership Profile (yes)',
291 'ownership-kind-exclusive!', 'Exclusive Ownership (Ownership Profile) (yes)',
292 'object-model-profile!', 'Object Model Profile (yes)',
293 'persistence-profile!', 'Persistence Profile (yes)',
294 'safety-profile:s', 'Safety Profile: base or extended (none)',
295 'tests!', 'Build tests, examples, and performance tests (no)' .
296 $argIndent . 'Requires --gtest if missing git submodule',
297 'security!', 'DDS Security plugin (no) Implies --openssl and' .
298 $argIndent . '--xerces3',
303 my $callback = shift;
304 for my $group (@specs) {
305 for my $n (1 .. (scalar @
{$group} / 2)) {
306 my $opt = ${$group}[$n * 2 - 1];
307 my $descr = ${$group}[$n * 2];
308 $opt =~ /(\<\w+\>)?([\w-]+)/;
309 my $optkey = (defined $1 ?
$1 : "") . $2;
310 &$callback(${$group}[0], $opt, $descr, $optkey, @_);
319 open VER
, 'dds/Version.h' or die "ERROR: can't open dds/Version.h, stopped";
321 $ver = $1 if /#define OPENDDS_VERSION "([^"]+)"/;
325 Welcome to OpenDDS version $ver
327 Options for this script are listed below, with the default behavior described
328 in parenthesis after the option description.
329 Boolean options can take the form "--opt" or "--no-opt", the more commonly
330 needed one (the one that changes the default behavior) is shown below.
331 Options that require arguments are shown as "--opt=VAL". Options with optional
332 arguments are shown as "--opt[=VAL]". Options that can be repeated with
333 cumulative effect are shown with a trailing "...". Some third-party
334 optional dependencies can be automatically located if they are installed in the
335 expected locations (see entries below marked with "system pkg"). In those
336 cases, specify the option as --opt without an = to enable the corresponding
337 feature in OpenDDS and use the default installation location.
340 my ($group, $opt, $descr, $optkey) = @_;
341 if (!defined $current || $group ne $current) {
345 $optkey .= '=VAL' if $opt =~ /=s/;
346 $optkey .= '[=VAL]' if $opt =~ /:s/;
347 $optkey = "[no-]$optkey" if ($opt =~ /!$/ && $descr =~ / \(yes\)/);
348 if ($optkey =~ /^\<hidden\>/) {
351 if ($opt =~ /^\<usage\>(.*)$/) {
354 $optkey =~ s/^\<default\>(.*)$/\[no-\]$1/g;
355 $optkey .= '...' if $opt =~ /s\@$/;
356 my $pad = $argPadding - length $optkey;
357 print "--$optkey" . ' ' x
(($pad > 0) ?
$pad : 0) . " $descr\n";
369 my ($group, $opt, $descr, $optkey) = @_;
370 if ($opt =~ /^\<usage\>/) {
373 if ($opt =~ /^<default>(.*)$/) {
375 $optkey =~ /^<default>(.*)$/;
376 push @getopts, "no-$1";
380 $opt =~ s/^\<hidden\>(.*)$/$1/;
386 if (! -r
'rules.dds.GNU') {
387 print "ERROR: this script must be run from its own directory\n";
392 Getopt
::Long
::Configure
('pass_through');
393 GetOptions
($opts, @getopts) or usage
(1);
394 usage
(0) if $opts->{'help'};
395 targetUsage
(0) if $opts->{'target-help'};
398 my $arg = shift(@ARGV);
399 if ($arg =~ /^--mpc:([^=]*)(?:=(.*))?$/) {
402 if (defined($value)) {
403 push(@
{$opts->{'mpcopts'}}, '-' . $key, $value);
406 $value = shift(@ARGV);
407 push(@
{$opts->{'mpcopts'}}, '-' . $key, $value);
409 print STDERR
"ERROR: $arg requires a value\n";
413 print STDERR
"ERROR: unknown argument $arg\n";
418 if ($opts->{'verbose'}) {
420 new Dumpvalue
()->dumpValue($opts);
423 for my $opt (@default) {
424 if ($opt eq 'rapidjson' && defined $opts->{'safety-profile'}) {
425 print("Although it's a default, rapidjson is not compatible with Safety ".
426 "Profile so it will not be enabled\n") if $opts->{'verbose'};
429 if (!exists $opts->{$opt} && !exists $opts->{"no-$opt"}) {
431 $defaulted->{$opt} = 1;
432 print("By default, --$opt is added to the options\n") if $opts->{'verbose'};
439 my $cross_compile = 0;
440 my %opts = %{parseArgs
()};
442 my $debug = exists $opts{'debug'} ?
$opts{'debug'} : 1;
443 my $backup = exists $opts{'backup'} ?
$opts{'backup'} : 1;
444 my $force_ace_tao = exists $opts{'force-ace-tao'} ?
$opts{'force-ace-tao'} : 0;
445 my $no_disable_deprecated = exists $opts{'no-disable-deprecated'} ?
$opts{'no-disable-deprecated'} : 0;
447 if (exists($opts{'std'})) {
448 $cxx_std = $opts{'std'};
449 # Accept any of --std=17, --std=stdcpp17, --std=c++17, etc.
450 $cxx_std =~ s/^(std)?(cpp|c\+\+)//;
453 push(@mpcopts, @
{$opts{'mpcopts'}}) if exists($opts{'mpcopts'});
455 push(@features, @
{$opts{'features'}}) if exists($opts{'features'});
457 $opts{'host'} = perlOS_to_host
() unless $opts{'host'};
459 my $is_windows = $opts{'host'} eq 'win32';
461 my ($slash, $exeext) = $is_windows ?
('\\', '.exe') : ('/', '');
465 ('ext' => 'cmd', 'pathsep' => ';', 'refpre' => '%',
466 'refpost' => '%', 'comment' => '::') :
467 ('ext' => 'sh', 'pathsep' => ':', 'refpre' => '${',
468 'refpost' => '}', 'comment' => '#')
471 sub might_be_executable
{
473 return -x
$path && -f
$path; # On Windows -x can return true for directories
478 for my $p (File
::Spec
->path()) {
480 my $path = "$p/$file";
481 if (might_be_executable
($path)) {
484 elsif ($exeext ne '') {
486 if (might_be_executable
($path)) {
494 sub addCurLibPathRef
{
495 my $buildEnvRef = shift;
496 my $platform = $opts{$buildEnvRef->{'build'}};
497 my $libpathname = $platforminfo{$platform}->{'libpath'};
498 my $curLibPathRef = $specific{'refpre'} . $libpathname . $specific{'refpost'};
499 $buildEnvRef->{$libpathname} = $curLibPathRef;
504 return command_utils
::run_command
(
506 script_name
=> 'configure',
507 dry_run
=> $opts{'dry-run'},
508 verbose
=> $opts{'verbose'},
517 my $branch = $args{branch
};
518 my $commit = $args{commit
};
520 print "Cloning git repo $url ", $branch // $commit, "\n";
523 if (defined($commit)) {
524 # Git can't directly clone a specific commit. Could use clone and checkout,
525 # but can't do a single shallow clone that way.
526 my $chdir = ChangeDir
->new($dest);
527 $failed = run_command
(['git', 'init', '--quiet']) ||
528 run_command
(['git', 'remote', 'add', 'origin', $url]) ||
529 run_command
(['git', 'fetch', '--quiet', '--depth=1', 'origin', $commit]) ||
530 run_command
(['git', 'checkout', '--quiet', 'FETCH_HEAD']);
533 my @cmd = ('git', 'clone', '--quiet', '--depth=1', $url, $dest);
534 push(@cmd, '--branch', $branch) if (defined($branch));
535 $failed = run_command
(\
@cmd);
539 run_command
(['git', '--no-pager', 'log', '-1', '--oneline'], chdir => $dest);
544 sub git_submodule_prop
{
546 my $prop_name = shift;
547 my $full_prop_name = "submodule.$path.$prop_name";
548 open(my $fd, "-|", "git config --file .gitmodules --get $full_prop_name")
549 or die("git_submodule_prop open failed: $!\nStopped");
550 my $prop_value = <$fd>;
552 chomp($prop_value) if (defined($prop_value));
554 die("Couldn't get $full_prop_name from .gitmodules\nStopped");
559 sub git_ensure_submodule
{
563 print STDERR
"Can't ensure we have $path becuase we can't find the git command\n";
567 my $commit_prop = 'openddsConfigureCommit';
568 my $commit = git_submodule_prop
($path, $commit_prop);
570 if (!$opts{'force-clone-submodules'} &&
571 !run_command
(['git', 'submodule', 'update', '--init', $path])) {
572 # This doesn't affect us in this run, but since we can get the actual
573 # submodule commit, make sure it matches the commit from .gitmodules for
574 # the case when the source tree is not a git repo.
575 open(my $fd, "-|", "git ls-tree HEAD $path")
576 or die("git_ensure_submodule open failed: $!\nStopped");
577 my $real_commit = <$fd>;
580 $real_commit =~ s/^\S+ \S+ ([0-9a-f]+).*$/$1/;
581 if ($real_commit ne $commit) {
582 print STDERR
"WARNING: for submodule $path $commit_prop = $commit ",
583 "from .gitmodules doesn't match actual commit $real_commit\n";
589 return !git_clone
($path, git_submodule_prop
($path, 'url'), commit
=> $commit);
594 my $expected_hash = shift();
596 my $md5 = Digest
::MD5
->new;
597 open(my $fh, $path) or die("Couldn't open \"$path\": $!");
600 my $hash = $md5->hexdigest();
601 my $failed = $expected_hash ne $hash;
604 "MD5 hash mismatch for $path\n",
605 " expected: $expected_hash\n",
611 my $curpathRef = $specific{'refpre'} . 'PATH' . $specific{'refpost'};
612 my %hostEnv = ('build' => 'host', 'PATH' => $curpathRef);
613 my %targetEnv = ('build' => 'target', 'PATH' => $curpathRef);
615 my $would_download; # can dry-run assume directories that don't exist yet?
619 if (defined $opts{'mpc'}) {
620 setEnv
('MPC_ROOT', $opts{'mpc'});
622 elsif (!$ENV{'MPC_ROOT'} && (-r
$ace_src . '/MPC/MPC.ico'
623 || ($opts{'dry-run'} && $would_download))) {
624 setEnv
('MPC_ROOT', $ace_src . $slash . 'MPC');
626 elsif (!$ENV{'MPC_ROOT'}) {
627 die "ERROR: Can't find MPC. Please set MPC_ROOT or make sure MPC exists".
628 "\n in the 'MPC' directory under ACE_ROOT ($ace_src), stopped";
631 $targetEnv{'MPC_ROOT'} = $ENV{'MPC_ROOT'};
633 $hostEnv{'MPC_ROOT'} = $targetEnv{'MPC_ROOT'};
636 if (!exists $platforminfo{$opts{'host'}} ||
637 $platforminfo{$opts{'host'}}->{'no_host'}) {
638 die "ERROR: unknown host $opts{'host'}, stopped";
640 print "host system is: $opts{'host'}\n" if $opts{'verbose'};
642 $opts{'target'} = $opts{'host'} unless $opts{'target'};
644 if (!exists $platforminfo{$opts{'target'}}) {
645 die "ERROR: unknown target $opts{'target'}, stopped";
648 if (exists($opts{'workspace'})) {
649 if (!-r
$opts{'workspace'}) {
650 die "ERROR: workspace file $opts{'workspace'} isn't a readable file, stopped";
652 $opts{'workspace'} = Cwd
::realpath
($opts{'workspace'});
655 if (exists($opts{'prefix'}) && !File
::Spec
->file_name_is_absolute($opts{'prefix'})) {
656 die("ERROR: --prefix argument $opts{'prefix'} is not an absolute path, stopped");
659 # Set initial libpath
660 addCurLibPathRef
(\
%hostEnv);
661 addCurLibPathRef
(\
%targetEnv);
664 if (defined $opts{'safety-profile'} && $opts{'safety-profile'} eq '') {
665 print "Defaulting safety profile to extended\n";
666 $opts{'safety-profile'} = 'extended';
669 my $build_host_tools = 0;
670 if ($opts{'host'} ne $opts{'target'} || $opts{'safety-profile'}) {
671 $build_host_tools = !$opts{'host-tools'};
672 print "Cross-compile build " .
673 ($build_host_tools ?
'including' : 'excluding') . " host tools\n"
677 my $has_host_compiler = $build_host_tools || !$cross_compile;
679 if ($platforminfo{$opts{'target'}}->{'compiler_root_env'}) {
680 # This target puts its cross-compiler in the PATH before the host compiler,
681 # we will need to override (not append to) PATH for the host build.
682 my $root_env = $platforminfo{$opts{'target'}}->{'compiler_root_env'};
683 my $root_dir = $ENV{$root_env};
684 my @oldpath = split /$specific{'pathsep'}/, $ENV{'PATH'};
685 my $newpath = join($specific{'pathsep'}, grep {!/^$root_dir/} @oldpath);
687 s/\Q$specific{'refpre'}\EPATH\Q$specific{'refpost'}\E/$newpath/;
690 if (!exists $platforminfo{$opts{'target'}}->{'needs_i2jrt_corba'}) {
691 $platforminfo{$opts{'target'}}->{'needs_i2jrt_corba'} = 0;
696 if ($has_host_compiler) {
697 if ($opts{'compiler'}) {
699 for my $stdcomp (@
{$platforminfo{$opts{'host'}}->{'compilers'}}) {
700 $standard = 1 if $opts{'compiler'} eq $stdcomp;
702 $opts{'nonstdcompiler'} = 1 unless $standard;
705 print "Auto-detecting compiler\n" if $opts{'verbose'};
706 for my $stdcomp (@
{$platforminfo{$opts{'host'}}->{'compilers'}}) {
707 my $path = which
($stdcomp);
709 print "Found $stdcomp at: $path\n" if $opts{'verbose'};
710 $opts{'compiler'} = $stdcomp;
714 if (!defined $opts{'compiler'}) {
715 die "ERROR: Can't find a compiler, set PATH or run this script with the ".
716 "--compiler option.\n" . ($is_windows ?
" For Microsoft Visual C++, ".
717 "run this script from the Visual Studio ".
718 "Command Prompt.\n" : '') . "Stopped";
721 print "compiler is: $opts{'compiler'}\n" if $opts{'verbose'};
723 if ($opts{'compiler'} =~ /cl(\.exe)?$/i) {
724 my $savepath = $ENV{'PATH'};
725 my $clpath = which
($opts{'compiler'});
727 $clpath =~ s/vc\\bin(\\(x86_)?amd64)?/common7\\ide/i;
728 $ENV{'PATH'} .= ";$clpath";
731 # Have CL Tell Us Its Target Architecture and Version
732 my ($tmp_fd, $tmp_filename) = File
::Temp
::tempfile
();
733 my $cl_check = << "EOF";
736 #elif defined(_M_IX86)
738 #elif defined(_M_ARM64)
740 #elif defined(_M_ARM)
743 # define ARCH Unknown
747 print $tmp_fd $cl_check;
749 my $cl_command = "\"$opts{'compiler'}\" /EP $tmp_filename 2>&1";
750 print "Running $cl_command\n" if $opts{'verbose'};
751 open(my $cl_out_fd, "-|", $cl_command)
752 or die "ERROR: Could not detect Visual C++ version, try running this ".
753 "script from the Visual Studio Command Prompt.\nStopped";
756 while (my $line = <$cl_out_fd>) {
758 print "CL says: $line\n" if $opts{'verbose'} && $line !~ /^\s*$/;
759 # Convert _MSC_VER to the form \d+\.\d
760 if ($line =~ /^CL is (\d+)\d (\w+)$/) {
767 unlink($tmp_filename)
768 or warn "Unable to delete temporary file $tmp_filename: $!";
769 print "CL Version is $ver, architecture is $arch\n" if $opts{'verbose'};
770 if (!$ver && !$arch) {
771 die "cl version probe failed, invalid output from cl\nStopped";
773 if ($arch eq 'Unknown') {
774 die "cl version probe failed, no known architecture macro was defined\nStopped";
777 my $archs = $platforminfo{'win32'}->{'cl_archs'};
778 if (!exists($archs->{$arch})) {
779 die "cl version probe failed, unknown architecture \"$arch\"\nStopped";
781 if (!$archs->{$arch}) {
782 die "ERROR: Windows for $arch isn't supported\nStopped";
784 $opts{'compiler_target_architecture'} = $arch;
786 my $vers = $platforminfo{'win32'}->{'cl_versions'};
787 if (!exists($vers->{$ver})) {
788 my @vers_sorted = sort(keys(%{$vers}));
789 my $last_cl = $vers_sorted[-1];
790 print "$ver isn't a known version of cl, using the last known version: $last_cl\n"
794 $opts{'compiler_version'} = $vers->{$ver};
797 push(@features, 'no_cxx11=0');
798 print "Visual C++ has >= C++11 support\n" if $opts{'verbose'};
801 my $std = "stdcpp$cxx_std";
802 push(@mpcopts, '-value_template', "LanguageStandard=$std");
803 print "Setting Visual C++ LanguageStandard to $std\n" if $opts{'verbose'};
804 if ($opts{'std'} eq 'latest' || $cxx_std >= 17) {
805 push(@features, 'no_cxx17=0');
806 print "Visual C++ has >= C++17 support\n" if $opts{'verbose'};
809 $ENV{'PATH'} = $savepath;
810 print "Detected Visual C++ version: $opts{'compiler_version'}\n"
813 elsif ($opts{'compiler'} =~ /g\+\+|clang/) {
814 my $version_string = `$opts{'compiler'} --version`;
815 print "Compiler version: $version_string\n" if $opts{'verbose'};
816 $opts{'is apple clang'} = $version_string =~ /^Apple/;
818 push(@
{$opts{'macros'}}, 'CCFLAGS += -std=' . $opts{'std'});
819 print "Added platform_macros for -std=$opts{std}\n" if $opts{'verbose'};
821 elsif ($opts{'compiler'} !~ /clang/) {
822 $version_string =~ /\(.*\) (\d+)\.\d+/;
824 $opts{'std'} = 'gnu++17';
825 print "Detected GCC >= 11, default -std=gnu++17\n" if $opts{'verbose'};
828 $opts{'std'} = 'gnu++14';
829 print "Detected GCC >= 6, default -std=gnu++14\n" if $opts{'verbose'};
832 elsif ($opts{'compiler'} =~ /clang/ && $version_string !~ /^Apple / &&
833 $version_string =~ /(\d+)\.(\d+)\.(\d+)/) {
834 # Apple's version of Clang doesn't default to c++11 or higher, users
835 # can pass --std= to change the C++ standard version used.
837 $opts{'std'} = 'gnu++17';
838 print "Detected Clang >= 16, default -std=gnu++17\n" if $opts{'verbose'};
841 # Non-Apple versions of Clang, if version 6 or newer, default to C++14 like GCC
842 $opts{'std'} = 'gnu++14';
843 print "Detected Clang >= 6, default -std=gnu++14\n" if $opts{'verbose'};
848 my $cpp17 = qr/(17|2a|20|2b|23)/;
849 if ($opts{'std'} =~ /(0x|11|1y|14|1z|$cpp17)$/) {
850 push(@features, 'no_cxx11=0');
851 print "Compiler has >= C++11 support\n" if $opts{'verbose'};
854 if ($opts{'std'} =~ /$cpp17$/) {
855 push(@features, 'no_cxx17=0');
856 print "Compiler has >= C++17 support\n" if $opts{'verbose'};
862 my $compile_warnings = $opts{'compile-warnings'} // '';
863 if ($compile_warnings eq 'WARNING' or $compile_warnings eq 'ERROR') {
864 my ($section_names, $sections) = read_ini_file
("$FindBin::RealBin/build.ini");
865 my %compiler_map = ( 'g++' => 'GNU', 'clang' => 'Clang', 'cl' => 'MSVC', 'cl.exe' => 'MSVC');
866 my $section = $compiler_map{$opts{'compiler'}};
867 if ($opts{'is apple clang'}) {
868 $section = 'AppleClang';
870 my $warning_flags = $sections->{$section}{'warning'};
871 my $error_flags = $sections->{$section}{'error'};
872 if ($section eq 'MSVC') {
873 $warning_flags =~ s/^\/W//;
874 push(@mpcopts, '-value_template', "warning_level+=${warning_flags}");
875 if ($compile_warnings eq 'ERROR') {
876 push(@mpcopts, '-value_template', 'WarnAsError=1');
879 push(@mpcopts, '-value_template', "compile_flags+=${warning_flags}");
880 if ($compile_warnings eq 'ERROR') {
881 push(@mpcopts, '-value_template', "compile_flags+=${error_flags}");
888 return substr($val, 0, 1) ne $slash && ($slash eq '/' || $val !~ /^[a
-z
]:/i
);
893 return Cwd
::abs_path
($val) if $val && -d
$val && $val =~ /../;
898 my($hashref, $name, $val, $notdir) = @_;
899 $val = Cwd
::abs_path
($val) if -d
$val;
900 if ($opts{'dry-run'} && !$notdir && looksRelative
($val)) {
901 $val = getcwd
. $slash . $val;
903 $val =~ s!/!\\!g if $is_windows;
904 $hashref->{$name} = $val;
908 setSomeEnv
(\
%targetEnv, @_);
912 setSomeEnv
(\
%hostEnv, @_);
919 if ($opts{'ace'} ne 'download') {
920 if (!-r
$opts{'ace'} . '/ace/ACE.h') {
921 die "ERROR: Can't find ACE at $opts{'ace'}.\nStopped";
923 $ace_src = $opts{'ace'};
926 elsif ($ENV{'ACE_ROOT'}) {
927 if (!-r
$ENV{'ACE_ROOT'} . '/ace/ACE.h') {
928 die "ERROR: Can't find ACE at $ENV{'ACE_ROOT'}.\nStopped";
930 $ace_src = $ENV{'ACE_ROOT'};
932 elsif (-r
'../ACE_wrappers/ace/ACE.h') {
933 die "ERROR: Older versions of this script would default to using ACE at " .
934 "../ACE_wrappers, but this version doesn't. Use the --ace command line " .
935 "option to override this error. Use --ace=download to have this script " .
936 "download an ACE+TAO package and expand it to ACE_wrappers.\nStopped";
938 elsif (-r
'ACE_wrappers/ace/ACE.h') {
939 $ace_src = 'ACE_wrappers';
941 elsif (-r
'ATCD/ACE/ace/ACE.h') {
942 $ace_src = 'ATCD/ACE';
944 elsif (-r
'ACE_TAO/ACE/ace/ACE.h') {
945 $ace_src = 'ACE_TAO/ACE';
948 $ace_src = normalizePath
($ace_src);
954 if (!-r
$opts{'tao'} . '/tao/ORB.h') {
955 die "ERROR: Can't find TAO at $opts{'tao'}.\nStopped";
957 $tao_src = $opts{'tao'};
959 elsif ($ENV{'TAO_ROOT'}) {
960 if (!-r
$ENV{'TAO_ROOT'} . '/tao/ORB.h') {
961 die "ERROR: Can't find TAO at $ENV{'TAO_ROOT'}.\nStopped";
963 $tao_src = $ENV{'TAO_ROOT'};
965 elsif (defined $ace_src && -r
$ace_src . '/TAO/tao/ORB.h') {
966 $tao_src = $ace_src . $slash . 'TAO';
968 elsif (defined $ace_src && -r
$ace_src . '/../TAO/tao/ORB.h') {
969 $tao_src = (File
::Spec
->splitpath($ace_src))[1] .'TAO';
972 $tao_src = normalizePath
($tao_src);
974 if ($opts{'safety-profile'}) {
975 # convert to lower case
976 $opts{'safety-profile'} = lc($opts{'safety-profile'});
980 if (!$ace_src || !$tao_src) {
981 if ($opts{'ace-github-latest'}) {
982 die "ERROR: Git not found in path (required to clone ACE/TAO/MPC)"
985 my $urlbase = 'https://github.com/DOCGroup';
986 my $branch = 'ace6tao2';
987 if ($opts{'doc-group3'}) {
991 my $err = git_clone
('ACE_TAO', "$urlbase/ACE_TAO", branch
=> $branch);
992 die "ERROR: Failed to clone ACE/TAO from GitHub\nStopped"
994 ! -r
'ACE_TAO/ACE/ace/ACE.h' ||
995 ! -r
'ACE_TAO/TAO/tao/ORB.h';
997 $err = git_clone
('ACE_TAO/ACE/MPC', "$urlbase/MPC", branch
=> 'master');
998 die "ERROR: Failed to clone MPC (into ACE_TAO/ACE/MPC) from GitHub\nStopped"
1000 ! -r
'ACE_TAO/ACE/MPC/mwc.pl';
1002 $ace_src = normalizePath
('ACE_TAO/ACE');
1003 $tao_src = normalizePath
('ACE_TAO/TAO');
1006 # Get ACE/TAO version info
1007 my ($section_names, $sections) = read_ini_file
("$FindBin::RealBin/acetao.ini");
1008 my $ace_tao_version = $opts{'doc-group3'} ?
$sections->{ace7tao3
} : $sections->{ace6tao2
};
1009 if ($opts{'ace-tao'}) {
1010 $ace_tao_version = $sections->{$opts{'ace-tao'}};
1011 die "ERROR: No entry named '$opts{'ace-tao'}' in acetao.ini" unless $ace_tao_version;
1013 if ($opts{verbose
}) {
1014 print("ACE/TAO Version Info:");
1015 new Dumpvalue
()->dumpValue($ace_tao_version);
1017 my $ext = $is_windows ?
'zip' : 'tar.gz';
1018 my $file = $ace_tao_version->{"$ext-filename"};
1019 my $url = $ace_tao_version->{"$ext-url"};
1020 my $md5_hash = $ace_tao_version->{"$ext-md5"};
1022 # Check for an existing file
1024 if (md5sum
($file, $md5_hash)) {
1025 if ($opts{'dry-run'}) {
1026 print("Would remove existing $file and attempt to download\n");
1029 print("Removing existing $file and attempting to download\n");
1030 unlink($file) or die("Couldn't remove $file: $!\nStopped");
1033 elsif ($opts{'verbose'}) {
1034 print("Using ACE+TAO source package $file\n");
1039 my $dl_msg = "Downloading $file from $url using";
1040 $would_download = 1;
1042 require LWP
::UserAgent
;
1043 my $ua = LWP
::UserAgent
->new;
1045 print("$dl_msg LWP\n");
1046 if ($opts{'dry-run'}) {
1047 print("Dry-run: would LWP::UserAgent get $url\n");
1050 my $response = $ua->get($url, ':content_file' => $file);
1051 if ($response->is_error) {
1052 die $response->message . "\nstopped";
1057 if (which
('wget')) {
1058 print("$dl_msg wget\n");
1059 run_command
(['wget', '--output-document', $file, $url], autodie
=> 1);
1061 elsif (which
('curl')) {
1062 print("$dl_msg curl\n");
1063 run_command
(['curl', '--location', $url, '--output', $file], autodie
=> 1);
1066 die "ERROR: Can't download ACE+TAO using LWP, wget, or curl.\n" .
1067 "Download ACE+TAO from $url, place the file here\n, " .
1068 "and re-run the script.\nStopped";
1073 if (!$opts{'dry-run'} && md5sum
($file, $md5_hash)) {
1074 die("MD5 hash check failed after download, try running again?\nStopped");
1077 print "Extracting archive $file\n";
1078 $ENV{'ACTIVEPERL_CONFIG_DISABLE'} = 1 if $^O
eq 'MSWin32';
1079 $ENV{'ACTIVEPERL_CONFIG_SILENT'} = 1 if $^O
eq 'MSWin32';
1080 eval {require Archive
::Extract
;};
1083 my $ddsroot = getcwd
;
1085 $err = run_command
(['tar', 'xzf', "$ddsroot/$file"]);
1089 print "Archive::Extract isn't installed, trying Archive::Zip\n" if $opts{'verbose'};
1090 eval {require Archive
::Zip
};
1092 print "Neither Archive::Extract or Archive::Zip are installed\n" if $opts{'verbose'};
1095 if ($opts{'dry-run'}) {
1096 print "Dry-run: would Archive::Zip $file\n";
1099 my $zip = Archive
::Zip
->new();
1100 if ($zip->read( $file ) == Archive
::Zip
::AZ_OK
() &&
1101 $zip->extractTree() == Archive
::Zip
::AZ_OK
()) {
1109 die "ERROR: Can't extract $file, extract it to " . Cwd
::abs_path
('.') .
1110 "\nand run this script again.\nStopped";
1114 if ($opts{'dry-run'}) {
1115 print "Dry-run: would Archive::Extract $file\n";
1118 if ($^O
ne 'MSWin32') {
1120 $Archive::Extract
::PREFER_BIN
= 1;
1122 my $ae = Archive
::Extract
->new('archive' => $file);
1123 if (!$ae->extract('to' => '.')) {
1124 die $ae->error . "\nstopped";
1130 print "Removed $file\n" if $opts{'verbose'};
1131 $ace_src = 'ACE_wrappers';
1132 $tao_src = 'ACE_wrappers/TAO';
1136 print "Using ace_src: $ace_src\n" if $opts{'verbose'};
1137 print "Using tao_src: $tao_src\n" if $opts{'verbose'};
1139 sub clone_host_and_target
{
1140 my $source_dir = shift;
1141 locate_mpc
($ace_src);
1142 print "cloning build tree\n" if $opts{'verbose'};
1144 ["$targetEnv{'MPC_ROOT'}/clone_build_tree.pl", 'host', 'target'],
1145 chdir => $source_dir)) {
1146 die("Failed to clone tree");
1152 if (!$opts{'dry-run'} && -r
$file) {
1153 print "WARNING: overwriting existing $file\n";
1155 my $backup_path = $file . '.bak';
1156 $backup_path .= ".$backup_timestamp" if -e
$backup_path;
1157 copy
($file, $backup_path);
1158 print " (saved a backup copy as $backup_path)\n";
1164 sub backup_and_copy
{
1168 if ($opts{'dry-run'}) {
1169 print("Would copy $src to $dst\n");
1176 sub backup_and_open
{
1179 if ($opts{'dry-run'}) {
1180 return File
::Temp
->new();
1182 my $fh = new FileHandle
;
1183 open $fh, ">$file" or die "ERROR: Can't write to $file, stopped";
1187 sub dump_and_unlink
{ # removes temp files created by dry-run
1189 if ($opts{'verbose'}) {
1197 sub write_config_h
{
1198 my %buildEnv = %{shift()};
1199 my $platform = $opts{$buildEnv{'build'}};
1200 my $pi = $platforminfo{$platform};
1201 $opts{'optimize'} = 0 if (!exists $opts{'optimize'} && !exists $opts{'sanitize'});
1203 my $CFGH = backup_and_open
("$buildEnv{'ACE_ROOT'}/ace/config.h");
1204 if (!$no_disable_deprecated) {
1205 for my $line (@default_configh) {
1206 print $CFGH "$line\n";
1209 if ($buildEnv{'build'} eq 'target') {
1210 for my $line (@
{$opts{'configh'}}) {
1211 print $CFGH "$line\n";
1214 my $cfg = $platform;
1215 if ($pi->{'aceconfig'}) {
1216 $cfg = $pi->{'aceconfig'};
1217 $cfg =~ s/\$UNAMER/my $u = `uname -r`; chomp $u; $u/e;
1219 $cfg .= '-' . $opts{'host_version'} if $opts{'host_version'};
1220 print $CFGH "#include \"ace/config-$cfg.h\"\n";
1221 if (defined $opts{'no-opendds-safety-profile'}) {
1222 print $CFGH "#define ACE_FACE_SAFETY_" . uc($opts{'safety-profile'}) . "\n";
1223 if ($opts{'safety-profile'} eq 'extended') {
1224 print $CFGH "#ifndef ACE_HAS_ALLOC_HOOKS\n";
1225 print $CFGH "# define ACE_HAS_ALLOC_HOOKS\n";
1226 print $CFGH "#endif\n";
1231 print "Wrote $buildEnv{'ACE_ROOT'}/ace/config.h\n" if $opts{'verbose'};
1232 dump_and_unlink
($CFGH) if $opts{'dry-run'};
1237 sub default_features
{
1238 my %buildEnv = %{shift()};
1240 if ($buildEnv{'build'} eq 'target') {
1241 push(@feat, 'ipv6=1') if $opts{'ipv6'};
1242 my @normalized = map {/=/ ?
$_ : "$_=1"} @features;
1243 push(@feat, @normalized) if @normalized;
1244 } elsif ($opts{'java'}) {
1245 push(@feat, 'java=1');
1250 sub write_default_features
{
1251 my %buildEnv = %{shift()};
1252 my @feat = default_features
(\
%buildEnv);
1255 my $DF = backup_and_open
("$buildEnv{'ACE_ROOT'}/bin/MakeProjectCreator" .
1256 "/config/default.features");
1262 print "Wrote $buildEnv{'ACE_ROOT'}/.../default.features\n"
1263 if $opts{'verbose'};
1264 dump_and_unlink
($DF) if $opts{'dry-run'};
1268 my %all_sanitizers = (
1270 fsanitize
=> 'address',
1272 LSAN_OPTIONS
=> "suppressions=$FindBin::RealBin/etc/asan-suppr.txt",
1273 ASAN_OPTIONS
=> 'detect_leaks=1:fast_unwind_on_malloc=0:strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1',
1275 compiler_args
=> ['-fsanitize-address-use-after-scope'],
1278 fsanitize
=> 'thread',
1280 TSAN_OPTIONS
=> "history_size=7 second_deadlock_stack=1 suppressions=$FindBin::RealBin/etc/tsan-suppr.txt",
1284 fsanitize
=> 'undefined',
1286 UBSAN_OPTIONS
=> "suppressions=$FindBin::RealBin/etc/ubsan-suppr.txt:print_stacktrace=1",
1288 configh
=> ['#define ACE_INITIALIZE_MEMORY_BEFORE_USE'],
1289 compiler_args
=> ['-fno-sanitize=enum'],
1292 my %enabled_sanitizers = ();
1293 if (exists $opts{'sanitize'}) {
1294 for my $arg (@
{$opts{'sanitize'}}) {
1295 for my $name (split(/,/, $arg)) {
1296 if (exists($all_sanitizers{$name})) {
1297 $enabled_sanitizers{$name} = $all_sanitizers{$name};
1300 die("ERROR: \"$name\" isn't a valid sanitizer to pass to --sanitize\nStopped");
1307 my @sanitizer_compiler_args = ();
1308 my @sanitizer_linker_args = ();
1309 for my $name (sort(keys(%enabled_sanitizers))) {
1310 my $sanitizer = $enabled_sanitizers{$name};
1311 push(@fsanitize, $sanitizer->{fsanitize
});
1312 if (exists($sanitizer->{env
})) {
1313 for my $env (keys(%{$sanitizer->{env
}})) {
1314 setEnv
($env, $sanitizer->{env
}->{$env});
1317 if (exists($sanitizer->{configh
})) {
1318 push(@
{$opts{'configh'}}, @
{$sanitizer->{configh
}});
1320 if (exists($sanitizer->{compiler_args
})) {
1321 push(@sanitizer_compiler_args, @
{$sanitizer->{compiler_args
}});
1323 if (exists($sanitizer->{linker_args
})) {
1324 push(@sanitizer_linker_args, @
{$sanitizer->{linker_args
}});
1327 if (scalar(@fsanitize)) {
1329 die("ERROR: Using sanitizers requires --debug");
1331 my @common = ('-ggdb', '-fsanitize=' . join(',', @fsanitize));
1332 @sanitizer_compiler_args = ('-O1', @common, '-fno-omit-frame-pointer', @sanitizer_compiler_args);
1333 @sanitizer_linker_args = (@common, @sanitizer_linker_args);
1337 my %buildEnv = %{shift()};
1338 return ($buildEnv{'build'} eq 'target' && $opts{'target-compiler'}) ?
1339 $opts{'target-compiler'} : $opts{'compiler'};
1342 my @ace_macros = ('debug',
1349 sub write_platform_macros
{
1350 my %buildEnv = %{shift()};
1352 ($cross_compile && $buildEnv{'build'} eq 'target')) {
1353 my $pi = $platforminfo{$opts{$buildEnv{'build'}}};
1354 my $PMG = backup_and_open
("$buildEnv{'ACE_ROOT'}/include/makeinclude" .
1355 "/platform_macros.GNU");
1356 my $macro_cross_compile = 0;
1357 if ($buildEnv{'build'} eq 'target') {
1358 for my $line (@
{$opts{'macros'}}) {
1359 print $PMG "$line\n";
1361 for my $key (@ace_macros) {
1362 if (exists $opts{$key}) {
1363 my $macro = ($key eq 'static') ?
'static_libs_only' : $key;
1364 print $PMG "$macro = $opts{$key}\n";
1367 if ($cross_compile) {
1368 print $PMG "CROSS-COMPILE = 1\n";
1369 print $PMG 'TAO_IDL = $(HOST_ACE)/bin/tao_idl', "\n";
1371 print $PMG "HOST_EXE_EXT = .exe\n";
1373 print $PMG 'TAO_IDL_DEP = $(TAO_IDL)$(HOST_EXE_EXT)', "\n";
1374 if ($has_host_compiler) {
1375 print $PMG 'TAO_IDL_PREPROCESSOR = ', $opts{'compiler'}, "\n";
1377 print $PMG 'TAO_IDLFLAGS += -g $(HOST_ACE)/bin/ace_gperf', "\n";
1378 print $PMG 'build_tao_idl_be = 0', "\n";
1379 unless ($build_host_tools) {
1381 if (exists $opts{'host-ace'}) {
1382 $host_ace = $opts{'host-ace'};
1385 $host_ace = '$(HOST_DDS)' . nested
($ace_src, '.');
1387 print $PMG "HOST_ACE = $host_ace\n";
1389 if ($opts{'target-compiler'}) {
1390 my $tcomp = $opts{'target-compiler'};
1391 if ($tcomp =~ s/-g([c+])\1$/-/) {
1392 $macro_cross_compile = 1;
1393 print $PMG 'CROSS_COMPILE = ', $tcomp, "\n";
1396 $opts{'nonstdcompiler'} = $tcomp;
1397 print $PMG 'LDFLAGS += -Wl,-rpath-link,$(ACE_ROOT)/lib', "\n";
1400 if ($opts{'target-arch'}) {
1401 print $PMG "FLAGS_C_CC += -target $opts{'target-arch'}\n";
1402 print $PMG "LDFLAGS += -target $opts{'target-arch'}\n";
1404 if ($opts{'target'} eq 'android') {
1405 print $PMG 'ifeq (,$(findstring -isystem$(ACE_ROOT),$(INCLDIRS)))', "\n";
1406 print $PMG ' INCLDIRS += -isystem $(ACE_ROOT)', "\n";
1407 print $PMG 'endif', "\n";
1411 for my $f (@platformmacros) {
1412 print $PMG ($f =~ /=/ ?
$f : "$f=1"), "\n";
1414 if ($buildEnv{'build'} eq 'host') {
1415 print $PMG "static_libs_only = 1\n";
1416 print $PMG "java = 1\n" if $opts{'java'};
1418 if ($opts{'prefix'}) {
1419 print $PMG "INSTALL_PREFIX=" . $opts{'prefix'} . "\n";
1421 if (scalar(@fsanitize)) {
1423 'CPPFLAGS += ' . join(' ', @sanitizer_compiler_args) . "\n" .
1424 'LDFLAGS += ' . join(' ', @sanitizer_linker_args) . "\n";
1426 my $plat = $opts{$buildEnv{'build'}};
1427 if ($pi->{'aceplatform'}) {
1428 $plat = $pi->{'aceplatform'};
1429 $plat =~ s/\$COMP/'g++'/e;
1430 $plat =~ s/\$NONSTDCOMP/($opts{'compiler'} =~ m!clang!) ? 'clang' : ''/e;
1433 $plat .= '_' . $opts{'host_version'} if $opts{'host_version'};
1434 print $PMG "include \$(ACE_ROOT)/include/makeinclude/platform_$plat.GNU\n";
1435 if ($opts{'nonstdcompiler'} && !$macro_cross_compile) {
1436 my $comp = compiler
(\
%buildEnv);
1437 for my $var ('CC', 'CXX', 'LD') {
1438 print $PMG "$var = $comp\n";
1441 if ($opts{'prefix'} && $opts{'install-origin-relative'}) {
1444 INSTALL_ORIGIN = $$ORIGIN/../$(INSTALL_LIB)
1445 LDFLAGS += '-Wl,-rpath,$(INSTALL_ORIGIN)' $(LD_RPATH_FLAGS)
1449 print "Wrote $buildEnv{'ACE_ROOT'}/.../platform_macros.GNU\n"
1450 if $opts{'verbose'};
1451 dump_and_unlink
($PMG) if $opts{'dry-run'};
1455 sub write_opendds_configh
{
1456 my %buildEnv = %{shift()};
1457 my $CFGH = backup_and_open
("$buildEnv{'DDS_ROOT'}/dds/OpenDDSConfig.h");
1458 my $CFGIN = new FileHandle
;
1459 open($CFGIN, 'dds/OpenDDSConfig.h.in') or die("Can't open OpenDDSConfig.h.in for reading: $!\nStopped");
1462 'OPENDDS_CONFIG_AUTO_STATIC_INCLUDES' => 0,
1463 'OPENDDS_CONFIG_BOOTTIME_TIMERS' => $opts{'boottime'} // 0,
1464 'OPENDDS_CONFIG_SECURITY' => $opts{'security'} // 0,
1467 my $replace_value = sub {
1469 return 'UNDEFINED_NEED_TO_UPDATE_CONFIGURE_SCRIPT' unless exists $config{$var};
1470 return $config{$var};
1474 s/@(\w+)@/&$replace_value($1)/e;
1480 print "Wrote $buildEnv{'DDS_ROOT'}/dds/OpenDDSConfig.h\n"
1481 if $opts{'verbose'};
1482 dump_and_unlink
($CFGH) if $opts{'dry-run'};
1485 ## Optional OpenDDS dependencies
1487 'java' => {env
=> 'JAVA_HOME', sanity
=> 'include/jni.h', mpc
=> 'java'},
1488 'jboss' => {env
=> 'JBOSS_HOME', sanity
=> 'lib/jboss-common.jar'},
1489 'ant' => {env
=> 'ANT_HOME', sanity
=> 'bin/ant'},
1490 'wireshark' => {env
=> 'WIRESHARK_SRC', sanity
=> 'epan/packet.h', mpc
=> 'wireshark'},
1491 'wireshark-cmake' => {
1492 env
=> 'WIRESHARK_SRC',
1493 sanity
=> 'epan/packet.h',
1494 mpc
=> 'wireshark_cmake',
1496 'wireshark-build' => {env
=> 'WIRESHARK_BUILD', sanity
=> 'config.h'},
1497 'wireshark-lib' => {env
=> 'WIRESHARK_LIB', may_be_blank
=> 1},
1501 'include/glib-2.0/glib.h' => undef,
1502 'include/glib.h' => 'glib_versioned_includes=0',
1506 env
=> 'RAPIDJSON_ROOT',
1507 sanity
=> 'include/rapidjson/rapidjson.h',
1508 mpc
=> 'no_rapidjson=0',
1510 'qt' => {env
=> 'QTDIR', sanity
=> '', mpc
=> 'qt5'},
1512 env
=> 'XERCESCROOT',
1513 sanity
=> 'include/xercesc/dom/DOM.hpp',
1516 'openssl' => {env
=> 'SSL_ROOT', sanity
=> 'include/openssl/opensslv.h', mpc
=> 'ssl'},
1519 my $host_tools_only = exists $opts{'host-tools-only'} && $opts{'host-tools-only'};
1520 if ($host_tools_only) {
1521 print "--host-tools-only implies --static\n" if $opts{'verbose'};
1522 $opts{'static'} = 1;
1523 if ($cross_compile) {
1524 die "ERROR: Can't use --host-tools-only for cross compile\nStopped";
1528 if ((exists $opts{'wireshark'} || exists $opts{'wireshark-cmake'}) &&
1529 !exists $opts{'glib'}) {
1530 print "--wireshark and --wireshark-cmake imply --glib\n" if $opts{'verbose'};
1534 # Use this to check if tests are enabled (instead of $opts{'tests'} directly).
1535 my $tests = exists $opts{'tests'} && $opts{'tests'};
1537 my @ace_features = ('xerces3');
1539 if (exists $opts{'java'}) {
1540 if ($opts{'static'} && !$host_tools_only) {
1541 die "ERROR: --static can't be used with --java\nStopped";
1543 my $host_java_platform = perlOS_to_java_platform
();
1544 if ($cross_compile) {
1545 if (exists $platforminfo{$opts{'target'}}->{'java_platform'}) {
1546 setEnv
('JAVA_PLATFORM', $platforminfo{$opts{'target'}}->{'java_platform'});
1547 setHostEnv
('JAVA_PLATFORM', $host_java_platform);
1550 die "Cross-compile with Java for $opts{'target'} in not supported.\nStopped";
1554 setEnv
('JAVA_PLATFORM', $host_java_platform);
1558 my $try_to_use_qt_system_pkg =
1559 exists $opts{'qt'} && !length($opts{'qt'}) && !exists $opts{'qt-include'};
1561 # Default to Wireshark Development Package if installed and a path wasn't
1563 my $wireshark_install = '/usr/include/wireshark';
1564 if (exists $opts{'wireshark'} && !defined $ENV{'WIRESHARK_SRC'} && $opts{'wireshark'} eq '') {
1565 my $sanity = $optdep{'wireshark'}->{sanity
};
1566 if (-f File
::Spec
->catdir($wireshark_install, $sanity)) {
1567 $opts{'wireshark'} = $wireshark_install;
1570 die "ERROR: --wireshark must be given a value because there is not a " .
1571 "development package installed at " . $wireshark_install . ", stopped";
1575 my $wireshark_lib_defaulted = 0;
1576 if (exists $opts{'wireshark-cmake'} && !exists $opts{'wireshark-lib'}) {
1577 if ($^O
=~ /MSWin32/) {
1578 $opts{'wireshark-lib'} = "run\\RelWithDebInfo";
1580 elsif ($^O
=~ /darwin/) {
1581 $opts{'wireshark-lib'} = "run/Wireshark.app/Contents/Frameworks";
1583 elsif ($^O
=~ /linux/) {
1584 $opts{'wireshark-lib'} = "";
1587 die "ERROR: --wireshark-lib is needed because we couldn't decide on a default value";
1589 $wireshark_lib_defaulted = 1;
1592 if ($opts{'security'}) {
1593 unless (exists $opts{'openssl'}) {
1594 $opts{'openssl'} = '';
1595 print "Forcing --openssl (security dependency)\n" if $opts{'verbose'};
1597 unless (exists $opts{'xerces3'}) {
1598 $opts{'xerces3'} = '';
1599 print "Forcing --xerces3 (security dependency)\n" if $opts{'verbose'};
1604 unless ($opts{'cmake'}) {
1605 print "--cmake not specified by user; searching path...\n" if $opts{'verbose'};
1606 $opts{'cmake'} = which
('cmake');
1608 unless ($opts{'cmake'}) {
1609 print "CMake not found in path; searching default location...\n"
1610 if $opts{'verbose'};
1614 (-f
$ENV{'ProgramFiles'} . '\\CMake\\bin\\cmake.exe' ?
1615 $ENV{'ProgramFiles'} . '\\CMake\\bin\\cmake.exe' :
1616 $ENV{'ProgramFiles(x86)'} . '\\CMake\\bin\\cmake.exe') :
1620 my $has_cmake = -f
$opts{'cmake'};
1622 print "Using CMake '$opts{'cmake'}' if needed\n" if $opts{'verbose'};
1625 print "Could not find CMake at '$opts{'cmake'}'\n" if $opts{'verbose'};
1629 my $arch = exists $opts{'compiler_target_architecture'} ?
1630 $opts{'compiler_target_architecture'} : '';
1632 return $arch eq 'x64';
1635 sub system_default_install_dir
{
1637 # When the host is 32-bit.
1638 return $ENV{'ProgramFiles'}
1639 if ! exists $ENV{'ProgramFiles(x86)'};
1641 return targets_win64
() ?
$ENV{'ProgramFiles'} : $ENV{'ProgramFiles(x86)'};
1646 my $build_gtest = 0;
1647 if (exists $opts{'gtest'} || $tests) {
1648 my $gtest_sanity = 'include/gtest/gtest.h';
1649 my $gtest_root = undef;
1651 if ($opts{'gtest'}) {
1652 die "ERROR: '$gtest_sanity' not found in supplied gtest directory '$opts{'gtest'}'"
1653 if ! -f File
::Spec
->catfile($opts{'gtest'}, $gtest_sanity);
1655 $gtest_root = $opts{'gtest'};
1656 setEnv
('GTEST_ROOT', $gtest_root);
1660 my $rel_path = 'tests/googletest';
1661 my $sm_dir = Cwd
::abs_path
($rel_path);
1662 my $sm_src = File
::Spec
->catdir($sm_dir, 'googletest');
1663 my $sys_dir = File
::Spec
->catdir((system_default_install_dir
(),
1664 $is_windows ?
'googletest-distribution' : ''));
1667 if (-f File
::Spec
->catfile($sm_src, $gtest_sanity)) {
1670 elsif (-f File
::Spec
->catfile($sys_dir, $gtest_sanity)) {
1671 $opts{'gtest'} = $sys_dir;
1672 $gtest_root = $sys_dir;
1673 setEnv
('GTEST_ROOT', $gtest_root);
1676 print "Could not find GoogleTest, cloning...\n" if $opts{'verbose'};
1677 if (git_ensure_submodule
($rel_path)) {
1683 # Check for existing build
1684 $gtest_root = File
::Spec
->catdir($sm_dir, 'build', 'install');
1685 $build_gtest = ! -d
$gtest_root;
1686 $opts{'gtest'} = $sm_dir;
1687 # No need to set env. variable with submodule UNLESS we're in safetyprofile
1688 if ($opts{'safety-profile'}) {
1689 print "Setting GTEST_ROOT to ${gtest_root} for use in safety-profile.\n" if $opts{'verbose'};
1690 setEnv
('GTEST_ROOT', $gtest_root);
1694 if (!defined($gtest_root)) {
1695 die "ERROR: GoogleTest '$gtest_sanity' not found in submodule src '$sm_src' or " .
1696 "default install dir '$sys_dir', please pass a correct version of GoogleTest to --gtest\nStopped";
1699 if ($is_windows && -d File
::Spec
->catdir($gtest_root, 'bin')) {
1700 push_path
(\
%targetEnv, $gtest_root . $slash . 'bin');
1702 elsif (!$is_windows && -f File
::Spec
->catfile($gtest_root, 'lib', 'libgtest.so')) {
1703 push_libpath
(\
%targetEnv, $gtest_root . $slash . 'lib');
1707 if ($build_gtest && !$has_cmake) {
1708 die "ERROR: GoogleTest in $opts{'gtest'} must be built but can't find CMake\nStopped";
1711 if (exists $opts{'rapidjson'}) {
1712 if ($opts{'rapidjson'} eq '') {
1713 my $sanity = $optdep{'rapidjson'}->{sanity
};
1714 my $rel_path = 'tools/rapidjson';
1715 my $sm_dir = Cwd
::abs_path
($rel_path);
1716 my $sys_dir = File
::Spec
->catdir((system_default_install_dir
(),
1717 $is_windows ?
'RapidJSON' : ''));
1720 "Could not find RapidJSON (using '$sanity') in:\n".
1721 " Git Submodule: '$sm_dir'\n" .
1722 " Default Install Prefix: '$sys_dir'\n";
1723 my $rapidjson = undef;
1724 if (-f File
::Spec
->catfile($sm_dir, $sanity)) {
1725 $rapidjson = $sm_dir;
1727 elsif (-f File
::Spec
->catfile($sys_dir, $sanity)) {
1728 $rapidjson = $sys_dir;
1731 print "Could not find RapidJSON, cloning...\n" if $opts{'verbose'};
1732 if (git_ensure_submodule
($rel_path)) {
1733 $rapidjson = $sm_dir;
1737 if (defined($rapidjson)) {
1738 print "Using '$rapidjson' for RapidJSON\n" if ($opts{'verbose'});
1739 $opts{'rapidjson'} = $rapidjson;
1741 elsif (exists($defaulted->{'rapidjson'})) {
1742 print "${rapidjson_msg}Continuing without it.\n" if $opts{'verbose'};
1743 delete $opts{'rapidjson'};
1746 die "ERROR: ${rapidjson_msg}Stopped";
1751 my %use_system_pkg = map {$_, 1} qw
/ant glib qt xerces3 openssl/;
1753 my %use_win_default = (
1754 'openssl' => system_default_install_dir
() . '/OpenSSL',
1755 'xerces3' => system_default_install_dir
() . '/xerces-c');
1757 my %need_platform_macros = map {$_, 1} qw
/xerces3/;
1759 sub default_java_home
{
1760 my $host = $opts{'host'};
1762 if ($host eq 'macosx') {
1763 $result = `/usr/libexec/java_home`;
1768 $result = which
('javac');
1770 die "ERROR: No javac in PATH.\nStopped";
1772 while (-l
$result) {
1773 $result = readlink($result);
1776 return dirname
(dirname
($result))
1780 # Detect and populate dependency info from environment variables
1781 # or system-wide default paths.
1782 for my $key (keys %optdep) {
1783 if (exists $opts{$key} && $opts{$key} eq '') {
1784 if (defined $optdep{$key}->{env
} && $ENV{$optdep{$key}->{env
}}) {
1785 $opts{$key} = $ENV{$optdep{$key}->{env
}};
1787 if ($key eq 'java') {
1788 ## when the environment variable JAVA_HOME is set to a JRE location,
1789 ## try to resolve JAVA_HOME based on the location of javac
1790 my $java_home = default_java_home
();
1791 if (!-r
"$opts{$key}$slash$optdep{'java'}->{sanity}" and $java_home ne '') {
1792 $opts{'java'} = $java_home;
1796 elsif (!$is_windows && exists $use_system_pkg{$key}) {
1797 $opts{$key} = '/usr';
1798 print "Defaulting $key to $opts{$key}\n" if $opts{'verbose'};
1800 elsif ($is_windows && exists $use_win_default{$key}) {
1801 my $dir = $use_win_default{$key};
1807 die "Default '$key' directory '$dir' not found.\nStopped";
1810 print "Defaulting $key to $opts{$key}\n" if $opts{'verbose'};
1812 elsif ($key eq 'java') {
1814 $opts{'java'} = default_java_home
();
1816 if ($opts{'java'} eq '') {
1817 die "ERROR: --$key requires a value.\nStopped";
1820 elsif (exists $optdep{$key}->{env
} && !$optdep{$key}->{may_be_blank
}) {
1821 die "ERROR: --$key requires a value.\nStopped";
1828 for my $f (@features) {
1829 my ($key, $value) = split(/=/, $f);
1830 if ($key eq $feat) {
1837 if ($opts{'java'}) {
1838 push(@features, 'java=1');
1840 my $feat = 'java_pre_jpms';
1841 unless (has_feature
($feat)) {
1842 my $javac = File
::Spec
->catfile($opts{'java'}, 'bin', 'javac');
1843 open(my $vers, "\"$javac\" -version |");
1845 if (/javac (\d+)/) {
1846 print "Found javac major version $1\n" if $opts{'verbose'};
1848 push(@features, "$feat=0");
1849 print "Feature $feat=0 due to Java version\n" if $opts{'verbose'};
1862 setEnv
($e, $opts{$key}, $notdir);
1866 # Enable MPC features and populate expected environment variables
1867 # for all required "optional" dependencies.
1868 for my $key (keys %optdep) {
1869 if (exists $opts{$key}) {
1870 print "Enabling $key\n" if $opts{'verbose'};
1871 my $e = $optdep{$key}->{env
};
1872 my $s = $optdep{$key}->{sanity
};
1873 my $m = $optdep{$key}->{mpc
};
1874 if ($opts{$key} ne 'skip_version_check') {
1875 env_from_opt
($key, $e) if defined $e;
1876 if (ref $s eq 'HASH') {
1878 for my $alt (keys %{$s}) {
1879 if (-r
$targetEnv{$e} . '/' . $alt) {
1880 print "Found $key at $targetEnv{$e} using alternative $alt\n"
1881 if $opts{'verbose'};
1883 push(@features, $s->{$alt}) if defined $s->{$alt};
1886 print "Didn't find $key at $targetEnv{$e} using alternative $alt\n"
1887 if $opts{'verbose'};
1890 die "ERROR: Can't find $key at $targetEnv{$e}.\nStopped";
1893 elsif ($s && !-r
$targetEnv{$e} . '/' . $s) {
1894 die "ERROR: Can't find $key at $targetEnv{$e} (using $s).\nStopped";
1897 push(@features, $m) if $m;
1898 push(@platformmacros, $m) if $need_platform_macros{$key};
1902 if ($is_windows && !$opts{'optimize'}) { # look for nonstandard vcpkg layout
1903 for my $key ('xerces3', 'openssl') {
1904 my $env = $optdep{$key}->{env
};
1905 if ($opts{$key} && $targetEnv{$env}) {
1906 if (-d
$targetEnv{$env} . '/debug/lib') {
1907 print "Using debug/lib subdir for $key\n" if $opts{'verbose'};
1909 $libenv =~ s/_?ROOT$/_LIBDIR/;
1910 setEnv
($libenv, $targetEnv{$env} . '/debug/lib');
1911 $opts{$key . '-debugbin'} = 1;
1917 ## OpenSSL version-detection / feature-injection
1918 if ($opts{'openssl'} && $opts{'openssl'} ne 'skip_version_check') {
1919 my $ssl_version_file = $opts{'openssl'} . '/' . $optdep{'openssl'}->{sanity
};
1921 open my $fh, '<', $ssl_version_file
1922 or die "ERROR: Failed to open '$ssl_version_file' for OpenSSL version detection.\nStopped";
1925 if (/^\s*#\s*define\s*OPENSSL_VERSION_TEXT\s*"([^"]*)"/) {
1927 print "OpenSSL version detected: \"$ver\"\n" if $opts{'verbose'};
1928 if ($ver =~ /OpenSSL[\W]+1\.1/ || $ver =~ /OpenSSL[\W]+3\./) {
1929 print "OpenSSL 1.1+ MPC feature enabled\n" if $opts{'verbose'};
1930 push(@features, 'openssl11=1');
1937 sub win32_cmake_generator
{
1940 my %map = ('vc9' => 'Visual Studio 9 2008',
1941 'vc10' => 'Visual Studio 10 2010',
1942 'vc11' => 'Visual Studio 11 2012',
1943 'vc12' => 'Visual Studio 12 2013',
1944 'vc14' => 'Visual Studio 14 2015',
1945 'vs2017' => 'Visual Studio 15 2017',
1946 'vs2019' => 'Visual Studio 16 2019',
1947 'vs2022' => 'Visual Studio 17 2022');
1949 die "ERROR: Unsupported Visual Studio version '$ver' supplied.\nStopped"
1950 if ! exists $map{$ver};
1956 print("Building GoogleTest...\n");
1958 my $cwd = Cwd
::getcwd
();
1959 my $build_dir = $opts{'gtest'} . $slash . 'build';
1960 my $install_dir = $build_dir . $slash . 'install';
1961 my $cmake = $opts{'cmake'};
1962 my @cmake_platform_args = $is_windows ?
1963 ('-Dgtest_force_shared_crt=ON',
1964 '-DCMAKE_CXX_FLAGS=/D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING=1',
1965 '-G', '"' . win32_cmake_generator
($opts{'compiler_version'}) . '"',
1966 '-A', $opts{'compiler_target_architecture'}) : ();
1967 if ($opts{'nonstdcompiler'}) {
1968 push @cmake_platform_args, "-DCMAKE_CXX_COMPILER=$opts{'compiler'}";
1970 my @cmake_cmds = ([$cmake,
1971 "-DCMAKE_INSTALL_PREFIX=$install_dir",
1972 '-DCMAKE_INSTALL_LIBDIR=lib',
1973 '-DCMAKE_POSITION_INDEPENDENT_CODE=TRUE',
1974 @cmake_platform_args,
1976 ["$cmake", "--build", ".", "--target", "install"]);
1979 or die "ERROR '$!': failed to make directory $build_dir from $cwd.\nStopped"
1983 or die "ERROR '$!': failed to make directory $install_dir from $cwd.\nStopped"
1984 if ! -d
$install_dir;
1986 my $cd_build_dir = ChangeDir
->new($build_dir);
1987 for my $cmd (@cmake_cmds) {
1988 run_command
($cmd, capture
=> [undef, dump_on_failure
=> 1]) == 0
1989 or die "ERROR: Invoking @{$cmd} failed.\nStopped";
1992 print("Done Building GoogleTest\n");
1995 if (exists $opts{'jboss'} && !exists $opts{'java'}) {
1996 die "ERROR: --java is required for --jboss (OpenDDS JMS Provider).\nStopped";
1999 if (exists $opts{'jboss'} && !exists $opts{'ant'}) {
2000 die "ERROR: --ant is required for --jboss (OpenDDS JMS Provider).\nStopped";
2003 if (exists $opts{'wireshark-cmake'}) {
2004 if (exists $opts{'wireshark'}) {
2005 die "ERROR: --wireshark and --wireshark-cmake can not be used at the same time.\nStopped";
2008 if (! -d
($opts{'wireshark-build'} . '/' . $opts{'wireshark-lib'})) {
2009 if ($wireshark_lib_defaulted) {
2010 die "ERROR: The default value for wireshark-lib: " . $opts{'wireshark-lib'} .
2011 " does not exist, please supply wireshark-lib with the correct value";
2014 die "ERROR: The supplied wireshark-lib: " . $opts{'wireshark-lib'} . " does not exist.";
2019 if (exists $opts{'wireshark-cmake'} && !exists $opts{'wireshark-build'}) {
2020 die "ERROR: --wireshark-build are required with --wireshark-cmake.\nStopped";
2023 if (exists $opts{'wireshark-lib'} && !exists $opts{'wireshark-cmake'}) {
2024 die "ERROR: --wireshark-cmake and --wireshark-build is required for --wireshark-lib.\nStopped";
2027 if (exists $opts{'wireshark-build'} && !exists $opts{'wireshark-cmake'}) {
2028 die "ERROR: --wireshark-cmake is required for --wireshark-build.\nStopped";
2031 if ($opts{'glib'}) {
2032 if (!-r
"$opts{'glib'}/lib/glib-2.0/include/glibconfig.h") {
2033 my $pc = `pkg-config --cflags-only-I glib-2.0`;
2035 if ($pc =~ m!-I$opts{'glib'}/([-\w/]+)/glib-2.0/include!) {
2036 print "pkg-config found GLIB_LIB_DIR=$1\n" if $opts{'verbose'};
2037 setEnv
('GLIB_LIB_DIR', $1);
2040 print "Failed to locate glibconfig.h using pkg-config ($pc). Set the " .
2041 "environment variable GLIB_LIB_DIR and re-run MPC.\n";
2047 my ($buildEnvRef, $var, $path) = @_;
2048 if (exists $buildEnvRef->{$var}) {
2049 $buildEnvRef->{$var} .= $specific{'pathsep'} . $path;
2052 $buildEnvRef->{$var} = $path;
2057 my ($buildEnvRef, $path) = @_;
2058 push_env_dir
($buildEnvRef, 'PATH', $path);
2062 my ($buildEnvRef, $path) = @_;
2063 my $build = $buildEnvRef->{'build'};
2064 my $platform = $opts{$build};
2065 my $libpathname = $platforminfo{$platform}->{'libpath'};
2066 push_env_dir
($buildEnvRef, $libpathname, $path);
2070 if (exists $opts{'qt'}) {
2071 my $qglobal = "QtCore" . $slash . "qglobal.h";
2073 my $qt_bin; # location of Qt's code generators (like moc)
2074 my $qt_lib; # where linker should look for input (location of .lib or .so)
2075 my $qt_path; # add to PATH or LD_LIBRARY_PATH (location of .dll or .so.*)
2076 my $qt_bin_suffix = exists $ENV{'QT5_SUFFIX'} ?
$ENV{'QT5_SUFFIX'} : '';
2077 my $qt_moc = "moc" . $qt_bin_suffix . $exeext;
2078 my $qt_default_suffix = "-qt5";
2079 my $qt_moc_default_suffix = "moc" . $qt_default_suffix . $exeext;
2080 my $qt_help_mesg = ", stopped\nPlease either install Qt or provide the correct " .
2081 "Qt5 locations (see docs/qt.md for details).\n";
2083 if ($try_to_use_qt_system_pkg) {
2084 # Try to use pkg-config to get Qt locations
2085 `pkg-config --print-variables Qt5Core`;
2087 die "ERROR: Trying to use system Qt package but could not confirm " .
2088 "Qt and/or pkg-config exists on the system$qt_help_mesg";
2090 $qt_include = `pkg-config --variable=includedir Qt5Core`;
2091 die "ERROR: could not resolve system Qt include location$qt_help_mesg" if ($?
);
2093 $qt_bin = `pkg-config --variable=host_bins Qt5Core`;
2094 die "ERROR: could not resolve system Qt build tools location$qt_help_mesg" if ($?
);
2096 $qt_lib = `pkg-config --variable=libdir Qt5Core`;
2097 die "ERROR: could not resolve system Qt lib location$qt_help_mesg" if ($?
);
2101 if (exists $opts{'qt-include'}) {
2102 if (!length($opts{'qt-include'})) {
2103 die "ERROR: --qt-include requires an argument$qt_help_mesg";
2105 $qt_include = $opts{'qt-include'};
2108 $qt_include = $targetEnv{'QTDIR'} . $slash . 'include';
2111 if (exists $ENV{'QT5_BINDIR'}) {
2112 $qt_bin = $ENV{'QT5_BINDIR'};
2115 $qt_bin = $targetEnv{'QTDIR'} . $slash . 'bin';
2118 if (exists $ENV{'QT5_LIBDIR'}) {
2119 $qt_lib = $ENV{'QT5_LIBDIR'};
2122 $qt_lib = $targetEnv{'QTDIR'} . $slash . ($is_windows ?
'bin' : 'lib');
2127 # Try to guess if Qt vcpkg is being used
2128 my $vcpkg_tools = join($slash, $targetEnv{'QTDIR'}, "tools", "qt5");
2130 (-r
$vcpkg_tools . $slash . 'bin' . $slash . $qt_moc) &&
2131 !exists $ENV{'QT5_LIBDIR'} &&
2132 !exists $ENV{'QT5_BINDIR'};
2133 if ($assume_vcpkg) {
2134 $qt_bin = $vcpkg_tools . $slash . 'bin';
2136 $qt_lib = join($slash, $targetEnv{'QTDIR'}, "debug", "lib");
2137 $qt_path = join($slash, $targetEnv{'QTDIR'}, "debug",
2138 ($is_windows ?
'bin' : 'lib'));
2141 $qt_lib = join($slash, $targetEnv{'QTDIR'}, 'lib');
2145 # Check for Qt Headers using qglobal.h
2146 # Also try to detect if Qt Headers were just put in the include directory or
2147 # put in qt5 directory inside the include directory. For example, the former
2148 # might happen on Windows with prebuilt Qt while the latter might be the
2149 # case with Linux with Qt installed from package manager.
2150 if (! -r
$qt_include . $slash . $qglobal) {
2151 my $qt_subdir = $qt_include . $slash . 'qt5';
2152 if (-r
$qt_subdir . $slash . $qglobal) {
2153 $qt_include = $qt_subdir;
2156 die "ERROR: Could not find Qt headers at $qt_include" .
2157 " ($qglobal could not be found)$qt_help_mesg";
2161 # Check for Qt Tools using moc
2162 if (! -r
$qt_bin . $slash . $qt_moc) {
2163 # If QT5_SUFFIX isn't defined, maybe it needs a suffix
2164 if ((!exists $ENV{'QT5_SUFFIX'}) &&
2165 (-r
$qt_bin . $slash . $qt_moc_default_suffix)) {
2166 $qt_bin_suffix = $qt_default_suffix;
2169 die "ERROR: Could not find Qt build tools at $qt_bin" .
2170 " ($qt_moc could not be found)$qt_help_mesg";
2174 setEnv
('QT5_INCDIR', $qt_include);
2175 setEnv
('QT5_BINDIR', $qt_bin);
2176 setEnv
('QT5_SUFFIX', $qt_bin_suffix);
2177 setEnv
('QT5_LIBDIR', $qt_lib);
2178 push_libpath
(\
%targetEnv, $qt_path);
2180 elsif (exists $opts{'qt-include'}) {
2181 die "ERROR: --qt-include requires --qt, stopped\n";
2184 sub write_host_workspace
{
2185 my %buildEnv = %{shift()};
2186 my $MWC = backup_and_open
($buildEnv{'DDS_ROOT'} . '/host_tools.mwc');
2189 $(ACE_ROOT)/ace/ace.mpc
2190 $(ACE_ROOT)/apps/gperf/src
2192 dds/DCPS/OpenDDS_Util.mpc
2194 java/idl2jni/codegen
2196 print $MWC " \$(TAO_ROOT)/tao/tao.mpc\n" if $opts{'safety-profile'};
2199 print "Wrote host_tools.mwc in $buildEnv{'DDS_ROOT'}\n" if $opts{'verbose'};
2200 dump_and_unlink
($MWC) if $opts{'dry-run'};
2204 my $buildEnv = shift;
2205 for my $k (keys %{$buildEnv}) {
2206 next if $k eq 'build';
2207 if ($buildEnv->{$k} =~
2208 /^\Q$specific{'refpre'}\E$k\Q$specific{'refpost'}\E(.*)/) {
2211 print "ENV: Appending $1 to $k\n" if $opts{'verbose'};
2215 $ENV{$k} = $buildEnv->{$k};
2216 print "ENV: Setting $k to $buildEnv->{$k}\n" if $opts{'verbose'};
2221 sub disable_feature
{
2222 my($featureArray, $feature) = @_;
2223 $feature =~ s/-/_/g;
2224 push(@
{$featureArray}, "$feature=0");
2227 sub get_default_features
{
2228 my $buildEnv = shift;
2230 my %default_features;
2231 my $file = "$buildEnv->{ACE_ROOT}/bin/MakeProjectCreator/config/default.features";
2233 open(my $fh, '<', $file) or die "ERROR: Could not open $file: $!";
2234 while (my $row = <$fh>) {
2240 my ($key, $value) = split(/\s*=\s*/, $row);
2241 $default_features{$key} = $value;
2244 return %default_features;
2247 sub get_requested_features
{
2248 my %requested_features;
2249 for my $f (@features) {
2250 my ($key, $value) = split(/=/, $f);
2251 $value = "1" unless defined $value;
2252 $requested_features{$key} = $value;
2254 return %requested_features;
2258 my $buildEnv = shift;
2260 my %features = get_default_features
($buildEnv);
2261 my %requested_features = get_requested_features
();
2262 for my $key (keys(%requested_features)) {
2263 $features{$key} = $requested_features{$key};
2268 sub write_opendds_mwc
{
2272 $args = join(', ', (map {perlstring
($_)} @
{$args}));
2274 my $path = "$root/bin/opendds_mwc.pl";
2275 my $fd = backup_and_open
($path);
2278 if (!defined(\$ENV{ACE_ROOT}) || !defined(\$ENV{MPC_ROOT})) {
2279 die("The enviroment needs to be setup.");
2281 system('perl', "\$ENV{ACE_ROOT}/bin/mwc.pl", $args, \@ARGV) == 0
2282 or die("Failed to run mwc: \$!");
2285 print "Wrote $path\n" if $opts{'verbose'};
2286 dump_and_unlink
($fd) if $opts{'dry-run'};
2292 sub generate_workspace
{
2293 my $buildEnv = shift;
2294 $buildtao = $force_ace_tao;
2295 my $is_target = $buildEnv->{'build'} eq 'target';
2297 for my $feat (qw
/built-in-topics ownership-profile/) {
2298 if (exists $opts{$feat} && !$opts{$feat}) {
2299 disable_feature
(\
@features, $feat);
2303 if ($opts{'security'}) {
2304 disable_feature
(\
@features, 'no-opendds-security');
2307 # default of these depends on whether we are doing a safety-profile build
2308 for my $feat (qw
/content
-subscription content
-filtered
-topic
2309 multi
-topic query
-condition ownership
-kind
-exclusive
2310 object
-model
-profile persistence
-profile
2311 no-opendds
-safety
-profile
/) {
2312 if (defined $opts{'no-opendds-safety-profile'}) {
2313 if (!(exists $opts{$feat} && $opts{$feat})) {
2314 disable_feature
(\
@features, $feat);
2317 elsif (exists $opts{$feat} && !$opts{$feat}) {
2318 disable_feature
(\
@features, $feat);
2322 if ($is_target && $opts{'target'} eq 'android') {
2323 # We can't detect C++11 compatibility in cross compilers at the moment,
2324 # but all the NDKs we officially support are C++11+ by default, so enable
2325 # C++11 features unless an explicit 'no_cxx11' feature already is set.
2326 my $feat = 'no_cxx11';
2327 unless (has_feature
($feat)) {
2328 disable_feature
(\
@features, $feat);
2329 print "Setting $feat=0 for Android\n";
2332 # Disable including $JAVA_HOME/include on Android. Android NDK includes a
2334 disable_feature
(\
@features, 'jni_include')
2337 my $mpctype = (!$is_windows || ($cross_compile && $is_target))
2338 ?
'gnuace' : $opts{'compiler_version'};
2340 if ($mpctype eq 'gnuace') {
2342 if (@features || $cross_compile) {
2343 print "Writing $buildEnv->{'DDS_ROOT'}/user_macros.GNU\n"
2344 if $opts{'verbose'};
2345 $UM = backup_and_open
($buildEnv->{'DDS_ROOT'} . '/user_macros.GNU');
2348 for my $feat (@features) {
2351 print $UM ($feat =~ /=/ ?
$feat : "$feat=1"), "\n"
2352 unless $need_platform_macros{$key};
2354 if ($cross_compile) {
2356 OPENDDS_IDL = $(HOST_DDS)/bin/opendds_idl
2357 OPENDDS_IDL_DEP = $(OPENDDS_IDL)$(HOST_EXE_EXT)
2358 IDL2JNI = $(HOST_DDS)/bin/idl2jni
2359 IDL2JNI_DEP = $(IDL2JNI)$(HOST_EXE_EXT)
2364 dump_and_unlink
($UM) if $UM && $opts{'dry-run'};
2367 if ($opts{'safety-profile'} && $is_target) {
2368 $buildtao = 0; # TAO will be built separately
2371 # build tao if tao_idl does not exist
2372 $buildtao = $buildtao || !-x
"$buildEnv->{'ACE_ROOT'}/bin/tao_idl$exeext";
2375 locate_mpc
($ace_src);
2377 # Append to default.features
2379 push(@features, 'cross_compile') if $cross_compile;
2381 if ($platforminfo{$opts{'target'}}->{'needs_i2jrt_corba'} && $opts{'java'}) {
2382 if ($opts{'verbose'}) {
2383 print "Target platform needs i2jrt_corba.jar, forcing java_pre_jpms=0 to get it\n";
2386 for my $i (0 .. scalar $#features) {
2387 if ($features[$i] =~ /^java_pre_jpms/) {
2388 $features[$i] = 'java_pre_jpms=0';
2393 push(@features, "java_pre_jpms=0");
2397 if ($opts{'java'} && $cross_compile) {
2398 push(@features, "jni_check=0");
2401 if ($buildtao && @features) {
2402 my $df_file = $buildEnv->{'ACE_ROOT'} .
2403 '/bin/MakeProjectCreator/config/default.features';
2404 my $DF = $opts{'dry-run'} ? File
::Temp
->new()
2405 : new FileHandle
(">>$df_file");
2406 for my $f (@features) {
2407 print $DF ($f =~ /=/ ?
$f : "$f=1"), "\n";
2410 if ($opts{'verbose'}) {
2411 print '' . ($wrote_df ?
'Appended to' : 'Wrote') .
2412 " $buildEnv->{'ACE_ROOT'}/.../default.features\n";
2414 dump_and_unlink
($DF) if $opts{'dry-run'};
2417 if (!$buildtao && !defined $opts{'safety-profile'}) {
2418 # Check for compatibility between the requested features/macros
2419 # and the pre-built ACE/TAO.
2420 my %existing_features = get_default_features
($buildEnv);
2421 my %requested_features = get_requested_features
();
2422 for my $f (@ace_features) {
2423 if (defined $requested_features{$f}) {
2424 if (!defined $existing_features{$f}) {
2425 die "ERROR: Requested feature $f not defined for ACE/TAO";
2427 elsif ($requested_features{$f} != $existing_features{$f}) {
2428 die "ERROR: Feature $f set to $requested_features{$f} but has " .
2429 "value $existing_features{$f} in ACE/TAO";
2434 my $file = "$buildEnv->{'ACE_ROOT'}/include/makeinclude/platform_macros.GNU";
2435 my %existing_macros;
2437 open(my $fh, '<', $file) or die "ERROR: Could not open $file: $!";
2438 while (my $row = <$fh>) {
2440 $row =~ s/\s*#.*$//;
2441 if ($row =~ /^\s*(\w+)\s*[:?+]?=\s*(.*)$/) {
2442 my ($key, $value) = ($1, $2);
2443 $existing_macros{$key} = $value;
2446 my %requested_macros;
2447 for my $f (@platformmacros, @
{$opts{'macros'}}) {
2448 my ($key, $value) = split(/=/, $f);
2449 $value = "1" unless defined $value;
2450 $requested_macros{$key} = $value;
2452 for my $key (@ace_macros) {
2453 if (exists $opts{$key}) {
2454 my $macro = ($key eq 'static') ?
'static_libs_only' : $key;
2455 $requested_macros{$macro} = $opts{$key};
2458 for my $f (@ace_macros) {
2459 if (defined $requested_macros{$f}) {
2460 if (!defined $existing_macros{$f}) {
2461 die "ERROR: Requested macro $f not defined for ACE/TAO";
2463 elsif ($requested_macros{$f} != $existing_macros{$f}) {
2464 die "ERROR: Macro $f set to $requested_macros{$f} but has " .
2465 "value $existing_macros{$f} in ACE/TAO";
2473 my $custom_ws = "OpenDDS_custom.mwc";
2474 if (exists($opts{'workspace'})) {
2475 backup_and_copy
($opts{'workspace'}, $custom_ws);
2479 if (-r
"$buildEnv->{'DDS_ROOT'}/host_tools.mwc") {
2480 $ws = 'host_tools.mwc';
2482 elsif (-r
$custom_ws) {
2485 elsif (!$tests && $buildtao) {
2486 $ws = 'DDS_TAOv2.mwc';
2488 elsif (!$tests && !$buildtao) {
2489 $ws = 'DDS_no_tests.mwc';
2492 $ws = 'DDS_TAOv2_all.mwc';
2498 my $static = (($opts{'static'} && $is_windows) ||
2499 ($cross_compile && $buildEnv->{'build'} eq 'host' && $mpctype ne 'gnuace'));
2501 # We are not using CIAO or DAnCE, but MPC.cfg expands $CIAO_ROOT and
2502 # $DANCE_ROOT so leaving them empty/undefined would cause /MPC/config
2503 # to be on the include path for .mpb files.
2504 for my $var ('CIAO_ROOT', 'DANCE_ROOT') {
2505 $buildEnv->{$var} = 'unused' unless defined $buildEnv->{$var};
2508 my %savedEnv = %ENV;
2509 print "ENV: saving current environment\n" if $opts{'verbose'};
2510 mergeToEnv
($buildEnv);
2512 my @mwc_common_args = ('-type', $mpctype, @mpcopts);
2514 push(@mwc_common_args, '-static');
2518 my %existing_features = get_default_features
($buildEnv);
2519 my %requested_features = get_requested_features
();
2520 my @features_to_add;
2521 for my $feature (keys(%requested_features)) {
2522 my $value = $requested_features{$feature};
2523 push(@features_to_add, "$feature=$value") unless exists($existing_features{$feature});
2525 if (@features_to_add) {
2526 push(@mwc_common_args, '-features', join(',', @features_to_add));
2530 # Generate our own mwc wrapper script
2531 write_opendds_mwc
($buildEnv->{'DDS_ROOT'}, [@mwc_common_args]);
2533 my @mwc = ('perl', "$ENV{ACE_ROOT}/bin/mwc.pl");
2534 print 'Running MPC to generate ', ($mpctype eq 'gnuace' ?
'makefiles' :
2535 'project files'), ".\n";
2536 if (run_command
([@mwc, @mwc_common_args, "$buildEnv->{'DDS_ROOT'}$slash$ws"])) {
2537 die "ERROR: Error from MPC, stopped";
2539 $buildEnv->{'mpctype'} = $mpctype;
2541 # If this is a target safety profile build
2542 if (defined $opts{'no-opendds-safety-profile'}) {
2543 # Generate ACE workspace separately, to exclude TAO
2544 if (run_command
([@mwc, @mwc_common_args, "$buildEnv->{'ACE_ROOT'}/ace"])) {
2545 die "ERROR: Error from MPC, stopped";
2550 print "ENV: restoring previous environment\n" if $opts{'verbose'};
2552 $ws =~ s/\.mwc$/.sln/;
2553 $opts{'solution_file'} = $ws;
2556 sub convert_environment
{
2559 $$val =~ s/%(\w+)%/\$\{$1\}/g;
2562 sub write_environment
{
2563 my %buildEnv = %{shift()};
2566 if ($buildEnv{'mpctype'} eq 'gnuace') {
2567 if (!$opts{'dry-run'}) {
2568 move
($dir . '/GNUmakefile', $dir . '/GNUmakefile.dist');
2570 $MK = backup_and_open
($dir . '/GNUmakefile');
2573 my $SE = backup_and_open
($dir . '/setenv.' . $specific{'ext'});
2575 my $args_ = join(' ', map {/ / ?
('"' . $_ . '"') : $_} @ARGS);
2576 print $SE "$specific{'comment'} OpenDDS configure script: $0 $args_\n";
2577 print $MK "$specific{'comment'} OpenDDS configure script: $0 $args_\n" if $MK;
2579 for my $key (sort(keys(%buildEnv))) {
2580 if ($key ne 'build' && $key ne 'mpctype') {
2581 my $value = $buildEnv{$key};
2582 $value =~ s/^"(.*)"$/$1/g;
2585 print $SE "set \"$key=$value\"\n";
2588 my $posix_value = $value;
2589 $posix_value =~ s/"/\\"/g;
2590 print $SE "export $key=\"$posix_value\"\n";
2594 convert_environment
(\
$value) if $is_windows;
2595 print $MK "export $key := $value\n";
2601 print "Wrote $dir/setenv.$specific{'ext'}\n" if $opts{'verbose'};
2602 dump_and_unlink
($SE) if $opts{'dry-run'};
2605 print $MK "include GNUmakefile.dist\n";
2607 print "Wrote $dir/GNUmakefile, wrapping original GNUmakefile.dist\n"
2608 if $opts{'verbose'};
2609 dump_and_unlink
($MK) if $opts{'dry-run'};
2613 sub check_mac_version
{
2614 my $buildEnvRef = shift;
2615 if (-r
"$buildEnvRef->{ACE_ROOT}/ace/config-macosx.h") {
2616 my $cfg = new FileHandle
("$buildEnvRef->{ACE_ROOT}/ace/config-macosx.h");
2618 if (/__MAC_OS_X_VERSION_MAX_ALLOWED/) {
2624 die "ERROR: This version of ACE doesn't contain the required configuration " .
2625 "files for Apple macOS. Stopped";
2628 sub configure_build
{
2629 my $buildEnvRef = shift;
2630 if (-r
"$buildEnvRef->{ACE_ROOT}/ace/config.h" && !$force_ace_tao) {
2631 print "ACE_ROOT/ace/config.h exists, skipping configuration of ACE+TAO\n";
2634 check_mac_version
($buildEnvRef) if $opts{'host'} eq 'macosx';
2636 write_config_h
($buildEnvRef);
2637 write_default_features
($buildEnvRef);
2638 write_platform_macros
($buildEnvRef);
2640 write_opendds_configh
($buildEnvRef);
2641 generate_workspace
($buildEnvRef);
2642 write_environment
($buildEnvRef, $buildEnvRef->{'DDS_ROOT'});
2644 if ($buildEnvRef->{'build'} eq 'target') {
2645 write_cmake_file
($buildEnvRef);
2649 sub write_cross_compile_makefile
{
2650 my $MF = backup_and_open
('GNUmakefile');
2651 my $safety_profile_step = $opts{'safety-profile'} ?
2652 "\tcd $targetEnv{'ACE_ROOT'}/ace && " .
2653 '$(MAKE) $(if $(filter all,$@),ACE,$@)' . "\n" : '';
2655 # OpenDDS configure script: $0 @ARGS
2656 all clean realclean depend:
2657 \tcd build/host && \$(MAKE) \$@
2658 $safety_profile_step\tcd build/target && \$(MAKE) \$@
2659 .PHONY: all clean realclean depend
2662 print "Wrote top-level GNUmakefile for cross-compile\n" if $opts{'verbose'};
2663 dump_and_unlink
($MF) if $opts{'dry-run'};
2667 my($sub, $top) = @_;
2668 my $subdir = $opts{'dry-run'} ?
$sub : Cwd
::abs_path
($sub);
2669 my $parent = $opts{'dry-run'} ?
$top : Cwd
::abs_path
($top);
2670 if ($opts{'dry-run'} && $top eq '.' && looksRelative
($sub)) {
2671 return $slash . $sub;
2673 if (index($subdir, $parent) == 0) {
2674 return substr($subdir, length($parent));
2679 sub add_dependency_paths
{
2681 for my $key ('openssl', 'xerces3') {
2683 next if $opts{$key} eq '/usr' || $opts{$key} eq 'skip_version_check';
2684 my $suffix = $slash . 'bin';
2685 if ($opts{$key . '-debugbin'}) {
2686 $suffix = $slash . 'debug' . $suffix;
2688 $dirs{$targetEnv{$optdep{$key}->{env
}} . $suffix} = 1;
2691 for my $d (keys %dirs) {
2692 push_libpath
(\
%targetEnv, $d);
2695 if ($opts{'openssl'} && $ENV{'SSL_LIBDIR'}) {
2696 push_libpath
(\
%targetEnv, $ENV{'SSL_LIBDIR'});
2700 my $cloned_build = $cross_compile && $build_host_tools;
2701 if ($cloned_build) {
2702 clone_host_and_target
('.');
2703 setHostEnv
('DDS_ROOT', 'build/host');
2704 setEnv
('HOST_DDS', 'build/host');
2705 setEnv
('DDS_ROOT', 'build/target');
2707 my $tao_clone = $opts{'safety-profile'} ?
'host' : 'target';
2708 my $ace_sub_dds = nested
($ace_src, '.');
2709 my $tao_sub_dds = nested
($tao_src, '.');
2710 my $tao_sub_ace = nested
($tao_src, $ace_src);
2713 setHostEnv
('ACE_ROOT', 'build/host' . $ace_sub_dds);
2714 setEnv
('HOST_ACE', 'build/host' . $ace_sub_dds);
2715 setEnv
('ACE_ROOT', 'build/target' . $ace_sub_dds);
2718 clone_host_and_target
($ace_src);
2719 setHostEnv
('ACE_ROOT', $ace_src . '/build/host');
2720 setEnv
('HOST_ACE', $ace_src . '/build/host');
2721 setEnv
('ACE_ROOT', $ace_src . '/build/target');
2723 setHostEnv
('TAO_ROOT', $ace_src . '/build/host' . $tao_sub_ace);
2724 setEnv
('TAO_ROOT', $ace_src . '/build/' . $tao_clone . $tao_sub_ace);
2729 setHostEnv
('TAO_ROOT', 'build/host' . $tao_sub_dds);
2730 setEnv
('TAO_ROOT', 'build/' . $tao_clone . $tao_sub_dds);
2732 elsif (!$tao_sub_ace) {
2733 if ($opts{'safety-profile'}) {
2734 setHostEnv
('TAO_ROOT', $tao_src);
2735 setEnv
('TAO_ROOT', $tao_src);
2738 clone_host_and_target
($tao_src);
2739 setHostEnv
('TAO_ROOT', $tao_src . '/build/host');
2740 setEnv
('TAO_ROOT', $tao_src . '/build/target');
2744 push_path
(\
%targetEnv, $hostEnv{'ACE_ROOT'} . $slash . 'bin');
2745 push_path
(\
%targetEnv, $hostEnv{'DDS_ROOT'} . $slash . 'bin');
2747 print "Cross-compile configuring host\n";
2749 write_host_workspace
(\
%hostEnv); # host_tools.mwc
2750 configure_build
(\
%hostEnv);
2752 print "Cross-compile configuring target\n";
2754 if ($opts{'safety-profile'}) {
2755 $opts{'no-opendds-safety-profile'} = 0; # only set for target
2758 unless ($opts{'static'}) {
2759 push_libpath
(\
%targetEnv, $targetEnv{'ACE_ROOT'} . $slash . 'lib');
2760 push_libpath
(\
%targetEnv, $targetEnv{'DDS_ROOT'} . $slash . 'lib');
2762 add_dependency_paths
();
2765 configure_build
(\
%targetEnv);
2767 write_environment
(\
%targetEnv, $targetEnv{'ACE_ROOT'} . '/ace')
2768 if $opts{'safety-profile'};
2770 write_cross_compile_makefile
() if !$is_windows;
2772 else { # does not require cloned builds
2773 setEnv
('ACE_ROOT', $ace_src);
2774 setEnv
('TAO_ROOT', $tao_src);
2775 setEnv
('DDS_ROOT', '.');
2777 if (!$build_host_tools && $opts{'host-tools'}) {
2778 setEnv
('HOST_DDS', $opts{'host-tools'});
2781 push_path
(\
%targetEnv, $targetEnv{'ACE_ROOT'} . $slash . 'bin');
2782 push_path
(\
%targetEnv, $targetEnv{'DDS_ROOT'} . $slash . 'bin');
2784 unless ($opts{'static'}) {
2785 push_libpath
(\
%targetEnv, $targetEnv{'ACE_ROOT'} . $slash . 'lib');
2786 push_libpath
(\
%targetEnv, $targetEnv{'DDS_ROOT'} . $slash . 'lib');
2788 add_dependency_paths
();
2791 if ($host_tools_only) {
2792 write_host_workspace
(\
%targetEnv);
2795 configure_build
(\
%targetEnv);
2798 print "Completed configuring OpenDDS, next ";
2799 if (!$is_windows || ($cross_compile && !$cloned_build)) {
2800 print "run '", (($^O
eq 'freebsd') ?
'g' : ''), "make'";
2802 elsif ($cloned_build) {
2803 print "compile build\\host\\host_tools.sln\n",
2804 "using the environment in build\\host\\setenv.cmd.\n",
2805 "Then build OpenDDS for $opts{'target'} by running make in ",
2810 print "build '", $opts{'solution_file'}, "' using the '",
2811 ($opts{'optimize'} ?
'Release' : 'Debug'), "' configuration";
2814 print " to compile ",
2815 ($cloned_build ?
"\nthe host and target builds of " : ''),
2816 "OpenDDS", (($buildtao || $cloned_build) ?
' and ACE+TAO' : '') ,".\n",
2817 "You can use the generated setenv.$specific{'ext'} script ",
2819 "in the\nbuild${slash}host and build${slash}target dirs " : ''),
2820 "to set environment\nvariables for future shell sessions.\n";
2821 if ($is_windows && !$cross_compile) {
2822 print "Start Visual Studio from this command prompt so that it inherits ",
2823 "the correct\nenvironment variables. Try running \"devenv $opts{'solution_file'}\".\n";
2826 sub write_cmake_file
{
2827 my $buildEnv = shift();
2829 my $module_dir = "$buildEnv->{'DDS_ROOT'}/cmake";
2830 mkpath
($module_dir) unless -d
$module_dir;
2831 my $fh = backup_and_open
($module_dir . '/config.cmake');
2833 sub whack_to_slash
{
2839 sub to_cmake_scalar
{
2841 return 'ON' if "$val" eq '1';
2842 return 'OFF' if "$val" eq '0';
2843 return '"' . whack_to_slash
($val) . '"';
2847 my @list = @
{$_[0]};
2848 return '"' . join(';', map {whack_to_slash
($_)} @list) . '"';
2851 sub to_cmake_value
{
2852 my $value = shift();
2854 my $ref_type = ref($value);
2855 if ($ref_type eq 'ARRAY') {
2856 return to_cmake_list
($value);
2858 elsif ($ref_type eq '') {
2859 return to_cmake_scalar
($value);
2862 die "ERROR: to_cmake_value invalid value type, stopped";
2866 sub print_cmake_config
{
2869 my $value = shift();
2871 $name = uc("OPENDDS_$name");
2874 print $fh "set($name ", to_cmake_value
($value), ")\n";
2877 sub generate_config_cmake
{
2879 my $buildEnv = shift();
2881 print_cmake_config
($fh, 'MPC', Cwd
::abs_path
($buildEnv->{'MPC_ROOT'}));
2882 print_cmake_config
($fh, 'ACE', Cwd
::abs_path
($buildEnv->{'ACE_ROOT'}));
2883 print_cmake_config
($fh, 'TAO', Cwd
::abs_path
($buildEnv->{'TAO_ROOT'}));
2885 print $fh "\n# Based on MPC features\n";
2889 feature
=> 'no_cxx11',
2894 feature
=> 'uses_wchar',
2901 name
=> 'SAFETY_PROFILE',
2902 feature
=> 'no_opendds_safety_profile',
2906 name
=> 'VERSIONED_NAMESPACE',
2907 feature
=> 'versioned_namespace',
2910 name
=> 'SUPPRESS_ANYS',
2911 feature
=> 'dds_suppress_anys',
2916 feature
=> 'dds_non_coverage',
2920 name
=> 'TAO_CORBA_E_COMPACT',
2921 feature
=> 'corba_e_compact',
2924 name
=> 'TAO_CORBA_E_MICRO',
2925 feature
=> 'corba_e_micro',
2928 name
=> 'TAO_MINIMUM_CORBA',
2929 feature
=> 'minimum_corba',
2933 feature
=> 'tao_no_iiop',
2938 name
=> 'TAO_GEN_OSTREAM',
2939 feature
=> 'gen_ostream',
2942 name
=> 'TAO_OPTIMIZE_COLLOCATED_INVOCATIONS',
2943 feature
=> 'optimize_collocated_invocations',
2947 my %features = get_features
($buildEnv);
2948 for my $config (@configs) {
2949 my $inverted = $config->{inverted
} // 0;
2950 my $default = $config->{default} // 0;
2952 if (exists($features{$config->{feature
}})) {
2953 $enabled = $features{$config->{feature
}} eq "1" ?
!$inverted : $inverted;
2956 $enabled = $default;
2958 print_cmake_config
($fh, $config->{name
}, $enabled);
2961 if (defined($cxx_std)) {
2962 print_cmake_config
($fh, 'OPENDDS_CXX_STD', $cxx_std);
2965 # TODO(iguessthislldo): Move to a smarter system that can use existing
2966 # ACE/TAO and that works with cross compiling.
2967 print $fh "\n# Based on configure script options\n";
2969 'built-in-topics' => 1,
2971 'content-filtered-topic' => 1,
2972 'content-subscription' => 1,
2978 'object-model-profile' => 1,
2980 'ownership-kind-exclusive' => 1,
2981 'ownership-profile' => 1,
2982 'persistence-profile' => 1,
2984 'query-condition' => 1,
2991 for my $opt (sort(keys(%opts_to_use))) {
2992 print_cmake_config
($fh, $opt, exists($opts{$opt}) ?
$opts{$opt} : $opts_to_use{$opt});
2994 print_cmake_config
($fh, 'features', \
@features);
2995 print_cmake_config
($fh, 'mpcopts', \
@mpcopts);
2997 print $fh "\n# Sanitizers\n";
2998 for my $name (sort(keys(%all_sanitizers))) {
2999 print_cmake_config
($fh, $name, exists($enabled_sanitizers{$name}) ?
1 : 0);
3001 if (scalar(@fsanitize)) {
3002 print_cmake_config
($fh, 'SANITIZER_COMPILER_ARGS', \
@sanitizer_compiler_args);
3003 print_cmake_config
($fh, 'SANITIZER_LINKER_ARGS', \
@sanitizer_linker_args);
3008 # Contains configuration variables for the FindOpenDDS cmake module based on
3009 # detected defaults and/or user-supplied switches. Feel free to edit them as
3010 # necessary, but keep in mind that they will be moved to config.cmake.bak.*
3011 # the next time the \$DDS_ROOT/configure script is executed.
3013 # THIS FILE WAS AUTO-GENERATED BY: $0 @ARGS
3016 generate_config_cmake
($fh, $buildEnv);
3017 dump_and_unlink
($fh) if $opts{'dry-run'};