[RFC][build] Use dune environments and profiles instead of contexts

Summary:
With profiles and `(env ...)` stanza it's possible to consolidate
various ocamlc/ocamlopt/etc setups in a single place.

Where previously we needed to append `dune.common` to every dune file
and specify `flags` and `ocamlopt_flags` now the flags are specified
in `env` and applied accross the board.

This allows to
1. simplify build definitions,
2. avoid the need to generate dune files,
3. use plain sexps instead of OCaml and JBuilder plugin in build
files.

(I'll try to address 2 and 3 in the followup patches).

Existing `make` targets should continue working as before. Also, we
can use dune CLI like so:
```
infer/src$ dune printenv --profile opt # <- very useful for introspection
infer/src$ dune build check
infer/src$ dune build check --profile test
infer/src$ dune build infer.exe --profile dev
infer/src$ dune build infer.exe --profile opt
```

Also, with just 1 context something like `dune runtest` will run unit
tests only once instead of N times, where N is the number of contexts.

Now, there's one difference compared to the previous setup with
contexts:
- Previously, each context had its own build folder, and building infer
in opt context didn't invalidate any of the build artifacts in default
context. Therefore, alternating between `make` and `make opt` had low
overhead at the expense of having N copies of all build artifacts (1
for every context).
- Now, there's just 1 build folder and switching between profiles does
invalidate some artifacts (but not all) and rebuild takes a bit more
time.

So, if you're alternating like crazy between profiles your experience
may get worse (but not necessarily, more on that below). If you want
to trigger an opt build occasionally, you shouldn't notice much
difference.

For those who are concerned about slower build times when alternating
between different build profiles, there's a solution: [dune
cache](https://dune.readthedocs.io/en/stable/caching.html).

You can enable it by creating a file `~/.config/dune/config` with the
following contents:
```
(lang dune 2.0)
(cache enabled)
```

With cache enabled switching between different build profiles (but
also branches and commits) has ~0 overhead.

Dune cache works fine on Linux, but unfortunately there are [certain
problems with
MacOS](https://github.com/ocaml/dune/issues/3233) (hopefully, those
will be fixed soon and then there will be no downsides to using
profiles compared to contexts for our case).

Reviewed By: jvillard

Differential Revision: D20247864

fbshipit-source-id: 5f8afa0db
master
Artem Pianykh 5 years ago committed by Facebook GitHub Bot
parent 40e5a3c5c3
commit fcce3c0659

@ -20,12 +20,12 @@ make devsetup
### Building Infer for Development ### Building Infer for Development
- Build the code faster: `make -j BUILD_MODE=default`. By default `make` builds infer with flambda - Build the code faster: `make -j BUILD_MODE=dev`. By default `make` builds infer with flambda
enabled, which makes it very slow (but makes infer significantly faster). enabled, which makes it very slow (but makes infer significantly faster).
- Faster edit/build cycle when working on OCaml code inside infer/src/: build inside infer/src/ - Faster edit/build cycle when working on OCaml code inside infer/src/: build inside infer/src/
(skips building the models after infer has been built), and build bytecode instead of native: (skips building the models after infer has been built), and build bytecode instead of native:
`make -j -C infer/src byte`. You need to have run `make -j` (with or without `BUILD_MODE=default`) `make -j -C infer/src byte`. You need to have run `make -j` (with or without `BUILD_MODE=dev`)
at some point before. at some point before.
- In general, `make` commands from the root of the repository make sure that dependencies are in a - In general, `make` commands from the root of the repository make sure that dependencies are in a
@ -37,7 +37,7 @@ make devsetup
before running the test, but running `make -C infer/tests/codetoanalyze/java/infer test` will just before running the test, but running `make -C infer/tests/codetoanalyze/java/infer test` will just
execute the test. execute the test.
- To switch the default build mode to flambda disabled, you can `export BUILD_MODE=default` in your - To switch the default build mode to flambda disabled, you can `export BUILD_MODE=dev` in your
shell. shell.
### Debugging OCaml Code ### Debugging OCaml Code

@ -13,7 +13,7 @@ ORIG_SHELL_BUILD_MODE = $(BUILD_MODE)
# override this for faster builds (but slower infer) # override this for faster builds (but slower infer)
BUILD_MODE ?= opt BUILD_MODE ?= opt
MAKE_SOURCE = $(MAKE) -C $(SRC_DIR) INFER_BUILD_DIR=_build/$(BUILD_MODE) MAKE_SOURCE = $(MAKE) -C $(SRC_DIR)
ifneq ($(UTOP),no) ifneq ($(UTOP),no)
BUILD_SYSTEMS_TESTS += infertop BUILD_SYSTEMS_TESTS += infertop
@ -293,9 +293,9 @@ toplevel:
$(QUIET)echo "You can now use the infer REPL:" $(QUIET)echo "You can now use the infer REPL:"
$(QUIET)echo " \"$(ABSOLUTE_ROOT_DIR)/scripts/infer_repl\"" $(QUIET)echo " \"$(ABSOLUTE_ROOT_DIR)/scripts/infer_repl\""
toplevel_test: test_build toplevel_test:
$(QUIET)$(call silent_on_success,Building Infer REPL (test mode),\ $(QUIET)$(call silent_on_success,Building Infer REPL,\
$(MAKE_SOURCE) BUILD_MODE=test toplevel) $(MAKE_SOURCE) toplevel)
ifeq ($(IS_FACEBOOK_TREE),yes) ifeq ($(IS_FACEBOOK_TREE),yes)
byte src_build_common src_build test_build: fb-setup byte src_build_common src_build test_build: fb-setup
@ -331,16 +331,14 @@ $(INFER_GROFF_MANUALS_GZIPPED): %.gz: %
infer_models: src_build infer_models: src_build
ifeq ($(BUILD_JAVA_ANALYZERS),yes) ifeq ($(BUILD_JAVA_ANALYZERS),yes)
$(MAKE) -C $(ANNOTATIONS_DIR) $(QUIET)$(call silent_on_success,Building infer annotations,\
$(MAKE) -C $(ANNOTATIONS_DIR))
endif endif
$(MAKE) -C $(MODELS_DIR) all $(QUIET)$(call silent_on_success,Building infer models,\
$(MAKE) -C $(MODELS_DIR) all)
.PHONY: infer byte_infer .PHONY: infer byte_infer
infer byte_infer: infer byte_infer: infer_models
$(QUIET)$(call silent_on_success,Building Infer models,\
$(MAKE) infer_models)
$(QUIET)$(call silent_on_success,Building Infer manuals,\
$(MAKE) $(INFER_MANUALS))
infer: src_build infer: src_build
byte_infer: byte byte_infer: byte
@ -442,8 +440,7 @@ ocaml_unit_test: test_build
$(QUIET)$(REMOVE_DIR) infer-out-unit-tests $(QUIET)$(REMOVE_DIR) infer-out-unit-tests
$(QUIET)$(call silent_on_success,Running OCaml unit tests,\ $(QUIET)$(call silent_on_success,Running OCaml unit tests,\
INFER_ARGS=--results-dir^infer-out-unit-tests \ INFER_ARGS=--results-dir^infer-out-unit-tests \
BUILD_DIR=$(BUILD_DIR)/test \ $(SCRIPT_DIR)/dune_exec_shim.sh $(BUILD_DIR)/default/inferunit.bc)
$(SCRIPT_DIR)/dune_exec_shim.sh $(BUILD_DIR)/test/inferunit.bc)
define silence_make define silence_make
$(1) 2> >(grep -v 'warning: \(ignoring old\|overriding\) \(commands\|recipe\) for target') $(1) 2> >(grep -v 'warning: \(ignoring old\|overriding\) \(commands\|recipe\) for target')
@ -580,11 +577,14 @@ mod_dep: src_build_common
$(MAKE) -C $(SRC_DIR) mod_dep.dot) $(MAKE) -C $(SRC_DIR) mod_dep.dot)
.PHONY: config_tests .PHONY: config_tests
config_tests: test_build ocaml_unit_test endtoend_test checkCopyright validate-skel mod_dep config_tests: test_build ocaml_unit_test validate-skel mod_dep
$(MAKE) endtoend_test checkCopyright
$(QUIET)$(call silent_on_success,Building Infer manuals,\
$(MAKE) $(INFER_MANUALS))
ifneq ($(filter config_tests test,${MAKECMDGOALS}),) ifneq ($(filter endtoend_test,${MAKECMDGOALS}),)
test_build: src_build checkCopyright: src_build
checkCopyright: src_build test_build toplevel_test: checkCopyright
endif endif
.PHONY: test .PHONY: test
@ -841,14 +841,14 @@ devsetup: Makefile.autoconf
fi; \ fi; \
if [ -z "$(ORIG_SHELL_BUILD_MODE)" ]; then \ if [ -z "$(ORIG_SHELL_BUILD_MODE)" ]; then \
echo >&2; \ echo >&2; \
echo '$(TERM_INFO)*** NOTE: Set `BUILD_MODE=default` in your shell to disable flambda by default.$(TERM_RESET)' >&2; \ echo '$(TERM_INFO)*** NOTE: Set `BUILD_MODE=dev` in your shell to disable flambda by default.$(TERM_RESET)' >&2; \
echo '$(TERM_INFO)*** NOTE: Compiling with flambda is ~5 times slower than without, so unless you are$(TERM_RESET)' >&2; \ echo '$(TERM_INFO)*** NOTE: Compiling with flambda is ~5 times slower than without, so unless you are$(TERM_RESET)' >&2; \
echo '$(TERM_INFO)*** NOTE: testing infer on a very large project it will not be worth it. Use the$(TERM_RESET)' >&2; \ echo '$(TERM_INFO)*** NOTE: testing infer on a very large project it will not be worth it. Use the$(TERM_RESET)' >&2; \
echo '$(TERM_INFO)*** NOTE: commands below to set the default build mode. You can then use `make opt`$(TERM_RESET)' >&2; \ echo '$(TERM_INFO)*** NOTE: commands below to set the default build mode. You can then use `make opt`$(TERM_RESET)' >&2; \
echo '$(TERM_INFO)*** NOTE: when you really do want to enable flambda.$(TERM_RESET)' >&2; \ echo '$(TERM_INFO)*** NOTE: when you really do want to enable flambda.$(TERM_RESET)' >&2; \
echo >&2; \ echo >&2; \
printf "$(TERM_INFO) export BUILD_MODE=default$(TERM_RESET)\n" >&2; \ printf "$(TERM_INFO) export BUILD_MODE=dev$(TERM_RESET)\n" >&2; \
printf "$(TERM_INFO) echo 'export BUILD_MODE=default' >> \"$$shell_config_file\"$(TERM_RESET)\n" >&2; \ printf "$(TERM_INFO) echo 'export BUILD_MODE=dev' >> \"$$shell_config_file\"$(TERM_RESET)\n" >&2; \
fi fi
$(QUIET)PATH=$(ORIG_SHELL_PATH); if [ "$$(ocamlc -where 2>/dev/null)" != "$$($(OCAMLC) -where)" ]; then \ $(QUIET)PATH=$(ORIG_SHELL_PATH); if [ "$$(ocamlc -where 2>/dev/null)" != "$$($(OCAMLC) -where)" ]; then \
echo >&2; \ echo >&2; \
@ -867,7 +867,7 @@ doc: src_build_common
# do not call the browser if we are publishing the docs # do not call the browser if we are publishing the docs
ifeq ($(filter doc-publish,${MAKECMDGOALS}),) ifeq ($(filter doc-publish,${MAKECMDGOALS}),)
$(QUIET)$(call silent_on_success,Opening in browser,\ $(QUIET)$(call silent_on_success,Opening in browser,\
browse $(SRC_DIR)/_build/$(BUILD_MODE)/_doc/_html/index.html) browse $(SRC_DIR)/_build/default/_doc/_html/index.html)
$(QUIET)echo "Tip: you can generate the doc for all the opam dependencies of infer like this:" $(QUIET)echo "Tip: you can generate the doc for all the opam dependencies of infer like this:"
$(QUIET)echo $(QUIET)echo
$(QUIET)echo " odig odoc # takes a while, run it only when the dependencies change" $(QUIET)echo " odig odoc # takes a while, run it only when the dependencies change"
@ -895,7 +895,7 @@ endif
ifeq ($(IS_FACEBOOK_TREE),no) ifeq ($(IS_FACEBOOK_TREE),no)
$(QUIET)$(call silent_on_success,Copying OCaml modules documentation,\ $(QUIET)$(call silent_on_success,Copying OCaml modules documentation,\
version=$$($(INFER_BIN) --version | head -1 | cut -d ' ' -f 3 | cut -c 2-); \ version=$$($(INFER_BIN) --version | head -1 | cut -d ' ' -f 3 | cut -c 2-); \
rsync -a --delete $(SRC_DIR)/_build/$(BUILD_MODE)/_doc/_html/ "$(GHPAGES)"/static/odoc/"$$version"; \ rsync -a --delete $(SRC_DIR)/_build/default/_doc/_html/ "$(GHPAGES)"/static/odoc/"$$version"; \
$(REMOVE) "$(GHPAGES)"/static/odoc/latest; \ $(REMOVE) "$(GHPAGES)"/static/odoc/latest; \
$(LN_S) "$$version" "$(GHPAGES)"/static/odoc/latest) $(LN_S) "$$version" "$(GHPAGES)"/static/odoc/latest)
else else

