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

scyther: init at 1.1.3 #27006

Merged
merged 2 commits into from
Aug 1, 2017
Merged

scyther: init at 1.1.3 #27006

merged 2 commits into from
Aug 1, 2017

Conversation

infinisil
Copy link
Member

@infinisil infinisil commented Jul 1, 2017

This PR adds the scyther application, a tool for automatic verification of security protocols. On GitHub

This is the first time I wrote a non-trivial amount of nix code, I tried to structure it well :)

I split the package up into 4 files:

  • sources.nix contains different versions of the package. The official latest release is 1.1.3, there is also a Compromise-0.9.2 version which has some different performance characteristics which may not everybody want. Then I also included the latest commit from master, as the project hasn't seen a new release in a while and there were some bug fixes.
  • cli.nix contains the 32bit package for building the C part, which generates a single executable, usable by itself.
  • gui.nix contains the python GUI frontend, which uses the CLI at runtime
  • default.nix contains the actual package which builds a single environment. Using the includeGUI (default true) option, one can choose to not to have the GUI, while the version option lets you select one of the three above mentioned versions.

This split into multiple derivations is made to reduce build time and output path size.

Motivation for this change
Things done
  • Tested using sandboxing
    (nix.useSandbox on NixOS,
    or option build-use-sandbox in nix.conf
    on non-NixOS)
  • Built on platform(s)
    • NixOS
    • macOS
    • Linux
  • Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)
  • Tested compilation of all pkgs that depend on this change using nix-shell -p nox --run "nox-review wip"
  • Tested execution of all binary files (usually in ./result/bin/)
  • Fits CONTRIBUTING.md.

Copy link
Contributor

@MostAwesomeDude MostAwesomeDude left a comment

Choose a reason for hiding this comment

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

I have no serious objections as-is, but there's a few nits. Thank you for your hard work.

@@ -0,0 +1,30 @@
{ lib, callPackage, callPackage_i686, buildEnv
, includeGUI ? true
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't know this package at all; how useful is it to its audience without the GUI? I'm wondering whether this should default to false.

Copy link
Member Author

Choose a reason for hiding this comment

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

The package is advertised as a GUI application first, it provides visualizations the cli can't do easily.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thinking about it again, it might be better to default to false, the current NixOS target audience would probably prefer CLI tools (me included). Also the CLI tool doesn't have the mentioned runtime problems with certain protocol

Copy link
Member

Choose a reason for hiding this comment

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

Why bother joining the two tools in a single output?

paths = [ cli ] ++ lib.optional includeGUI gui;
pathsToLink = ["/bin"];

postBuild = if includeGUI then ''
Copy link
Contributor

Choose a reason for hiding this comment

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

I did a double-take here. I think I understand what's happening; if the GUI's included, then link the GUI protocols in; otherwise, copy the (bare-bones?) protocols from the source package. But I'm not sure why. Can we get a comment explaining this trickery?

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah yes, I'm copying the whole ./gui directory from the source to $out, because that's where all the GUI is. I believe there is some way for the GUI to show these protocols, that's why they're there. But the CLI wouldn't include them, but because the protocols are so useful, I decided to have them in there anyways. Could be made a seperate output though, doesn't technically need to be there.

Copy link
Member Author

Choose a reason for hiding this comment

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

And if I always copied them from source they would be duplicated in the case of includeGUI = true

let
filtered = builtins.filter (s: s.name == "${version}") versions;
in if filtered != [] then fetchSource (builtins.head filtered) else
throw "Scyther version ${version} is not available, choose one of ${showVersions} instead.";
Copy link
Contributor

Choose a reason for hiding this comment

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

Friendly.

Copy link
Member Author

Choose a reason for hiding this comment

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

UX is key :)

@infinisil
Copy link
Member Author

Running it on Ubuntu doesn't work (the build succeeds though). I'll try to fix that and add some simple checks

@infinisil
Copy link
Member Author

Now doesn't have any runtime problems (the problem I mentioned before was on both Ubuntu and NixOS btw). I added a simple execution of the program as a test. I couldn't get the default installCheck phase to work (maybe because of this?), so I just put in a custom testPhase which gets run at the very end.

This package is done as far as I can tell. There are some issues when running certain protocols, but I'm 99.9% sure this is a bug in the package and has nothing to do with Nix.

