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'},
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-github-latest!', 'Clone latest ACE/TAO/MPC from GitHub (no)',
228 'force-ace-tao', 'Force configuration of ACE/TAO (no)',
229 'no-disable-deprecated', 'Turn off disabling deprecated interfaces when' .
230 $argIndent . 'configuring ACE/TAO (no)',
232 ['Advanced configuration:',
233 'configh=s@', 'Extra text for config.h',
234 'macros=s@', 'Extra text for platform_macros.GNU',
235 'features=s@', 'Extra text for default.features',
236 'mpcopts=s@', 'Extra command-line options for MPC' .
237 $argIndent . 'This option can be given multiple times' .
238 $argIndent . 'For example:' .
239 $argIndent . ' --mpcopts=-value_template --mpcopts=build_flags+="-Wall -Werror"' .
240 $argIndent . 'turns into the following arguments for MPC:' .
241 $argIndent . ' -value_template build_flags+="-Wall -Werror"',
242 '<usage>mpc:OPT=VALUE', 'Extra command-line options for MPC' .
243 $argIndent . 'For example:' .
244 $argIndent . ' --mpc:value_template build_flags+="-Wall -Werror"' .
245 $argIndent . 'turns into the following arguments for MPC:' .
246 $argIndent . ' -value_template build_flags+="-Wall -Werror"' .
247 $argIndent . 'This option can be given multiple times',
248 'boottime!', 'Use CLOCK_BOOTTIME for timers (no)',
250 ['Optional dependencies for OpenDDS (disabled by default unless noted otherwise):',
251 'java:s', 'Java development kit (use JAVA_HOME)',
252 'jboss:s', 'JBoss application server (use JBOSS_HOME)',
253 'ant:s', 'Ant for JBoss (use ANT_HOME or system pkg)',
255 'Wireshark dev headers or source not built with' .
256 $argIndent . 'CMake (use WIRESHARK_SRC or system pkg)' .
257 $argIndent . 'Implies --glib',
258 'wireshark-cmake|wireshark_cmake:s',
259 'Wireshark source built with CMake, requires' .
260 $argIndent . '--wireshark-build. Requires --wireshark-lib if' .
261 $argIndent . 'guessing fails (use WIRESHARK_SRC)' .
262 $argIndent . 'Implies --glib',
263 'wireshark-build|wireshark_build=s', 'Wireshark CMake Build Location',
264 'wireshark-lib|wireshark_lib=s',
265 'Optional Wireshark CMake libraries location' .
266 $argIndent . 'relative to wireshark-build (guesses)',
267 'glib:s', 'GLib for Wireshark (use GLIB_ROOT or system pkg)',
268 '<default>rapidjson:s',
269 'RapidJSON for Wireshark dissector and JSON' .
270 $argIndent . 'Sample Serialization (Enabled by default,' .
271 $argIndent . 'use git submodule, RAPIDJSON_ROOT, or system pkg)',
272 'qt:s', 'Qt5 (use QTDIR or system pkg)',
273 'qt-include:s', 'Qt include dir (use QT5_INCDIR, QTDIR/include,' .
274 $argIndent . 'or system package)',
275 'xerces3:s', 'Xerces-C++ 3 for QoS XML handling, DDS Security',
276 'openssl:s', 'OpenSSL for DDS Security',
277 'cmake:s', 'Path to CMake for compiling GoogleTest' .
278 $argIndent . '(Check PATH and normal locations)',
279 'gtest:s', 'Path to GoogleTest, required for tests' .
280 $argIndent . '(uses GTEST_ROOT)' .
281 $argIndent . 'If not built, will try to build using CMake.',
283 ['Optional OpenDDS features:',
284 'built-in-topics!', 'Built-in Topics (yes)',
285 'content-subscription!', 'Content-Subscription Profile (yes)',
286 'content-filtered-topic!', 'ContentFilteredTopic (CS Profile) (yes)',
287 'multi-topic!', 'MultiTopic (CS Profile) (yes)',
288 'query-condition!', 'QueryCondition (CS Profile) (yes)',
289 'ownership-profile!', 'Ownership Profile (yes)',
290 'ownership-kind-exclusive!', 'Exclusive Ownership (Ownership Profile) (yes)',
291 'object-model-profile!', 'Object Model Profile (yes)',
292 'persistence-profile!', 'Persistence Profile (yes)',
293 'safety-profile:s', 'Safety Profile: base or extended (none)',
294 'tests!', 'Build tests, examples, and performance tests (no)' .
295 $argIndent . 'Requires --gtest if missing git submodule',
296 'security!', 'DDS Security plugin (no) Implies --openssl and' .
297 $argIndent . '--xerces3',
302 my $callback = shift;
303 for my $group (@specs) {
304 for my $n (1 .. (scalar @
{$group} / 2)) {
305 my $opt = ${$group}[$n * 2 - 1];
306 my $descr = ${$group}[$n * 2];
307 $opt =~ /(\<\w+\>)?([\w-]+)/;
308 my $optkey = (defined $1 ?
$1 : "") . $2;
309 &$callback(${$group}[0], $opt, $descr, $optkey, @_);
318 open VER
, 'dds/Version.h' or die "ERROR: can't open dds/Version.h, stopped";
320 $ver = $1 if /#define OPENDDS_VERSION "([^"]+)"/;
324 Welcome to OpenDDS version $ver
326 Options for this script are listed below, with the default behavior described
327 in parenthesis after the option description.
328 Boolean options can take the form "--opt" or "--no-opt", the more commonly
329 needed one (the one that changes the default behavior) is shown below.
330 Options that require arguments are shown as "--opt=VAL". Options with optional
331 arguments are shown as "--opt[=VAL]". Options that can be repeated with
332 cumulative effect are shown with a trailing "...". Some third-party
333 optional dependencies can be automatically located if they are installed in the
334 expected locations (see entries below marked with "system pkg"). In those
335 cases, specify the option as --opt without an = to enable the corresponding
336 feature in OpenDDS and use the default installation location.
339 my ($group, $opt, $descr, $optkey) = @_;
340 if (!defined $current || $group ne $current) {
344 $optkey .= '=VAL' if $opt =~ /=s/;
345 $optkey .= '[=VAL]' if $opt =~ /:s/;
346 $optkey = "[no-]$optkey" if ($opt =~ /!$/ && $descr =~ / \(yes\)/);
347 if ($optkey =~ /^\<hidden\>/) {
350 if ($opt =~ /^\<usage\>(.*)$/) {
353 $optkey =~ s/^\<default\>(.*)$/\[no-\]$1/g;
354 $optkey .= '...' if $opt =~ /s\@$/;
355 my $pad = $argPadding - length $optkey;
356 print "--$optkey" . ' ' x
(($pad > 0) ?
$pad : 0) . " $descr\n";
368 my ($group, $opt, $descr, $optkey) = @_;
369 if ($opt =~ /^\<usage\>/) {
372 if ($opt =~ /^<default>(.*)$/) {
374 $optkey =~ /^<default>(.*)$/;
375 push @getopts, "no-$1";
379 $opt =~ s/^\<hidden\>(.*)$/$1/;
385 if (! -r
'rules.dds.GNU') {
386 print "ERROR: this script must be run from its own directory\n";
391 Getopt
::Long
::Configure
('pass_through');
392 GetOptions
($opts, @getopts) or usage
(1);
393 usage
(0) if $opts->{'help'};
394 targetUsage
(0) if $opts->{'target-help'};
397 my $arg = shift(@ARGV);
398 if ($arg =~ /^--mpc:([^=]*)(?:=(.*))?$/) {
401 if (defined($value)) {
402 push(@
{$opts->{'mpcopts'}}, '-' . $key, $value);
405 $value = shift(@ARGV);
406 push(@
{$opts->{'mpcopts'}}, '-' . $key, $value);
408 print STDERR
"ERROR: $arg requires a value\n";
412 print STDERR
"ERROR: unknown argument $arg\n";
417 if ($opts->{'verbose'}) {
419 new Dumpvalue
()->dumpValue($opts);
422 for my $opt (@default) {
423 if ($opt eq 'rapidjson' && defined $opts->{'safety-profile'}) {
424 print("Although it's a default, rapidjson is not compatible with Safety ".
425 "Profile so it will not be enabled\n") if $opts->{'verbose'};
428 if (!exists $opts->{$opt} && !exists $opts->{"no-$opt"}) {
430 $defaulted->{$opt} = 1;
431 print("By default, --$opt is added to the options\n") if $opts->{'verbose'};
438 my $cross_compile = 0;
439 my %opts = %{parseArgs
()};
441 my $debug = exists $opts{'debug'} ?
$opts{'debug'} : 1;
442 my $backup = exists $opts{'backup'} ?
$opts{'backup'} : 1;
443 my $force_ace_tao = exists $opts{'force-ace-tao'} ?
$opts{'force-ace-tao'} : 0;
444 my $no_disable_deprecated = exists $opts{'no-disable-deprecated'} ?
$opts{'no-disable-deprecated'} : 0;
446 if (exists($opts{'std'})) {
447 $cxx_std = $opts{'std'};
448 # Accept any of --std=17, --std=stdcpp17, --std=c++17, etc.
449 $cxx_std =~ s/^(std)?(cpp|c\+\+)//;
452 push(@mpcopts, @
{$opts{'mpcopts'}}) if exists($opts{'mpcopts'});
454 push(@features, @
{$opts{'features'}}) if exists($opts{'features'});
456 $opts{'host'} = perlOS_to_host
() unless $opts{'host'};
458 my $is_windows = $opts{'host'} eq 'win32';
460 my ($slash, $exeext) = $is_windows ?
('\\', '.exe') : ('/', '');
464 ('ext' => 'cmd', 'pathsep' => ';', 'refpre' => '%',
465 'refpost' => '%', 'comment' => '::') :
466 ('ext' => 'sh', 'pathsep' => ':', 'refpre' => '${',
467 'refpost' => '}', 'comment' => '#')
470 sub might_be_executable
{
472 return -x
$path && -f
$path; # On Windows -x can return true for directories
477 for my $p (File
::Spec
->path()) {
479 my $path = "$p/$file";
480 if (might_be_executable
($path)) {
483 elsif ($exeext ne '') {
485 if (might_be_executable
($path)) {
493 sub addCurLibPathRef
{
494 my $buildEnvRef = shift;
495 my $platform = $opts{$buildEnvRef->{'build'}};
496 my $libpathname = $platforminfo{$platform}->{'libpath'};
497 my $curLibPathRef = $specific{'refpre'} . $libpathname . $specific{'refpost'};
498 $buildEnvRef->{$libpathname} = $curLibPathRef;
503 return command_utils
::run_command
(
505 script_name
=> 'configure',
506 dry_run
=> $opts{'dry-run'},
507 verbose
=> $opts{'verbose'},
516 my $branch = $args{branch
};
517 my $commit = $args{commit
};
519 print "Cloning git repo $url ", $branch // $commit, "\n";
522 if (defined($commit)) {
523 # Git can't directly clone a specific commit. Could use clone and checkout,
524 # but can't do a single shallow clone that way.
525 my $chdir = ChangeDir
->new($dest);
526 $failed = run_command
(['git', 'init', '--quiet']) ||
527 run_command
(['git', 'remote', 'add', 'origin', $url]) ||
528 run_command
(['git', 'fetch', '--quiet', '--depth=1', 'origin', $commit]) ||
529 run_command
(['git', 'checkout', '--quiet', 'FETCH_HEAD']);
532 my @cmd = ('git', 'clone', '--quiet', '--depth=1', $url, $dest);
533 push(@cmd, '--branch', $branch) if (defined($branch));
534 $failed = run_command
(\
@cmd);
538 run_command
(['git', '--no-pager', 'log', '-1', '--oneline'], chdir => $dest);
543 sub git_submodule_prop
{
545 my $prop_name = shift;
546 my $full_prop_name = "submodule.$path.$prop_name";
547 open(my $fd, "-|", "git config --file .gitmodules --get $full_prop_name")
548 or die("git_submodule_prop open failed: $!\nStopped");
549 my $prop_value = <$fd>;
551 chomp($prop_value) if (defined($prop_value));
553 die("Couldn't get $full_prop_name from .gitmodules\nStopped");
558 sub git_ensure_submodule
{
562 print STDERR
"Can't ensure we have $path becuase we can't find the git command\n";
566 my $commit_prop = 'openddsConfigureCommit';
567 my $commit = git_submodule_prop
($path, $commit_prop);
569 if (!$opts{'force-clone-submodules'} &&
570 !run_command
(['git', 'submodule', 'update', '--init', $path])) {
571 # This doesn't affect us in this run, but since we can get the actual
572 # submodule commit, make sure it matches the commit from .gitmodules for
573 # the case when the source tree is not a git repo.
574 open(my $fd, "-|", "git ls-tree HEAD $path")
575 or die("git_ensure_submodule open failed: $!\nStopped");
576 my $real_commit = <$fd>;
579 $real_commit =~ s/^\S+ \S+ ([0-9a-f]+).*$/$1/;
580 if ($real_commit ne $commit) {
581 print STDERR
"WARNING: for submodule $path $commit_prop = $commit ",
582 "from .gitmodules doesn't match actual commit $real_commit\n";
588 return !git_clone
($path, git_submodule_prop
($path, 'url'), commit
=> $commit);
593 my $expected_hash = shift();
595 my $md5 = Digest
::MD5
->new;
596 open(my $fh, $path) or die("Couldn't open \"$path\": $!");
599 my $hash = $md5->hexdigest();
600 my $failed = $expected_hash ne $hash;
603 "MD5 hash mismatch for $path\n",
604 " expected: $expected_hash\n",
610 my $curpathRef = $specific{'refpre'} . 'PATH' . $specific{'refpost'};
611 my %hostEnv = ('build' => 'host', 'PATH' => $curpathRef);
612 my %targetEnv = ('build' => 'target', 'PATH' => $curpathRef);
614 my $would_download; # can dry-run assume directories that don't exist yet?
618 if (defined $opts{'mpc'}) {
619 setEnv
('MPC_ROOT', $opts{'mpc'});
621 elsif (!$ENV{'MPC_ROOT'} && (-r
$ace_src . '/MPC/MPC.ico'
622 || ($opts{'dry-run'} && $would_download))) {
623 setEnv
('MPC_ROOT', $ace_src . $slash . 'MPC');
625 elsif (!$ENV{'MPC_ROOT'}) {
626 die "ERROR: Can't find MPC. Please set MPC_ROOT or make sure MPC exists".
627 "\n in the 'MPC' directory under ACE_ROOT ($ace_src), stopped";
630 $targetEnv{'MPC_ROOT'} = $ENV{'MPC_ROOT'};
632 $hostEnv{'MPC_ROOT'} = $targetEnv{'MPC_ROOT'};
635 if (!exists $platforminfo{$opts{'host'}} ||
636 $platforminfo{$opts{'host'}}->{'no_host'}) {
637 die "ERROR: unknown host $opts{'host'}, stopped";
639 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";
776 if (!exists $platforminfo{'win32'}->{'cl_archs'}->{$arch}) {
777 die "cl version probe failed, invalid architecture \"$arch\"\nStopped";
779 if (!$platforminfo{'win32'}->{'cl_archs'}->{$arch}) {
780 die "ERROR: Windows for $arch isn't supported\nStopped";
782 if (!exists $platforminfo{'win32'}->{'cl_versions'}->{$ver}) {
783 die "ERROR: Unknown or unsupported Visual C++ compiler version: $ver\n"
787 $opts{'compiler_version'} = $platforminfo{'win32'}->{'cl_versions'}->{$ver};
788 $opts{'compiler_target_architecture'} = $arch;
791 push(@features, 'no_cxx11=0');
792 print "Visual C++ has >= C++11 support\n" if $opts{'verbose'};
795 my $std = "stdcpp$cxx_std";
796 push(@mpcopts, '-value_template', "LanguageStandard=$std");
797 print "Setting Visual C++ LanguageStandard to $std\n" if $opts{'verbose'};
798 if ($opts{'std'} eq 'latest' || $cxx_std >= 17) {
799 push(@features, 'no_cxx17=0');
800 print "Visual C++ has >= C++17 support\n" if $opts{'verbose'};
803 $ENV{'PATH'} = $savepath;
804 print "Detected Visual C++ version: $opts{'compiler_version'}\n"
807 elsif ($opts{'compiler'} =~ /g\+\+|clang/) {
808 my $version_string = `$opts{'compiler'} --version`;
809 print "Compiler version: $version_string\n" if $opts{'verbose'};
810 $opts{'is apple clang'} = $version_string =~ /^Apple/;
812 push(@
{$opts{'macros'}}, 'CCFLAGS += -std=' . $opts{'std'});
813 print "Added platform_macros for -std=$opts{std}\n" if $opts{'verbose'};
815 elsif ($opts{'compiler'} !~ /clang/) {
816 $version_string =~ /\(.*\) (\d+)\.\d+/;
818 $opts{'std'} = 'gnu++17';
819 print "Detected GCC >= 11, default -std=gnu++17\n" if $opts{'verbose'};
822 $opts{'std'} = 'gnu++14';
823 print "Detected GCC >= 6, default -std=gnu++14\n" if $opts{'verbose'};
826 elsif ($opts{'compiler'} =~ /clang/ && $version_string !~ /^Apple / &&
827 $version_string =~ /(\d+)\.(\d+)\.(\d+)/) {
828 # Apple's version of Clang doesn't default to c++11 or higher, users
829 # can pass --std= to change the C++ standard version used.
831 $opts{'std'} = 'gnu++17';
832 print "Detected Clang >= 16, default -std=gnu++17\n" if $opts{'verbose'};
835 # Non-Apple versions of Clang, if version 6 or newer, default to C++14 like GCC
836 $opts{'std'} = 'gnu++14';
837 print "Detected Clang >= 6, default -std=gnu++14\n" if $opts{'verbose'};
841 if ($opts{'std'} && $opts{'std'} =~ /(0x|11|1y|14|1z|17|2a|20|2b|23)$/) {
842 push(@features, 'no_cxx11=0');
843 print "Compiler has >= C++11 support\n" if $opts{'verbose'};
848 my $compile_warnings = $opts{'compile-warnings'} // '';
849 if ($compile_warnings eq 'WARNING' or $compile_warnings eq 'ERROR') {
850 my ($section_names, $sections) = read_ini_file
("$FindBin::RealBin/build.ini");
851 my %compiler_map = ( 'g++' => 'GNU', 'clang' => 'Clang', 'cl' => 'MSVC', 'cl.exe' => 'MSVC');
852 my $section = $compiler_map{$opts{'compiler'}};
853 if ($opts{'is apple clang'}) {
854 $section = 'AppleClang';
856 my $warning_flags = $sections->{$section}{'warning'};
857 my $error_flags = $sections->{$section}{'error'};
858 push(@mpcopts, '-value_template', "compile_flags+=${warning_flags}");
859 if ($compile_warnings eq 'ERROR') {
860 push(@mpcopts, '-value_template', "compile_flags+=${error_flags}");
866 return substr($val, 0, 1) ne $slash && ($slash eq '/' || $val !~ /^[a
-z
]:/i
);
871 return Cwd
::abs_path
($val) if $val && -d
$val && $val =~ /../;
876 my($hashref, $name, $val, $notdir) = @_;
877 $val = Cwd
::abs_path
($val) if -d
$val;
878 if ($opts{'dry-run'} && !$notdir && looksRelative
($val)) {
879 $val = getcwd
. $slash . $val;
881 $val =~ s!/!\\!g if $is_windows;
882 $hashref->{$name} = $val;
886 setSomeEnv
(\
%targetEnv, @_);
890 setSomeEnv
(\
%hostEnv, @_);
897 if ($opts{'ace'} ne 'download') {
898 if (!-r
$opts{'ace'} . '/ace/ACE.h') {
899 die "ERROR: Can't find ACE at $opts{'ace'}.\nStopped";
901 $ace_src = $opts{'ace'};
904 elsif ($ENV{'ACE_ROOT'}) {
905 if (!-r
$ENV{'ACE_ROOT'} . '/ace/ACE.h') {
906 die "ERROR: Can't find ACE at $ENV{'ACE_ROOT'}.\nStopped";
908 $ace_src = $ENV{'ACE_ROOT'};
910 elsif (-r
'../ACE_wrappers/ace/ACE.h') {
911 die "ERROR: Older versions of this script would default to using ACE at " .
912 "../ACE_wrappers, but this version doesn't. Use the --ace command line " .
913 "option to override this error. Use --ace=download to have this script " .
914 "download an ACE+TAO package and expand it to ACE_wrappers.\nStopped";
916 elsif (-r
'ACE_wrappers/ace/ACE.h') {
917 $ace_src = 'ACE_wrappers';
919 elsif (-r
'ATCD/ACE/ace/ACE.h') {
920 $ace_src = 'ATCD/ACE';
922 elsif (-r
'ACE_TAO/ACE/ace/ACE.h') {
923 $ace_src = 'ACE_TAO/ACE';
926 $ace_src = normalizePath
($ace_src);
932 if (!-r
$opts{'tao'} . '/tao/ORB.h') {
933 die "ERROR: Can't find TAO at $opts{'tao'}.\nStopped";
935 $tao_src = $opts{'tao'};
937 elsif ($ENV{'TAO_ROOT'}) {
938 if (!-r
$ENV{'TAO_ROOT'} . '/tao/ORB.h') {
939 die "ERROR: Can't find TAO at $ENV{'TAO_ROOT'}.\nStopped";
941 $tao_src = $ENV{'TAO_ROOT'};
943 elsif (defined $ace_src && -r
$ace_src . '/TAO/tao/ORB.h') {
944 $tao_src = $ace_src . $slash . 'TAO';
946 elsif (defined $ace_src && -r
$ace_src . '/../TAO/tao/ORB.h') {
947 $tao_src = (File
::Spec
->splitpath($ace_src))[1] .'TAO';
950 $tao_src = normalizePath
($tao_src);
952 if ($opts{'safety-profile'}) {
953 # convert to lower case
954 $opts{'safety-profile'} = lc($opts{'safety-profile'});
958 if (!$ace_src || !$tao_src) {
959 if ($opts{'ace-github-latest'}) {
960 die "ERROR: Git not found in path (required to clone ACE/TAO/MPC)"
963 my $urlbase = 'https://github.com/DOCGroup';
964 my $branch = 'ace6tao2';
965 if ($opts{'doc-group3'}) {
969 my $err = git_clone
('ACE_TAO', "$urlbase/ACE_TAO", branch
=> $branch);
970 die "ERROR: Failed to clone ACE/TAO from GitHub\nStopped"
972 ! -r
'ACE_TAO/ACE/ace/ACE.h' ||
973 ! -r
'ACE_TAO/TAO/tao/ORB.h';
975 $err = git_clone
('ACE_TAO/ACE/MPC', "$urlbase/MPC", branch
=> 'master');
976 die "ERROR: Failed to clone MPC (into ACE_TAO/ACE/MPC) from GitHub\nStopped"
978 ! -r
'ACE_TAO/ACE/MPC/mwc.pl';
980 $ace_src = normalizePath
('ACE_TAO/ACE');
981 $tao_src = normalizePath
('ACE_TAO/TAO');
984 # Get ACE/TAO version info
985 my ($section_names, $sections) = read_ini_file
("$FindBin::RealBin/acetao.ini");
986 my $ace_tao_version = $opts{'doc-group3'} ?
$sections->{ace7tao3
} : $sections->{ace6tao2
};
987 if ($opts{verbose
}) {
988 print("ACE/TAO Version Info:");
989 new Dumpvalue
()->dumpValue($ace_tao_version);
991 my $ext = $is_windows ?
'zip' : 'tar.gz';
992 my $file = $ace_tao_version->{"$ext-filename"};
993 my $url = $ace_tao_version->{"$ext-url"};
994 my $md5_hash = $ace_tao_version->{"$ext-md5"};
996 # Check for an existing file
998 if (md5sum
($file, $md5_hash)) {
999 if ($opts{'dry-run'}) {
1000 print("Would remove existing $file and attempt to download\n");
1003 print("Removing existing $file and attempting to download\n");
1004 unlink($file) or die("Couldn't remove $file: $!\nStopped");
1007 elsif ($opts{'verbose'}) {
1008 print("Using ACE+TAO source package $file\n");
1013 my $dl_msg = "Downloading $file from $url using";
1014 $would_download = 1;
1016 require LWP
::UserAgent
;
1017 my $ua = LWP
::UserAgent
->new;
1019 print("$dl_msg LWP\n");
1020 if ($opts{'dry-run'}) {
1021 print("Dry-run: would LWP::UserAgent get $url\n");
1024 my $response = $ua->get($url, ':content_file' => $file);
1025 if ($response->is_error) {
1026 die $response->message . "\nstopped";
1031 if (which
('wget')) {
1032 print("$dl_msg wget\n");
1033 run_command
(['wget', '--output-document', $file, $url], autodie
=> 1);
1035 elsif (which
('curl')) {
1036 print("$dl_msg curl\n");
1037 run_command
(['curl', '--location', $url, '--output', $file], autodie
=> 1);
1040 die "ERROR: Can't download ACE+TAO using LWP, wget, or curl.\n" .
1041 "Download ACE+TAO from $url, place the file here\n, " .
1042 "and re-run the script.\nStopped";
1047 if (!$opts{'dry-run'} && md5sum
($file, $md5_hash)) {
1048 die("MD5 hash check failed after download, try running again?\nStopped");
1051 print "Extracting archive $file\n";
1052 $ENV{'ACTIVEPERL_CONFIG_DISABLE'} = 1 if $^O
eq 'MSWin32';
1053 $ENV{'ACTIVEPERL_CONFIG_SILENT'} = 1 if $^O
eq 'MSWin32';
1054 eval {require Archive
::Extract
;};
1057 my $ddsroot = getcwd
;
1059 $err = run_command
(['tar', 'xzf', "$ddsroot/$file"]);
1063 print "Archive::Extract isn't installed, trying Archive::Zip\n" if $opts{'verbose'};
1064 eval {require Archive
::Zip
};
1066 print "Neither Archive::Extract or Archive::Zip are installed\n" if $opts{'verbose'};
1069 if ($opts{'dry-run'}) {
1070 print "Dry-run: would Archive::Zip $file\n";
1073 my $zip = Archive
::Zip
->new();
1074 if ($zip->read( $file ) == Archive
::Zip
::AZ_OK
() &&
1075 $zip->extractTree() == Archive
::Zip
::AZ_OK
()) {
1083 die "ERROR: Can't extract $file, extract it to " . Cwd
::abs_path
('.') .
1084 "\nand run this script again.\nStopped";
1088 if ($opts{'dry-run'}) {
1089 print "Dry-run: would Archive::Extract $file\n";
1092 if ($^O
ne 'MSWin32') {
1094 $Archive::Extract
::PREFER_BIN
= 1;
1096 my $ae = Archive
::Extract
->new('archive' => $file);
1097 if (!$ae->extract('to' => '.')) {
1098 die $ae->error . "\nstopped";
1104 print "Removed $file\n" if $opts{'verbose'};
1105 $ace_src = 'ACE_wrappers';
1106 $tao_src = 'ACE_wrappers/TAO';
1110 print "Using ace_src: $ace_src\n" if $opts{'verbose'};
1111 print "Using tao_src: $tao_src\n" if $opts{'verbose'};
1113 sub clone_host_and_target
{
1114 my $source_dir = shift;
1115 locate_mpc
($ace_src);
1116 print "cloning build tree\n" if $opts{'verbose'};
1118 ["$targetEnv{'MPC_ROOT'}/clone_build_tree.pl", 'host', 'target'],
1119 chdir => $source_dir)) {
1120 die("Failed to clone tree");
1126 if (!$opts{'dry-run'} && -r
$file) {
1127 print "WARNING: overwriting existing $file\n";
1129 my $backup_path = $file . '.bak';
1130 $backup_path .= ".$backup_timestamp" if -e
$backup_path;
1131 copy
($file, $backup_path);
1132 print " (saved a backup copy as $backup_path)\n";
1138 sub backup_and_copy
{
1142 if ($opts{'dry-run'}) {
1143 print("Would copy $src to $dst\n");
1150 sub backup_and_open
{
1153 if ($opts{'dry-run'}) {
1154 return File
::Temp
->new();
1156 my $fh = new FileHandle
;
1157 open $fh, ">$file" or die "ERROR: Can't write to $file, stopped";
1161 sub dump_and_unlink
{ # removes temp files created by dry-run
1163 if ($opts{'verbose'}) {
1171 sub write_config_h
{
1172 my %buildEnv = %{shift()};
1173 my $platform = $opts{$buildEnv{'build'}};
1174 my $pi = $platforminfo{$platform};
1175 $opts{'optimize'} = 0 if (!exists $opts{'optimize'} && !exists $opts{'sanitize'});
1177 my $CFGH = backup_and_open
("$buildEnv{'ACE_ROOT'}/ace/config.h");
1178 if (!$no_disable_deprecated) {
1179 for my $line (@default_configh) {
1180 print $CFGH "$line\n";
1183 if ($buildEnv{'build'} eq 'target') {
1184 for my $line (@
{$opts{'configh'}}) {
1185 print $CFGH "$line\n";
1188 my $cfg = $platform;
1189 if ($pi->{'aceconfig'}) {
1190 $cfg = $pi->{'aceconfig'};
1191 $cfg =~ s/\$UNAMER/my $u = `uname -r`; chomp $u; $u/e;
1193 $cfg .= '-' . $opts{'host_version'} if $opts{'host_version'};
1194 print $CFGH "#include \"ace/config-$cfg.h\"\n";
1195 if (defined $opts{'no-opendds-safety-profile'}) {
1196 print $CFGH "#define ACE_FACE_SAFETY_" . uc($opts{'safety-profile'}) . "\n";
1197 if ($opts{'safety-profile'} eq 'extended') {
1198 print $CFGH "#ifndef ACE_HAS_ALLOC_HOOKS\n";
1199 print $CFGH "# define ACE_HAS_ALLOC_HOOKS\n";
1200 print $CFGH "#endif\n";
1205 print "Wrote $buildEnv{'ACE_ROOT'}/ace/config.h\n" if $opts{'verbose'};
1206 dump_and_unlink
($CFGH) if $opts{'dry-run'};
1211 sub default_features
{
1212 my %buildEnv = %{shift()};
1214 if ($buildEnv{'build'} eq 'target') {
1215 push(@feat, 'ipv6=1') if $opts{'ipv6'};
1216 my @normalized = map {/=/ ?
$_ : "$_=1"} @features;
1217 push(@feat, @normalized) if @normalized;
1222 sub write_default_features
{
1223 my %buildEnv = %{shift()};
1224 my @feat = default_features
(\
%buildEnv);
1227 my $DF = backup_and_open
("$buildEnv{'ACE_ROOT'}/bin/MakeProjectCreator" .
1228 "/config/default.features");
1234 print "Wrote $buildEnv{'ACE_ROOT'}/.../default.features\n"
1235 if $opts{'verbose'};
1236 dump_and_unlink
($DF) if $opts{'dry-run'};
1240 my %all_sanitizers = (
1242 fsanitize
=> 'address',
1244 LSAN_OPTIONS
=> "suppressions=$FindBin::RealBin/etc/asan-suppr.txt",
1245 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',
1247 compiler_args
=> ['-fsanitize-address-use-after-scope'],
1250 fsanitize
=> 'thread',
1252 TSAN_OPTIONS
=> "history_size=7 second_deadlock_stack=1 suppressions=$FindBin::RealBin/etc/tsan-suppr.txt",
1256 fsanitize
=> 'undefined',
1258 UBSAN_OPTIONS
=> "suppressions=$FindBin::RealBin/etc/ubsan-suppr.txt:print_stacktrace=1",
1260 configh
=> ['#define ACE_INITIALIZE_MEMORY_BEFORE_USE'],
1261 compiler_args
=> ['-fno-sanitize=enum'],
1264 my %enabled_sanitizers = ();
1265 if (exists $opts{'sanitize'}) {
1266 for my $arg (@
{$opts{'sanitize'}}) {
1267 for my $name (split(/,/, $arg)) {
1268 if (exists($all_sanitizers{$name})) {
1269 $enabled_sanitizers{$name} = $all_sanitizers{$name};
1272 die("ERROR: \"$name\" isn't a valid sanitizer to pass to --sanitize\nStopped");
1279 my @sanitizer_compiler_args = ();
1280 my @sanitizer_linker_args = ();
1281 for my $name (sort(keys(%enabled_sanitizers))) {
1282 my $sanitizer = $enabled_sanitizers{$name};
1283 push(@fsanitize, $sanitizer->{fsanitize
});
1284 if (exists($sanitizer->{env
})) {
1285 for my $env (keys(%{$sanitizer->{env
}})) {
1286 setEnv
($env, $sanitizer->{env
}->{$env});
1289 if (exists($sanitizer->{configh
})) {
1290 push(@
{$opts{'configh'}}, @
{$sanitizer->{configh
}});
1292 if (exists($sanitizer->{compiler_args
})) {
1293 push(@sanitizer_compiler_args, @
{$sanitizer->{compiler_args
}});
1295 if (exists($sanitizer->{linker_args
})) {
1296 push(@sanitizer_linker_args, @
{$sanitizer->{linker_args
}});
1299 if (scalar(@fsanitize)) {
1301 die("ERROR: Using sanitizers requires --debug");
1303 my @common = ('-ggdb', '-fsanitize=' . join(',', @fsanitize));
1304 @sanitizer_compiler_args = ('-O1', @common, '-fno-omit-frame-pointer', @sanitizer_compiler_args);
1305 @sanitizer_linker_args = (@common, @sanitizer_linker_args);
1309 my %buildEnv = %{shift()};
1310 return ($buildEnv{'build'} eq 'target' && $opts{'target-compiler'}) ?
1311 $opts{'target-compiler'} : $opts{'compiler'};
1314 my @ace_macros = ('debug',
1321 sub write_platform_macros
{
1322 my %buildEnv = %{shift()};
1324 ($cross_compile && $buildEnv{'build'} eq 'target')) {
1325 my $pi = $platforminfo{$opts{$buildEnv{'build'}}};
1326 my $PMG = backup_and_open
("$buildEnv{'ACE_ROOT'}/include/makeinclude" .
1327 "/platform_macros.GNU");
1328 my $macro_cross_compile = 0;
1329 if ($buildEnv{'build'} eq 'target') {
1330 for my $line (@
{$opts{'macros'}}) {
1331 print $PMG "$line\n";
1333 for my $key (@ace_macros) {
1334 if (exists $opts{$key}) {
1335 my $macro = ($key eq 'static') ?
'static_libs_only' : $key;
1336 print $PMG "$macro = $opts{$key}\n";
1339 if ($cross_compile) {
1340 print $PMG "CROSS-COMPILE = 1\n";
1341 print $PMG 'TAO_IDL = $(HOST_ACE)/bin/tao_idl', "\n";
1343 print $PMG "HOST_EXE_EXT = .exe\n";
1345 print $PMG 'TAO_IDL_DEP = $(TAO_IDL)$(HOST_EXE_EXT)', "\n";
1346 if ($has_host_compiler) {
1347 print $PMG 'TAO_IDL_PREPROCESSOR = ', $opts{'compiler'}, "\n";
1349 print $PMG 'TAO_IDLFLAGS += -g $(HOST_ACE)/bin/ace_gperf', "\n";
1350 print $PMG 'build_tao_idl_be = 0', "\n";
1351 unless ($build_host_tools) {
1353 if (exists $opts{'host-ace'}) {
1354 $host_ace = $opts{'host-ace'};
1357 $host_ace = '$(HOST_DDS)' . nested
($ace_src, '.');
1359 print $PMG "HOST_ACE = $host_ace\n";
1361 if ($opts{'target-compiler'}) {
1362 my $tcomp = $opts{'target-compiler'};
1363 if ($tcomp =~ s/-g([c+])\1$/-/) {
1364 $macro_cross_compile = 1;
1365 print $PMG 'CROSS_COMPILE = ', $tcomp, "\n";
1368 $opts{'nonstdcompiler'} = $tcomp;
1369 print $PMG 'LDFLAGS += -Wl,-rpath-link,$(ACE_ROOT)/lib', "\n";
1372 if ($opts{'target-arch'}) {
1373 print $PMG "FLAGS_C_CC += -target $opts{'target-arch'}\n";
1374 print $PMG "LDFLAGS += -target $opts{'target-arch'}\n";
1376 if ($opts{'target'} eq 'android') {
1377 print $PMG 'ifeq (,$(findstring -isystem$(ACE_ROOT),$(INCLDIRS)))', "\n";
1378 print $PMG ' INCLDIRS += -isystem $(ACE_ROOT)', "\n";
1379 print $PMG 'endif', "\n";
1383 for my $f (@platformmacros) {
1384 print $PMG ($f =~ /=/ ?
$f : "$f=1"), "\n";
1386 if ($buildEnv{'build'} eq 'host') {
1387 print $PMG "static_libs_only = 1\n";
1388 print $PMG "java = 1\n" if $opts{'java'};
1390 if ($opts{'prefix'}) {
1391 print $PMG "INSTALL_PREFIX=" . $opts{'prefix'} . "\n";
1393 if (scalar(@fsanitize)) {
1395 'CPPFLAGS += ' . join(' ', @sanitizer_compiler_args) . "\n" .
1396 'LDFLAGS += ' . join(' ', @sanitizer_linker_args) . "\n";
1398 my $plat = $opts{$buildEnv{'build'}};
1399 if ($pi->{'aceplatform'}) {
1400 $plat = $pi->{'aceplatform'};
1401 $plat =~ s/\$COMP/'g++'/e;
1402 $plat =~ s/\$NONSTDCOMP/($opts{'compiler'} =~ m!clang!) ? 'clang' : ''/e;
1405 $plat .= '_' . $opts{'host_version'} if $opts{'host_version'};
1406 print $PMG "include \$(ACE_ROOT)/include/makeinclude/platform_$plat.GNU\n";
1407 if ($opts{'nonstdcompiler'} && !$macro_cross_compile) {
1408 my $comp = compiler
(\
%buildEnv);
1409 for my $var ('CC', 'CXX', 'LD') {
1410 print $PMG "$var = $comp\n";
1413 if ($opts{'prefix'} && $opts{'install-origin-relative'}) {
1416 INSTALL_ORIGIN = $$ORIGIN/../$(INSTALL_LIB)
1417 LDFLAGS += '-Wl,-rpath,$(INSTALL_ORIGIN)' $(LD_RPATH_FLAGS)
1421 print "Wrote $buildEnv{'ACE_ROOT'}/.../platform_macros.GNU\n"
1422 if $opts{'verbose'};
1423 dump_and_unlink
($PMG) if $opts{'dry-run'};
1427 sub write_opendds_configh
{
1428 my %buildEnv = %{shift()};
1429 my $CFGH = backup_and_open
("$buildEnv{'DDS_ROOT'}/dds/OpenDDSConfig.h");
1430 my $CFGIN = new FileHandle
;
1431 open($CFGIN, 'dds/OpenDDSConfig.h.in') or die("Can't open OpenDDSConfig.h.in for reading: $!\nStopped");
1434 'OPENDDS_CONFIG_AUTO_STATIC_INCLUDES' => 0,
1435 'OPENDDS_CONFIG_BOOTTIME_TIMERS' => $opts{'boottime'} // 0,
1438 my $replace_value = sub {
1440 return 'UNDEFINED_NEED_TO_UPDATE_CONFIGURE_SCRIPT' unless exists $config{$var};
1441 return $config{$var};
1445 s/@(\w+)@/&$replace_value($1)/e;
1451 print "Wrote $buildEnv{'DDS_ROOT'}/dds/OpenDDSConfig.h\n"
1452 if $opts{'verbose'};
1453 dump_and_unlink
($CFGH) if $opts{'dry-run'};
1456 ## Optional OpenDDS dependencies
1458 'java' => {env
=> 'JAVA_HOME', sanity
=> 'include/jni.h', mpc
=> 'java'},
1459 'jboss' => {env
=> 'JBOSS_HOME', sanity
=> 'lib/jboss-common.jar'},
1460 'ant' => {env
=> 'ANT_HOME', sanity
=> 'bin/ant'},
1461 'wireshark' => {env
=> 'WIRESHARK_SRC', sanity
=> 'epan/packet.h', mpc
=> 'wireshark'},
1462 'wireshark-cmake' => {
1463 env
=> 'WIRESHARK_SRC',
1464 sanity
=> 'epan/packet.h',
1465 mpc
=> 'wireshark_cmake',
1467 'wireshark-build' => {env
=> 'WIRESHARK_BUILD', sanity
=> 'config.h'},
1468 'wireshark-lib' => {env
=> 'WIRESHARK_LIB', may_be_blank
=> 1},
1472 'include/glib-2.0/glib.h' => undef,
1473 'include/glib.h' => 'glib_versioned_includes=0',
1477 env
=> 'RAPIDJSON_ROOT',
1478 sanity
=> 'include/rapidjson/rapidjson.h',
1479 mpc
=> 'no_rapidjson=0',
1481 'qt' => {env
=> 'QTDIR', sanity
=> '', mpc
=> 'qt5'},
1483 env
=> 'XERCESCROOT',
1484 sanity
=> 'include/xercesc/dom/DOM.hpp',
1487 'openssl' => {env
=> 'SSL_ROOT', sanity
=> 'include/openssl/opensslv.h', mpc
=> 'ssl'},
1490 my $host_tools_only = exists $opts{'host-tools-only'} && $opts{'host-tools-only'};
1491 if ($host_tools_only) {
1492 print "--host-tools-only implies --static\n" if $opts{'verbose'};
1493 $opts{'static'} = 1;
1494 if ($cross_compile) {
1495 die "ERROR: Can't use --host-tools-only for cross compile\nStopped";
1499 if ((exists $opts{'wireshark'} || exists $opts{'wireshark-cmake'}) &&
1500 !exists $opts{'glib'}) {
1501 print "--wireshark and --wireshark-cmake imply --glib\n" if $opts{'verbose'};
1505 # Use this to check if tests are enabled (instead of $opts{'tests'} directly).
1506 my $tests = exists $opts{'tests'} && $opts{'tests'};
1508 my @ace_features = ('xerces3');
1510 if (exists $opts{'java'}) {
1511 if ($opts{'static'} && !$host_tools_only) {
1512 die "ERROR: --static can't be used with --java\nStopped";
1514 my $host_java_platform = perlOS_to_java_platform
();
1515 if ($cross_compile) {
1516 if (exists $platforminfo{$opts{'target'}}->{'java_platform'}) {
1517 setEnv
('JAVA_PLATFORM', $platforminfo{$opts{'target'}}->{'java_platform'});
1518 setHostEnv
('JAVA_PLATFORM', $host_java_platform);
1521 die "Cross-compile with Java for $opts{'target'} in not supported.\nStopped";
1525 setEnv
('JAVA_PLATFORM', $host_java_platform);
1529 my $try_to_use_qt_system_pkg =
1530 exists $opts{'qt'} && !length($opts{'qt'}) && !exists $opts{'qt-include'};
1532 # Default to Wireshark Development Package if installed and a path wasn't
1534 my $wireshark_install = '/usr/include/wireshark';
1535 if (exists $opts{'wireshark'} && !defined $ENV{'WIRESHARK_SRC'} && $opts{'wireshark'} eq '') {
1536 my $sanity = $optdep{'wireshark'}->{sanity
};
1537 if (-f File
::Spec
->catdir($wireshark_install, $sanity)) {
1538 $opts{'wireshark'} = $wireshark_install;
1541 die "ERROR: --wireshark must be given a value because there is not a " .
1542 "development package installed at " . $wireshark_install . ", stopped";
1546 my $wireshark_lib_defaulted = 0;
1547 if (exists $opts{'wireshark-cmake'} && !exists $opts{'wireshark-lib'}) {
1548 if ($^O
=~ /MSWin32/) {
1549 $opts{'wireshark-lib'} = "run\\RelWithDebInfo";
1551 elsif ($^O
=~ /darwin/) {
1552 $opts{'wireshark-lib'} = "run/Wireshark.app/Contents/Frameworks";
1554 elsif ($^O
=~ /linux/) {
1555 $opts{'wireshark-lib'} = "";
1558 die "ERROR: --wireshark-lib is needed because we couldn't decide on a default value";
1560 $wireshark_lib_defaulted = 1;
1563 if ($opts{'security'}) {
1564 unless (exists $opts{'openssl'}) {
1565 $opts{'openssl'} = '';
1566 print "Forcing --openssl (security dependency)\n" if $opts{'verbose'};
1568 unless (exists $opts{'xerces3'}) {
1569 $opts{'xerces3'} = '';
1570 print "Forcing --xerces3 (security dependency)\n" if $opts{'verbose'};
1575 unless ($opts{'cmake'}) {
1576 print "--cmake not specified by user; searching path...\n" if $opts{'verbose'};
1577 $opts{'cmake'} = which
('cmake');
1579 unless ($opts{'cmake'}) {
1580 print "CMake not found in path; searching default location...\n"
1581 if $opts{'verbose'};
1585 (-f
$ENV{'ProgramFiles'} . '\\CMake\\bin\\cmake.exe' ?
1586 $ENV{'ProgramFiles'} . '\\CMake\\bin\\cmake.exe' :
1587 $ENV{'ProgramFiles(x86)'} . '\\CMake\\bin\\cmake.exe') :
1591 my $has_cmake = -f
$opts{'cmake'};
1593 print "Using CMake '$opts{'cmake'}' if needed\n" if $opts{'verbose'};
1596 print "Could not find CMake at '$opts{'cmake'}'\n" if $opts{'verbose'};
1600 my $arch = exists $opts{'compiler_target_architecture'} ?
1601 $opts{'compiler_target_architecture'} : '';
1603 return $arch eq 'x64';
1606 sub system_default_install_dir
{
1608 # When the host is 32-bit.
1609 return $ENV{'ProgramFiles'}
1610 if ! exists $ENV{'ProgramFiles(x86)'};
1612 return targets_win64
() ?
$ENV{'ProgramFiles'} : $ENV{'ProgramFiles(x86)'};
1617 my $build_gtest = 0;
1618 if (exists $opts{'gtest'} || $tests) {
1619 my $gtest_sanity = 'include/gtest/gtest.h';
1620 my $gtest_root = undef;
1622 if ($opts{'gtest'}) {
1623 die "ERROR: '$gtest_sanity' not found in supplied gtest directory '$opts{'gtest'}'"
1624 if ! -f File
::Spec
->catfile($opts{'gtest'}, $gtest_sanity);
1626 $gtest_root = $opts{'gtest'};
1627 setEnv
('GTEST_ROOT', $gtest_root);
1631 my $rel_path = 'tests/googletest';
1632 my $sm_dir = Cwd
::abs_path
($rel_path);
1633 my $sm_src = File
::Spec
->catdir($sm_dir, 'googletest');
1634 my $sys_dir = File
::Spec
->catdir((system_default_install_dir
(),
1635 $is_windows ?
'googletest-distribution' : ''));
1638 if (-f File
::Spec
->catfile($sm_src, $gtest_sanity)) {
1641 elsif (-f File
::Spec
->catfile($sys_dir, $gtest_sanity)) {
1642 $opts{'gtest'} = $sys_dir;
1643 $gtest_root = $sys_dir;
1644 setEnv
('GTEST_ROOT', $gtest_root);
1647 print "Could not find GoogleTest, cloning...\n" if $opts{'verbose'};
1648 if (git_ensure_submodule
($rel_path)) {
1654 # Check for existing build
1655 $gtest_root = File
::Spec
->catdir($sm_dir, 'build', 'install');
1656 $build_gtest = ! -d
$gtest_root;
1657 $opts{'gtest'} = $sm_dir;
1658 # No need to set env. variable with submodule UNLESS we're in safetyprofile
1659 if ($opts{'safety-profile'}) {
1660 print "Setting GTEST_ROOT to ${gtest_root} for use in safety-profile.\n" if $opts{'verbose'};
1661 setEnv
('GTEST_ROOT', $gtest_root);
1665 if (!defined($gtest_root)) {
1666 die "ERROR: GoogleTest '$gtest_sanity' not found in submodule src '$sm_src' or " .
1667 "default install dir '$sys_dir', please pass a correct version of GoogleTest to --gtest\nStopped";
1670 if ($is_windows && -d File
::Spec
->catdir($gtest_root, 'bin')) {
1671 push_path
(\
%targetEnv, $gtest_root . $slash . 'bin');
1673 elsif (!$is_windows && -f File
::Spec
->catfile($gtest_root, 'lib', 'libgtest.so')) {
1674 push_libpath
(\
%targetEnv, $gtest_root . $slash . 'lib');
1678 if ($build_gtest && !$has_cmake) {
1679 die "ERROR: GoogleTest in $opts{'gtest'} must be built but can't find CMake\nStopped";
1682 if (exists $opts{'rapidjson'}) {
1683 if ($opts{'rapidjson'} eq '') {
1684 my $sanity = $optdep{'rapidjson'}->{sanity
};
1685 my $rel_path = 'tools/rapidjson';
1686 my $sm_dir = Cwd
::abs_path
($rel_path);
1687 my $sys_dir = File
::Spec
->catdir((system_default_install_dir
(),
1688 $is_windows ?
'RapidJSON' : ''));
1691 "Could not find RapidJSON (using '$sanity') in:\n".
1692 " Git Submodule: '$sm_dir'\n" .
1693 " Default Install Prefix: '$sys_dir'\n";
1694 my $rapidjson = undef;
1695 if (-f File
::Spec
->catfile($sm_dir, $sanity)) {
1696 $rapidjson = $sm_dir;
1698 elsif (-f File
::Spec
->catfile($sys_dir, $sanity)) {
1699 $rapidjson = $sys_dir;
1702 print "Could not find RapidJSON, cloning...\n" if $opts{'verbose'};
1703 if (git_ensure_submodule
($rel_path)) {
1704 $rapidjson = $sm_dir;
1708 if (defined($rapidjson)) {
1709 print "Using '$rapidjson' for RapidJSON\n" if ($opts{'verbose'});
1710 $opts{'rapidjson'} = $rapidjson;
1712 elsif (exists($defaulted->{'rapidjson'})) {
1713 print "${rapidjson_msg}Continuing without it.\n" if $opts{'verbose'};
1714 delete $opts{'rapidjson'};
1717 die "ERROR: ${rapidjson_msg}Stopped";
1722 my %use_system_pkg = map {$_, 1} qw
/ant glib qt xerces3 openssl/;
1724 my %use_win_default = (
1725 'openssl' => system_default_install_dir
() . '/OpenSSL',
1726 'xerces3' => system_default_install_dir
() . '/xerces-c');
1728 my %need_platform_macros = map {$_, 1} qw
/xerces3/;
1730 sub default_java_home
{
1731 my $host = $opts{'host'};
1733 if ($host eq 'macosx') {
1734 $result = `/usr/libexec/java_home`;
1739 $result = which
('javac');
1741 die "ERROR: No javac in PATH.\nStopped";
1743 while (-l
$result) {
1744 $result = readlink($result);
1747 return dirname
(dirname
($result))
1751 # Detect and populate dependency info from environment variables
1752 # or system-wide default paths.
1753 for my $key (keys %optdep) {
1754 if (exists $opts{$key} && $opts{$key} eq '') {
1755 if (defined $optdep{$key}->{env
} && $ENV{$optdep{$key}->{env
}}) {
1756 $opts{$key} = $ENV{$optdep{$key}->{env
}};
1758 if ($key eq 'java') {
1759 ## when the environment variable JAVA_HOME is set to a JRE location,
1760 ## try to resolve JAVA_HOME based on the location of javac
1761 my $java_home = default_java_home
();
1762 if (!-r
"$opts{$key}$slash$optdep{'java'}->{sanity}" and $java_home ne '') {
1763 $opts{'java'} = $java_home;
1767 elsif (!$is_windows && exists $use_system_pkg{$key}) {
1768 $opts{$key} = '/usr';
1769 print "Defaulting $key to $opts{$key}\n" if $opts{'verbose'};
1771 elsif ($is_windows && exists $use_win_default{$key}) {
1772 my $dir = $use_win_default{$key};
1778 die "Default '$key' directory '$dir' not found.\nStopped";
1781 print "Defaulting $key to $opts{$key}\n" if $opts{'verbose'};
1783 elsif ($key eq 'java') {
1785 $opts{'java'} = default_java_home
();
1787 if ($opts{'java'} eq '') {
1788 die "ERROR: --$key requires a value.\nStopped";
1791 elsif (exists $optdep{$key}->{env
} && !$optdep{$key}->{may_be_blank
}) {
1792 die "ERROR: --$key requires a value.\nStopped";
1799 for my $f (@features) {
1800 my ($key, $value) = split(/=/, $f);
1801 if ($key eq $feat) {
1808 if ($opts{'java'}) {
1809 push(@features, 'java=1');
1811 my $feat = 'java_pre_jpms';
1812 unless (has_feature
($feat)) {
1813 my $javac = File
::Spec
->catfile($opts{'java'}, 'bin', 'javac');
1814 open(my $vers, "\"$javac\" -version |");
1816 if (/javac (\d+)/) {
1817 print "Found javac major version $1\n" if $opts{'verbose'};
1819 push(@features, "$feat=0");
1820 print "Feature $feat=0 due to Java version\n" if $opts{'verbose'};
1833 setEnv
($e, $opts{$key}, $notdir);
1837 # Enable MPC features and populate expected environment variables
1838 # for all required "optional" dependencies.
1839 for my $key (keys %optdep) {
1840 if (exists $opts{$key}) {
1841 print "Enabling $key\n" if $opts{'verbose'};
1842 my $e = $optdep{$key}->{env
};
1843 my $s = $optdep{$key}->{sanity
};
1844 my $m = $optdep{$key}->{mpc
};
1845 if ($opts{$key} ne 'skip_version_check') {
1846 env_from_opt
($key, $e) if defined $e;
1847 if (ref $s eq 'HASH') {
1849 for my $alt (keys %{$s}) {
1850 if (-r
$targetEnv{$e} . '/' . $alt) {
1851 print "Found $key at $targetEnv{$e} using alternative $alt\n"
1852 if $opts{'verbose'};
1854 push(@features, $s->{$alt}) if defined $s->{$alt};
1857 print "Didn't find $key at $targetEnv{$e} using alternative $alt\n"
1858 if $opts{'verbose'};
1861 die "ERROR: Can't find $key at $targetEnv{$e}.\nStopped";
1864 elsif ($s && !-r
$targetEnv{$e} . '/' . $s) {
1865 die "ERROR: Can't find $key at $targetEnv{$e} (using $s).\nStopped";
1868 push(@features, $m) if $m;
1869 push(@platformmacros, $m) if $need_platform_macros{$key};
1873 if ($is_windows && !$opts{'optimize'}) { # look for nonstandard vcpkg layout
1874 for my $key ('xerces3', 'openssl') {
1875 my $env = $optdep{$key}->{env
};
1876 if ($opts{$key} && $targetEnv{$env}) {
1877 if (-d
$targetEnv{$env} . '/debug/lib') {
1878 print "Using debug/lib subdir for $key\n" if $opts{'verbose'};
1880 $libenv =~ s/_?ROOT$/_LIBDIR/;
1881 setEnv
($libenv, $targetEnv{$env} . '/debug/lib');
1882 $opts{$key . '-debugbin'} = 1;
1888 ## OpenSSL version-detection / feature-injection
1889 if ($opts{'openssl'} && $opts{'openssl'} ne 'skip_version_check') {
1890 my $ssl_version_file = $opts{'openssl'} . '/' . $optdep{'openssl'}->{sanity
};
1892 open my $fh, '<', $ssl_version_file
1893 or die "ERROR: Failed to open '$ssl_version_file' for OpenSSL version detection.\nStopped";
1896 if (/^\s*#\s*define\s*OPENSSL_VERSION_TEXT\s*"([^"]*)"/) {
1898 print "OpenSSL version detected: \"$ver\"\n" if $opts{'verbose'};
1899 if ($ver =~ /OpenSSL[\W]+1\.1/ || $ver =~ /OpenSSL[\W]+3\./) {
1900 print "OpenSSL 1.1+ MPC feature enabled\n" if $opts{'verbose'};
1901 push(@features, 'openssl11=1');
1908 sub win32_cmake_generator
{
1911 my %map = ('vc9' => 'Visual Studio 9 2008',
1912 'vc10' => 'Visual Studio 10 2010',
1913 'vc11' => 'Visual Studio 11 2012',
1914 'vc12' => 'Visual Studio 12 2013',
1915 'vc14' => 'Visual Studio 14 2015',
1916 'vs2017' => 'Visual Studio 15 2017',
1917 'vs2019' => 'Visual Studio 16 2019',
1918 'vs2022' => 'Visual Studio 17 2022');
1920 die "ERROR: Unsupported Visual Studio version '$ver' supplied.\nStopped"
1921 if ! exists $map{$ver};
1927 print("Building GoogleTest...\n");
1929 my $cwd = Cwd
::getcwd
();
1930 my $build_dir = $opts{'gtest'} . $slash . 'build';
1931 my $install_dir = $build_dir . $slash . 'install';
1932 my $cmake = $opts{'cmake'};
1933 my @cmake_platform_args = $is_windows ?
1934 ('-Dgtest_force_shared_crt=ON',
1935 '-DCMAKE_CXX_FLAGS=/D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING=1',
1936 '-G', '"' . win32_cmake_generator
($opts{'compiler_version'}) . '"',
1937 '-A', $opts{'compiler_target_architecture'}) : ();
1938 if ($opts{'nonstdcompiler'}) {
1939 push @cmake_platform_args, "-DCMAKE_CXX_COMPILER=$opts{'compiler'}";
1941 my @cmake_cmds = ([$cmake,
1942 "-DCMAKE_INSTALL_PREFIX=$install_dir",
1943 '-DCMAKE_INSTALL_LIBDIR=lib',
1944 '-DCMAKE_POSITION_INDEPENDENT_CODE=TRUE',
1945 @cmake_platform_args,
1947 ["$cmake", "--build", ".", "--target", "install"]);
1950 or die "ERROR '$!': failed to make directory $build_dir from $cwd.\nStopped"
1954 or die "ERROR '$!': failed to make directory $install_dir from $cwd.\nStopped"
1955 if ! -d
$install_dir;
1957 my $cd_build_dir = ChangeDir
->new($build_dir);
1958 for my $cmd (@cmake_cmds) {
1959 run_command
($cmd, capture
=> [undef, dump_on_failure
=> 1]) == 0
1960 or die "ERROR: Invoking @{$cmd} failed.\nStopped";
1963 print("Done Building GoogleTest\n");
1966 if (exists $opts{'jboss'} && !exists $opts{'java'}) {
1967 die "ERROR: --java is required for --jboss (OpenDDS JMS Provider).\nStopped";
1970 if (exists $opts{'jboss'} && !exists $opts{'ant'}) {
1971 die "ERROR: --ant is required for --jboss (OpenDDS JMS Provider).\nStopped";
1974 if (exists $opts{'wireshark-cmake'}) {
1975 if (exists $opts{'wireshark'}) {
1976 die "ERROR: --wireshark and --wireshark-cmake can not be used at the same time.\nStopped";
1979 if (! -d
($opts{'wireshark-build'} . '/' . $opts{'wireshark-lib'})) {
1980 if ($wireshark_lib_defaulted) {
1981 die "ERROR: The default value for wireshark-lib: " . $opts{'wireshark-lib'} .
1982 " does not exist, please supply wireshark-lib with the correct value";
1985 die "ERROR: The supplied wireshark-lib: " . $opts{'wireshark-lib'} . " does not exist.";
1990 if (exists $opts{'wireshark-cmake'} && !exists $opts{'wireshark-build'}) {
1991 die "ERROR: --wireshark-build are required with --wireshark-cmake.\nStopped";
1994 if (exists $opts{'wireshark-lib'} && !exists $opts{'wireshark-cmake'}) {
1995 die "ERROR: --wireshark-cmake and --wireshark-build is required for --wireshark-lib.\nStopped";
1998 if (exists $opts{'wireshark-build'} && !exists $opts{'wireshark-cmake'}) {
1999 die "ERROR: --wireshark-cmake is required for --wireshark-build.\nStopped";
2002 if ($opts{'glib'}) {
2003 if (!-r
"$opts{'glib'}/lib/glib-2.0/include/glibconfig.h") {
2004 my $pc = `pkg-config --cflags-only-I glib-2.0`;
2006 if ($pc =~ m!-I$opts{'glib'}/([-\w/]+)/glib-2.0/include!) {
2007 print "pkg-config found GLIB_LIB_DIR=$1\n" if $opts{'verbose'};
2008 setEnv
('GLIB_LIB_DIR', $1);
2011 print "Failed to locate glibconfig.h using pkg-config ($pc). Set the " .
2012 "environment variable GLIB_LIB_DIR and re-run MPC.\n";
2018 my ($buildEnvRef, $var, $path) = @_;
2019 if (exists $buildEnvRef->{$var}) {
2020 $buildEnvRef->{$var} .= $specific{'pathsep'} . $path;
2023 $buildEnvRef->{$var} = $path;
2028 my ($buildEnvRef, $path) = @_;
2029 push_env_dir
($buildEnvRef, 'PATH', $path);
2033 my ($buildEnvRef, $path) = @_;
2034 my $build = $buildEnvRef->{'build'};
2035 my $platform = $opts{$build};
2036 my $libpathname = $platforminfo{$platform}->{'libpath'};
2037 push_env_dir
($buildEnvRef, $libpathname, $path);
2041 if (exists $opts{'qt'}) {
2042 my $qglobal = "QtCore" . $slash . "qglobal.h";
2044 my $qt_bin; # location of Qt's code generators (like moc)
2045 my $qt_lib; # where linker should look for input (location of .lib or .so)
2046 my $qt_path; # add to PATH or LD_LIBRARY_PATH (location of .dll or .so.*)
2047 my $qt_bin_suffix = exists $ENV{'QT5_SUFFIX'} ?
$ENV{'QT5_SUFFIX'} : '';
2048 my $qt_moc = "moc" . $qt_bin_suffix . $exeext;
2049 my $qt_default_suffix = "-qt5";
2050 my $qt_moc_default_suffix = "moc" . $qt_default_suffix . $exeext;
2051 my $qt_help_mesg = ", stopped\nPlease either install Qt or provide the correct " .
2052 "Qt5 locations (see docs/qt.md for details).\n";
2054 if ($try_to_use_qt_system_pkg) {
2055 # Try to use pkg-config to get Qt locations
2056 `pkg-config --print-variables Qt5Core`;
2058 die "ERROR: Trying to use system Qt package but could not confirm " .
2059 "Qt and/or pkg-config exists on the system$qt_help_mesg";
2061 $qt_include = `pkg-config --variable=includedir Qt5Core`;
2062 die "ERROR: could not resolve system Qt include location$qt_help_mesg" if ($?
);
2064 $qt_bin = `pkg-config --variable=host_bins Qt5Core`;
2065 die "ERROR: could not resolve system Qt build tools location$qt_help_mesg" if ($?
);
2067 $qt_lib = `pkg-config --variable=libdir Qt5Core`;
2068 die "ERROR: could not resolve system Qt lib location$qt_help_mesg" if ($?
);
2072 if (exists $opts{'qt-include'}) {
2073 if (!length($opts{'qt-include'})) {
2074 die "ERROR: --qt-include requires an argument$qt_help_mesg";
2076 $qt_include = $opts{'qt-include'};
2079 $qt_include = $targetEnv{'QTDIR'} . $slash . 'include';
2082 if (exists $ENV{'QT5_BINDIR'}) {
2083 $qt_bin = $ENV{'QT5_BINDIR'};
2086 $qt_bin = $targetEnv{'QTDIR'} . $slash . 'bin';
2089 if (exists $ENV{'QT5_LIBDIR'}) {
2090 $qt_lib = $ENV{'QT5_LIBDIR'};
2093 $qt_lib = $targetEnv{'QTDIR'} . $slash . ($is_windows ?
'bin' : 'lib');
2098 # Try to guess if Qt vcpkg is being used
2099 my $vcpkg_tools = join($slash, $targetEnv{'QTDIR'}, "tools", "qt5");
2101 (-r
$vcpkg_tools . $slash . 'bin' . $slash . $qt_moc) &&
2102 !exists $ENV{'QT5_LIBDIR'} &&
2103 !exists $ENV{'QT5_BINDIR'};
2104 if ($assume_vcpkg) {
2105 $qt_bin = $vcpkg_tools . $slash . 'bin';
2107 $qt_lib = join($slash, $targetEnv{'QTDIR'}, "debug", "lib");
2108 $qt_path = join($slash, $targetEnv{'QTDIR'}, "debug",
2109 ($is_windows ?
'bin' : 'lib'));
2112 $qt_lib = join($slash, $targetEnv{'QTDIR'}, 'lib');
2116 # Check for Qt Headers using qglobal.h
2117 # Also try to detect if Qt Headers were just put in the include directory or
2118 # put in qt5 directory inside the include directory. For example, the former
2119 # might happen on Windows with prebuilt Qt while the latter might be the
2120 # case with Linux with Qt installed from package manager.
2121 if (! -r
$qt_include . $slash . $qglobal) {
2122 my $qt_subdir = $qt_include . $slash . 'qt5';
2123 if (-r
$qt_subdir . $slash . $qglobal) {
2124 $qt_include = $qt_subdir;
2127 die "ERROR: Could not find Qt headers at $qt_include" .
2128 " ($qglobal could not be found)$qt_help_mesg";
2132 # Check for Qt Tools using moc
2133 if (! -r
$qt_bin . $slash . $qt_moc) {
2134 # If QT5_SUFFIX isn't defined, maybe it needs a suffix
2135 if ((!exists $ENV{'QT5_SUFFIX'}) &&
2136 (-r
$qt_bin . $slash . $qt_moc_default_suffix)) {
2137 $qt_bin_suffix = $qt_default_suffix;
2140 die "ERROR: Could not find Qt build tools at $qt_bin" .
2141 " ($qt_moc could not be found)$qt_help_mesg";
2145 setEnv
('QT5_INCDIR', $qt_include);
2146 setEnv
('QT5_BINDIR', $qt_bin);
2147 setEnv
('QT5_SUFFIX', $qt_bin_suffix);
2148 setEnv
('QT5_LIBDIR', $qt_lib);
2149 push_libpath
(\
%targetEnv, $qt_path);
2151 elsif (exists $opts{'qt-include'}) {
2152 die "ERROR: --qt-include requires --qt, stopped\n";
2155 sub write_host_workspace
{
2156 my %buildEnv = %{shift()};
2157 my $MWC = backup_and_open
($buildEnv{'DDS_ROOT'} . '/host_tools.mwc');
2160 $(ACE_ROOT)/ace/ace.mpc
2161 $(ACE_ROOT)/apps/gperf/src
2163 dds/DCPS/OpenDDS_Util.mpc
2165 java/idl2jni/codegen
2167 print $MWC " \$(TAO_ROOT)/tao/tao.mpc\n" if $opts{'safety-profile'};
2170 print "Wrote host_tools.mwc in $buildEnv{'DDS_ROOT'}\n" if $opts{'verbose'};
2171 dump_and_unlink
($MWC) if $opts{'dry-run'};
2175 my $buildEnv = shift;
2176 for my $k (keys %{$buildEnv}) {
2177 next if $k eq 'build';
2178 if ($buildEnv->{$k} =~
2179 /^\Q$specific{'refpre'}\E$k\Q$specific{'refpost'}\E(.*)/) {
2182 print "ENV: Appending $1 to $k\n" if $opts{'verbose'};
2186 $ENV{$k} = $buildEnv->{$k};
2187 print "ENV: Setting $k to $buildEnv->{$k}\n" if $opts{'verbose'};
2192 sub disable_feature
{
2193 my($featureArray, $feature) = @_;
2194 $feature =~ s/-/_/g;
2195 push(@
{$featureArray}, "$feature=0");
2198 sub get_default_features
{
2199 my $buildEnv = shift;
2201 my %default_features;
2202 my $file = "$buildEnv->{ACE_ROOT}/bin/MakeProjectCreator/config/default.features";
2204 open(my $fh, '<', $file) or die "ERROR: Could not open $file: $!";
2205 while (my $row = <$fh>) {
2211 my ($key, $value) = split(/\s*=\s*/, $row);
2212 $default_features{$key} = $value;
2215 return %default_features;
2218 sub get_requested_features
{
2219 my %requested_features;
2220 for my $f (@features) {
2221 my ($key, $value) = split(/=/, $f);
2222 $value = "1" unless defined $value;
2223 $requested_features{$key} = $value;
2225 return %requested_features;
2229 my $buildEnv = shift;
2231 my %features = get_default_features
($buildEnv);
2232 my %requested_features = get_requested_features
();
2233 for my $key (keys(%requested_features)) {
2234 $features{$key} = $requested_features{$key};
2239 sub write_opendds_mwc
{
2243 $args = join(', ', (map {perlstring
($_)} @
{$args}));
2245 my $path = "$root/bin/opendds_mwc.pl";
2246 my $fd = backup_and_open
($path);
2249 if (!defined(\$ENV{ACE_ROOT}) || !defined(\$ENV{MPC_ROOT})) {
2250 die("The enviroment needs to be setup.");
2252 system('perl', "\$ENV{ACE_ROOT}/bin/mwc.pl", $args, \@ARGV) == 0
2253 or die("Failed to run mwc: \$!");
2256 print "Wrote $path\n" if $opts{'verbose'};
2257 dump_and_unlink
($fd) if $opts{'dry-run'};
2263 sub generate_workspace
{
2264 my $buildEnv = shift;
2265 $buildtao = $force_ace_tao;
2266 my $is_target = $buildEnv->{'build'} eq 'target';
2268 for my $feat (qw
/built-in-topics ownership-profile/) {
2269 if (exists $opts{$feat} && !$opts{$feat}) {
2270 disable_feature
(\
@features, $feat);
2274 if ($opts{'security'}) {
2275 disable_feature
(\
@features, 'no-opendds-security');
2278 # default of these depends on whether we are doing a safety-profile build
2279 for my $feat (qw
/content
-subscription content
-filtered
-topic
2280 multi
-topic query
-condition ownership
-kind
-exclusive
2281 object
-model
-profile persistence
-profile
2282 no-opendds
-safety
-profile
/) {
2283 if (defined $opts{'no-opendds-safety-profile'}) {
2284 if (!(exists $opts{$feat} && $opts{$feat})) {
2285 disable_feature
(\
@features, $feat);
2288 elsif (exists $opts{$feat} && !$opts{$feat}) {
2289 disable_feature
(\
@features, $feat);
2293 if ($is_target && $opts{'target'} eq 'android') {
2294 # We can't detect C++11 compatibility in cross compilers at the moment,
2295 # but all the NDKs we officially support are C++11+ by default, so enable
2296 # C++11 features unless an explicit 'no_cxx11' feature already is set.
2297 my $feat = 'no_cxx11';
2298 unless (has_feature
($feat)) {
2299 disable_feature
(\
@features, $feat);
2300 print "Setting $feat=0 for Android\n";
2303 # Disable including $JAVA_HOME/include on Android. Android NDK includes a
2305 disable_feature
(\
@features, 'jni_include')
2308 my $mpctype = (!$is_windows || ($cross_compile && $is_target))
2309 ?
'gnuace' : $opts{'compiler_version'};
2311 if ($mpctype eq 'gnuace') {
2313 if (@features || $cross_compile) {
2314 print "Writing $buildEnv->{'DDS_ROOT'}/user_macros.GNU\n"
2315 if $opts{'verbose'};
2316 $UM = backup_and_open
($buildEnv->{'DDS_ROOT'} . '/user_macros.GNU');
2319 for my $feat (@features) {
2322 print $UM ($feat =~ /=/ ?
$feat : "$feat=1"), "\n"
2323 unless $need_platform_macros{$key};
2325 if ($cross_compile) {
2327 OPENDDS_IDL = $(HOST_DDS)/bin/opendds_idl
2328 OPENDDS_IDL_DEP = $(OPENDDS_IDL)$(HOST_EXE_EXT)
2329 IDL2JNI = $(HOST_DDS)/bin/idl2jni
2330 IDL2JNI_DEP = $(IDL2JNI)$(HOST_EXE_EXT)
2335 dump_and_unlink
($UM) if $UM && $opts{'dry-run'};
2338 if ($opts{'safety-profile'} && $is_target) {
2339 $buildtao = 0; # TAO will be built separately
2342 # build tao if tao_idl does not exist
2343 $buildtao = $buildtao || !-x
"$buildEnv->{'ACE_ROOT'}/bin/tao_idl$exeext";
2346 locate_mpc
($ace_src);
2348 # Append to default.features
2350 push(@features, 'cross_compile') if $cross_compile;
2352 if ($platforminfo{$opts{'target'}}->{'needs_i2jrt_corba'} && $opts{'java'}) {
2353 if ($opts{'verbose'}) {
2354 print "Target platform needs i2jrt_corba.jar, forcing java_pre_jpms=0 to get it\n";
2357 for my $i (0 .. scalar $#features) {
2358 if ($features[$i] =~ /^java_pre_jpms/) {
2359 $features[$i] = 'java_pre_jpms=0';
2364 push(@features, "java_pre_jpms=0");
2368 if ($opts{'java'} && $cross_compile) {
2369 push(@features, "jni_check=0");
2372 if ($buildtao && @features) {
2373 my $df_file = $buildEnv->{'ACE_ROOT'} .
2374 '/bin/MakeProjectCreator/config/default.features';
2375 my $DF = $opts{'dry-run'} ? File
::Temp
->new()
2376 : new FileHandle
(">>$df_file");
2377 for my $f (@features) {
2378 print $DF ($f =~ /=/ ?
$f : "$f=1"), "\n";
2381 if ($opts{'verbose'}) {
2382 print '' . ($wrote_df ?
'Appended to' : 'Wrote') .
2383 " $buildEnv->{'ACE_ROOT'}/.../default.features\n";
2385 dump_and_unlink
($DF) if $opts{'dry-run'};
2388 if (!$buildtao && !defined $opts{'safety-profile'}) {
2389 # Check for compatibility between the requested features/macros
2390 # and the pre-built ACE/TAO.
2391 my %existing_features = get_default_features
($buildEnv);
2392 my %requested_features = get_requested_features
();
2393 for my $f (@ace_features) {
2394 if (defined $requested_features{$f}) {
2395 if (!defined $existing_features{$f}) {
2396 die "ERROR: Requested feature $f not defined for ACE/TAO";
2398 elsif ($requested_features{$f} != $existing_features{$f}) {
2399 die "ERROR: Feature $f set to $requested_features{$f} but has " .
2400 "value $existing_features{$f} in ACE/TAO";
2405 my $file = "$buildEnv->{'ACE_ROOT'}/include/makeinclude/platform_macros.GNU";
2406 my %existing_macros;
2408 open(my $fh, '<', $file) or die "ERROR: Could not open $file: $!";
2409 while (my $row = <$fh>) {
2411 $row =~ s/\s*#.*$//;
2412 if ($row =~ /^\s*(\w+)\s*[:?+]?=\s*(.*)$/) {
2413 my ($key, $value) = ($1, $2);
2414 $existing_macros{$key} = $value;
2417 my %requested_macros;
2418 for my $f (@platformmacros, @
{$opts{'macros'}}) {
2419 my ($key, $value) = split(/=/, $f);
2420 $value = "1" unless defined $value;
2421 $requested_macros{$key} = $value;
2423 for my $key (@ace_macros) {
2424 if (exists $opts{$key}) {
2425 my $macro = ($key eq 'static') ?
'static_libs_only' : $key;
2426 $requested_macros{$macro} = $opts{$key};
2429 for my $f (@ace_macros) {
2430 if (defined $requested_macros{$f}) {
2431 if (!defined $existing_macros{$f}) {
2432 die "ERROR: Requested macro $f not defined for ACE/TAO";
2434 elsif ($requested_macros{$f} != $existing_macros{$f}) {
2435 die "ERROR: Macro $f set to $requested_macros{$f} but has " .
2436 "value $existing_macros{$f} in ACE/TAO";
2444 my $custom_ws = "OpenDDS_custom.mwc";
2445 if (exists($opts{'workspace'})) {
2446 backup_and_copy
($opts{'workspace'}, $custom_ws);
2450 if (-r
"$buildEnv->{'DDS_ROOT'}/host_tools.mwc") {
2451 $ws = 'host_tools.mwc';
2453 elsif (-r
$custom_ws) {
2456 elsif (!$tests && $buildtao) {
2457 $ws = 'DDS_TAOv2.mwc';
2459 elsif (!$tests && !$buildtao) {
2460 $ws = 'DDS_no_tests.mwc';
2463 $ws = 'DDS_TAOv2_all.mwc';
2469 my $static = (($opts{'static'} && $is_windows) ||
2470 ($cross_compile && $buildEnv->{'build'} eq 'host' && $mpctype ne 'gnuace'));
2472 # We are not using CIAO or DAnCE, but MPC.cfg expands $CIAO_ROOT and
2473 # $DANCE_ROOT so leaving them empty/undefined would cause /MPC/config
2474 # to be on the include path for .mpb files.
2475 for my $var ('CIAO_ROOT', 'DANCE_ROOT') {
2476 $buildEnv->{$var} = 'unused' unless defined $buildEnv->{$var};
2479 my %savedEnv = %ENV;
2480 print "ENV: saving current environment\n" if $opts{'verbose'};
2481 mergeToEnv
($buildEnv);
2483 my @mwc_common_args = ('-type', $mpctype, @mpcopts);
2485 push(@mwc_common_args, '-static');
2489 my %existing_features = get_default_features
($buildEnv);
2490 my %requested_features = get_requested_features
();
2491 my @features_to_add;
2492 for my $feature (keys(%requested_features)) {
2493 my $value = $requested_features{$feature};
2494 push(@features_to_add, "$feature=$value") unless exists($existing_features{$feature});
2496 if (@features_to_add) {
2497 push(@mwc_common_args, '-features', join(',', @features_to_add));
2501 # Generate our own mwc wrapper script
2502 write_opendds_mwc
($buildEnv->{'DDS_ROOT'}, [@mwc_common_args]);
2504 my @mwc = ('perl', "$ENV{ACE_ROOT}/bin/mwc.pl");
2505 print 'Running MPC to generate ', ($mpctype eq 'gnuace' ?
'makefiles' :
2506 'project files'), ".\n";
2507 if (run_command
([@mwc, @mwc_common_args, "$buildEnv->{'DDS_ROOT'}$slash$ws"])) {
2508 die "ERROR: Error from MPC, stopped";
2510 $buildEnv->{'mpctype'} = $mpctype;
2512 # If this is a target safety profile build
2513 if (defined $opts{'no-opendds-safety-profile'}) {
2514 # Generate ACE workspace separately, to exclude TAO
2515 if (run_command
([@mwc, @mwc_common_args, "$buildEnv->{'ACE_ROOT'}/ace"])) {
2516 die "ERROR: Error from MPC, stopped";
2521 print "ENV: restoring previous environment\n" if $opts{'verbose'};
2523 $ws =~ s/\.mwc$/.sln/;
2524 $opts{'solution_file'} = $ws;
2527 sub convert_environment
{
2530 $$val =~ s/%(\w+)%/\$\{$1\}/g;
2533 sub write_environment
{
2534 my %buildEnv = %{shift()};
2537 if ($buildEnv{'mpctype'} eq 'gnuace') {
2538 if (!$opts{'dry-run'}) {
2539 move
($dir . '/GNUmakefile', $dir . '/GNUmakefile.dist');
2541 $MK = backup_and_open
($dir . '/GNUmakefile');
2544 my $SE = backup_and_open
($dir . '/setenv.' . $specific{'ext'});
2546 my $args_ = join(' ', map {/ / ?
('"' . $_ . '"') : $_} @ARGS);
2547 print $SE "$specific{'comment'} OpenDDS configure script: $0 $args_\n";
2548 print $MK "$specific{'comment'} OpenDDS configure script: $0 $args_\n" if $MK;
2550 for my $key (sort(keys(%buildEnv))) {
2551 if ($key ne 'build' && $key ne 'mpctype') {
2552 my $value = $buildEnv{$key};
2553 $value =~ s/^"(.*)"$/$1/g;
2556 print $SE "set \"$key=$value\"\n";
2559 my $posix_value = $value;
2560 $posix_value =~ s/"/\\"/g;
2561 print $SE "export $key=\"$posix_value\"\n";
2565 convert_environment
(\
$value) if $is_windows;
2566 print $MK "export $key := $value\n";
2572 print "Wrote $dir/setenv.$specific{'ext'}\n" if $opts{'verbose'};
2573 dump_and_unlink
($SE) if $opts{'dry-run'};
2576 print $MK "include GNUmakefile.dist\n";
2578 print "Wrote $dir/GNUmakefile, wrapping original GNUmakefile.dist\n"
2579 if $opts{'verbose'};
2580 dump_and_unlink
($MK) if $opts{'dry-run'};
2584 sub check_mac_version
{
2585 my $buildEnvRef = shift;
2586 if (-r
"$buildEnvRef->{ACE_ROOT}/ace/config-macosx.h") {
2587 my $cfg = new FileHandle
("$buildEnvRef->{ACE_ROOT}/ace/config-macosx.h");
2589 if (/__MAC_OS_X_VERSION_MAX_ALLOWED/) {
2595 die "ERROR: This version of ACE doesn't contain the required configuration " .
2596 "files for Apple macOS. Stopped";
2599 sub configure_build
{
2600 my $buildEnvRef = shift;
2601 if (-r
"$buildEnvRef->{ACE_ROOT}/ace/config.h" && !$force_ace_tao) {
2602 print "ACE_ROOT/ace/config.h exists, skipping configuration of ACE+TAO\n";
2605 check_mac_version
($buildEnvRef) if $opts{'host'} eq 'macosx';
2607 write_config_h
($buildEnvRef);
2608 write_default_features
($buildEnvRef);
2609 write_platform_macros
($buildEnvRef);
2611 write_opendds_configh
($buildEnvRef);
2612 generate_workspace
($buildEnvRef);
2613 write_environment
($buildEnvRef, $buildEnvRef->{'DDS_ROOT'});
2615 if ($buildEnvRef->{'build'} eq 'target') {
2616 write_cmake_file
($buildEnvRef);
2620 sub write_cross_compile_makefile
{
2621 my $MF = backup_and_open
('GNUmakefile');
2622 my $safety_profile_step = $opts{'safety-profile'} ?
2623 "\tcd $targetEnv{'ACE_ROOT'}/ace && " .
2624 '$(MAKE) $(if $(filter all,$@),ACE,$@)' . "\n" : '';
2626 # OpenDDS configure script: $0 @ARGS
2627 all clean realclean depend:
2628 \tcd build/host && \$(MAKE) \$@
2629 $safety_profile_step\tcd build/target && \$(MAKE) \$@
2630 .PHONY: all clean realclean depend
2633 print "Wrote top-level GNUmakefile for cross-compile\n" if $opts{'verbose'};
2634 dump_and_unlink
($MF) if $opts{'dry-run'};
2638 my($sub, $top) = @_;
2639 my $subdir = $opts{'dry-run'} ?
$sub : Cwd
::abs_path
($sub);
2640 my $parent = $opts{'dry-run'} ?
$top : Cwd
::abs_path
($top);
2641 if ($opts{'dry-run'} && $top eq '.' && looksRelative
($sub)) {
2642 return $slash . $sub;
2644 if (index($subdir, $parent) == 0) {
2645 return substr($subdir, length($parent));
2650 sub add_dependency_paths
{
2652 for my $key ('openssl', 'xerces3') {
2654 next if $opts{$key} eq '/usr' || $opts{$key} eq 'skip_version_check';
2655 my $suffix = $slash . 'bin';
2656 if ($opts{$key . '-debugbin'}) {
2657 $suffix = $slash . 'debug' . $suffix;
2659 $dirs{$targetEnv{$optdep{$key}->{env
}} . $suffix} = 1;
2662 for my $d (keys %dirs) {
2663 push_libpath
(\
%targetEnv, $d);
2666 if ($opts{'openssl'} && $ENV{'SSL_LIBDIR'}) {
2667 push_libpath
(\
%targetEnv, $ENV{'SSL_LIBDIR'});
2671 my $cloned_build = $cross_compile && $build_host_tools;
2672 if ($cloned_build) {
2673 clone_host_and_target
('.');
2674 setHostEnv
('DDS_ROOT', 'build/host');
2675 setEnv
('HOST_DDS', 'build/host');
2676 setEnv
('DDS_ROOT', 'build/target');
2678 my $tao_clone = $opts{'safety-profile'} ?
'host' : 'target';
2679 my $ace_sub_dds = nested
($ace_src, '.');
2680 my $tao_sub_dds = nested
($tao_src, '.');
2681 my $tao_sub_ace = nested
($tao_src, $ace_src);
2684 setHostEnv
('ACE_ROOT', 'build/host' . $ace_sub_dds);
2685 setEnv
('HOST_ACE', 'build/host' . $ace_sub_dds);
2686 setEnv
('ACE_ROOT', 'build/target' . $ace_sub_dds);
2689 clone_host_and_target
($ace_src);
2690 setHostEnv
('ACE_ROOT', $ace_src . '/build/host');
2691 setEnv
('HOST_ACE', $ace_src . '/build/host');
2692 setEnv
('ACE_ROOT', $ace_src . '/build/target');
2694 setHostEnv
('TAO_ROOT', $ace_src . '/build/host' . $tao_sub_ace);
2695 setEnv
('TAO_ROOT', $ace_src . '/build/' . $tao_clone . $tao_sub_ace);
2700 setHostEnv
('TAO_ROOT', 'build/host' . $tao_sub_dds);
2701 setEnv
('TAO_ROOT', 'build/' . $tao_clone . $tao_sub_dds);
2703 elsif (!$tao_sub_ace) {
2704 if ($opts{'safety-profile'}) {
2705 setHostEnv
('TAO_ROOT', $tao_src);
2706 setEnv
('TAO_ROOT', $tao_src);
2709 clone_host_and_target
($tao_src);
2710 setHostEnv
('TAO_ROOT', $tao_src . '/build/host');
2711 setEnv
('TAO_ROOT', $tao_src . '/build/target');
2715 push_path
(\
%targetEnv, $hostEnv{'ACE_ROOT'} . $slash . 'bin');
2716 push_path
(\
%targetEnv, $hostEnv{'DDS_ROOT'} . $slash . 'bin');
2718 print "Cross-compile configuring host\n";
2720 write_host_workspace
(\
%hostEnv); # host_tools.mwc
2721 configure_build
(\
%hostEnv);
2723 print "Cross-compile configuring target\n";
2725 if ($opts{'safety-profile'}) {
2726 $opts{'no-opendds-safety-profile'} = 0; # only set for target
2729 unless ($opts{'static'}) {
2730 push_libpath
(\
%targetEnv, $targetEnv{'ACE_ROOT'} . $slash . 'lib');
2731 push_libpath
(\
%targetEnv, $targetEnv{'DDS_ROOT'} . $slash . 'lib');
2733 add_dependency_paths
();
2736 configure_build
(\
%targetEnv);
2738 write_environment
(\
%targetEnv, $targetEnv{'ACE_ROOT'} . '/ace')
2739 if $opts{'safety-profile'};
2741 write_cross_compile_makefile
() if !$is_windows;
2743 else { # does not require cloned builds
2744 setEnv
('ACE_ROOT', $ace_src);
2745 setEnv
('TAO_ROOT', $tao_src);
2746 setEnv
('DDS_ROOT', '.');
2748 if (!$build_host_tools && $opts{'host-tools'}) {
2749 setEnv
('HOST_DDS', $opts{'host-tools'});
2752 push_path
(\
%targetEnv, $targetEnv{'ACE_ROOT'} . $slash . 'bin');
2753 push_path
(\
%targetEnv, $targetEnv{'DDS_ROOT'} . $slash . 'bin');
2755 unless ($opts{'static'}) {
2756 push_libpath
(\
%targetEnv, $targetEnv{'ACE_ROOT'} . $slash . 'lib');
2757 push_libpath
(\
%targetEnv, $targetEnv{'DDS_ROOT'} . $slash . 'lib');
2759 add_dependency_paths
();
2762 if ($host_tools_only) {
2763 write_host_workspace
(\
%targetEnv);
2766 configure_build
(\
%targetEnv);
2769 print "Completed configuring OpenDDS, next ";
2770 if (!$is_windows || ($cross_compile && !$cloned_build)) {
2771 print "run '", (($^O
eq 'freebsd') ?
'g' : ''), "make'";
2773 elsif ($cloned_build) {
2774 print "compile build\\host\\host_tools.sln\n",
2775 "using the environment in build\\host\\setenv.cmd.\n",
2776 "Then build OpenDDS for $opts{'target'} by running make in ",
2781 print "build '", $opts{'solution_file'}, "' using the '",
2782 ($opts{'optimize'} ?
'Release' : 'Debug'), "' configuration";
2785 print " to compile ",
2786 ($cloned_build ?
"\nthe host and target builds of " : ''),
2787 "OpenDDS", (($buildtao || $cloned_build) ?
' and ACE+TAO' : '') ,".\n",
2788 "You can use the generated setenv.$specific{'ext'} script ",
2790 "in the\nbuild${slash}host and build${slash}target dirs " : ''),
2791 "to set environment\nvariables for future shell sessions.\n";
2792 if ($is_windows && !$cross_compile) {
2793 print "Start Visual Studio from this command prompt so that it inherits ",
2794 "the correct\nenvironment variables. Try running \"devenv $opts{'solution_file'}\".\n";
2797 sub write_cmake_file
{
2798 my $buildEnv = shift();
2800 my $module_dir = "$buildEnv->{'DDS_ROOT'}/cmake";
2801 mkpath
($module_dir) unless -d
$module_dir;
2802 my $fh = backup_and_open
($module_dir . '/config.cmake');
2804 sub whack_to_slash
{
2810 sub to_cmake_scalar
{
2812 return 'ON' if "$val" eq '1';
2813 return 'OFF' if "$val" eq '0';
2814 return '"' . whack_to_slash
($val) . '"';
2818 my @list = @
{$_[0]};
2819 return '"' . join(';', map {whack_to_slash
($_)} @list) . '"';
2822 sub to_cmake_value
{
2823 my $value = shift();
2825 my $ref_type = ref($value);
2826 if ($ref_type eq 'ARRAY') {
2827 return to_cmake_list
($value);
2829 elsif ($ref_type eq '') {
2830 return to_cmake_scalar
($value);
2833 die "ERROR: to_cmake_value invalid value type, stopped";
2837 sub print_cmake_config
{
2840 my $value = shift();
2842 $name = uc("OPENDDS_$name");
2845 print $fh "set($name ", to_cmake_value
($value), ")\n";
2848 sub generate_config_cmake
{
2850 my $buildEnv = shift();
2852 print_cmake_config
($fh, 'MPC', Cwd
::abs_path
($buildEnv->{'MPC_ROOT'}));
2853 print_cmake_config
($fh, 'ACE', Cwd
::abs_path
($buildEnv->{'ACE_ROOT'}));
2854 print_cmake_config
($fh, 'TAO', Cwd
::abs_path
($buildEnv->{'TAO_ROOT'}));
2856 print $fh "\n# Based on MPC features\n";
2860 feature
=> 'no_cxx11',
2865 feature
=> 'uses_wchar',
2872 name
=> 'SAFETY_PROFILE',
2873 feature
=> 'no_opendds_safety_profile',
2877 name
=> 'VERSIONED_NAMESPACE',
2878 feature
=> 'versioned_namespace',
2881 name
=> 'SUPPRESS_ANYS',
2882 feature
=> 'dds_suppress_anys',
2887 feature
=> 'dds_non_coverage',
2891 name
=> 'TAO_CORBA_E_COMPACT',
2892 feature
=> 'corba_e_compact',
2895 name
=> 'TAO_CORBA_E_MICRO',
2896 feature
=> 'corba_e_micro',
2899 name
=> 'TAO_MINIMUM_CORBA',
2900 feature
=> 'minimum_corba',
2904 feature
=> 'tao_no_iiop',
2909 name
=> 'TAO_GEN_OSTREAM',
2910 feature
=> 'gen_ostream',
2913 name
=> 'TAO_OPTIMIZE_COLLOCATED_INVOCATIONS',
2914 feature
=> 'optimize_collocated_invocations',
2918 my %features = get_features
($buildEnv);
2919 for my $config (@configs) {
2920 my $inverted = $config->{inverted
} // 0;
2921 my $default = $config->{default} // 0;
2923 if (exists($features{$config->{feature
}})) {
2924 $enabled = $features{$config->{feature
}} eq "1" ?
!$inverted : $inverted;
2927 $enabled = $default;
2929 print_cmake_config
($fh, $config->{name
}, $enabled);
2932 if (defined($cxx_std)) {
2933 print_cmake_config
($fh, 'OPENDDS_CXX_STD', $cxx_std);
2936 # TODO(iguessthislldo): Move to a smarter system that can use existing
2937 # ACE/TAO and that works with cross compiling.
2938 print $fh "\n# Based on configure script options\n";
2940 'built-in-topics' => 1,
2942 'content-filtered-topic' => 1,
2943 'content-subscription' => 1,
2949 'object-model-profile' => 1,
2951 'ownership-kind-exclusive' => 1,
2952 'ownership-profile' => 1,
2953 'persistence-profile' => 1,
2955 'query-condition' => 1,
2962 for my $opt (sort(keys(%opts_to_use))) {
2963 print_cmake_config
($fh, $opt, exists($opts{$opt}) ?
$opts{$opt} : $opts_to_use{$opt});
2965 print_cmake_config
($fh, 'features', \
@features);
2966 print_cmake_config
($fh, 'mpcopts', \
@mpcopts);
2968 print $fh "\n# Sanitizers\n";
2969 for my $name (sort(keys(%all_sanitizers))) {
2970 print_cmake_config
($fh, $name, exists($enabled_sanitizers{$name}) ?
1 : 0);
2972 if (scalar(@fsanitize)) {
2973 print_cmake_config
($fh, 'SANITIZER_COMPILER_ARGS', \
@sanitizer_compiler_args);
2974 print_cmake_config
($fh, 'SANITIZER_LINKER_ARGS', \
@sanitizer_linker_args);
2979 # Contains configuration variables for the FindOpenDDS cmake module based on
2980 # detected defaults and/or user-supplied switches. Feel free to edit them as
2981 # necessary, but keep in mind that they will be moved to config.cmake.bak.*
2982 # the next time the \$DDS_ROOT/configure script is executed.
2984 # THIS FILE WAS AUTO-GENERATED BY: $0 @ARGS
2987 generate_config_cmake
($fh, $buildEnv);
2988 dump_and_unlink
($fh) if $opts{'dry-run'};