Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Makefile rework and sharness test coverage #3504

Merged
merged 17 commits into from
Feb 12, 2017
Merged

Conversation

Kubuxu
Copy link
Member

@Kubuxu Kubuxu commented Dec 14, 2016

This PR introduces non-recursive Makefile infrastructure that replaces current Makefile infrastructure.
It also generally cleanups the Makefiles, separates them into nicer sub-modules and centralizes common operations into single definitions.

Why non-recursive Makefile?

It allows to depend on any target that is defined in the makefile, this means that for example gx install is called once when make build test_expensive_sharness is called instead of 4 or 5 times.

It also makes the dependencies much cleaner and allows for reuse of modules. For example sharness coverage collection uses sharness target with amended PATH, previously it might have been possible but not without wiring the coverage collection into sharness Makefile runner code.

Isn't non-recursive Makefile much more complex?

Yes, it is a bit more complex but not much more. There are few rules that have to be followed and few complexities added but IMHO it is worth it.

How to NR-make:

  1. If make is to generate some file via a target, it MUST be defined in Rules.mk file in the directory of the target.
  2. Rules.mk file MUST have include mk/header.mk statement as the first line and include mk/footer.mk statement as the last line (apart from project root Rules.mk).
  3. It then MUST be included by the closest Rules.mk file up the directory tree.
  4. Inside a Rules.mk special variable accessed as $(d) is defined. Its value is current directory, use it so if the Rules.mk file is moved in the tree it still works without a problem. Caution: this variable is not available in the recipe part and MUST NOT be used there. Use name of the target or prerequisite to extract it if you need it.
  5. Make has only one global scope, this means that name conflicts are a thing. Names SHOULD follow VAR_NAME_$(d) convention. There are exceptions from this rule in form of well defined global variables. Examples: General lists TGT_BIN, CLEAN; General targets: TEST, COVERAGE; General variables: GOFLAGS, DEPS_GO.
  6. Any rules, definitions or variables that fit some family SHOULD be defined in mk/$family.mk file and included from project root Rules.mk

