Building stuff with monadic dependencies + unchanging dependencies + polymorphic dependencies + abstraction Neil Mitchell

Slides:



Advertisements
Similar presentations
Chapter 11 Introduction to Programming in C
Advertisements

R Packages Davor Cubranic SCARL, Dept. of Statistics.
I/O means Input and Output. One way: use standard input and standard output. To read in data, use scanf() (or a few other functions) To write out data,
The make Utility Programming Tools and Environments Winter 2006.
Programming Types of Testing.
Shake Before Building Replacing Make with Haskell community.haskell.org/~ndm/shake Neil Mitchell.
Python Programming Chapter 1: The way of the program Saad Bani Mohammad Department of Computer Science Al al-Bayt University 1 st 2011/2012.
Understanding Makefiles COMP 2400, Fall 2008 Prof. Chris GauthierDickey.
10-Jun-15 Fibonacci Numbers A simple example of program design.
Copyright © 2008 Pearson Addison-Wesley. All rights reserved. Chapter 12 Separate Compilation Namespaces Simple Make Files (Ignore all class references.
B-1 Lecture 2: Problems, Algorithms, and Programs © 2000 UW CSE University of Washington Computer Programming I.
Low level CASE: Source Code Management. Source Code Management  Also known as Configuration Management  Source Code Managers are tools that: –Archive.
Introduction to Unix – CS 21 Lecture 5. Lecture Overview Lab Review Useful commands that will illustrate today’s lecture Streams of input and output File.
1 SEEM3460 Tutorial Unix Introduction. 2 Introduction What is Unix? An operation system (OS), similar to Windows, MacOS X Why learn Unix? Greatest Software.
1 Introduction to Tool chains. 2 Tool chain for the Sitara Family (but it is true for other ARM based devices as well) A tool chain is a collection of.
1 ENG236: ENG236: C++ Programming Environment (2) Rocky K. C. Chang THE HONG KONG POLYTECHNIC UNIVERSITY.
Chocolate Bar! luqili. Milestone 3 Speed 11% of final mark 7%: path quality and speed –Some cleverness required for full marks –Implement some A* techniques.
Erlware For Managing Distribution and Build Erlang User Conference 2007.
PHP TUTORIAL. HISTORY OF PHP  PHP as it's known today is actually the successor to a product named PHP/FI.  Created in 1994 by Rasmus Lerdorf, the very.
CSnake C++ build automation based on CMake and Python Maarten Nieber, 2009.
Introduction Use of makefiles to manage the build process Declarative, imperative and relational rules Environment variables, phony targets, automatic.
Programming With C.
Writing Scala Programs. Command Line There are three common operating systems: Windows (various flavors; I recommend Windows 7) UNIX or Linux (basically.
Scons Writing Solid Code Overview What is scons? scons Basics Other cools scons stuff Resources.
CS 11 java track: lecture 1 Administrivia need a CS cluster account cgi-bin/sysadmin/account_request.cgi need to know UNIX
CRT State Stuff Dana Robinson The HDF Group. In the next slide, I show a single executable linked to three dlls. Two dlls and the executable were built.
Computer Programming I Hour 2 - Writing Your First C Program.
CSE 303 Concepts and Tools for Software Development Richard C. Davis UW CSE – 12/6/2006 Lecture 24 – Profilers.
CSE 232: C++ debugging in Visual Studio and emacs C++ Debugging (in Visual Studio and emacs) We’ve looked at programs from a text-based mode –Shell commands.
Introduction Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See
Makefiles. Multiple Source Files (1) u Obviously, large programs are not going to be contained within single files. u C provides several techniques to.
1 SEEM3460 Tutorial Compiling and Debugging C programs.
Test Specifications A Specification System for Multi-Platform Test Suite Configuration, Build, and Execution Greg Cooksey.
Exam / Homework Exam 1 Starting K&R chapter 4 tonight
Data Display Debugger (DDD)
Dissecting the Windows CE Build Process James Y. Wilson Principal Engineer, Windows Embedded MVP CalAmp, Inc. James Y. Wilson Principal Engineer, Windows.
Discussion Week 1 TA: Kyle Dewey. Project 0 Walkthrough.
Makefiles CARYL RAHN. Separate compilation Large programs are generally separated into multiple files, e.g. main.c addmoney.c removemoney.c money.h With.
Version Control and SVN ECE 297. Why Do We Need Version Control?
The single most important skill for a computer programmer is problem solving Problem solving means the ability to formulate problems, think creatively.
Announcements Assignment 1 due Wednesday at 11:59PM Quiz 1 on Thursday 1.
Make a Copy Of File Main.cpp (of Student-Class). Place It On Your Desktop. Open it With A Text Editor 3.
Build Tools 1. Building a program for a large project is usually managed by a build tool that controls the various steps involved. These steps may include:
Program Libraries 1. What is a program library? A library is a collection of implementations of behavior, written in terms of a language, that has a well-defined.
CSc 352 An Introduction to make Saumya Debray Dept. of Computer Science The University of Arizona, Tucson
Announcements Assignment 2 Out Today Quiz today - so I need to shut up at 4:25 1.
LECTURE 3 Translation. PROCESS MEMORY There are four general areas of memory in a process. The text area contains the instructions for the application.
Today… Modularity, or Writing Functions. Winter 2016CISC101 - Prof. McLeod1.
1 Building a program in C: Preprocessor, Compilation and Linkage.
CSE 374 Programming Concepts & Tools Hal Perkins Fall 2015 Lecture 18 – Linking and Libraries.
Multiple file project management & Makefile
Lecture 3 Translation.
Development Environment
Prof: Dr. Shu-Ching Chen TA: Hsin-Yu Ha Fall 2015
C – Multi-file development and make
From C to C++.
Behavioral Design Patterns
Brian Leonard ブライアン レオナルド
From C to C++.
CSE 303 Concepts and Tools for Software Development
Makefile Tutorial CIS5027 Prof: Dr. Shu-Ching Chen
Prof: Dr. Shu-Ching Chen TA: Yimin Yang
Prof: Dr. Shu-Ching Chen TA: Samira Pouyanfar Hector Cen Fall 2017
Chapter 11 Introduction to Programming in C
Prof: Dr. Shu-Ching Chen TA: Hsin-Yu Ha
Brought to you by C++ Tutorial Brought to you by
CSE 303 Concepts and Tools for Software Development
Build Tools (make) CSE 333 Autumn 2018
SPL – PS1 Introduction to C++.
Presentation transcript:

Building stuff with monadic dependencies + unchanging dependencies + polymorphic dependencies + abstraction Neil Mitchell

Building stuff with Shake Neil Mitchell

What is Shake? A Haskell library for writing build systems – Alternative to make, Scons, Ant, Waf… I wrote it at Standard Chartered in 2009 I rewrote it open-source in 2012 Who has used Haskell? Shake?

When to use a build system Not compiling stuff Compiling stuff Use Shake Use Cabal Use ghc --make Use Visual Studio projects Fractal rendering Paleo experiments

Tutorial Overview Tutorial rules – Ask if you don’t understand – There is no end – I stop when the clock hits 0 – All slides will be online – Not a “sales pitch” – Questions for you in italic on most slides. One main example (compiling a C file) Lots of independent extensions to that

Main example Some C files /* main.c */ #include #include "a.h" #include "b.h" void main() { printf("%s %s\n",a,b); } /* a.h */ char* a = "hello"; /* b.h */ char* b = "world"; What does this print?

Main example Compiling C gcc -c main.c gcc main.o -o main What files are involved at each step?

Main example Compiling C in Haskell import Development.Shake main = do () <- cmd "gcc -c main.c" () <- cmd "gcc main.o -o main" return () Why do we have the ugly () <- line noise?

Main example A Shake system import Development.Shake import Development.Shake.FilePath main = shakeArgs shakeOptions $ do want ["main" exe] "main" exe %> \out -> do () <- cmd "gcc -c main.c" () <- cmd "gcc main.o -o main" return () Boilerplate When will main.exe rebuild?

Main example With dependencies want ["main" exe] "main" exe %> \out -> do need ["main.c", "a.h", "b.h"] () <- cmd "gcc -c main.c" () <- cmd "gcc main.o -o main" return () Why is this a bad idea?

Main example Asking gcc for depends $ gcc -MM main.c main.o: main.c a.h b.h Anyone used that before?

Main example Using gcc -MM import Development.Shake.Util "main" exe %> \out -> do Stdout s <- cmd "gcc -c -MM main.c" need $ concatMap snd $ parseMakefile s () <- cmd "gcc main.o -o main" return () Did you know you can combine -c and -MM?

Main example Two rules "main.o" %> \out -> do Stdout s <- cmd "gcc -c -MM main.c" need $ concatMap snd $ parseMakefile s "main" exe %> \out -> do need ["main.o"] cmd "gcc main.o -o main" Why are two rules better?

Main example The result main = shakeArgs shakeOptions $ do want ["main" exe] "main" exe %> \out -> do need ["main.o"] cmd "gcc main.o -o main" "main.o" %> \out -> do Stdout s <- cmd "gcc -c -MM main.c" need $ concatMap snd $ parseMakefile s

The “perfect” build system A bunch of wants – Each thing that goes in the release A bunch of rules – Simple pattern – A bunch of need, a bit of Haskell – A single command line (occasionally two)

Your thoughts What goes in a release What is the command What it depends on

File patterns Any file "*.o" %> \out -> do let src = out - "c" Stdout s <- cmd "gcc -c -MM" [src] need $ concatMap snd $ parseMakefile s Why do we use [src], not just src?

File patterns Source to object "obj//*.o" %> \out -> do let src = "src" dropDirectory1 out - "c" Stdout s <- cmd "gcc -c -MM" [src] "-o" [out] need $ concatMap snd $ parseMakefile s What if we want to do lower-case files?

File patterns Pattern predicates (\x -> all isLower (takeBaseName x) && "*.o" ?== x) ?> \out -> do let src = out - "c" Stdout s <- cmd "gcc -c -MM" [src] need $ concatMap snd $ parseMakefile s What can’t we do?

Version deps Dependencies on $PATH "main" exe %> \out -> do need ["main.o"] cmd "gcc main.o -o main" We depend on the version of gcc on $PATH – But we don’t track it What else don’t we track?

Version deps Store gcc version "gcc.version" %> \out -> do alwaysRerun Stdout s <- cmd "gcc --version" writeFileChanged out s What if we didn’t use writeFileChanged?

Version deps Depending on gcc version "main" exe %> \out -> do need ["main.o", "gcc.version"] cmd "gcc main.o -o main" Are two need’s after each other equivalent?

Dir contents Compile all files in a dir "main" exe %> \out -> do need ["main.o"] cmd "gcc main.o -o main" Compile in all.c files in a directory Do we already have enough to do that?

Dir contents getDirectoryFiles "main" exe %> \out -> do xs <- getDirectoryFiles "" ["*.c"] let os = map (- "o") xs need os cmd "gcc" os "-o main" What if we want to find all files recursively?

The four features 1.Monadic (dynamic?) dependencies 2.Unchanging dependencies 3.Polymorphic dependencies 4.Abstraction Where have we used each so far?

#1: Monadic dependencies Ask for further dependencies at any point – The need doesn’t have to be on the first line Absolutely essential Found in Shake (+clones), Redo, a bit in Scons Every non-monadic build system has hacks to get some monadic power – None are direct and powerful

#2: Unchanging dependencies A dependency may rebuild, but not change Very important to reduce rebuilds – Allows writeFileChanged, depending on gcc More common, but not in make, not a default – Ninja = restat, Tup = ^o^ – Redo = redo-ifchange – Requires a database of metadata

#3: Polymorphic dependencies Dependencies don’t have to be files If you have monadic + unchanging, polymorphic is no new power – Just more convenient, avoid on-disk files Quite rare, only Shake that I know of – (Redo has redo-ifcreate)

#4: Abstraction Mostly a DSL vs EDSL question – Custom languages usually lack abstraction – Almost always lack package managers Monadic also makes abstraction easier – Shake has about 7 released packages of rules – Other build systems don’t seem to share as much Available in Scons, Shake, a few others

Generate.c Generate the.c file "main.c" %> \out -> do need ["main.txt"] cmd Shell "generate main.txt > main.c" Where is the bug?

Generate.c Generate the.c file Is there a way to fix gcc -MM directly? "*.o" %> \out -> do let src = out - "c“ need [src] Stdout s <- cmd "gcc -c -MM" [src] needed $ concatMap snd $ parseMakefile s

Avoid gcc -M Manual header scan usedHeaders :: String -> [FilePath] usedHeaders src = [ init x | x <- lines src, Just x <- [stripPrefix "#include \"" x]] What’s the disadvantage of a manual scan?

Avoid gcc -M Manual header scan "main.o" %> \out -> do src <- readFile' "main.c" need $ usedHeaders src cmd "gcc -c main.c" What’s the advantage of a manual scan?

Generate.h Generate the.h file "*.h" %> \out -> do let src = out - "txt" need [src] cmd Shell "generate" [src] ">" [out] What made this change self-contained?

Transitive One-step includes ["*.c.dep","*.h.dep"] |%> \out -> do src <- readFile' $ dropExtension out writeFileLines out $ usedHeaders src What are we reusing?

Transitive Transitive includes "*.deps" %> \out -> do dep "dep" deps "deps")) dep writeFileLines out $ nub $ dropExtension out : concat deps deps a = a : concatMap deps (dep a)