@ -58,7 +58,7 @@ RUN eval $(opam env) && \
ENV PATH /infer-host/infer/bin:/infer/bin:$PATH ENV PATH /infer-host/infer/bin:/infer/bin:$PATH
# build in non-optimized mode by default to speed up build times # build in non-optimized mode by default to speed up build times
ENV BUILD_MODE=default ENV BUILD_MODE=dev
# prevent exiting by compulsively hitting Control-D # prevent exiting by compulsively hitting Control-D
ENV IGNOREEOF=9 ENV IGNOREEOF=9

@ -13,8 +13,7 @@ Format.sprintf
(library (library
(name InferIR) (name InferIR)
(public_name InferIR) (public_name InferIR)
(flags (%s -open Core -open InferStdlib -open IStd -open InferGenerated -open InferBase)) (flags (:standard -open Core -open InferStdlib -open IStd -open InferGenerated -open InferBase))
(ocamlopt_flags (%s))
(libraries %s) (libraries %s)
(preprocess (pps ppx_compare)) (preprocess (pps ppx_compare))
) )
@ -24,7 +23,5 @@ Format.sprintf
(mld_files index) (mld_files index)
) )
|} |}
(String.concat " " common_cflags)
(String.concat " " common_optflags)
(String.concat " " ("InferBase" :: common_libraries)) (String.concat " " ("InferBase" :: common_libraries))
|> Jbuild_plugin.V1.send |> Jbuild_plugin.V1.send

