Compiling with ocamlbuild and camlp5 - preprocessor

I am trying to make a project I am working on compile with ocamlbuild, in order to avoid the use of a regular Makefile, which I find to be slightly more complicated.
Specifically, I have a syntax extension file (extend.ml), which I need to be compiled first. In a regular Makefile there would be a rule:
extend.cmo: extend.ml
$(OCAMLC) -pp "camlp5o pa_extend.cmo q_MLast.cmo" -I +camlp5 -c $<
and then, for calculating the dependencies there would be a rule like this:
depend: $(MLFILES) extend.cmo
$(OCAMLDEP) -pp "camlp5o ./extend.cmo"
Of course, the creation of any object file would require a similar rule to the one above.
My question is, how can I integrate these rules/requirements to one ocamlbuild command (if possible)?
I have tried to compile the extend.ml file first, and then use the following command:
ocamlbuild -pp "camlp5o ./extend.cmo" -I +camlp5 -use-menhir -no-hygiene Main.byte
but I don't think it's optimal in any way.
Unfortunately, I am not familiar with the use of ocamlbuild as a compilation tool, so any help will be much appreciated.

You could define two new tags, compile_extend and use_extend, that specify the expected options. In your myocamlbuild.ml file:
open Ocamlbuild_plugin
let my_flags () =
flag ["ocaml"; "pp"; "compile_extend"]
(S [A"camlp5o"; A "pa_extend.cmo"; A "q_MLast.cmo"]);
flag ["ocaml"; "pp"; "use_extend"]
(S [A"camlp5o"; A "extend.cmo"]);
(* files with the use_extend flag must depend on extend.cmo *)
dep ["ocaml"; "use_extend"] ["extend.cmo"];
()
let () =
dispatch (function
| After_rules ->
my_flags ();
| _ -> ())
Then you would have a tags file with:
"extend.cmo": compile_extend
<Main.*>: use_extend
That said, this is all bling guessing, I have not tested this setup. Could you provide a tarball with an example extend.ml file and Main.ml allowing to reproduce your situation?

Related

Some exported symbols disappear after creating a dynamic framework with the ios_framework rule

