From fcce3c0659e59ad0613b67017b76e24594d44976 Mon Sep 17 00:00:00 2001 From: Artem Pianykh Date: Wed, 11 Mar 2020 05:56:58 -0700 Subject: [PATCH] [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 --- CONTRIBUTING.md | 6 +- Makefile | 44 +++---- docker/master-java/Dockerfile | 2 +- infer/src/IR/dune.in | 5 +- infer/src/Makefile | 48 ++++--- infer/src/atd/dune.in | 7 +- infer/src/base/dune.in | 14 +-- infer/src/deadcode/Makefile | 4 +- infer/src/deadcode/dune.in | 5 +- infer/src/dune-workspace.in | 2 - infer/src/dune.common.in | 73 +++++------ infer/src/dune.in | 133 ++++++++++++-------- infer/src/istd/dune.in | 5 +- infer/src/scripts/dune.in | 3 +- infer/tests/build_systems/infertop/Makefile | 4 +- scripts/dune_exec_shim.sh | 4 +- 16 files changed, 183 insertions(+), 176 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 96cef4a90..7b58f691b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -20,12 +20,12 @@ make devsetup ### 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). - 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: - `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. - 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 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. ### Debugging OCaml Code diff --git a/Makefile b/Makefile index b6f13f886..cfc5f7708 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ ORIG_SHELL_BUILD_MODE = $(BUILD_MODE) # override this for faster builds (but slower infer) BUILD_MODE ?= opt -MAKE_SOURCE = $(MAKE) -C $(SRC_DIR) INFER_BUILD_DIR=_build/$(BUILD_MODE) +MAKE_SOURCE = $(MAKE) -C $(SRC_DIR) ifneq ($(UTOP),no) BUILD_SYSTEMS_TESTS += infertop @@ -293,9 +293,9 @@ toplevel: $(QUIET)echo "You can now use the infer REPL:" $(QUIET)echo " \"$(ABSOLUTE_ROOT_DIR)/scripts/infer_repl\"" -toplevel_test: test_build - $(QUIET)$(call silent_on_success,Building Infer REPL (test mode),\ - $(MAKE_SOURCE) BUILD_MODE=test toplevel) +toplevel_test: + $(QUIET)$(call silent_on_success,Building Infer REPL,\ + $(MAKE_SOURCE) toplevel) ifeq ($(IS_FACEBOOK_TREE),yes) byte src_build_common src_build test_build: fb-setup @@ -331,16 +331,14 @@ $(INFER_GROFF_MANUALS_GZIPPED): %.gz: % infer_models: src_build ifeq ($(BUILD_JAVA_ANALYZERS),yes) - $(MAKE) -C $(ANNOTATIONS_DIR) + $(QUIET)$(call silent_on_success,Building infer annotations,\ + $(MAKE) -C $(ANNOTATIONS_DIR)) endif - $(MAKE) -C $(MODELS_DIR) all + $(QUIET)$(call silent_on_success,Building infer models,\ + $(MAKE) -C $(MODELS_DIR) all) .PHONY: infer byte_infer -infer byte_infer: - $(QUIET)$(call silent_on_success,Building Infer models,\ - $(MAKE) infer_models) - $(QUIET)$(call silent_on_success,Building Infer manuals,\ - $(MAKE) $(INFER_MANUALS)) +infer byte_infer: infer_models infer: src_build byte_infer: byte @@ -442,8 +440,7 @@ ocaml_unit_test: test_build $(QUIET)$(REMOVE_DIR) infer-out-unit-tests $(QUIET)$(call silent_on_success,Running OCaml unit tests,\ INFER_ARGS=--results-dir^infer-out-unit-tests \ - BUILD_DIR=$(BUILD_DIR)/test \ - $(SCRIPT_DIR)/dune_exec_shim.sh $(BUILD_DIR)/test/inferunit.bc) + $(SCRIPT_DIR)/dune_exec_shim.sh $(BUILD_DIR)/default/inferunit.bc) define silence_make $(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) .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}),) -test_build: src_build -checkCopyright: src_build test_build +ifneq ($(filter endtoend_test,${MAKECMDGOALS}),) +checkCopyright: src_build +toplevel_test: checkCopyright endif .PHONY: test @@ -841,14 +841,14 @@ devsetup: Makefile.autoconf fi; \ if [ -z "$(ORIG_SHELL_BUILD_MODE)" ]; then \ 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: 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: when you really do want to enable flambda.$(TERM_RESET)' >&2; \ echo >&2; \ - printf "$(TERM_INFO) export BUILD_MODE=default$(TERM_RESET)\n" >&2; \ - printf "$(TERM_INFO) echo 'export BUILD_MODE=default' >> \"$$shell_config_file\"$(TERM_RESET)\n" >&2; \ + printf "$(TERM_INFO) export BUILD_MODE=dev$(TERM_RESET)\n" >&2; \ + printf "$(TERM_INFO) echo 'export BUILD_MODE=dev' >> \"$$shell_config_file\"$(TERM_RESET)\n" >&2; \ fi $(QUIET)PATH=$(ORIG_SHELL_PATH); if [ "$$(ocamlc -where 2>/dev/null)" != "$$($(OCAMLC) -where)" ]; then \ echo >&2; \ @@ -867,7 +867,7 @@ doc: src_build_common # do not call the browser if we are publishing the docs ifeq ($(filter doc-publish,${MAKECMDGOALS}),) $(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 $(QUIET)echo " odig odoc # takes a while, run it only when the dependencies change" @@ -895,7 +895,7 @@ endif ifeq ($(IS_FACEBOOK_TREE),no) $(QUIET)$(call silent_on_success,Copying OCaml modules documentation,\ 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; \ $(LN_S) "$$version" "$(GHPAGES)"/static/odoc/latest) else diff --git a/docker/master-java/Dockerfile b/docker/master-java/Dockerfile index 9ad9620d0..5584aaa71 100644 --- a/docker/master-java/Dockerfile +++ b/docker/master-java/Dockerfile @@ -58,7 +58,7 @@ RUN eval $(opam env) && \ ENV PATH /infer-host/infer/bin:/infer/bin:$PATH # 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 ENV IGNOREEOF=9 diff --git a/infer/src/IR/dune.in b/infer/src/IR/dune.in index be354cc9f..12123142c 100644 --- a/infer/src/IR/dune.in +++ b/infer/src/IR/dune.in @@ -13,8 +13,7 @@ Format.sprintf (library (name InferIR) (public_name InferIR) - (flags (%s -open Core -open InferStdlib -open IStd -open InferGenerated -open InferBase)) - (ocamlopt_flags (%s)) + (flags (:standard -open Core -open InferStdlib -open IStd -open InferGenerated -open InferBase)) (libraries %s) (preprocess (pps ppx_compare)) ) @@ -24,7 +23,5 @@ Format.sprintf (mld_files index) ) |} - (String.concat " " common_cflags) - (String.concat " " common_optflags) (String.concat " " ("InferBase" :: common_libraries)) |> Jbuild_plugin.V1.send diff --git a/infer/src/Makefile b/infer/src/Makefile index 78e391da3..555d27497 100644 --- a/infer/src/Makefile +++ b/infer/src/Makefile @@ -8,10 +8,15 @@ include $(ROOT_DIR)/Makefile.config #### 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 -# can be overriden to specify another build mode (eg opt) -INFER_BUILD_DIR = _build/default +INFER_BUILD_DIR = $(BUILD_ROOT)/default + +DUNE_BUILD = dune build --profile=$(BUILD_MODE) --build-dir=$(BUILD_ROOT) + +ETC_DIR = $(INFER_DIR)/etc #### Backend declarations #### @@ -103,28 +108,33 @@ endif .PHONY: 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 -# produced by the build +# Single out infer.exe as the source of truth for make, knowing that in fact several +# 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) - $(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 $(QUIET)touch $@ .PHONY: test +test: BUILD_MODE = test test: $(SRC_BUILD_COMMON) $(MAKEFILE_LIST) # needed for dune to "install" the relevant dynamic libraries for the C stubs - $(QUIET)cd c_stubs; dune build InferCStubs.install - $(QUIET)dune build \ - $(patsubst $(INFER_BUILD_DIR)/%.exe,_build/test/%.bc,$(INFER_CONFIG_TARGETS)) \ - _build/test/scripts/checkCopyright.bc _build/test/$(INFERUNIT_MAIN).bc _build/test/infertop.bc + $(QUIET)cd c_stubs; $(DUNE_BUILD) InferCStubs.install + $(QUIET)$(DUNE_BUILD) \ + $(patsubst $(INFER_BUILD_DIR)/%.exe,%.bc, $(INFER_CONFIG_TARGETS)) \ + scripts/checkCopyright.bc $(INFERUNIT_MAIN).bc infertop.bc .PHONY: doc doc: $(SRC_BUILD_COMMON) $(MAKEFILE_LIST) - $(QUIET)dune build @$(INFER_BUILD_DIR)/doc + $(QUIET)$(DUNE_BUILD) @doc .PHONY: check check: src_build_common - dune build @check + $(DUNE_BUILD) @check 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) $(MAKE) $(INFER_BIN_ALIASES) +.PHONY: $(INFER_BUILD_DIR)/$(INFER_MAIN).bc $(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 $@ +.PHONY: $(INFER_BIN).bc $(INFER_BIN).bc: $(INFER_BUILD_DIR)/$(INFER_MAIN).bc $(QUIET)$(MKDIR_P) $(BIN_DIR) ifeq ($(WINDOWS_BUILD),yes) @@ -168,7 +180,7 @@ ifeq ($(IS_FACEBOOK_TREE),yes) $(INFER_CREATE_TRACEVIEW_LINKS_BIN) endif # 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 byte: $(INFER_BIN).bc @@ -200,10 +212,11 @@ mod_dep.pdf: mod_dep.dot dsort: $(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) - dune build $@ + $(DUNE_BUILD) $@ # 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 $@ $(INFERTOP_BIN): $(INFER_BUILD_DIR)/infertop.bc @@ -216,8 +229,9 @@ toplevel: $(INFERTOP_BIN) .PHONY: checkCopyright checkCopyright: $(CHECKCOPYRIGHT_BIN) +.PHONY: $(CHECKCOPYRIGHT_BIN) $(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) define gen_atdgen_rules diff --git a/infer/src/atd/dune.in b/infer/src/atd/dune.in index fc70885ff..e33b7b496 100644 --- a/infer/src/atd/dune.in +++ b/infer/src/atd/dune.in @@ -7,16 +7,13 @@ *) (* NOTE: prepend dune.common to this file! *) -let cflags = common_cflags @ ["-w"; "-27-32-34-35-39"] - ;; Format.sprintf {| (library (name InferGenerated) (public_name InferGenerated) - (flags (%s)) - (ocamlopt_flags (%s)) + (flags (:standard -w -27-32-34-35-39)) (libraries atdgen core) (preprocess (pps ppx_compare)) ) @@ -26,6 +23,4 @@ Format.sprintf (mld_files index) ) |} - (String.concat " " cflags) - (String.concat " " common_optflags) |> Jbuild_plugin.V1.send diff --git a/infer/src/base/dune.in b/infer/src/base/dune.in index 390cbc082..d92c3f8cd 100644 --- a/infer/src/base/dune.in +++ b/infer/src/base/dune.in @@ -13,18 +13,12 @@ Format.sprintf (library (name InferBase) (public_name InferBase) - (flags (%s -open Core -open InferStdlib -open IStd -open InferGenerated)) - (ocamlopt_flags (%s)) - (libraries %s) - (preprocess (pps ppx_compare ppx_enumerate)) -) + (flags (:standard -open Core -open InferStdlib -open IStd -open InferGenerated)) + (libraries InferStdlib InferGenerated core) + (preprocess (pps ppx_compare ppx_enumerate))) (documentation (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 diff --git a/infer/src/deadcode/Makefile b/infer/src/deadcode/Makefile index ecb03d89a..2e6d1b23f 100644 --- a/infer/src/deadcode/Makefile +++ b/infer/src/deadcode/Makefile @@ -28,7 +28,7 @@ ROOT_DIR = ../../.. 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_ML_FILES = all_ml_files @@ -168,7 +168,7 @@ detect_dead_code: rm "$$tmp_file_copied" $(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 - 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; \ exit 1; \ fi diff --git a/infer/src/deadcode/dune.in b/infer/src/deadcode/dune.in index 7d8a407a2..21a665010 100644 --- a/infer/src/deadcode/dune.in +++ b/infer/src/deadcode/dune.in @@ -13,14 +13,11 @@ Format.sprintf (executable (name all_infer_in_one_file) (modes byte) - (flags (%s -w +60)) - (ocamlopt_flags (%s)) + (flags (:standard -w +60)) (libraries %s) (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)) ) |} - (String.concat " " common_cflags) - (String.concat " " common_optflags) (String.concat " " ("InferCStubs" :: common_libraries)) |> Jbuild_plugin.V1.send diff --git a/infer/src/dune-workspace.in b/infer/src/dune-workspace.in index 327d6a99b..9f6606f5b 100644 --- a/infer/src/dune-workspace.in +++ b/infer/src/dune-workspace.in @@ -5,5 +5,3 @@ ; LICENSE file in the root directory of this source tree. (context (opam (switch @OPAMSWITCH@) (name default) (merlin))) -(context (opam (switch @OPAMSWITCH@) (name opt))) -(context (opam (switch @OPAMSWITCH@) (name test))) diff --git a/infer/src/dune.common.in b/infer/src/dune.common.in index 9e64e189c..2e87e30e1 100644 --- a/infer/src/dune.common.in +++ b/infer/src/dune.common.in @@ -7,61 +7,46 @@ *) (* 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_empty = String.equal "" + let clang = is_yes "@BUILD_C_ANALYZERS@" let java = is_yes "@BUILD_JAVA_ANALYZERS@" 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 = - (* - * 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 lenient_flags = ocamlc_flags @ ["-w"; warnings] |> String.concat " " +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 = (if java then ["javalib"; "sawja"] else []) diff --git a/infer/src/dune.in b/infer/src/dune.in index 9b09cd1fe..b10ead81c 100644 --- a/infer/src/dune.in +++ b/infer/src/dune.in @@ -35,90 +35,121 @@ let source_dirs = 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 = - common_cflags - @ [ "-open" - ; "Core" - ; "-open" - ; "InferStdlib" - ; "-open" - ; "IStd" - ; "-open" - ; "InferGenerated" - ; "-open" - ; "InferIR" - ; "-open" - ; "InferBase" - ; "-open" - ; "InferCStubs" - ; "-w" - ; "+A-4@8-9-40-41-42-44-45-48-60-66" ] + [ "-open" + ; "Core" + ; "-open" + ; "InferStdlib" + ; "-open" + ; "IStd" + ; "-open" + ; "InferGenerated" + ; "-open" + ; "InferIR" + ; "-open" + ; "InferBase" + ; "-open" + ; "InferCStubs" ] + |> String.concat " " -(** The build stanzas to be passed to dune *) -let stanzas = - ( 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 - {| +let main_lib_stanza = + Format.sprintf + {| (library (name InferModules) (public_name infer) - (flags (%s)) - (ocamlopt_flags (%s)) + (flags (:standard %s)) (libraries %s) (modules :standard \ %s infertop) (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 (package infer) (mld_files index) ) |} - (String.concat " " infer_cflags) - (String.concat " " common_optflags) - (String.concat " " ("InferCStubs" :: "InferIR" :: common_libraries)) - (String.concat " " infer_binaries) - ; Format.sprintf - {| + +let infer_exe_stanza = + Format.sprintf + {| (executables (names %s) (modes byte exe) - (flags (%s -open InferModules)) - (ocamlopt_flags (%s)) + (flags (:standard %s -open InferModules)) (libraries InferModules) (modules %s) (preprocess (pps ppx_compare ppx_fields_conv ppx_hash ppx_sexp_conv ppx_variants_conv -no-check)) ) |} - (String.concat " " infer_binaries) - (String.concat " " infer_cflags) - (String.concat " " common_optflags) - (String.concat " " infer_binaries) - ; Format.sprintf - {| + (String.concat " " infer_binaries) + infer_cflags + (String.concat " " infer_binaries) + + +let infertop_stanza = + Format.sprintf + {| (executable (name infertop) (modes byte) - (flags (%s)) + (flags (:standard %s)) (libraries utop InferModules) (modules Infertop) (preprocess (pps ppx_compare ppx_fields_conv ppx_hash ppx_sexp_conv ppx_variants_conv -no-check)) (link_flags (-linkall -warn-error -31)) ) |} - (String.concat " " infer_cflags) ] - @ ( List.map - (fun source_dir -> - [ Printf.sprintf "(copy_files# %s/*.ml{,i,l})" source_dir - ; (* menhir doesn't support '# 1 ""' directives at the start of the file inserted by - copy# actions *) - Printf.sprintf "(copy_files %s/*.mly)" source_dir ] ) - source_dirs - |> List.concat ) + infer_cflags + + +let topl_stanzas = + ["(ocamllex ToplLexer)"; "(menhir (flags --unused-token INDENT --explain) (modules ToplParser))"] + + +let flatten_sources_stanzas = + List.map + (fun source_dir -> + [ Printf.sprintf "(copy_files# %s/*.ml{,i,l})" source_dir + ; (* menhir doesn't support '# 1 ""' 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 ;; diff --git a/infer/src/istd/dune.in b/infer/src/istd/dune.in index be3c96f03..b6b174839 100644 --- a/infer/src/istd/dune.in +++ b/infer/src/istd/dune.in @@ -13,8 +13,7 @@ Format.sprintf (library (name InferStdlib) (public_name InferStdlib) - (flags (%s -open Core)) - (ocamlopt_flags (%s)) + (flags (:standard -open Core)) (libraries %s) (preprocess (pps ppx_compare)) ) @@ -24,7 +23,5 @@ Format.sprintf (mld_files index) ) |} - (String.concat " " common_cflags) - (String.concat " " common_optflags) (String.concat " " common_libraries) |> Jbuild_plugin.V1.send diff --git a/infer/src/scripts/dune.in b/infer/src/scripts/dune.in index df528ecb1..caef1ddc1 100644 --- a/infer/src/scripts/dune.in +++ b/infer/src/scripts/dune.in @@ -12,10 +12,9 @@ Format.sprintf (executable (name checkCopyright) (modes byte exe) - (flags (%s)) + (flags (:standard)) (libraries core str) (preprocess (pps ppx_compare)) ) |} - (String.concat " " common_cflags) |> Jbuild_plugin.V1.send diff --git a/infer/tests/build_systems/infertop/Makefile b/infer/tests/build_systems/infertop/Makefile index a49877ead..c4b53bfea 100644 --- a/infer/tests/build_systems/infertop/Makefile +++ b/infer/tests/build_systems/infertop/Makefile @@ -8,10 +8,10 @@ ROOT_DIR = $(TESTS_DIR)/../.. 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 $(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 | \ sed -e 's#^The files .*/extLib.cma$$#The files [...]/extLib.cma#' \ -e 's#^and .*/infertop.bc$$#and [...]/infertop.bc#' \ diff --git a/scripts/dune_exec_shim.sh b/scripts/dune_exec_shim.sh index de2c804d7..d1b14e94e 100755 --- a/scripts/dune_exec_shim.sh +++ b/scripts/dune_exec_shim.sh @@ -17,8 +17,8 @@ shift SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" SRC_DIR="$SCRIPT_DIR"/../infer/src -BUILD_MODE=${BUILD_MODE:-default} -DUNE_INSTALL_DIR=${INSTALL_DIR:-"$SRC_DIR/_build/install/$BUILD_MODE"} +BUILD_MODE=${BUILD_MODE:-dev} +DUNE_INSTALL_DIR=${INSTALL_DIR:-"$SRC_DIR/_build/install/default"} export CAML_LD_LIBRARY_PATH="$DUNE_INSTALL_DIR"/lib/stublibs:"$CAML_LD_LIBRARY_PATH"