@ -8,10 +8,15 @@ include $(ROOT_DIR)/Makefile.config
#### Global declarations #### #### Global declarations ####
ETC_DIR = $(INFER_DIR)/etc # override this for faster builds (but slower infer)
BUILD_MODE ?= opt
BUILD_ROOT = _build
# paths to BUILD_DIR are relative because that's how dune likes it # paths to BUILD_DIR are relative because that's how dune likes it
# can be overriden to specify another build mode (eg opt) INFER_BUILD_DIR = $(BUILD_ROOT)/default
INFER_BUILD_DIR = _build/default
DUNE_BUILD = dune build --profile=$(BUILD_MODE) --build-dir=$(BUILD_ROOT)
ETC_DIR = $(INFER_DIR)/etc
#### Backend declarations #### #### Backend declarations ####
@ -103,28 +108,33 @@ endif
.PHONY: src_build_common .PHONY: src_build_common
src_build_common: $(SRC_BUILD_COMMON) src_build_common: $(SRC_BUILD_COMMON)
# single out infer.exe as the source of truth for make, knowing that in fact several targets are # Single out infer.exe as the source of truth for make, knowing that in fact several
# produced by the build # targets are produced by the build.
# The target is marked as .PHONY because if you build with one profile `make
# BUILD_MODE=dev` and then try with another profile `make BUILD_MODE=opt`, make won't
# trigger a rebuild since it has only partial view on the dependencies.
.PHONY: $(INFER_BUILD_DIR)/$(INFER_MAIN).exe
$(INFER_BUILD_DIR)/$(INFER_MAIN).exe: $(SRC_BUILD_COMMON) $(MAKEFILE_LIST) $(INFER_BUILD_DIR)/$(INFER_MAIN).exe: $(SRC_BUILD_COMMON) $(MAKEFILE_LIST)
$(QUIET)dune build $(INFER_CONFIG_TARGETS) $(QUIET)$(DUNE_BUILD) $(INFER_CONFIG_TARGETS)
# let make know that the target is up-to-date even if ocamlbuild cached it # let make know that the target is up-to-date even if ocamlbuild cached it
$(QUIET)touch $@ $(QUIET)touch $@
.PHONY: test .PHONY: test
test: BUILD_MODE = test
test: $(SRC_BUILD_COMMON) $(MAKEFILE_LIST) test: $(SRC_BUILD_COMMON) $(MAKEFILE_LIST)
# needed for dune to "install" the relevant dynamic libraries for the C stubs # needed for dune to "install" the relevant dynamic libraries for the C stubs
$(QUIET)cd c_stubs; dune build InferCStubs.install $(QUIET)cd c_stubs; $(DUNE_BUILD) InferCStubs.install
$(QUIET)dune build \ $(QUIET)$(DUNE_BUILD) \
$(patsubst $(INFER_BUILD_DIR)/%.exe,_build/test/%.bc,$(INFER_CONFIG_TARGETS)) \ $(patsubst $(INFER_BUILD_DIR)/%.exe,%.bc, $(INFER_CONFIG_TARGETS)) \
_build/test/scripts/checkCopyright.bc _build/test/$(INFERUNIT_MAIN).bc _build/test/infertop.bc scripts/checkCopyright.bc $(INFERUNIT_MAIN).bc infertop.bc
.PHONY: doc .PHONY: doc
doc: $(SRC_BUILD_COMMON) $(MAKEFILE_LIST) doc: $(SRC_BUILD_COMMON) $(MAKEFILE_LIST)
$(QUIET)dune build @$(INFER_BUILD_DIR)/doc $(QUIET)$(DUNE_BUILD) @doc
.PHONY: check .PHONY: check
check: src_build_common check: src_build_common
dune build @check $(DUNE_BUILD) @check
INFER_BIN_ALIASES = $(foreach alias,$(INFER_COMMANDS),$(BIN_DIR)/$(alias)) INFER_BIN_ALIASES = $(foreach alias,$(INFER_COMMANDS),$(BIN_DIR)/$(alias))
@ -152,10 +162,12 @@ infer: $(INFER_BIN).exe
$(INSTALL_PROGRAM) -C $(INFER_BIN).exe $(INFER_BIN) $(INSTALL_PROGRAM) -C $(INFER_BIN).exe $(INFER_BIN)
$(MAKE) $(INFER_BIN_ALIASES) $(MAKE) $(INFER_BIN_ALIASES)
.PHONY: $(INFER_BUILD_DIR)/$(INFER_MAIN).bc
$(INFER_BUILD_DIR)/$(INFER_MAIN).bc: $(SRC_BUILD_COMMON) $(MAKEFILE_LIST) $(INFER_BUILD_DIR)/$(INFER_MAIN).bc: $(SRC_BUILD_COMMON) $(MAKEFILE_LIST)
dune build $(INFER_CONFIG_TARGETS:.exe=.bc) $(DUNE_BUILD) $(INFER_CONFIG_TARGETS:.exe=.bc)
$(QUIET)touch $@ $(QUIET)touch $@
.PHONY: $(INFER_BIN).bc
$(INFER_BIN).bc: $(INFER_BUILD_DIR)/$(INFER_MAIN).bc $(INFER_BIN).bc: $(INFER_BUILD_DIR)/$(INFER_MAIN).bc
$(QUIET)$(MKDIR_P) $(BIN_DIR) $(QUIET)$(MKDIR_P) $(BIN_DIR)
ifeq ($(WINDOWS_BUILD),yes) ifeq ($(WINDOWS_BUILD),yes)
@ -168,7 +180,7 @@ ifeq ($(IS_FACEBOOK_TREE),yes)
$(INFER_CREATE_TRACEVIEW_LINKS_BIN) $(INFER_CREATE_TRACEVIEW_LINKS_BIN)
endif endif
# needed for dune to "install" the relevant dynamic libraries for the C stubs # needed for dune to "install" the relevant dynamic libraries for the C stubs
cd c_stubs; dune build InferCStubs.install cd c_stubs; $(DUNE_BUILD) InferCStubs.install
.PHONY: byte .PHONY: byte
byte: $(INFER_BIN).bc byte: $(INFER_BIN).bc
@ -200,10 +212,11 @@ mod_dep.pdf: mod_dep.dot
dsort: dsort:
$(QUIET)ocamldep.opt -sort $(inc_flags) $(ml_src_files) $(QUIET)ocamldep.opt -sort $(inc_flags) $(ml_src_files)
.PHONY: $(INFER_BUILD_DIR)/infertop.bc
$(INFER_BUILD_DIR)/infertop.bc: $(SRC_DIR)/infertop.ml $(SRC_BUILD_COMMON) $(MAKEFILE_LIST) $(INFER_BUILD_DIR)/infertop.bc: $(SRC_DIR)/infertop.ml $(SRC_BUILD_COMMON) $(MAKEFILE_LIST)
dune build $@ $(DUNE_BUILD) $@
# needed for dune to "install" the relevant dynamic libraries for the C stubs # needed for dune to "install" the relevant dynamic libraries for the C stubs
cd c_stubs; dune build InferCStubs.install cd c_stubs; $(DUNE_BUILD) InferCStubs.install
$(QUIET)touch $@ $(QUIET)touch $@
$(INFERTOP_BIN): $(INFER_BUILD_DIR)/infertop.bc $(INFERTOP_BIN): $(INFER_BUILD_DIR)/infertop.bc
@ -216,8 +229,9 @@ toplevel: $(INFERTOP_BIN)
.PHONY: checkCopyright .PHONY: checkCopyright
checkCopyright: $(CHECKCOPYRIGHT_BIN) checkCopyright: $(CHECKCOPYRIGHT_BIN)
.PHONY: $(CHECKCOPYRIGHT_BIN)
$(CHECKCOPYRIGHT_BIN): $(SRC_BUILD_COMMON) $(MAKEFILE_LIST) $(CHECKCOPYRIGHT_BIN): $(SRC_BUILD_COMMON) $(MAKEFILE_LIST)
dune build $(INFER_BUILD_DIR)/scripts/$(CHECKCOPYRIGHT_MAIN).exe $(DUNE_BUILD) $(INFER_BUILD_DIR)/scripts/$(CHECKCOPYRIGHT_MAIN).exe
$(INSTALL_PROGRAM) -C $(INFER_BUILD_DIR)/scripts/$(CHECKCOPYRIGHT_MAIN).exe $(CHECKCOPYRIGHT_BIN) $(INSTALL_PROGRAM) -C $(INFER_BUILD_DIR)/scripts/$(CHECKCOPYRIGHT_MAIN).exe $(CHECKCOPYRIGHT_BIN)
define gen_atdgen_rules define gen_atdgen_rules