# For some reason it doesn't use the C89 standard which would allow __inline__
for file in *.*
do
substituteInPlace $file --replace "__inline__ " ""
Copy link
Contributor

Choose a reason for hiding this comment

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

Please do an upstream PR for this, such that we don't need to patch it ourselves. The rest of your PR looks good enough.

Copy link
Member Author

Choose a reason for hiding this comment

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

The issue about this version.h file comes from the fact that the python script for its generation relies on being in a git repo (so it can check the tag/rev). This could be solved by doing a full checkout, but I don't think it's worth the build time dependency of python, considering the script is dead simple.

The issue with these __inline__ attributes I have no idea how to solve, cmake is supposed to use the C89 standard but it doesn't for some reason. If somebody could show me how it's done that would be awesome.

@infinisil
Copy link
Member Author

infinisil commented Jul 1, 2017

Ahh I just figured it out, I was able to remove the __inline__ patch, I fixed it by adding the -std=gnu89 flag explicitly, because it was only recently added (not present in versions other than master).

@FRidh
Copy link
Member

FRidh commented Jul 2, 2017

Here's a PR I opened when @infinisil was trying to package this https://github.com/NixOS/nixpkgs/pull/26785/files. Note that I do not use this package.

@@ -0,0 +1,26 @@
{ stdenv, lib, cmake, glibc, makeWrapper, fetchFromGitHub, flex, bison, source }:
stdenv.mkDerivation {
name = "scyther-cli-${source.rev}";
Copy link
Member

Choose a reason for hiding this comment

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

a source revision is not a valid version for in Nixpkgs

flex
bison
];
}
Copy link
Member

Choose a reason for hiding this comment

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

meta is missing

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for the review!

Since only the drv in default.nix is intended to be used I only put meta there, it would be the same for all (internal) drvs.

