diff options
Diffstat (limited to 'pkgtools/pkglint/files')
-rw-r--r-- | pkgtools/pkglint/files/buildlink3.go | 4 | ||||
-rw-r--r-- | pkgtools/pkglint/files/main.go | 14 | ||||
-rw-r--r-- | pkgtools/pkglint/files/mkline.go | 47 | ||||
-rw-r--r-- | pkgtools/pkglint/files/mkline_test.go | 13 | ||||
-rw-r--r-- | pkgtools/pkglint/files/package.go | 13 | ||||
-rw-r--r-- | pkgtools/pkglint/files/parser.go | 30 | ||||
-rw-r--r-- | pkgtools/pkglint/files/parser_test.go | 19 | ||||
-rw-r--r-- | pkgtools/pkglint/files/vardefs.go | 18 | ||||
-rw-r--r-- | pkgtools/pkglint/files/vartype.go | 2 | ||||
-rw-r--r-- | pkgtools/pkglint/files/vartypecheck.go | 113 | ||||
-rw-r--r-- | pkgtools/pkglint/files/vartypecheck_test.go | 18 |
11 files changed, 206 insertions, 85 deletions
diff --git a/pkgtools/pkglint/files/buildlink3.go b/pkgtools/pkglint/files/buildlink3.go index ab42134c7cd..5f93cb48d24 100644 --- a/pkgtools/pkglint/files/buildlink3.go +++ b/pkgtools/pkglint/files/buildlink3.go @@ -118,7 +118,7 @@ func ChecklinesBuildlink3Mk(mklines *MkLines) { if varname == "BUILDLINK_ABI_DEPENDS."+pkgbase { abiLine = line - parser := NewParser(value) + parser := NewParser(line, value) if dp := parser.Dependency(); dp != nil && parser.EOF() { abi = dp } @@ -126,7 +126,7 @@ func ChecklinesBuildlink3Mk(mklines *MkLines) { } if varname == "BUILDLINK_API_DEPENDS."+pkgbase { apiLine = line - parser := NewParser(value) + parser := NewParser(line, value) if dp := parser.Dependency(); dp != nil && parser.EOF() { api = dp } diff --git a/pkgtools/pkglint/files/main.go b/pkgtools/pkglint/files/main.go index 9d39e47f869..959c7a851f7 100644 --- a/pkgtools/pkglint/files/main.go +++ b/pkgtools/pkglint/files/main.go @@ -5,7 +5,6 @@ import ( "io" "os" "path/filepath" - "runtime" "runtime/pprof" ) @@ -40,14 +39,13 @@ func (pkglint *Pkglint) Main(args ...string) (exitcode int) { } if G.opts.Profiling { - if runtime.GOOS != "netbsd" { // See https://github.com/golang/go/issues/13914 - f, err := os.Create("pkglint.pprof") - if err != nil { - dummyLine.Fatalf("Cannot create profiling file: %s", err) - } - pprof.StartCPUProfile(f) - defer pprof.StopCPUProfile() + f, err := os.Create("pkglint.pprof") + if err != nil { + dummyLine.Fatalf("Cannot create profiling file: %s", err) } + pprof.StartCPUProfile(f) + defer pprof.StopCPUProfile() + G.rematch = NewHistogram() G.renomatch = NewHistogram() G.retime = NewHistogram() diff --git a/pkgtools/pkglint/files/mkline.go b/pkgtools/pkglint/files/mkline.go index aa51d9d4fe2..96677eb7b21 100644 --- a/pkgtools/pkglint/files/mkline.go +++ b/pkgtools/pkglint/files/mkline.go @@ -144,7 +144,7 @@ func (mkline *MkLine) Targets() string { return mkline.xs1 } func (mkline *MkLine) Sources() string { return mkline.xs2 } func (mkline *MkLine) Tokenize(s string) { - p := NewParser(s) + p := NewParser(mkline.Line, s) p.MkTokens() if p.Rest() != "" { mkline.Error1("Invalid Makefile syntax at %q.", p.Rest()) @@ -330,24 +330,24 @@ func (mkline *MkLine) WarnVaruseLocalbase() { "(1) To locate a file or directory from another package.", "(2) To refer to own files after installation.", "", - "In the first case, the example is:", + "Example for (1):", "", " STRLIST= ${LOCALBASE}/bin/strlist", " do-build:", " cd ${WRKSRC} && ${STRLIST} *.str", "", - "This should really be:", + "This should better be:", "", " EVAL_PREFIX= STRLIST_PREFIX=strlist", " STRLIST= ${STRLIST_PREFIX}/bin/strlist", " do-build:", " cd ${WRKSRC} && ${STRLIST} *.str", "", - "In the second case, the example is:", + "Example for (2):", "", " CONFIGURE_ENV+= --with-datafiles=${LOCALBASE}/share/pkgbase", "", - "This should really be:", + "This should better be:", "", " CONFIGURE_ENV+= --with-datafiles=${PREFIX}/share/pkgbase") } @@ -816,7 +816,7 @@ func (mkline *MkLine) CheckCond() { defer tracecall0()() } - p := NewParser(mkline.Args()) + p := NewParser(mkline.Line, mkline.Args()) cond := p.MkCond() if !p.EOF() { mkline.Warn1("Invalid conditional %q.", mkline.Args()) @@ -826,6 +826,21 @@ func (mkline *MkLine) CheckCond() { cond.Visit("empty", func(node *Tree) { varuse := node.args[0].(MkVarUse) varname := varuse.varname + if matches(varname, `^\$.*:[MN]`) { + mkline.Warn0("The empty() function takes a variable name as parameter, not a variable expression.") + Explain( + "Instead of empty(${VARNAME:Mpattern}), you should write either", + "of the following:", + "", + "\tempty(VARNAME:Mpattern)", + "\t${VARNAME:Mpattern} == \"\"", + "", + "Instead of !empty(${VARNAME:Mpattern}), you should write either", + "of the following:", + "", + "\t!empty(VARNAME:Mpattern)", + "\t${VARNAME:Mpattern}") + } for _, modifier := range varuse.modifiers { if modifier[0] == 'M' || modifier[0] == 'N' { mkline.CheckVartype(varname, opUseMatch, modifier[1:], "") @@ -838,7 +853,9 @@ func (mkline *MkLine) CheckCond() { varname := varuse.varname varmods := varuse.modifiers value := node.args[2].(string) - if len(varmods) == 0 || len(varmods) == 1 && matches(varmods[0], `^[MN]`) && value != "" { + if len(varmods) == 0 { + mkline.CheckVartype(varname, opUse, value, "") + } else if len(varmods) == 1 && matches(varmods[0], `^[MN]`) && value != "" { mkline.CheckVartype(varname, opUseMatch, value, "") } }) @@ -976,21 +993,31 @@ func (mkline *MkLine) variableNeedsQuoting(varname string, vuc *VarUseContext) ( isPlainWord := vartype.checker.IsEnum() switch vartype.checker { - case CheckvarDistSuffix, + case CheckvarBuildlinkDepmethod, + CheckvarCategory, + CheckvarDistSuffix, + CheckvarEmulPlatform, CheckvarFileMode, CheckvarFilename, CheckvarIdentifier, + CheckvarInteger, CheckvarOption, CheckvarPathname, + CheckvarPerl5Packlist, CheckvarPkgName, CheckvarPkgOptionsVar, + CheckvarPkgPath, CheckvarPkgRevision, + CheckvarPrefixPathname, + CheckvarPythonDependency, CheckvarRelativePkgDir, CheckvarRelativePkgPath, + CheckvarStage, CheckvarUserGroupName, - CheckvarVarname, CheckvarVersion, - CheckvarWrkdirSubdirectory: + CheckvarWrkdirSubdirectory, + CheckvarYesNo, + CheckvarYesNoIndirectly: isPlainWord = true } if isPlainWord { diff --git a/pkgtools/pkglint/files/mkline_test.go b/pkgtools/pkglint/files/mkline_test.go index 2f71f5d066e..baace91dfce 100644 --- a/pkgtools/pkglint/files/mkline_test.go +++ b/pkgtools/pkglint/files/mkline_test.go @@ -330,6 +330,18 @@ func (s *Suite) TestChecklineMkCondition(c *check.C) { NewMkLine(NewLine("fname", 1, ".if !empty(IS_BUILTIN.Xfixes:M[yY][eE][sS])", nil)).CheckCond() c.Check(s.Output(), equals, "") + + NewMkLine(NewLine("fname", 1, ".if !empty(${IS_BUILTIN.Xfixes:M[yY][eE][sS]})", nil)).CheckCond() + + c.Check(s.Output(), equals, "WARN: fname:1: The empty() function takes a variable name as parameter, not a variable expression.\n") + + NewMkLine(NewLine("fname", 1, ".if ${EMUL_PLATFORM} == \"linux-x386\"", nil)).CheckCond() + + c.Check(s.Output(), equals, "WARN: fname:1: \"x386\" is not valid for the hardware architecture part of EMUL_PLATFORM. Use one of { alpha amd64 arc arm arm32 cobalt convex dreamcast hpcmips hpcsh hppa i386 ia64 m68k m88k mips mips64 mips64eb mips64el mipseb mipsel mipsn32 ns32k pc532 pmax powerpc rs6000 s390 sh3eb sh3el sparc sparc64 vax x86_64 } instead.\n") + + NewMkLine(NewLine("fname", 1, ".if ${EMUL_PLATFORM:Mlinux-x386}", nil)).CheckCond() + + c.Check(s.Output(), equals, "WARN: fname:1: The pattern \"x386\" cannot match any of { alpha amd64 arc arm arm32 cobalt convex dreamcast hpcmips hpcsh hppa i386 ia64 m68k m88k mips mips64 mips64eb mips64el mipseb mipsel mipsn32 ns32k pc532 pmax powerpc rs6000 s390 sh3eb sh3el sparc sparc64 vax x86_64 } for the hardware architecture part of EMUL_PLATFORM.\n") } func (s *Suite) TestMkLine_variableNeedsQuoting(c *check.C) { @@ -435,7 +447,6 @@ func (s *Suite) TestMkLine_CheckVarusePermissions(c *check.C) { "WARN: options.mk:2: The user-defined variable GAMES_USER is used but not added to BUILD_DEFS.\n"+ "WARN: options.mk:3: PKGBASE should not be evaluated at load time.\n"+ "WARN: options.mk:4: The variable PYPKGPREFIX may not be set in this file; it would be ok in pyversion.mk.\n"+ - "WARN: options.mk:4: \"${PKGBASE}\" is not valid for PYPKGPREFIX. Use one of { py27 py33 py34 py35 } instead.\n"+ "WARN: options.mk:4: PKGBASE should not be evaluated indirectly at load time.\n"+ "NOTE: options.mk:4: This variable value should be aligned to column 17.\n") } diff --git a/pkgtools/pkglint/files/package.go b/pkgtools/pkglint/files/package.go index 4419db20092..40232102c7a 100644 --- a/pkgtools/pkglint/files/package.go +++ b/pkgtools/pkglint/files/package.go @@ -164,6 +164,9 @@ func checkdirPackage(pkgpath string) { } for _, fname := range files { + if containsVarRef(fname) { + continue + } if fname == G.CurrentDir+"/Makefile" { if G.opts.CheckMakefile { pkg.checkfilePackageMakefile(fname, lines) @@ -294,7 +297,8 @@ func readMakefile(fname string, mainLines *MkLines, allLines *MkLines, including G.Pkg.seenMakefileCommon = true } - if !contains(incDir, "/mk/") || strings.HasSuffix(includeFile, "/mk/haskell.mk") || contains(incDir, "/wip/mk/") { + skip := contains(fname, "/mk/") || hasSuffix(includeFile, "/bsd.pkg.mk") || hasSuffix(includeFile, "/bsd.prefs.mk") + if !skip { dirname, _ := path.Split(fname) dirname = cleanpath(dirname) @@ -389,9 +393,10 @@ func (pkg *Package) checkfilePackageMakefile(fname string, mklines *MkLines) { Warnf(fname, noLines, "No COMMENT given.") } - if vardef["USE_IMAKE"] != nil && vardef["USE_X11"] != nil { - vardef["USE_IMAKE"].Note0("USE_IMAKE makes ...") - vardef["USE_X11"].Note0("... USE_X11 superfluous.") + if imake, x11 := vardef["USE_IMAKE"], vardef["USE_X11"]; imake != nil && x11 != nil { + if !hasSuffix(x11.Line.Fname, "/mk/x11.buildlink3.mk") { + imake.Line.Note1("USE_IMAKE makes USE_X11 in %s superfluous.", x11.Line.ReferenceFrom(imake.Line)) + } } pkg.checkUpdate() diff --git a/pkgtools/pkglint/files/parser.go b/pkgtools/pkglint/files/parser.go index 0b8b3b98206..f33bc1343c5 100644 --- a/pkgtools/pkglint/files/parser.go +++ b/pkgtools/pkglint/files/parser.go @@ -5,11 +5,12 @@ import ( ) type Parser struct { + line *Line repl *PrefixReplacer } -func NewParser(s string) *Parser { - return &Parser{NewPrefixReplacer(s)} +func NewParser(line *Line, s string) *Parser { + return &Parser{line, NewPrefixReplacer(s)} } func (p *Parser) EOF() bool { @@ -155,15 +156,16 @@ func (p *Parser) VarUse() *MkVarUse { mark := repl.Mark() if repl.AdvanceStr("${") || repl.AdvanceStr("$(") { - closing := "}" - if repl.Since(mark) == "$(" { - closing = ")" - } + usingRoundParen := repl.Since(mark) == "$(" + closing := ifelseStr(usingRoundParen, ")", "}") varnameMark := repl.Mark() varname := p.Varname() if varname != "" { - modifiers := p.VarUseModifiers(closing) + if usingRoundParen { + p.line.Warn1("Please use curly braces {} instead of round parentheses () for %s.", varname) + } + modifiers := p.VarUseModifiers(varname, closing) if repl.AdvanceStr(closing) { return &MkVarUse{varname, modifiers} } @@ -174,7 +176,7 @@ func (p *Parser) VarUse() *MkVarUse { rest := p.Rest() if hasPrefix(rest, ":L") || hasPrefix(rest, ":sh") || hasPrefix(rest, ":?") { varexpr := repl.Since(varnameMark) - modifiers := p.VarUseModifiers(closing) + modifiers := p.VarUseModifiers(varexpr, closing) if repl.AdvanceStr(closing) { return &MkVarUse{varexpr, modifiers} } @@ -185,7 +187,7 @@ func (p *Parser) VarUse() *MkVarUse { return nil } -func (p *Parser) VarUseModifiers(closing string) []string { +func (p *Parser) VarUseModifiers(varname, closing string) []string { repl := p.repl var modifiers []string @@ -243,12 +245,14 @@ func (p *Parser) VarUseModifiers(closing string) []string { case '@': if repl.AdvanceRegexp(`^@([\w.]+)@`) { + loopvar := repl.m[1] for p.VarUse() != nil || repl.AdvanceRegexp(`^([^$:@`+closing+`\\]|\$\$|\\.)+`) { } - if repl.AdvanceStr("@") { - modifiers = append(modifiers, repl.Since(modifierMark)) - continue + if !repl.AdvanceStr("@") { + p.line.Warn2("Modifier ${%s:@%s@...@} is missing the final \"@\".", varname, loopvar) } + modifiers = append(modifiers, repl.Since(modifierMark)) + continue } case '[': @@ -365,7 +369,7 @@ func (p *Parser) mkCondAtom() *Tree { } case repl.AdvanceRegexp(`^empty\s*\(`): if varname := p.Varname(); varname != "" { - modifiers := p.VarUseModifiers(")") + modifiers := p.VarUseModifiers(varname, ")") if repl.AdvanceStr(")") { return NewTree("empty", MkVarUse{varname, modifiers}) } diff --git a/pkgtools/pkglint/files/parser_test.go b/pkgtools/pkglint/files/parser_test.go index 72dd8b8d12f..d094250b682 100644 --- a/pkgtools/pkglint/files/parser_test.go +++ b/pkgtools/pkglint/files/parser_test.go @@ -6,7 +6,7 @@ import ( func (s *Suite) TestParser_PkgbasePattern(c *check.C) { test := func(pattern, expected, rest string) { - parser := NewParser(pattern) + parser := NewParser(dummyLine, pattern) actual := parser.PkgbasePattern() c.Check(actual, equals, expected) c.Check(parser.Rest(), equals, rest) @@ -22,7 +22,7 @@ func (s *Suite) TestParser_PkgbasePattern(c *check.C) { func (s *Suite) TestParser_Dependency(c *check.C) { testDependencyRest := func(pattern string, expected DependencyPattern, rest string) { - parser := NewParser(pattern) + parser := NewParser(dummyLine, pattern) dp := parser.Dependency() if c.Check(dp, check.NotNil) { c.Check(*dp, equals, expected) @@ -53,7 +53,7 @@ func (s *Suite) TestParser_Dependency(c *check.C) { func (s *Suite) TestParser_MkTokens(c *check.C) { parse := func(input string, expectedTokens []*MkToken, expectedRest string) { - p := NewParser(input) + p := NewParser(dummyLine, input) actualTokens := p.MkTokens() c.Check(actualTokens, deepEquals, expectedTokens) for i, expectedToken := range expectedTokens { @@ -109,7 +109,6 @@ func (s *Suite) TestParser_MkTokens(c *check.C) { token("${_PERL5_VARS_OUT:M${_var_:tl}=*:S/^${_var_:tl}=${_PERL5_PREFIX:=/}//}", varuse("_PERL5_VARS_OUT", "M${_var_:tl}=*", "S/^${_var_:tl}=${_PERL5_PREFIX:=/}//")) token("${RUBY${RUBY_VER}_PATCHLEVEL}", varuse("RUBY${RUBY_VER}_PATCHLEVEL")) token("${DISTFILES:M*.gem}", varuse("DISTFILES", "M*.gem")) - token("$(GNUSTEP_USER_ROOT)", varuse("GNUSTEP_USER_ROOT")) token("${LOCALBASE:S^/^_^}", varuse("LOCALBASE", "S^/^_^")) token("${SOURCES:%.c=%.o}", varuse("SOURCES", "%.c=%.o")) token("${GIT_TEMPLATES:@.t.@ ${EGDIR}/${GIT_TEMPLATEDIR}/${.t.} ${PREFIX}/${GIT_CORE_TEMPLATEDIR}/${.t.} @:M*}", @@ -135,13 +134,21 @@ func (s *Suite) TestParser_MkTokens(c *check.C) { token("${VAR:ts\\000012}", varuse("VAR", "ts\\000012")) // The separator character can be a long octal number. token("${VAR:ts\\124}", varuse("VAR", "ts\\124")) // Or even decimal. + token("$(GNUSTEP_USER_ROOT)", varuse("GNUSTEP_USER_ROOT")) + c.Check(s.Output(), equals, "WARN: Please use curly braces {} instead of round parentheses () for GNUSTEP_USER_ROOT.\n") + parse("${VAR)", nil, "${VAR)") // Opening brace, closing parenthesis parse("$(VAR}", nil, "$(VAR}") // Opening parenthesis, closing brace + c.Check(s.Output(), equals, "WARN: Please use curly braces {} instead of round parentheses () for VAR.\n") + + token("${PLIST_SUBST_VARS:@var@${var}=${${var}:Q}@}", varuse("PLIST_SUBST_VARS", "@var@${var}=${${var}:Q}@")) + token("${PLIST_SUBST_VARS:@var@${var}=${${var}:Q}}", varuse("PLIST_SUBST_VARS", "@var@${var}=${${var}:Q}")) // Missing @ at the end + c.Check(s.Output(), equals, "WARN: Modifier ${PLIST_SUBST_VARS:@var@...@} is missing the final \"@\".\n") } func (s *Suite) TestParser_MkCond_Basics(c *check.C) { condrest := func(input string, expectedTree *Tree, expectedRest string) { - p := NewParser(input) + p := NewParser(dummyLine, input) actualTree := p.MkCond() c.Check(actualTree, deepEquals, expectedTree) c.Check(p.Rest(), equals, expectedRest) @@ -209,6 +216,8 @@ func (s *Suite) TestParser_MkCond_Basics(c *check.C) { NewTree("compareVarNum", varuse("OS_VERSION"), ">=", "6.5")) cond("${OS_VERSION} == 5.3", NewTree("compareVarNum", varuse("OS_VERSION"), "==", "5.3")) + cond("!empty(${OS_VARIANT:MIllumos})", // Probably not intended + NewTree("not", NewTree("empty", varuse("${OS_VARIANT:MIllumos}")))) // Errors condrest("!empty(PKG_OPTIONS:Msndfile) || defined(PKG_OPTIONS:Msamplerate)", diff --git a/pkgtools/pkglint/files/vardefs.go b/pkgtools/pkglint/files/vardefs.go index 3352c07ee91..394ebaa6676 100644 --- a/pkgtools/pkglint/files/vardefs.go +++ b/pkgtools/pkglint/files/vardefs.go @@ -118,8 +118,8 @@ func (gd *GlobalData) InitVartypes() { pkg("BOOTSTRAP_PKG", lkNone, CheckvarYesNo) acl("BROKEN", lkNone, CheckvarMessage, "") pkg("BROKEN_GETTEXT_DETECTION", lkNone, CheckvarYesNo) - pkglist("BROKEN_EXCEPT_ON_PLATFORM", lkShell, CheckvarPlatformTriple) - pkglist("BROKEN_ON_PLATFORM", lkSpace, CheckvarPlatformTriple) + pkglist("BROKEN_EXCEPT_ON_PLATFORM", lkShell, CheckvarPlatformPattern) + pkglist("BROKEN_ON_PLATFORM", lkSpace, CheckvarPlatformPattern) sys("BSD_MAKE_ENV", lkShell, CheckvarShellWord) acl("BUILDLINK_ABI_DEPENDS.*", lkSpace, CheckvarDependency, "*: append") acl("BUILDLINK_API_DEPENDS.*", lkSpace, CheckvarDependency, "*: append") @@ -334,8 +334,8 @@ func (gd *GlobalData) InitVartypes() { pkglist("HEADER_TEMPLATES", lkShell, CheckvarPathname) pkg("HOMEPAGE", lkNone, CheckvarURL) acl("IGNORE_PKG.*", lkNone, CheckvarYes, "*: set, use-loadtime") - acl("INCOMPAT_CURSES", lkSpace, CheckvarPlatformTriple, "Makefile: set, append") - acl("INCOMPAT_ICONV", lkSpace, CheckvarPlatformTriple, "") + acl("INCOMPAT_CURSES", lkSpace, CheckvarPlatformPattern, "Makefile: set, append") + acl("INCOMPAT_ICONV", lkSpace, CheckvarPlatformPattern, "") acl("INFO_DIR", lkNone, CheckvarPathname, "") // relative to PREFIX pkg("INFO_FILES", lkNone, CheckvarYes) sys("INSTALL", lkNone, CheckvarShellCommand) @@ -392,7 +392,7 @@ func (gd *GlobalData) InitVartypes() { sys("LOWER_OPSYS", lkNone, CheckvarIdentifier) acl("LTCONFIG_OVERRIDE", lkShell, CheckvarPathmask, "Makefile: set, append; Makefile.common: append") sys("MACHINE_ARCH", lkNone, CheckvarIdentifier) - sys("MACHINE_GNU_PLATFORM", lkNone, CheckvarPlatformTriple) + sys("MACHINE_GNU_PLATFORM", lkNone, CheckvarPlatformPattern) // This one is actually not a pattern acl("MAINTAINER", lkNone, CheckvarMailAddress, "Makefile: set; Makefile.common: default") sys("MAKE", lkNone, CheckvarShellCommand) pkglist("MAKEFLAGS", lkShell, CheckvarShellWord) @@ -451,7 +451,7 @@ func (gd *GlobalData) InitVartypes() { sys("NM", lkNone, CheckvarShellCommand) sys("NONBINMODE", lkNone, CheckvarFileMode) pkg("NOT_FOR_COMPILER", lkShell, enum("ccache ccc clang distcc f2c gcc hp icc ido mipspro mipspro-ucode pcc sunpro xlc")) - pkglist("NOT_FOR_PLATFORM", lkSpace, CheckvarPlatformTriple) + pkglist("NOT_FOR_PLATFORM", lkSpace, CheckvarPlatformPattern) pkg("NOT_FOR_UNPRIVILEGED", lkNone, CheckvarYesNo) acl("NO_BIN_ON_CDROM", lkNone, CheckvarRestricted, "Makefile, Makefile.common: set") acl("NO_BIN_ON_FTP", lkNone, CheckvarRestricted, "Makefile, Makefile.common: set") @@ -465,7 +465,7 @@ func (gd *GlobalData) InitVartypes() { acl("NO_SRC_ON_CDROM", lkNone, CheckvarRestricted, "Makefile, Makefile.common: set") acl("NO_SRC_ON_FTP", lkNone, CheckvarRestricted, "Makefile, Makefile.common: set") pkglist("ONLY_FOR_COMPILER", lkShell, enum("ccc clang gcc hp icc ido mipspro mipspro-ucode pcc sunpro xlc")) - pkglist("ONLY_FOR_PLATFORM", lkSpace, CheckvarPlatformTriple) + pkglist("ONLY_FOR_PLATFORM", lkSpace, CheckvarPlatformPattern) pkg("ONLY_FOR_UNPRIVILEGED", lkNone, CheckvarYesNo) sys("OPSYS", lkNone, CheckvarIdentifier) acl("OPSYSVARS", lkShell, CheckvarVarname, "Makefile, Makefile.common: append") @@ -537,7 +537,7 @@ func (gd *GlobalData) InitVartypes() { acl("PKG_HACKS", lkShell, CheckvarIdentifier, "hacks.mk: append") sys("PKG_INFO", lkNone, CheckvarShellCommand) sys("PKG_JAVA_HOME", lkNone, CheckvarPathname) - jvms := enum("blackdown-jdk13 jdk jdk14 kaffe run-jdk13 sun-jdk14 sun-jdk15 sun-jdk6 openjdk7 openjdk7-bin sun-jdk7 openjdk8 oracle-jdk8") + jvms := enum("openjdk8 oracle-jdk8 openjdk7 sun-jdk7 sun-jdk6 jdk16 jdk15 kaffe") // See mk/java-vm.mk:/_PKG_JVMS/ sys("PKG_JVM", lkNone, jvms) acl("PKG_JVMS_ACCEPTED", lkShell, jvms, "Makefile: set; Makefile.common: default, set") usr("PKG_JVM_DEFAULT", lkNone, jvms) @@ -724,7 +724,7 @@ func enum(values string) *VarChecker { return } - if !vmap[cv.value] { + if cv.value == cv.valueNovar && !vmap[cv.value] { cv.line.Warnf("%q is not valid for %s. Use one of { %s } instead.", cv.value, cv.varname, values) } }} diff --git a/pkgtools/pkglint/files/vartype.go b/pkgtools/pkglint/files/vartype.go index 686565e8dda..f88e548d5c3 100644 --- a/pkgtools/pkglint/files/vartype.go +++ b/pkgtools/pkglint/files/vartype.go @@ -179,7 +179,7 @@ var ( CheckvarPkgPath = &VarChecker{"PkgPath", (*VartypeCheck).PkgPath} CheckvarPkgOptionsVar = &VarChecker{"PkgOptionsVar", (*VartypeCheck).PkgOptionsVar} CheckvarPkgRevision = &VarChecker{"PkgRevision", (*VartypeCheck).PkgRevision} - CheckvarPlatformTriple = &VarChecker{"PlatformTriple", (*VartypeCheck).PlatformTriple} + CheckvarPlatformPattern = &VarChecker{"PlatformPattern", (*VartypeCheck).PlatformPattern} CheckvarPrefixPathname = &VarChecker{"PrefixPathname", (*VartypeCheck).PrefixPathname} CheckvarPythonDependency = &VarChecker{"PythonDependency", (*VartypeCheck).PythonDependency} CheckvarRelativePkgDir = &VarChecker{"RelativePkgDir", (*VartypeCheck).RelativePkgDir} diff --git a/pkgtools/pkglint/files/vartypecheck.go b/pkgtools/pkglint/files/vartypecheck.go index a91a1ce372d..bcf2deb5734 100644 --- a/pkgtools/pkglint/files/vartypecheck.go +++ b/pkgtools/pkglint/files/vartypecheck.go @@ -50,6 +50,26 @@ func (op MkOperator) String() string { return [...]string{"=", "!=", ":=", "+=", "?=", "use", "use-loadtime", "use-match"}[op] } +const ( + reEmulPlatform = "" + + "bitrig|bsdos|cygwin|darwin|dragonfly|freebsd|" + + "haiku|hpux|interix|irix|linux|mirbsd|netbsd|openbsd|osf1|solaris" + rePlatformOs = "" + + "Bitrig|BSDOS|Cygwin|Darwin|DragonFly|FreeBSD|" + + "Haiku|HPUX|Interix|IRIX|Linux|MirBSD|NetBSD|OpenBSD|OSF1|QNX|SunOS" + rePlatformArch = "" + + "alpha|amd64|arc|arm|arm32|cobalt|convex|dreamcast|" + + "hpcmips|hpcsh|hppa|i386|ia64|" + + "m68k|m88k|mips|mips64|mips64eb|mips64el|mipseb|mipsel|mipsn32|" + + "ns32k|pc532|pmax|powerpc|rs6000|s390|sh3eb|sh3el|sparc|sparc64|vax|x86_64" +) + +var ( + emulPlatformEnum = enum(strings.Replace(reEmulPlatform, "|", " ", -1)) + platformOsEnum = enum(strings.Replace(rePlatformOs, "|", " ", -1)) + platformArchEnum = enum(strings.Replace(rePlatformArch, "|", " ", -1)) +) + func (cv *VartypeCheck) AwkCommand() { if G.opts.DebugUnchecked { cv.line.Debug1("Unchecked AWK command: %q", cv.value) @@ -137,7 +157,7 @@ func (cv *VartypeCheck) Comment() { func (cv *VartypeCheck) Dependency() { line, value := cv.line, cv.value - parser := NewParser(value) + parser := NewParser(line, value) deppat := parser.Dependency() if deppat != nil && deppat.wildcard == "" && (parser.Rest() == "{,nb*}" || parser.Rest() == "{,nb[0-9]*}") { line.Warn0("Dependency patterns of the form pkgbase>=1.0 don't need the \"{,nb*}\" extension.") @@ -243,16 +263,34 @@ func (cv *VartypeCheck) DistSuffix() { } func (cv *VartypeCheck) EmulPlatform() { + const rePart = `(?:\[[^\]]+\]|[^-\[])+` + const rePair = `^(` + rePart + `)-(` + rePart + `)$` + if m, opsysPattern, archPattern := match2(cv.value, rePair); m { + opsysCv := &VartypeCheck{ + cv.mkline, + cv.line, + "the operating system part of " + cv.varname, + cv.op, + opsysPattern, + opsysPattern, + cv.comment, + cv.listContext, + cv.guessed} + emulPlatformEnum.checker(opsysCv) - if m, opsys, arch := match2(cv.value, `^(\w+)-(\w+)$`); m { - if !matches(opsys, `^(?:bitrig|bsdos|cygwin|darwin|dragonfly|freebsd|haiku|hpux|interix|irix|linux|mirbsd|netbsd|openbsd|osf1|sunos|solaris)$`) { - cv.line.Warn1("Unknown operating system: %s", opsys) - } // no check for os_version - if !matches(arch, `^(?:i386|alpha|amd64|arc|arm|arm32|cobalt|convex|dreamcast|hpcmips|hpcsh|hppa|ia64|m68k|m88k|mips|mips64|mipsel|mipseb|mipsn32|ns32k|pc532|pmax|powerpc|rs6000|s390|sparc|sparc64|vax|x86_64)$`) { - cv.line.Warn1("Unknown hardware architecture: %s", arch) - } + archCv := &VartypeCheck{ + cv.mkline, + cv.line, + "the hardware architecture part of " + cv.varname, + cv.op, + archPattern, + archPattern, + cv.comment, + cv.listContext, + cv.guessed} + platformArchEnum.checker(archCv) } else { cv.line.Warn1("%q is not a valid emulation platform.", cv.value) Explain( @@ -260,7 +298,9 @@ func (cv *VartypeCheck) EmulPlatform() { "OPSYS is the lower-case name of the operating system, and", "MACHINE_ARCH is the hardware architecture.", "", - "Examples: linux-i386, irix-mipsel.") + "Examples:", + "* linux-i386", + "* irix-mipsel") } } @@ -535,31 +575,54 @@ func (cv *VartypeCheck) PkgRevision() { } } -func (cv *VartypeCheck) PlatformTriple() { +func (cv *VartypeCheck) PlatformPattern() { if cv.value != cv.valueNovar { return } - rePart := `(?:\[[^\]]+\]|[^-\[])+` - reTriple := `^(` + rePart + `)-(` + rePart + `)-(` + rePart + `)$` - if m, opsys, _, arch := match3(cv.value, reTriple); m { - if !matches(opsys, `^(?:\*|Bitrig|BSDOS|Cygwin|Darwin|DragonFly|FreeBSD|Haiku|HPUX|Interix|IRIX|Linux|MirBSD|NetBSD|OpenBSD|OSF1|QNX|SunOS)$`) { - cv.line.Warn1("Unknown operating system: %s", opsys) - } + const rePart = `(?:\[[^\]]+\]|[^-\[])+` + const reTriple = `^(` + rePart + `)-(` + rePart + `)-(` + rePart + `)$` + if m, opsysPattern, _, archPattern := match3(cv.value, reTriple); m { + opsysCv := &VartypeCheck{ + cv.mkline, + cv.line, + "the operating system part of " + cv.varname, + opUseMatch, // Always allow patterns, since this is a PlatformPattern. + opsysPattern, + opsysPattern, + cv.comment, + cv.listContext, + cv.guessed} + platformOsEnum.checker(opsysCv) + // no check for os_version - if !matches(arch, `^(?:\*|i386|alpha|amd64|arc|arm|arm32|cobalt|convex|dreamcast|hpcmips|hpcsh|hppa|ia64|m68k|m88k|mips|mips64|mipsel|mipseb|mipsn32|ns32k|pc532|pmax|powerpc|rs6000|s390|sparc|sparc64|vax|x86_64)$`) { - cv.line.Warn1("Unknown hardware architecture: %s", arch) - } + + archCv := &VartypeCheck{ + cv.mkline, + cv.line, + "the hardware architecture part of " + cv.varname, + opUseMatch, // Always allow patterns, since this is a PlatformPattern. + archPattern, + archPattern, + cv.comment, + cv.listContext, + cv.guessed} + platformArchEnum.checker(archCv) } else { - cv.line.Warn1("%q is not a valid platform triple.", cv.value) - Explain3( - "A platform triple has the form <OPSYS>-<OS_VERSION>-<MACHINE_ARCH>.", + cv.line.Warn1("%q is not a valid platform pattern.", cv.value) + Explain( + "A platform pattern has the form <OPSYS>-<OS_VERSION>-<MACHINE_ARCH>.", "Each of these components may be a shell globbing expression.", - "Examples: NetBSD-*-i386, *-*-*, Linux-*-*.") + "", + "Examples:", + "* NetBSD-[456].*-i386", + "* *-*-*", + "* Linux-*-*") } } +// A pathname relative to ${PREFIX}. func (cv *VartypeCheck) PrefixPathname() { if m, mansubdir := match1(cv.value, `^man/(.+)`); m { cv.line.Warn2("Please use \"${PKGMANDIR}/%s\" instead of %q.", mansubdir, cv.value) @@ -579,12 +642,12 @@ func (cv *VartypeCheck) PythonDependency() { } } -// Refers to a package directory. +// Refers to a package directory, e.g. ../../category/pkgbase. func (cv *VartypeCheck) RelativePkgDir() { cv.mkline.CheckRelativePkgdir(cv.value) } -// Refers to a file or directory. +// Refers to a file or directory, e.g. ../../category/pkgbase, ../../category/pkgbase/Makefile. func (cv *VartypeCheck) RelativePkgPath() { cv.mkline.CheckRelativePath(cv.value, true) } diff --git a/pkgtools/pkglint/files/vartypecheck_test.go b/pkgtools/pkglint/files/vartypecheck_test.go index 4cf8a54c4f7..dcd0615fe32 100644 --- a/pkgtools/pkglint/files/vartypecheck_test.go +++ b/pkgtools/pkglint/files/vartypecheck_test.go @@ -166,8 +166,8 @@ func (s *Suite) TestVartypeCheck_EmulPlatform(c *check.C) { "${LINUX}") c.Check(s.Output(), equals, ""+ - "WARN: fname:2: Unknown operating system: nextbsd\n"+ - "WARN: fname:2: Unknown hardware architecture: 8087\n"+ + "WARN: fname:2: \"nextbsd\" is not valid for the operating system part of EMUL_PLATFORM. Use one of { bitrig bsdos cygwin darwin dragonfly freebsd haiku hpux interix irix linux mirbsd netbsd openbsd osf1 solaris } instead.\n"+ + "WARN: fname:2: \"8087\" is not valid for the hardware architecture part of EMUL_PLATFORM. Use one of { alpha amd64 arc arm arm32 cobalt convex dreamcast hpcmips hpcsh hppa i386 ia64 m68k m88k mips mips64 mips64eb mips64el mipseb mipsel mipsn32 ns32k pc532 pmax powerpc rs6000 s390 sh3eb sh3el sparc sparc64 vax x86_64 } instead.\n"+ "WARN: fname:3: \"${LINUX}\" is not a valid emulation platform.\n") } @@ -287,16 +287,20 @@ func (s *Suite) TestVartypeCheck_PkgRevision(c *check.C) { c.Check(s.Output(), equals, "") } -func (s *Suite) TestVartypeCheck_PlatformTriple(c *check.C) { - runVartypeChecks("ONLY_FOR_PLATFORM", opAssign, (*VartypeCheck).PlatformTriple, +func (s *Suite) TestVartypeCheck_PlatformPattern(c *check.C) { + runVartypeMatchChecks("ONLY_FOR_PLATFORM", (*VartypeCheck).PlatformPattern, "linux-i386", "nextbsd-5.0-8087", + "netbsd-7.0-l*", + "NetBSD-1.6.2-i386", "${LINUX}") c.Check(s.Output(), equals, ""+ - "WARN: fname:1: \"linux-i386\" is not a valid platform triple.\n"+ - "WARN: fname:2: Unknown operating system: nextbsd\n"+ - "WARN: fname:2: Unknown hardware architecture: 8087\n") + "WARN: fname:1: \"linux-i386\" is not a valid platform pattern.\n"+ + "WARN: fname:2: The pattern \"nextbsd\" cannot match any of { Bitrig BSDOS Cygwin Darwin DragonFly FreeBSD Haiku HPUX Interix IRIX Linux MirBSD NetBSD OpenBSD OSF1 QNX SunOS } for the operating system part of ONLY_FOR_PLATFORM.\n"+ + "WARN: fname:2: The pattern \"8087\" cannot match any of { alpha amd64 arc arm arm32 cobalt convex dreamcast hpcmips hpcsh hppa i386 ia64 m68k m88k mips mips64 mips64eb mips64el mipseb mipsel mipsn32 ns32k pc532 pmax powerpc rs6000 s390 sh3eb sh3el sparc sparc64 vax x86_64 } for the hardware architecture part of ONLY_FOR_PLATFORM.\n"+ + "WARN: fname:3: The pattern \"netbsd\" cannot match any of { Bitrig BSDOS Cygwin Darwin DragonFly FreeBSD Haiku HPUX Interix IRIX Linux MirBSD NetBSD OpenBSD OSF1 QNX SunOS } for the operating system part of ONLY_FOR_PLATFORM.\n"+ + "WARN: fname:3: The pattern \"l*\" cannot match any of { alpha amd64 arc arm arm32 cobalt convex dreamcast hpcmips hpcsh hppa i386 ia64 m68k m88k mips mips64 mips64eb mips64el mipseb mipsel mipsn32 ns32k pc532 pmax powerpc rs6000 s390 sh3eb sh3el sparc sparc64 vax x86_64 } for the hardware architecture part of ONLY_FOR_PLATFORM.\n") } func (s *Suite) TestVartypeCheck_PythonDependency(c *check.C) { |