@ -7,16 +7,13 @@
*) *)
(* NOTE: prepend dune.common to this file! *) (* NOTE: prepend dune.common to this file! *)
let cflags = common_cflags @ ["-w"; "-27-32-34-35-39"]
;; ;;
Format.sprintf Format.sprintf
{| {|
(library (library
(name InferGenerated) (name InferGenerated)
(public_name InferGenerated) (public_name InferGenerated)
(flags (%s)) (flags (:standard -w -27-32-34-35-39))
(ocamlopt_flags (%s))
(libraries atdgen core) (libraries atdgen core)
(preprocess (pps ppx_compare)) (preprocess (pps ppx_compare))
) )
@ -26,6 +23,4 @@ Format.sprintf
(mld_files index) (mld_files index)
) )
|} |}
(String.concat " " cflags)
(String.concat " " common_optflags)
|> Jbuild_plugin.V1.send |> Jbuild_plugin.V1.send

@ -13,18 +13,12 @@ Format.sprintf
(library (library
(name InferBase) (name InferBase)
(public_name InferBase) (public_name InferBase)
(flags (%s -open Core -open InferStdlib -open IStd -open InferGenerated)) (flags (:standard -open Core -open InferStdlib -open IStd -open InferGenerated))
(ocamlopt_flags (%s)) (libraries InferStdlib InferGenerated core)
(libraries %s) (preprocess (pps ppx_compare ppx_enumerate)))
(preprocess (pps ppx_compare ppx_enumerate))
)
(documentation (documentation
(package InferBase) (package InferBase)
(mld_files index) (mld_files index))
)
|} |}
(String.concat " " common_cflags)
(String.concat " " common_optflags)
(String.concat " " ("InferStdlib" :: "InferGenerated" :: common_libraries))
|> Jbuild_plugin.V1.send |> Jbuild_plugin.V1.send