@@ -0,0 +1,30 @@
{ lib, callPackage, callPackage_i686, buildEnv
, includeGUI ? true
Copy link
Member

Choose a reason for hiding this comment

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

Why bother joining the two tools in a single output?


format = "other";

phases = [ "unpackPhase" "patchPhase" "installPhase" "fixupPhase" "testPhase" ];
Copy link
Member

Choose a reason for hiding this comment

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

don't set phases, bad practice


phases = [ "unpackPhase" "patchPhase" "installPhase" "fixupPhase" "testPhase" ];

patchPhase = ''
Copy link
Member

Choose a reason for hiding this comment

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

postPatch, try not to override the phases

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'll fix that

And my reply to your comment about joining the outputs (can't reply to that for some reason): it separates stuff nicely I think, since the source needs to be shared by both parts and the gui depends on the cli with this setup one can only install the cli if desired. I'll think about it once more but I believe it's the cleanest like this. One other solution would be to just use 2 top-level packaged as you did before

'';

# This would call wrapPythonPrograms which only wraps ones in $out/bin
dontWrapPythonPrograms = true;
Copy link
Member

Choose a reason for hiding this comment

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

if you don't want the wrappers you may as well just use stdenv.mkDerivation.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good call, I thought about this when writing it, I'll try this

@@ -0,0 +1,33 @@
{ lib, fetchFromGitHub }:
let
versions = map (s: { name = s.rev; } // s) [
Copy link
Member

Choose a reason for hiding this comment

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

We typically provide only a single version. If users want another version, they could override and pass their own src in.

Copy link
Member Author

Choose a reason for hiding this comment

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

Heh, yes that is a very valid point, I thought it would be neat if it could be chosen between two releases which very much differ (very comparable to firefox and firefox-esr).

How about this: Getting rid of the master version (this can also fix the rev as version in your other comment) and making it possible to override source like all other packages?

src = source;
preConfigure = ''
cd src
# Since we're not in a git dir, the normal command this project uses to create this file wouldn't work
Copy link
Contributor

Choose a reason for hiding this comment

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

This works until the moment it doesn't. Please add some kind of assertion checking that upstream didn't change their method of producing this string in a couple of versions.

preConfigure = ''
cd src
# Since we're not in a git dir, the normal command this project uses to create this file wouldn't work
printf "#define TAGVERSION \"${source.rev}\"\n" >> version.h
Copy link
Contributor

Choose a reason for hiding this comment

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

The Python script writes to the file, you append to it. Your use of printf is potentially wrong depending on the value of ${source.rev}, so please use a format string.

@infinisil
Copy link
Member Author

infinisil commented Jul 5, 2017

@FRidh @0xABAB @MostAwesomeDude I redid the whole package, putting everything into a single derivation, abandoning the 'providing different versions by default' thing. While it was a cool idea, it's not the right thing to do.

I fixed every mentioned flaw of previous review comments, except what @0xABAB said regarding the generation of the version.h file which might not work forever. Since this package is in a pretty inactive phase I doubt it will ever get so much attention to get this changed (and even if it does, I'll fix it then).

One big drawback of how its done now is that since everything (both cli and gui part) gets built using callPackage_i686, it uses 32bit everything for python, which isn't needed at all. If somebody knows how to fix this, let me know, I'll think about it some more too.


patchPhase = ''
# Since we're not in a git dir, the normal command this project uses to create this file wouldn't work
printf "%s\n" "#define TAGVERSION \"${version}\"" >> src/version.h
Copy link
Contributor

Choose a reason for hiding this comment

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

You are still appending (>>) instead of writing (>) to src/version.h.



configurePhase = ''
pushd src
Copy link
Contributor

Choose a reason for hiding this comment

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

(cd src && cmakeConfigurePhase) (including the parentheses does the same, right? (And is shorter and more portable.)

];

dontUseCmakeBuildDir = true;
cmakeFlags = [ "-DCMAKE_C_FLAGS=\"-std=gnu89\"" ];
Copy link
Contributor

Choose a reason for hiding this comment

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

"-DCMAKE_C_FLAGS=-std=gnu89" does the same.

, includeProtocols ? true
}:
let
version = "v1.1.3";
Copy link
Contributor

Choose a reason for hiding this comment

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

This version string is invalid. See builtins.parseDrvName. A version string must begin with a digit.

stdenv.mkDerivation {
name = "scyther-${version}";
src = fetchFromGitHub {
rev = "v1.1.3";
Copy link
Contributor

Choose a reason for hiding this comment

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

Once the version has been fixed, you can do rev = v${version}.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks, didn't notice that, fixed now

@infinisil
Copy link
Member Author

Pinging @FRidh, the things you mentioned have all been corrected in the totally new revision of this package.

@infinisil
Copy link
Member Author

Can somebody tell my why travis complains about wrong platform on Darwin even though I explicitly set platforms to linux only? https://travis-ci.org/NixOS/nixpkgs/jobs/254011342#L1544

@FRidh FRidh self-assigned this Jul 16, 2017
(cd src && cmakeConfigurePhase)
'';

propagatedBuildInputs = [] ++ lib.optional includeGUI [
Copy link
Member

Choose a reason for hiding this comment

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

This can omit the [] ++

@grahamc
Copy link
Member

grahamc commented Jul 16, 2017

LGTM if @FRidh doesn't review and/or merge soon, let me know.

@FRidh
Copy link
Member

FRidh commented Jul 17, 2017

One big drawback of how its done now is that since everything (both cli and gui part) gets built using callPackage_i686, it uses 32bit everything for python, which isn't needed at all. If somebody knows how to fix this, let me know, I'll think about it some more too.

That's why its better to build it in two separate derivations. The one, that just builds that little binary, and the other that puts it all together in one derivation.

@FRidh
Copy link
Member

FRidh commented Jul 17, 2017

Can somebody tell my why travis complains about wrong platform on Darwin even though I explicitly set platforms to linux only? https://travis-ci.org/NixOS/nixpkgs/jobs/254011342#L1544

You set platforms correct, but callPackage_i686 assumes an i686 Linux system. See line 30 in all-packages.nix

callPackage_i686 = pkgsi686Linux.callPackage;

You can ignore this error because its expected behavior.

@infinisil
Copy link
Member Author

@FRidh I'll make another revision to separate the two parts

@infinisil
Copy link
Member Author

@FRidh I separated the package into two versions so it doesn't require 32-bit versions of everything. One thing I changed is the inclusion of protocols. If includeGUI && includeProtocols, then they are included twice, but I don't think it's worth symlinking it (it's only 1MB).

Since some things changed, I'd love the other reviewers to have another look (especially the buildEnv part)

@infinisil
Copy link
Member Author

@FRidh ping

@FRidh FRidh merged commit d1af3b3 into NixOS:master Aug 1, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants