From patchwork Fri Feb 9 03:09:04 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Gunthorpe X-Patchwork-Id: 10208227 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 5D6EC60247 for ; Fri, 9 Feb 2018 03:09:25 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4A96329680 for ; Fri, 9 Feb 2018 03:09:25 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3F13429684; Fri, 9 Feb 2018 03:09:25 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BC26729680 for ; Fri, 9 Feb 2018 03:09:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752514AbeBIDJP (ORCPT ); Thu, 8 Feb 2018 22:09:15 -0500 Received: from mail-io0-f194.google.com ([209.85.223.194]:39042 "EHLO mail-io0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752498AbeBIDJO (ORCPT ); Thu, 8 Feb 2018 22:09:14 -0500 Received: by mail-io0-f194.google.com with SMTP id b198so8177378iof.6 for ; Thu, 08 Feb 2018 19:09:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ziepe.ca; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=1mG9Rh0Ob4rCxT+rr694nx+WTF0gVJ7Pha7FW6IT9CE=; b=JIPm8IGBnkvRNKpvYFq5yk2r45hTAX3tTUH3qqPbUGyuaBNwANpGd42WSx8D8tqS21 n9J7mYkI3YBjX/oErfEsyxw+KlzYblnWmzuOyiy6thU5A1Fd4SdTrBb7lhB9/+uaivpF Kt3az0JRZheyNhvjt6yMxkIZLsAjnv8balx4rvnrkTqwpZjahBF/dweYcD4fMIJ59EtA 1EFoFwbOj6VfcN7HSxBVO+TFlYGdtG7DY4ygI17yAFbeY5RKp6wlRCAtOFm9IFyN6Edc HEtWCCUvmhxJEK3ETqhj3ndeJd/aRtmvLuYaUbFY7Y2HwZrQv3rUt6BCxPoSXrChexH7 dOjw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=1mG9Rh0Ob4rCxT+rr694nx+WTF0gVJ7Pha7FW6IT9CE=; b=cOkY9jX8tg+wWZ7A4t+P7NZXJd4h13aPi1P43v0DpgRQQKN0wPiS8DtbLTLme3fUxH 3va5A6KifB8IE9YDVDuyPQ33JBQqdIXpRu6enty2DafjCOFxubhh0HpAkUTZk2P/SLmE axJShmuZ83GtY5i4esY8UbNsMQpqilj+FpU79LQZD0xfFKpIJMUqSi1b1VC4PUByuM3A URqOft19cux9xILIPlXhH+2FNlzXt91ZN5CEk8UlHTkLjQ1yBgpM6SCm/9D7NI6TfXiH bUuKVRh3D7tZM3gaY+8QhPoyK2h67aaOSgRqhvVwAPeFR++UUSiy4A0V4a7JqyVwesNd S8Jg== X-Gm-Message-State: APf1xPA0ExZgD9Njqew+3b6+DRFZZBvBjnZL3GVknVtgzAy0scXzGXK5 PLj3RcCtE7RYk3f3oZFfzqrlt2hLksc= X-Google-Smtp-Source: AH8x227jKItAsKRJL94taxIn2hl4FA5XZO2LqCd19LD9osAOGvOjT7Bo0UsX0xSVpfunB8jaTI6i1g== X-Received: by 10.107.142.13 with SMTP id q13mr1623045iod.299.1518145753546; Thu, 08 Feb 2018 19:09:13 -0800 (PST) Received: from ziepe.ca (S010614cc2056d97f.ed.shawcable.net. [70.74.179.152]) by smtp.gmail.com with ESMTPSA id w132sm1220979iow.51.2018.02.08.19.09.11 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 08 Feb 2018 19:09:11 -0800 (PST) Received: from jgg by mlx.ziepe.ca with local (Exim 4.86_2) (envelope-from ) id 1ejz3m-0005qg-CO; Thu, 08 Feb 2018 20:09:10 -0700 From: Jason Gunthorpe To: linux-rdma@vger.kernel.org Cc: Jason Gunthorpe Subject: [PATCH rdma-core 7/7] Check that published headers do not rely on internal headers Date: Thu, 8 Feb 2018 20:09:04 -0700 Message-Id: <20180209030904.22370-8-jgg@ziepe.ca> X-Mailer: git-send-email 2.16.1 In-Reply-To: <20180209030904.22370-1-jgg@ziepe.ca> References: <20180209030904.22370-1-jgg@ziepe.ca> Sender: linux-rdma-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rdma@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Jason Gunthorpe We already check that the published headers can be compiled, but that test is done with our build directory in the search path, and can see a full set of kernel headers. This new CI test ensures that only glibc headers or two allowed kernel headers are being #include'd by the public headers. This prevents a very easy mistake to use a kernel ABI or private header in the wrong place. Signed-off-by: Jason Gunthorpe --- buildlib/check-build | 86 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 69 insertions(+), 17 deletions(-) diff --git a/buildlib/check-build b/buildlib/check-build index bfd53b21b789a4..766db7ae46259f 100755 --- a/buildlib/check-build +++ b/buildlib/check-build @@ -10,6 +10,7 @@ import shutil import subprocess import tempfile import sys +import copy from contextlib import contextmanager; def get_src_dir(): @@ -204,31 +205,82 @@ def is_fixup(fn): return "buildlib/fixup-include/" in os.readlink(fn); return False; -def test_public_headers(args): - """Test that every header file can be included on its own, and has no obvious - implicit dependencies. This is mainly intended to check the public - headers, but this sweeps in published internal headers too.""" - incdir = os.path.abspath(os.path.join(args.BUILD,"include")); +def get_headers(incdir): includes = set(); for root,dirs,files in os.walk(incdir): for I in files: if I.endswith(".h"): includes.add(os.path.join(root,I)); + return includes; + +def compile_test_headers(tmpd,incdir,includes): + with open(os.path.join(tmpd,"build.ninja"),"wt") as F: + print >> F,"rule comp"; + print >> F," command = %s -Werror -c -I %s $in -o $out"%(args.CC,incdir); + print >> F," description=Header check for $in"; + count = 0; + for I in sorted(includes): + if is_obsolete(I) or is_fixup(I): + continue; + print >> F,"build %s : comp %s"%("out%d.o"%(count),I); + print >> F,"default %s"%("out%d.o"%(count)); + count = count + 1; + subprocess.check_call(["ninja"],cwd=tmpd); + +def test_published_headers(args): + """Test that every header file can be included on its own, and has no obvious + implicit dependencies. This is intended as a first pass check of the public + installed API headers""" + incdir = os.path.abspath(os.path.join(args.BUILD,"include")); + includes = get_headers(incdir); # Make a little ninja file to compile each header with private_tmp() as tmpd: - with open(os.path.join(tmpd,"build.ninja"),"wt") as F: - print >> F,"rule comp"; - print >> F," command = %s -Werror -c -I %s $in -o $out"%(args.CC,incdir); - print >> F," description=Header check for $in"; - count = 0; - for I in sorted(includes): - if is_obsolete(I) or is_fixup(I): - continue; - print >> F,"build %s : comp %s"%("out%d.o"%(count),I); - print >> F,"default %s"%("out%d.o"%(count)); - count = count + 1; - subprocess.check_call(["ninja"],cwd=tmpd); + compile_test_headers(tmpd,incdir,includes); + +# ------------------------------------------------------------------------- + +allowed_uapi_headers = { + # This header is installed in all supported distributions + "rdma/ib_user_sa.h", + "rdma/ib_user_verbs.h", +} + +def test_installed_headers(args): + """This test also checks that the public headers can be compiled on their own, + but goes further and confirms that the public headers do not depend on any + internal headers, or kernel kAPI headers.""" + with private_tmp() as tmpd: + env = copy.deepcopy(os.environ); + env["DESTDIR"] = tmpd; + subprocess.check_output(["ninja","install"],env=env); + + includes = get_headers(tmpd); + incdir = os.path.commonprefix(includes); + rincludes = {I[len(incdir):] for I in includes}; + + bincdir = os.path.abspath(os.path.join(args.BUILD,"include")); + all_includes = set(); + for I in get_headers(bincdir): + if not is_fixup(I) and not is_obsolete(I): + all_includes.add(I[len(bincdir)+1:]); + + # Drop error includes for any include file that is internal, this way + # when we compile the public headers any include of an internal header + # will fail. + for I in sorted(all_includes - rincludes): + if I in allowed_uapi_headers: + continue; + + I = os.path.join(incdir,I) + dfn = os.path.dirname(I); + if not os.path.isdir(dfn): + os.makedirs(dfn); + assert not os.path.exists(I); + with open(I,"w") as F: + print >> F,'#error "Private internal header"'; + + compile_test_headers(tmpd,incdir,includes); # -------------------------------------------------------------------------