@ -28,7 +28,7 @@
ROOT_DIR = ../../.. ROOT_DIR = ../../..
include $(ROOT_DIR)/Makefile.config include $(ROOT_DIR)/Makefile.config
INFER_BUILD_DIR = ../_build/test INFER_BUILD_DIR = ../_build/default
ALL_INFER_IN_ONE_FILE_ML = all_infer_in_one_file.ml ALL_INFER_IN_ONE_FILE_ML = all_infer_in_one_file.ml
ALL_ML_FILES = all_ml_files ALL_ML_FILES = all_ml_files
@ -168,7 +168,7 @@ detect_dead_code:
rm "$$tmp_file_copied" rm "$$tmp_file_copied"
$(MAKE) -j 1 detect_dead_src_file $(MAKE) -j 1 detect_dead_src_file
# build and get dead code warnings; clean in case of errors so as not to leave rubbish around # build and get dead code warnings; clean in case of errors so as not to leave rubbish around
if ! dune build $(INFER_BUILD_DIR)/deadcode/all_infer_in_one_file.bc; then \ if ! dune build --profile test $(INFER_BUILD_DIR)/deadcode/all_infer_in_one_file.bc; then \
$(MAKE) clean; \ $(MAKE) clean; \
exit 1; \ exit 1; \
fi fi