(Based on https://evbergen.home.xs4all.nl/nonrecursive-make.html)


Resolves: #3488

@Kubuxu Kubuxu added the status/in-progress In progress label Dec 14, 2016
@Kubuxu Kubuxu changed the title Makefile rework Makefile rework and sharness test coverage Dec 15, 2016
@Kubuxu Kubuxu force-pushed the feat/makefile/refactor branch 3 times, most recently from b051e28 to bb2575f Compare December 15, 2016 22:30
@Kubuxu
Copy link
Member Author

Kubuxu commented Dec 16, 2016

It finally works again. Teamcity OSX and js-ipfs-api test failures are unrelated.

67 commits bye-bye.

@Kubuxu
Copy link
Member Author

Kubuxu commented Dec 16, 2016

The sharness test with coverage is about 4 to 6 min + 2min for coverage report merge procedure.
The unit test with coverage takes about 8 to 10 min.

@Kubuxu
Copy link
Member Author

Kubuxu commented Dec 16, 2016

@lgierth @whyrusleeping this should be ready for CR

@Kubuxu Kubuxu added the need/analysis Needs further analysis before proceeding label Dec 17, 2016
@Kubuxu Kubuxu requested review from a user and whyrusleeping December 17, 2016 00:27
@Kubuxu Kubuxu mentioned this pull request Dec 17, 2016
13 tasks
@Kubuxu Kubuxu added need/review Needs a review and removed need/analysis Needs further analysis before proceeding labels Dec 18, 2016
@Kubuxu Kubuxu self-assigned this Dec 19, 2016
@Kubuxu
Copy link
Member Author

Kubuxu commented Dec 19, 2016

I have figured out smart way to do cross package coverage. The cross package unit test coverage increased the test time only by 10% over normal coverage unit tests.

@kevina
Copy link
Contributor

kevina commented Dec 19, 2016

I have some experience with Makefiles, I am also going to have a look.

# DEPS_OO_$(d) += pin/internal/pb/header.pb.go unixfs/pb/unixfs.pb.go

# uses second expansion to collect all $(DEPS_GO)
$(IPFS_BIN_$(d)): $(d) $$(DEPS_GO) ALWAYS #| $(DEPS_OO_$(d))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I missed the ldflags for the current hash.

@kevina kevina self-requested a review December 19, 2016 20:20
@kevina
Copy link
Contributor

kevina commented Dec 19, 2016

Also, this looks like it is going to disrupt my workflow so I want a chance to try it. Added myself as a reviewer. Should be able to look at it this week.

@kevina
Copy link
Contributor

kevina commented Dec 19, 2016

The makefile is a bit slow. For example:

$ /usr/bin/time make
...
0.92user 0.16system 0:00.96elapsed 114%CPU (0avgtext+0avgdata 18244maxresident)k
8inputs+64outputs (0major+23775minor)pagefaults 0swaps

That is around a second to do nothing.

@kevina
Copy link
Contributor

kevina commented Dec 19, 2016

@Kubuxu would it be okay if I add some dummy Makefiles in some key sub-directories that just call the top level Makefile? For example I often do:

make -j4 > log

in the shareness directory. I also sometimes do

make deps

within the shareness directory and then run a failing test manually. Now I have to type something a lot longer to get the same effect.

Copy link
Contributor

@kevina kevina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I can tell it looks good. I left two general comments but neither of them are critical.

Copy link
Member

@whyrusleeping whyrusleeping left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR conflates a lot of real changes with refactor. I would really appreciate breaking this apart into isolated changes as much as we can.

bin/Rules.mk Outdated

dist_root_$(d)=/ipfs/QmNZL8wNsvAGdVYr8uGeUE9aGfHjFpHegAWywQFEdSaJbp

$(d)/gx: $(d)/gx-v0.9.0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is d?

Copy link
Member Author

@Kubuxu Kubuxu Dec 20, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See point number 4 in the PR comment.

@@ -0,0 +1,9 @@
#!/bin/sh
(for p ; do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is going on here? where is p coming from? i'm so confused. what is tac?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This script is not used right now, committed as I thought I would use it, tac is cat that reverses lines, for p; is equivalent to for p in "@";

circle.yml Outdated
@@ -35,6 +35,6 @@ dependencies:

test:
override:
- case $CIRCLE_NODE_INDEX in 0) make coverage ;; 1) make test_sharness_expensive ;; esac:
- case $CIRCLE_NODE_INDEX in 0) make -j 1 coverage/unit_tests.coverprofile && bash <(curl -s https://codecov.io/bash) -cF unittests -X search -f coverage/unit_tests.coverprofile;; 1) make -j 1 coverage/sharness_tests.coverprofile && bash <(curl -s https://codecov.io/bash) -cF sharness -X search -f coverage/sharness_tests.coverprofile;; esac:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this really need to be a one-liner? Its very... uh... Kubuxuy :P

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can make it separate script, AFAIK yaml doesn't support multiline keys.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, makes sense. Having it be a separate script (with comments explaining its existence) might help readability a bit

$(COVER_BIN_$(d)): $(d) $$(DEPS_GO) ALWAYS
$(eval TMP_PKGS := $(shell go list -f '{{range .Deps}}{{.}} {{end}}' $(go-flags-with-tags) ./cmd/ipfs | sed 's/ /\n/g' | grep ipfs/go-ipfs | grep -v ipfs/go-ipfs/Godeps) $(call go-pkg-name,$<))
$(eval TMP_LIST := $(call join-with,$(comma),$(TMP_PKGS)))
@echo go test $@ -c -covermode atomic -coverpkg ... $(go-flags-with-tags) ./$(@D) # for info
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is @D ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is short form of $(dir $@)

os.Args = append([]string{os.Args[0]}, args...)
ret := mainRet()

p := os.Getenv("IPFS_COVER_RET_FILE")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is this used for?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't return value from test binary, it has to exit naturally, so I save the to be return value to a file and return it from wrapper program, coverage/main/main.go

@@ -0,0 +1,8 @@
include mk/header.mk
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this include relative to the root dir? That feels really weird...

Copy link
Member Author

@Kubuxu Kubuxu Dec 20, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the working dir is constant and it is the root dir, the current working dir is under $(d).

pin/pin.go Outdated
os.Exit(1)
msg := "failed to decode empty key constant"
log.Error(msg)
panic(msg)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whats the reason for this change? I'd prefer not the have the user see an ugly panic stack trace.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't want to exit over there as it would change the coverage, but as it shouldn't happen here I will switch back to Exit.

@Kubuxu
Copy link
Member Author

Kubuxu commented Dec 20, 2016

@kevina 3d84db9 should resolve the running make in sharness dir and 6b38da2 cuts down the flat time by half by not running coverage Rules.mk file unless coverage category or clean targets are used.

@whyrusleeping
Copy link
Member

@Kubuxu Is this ready? It seems to be failing on circleCI

This commit introduces non-recursive Makefile infrastructure that replaces current Makefile infrastructure.
It also generally cleanups the Makefiles, separates them into nicer sub-modules and centralizes common operations into single definitions.

It allows to depend on any target that is defined in the makefile, this means that for example `gx install` is called once when `make build test_expensive_sharness` is called instead of 4 or 5 times.

It also makes the dependencies much cleaner and allows for reuse of modules. For example sharness coverage collection (WIP) uses sharness target with amended PATH, previously it might have been possible but not without wiring in the coverage collection into sharness make runner code.

Yes, it is more complex but not much more. There are few rules that have to be followed and few complexities added but IMHO it is worth it.

How to NR-make:
1. If make is to generate some file via a target, it MUST be defined in Rules.mk file in the directory of the target.
2. `Rules.mk` file MUST have `include mk/header.mk` statement as the first line and `include mk/footer.mk` statement as the last line (apart from project root `Rules.mk`).
3. It then MUST be included by the closest `Rules.mk` file up the directory tree.
4. Inside a `Rules.mk` special variable accessed as `$(d)` is defined. Its value is current directory, use it so if the `Rules.mk` file is moved in the tree it still works without a problem. Caution: this variable is not available in the recipe part and MUST NOT be used. Use name of the target or prerequisite to extract it if you need it.
5. Make has only one global scope, this means that name conflicts are a thing. Names SHOULD  follow `VAR_NAME_$(d)` convention. There are exceptions from this rule in form of well defined global variables. Examples: General lists `TGT_BIN`, `CLEAN`; General targets: `TEST`, `COVERAGE`; General variables: `GOFLAGS`, `DEPS_GO`.
3. Any rules, definitions or variables that fit some family SHOULD be defined in `mk/$family.mk` file and included from project root `Rules.mk`

License: MIT
Signed-off-by: Jakub Sztandera <kubuxu@protonmail.ch>
License: MIT
Signed-off-by: Jakub Sztandera <kubuxu@protonmail.ch>
Figured out the way to do it much more cheaply, only few % overhead over
normal coverage.

License: MIT
Signed-off-by: Jakub Sztandera <kubuxu@protonmail.ch>
License: MIT
Signed-off-by: Jakub Sztandera <kubuxu@protonmail.ch>
License: MIT
Signed-off-by: Jakub Sztandera <kubuxu@protonmail.ch>
License: MIT
Signed-off-by: Jakub Sztandera <kubuxu@protonmail.ch>
License: MIT
Signed-off-by: Jakub Sztandera <kubuxu@protonmail.ch>
This reduces flat make time by half

License: MIT
Signed-off-by: Jakub Sztandera <kubuxu@protonmail.ch>
License: MIT
Signed-off-by: Jakub Sztandera <kubuxu@protonmail.ch>
License: MIT
Signed-off-by: Jakub Sztandera <kubuxu@protonmail.ch>
The comparison was wrong

License: MIT
Signed-off-by: Jakub Sztandera <kubuxu@protonmail.ch>
License: MIT
Signed-off-by: Jakub Sztandera <kubuxu@protonmail.ch>
License: MIT
Signed-off-by: Jakub Sztandera <kubuxu@protonmail.ch>
License: MIT
Signed-off-by: Jakub Sztandera <kubuxu@protonmail.ch>
License: MIT
Signed-off-by: Jakub Sztandera <kubuxu@protonmail.ch>
License: MIT
Signed-off-by: Jakub Sztandera <kubuxu@protonmail.ch>
@Kubuxu
Copy link
Member Author

Kubuxu commented Feb 12, 2017

This last commit explains small issue I had in Jenkins with codecoverage, but because Jenkins doesn't provide require variables in Pipelines we will have to use Circle for time being.

License: MIT
Signed-off-by: Jakub Sztandera <kubuxu@protonmail.ch>
@whyrusleeping whyrusleeping merged commit e1619bf into master Feb 12, 2017
@whyrusleeping whyrusleeping deleted the feat/makefile/refactor branch February 12, 2017 01:26
@whyrusleeping whyrusleeping removed the status/ready Ready to be worked label Feb 12, 2017
whyrusleeping added a commit that referenced this pull request Feb 12, 2017
This reverts commit e1619bf, reversing
changes made to 14d5186.
whyrusleeping added a commit that referenced this pull request Feb 12, 2017
This reverts commit e1619bf, reversing
changes made to 14d5186.

License: MIT
Signed-off-by: Jeromy <jeromyj@gmail.com>

GOTAGS =
GOTAGS += "" # we have to have always at least one tag, empty tag works well
SHELL=PATH=$(PATH) /bin/sh
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might this be causing the Windows build issue?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly thanks.

TGTS_$(d) := $(d)/gx $(d)/gx-go
DISTCLEAN += $(wildcard $(d)/gx-v*) $(wildcard $(d)/gx-go-v*) $(d)/tmp

PATH := $(realpath $(d)):$(PATH)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this needs quoting, but it's probably safer to do so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
need/review Needs a review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

make: rework test/ Makefile
6 participants