Transitive Transitive includes "main.o" %> \out -> do src <- readFileLines "main.c.deps" need src cmd "gcc -c main.c" How could we test this rule?

Config Define config # build.cfg main.exe = main foo config.exe = config foo Is this easy enough for Haskell-phobes? Keep regularly changing details out of.hs

Config Interpret config import Development.Shake.Config usingConfigFile "build.cfg" action $ need =<< getConfigKeys "*.exe" %> \out -> do Just src <- getConfig out let os = map ( "o") $ words src need os cmd "gcc" os "-o" [out] What else might we put in the config?

Resources What is a resource? What are some other resources? Build systems allocate CPU resources What about other resources? Only have 12 licenses for the FPGA tester Can only run one copy of Excel at a time

Resources Using resources What is the performance impact? disk <- newResource "Disk" 4 "*.exe" %> \out -> withResource disk 1 $ cmd "gcc -o" [out]...

Flags Command line flags $ runhaskell Main.hs --help Usage: shake [options] [target]... Options: -B, --always-make Unconditionally make all targets. --no-build Don't build anything. --color, --colour Colorize the output. -d[=FILE], --debug[=FILE] Print lots of debugging information. -j[=N], --jobs[=N] Allow N jobs/threads at once [default CPUs]. -k, --keep-going Keep going when some targets can't be made. -l, --lint Perform limited validation after the run. --live[=FILE] List the files that are live [to live.txt]. --assume-skip Don't remake any files this run. -p[=N], --progress[=N] Show progress messages [every N secs, default 5] lines in total...

Flags Flags vs options opts = shakeOptions{shakeThreads=8} main = shakeArgs opts … $ runhaskell Main.hs -j5 Who wins? Developer or user?

Flags Named arguments phony "clean" $ do removeFilesAfter ".shake" ["//*"] Why removeFilesAfter?

Flags Extra flags data Flags = DistCC flags = Option "" ["distcc"] (NoArg $ Right DistCC) "Run distributed." main = shakeArgsWith shakeOptions [flag] … What do non-flags args do by default?

Also files Many-out Could we avoid &%> ? ["*.o","*.hi"] &%> \[o,hi] -> do let hs = o - "hs" need all files the.hs import cmd "ghc -c" [hs]

Lint Lint rules What others? Enable by passing --lint – Don’t change current directory – Files written only once – Files not used before need Enabled by passing --lint-tracker – Dependencies are not used without need

Lint Lint rules When is needed safe? "main.o" %> \out -> do Stdout s <- cmd "gcc -c -MM main.c" needed $ concatMap snd $ parseMakefile s

Error: Out of slides