@ -13,14 +13,11 @@ Format.sprintf
(executable (executable
(name all_infer_in_one_file) (name all_infer_in_one_file)
(modes byte) (modes byte)
(flags (%s -w +60)) (flags (:standard -w +60))
(ocamlopt_flags (%s))
(libraries %s) (libraries %s)
(modules All_infer_in_one_file) (modules All_infer_in_one_file)
(preprocess (pps ppx_compare ppx_enumerate ppx_fields_conv ppx_hash ppx_sexp_conv ppx_variants_conv -no-check)) (preprocess (pps ppx_compare ppx_enumerate ppx_fields_conv ppx_hash ppx_sexp_conv ppx_variants_conv -no-check))
) )
|} |}
(String.concat " " common_cflags)
(String.concat " " common_optflags)
(String.concat " " ("InferCStubs" :: common_libraries)) (String.concat " " ("InferCStubs" :: common_libraries))
|> Jbuild_plugin.V1.send |> Jbuild_plugin.V1.send

@ -5,5 +5,3 @@
; LICENSE file in the root directory of this source tree. ; LICENSE file in the root directory of this source tree.
(context (opam (switch @OPAMSWITCH@) (name default) (merlin))) (context (opam (switch @OPAMSWITCH@) (name default) (merlin)))
(context (opam (switch @OPAMSWITCH@) (name opt)))
(context (opam (switch @OPAMSWITCH@) (name test)))

@ -7,61 +7,46 @@
*) *)
(* use strings so that it looks like OCaml even before substituting, e.g. to use ocamlformat *) (* use strings so that it looks like OCaml even before substituting, e.g. to use ocamlformat *)
type build_mode = Default | Opt | Test
let build_mode =
match Jbuild_plugin.V1.context with
| "test" ->
Test
| "default" ->
Default
| "opt" ->
Opt
| ctx ->
invalid_arg ("unknown context: " ^ ctx)
let is_yes = String.equal "yes" let is_yes = String.equal "yes"
let is_empty = String.equal ""
let clang = is_yes "@BUILD_C_ANALYZERS@" let clang = is_yes "@BUILD_C_ANALYZERS@"
let java = is_yes "@BUILD_JAVA_ANALYZERS@" let java = is_yes "@BUILD_JAVA_ANALYZERS@"
let facebook = is_yes "@IS_FACEBOOK_TREE@" let facebook = is_yes "@IS_FACEBOOK_TREE@"
let extra_cflags = if "@EXTRA_CFLAGS@" = "" then [] else ["@EXTRA_CFLAGS@"] let extra_cflags = if is_empty "@EXTRA_CFLAGS@" then [] else ["@EXTRA_CFLAGS@"]
(*
* A known issue: At the moment of writing warning 14 (illegal backslash
* escape in string) does not manifest as an error, presumably due to
* peculiarities in communication between preprocessor and compiler.
* Still leave it for visibility and in hope that the issue will be
* fixed one day.
*)
let fatal_warnings =
"+3+5+6+8+10+11+12+14+18+19+20+21+23+26+29+27+28+32+33+34+35+37+38+39+50+52+57+60"
let warnings = fatal_warnings ^ "-4-9-40-41-42-45-48"
let ocamlc_flags =
[ "-g"
; "-short-paths"
; "-safe-string"
; "-principal"
; "-strict-formats"
; "-strict-sequence"
; "-bin-annot" ]
let common_cflags = let lenient_flags = ocamlc_flags @ ["-w"; warnings] |> String.concat " "
(*
* A known issue: At the moment of writing warning 14 (illegal backslash
* escape in string) does not manifest as an error, presumably due to
* peculiarities in communication between preprocessor and compiler.
* Still leave it for visibility and in hope that the issue will be
* fixed one day.
*)
let fatal_warnings =
"+3+5+6+8+10+11+12+14+18+19+20+21+23+26+29+27+28+32+33+34+35+37+38+39+50+52+57+60"
in
let warnings = fatal_warnings ^ "-4-9-40-41-42-45-48" in
let common_flags =
[ "-g"
; "-short-paths"
; "-safe-string"
; "-principal"
; "-strict-formats"
; "-strict-sequence"
; "-bin-annot"
; "-w"
; warnings ]
in
match build_mode with
| Default | Opt ->
common_flags
| Test ->
"-warn-error" :: fatal_warnings :: common_flags
let strict_flags =
ocamlc_flags @ ["-w"; warnings; "-warn-error"; fatal_warnings] |> String.concat " "
let common_optflags = match build_mode with Opt -> ["-O3"] | Default | Test -> []
let common_libraries = let common_libraries =
(if java then ["javalib"; "sawja"] else []) (if java then ["javalib"; "sawja"] else [])