I am facing quite a strange situation trying to build a mixed-language dynamic iOS framework with Bazel.
The source code of the framework consists of *.c, *.cpp, *.m, *.mm, *.h, *.hpp files.
My first naive attempt was to declare a single objc_library rule referencing all the sources. That failed with an error message reading something about conflicting rules. Then I declared four distinct objc_library rules for *.m, *.mm, *.c, and *.cpp files respectively, and then referenced all these four rules as dependencies for the final ios_framework rule.
At this point, everything compiled and linked just fine (barring several compiler warnings which were expected). However, now the black magic begins:
The static library resulting from compiling ObjectiveC++ sources does contain all the necessary symbols (verified with the "nm" tool)
The .apple_binary_lipobin file resulting from the linking phase does not contain symbols from ObjectiveC++ sources
I believe I carefully went through the command lines used for compiling and linking, both for Bazel and xcodebuild.
The only anomalies I was able to spot:
xcodebuild passes a -single_module argument when linking, while Bazel cross tool does not.
Bazel cross tool adds '-stdlib=libc++' '-std=gnu++11' command line arguments when invoking wrapped_clang_pp during linking, while xcodebuild does not pass these arguments. I guess Bazel does this because there're these lines in the default Apple CROSSTOOL:
action_config {
config_name: "objc++-executable"
action_name: "objc++-executable"
tool {
tool_path: "wrapped_clang_pp"
execution_requirement: "requires-darwin"
}
flag_set {
flag_group {
flag: "-stdlib=libc++"
flag: "-std=gnu++11"
}
but I am not sure if these flags are really needed when invoking the linker.
I must admit I've run out of ideas except for trying to patch the CROSSTOOl file to make it behave as close as xcodebuild as possible.
Please help.
Can you try adding alwayslink = 1 to the objc_library target containing the C++ symbols? The linker is deadstripping the C++ symbols as they are not being referenced anywhere in the binary.

How to create a call graph of an iOS app?

I'm looking for a relatively simple way of creating a call graph of an iOS app (or a framework), using it's Xcode project or the obj code it emits.
The project files are a combination of Objective C, Swift and C++.
I've already tried clang's scan-build, but haven't had any luck turning the .dot files into graphViz graphs. I ended up with hundreds of .dot files and after dot, for over an hour, tries to load them up, nothing happens.
I've also tried to use opt, by adding this to my build line:
-S -emit-llvm -o - | opt -dot-callgraph -S
(from this SO question
but I get only a 107 byte callgraph.dot file and that doesn't have anything notable in it.
I think these errors are what make the output useless:
clang-5.0: warning: 'linker' input unused [-Wunused-command-line-argument]
clang-5.0: warning: argument unused during compilation: '-emit-llvm' [-Wunused-command-line-argument]

How parse Perl 6 code using STD.pm6 grammar?

I would like minimal working example of parsing Perl 6 code from Perl 6 using STD.pm6
Running something like this
use v6;
use STD.pm6;
my $j = slurp 'e:\src\perl6\valid-p6-script.p6';
my $o = STD::Grammar.parse($j);
say $o.perl;
under debugger give me absolutely weird output:
e:\src\prg\perl6>c:\rakudo\bin\perl6-debug-m.bat -I. p6.p6
>>> LOADING p6.p6
>>> LOADING E:\src\prg\perl6\STD.pm6
Unhandled exception: ctxlexpad needs an MVMContext
at gen/moar/m-CORE.setting:15136 (C:\rakudo/share/perl6/runtime/CORE.setting.moarvm::24)
from gen/moar/m-CORE.setting:15250 (C:\rakudo/share/perl6/runtime/CORE.setting.moarvm:AT-KEY:95)
from gen/moar/m-CORE.setting:4291 (C:\rakudo/share/perl6/runtime/CORE.setting.moarvm:postcircumfix:<{ }>:4294967295)
from C:\rakudo/share/perl6/lib/Debugger/UI/CommandLine.pm:736 (C:\rakudo\share\perl6\lib\Debugger\UI\CommandLine.pm.mo
arvm::82)
from gen/moar/m-CORE.setting:2826 (C:\rakudo/share/perl6/runtime/CORE.setting.moarvm:sink-all:168)
from gen/moar/m-CORE.setting:10187 (C:\rakudo/share/perl6/runtime/CORE.setting.moarvm:sink:36)
from C:\rakudo/share/perl6/lib/Debugger/UI/CommandLine.pm:730 (C:\rakudo\share\perl6\lib\Debugger\UI\CommandLine.pm.mo
arvm:unhandled:114)
from C:\rakudo/share/perl6/lib/Debugger/UI/CommandLine.pm:721 (C:\rakudo\share\perl6\lib\Debugger\UI\CommandLine.pm.mo
arvm::25)
from gen/moar/m-Metamodel.nqp:3586 (C:\rakudo\share\nqp\lib/Perl6/Metamodel.moarvm:enter:28)
from gen/moar/m-CORE.setting:5190 (C:\rakudo/share/perl6/runtime/CORE.setting.moarvm:CALL-ME:57)
from gen/moar/m-BOOTSTRAP.nqp:2749 (C:\rakudo/share/nqp/lib/Perl6/BOOTSTRAP.moarvm::93)
from gen\moar\stage2\NQPHLL.nqp:1425 (C:\rakudo\share\nqp\lib/NQPHLL.moarvm:command_eval:380)
from src/Perl6/Compiler.nqp:59 (C:\rakudo\share\nqp\lib/Perl6/Compiler.moarvm:command_eval:93)
from gen\moar\stage2\NQPHLL.nqp:1365 (C:\rakudo\share\nqp\lib/NQPHLL.moarvm:command_line:114)
from gen/moar/m-perl6-debug.nqp:497 (C:\rakudo\share\perl6\runtime\perl6-debug.moarvm:MAIN:190)
from gen/moar/m-perl6-debug.nqp:440 (C:\rakudo\share\perl6\runtime\perl6-debug.moarvm:<mainline>:68)
from <unknown>:1 (C:\rakudo\share\perl6\runtime\perl6-debug.moarvm:<main>:8)
from <unknown>:1 (C:\rakudo\share\perl6\runtime\perl6-debug.moarvm:<entry>:9)
or without debugger:
e:\src\prg\perl6>c:\rakudo\bin\perl6.bat -I. p6.p6
===SORRY!=== Error while compiling E:\src\prg\perl6\STD.pm6
Semicolon form of 'grammar' without 'unit' is illegal. You probably want to use 'unit grammar'
at E:\src\prg\perl6\STD.pm6:8
------> :ver<6.0.0.alpha>:auth<http://perl.org>;<HERE><EOL>
from p6.p6:2
STD.pm6 was the reference grammar/verifier maintained by Larry during the development of the various Perl 6 compilers (Rakudo, Pugs, Niecza, ...). It comes with a dedicated tool called viv that translates it to Perl 5. As far as I know, it never ran on any of the mainstream compilers.
With the 6.c language release, the torch of reference implementation has essentially passed on to Rakudo, which uses its own grammar written in NQP to parse Perl 6.
While this Grammar (in combination with the corresponding actions) can be used for manual parsing by importing these modules :from<NQP>, the more friendly approach (eg no need to declare $*LINEPOSCACHE) would be via the corresponding compiler object:
say nqp::getcomp('perl6').eval($source, :target<parse>).dump;
Other targets of interest might be :target<syntaxcheck> as well as the more low-level :target<ast> or for the curious perhaps even :target<mast>.
Working example from #perl6 conversation:
use nqp;
use Perl6::Grammar:from<NQP>;
use Perl6::Actions:from<NQP>;
my $source = q|say "hello world";|;
my $*LINEPOSCACHE;
my $p6c = Perl6::Grammar.parse($source, :actions(Perl6::Actions.new()));
say $p6c.dump

Compile with standalone flag gives compilation errors in client code

I'm attempting to compile Zero29 with the --standalone compiler flag. The project itself compiles fine, but I have a unit test project that exercises some code in the Zero29 project, even though it's an executable program (.exe).
Everything works fine without the --standalone compilation flag.
However, when I add the --standalone compilation flag to the Zero29 project, the Zero29 project compiles fine, but in the unit test project, the compiler complains about this Discriminated Union defined in the Zero29 project:
namespace Ploeh.ZeroToNine
open System
open Ploeh.ZeroToNine.Versioning
type Arg =
| Assign of Version
| AssignRank of Rank * int
| Increment of Rank
| ListVersions
| ShowHelp
| Unknown of string list
The unit test project directly references the Zero29 project:
Zero29.UnitTests --references--> Zero29 (where --standalone is added)
When I attempt to compile the entire solution, the Zero29 project compiles with the --standalone flag, but then compilation of Zero29.UnitTests fails. There are several errors, but they are all the same, so here's a single example:
error FS0039: The value or constructor 'Assign' is not defined
Which points to the third line of this code:
let ParseAssignVersionReturnsCorrectResult(version : string) =
let actual = [| "-a"; version |] |> Args.Parse
verify <# [Assign(Version version)] = (actual |> Seq.toList) #>
The strange thing is that while the compiler complains about Assign in the third line of this code snippet, it doesn't complain about the use of Args.Parse, even though it's defined in the same code file as the Arg Discriminated Union.
Why does it do that, and how can I resolve this issue?
(I've attempted to distil the problem here, but the links I've provided point to the actual code files on GitHub, if more information is required.)
Libraries compiled with the --standalone switch cannot expose any F# datatypes. This is, for one, expressly stated in Pickering (2007), p. 210. In your case, a discriminated union is one of these prohibited types. The fact that the file is an executable changes nothing here: it becomes a library the moment you attempt to use it as one.
There have been also multiple reports (for example, here and here) that even libraries compiled with --standalone behave, quoting one of these sources, “funky.” It would be safe to say that the use of this switch should perhaps be limited to stand-alone executables only (and they cannot pretend to be a library even when under unit tests).
Pickering R. (2007). Foundations of F#. Apress.

Erlang binary: Will this result in a copy?

After reading this document, I'm not sure whether or not the following code will make the run-time copy binaries of A internally.
f(<<>>, A) ->
A;
f(<<X:2/binary, R/binary>>, A) ->
I = binary_to_integer(X, 16),
f(R, <<A/binary, I>>).
My guess is "no", because A isn't sent nor is it deconstructed. Am I right, or did I miss something?
Your code will not result in run-time copying of the A binaries since no sharing of sub-binaries is done. If we manually unroll the sequence of append operations it looks something like
A0 = <<A/binary, SomeByte>>,
A1 = <<A0/binary, SomeByte1>>,
A2 = <<A1/binary, SomeByte2>>,
.....
An = <<An-1, SomeByteN>>.
So we are only appending to the binary resulting from the latest append operation, i.e. there is a single reference to the ProcBin that was created for A0(as described in the efficiency documentation).
Why not use bin_opt_info option ?
For your code :
[root#nimbus bin_test]# erlc +bin_opt_info a.erl
a.erl:8: Warning: OPTIMIZED: creation of sub binary delayed
For the code in https://gist.github.com/wardbekker/5673200
The output is :
[root#nimbus bin_test]# erlc +bin_opt_info test.erl
test.erl:14: Warning: OPTIMIZED: creation of sub binary delayed
[root#nimbus bin_test]# erlc +bin_opt_info test2.erl
test2.erl:8: Warning: variable 'A' is unused
test2.erl:13: Warning: OPTIMIZED: creation of sub binary delayed

Resources