@ -35,90 +35,121 @@ let source_dirs =
let infer_binaries = ["infer"; "inferunit"] @ if facebook then ["InferCreateTraceViewLinks"] else [] let infer_binaries = ["infer"; "inferunit"] @ if facebook then ["InferCreateTraceViewLinks"] else []
let env_stanza =
Format.sprintf
{|
(env
(dev
(flags %s))
(opt
(flags %s)
(ocamlopt_flags (:standard -O3)))
(test
(flags %s)))
|}
lenient_flags lenient_flags strict_flags
let clang_lexer_stanzas =
if clang then ["(ocamllex types_lexer ctl_lexer)"; "(menhir (modules types_parser ctl_parser))"]
else []
let infer_cflags = let infer_cflags =
common_cflags [ "-open"
@ [ "-open" ; "Core"
; "Core" ; "-open"
; "-open" ; "InferStdlib"
; "InferStdlib" ; "-open"
; "-open" ; "IStd"
; "IStd" ; "-open"
; "-open" ; "InferGenerated"
; "InferGenerated" ; "-open"
; "-open" ; "InferIR"
; "InferIR" ; "-open"
; "-open" ; "InferBase"
; "InferBase" ; "-open"
; "-open" ; "InferCStubs" ]
; "InferCStubs" |> String.concat " "
; "-w"
; "+A-4@8-9-40-41-42-44-45-48-60-66" ]
(** The build stanzas to be passed to dune *) let main_lib_stanza =
let stanzas = Format.sprintf
( if clang then ["(ocamllex types_lexer ctl_lexer)"; "(menhir (modules types_parser ctl_parser))"] {|
else [] )
@ [ "(ocamllex ToplLexer)"
; "(menhir (flags --unused-token INDENT --explain) (modules ToplParser))"
; Format.sprintf
{|
(library (library
(name InferModules) (name InferModules)
(public_name infer) (public_name infer)
(flags (%s)) (flags (:standard %s))
(ocamlopt_flags (%s))
(libraries %s) (libraries %s)
(modules :standard \ %s infertop) (modules :standard \ %s infertop)
(preprocess (pps ppx_compare ppx_fields_conv ppx_hash ppx_sexp_conv ppx_variants_conv -no-check)) (preprocess (pps ppx_compare ppx_fields_conv ppx_hash ppx_sexp_conv ppx_variants_conv -no-check))
) )
|}
infer_cflags
(String.concat " " ("InferCStubs" :: "InferIR" :: common_libraries))
(String.concat " " infer_binaries)
let docs_stanza = {|
(documentation (documentation
(package infer) (package infer)
(mld_files index) (mld_files index)
) )
|} |}
(String.concat " " infer_cflags)
(String.concat " " common_optflags) let infer_exe_stanza =
(String.concat " " ("InferCStubs" :: "InferIR" :: common_libraries)) Format.sprintf
(String.concat " " infer_binaries) {|
; Format.sprintf
{|
(executables (executables
(names %s) (names %s)
(modes byte exe) (modes byte exe)
(flags (%s -open InferModules)) (flags (:standard %s -open InferModules))
(ocamlopt_flags (%s))
(libraries InferModules) (libraries InferModules)
(modules %s) (modules %s)
(preprocess (pps ppx_compare ppx_fields_conv ppx_hash ppx_sexp_conv ppx_variants_conv -no-check)) (preprocess (pps ppx_compare ppx_fields_conv ppx_hash ppx_sexp_conv ppx_variants_conv -no-check))
) )
|} |}
(String.concat " " infer_binaries) (String.concat " " infer_binaries)
(String.concat " " infer_cflags) infer_cflags
(String.concat " " common_optflags) (String.concat " " infer_binaries)
(String.concat " " infer_binaries)
; Format.sprintf
{| let infertop_stanza =
Format.sprintf
{|
(executable (executable
(name infertop) (name infertop)
(modes byte) (modes byte)
(flags (%s)) (flags (:standard %s))
(libraries utop InferModules) (libraries utop InferModules)
(modules Infertop) (modules Infertop)
(preprocess (pps ppx_compare ppx_fields_conv ppx_hash ppx_sexp_conv ppx_variants_conv -no-check)) (preprocess (pps ppx_compare ppx_fields_conv ppx_hash ppx_sexp_conv ppx_variants_conv -no-check))
(link_flags (-linkall -warn-error -31)) (link_flags (-linkall -warn-error -31))
) )
|} |}
(String.concat " " infer_cflags) ] infer_cflags
@ ( List.map
(fun source_dir ->
[ Printf.sprintf "(copy_files# %s/*.ml{,i,l})" source_dir let topl_stanzas =
; (* menhir doesn't support '# 1 "<source file>"' directives at the start of the file inserted by ["(ocamllex ToplLexer)"; "(menhir (flags --unused-token INDENT --explain) (modules ToplParser))"]
copy# actions *)
Printf.sprintf "(copy_files %s/*.mly)" source_dir ] )
source_dirs let flatten_sources_stanzas =
|> List.concat ) List.map
(fun source_dir ->
[ Printf.sprintf "(copy_files# %s/*.ml{,i,l})" source_dir
; (* menhir doesn't support '# 1 "<source file>"' directives at the start of the file inserted by
copy# actions *)
Printf.sprintf "(copy_files %s/*.mly)" source_dir ] )
source_dirs
|> List.concat
(** The build stanzas to be passed to dune *)
let stanzas =
env_stanza :: main_lib_stanza :: infer_exe_stanza :: infertop_stanza :: docs_stanza
:: clang_lexer_stanzas
@ topl_stanzas @ flatten_sources_stanzas
;; ;;

@ -13,8 +13,7 @@ Format.sprintf
(library (library
(name InferStdlib) (name InferStdlib)
(public_name InferStdlib) (public_name InferStdlib)
(flags (%s -open Core)) (flags (:standard -open Core))
(ocamlopt_flags (%s))
(libraries %s) (libraries %s)
(preprocess (pps ppx_compare)) (preprocess (pps ppx_compare))
) )
@ -24,7 +23,5 @@ Format.sprintf
(mld_files index) (mld_files index)
) )
|} |}
(String.concat " " common_cflags)
(String.concat " " common_optflags)
(String.concat " " common_libraries) (String.concat " " common_libraries)
|> Jbuild_plugin.V1.send |> Jbuild_plugin.V1.send

@ -12,10 +12,9 @@ Format.sprintf
(executable (executable
(name checkCopyright) (name checkCopyright)
(modes byte exe) (modes byte exe)
(flags (%s)) (flags (:standard))
(libraries core str) (libraries core str)
(preprocess (pps ppx_compare)) (preprocess (pps ppx_compare))
) )
|} |}
(String.concat " " common_cflags)
|> Jbuild_plugin.V1.send |> Jbuild_plugin.V1.send

@ -8,10 +8,10 @@ ROOT_DIR = $(TESTS_DIR)/../..
include $(TESTS_DIR)/base.make include $(TESTS_DIR)/base.make
toplevel.exp.test: $(BUILD_DIR)/test/infertop.bc $(SCRIPT_DIR)/infer_repl \ toplevel.exp.test: $(BUILD_DIR)/default/infertop.bc $(SCRIPT_DIR)/infer_repl \
$(SCRIPT_DIR)/toplevel_init $(INFER_DIR)/tests/repl/infer_batch_script.mltop $(SCRIPT_DIR)/toplevel_init $(INFER_DIR)/tests/repl/infer_batch_script.mltop
$(QUIET)$(call silent_on_success,Testing infer OCaml REPL,\ $(QUIET)$(call silent_on_success,Testing infer OCaml REPL,\
BUILD_DIR=$(BUILD_DIR)/test \ BUILD_DIR=$(BUILD_DIR)/default \
$(SCRIPT_DIR)/infer_repl $(INFER_DIR)/tests/repl/infer_batch_script.mltop | \ $(SCRIPT_DIR)/infer_repl $(INFER_DIR)/tests/repl/infer_batch_script.mltop | \
sed -e 's#^The files .*/extLib.cma$$#The files [...]/extLib.cma#' \ sed -e 's#^The files .*/extLib.cma$$#The files [...]/extLib.cma#' \
-e 's#^and .*/infertop.bc$$#and [...]/infertop.bc#' \ -e 's#^and .*/infertop.bc$$#and [...]/infertop.bc#' \

@ -17,8 +17,8 @@ shift
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
SRC_DIR="$SCRIPT_DIR"/../infer/src SRC_DIR="$SCRIPT_DIR"/../infer/src
BUILD_MODE=${BUILD_MODE:-default} BUILD_MODE=${BUILD_MODE:-dev}
DUNE_INSTALL_DIR=${INSTALL_DIR:-"$SRC_DIR/_build/install/$BUILD_MODE"} DUNE_INSTALL_DIR=${INSTALL_DIR:-"$SRC_DIR/_build/install/default"}
export CAML_LD_LIBRARY_PATH="$DUNE_INSTALL_DIR"/lib/stublibs:"$CAML_LD_LIBRARY_PATH" export CAML_LD_LIBRARY_PATH="$DUNE_INSTALL_DIR"/lib/stublibs:"$CAML_LD_LIBRARY_PATH"

Loading…
Cancel
Save